soup-address: fix proxy enumerator implementation
[platform/upstream/libsoup.git] / libsoup / soup-uri.c
index 382a2a9..26ec24a 100644 (file)
  * Since: 2.24
  **/
 
+/**
+ * SOUP_URI_SCHEME_HTTP:
+ *
+ * "http" as an interned string; you can compare this directly to a
+ * #SoupURI's <literal>scheme</literal> field using
+ * <literal>==</literal>.
+ */
+/**
+ * SOUP_URI_SCHEME_HTTPS:
+ *
+ * "https" as an interned string; you can compare this directly to a
+ * #SoupURI's <literal>scheme</literal> field using
+ * <literal>==</literal>.
+ */
+/**
+ * SOUP_URI_SCHEME_FTP:
+ *
+ * "ftp" as an interned string; you can compare this directly to a
+ * #SoupURI's <literal>scheme</literal> field using
+ * <literal>==</literal>.
+ *
+ * Since: 2.30
+ */
+/**
+ * SOUP_URI_SCHEME_FILE:
+ *
+ * "file" as an interned string; you can compare this directly to a
+ * #SoupURI's <literal>scheme</literal> field using
+ * <literal>==</literal>.
+ *
+ * Since: 2.30
+ */
+/**
+ * SOUP_URI_SCHEME_DATA:
+ *
+ * "data" as an interned string; you can compare this directly to a
+ * #SoupURI's <literal>scheme</literal> field using
+ * <literal>==</literal>.
+ *
+ * Since: 2.30
+ */
+/**
+ * SOUP_URI_SCHEME_RESOURCE:
+ *
+ * "data" as an interned string; you can compare this directly to a
+ * #SoupURI's <literal>scheme</literal> field using
+ * <literal>==</literal>.
+ *
+ * Since: 2.42
+ */
+
 static void append_uri_encoded (GString *str, const char *in, const char *extra_enc_chars);
 static char *uri_normalized_copy (const char *str, int length, const char *unescape_extra);
 
 gpointer _SOUP_URI_SCHEME_HTTP, _SOUP_URI_SCHEME_HTTPS;
 gpointer _SOUP_URI_SCHEME_FTP;
-gpointer _SOUP_URI_SCHEME_FILE, _SOUP_URI_SCHEME_DATA;
+gpointer _SOUP_URI_SCHEME_FILE, _SOUP_URI_SCHEME_DATA, _SOUP_URI_SCHEME_RESOURCE;
 
 static inline const char *
 soup_uri_parse_scheme (const char *scheme, int len)
@@ -119,6 +170,8 @@ soup_uri_parse_scheme (const char *scheme, int len)
                return SOUP_URI_SCHEME_HTTP;
        } else if (len == 5 && !g_ascii_strncasecmp (scheme, "https", len)) {
                return SOUP_URI_SCHEME_HTTPS;
+       } else if (len == 8 && !g_ascii_strncasecmp (scheme, "resource", len)) {
+               return SOUP_URI_SCHEME_RESOURCE;
        } else {
                char *lower_scheme;
 
@@ -238,14 +291,14 @@ soup_uri_new_with_base (SoupURI *base, const char *uri_string)
                        colon = strchr (uri_string, ':');
                        if (colon && colon < at) {
                                uri->password = uri_decoded_copy (colon + 1,
-                                                                 at - colon - 1);
+                                                                 at - colon - 1, NULL);
                        } else {
                                uri->password = NULL;
                                colon = at;
                        }
 
                        uri->user = uri_decoded_copy (uri_string,
-                                                     colon - uri_string);
+                                                     colon - uri_string, NULL);
                        uri_string = at + 1;
                } else
                        uri->user = uri->password = NULL;
@@ -267,7 +320,7 @@ soup_uri_new_with_base (SoupURI *base, const char *uri_string)
                        hostend = colon ? colon : path;
                }
 
-               uri->host = uri_decoded_copy (uri_string, hostend - uri_string);
+               uri->host = uri_decoded_copy (uri_string, hostend - uri_string, NULL);
 
                if (colon && colon != path - 1) {
                        char *portend;
@@ -436,21 +489,9 @@ soup_uri_new (const char *uri_string)
 }
 
 
-/**
- * soup_uri_to_string:
- * @uri: a #SoupURI
- * @just_path_and_query: if %TRUE, output just the path and query portions
- *
- * Returns a string representing @uri.
- *
- * If @just_path_and_query is %TRUE, this concatenates the path and query
- * together. That is, it constructs the string that would be needed in
- * the Request-Line of an HTTP request for @uri.
- *
- * Return value: a string representing @uri, which the caller must free.
- **/
 char *
-soup_uri_to_string (SoupURI *uri, gboolean just_path_and_query)
+soup_uri_to_string_internal (SoupURI *uri, gboolean just_path_and_query,
+                            gboolean force_port)
 {
        GString *str;
        char *return_result;
@@ -458,7 +499,7 @@ soup_uri_to_string (SoupURI *uri, gboolean just_path_and_query)
        g_return_val_if_fail (uri != NULL, NULL);
        g_warn_if_fail (SOUP_URI_IS_VALID (uri));
 
-       str = g_string_sized_new (20);
+       str = g_string_sized_new (40);
 
        if (uri->scheme && !just_path_and_query)
                g_string_append_printf (str, "%s:", uri->scheme);
@@ -474,7 +515,7 @@ soup_uri_to_string (SoupURI *uri, gboolean just_path_and_query)
                        g_string_append_c (str, ']');
                } else
                        append_uri_encoded (str, uri->host, ":/");
