00001
00002
00003
00004
00005
00006
00007
00008 #include "strutils.h"
00009 #include "wvbuf.h"
00010 #include <ctype.h>
00011 #include <stdio.h>
00012 #include <string.h>
00013 #include <time.h>
00014
00015 #ifndef _WIN32
00016 #include <errno.h>
00017 #include <netdb.h>
00018 #include <unistd.h>
00019 #else
00020 #undef errno
00021 #define errno GetLastError()
00022 #define strcasecmp _stricmp
00023 #include <winsock2.h>
00024 #endif
00025
00026 char *terminate_string(char *string, char c)
00027
00028
00029
00030
00031 {
00032 char *p;
00033
00034 if (string == NULL)
00035 return NULL;
00036
00037 p = string + strlen(string) - 1;
00038 while (*p == '\r' || *p == '\n')
00039 p--;
00040
00041 *(++p) = c;
00042 *(++p) = 0;
00043
00044 return string;
00045 }
00046
00047
00048 char *trim_string(char *string)
00049
00050
00051
00052 {
00053 char *p;
00054 char *q;
00055
00056 if (string == NULL)
00057 return NULL;
00058
00059 p = string;
00060 q = string + strlen(string) - 1;
00061
00062 while (q >= p && isspace(*q))
00063 *(q--) = 0;
00064 while (isspace(*p))
00065 p++;
00066
00067 return p;
00068 }
00069
00070
00071 char *trim_string(char *string, char c)
00072
00073
00074 {
00075 char *p;
00076
00077 if (string == NULL)
00078 return NULL;
00079
00080 p = string;
00081
00082 while (*p != 0 && *p != c)
00083 p++;
00084
00085 while (*p)
00086 *(p++) = 0;
00087
00088 return string;
00089 }
00090
00091
00092
00093 char *non_breaking(char * string)
00094 {
00095 if (string == NULL)
00096 return (NULL);
00097
00098 WvDynBuf buf;
00099
00100 while (*string)
00101 {
00102 if (isspace(*string))
00103 buf.putstr(" ");
00104 else
00105 buf.putch(*string);
00106 string++;
00107 }
00108
00109 WvString s(buf.getstr());
00110 return s.edit();
00111 }
00112
00113
00114
00115
00116 void replace_char(void *_string, char c1, char c2, int length)
00117 {
00118 char *string = (char *)_string;
00119 for (int i=0; i < length; i++)
00120 if (*(string+i) == c1)
00121 *(string+i) = c2;
00122 }
00123
00124
00125 char *snip_string(char *haystack, char *needle)
00126 {
00127 if(!haystack)
00128 return NULL;
00129 if(!needle)
00130 return haystack;
00131 char *p = strstr(haystack, needle);
00132 if(!p || p != haystack)
00133 return haystack;
00134 else
00135 return haystack + strlen(needle);
00136 }
00137
00138 #ifndef _WIN32
00139 char *strlwr(char *string)
00140 {
00141 char *p = string;
00142 while (*p)
00143 {
00144 *p = tolower(*p);
00145 p++;
00146 }
00147
00148 return string;
00149 }
00150
00151
00152 char *strupr(char *string)
00153 {
00154 char *p = string;
00155 while (*p)
00156 {
00157 *p = toupper(*p);
00158 p++;
00159 }
00160
00161 return string;
00162 }
00163 #endif
00164
00165
00166 bool is_word(const char *p)
00167 {
00168 while (*p)
00169 {
00170 if(!isalnum(*p++))
00171 return false;
00172 }
00173
00174 return true;
00175 }
00176
00177
00178
00179
00180
00181 WvString hexdump_buffer(const void *_buf, size_t len, bool charRep)
00182 {
00183 const unsigned char *buf = (const unsigned char *)_buf;
00184 size_t count, count2, top;
00185 WvString out;
00186
00187 out.setsize(len / 16 * 80 + 80);
00188 char *cptr = out.edit();
00189
00190 for (count = 0; count < len; count+=16)
00191 {
00192 top = len-count < 16 ? len-count : 16;
00193 cptr += sprintf(cptr, "[%03X] ", (unsigned int)count);
00194
00195
00196 for (count2 = 0; count2 < top; count2++)
00197 {
00198 if (count2 && !(count2 % 4))
00199 *cptr++ = ' ';
00200 cptr += sprintf(cptr, "%02X", buf[count+count2]);
00201 }
00202
00203
00204 for (count2 = top; count2 < 16; count2++)
00205 {
00206 if (count2 && !(count2 % 4))
00207 {
00208 strcat(cptr, " ");
00209 cptr += 3;
00210 }
00211 else
00212 {
00213 strcat(cptr, " ");
00214 cptr += 2;
00215 }
00216 }
00217
00218 *cptr++ = ' ';
00219
00220
00221 if (charRep)
00222 for (count2 = 0; count2 < top; count2++)
00223 *cptr++ = (isprint(buf[count+count2])
00224 ? buf[count+count2] : '.');
00225
00226 *cptr++ = '\n';
00227 }
00228 *cptr = 0;
00229 return out;
00230 }
00231
00232
00233
00234 bool isnewline(char c)
00235 {
00236 return c=='\n' || c=='\r';
00237 }
00238
00239
00240 WvString web_unescape(const char *str)
00241 {
00242 const char *iptr;
00243 char *optr;
00244 char *idx1, *idx2;
00245 static const char hex[] = "0123456789ABCDEF";
00246 WvString in, intmp(str), out;
00247
00248 in = trim_string(intmp.edit());
00249 out.setsize(strlen(in) + 1);
00250
00251 optr = out.edit();
00252 for (iptr = in, optr = out.edit(); *iptr; iptr++)
00253 {
00254 if (*iptr == '+')
00255 *optr++ = ' ';
00256 else if (*iptr == '%' && iptr[1] && iptr[2])
00257 {
00258 idx1 = strchr(hex, toupper((unsigned char) iptr[1]));
00259 idx2 = strchr(hex, toupper((unsigned char) iptr[2]));
00260
00261 if (idx1 && idx2)
00262 *optr++ = ((idx1 - hex) << 4) | (idx2 - hex);
00263
00264 iptr += 2;
00265 }
00266 else
00267 *optr++ = *iptr;
00268 }
00269
00270 *optr = 0;
00271
00272 return out;
00273 }
00274
00275
00276
00277 WvString url_encode(WvStringParm stuff)
00278 {
00279 unsigned int i;
00280 WvDynBuf retval;
00281
00282 for (i=0; i < stuff.len(); i++)
00283 {
00284 if (isalnum(stuff[i]) || strchr("/_.-~", stuff[i]))
00285 {
00286 retval.put(&stuff[i], 1);
00287 }
00288 else
00289 {
00290 char buf[3];
00291 sprintf(buf, "%%%02x", stuff[i] & 0xff);
00292 retval.put(&buf, 3);
00293 }
00294 }
00295 return retval.getstr();
00296 }
00297
00298
00299 WvString rfc822_date(time_t when)
00300 {
00301 WvString out;
00302 out.setsize(80);
00303
00304 if (when < 0)
00305 when = time(NULL);
00306
00307 struct tm *tmwhen = localtime(&when);
00308 strftime(out.edit(), 80, "%a, %d %b %Y %H:%M:%S %z", tmwhen);
00309
00310 return out;
00311 }
00312
00313
00314 WvString backslash_escape(WvStringParm s1)
00315 {
00316
00317 if (!s1)
00318 return "";
00319
00320 WvString s2;
00321 s2.setsize(s1.len() * 2 + 1);
00322
00323 const char *p1 = s1;
00324 char *p2 = s2.edit();
00325 while (*p1)
00326 {
00327 if (!isalnum(*p1))
00328 *p2++ = '\\';
00329 *p2++ = *p1++;
00330 }
00331 *p2 = 0;
00332
00333 return s2;
00334 }
00335
00336
00337 int strcount(WvStringParm s, const char c)
00338 {
00339 int n=0;
00340 const char *p = s;
00341 while ((p=strchr(p, c)) != NULL && p++)
00342 n++;
00343
00344 return n;
00345 }
00346
00347
00348 WvString encode_hostname_as_DN(WvStringParm hostname)
00349 {
00350 WvString dn("");
00351
00352 WvStringList fqdnlist;
00353 WvStringList::Iter i(fqdnlist);
00354
00355 fqdnlist.split(hostname, ".");
00356 for (i.rewind(); i.next(); )
00357 dn.append("dc=%s,", *i);
00358 dn.append("cn=%s", hostname);
00359
00360 return dn;
00361 }
00362
00363
00364 WvString nice_hostname(WvStringParm name)
00365 {
00366 WvString nice;
00367 char *optr, *optr_start;
00368 const char *iptr;
00369 bool last_was_dash;
00370
00371 nice.setsize(name.len() + 2);
00372
00373 iptr = name;
00374 optr = optr_start = nice.edit();
00375 if (!isascii(*iptr) || !isalnum(*(const unsigned char *)iptr))
00376 *optr++ = 'x';
00377
00378 last_was_dash = false;
00379 for (; *iptr; iptr++)
00380 {
00381 if (!isascii(*iptr))
00382 continue;
00383
00384 if (*iptr == '-' || *iptr == '_')
00385 {
00386 if (last_was_dash)
00387 continue;
00388 last_was_dash = true;
00389 *optr++ = '-';
00390 }
00391 else if (isalnum(*(const unsigned char *)iptr) || *iptr == '.')
00392 {
00393 *optr++ = *iptr;
00394 last_was_dash = false;
00395 }
00396 }
00397
00398 if (optr > optr_start && !isalnum(*(const unsigned char *)(optr-1)))
00399 *optr++ = 'x';
00400
00401 *optr++ = 0;
00402
00403 if (!nice.len())
00404 return "UNKNOWN";
00405
00406 return nice;
00407 }
00408
00409
00410 WvString getfilename(WvStringParm fullname)
00411 {
00412 WvString tmp(fullname);
00413 char *cptr = strrchr(tmp.edit(), '/');
00414
00415 if (!cptr)
00416 return fullname;
00417 else if (!cptr[1])
00418 {
00419 *cptr = 0;
00420 return getfilename(tmp);
00421 }
00422 else
00423 return cptr+1;
00424 }
00425
00426
00427 WvString getdirname(WvStringParm fullname)
00428 {
00429 WvString tmp(fullname);
00430 char *cptr = strrchr(tmp.edit(), '/');
00431
00432 if (!cptr)
00433 return ".";
00434 else if (!cptr[1])
00435 {
00436 *cptr = 0;
00437 return getdirname(tmp);
00438 }
00439 else
00440 {
00441 *cptr = 0;
00442 return !tmp ? WvString("/") : tmp;
00443 }
00444 }
00445
00446
00447 WvString sizetoa(long long blocks, int blocksize)
00448 {
00449 long long kbytes = blocks * (long long) blocksize / 1000;
00450
00451 if (kbytes >= 1000*1000*1000)
00452 return WvString("%s.%s TB",
00453 (unsigned long) (kbytes/(1000*1000*1000)),
00454 (unsigned long) (kbytes%(1000*1000*1000))/(100*1000*1000));
00455 else if (kbytes >= 1000*1000)
00456 return WvString("%s.%s GB",
00457 (unsigned long) (kbytes/(1000*1000)),
00458 (unsigned long) (kbytes % (1000*1000))/(100*1000));
00459 else if (kbytes >= 1000)
00460 return WvString("%s.%s MB",
00461 (unsigned long) (kbytes/(1000)),
00462 (unsigned long) (kbytes % (1000))/(100));
00463 else if (kbytes)
00464 return WvString("%s.%s KB",
00465 (unsigned long) (blocks*blocksize / 1000),
00466 (unsigned long) ((blocks*blocksize) % 1000)/(100));
00467 else
00468 return WvString("%s bytes", blocks*blocksize);
00469 }
00470
00471
00472 WvString strreplace(WvStringParm s, WvStringParm a, WvStringParm b)
00473 {
00474 WvDynBuf buf;
00475 const char *sptr = s, *eptr;
00476
00477 while ((eptr = strstr(sptr, a)) != NULL)
00478 {
00479 buf.put(sptr, eptr-sptr);
00480 buf.putstr(b);
00481 sptr = eptr + strlen(a);
00482 }
00483
00484 buf.put(sptr, strlen(sptr));
00485
00486 return buf.getstr();
00487 }
00488
00489 WvString undupe(WvStringParm s, char c)
00490 {
00491 WvDynBuf out;
00492
00493 bool last = false;
00494
00495 for (int i = 0; s[i] != '\0'; i++)
00496 {
00497 if (s[i] != c)
00498 {
00499 out.putch(s[i]);
00500 last = false;
00501 }
00502 else if (!last)
00503 {
00504 out.putch(c);
00505 last = true;
00506 }
00507 }
00508
00509 return out.getstr();
00510 }
00511
00512
00513 WvString rfc1123_date(time_t t)
00514 {
00515 struct tm *tm = gmtime(&t);
00516 WvString s;
00517
00518 s.setsize(128);
00519 strftime(s.edit(), 128, "%a, %d %b %Y %H:%M:%S GMT", tm);
00520
00521 return s;
00522 }
00523
00524
00525 int lookup(const char *str, const char * const *table, bool case_sensitive)
00526 {
00527 for (int i = 0; table[i]; ++i)
00528 {
00529 if (case_sensitive)
00530 {
00531 if (strcmp(str, table[i]) != 0)
00532 continue;
00533 }
00534 else
00535 {
00536 if (strcasecmp(str, table[i]) != 0)
00537 continue;
00538 }
00539 return i;
00540 }
00541 return -1;
00542 }
00543
00544
00545 WvString hostname()
00546 {
00547 int maxlen = 0;
00548 for(;;)
00549 {
00550 maxlen += 80;
00551 char *name = new char[maxlen];
00552 int result = gethostname(name, maxlen);
00553 if (result == 0)
00554 {
00555 WvString hostname(name);
00556 delete [] name;
00557 return hostname;
00558 }
00559 #ifdef _WIN32
00560 assert(errno == WSAEFAULT);
00561 #else
00562 assert(errno == EINVAL);
00563 #endif
00564 }
00565 }
00566
00567
00568 WvString fqdomainname()
00569 {
00570 struct hostent *myhost;
00571
00572 myhost = gethostbyname(hostname());
00573 if (myhost)
00574 return myhost->h_name;
00575 else
00576 return WvString::null;
00577 }
00578
00579
00580 WvString metriculate(const off_t i)
00581 {
00582 WvString res;
00583 int digits=0;
00584 int digit=0;
00585 long long int j=i;
00586 char *p;
00587
00588 while (j)
00589 {
00590 digits++;
00591 j/=10;
00592 }
00593
00594 j=i;
00595 res.setsize(digits + (digits-1)/3 + 1);
00596 p=res.edit()+digits+((digits-1)/3);
00597 *p-- = '\0';
00598
00599 for (digit=0; digit<digits; digit++)
00600 {
00601 *p-- = '0' + ( j%10 );
00602 if (((digit+1) % 3) == 0)
00603 *p-- = ' ';
00604 j /= 10;
00605 }
00606
00607 return res;
00608 }