Updated changelog.
[ashd.git] / lib / utils.c
CommitLineData
f0bbedf7
FT
1/*
2 ashd - A Sane HTTP Daemon
3 Copyright (C) 2008 Fredrik Tolf <fredrik@dolda2000.com>
4
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.
9
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.
14
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/>.
17*/
18
19#include <stdlib.h>
90f6e953 20#include <stdio.h>
f2b26d44
FT
21#include <string.h>
22#include <ctype.h>
f0bbedf7 23
ddf99192
FT
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
f0bbedf7
FT
27#include <utils.h>
28
be6e50bf
FT
29static char *base64set = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
30static int base64rev[] = {
31 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
32 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
33 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
34 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
35 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
36 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
37 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
38 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
39 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
40 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
41 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
42 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
43 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
44 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
45 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
46 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
47};
48
f0bbedf7
FT
49void _sizebuf(struct buffer *buf, size_t wanted, size_t el)
50{
51 size_t n;
52
53 n = buf->s;
54 if(n == 0)
55 n = 1;
56 while(n < wanted)
57 n <<= 1;
58 if(n <= buf->s)
59 return;
60 if(buf->b != NULL)
61 buf->b = srealloc(buf->b, n * el);
62 else
63 buf->b = smalloc(n * el);
64 buf->s = n;
65}
66
90f6e953
FT
67char *decstr(char **p, size_t *len)
68{
69 char *p2, *ret;
70
71 for(p2 = *p; (p2 - *p) < *len; p2++) {
72 if(*p2 == 0)
73 break;
74 }
75 if((p2 - *p) == *len)
76 return(NULL);
77 p2++;
78 ret = *p;
79 *len -= p2 - *p;
80 *p = p2;
81 return(ret);
82}
83
84char *vsprintf2(char *format, va_list al)
85{
86 int ret;
87 char *buf;
88 va_list al2;
89
90 va_copy(al2, al);
91 ret = vsnprintf(NULL, 0, format, al2);
92 va_end(al2);
93 buf = smalloc(ret + 1);
94 va_copy(al2, al);
95 vsnprintf(buf, ret + 1, format, al2);
96 va_end(al2);
97 return(buf);
98}
99
100char *sprintf2(char *format, ...)
101{
102 va_list args;
103 char *buf;
104
105 va_start(args, format);
106 buf = vsprintf2(format, args);
107 va_end(args);
108 return(buf);
109}
110
111char *sprintf3(char *format, ...)
112{
113 static char *buf = NULL;
114 va_list args;
115
116 if(buf != NULL)
117 free(buf);
118 va_start(args, format);
119 buf = vsprintf2(format, args);
120 va_end(args);
121 return(buf);
122}
9aee4cbc
FT
123
124off_t atoo(char *n)
125{
126 return((off_t)strtoll(n, NULL, 10));
127}
f2b26d44
FT
128
129char **tokenize(char *src)
130{
131 char **ret;
132 char *p, *p2, *n;
133 int s, q, cl;
134
135 p = src;
136 s = 0;
137 ret = NULL;
138 while(1) {
139 while(isspace(*p))
140 p++;
141 if(!*p)
142 break;
143 p2 = p;
144 q = 0;
145 while(1) {
146 if(q) {
147 if(*p == '\"')
148 q = 0;
149 else if(*p == '\\')
150 p++;
151 } else {
152 if(*p == '\"')
153 q = 1;
154 else if(isspace(*p) || !*p)
155 break;
156 else if(*p == '\\')
157 p++;
158 }
159 p++;
160 }
161 cl = p - p2;
162 n = memcpy(malloc(cl + 1), p2, cl);
163 n[cl] = 0;
164 for(p2 = n; *p2; cl--) {
165 if(*p2 == '\\') {
166 memmove(p2, p2 + 1, cl--);
167 p2++;
168 } else if(*p2 == '\"') {
169 memmove(p2, p2 + 1, cl);
170 } else {
171 p2++;
172 }
173 }
174 ret = realloc(ret, sizeof(char *) * (++s));
175 ret[s - 1] = n;
176 }
177 ret = realloc(ret, sizeof(char *) * (++s));
178 ret[s - 1] = NULL;
179 return(ret);
180}
181
182void freeca(char **ca)
183{
184 char **c;
185
06c1a718
FT
186 if(ca == NULL)
187 return;
f2b26d44
FT
188 for(c = ca; *c; c++)
189 free(*c);
190 free(ca);
191}
d1bd343c
FT
192
193int calen(char **a)
194{
195 int i;
196
197 for(i = 0; *a; a++, i++);
198 return(i);
199}
d422fdfd
FT
200
201void bvprintf(struct charbuf *buf, char *format, va_list al)
202{
203 va_list al2;
204 int ret;
205
206 while(1) {
207 va_copy(al2, al);
208 ret = vsnprintf(buf->b + buf->d, buf->s - buf->d, format, al2);
209 va_end(al2);
210 if(ret < buf->s - buf->d) {
211 buf->d += ret;
212 return;
213 }
214 sizebuf(*buf, buf->d + ret + 1);
215 }
216}
217
218void bprintf(struct charbuf *buf, char *format, ...)
219{
220 va_list args;
221
222 va_start(args, format);
223 bvprintf(buf, format, args);
224 va_end(args);
225}
5fc1bf9f
FT
226
227void replstr(char **p, char *n)
228{
229 char *tmp;
230
231 tmp = *p;
232 if(n)
233 *p = sstrdup(n);
234 else
235 *p = NULL;
236 if(tmp)
237 free(tmp);
238}
be6e50bf
FT
239
240char *base64encode(char *data, size_t datalen)
241{
242 struct charbuf buf;
243
244 if(datalen == 0)
245 return(sstrdup(""));
246 bufinit(buf);
247 while(datalen >= 3)
248 {
249 bufadd(buf, base64set[(data[0] & 0xfc) >> 2]);
250 bufadd(buf, base64set[((data[0] & 0x03) << 4) | ((data[1] & 0xf0) >> 4)]);
251 bufadd(buf, base64set[((data[1] & 0x0f) << 2) | ((data[2] & 0xc0) >> 6)]);
252 bufadd(buf, base64set[data[2] & 0x3f]);
253 datalen -= 3;
254 data += 3;
255 }
256 if(datalen == 1)
257 {
258 bufadd(buf, base64set[(data[0] & 0xfc) >> 2]);
259 bufadd(buf, base64set[(data[0] & 0x03) << 4]);
260 bufcat(buf, "==", 2);
261 }
262 if(datalen == 2)
263 {
264 bufadd(buf, base64set[(data[0] & 0xfc) >> 2]);
265 bufadd(buf, base64set[((data[0] & 0x03) << 4) | ((data[1] & 0xf0) >> 4)]);
266 bufadd(buf, base64set[(data[1] & 0x0f) << 2]);
267 bufadd(buf, '=');
268 }
269 bufadd(buf, 0);
270 return(buf.b);
271}
272
273char *base64decode(char *data, size_t *datalen)
274{
275 int b, c;
276 char cur;
277 struct charbuf buf;
278
279 bufinit(buf);
280 cur = 0;
281 b = 8;
282 for(; *data > 0; data++)
283 {
284 c = (int)(unsigned char)*data;
285 if(c == '=')
286 break;
287 if(c == '\n')
288 continue;
289 if(base64rev[c] == -1)
290 {
291 buffree(buf);
292 return(NULL);
293 }
294 b -= 6;
295 if(b <= 0)
296 {
297 cur |= base64rev[c] >> -b;
298 bufadd(buf, cur);
299 b += 8;
300 cur = 0;
301 }
302 cur |= base64rev[c] << b;
303 }
304 if(datalen != NULL)
305 *datalen = buf.d;
306 bufadd(buf, 0);
307 return(buf.b);
308}