mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 23:58:49 -05:00
Multiple URL support added
This commit is contained in:
parent
53c27c7722
commit
14ca732a8f
701
src/main.c
701
src/main.c
@ -39,7 +39,6 @@
|
|||||||
#include "writeout.h"
|
#include "writeout.h"
|
||||||
|
|
||||||
#define CURLseparator "--_curl_--"
|
#define CURLseparator "--_curl_--"
|
||||||
#define MIMEseparator "_curl_"
|
|
||||||
|
|
||||||
/* This define make use of the "Curlseparator" as opposed to the
|
/* This define make use of the "Curlseparator" as opposed to the
|
||||||
MIMEseparator. We might add support for the latter one in the
|
MIMEseparator. We might add support for the latter one in the
|
||||||
@ -222,6 +221,20 @@ static void helpf(char *fmt, ...)
|
|||||||
fprintf(stderr, "curl: try 'curl --help' for more information\n");
|
fprintf(stderr, "curl: try 'curl --help' for more information\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A chain of these nodes contain URL to get and where to put the URL's
|
||||||
|
* contents.
|
||||||
|
*/
|
||||||
|
struct getout {
|
||||||
|
struct getout *next;
|
||||||
|
char *url;
|
||||||
|
char *outfile;
|
||||||
|
int flags;
|
||||||
|
};
|
||||||
|
#define GETOUT_OUTFILE (1<<0) /* set when outfile is deemed done */
|
||||||
|
#define GETOUT_URL (1<<1) /* set when URL is deemed done */
|
||||||
|
#define GETOUT_USEREMOTE (1<<2) /* use remote file name locally */
|
||||||
|
|
||||||
static void help(void)
|
static void help(void)
|
||||||
{
|
{
|
||||||
printf(CURL_ID "%s\n"
|
printf(CURL_ID "%s\n"
|
||||||
@ -303,9 +316,7 @@ struct Configurable {
|
|||||||
char *referer;
|
char *referer;
|
||||||
long timeout;
|
long timeout;
|
||||||
long maxredirs;
|
long maxredirs;
|
||||||
char *outfile;
|
|
||||||
char *headerfile;
|
char *headerfile;
|
||||||
char remotefile;
|
|
||||||
char *ftpport;
|
char *ftpport;
|
||||||
char *iface;
|
char *iface;
|
||||||
unsigned short porttouse;
|
unsigned short porttouse;
|
||||||
@ -320,7 +331,13 @@ struct Configurable {
|
|||||||
bool configread;
|
bool configread;
|
||||||
bool proxytunnel;
|
bool proxytunnel;
|
||||||
long conf;
|
long conf;
|
||||||
char *url;
|
|
||||||
|
struct getout *url_list; /* point to the first node */
|
||||||
|
struct getout *url_last; /* point to the last/current node */
|
||||||
|
|
||||||
|
struct getout *url_get; /* point to the node to fill in URL */
|
||||||
|
struct getout *url_out; /* point to the node to fill in outfile */
|
||||||
|
|
||||||
char *cert;
|
char *cert;
|
||||||
char *cacert;
|
char *cacert;
|
||||||
char *cert_passwd;
|
char *cert_passwd;
|
||||||
@ -426,6 +443,29 @@ static char *file2memory(FILE *file, long *size)
|
|||||||
return NULL; /* no string */
|
return NULL; /* no string */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct getout *new_getout(struct Configurable *config)
|
||||||
|
{
|
||||||
|
struct getout *node =malloc(sizeof(struct getout));
|
||||||
|
struct getout *last= config->url_last;
|
||||||
|
if(node) {
|
||||||
|
/* clear the struct */
|
||||||
|
memset(node, 0, sizeof(struct getout));
|
||||||
|
|
||||||
|
/* append this new node last in the list */
|
||||||
|
if(last)
|
||||||
|
last->next = node;
|
||||||
|
else
|
||||||
|
config->url_list = node; /* first node */
|
||||||
|
|
||||||
|
/* move the last pointer */
|
||||||
|
config->url_last = node;
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PARAM_OK,
|
PARAM_OK,
|
||||||
PARAM_OPTION_AMBIGUOUS,
|
PARAM_OPTION_AMBIGUOUS,
|
||||||
@ -610,7 +650,30 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
|
|||||||
break;
|
break;
|
||||||
case '5':
|
case '5':
|
||||||
/* the URL! */
|
/* the URL! */
|
||||||
GetStr(&config->url, nextarg);
|
{
|
||||||
|
struct getout *url;
|
||||||
|
if(config->url_get || (config->url_get=config->url_list)) {
|
||||||
|
/* there's a node here, if it already is filled-in continue to find
|
||||||
|
an "empty" node */
|
||||||
|
while(config->url_get && (config->url_get->flags&GETOUT_URL))
|
||||||
|
config->url_get = config->url_get->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now there might or might not be an available node to fill in! */
|
||||||
|
|
||||||
|
if(config->url_get)
|
||||||
|
/* existing node */
|
||||||
|
url = config->url_get;
|
||||||
|
else
|
||||||
|
/* there was no free node, create one! */
|
||||||
|
url=new_getout(config);
|
||||||
|
|
||||||
|
if(url) {
|
||||||
|
/* fill in the URL */
|
||||||
|
GetStr(&url->url, nextarg);
|
||||||
|
url->flags |= GETOUT_URL;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case '#': /* added 19990617 larsa */
|
case '#': /* added 19990617 larsa */
|
||||||
config->progressmode ^= CURL_PROGRESS_BAR;
|
config->progressmode ^= CURL_PROGRESS_BAR;
|
||||||
@ -794,12 +857,37 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
|
|||||||
config->nobuffer ^= 1;
|
config->nobuffer ^= 1;
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
/* output file */
|
|
||||||
GetStr(&config->outfile, nextarg); /* write to this file */
|
|
||||||
break;
|
|
||||||
case 'O':
|
case 'O':
|
||||||
/* output file */
|
/* output file */
|
||||||
config->remotefile ^= TRUE;
|
{
|
||||||
|
struct getout *url;
|
||||||
|
if(config->url_out || (config->url_out=config->url_list)) {
|
||||||
|
/* there's a node here, if it already is filled-in continue to find
|
||||||
|
an "empty" node */
|
||||||
|
while(config->url_out && (config->url_out->flags&GETOUT_OUTFILE))
|
||||||
|
config->url_out = config->url_out->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now there might or might not be an available node to fill in! */
|
||||||
|
|
||||||
|
if(config->url_out)
|
||||||
|
/* existing node */
|
||||||
|
url = config->url_out;
|
||||||
|
else
|
||||||
|
/* there was no free node, create one! */
|
||||||
|
url=new_getout(config);
|
||||||
|
|
||||||
|
if(url) {
|
||||||
|
/* fill in the outfile */
|
||||||
|
if('o' == letter)
|
||||||
|
GetStr(&url->outfile, nextarg);
|
||||||
|
else {
|
||||||
|
url->outfile=NULL; /* leave it */
|
||||||
|
url->flags |= GETOUT_USEREMOTE;
|
||||||
|
}
|
||||||
|
url->flags |= GETOUT_OUTFILE;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
/* This makes the FTP sessions use PORT instead of PASV */
|
/* This makes the FTP sessions use PORT instead of PASV */
|
||||||
@ -1253,8 +1341,6 @@ void progressbarinit(struct ProgressData *bar)
|
|||||||
|
|
||||||
void free_config_fields(struct Configurable *config)
|
void free_config_fields(struct Configurable *config)
|
||||||
{
|
{
|
||||||
if(config->url)
|
|
||||||
free(config->url);
|
|
||||||
if(config->userpwd)
|
if(config->userpwd)
|
||||||
free(config->userpwd);
|
free(config->userpwd);
|
||||||
if(config->postfields)
|
if(config->postfields)
|
||||||
@ -1271,8 +1357,6 @@ void free_config_fields(struct Configurable *config)
|
|||||||
free(config->krb4level);
|
free(config->krb4level);
|
||||||
if(config->headerfile)
|
if(config->headerfile)
|
||||||
free(config->headerfile);
|
free(config->headerfile);
|
||||||
if(config->outfile)
|
|
||||||
free(config->outfile);
|
|
||||||
if(config->ftpport)
|
if(config->ftpport)
|
||||||
free(config->ftpport);
|
free(config->ftpport);
|
||||||
if(config->infile)
|
if(config->infile)
|
||||||
@ -1300,6 +1384,8 @@ operate(struct Configurable *config, int argc, char *argv[])
|
|||||||
char errorbuffer[CURL_ERROR_SIZE];
|
char errorbuffer[CURL_ERROR_SIZE];
|
||||||
char useragent[128]; /* buah, we don't want a larger default user agent */
|
char useragent[128]; /* buah, we don't want a larger default user agent */
|
||||||
struct ProgressData progressbar;
|
struct ProgressData progressbar;
|
||||||
|
struct getout *urlnode;
|
||||||
|
struct getout *nextnode;
|
||||||
|
|
||||||
struct OutStruct outs;
|
struct OutStruct outs;
|
||||||
struct OutStruct heads;
|
struct OutStruct heads;
|
||||||
@ -1323,9 +1409,6 @@ operate(struct Configurable *config, int argc, char *argv[])
|
|||||||
int res;
|
int res;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
outs.stream = stdout;
|
|
||||||
outs.config = config;
|
|
||||||
|
|
||||||
#ifdef MALLOCDEBUG
|
#ifdef MALLOCDEBUG
|
||||||
/* this sends all memory debug messages to a logfile named memdump */
|
/* this sends all memory debug messages to a logfile named memdump */
|
||||||
curl_memdebug("memdump");
|
curl_memdebug("memdump");
|
||||||
@ -1356,7 +1439,7 @@ operate(struct Configurable *config, int argc, char *argv[])
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((argc < 2) && !config->url) {
|
if ((argc < 2) && !config->url_list) {
|
||||||
helpf(NULL);
|
helpf(NULL);
|
||||||
return CURLE_FAILED_INIT;
|
return CURLE_FAILED_INIT;
|
||||||
}
|
}
|
||||||
@ -1405,20 +1488,15 @@ operate(struct Configurable *config, int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(url) {
|
bool used;
|
||||||
helpf("only one URL is supported!\n");
|
/* just add the URL please */
|
||||||
return CURLE_FAILED_INIT;
|
res = getparameter("--url", argv[i], &used, config);
|
||||||
}
|
if(res)
|
||||||
url = argv[i];
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if no URL was specified and there was one in the config file, get that
|
if(!config->url_list) {
|
||||||
one */
|
|
||||||
if(!url && config->url)
|
|
||||||
url = config->url;
|
|
||||||
|
|
||||||
if(!url) {
|
|
||||||
helpf("no URL specified!\n");
|
helpf("no URL specified!\n");
|
||||||
return CURLE_FAILED_INIT;
|
return CURLE_FAILED_INIT;
|
||||||
}
|
}
|
||||||
@ -1430,331 +1508,336 @@ operate(struct Configurable *config, int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
allocuseragent = TRUE;
|
allocuseragent = TRUE;
|
||||||
#if 0
|
|
||||||
fprintf(stderr, "URL: %s PROXY: %s\n", url, config->proxy?config->proxy:"none");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* expand '{...}' and '[...]' expressions and return total number of URLs
|
urlnode = config->url_list;
|
||||||
in pattern set */
|
|
||||||
res = glob_url(&urls, url, &urlnum);
|
|
||||||
if(res != CURLE_OK)
|
|
||||||
return res;
|
|
||||||
|
|
||||||
/* save outfile pattern befor expansion */
|
/* loop through the list of given URLs */
|
||||||
outfiles = config->outfile?strdup(config->outfile):NULL;
|
while(urlnode) {
|
||||||
|
|
||||||
if (!outfiles && !config->remotefile && urlnum > 1) {
|
/* get the full URL */
|
||||||
#ifdef CURL_SEPARATORS
|
url=urlnode->url;
|
||||||
/* multiple files extracted to stdout, insert separators! */
|
|
||||||
separator = 1;
|
/* default output stream is stdout */
|
||||||
#endif
|
outs.stream = stdout;
|
||||||
#ifdef MIME_SEPARATORS
|
outs.config = config;
|
||||||
/* multiple files extracted to stdout, insert MIME separators! */
|
|
||||||
separator = 1;
|
/* expand '{...}' and '[...]' expressions and return total number of URLs
|
||||||
printf("MIME-Version: 1.0\n");
|
in pattern set */
|
||||||
printf("Content-Type: multipart/mixed; boundary=%s\n\n", MIMEseparator);
|
res = glob_url(&urls, url, &urlnum);
|
||||||
#endif
|
if(res != CURLE_OK)
|
||||||
}
|
return res;
|
||||||
for (i = 0; (url = next_url(urls)); ++i) {
|
|
||||||
if (config->outfile) {
|
/* save outfile pattern before expansion */
|
||||||
free(config->outfile);
|
outfiles = urlnode->outfile?strdup(urlnode->outfile):NULL;
|
||||||
config->outfile = outfiles?strdup(outfiles):NULL;
|
|
||||||
|
if (outfiles && strequal(outfiles, "-") && urlnum > 1) {
|
||||||
|
/* multiple files extracted to stdout, insert separators! */
|
||||||
|
separator = 1;
|
||||||
}
|
}
|
||||||
|
for (i = 0; (url = next_url(urls)); ++i) {
|
||||||
|
char *outfile;
|
||||||
|
outfile = outfiles?strdup(outfiles):NULL;
|
||||||
|
|
||||||
|
|
||||||
if (config->outfile || config->remotefile) {
|
if((urlnode->flags&GETOUT_USEREMOTE) ||
|
||||||
/*
|
(outfile && !strequal("-", outfile)) ) {
|
||||||
* We have specified a file name to store the result in, or we have
|
|
||||||
* decided we want to use the remote file name.
|
/*
|
||||||
*/
|
* We have specified a file name to store the result in, or we have
|
||||||
|
* decided we want to use the remote file name.
|
||||||
|
*/
|
||||||
|
|
||||||
if(!config->outfile && config->remotefile) {
|
if(!outfile) {
|
||||||
/* Find and get the remote file name */
|
/* Find and get the remote file name */
|
||||||
char * pc =strstr(url, "://");
|
char * pc =strstr(url, "://");
|
||||||
if(pc)
|
if(pc)
|
||||||
pc+=3;
|
pc+=3;
|
||||||
else
|
else
|
||||||
pc=url;
|
pc=url;
|
||||||
pc = strrchr(pc, '/');
|
pc = strrchr(pc, '/');
|
||||||
config->outfile = (char *) NULL == pc ? NULL : strdup(pc+1) ;
|
outfile = (char *) NULL == pc ? NULL : strdup(pc+1) ;
|
||||||
if(!config->outfile || !strlen(config->outfile)) {
|
if(!outfile) {
|
||||||
helpf("Remote file name has no length!\n");
|
helpf("Remote file name has no length!\n");
|
||||||
return CURLE_WRITE_ERROR;
|
return CURLE_WRITE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* fill '#1' ... '#9' terms from URL pattern */
|
||||||
|
char *storefile = outfile;
|
||||||
|
outfile = match_url(storefile, urls);
|
||||||
|
free(storefile);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((0 == config->resume_from) && config->use_resume) {
|
||||||
|
/* we're told to continue where we are now, then we get the size of
|
||||||
|
the file as it is now and open it for append instead */
|
||||||
|
|
||||||
|
struct stat fileinfo;
|
||||||
|
|
||||||
|
if(0 == stat(outfile, &fileinfo)) {
|
||||||
|
/* set offset to current file size: */
|
||||||
|
config->resume_from = fileinfo.st_size;
|
||||||
|
}
|
||||||
|
/* else let offset remain 0 */
|
||||||
|
}
|
||||||
|
|
||||||
|
if(config->resume_from) {
|
||||||
|
/* open file for output: */
|
||||||
|
outs.stream=(FILE *) fopen(outfile, config->resume_from?"ab":"wb");
|
||||||
|
if (!outs.stream) {
|
||||||
|
helpf("Can't open '%s'!\n", outfile);
|
||||||
|
return CURLE_WRITE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
outs.filename = outfile;
|
||||||
|
outs.stream = NULL; /* open when needed */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
if(config->infile) {
|
||||||
/* fill '#1' ... '#9' terms from URL pattern */
|
/*
|
||||||
char *outfile = config->outfile;
|
* We have specified a file to upload
|
||||||
config->outfile = match_url(config->outfile, urls);
|
*/
|
||||||
free(outfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
if((0 == config->resume_from) && config->use_resume) {
|
|
||||||
/* we're told to continue where we are now, then we get the size of the
|
|
||||||
file as it is now and open it for append instead */
|
|
||||||
struct stat fileinfo;
|
struct stat fileinfo;
|
||||||
|
|
||||||
if(0 == stat(config->outfile, &fileinfo)) {
|
/* If no file name part is given in the URL, we add this file name */
|
||||||
/* set offset to current file size: */
|
char *ptr=strstr(url, "://");
|
||||||
config->resume_from = fileinfo.st_size;
|
|
||||||
}
|
|
||||||
/* else let offset remain 0 */
|
|
||||||
}
|
|
||||||
|
|
||||||
if(config->resume_from) {
|
|
||||||
/* open file for output: */
|
|
||||||
outs.stream=(FILE *) fopen(config->outfile, config->resume_from?"ab":"wb");
|
|
||||||
if (!outs.stream) {
|
|
||||||
helpf("Can't open '%s'!\n", config->outfile);
|
|
||||||
return CURLE_WRITE_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
outs.filename = config->outfile;
|
|
||||||
outs.stream = NULL; /* open when needed */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (config->infile) {
|
|
||||||
/*
|
|
||||||
* We have specified a file to upload
|
|
||||||
*/
|
|
||||||
struct stat fileinfo;
|
|
||||||
|
|
||||||
/* If no file name part is given in the URL, we add this file name */
|
|
||||||
char *ptr=strstr(url, "://");
|
|
||||||
if(ptr)
|
|
||||||
ptr+=3;
|
|
||||||
else
|
|
||||||
ptr=url;
|
|
||||||
ptr = strrchr(ptr, '/');
|
|
||||||
if(!ptr || !strlen(++ptr)) {
|
|
||||||
/* The URL has no file name part, add the local file name. In order to
|
|
||||||
be able to do so, we have to create a new URL in another buffer.*/
|
|
||||||
|
|
||||||
urlbuffer=(char *)malloc(strlen(url) + strlen(config->infile) + 3);
|
|
||||||
if(!urlbuffer) {
|
|
||||||
helpf("out of memory\n");
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
if(ptr)
|
if(ptr)
|
||||||
/* there is a trailing slash on the URL */
|
ptr+=3;
|
||||||
sprintf(urlbuffer, "%s%s", url, config->infile);
|
|
||||||
else
|
else
|
||||||
/* thers is no trailing slash on the URL */
|
ptr=url;
|
||||||
sprintf(urlbuffer, "%s/%s", url, config->infile);
|
ptr = strrchr(ptr, '/');
|
||||||
|
if(!ptr || !strlen(++ptr)) {
|
||||||
url = urlbuffer; /* use our new URL instead! */
|
/* The URL has no file name part, add the local file name. In order
|
||||||
}
|
to be able to do so, we have to create a new URL in another
|
||||||
|
buffer.*/
|
||||||
|
|
||||||
infd=(FILE *) fopen(config->infile, "rb");
|
urlbuffer=(char *)malloc(strlen(url) + strlen(config->infile) + 3);
|
||||||
if (!infd || stat(config->infile, &fileinfo)) {
|
if(!urlbuffer) {
|
||||||
helpf("Can't open '%s'!\n", config->infile);
|
helpf("out of memory\n");
|
||||||
return CURLE_READ_ERROR;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
infilesize=fileinfo.st_size;
|
if(ptr)
|
||||||
|
/* there is a trailing slash on the URL */
|
||||||
|
sprintf(urlbuffer, "%s%s", url, config->infile);
|
||||||
|
else
|
||||||
|
/* thers is no trailing slash on the URL */
|
||||||
|
sprintf(urlbuffer, "%s/%s", url, config->infile);
|
||||||
|
|
||||||
|
url = urlbuffer; /* use our new URL instead! */
|
||||||
|
}
|
||||||
|
|
||||||
|
infd=(FILE *) fopen(config->infile, "rb");
|
||||||
|
if (!infd || stat(config->infile, &fileinfo)) {
|
||||||
|
helpf("Can't open '%s'!\n", config->infile);
|
||||||
|
return CURLE_READ_ERROR;
|
||||||
|
}
|
||||||
|
infilesize=fileinfo.st_size;
|
||||||
|
|
||||||
}
|
|
||||||
if((config->conf&CONF_UPLOAD) &&
|
|
||||||
config->use_resume &&
|
|
||||||
(0==config->resume_from)) {
|
|
||||||
config->resume_from = -1; /* -1 will then force get-it-yourself */
|
|
||||||
}
|
|
||||||
if(config->headerfile) {
|
|
||||||
/* open file for output: */
|
|
||||||
if(strcmp(config->headerfile,"-")) {
|
|
||||||
heads.filename = config->headerfile;
|
|
||||||
headerfilep=NULL;
|
|
||||||
}
|
}
|
||||||
else
|
if((config->conf&CONF_UPLOAD) &&
|
||||||
headerfilep=stdout;
|
config->use_resume &&
|
||||||
heads.stream = headerfilep;
|
(0==config->resume_from)) {
|
||||||
heads.config = config;
|
config->resume_from = -1; /* -1 will then force get-it-yourself */
|
||||||
}
|
}
|
||||||
|
if(config->headerfile) {
|
||||||
|
/* open file for output: */
|
||||||
|
if(strcmp(config->headerfile,"-")) {
|
||||||
|
heads.filename = config->headerfile;
|
||||||
|
headerfilep=NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
headerfilep=stdout;
|
||||||
|
heads.stream = headerfilep;
|
||||||
|
heads.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
if(outs.stream && isatty(fileno(outs.stream)) &&
|
if(outs.stream && isatty(fileno(outs.stream)) &&
|
||||||
!(config->conf&(CONF_UPLOAD|CONF_HTTPPOST)))
|
!(config->conf&(CONF_UPLOAD|CONF_HTTPPOST)))
|
||||||
/* we send the output to a tty and it isn't an upload operation,
|
/* we send the output to a tty and it isn't an upload operation,
|
||||||
therefore we switch off the progress meter */
|
therefore we switch off the progress meter */
|
||||||
config->conf |= CONF_NOPROGRESS;
|
config->conf |= CONF_NOPROGRESS;
|
||||||
|
|
||||||
|
|
||||||
if (urlnum > 1) {
|
if (urlnum > 1) {
|
||||||
fprintf(stderr, "\n[%d/%d]: %s --> %s\n",
|
fprintf(stderr, "\n[%d/%d]: %s --> %s\n",
|
||||||
i+1, urlnum, url, config->outfile ? config->outfile : "<stdout>");
|
i+1, urlnum, url, outfile ? outfile : "<stdout>");
|
||||||
if (separator) {
|
if (separator)
|
||||||
#ifdef CURL_SEPARATORS
|
printf("%s%s\n", CURLseparator, url);
|
||||||
printf("%s%s\n", CURLseparator, url);
|
|
||||||
#endif
|
|
||||||
#ifdef MIME_SEPARATORS
|
|
||||||
printf("--%s\n", MIMEseparator);
|
|
||||||
printf("Content-ID: %s\n\n", url);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(!config->errors)
|
if(!config->errors)
|
||||||
config->errors = stderr;
|
config->errors = stderr;
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
if(!config->outfile && !(config->conf & CONF_GETTEXT)) {
|
if(!outfile && !(config->conf & CONF_GETTEXT)) {
|
||||||
/* We get the output to stdout and we have not got the ASCII/text flag,
|
/* We get the output to stdout and we have not got the ASCII/text flag,
|
||||||
then set stdout to be binary */
|
then set stdout to be binary */
|
||||||
setmode( 1, O_BINARY );
|
setmode( 1, O_BINARY );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
main_init();
|
main_init();
|
||||||
|
|
||||||
/* The new, v7-style easy-interface! */
|
curl = curl_easy_init();
|
||||||
curl = curl_easy_init();
|
if(curl) {
|
||||||
if(curl) {
|
curl_easy_setopt(curl, CURLOPT_FILE, (FILE *)&outs); /* where to store */
|
||||||
curl_easy_setopt(curl, CURLOPT_FILE, (FILE *)&outs); /* where to store */
|
/* what call to write: */
|
||||||
/* what call to write: */
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
|
curl_easy_setopt(curl, CURLOPT_INFILE, infd); /* for uploads */
|
||||||
curl_easy_setopt(curl, CURLOPT_INFILE, infd); /* for uploads */
|
/* size of uploaded file: */
|
||||||
/* size of uploaded file: */
|
curl_easy_setopt(curl, CURLOPT_INFILESIZE, infilesize);
|
||||||
curl_easy_setopt(curl, CURLOPT_INFILESIZE, infilesize);
|
curl_easy_setopt(curl, CURLOPT_URL, url); /* what to fetch */
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, url); /* what to fetch */
|
curl_easy_setopt(curl, CURLOPT_PROXY, config->proxy); /* proxy to use */
|
||||||
curl_easy_setopt(curl, CURLOPT_PROXY, config->proxy); /* proxy to use */
|
curl_easy_setopt(curl, CURLOPT_VERBOSE, config->conf&CONF_VERBOSE);
|
||||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, config->conf&CONF_VERBOSE);
|
curl_easy_setopt(curl, CURLOPT_HEADER, config->conf&CONF_HEADER);
|
||||||
curl_easy_setopt(curl, CURLOPT_HEADER, config->conf&CONF_HEADER);
|
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, config->conf&CONF_NOPROGRESS);
|
||||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, config->conf&CONF_NOPROGRESS);
|
curl_easy_setopt(curl, CURLOPT_NOBODY, config->conf&CONF_NOBODY);
|
||||||
curl_easy_setopt(curl, CURLOPT_NOBODY, config->conf&CONF_NOBODY);
|
curl_easy_setopt(curl, CURLOPT_FAILONERROR,
|
||||||
curl_easy_setopt(curl, CURLOPT_FAILONERROR,
|
config->conf&CONF_FAILONERROR);
|
||||||
config->conf&CONF_FAILONERROR);
|
curl_easy_setopt(curl, CURLOPT_UPLOAD, config->conf&CONF_UPLOAD);
|
||||||
curl_easy_setopt(curl, CURLOPT_UPLOAD, config->conf&CONF_UPLOAD);
|
curl_easy_setopt(curl, CURLOPT_POST, config->conf&CONF_POST);
|
||||||
curl_easy_setopt(curl, CURLOPT_POST, config->conf&CONF_POST);
|
curl_easy_setopt(curl, CURLOPT_FTPLISTONLY,
|
||||||
curl_easy_setopt(curl, CURLOPT_FTPLISTONLY,
|
config->conf&CONF_FTPLISTONLY);
|
||||||
config->conf&CONF_FTPLISTONLY);
|
curl_easy_setopt(curl, CURLOPT_FTPAPPEND, config->conf&CONF_FTPAPPEND);
|
||||||
curl_easy_setopt(curl, CURLOPT_FTPAPPEND, config->conf&CONF_FTPAPPEND);
|
curl_easy_setopt(curl, CURLOPT_NETRC, config->conf&CONF_NETRC);
|
||||||
curl_easy_setopt(curl, CURLOPT_NETRC, config->conf&CONF_NETRC);
|
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION,
|
||||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION,
|
config->conf&CONF_FOLLOWLOCATION);
|
||||||
config->conf&CONF_FOLLOWLOCATION);
|
curl_easy_setopt(curl, CURLOPT_TRANSFERTEXT, config->conf&CONF_GETTEXT);
|
||||||
curl_easy_setopt(curl, CURLOPT_TRANSFERTEXT, config->conf&CONF_GETTEXT);
|
curl_easy_setopt(curl, CURLOPT_PUT, config->conf&CONF_PUT);
|
||||||
curl_easy_setopt(curl, CURLOPT_PUT, config->conf&CONF_PUT);
|
curl_easy_setopt(curl, CURLOPT_MUTE, config->conf&CONF_MUTE);
|
||||||
curl_easy_setopt(curl, CURLOPT_MUTE, config->conf&CONF_MUTE);
|
curl_easy_setopt(curl, CURLOPT_USERPWD, config->userpwd);
|
||||||
curl_easy_setopt(curl, CURLOPT_USERPWD, config->userpwd);
|
curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd);
|
||||||
curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd);
|
curl_easy_setopt(curl, CURLOPT_RANGE, config->range);
|
||||||
curl_easy_setopt(curl, CURLOPT_RANGE, config->range);
|
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer);
|
||||||
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer);
|
curl_easy_setopt(curl, CURLOPT_TIMEOUT, config->timeout);
|
||||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, config->timeout);
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, config->postfields);
|
||||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, config->postfields);
|
|
||||||
|
/* new in libcurl 7.2: */
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, config->postfieldsize);
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_REFERER, config->referer);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_AUTOREFERER,
|
||||||
|
config->conf&CONF_AUTO_REFERER);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_USERAGENT, config->useragent);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_FTPPORT, config->ftpport);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, config->low_speed_limit);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, config->low_speed_time);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_RESUME_FROM,
|
||||||
|
config->use_resume?config->resume_from:0);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_COOKIE, config->cookie);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, config->headers);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPPOST, config->httppost);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSLCERT, config->cert);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSLCERTPASSWD, config->cert_passwd);
|
||||||
|
|
||||||
|
if(config->cacert) {
|
||||||
|
/* available from libcurl 7.5: */
|
||||||
|
curl_easy_setopt(curl, CURLOPT_CAINFO, config->cacert);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(config->conf&(CONF_NOBODY|CONF_USEREMOTETIME)) {
|
||||||
|
/* no body or use remote time */
|
||||||
|
/* new in 7.5 */
|
||||||
|
curl_easy_setopt(curl, CURLOPT_FILETIME, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
/* new in libcurl 7.2: */
|
/* 7.5 news: */
|
||||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, config->postfieldsize);
|
if (config->maxredirs)
|
||||||
|
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, config->maxredirs);
|
||||||
curl_easy_setopt(curl, CURLOPT_REFERER, config->referer);
|
else
|
||||||
curl_easy_setopt(curl, CURLOPT_AUTOREFERER,
|
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, DEFAULT_MAXREDIRS);
|
||||||
config->conf&CONF_AUTO_REFERER);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, config->useragent);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_FTPPORT, config->ftpport);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, config->low_speed_limit);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, config->low_speed_time);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_RESUME_FROM,
|
|
||||||
config->use_resume?config->resume_from:0);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_COOKIE, config->cookie);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, config->headers);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPPOST, config->httppost);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_SSLCERT, config->cert);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_SSLCERTPASSWD, config->cert_passwd);
|
|
||||||
|
|
||||||
if(config->cacert) {
|
|
||||||
/* available from libcurl 7.5: */
|
|
||||||
curl_easy_setopt(curl, CURLOPT_CAINFO, config->cacert);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(config->conf&(CONF_NOBODY|CONF_USEREMOTETIME)) {
|
|
||||||
/* no body or use remote time */
|
|
||||||
/* new in 7.5 */
|
|
||||||
curl_easy_setopt(curl, CURLOPT_FILETIME, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 7.5 news: */
|
|
||||||
if (config->maxredirs)
|
|
||||||
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, config->maxredirs);
|
|
||||||
else
|
|
||||||
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, DEFAULT_MAXREDIRS);
|
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_CRLF, config->crlf);
|
||||||
curl_easy_setopt(curl, CURLOPT_CRLF, config->crlf);
|
curl_easy_setopt(curl, CURLOPT_QUOTE, config->quote);
|
||||||
curl_easy_setopt(curl, CURLOPT_QUOTE, config->quote);
|
curl_easy_setopt(curl, CURLOPT_POSTQUOTE, config->postquote);
|
||||||
curl_easy_setopt(curl, CURLOPT_POSTQUOTE, config->postquote);
|
curl_easy_setopt(curl, CURLOPT_WRITEHEADER,
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEHEADER,
|
config->headerfile?&heads:NULL);
|
||||||
config->headerfile?&heads:NULL);
|
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, config->cookiefile);
|
||||||
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, config->cookiefile);
|
curl_easy_setopt(curl, CURLOPT_SSLVERSION, config->ssl_version);
|
||||||
curl_easy_setopt(curl, CURLOPT_SSLVERSION, config->ssl_version);
|
curl_easy_setopt(curl, CURLOPT_TIMECONDITION, config->timecond);
|
||||||
curl_easy_setopt(curl, CURLOPT_TIMECONDITION, config->timecond);
|
curl_easy_setopt(curl, CURLOPT_TIMEVALUE, config->condtime);
|
||||||
curl_easy_setopt(curl, CURLOPT_TIMEVALUE, config->condtime);
|
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, config->customrequest);
|
||||||
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, config->customrequest);
|
curl_easy_setopt(curl, CURLOPT_STDERR, config->errors);
|
||||||
curl_easy_setopt(curl, CURLOPT_STDERR, config->errors);
|
|
||||||
|
|
||||||
/* three new ones in libcurl 7.3: */
|
/* three new ones in libcurl 7.3: */
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel);
|
curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel);
|
||||||
curl_easy_setopt(curl, CURLOPT_INTERFACE, config->iface);
|
curl_easy_setopt(curl, CURLOPT_INTERFACE, config->iface);
|
||||||
curl_easy_setopt(curl, CURLOPT_KRB4LEVEL, config->krb4level);
|
curl_easy_setopt(curl, CURLOPT_KRB4LEVEL, config->krb4level);
|
||||||
|
|
||||||
if((config->progressmode == CURL_PROGRESS_BAR) &&
|
if((config->progressmode == CURL_PROGRESS_BAR) &&
|
||||||
!(config->conf&(CONF_NOPROGRESS|CONF_MUTE))) {
|
!(config->conf&(CONF_NOPROGRESS|CONF_MUTE))) {
|
||||||
/* we want the alternative style, then we have to implement it
|
/* we want the alternative style, then we have to implement it
|
||||||
ourselves! */
|
ourselves! */
|
||||||
progressbarinit(&progressbar);
|
progressbarinit(&progressbar);
|
||||||
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, myprogress);
|
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, myprogress);
|
||||||
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &progressbar);
|
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &progressbar);
|
||||||
|
}
|
||||||
|
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
|
||||||
|
if(config->writeout) {
|
||||||
|
ourWriteOut(curl, config->writeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* always cleanup */
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
|
if((res!=CURLE_OK) && config->showerror)
|
||||||
|
fprintf(config->errors, "curl: (%d) %s\n", res, errorbuffer);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
fprintf(config->errors, "curl: failed to init libcurl!\n");
|
||||||
|
|
||||||
res = curl_easy_perform(curl);
|
main_free();
|
||||||
|
|
||||||
if(config->writeout) {
|
if((config->errors != stderr) &&
|
||||||
ourWriteOut(curl, config->writeout);
|
(config->errors != stdout))
|
||||||
}
|
/* it wasn't directed to stdout or stderr so close the file! */
|
||||||
|
fclose(config->errors);
|
||||||
|
|
||||||
|
if(config->headerfile && !headerfilep && heads.stream)
|
||||||
|
fclose(heads.stream);
|
||||||
|
|
||||||
/* always cleanup */
|
if(urlbuffer)
|
||||||
curl_easy_cleanup(curl);
|
free(urlbuffer);
|
||||||
|
if (outfile && !strequal(outfile, "-") && outs.stream)
|
||||||
|
fclose(outs.stream);
|
||||||
|
if (config->infile)
|
||||||
|
fclose(infd);
|
||||||
|
if(headerfilep)
|
||||||
|
fclose(headerfilep);
|
||||||
|
|
||||||
|
if(url)
|
||||||
|
free(url);
|
||||||
|
|
||||||
if((res!=CURLE_OK) && config->showerror)
|
if(outfile)
|
||||||
fprintf(config->errors, "curl: (%d) %s\n", res, errorbuffer);
|
free(outfile);
|
||||||
}
|
}
|
||||||
else
|
if(outfiles)
|
||||||
fprintf(config->errors, "curl: failed to init libcurl!\n");
|
free(outfiles);
|
||||||
|
|
||||||
main_free();
|
/* cleanup memory used for URL globbing patterns */
|
||||||
|
glob_cleanup(urls);
|
||||||
|
|
||||||
if((config->errors != stderr) &&
|
/* empty this urlnode struct */
|
||||||
(config->errors != stdout))
|
if(urlnode->url)
|
||||||
/* it wasn't directed to stdout or stderr so close the file! */
|
free(urlnode->url);
|
||||||
fclose(config->errors);
|
if(urlnode->outfile)
|
||||||
|
free(urlnode->outfile);
|
||||||
|
|
||||||
if(config->headerfile && !headerfilep && heads.stream)
|
/* move on to the next URL */
|
||||||
fclose(heads.stream);
|
nextnode=urlnode->next;
|
||||||
|
free(urlnode); /* free the node */
|
||||||
|
urlnode = nextnode;
|
||||||
|
|
||||||
if(urlbuffer)
|
} /* while-loop through all URLs */
|
||||||
free(urlbuffer);
|
|
||||||
if (config->outfile && outs.stream)
|
|
||||||
fclose(outs.stream);
|
|
||||||
if (config->infile)
|
|
||||||
fclose(infd);
|
|
||||||
if(headerfilep)
|
|
||||||
fclose(headerfilep);
|
|
||||||
|
|
||||||
if(url)
|
|
||||||
free(url);
|
|
||||||
|
|
||||||
}
|
|
||||||
if(outfiles)
|
|
||||||
free(outfiles);
|
|
||||||
|
|
||||||
#ifdef MIME_SEPARATORS
|
|
||||||
if (separator)
|
|
||||||
printf("--%s--\n", MIMEseparator);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(allocuseragent)
|
if(allocuseragent)
|
||||||
free(config->useragent);
|
free(config->useragent);
|
||||||
|
|
||||||
/* cleanup memory used for URL globbing patterns */
|
|
||||||
glob_cleanup(urls);
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,6 +213,7 @@ int glob_url(URLGlob** glob, char* url, int *urlnum)
|
|||||||
glob_expand->size = 0;
|
glob_expand->size = 0;
|
||||||
glob_expand->urllen = strlen(url);
|
glob_expand->urllen = strlen(url);
|
||||||
glob_expand->glob_buffer = glob_buffer;
|
glob_expand->glob_buffer = glob_buffer;
|
||||||
|
glob_expand->beenhere=0;
|
||||||
*urlnum = glob_word(glob_expand, url, 1);
|
*urlnum = glob_word(glob_expand, url, 1);
|
||||||
*glob = glob_expand;
|
*glob = glob_expand;
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
@ -240,15 +241,14 @@ void glob_cleanup(URLGlob* glob)
|
|||||||
|
|
||||||
char *next_url(URLGlob *glob)
|
char *next_url(URLGlob *glob)
|
||||||
{
|
{
|
||||||
static int beenhere = 0;
|
|
||||||
char *buf = glob->glob_buffer;
|
char *buf = glob->glob_buffer;
|
||||||
URLPattern *pat;
|
URLPattern *pat;
|
||||||
char *lit;
|
char *lit;
|
||||||
signed int i;
|
signed int i;
|
||||||
int carry;
|
int carry;
|
||||||
|
|
||||||
if (!beenhere)
|
if (!glob->beenhere)
|
||||||
beenhere = 1;
|
glob->beenhere = 1;
|
||||||
else {
|
else {
|
||||||
carry = 1;
|
carry = 1;
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@ typedef struct {
|
|||||||
int size;
|
int size;
|
||||||
int urllen;
|
int urllen;
|
||||||
char *glob_buffer;
|
char *glob_buffer;
|
||||||
|
char beenhere;
|
||||||
} URLGlob;
|
} URLGlob;
|
||||||
|
|
||||||
int glob_url(URLGlob**, char*, int *);
|
int glob_url(URLGlob**, char*, int *);
|
||||||
|
Loading…
Reference in New Issue
Block a user