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