diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 111 |
1 files changed, 95 insertions, 16 deletions
diff --git a/src/main.c b/src/main.c index d1b7009b7..d0bbdcdd7 100644 --- a/src/main.c +++ b/src/main.c @@ -357,6 +357,7 @@ struct OutStruct { }; struct Configurable { + CURL *easy; /* once we have one, we keep it here */ bool remote_time; char *random_file; char *egd_file; @@ -619,6 +620,7 @@ static void help(void) " -d/--data <data> HTTP POST data (H)", " --data-ascii <data> HTTP POST ASCII data (H)", " --data-binary <data> HTTP POST binary data (H)", + " --data-urlencode <name=data/name@filename> HTTP POST data url encoded (H)", " --negotiate Use HTTP Negotiate Authentication (H)", " --digest Use HTTP Digest Authentication (H)", " --disable-eprt Inhibit using EPRT or LPRT (F)", @@ -1532,6 +1534,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */ {"d", "data", TRUE}, {"da", "data-ascii", TRUE}, {"db", "data-binary", TRUE}, + {"de", "data-urlencode", TRUE}, {"D", "dump-header", TRUE}, {"e", "referer", TRUE}, {"E", "cert", TRUE}, @@ -2045,12 +2048,83 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */ /* postfield data */ { char *postdata=NULL; + FILE *file; + + if(subletter == 'e') { /* --data-urlencode*/ + /* [name]=[content], we encode the content part only + * [name]@[file name] + * + * Case 2: we first load the file using that name and then encode + * the content. + */ + char *p = strchr(nextarg, '='); + long size = 0; + size_t nlen; + if(!p) + p = strchr(nextarg, '@'); + if(!p) { + warnf(config, "bad use of --data-urlencode\n"); + return PARAM_BAD_USE; + } + nlen = p - nextarg; /* length of the name part */ + if('@' == *p) { + /* a '@' letter, it means that a file name or - (stdin) follows */ + + p++; /* pass the separator */ - if('@' == *nextarg) { + if(curlx_strequal("-", p)) { + file = stdin; + SET_BINMODE(stdin); + } + else { + file = fopen(p, "rb"); + if(!file) + warnf(config, + "Couldn't read data from file \"%s\", this makes " + "an empty POST.\n", nextarg); + } + + postdata = file2memory(file, &size); + + if(file && (file != stdin)) + fclose(file); + } + else { + GetStr(&postdata, ++p); + size = strlen(postdata); + } + + if(!postdata) { + /* no data from the file, point to a zero byte string to make this + get sent as a POST anyway */ + postdata=strdup(""); + } + else { + char *enc = curl_easy_escape(config->easy, postdata, size); + if(enc) { + /* now make a string with the name from above and append the + encoded string */ + size_t outlen = nlen + strlen(enc) + 2; + char *n = malloc(outlen); + if(!n) + return PARAM_NO_MEM; + + snprintf(n, outlen, "%.*s=%s", nlen, nextarg, enc); + curl_free(enc); + free(postdata); + if(n) { + postdata = n; + } + else + return PARAM_NO_MEM; + } + else + return PARAM_NO_MEM; + } + } + else if('@' == *nextarg) { /* the data begins with a '@' letter, it means that a file name or - (stdin) follows */ - FILE *file; - nextarg++; /* pass the @ */ if(curlx_strequal("-", nextarg)) { @@ -3334,6 +3408,9 @@ static void free_config_fields(struct Configurable *config) curl_slist_free_all(config->postquote); curl_slist_free_all(config->headers); curl_slist_free_all(config->telnet_options); + + if(config->easy) + curl_easy_cleanup(config->easy); } #ifdef WIN32 @@ -3443,9 +3520,9 @@ CURLcode _my_setopt(CURL *curl, struct Configurable *config, const char *name, if(config->libcurl) { /* we only use this for real if --libcurl was used */ - bufp = curl_maprintf("%scurl_easy_setopt(hnd, %s, %s);%s", - remark?"/* ":"", name, value, - remark?" [REMARK] */":""); + bufp = curlx_maprintf("%scurl_easy_setopt(hnd, %s, %s);%s", + remark?"/* ":"", name, value, + remark?" [REMARK] */":""); if (!bufp || !curl_slist_append(easycode, bufp)) ret = CURLE_OUT_OF_MEMORY; @@ -3577,6 +3654,17 @@ operate(struct Configurable *config, int argc, argv_item_t argv[]) } #endif + /* + * Get a curl handle to use for all forthcoming curl transfers. Cleanup + * when all transfers are done. + */ + curl = curl_easy_init(); + if(!curl) { + clean_getout(config); + return CURLE_FAILED_INIT; + } + config->easy = curl; + memset(&outs,0,sizeof(outs)); config->outs = &outs; @@ -3733,16 +3821,6 @@ operate(struct Configurable *config, int argc, argv_item_t argv[]) } } - /* - * Get a curl handle to use for all forthcoming curl transfers. Cleanup - * when all transfers are done. - */ - curl = curl_easy_init(); - if(!curl) { - clean_getout(config); - return CURLE_FAILED_INIT; - } - /* This is the first entry added to easycode and it initializes the slist */ easycode = curl_slist_append(easycode, "CURL *hnd = curl_easy_init();"); if(!easycode) { @@ -4663,6 +4741,7 @@ quit_curl: /* cleanup the curl handle! */ curl_easy_cleanup(curl); + config->easy = NULL; /* cleanup now */ if (easycode) curl_slist_append(easycode, "curl_easy_cleanup(hnd);"); |