]> granicus.if.org Git - curl/commitdiff
urlapi: add CURLUPART_ZONEID to set and get
authorDaniel Stenberg <daniel@haxx.se>
Fri, 3 May 2019 11:18:12 +0000 (13:18 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Sun, 5 May 2019 13:52:46 +0000 (15:52 +0200)
The zoneid can be used with IPv6 numerical addresses.

Updated test 1560 to verify.

Closes #3834

docs/TODO
docs/libcurl/curl_url_get.3
docs/libcurl/curl_url_set.3
docs/libcurl/symbols-in-versions
include/curl/urlapi.h
lib/urlapi.c
tests/data/test1560
tests/libtest/lib1560.c

index 5454b5e023754c71dc92d970456959dbefa08667..912eefc1a5baec8f9b462c88e66c3c0507717808 100644 (file)
--- a/docs/TODO
+++ b/docs/TODO
@@ -35,7 +35,6 @@
  1.16 Try to URL encode given URL
  1.17 Add support for IRIs
  1.18 try next proxy if one doesn't work
- 1.19 add CURLUPART_SCOPEID
  1.20 SRV and URI DNS records
  1.21 Have the URL API offer IDN decoding
  1.22 CURLINFO_PAUSE_STATE
 
  https://github.com/curl/curl/issues/896
 
-1.19 add CURLUPART_SCOPEID
-
- Add support for CURLUPART_SCOPEID to curl_url_set() and curl_url_get(). It is
- only really used when the host name is an IPv6 numerical address.
-
 1.20 SRV and URI DNS records
 
  Offer support for resolving SRV and URI DNS records for libcurl to know which
index 0adc65a5fb89c7f5dff9b6994e68806932aa5045..d5445e3c8f5d64c9b726bf62190b4b259e7b5ff1 100644 (file)
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
 .\" *
 .\" * This software is licensed as described in the file COPYING, which
 .\" * you should have received as part of this distribution. The terms
@@ -76,6 +76,10 @@ Scheme cannot be URL decoded on get.
 .IP CURLUPART_PASSWORD
 .IP CURLUPART_OPTIONS
 .IP CURLUPART_HOST
+If the host part is an IPv6 numeric address, the zoneid will not be part of
+the extracted host but is provided separately in \fICURLUPART_ZONEID\fP.
+.IP CURLUPART_ZONEID
+If the host name is a numeric IPv6 address, this field might also be set.
 .IP CURLUPART_PORT
 Port cannot be URL decoded on get.
 .IP CURLUPART_PATH
@@ -104,7 +108,7 @@ If this function returns an error, no URL part is returned.
   }
 .fi
 .SH AVAILABILITY
-Added in curl 7.62.0
+Added in curl 7.62.0. CURLUPART_ZONEID was added in 7.65.0.
 .SH "SEE ALSO"
 .BR curl_url_cleanup "(3), " curl_url "(3), " curl_url_set "(3), "
 .BR curl_url_dup "(3), "
index 4096d8a23fd1a500b4fe3c4b33faa5f78a8905c2..43d741220b992775e3efb8e97f475f5b2decb17d 100644 (file)
@@ -62,6 +62,8 @@ Scheme cannot be URL decoded on set.
 .IP CURLUPART_HOST
 The host name can use IDNA. The string must then be encoded as your locale
 says or UTF-8 (when winidn is used).
+.IP CURLUPART_ZONEID
+If the host name is a numeric IPv6 address, this field can also be set.
 .IP CURLUPART_PORT
 Port cannot be URL encoded on set. The given port number is provided as a
 string and the decimal number must be between 1 and 65535. Anything else will
@@ -127,7 +129,7 @@ If this function returns an error, no URL part is returned.
   curl_url_cleanup(url);
 .fi
 .SH AVAILABILITY
-Added in curl 7.62.0
+Added in curl 7.62.0. CURLUPART_ZONEID was added in 7.65.0.
 .SH "SEE ALSO"
 .BR curl_url_cleanup "(3), " curl_url "(3), " curl_url_get "(3), "
 .BR curl_url_dup "(3), "
