summaryrefslogtreecommitdiff
path: root/libsoup/soup-uri.c
diff options
context:
space:
mode:
Diffstat (limited to 'libsoup/soup-uri.c')
-rw-r--r--libsoup/soup-uri.c189
1 files changed, 189 insertions, 0 deletions
diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c
new file mode 100644
index 00000000..31a2aca0
--- /dev/null
+++ b/libsoup/soup-uri.c
@@ -0,0 +1,189 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* soup-uri.c : utility functions to parse URLs */
+
+/*
+ * Authors :
+ * Bertrand Guiheneuf <bertrand@helixcode.com>
+ * Dan Winship <danw@helixcode.com>
+ *
+ * Copyright 1999, 2000 Helix Code, Inc. (http://www.helixcode.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+
+/*
+ * Here we deal with URLs following the general scheme:
+ * protocol://user;AUTH=mech:password@host:port/name
+ * where name is a path-like string (ie dir1/dir2/....) See RFC 1738
+ * for the complete description of Uniform Resource Locators. The
+ * ";AUTH=mech" addition comes from RFC 2384, "POP URL Scheme".
+ */
+
+/* XXX TODO:
+ * recover the words between #'s or ?'s after the path
+ * % escapes
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include "soup-uri.h"
+
+/**
+ * soup_uri_new: create a Gurl object from a string
+ *
+ * @uri_string: The string containing the URL to scan
+ *
+ * This routine takes a gchar and parses it as a
+ * URL of the form:
+ * protocol://user;AUTH=mech:password@host:port/path
+ * There is no test on the values. For example,
+ * "port" can be a string, not only a number!
+ * The Gurl structure fields are filled with
+ * the scan results. When a member of the
+ * general URL can not be found, the corresponding
+ * Gurl member is NULL.
+ * Fields filled in the Gurl structure are allocated
+ * and url_string is not modified.
+ *
+ * Return value: a Gurl structure containing the URL items.
+ **/
+SoupUri *soup_uri_new (const gchar* uri_string)
+{
+ SoupUri *g_uri;
+ char *semi, *colon, *at, *slash, *path;
+ char **split;
+
+ g_uri = g_new (SoupUri,1);
+
+ /* Find protocol: initial substring until "://" */
+ colon = strchr (uri_string, ':');
+ if (colon && !strncmp (colon, "://", 3)) {
+ g_uri->protocol = g_strndup (uri_string, colon - uri_string);
+ uri_string = colon + 3;
+ } else
+ g_uri->protocol = NULL;
+
+ /* If there is an @ sign, look for user, authmech, and
+ * password before it.
+ */
+ at = strchr (uri_string, '@');
+ if (at) {
+ colon = strchr (uri_string, ':');
+ if (colon && colon < at)
+ g_uri->passwd = g_strndup (colon + 1, at - colon - 1);
+ else {
+ g_uri->passwd = NULL;
+ colon = at;
+ }
+
+ semi = strchr(uri_string, ';');
+ if (semi && semi < colon && !strncasecmp (semi, ";auth=", 6))
+ g_uri->authmech = g_strndup (semi + 6, colon - semi - 6);
+ else {
+ g_uri->authmech = NULL;
+ semi = colon;
+ }
+
+ g_uri->user = g_strndup (uri_string, semi - uri_string);
+ uri_string = at + 1;
+ } else
+ g_uri->user = g_uri->passwd = g_uri->authmech = NULL;
+
+ /* Find host (required) and port. */
+ slash = strchr (uri_string, '/');
+ colon = strchr (uri_string, ':');
+ if (slash && colon > slash)
+ colon = 0;
+
+ if (colon) {
+ g_uri->host = g_strndup (uri_string, colon - uri_string);
+ if (slash)
+ g_uri->port = atoi(colon + 1);
+ else
+ g_uri->port = atoi(colon + 1);
+ } else if (slash) {
+ g_uri->host = g_strndup (uri_string, slash - uri_string);
+ g_uri->port = -1;
+ } else {
+ g_uri->host = g_strdup (uri_string);
+ g_uri->port = -1;
+ }
+
+ /* setup a fallback, if relative, then empty string, else
+ it will be from root */
+ if (slash == NULL) {
+ slash = "/";
+ }
+ if (slash && *slash && g_uri->protocol == NULL)
+ slash++;
+
+ split = g_strsplit(slash, " ", 0);
+ path = g_strjoinv("%20", split);
+ g_strfreev(split);
+
+ g_uri->path = path;
+
+ return g_uri;
+}
+
+gchar *
+soup_uri_to_string (const SoupUri *uri, gboolean show_passwd)
+{
+ if (uri->port != -1)
+ return g_strdup_printf(
+ "%s%s%s%s%s%s%s%s%s:%d%s",
+ uri->protocol ? uri->protocol : "",
+ uri->protocol ? "://" : "",
+ uri->user ? uri->user : "",
+ uri->authmech ? ";auth=" : "",
+ uri->authmech ? uri->authmech : "",
+ uri->passwd && show_passwd ? ":" : "",
+ uri->passwd && show_passwd ? uri->passwd : "",
+ uri->user ? "@" : "",
+ uri->host,
+ uri->port,
+ uri->path ? uri->path : "");
+ else
+ return g_strdup_printf(
+ "%s%s%s%s%s%s%s%s%s%s",
+ uri->protocol ? uri->protocol : "",
+ uri->protocol ? "://" : "",
+ uri->user ? uri->user : "",
+ uri->authmech ? ";auth=" : "",
+ uri->authmech ? uri->authmech : "",
+ uri->passwd && show_passwd ? ":" : "",
+ uri->passwd && show_passwd ? uri->passwd : "",
+ uri->user ? "@" : "",
+ uri->host,
+ uri->path ? uri->path : "");
+}
+
+void
+soup_uri_free (SoupUri *uri)
+{
+ g_assert (uri);
+
+ g_free (uri->protocol);
+ g_free (uri->user);
+ g_free (uri->authmech);
+ g_free (uri->passwd);
+ g_free (uri->host);
+ g_free (uri->path);
+
+ g_free (uri);
+}