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