summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Griffis <pgriffis@igalia.com>2013-11-24 14:50:41 -0500
committerPatrick Griffis <pgriffis@igalia.com>2020-07-26 10:02:46 -0700
commitd0f257fc8f3c245476eef0f015ab15cc98bbd061 (patch)
treedb0c8b4c22449f4ef52df519a6470fec1f9e9b53
parentbfdcd72d11c15d5aafd38e1e193fff5ae6c015d1 (diff)
downloadlibsoup-d0f257fc8f3c245476eef0f015ab15cc98bbd061.tar.gz
WIP: Back SoupURI with GUriwip/uri-testing-2
-rw-r--r--libsoup/soup-uri.c328
1 files changed, 81 insertions, 247 deletions
diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c
index 4bb55b81..ccac4b6f 100644
--- a/libsoup/soup-uri.c
+++ b/libsoup/soup-uri.c
@@ -186,30 +186,6 @@ gpointer _SOUP_URI_SCHEME_WS, _SOUP_URI_SCHEME_WSS;
gpointer _SOUP_URI_SCHEME_FTP;
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)
-{
- if (len == 4 && !g_ascii_strncasecmp (scheme, "http", 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 if (len == 2 && !g_ascii_strncasecmp (scheme, "ws", len)) {
- return SOUP_URI_SCHEME_WS;
- } else if (len == 3 && !g_ascii_strncasecmp (scheme, "wss", len)) {
- return SOUP_URI_SCHEME_WSS;
- } else {
- char *lower_scheme;
-
- lower_scheme = g_ascii_strdown (scheme, len);
- scheme = g_intern_static_string (lower_scheme);
- if (scheme != (const char *)lower_scheme)
- g_free (lower_scheme);
- return scheme;
- }
-}
-
static inline guint
soup_scheme_default_port (const char *scheme)
{
@@ -223,6 +199,44 @@ soup_scheme_default_port (const char *scheme)
return 0;
}
+static GUri *
+soup_uri_to_g_uri (SoupURI *uri)
+{
+ gint port = -1;
+
+ if (!uri)
+ return NULL;
+
+ if (uri->port != 0 && uri->port != soup_scheme_default_port (uri->scheme))
+ port = uri->port;
+
+ return g_uri_build_with_user (G_URI_FLAGS_ENCODED | G_URI_FLAGS_HAS_PASSWORD,
+ uri->scheme,
+ uri->user, uri->password, NULL,
+ uri->host,
+ port,
+ uri->path, uri->query, uri->fragment);
+}
+
+static SoupURI *
+soup_uri_from_g_uri (GUri *guri)
+{
+ SoupURI *uri;
+ gint port = g_uri_get_port (guri);;
+
+ uri = g_slice_new0 (SoupURI);
+ uri->scheme = g_intern_string (g_uri_get_scheme (guri));
+ uri->user = g_strdup (g_uri_get_user (guri));
+ uri->password = g_strdup (g_uri_get_password (guri));
+ uri->host = g_strdup (g_uri_get_host (guri));
+ uri->port = port == -1 ? 0 : port;
+ uri->path = g_strdup (g_uri_get_path (guri));
+ uri->query = g_strdup (g_uri_get_query (guri));
+ uri->fragment = g_strdup (g_uri_get_fragment (guri));
+
+ return uri;
+}
+
/**
* soup_uri_new_with_base: (constructor)
* @base: a base URI
@@ -236,12 +250,7 @@ SoupURI *
soup_uri_new_with_base (SoupURI *base, const char *uri_string)
{
SoupURI *uri, fixed_base;
- const char *end, *hash, *colon, *at, *path, *question;
- const char *p, *hostend;
- gboolean remove_dot_segments = TRUE;
- int len;
-
- g_return_val_if_fail (uri_string != NULL, NULL);
+ GUri *base_guri, *guri;
/* Allow a %NULL path in @base, for compatibility */
if (base && base->scheme && !base->path) {
@@ -254,225 +263,24 @@ soup_uri_new_with_base (SoupURI *base, const char *uri_string)
g_return_val_if_fail (base == NULL || SOUP_URI_IS_VALID (base), NULL);
- /* First some cleanup steps (which are supposed to all be no-ops,
- * but...). Skip initial whitespace, strip out internal tabs and
- * line breaks, and ignore trailing whitespace.
- */
- while (g_ascii_isspace (*uri_string))
- uri_string++;
+ base_guri = soup_uri_to_g_uri (base);
+ guri = g_uri_parse_relative (base_guri, uri_string, G_URI_FLAGS_ENCODED | G_URI_FLAGS_HAS_PASSWORD, NULL);
+ if (base_guri)
+ g_uri_unref (base_guri);
- len = strcspn (uri_string, "\t\n\r");
- if (uri_string[len]) {
- char *clean = g_malloc (strlen (uri_string) + 1), *d;
- const char *s;
-
- for (s = uri_string, d = clean; *s; s++) {
- if (*s != '\t' && *s != '\n' && *s != '\r')
- *d++ = *s;
- }
- *d = '\0';
-
- uri = soup_uri_new_with_base (base, clean);
- g_free (clean);
- return uri;
- }
- end = uri_string + len;
- while (end > uri_string && g_ascii_isspace (end[-1]))
- end--;
-
- uri = g_slice_new0 (SoupURI);
-
- /* Find fragment. */
- hash = strchr (uri_string, '#');
- if (hash) {
- uri->fragment = uri_normalized_copy (hash + 1, end - hash + 1,
- NULL);
- end = hash;
- }
-
- /* Find scheme */
- p = uri_string;
- while (p < end && (g_ascii_isalpha (*p) ||
- (p > uri_string && (g_ascii_isdigit (*p) ||
- *p == '.' ||
- *p == '+' ||
- *p == '-'))))
- p++;
-
- if (p > uri_string && *p == ':') {
- uri->scheme = soup_uri_parse_scheme (uri_string, p - uri_string);
- uri_string = p + 1;
- }
-
- if (uri_string == end && !base && !uri->fragment) {
- uri->path = g_strdup ("");
- return uri;
- }
-
- /* Check for authority */
- if (strncmp (uri_string, "//", 2) == 0) {
- uri_string += 2;
-
- path = uri_string + strcspn (uri_string, "/?#");
- if (path > end)
- path = end;
- at = strchr (uri_string, '@');
- if (at && at < path) {
- colon = strchr (uri_string, ':');
- if (colon && colon < at) {
- uri->password = soup_uri_decoded_copy (colon + 1,
- at - colon - 1, NULL);
- } else {
- uri->password = NULL;
- colon = at;
- }
-
- 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) {
- soup_uri_free (uri);
- return NULL;
- }
- if (*(hostend + 1) == ':')
- 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);
- }
-
- if (colon && colon != path - 1) {
- char *portend;
- uri->port = strtoul (colon + 1, &portend, 10);
- if (portend != (char *)path) {
- soup_uri_free (uri);
- return NULL;
- }
- }
-
- uri_string = path;
- }
-
- /* Find query */
- question = memchr (uri_string, '?', end - uri_string);
- if (question) {
- uri->query = uri_normalized_copy (question + 1,
- end - (question + 1),
- NULL);
- end = question;
- }
-
- if (end != uri_string) {
- uri->path = uri_normalized_copy (uri_string, end - uri_string,
- NULL);
- }
-
- /* Apply base URI. This is spelled out in RFC 3986. */
- if (base && !uri->scheme && uri->host)
- uri->scheme = base->scheme;
- else if (base && !uri->scheme) {
- uri->scheme = base->scheme;
- uri->user = g_strdup (base->user);
- uri->password = g_strdup (base->password);
- uri->host = g_strdup (base->host);
- uri->port = base->port;
-
- if (!uri->path) {
- uri->path = g_strdup (base->path);
- if (!uri->query)
- uri->query = g_strdup (base->query);
- remove_dot_segments = FALSE;
- } else if (*uri->path != '/') {
- char *newpath, *last;
-
- last = strrchr (base->path, '/');
- if (last) {
- newpath = g_strdup_printf ("%.*s%s",
- (int)(last + 1 - base->path),
- base->path,
- uri->path);
- } else
- newpath = g_strdup_printf ("/%s", uri->path);
-
- g_free (uri->path);
- uri->path = newpath;
- }
- }
-
- if (remove_dot_segments && uri->path && *uri->path) {
- char *p, *q;
-
- /* Remove "./" where "." is a complete segment. */
- for (p = uri->path + 1; *p; ) {
- if (*(p - 1) == '/' &&
- *p == '.' && *(p + 1) == '/')
- memmove (p, p + 2, strlen (p + 2) + 1);
- else
- p++;
- }
- /* Remove "." at end. */
- if (p > uri->path + 2 &&
- *(p - 1) == '.' && *(p - 2) == '/')
- *(p - 1) = '\0';
-
- /* Remove "<segment>/../" where <segment> != ".." */
- for (p = uri->path + 1; *p; ) {
- if (!strncmp (p, "../", 3)) {
- p += 3;
- continue;
- }
- q = strchr (p + 1, '/');
- if (!q)
- break;
- if (strncmp (q, "/../", 4) != 0) {
- p = q + 1;
- continue;
- }
- memmove (p, q + 4, strlen (q + 4) + 1);
- p = uri->path + 1;
- }
- /* Remove "<segment>/.." at end where <segment> != ".." */
- q = strrchr (uri->path, '/');
- if (q && q != uri->path && !strcmp (q, "/..")) {
- p = q - 1;
- while (p > uri->path && *p != '/')
- p--;
- if (strncmp (p, "/../", 4) != 0)
- *(p + 1) = 0;
- }
+ if (!guri)
+ return NULL;
- /* Remove extraneous initial "/.."s */
- while (!strncmp (uri->path, "/../", 4))
- memmove (uri->path, uri->path + 3, strlen (uri->path) - 2);
- if (!strcmp (uri->path, "/.."))
- uri->path[1] = '\0';
- }
+ uri = soup_uri_from_g_uri (guri);
+ g_uri_unref (guri);
- /* HTTP-specific stuff */
+ /* HTTP-specific fixes */
if (uri->scheme == SOUP_URI_SCHEME_HTTP ||
uri->scheme == SOUP_URI_SCHEME_HTTPS) {
- if (!uri->path)
+ if (!*uri->path) {
+ g_free (uri->path);
uri->path = g_strdup ("/");
+ }
if (!SOUP_URI_VALID_FOR_HTTP (uri)) {
soup_uri_free (uri);
return NULL;
@@ -488,8 +296,6 @@ soup_uri_new_with_base (SoupURI *base, const char *uri_string)
if (!uri->port)
uri->port = soup_scheme_default_port (uri->scheme);
- if (!uri->path)
- uri->path = g_strdup ("");
return uri;
}
@@ -615,7 +421,35 @@ soup_uri_to_string_internal (SoupURI *uri, gboolean just_path_and_query,
char *
soup_uri_to_string (SoupURI *uri, gboolean just_path_and_query)
{
- return soup_uri_to_string_internal (uri, just_path_and_query, FALSE, FALSE);
+ GUri *guri;
+ char *ret;
+
+ g_return_val_if_fail (uri != NULL, NULL);
+
+ if (!SOUP_URI_IS_VALID (uri)) {
+ g_warn_if_fail (SOUP_URI_IS_VALID (uri));
+ return g_strdup ("");
+ }
+
+ if (just_path_and_query) {
+ guri = g_uri_build (G_URI_FLAGS_ENCODED,
+ "", NULL, NULL, -1,
+ uri->path, uri->query, NULL);
+ } else {
+ guri = soup_uri_to_g_uri (uri);
+ }
+
+ g_return_val_if_fail (guri != NULL, NULL);
+
+ ret = g_uri_to_string_partial (guri, G_URI_HIDE_PASSWORD);
+ g_uri_unref (guri);
+
+ if (just_path_and_query) {
+ /* GUri always adds a : after the scheme which is empty. */
+ memmove (ret, ret + 1, strlen (ret) + 1);
+ }
+
+ return ret;
}
/**
@@ -959,7 +793,7 @@ soup_uri_set_scheme (SoupURI *uri, const char *scheme)
g_return_if_fail (uri != NULL);
g_return_if_fail (scheme != NULL);
- uri->scheme = soup_uri_parse_scheme (scheme, strlen (scheme));
+ uri->scheme = g_intern_string (scheme);
uri->port = soup_scheme_default_port (uri->scheme);
}