summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2022-10-10 10:55:05 +0200
committerDaniel Stenberg <daniel@haxx.se>2022-10-10 22:39:41 +0200
commitd24a2ffefe37501e65b57719ca8a8aaa0035a57d (patch)
treeacb41d1f22c481ca882d1920e41df3846d0747a4
parentb82eb72d8097c93313329a4aecd41317a293f506 (diff)
downloadcurl-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.c8
-rw-r--r--src/tool_operhlp.c112
-rw-r--r--src/tool_operhlp.h2
-rw-r--r--tests/data/test582
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: */*