/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* camel-url.c : utility functions to parse URLs */ /* * Authors: * Bertrand Guiheneuf * Dan Winship * * 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 */ /* XXX TODO: * recover the words between #'s or ?'s after the path * % escapes */ #include #include #include #include "camel-url.h" #include "camel-exception.h" /** * camel_url_new: create a CamelURL object from a string * @url_string: The string containing the URL to scan * * This routine takes a string and parses it as a URL of the form: * * protocol://user;AUTH=mech:password@host:port/path * * The protocol, followed by a ":" is required. If it is followed by * "//", there must be an "authority" containing at least a host, * which ends at the end of the string or at the next "/". If there * is an "@" in the authority, there must be a username before it, * and the host comes after it. The authmech, password, and port are * optional, and the punctuation that preceeds them is omitted if * they are. Everything after the authority (or everything after the * protocol if there was no authority) is the path. We consider the * "/" between the authority and the path to be part of the path, * although this is incorrect according to RFC 1738. * * The port, if present, must be numeric. * * Return value: a CamelURL structure containing the URL items. **/ CamelURL * camel_url_new (const char *url_string, CamelException *ex) { CamelURL *url; char *semi, *colon, *at, *slash; /* Find protocol: initial substring until ":" */ colon = strchr (url_string, ':'); if (!colon) { camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_URL_INVALID, "URL string `%s' contains no protocol", url_string); return NULL; } url = g_new0 (CamelURL, 1); url->protocol = g_strndup (url_string, colon - url_string); if (strncmp (colon, "://", 3) != 0) { if (*(colon + 1)) url->path = g_strdup (colon + 1); return url; } url_string = colon + 3; /* If there is an @ sign in the authority, look for user, * authmech, and password before it. */ slash = strchr (url_string, '/'); at = strchr (url_string, '@'); if (at && (!slash || at < slash)) { colon = strchr (url_string, ':'); if (colon && colon < at) url->passwd = g_strndup (colon + 1, at - colon - 1); else { url->passwd = NULL; colon = at; } semi = strchr(url_string, ';'); if (semi && (semi < colon || (!colon && semi < at)) && !strncasecmp (semi, ";auth=", 6)) { url->authmech = g_strndup (semi + 6, colon - semi - 6); } else { url->authmech = NULL; semi = colon; } url->user = g_strndup (url_string, semi - url_string); url_string = at + 1; } else url->user = url->passwd = url->authmech = NULL; /* Find host and port. */ slash = strchr (url_string, '/'); colon = strchr (url_string, ':'); if (slash && colon > slash) colon = NULL; if (colon) { url->host = g_strndup (url_string, colon - url_string); url->port = strtoul (colon + 1, &colon, 10); if (*colon && colon != slash) { camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_URL_INVALID, "Port number in URL `%s' is non-" "numeric", url_string); camel_url_free (url); return NULL; } } else if (slash) { url->host = g_strndup (url_string, slash - url_string); url->port = 0; } else { url->host = g_strdup (url_string); url->port = 0; } if (!slash) slash = "/"; url->path = g_strdup (slash); return url; } char * camel_url_to_string (CamelURL *url, gboolean show_passwd) { char port[20]; if (url->port) g_snprintf (port, sizeof (port), "%d", url->port); else *port = '\0'; return g_strdup_printf ("%s:%s%s%s%s%s%s%s%s%s%s%s", url->protocol, url->host ? "//" : "", url->user ? url->user : "", url->authmech ? ";auth=" : "", url->authmech ? url->authmech : "", url->passwd && show_passwd ? ":" : "", url->passwd && show_passwd ? url->passwd : "", url->user ? "@" : "", url->host ? url->host : "", url->port ? ":" : "", port, url->path ? url->path : ""); } void camel_url_free (CamelURL *url) { g_assert (url); g_free (url->protocol); g_free (url->user); g_free (url->authmech); g_free (url->passwd); g_free (url->host); g_free (url->path); g_free (url); }