d3372da9 |
1 | /* |
2 | * Dolda Connect - Modular multiuser Direct Connect-style client |
3 | * Copyright (C) 2004 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 2 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, write to the Free Software |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | */ |
19 | #include <malloc.h> |
20 | #include <stdarg.h> |
21 | #include <stdio.h> |
22 | #include <wchar.h> |
23 | #include <iconv.h> |
24 | #include <errno.h> |
25 | #include <string.h> |
26 | #include <wctype.h> |
27 | #include <langinfo.h> |
28 | #include <pwd.h> |
29 | #include <unistd.h> |
30 | #include <sys/time.h> |
31 | #include <netinet/in.h> |
32 | |
33 | #ifdef HAVE_CONFIG_H |
34 | #include <config.h> |
35 | #endif |
36 | #include "utils.h" |
37 | #include "log.h" |
38 | |
39 | static char *base64set = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
40 | static int base64rev[] = { |
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, 62, -1, -1, -1, 63, |
44 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, |
45 | -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, |
46 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, |
47 | -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, |
48 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, |
49 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
50 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
51 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
52 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
53 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
54 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
55 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
56 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
57 | }; |
58 | static char *base32set = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; |
59 | static int base32rev[] = { |
60 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
61 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
62 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
63 | -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, -1, |
64 | -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, |
65 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, |
66 | -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, |
67 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, |
68 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
69 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
70 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
71 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
72 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
73 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
74 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
75 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
76 | }; |
77 | |
78 | char *vsprintf2(char *format, va_list al) |
79 | { |
80 | int ret; |
81 | char *buf; |
82 | |
83 | ret = vsnprintf(NULL, 0, format, al); |
84 | if((buf = malloc(ret + 1)) == NULL) |
85 | { |
86 | LOGOOM(ret + 1); |
87 | return(NULL); |
88 | } |
89 | vsnprintf(buf, ret + 1, format, al); |
90 | return(buf); |
91 | } |
92 | |
93 | char *sprintf2(char *format, ...) |
94 | { |
95 | va_list args; |
96 | char *buf; |
97 | |
98 | va_start(args, format); |
99 | buf = vsprintf2(format, args); |
100 | va_end(args); |
101 | return(buf); |
102 | } |
103 | |
104 | wchar_t *vswprintf2(wchar_t *format, va_list al) |
105 | { |
106 | int ret; |
107 | wchar_t *buf; |
108 | size_t bufsize; |
109 | |
110 | buf = smalloc(sizeof(wchar_t) * (bufsize = 1024)); |
111 | while((ret = vswprintf(buf, bufsize, format, al)) < 0) |
112 | buf = srealloc(buf, sizeof(wchar_t) * (bufsize *= 2)); |
113 | if(bufsize > ret + 1) |
114 | buf = srealloc(buf, sizeof(wchar_t) * (ret + 1)); |
115 | return(buf); |
116 | } |
117 | |
118 | wchar_t *swprintf2(wchar_t *format, ...) |
119 | { |
120 | va_list args; |
121 | wchar_t *buf; |
122 | |
123 | va_start(args, format); |
124 | buf = vswprintf2(format, args); |
125 | va_end(args); |
126 | return(buf); |
127 | } |
128 | |
129 | wchar_t *icmbstowcs(char *mbs, char *charset) |
130 | { |
131 | int ret; |
132 | char *buf; |
133 | char *p, *p2; |
134 | size_t len1, len2, bufsize, data; |
135 | iconv_t cd; |
136 | |
137 | len1 = strlen(mbs) + 1; |
138 | bufsize = len2 = len1 * sizeof(wchar_t); |
139 | if((buf = malloc(bufsize)) == NULL) |
140 | { |
141 | LOGOOM(bufsize); |
142 | return(NULL); |
143 | } |
144 | if(charset == NULL) |
145 | charset = nl_langinfo(CODESET); |
146 | if((cd = iconv_open("wchar_t", charset)) == (iconv_t)-1) |
147 | { |
148 | flog(LOG_ERR, "icmbstowcs: could not open iconv structure for %s: %s", charset, strerror(errno)); |
149 | free(buf); |
150 | return(NULL); |
151 | } |
152 | p = buf; |
153 | while(len1 > 0) |
154 | { |
155 | ret = iconv(cd, &mbs, &len1, &p, &len2); |
156 | if(ret < 0) |
157 | { |
158 | if(errno == E2BIG) |
159 | { |
160 | data = p - buf; |
161 | len2 += 128; |
162 | bufsize += 128; |
163 | if((p2 = realloc(buf, bufsize)) == NULL) |
164 | { |
165 | LOGOOM(bufsize); |
166 | free(buf); |
167 | iconv_close(cd); |
168 | return(NULL); |
169 | } |
170 | buf = p2; |
171 | p = buf + data; |
172 | } else { |
173 | free(buf); |
174 | iconv_close(cd); |
175 | return(NULL); |
176 | } |
177 | } |
178 | } |
179 | if(len2 > 0) |
180 | buf = realloc(buf, p - buf); |
181 | iconv_close(cd); |
182 | return((wchar_t *)buf); |
183 | } |
184 | |
185 | wchar_t *icsmbstowcs(char *mbs, char *charset, wchar_t *def) |
186 | { |
187 | static wchar_t *buf = NULL; |
188 | |
189 | if(buf != NULL) |
190 | free(buf); |
191 | if((buf = icmbstowcs(mbs, charset)) == NULL) |
192 | { |
96cf7d1f |
193 | if((def != NULL) && (*def == L'~')) |
d3372da9 |
194 | { |
195 | flog(LOG_WARNING, "icsmbstowcs: could not convert wcs string into charset %s: %s", charset, strerror(errno)); |
196 | def++; |
197 | } |
198 | return(def); |
199 | } |
200 | return(buf); |
201 | } |
202 | |
203 | char *icwcstombs(wchar_t *wcs, char *charset) |
204 | { |
205 | int ret; |
206 | char *buf; |
207 | char *p, *p2; |
208 | size_t len1, len2, bufsize, data; |
209 | iconv_t cd; |
210 | |
211 | len1 = sizeof(wchar_t) * (wcslen(wcs) + 1); |
212 | bufsize = len2 = len1; |
213 | if((buf = malloc(bufsize)) == NULL) |
214 | { |
215 | LOGOOM(bufsize); |
216 | return(NULL); |
217 | } |
218 | if(charset == NULL) |
219 | charset = nl_langinfo(CODESET); |
220 | if((cd = iconv_open(charset, "wchar_t")) == (iconv_t)-1) |
221 | { |
222 | flog(LOG_ERR, "icwcstombs: could not open iconv structure for %s: %s", charset, strerror(errno)); |
223 | free(buf); |
224 | return(NULL); |
225 | } |
226 | p = buf; |
227 | while(len1 > 0) |
228 | { |
229 | ret = iconv(cd, (char **)&wcs, &len1, &p, &len2); |
230 | if(ret < 0) |
231 | { |
232 | if(errno == E2BIG) |
233 | { |
234 | data = p - buf; |
235 | len2 += 128; |
236 | bufsize += 128; |
237 | if((p2 = realloc(buf, bufsize)) == NULL) |
238 | { |
239 | LOGOOM(bufsize); |
240 | free(buf); |
241 | iconv_close(cd); |
242 | return(NULL); |
243 | } |
244 | buf = p2; |
245 | p = buf + data; |
246 | } else { |
247 | free(buf); |
248 | iconv_close(cd); |
249 | return(NULL); |
250 | } |
251 | } |
252 | } |
253 | if(len2 > 0) |
254 | buf = realloc(buf, p - buf); |
255 | iconv_close(cd); |
256 | return(buf); |
257 | } |
258 | |
259 | char *icswcstombs(wchar_t *wcs, char *charset, char *def) |
260 | { |
261 | static char *buf = NULL; |
262 | |
263 | if(buf != NULL) |
264 | free(buf); |
265 | if((buf = icwcstombs(wcs, charset)) == NULL) |
266 | { |
96cf7d1f |
267 | if((def != NULL) && (*def == '~')) |
d3372da9 |
268 | { |
269 | flog(LOG_WARNING, "icswcstombs: could not convert mbs string from charset %s: %s", charset, strerror(errno)); |
270 | def++; |
271 | } |
272 | return(def); |
273 | } |
274 | return(buf); |
275 | } |
276 | |
277 | wchar_t *wcstolower(wchar_t *wcs) |
278 | { |
279 | wchar_t *p; |
280 | |
281 | for(p = wcs; *p != L'\0'; p++) |
282 | *p = towlower(*p); |
283 | return(wcs); |
284 | } |
285 | |
286 | wchar_t ucptowc(int ucp) |
287 | { |
288 | int ret; |
289 | unsigned long ucpbuf; |
290 | char *buf; |
291 | char *mbsp, *p, *p2; |
292 | wchar_t res; |
293 | size_t len1, len2, bufsize, data; |
294 | iconv_t cd; |
295 | |
296 | ucpbuf = htonl(ucp); |
297 | mbsp = (char *)&ucpbuf; |
298 | len1 = 4; |
299 | bufsize = len2 = len1 * sizeof(wchar_t); |
300 | if((buf = malloc(bufsize)) == NULL) |
301 | { |
302 | LOGOOM(bufsize); |
303 | return(L'\0'); |
304 | } |
305 | if((cd = iconv_open("wchar_t", "UCS-4BE")) == (iconv_t)-1) |
306 | { |
307 | flog(LOG_ERR, "ucptowc: could not open iconv structure for UCS-4BE: %s", strerror(errno)); |
308 | free(buf); |
309 | return(L'\0'); |
310 | } |
311 | p = buf; |
312 | while(len1 > 0) |
313 | { |
314 | ret = iconv(cd, &mbsp, &len1, &p, &len2); |
315 | if(ret < 0) |
316 | { |
317 | if(errno == E2BIG) |
318 | { |
319 | data = p - buf; |
320 | len2 += 128; |
321 | bufsize += 128; |
322 | if((p2 = realloc(buf, bufsize)) == NULL) |
323 | { |
324 | LOGOOM(bufsize); |
325 | free(buf); |
326 | iconv_close(cd); |
327 | return(L'\0'); |
328 | } |
329 | buf = p2; |
330 | p = buf + data; |
331 | } else { |
332 | free(buf); |
333 | iconv_close(cd); |
334 | return(L'\0'); |
335 | } |
336 | } |
337 | } |
338 | if(len2 > 0) |
339 | buf = realloc(buf, p - buf); |
340 | iconv_close(cd); |
341 | res = *(wchar_t *)buf; |
342 | free(buf); |
343 | return(res); |
344 | } |
345 | |
346 | void _sizebuf(void **buf, size_t *bufsize, size_t reqsize, size_t elsize, int algo) |
347 | { |
348 | if(*bufsize >= reqsize) |
349 | return; |
350 | switch(algo) |
351 | { |
352 | case 0: |
353 | *buf = srealloc(*buf, elsize * ((*bufsize) = reqsize)); |
354 | break; |
355 | case 1: |
356 | if(*bufsize == 0) |
357 | *bufsize = 1; |
358 | while(*bufsize < reqsize) |
359 | *bufsize <<= 1; |
360 | *buf = srealloc(*buf, elsize * (*bufsize)); |
361 | break; |
362 | } |
363 | } |
364 | |
365 | double ntime(void) |
366 | { |
367 | struct timeval tv; |
368 | |
369 | gettimeofday(&tv, NULL); |
370 | return((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0)); |
371 | } |
372 | |
373 | int wcsexists(wchar_t *h, wchar_t *n) |
374 | { |
375 | int i, o, nl, hl; |
376 | wchar_t *ln, *lh; |
377 | |
378 | ln = alloca(sizeof(*ln) * (nl = wcslen(n))); |
379 | for(i = 0; i < nl; i++) |
380 | ln[i] = towlower(n[i]); |
381 | lh = alloca(sizeof(*lh) * (hl = wcslen(h))); |
382 | if(nl > hl) |
383 | return(0); |
384 | for(i = 0; i < nl; i++) |
385 | lh[i] = towlower(h[i]); |
386 | i = 0; |
387 | while(1) |
388 | { |
389 | for(o = 0; o < nl; o++) |
390 | { |
391 | if(lh[i + o] != ln[o]) |
392 | break; |
393 | } |
394 | if(o == nl) |
395 | return(1); |
396 | if(i == hl - nl) |
397 | return(0); |
398 | lh[i + nl] = towlower(h[i + nl]); |
399 | i++; |
400 | } |
401 | } |
402 | |
403 | #ifndef HAVE_WCSCASECMP |
404 | int wcscasecmp(const wchar_t *s1, const wchar_t *s2) |
405 | { |
406 | while(towlower(*s1) == towlower(*s2)) |
407 | { |
408 | if(*s1 == L'\0') |
409 | return(0); |
410 | } |
411 | return(towlower(*s1) - towlower(*s2)); |
412 | } |
413 | #endif |
414 | |
415 | char *hexencode(char *data, size_t datalen) |
416 | { |
417 | char *buf, this; |
418 | size_t bufsize, bufdata; |
419 | int dig; |
420 | |
421 | buf = NULL; |
422 | bufsize = bufdata = 0; |
423 | for(; datalen > 0; datalen--, data++) |
424 | { |
425 | dig = (*data & 0xF0) >> 4; |
426 | if(dig > 9) |
427 | this = 'A' + dig - 10; |
428 | else |
429 | this = dig + '0'; |
430 | addtobuf(buf, this); |
431 | dig = *data & 0x0F; |
432 | if(dig > 9) |
433 | this = 'A' + dig - 10; |
434 | else |
435 | this = dig + '0'; |
436 | addtobuf(buf, this); |
437 | } |
438 | addtobuf(buf, 0); |
439 | return(buf); |
440 | } |
441 | |
442 | char *hexdecode(char *data, size_t *len) |
443 | { |
444 | char *buf, this; |
445 | size_t bufsize, bufdata; |
446 | |
447 | buf = NULL; |
448 | bufsize = bufdata = 0; |
449 | for(; *data; data++) |
450 | { |
451 | if((*data >= 'A') && (*data <= 'F')) |
452 | { |
453 | this = (this & 0x0F) | ((*data - 'A' + 10) << 4); |
454 | } else if((*data >= '0') && (*data <= '9')) { |
455 | this = (this & 0x0F) | ((*data - '0') << 4); |
456 | } else { |
457 | if(buf != NULL) |
458 | free(buf); |
459 | return(NULL); |
460 | } |
461 | data++; |
462 | if(!*data) |
463 | { |
464 | if(buf != NULL) |
465 | free(buf); |
466 | return(NULL); |
467 | } |
468 | if((*data >= 'A') && (*data <= 'F')) |
469 | { |
470 | this = (this & 0xF0) | (*data - 'A' + 10); |
471 | } else if((*data >= '0') && (*data <= '9')) { |
472 | this = (this & 0xF0) | (*data - '0'); |
473 | } else { |
474 | if(buf != NULL) |
475 | free(buf); |
476 | return(NULL); |
477 | } |
478 | addtobuf(buf, this); |
479 | } |
480 | addtobuf(buf, 0); |
481 | if(len != NULL) |
482 | *len = bufdata - 1; |
483 | return(buf); |
484 | } |
485 | |
486 | char *base64encode(char *data, size_t datalen) |
487 | { |
488 | char *buf; |
489 | size_t bufsize, bufdata; |
490 | |
491 | if(datalen == 0) |
492 | return(sstrdup("")); |
493 | buf = NULL; |
494 | bufsize = bufdata = 0; |
495 | while(datalen >= 3) |
496 | { |
497 | addtobuf(buf, base64set[(data[0] & 0xfc) >> 2]); |
498 | addtobuf(buf, base64set[((data[0] & 0x03) << 4) | ((data[1] & 0xf0) >> 4)]); |
499 | addtobuf(buf, base64set[((data[1] & 0x0f) << 2) | ((data[2] & 0xc0) >> 6)]); |
500 | addtobuf(buf, base64set[data[2] & 0x3f]); |
501 | datalen -= 3; |
502 | data += 3; |
503 | } |
504 | if(datalen == 1) |
505 | { |
506 | addtobuf(buf, base64set[(data[0] & 0xfc) >> 2]); |
507 | addtobuf(buf, base64set[(data[0] & 0x03) << 4]); |
508 | bufcat(buf, "==", 2); |
509 | } |
510 | if(datalen == 2) |
511 | { |
512 | addtobuf(buf, base64set[(data[0] & 0xfc) >> 2]); |
513 | addtobuf(buf, base64set[((data[0] & 0x03) << 4) | ((data[1] & 0xf0) >> 4)]); |
514 | addtobuf(buf, base64set[(data[1] & 0x0f) << 2]); |
515 | addtobuf(buf, '='); |
516 | } |
517 | addtobuf(buf, 0); |
518 | return(buf); |
519 | } |
520 | |
521 | char *base64decode(char *data, size_t *datalen) |
522 | { |
523 | int b, c; |
524 | char *buf, cur; |
525 | size_t bufsize, bufdata; |
526 | |
527 | buf = NULL; |
528 | bufsize = bufdata = 0; |
529 | cur = 0; |
530 | b = 8; |
531 | for(; *data > 0; data++) |
532 | { |
533 | c = (int)(unsigned char)*data; |
534 | if(c == '=') |
535 | break; |
65399bc2 |
536 | if(c == '\n') |
537 | continue; |
d3372da9 |
538 | if(base64rev[c] == -1) |
539 | { |
540 | if(buf != NULL) |
541 | free(buf); |
542 | return(NULL); |
543 | } |
544 | b -= 6; |
545 | if(b <= 0) |
546 | { |
547 | cur |= base64rev[c] >> -b; |
548 | addtobuf(buf, cur); |
549 | b += 8; |
550 | cur = 0; |
551 | } |
552 | cur |= base64rev[c] << b; |
553 | } |
554 | if(datalen != NULL) |
555 | *datalen = bufdata; |
556 | addtobuf(buf, 0); |
557 | return(buf); |
558 | } |
559 | |
560 | char *base32encode(char *data, size_t datalen) |
561 | { |
562 | char *buf; |
563 | size_t bufsize, bufdata; |
564 | |
565 | if(datalen == 0) |
566 | return(sstrdup("")); |
567 | buf = NULL; |
568 | bufsize = bufdata = 0; |
569 | while(datalen >= 5) |
570 | { |
571 | addtobuf(buf, base32set[((data[0] & 0xf8) >> 3)]); |
572 | addtobuf(buf, base32set[((data[0] & 0x07) << 2) | ((data[1] & 0xc0) >> 6)]); |
573 | addtobuf(buf, base32set[((data[1] & 0x3e) >> 1)]); |
574 | addtobuf(buf, base32set[((data[1] & 0x01) << 4) | ((data[2] & 0xf0) >> 4)]); |
575 | addtobuf(buf, base32set[((data[2] & 0x0f) << 1) | ((data[3] & 0x80) >> 7)]); |
576 | addtobuf(buf, base32set[((data[3] & 0x7c) >> 2)]); |
577 | addtobuf(buf, base32set[((data[3] & 0x03) << 3) | ((data[4] & 0xe0) >> 5)]); |
578 | addtobuf(buf, base32set[data[4] & 0x1f]); |
579 | datalen -= 5; |
580 | data += 5; |
581 | } |
582 | if(datalen == 1) |
583 | { |
584 | addtobuf(buf, base32set[((data[0] & 0xf8) >> 3)]); |
585 | addtobuf(buf, base32set[((data[0] & 0x07) << 2)]); |
586 | bufcat(buf, "======", 6); |
587 | } |
588 | if(datalen == 2) |
589 | { |
590 | addtobuf(buf, base32set[((data[0] & 0xf8) >> 3)]); |
591 | addtobuf(buf, base32set[((data[0] & 0x07) << 2) | ((data[1] & 0xc0) >> 6)]); |
592 | addtobuf(buf, base32set[((data[1] & 0x3e) >> 1)]); |
593 | addtobuf(buf, base32set[((data[1] & 0x01) << 4)]); |
594 | bufcat(buf, "====", 4); |
595 | } |
596 | if(datalen == 3) |
597 | { |
598 | addtobuf(buf, base32set[((data[0] & 0xf8) >> 3)]); |
599 | addtobuf(buf, base32set[((data[0] & 0x07) << 2) | ((data[1] & 0xc0) >> 6)]); |
600 | addtobuf(buf, base32set[((data[1] & 0x3e) >> 1)]); |
601 | addtobuf(buf, base32set[((data[1] & 0x01) << 4) | ((data[2] & 0xf0) >> 4)]); |
602 | addtobuf(buf, base32set[((data[2] & 0x0f) << 1)]); |
603 | bufcat(buf, "===", 3); |
604 | } |
605 | if(datalen == 4) |
606 | { |
607 | addtobuf(buf, base32set[((data[0] & 0xf8) >> 3)]); |
608 | addtobuf(buf, base32set[((data[0] & 0x07) << 2) | ((data[1] & 0xc0) >> 6)]); |
609 | addtobuf(buf, base32set[((data[1] & 0x3e) >> 1)]); |
610 | addtobuf(buf, base32set[((data[1] & 0x01) << 4) | ((data[2] & 0xf0) >> 4)]); |
611 | addtobuf(buf, base32set[((data[2] & 0x0f) << 1) | ((data[3] & 0x80) >> 7)]); |
612 | addtobuf(buf, base32set[((data[3] & 0x7c) >> 2)]); |
613 | addtobuf(buf, base32set[((data[3] & 0x03) << 3)]); |
614 | bufcat(buf, "=", 1); |
615 | } |
616 | addtobuf(buf, 0); |
617 | return(buf); |
618 | } |
619 | |
620 | char *base32decode(char *data, size_t *datalen) |
621 | { |
622 | int b, c; |
623 | char *buf, cur; |
624 | size_t bufsize, bufdata; |
625 | |
626 | buf = NULL; |
627 | bufsize = bufdata = 0; |
628 | cur = 0; |
629 | b = 8; |
630 | for(; *data > 0; data++) |
631 | { |
632 | c = (int)(unsigned char)*data; |
633 | if(c == '=') |
634 | break; |
65399bc2 |
635 | if(c == '\n') |
636 | continue; |
d3372da9 |
637 | if(base32rev[c] == -1) |
638 | { |
639 | if(buf != NULL) |
640 | free(buf); |
641 | return(NULL); |
642 | } |
643 | b -= 5; |
644 | if(b <= 0) |
645 | { |
646 | cur |= base32rev[c] >> -b; |
647 | addtobuf(buf, cur); |
648 | b += 8; |
649 | cur = 0; |
650 | } |
651 | cur |= base32rev[c] << b; |
652 | } |
653 | if(datalen != NULL) |
654 | *datalen = bufdata; |
655 | addtobuf(buf, 0); |
656 | return(buf); |
657 | } |
658 | |
659 | void _freeparr(void **arr) |
660 | { |
661 | void **buf; |
662 | |
663 | if(arr == NULL) |
664 | return; |
665 | for(buf = arr; *buf != NULL; buf++) |
666 | free(*buf); |
667 | free(arr); |
668 | } |
669 | |
670 | int _parrlen(void **arr) |
671 | { |
672 | int i; |
673 | |
674 | if(arr == NULL) |
675 | return(0); |
676 | for(i = 0; *arr != NULL; arr++) |
677 | i++; |
678 | return(i); |
679 | } |
680 | |
681 | char *getetcpath(char *binpath) |
682 | { |
73247114 |
683 | int f; |
d3372da9 |
684 | char *etcpath, *p; |
685 | size_t etcpathsize, etcpathdata; |
686 | |
687 | etcpath = NULL; |
688 | etcpathsize = etcpathdata = 0; |
73247114 |
689 | f = 1; |
d3372da9 |
690 | do |
691 | { |
73247114 |
692 | if(f) |
693 | f = 0; |
694 | else |
695 | binpath++; |
d3372da9 |
696 | for(p = binpath; *p && (*p != ':'); p++); |
697 | for(; (p >= binpath) && (*p != '/'); p--); |
698 | if(p >= binpath) |
699 | { |
700 | if(etcpathdata > 0) |
701 | addtobuf(etcpath, ':'); |
702 | bufcat(etcpath, binpath, p - binpath + 1); |
703 | bufcat(etcpath, "etc", 3); |
704 | } |
705 | } while((binpath = strchr(binpath, ':')) != NULL); |
706 | addtobuf(etcpath, 0); |
707 | return(etcpath); |
708 | } |
709 | |
710 | char *findfile(char *gname, char *uname, char *homedir) |
711 | { |
712 | char *path, *binpath, *etcpath, *p; |
713 | |
714 | if((homedir != NULL) && ((path = sprintf2("%s/.%s", homedir, uname)) != NULL)) |
715 | { |
716 | if(!access(path, F_OK)) |
717 | return(path); |
718 | free(path); |
719 | } |
720 | if(gname != NULL) |
721 | { |
722 | if(strchr(gname, '/') != NULL) |
723 | { |
724 | if(!access(gname, F_OK)) |
725 | return(sstrdup(gname)); |
726 | } else { |
727 | if((binpath = getenv("PATH")) == NULL) |
728 | etcpath = sstrdup("/usr/local/etc:/etc:/usr/etc"); |
729 | else |
730 | etcpath = getetcpath(binpath); |
731 | for(p = strtok(etcpath, ":"); p != NULL; p = strtok(NULL, ":")) |
732 | { |
733 | if((path = sprintf2("%s/%s", p, gname)) != NULL) |
734 | { |
735 | if(!access(path, F_OK)) |
736 | { |
737 | free(etcpath); |
738 | return(path); |
739 | } |
740 | free(path); |
741 | } |
742 | } |
743 | free(etcpath); |
744 | } |
745 | } |
746 | return(NULL); |
747 | } |
9ec790e8 |
748 | |
749 | struct wcspair *newwcspair(wchar_t *key, wchar_t *val, struct wcspair **list) |
750 | { |
751 | struct wcspair *pair; |
752 | |
753 | pair = smalloc(sizeof(*pair)); |
754 | memset(pair, 0, sizeof(*pair)); |
755 | if(key != NULL) |
756 | pair->key = swcsdup(key); |
757 | if(val != NULL) |
758 | pair->val = swcsdup(val); |
759 | if(list == NULL) |
760 | { |
761 | pair->next = NULL; |
762 | } else { |
763 | pair->next = *list; |
764 | *list = pair; |
765 | } |
766 | return(pair); |
767 | } |
768 | |
769 | void freewcspair(struct wcspair *pair, struct wcspair **list) |
770 | { |
497fe07b |
771 | struct wcspair *cur; |
772 | |
773 | for(cur = *list; cur != NULL; list = &(cur->next), cur = cur->next) |
9ec790e8 |
774 | { |
497fe07b |
775 | if(cur == pair) |
776 | { |
777 | *list = cur->next; |
778 | break; |
779 | } |
9ec790e8 |
780 | } |
781 | free(pair->key); |
782 | free(pair->val); |
783 | free(pair); |
784 | } |
a2761258 |
785 | |
786 | wchar_t *wpfind(struct wcspair *list, wchar_t *key) |
787 | { |
788 | for(; list != NULL; list = list->next) |
789 | { |
790 | if(!wcscmp(list->key, key)) |
791 | return(list->val); |
792 | } |
793 | return(NULL); |
794 | } |