freearc/clibs/URL.cpp

134 lines
3.8 KiB
C++

#include "URL.h"
#include "Compression/Compression.h"
#define FREEARC_USER_AGENT "FreeArc/0.67"
// ****************************************************************************
// ** URL reading library
// ****************************************************************************
#ifdef FREEARC_NOURL
void url_setup_proxy(char *_proxy) {}
void url_setup_bypass_list(char *_bypass_list) {}
URL *url_open(char *_url) { return NULL; }
int url_readp(URL *url, int64 offset, char *buf, int size) { return -1; }
void url_close(URL *url) {}
#else
char *proxy = NULL;
void url_setup_proxy (char *_proxy)
{
proxy = strequ(_proxy,"--") ? NULL : strdup_msg (_proxy);
}
void url_setup_bypass_list (char *_bypass_list)
{
}
static size_t NoWriteCallback(void *ptr, size_t size, size_t nmemb, void *data)
{
return -1;
}
static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
{
char **buf = (char **) data;
memcpy (*buf, ptr, size*nmemb);
*buf += size*nmemb;
return size*nmemb;
}
URL* url_open (char *_url)
{
static bool curl_inited = FALSE;
if (!curl_inited) curl_global_init(CURL_GLOBAL_ALL), curl_inited=TRUE;
URL *url = (URL*) malloc(sizeof(URL));
if (!url) return NULL;
url->url = strdup_msg (_url);
url->curpos = 0;
/* init the curl session */
url->curl_handle = curl_easy_init();
/* set proxy if it was specified by user */
if (proxy) curl_easy_setopt (url->curl_handle, CURLOPT_PROXY, proxy);
/* some servers don't like requests that are made without a user-agent
field, so we provide one */
curl_easy_setopt (url->curl_handle, CURLOPT_USERAGENT, FREEARC_USER_AGENT);
/* specify URL to get */
curl_easy_setopt (url->curl_handle, CURLOPT_URL, url->url);
// Get file size
curl_easy_setopt (url->curl_handle, CURLOPT_WRITEFUNCTION, NoWriteCallback);
CURLcode res = curl_easy_perform (url->curl_handle);
if (CURLE_OK!=res && CURLE_WRITE_ERROR!=res) {url_close(url); return NULL;}
long response;
curl_easy_getinfo (url->curl_handle, CURLINFO_RESPONSE_CODE, &response);
if (response!=200 && response!=301 && response!=302) {url_close(url); return NULL;}
double size;
res = curl_easy_getinfo (url->curl_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &size);
if (CURLE_OK != res) {url_close(url); return NULL;}
url->size = (int64)size;
/* send all data read to this function */
curl_easy_setopt (url->curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
return url;
}
// Check existence of given url
int url_exists (char *_url)
{
URL *url = url_open(_url);
url_close(url);
return url!=NULL;
}
int url_readp (URL *url, int64 offset, char *buf, int size)
{
if (size==0) return 0;
if (!url) return -1;
/* specify byte range to get */
char Range[100];
sprintf (Range, "%.0lf-%.0lf", double(offset), double(offset+size-1));
curl_easy_setopt (url->curl_handle, CURLOPT_RANGE, Range);
/* we pass address of 'current write pointer' variable to the callback function */
char *ptr = buf;
curl_easy_setopt (url->curl_handle, CURLOPT_WRITEDATA, (void *)&ptr);
/* get it! */
curl_easy_perform (url->curl_handle);
return ptr-buf;
}
void url_reset (URL *url)
{
}
void url_close (URL *url)
{
if (!url) return;
/* cleanup curl stuff */
curl_easy_cleanup (url->curl_handle);
free (url->url);
free (url);
}
#endif
int64 url_size (URL *url) {return url? url->size : 0;}
int64 url_pos (URL *url) {return url? url->curpos : 0;}
void url_seek (URL *url, int64 newpos) {if (url) url->curpos = newpos, url_reset(url);}
int url_read (URL *url, char *buf, int size) {return url? url_readp (url, url->curpos, buf, size) : -1;}