sort out some prototypes, put them where they belong.
[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 <stdio.h>
37 #include <ctype.h>
38
39 #include <lib-lib/lib-lib.h>
40
41 static struct mapping_t UrlMap[] = {
42     {"file",   U_FILE},
43     {"imap",   U_IMAP},
44     {"imaps",  U_IMAPS},
45     {"pop",    U_POP},
46     {"pops",   U_POPS},
47     {"nntp",   U_NNTP},
48     {"news",   U_NNTP},
49     {"nntps",  U_NNTPS},
50     {"snews",  U_NNTPS},
51     {"mailto", U_MAILTO},
52     {NULL,     U_UNKNOWN}
53 };
54
55 /* decode url escaping */
56 char *url_decode(char *p)
57 {
58     char *q = p;
59
60     if (!p)
61         return NULL;
62
63     while (*q) {
64         if (*q == '%' && hexval(q[1]) >= 0 && hexval(q[2]) >= 0) {
65             *p++ = (hexval(q[1]) << 4) | hexval(q[2]);
66             q += 3;
67         } else {
68             *p++ = *q++;
69         }
70     }
71
72     *p = '\0';
73     return p;
74 }
75
76 url_scheme_t url_check_scheme(const char *s)
77 {
78     char sbuf[STRING];
79     char *t;
80     int i;
81
82     if (!s || !(t = strchr(s, ':')))
83         return U_UNKNOWN;
84
85     m_strncpy(sbuf, sizeof(sbuf), s, t - s);
86     i = mutt_getvaluebyname(sbuf, UrlMap);
87     return i == -1 ? U_UNKNOWN : i;
88 }
89
90 /* ciss_parse_userhost: fill in components of ciss with info from src. Note
91  *   these are pointers into src, which is altered with '\0's. Port of 0
92  *   means no port given.
93  * FIXME: THIS IS TASTELESS
94  */
95 static char *ciss_parse_userhost(ciss_url_t *ciss, char *src)
96 {
97     char *t;
98     char *p;
99     char *path;
100
101     ciss->user = NULL;
102     ciss->pass = NULL;
103     ciss->host = NULL;
104     ciss->port = 0;
105
106     if (strncmp(src, "//", 2))
107         return src;
108
109     src += 2;
110
111     if ((path = strchr(src, '/')))
112         *path++ = '\0';
113
114     if ((t = strrchr(src, '@'))) {
115         *t = '\0';
116         if ((p = strchr (src, ':'))) {
117             *p = '\0';
118             ciss->pass = p + 1;
119             url_decode (ciss->pass);
120         }
121         ciss->user = src;
122         url_decode (ciss->user);
123         t++;
124     }
125     else
126         t = src;
127
128     if ((p = strchr (t, ':'))) {
129         *p++ = '\0';
130         ciss->port = atoi (p);
131     }
132     else
133         ciss->port = 0;
134
135     ciss->host = t;
136     url_decode(ciss->host);
137     return path;
138 }
139
140 /* url_parse_ciss: Fill in ciss_url_t. char* elements are pointers into src,
141  *   which is modified by this call (duplicate it first if you need to).
142  * FIXME: THIS IS TASTELESS
143  */
144 int url_parse_ciss(ciss_url_t *ciss, char *src)
145 {
146     ciss->scheme = url_check_scheme(src);
147     if (ciss->scheme == U_UNKNOWN)
148         return -1;
149
150     ciss->path = ciss_parse_userhost(ciss, strchr(src, ':') + 1);
151     url_decode(ciss->path);
152
153     return 0;
154 }
155
156 /* url_ciss_tostring: output the URL string for a given CISS object. */
157 int url_ciss_tostring(ciss_url_t *ciss, char *dst, ssize_t len, int flags)
158 {
159     ssize_t l = 0;
160
161     if (ciss->scheme == U_UNKNOWN)
162         return -1;
163
164     snprintf(dst, len, "%s:", mutt_getnamebyvalue(ciss->scheme, UrlMap));
165
166     if (ciss->host) {
167         l = m_strcat(dst, len, "//");
168
169         if (ciss->user) {
170             if ((flags & U_DECODE_PASSWD) && ciss->pass) {
171                 l += snprintf(dst + l, len - l, "%s:%s@", ciss->user, ciss->pass);
172             } else {
173                 l += snprintf(dst + l, len - l, "%s@", ciss->user);
174             }
175         }
176
177         if (ciss->port) {
178             l += snprintf(dst + l, len - l, "%s:%hu/", ciss->host, ciss->port);
179         } else {
180             l += snprintf(dst + l, len - l, "%s/", ciss->host);
181         }
182     }
183
184     l += m_strcpy(dst + l, len - l, ciss->path);
185
186     return 0;
187 }