예제 #1
0
static GInputStream *
soup_request_data_send (SoupRequest   *request,
			GCancellable  *cancellable,
			GError       **error)
{
	SoupRequestData *data = SOUP_REQUEST_DATA (request);
	SoupURI *uri = soup_request_get_uri (request);
	GInputStream *memstream;
	const char *comma, *start, *end;
	gboolean base64 = FALSE;
	char *uristr;

	uristr = soup_uri_to_string (uri, FALSE);
	start = uristr + 5;
	comma = strchr (start, ',');
	if (comma && comma != start) {
		/* Deal with MIME type / params */
		if (comma >= start + BASE64_INDICATOR_LEN && !g_ascii_strncasecmp (comma - BASE64_INDICATOR_LEN, BASE64_INDICATOR, BASE64_INDICATOR_LEN)) {
			end = comma - BASE64_INDICATOR_LEN;
			base64 = TRUE;
		} else
			end = comma;

		if (end != start)
			data->priv->content_type = soup_uri_decoded_copy (start, end - start, NULL);
	}

	memstream = g_memory_input_stream_new ();

	if (comma)
		start = comma + 1;

	if (*start) {
		int decoded_length = 0;
		guchar *buf = (guchar *) soup_uri_decoded_copy (start, strlen (start),
								&decoded_length);

		if (base64)
			buf = g_base64_decode_inplace ((gchar*) buf, &data->priv->content_length);
		else
			data->priv->content_length = decoded_length;

		g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (memstream),
						buf, data->priv->content_length,
						g_free);
	}
	g_free (uristr);

	return memstream;
}
예제 #2
0
파일: soup-uri.c 프로젝트: GNOME/libsoup
/**
 * soup_uri_decode:
 * @part: a URI part
 *
 * Fully %<!-- -->-decodes @part.
 *
 * In the past, this would return %NULL if @part contained invalid
 * percent-encoding, but now it just ignores the problem (as
 * soup_uri_new() already did).
 *
 * Return value: the decoded URI part.
 */
char *
soup_uri_decode (const char *part)
{
    g_return_val_if_fail (part != NULL, NULL);

    return soup_uri_decoded_copy (part, strlen (part), NULL);
}
예제 #3
0
파일: soup-uri.c 프로젝트: GNOME/libsoup
/**
 * 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;
}