Esempio n. 1
0
/**
 * soup_uri_equal:
 * @uri1: a #SoupURI
 * @uri2: another #SoupURI
 *
 * Tests whether or not @uri1 and @uri2 are equal in all parts
 *
 * Return value: %TRUE or %FALSE
 **/
gboolean
soup_uri_equal (SoupURI *uri1, SoupURI *uri2)
{
    g_return_val_if_fail (uri1 != NULL, FALSE);
    g_return_val_if_fail (uri2 != NULL, FALSE);
    g_warn_if_fail (SOUP_URI_IS_VALID (uri1));
    g_warn_if_fail (SOUP_URI_IS_VALID (uri2));

    if (uri1->scheme != uri2->scheme                         ||
            uri1->port   != uri2->port                           ||
            !parts_equal (uri1->user, uri2->user, FALSE)         ||
            !parts_equal (uri1->password, uri2->password, FALSE) ||
            !parts_equal (uri1->host, uri2->host, TRUE)          ||
            !parts_equal (uri1->path, uri2->path, FALSE)         ||
            !parts_equal (uri1->query, uri2->query, FALSE)       ||
            !parts_equal (uri1->fragment, uri2->fragment, FALSE))
        return FALSE;

    return TRUE;
}
Esempio n. 2
0
/**
 * soup_uri_host_hash:
 * @key: (type Soup.URI): a #SoupURI with a non-%NULL @host member
 *
 * Hashes @key, considering only the scheme, host, and port.
 *
 * Return value: a hash
 *
 * Since: 2.28
 **/
guint
soup_uri_host_hash (gconstpointer key)
{
    const SoupURI *uri = key;

    g_return_val_if_fail (uri != NULL && uri->host != NULL, 0);
    g_warn_if_fail (SOUP_URI_IS_VALID (uri));

    return GPOINTER_TO_UINT (uri->scheme) + uri->port +
           soup_str_case_hash (uri->host);
}
/**
 * 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)
{
	GString *str;
	char *return_result;

	g_return_val_if_fail (uri != NULL, NULL);
	g_warn_if_fail (SOUP_URI_IS_VALID (uri));

	str = g_string_sized_new (20);

	if (uri->scheme && !just_path_and_query)
		g_string_append_printf (str, "%s:", uri->scheme);
	if (uri->host && !just_path_and_query) {
		g_string_append (str, "//");
		if (uri->user) {
			append_uri_encoded (str, uri->user, ":;@?/");
			g_string_append_c (str, '@');
		}
		if (strchr (uri->host, ':')) {
			g_string_append_c (str, '[');
			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))
			g_string_append_printf (str, ":%u", uri->port);
		if (!uri->path && (uri->query || uri->fragment))
			g_string_append_c (str, '/');
		else if ((!uri->path || !*uri->path) &&
			 (uri->scheme == SOUP_URI_SCHEME_HTTP ||
			  uri->scheme == SOUP_URI_SCHEME_HTTPS))
			g_string_append_c (str, '/');
	}

	if (uri->path && *uri->path)
		g_string_append (str, uri->path);
	else if (just_path_and_query)
		g_string_append_c (str, '/');

	if (uri->query) {
		g_string_append_c (str, '?');
		g_string_append (str, uri->query);
	}
	if (uri->fragment && !just_path_and_query) {
		g_string_append_c (str, '#');
		g_string_append (str, uri->fragment);
	}

	return_result = str->str;
	g_string_free (str, FALSE);

	return return_result;
}
Esempio n. 4
0
/**
 * soup_uri_copy_host:
 * @uri: a #SoupURI
 *
 * Makes a copy of @uri, considering only the protocol, host, and port
 *
 * Return value: the new #SoupURI
 *
 * Since: 2.28
 **/
