Annotation of libwww/Library/src/HTString.c, revision 2.12.2.1
2.10 frystyk 1: /* HTString.c
2: ** DYNAMIC STRING UTILITIES
3: **
4: ** (c) COPYRIGHT CERN 1994.
5: ** Please first read the full copyright statement in the file COPYRIGH.
1.1 timbl 6: **
7: ** Original version came with listserv implementation.
8: ** Version TBL Oct 91 replaces one which modified the strings.
9: ** 02-Dec-91 (JFG) Added stralloccopy and stralloccat
10: ** 23 Jan 92 (TBL) Changed strallocc* to 8 char HTSAC* for VM and suchlike
11: ** 6 Oct 92 (TBL) Moved WWW_TraceFlag in here to be in library
12: */
2.8 frystyk 13:
2.12 frystyk 14: /* Library include files */
15: #include "tcp.h"
1.1 timbl 16: #include "HTUtils.h"
2.12.2.1! frystyk 17: #include "HTTCP.h"
2.8 frystyk 18: #include "HTString.h" /* Implemented here */
1.1 timbl 19:
2.12 frystyk 20: #ifdef NO_STDIO
21: PUBLIC FILE *WWWTrace = NULL;
22: #endif
23:
1.1 timbl 24: PUBLIC int WWW_TraceFlag = 0; /* Global trace flag for ALL W3 code */
25:
26: #ifndef VC
27: #define VC "unknown"
28: #endif
29:
30: PUBLIC CONST char * HTLibraryVersion = VC; /* String for help screen etc */
31:
2.12.2.1! frystyk 32: PRIVATE long HTTimeZone = 0L; /* Offset from GMT in seconds */
! 33:
! 34: /* ------------------------------------------------------------------------- */
! 35:
2.12 frystyk 36: #ifndef VM /* VM has these already it seems */
1.1 timbl 37:
38: /* Strings of any length
39: ** ---------------------
40: */
41: PUBLIC int strcasecomp ARGS2 (CONST char*,a, CONST char *,b)
42: {
2.12.2.1! frystyk 43: int diff;
! 44: for( ; *a && *b; a++, b++) {
! 45: if ((diff = TOLOWER(*a) - TOLOWER(*b)))
! 46: return diff;
! 47: }
! 48: if (*a) return 1; /* a was longer than b */
! 49: if (*b) return -1; /* a was shorter than b */
! 50: return 0; /* Exact match */
1.1 timbl 51: }
52:
53:
54: /* With count limit
55: ** ----------------
56: */
57: PUBLIC int strncasecomp ARGS3(CONST char*,a, CONST char *,b, int,n)
58: {
59: CONST char *p =a;
60: CONST char *q =b;
61:
62: for(p=a, q=b;; p++, q++) {
63: int diff;
64: if (p == a+n) return 0; /* Match up to n characters */
65: if (!(*p && *q)) return *p - *q;
66: diff = TOLOWER(*p) - TOLOWER(*q);
67: if (diff) return diff;
68: }
69: /*NOTREACHED*/
70: }
71: #endif
72:
2.7 luotonen 73:
74: /*
75: * strcasestr(s1,s2) -- like strstr(s1,s2) but case-insensitive.
76: */
77: PUBLIC char * strcasestr ARGS2(char *, s1,
78: char *, s2)
79: {
2.9 frystyk 80: char * ptr = s1;
2.7 luotonen 81:
82: if (!s1 || !s2 || !*s2) return s1;
83:
2.9 frystyk 84: while (*ptr) {
85: if (TOUPPER(*ptr) == TOUPPER(*s2)) {
86: char * cur1 = ptr + 1;
2.7 luotonen 87: char * cur2 = s2 + 1;
88: while (*cur1 && *cur2 && TOUPPER(*cur1) == TOUPPER(*cur2)) {
89: cur1++;
90: cur2++;
91: }
92: if (!*cur2) {
2.12.2.1! frystyk 93: if (TRACE)
2.12 frystyk 94: fprintf(TDEST, "Debug....... strcasestr(s1 = \"%s\", s2 = \"%s\") => \"%s\"\n",
95: s1,s2,ptr);
2.9 frystyk 96: return ptr;
2.7 luotonen 97: }
98: }
2.9 frystyk 99: ptr++;
2.7 luotonen 100: }
2.12 frystyk 101: if (TRACE)
102: fprintf(TDEST,
103: "Debug....... strcasestr(s1=\"%s\", s2=\"%s\") => No match\n",
104: s1,s2);
2.7 luotonen 105: return NULL;
106: }
107:
108:
109:
1.1 timbl 110: /* Allocate a new copy of a string, and returns it
111: */
112: PUBLIC char * HTSACopy
113: ARGS2 (char **,dest, CONST char *,src)
114: {
115: if (*dest) free(*dest);
116: if (! src)
117: *dest = NULL;
118: else {
119: *dest = (char *) malloc (strlen(src) + 1);
120: if (*dest == NULL) outofmem(__FILE__, "HTSACopy");
121: strcpy (*dest, src);
122: }
123: return *dest;
124: }
125:
2.6 timbl 126: /* String Allocate and Concatenate
127: */
1.1 timbl 128: PUBLIC char * HTSACat
129: ARGS2 (char **,dest, CONST char *,src)
130: {
131: if (src && *src) {
132: if (*dest) {
133: int length = strlen (*dest);
134: *dest = (char *) realloc (*dest, length + strlen(src) + 1);
135: if (*dest == NULL) outofmem(__FILE__, "HTSACat");
136: strcpy (*dest + length, src);
137: } else {
138: *dest = (char *) malloc (strlen(src) + 1);
139: if (*dest == NULL) outofmem(__FILE__, "HTSACat");
140: strcpy (*dest, src);
141: }
142: }
143: return *dest;
2.6 timbl 144: }
145:
146:
147: /* Find next Field
148: ** ---------------
149: **
150: ** On entry,
2.12.2.1! frystyk 151: ** *pstr points to a string containing a word separated
! 152: ** by white white space "," ";" or "=". The word
! 153: ** can optionally be quoted using <"> or "<" ">"
! 154: ** Comments surrrounded by '(' ')' are filtered out
2.6 timbl 155: **
156: ** On exit,
157: ** *pstr has been moved to the first delimiter past the
158: ** field
159: ** THE STRING HAS BEEN MUTILATED by a 0 terminator
160: **
2.12.2.1! frystyk 161: ** Returns a pointer to the first word or NULL on error
2.6 timbl 162: */
163: PUBLIC char * HTNextField ARGS1(char **, pstr)
164: {
165: char * p = *pstr;
2.12.2.1! frystyk 166: char * start;
! 167:
! 168: while (1) {
! 169: /* Strip white space and other delimiters */
! 170: while (*p && (WHITE(*p) || *p==',' || *p==';' || *p=='=')) p++;
! 171: if (!*p) {
! 172: *pstr = p;
! 173: return NULL; /* No field */
! 174: }
! 175:
! 176: if (*p == '"') { /* quoted field */
! 177: start = ++p;
! 178: for(;*p && *p!='"'; p++)
! 179: if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */
! 180: } else if (*p == '<') { /* quoted field */
! 181: for(;*p && *p!='>'; p++)
! 182: if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */
! 183: } else if (*p == '(') { /* Comment */
! 184: for(;*p && *p!=')'; p++)
! 185: if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */
! 186: p++;
! 187: } else { /* Spool field */
! 188: start = p;
! 189: while(*p && !WHITE(*p) && *p!=',' && *p!=';' && *p!='=')
! 190: p++;
! 191: break; /* Got it */
2.6 timbl 192: }
193: }
2.12.2.1! frystyk 194: if (*p) *p++ = '\0';
2.6 timbl 195: *pstr = p;
196: return start;
2.12.2.1! frystyk 197: }
! 198:
! 199:
! 200: /*
! 201: ** Returns a string pointer to a static area of the current calendar
! 202: ** time in RFC 1123 format, for example
! 203: **
! 204: ** Sun, 06 Nov 1994 08:49:37 GMT
! 205: **
! 206: ** The result can be given in both local and GMT dependent on the flag
! 207: */
! 208: PUBLIC CONST char *HTDateTimeStr ARGS2(time_t *, calendar, BOOL, local)
! 209: {
! 210: static char buf[40];
! 211:
! 212: #ifndef NO_STRFTIME
! 213: if (local) {
! 214: #ifdef SOLARIS /* Thomas Maslen <tmaslen@verity.com> */
! 215: struct tm loctime;
! 216: localtime_r(calendar, &loctime);
! 217: strftime(buf, 40, "%a, %d %b %Y %H:%M:%S", &loctime);
! 218: #else
! 219: struct tm *loctime = localtime(calendar);
! 220: strftime(buf, 40, "%a, %d %b %Y %H:%M:%S", loctime);
! 221: #endif /* SOLARIS */
! 222: } else {
! 223: #ifdef SOLARIS
! 224: struct tm gmt;
! 225: gmtime_r(calendar, &gmt);
! 226: strftime(buf, 40, "%a, %d %b %Y %H:%M:%S GMT", &gmt);
! 227: #else
! 228: struct tm *gmt = gmtime(calendar);
! 229: strftime(buf, 40, "%a, %d %b %Y %H:%M:%S GMT", gmt);
! 230: #endif /* SOLARIS */
! 231: }
! 232: #else
! 233: if (local) {
! 234: struct tm *loctime = localtime(calendar);
! 235: sprintf(buf,"%s, %02d %s 19%02d %02d:%02d:%02d",
! 236: wkday[gmt->tm_wday],
! 237: gmt->tm_mday,
! 238: month[gmt->tm_mon],
! 239: gmt->tm_year % 100,
! 240: gmt->tm_hour,
! 241: gmt->tm_min,
! 242: gmt->tm_sec);
! 243: } else {
! 244: struct tm *gmt = gmtime(calendar);
! 245: sprintf(buf,"%s, %02d %s 19%02d %02d:%02d:%02d GMT",
! 246: wkday[gmt->tm_wday],
! 247: gmt->tm_mday,
! 248: month[gmt->tm_mon],
! 249: gmt->tm_year % 100,
! 250: gmt->tm_hour,
! 251: gmt->tm_min,
! 252: gmt->tm_sec);
! 253: }
! 254: #endif
! 255: return buf;
! 256: }
! 257:
! 258:
! 259: /*
! 260: ** Returns a Message-ID string including the open '<' and the closing '>'.
! 261: ** The format of the string is:
! 262: **
! 263: ** "<" time-in-sec "Z" process-id "@" FQDN ">"
! 264: **
! 265: ** or on systems that doesn't have process-id:
! 266: **
! 267: ** "<" time-in-sec "Z" user "@" FQDN ">"
! 268: **
! 269: ** Returns a pointer to the MessageID
! 270: */
! 271: PUBLIC CONST char *HTMessageIdStr NOARGS
! 272: {
! 273: static char buf[80];
! 274: time_t sectime = time(NULL);
! 275: #ifndef NO_GETPID
! 276: CONST char *address = HTGetDomainName();
! 277: #else
! 278: CONST char *address = HTGetMailAddress();
! 279: #endif /* NO_GETPID */
! 280: if (!address) address = tmpnam(NULL);
! 281: if ((!address || !*address) && sectime < 0) {
! 282: if (TRACE)
! 283: fprintf(TDEST, "MessageID... Can't make a unique MessageID\n");
! 284: return "";
! 285: }
! 286: #ifndef NO_GETPID
! 287: sprintf(buf, "<%ldZ%d@%s>", sectime, getpid(), address ? address : "@@@");
! 288: #else
! 289: sprintf(buf, "<%ldZ%s>", sectime, address ? address : "@@@");
! 290: #endif /* NO_GETPID */
! 291:
! 292: *(buf+79) = '\0';
! 293: return buf;
! 294: }
! 295:
! 296:
! 297: /* Date and Time Parser
! 298: ** --------------------
! 299: ** These functions are taken from the server written by Ari Luotonen
! 300: */
! 301:
! 302: PRIVATE char * month_names[12] =
! 303: {
! 304: "Jan", "Feb", "Mar", "Apr", "May", "Jun",
! 305: "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
! 306: };
! 307:
! 308: PRIVATE int make_num ARGS1(CONST char *, s)
! 309: {
! 310: if (*s >= '0' && *s <= '9')
! 311: return 10 * (*s - '0') + *(s+1) - '0';
! 312: else
! 313: return *(s+1) - '0';
! 314: }
! 315:
! 316: PRIVATE int make_month ARGS1(CONST char *, s)
! 317: {
! 318: int i;
! 319: for (i=0; i<12; i++)
! 320: if (!strncasecomp(month_names[i], s, 3))
! 321: return i;
! 322: return 0;
! 323: }
! 324:
! 325: /* Timezone Offset
! 326: ** ---------------
! 327: ** Calculates the offset from GMT in seconds
! 328: */
! 329: PUBLIC long HTGetTimeZoneOffset NOARGS
! 330: {
! 331: #ifndef NO_TIMEZONE
! 332: {
! 333: #ifndef NO_ALTZONE
! 334: time_t cur_t = time(NULL);
! 335: struct tm * local = localtime(&cur_t);
! 336: if (daylight && local->tm_isdst==1) /* daylight time? */
! 337: HTTimeZone = altzone; /* yes */
! 338: else
! 339: HTTimeZone = timezone; /* no */
! 340: HTTimeZone = -HTTimeZone;
! 341: if (TRACE)
! 342: fprintf(TDEST,"TimeZone.... GMT + (%02d) hours (including DST)\n",
! 343: (int) HTTimeZone/3600);
! 344: #else
! 345: HTTimeZone = -timezone;
! 346: if (TRACE)
! 347: fprintf(TDEST,"TimeZone.... GMT + (%02d) hours (excluding DST)\n",
! 348: (int) HTTimeZone/3600);
! 349: #endif
! 350: }
! 351: #else
! 352: #ifndef NO_GMTOFF
! 353: {
! 354: time_t cur_t = time(NULL);
! 355: struct tm * local = localtime(&cur_t);
! 356: HTTimeZone = local->tm_gmtoff;
! 357: if (TRACE) fprintf(TDEST,"TimeZone.... GMT + (%02d) hours\n",
! 358: (int)local->tm_gmtoff / 3600);
! 359: }
! 360: #else
! 361: if (TRACE) fprintf(TDEST,"TimeZone.... Not defined\n");
! 362: #endif /* !NO_TIMEZONE */
! 363: #endif /* !NO_GMTOFF */
! 364: return HTTimeZone;
! 365: }
! 366:
! 367: /*
! 368: ** Parse a str in GMT format to a local time time_t representation
! 369: ** Four formats are accepted:
! 370: **
! 371: ** Wkd, 00 Mon 0000 00:00:00 GMT (rfc1123)
! 372: ** Weekday, 00-Mon-00 00:00:00 GMT (rfc850)
! 373: ** Wkd Mon 00 00:00:00 0000 GMT (ctime)
! 374: ** 1*DIGIT (delta-seconds)
! 375: */
! 376: PUBLIC time_t HTParseTime ARGS1(CONST char *, str)
! 377: {
! 378: CONST char * s;
! 379: struct tm tm;
! 380: time_t t;
! 381:
! 382: if (!str) return 0;
! 383:
! 384: if ((s = strchr(str, ','))) { /* Thursday, 10-Jun-93 01:29:59 GMT */
! 385: s++; /* or: Thu, 10 Jan 1993 01:29:59 GMT */
! 386: while (*s && *s==' ') s++;
! 387: if (strchr(s,'-')) { /* First format */
! 388: if (TRACE)
! 389: fprintf(TDEST, "Format...... Weekday, 00-Mon-00 00:00:00 GMT\n");
! 390: if ((int)strlen(s) < 18) {
! 391: if (TRACE)
! 392: fprintf(TDEST,
! 393: "ERROR....... Not a valid time format \"%s\"\n",s);
! 394: return 0;
! 395: }
! 396: tm.tm_mday = make_num(s);
! 397: tm.tm_mon = make_month(s+3);
! 398: tm.tm_year = make_num(s+7);
! 399: tm.tm_hour = make_num(s+10);
! 400: tm.tm_min = make_num(s+13);
! 401: tm.tm_sec = make_num(s+16);
! 402: } else { /* Second format */
! 403: if (TRACE)
! 404: fprintf(TDEST, "Format...... Wkd, 00 Mon 0000 00:00:00 GMT\n");
! 405: if ((int)strlen(s) < 20) {
! 406: if (TRACE)
! 407: fprintf(TDEST,
! 408: "ERROR....... Not a valid time format \"%s\"\n",s);
! 409: return 0;
! 410: }
! 411: tm.tm_mday = make_num(s);
! 412: tm.tm_mon = make_month(s+3);
! 413: tm.tm_year = (100*make_num(s+7) - 1900) + make_num(s+9);
! 414: tm.tm_hour = make_num(s+12);
! 415: tm.tm_min = make_num(s+15);
! 416: tm.tm_sec = make_num(s+18);
! 417:
! 418: }
! 419: } else if (isdigit(*str)) { /* delta seconds */
! 420: t = time(NULL) + atol(str); /* Current local calendar time */
! 421: if (TRACE)
! 422: fprintf(TDEST, "Time string. Delta-time %s parsed to %ld seconds, or in local time: %s", str, (long) t, ctime(&t));
! 423: return t;
! 424:
! 425: } else { /* Try the other format: Wed Jun 9 01:29:59 1993 GMT */
! 426: if (TRACE)
! 427: fprintf(TDEST, "Format...... Wkd Mon 00 00:00:00 0000 GMT\n");
! 428: s = str;
! 429: while (*s && *s==' ') s++;
! 430: if (TRACE)
! 431: fprintf(TDEST, "Trying...... The Wrong time format: %s\n", s);
! 432: if ((int)strlen(s) < 24) {
! 433: if (TRACE)
! 434: fprintf(TDEST, "ERROR....... Not a valid time format \"%s\"\n",s);
! 435: return 0;
! 436: }
! 437: tm.tm_mday = make_num(s+8);
! 438: tm.tm_mon = make_month(s+4);
! 439: tm.tm_year = make_num(s+22);
! 440: tm.tm_hour = make_num(s+11);
! 441: tm.tm_min = make_num(s+14);
! 442: tm.tm_sec = make_num(s+17);
! 443: }
! 444: if (tm.tm_sec < 0 || tm.tm_sec > 59 ||
! 445: tm.tm_min < 0 || tm.tm_min > 59 ||
! 446: tm.tm_hour < 0 || tm.tm_hour > 23 ||
! 447: tm.tm_mday < 1 || tm.tm_mday > 31 ||
! 448: tm.tm_mon < 0 || tm.tm_mon > 11 ||
! 449: tm.tm_year <70 || tm.tm_year >120) {
! 450: if (TRACE) fprintf(TDEST,
! 451: "ERROR....... Parsed illegal time: %02d.%02d.%02d %02d:%02d:%02d\n",
! 452: tm.tm_mday, tm.tm_mon+1, tm.tm_year,
! 453: tm.tm_hour, tm.tm_min, tm.tm_sec);
! 454: return 0;
! 455: }
! 456:
! 457: #if !defined(NO_TIMEZONE) && !defined(NO_ALTZONE)
! 458: tm.tm_isdst = daylight; /* Already taken into account */
! 459: #else
! 460: tm.tm_isdst = -1;
! 461: #endif
! 462:
! 463: #ifndef NO_MKTIME
! 464: t = mktime(&tm);
! 465: t += (HTTimeZone);
! 466: #else
! 467: #ifndef NO_TIMEGM
! 468: t = timegm(&tm);
! 469: #else
! 470: if (TRACE) fprintf(TDEST,"Time String. Can not be parsed\n");
! 471: #endif /* !NO_TIMEGM */
! 472: #endif /* !NO_MKTIME */
! 473:
! 474: if (TRACE)
! 475: fprintf(TDEST,
! 476: "Time string. %s parsed to %ld seconds, or in local time: %s",
! 477: str, (long) t, ctime(&t));
! 478: return t;
1.1 timbl 479: }
Webmaster