#include "webdownload.h" #include "qcommon.h" #include #include static int Web_Init(void); static void Web_Cleanup(void); // to get the size and mime type before the download we can use that // http://curl.haxx.se/mail/lib-2002-05/0036.html static CURL *curl=NULL; static char curl_err[1024]; static int (*progress)(double)=NULL; static size_t Write(void *ptr, size_t size, size_t nmemb, void *stream) { FILE *f; //Com_Printf("name %s path %s\n", data->name, data->path); f=fopen((char *)stream,"ab"); if(f==NULL) return size*nmemb; // weird //fwrite(ptr,size,nmemb,(FILE *) stream); fwrite(ptr,size,nmemb,f); fclose(f); return size*nmemb; } static int Progress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) { // callback if(progress!=NULL) { if(progress(dlnow/dltotal)!=0) return 1; // we abort } //Com_Printf("Progress: %2.2f\n",dlnow*100.0/dltotal); return 0; } static void Web_Cleanup(void) { if(curl!=NULL) { /* always cleanup */ curl_easy_cleanup(curl); curl=NULL; // reset callback progress=NULL; } } static int Web_Init(void) { CURLcode code; if(curl!=NULL) { Web_Cleanup(); } // reinit curl = curl_easy_init(); // reset callback progress=NULL; // http://curl.haxx.se/libcurl/c/curl_easy_setopt.html /* init some options of curl */ code=curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_err); if( code != CURLE_OK ) { Com_Printf("Failed to set error buffer\n"); return 0; } code=curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); if( code != CURLE_OK ) { Com_Printf("Failed to set NoProgress\n"); return 0; } code=curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1 ); if( code != CURLE_OK ) { Com_Printf("Failed to set libcurl nosignal mode\n"); return 0; } code=curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); if( code != CURLE_OK ) { Com_Printf("Failed to set FollowLocation\n"); return 0; } code=curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 2); if( code != CURLE_OK ) { Com_Printf("Failed to set Max Redirection\n"); return 0; } code=curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Write); if( code != CURLE_OK ) { Com_Printf("Failed to set writer callback function\n"); return 0; } code=curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, Progress); if( code != CURLE_OK ) { Com_Printf("Failed to set progress callback function\n"); return 0; } // same as in cvar version, qcommon.c if( versioncvar && versioncvar->string && strlen(versioncvar->string) ) code=curl_easy_setopt(curl, CURLOPT_USERAGENT, va("%s %s", APPLICATION, versioncvar->string)); else code=curl_easy_setopt(curl, CURLOPT_USERAGENT, APPLICATION); if( code != CURLE_OK ) { Com_Printf("Failed to set UserAgent\n"); return 0; } code=curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1); if( code != CURLE_OK ) { Com_Printf("Failed to set fail on error\n"); return 0; } return 1; } int Web_Get(const char *url, const char *referer, const char *name, int resume, int timeout, int (*_progress)(double)) { CURLcode code; FILE *f; unsigned int fsize; // init/reinit curl Web_Init(); code=curl_easy_setopt(curl, CURLOPT_URL, url); if( code != CURLE_OK ) { Com_Printf("Failed to set url\n");; return 0; } // same as in cvar version, qcommon.c if( referer ) { code=curl_easy_setopt(curl, CURLOPT_REFERER, referer); if( code != CURLE_OK ) { Com_Printf("Failed to set Referer\n"); return 0; } } // connection timeout code=curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout ); if( code != CURLE_OK ) { Com_Printf("Failed to set libcurl connection timeout\n"); return 0; } code=curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout ); if( code != CURLE_OK ) { Com_Printf("Failed to set libcurl global timeout\n"); return 0; } if(resume==1) { // test if file exist if((f=fopen(name,"r"))==NULL) { // file does not exist goto new_file; } // the file exist // get the size fsize=fseek(f,0,SEEK_END); fclose(f); code=curl_easy_setopt(curl, CURLOPT_RESUME_FROM, fsize); if( code != CURLE_OK ) { Com_Printf("Failed to set file resume from length\n");; return 0; } // file exist all good } new_file: code=curl_easy_setopt(curl, CURLOPT_FILE, name); //code=curl_easy_setopt(curl, CURLOPT_FILE, &f); if( code != CURLE_OK ) { Com_Printf("Failed to set writer data\n");; return 0; } Com_Printf("Downloading %s from %s\n",name,url);; // set callback progress=_progress; code=curl_easy_perform(curl); if( code != CURLE_OK ) { Com_Printf("Failed to download %s from %s\n",name,url);; Com_Printf("Error: %s\n",curl_err);; Web_Cleanup(); return 0; } Web_Cleanup(); return 1; }