SoupURI *
soup_uri_copy_host (SoupURI *uri)
{
    SoupURI *dup;

    g_return_val_if_fail (uri != NULL, NULL);
    g_warn_if_fail (SOUP_URI_IS_VALID (uri));

    dup = soup_uri_new (NULL);
    dup->scheme = uri->scheme;
    dup->host   = g_strdup (uri->host);
    dup->port   = uri->port;
    dup->path   = g_strdup ("");

    return dup;
}
Esempio n. 5
0
/**
 * soup_uri_new:
 * @uri_string: (allow-none): a URI
 *
 * Parses an absolute URI.
 *
 * You can also pass %NULL for @uri_string if you want to get back an
 * "empty" #SoupURI that you can fill in by hand. (You will need to
 * call at least soup_uri_set_scheme() and soup_uri_set_path(), since
 * those fields are required.)
 *
 * Return value: (nullable): a #SoupURI, or %NULL if the given string
 *  was found to be invalid.
 **/
SoupURI *
soup_uri_new (const char *uri_string)
{
    SoupURI *uri;

    if (!uri_string)
        return g_slice_new0 (SoupURI);

    uri = soup_uri_new_with_base (NULL, uri_string);
    if (!uri)
        return NULL;
    if (!SOUP_URI_IS_VALID (uri)) {
        soup_uri_free (uri);
        return NULL;
    }

    return uri;
}
Esempio n. 6
0
/**
 * soup_uri_copy:
 * @uri: a #SoupURI
 *
 * Copies @uri
 *
 * Return value: a copy of @uri, which must be freed with soup_uri_free()
 **/
