diff options
author | Daniel Stenberg <daniel@haxx.se> | 2022-10-10 10:55:05 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2022-10-10 22:39:41 +0200 |
commit | d24a2ffefe37501e65b57719ca8a8aaa0035a57d (patch) | |
tree | acb41d1f22c481ca882d1920e41df3846d0747a4 | |
parent | b82eb72d8097c93313329a4aecd41317a293f506 (diff) | |
download | curl-d24a2ffefe37501e65b57719ca8a8aaa0035a57d.tar.gz |
curl/add_file_name_to_url: use the libcurl URL parser
instead of the custom error-prone parser, to extract and update the path
of the given URL
Closes #9683
-rw-r--r-- | src/tool_operate.c | 8 | ||||
-rw-r--r-- | src/tool_operhlp.c | 112 | ||||
-rw-r--r-- | src/tool_operhlp.h | 2 | ||||
-rw-r--r-- | tests/data/test58 | 2 |
4 files changed, 67 insertions, 57 deletions
diff --git a/src/tool_operate.c b/src/tool_operate.c index d45c3315e..544c04a29 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -1131,12 +1131,10 @@ static CURLcode single_transfer(struct GlobalConfig *global, /* * We have specified a file to upload and it isn't "-". */ - char *nurl = add_file_name_to_url(per->this_url, per->uploadfile); - if(!nurl) { - result = CURLE_OUT_OF_MEMORY; + result = add_file_name_to_url(per->curl, &per->this_url, + per->uploadfile); + if(result) break; - } - per->this_url = nurl; } else if(per->uploadfile && stdin_upload(per->uploadfile)) { /* count to see if there are more than one auth bit set diff --git a/src/tool_operhlp.c b/src/tool_operhlp.c index 014444219..d311e8d9d 100644 --- a/src/tool_operhlp.c +++ b/src/tool_operhlp.c @@ -73,61 +73,73 @@ bool stdin_upload(const char *uploadfile) * Adds the file name to the URL if it doesn't already have one. * url will be freed before return if the returned pointer is different */ -char *add_file_name_to_url(char *url, const char *filename) +CURLcode add_file_name_to_url(CURL *curl, char **inurlp, const char *filename) { - /* If no file name part is given in the URL, we add this file name */ - char *ptr = strstr(url, "://"); - CURL *curl = curl_easy_init(); /* for url escaping */ - if(!curl) - return NULL; /* error! */ - if(ptr) - ptr += 3; - else - ptr = url; - ptr = strrchr(ptr, '/'); - if(!ptr || !*++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. */ - const char *filep = strrchr(filename, '/'); - char *file2 = strrchr(filep?filep:filename, '\\'); - char *encfile; - - if(file2) - filep = file2 + 1; - else if(filep) - filep++; - else - filep = filename; - - /* URL encode the file name */ - encfile = curl_easy_escape(curl, filep, 0 /* use strlen */); - if(encfile) { - char *urlbuffer; - if(ptr) - /* there is a trailing slash on the URL */ - urlbuffer = aprintf("%s%s", url, encfile); + CURLcode result = CURLE_OUT_OF_MEMORY; + CURLU *uh = curl_url(); + char *path = NULL; + if(uh) { + char *ptr; + if(curl_url_set(uh, CURLUPART_URL, *inurlp, + CURLU_GUESS_SCHEME|CURLU_NON_SUPPORT_SCHEME)) + goto fail; + if(curl_url_get(uh, CURLUPART_PATH, &path, 0)) + goto fail; + + ptr = strrchr(path, '/'); + if(!ptr || !*++ptr) { + /* The URL path 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. */ + const char *filep = strrchr(filename, '/'); + char *file2 = strrchr(filep?filep:filename, '\\'); + char *encfile; + + if(file2) + filep = file2 + 1; + else if(filep) + filep++; else - /* there is no trailing slash on the URL */ - urlbuffer = aprintf("%s/%s", url, encfile); - - curl_free(encfile); - - if(!urlbuffer) { - url = NULL; - goto end; + filep = filename; + + /* URL encode the file name */ + encfile = curl_easy_escape(curl, filep, 0 /* use strlen */); + if(encfile) { + char *newpath; + char *newurl; + CURLUcode uerr; + if(ptr) + /* there is a trailing slash on the path */ + newpath = aprintf("%s%s", path, encfile); + else + /* there is no trailing slash on the path */ + newpath = aprintf("%s/%s", path, encfile); + + curl_free(encfile); + + if(!newpath) + goto fail; + uerr = curl_url_set(uh, CURLUPART_PATH, newpath, 0); + free(newpath); + if(uerr) + goto fail; + if(curl_url_get(uh, CURLUPART_URL, &newurl, CURLU_DEFAULT_SCHEME)) + goto fail; + free(*inurlp); + *inurlp = newurl; + result = CURLE_OK; } - - Curl_safefree(url); - url = urlbuffer; /* use our new URL instead! */ } + else + /* nothing to do */ + result = CURLE_OK; } - end: - curl_easy_cleanup(curl); - return url; + fail: + curl_url_cleanup(uh); + curl_free(path); + return result; } /* Extracts the name portion of the URL. diff --git a/src/tool_operhlp.h b/src/tool_operhlp.h index c48d7eca6..8018d1a67 100644 --- a/src/tool_operhlp.h +++ b/src/tool_operhlp.h @@ -33,7 +33,7 @@ bool output_expected(const char *url, const char *uploadfile); bool stdin_upload(const char *uploadfile); -char *add_file_name_to_url(char *url, const char *filename); +CURLcode add_file_name_to_url(CURL *curl, char **inurlp, const char *filename); CURLcode get_url_file_name(char **filename, const char *url); diff --git a/tests/data/test58 b/tests/data/test58 index 01d7189a8..75765b224 100644 --- a/tests/data/test58 +++ b/tests/data/test58 @@ -36,7 +36,7 @@ a few bytes # Verify data after the test has been "shot" <verify> <protocol> -PUT /we/want/%TESTNUMBERte%5B%5Dst.txt HTTP/1.1
+PUT /we/want/%TESTNUMBERte%5b%5dst.txt HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
|