00001
00002 #include <ctype.h>
00003 #include <errno.h>
00004 #include <iconv.h>
00005 #include <limits.h>
00006 #include <malloc.h>
00007 #include <signal.h>
00008 #include <stdarg.h>
00009 #include <stdio.h>
00010 #include <stdlib.h>
00011 #include <string.h>
00012
00013 #include "define.h"
00014 #include "vbuf.h"
00015
00016 #ifdef WITH_DMALLOC
00017 #include <dmalloc.h>
00018 #endif
00019
00020 #define STUPID_CR "\r\n"
00021 #define ASSERT(x,...) { if( !(x) ) DIE(( __VA_ARGS__)); }
00022
00023
00024 int skip_nl(char *s)
00025 {
00026 if (s[0] == '\n')
00027 return 1;
00028 if (s[0] == '\r' && s[1] == '\n')
00029 return 2;
00030 if (s[0] == '\0')
00031 return 0;
00032 return -1;
00033 }
00034
00035
00036 int find_nl(vstr * vs)
00037 {
00038 char *nextr, *nextn;
00039
00040 nextr = memchr(vs->b, '\r', vs->dlen);
00041 nextn = memchr(vs->b, '\n', vs->dlen);
00042
00043
00044 if (nextn && (nextr == NULL || nextr > nextn)) {
00045 return nextn - vs->b;
00046 }
00047
00048 if (NULL != nextr && NULL != nextn && 1 == (char *) nextn - (char *) nextr) {
00049 return nextr - vs->b;
00050 }
00051
00052
00053 return -1;
00054 }
00055
00056
00057
00058
00059
00060 char *wwbuf = NULL;
00061 size_t nwwbuf = 0;
00062 static int unicode_up = 0;
00063 iconv_t i16to8, i8to16, i8859_1to8, i8toi8859_1;
00064
00065
00066 void unicode_init()
00067 {
00068 char *wipe = "";
00069 char dump[4];
00070
00071 if (unicode_up)
00072 unicode_close();
00073
00074 if ((iconv_t) - 1 == (i16to8 = iconv_open("UTF-8", "UTF-16"))) {
00075 fprintf(stderr, "doexport(): Couldn't open iconv descriptor for UTF-16 to UTF-8.\n");
00076 exit(1);
00077 }
00078
00079 if ((iconv_t) - 1 == (i8to16 = iconv_open("UTF-16", "UTF-8"))) {
00080 fprintf(stderr, "doexport(): Couldn't open iconv descriptor for UTF-8 to UTF-16.\n");
00081 exit(2);
00082 }
00083
00084 memset(dump, 'x', 4);
00085 ASSERT(0 == utf8to16(wipe, 1, dump, 4), "unicode_init(): attempt to dump FF FE failed.");
00086
00087 if ((iconv_t) - 1 == (i8859_1to8 = iconv_open("UTF-8", "ISO_8859-1"))) {
00088 fprintf(stderr, "doexport(): Couldn't open iconv descriptor for ASCII to UTF-8.\n");
00089 exit(1);
00090 }
00091
00092 if ((iconv_t) - 1 == (i8toi8859_1 = iconv_open("ISO_8859-1", "UTF-8"))) {
00093 fprintf(stderr, "doexport(): Couldn't open iconv descriptor for UTF-8 to ASCII.\n");
00094 exit(1);
00095 }
00096
00097 unicode_up = 1;
00098 }
00099
00100
00101 void unicode_close()
00102 {
00103 unicode_up = 0;
00104 iconv_close(i8to16);
00105 iconv_close(i16to8);
00106 iconv_close(i8859_1to8);
00107 iconv_close(i8toi8859_1);
00108 }
00109
00110
00111 int utf16_is_terminated(char *str, int length)
00112 {
00113 VSTR_STATIC(errbuf, 100);
00114 int len = -1;
00115 int i;
00116 for (i = 0; i < length; i += 2) {
00117 if (str[i] == 0 && str[i + 1] == 0) {
00118 len = i;
00119 }
00120 }
00121
00122 if (-1 == len) {
00123 vshexdump(errbuf, str, 0, length, 1);
00124 WARN(("String is not zero terminated (probably broken data from registry) %s.", errbuf->b));
00125 }
00126
00127 return (-1 == len) ? 0 : 1;
00128 }
00129
00130
00131 int vb_utf16to8(vbuf * dest, char *buf, int len)
00132 {
00133 size_t inbytesleft = len;
00134 char *inbuf = buf;
00135 size_t icresult = (size_t)-1;
00136 VBUF_STATIC(dumpster, 100);
00137
00138 size_t outbytesleft = 0;
00139 char *outbuf = NULL;
00140
00141 ASSERT(unicode_up, "vb_utf16to8() called before unicode started.");
00142
00143 if (2 > dest->blen)
00144 vbresize(dest, 2);
00145 dest->dlen = 0;
00146
00147
00148 if (!utf16_is_terminated(buf, len))
00149 return -1;
00150
00151 do {
00152 outbytesleft = dest->blen - dest->dlen;
00153 outbuf = dest->b + dest->dlen;
00154 icresult = iconv(i16to8, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
00155 dest->dlen = outbuf - dest->b;
00156 vbgrow(dest, inbytesleft);
00157 } while ((size_t)-1 == icresult && E2BIG == errno);
00158
00159 if (0 != vb_utf8to16T(dumpster, dest->b, dest->dlen))
00160 DIE(("Reverse conversion failed."));
00161
00162 if (icresult == (size_t)-1) {
00163
00164
00165 unicode_init();
00166 return -1;
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 }
00182
00183 if (icresult) {
00184
00185 return -1;
00186 }
00187 return icresult;
00188 }
00189
00190
00191 int utf8to16(char *inbuf_o, int iblen, char *outbuf_o, int oblen)
00192 {
00193
00194
00195 size_t inbytesleft = 0;
00196 size_t outbytesleft = oblen;
00197 char *inbuf = inbuf_o;
00198 char *outbuf = outbuf_o;
00199 size_t icresult = (size_t)-1;
00200 char *stend;
00201
00202 stend = memchr(inbuf_o, '\0', iblen);
00203 ASSERT(NULL != stend, "utf8to16(): in string not zero terminated.");
00204 inbytesleft = (stend - inbuf_o + 1 < iblen) ? stend - inbuf_o + 1 : iblen;
00205 icresult = iconv(i8to16, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
00206
00207 if (icresult == (size_t)-1) {
00208 DIE(("iconv failure(%d): %s\n", errno, strerror(errno)));
00209 }
00210 if (icresult > (size_t)INT_MAX) {
00211 return (-1);
00212 }
00213 return (int) icresult;
00214 }
00215
00216
00217 int vb_utf8to16T(vbuf * bout, char *cin, int inlen)
00218 {
00219
00220 size_t inbytesleft = inlen;
00221 char *inbuf = cin;
00222
00223 size_t icresult = (size_t)-1;
00224 size_t outbytesleft = 0;
00225 char *outbuf = NULL;
00226
00227 if (2 > bout->blen)
00228 vbresize(bout, 2);
00229 bout->dlen = 0;
00230
00231 do {
00232 outbytesleft = bout->blen - bout->dlen;
00233 outbuf = bout->b + bout->dlen;
00234 icresult = iconv(i8to16, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
00235 bout->dlen = outbuf - bout->b;
00236 vbgrow(bout, 20);
00237 } while ((size_t)-1 == icresult && E2BIG == errno);
00238
00239 if (icresult == (size_t)-1) {
00240 WARN(("iconv failure: %s", strerror(errno)));
00241 unicode_init();
00242 return -1;
00243 }
00244 if (icresult > (size_t) INT_MAX) {
00245 return (-1);
00246 }
00247 return icresult;
00248 }
00249
00250
00251
00252 void cheap_uni2ascii(char *src, char *dest, int l)
00253 {
00254
00255 for (; l > 0; l -= 2) {
00256 *dest = *src;
00257 dest++;
00258 src += 2;
00259 }
00260 *dest = 0;
00261 }
00262
00263
00264
00265 void cheap_ascii2uni(char *src, char *dest, int l)
00266 {
00267 for (; l > 0; l--) {
00268 *dest++ = *src++;
00269 *dest++ = 0;
00270
00271 }
00272 }
00273
00274
00275 vbuf *vballoc(size_t len)
00276 {
00277 struct varbuf *result = malloc(sizeof(struct varbuf));
00278 if (result) {
00279 result->dlen = 0;
00280 result->blen = 0;
00281 result->buf = NULL;
00282 vbresize(result, len);
00283 }
00284 else DIE(("malloc() failure"));
00285 return result;
00286 }
00287
00288
00289 void vbcheck(vbuf * vb)
00290 {
00291 ASSERT(vb->b >= vb->buf, "vbcheck(): data not inside buffer");
00292 ASSERT((size_t)(vb->b - vb->buf) <= vb->blen, "vbcheck(): vb->b outside of buffer range.");
00293 ASSERT(vb->dlen <= vb->blen, "vbcheck(): data length > buffer length.");
00294 ASSERT(vb->blen < 1024 * 1024, "vbcheck(): blen is a bit large...hmmm.");
00295 }
00296
00297
00298 void vbfree(vbuf * vb)
00299 {
00300 free(vb->buf);
00301 free(vb);
00302 }
00303
00304
00305 void vbclear(struct varbuf *vb)
00306 {
00307 vbresize(vb, 0);
00308 }
00309
00310
00311 void vbresize(struct varbuf *vb, size_t len)
00312 {
00313 vb->dlen = 0;
00314
00315 if (vb->blen >= len) {
00316 vb->b = vb->buf;
00317 return;
00318 }
00319
00320 vb->buf = realloc(vb->buf, len);
00321 vb->b = vb->buf;
00322 vb->blen = len;
00323 }
00324
00325
00326 size_t vbavail(vbuf * vb)
00327 {
00328 return vb->blen - vb->dlen - (size_t)(vb->b - vb->buf);
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 void vbgrow(struct varbuf *vb, size_t len)
00347 {
00348 if (0 == len)
00349 return;
00350
00351 if (0 == vb->blen) {
00352 vbresize(vb, len);
00353 return;
00354 }
00355
00356 if (vb->dlen + len > vb->blen) {
00357 if (vb->dlen + len < vb->blen * 1.5)
00358 len = vb->blen * 1.5;
00359 char *nb = malloc(vb->blen + len);
00360 if (!nb) DIE(("malloc() failure"));
00361 vb->blen = vb->blen + len;
00362 memcpy(nb, vb->b, vb->dlen);
00363
00364 free(vb->buf);
00365 vb->buf = nb;
00366 vb->b = vb->buf;
00367 } else {
00368 if (vb->b != vb->buf)
00369 memcpy(vb->buf, vb->b, vb->dlen);
00370 }
00371
00372 vb->b = vb->buf;
00373
00374 ASSERT(vbavail(vb) >= len, "vbgrow(): I have failed in my mission.");
00375 }
00376
00377
00378 void vbset(vbuf * vb, void *b, size_t len)
00379 {
00380 vbresize(vb, len);
00381
00382 memcpy(vb->b, b, len);
00383 vb->dlen = len;
00384 }
00385
00386
00387 void vsskipws(vstr * vs)
00388 {
00389 char *p = vs->b;
00390 while ((size_t)(p - vs->b) < vs->dlen && isspace(p[0]))
00391 p++;
00392
00393 vbskip((vbuf *) vs, p - vs->b);
00394 }
00395
00396
00397
00398 void vbappend(struct varbuf *vb, void *b, size_t len)
00399 {
00400 if (0 == vb->dlen) {
00401 vbset(vb, b, len);
00402 return;
00403 }
00404 vbgrow(vb, len);
00405 memcpy(vb->b + vb->dlen, b, len);
00406 vb->dlen += len;
00407 }
00408
00409
00410
00411 void vbskip(struct varbuf *vb, size_t skip)
00412 {
00413 ASSERT(skip <= vb->dlen, "vbskip(): Attempt to seek past end of buffer.");
00414 vb->b += skip;
00415 vb->dlen -= skip;
00416 }
00417
00418
00419
00420 void vboverwrite(struct varbuf *vbdest, struct varbuf *vbsrc)
00421 {
00422 vbresize(vbdest, vbsrc->blen);
00423 memcpy(vbdest->b, vbsrc->b, vbsrc->dlen);
00424 vbdest->blen = vbsrc->blen;
00425 vbdest->dlen = vbsrc->dlen;
00426 }
00427
00428
00429 vstr *vsalloc(size_t len)
00430 {
00431 vstr *result = (vstr *) vballoc(len + 1);
00432 vsset(result, "");
00433 return result;
00434 }
00435
00436
00437 char *vsstr(vstr * vs)
00438 {
00439 return vs->b;
00440 }
00441
00442
00443 size_t vslen(vstr * vs)
00444 {
00445 return strlen(vsstr(vs));
00446 }
00447
00448
00449 void vsfree(vstr * vs)
00450 {
00451 vbfree((vbuf *) vs);
00452 }
00453
00454
00455 void vscharcat(vstr * vb, int ch)
00456 {
00457 vbgrow((vbuf *) vb, 1);
00458 vb->b[vb->dlen - 1] = ch;
00459 vb->b[vb->dlen] = '\0';
00460 vb->dlen++;
00461 }
00462
00463
00464
00465 void vsnprepend(vstr * vb, char *str, size_t len)
00466 {
00467 ASSERT(vb->b[vb->dlen - 1] == '\0', "vsncat(): attempt to append string to non-string.");
00468 size_t sl = strlen(str);
00469 size_t n = (sl < len) ? sl : len;
00470 vbgrow((vbuf *) vb, n + 1);
00471 memmove(vb->b + n, vb->b, vb->dlen - 1);
00472 memcpy(vb->b, str, n);
00473 vb->dlen += n;
00474 vb->b[vb->dlen - 1] = '\0';
00475 }
00476
00477
00478
00479 void vsskip(vstr * vs, size_t len)
00480 {
00481 ASSERT(len < vs->dlen - 1, "Attempt to skip past end of string");
00482 vbskip((vbuf *) vs, len);
00483 }
00484
00485
00486
00487 int vsskipline(vstr * vs)
00488 {
00489 int nloff = find_nl(vs);
00490 int nll = skip_nl(vs->b + nloff);
00491
00492 if (nloff < 0) {
00493
00494 printf("vb_skipline(): there seems to be no newline here.\n");
00495 return -1;
00496 }
00497 if (nll < 0) {
00498
00499 printf("vb_skipline(): there seems to be no newline here...except there should be. :P\n");
00500 return -1;
00501 }
00502
00503 memmove(vs->b, vs->b + nloff + nll, vs->dlen - nloff - nll);
00504
00505 vs->dlen -= nloff + nll;
00506
00507 return 0;
00508 }
00509
00510
00511 int vscatprintf(vstr * vs, char *fmt, ...)
00512 {
00513 int size;
00514 va_list ap;
00515
00516
00517
00518 if (!vs->b || vs->dlen == 0) {
00519 vsset(vs, "");
00520 }
00521
00522 while (1) {
00523
00524 va_start(ap, fmt);
00525 size = vsnprintf(vs->b + vs->dlen - 1, vs->blen - vs->dlen, fmt, ap);
00526 va_end(ap);
00527
00528
00529 if ((size > -1) && ((size_t)size < vs->blen - vs->dlen)) {
00530 vs->dlen += size;
00531 return size;
00532 }
00533
00534 if (size >= 0)
00535 vbgrow((vbuf *) vs, size + 1);
00536 else
00537 vbgrow((vbuf *) vs, vs->blen);
00538 }
00539 }
00540
00541
00542
00543 int vslast(vstr * vs)
00544 {
00545 if (vs->dlen < 1)
00546 return -1;
00547 if (vs->b[vs->dlen - 1] != '\0')
00548 return -1;
00549 if (vs->dlen == 1)
00550 return '\0';
00551 return vs->b[vs->dlen - 2];
00552 }
00553
00554
00555
00556 void vs_printf(vstr * vs, char *fmt, ...)
00557 {
00558 int size;
00559 va_list ap;
00560
00561
00562 vbresize((vbuf *) vs, 100);
00563
00564 while (1) {
00565
00566 va_start(ap, fmt);
00567 size = vsnprintf(vs->b, vs->blen, fmt, ap);
00568 va_end(ap);
00569
00570
00571 if ((size > -1) && ((size_t)size < vs->blen)) {
00572 vs->dlen = size + 1;
00573 return;
00574 }
00575
00576 if (size >= 0)
00577 vbresize((vbuf *) vs, size + 1);
00578 else
00579 vbresize((vbuf *) vs, vs->blen * 2);
00580 }
00581 }
00582
00583
00584
00585 void vs_printfa(vstr * vs, char *fmt, ...)
00586 {
00587 int size;
00588 va_list ap;
00589
00590 if (vs->blen - vs->dlen < 50)
00591 vbgrow((vbuf *) vs, 100);
00592
00593 while (1) {
00594
00595 va_start(ap, fmt);
00596 size = vsnprintf(vs->b + vs->dlen - 1, vs->blen - vs->dlen + 1, fmt, ap);
00597 va_end(ap);
00598
00599
00600 if ((size > -1) && ((size_t)size < vs->blen)) {
00601 vs->dlen += size;
00602 return;
00603 }
00604
00605 if (size >= 0)
00606 vbgrow((vbuf *) vs, size + 1 - vs->dlen);
00607 else
00608 vbgrow((vbuf *) vs, size);
00609 }
00610 }
00611
00612
00613 void vshexdump(vstr * vs, char *b, size_t start, size_t stop, int ascii)
00614 {
00615 char c;
00616 int diff, i;
00617
00618 while (start < stop) {
00619 diff = stop - start;
00620 if (diff > 16)
00621 diff = 16;
00622
00623 vs_printfa(vs, ":%08X ", start);
00624
00625 for (i = 0; i < diff; i++) {
00626 if (8 == i)
00627 vs_printfa(vs, " ");
00628 vs_printfa(vs, "%02X ", (unsigned char) *(b + start + i));
00629 }
00630 if (ascii) {
00631 for (i = diff; i < 16; i++)
00632 vs_printfa(vs, " ");
00633 for (i = 0; i < diff; i++) {
00634 c = *(b + start + i);
00635 vs_printfa(vs, "%c", isprint(c) ? c : '.');
00636 }
00637 }
00638 vs_printfa(vs, "\n");
00639 start += 16;
00640 }
00641 }
00642
00643
00644 void vsset(vstr * vs, char *s)
00645 {
00646 vsnset(vs, s, strlen(s));
00647 }
00648
00649
00650 void vsnset(vstr * vs, char *s, size_t n)
00651 {
00652 vbresize((vbuf *) vs, n + 1);
00653 memcpy(vs->b, s, n);
00654 vs->b[n] = '\0';
00655 vs->dlen = n + 1;
00656 }
00657
00658
00659 void vsgrow(vstr * vs, size_t len)
00660 {
00661 vbgrow((vbuf *) vs, len);
00662 }
00663
00664
00665 size_t vsavail(vstr * vs)
00666 {
00667 return vbavail((vbuf *) vs);
00668 }
00669
00670
00671 void vsnset16(vstr * vs, char *s, size_t len)
00672 {
00673 vbresize((vbuf *) vs, len + 1);
00674 memcpy(vs->b, s, len);
00675
00676 vs->b[len] = '\0';
00677 vs->dlen = len + 1;
00678 vs->b[len] = '\0';
00679 }
00680
00681
00682 void vscat(vstr * vs, char *str)
00683 {
00684 vsncat(vs, str, strlen(str));
00685 }
00686
00687
00688 int vscmp(vstr * vs, char *str)
00689 {
00690 return strcmp(vs->b, str);
00691 }
00692
00693
00694 void vsncat(vstr * vs, char *str, size_t len)
00695 {
00696 ASSERT(vs->b[vs->dlen - 1] == '\0', "vsncat(): attempt to append string to non-string.");
00697 size_t sl = strlen(str);
00698 size_t n = (sl < len) ? sl : len;
00699
00700 vbgrow((vbuf *) vs, n + 1);
00701 memcpy(vs->b + vs->dlen - 1, str, n);
00702 vs->dlen += n;
00703 vs->b[vs->dlen - 1] = '\0';
00704 }
00705
00706
00707 void vstrunc(vstr * v, size_t off)
00708 {
00709 if (off >= v->dlen - 1)
00710 return;
00711 v->b[off] = '\0';
00712 v->dlen = off + 1;
00713 }
00714
00715