source: trunk/third/evolution/e-util/e-url.c @ 16787

Revision 16787, 7.7 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r16786, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3/*
4 * e-url.c
5 *
6 * Copyright (C) 2001 Ximian, Inc.
7 *
8 * Developed by Jon Trowbridge <trow@ximian.com>
9 *              Rodrigo Moya   <rodrigo@ximian.com>
10 */
11
12/*
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of version 2 of the GNU General Public
15 * License as published by the Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
25 * USA.
26 */
27
28#include <config.h>
29#include <ctype.h>
30#include <stdlib.h>
31#include <string.h>
32#include "e-url.h"
33
34char *
35e_url_shroud (const char *url)
36{
37        const char *first_colon = NULL;
38        const char *last_at = NULL;
39        const char *p;
40        char *shrouded;
41       
42        if (url == NULL)
43                return NULL;
44
45        /* Skip past the moniker */
46        for (p = url; *p && *p != ':'; ++p);
47        if (*p)
48                ++p;
49
50        while (*p) {
51                if (first_colon == NULL && *p == ':')
52                        first_colon = p;
53                if (*p == '@')
54                        last_at = p;
55                ++p;
56        }
57
58        if (first_colon && last_at && first_colon < last_at) {
59                shrouded = g_strdup_printf ("%.*s%s", first_colon - url, url, last_at);
60        } else {
61                shrouded = g_strdup (url);
62        }
63
64        return shrouded;
65}
66
67gboolean
68e_url_equal (const char *url1, const char *url2)
69{
70        char *shroud1 = e_url_shroud (url1);
71        char *shroud2 = e_url_shroud (url2);
72        gint len1, len2;
73        gboolean rv;
74
75        if (shroud1 == NULL || shroud2 == NULL) {
76                rv = (shroud1 == shroud2);
77        } else {
78                len1 = strlen (shroud1);
79                len2 = strlen (shroud2);
80
81                rv = !strncmp (shroud1, shroud2, MIN (len1, len2));
82        }
83
84        g_free (shroud1);
85        g_free (shroud2);
86
87        return rv;
88}
89
90#define HEXVAL(c) (isdigit (c) ? (c) - '0' : tolower (c) - 'a' + 10)
91
92static void
93uri_decode (char *part)
94{
95        guchar *s, *d;
96
97        s = d = (guchar *)part;
98        while (*s) {
99                if (*s == '%') {
100                        if (isxdigit (s[1]) && isxdigit (s[2])) {
101                                *d++ = HEXVAL (s[1]) * 16 + HEXVAL (s[2]);
102                                s += 3;
103                        } else
104                                *d++ = *s++;
105                } else
106                        *d++ = *s++;
107        }
108        *d = '\0';
109}
110
111EUri *
112e_uri_new (const char *uri_string)
113{
114        EUri *uri;
115        const char *end, *hash, *colon, *semi, *at, *slash, *question;
116        const char *p;
117
118        uri = g_new0 (EUri, 1);
119
120        /* find fragment */
121        end = hash = strchr (uri_string, '#');
122        if (hash && hash[1]) {
123                uri->fragment = g_strdup (hash + 1);
124                uri_decode (uri->fragment);
125        }
126        else
127                end = uri_string + strlen (uri_string);
128
129        /* find protocol: initial [a-z+.-]* substring until ":" */
130        p = uri_string;
131        while (p < end && (isalnum ((unsigned char) *p) ||
132                           *p == '.' || *p == '+' || *p == '-'))
133                p++;
134
135        if (p > uri_string && *p == ':') {
136                uri->protocol = g_strndup (uri_string, p - uri_string);
137                g_strdown (uri->protocol);
138                uri_string = p + 1;
139        }
140        else
141                uri->protocol = g_strdup ("file");
142
143        if (!*uri_string)
144                return uri;
145
146        /* check for authority */
147        if (strncmp (uri_string, "//", 2) == 0) {
148                uri_string += 2;
149
150                slash = uri_string + strcspn (uri_string, "/#");
151                at = strchr (uri_string, '@');
152                if (at && at < slash) {
153                        colon = strchr (uri_string, ':');
154                        if (colon && colon < at) {
155                                uri->passwd = g_strndup (colon + 1, at - colon - 1);
156                                uri_decode (uri->passwd);
157                        }
158                        else {
159                                uri->passwd = NULL;
160                                colon = at;
161                        }
162
163                        semi = strchr (uri_string, ';');
164                        if (semi && semi < colon &&
165                            !strncasecmp (semi, ";auth=", 6)) {
166                                uri->authmech = g_strndup (semi + 6, colon - semi - 6);
167                                uri_decode (uri->authmech);
168                        }
169                        else {
170                                uri->authmech = NULL;
171                                semi = colon;
172                        }
173
174                        uri->user = g_strndup (uri_string, semi - uri_string);
175                        uri_decode (uri->user);
176                        uri_string = at + 1;
177                }
178                else
179                        uri->user = uri->passwd = uri->authmech = NULL;
180
181                /* find host and port */
182                colon = strchr (uri_string, ':');
183                if (colon && colon < slash) {
184                        uri->host = g_strndup (uri_string, colon - uri_string);
185                        uri->port = strtoul (colon + 1, NULL, 10);
186                }
187                else {
188                        uri->host = g_strndup (uri_string, slash - uri_string);
189                        uri_decode (uri->host);
190                        uri->port = 0;
191                }
192
193                uri_string = slash;
194        }
195
196        /* find query */
197        question = memchr (uri_string, '?', end - uri_string);
198        if (question) {
199                if (question[1]) {
200                        uri->query = g_strndup (question + 1, end - (question + 1));
201                        uri_decode (uri->query);
202                }
203                end = question;
204        }
205
206        /* find parameters */
207        semi = memchr (uri_string, ';', end - uri_string);
208        if (semi) {
209                if (semi[1]) {
210                        const char *cur, *p, *eq;
211                        char *name, *value;
212
213                        for (cur = semi + 1; cur < end; cur = p + 1) {
214                                p = memchr (cur, ';', end - cur);
215                                if (!p)
216                                        p = end;
217                                eq = memchr (cur, '=', p - cur);
218                                if (eq) {
219                                        name = g_strndup (cur, eq - cur);
220                                        value = g_strndup (eq + 1, p - (eq + 1));
221                                        uri_decode (value);
222                                } else {
223                                        name = g_strndup (cur, p - cur);
224                                        value = g_strdup ("");
225                                }
226                                uri_decode (name);
227                                g_datalist_set_data_full (&uri->params, name,
228                                                          value, g_free);
229                                g_free (name);
230                        }
231                }
232                end = semi;
233        }
234
235        if (end != uri_string) {
236                uri->path = g_strndup (uri_string, end - uri_string);
237                uri_decode (uri->path);
238        }
239
240        return uri;
241}
242
243void
244e_uri_free (EUri *uri)
245{
246        if (uri) {
247                g_free (uri->protocol);
248                g_free (uri->user);
249                g_free (uri->authmech);
250                g_free (uri->passwd);
251                g_free (uri->host);
252                g_free (uri->path);
253                g_datalist_clear (&uri->params);
254                g_free (uri->query);
255                g_free (uri->fragment);
256
257                g_free (uri);
258        }
259}
260
261const char *
262e_uri_get_param (EUri *uri, const char *name)
263{
264        return g_datalist_get_data (&uri->params, name);
265}
266
267static void
268copy_param_cb (GQuark key_id, gpointer data, gpointer user_data)
269{
270        GData *params = (GData *) user_data;
271
272        g_datalist_id_set_data_full (&params, key_id, g_strdup (data), g_free);
273}
274
275EUri *
276e_uri_copy (EUri *uri)
277{
278        EUri *uri_copy;
279
280        g_return_val_if_fail (uri != NULL, NULL);
281
282        uri_copy = g_new0 (EUri, 1);
283        uri_copy->protocol = g_strdup (uri->protocol);
284        uri_copy->user = g_strdup (uri->user);
285        uri_copy->authmech = g_strdup (uri->authmech);
286        uri_copy->passwd = g_strdup (uri->passwd);
287        uri_copy->host = g_strdup (uri->host);
288        uri_copy->port = uri->port;
289        uri_copy->path = g_strdup (uri->path);
290        uri_copy->query = g_strdup (uri->query);
291        uri_copy->fragment = g_strdup (uri->fragment);
292
293        /* copy uri->params */
294        g_datalist_foreach (&uri->params,
295                            (GDataForeachFunc) copy_param_cb,
296                            &uri_copy->params);
297
298        return uri_copy;
299}
300
301char *
302e_uri_to_string (EUri *uri, gboolean show_password)
303{
304        char *str_uri = NULL;
305
306        g_return_val_if_fail (uri != NULL, NULL);
307
308        if (uri->port != 0)
309                str_uri = g_strdup_printf (
310                        "%s://%s%s%s%s%s%s%s:%d%s%s%s",
311                        uri->protocol,
312                        uri->user ? uri->user : "",
313                        uri->authmech ? ";auth=" : "",
314                        uri->authmech ? uri->authmech : "",
315                        uri->passwd && show_password ? ":" : "",
316                        uri->passwd && show_password ? uri->passwd : "",
317                        uri->user ? "@" : "",
318                        uri->host ? uri->host : "",
319                        uri->port,
320                        uri->path ? uri->path : "",
321                        uri->query ? "?" : "",
322                        uri->query ? uri->query : "");
323        else
324                str_uri = g_strdup_printf(
325                        "%s://%s%s%s%s%s%s%s%s%s%s",
326                        uri->protocol,
327                        uri->user ? uri->user : "",
328                        uri->authmech ? ";auth=" : "",
329                        uri->authmech ? uri->authmech : "",
330                        uri->passwd && show_password ? ":" : "",
331                        uri->passwd && show_password ? uri->passwd : "",
332                        uri->user ? "@" : "",
333                        uri->host ? uri->host : "",
334                        uri->path ? uri->path : "",
335                        uri->query ? "?" : "",
336                        uri->query ? uri->query : "");
337
338        return str_uri;
339}
Note: See TracBrowser for help on using the repository browser.