#include #include #include #include #include #include #include #include #include #include "dialogs.h" #include "network.h" volatile char generic_url[512]; static CURL *curl_handle = NULL; volatile uint64_t total_bytes = 0xFFFFFFFF; volatile uint64_t downloaded_bytes = 0; volatile uint8_t downloader_pass = 1; uint8_t *generic_mem_buffer = nullptr; static FILE *fh; char *bytes_string; static size_t write_cb(void *ptr, size_t size, size_t nmemb, void *stream) { if (total_bytes > MEM_BUFFER_SIZE || fh) { if (!fh) fh = fopen(TEMP_DOWNLOAD_NAME, "wb"); fwrite(ptr, 1, nmemb, fh); } else { uint8_t *dst = &generic_mem_buffer[downloaded_bytes]; sceClibMemcpy(dst, ptr, nmemb); } downloaded_bytes += nmemb; if (total_bytes < downloaded_bytes) total_bytes = downloaded_bytes; return nmemb; } static size_t header_cb(char *buffer, size_t size, size_t nitems, void *userdata) { char *ptr = strcasestr(buffer, "Content-Length"); if (ptr != NULL) sscanf(ptr, "Content-Length: %llu", &total_bytes); return nitems; } static size_t header_dummy_cb(char *buffer, size_t size, size_t nitems, void *userdata) { return nitems; } static void startDownload(const char *url) { curl_easy_reset(curl_handle); curl_easy_setopt(curl_handle, CURLOPT_URL, url); curl_easy_setopt(curl_handle, CURLOPT_HTTPGET, 1L); curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"); curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0L); curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, 10L); curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_cb); curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, bytes_string); // Dummy curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, downloaded_bytes ? header_dummy_cb : header_cb); curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, bytes_string); // Dummy curl_easy_setopt(curl_handle, CURLOPT_RESUME_FROM, downloaded_bytes); curl_easy_setopt(curl_handle, CURLOPT_BUFFERSIZE, 524288); struct curl_slist *headerchunk = NULL; headerchunk = curl_slist_append(headerchunk, "Accept: */*"); headerchunk = curl_slist_append(headerchunk, "Content-Type: application/json"); headerchunk = curl_slist_append(headerchunk, "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"); headerchunk = curl_slist_append(headerchunk, "Content-Length: 0"); curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headerchunk); curl_easy_perform(curl_handle); } int downloadThread(unsigned int args, void *arg) { curl_handle = curl_easy_init(); //printf("downloading %s\n", generic_url); char *url = (char *)generic_url; char *space = strstr(url, " "); char *s = url; char final_url[512] = ""; fh = NULL; while (space) { space[0] = 0; sprintf(final_url, "%s%s%%20", final_url, s); space[0] = ' '; s = space + 1; space = strstr(s, " "); } sprintf(final_url, "%s%s", final_url, s); //printf("starting download of %s\n", final_url); downloader_pass = 1; downloaded_bytes = 0; total_bytes = 180; startDownload(final_url); while (downloaded_bytes < total_bytes) { startDownload(final_url); } if (downloaded_bytes > 180 && total_bytes <= MEM_BUFFER_SIZE) { fh = fopen(TEMP_DOWNLOAD_NAME, "wb"); fwrite(generic_mem_buffer, 1, downloaded_bytes, fh); } fclose(fh); downloaded_bytes = total_bytes; curl_easy_cleanup(curl_handle); return sceKernelExitDeleteThread(0); } void download_file(char *url, char *text) { SceKernelThreadInfo info; info.size = sizeof(SceKernelThreadInfo); int res = 0; SceUID thd = sceKernelCreateThread("Generic Downloader", &downloadThread, 0x10000100, 0x100000, 0, 0, NULL); sprintf(generic_url, url); sceKernelStartThread(thd, 0, NULL); do { DrawDownloaderDialog(downloader_pass, downloaded_bytes, total_bytes, text, 1, true); res = sceKernelGetThreadInfo(thd, &info); } while (info.status <= SCE_THREAD_DORMANT && res >= 0); }