index 36c510139c469101bd1132cb8f33603313a5e09d..715badf9718114e8850ca3f3bfdcafd7158eb1f3 100644 (file)
@@ -764,6 +764,7 @@ CURLUPART_QUERY                 7.62.0
 CURLUPART_SCHEME                7.62.0
 CURLUPART_URL                   7.62.0
 CURLUPART_USER                  7.62.0
+CURLUPART_ZONEID                7.65.0
 CURLUSESSL_ALL                  7.17.0
 CURLUSESSL_CONTROL              7.17.0
 CURLUSESSL_NONE                 7.17.0
index 850faa97a553d04cfcda9f05e7b7afd7cb09bfc1..58e89d85c2a01ca8274daf47232b915eedab6785 100644 (file)
@@ -60,7 +60,8 @@ typedef enum {
   CURLUPART_PORT,
   CURLUPART_PATH,
   CURLUPART_QUERY,
-  CURLUPART_FRAGMENT
+  CURLUPART_FRAGMENT,
+  CURLUPART_ZONEID /* added in 7.65.0 */
 } CURLUPart;
 
 #define CURLU_DEFAULT_PORT (1<<0)       /* return default port number */
index c42dc737a27d1682dd8f8c97fc17d444fa2b9939..c66c07f0a8a88f0f738d81b9b55431cbfa33dfaf 100644 (file)
@@ -56,7 +56,7 @@ struct Curl_URL {
   char *password;
   char *options; /* IMAP only? */
   char *host;
-  char *scopeid; /* for numerical IPv6 addresses */
+  char *zoneid; /* for numerical IPv6 addresses */
   char *port;
   char *path;
   char *query;
@@ -75,7 +75,7 @@ static void free_urlhandle(struct Curl_URL *u)
   free(u->password);
   free(u->options);
   free(u->host);
-  free(u->scopeid);
+  free(u->zoneid);
   free(u->port);
   free(u->path);
   free(u->query);
@@ -606,7 +606,7 @@ static CURLUcode hostname_check(struct Curl_URL *u, char *hostname)
     len = strspn(hostname, l);
     if(hlen != len) {
       /* this could now be '%[zone id]' */
-      char scopeid[16];
+      char zoneid[16];
       if(hostname[len] == '%') {
         int i = 0;
         char *h = &hostname[len + 1];
@@ -614,12 +614,12 @@ static CURLUcode hostname_check(struct Curl_URL *u, char *hostname)
         if(!strncmp(h, "25", 2) && h[2] && (h[2] != ']'))
           h += 2;
         while(*h && (*h != ']') && (i < 15))
-          scopeid[i++] = *h++;
+          zoneid[i++] = *h++;
         if(!i || (']' != *h))
           return CURLUE_MALFORMED_INPUT;
-        scopeid[i] = 0;
-        u->scopeid = strdup(scopeid);
-        if(!u->scopeid)
+        zoneid[i] = 0;
+        u->zoneid = strdup(zoneid);
+        if(!u->zoneid)
           return CURLUE_OUT_OF_MEMORY;
         hostname[len] = ']'; /* insert end bracket */
         hostname[len + 1] = 0; /* terminate the hostname */
@@ -997,6 +997,9 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
     ptr = u->host;
     ifmissing = CURLUE_NO_HOST;
     break;
+  case CURLUPART_ZONEID:
+    ptr = u->zoneid;
+    break;
   case CURLUPART_PORT:
     ptr = u->port;
     ifmissing = CURLUE_NO_PORT;
@@ -1082,16 +1085,16 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
       if(h && !(h->flags & PROTOPT_URLOPTIONS))
         options = NULL;
 
-      if((u->host[0] == '[') && u->scopeid) {
-        /* make it '[ host %25 scopeid ]' */
+      if((u->host[0] == '[') && u->zoneid) {
+        /* make it '[ host %25 zoneid ]' */
         size_t hostlen = strlen(u->host);
-        size_t alen = hostlen + 3 + strlen(u->scopeid) + 1;
+        size_t alen = hostlen + 3 + strlen(u->zoneid) + 1;
         allochost = malloc(alen);
         if(!allochost)
           return CURLUE_OUT_OF_MEMORY;
         memcpy(allochost, u->host, hostlen - 1);
         msnprintf(&allochost[hostlen - 1], alen - hostlen + 1,
-                  "%%25%s]", u->scopeid);
+                  "%%25%s]", u->zoneid);
       }
 
       url = aprintf("%s://%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
@@ -1184,6 +1187,9 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
     case CURLUPART_HOST:
       storep = &u->host;
       break;
+    case CURLUPART_ZONEID:
+      storep = &u->zoneid;
+      break;
     case CURLUPART_PORT:
       u->portnum = 0;
       storep = &u->port;
@@ -1227,8 +1233,11 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
     break;
   case CURLUPART_HOST:
     storep = &u->host;
-    free(u->scopeid);
-    u->scopeid = NULL;
+    free(u->zoneid);
+    u->zoneid = NULL;
+    break;
+  case CURLUPART_ZONEID:
+    storep = &u->zoneid;
     break;
   case CURLUPART_PORT:
   {
index 9f6a122a052532120d8b301dce90bddbab6203f0..a0e603bfc9911c5b9467de28af1107f116c7cf02 100644 (file)
@@ -38,6 +38,8 @@ we got https://[::1]/hello.html
 we got https://example.com/hello.html
 we got https://[fe80::20c:29ff:fe9c:409b%25eth0]/hello.html
 we got [fe80::20c:29ff:fe9c:409b]
+we got eth0
+we got https://[fe80::20c:29ff:fe9c:409b%25clown]/hello.html
 success
 </stdout>
 </verify>
index 0b94957675ee97a8a204ec1973eed0af7ddee671..5ad7134d0bdb79851e5d734b7a54012117047868 100644 (file)
@@ -414,6 +414,10 @@ static int checkurl(const char *url, const char *out)
 
 /* !checksrc! disable SPACEBEFORECOMMA 1 */
 static struct setcase set_parts_list[] = {
+  {"https://[::1%25fake]:1234/",
+   "zoneid=NULL,",
+   "https://[::1]:1234/",
+   0, 0, CURLUE_OK, CURLUE_OK},
   {"https://host:1234/",
    "port=NULL,",
    "https://host/",
@@ -547,6 +551,8 @@ static CURLUPart part2id(char *part)
     return CURLUPART_QUERY;
   if(!strcmp("fragment", part))
     return CURLUPART_FRAGMENT;
+  if(!strcmp("zoneid", part))
+    return CURLUPART_ZONEID;
   return 9999; /* bad input => bad output */
 }
 
@@ -571,6 +577,9 @@ static CURLUcode updateurl(CURLU *u, const char *cmd, unsigned int setflags)
         /* for debugging this */
         fprintf(stderr, "%s = %s [%d]\n", part, value, (int)what);
 #endif
+        if(what > CURLUPART_ZONEID)
+          fprintf(stderr, "UNKNOWN part '%s'\n", part);
+
         if(!strcmp("NULL", value))
           uc = curl_url_set(u, what, NULL, setflags);
         else if(!strcmp("\"\"", value))
@@ -942,6 +951,35 @@ static int scopeid(void)
     curl_free(url);
   }
 
+  rc = curl_url_get(u, CURLUPART_ZONEID, &url, 0);
+  if(rc != CURLUE_OK) {
+    fprintf(stderr, "%s:%d curl_url_get CURLUPART_ZONEID returned %d\n",
+            __FILE__, __LINE__, (int)rc);
+    error++;
+  }
+  else {
+    printf("we got %s\n", url);
+    curl_free(url);
+  }
+
+  rc = curl_url_set(u, CURLUPART_ZONEID, "clown", 0);
+  if(rc != CURLUE_OK) {
+    fprintf(stderr, "%s:%d curl_url_set CURLUPART_ZONEID returned %d\n",
+            __FILE__, __LINE__, (int)rc);
+    error++;
+  }
+
+  rc = curl_url_get(u, CURLUPART_URL, &url, 0);
+  if(rc != CURLUE_OK) {
+    fprintf(stderr, "%s:%d curl_url_get CURLUPART_URL returned %d\n",
+            __FILE__, __LINE__, (int)rc);
+    error++;
+  }
+  else {
+    printf("we got %s\n", url);
+    curl_free(url);
+  }
+
   curl_url_cleanup(u);
 
   return error;