SoupURI *
soup_uri_copy (SoupURI *uri)
{
    SoupURI *dup;

    g_return_val_if_fail (uri != NULL, NULL);
    g_warn_if_fail (SOUP_URI_IS_VALID (uri));

    dup = g_slice_new0 (SoupURI);
    dup->scheme   = uri->scheme;
    dup->user     = g_strdup (uri->user);
    dup->password = g_strdup (uri->password);
    dup->host     = g_strdup (uri->host);
    dup->port     = uri->port;
    dup->path     = g_strdup (uri->path);
    dup->query    = g_strdup (uri->query);
    dup->fragment = g_strdup (uri->fragment);

    return dup;
}
Esempio n. 7
0
static void
network_set_soup_session_proxy (SoupSession *session, ProxyDetectMode mode, const gchar *host, guint port, const gchar *user, const gchar *password)
{
	SoupURI *uri = NULL;

	switch (mode) {
		case PROXY_DETECT_MODE_AUTO:
			/* Sets proxy-resolver to the default resolver, this unsets proxy-uri. */
			g_object_set (G_OBJECT (session),
				SOUP_SESSION_PROXY_RESOLVER, g_proxy_resolver_get_default (),
				NULL);
			break;
		case PROXY_DETECT_MODE_NONE:
			/* Sets proxy-resolver to NULL, this unsets proxy-uri. */
			g_object_set (G_OBJECT (session),
				SOUP_SESSION_PROXY_RESOLVER, NULL,
				NULL);
			break;
		case PROXY_DETECT_MODE_MANUAL:
			uri = soup_uri_new (NULL);
			soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP);
			soup_uri_set_host (uri, host);
			soup_uri_set_port (uri, port);
			soup_uri_set_user (uri, user);
			soup_uri_set_password (uri, password);
			soup_uri_set_path (uri, "/");

			if (SOUP_URI_IS_VALID (uri)) {
				/* Sets proxy-uri, this unsets proxy-resolver. */
				g_object_set (G_OBJECT (session),
					SOUP_SESSION_PROXY_URI, uri,
					NULL);
			}
			soup_uri_free (uri);
			break;
	}
}
Esempio n. 8
0
char *
soup_uri_to_string_internal (SoupURI *uri, gboolean just_path_and_query,
                             gboolean include_password, gboolean force_port)
{
    GString *str;
    char *return_result;

    g_return_val_if_fail (uri != NULL, NULL);
    g_warn_if_fail (SOUP_URI_IS_VALID (uri));

    str = g_string_sized_new (40);

    if (uri->scheme && !just_path_and_query)
        g_string_append_printf (str, "%s:", uri->scheme);
    if (uri->host && !just_path_and_query) {
        g_string_append (str, "//");
        if (uri->user) {
            append_uri_encoded (str, uri->user, ":;@?/");
            if (uri->password && include_password) {
                g_string_append_c (str, ':');
                append_uri_encoded (str, uri->password, ";@?/");
            }
            g_string_append_c (str, '@');
        }
        if (strchr (uri->host, ':')) {
            const char *pct;

            g_string_append_c (str, '[');
            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 && (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, '/');
        else if ((!uri->path || !*uri->path) &&
                 (uri->scheme == SOUP_URI_SCHEME_HTTP ||
                  uri->scheme == SOUP_URI_SCHEME_HTTPS))
            g_string_append_c (str, '/');
    }

    if (uri->path && *uri->path)
        g_string_append (str, uri->path);
    else if (just_path_and_query)
        g_string_append_c (str, '/');

    if (uri->query) {
        g_string_append_c (str, '?');
        g_string_append (str, uri->query);
    }
    if (uri->fragment && !just_path_and_query) {
        g_string_append_c (str, '#');
        g_string_append (str, uri->fragment);
    }

    return_result = str->str;
    g_string_free (str, FALSE);

    return return_result;
}
Esempio n. 9
0
/**
 * soup_uri_new_with_base:
 * @base: a base URI
 * @uri_string: the URI
 *
 * Parses @uri_string relative to @base.
 *
 * Return value: a parsed #SoupURI.
 **/
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);

    /* Allow a %NULL path in @base, for compatibility */
    if (base && base->scheme && !base->path) {
        g_warn_if_fail (SOUP_URI_IS_VALID (base));

        memcpy (&fixed_base, base, sizeof (SoupURI));
        fixed_base.path = "";
        base = &fixed_base;
    }

    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++;

    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 && !strcmp (q, "/..")) {
            p = q - 1;
            while (p > uri->path && *p != '/')
                p--;
            if (strncmp (p, "/../", 4) != 0)
                *(p + 1) = 0;
        }

        /* 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';
    }

    /* HTTP-specific stuff */
    if (uri->scheme == SOUP_URI_SCHEME_HTTP ||
            uri->scheme == SOUP_URI_SCHEME_HTTPS) {
        if (!uri->path)
            uri->path = g_strdup ("/");
        if (!SOUP_URI_VALID_FOR_HTTP (uri)) {
            soup_uri_free (uri);
            return NULL;
        }
    }

    if (uri->scheme == SOUP_URI_SCHEME_FTP) {
        if (!uri->host) {
            soup_uri_free (uri);
            return NULL;
        }
    }

    if (!uri->port)
        uri->port = soup_scheme_default_port (uri->scheme);
    if (!uri->path)
        uri->path = g_strdup ("");

    return uri;
}
static void
do_soup_uri_null_tests (void)
{
	SoupURI *uri, *uri2;
	char *uri_string;

	debug_printf (1, "\nsoup_uri_new (NULL)\n");
	uri = soup_uri_new (NULL);
	if (SOUP_URI_IS_VALID (uri) || SOUP_URI_VALID_FOR_HTTP (uri)) {
		debug_printf (1, "  ERROR: soup_uri_new(NULL) returns valid URI?\n");
		errors++;
	}

	/* This implicitly also verifies that none of these methods g_warn */
	if (soup_uri_get_scheme (uri) ||
	    soup_uri_get_user (uri) ||
	    soup_uri_get_password (uri) ||
	    soup_uri_get_host (uri) ||
	    soup_uri_get_port (uri) ||
	    soup_uri_get_path (uri) ||
	    soup_uri_get_query (uri) ||
	    soup_uri_get_fragment (uri)) {
		debug_printf (1, "  ERROR: soup_uri_new(NULL) returns non-empty URI?\n");
		errors++;
	}

	expect_warning = TRUE;
	uri2 = soup_uri_new_with_base (uri, "/path");
	if (uri2 || expect_warning) {
		debug_printf (1, "  ERROR: soup_uri_new_with_base didn't fail on NULL URI?\n");
		errors++;
		expect_warning = FALSE;
	}

	expect_warning = TRUE;
	uri_string = soup_uri_to_string (uri, FALSE);
	if (expect_warning) {
		debug_printf (1, "  ERROR: soup_uri_to_string didn't fail on NULL URI?\n");
		errors++;
		expect_warning = FALSE;
	} else if (*uri_string) {
		debug_printf (1, "  ERROR: soup_uri_to_string on NULL URI returned '%s'\n",
			      uri_string);
		errors++;
	}
	g_free (uri_string);

	soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP);
	if (SOUP_URI_IS_VALID (uri) || SOUP_URI_VALID_FOR_HTTP (uri)) {
		debug_printf (1, "  ERROR: setting scheme on NULL URI makes it valid?\n");
		errors++;
	}

	expect_warning = TRUE;
	uri_string = soup_uri_to_string (uri, FALSE);
	if (expect_warning) {
		debug_printf (1, "  ERROR: soup_uri_to_string didn't fail on scheme-only URI?\n");
		errors++;
		expect_warning = FALSE;
	} else if (strcmp (uri_string, "http:") != 0) {
		debug_printf (1, "  ERROR: soup_uri_to_string returned '%s' instead of 'http:'\n",
			      uri_string);
		errors++;
	}
	g_free (uri_string);

	soup_uri_set_host (uri, "localhost");
	if (SOUP_URI_IS_VALID (uri)) {
		debug_printf (1, "  ERROR: setting scheme+host on NULL URI makes it valid?\n");
		errors++;
	}
	if (SOUP_URI_VALID_FOR_HTTP (uri)) {
		debug_printf (1, "  ERROR: setting scheme+host on NULL URI makes it valid for http?\n");
		errors++;
	}

	expect_warning = TRUE;
	uri_string = soup_uri_to_string (uri, FALSE);
	if (expect_warning) {
		debug_printf (1, "  ERROR: soup_uri_to_string didn't fail on scheme+host URI?\n");
		errors++;
		expect_warning = FALSE;
	} else if (strcmp (uri_string, "http://localhost/") != 0) {
		debug_printf (1, "  ERROR: soup_uri_to_string with NULL path returned '%s' instead of 'http://localhost/'\n",
			      uri_string);
		errors++;
	}
	g_free (uri_string);

	expect_warning = TRUE;
	uri2 = soup_uri_new_with_base (uri, "/path");
	if (expect_warning) {
		debug_printf (1, "  ERROR: soup_uri_new_with_base didn't warn on NULL+scheme URI?\n");
		errors++;
		expect_warning = FALSE;
	} else if (!uri2) {
		debug_printf (1, "  ERROR: soup_uri_new_with_base didn't fix path on NULL+scheme URI\n");
		errors++;
	}

	if (uri2) {
		uri_string = soup_uri_to_string (uri2, FALSE);
		if (!uri_string) {
			debug_printf (1, "  ERROR: soup_uri_to_string failed on uri2?\n");
			errors++;
		} else if (strcmp (uri_string, "http://localhost/path") != 0) {
			debug_printf (1, "  ERROR: soup_uri_to_string returned '%s' instead of 'http://localhost/path'\n",
				      uri_string);
			errors++;
		}
		g_free (uri_string);
		soup_uri_free (uri2);
	}

	expect_warning = TRUE;
	soup_uri_set_path (uri, NULL);
	if (expect_warning) {
		debug_printf (1, "  ERROR: setting path to NULL doesn't warn\n");
		errors++;
		expect_warning = FALSE;
	}
	if (!uri->path || *uri->path) {
		debug_printf (1, "  ERROR: setting path to NULL != \"\"\n");
		errors++;
		soup_uri_set_path (uri, "");
	}

	uri_string = soup_uri_to_string (uri, FALSE);
	if (!uri_string) {
		debug_printf (1, "  ERROR: soup_uri_to_string failed on complete URI?\n");
		errors++;
	} else if (strcmp (uri_string, "http://localhost/") != 0) {
		debug_printf (1, "  ERROR: soup_uri_to_string with empty path returned '%s' instead of 'http://localhost/'\n",
			      uri_string);
		errors++;
	}
	g_free (uri_string);

	if (!SOUP_URI_IS_VALID (uri)) {
		debug_printf (1, "  ERROR: setting scheme+path on NULL URI doesn't make it valid?\n");
		errors++;
	}
	if (!SOUP_URI_VALID_FOR_HTTP (uri)) {
		debug_printf (1, "  ERROR: setting scheme+host+path on NULL URI doesn't make it valid for http?\n");
		errors++;
	}

	soup_uri_free (uri);
}