2 * This file is part of DisOrder.
3 * Copyright (C) 2004, 2005, 2007, 2008 Richard Kettlewell
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28 int urldecode(struct sink
*sink
, const char *ptr
, size_t n
) {
34 if((d1
= unhexdigit(ptr
[0])) == -1
35 || (d2
= unhexdigit(ptr
[1])) == -1)
47 if(sink_writec(sink
,c
) < 0)
53 static char *decode(const char *ptr
, size_t n
) {
59 if(urldecode(s
, ptr
, n
))
65 struct kvp
*kvp_urldecode(const char *ptr
, size_t n
) {
66 struct kvp
*kvp
, **kk
= &kvp
, *k
;
67 const char *q
, *r
, *top
= ptr
+ n
, *next
;
70 *kk
= k
= xmalloc(sizeof *k
);
71 if(!(q
= memchr(ptr
, '=', top
- ptr
)))
73 if(!(k
->name
= decode(ptr
, q
- ptr
))) break;
74 if((r
= memchr(ptr
, '&', top
- ptr
)))
80 if(!(k
->value
= decode(q
+ 1, r
- (q
+ 1)))) break;
88 int urlencode(struct sink
*sink
, const char *s
, size_t n
) {
96 if((c
>= '0' && c
<= '9')
97 || (c
>= 'a' && c
<= 'z')
98 || (c
>= 'A' && c
<= 'Z')) {
99 /* RFC2396 2.3 unreserved characters */
109 /* additional unreserved characters */
111 if(sink_writec(sink
, c
) < 0)
114 if(sink_printf(sink
, "%%%02x", (unsigned int)c
) < 0)
121 /** @brief URL-encode @p s
122 * @param s String to encode
123 * @return Encoded string
125 char *urlencodestring(const char *s
) {
129 urlencode(sink_dynstr(&d
), s
, strlen(s
));
130 dynstr_terminate(&d
);
134 /** @brief URL-decode @p s
135 * @param s String to decode
136 * @param ns Length of string
137 * @return Decoded string or NULL
139 char *urldecodestring(const char *s
, size_t ns
) {
143 if(urldecode(sink_dynstr(&d
), s
, ns
))
145 dynstr_terminate(&d
);
149 char *kvp_urlencode(const struct kvp
*kvp
, size_t *np
) {
154 sink
= sink_dynstr(&d
);
156 urlencode(sink
, kvp
->name
, strlen(kvp
->name
));
157 dynstr_append(&d
, '=');
158 urlencode(sink
, kvp
->value
, strlen(kvp
->value
));
159 if((kvp
= kvp
->next
))
160 dynstr_append(&d
, '&');
163 dynstr_terminate(&d
);
169 int kvp_set(struct kvp
**kvpp
, const char *name
, const char *value
) {
172 for(kk
= kvpp
; (k
= *kk
) && strcmp(name
, k
->name
); kk
= &k
->next
)
176 if(strcmp(k
->value
, value
)) {
177 k
->value
= xstrdup(value
);
187 *kk
= k
= xmalloc(sizeof *k
);
188 k
->name
= xstrdup(name
);
189 k
->value
= xstrdup(value
);
196 const char *kvp_get(const struct kvp
*kvp
, const char *name
) {
197 for(;kvp
&& strcmp(kvp
->name
, name
); kvp
= kvp
->next
)
199 return kvp ? kvp
->value
: 0;
202 struct kvp
*kvp_make(const char *name
, ...) {
204 struct kvp
*kvp
= 0, *k
;
209 value
= va_arg(ap
, const char *);
210 k
= xmalloc(sizeof *k
);
212 k
->value
= value ?
xstrdup(value
) : value
;
215 name
= va_arg(ap
, const char *);