diff options
Diffstat (limited to 'lib/curl.c')
-rw-r--r-- | lib/curl.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/lib/curl.c b/lib/curl.c new file mode 100644 index 0000000..6eff24c --- /dev/null +++ b/lib/curl.c @@ -0,0 +1,176 @@ +/* + * curl.c: + * + * See the README file for copyright information and how to reach the author. + * + */ + +#include <curl/curl.h> + +#include "common.h" +#include "config.h" + +//*************************************************************************** +// Callbacks +//*************************************************************************** + +static size_t WriteMemoryCallback(void* ptr, size_t size, size_t nmemb, void* data) +{ + size_t realsize = size * nmemb; + struct MemoryStruct* mem = (struct MemoryStruct*)data; + + if (mem->memory) + mem->memory = (char*)realloc(mem->memory, mem->size + realsize + 1); + else + mem->memory = (char*)malloc(mem->size + realsize + 1); + + if (mem->memory) + { + memcpy (&(mem->memory[mem->size]), ptr, realsize); + mem->size += realsize; + mem->memory[mem->size] = 0; + } + + return realsize; +} + +static size_t WriteHeaderCallback(void* ptr, size_t size, size_t nmemb, void* data) +{ + size_t realsize = size * nmemb; + struct MemoryStruct* mem = (struct MemoryStruct*)data; + char* p; + + if (ptr) + { + // get filename + { + // Content-Disposition: attachment; filename="20140103_20140103_de_qy.zip" + + const char* attribute = "Content-disposition: "; + + if ((p = strcasestr((char*)ptr, attribute))) + { + if (p = strcasestr(p, "filename=")) + { + p += strlen("filename="); + + tell(4, "found filename at [%s]", p); + + if (*p == '"') + p++; + + sprintf(mem->name, "%s", p); + + if ((p = strchr(mem->name, '\n'))) + *p = 0; + + if ((p = strchr(mem->name, '\r'))) + *p = 0; + + if ((p = strchr(mem->name, '"'))) + *p = 0; + + tell(4, "set name to '%s'", mem->name); + } + } + } + + // since some sources update "ETag" an "Last-Modified:" without changing the contents + // we have to use "Content-Length:" to check for updates :( + { + const char* attribute = "Content-Length: "; + + if ((p = strcasestr((char*)ptr, attribute))) + { + sprintf(mem->tag, "%s", p+strlen(attribute)); + + if ((p = strchr(mem->tag, '\n'))) + *p = 0; + + if ((p = strchr(mem->tag, '\r'))) + *p = 0; + + if ((p = strchr(mem->tag, '"'))) + *p = 0; + } + } + } + + return realsize; +} + +//*************************************************************************** +// Download File +//*************************************************************************** + +int downloadFile(const char* url, int& size, MemoryStruct* data, int timeout, const char* userAgent) +{ + CURL* curl_handle; + long code; + CURLcode res = CURLE_OK; + + size = 0; + + // init curl + + if (curl_global_init(CURL_GLOBAL_ALL) != 0) + { + tell(0, "Error, something went wrong with curl_global_init()"); + + return fail; + } + + curl_handle = curl_easy_init(); + + if (!curl_handle) + { + tell(0, "Error, unable to get handle from curl_easy_init()"); + + return fail; + } + + if (EPG2VDRConfig.useproxy) + { + curl_easy_setopt(curl_handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); + curl_easy_setopt(curl_handle, CURLOPT_PROXY, EPG2VDRConfig.httpproxy); // Specify HTTP proxy + } + + curl_easy_setopt(curl_handle, CURLOPT_URL, url); // Specify URL to get + curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 0); // don't follow redirects + curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); // Send all data to this function + curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void*)data); // Pass our 'data' struct to the callback function + curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, WriteHeaderCallback); // Send header to this function + curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, (void*)data); // Pass some header details to this struct + curl_easy_setopt(curl_handle, CURLOPT_MAXFILESIZE, 100*1024*1024); // Set maximum file size to get (bytes) + curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1); // No progress meter + curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1); // No signaling + curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, timeout); // Set timeout + curl_easy_setopt(curl_handle, CURLOPT_NOBODY, data->headerOnly ? 1 : 0); // + curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, userAgent); // Some servers don't like requests + // that are made without a user-agent field + // perform http-get + + if ((res = curl_easy_perform(curl_handle)) != 0) + { + data->clear(); + + tell(1, "Error, download failed; %s (%d)", + curl_easy_strerror(res), res); + curl_easy_cleanup(curl_handle); // Cleanup curl stuff + + return fail; + } + + curl_easy_getinfo(curl_handle, CURLINFO_HTTP_CODE, &code); + curl_easy_cleanup(curl_handle); // cleanup curl stuff + + if (code == 404) + { + data->clear(); + return fail; + } + + size = data->size; + + return success; +} |