#include #include #include #include #include #include #include #include "net.h" #include "common.h" void net_init(void) { curl_global_init(CURL_GLOBAL_ALL); } void net_deinit(void) { curl_global_cleanup(); } static inline size_t memoryCallback(const void* contents, size_t size, size_t nmemb, void* userp) { size_t realsize = size * nmemb; struct MemoryStruct* mem = (struct MemoryStruct*)userp; uint8_t* ptr = realloc(mem->memory, mem->size + realsize + 1); if(ptr == NULL) { fprintf(stderr, "Unable to allocate memory\n"); return 0; } mem->memory = ptr; memcpy(&(mem->memory[mem->size]), contents, realsize); mem->size += realsize; mem->memory[mem->size] = 0; return realsize; } static inline int xferinfo(UNUSED void *p, curl_off_t dltotal, curl_off_t dlnow, UNUSED curl_off_t ultotal, UNUSED curl_off_t ulnow) { curl_off_t progress = 0; if (dltotal != 0) progress = (dlnow * 100) / dltotal; fprintf(stderr, "\rProgress: %3" CURL_FORMAT_CURL_OFF_T "%%", progress); if (progress == 100) fprintf(stderr, "\r"); return 0; } struct MemoryStruct* downloadToRam(const char* URL, int progress) { if (no_net) return NULL; CURL* curl_handle; CURLcode res = CURLE_OK; if (!isatty(STDERR_FILENO)) progress = 0; struct MemoryStruct* chunk = malloc(sizeof(struct MemoryStruct)); if (chunk) { chunk->memory = malloc(1); if (!chunk->memory) { free(chunk); return NULL; } chunk->memory[0] = 0; chunk->size = 0; curl_handle = curl_easy_init(); curl_easy_setopt(curl_handle, CURLOPT_URL, URL); curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, memoryCallback); curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void*)chunk); curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, USER_AGENT); curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl_handle, CURLOPT_XFERINFOFUNCTION, xferinfo); curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, !progress); res = curl_easy_perform(curl_handle); long http_code = 0; curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &http_code); if(res != CURLE_OK) { free(chunk->memory); free(chunk); puts(curl_easy_strerror(res)); chunk = NULL; } else if (http_code != 200) { free(chunk->memory); free(chunk); #ifndef NDEBUG printf("HTTP Error %li\n", http_code); #endif chunk = NULL; } curl_easy_cleanup(curl_handle); } else { fprintf(stderr, "Unable to allocate memory\n"); } return chunk; } void downloadToFile(const char* URL, const char* path, int progress) { struct MemoryStruct* chunk = downloadToRam(URL, progress); if (chunk) { FILE* fp = fopen(path, "wb"); if (fp) { fwrite(chunk->memory, sizeof(uint8_t), chunk->size, fp); fclose(fp); } free(chunk->memory); free(chunk); } } struct json_object* fetchJSON(const char* URL) { struct json_object* json = NULL; struct MemoryStruct* chunk = downloadToRam(URL, 0); if (chunk) { json = json_tokener_parse((char*)chunk->memory); free(chunk->memory); free(chunk); } else if (isatty(STDERR_FILENO)) { fprintf(stderr, "Couldn't fetch JSON\n"); } return json; }