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 "-".
*/
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

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.
* 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.*/
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;
/* 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;
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.*/
if(file2)
filep = file2 + 1;
else if(filep)
filep++;
else
filep = filename;
/* 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;
/* 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);
if(file2)
filep = file2 + 1;
else if(filep)
filep++;
else
/* there is no trailing slash on the URL */
urlbuffer = aprintf("%s/%s", url, encfile);
filep = filename;
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) {
url = NULL;
goto end;
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.

View File

@ -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);

View File

@ -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: */*