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
This commit is contained in:
Daniel Stenberg 2022-10-10 10:55:05 +02:00
parent b82eb72d80
commit d24a2ffefe
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
4 changed files with 62 additions and 52 deletions

View File

@ -1131,12 +1131,10 @@ static CURLcode single_transfer(struct GlobalConfig *global,
/* /*
* We have specified a file to upload and it isn't "-". * We have specified a file to upload and it isn't "-".
*/ */
char *nurl = add_file_name_to_url(per->this_url, per->uploadfile); result = add_file_name_to_url(per->curl, &per->this_url,
if(!nurl) { per->uploadfile);
result = CURLE_OUT_OF_MEMORY; if(result)
break; break;
}
per->this_url = nurl;
} }
else if(per->uploadfile && stdin_upload(per->uploadfile)) { else if(per->uploadfile && stdin_upload(per->uploadfile)) {
/* count to see if there are more than one auth bit set /* count to see if there are more than one auth bit set

View File

@ -73,61 +73,73 @@ bool stdin_upload(const char *uploadfile)
* Adds the file name to the URL if it doesn't already have one. * 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 * 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 */ CURLcode result = CURLE_OUT_OF_MEMORY;
char *ptr = strstr(url, "://"); CURLU *uh = curl_url();
CURL *curl = curl_easy_init(); /* for url escaping */ char *path = NULL;
if(!curl) if(uh) {
return NULL; /* error! */ char *ptr;
if(ptr) if(curl_url_set(uh, CURLUPART_URL, *inurlp,
ptr += 3; CURLU_GUESS_SCHEME|CURLU_NON_SUPPORT_SCHEME))
else goto fail;
ptr = url; if(curl_url_get(uh, CURLUPART_PATH, &path, 0))
ptr = strrchr(ptr, '/'); goto fail;
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 ptr = strrchr(path, '/');
side of the rightmost slash and backslash. */ if(!ptr || !*++ptr) {
const char *filep = strrchr(filename, '/'); /* The URL path has no file name part, add the local file name. In order
char *file2 = strrchr(filep?filep:filename, '\\'); to be able to do so, we have to create a new URL in another buffer.*/
char *encfile;
if(file2) /* We only want the part of the local path that is on the right
filep = file2 + 1; side of the rightmost slash and backslash. */
else if(filep) const char *filep = strrchr(filename, '/');
filep++; char *file2 = strrchr(filep?filep:filename, '\\');
else char *encfile;
filep = filename;
/* URL encode the file name */ if(file2)
encfile = curl_easy_escape(curl, filep, 0 /* use strlen */); filep = file2 + 1;
if(encfile) { else if(filep)
char *urlbuffer; filep++;
if(ptr)
/* there is a trailing slash on the URL */
urlbuffer = aprintf("%s%s", url, encfile);
else else
/* there is no trailing slash on the URL */ filep = filename;
urlbuffer = aprintf("%s/%s", url, encfile);
curl_free(encfile); /* 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);
if(!urlbuffer) { curl_free(encfile);
url = NULL;
goto end; 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: fail:
curl_easy_cleanup(curl); curl_url_cleanup(uh);
return url; curl_free(path);
return result;
} }
/* Extracts the name portion of the URL. /* Extracts the name portion of the URL.

View File

@ -33,7 +33,7 @@ bool output_expected(const char *url, const char *uploadfile);
bool stdin_upload(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); CURLcode get_url_file_name(char **filename, const char *url);

View File

@ -36,7 +36,7 @@ a few bytes
# Verify data after the test has been "shot" # Verify data after the test has been "shot"
<verify> <verify>
<protocol> <protocol>
PUT /we/want/%TESTNUMBERte%5B%5Dst.txt HTTP/1.1 PUT /we/want/%TESTNUMBERte%5b%5dst.txt HTTP/1.1
Host: %HOSTIP:%HTTPPORT Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION User-Agent: curl/%VERSION
Accept: */* Accept: */*