move url.[hc] into the lib-lib.
[apps/madmutt.git] / lib-lib / url.c
1 /*
2  *  This program is free software; you can redistribute it and/or modify
3  *  it under the terms of the GNU General Public License as published by
4  *  the Free Software Foundation; either version 2 of the License, or (at
5  *  your option) any later version.
6  *
7  *  This program is distributed in the hope that it will be useful, but
8  *  WITHOUT ANY WARRANTY; without even the implied warranty of
9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10  *  General Public License for more details.
11  *
12  *  You should have received a copy of the GNU General Public License
13  *  along with this program; if not, write to the Free Software
14  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
15  *  MA 02110-1301, USA.
16  *
17  *  Copyright © 2006 Pierre Habouzit
18  */
19 /*
20  * Copyright notice from original mutt:
21  * Copyright (C) 2000 Thomas Roessler <roessler@does-not-exist.org>
22  *
23  * This file is part of mutt-ng, see http://www.muttng.org/.
24  * It's licensed under the GNU General Public License,
25  * please see the file GPL in the top level source directory.
26  */
27
28 /*
29  * A simple URL parser.
30  */
31
32 #if HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include <ctype.h>
37
38 #include <lib-lib/mem.h>
39 #include <lib-lib/ascii.h>
40 #include <lib-lib/mapping.h>
41 #include <lib-lib/url.h>
42
43 #include <lib-mime/mime.h>
44
45 #include "mutt.h"
46
47 static struct mapping_t UrlMap[] = {
48     {"file",   U_FILE},
49     {"imap",   U_IMAP},
50     {"imaps",  U_IMAPS},
51     {"pop",    U_POP},
52     {"pops",   U_POPS},
53     {"nntp",   U_NNTP},
54     {"news",   U_NNTP},
55     {"nntps",  U_NNTPS},
56     {"snews",  U_NNTPS},
57     {"mailto", U_MAILTO},
58     {NULL,     U_UNKNOWN}
59 };
60
61 /* decode url escaping */
62 char *url_decode(char *p)
63 {
64     char *q = p;
65
66     if (!p)
67         return NULL;
68
69     while (*q) {
70         if (*q == '%' && hexval(q[1]) >= 0 && hexval(q[2]) >= 0) {
71             *p++ = (hexval(q[1]) << 4) | hexval(q[2]);
72             q += 3;
73         } else {
74             *p++ = *q++;
75         }
76     }
77
78     *p = '\0';
79     return p;
80 }
81
82 url_scheme_t url_check_scheme(const char *s)
83 {
84     char sbuf[STRING];
85     char *t;
86     int i;
87
88     if (!s || !(t = strchr(s, ':')))
89         return U_UNKNOWN;
90
91     m_strncpy(sbuf, sizeof(sbuf), s, t - s);
92     i = mutt_getvaluebyname(sbuf, UrlMap);
93     return i == -1 ? U_UNKNOWN : i;
94 }
95
96 /* ciss_parse_userhost: fill in components of ciss with info from src. Note
97  *   these are pointers into src, which is altered with '\0's. Port of 0
98  *   means no port given.
99  * FIXME: THIS IS TASTELESS
100  */
101 static char *ciss_parse_userhost(ciss_url_t *ciss, char *src)
102 {
103     char *t;
104     char *p;
105     char *path;
106
107     ciss->user = NULL;
108     ciss->pass = NULL;
109     ciss->host = NULL;
110     ciss->port = 0;
111
112     if (strncmp(src, "//", 2))
113         return src;
114
115     src += 2;
116
117     if ((path = strchr(src, '/')))
118         *path++ = '\0';
119
120     if ((t = strrchr(src, '@'))) {
121         *t = '\0';
122         if ((p = strchr (src, ':'))) {
123             *p = '\0';
124             ciss->pass = p + 1;
125             url_decode (ciss->pass);
126         }
127         ciss->user = src;
128         url_decode (ciss->user);
129         t++;
130     }
131     else
132         t = src;
133
134     if ((p = strchr (t, ':'))) {
135         *p++ = '\0';
136         ciss->port = atoi (p);
137     }
138     else
139         ciss->port = 0;
140
141     ciss->host = t;
142     url_decode(ciss->host);
143     return path;
144 }
145
146 /* url_parse_ciss: Fill in ciss_url_t. char* elements are pointers into src,
147  *   which is modified by this call (duplicate it first if you need to).
148  * FIXME: THIS IS TASTELESS
149  */
150 int url_parse_ciss(ciss_url_t *ciss, char *src)
151 {
152     ciss->scheme = url_check_scheme(src);
153     if (ciss->scheme == U_UNKNOWN)
154         return -1;
155
156     ciss->path = ciss_parse_userhost(ciss, strchr(src, ':') + 1);
157     url_decode(ciss->path);
158
159     return 0;
160 }
161
162 /* url_ciss_tostring: output the URL string for a given CISS object. */
163 int url_ciss_tostring(ciss_url_t *ciss, char *dst, ssize_t len, int flags)
164 {
165     ssize_t l = 0;
166
167     if (ciss->scheme == U_UNKNOWN)
168         return -1;
169
170     snprintf(dst, len, "%s:", mutt_getnamebyvalue(ciss->scheme, UrlMap));
171
172     if (ciss->host) {
173         l = m_strcat(dst, len, "//");
174
175         if (ciss->user) {
176             if ((flags & U_DECODE_PASSWD) && ciss->pass) {
177                 l += snprintf(dst + l, len - l, "%s:%s@", ciss->user, ciss->pass);
178             } else {
179                 l += snprintf(dst + l, len - l, "%s@", ciss->user);
180             }
181         }
182
183         if (ciss->port) {
184             l += snprintf(dst + l, len - l, "%s:%hu/", ciss->host, ciss->port);
185         } else {
186             l += snprintf(dst + l, len - l, "%s/", ciss->host);
187         }
188     }
189
190     l += m_strcpy(dst + l, len - l, ciss->path);
191
192     return 0;
193 }