1 /*****************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * The contents of this file are subject to the Mozilla Public License
9 * Version 1.0 (the "License"); you may not use this file except in
10 * compliance with the License. You may obtain a copy of the License at
11 * http://www.mozilla.org/MPL/
13 * Software distributed under the License is distributed on an "AS IS"
14 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
15 * License for the specific language governing rights and limitations
18 * The Original Code is Curl.
20 * The Initial Developer of the Original Code is Daniel Stenberg.
22 * Portions created by the Initial Developer are Copyright (C) 1998.
23 * All Rights Reserved.
25 * ------------------------------------------------------------
27 * - Daniel Stenberg <Daniel.Stenberg@haxx.nu>
38 * ------------------------------------------------------------
39 ****************************************************************************/
48 #include <curl/curl.h>
49 #include <curl/mprintf.h>
50 #include "../lib/getdate.h"
53 #define CURLseparator "--_curl_--"
54 #define MIMEseparator "_curl_"
57 /* This is now designed to have its own local setup.h */
62 #ifdef HAVE_IO_H /* typical win32 habit */
70 extern void hugehelp(void);
72 static void helpf(char *fmt, ...)
77 fputs("curl: ", stderr); /* prefix it */
78 vfprintf(stderr, fmt, ap);
81 fprintf(stderr, "curl: try 'curl --help' for more information\n");
84 static void help(void)
87 "Usage: curl [options...] <url>\n"
88 "Options: (H) means HTTP/HTTPS only, (F) means FTP only\n"
89 " -a/--append Append to target file when uploading (F)\n"
90 " -A/--user-agent <string> User-Agent to send to server (H)\n"
91 " -b/--cookie <name=string/file> Cookie string or file to read cookies from (H)\n"
92 " -B/--ftp-ascii Use ASCII transfer (F)\n"
93 " -c/--continue Resume a previous transfer where we left it\n"
94 " -C/--continue-at <offset> Specify absolute resume offset\n"
95 " -d/--data POST data (H)\n"
96 " -D/--dump-header <file> Write the headers to this file\n"
97 " -e/--referer Referer page (H)\n"
98 " -E/--cert <cert:passwd> Specifies your certificate file and password (HTTPS)\n"
99 " -f/--fail Fail silently (no output at all) on errors (H)\n"
100 " -F/--form <name=content> Specify HTTP POST data (H)\n"
102 " -h/--help This help text\n"
103 " -H/--header <line> Custom header to pass to server. (H)\n"
104 " -i/--include Include the HTTP-header in the output (H)\n"
105 " -I/--head Fetch document info only (HTTP HEAD/FTP SIZE)\n"
106 " -K/--config Specify which config file to read\n"
107 " -l/--list-only List only names of an FTP directory (F)\n"
108 " -L/--location Follow Location: hints (H)\n"
109 " -m/--max-time <seconds> Maximum time allowed for the transfer\n"
110 " -M/--manual Display huge help text\n"
111 " -n/--netrc Read .netrc for user name and password\n"
112 " -o/--output <file> Write output to <file> instead of stdout\n"
113 " -O/--remote-name Write output to a file named as the remote file\n"
115 " -p/--port <port> Use port other than default for current protocol.\n"
117 " -P/--ftpport <address> Use PORT with address instead of PASV when ftping (F)\n"
118 " -q When used as the first parameter disables .curlrc\n"
119 " -Q/--quote <cmd> Send QUOTE command to FTP before file transfer (F)\n"
120 " -r/--range <range> Retrieve a byte range from a HTTP/1.1 or FTP server\n"
121 " -s/--silent Silent mode. Don't output anything\n"
122 " -S/--show-error Show error. With -s, make curl show errors when they occur\n"
123 " -t/--upload Transfer/upload stdin to remote site\n"
124 " -T/--upload-file <file> Transfer/upload <file> to remote site\n"
125 " -u/--user <user:password> Specify user and password to use\n"
126 " -U/--proxy-user <user:password> Specify Proxy authentication\n"
127 " -v/--verbose Makes the operation more talkative\n"
128 " -V/--version Outputs version number then quits\n"
129 " -x/--proxy <host> Use proxy. (Default port is 1080)\n"
130 " -X/--request <command> Specific request command to use\n"
131 " -y/--speed-limit Stop transfer if below speed-limit for 'speed-time' secs\n"
132 " -Y/--speed-time Time needed to trig speed-limit abort. Defaults to 30\n"
133 " -z/--time-cond <time> Includes a time condition to the server (H)\n"
134 " -2/--sslv2 Force usage of SSLv2 (H)\n"
135 " -3/--sslv3 Force usage of SSLv3 (H)\n"
136 " -#/--progress-bar Display transfer progress as a progress bar\n"
137 " --crlf Convert LF to CRLF in upload. Useful for MVS (OS/390)\n"
138 " --stderr <file> Where to redirect stderr. - means stdout.\n",
149 struct Configurable {
161 unsigned short porttouse;
180 FILE *errors; /* if stderr redirect is requested */
182 struct curl_slist *quote;
188 struct HttpHeader *headers;
189 struct HttpHeader *last_header;
191 struct HttpPost *httppost;
192 struct HttpPost *last_post;
195 static int parseconfig(char *filename,
196 struct Configurable *config);
198 static void GetStr(char **string,
203 *string = strdup(value);
206 static char *file2string(FILE *file)
215 while(fgets(buffer, sizeof(buffer), file)) {
216 ptr= strchr(buffer, '\r');
219 ptr= strchr(buffer, '\n');
222 stringlen=strlen(buffer);
224 string = realloc(string, len+stringlen+1);
226 string = malloc(stringlen+1);
228 strcpy(string+len, buffer);
235 return NULL; /* no string */
238 static int getparameter(char *flag, /* f or -long-flag */
239 char *nextarg, /* NULL if unset */
240 bool *usedarg, /* set to TRUE if the arg has been
242 struct Configurable *config)
247 struct HttpHeader *head;
254 boolean whether it takes an additional argument
256 struct LongShort aliases[]= {
257 {"9", "crlf", FALSE},
258 {"8", "stderr", TRUE},
260 {"2", "sslv2", FALSE},
261 {"3", "sslv3", FALSE},
262 {"a", "append", FALSE},
263 {"A", "user-agent", TRUE},
264 {"b", "cookie", TRUE},
265 {"B", "ftp-ascii", FALSE},
266 {"c", "continue", FALSE},
267 {"C", "continue-at", TRUE},
269 {"D", "dump-header", TRUE},
270 {"e", "referer", TRUE},
272 {"f", "fail", FALSE},
275 {"h", "help", FALSE},
276 {"H", "header", TRUE},
277 {"i", "include", FALSE},
278 {"I", "head", FALSE},
279 {"K", "config", TRUE},
280 {"l", "list-only", FALSE},
281 {"L", "location", FALSE},
282 {"m", "max-time", TRUE},
283 {"M", "manual", FALSE},
284 {"n", "netrc", FALSE},
285 {"o", "output", TRUE},
286 {"O", "remote-name", FALSE},
290 {"P", "ftpport", TRUE},
291 {"q", "disable", FALSE},
292 {"Q", "quote", TRUE},
293 {"r", "range", TRUE},
294 {"s", "silent", FALSE},
295 {"S", "show-error", FALSE},
296 {"t", "upload", FALSE},
297 {"T", "upload-file", TRUE},
299 {"U", "proxy-user", TRUE},
300 {"v", "verbose", FALSE},
301 {"V", "version", FALSE},
302 {"x", "proxy", TRUE},
303 {"X", "request", TRUE},
304 {"X", "http-request", TRUE}, /* OBSOLETE VERSION */
305 {"y", "speed-time", TRUE},
306 {"Y", "speed-limit", TRUE},
307 {"z", "time-cond", TRUE},
308 {"#", "progress-bar",FALSE},
312 /* try a long name */
313 int fnam=strlen(&flag[1]);
314 for(j=0; j< sizeof(aliases)/sizeof(aliases[0]); j++) {
315 if(strnequal(aliases[j].lname, &flag[1], fnam)) {
316 if(strequal(aliases[j].lname, &flag[1])) {
317 parse = aliases[j].letter;
322 /* this is the second match, we can't continue! */
323 helpf("option --%s is ambiguous\n", &flag[1]);
324 return URG_FAILED_INIT;
326 parse = aliases[j].letter;
331 helpf("unknown option -%s.\n", flag);
332 return URG_FAILED_INIT;
341 /* we can loop here if we have multiple single-letters */
343 letter = parse?*parse:'\0';
344 *usedarg = FALSE; /* default is that we don't use the arg */
347 fprintf(stderr, "OPTION: %c %s\n", letter, nextarg?nextarg:"<null>");
350 for(j=0; j< sizeof(aliases)/sizeof(aliases[0]); j++) {
351 if(letter == *aliases[j].letter) {
357 helpf("unknown option -%c.\n", letter);
358 return URG_FAILED_INIT;
362 helpf("unknown option -%c.\n", letter);
363 return URG_FAILED_INIT;
365 if(!nextarg && aliases[hit].extraparam) {
366 helpf("option -%s/--%s requires an extra argument!\n",
369 return URG_FAILED_INIT;
371 else if(nextarg && aliases[hit].extraparam)
372 *usedarg = TRUE; /* mark it as used */
375 case 'z': /* time condition coming up */
380 /* If-Modified-Since: (section 14.28 in RFC2068) */
381 config->timecond = TIMECOND_IFMODSINCE;
384 /* If-Unmodified-Since: (section 14.24 in RFC2068) */
385 config->timecond = TIMECOND_IFUNMODSINCE;
389 /* Last-Modified: (section 14.29 in RFC2068) */
390 config->timecond = TIMECOND_LASTMOD;
395 config->condtime=get_date(nextarg, &now);
396 if(-1 == config->condtime) {
397 /* now let's see if it is a file name to get the time from instead! */
399 if(-1 == stat(nextarg, &statbuf)) {
400 /* failed, remove time condition */
401 config->timecond = TIMECOND_NONE;
404 /* pull the time out from the file */
405 config->condtime = statbuf.st_mtime;
409 case '9': /* there is no short letter for this */
410 /* LF -> CRLF conversinon? */
413 case '8': /* there is no short letter for this */
414 if(strcmp(nextarg, "-"))
415 config->errors = fopen(nextarg, "wt");
417 config->errors = stdout;
419 case '#': /* added 19990617 larsa */
420 config->progressmode ^= CURL_PROGRESS_BAR;
424 config->ssl_version = 2;
428 config->ssl_version = 3;
431 /* This makes the FTP sessions use APPE instead of STOR */
432 config->conf ^= CONF_FTPAPPEND;
435 /* This specifies the User-Agent name */
436 GetStr(&config->useragent, nextarg);
438 case 'b': /* cookie string coming up: */
439 if(strchr(nextarg, '=')) {
440 /* A cookie string must have a =-letter */
441 GetStr(&config->cookie, nextarg);
444 /* We have a cookie file to read from! */
445 GetStr(&config->cookiefile, nextarg);
449 /* use type ASCII when transfering ftp files */
450 config->conf ^= CONF_FTPASCII;
453 /* This makes us continue an ftp transfer */
454 config->use_resume^=TRUE;
457 /* This makes us continue an ftp transfer at given position */
458 config->resume_from= atoi(nextarg);
459 config->use_resume=TRUE;
463 if('@' == *nextarg) {
464 /* the data begins with a '@' letter, it means that a file name
465 or - (stdin) follows */
467 nextarg++; /* pass the @ */
468 if(strequal("-", nextarg))
471 file = fopen(nextarg, "r");
472 config->postfields = file2string(file);
473 if(file && (file != stdin))
477 GetStr(&config->postfields, nextarg);
479 if(config->postfields)
480 config->conf |= CONF_POST;
483 /* dump-header to given file name */
484 GetStr(&config->headerfile, nextarg);
487 GetStr(&config->referer, nextarg);
488 config->conf |= CONF_REFERER;
492 char *ptr = strchr(nextarg, ':');
494 /* we have a password too */
497 GetStr(&config->cert_passwd, ptr);
499 GetStr(&config->cert, nextarg);
503 /* fail hard on errors */
504 config->conf ^= CONF_FAILONERROR;
507 /* "form data" simulation, this is a little advanced so lets do our best
508 to sort this out slowly and carefully */
509 if(curl_FormParse(nextarg,
512 return URG_FAILED_INIT;
513 config->conf |= CONF_HTTPPOST; /* no toggle, OR! */
516 case 'h': /* h for help */
518 return URG_FAILED_INIT;
520 head = (struct HttpHeader *)malloc(sizeof(struct HttpHeader));
523 head->header = NULL; /* first zero this */
524 GetStr(&head->header, nextarg); /* now get the header line */
526 /* point on our new one */
527 if(config->last_header)
528 config->last_header->next = head;
530 config->headers = head;
533 config->last_header = head;
537 config->conf ^= CONF_HEADER; /* include the HTTP header as well */
540 config->conf ^= CONF_HEADER; /* include the HTTP header in the output */
541 config->conf ^= CONF_NOBODY; /* don't fetch the body at all */
544 res = parseconfig(nextarg, config);
545 config->configread = TRUE;
550 config->conf ^= CONF_FTPLISTONLY; /* only list the names of the FTP dir */
553 config->conf ^= CONF_FOLLOWLOCATION; /* Follow Location: HTTP headers */
556 /* specified max time */
557 config->timeout = atoi(nextarg);
559 case 'M': /* M for manual, huge help */
561 return URG_FAILED_INIT;
563 /* pick info from .netrc, if this is used for http, curl will
564 automatically enfore user+password with the request */
565 config->conf ^= CONF_NETRC;
569 GetStr(&config->outfile, nextarg); /* write to this file */
573 config->remotefile ^= TRUE;
576 /* This makes the FTP sessions use PORT instead of PASV */
577 /* use <eth0> or <192.168.10.10> style addresses. Anything except
578 this will make us try to get the "default" address.
579 NOTE: this is a changed behaviour since the released 4.1!
581 config->conf |= CONF_FTPPORT;
582 GetStr(&config->ftpport, nextarg);
587 fputs("You've used the -p option, it will be removed in a future version\n",
589 config->porttouse = atoi(nextarg);
590 config->conf |= CONF_PORT; /* changed port */
593 case 'q': /* if used first, already taken care of, we do it like
594 this so we don't cause an error! */
597 /* QUOTE command to send to FTP server */
598 config->quote = curl_slist_append(config->quote, nextarg);
601 /* byte range requested */
602 GetStr(&config->range, nextarg);
603 config->conf |= CONF_RANGE;
606 /* don't show progress meter, don't show errors : */
607 config->conf |= (CONF_MUTE|CONF_NOPROGRESS);
608 config->showerror ^= TRUE; /* toggle off */
612 config->showerror ^= TRUE; /* toggle on if used with -s */
615 /* we are uploading */
616 config->conf ^= CONF_UPLOAD;
619 /* we are uploading */
620 config->conf |= CONF_UPLOAD;
621 GetStr(&config->infile, nextarg);
625 GetStr(&config->userpwd, nextarg);
626 config->conf |= CONF_USERPWD;
629 /* Proxy user:password */
630 GetStr(&config->proxyuserpwd, nextarg);
631 config->conf |= CONF_PROXYUSERPWD;
634 config->conf ^= CONF_VERBOSE; /* talk a lot */
637 printf(CURL_ID "%s\n", curl_version());
638 return URG_FAILED_INIT;
642 /* disable proxy when no proxy is given */
643 config->conf &= ~CONF_PROXY;
646 config->conf |= CONF_PROXY;
647 GetStr(&config->proxy, nextarg);
652 GetStr(&config->customrequest, nextarg);
656 config->low_speed_time = atoi(nextarg);
657 if(!config->low_speed_limit)
658 config->low_speed_limit = 1;
661 /* low speed limit */
662 config->low_speed_limit = atoi(nextarg);
663 if(!config->low_speed_time)
664 config->low_speed_time=30;
667 default: /* unknown flag */
669 helpf("Unknown option '%c'\n", letter);
671 helpf("Unknown option\n"); /* short help blurb */
672 return URG_FAILED_INIT;
676 } while(*++parse && !*usedarg);
682 static int parseconfig(char *filename,
683 struct Configurable *config)
687 char configbuffer[4096];
688 char filebuffer[256];
691 if(!filename || !*filename) {
692 /* NULL or no file name attempts to load .curlrc from the homedir! */
694 #define CURLRC DOT_CHAR "curlrc"
696 char *home = curl_GetEnv("HOME"); /* portable environment reader */
698 if(!home || (strlen(home)>(sizeof(filebuffer)-strlen(CURLRC))))
701 sprintf(filebuffer, "%s%s%s", home, DIR_CHAR, CURLRC);
703 filename = filebuffer;
706 if(strcmp(filename,"-"))
707 file = fopen(filename, "r");
714 while(fgets(configbuffer, sizeof(configbuffer), file)) {
715 /* lines with # in the fist column is a comment! */
718 fprintf(stderr, "%s", configbuffer);
720 if('#' == configbuffer[0])
724 while(*tok && isspace((int)*tok))
726 /* tok=strtok(configbuffer, " \t\n"); */
728 fprintf(stderr, "TOK: %s\n", tok);
734 config->url = strdup(tok);
735 nl = strchr(config->url, '\n');
739 while(('-' == tok[0])) {
741 char *firsttok = strdup(tok);
744 /* remove newline from firsttok */
745 nl = strchr(firsttok, '\n');
751 while(*tok2 && !isspace((int)*tok2))
754 /* pass the following white space */
755 while(*tok2 && isspace((int)*tok2))
759 fgets(configbuffer, sizeof(configbuffer), file)) {
760 /* lines with # in the fist column is a comment! */
762 fprintf(stderr, "%s", configbuffer);
764 if('#' == configbuffer[0])
767 /* tok2=strtok(configbuffer, " \t\n"); */
768 /* pass white space */
769 while(*tok2 && isspace((int)*tok2))
772 /* remove newline from tok2 */
773 nl = strchr(tok2, '\n');
777 res = getparameter(firsttok+1,
783 fprintf(stderr, "TOK %s TOK2: %s RES: %d\n",
784 firsttok, tok2?tok2:"NULL", res);
789 /* tok2 is unused, */
793 break; /* we've used both our words */
807 int my_fwrite(void *buffer, size_t size, size_t nmemb, FILE *stream)
809 struct OutStruct *out=(struct OutStruct *)stream;
810 if(out && !out->stream) {
811 /* open file for writing */
812 out->stream=fopen(out->filename, "wb");
814 return -1; /* failure */
816 return fwrite(buffer, size, nmemb, out->stream);
820 int main(int argc, char *argv[])
822 char errorbuffer[URLGET_ERROR_SIZE];
824 struct OutStruct outs;
830 char *outfiles = NULL;
835 FILE *headerfilep = NULL;
836 char *urlbuffer=NULL;
837 int infilesize=-1; /* -1 means unknown */
838 bool stillflags=TRUE;
842 struct Configurable config;
844 outs.stream = stdout;
846 memset(&config, 0, sizeof(struct Configurable));
848 /* set non-zero default values: */
849 config.useragent= maprintf(CURL_NAME "/" CURL_VERSION " (" OS ") "
850 "%s", curl_version());
851 config.showerror=TRUE;
852 config.conf=CONF_DEFAULT;
857 (!strnequal("--", argv[1], 2) && (argv[1][0] == '-')) &&
858 strchr(argv[1], 'q')) {
860 * The first flag, that is not a verbose name, but a shortname
861 * and it includes the 'q' flag!
864 fprintf(stderr, "I TURNED OFF THE CRAP\n");
869 res = parseconfig(NULL, &config);
874 if ((argc < 2) && !config.url) {
876 return URG_FAILED_INIT;
880 for (i = 1; i < argc; i++) {
882 ('-' == argv[i][0])) {
886 char *flag = &argv[i][1];
888 if(strequal("--", argv[i]))
889 /* this indicates the end of the flags and thus enables the
890 following (URL) argument to start with -. */
893 nextarg= (i < argc - 1)? argv[i+1]: NULL;
895 res = getparameter ( flag,
902 if(passarg) /* we're supposed to skip this */
908 helpf("only one URL is supported!\n");
909 return URG_FAILED_INIT;
915 /* if no URL was specified and there was one in the config file, get that
917 if(!url && config.url)
921 helpf("no URL specified!\n");
922 return URG_FAILED_INIT;
925 fprintf(stderr, "URL: %s PROXY: %s\n", url, config.proxy?config.proxy:"none");
929 urlnum = glob_url(&urls, url); /* expand '{...}' and '[...]' expressions and return
930 total number of URLs in pattern set */
931 outfiles = config.outfile; /* save outfile pattern befor expansion */
932 if (!outfiles && !config.remotefile && urlnum > 1) {
933 #ifdef CURL_SEPARATORS
934 /* multiple files extracted to stdout, insert separators! */
937 #ifdef MIME_SEPARATORS
938 /* multiple files extracted to stdout, insert MIME separators! */
940 printf("MIME-Version: 1.0\n");
941 printf("Content-Type: multipart/mixed; boundary=%s\n\n", MIMEseparator);
944 for (i = 0; (url = next_url(urls)); ++i) {
946 config.outfile = strdup(outfiles);
949 if(config.outfile && config.infile) {
950 helpf("you can't both upload and download!\n");
951 return URG_FAILED_INIT;
954 if (config.outfile || config.remotefile) {
956 * We have specified a file name to store the result in, or we have
957 * decided we want to use the remote file name.
960 if(config.remotefile) {
961 /* Find and get the remote file name */
962 config.outfile=strstr(url, "://");
967 config.outfile = strrchr(config.outfile, '/');
968 if(!config.outfile || !strlen(++config.outfile)) {
969 helpf("Remote file name has no length!\n");
970 return URG_WRITE_ERROR;
974 else /* fill '#1' ... '#9' terms from URL pattern */
975 config.outfile = match_url(config.outfile, *urls);
978 if((0 == config.resume_from) && config.use_resume) {
979 /* we're told to continue where we are now, then we get the size of the
980 file as it is now and open it for append instead */
981 struct stat fileinfo;
983 if(0 == stat(config.outfile, &fileinfo)) {
984 /* set offset to current file size: */
985 config.resume_from = fileinfo.st_size;
987 /* else let offset remain 0 */
990 if(config.resume_from) {
991 /* open file for output: */
992 outs.stream=(FILE *) fopen(config.outfile, config.resume_from?"ab":"wb");
994 helpf("Can't open '%s'!\n", config.outfile);
995 return URG_WRITE_ERROR;
999 outs.filename = config.outfile;
1000 outs.stream = NULL; /* open when needed */
1003 if (config.infile) {
1005 * We have specified a file to upload
1007 struct stat fileinfo;
1009 /* If no file name part is given in the URL, we add this file name */
1010 char *ptr=strstr(url, "://");
1015 ptr = strrchr(ptr, '/');
1016 if(!ptr || !strlen(++ptr)) {
1017 /* The URL has no file name part, add the local file name. In order
1018 to be able to do so, we have to create a new URL in another buffer.*/
1019 urlbuffer=(char *)malloc(strlen(url) + strlen(config.infile) + 3);
1021 helpf("out of memory\n");
1022 return URG_OUT_OF_MEMORY;
1025 /* there is a trailing slash on the URL */
1026 sprintf(urlbuffer, "%s%s", url, config.infile);
1028 /* thers is no trailing slash on the URL */
1029 sprintf(urlbuffer, "%s/%s", url, config.infile);
1031 url = urlbuffer; /* use our new URL instead! */
1034 infd=(FILE *) fopen(config.infile, "rb");
1035 if (!infd || stat(config.infile, &fileinfo)) {
1036 helpf("Can't open '%s'!\n", config.infile);
1037 return URG_READ_ERROR;
1039 infilesize=fileinfo.st_size;
1042 if((config.conf&CONF_UPLOAD) &&
1043 config.use_resume &&
1044 (0==config.resume_from)) {
1045 config.resume_from = -1; /* -1 will then force get-it-yourself */
1047 if(config.headerfile) {
1048 /* open file for output: */
1049 if(strcmp(config.headerfile,"-"))
1051 headerfilep=(FILE *) fopen(config.headerfile, "wb");
1053 helpf("Can't open '%s'!\n", config.headerfile);
1054 return URG_WRITE_ERROR;
1061 /* This was previously done in urlget, but that was wrong place to do it */
1062 if(outs.stream && isatty(fileno(outs.stream)))
1063 /* we send the output to a tty, and therefor we switch off the progress
1065 config.conf |= CONF_NOPROGRESS;
1069 fprintf(stderr, "\n[%d/%d]: %s --> %s\n", i+1, urlnum, url, config.outfile ? config.outfile : "<stdout>");
1071 #ifdef CURL_SEPARATORS
1072 printf("%s%s\n", CURLseparator, url);
1074 #ifdef MIME_SEPARATORS
1075 printf("--%s\n", MIMEseparator);
1076 printf("Content-ID: %s\n\n", url);
1083 config.errors = stderr;
1085 res = curl_urlget(URGTAG_FILE, (FILE *)&outs, /* where to store */
1086 URGTAG_WRITEFUNCTION, my_fwrite, /* what call to write */
1087 URGTAG_INFILE, infd, /* for uploads */
1088 URGTAG_INFILESIZE, infilesize, /* size of uploaded file */
1089 URGTAG_URL, url, /* what to fetch */
1090 URGTAG_PROXY, config.proxy, /* proxy to use */
1091 URGTAG_FLAGS, config.conf, /* flags */
1092 URGTAG_USERPWD, config.userpwd, /* user + passwd */
1093 URGTAG_PROXYUSERPWD, config.proxyuserpwd, /* Proxy user + passwd */
1094 URGTAG_RANGE, config.range, /* range of document */
1095 URGTAG_ERRORBUFFER, errorbuffer,
1096 URGTAG_TIMEOUT, config.timeout,
1097 URGTAG_POSTFIELDS, config.postfields,
1098 URGTAG_REFERER, config.referer,
1099 URGTAG_USERAGENT, config.useragent,
1100 URGTAG_FTPPORT, config.ftpport,
1101 URGTAG_LOW_SPEED_LIMIT, config.low_speed_limit,
1102 URGTAG_LOW_SPEED_TIME, config.low_speed_time,
1103 URGTAG_RESUME_FROM, config.use_resume?config.resume_from:0,
1104 URGTAG_COOKIE, config.cookie,
1105 URGTAG_HTTPHEADER, config.headers,
1106 URGTAG_HTTPPOST, config.httppost,
1107 URGTAG_SSLCERT, config.cert,
1108 URGTAG_SSLCERTPASSWD, config.cert_passwd,
1109 URGTAG_CRLF, config.crlf,
1110 URGTAG_QUOTE, config.quote,
1111 URGTAG_WRITEHEADER, headerfilep,
1112 URGTAG_COOKIEFILE, config.cookiefile,
1113 URGTAG_SSLVERSION, config.ssl_version,
1114 URGTAG_TIMECONDITION, config.timecond,
1115 URGTAG_TIMEVALUE, config.condtime,
1116 URGTAG_CUSTOMREQUEST, config.customrequest,
1117 URGTAG_STDERR, config.errors,
1118 URGTAG_DONE); /* always terminate the list of tags */
1119 if((res!=URG_OK) && config.showerror)
1120 fprintf(config.errors, "curl: (%d) %s\n", res, errorbuffer);
1122 if((config.errors != stderr) &&
1123 (config.errors != stdout))
1124 /* it wasn't directed to stdout or stderr so close the file! */
1125 fclose(config.errors);
1129 if (config.outfile && outs.stream)
1130 fclose(outs.stream);
1134 fclose(headerfilep);
1142 if(config.outfile && !config.remotefile)
1143 free(config.outfile);
1145 #ifdef MIME_SEPARATORS
1147 printf("--%s--\n", MIMEseparator);
1151 curl_slist_free_all(config.quote); /* the checks for config.quote == NULL */