-               if (uri->port && uri->port != soup_scheme_default_port (uri->scheme))
+               if (uri->port && (force_port || uri->port != soup_scheme_default_port (uri->scheme)))
                        g_string_append_printf (str, ":%u", uri->port);
                if (!uri->path && (uri->query || uri->fragment))
                        g_string_append_c (str, '/');
@@ -505,6 +546,25 @@ soup_uri_to_string (SoupURI *uri, gboolean just_path_and_query)
 }
 
 /**
+ * soup_uri_to_string:
+ * @uri: a #SoupURI
+ * @just_path_and_query: if %TRUE, output just the path and query portions
+ *
+ * Returns a string representing @uri.
+ *
+ * If @just_path_and_query is %TRUE, this concatenates the path and query
+ * together. That is, it constructs the string that would be needed in
+ * the Request-Line of an HTTP request for @uri.
+ *
+ * Return value: a string representing @uri, which the caller must free.
+ **/
+char *
+soup_uri_to_string (SoupURI *uri, gboolean just_path_and_query)
+{
+       return soup_uri_to_string_internal (uri, just_path_and_query, FALSE);
+}
+
+/**
  * soup_uri_copy:
  * @uri: a #SoupURI
  *
@@ -641,7 +701,7 @@ soup_uri_encode (const char *part, const char *escape_extra)
 #define HEXCHAR(s) ((XDIGIT (s[1]) << 4) + XDIGIT (s[2]))
 
 char *
-uri_decoded_copy (const char *part, int length)
+uri_decoded_copy (const char *part, int length, int *decoded_length)
 {
        unsigned char *s, *d;
        char *decoded = g_strndup (part, length);
@@ -662,6 +722,9 @@ uri_decoded_copy (const char *part, int length)
                        *d++ = *s;
        } while (*s++);
 
+       if (decoded_length)
+               *decoded_length = d - (unsigned char *)decoded - 1;
+
        return decoded;
 }
 
@@ -682,7 +745,7 @@ soup_uri_decode (const char *part)
 {
        g_return_val_if_fail (part != NULL, NULL);
 
-       return uri_decoded_copy (part, strlen (part));
+       return uri_decoded_copy (part, strlen (part), NULL);
 }
 
 static char *
@@ -693,6 +756,9 @@ uri_normalized_copy (const char *part, int length,
        char *normalized = g_strndup (part, length);
        gboolean need_fixup = FALSE;
 
+       if (!unescape_extra)
+               unescape_extra = "";
+
        s = d = (unsigned char *)normalized;
        while (*s) {
                if (*s == '%') {
@@ -704,7 +770,7 @@ uri_normalized_copy (const char *part, int length,
 
                        c = HEXCHAR (s);
                        if (soup_char_is_uri_unreserved (c) ||
-                           (unescape_extra && strchr (unescape_extra, c))) {
+                           (c && strchr (unescape_extra, c))) {
                                *d++ = c;
                                s += 3;
                        } else {
@@ -717,7 +783,8 @@ uri_normalized_copy (const char *part, int length,
                                *d++ = *s++;
                        }
                } else {
-                       if (!g_ascii_isgraph (*s))
+                       if (!g_ascii_isgraph (*s) &&
+                           !strchr (unescape_extra, *s))
                                need_fixup = TRUE;
                        *d++ = *s++;
                }
@@ -730,7 +797,8 @@ uri_normalized_copy (const char *part, int length,
                fixed = g_string_new (NULL);
                s = (guchar *)normalized;
                while (*s) {
-                       if (g_ascii_isgraph (*s))
+                       if (g_ascii_isgraph (*s) ||
+                           strchr (unescape_extra, *s))
                                g_string_append_c (fixed, *s);
                        else
                                g_string_append_printf (fixed, "%%%02X", (int)*s);
@@ -810,6 +878,15 @@ soup_uri_uses_default_port (SoupURI *uri)
  **/
 
 /**
+ * SOUP_URI_SCHEME_RESOURCE:
+ *
+ * "resource" as an interned string. This can be compared directly
+ * against the value of a #SoupURI's <structfield>scheme</structfield>
+ *
+ * Since: 2.42
+ **/
+
+/**
  * soup_uri_get_scheme:
  * @uri: a #SoupURI
  *
@@ -1147,7 +1224,7 @@ soup_uri_set_fragment (SoupURI *uri, const char *fragment)
  *
  * Return value: the new #SoupURI
  *
- * Since: 2.26.3
+ * Since: 2.28
  **/
 SoupURI *
 soup_uri_copy_host (SoupURI *uri)
@@ -1174,7 +1251,7 @@ soup_uri_copy_host (SoupURI *uri)
  *
  * Return value: a hash
  *
- * Since: 2.26.3
+ * Since: 2.28
  **/
 guint
 soup_uri_host_hash (gconstpointer key)
@@ -1198,7 +1275,7 @@ soup_uri_host_hash (gconstpointer key)
  * Return value: whether or not the URIs are equal in scheme, host,
  * and port.
  *
- * Since: 2.26.3
+ * Since: 2.28
  **/
 gboolean
 soup_uri_host_equal (gconstpointer v1, gconstpointer v2)