From 93a29c3c458f15d9cd3ccc217fbf78c45595e3d3 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 19 Aug 2003 23:42:24 +0000 Subject: [PATCH] Now offering support for multiple -T on the same command line, just make sure you have one URL for each -T. A -T file name can also be "globbed" like -T "{file1,file2}". Test case 149 verifies this functionality. --- src/main.c | 957 ++++++++++++++++++++++++++++------------------------- 1 file changed, 515 insertions(+), 442 deletions(-) diff --git a/src/main.c b/src/main.c index a8afbe9a8..bee66dbdb 100644 --- a/src/main.c +++ b/src/main.c @@ -143,7 +143,6 @@ typedef enum { #define CONF_NOPROGRESS (1<<10) /* shut off the progress meter */ #define CONF_NOBODY (1<<11) /* use HEAD to get http document */ #define CONF_FAILONERROR (1<<12) /* no output on http error codes >= 300 */ -#define CONF_UPLOAD (1<<14) /* this is an upload */ #define CONF_FTPLISTONLY (1<<16) /* Use NLST when listing ftp dir */ #define CONF_FTPAPPEND (1<<20) /* Append instead of overwrite on upload! */ #define CONF_NETRC (1<<22) /* read user+password from .netrc */ @@ -353,14 +352,18 @@ static void helpf(const char *fmt, ...) * contents. */ struct getout { - struct getout *next; - char *url; - char *outfile; - int flags; + struct getout *next; /* next one */ + char *url; /* the URL we deal with */ + char *outfile; /* where to store the output */ + char *infile; /* file to upload, if GETOUT_UPLOAD is set */ + int flags; /* options */ }; -#define GETOUT_OUTFILE (1<<0) /* set when outfile is deemed done */ -#define GETOUT_URL (1<<1) /* set when URL is deemed done */ +#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 */ +#define GETOUT_UPLOAD (1<<3) /* if set, -T has been used */ +#define GETOUT_NOUPLOAD (1<<4) /* if set, -T "" has been used */ + static void help(void) { @@ -508,7 +511,6 @@ struct Configurable { int low_speed_limit; int low_speed_time; bool showerror; - char *infile; char *userpwd; char *proxyuserpwd; char *proxy; @@ -675,6 +677,8 @@ void clean_getout(struct Configurable *config) free(node->url); if(node->outfile) free(node->outfile); + if(node->infile) + free(node->infile); free(node); node = next; /* GOTO next */ @@ -1756,10 +1760,34 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */ break; case 'T': /* we are uploading */ - config->conf |= CONF_UPLOAD; - if(!curl_strequal("-", nextarg)) - /* make - equal stdin */ - GetStr(&config->infile, nextarg); + { + 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_UPLOAD)) + 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) { + url->flags |= GETOUT_UPLOAD; /* mark -T used */ + if(!*nextarg) + url->flags |= GETOUT_NOUPLOAD; + else { + /* "-" equals stdin, but keep the string around for now */ + GetStr(&url->infile, nextarg); + } + } + } break; case 'u': /* user:password */ @@ -2408,8 +2436,6 @@ void free_config_fields(struct Configurable *config) free(config->headerfile); if(config->ftpport) free(config->ftpport); - if(config->infile) - free(config->infile); if(config->range) free(config->range); if(config->customrequest) @@ -2479,14 +2505,20 @@ operate(struct Configurable *config, int argc, char *argv[]) char *url = NULL; URLGlob *urls=NULL; + URLGlob *inglob=NULL; int urlnum; + int infilenum; char *outfiles; + char *infiles; /* might a glob pattern */ + char *uploadfile=NULL; /* a single file, never a glob */ + int separator = 0; - FILE *infd = stdin; + FILE *infd; + bool infdfopen; FILE *headerfilep = NULL; char *urlbuffer=NULL; - long infilesize=-1; /* -1 means unknown */ + long uploadfilesize; /* -1 means unknown */ bool stillflags=TRUE; bool allocuseragent=FALSE; @@ -2496,6 +2528,7 @@ operate(struct Configurable *config, int argc, char *argv[]) CURL *curl; int res = 0; int i; + int up; /* upload file counter within a single upload glob */ char *env; #ifdef CURLDEBUG @@ -2678,9 +2711,12 @@ operate(struct Configurable *config, int argc, char *argv[]) /* loop through the list of given URLs */ while(urlnode && !res) { + char *dourl; /* get the full URL (it might be NULL) */ - url=urlnode->url; + dourl=urlnode->url; + + url = dourl; if(NULL == url) { /* This node had no URL, skip it and continue to the next */ @@ -2698,10 +2734,14 @@ operate(struct Configurable *config, int argc, char *argv[]) outs.stream = stdout; outs.config = config; - if(!config->globoff) { - /* Unless explicitly shut off, we expand '{...}' and '[...]' expressions - and return total number of URLs in pattern set */ - res = glob_url(&urls, url, &urlnum, + /* save outfile pattern before expansion */ + outfiles = urlnode->outfile?strdup(urlnode->outfile):NULL; + + infiles = urlnode->infile; + + if(!config->globoff && infiles) { + /* Unless explicitly shut off */ + res = glob_url(&inglob, infiles, &infilenum, config->showerror? (config->errors?config->errors:stderr):NULL); if(res != CURLE_OK) { @@ -2710,162 +2750,180 @@ operate(struct Configurable *config, int argc, char *argv[]) } } + /* Here's the loop for uploading multiple files within the same + single globbed string. If no upload, we enter the loop once anyway. */ + for(up = 0; + (!up && !infiles) || + (uploadfile = inglob? + glob_next_url(inglob): + (!up?strdup(infiles):NULL)); + up++) { + uploadfilesize=-1; - /* save outfile pattern before expansion */ - outfiles = urlnode->outfile?strdup(urlnode->outfile):NULL; - - if ((!outfiles || curl_strequal(outfiles, "-")) && urlnum > 1) { - /* multiple files extracted to stdout, insert separators! */ - separator = 1; - } - for(i = 0; - (url = urls?glob_next_url(urls):(i?NULL:strdup(url))); - i++) { - char *outfile; - outfile = outfiles?strdup(outfiles):NULL; - - if((urlnode->flags&GETOUT_USEREMOTE) || - (outfile && !curl_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. - */ - - if(!outfile) { - /* Find and get the remote file name */ - char * pc =strstr(url, "://"); - if(pc) - pc+=3; - else - pc=url; - pc = strrchr(pc, '/'); - - if(pc) { - /* duplicate the string beyond the slash */ - pc++; - outfile = *pc ? strdup(pc): NULL; - } - if(!outfile || !*outfile) { - helpf("Remote file name has no length!\n"); - res = CURLE_WRITE_ERROR; - free(url); - break; - } -#if defined(__DJGPP__) - { - /* This is for DOS, and then we do some major replacing of - bad characters in the file name before using it */ - char *file1=xmalloc(PATH_MAX); - strcpy(file1, msdosify(outfile)); - strcpy(outfile, rename_if_dos_device_name(file1)); - xfree(file1); - } -#endif /* __DJGPP__ */ - } - else if(urls) { - /* fill '#1' ... '#9' terms from URL pattern */ - char *storefile = outfile; - outfile = glob_match_url(storefile, urls); - free(storefile); - if(!outfile) { - /* bad globbing */ - fprintf(stderr, "bad output glob!\n"); - free(url); - res = CURLE_FAILED_INIT; - break; - } - } - - /* Create the directory hierarchy, if not pre-existant to a multiple - file output call */ - - if(config->create_dirs) - if (-1 == create_dir_hierarchy(outfile)) { - return CURLE_WRITE_ERROR; - } - - if(config->resume_from_current) { - /* We're told to continue from where we are now. Get the - size of the file as it is now and open it for append instead */ - - struct stat fileinfo; - - /*VMS?? -- Danger, the filesize is only valid for stream files */ - if(0 == stat(outfile, &fileinfo)) - /* set offset to current file size: */ - config->resume_from = fileinfo.st_size; - else - /* let offset be 0 */ - config->resume_from = 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 */ + if(!config->globoff) { + /* Unless explicitly shut off, we expand '{...}' and '[...]' + expressions and return total number of URLs in pattern set */ + res = glob_url(&urls, dourl, &urlnum, + config->showerror? + (config->errors?config->errors:stderr):NULL); + if(res != CURLE_OK) { + break; } } - 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.*/ + /* if multiple files extracted to stdout, insert separators! */ + separator= ((!outfiles || curl_strequal(outfiles, "-")) && urlnum > 1); - /* We only want the part of the local path that is on the right - side of the rightmost slash and backslash. */ - char *filep = strrchr(config->infile, '/'); - char *file2 = strrchr(filep?filep:config->infile, '\\'); - - if(file2) - filep = file2+1; - else if(filep) - filep++; - else - filep = config->infile; - - /* URL encode the file name */ - filep = curl_escape(filep, 0 /* use strlen */); - - if(filep) { - - urlbuffer=(char *)malloc(strlen(url) + strlen(filep) + 3); - if(!urlbuffer) { - helpf("out of memory\n"); - return CURLE_OUT_OF_MEMORY; - } - if(ptr) - /* there is a trailing slash on the URL */ - sprintf(urlbuffer, "%s%s", url, filep); + /* Here's looping around each globbed URL */ + for(i = 0; + (url = urls?glob_next_url(urls):(i?NULL:strdup(url))); + i++) { + char *outfile; + outfile = outfiles?strdup(outfiles):NULL; + + if((urlnode->flags&GETOUT_USEREMOTE) || + (outfile && !curl_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. + */ + + if(!outfile) { + /* Find and get the remote file name */ + char * pc =strstr(url, "://"); + if(pc) + pc+=3; else - /* thers is no trailing slash on the URL */ - sprintf(urlbuffer, "%s/%s", url, filep); - - curl_free(filep); + pc=url; + pc = strrchr(pc, '/'); - free(url); - url = urlbuffer; /* use our new URL instead! */ + if(pc) { + /* duplicate the string beyond the slash */ + pc++; + outfile = *pc ? strdup(pc): NULL; + } + if(!outfile || !*outfile) { + helpf("Remote file name has no length!\n"); + res = CURLE_WRITE_ERROR; + free(url); + break; + } +#if defined(__DJGPP__) + { + /* This is for DOS, and then we do some major replacing of + bad characters in the file name before using it */ + char *file1=xmalloc(PATH_MAX); + strcpy(file1, msdosify(outfile)); + strcpy(outfile, rename_if_dos_device_name(file1)); + xfree(file1); + } +#endif /* __DJGPP__ */ + } + else if(urls) { + /* fill '#1' ... '#9' terms from URL pattern */ + char *storefile = outfile; + outfile = glob_match_url(storefile, urls); + free(storefile); + if(!outfile) { + /* bad globbing */ + fprintf(stderr, "bad output glob!\n"); + free(url); + res = CURLE_FAILED_INIT; + break; + } + } + + /* Create the directory hierarchy, if not pre-existant to a multiple + file output call */ + + if(config->create_dirs) + if (-1 == create_dir_hierarchy(outfile)) { + return CURLE_WRITE_ERROR; + } + + if(config->resume_from_current) { + /* We're told to continue from where we are now. Get the + size of the file as it is now and open it for append instead */ + + struct stat fileinfo; + + /*VMS?? -- Danger, the filesize is only valid for stream files */ + if(0 == stat(outfile, &fileinfo)) + /* set offset to current file size: */ + config->resume_from = fileinfo.st_size; + else + /* let offset be 0 */ + config->resume_from = 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 */ } } + infdfopen=FALSE; + if(uploadfile && !curl_strequal(uploadfile, "-")) { + /* + * We have specified a file to upload and it isn't "-". + */ + 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.*/ + + /* We only want the part of the local path that is on the right + side of the rightmost slash and backslash. */ + char *filep = strrchr(uploadfile, '/'); + char *file2 = strrchr(filep?filep:uploadfile, '\\'); + + if(file2) + filep = file2+1; + else if(filep) + filep++; + else + filep = uploadfile; + + /* URL encode the file name */ + filep = curl_escape(filep, 0 /* use strlen */); + + if(filep) { + + urlbuffer=(char *)malloc(strlen(url) + strlen(filep) + 3); + if(!urlbuffer) { + helpf("out of memory\n"); + return CURLE_OUT_OF_MEMORY; + } + if(ptr) + /* there is a trailing slash on the URL */ + sprintf(urlbuffer, "%s%s", url, filep); + else + /* thers is no trailing slash on the URL */ + sprintf(urlbuffer, "%s/%s", url, filep); + + curl_free(filep); + + free(url); + url = urlbuffer; /* use our new URL instead! */ + } + } /*VMS??-- Reading binary from files can be a problem... */ /*VMS?? Only FIXED, VAR etc WITHOUT implied CC will work */ /*VMS?? Others need a \n appended to a line */ @@ -2876,288 +2934,290 @@ operate(struct Configurable *config, int argc, char *argv[]) /*VMS?? for every record add 1 for linefeed and subtract 2 for the record header */ /*VMS?? for VARIABLE header files only the bare record data needs to be considered with one appended if implied CC */ - 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; + infd=(FILE *) fopen(uploadfile, "rb"); + if (!infd || stat(uploadfile, &fileinfo)) { + helpf("Can't open '%s'!\n", uploadfile); + return CURLE_READ_ERROR; + } + infdfopen=TRUE; + uploadfilesize=fileinfo.st_size; - } - if((config->conf&CONF_UPLOAD) && - config->resume_from_current) { - config->resume_from = -1; /* -1 will then force get-it-yourself */ - } - if(outs.stream && isatty(fileno(outs.stream)) && - !(config->conf&(CONF_UPLOAD|CONF_HTTPPOST))) - /* we send the output to a tty and it isn't an upload operation, - therefore we switch off the progress meter */ - config->conf |= CONF_NOPROGRESS; - - - if (urlnum > 1 && !(config->conf&CONF_MUTE)) { - fprintf(stderr, "\n[%d/%d]: %s --> %s\n", - i+1, urlnum, url, outfile ? outfile : ""); - if (separator) - printf("%s%s\n", CURLseparator, url); - } - if (httpgetfields) { - /* Find out whether the url contains a file name */ - char *pc =strstr(url, "://"); - char separator='?'; - if(pc) - pc+=3; - else - pc=url; - - pc = strrchr(pc, '/'); /* check for a slash */ - - if(pc) { - /* there is a slash present in the URL */ - - if(strchr(pc, '?')) - /* Ouch, there's already a question mark in the URL string, we - then appead the data with an amperand separator instead! */ - separator='&'; } - /* - * Then append ? followed by the get fields to the url. - */ - urlbuffer=(char *)malloc(strlen(url) + strlen(httpgetfields) + 2); - if(!urlbuffer) { - helpf("out of memory\n"); - return CURLE_OUT_OF_MEMORY; + else if(uploadfile && curl_strequal(uploadfile, "-")) { + infd = stdin; } - if (pc) - sprintf(urlbuffer, "%s%c%s", url, separator, httpgetfields); - else - /* Append / before the ? to create a well-formed url - if the url contains a hostname only - */ - sprintf(urlbuffer, "%s/?%s", url, httpgetfields); + + if(uploadfile && config->resume_from_current) + config->resume_from = -1; /* -1 will then force get-it-yourself */ + + if(outs.stream && isatty(fileno(outs.stream))) + /* we send the output to a tty, therefore we switch off the progress + meter */ + config->conf |= CONF_NOPROGRESS; + + if (urlnum > 1 && !(config->conf&CONF_MUTE)) { + fprintf(stderr, "\n[%d/%d]: %s --> %s\n", + i+1, urlnum, url, outfile ? outfile : ""); + if (separator) + printf("%s%s\n", CURLseparator, url); + } + if (httpgetfields) { + /* Find out whether the url contains a file name */ + char *pc =strstr(url, "://"); + char separator='?'; + if(pc) + pc+=3; + else + pc=url; + + pc = strrchr(pc, '/'); /* check for a slash */ + + if(pc) { + /* there is a slash present in the URL */ + + if(strchr(pc, '?')) + /* Ouch, there's already a question mark in the URL string, we + then appead the data with an amperand separator instead! */ + separator='&'; + } + /* + * Then append ? followed by the get fields to the url. + */ + urlbuffer=(char *)malloc(strlen(url) + strlen(httpgetfields) + 2); + if(!urlbuffer) { + helpf("out of memory\n"); + return CURLE_OUT_OF_MEMORY; + } + if (pc) + sprintf(urlbuffer, "%s%c%s", url, separator, httpgetfields); + else + /* Append / before the ? to create a well-formed url + if the url contains a hostname only + */ + sprintf(urlbuffer, "%s/?%s", url, httpgetfields); - free(url); /* free previous URL */ - url = urlbuffer; /* use our new URL instead! */ - } + free(url); /* free previous URL */ + url = urlbuffer; /* use our new URL instead! */ + } - if(!config->errors) - config->errors = stderr; + if(!config->errors) + config->errors = stderr; #ifdef O_BINARY - if(!outfile && !(config->conf & CONF_GETTEXT)) { - /* We get the output to stdout and we have not got the ASCII/text flag, - then set stdout to be binary */ - setmode( fileno(stdout), O_BINARY ); - } + if(!outfile && !(config->conf & CONF_GETTEXT)) { + /* We get the output to stdout and we have not got the ASCII/text flag, + then set stdout to be binary */ + setmode( fileno(stdout), O_BINARY ); + } #endif - curl_easy_setopt(curl, CURLOPT_SSLENGINE, config->engine); - curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1); + curl_easy_setopt(curl, CURLOPT_SSLENGINE, config->engine); + curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1); - /* where to store */ - curl_easy_setopt(curl, CURLOPT_WRITEDATA, (FILE *)&outs); - /* what call to write */ - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite); + /* where to store */ + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (FILE *)&outs); + /* what call to write */ + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite); - /* for uploads */ - input.stream = infd; - input.config = config; - curl_easy_setopt(curl, CURLOPT_READDATA, &input); - /* what call to read */ - curl_easy_setopt(curl, CURLOPT_READFUNCTION, my_fread); + /* for uploads */ + input.stream = infd; + input.config = config; + curl_easy_setopt(curl, CURLOPT_READDATA, &input); + /* what call to read */ + curl_easy_setopt(curl, CURLOPT_READFUNCTION, my_fread); - if(config->recvpersecond) { - /* tell libcurl to use a smaller sized buffer as it allows us to - make better sleeps! 7.9.9 stuff! */ - curl_easy_setopt(curl, CURLOPT_BUFFERSIZE, config->recvpersecond); - } + if(config->recvpersecond) { + /* tell libcurl to use a smaller sized buffer as it allows us to + make better sleeps! 7.9.9 stuff! */ + curl_easy_setopt(curl, CURLOPT_BUFFERSIZE, config->recvpersecond); + } - /* size of uploaded file: */ - curl_easy_setopt(curl, CURLOPT_INFILESIZE, infilesize); - 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_HEADER, config->conf&CONF_HEADER); - 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_FAILONERROR, - config->conf&CONF_FAILONERROR); - curl_easy_setopt(curl, CURLOPT_UPLOAD, config->conf&CONF_UPLOAD); - curl_easy_setopt(curl, CURLOPT_FTPLISTONLY, - config->conf&CONF_FTPLISTONLY); - curl_easy_setopt(curl, CURLOPT_FTPAPPEND, config->conf&CONF_FTPAPPEND); + /* size of uploaded file: */ + curl_easy_setopt(curl, CURLOPT_INFILESIZE, uploadfilesize); + 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_HEADER, config->conf&CONF_HEADER); + 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_FAILONERROR, + config->conf&CONF_FAILONERROR); + curl_easy_setopt(curl, CURLOPT_UPLOAD, uploadfile?TRUE:FALSE); + curl_easy_setopt(curl, CURLOPT_FTPLISTONLY, + config->conf&CONF_FTPLISTONLY); + curl_easy_setopt(curl, CURLOPT_FTPAPPEND, config->conf&CONF_FTPAPPEND); - if (config->conf&CONF_NETRC_OPT) - curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL); - else if (config->conf&CONF_NETRC) - curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_REQUIRED); - else - curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_IGNORED); + if (config->conf&CONF_NETRC_OPT) + curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL); + else if (config->conf&CONF_NETRC) + curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_REQUIRED); + else + curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_IGNORED); - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, - config->conf&CONF_FOLLOWLOCATION); - curl_easy_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, - config->conf&CONF_UNRESTRICTED_AUTH); - curl_easy_setopt(curl, CURLOPT_TRANSFERTEXT, config->conf&CONF_GETTEXT); - curl_easy_setopt(curl, CURLOPT_MUTE, config->conf&CONF_MUTE); - curl_easy_setopt(curl, CURLOPT_USERPWD, config->userpwd); - curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd); - curl_easy_setopt(curl, CURLOPT_RANGE, config->range); - curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer); - curl_easy_setopt(curl, CURLOPT_TIMEOUT, config->timeout); - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, config->postfields); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, + config->conf&CONF_FOLLOWLOCATION); + curl_easy_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, + config->conf&CONF_UNRESTRICTED_AUTH); + curl_easy_setopt(curl, CURLOPT_TRANSFERTEXT, config->conf&CONF_GETTEXT); + curl_easy_setopt(curl, CURLOPT_MUTE, config->conf&CONF_MUTE); + curl_easy_setopt(curl, CURLOPT_USERPWD, config->userpwd); + curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd); + curl_easy_setopt(curl, CURLOPT_RANGE, config->range); + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, config->timeout); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, config->postfields); - /* new in libcurl 7.2: */ - curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, config->postfieldsize); + /* 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_SSLCERTTYPE, config->cert_type); - curl_easy_setopt(curl, CURLOPT_SSLKEY, config->key); - curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, config->key_type); - curl_easy_setopt(curl, CURLOPT_SSLKEYPASSWD, config->key_passwd); + 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_SSLCERTTYPE, config->cert_type); + curl_easy_setopt(curl, CURLOPT_SSLKEY, config->key); + curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, config->key_type); + curl_easy_setopt(curl, CURLOPT_SSLKEYPASSWD, config->key_passwd); - /* default to strict verifyhost */ - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2); - if(config->cacert || config->capath) { - if (config->cacert) - curl_easy_setopt(curl, CURLOPT_CAINFO, config->cacert); + /* default to strict verifyhost */ + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2); + if(config->cacert || config->capath) { + if (config->cacert) + curl_easy_setopt(curl, CURLOPT_CAINFO, config->cacert); - if (config->capath) - curl_easy_setopt(curl, CURLOPT_CAPATH, config->capath); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, TRUE); - } - else - if(config->insecure_ok) { - /* new stuff needed for libcurl 7.10 */ - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 1); + if (config->capath) + curl_easy_setopt(curl, CURLOPT_CAPATH, config->capath); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, TRUE); + } + else + if(config->insecure_ok) { + /* new stuff needed for libcurl 7.10 */ + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 1); + } + + if((config->conf&CONF_NOBODY) || + config->remote_time) { + /* no body or use remote time */ + curl_easy_setopt(curl, CURLOPT_FILETIME, TRUE); } - if((config->conf&CONF_NOBODY) || - config->remote_time) { - /* no body or use remote time */ - curl_easy_setopt(curl, CURLOPT_FILETIME, TRUE); - } - - if (config->maxredirs) - curl_easy_setopt(curl, CURLOPT_MAXREDIRS, config->maxredirs); - else - curl_easy_setopt(curl, CURLOPT_MAXREDIRS, DEFAULT_MAXREDIRS); + 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_QUOTE, config->quote); - curl_easy_setopt(curl, CURLOPT_POSTQUOTE, config->postquote); - curl_easy_setopt(curl, CURLOPT_WRITEHEADER, - config->headerfile?&heads:NULL); - curl_easy_setopt(curl, CURLOPT_COOKIEFILE, config->cookiefile); - /* cookie jar was added in 7.9 */ - if(config->cookiejar) - curl_easy_setopt(curl, CURLOPT_COOKIEJAR, config->cookiejar); - /* cookie session added in 7.9.7 */ - curl_easy_setopt(curl, CURLOPT_COOKIESESSION, config->cookiesession); + curl_easy_setopt(curl, CURLOPT_CRLF, config->crlf); + curl_easy_setopt(curl, CURLOPT_QUOTE, config->quote); + curl_easy_setopt(curl, CURLOPT_POSTQUOTE, config->postquote); + curl_easy_setopt(curl, CURLOPT_WRITEHEADER, + config->headerfile?&heads:NULL); + curl_easy_setopt(curl, CURLOPT_COOKIEFILE, config->cookiefile); + /* cookie jar was added in 7.9 */ + if(config->cookiejar) + curl_easy_setopt(curl, CURLOPT_COOKIEJAR, config->cookiejar); + /* cookie session added in 7.9.7 */ + curl_easy_setopt(curl, CURLOPT_COOKIESESSION, config->cookiesession); - curl_easy_setopt(curl, CURLOPT_SSLVERSION, config->ssl_version); - curl_easy_setopt(curl, CURLOPT_TIMECONDITION, config->timecond); - curl_easy_setopt(curl, CURLOPT_TIMEVALUE, config->condtime); - curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, config->customrequest); - curl_easy_setopt(curl, CURLOPT_STDERR, config->errors); + curl_easy_setopt(curl, CURLOPT_SSLVERSION, config->ssl_version); + curl_easy_setopt(curl, CURLOPT_TIMECONDITION, config->timecond); + curl_easy_setopt(curl, CURLOPT_TIMEVALUE, config->condtime); + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, config->customrequest); + curl_easy_setopt(curl, CURLOPT_STDERR, config->errors); - /* three new ones in libcurl 7.3: */ - curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel); - curl_easy_setopt(curl, CURLOPT_INTERFACE, config->iface); - curl_easy_setopt(curl, CURLOPT_KRB4LEVEL, config->krb4level); + /* three new ones in libcurl 7.3: */ + curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel); + curl_easy_setopt(curl, CURLOPT_INTERFACE, config->iface); + curl_easy_setopt(curl, CURLOPT_KRB4LEVEL, config->krb4level); - if((config->progressmode == CURL_PROGRESS_BAR) && - !(config->conf&(CONF_NOPROGRESS|CONF_MUTE))) { - /* we want the alternative style, then we have to implement it - ourselves! */ - progressbarinit(&progressbar, config); - curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, myprogress); - curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &progressbar); - } + if((config->progressmode == CURL_PROGRESS_BAR) && + !(config->conf&(CONF_NOPROGRESS|CONF_MUTE))) { + /* we want the alternative style, then we have to implement it + ourselves! */ + progressbarinit(&progressbar, config); + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, myprogress); + curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &progressbar); + } - /* new in libcurl 7.6.2: */ - curl_easy_setopt(curl, CURLOPT_TELNETOPTIONS, config->telnet_options); + /* new in libcurl 7.6.2: */ + curl_easy_setopt(curl, CURLOPT_TELNETOPTIONS, config->telnet_options); - /* new in libcurl 7.7: */ - curl_easy_setopt(curl, CURLOPT_RANDOM_FILE, config->random_file); - curl_easy_setopt(curl, CURLOPT_EGDSOCKET, config->egd_file); - curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, config->connecttimeout); + /* new in libcurl 7.7: */ + curl_easy_setopt(curl, CURLOPT_RANDOM_FILE, config->random_file); + curl_easy_setopt(curl, CURLOPT_EGDSOCKET, config->egd_file); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, config->connecttimeout); - if(config->cipher_list) - curl_easy_setopt(curl, CURLOPT_SSL_CIPHER_LIST, config->cipher_list); + if(config->cipher_list) + curl_easy_setopt(curl, CURLOPT_SSL_CIPHER_LIST, config->cipher_list); - if(config->httpversion) - curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, config->httpversion); + if(config->httpversion) + curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, config->httpversion); - /* new in libcurl 7.9.2: */ - if(config->disable_epsv) - /* disable it */ - curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, FALSE); + /* new in libcurl 7.9.2: */ + if(config->disable_epsv) + /* disable it */ + curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, FALSE); - /* new in libcurl 7.10.5 */ - if(config->disable_eprt) - /* disable it */ - curl_easy_setopt(curl, CURLOPT_FTP_USE_EPRT, FALSE); + /* new in libcurl 7.10.5 */ + if(config->disable_eprt) + /* disable it */ + curl_easy_setopt(curl, CURLOPT_FTP_USE_EPRT, FALSE); - /* new in libcurl 7.10.6 (default is Basic) */ - if(config->authtype) - curl_easy_setopt(curl, CURLOPT_HTTPAUTH, config->authtype); + /* new in libcurl 7.10.6 (default is Basic) */ + if(config->authtype) + curl_easy_setopt(curl, CURLOPT_HTTPAUTH, config->authtype); - /* new in curl 7.9.7 */ - if(config->trace_dump) { - curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace); - curl_easy_setopt(curl, CURLOPT_DEBUGDATA, config); - config->conf |= CONF_VERBOSE; /* force verbose */ - } - curl_easy_setopt(curl, CURLOPT_VERBOSE, config->conf&CONF_VERBOSE); + /* new in curl 7.9.7 */ + if(config->trace_dump) { + curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace); + curl_easy_setopt(curl, CURLOPT_DEBUGDATA, config); + config->conf |= CONF_VERBOSE; /* force verbose */ + } + curl_easy_setopt(curl, CURLOPT_VERBOSE, config->conf&CONF_VERBOSE); - /* new in curl 7.10 */ - curl_easy_setopt(curl, CURLOPT_ENCODING, - (config->encoding) ? "" : NULL); + /* new in curl 7.10 */ + curl_easy_setopt(curl, CURLOPT_ENCODING, + (config->encoding) ? "" : NULL); - /* new in curl 7.10.7 */ - curl_easy_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS, - config->ftp_create_dirs); - if(config->proxyntlm) - curl_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_NTLM); + /* new in curl 7.10.7 */ + curl_easy_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS, + config->ftp_create_dirs); + if(config->proxyntlm) + curl_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_NTLM); - res = curl_easy_perform(curl); + res = curl_easy_perform(curl); - if((config->progressmode == CURL_PROGRESS_BAR) && - progressbar.calls) { - /* if the custom progress bar has been displayed, we output a - newline here */ - fputs("\n", progressbar.out); - } + if((config->progressmode == CURL_PROGRESS_BAR) && + progressbar.calls) { + /* if the custom progress bar has been displayed, we output a + newline here */ + fputs("\n", progressbar.out); + } - if(config->writeout) { - ourWriteOut(curl, config->writeout); - } + if(config->writeout) { + ourWriteOut(curl, config->writeout); + } #ifdef USE_ENVIRONMENT - if (config->writeenv) - ourWriteEnv(curl); + if (config->writeenv) + ourWriteEnv(curl); #endif #ifdef VMS - if (!config->showerror) { - vms_show = VMSSTS_HIDE; - } + if (!config->showerror) { + vms_show = VMSSTS_HIDE; + } #else - if((res!=CURLE_OK) && config->showerror) { - if(CURLE_SSL_CACERT == res) { - fprintf(config->errors, "curl: (%d) %s\n\n", res, errorbuffer); + if((res!=CURLE_OK) && config->showerror) { + if(CURLE_SSL_CACERT == res) { + fprintf(config->errors, "curl: (%d) %s\n\n", res, errorbuffer); #define CURL_CA_CERT_ERRORMSG1 \ "More details here: http://curl.haxx.se/docs/sslcerts.html\n\n" \ "curl performs SSL certificate verification by default, using a \"bundle\"\n" \ @@ -3173,60 +3233,73 @@ operate(struct Configurable *config, int argc, char *argv[]) "If you'd like to turn off curl's verification of the certificate, use\n" \ " the -k (or --insecure) option.\n" - fprintf(config->errors, "%s%s", - CURL_CA_CERT_ERRORMSG1, - CURL_CA_CERT_ERRORMSG2 ); + fprintf(config->errors, "%s%s", + CURL_CA_CERT_ERRORMSG1, + CURL_CA_CERT_ERRORMSG2 ); + } + else + fprintf(config->errors, "curl: (%d) %s\n", res, errorbuffer); } - else - fprintf(config->errors, "curl: (%d) %s\n", res, errorbuffer); - } #endif - if (outfile && !curl_strequal(outfile, "-") && outs.stream) - fclose(outs.stream); + if (outfile && !curl_strequal(outfile, "-") && outs.stream) + fclose(outs.stream); #ifdef HAVE_UTIME - /* Important that we set the time _after_ the file has been - closed, as is done above here */ - if(config->remote_time && outs.filename) { - /* as libcurl if we got a time. Pretty please */ - long filetime; - curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime); - if(filetime >= 0) { - struct utimbuf times; - times.actime = filetime; - times.modtime = filetime; - utime(outs.filename, ×); /* set the time we got */ + /* Important that we set the time _after_ the file has been + closed, as is done above here */ + if(config->remote_time && outs.filename) { + /* as libcurl if we got a time. Pretty please */ + long filetime; + curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime); + if(filetime >= 0) { + struct utimbuf times; + times.actime = filetime; + times.modtime = filetime; + utime(outs.filename, ×); /* set the time we got */ + } } - } #endif - if (config->infile) - fclose(infd); - if(headerfilep) - fclose(headerfilep); + if(headerfilep) + fclose(headerfilep); - if (httpgetfields) - free(httpgetfields); + if (httpgetfields) + free(httpgetfields); - if(url) - free(url); + if(url) + free(url); + + if(outfile) + free(outfile); + + if(infdfopen) + fclose(infd); + + } /* loop to the next URL */ + + if(urls) + /* cleanup memory used for URL globbing patterns */ + glob_cleanup(urls); + + if(uploadfile) + free(uploadfile); + + } /* loop to the next globbed upload file */ + + if(inglob) + glob_cleanup(inglob); - if(outfile) - free(outfile); - } if(outfiles) free(outfiles); - if(urls) - /* cleanup memory used for URL globbing patterns */ - glob_cleanup(urls); - /* empty this urlnode struct */ if(urlnode->url) free(urlnode->url); if(urlnode->outfile) free(urlnode->outfile); + if(urlnode->infile) + free(urlnode->infile); /* move on to the next URL */ nextnode=urlnode->next;