Multiple URL support added

This commit is contained in:
Daniel Stenberg 2001-01-08 07:37:44 +00:00
parent 53c27c7722
commit 14ca732a8f
3 changed files with 396 additions and 312 deletions

View File

@ -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;
} }

View File

@ -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;

View File

@ -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 *);