2 * Dolda Connect - Modular multiuser Direct Connect-style client
3 * Copyright (C) 2004 Fredrik Tolf (fredrik@dolda2000.com)
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.
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, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include <netinet/in.h>
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,
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,
78 char *vsprintf2(char *format, va_list al)
85 ret = vsnprintf(NULL, 0, format, al2);
87 if((buf = malloc(ret + 1)) == NULL)
93 vsnprintf(buf, ret + 1, format, al2);
98 char *sprintf2(char *format, ...)
103 va_start(args, format);
104 buf = vsprintf2(format, args);
109 wchar_t *vswprintf2(wchar_t *format, va_list al)
116 buf = smalloc(sizeof(wchar_t) * (bufsize = 1024));
120 ret = vswprintf(buf, bufsize, format, al2);
124 buf = srealloc(buf, sizeof(wchar_t) * (bufsize *= 2));
126 if(bufsize > ret + 1)
127 buf = srealloc(buf, sizeof(wchar_t) * (ret + 1));
131 wchar_t *swprintf2(wchar_t *format, ...)
136 va_start(args, format);
137 buf = vswprintf2(format, args);
142 int havecharset(char *charset)
146 if((cd = iconv_open("wchar_t", charset)) == (iconv_t)-1)
149 if((cd = iconv_open(charset, "wchar_t")) == (iconv_t)-1)
155 wchar_t *icmbstowcs(char *mbs, char *charset)
160 size_t len1, len2, bufsize, data;
163 len1 = strlen(mbs) + 1;
164 bufsize = len2 = len1 * sizeof(wchar_t);
165 if((buf = malloc(bufsize)) == NULL)
171 charset = nl_langinfo(CODESET);
172 if((cd = iconv_open("wchar_t", charset)) == (iconv_t)-1)
175 flog(LOG_ERR, "icmbstowcs: could not open iconv structure for %s: %s", charset, strerror(errno));
183 ret = iconv(cd, &mbs, &len1, &p, &len2);
191 if((p2 = realloc(buf, bufsize)) == NULL)
208 buf = realloc(buf, p - buf);
210 return((wchar_t *)buf);
213 wchar_t *icsmbstowcs(char *mbs, char *charset, wchar_t *def)
215 static wchar_t *buf = NULL;
219 if((buf = icmbstowcs(mbs, charset)) == NULL)
221 if((def != NULL) && (*def == L'~'))
224 flog(LOG_WARNING, "icsmbstowcs: could not convert wcs string into charset %s: %s", charset, strerror(errno));
233 char *icwcstombs(wchar_t *wcs, char *charset)
238 size_t len1, len2, bufsize, data;
241 len1 = sizeof(wchar_t) * (wcslen(wcs) + 1);
242 bufsize = len2 = len1;
243 if((buf = malloc(bufsize)) == NULL)
251 charset = nl_langinfo(CODESET);
252 if((cd = iconv_open(charset, "wchar_t")) == (iconv_t)-1)
255 flog(LOG_ERR, "icwcstombs: could not open iconv structure for %s: %s", charset, strerror(errno));
263 ret = iconv(cd, (char **)&wcs, &len1, &p, &len2);
271 if((p2 = realloc(buf, bufsize)) == NULL)
288 buf = realloc(buf, p - buf);
293 char *icswcstombs(wchar_t *wcs, char *charset, char *def)
295 static char *buf = NULL;
299 if((buf = icwcstombs(wcs, charset)) == NULL)
301 if((def != NULL) && (*def == '~'))
304 flog(LOG_WARNING, "icswcstombs: could not convert mbs string from charset %s: %s", charset, strerror(errno));
313 wchar_t *wcstolower(wchar_t *wcs)
317 for(p = wcs; *p != L'\0'; p++)
322 wchar_t ucptowc(int ucp)
325 unsigned long ucpbuf;
329 size_t len1, len2, bufsize, data;
333 mbsp = (char *)&ucpbuf;
335 bufsize = len2 = len1 * sizeof(wchar_t);
336 if((buf = malloc(bufsize)) == NULL)
341 if((cd = iconv_open("wchar_t", "UCS-4BE")) == (iconv_t)-1)
344 flog(LOG_ERR, "ucptowc: could not open iconv structure for UCS-4BE: %s", strerror(errno));
352 ret = iconv(cd, &mbsp, &len1, &p, &len2);
360 if((p2 = realloc(buf, bufsize)) == NULL)
377 buf = realloc(buf, p - buf);
379 res = *(wchar_t *)buf;
384 void _sizebuf(void **buf, size_t *bufsize, size_t reqsize, size_t elsize, int algo)
386 if(*bufsize >= reqsize)
391 *buf = srealloc(*buf, elsize * ((*bufsize) = reqsize));
396 while(*bufsize < reqsize)
398 *buf = srealloc(*buf, elsize * (*bufsize));
407 gettimeofday(&tv, NULL);
408 return((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
411 int wcsexists(wchar_t *h, wchar_t *n)
416 ln = alloca(sizeof(*ln) * (nl = wcslen(n)));
417 for(i = 0; i < nl; i++)
418 ln[i] = towlower(n[i]);
419 lh = alloca(sizeof(*lh) * (hl = wcslen(h)));
422 for(i = 0; i < nl; i++)
423 lh[i] = towlower(h[i]);
427 for(o = 0; o < nl; o++)
429 if(lh[i + o] != ln[o])
436 lh[i + nl] = towlower(h[i + nl]);
441 #ifndef HAVE_WCSCASECMP
442 int wcscasecmp(const wchar_t *s1, const wchar_t *s2)
444 for(; (towlower(*s1) == towlower(*s2)) && (*s1 != L'\0'); s1++, s2++);
445 return(towlower(*s1) - towlower(*s2));
449 char *hexencode(char *data, size_t datalen)
452 size_t bufsize, bufdata;
456 bufsize = bufdata = 0;
457 for(; datalen > 0; datalen--, data++)
459 dig = (*data & 0xF0) >> 4;
461 this = 'A' + dig - 10;
467 this = 'A' + dig - 10;
476 char *hexdecode(char *data, size_t *len)
479 size_t bufsize, bufdata;
482 bufsize = bufdata = 0;
485 if((*data >= 'A') && (*data <= 'F'))
487 this = (this & 0x0F) | ((*data - 'A' + 10) << 4);
488 } else if((*data >= '0') && (*data <= '9')) {
489 this = (this & 0x0F) | ((*data - '0') << 4);
502 if((*data >= 'A') && (*data <= 'F'))
504 this = (this & 0xF0) | (*data - 'A' + 10);
505 } else if((*data >= '0') && (*data <= '9')) {
506 this = (this & 0xF0) | (*data - '0');
520 char *base64encode(char *data, size_t datalen)
523 size_t bufsize, bufdata;
528 bufsize = bufdata = 0;
531 addtobuf(buf, base64set[(data[0] & 0xfc) >> 2]);
532 addtobuf(buf, base64set[((data[0] & 0x03) << 4) | ((data[1] & 0xf0) >> 4)]);
533 addtobuf(buf, base64set[((data[1] & 0x0f) << 2) | ((data[2] & 0xc0) >> 6)]);
534 addtobuf(buf, base64set[data[2] & 0x3f]);
540 addtobuf(buf, base64set[(data[0] & 0xfc) >> 2]);
541 addtobuf(buf, base64set[(data[0] & 0x03) << 4]);
542 bufcat(buf, "==", 2);
546 addtobuf(buf, base64set[(data[0] & 0xfc) >> 2]);
547 addtobuf(buf, base64set[((data[0] & 0x03) << 4) | ((data[1] & 0xf0) >> 4)]);
548 addtobuf(buf, base64set[(data[1] & 0x0f) << 2]);
555 char *base64decode(char *data, size_t *datalen)
559 size_t bufsize, bufdata;
562 bufsize = bufdata = 0;
565 for(; *data > 0; data++)
567 c = (int)(unsigned char)*data;
572 if(base64rev[c] == -1)
581 cur |= base64rev[c] >> -b;
586 cur |= base64rev[c] << b;
594 char *base32encode(char *data, size_t datalen)
597 size_t bufsize, bufdata;
602 bufsize = bufdata = 0;
605 addtobuf(buf, base32set[((data[0] & 0xf8) >> 3)]);
606 addtobuf(buf, base32set[((data[0] & 0x07) << 2) | ((data[1] & 0xc0) >> 6)]);
607 addtobuf(buf, base32set[((data[1] & 0x3e) >> 1)]);
608 addtobuf(buf, base32set[((data[1] & 0x01) << 4) | ((data[2] & 0xf0) >> 4)]);
609 addtobuf(buf, base32set[((data[2] & 0x0f) << 1) | ((data[3] & 0x80) >> 7)]);
610 addtobuf(buf, base32set[((data[3] & 0x7c) >> 2)]);
611 addtobuf(buf, base32set[((data[3] & 0x03) << 3) | ((data[4] & 0xe0) >> 5)]);
612 addtobuf(buf, base32set[data[4] & 0x1f]);
618 addtobuf(buf, base32set[((data[0] & 0xf8) >> 3)]);
619 addtobuf(buf, base32set[((data[0] & 0x07) << 2)]);
620 bufcat(buf, "======", 6);
624 addtobuf(buf, base32set[((data[0] & 0xf8) >> 3)]);
625 addtobuf(buf, base32set[((data[0] & 0x07) << 2) | ((data[1] & 0xc0) >> 6)]);
626 addtobuf(buf, base32set[((data[1] & 0x3e) >> 1)]);
627 addtobuf(buf, base32set[((data[1] & 0x01) << 4)]);
628 bufcat(buf, "====", 4);
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)]);
637 bufcat(buf, "===", 3);
641 addtobuf(buf, base32set[((data[0] & 0xf8) >> 3)]);
642 addtobuf(buf, base32set[((data[0] & 0x07) << 2) | ((data[1] & 0xc0) >> 6)]);
643 addtobuf(buf, base32set[((data[1] & 0x3e) >> 1)]);
644 addtobuf(buf, base32set[((data[1] & 0x01) << 4) | ((data[2] & 0xf0) >> 4)]);
645 addtobuf(buf, base32set[((data[2] & 0x0f) << 1) | ((data[3] & 0x80) >> 7)]);
646 addtobuf(buf, base32set[((data[3] & 0x7c) >> 2)]);
647 addtobuf(buf, base32set[((data[3] & 0x03) << 3)]);
654 char *base32decode(char *data, size_t *datalen)
658 size_t bufsize, bufdata;
661 bufsize = bufdata = 0;
664 for(; *data > 0; data++)
666 c = (int)(unsigned char)*data;
671 if(base32rev[c] == -1)
680 cur |= base32rev[c] >> -b;
685 cur |= base32rev[c] << b;
693 void _freeparr(void **arr)
699 for(buf = arr; *buf != NULL; buf++)
704 int _parrlen(void **arr)
710 for(i = 0; *arr != NULL; arr++)
715 char *getetcpath(char *binpath)
719 size_t etcpathsize, etcpathdata;
722 etcpathsize = etcpathdata = 0;
730 for(p = binpath; *p && (*p != ':'); p++);
731 for(; (p >= binpath) && (*p != '/'); p--);
735 addtobuf(etcpath, ':');
736 bufcat(etcpath, binpath, p - binpath + 1);
737 bufcat(etcpath, "etc", 3);
739 } while((binpath = strchr(binpath, ':')) != NULL);
740 addtobuf(etcpath, 0);
744 char *findfile(char *name, char *homedir, int filldef)
746 char *path, *binpath, *etcpath, *p;
753 mode = R_OK | (filldef ? W_OK : 0);
754 homeonly = homedir != NULL;
756 if(!strchr(name, '/'))
759 homedir = getenv("HOME");
760 if((homedir == NULL) && ((pw = getpwuid(getuid())) != NULL))
761 homedir = pw->pw_dir;
762 if((homedir != NULL) && ((path = sprintf2("%s/.%s", homedir, name)) != NULL))
764 if(!access(path, mode))
772 if(strchr(name, '/') != NULL)
774 if(!access(name, mode))
775 return(sstrdup(name));
777 if((binpath = getenv("PATH")) == NULL)
778 etcpath = sstrdup("/usr/local/etc:/etc:/usr/etc");
780 etcpath = getetcpath(binpath);
781 for(p = strtok(etcpath, ":"); p != NULL; p = strtok(NULL, ":"))
783 if((path = sprintf2("%s/%s", p, name)) != NULL)
785 if(!access(path, mode))
799 return(sprintf2("%s/.%s", homedir, name));
800 return(sprintf2("/etc/%s", name));
806 struct wcspair *newwcspair(wchar_t *key, wchar_t *val, struct wcspair **list)
808 struct wcspair *pair;
810 pair = smalloc(sizeof(*pair));
811 memset(pair, 0, sizeof(*pair));
813 pair->key = swcsdup(key);
815 pair->val = swcsdup(val);
826 void freewcspair(struct wcspair *pair, struct wcspair **list)
830 for(cur = *list; cur != NULL; list = &(cur->next), cur = cur->next)
843 wchar_t *wpfind(struct wcspair *list, wchar_t *key)
845 for(; list != NULL; list = list->next)
847 if(!wcscmp(list->key, key))