mirror of
https://github.com/xorgy/mediafire-fuse
synced 2026-01-13 13:14:29 -08:00
initial commit - import mediafire-shell sources
This commit is contained in:
601
cfile.c
Normal file
601
cfile.c
Normal file
@@ -0,0 +1,601 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "cfile.h"
|
||||
#include "strings.h"
|
||||
|
||||
struct _cfile_s
|
||||
{
|
||||
CURL *curl_handle;
|
||||
char *url;
|
||||
|
||||
int mode;
|
||||
uint32_t opts;
|
||||
|
||||
char *get_args;
|
||||
char *post_args;
|
||||
|
||||
size_t (*curl_rx_io) (char *,size_t,size_t,void *);
|
||||
size_t (*curl_tx_io) (char *,size_t,size_t,void *);
|
||||
|
||||
void (*user_io) (cfile_t *);
|
||||
void *userptr;
|
||||
|
||||
void (*progress) (cfile_t *);
|
||||
|
||||
char *rx_buffer;
|
||||
ssize_t rx_buffer_sz;
|
||||
|
||||
char *tx_buffer;
|
||||
ssize_t tx_buffer_sz;
|
||||
|
||||
double rx_length;
|
||||
double rx_count;
|
||||
double tx_length;
|
||||
double tx_count;
|
||||
};
|
||||
|
||||
/*
|
||||
according to libcurl doc the payload of these two callbacks (data)
|
||||
is size * nmemb which is logistically similar to calloc().
|
||||
*/
|
||||
|
||||
/*
|
||||
static size_t
|
||||
curl_send_callback(char *data,size_t size,size_t nmemb,void *user_ptr);
|
||||
*/
|
||||
|
||||
static size_t
|
||||
_cfile_rx_callback(char *data,size_t size,size_t nmemb,void *user_ptr);
|
||||
|
||||
static size_t
|
||||
_cfile_tx_callback(char *data,size_t size,size_t nmemb,void *user_ptr);
|
||||
|
||||
static int
|
||||
_cfile_progress_callback(void *user_ptr,double dltotal,double dlnow,
|
||||
double ultotal,double ulnow);
|
||||
|
||||
|
||||
cfile_t*
|
||||
cfile_create(void)
|
||||
{
|
||||
cfile_t *cfile;
|
||||
CURL *curl_handle;
|
||||
|
||||
curl_handle = curl_easy_init();
|
||||
|
||||
if(curl_handle == NULL) return NULL;
|
||||
|
||||
cfile = (cfile_t*)calloc(1,sizeof(cfile_t));
|
||||
|
||||
cfile->curl_handle = curl_handle;
|
||||
|
||||
cfile->curl_tx_io = &_cfile_tx_callback;
|
||||
curl_easy_setopt(cfile->curl_handle,
|
||||
CURLOPT_READFUNCTION,cfile->curl_tx_io);
|
||||
curl_easy_setopt(cfile->curl_handle,
|
||||
CURLOPT_READDATA,(void*)cfile);
|
||||
|
||||
cfile->curl_rx_io = &_cfile_rx_callback;
|
||||
curl_easy_setopt(cfile->curl_handle,
|
||||
CURLOPT_WRITEFUNCTION,cfile->curl_rx_io);
|
||||
curl_easy_setopt(cfile->curl_handle,
|
||||
CURLOPT_WRITEDATA,(void*)cfile);
|
||||
|
||||
// enable progress reporting
|
||||
curl_easy_setopt(cfile->curl_handle,
|
||||
CURLOPT_NOPROGRESS,0);
|
||||
curl_easy_setopt(cfile->curl_handle,
|
||||
CURLOPT_PROGRESSFUNCTION,_cfile_progress_callback);
|
||||
curl_easy_setopt(cfile->curl_handle,
|
||||
CURLOPT_PROGRESSDATA,(void*)cfile);
|
||||
|
||||
return cfile;
|
||||
}
|
||||
|
||||
int
|
||||
cfile_exec(cfile_t *cfile)
|
||||
{
|
||||
char *url = NULL;
|
||||
size_t len;
|
||||
int retval;
|
||||
|
||||
if(cfile == NULL) return -1;
|
||||
if(cfile->curl_handle == NULL) return -1;
|
||||
|
||||
// use an appended URL if GET arguments are supplied
|
||||
if(cfile->get_args != NULL)
|
||||
{
|
||||
len = strlen(cfile->get_args) + strlen(cfile->url) + 1;
|
||||
|
||||
url = (char*)calloc(1,len);
|
||||
|
||||
strcpy(url,cfile->url);
|
||||
strcat(url,cfile->get_args);
|
||||
|
||||
curl_easy_setopt(cfile->curl_handle,CURLOPT_URL,url);
|
||||
}
|
||||
|
||||
// has the user supplied POST arguments?
|
||||
if(cfile->post_args != NULL)
|
||||
{
|
||||
curl_easy_setopt(cfile->curl_handle,CURLOPT_POSTFIELDS,
|
||||
cfile->post_args);
|
||||
}
|
||||
|
||||
retval = curl_easy_perform(cfile->curl_handle);
|
||||
|
||||
// restore the URL to the cURL handle if it was modified
|
||||
if(url != NULL)
|
||||
{
|
||||
curl_easy_setopt(cfile->curl_handle,CURLOPT_URL,cfile->url);
|
||||
free(url);
|
||||
|
||||
url = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
if the user specified CFILE_MODE_TEXT, ensure that the buffer is
|
||||
NULL terminated.
|
||||
*/
|
||||
if(cfile->mode == CFILE_MODE_TEXT)
|
||||
{
|
||||
if(cfile->rx_buffer[cfile->rx_buffer_sz - 1] != '\0')
|
||||
{
|
||||
cfile->rx_buffer = (char*)realloc(cfile->rx_buffer,
|
||||
cfile->rx_buffer_sz + 1);
|
||||
|
||||
cfile->rx_buffer_sz++;
|
||||
|
||||
cfile->rx_buffer[cfile->rx_buffer_sz - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
cfile_destroy(cfile_t *cfile)
|
||||
{
|
||||
if(cfile == NULL) return;
|
||||
|
||||
if(cfile->url != NULL) free(cfile->url);
|
||||
if(cfile->get_args != NULL) free(cfile->get_args);
|
||||
if(cfile->post_args != NULL) free(cfile->post_args);
|
||||
if(cfile->rx_buffer != NULL) free(cfile->rx_buffer);
|
||||
if(cfile->tx_buffer != NULL) free(cfile->tx_buffer);
|
||||
|
||||
if(cfile->curl_handle != NULL)
|
||||
{
|
||||
curl_easy_cleanup(cfile->curl_handle);
|
||||
}
|
||||
|
||||
free(cfile);
|
||||
}
|
||||
|
||||
void
|
||||
cfile_set_mode(cfile_t *cfile,int mode)
|
||||
{
|
||||
if(cfile == NULL) return;
|
||||
if(mode <= 0) return;
|
||||
|
||||
/*
|
||||
CFILE_MODE_TEXT ensure that the final buffer contents is NULL
|
||||
terminated.
|
||||
|
||||
CFILE_MODE_BINARY does not modify the contents of the final
|
||||
buffer at all.
|
||||
*/
|
||||
|
||||
cfile->mode = mode;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
cfile_set_defaults(cfile_t *cfile)
|
||||
{
|
||||
if(cfile == NULL) return;
|
||||
|
||||
cfile->mode = CFILE_MODE_TEXT;
|
||||
|
||||
// if the protocol supports following redirects, do so
|
||||
cfile_set_opts(cfile,CFILE_OPT_FOLLOW_REDIRECTS);
|
||||
|
||||
// enable SSL engine
|
||||
cfile_set_opts(cfile,CFILE_OPT_ENABLE_SSL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
cfile_set_url(cfile_t *cfile,const char *url)
|
||||
{
|
||||
if(cfile == NULL) return;
|
||||
if(url == NULL) return;
|
||||
|
||||
// make sure curl handle was successfully instantiated
|
||||
if(cfile->curl_handle == NULL) return;
|
||||
|
||||
// reject the request if a source already exists
|
||||
if(cfile->url != NULL) return;
|
||||
|
||||
// escape the url
|
||||
// cfile->url = curl_easy_escape(cfile->url,url,0);
|
||||
|
||||
cfile->url = strdup(url);
|
||||
|
||||
curl_easy_setopt(cfile->curl_handle,CURLOPT_URL,cfile->url);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
cfile_get_url(cfile_t *cfile,char *buf,size_t buf_sz)
|
||||
{
|
||||
if(cfile == NULL) return -1;
|
||||
if(cfile->url == NULL) return -1;
|
||||
if(buf == NULL) return -1;
|
||||
if(buf_sz <=1 ) return -1;
|
||||
|
||||
strncpy(buf,cfile->url,buf_sz-1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
cfile_set_args(cfile_t *cfile,int type,const char *args)
|
||||
{
|
||||
int len;
|
||||
|
||||
if(cfile == NULL) return;
|
||||
if(args == NULL) return;
|
||||
if(cfile->curl_handle == NULL) return;
|
||||
|
||||
len = strlen(args);
|
||||
if(len == 0) return;
|
||||
|
||||
if(type == CFILE_ARGS_POST)
|
||||
{
|
||||
cfile->post_args = (char*)realloc(cfile->post_args,len + 1);
|
||||
strcpy(cfile->post_args,args);
|
||||
return;
|
||||
}
|
||||
|
||||
if(type == CFILE_ARGS_GET)
|
||||
{
|
||||
cfile->get_args = (char*)realloc(cfile->get_args,len + 1);
|
||||
strcpy(cfile->get_args,args);
|
||||
return;
|
||||
}
|
||||
|
||||
// todo: handle custome headers
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
cfile_add_args(cfile_t *cfile,int type,const char *args)
|
||||
{
|
||||
char *new_args;
|
||||
|
||||
if(cfile == NULL) return;
|
||||
|
||||
if(type == CFILE_ARGS_POST)
|
||||
{
|
||||
if(cfile->post_args == NULL)
|
||||
{
|
||||
cfile_set_args(cfile,CFILE_ARGS_POST,args);
|
||||
return;
|
||||
}
|
||||
|
||||
new_args = strdup_printf("%s%s",cfile->post_args,(char*)args);
|
||||
free(cfile->post_args);
|
||||
cfile->post_args = new_args;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(type == CFILE_ARGS_GET)
|
||||
{
|
||||
if(cfile->get_args == NULL)
|
||||
{
|
||||
cfile_set_args(cfile,CFILE_ARGS_GET,args);
|
||||
return;
|
||||
}
|
||||
|
||||
new_args = strdup_printf("%s%s",cfile->get_args,(char*)args);
|
||||
free(cfile->get_args);
|
||||
cfile->get_args = new_args;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
cfile_set_opts(cfile_t *cfile,uint32_t opts)
|
||||
{
|
||||
if(cfile == NULL) return -1;
|
||||
if(cfile->curl_handle == NULL) return -1;
|
||||
|
||||
cfile->opts = opts;
|
||||
|
||||
if(cfile->opts & CFILE_OPT_FOLLOW_REDIRECTS)
|
||||
{
|
||||
curl_easy_setopt(cfile->curl_handle,CURLOPT_FOLLOWLOCATION,1);
|
||||
}
|
||||
else
|
||||
{
|
||||
curl_easy_setopt(cfile->curl_handle,CURLOPT_FOLLOWLOCATION,0);
|
||||
}
|
||||
|
||||
if(cfile->opts & CFILE_OPT_ENABLE_SSL)
|
||||
{
|
||||
curl_easy_setopt(cfile->curl_handle,CURLOPT_SSLENGINE,NULL);
|
||||
curl_easy_setopt(cfile->curl_handle,CURLOPT_SSLENGINE_DEFAULT,1L);
|
||||
|
||||
// libcurl will use built-in CA certificate if none specified
|
||||
|
||||
//curl_easy_setopt(cfile->curl_handle,CURLOPT_SSLCERTTYPE,"PEM");
|
||||
//curl_easy_setopt(cfile->curl_handle,CURLOPT_CAINFO,"cacert.pem");
|
||||
}
|
||||
|
||||
if(cfile->opts & CFILE_OPT_ENABLE_SSL_LAX)
|
||||
{
|
||||
curl_easy_setopt(cfile->curl_handle,CURLOPT_SSL_VERIFYPEER,0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
cfile_set_io_func(cfile_t *cfile,CFileFunc user_io)
|
||||
{
|
||||
if(cfile == NULL) return;
|
||||
|
||||
cfile->user_io = user_io;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
cfile_set_progress_func(cfile_t *cfile,CFileFunc progress)
|
||||
{
|
||||
if(cfile == NULL) return;
|
||||
|
||||
cfile->progress = progress;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const char*
|
||||
cfile_get_rx_buffer(cfile_t *cfile)
|
||||
{
|
||||
if(cfile == NULL) return NULL;
|
||||
if(cfile->curl_handle == NULL) return NULL;
|
||||
|
||||
return cfile->rx_buffer;
|
||||
}
|
||||
|
||||
size_t
|
||||
cfile_get_rx_buffer_size(cfile_t *cfile)
|
||||
{
|
||||
if(cfile == NULL) return 0;
|
||||
|
||||
return cfile->rx_buffer_sz;
|
||||
}
|
||||
|
||||
const char*
|
||||
cfile_get_tx_buffer(cfile_t *cfile)
|
||||
{
|
||||
if(cfile == NULL) return NULL;
|
||||
if(cfile->curl_handle == NULL) return NULL;
|
||||
|
||||
return cfile->tx_buffer;
|
||||
}
|
||||
|
||||
size_t
|
||||
cfile_get_tx_buffer_size(cfile_t *cfile)
|
||||
{
|
||||
if(cfile == NULL) return 0;
|
||||
|
||||
return cfile->tx_buffer_sz;
|
||||
}
|
||||
|
||||
void
|
||||
cfile_reset_rx_buffer(cfile_t *cfile)
|
||||
{
|
||||
if(cfile == NULL) return;
|
||||
|
||||
if(cfile->rx_buffer != NULL)
|
||||
{
|
||||
free(cfile->rx_buffer);
|
||||
cfile->rx_buffer = NULL;
|
||||
}
|
||||
|
||||
cfile->rx_buffer_sz = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
cfile_reset_tx_buffer(cfile_t *cfile)
|
||||
{
|
||||
if(cfile == NULL) return;
|
||||
|
||||
if(cfile->tx_buffer != NULL)
|
||||
{
|
||||
free(cfile->tx_buffer);
|
||||
cfile->tx_buffer = NULL;
|
||||
}
|
||||
|
||||
cfile->tx_buffer_sz = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
double
|
||||
cfile_get_rx_count(cfile_t *cfile)
|
||||
{
|
||||
if(cfile == NULL) return 0;
|
||||
if(cfile->curl_handle == NULL) return 0;
|
||||
|
||||
return cfile->rx_count;
|
||||
}
|
||||
|
||||
double
|
||||
cfile_get_rx_length(cfile_t *cfile)
|
||||
{
|
||||
if(cfile == NULL) return 0;
|
||||
if(cfile->curl_handle == NULL) return 0;
|
||||
|
||||
return cfile->rx_length;
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
cfile_get_tx_count(cfile_t *cfile)
|
||||
{
|
||||
if(cfile == NULL) return 0;
|
||||
if(cfile->curl_handle == NULL) return 0;
|
||||
|
||||
return cfile->tx_count;
|
||||
}
|
||||
|
||||
double
|
||||
cfile_get_tx_length(cfile_t *cfile)
|
||||
{
|
||||
if(cfile == NULL) return 0;
|
||||
if(cfile->curl_handle == NULL) return 0;
|
||||
|
||||
return cfile->tx_length;
|
||||
}
|
||||
|
||||
void
|
||||
cfile_set_userptr(cfile_t *cfile,void *anything)
|
||||
{
|
||||
if(cfile == NULL) return;
|
||||
|
||||
cfile->userptr = anything;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void*
|
||||
cfile_get_userptr(cfile_t *cfile)
|
||||
{
|
||||
if(cfile == NULL) return NULL;
|
||||
|
||||
return cfile->userptr;
|
||||
}
|
||||
|
||||
static size_t
|
||||
_cfile_tx_callback(char *data,size_t size,size_t nmemb,void *user_ptr)
|
||||
{
|
||||
cfile_t *cfile;
|
||||
size_t data_sz = 0;
|
||||
char *buffer_tail;
|
||||
|
||||
/*
|
||||
Your function must return the actual number of bytes that you stored
|
||||
in that memory area. Returning 0 will signal end-of-file to the
|
||||
library and cause it to stop the current transfer.
|
||||
*/
|
||||
if(user_ptr == NULL) return 0;
|
||||
|
||||
cfile = (cfile_t*)user_ptr;
|
||||
data_sz = size * nmemb;
|
||||
|
||||
if(data_sz > 0)
|
||||
{
|
||||
cfile->tx_buffer = (char*)realloc(cfile->tx_buffer,
|
||||
cfile->tx_buffer_sz);
|
||||
|
||||
buffer_tail = cfile->tx_buffer + cfile->tx_buffer_sz;
|
||||
|
||||
memcpy(buffer_tail,data,data_sz);
|
||||
|
||||
cfile->tx_buffer_sz += data_sz;
|
||||
}
|
||||
|
||||
if(cfile->user_io != NULL)
|
||||
{
|
||||
cfile->user_io(cfile);
|
||||
}
|
||||
|
||||
if(cfile->progress != NULL)
|
||||
{
|
||||
cfile->progress(cfile);
|
||||
}
|
||||
|
||||
return data_sz;
|
||||
}
|
||||
|
||||
static size_t
|
||||
_cfile_rx_callback(char *data,size_t size,size_t nmemb,void *user_ptr)
|
||||
{
|
||||
cfile_t *cfile;
|
||||
size_t data_sz = 0;
|
||||
char *buffer_tail = NULL;
|
||||
|
||||
/*
|
||||
Your function must return the actual number of bytes that you stored
|
||||
in that memory area. Returning 0 will signal end-of-file to the
|
||||
library and cause it to stop the current transfer.
|
||||
*/
|
||||
if(user_ptr == NULL) return 0;
|
||||
|
||||
cfile = (cfile_t*)user_ptr;
|
||||
data_sz = size * nmemb;
|
||||
|
||||
if(data_sz > 0)
|
||||
{
|
||||
cfile->rx_buffer = (char*)realloc(cfile->rx_buffer,
|
||||
cfile->rx_buffer_sz + data_sz);
|
||||
|
||||
buffer_tail = cfile->rx_buffer + cfile->rx_buffer_sz;
|
||||
|
||||
memcpy(buffer_tail,data,data_sz);
|
||||
|
||||
cfile->rx_buffer_sz += data_sz;
|
||||
}
|
||||
|
||||
if(cfile->user_io != NULL)
|
||||
{
|
||||
cfile->user_io(cfile);
|
||||
}
|
||||
|
||||
if(cfile->progress != NULL)
|
||||
{
|
||||
cfile->progress(cfile);
|
||||
}
|
||||
|
||||
return data_sz;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
_cfile_progress_callback(void *user_ptr,double dltotal,double dlnow,
|
||||
double ultotal,double ulnow)
|
||||
{
|
||||
cfile_t *cfile;
|
||||
|
||||
if(user_ptr == NULL) return 0;
|
||||
|
||||
cfile = (cfile_t*)user_ptr;
|
||||
|
||||
cfile->tx_length = ultotal;
|
||||
cfile->tx_count = ulnow;
|
||||
|
||||
cfile->rx_length = dltotal;
|
||||
cfile->rx_count = dlnow;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user