]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
curl/add_file_name_to_url: use the libcurl URL parser
authorDaniel Stenberg <daniel@haxx.se>
Mon, 10 Oct 2022 08:55:05 +0000 (10:55 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 10 Oct 2022 20:39:41 +0000 (22:39 +0200)
instead of the custom error-prone parser, to extract and update the path
of the given URL

Closes #9683

src/tool_operate.c
src/tool_operhlp.c
src/tool_operhlp.h
tests/data/test58

index d45c3315e41a98b52d84ffb3543954df3f472aab..544c04a29f1fe97f2a10b12e3573042d46f89351 100644 (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
index 014444219c0fdd9fc2ec2f6f61145e9c635fd270..d311e8d9daa4f72069d2712b0da9ea1d31b67a2b 100644 (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.*/
-
-    /* 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.
index c48d7eca64c4a1a2c79bfcd8cf508476fce398de..8018d1a67c7e3d853a5898927235c1421c7952f3 100644 (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);
 
index 01d7189a81a95d98c1aa89a2f9e50881d22f2dce..75765b224f955ee0049889cfe080954ddf49cd42 100644 (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\r
+PUT /we/want/%TESTNUMBERte%5b%5dst.txt HTTP/1.1\r
 Host: %HOSTIP:%HTTPPORT\r
 User-Agent: curl/%VERSION\r
 Accept: */*\r