diff options
Diffstat (limited to 'libsoup/soup-uri.c')
-rw-r--r-- | libsoup/soup-uri.c | 210 |
1 files changed, 163 insertions, 47 deletions
diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c index 4be679d5..42c2f680 100644 --- a/libsoup/soup-uri.c +++ b/libsoup/soup-uri.c @@ -105,12 +105,63 @@ * 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; @@ -210,10 +263,13 @@ soup_uri_new_with_base (SoupURI *base, const char *uri_string) end = hash; } - /* Find scheme: initial [a-z+.-]* substring until ":" */ + /* Find scheme */ p = uri_string; while (p < end && (g_ascii_isalpha (*p) || - *p == '.' || *p == '+' || *p == '-')) + (p > uri_string && (g_ascii_isdigit (*p) || + *p == '.' || + *p == '+' || + *p == '-')))) p++; if (p > uri_string && *p == ':') { @@ -237,21 +293,23 @@ soup_uri_new_with_base (SoupURI *base, const char *uri_string) if (at && at < path) { colon = strchr (uri_string, ':'); if (colon && colon < at) { - uri->password = uri_decoded_copy (colon + 1, - at - colon - 1); + uri->password = soup_uri_decoded_copy (colon + 1, + at - colon - 1, NULL); } else { uri->password = NULL; colon = at; } - uri->user = uri_decoded_copy (uri_string, - colon - uri_string); + uri->user = soup_uri_decoded_copy (uri_string, + colon - uri_string, NULL); uri_string = at + 1; } else uri->user = uri->password = NULL; /* Find host and port. */ if (*uri_string == '[') { + const char *pct; + uri_string++; hostend = strchr (uri_string, ']'); if (!hostend || hostend > path) { @@ -262,13 +320,20 @@ soup_uri_new_with_base (SoupURI *base, const char *uri_string) colon = hostend + 1; else colon = NULL; + + pct = memchr (uri_string, '%', hostend - uri_string); + if (!pct || (pct[1] == '2' && pct[2] == '5')) { + uri->host = soup_uri_decoded_copy (uri_string, + hostend - uri_string, NULL); + } else + uri->host = g_strndup (uri_string, hostend - uri_string); } else { colon = memchr (uri_string, ':', path - uri_string); hostend = colon ? colon : path; + uri->host = soup_uri_decoded_copy (uri_string, + hostend - uri_string, NULL); } - uri->host = uri_decoded_copy (uri_string, hostend - uri_string); - if (colon && colon != path - 1) { char *portend; uri->port = strtoul (colon + 1, &portend, 10); @@ -436,21 +501,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 +511,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); @@ -469,12 +522,20 @@ soup_uri_to_string (SoupURI *uri, gboolean just_path_and_query) g_string_append_c (str, '@'); } if (strchr (uri->host, ':')) { + const char *pct; + g_string_append_c (str, '['); - g_string_append (str, uri->host); + pct = strchr (uri->host, '%'); + if (pct) { + g_string_append_printf (str, "%.*s%%25%s", + (int) (pct - uri->host), + uri->host, pct + 1); + } else + g_string_append (str, uri->host); 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 +566,28 @@ 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. + * + * Note that the output will never contain a password, even if @uri + * does. + * + * 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,13 +724,14 @@ 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) +soup_uri_decoded_copy (const char *part, int length, int *decoded_length) { unsigned char *s, *d; - char *decoded = g_strndup (part, length); + char *decoded; g_return_val_if_fail (part != NULL, NULL); + decoded = g_strndup (part, length); s = d = (unsigned char *)decoded; do { if (*s == '%') { @@ -662,6 +746,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 +769,7 @@ soup_uri_decode (const char *part) { g_return_val_if_fail (part != NULL, NULL); - return uri_decoded_copy (part, strlen (part)); + return soup_uri_decoded_copy (part, strlen (part), NULL); } static char * @@ -707,7 +794,7 @@ uri_normalized_copy (const char *part, int length, c = HEXCHAR (s); if (soup_char_is_uri_unreserved (c) || - strchr (unescape_extra, c)) { + (c && strchr (unescape_extra, c))) { *d++ = c; s += 3; } else { @@ -801,20 +888,6 @@ soup_uri_uses_default_port (SoupURI *uri) } /** - * SOUP_URI_SCHEME_HTTP: - * - * "http" as an interned string. This can be compared directly against - * the value of a #SoupURI's <structfield>scheme</structfield> - **/ - -/** - * SOUP_URI_SCHEME_HTTPS: - * - * "https" as an interned string. This can be compared directly - * against the value of a #SoupURI's <structfield>scheme</structfield> - **/ - -/** * soup_uri_get_scheme: * @uri: a #SoupURI * @@ -1152,7 +1225,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) @@ -1179,7 +1252,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) @@ -1203,7 +1276,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) @@ -1224,4 +1297,47 @@ soup_uri_host_equal (gconstpointer v1, gconstpointer v2) return g_ascii_strcasecmp (one->host, two->host) == 0; } +gboolean +soup_uri_is_http (SoupURI *uri, char **aliases) +{ + int i; + + if (uri->scheme == SOUP_URI_SCHEME_HTTP) + return TRUE; + else if (uri->scheme == SOUP_URI_SCHEME_HTTPS) + return FALSE; + else if (!aliases) + return FALSE; + + for (i = 0; aliases[i]; i++) { + if (uri->scheme == aliases[i]) + return TRUE; + } + + if (!aliases[1] && !strcmp (aliases[0], "*")) + return TRUE; + else + return FALSE; +} + +gboolean +soup_uri_is_https (SoupURI *uri, char **aliases) +{ + int i; + + if (uri->scheme == SOUP_URI_SCHEME_HTTPS) + return TRUE; + else if (uri->scheme == SOUP_URI_SCHEME_HTTP) + return FALSE; + else if (!aliases) + return FALSE; + + for (i = 0; aliases[i]; i++) { + if (uri->scheme == aliases[i]) + return TRUE; + } + + return FALSE; +} + G_DEFINE_BOXED_TYPE (SoupURI, soup_uri, soup_uri_copy, soup_uri_free) |