Annotation of libwww/Library/src/HTString.c, revision 2.14

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.13      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.13      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.13      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.13      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.13      frystyk   151: **     *pstr   points to a string containing a word separated
                    152: **             by white space, comma or semi-colon. 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.13      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.13      frystyk   166:     char * start;
                    167: 
                    168:     while (1) {
                    169:        while (*p && WHITE(*p)) p++;                    /* Strip white space */
                    170:        if (!*p) {
                    171:            *pstr = p;
                    172:            return NULL;                                         /* No field */
                    173:        }
                    174:        if (*p == '"') {                                     /* quoted field */
                    175:            start = ++p;
                    176:            for(;*p && *p!='"'; p++)
                    177:                if (*p == '\\' && *(p+1)) p++;         /* Skip escaped chars */
                    178:        } else if (*p == '<') {                              /* quoted field */
                    179:            for(;*p && *p!='>'; p++)
                    180:                if (*p == '\\' && *(p+1)) p++;         /* Skip escaped chars */
                    181:        } else if (*p == '(') {                                   /* Comment */
                    182:            for(;*p && *p!=')'; p++)
                    183:                if (*p == '\\' && *(p+1)) p++;         /* Skip escaped chars */
                    184:            p++;
                    185:        } else {
                    186:            start = p;
                    187:            while(*p && !WHITE(*p) && *p!=',' && *p!=';')     /* Spool field */
                    188:                p++;
                    189:            break;                                                 /* Got it */
2.6       timbl     190:        }
                    191:     }
2.13      frystyk   192:     if (*p) *p++ = '\0';
2.6       timbl     193:     *pstr = p;
                    194:     return start;
2.13      frystyk   195: }
                    196: 
                    197: 
                    198: /*
                    199: **     Returns a string pointer to a static area of the current calendar
                    200: **     time in RFC 1123 format, for example
                    201: **
                    202: **             Sun, 06 Nov 1994 08:49:37 GMT
                    203: **
                    204: **     The result can be given in both local and GMT dependent on the flag
                    205: */
                    206: PUBLIC CONST char *HTDateTimeStr ARGS2(time_t *, calendar, BOOL, local)
                    207: {
                    208:     static char buf[40];
                    209: 
                    210: #ifndef NO_STRFTIME
                    211:     if (local) {
                    212:        struct tm *loctime = localtime(calendar);
                    213:        strftime(buf, 40, "%a, %d %b %Y %H:%M:%S", loctime);
                    214:     } else {
                    215:        struct tm *gmt = gmtime(calendar);
                    216:        strftime(buf, 40, "%a, %d %b %Y %H:%M:%S GMT", gmt);
                    217:     }
                    218: #else
                    219:     if (local) {
                    220:        struct tm *loctime = localtime(calendar);
                    221:        sprintf(buf,"%s, %02d %s 19%02d %02d:%02d:%02d",
                    222:                wkday[gmt->tm_wday],
                    223:                gmt->tm_mday,
                    224:                month[gmt->tm_mon],
                    225:                gmt->tm_year % 100,
                    226:                gmt->tm_hour,
                    227:                gmt->tm_min,
                    228:                gmt->tm_sec);
                    229:     } else {
                    230:        struct tm *gmt = gmtime(calendar);
                    231:        sprintf(buf,"%s, %02d %s 19%02d %02d:%02d:%02d GMT",
                    232:                wkday[gmt->tm_wday],
                    233:                gmt->tm_mday,
                    234:                month[gmt->tm_mon],
                    235:                gmt->tm_year % 100,
                    236:                gmt->tm_hour,
                    237:                gmt->tm_min,
                    238:                gmt->tm_sec);
                    239:     }
                    240: #endif
                    241:     return buf;
                    242: }
                    243: 
                    244: 
                    245: /*
                    246: **     Returns a Message-ID string including the open '<' and the closing '>'.
                    247: **     The format of the string is:
                    248: **
                    249: **             "<" time-in-sec "Z" process-id "@" FQDN ">"
                    250: **
                    251: **     or on systems that doesn't have process-id:
                    252: **
                    253: **             "<" time-in-sec "Z" user "@" FQDN ">"
                    254: **
                    255: **     Returns a pointer to the MessageID
                    256: */
                    257: PUBLIC CONST char *HTMessageIdStr NOARGS
                    258: {
                    259:     static char buf[80];
                    260:     time_t sectime = time(NULL);
                    261: #ifndef NO_GETPID
                    262:     CONST char *address = HTGetDomainName();
                    263: #else
                    264:     CONST char *address = HTGetMailAddress();
                    265: #endif /* NO_GETPID */
                    266:     if (!address) address = tmpnam(NULL);
                    267:     if ((!address || !*address) && sectime < 0) {
                    268:        if (TRACE)
                    269:            fprintf(TDEST, "MessageID...  Can't make a unique MessageID\n");
                    270:        return "";
                    271:     }
                    272: #ifndef NO_GETPID
                    273:     sprintf(buf, "<%ldZ%d@%s>", sectime, getpid(), address ? address : "@@@");
                    274: #else
                    275:     sprintf(buf, "<%ldZ%s>", sectime, address ? address : "@@@");
                    276: #endif /* NO_GETPID */
                    277: 
                    278:     *(buf+79) = '\0';
                    279:     return buf;
                    280: }
                    281: 
                    282: 
                    283: /*     Date and Time Parser
                    284: **     --------------------
                    285: **     These functions are taken from the server written by Ari Luotonen
                    286: */
                    287: 
                    288: PRIVATE char * month_names[12] =
                    289: {
                    290:     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                    291:     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
                    292: };
                    293: 
                    294: PRIVATE int make_num ARGS1(CONST char *, s)
                    295: {
                    296:     if (*s >= '0' && *s <= '9')
                    297:        return 10 * (*s - '0') + *(s+1) - '0';
                    298:     else
                    299:        return *(s+1) - '0';
                    300: }
                    301: 
                    302: PRIVATE int make_month ARGS1(CONST char *, s)
                    303: {
                    304:     int i;
                    305:     for (i=0; i<12; i++)
                    306:        if (!strncasecomp(month_names[i], s, 3))
                    307:            return i;
                    308:     return 0;
                    309: }
                    310: 
                    311: /*     Timezone Offset
                    312: **     ---------------
                    313: **     Calculates the offset from GMT in seconds
                    314: */
                    315: PUBLIC long HTGetTimeZoneOffset NOARGS
                    316: {
                    317: #ifndef NO_TIMEZONE
                    318:     {
2.14    ! frystyk   319: #ifdef HAS_ALTZONE
2.13      frystyk   320:        time_t cur_t = time(NULL);
                    321:        struct tm * local = localtime(&cur_t);
                    322:        if (daylight && local->tm_isdst==1)     /* daylight time? */
                    323:            HTTimeZone = altzone;               /* yes */
                    324:        else
                    325:            HTTimeZone = timezone;              /* no */
                    326:        HTTimeZone = -HTTimeZone;
                    327:        if (TRACE)
2.14    ! frystyk   328:            fprintf(TDEST,"TimeZone.... GMT + (%02d) hours (including DST)\n",
2.13      frystyk   329:                    (int) HTTimeZone/3600);
2.14    ! frystyk   330: #else
        !           331:        HTTimeZone = -timezone;
        !           332:        if (TRACE)
        !           333:            fprintf(TDEST,"TimeZone.... GMT + (%02d) hours (excluding DST)\n",
        !           334:                    (int) HTTimeZone/3600);
        !           335: #endif
2.13      frystyk   336:     }
2.14    ! frystyk   337: #else
        !           338: #ifndef NO_GMTOFF
        !           339:     {
        !           340:        time_t cur_t = time(NULL);
        !           341:        struct tm * local = localtime(&cur_t);
        !           342:        HTTimeZone = local->tm_gmtoff;
        !           343:        if (TRACE) fprintf(TDEST,"TimeZone.... GMT + (%02d) hours\n",
        !           344:                           (int)local->tm_gmtoff / 3600);
        !           345:     }
        !           346: #else
        !           347:     if (TRACE) fprintf(TDEST,"TimeZone.... Not defined\n");
2.13      frystyk   348: #endif /* !NO_TIMEZONE */
                    349: #endif /* !NO_GMTOFF */
                    350:     return HTTimeZone;
                    351: }
                    352: 
                    353: /*
                    354: **     Parse a str in GMT format to a local time time_t representation
                    355: */
                    356: PUBLIC time_t HTParseTime ARGS1(CONST char *, str)
                    357: {
                    358:     CONST char * s;
                    359:     struct tm tm;
                    360:     time_t t;
                    361: 
                    362:     if (!str) return 0;
                    363: 
                    364:     if ((s = strchr(str, ','))) {      /* Thursday, 10-Jun-93 01:29:59 GMT */
                    365:        s++;                            /* or: Thu, 10 Jan 1993 01:29:59 GMT */
                    366:        while (*s && *s==' ') s++;
                    367:        if (strchr(s,'-')) {            /* First format */
                    368:            if (TRACE)
                    369:                fprintf(TDEST, "Format...... Weekday, 00-Mon-00 00:00:00 GMT\n");
                    370:            if ((int)strlen(s) < 18) {
                    371:                if (TRACE)
                    372:                    fprintf(TDEST,
                    373:                            "ERROR....... Not a valid time format \"%s\"\n",s);
                    374:                return 0;
                    375:            }
                    376:            tm.tm_mday = make_num(s);
                    377:            tm.tm_mon = make_month(s+3);
                    378:            tm.tm_year = make_num(s+7);
                    379:            tm.tm_hour = make_num(s+10);
                    380:            tm.tm_min = make_num(s+13);
                    381:            tm.tm_sec = make_num(s+16);
                    382:        }
                    383:        else {                          /* Second format */
                    384:            if (TRACE)
                    385:                fprintf(TDEST, "Format...... Wkd, 00 Mon 0000 00:00:00 GMT\n");
                    386:            if ((int)strlen(s) < 20) {
                    387:                if (TRACE)
                    388:                    fprintf(TDEST,
                    389:                            "ERROR....... Not a valid time format \"%s\"\n",s);
                    390:                return 0;
                    391:            }
                    392:            tm.tm_mday = make_num(s);
                    393:            tm.tm_mon = make_month(s+3);
                    394:            tm.tm_year = (100*make_num(s+7) - 1900) + make_num(s+9);
                    395:            tm.tm_hour = make_num(s+12);
                    396:            tm.tm_min = make_num(s+15);
                    397:            tm.tm_sec = make_num(s+18);
                    398: 
                    399:        }
                    400:     }
                    401:     else {     /* Try the other format:  Wed Jun  9 01:29:59 1993 GMT */
                    402:        if (TRACE)
                    403:            fprintf(TDEST, "Format...... Wkd Mon 00 00:00:00 0000 GMT\n");
                    404:        s = str;
                    405:        while (*s && *s==' ') s++;
                    406:        if (TRACE)
                    407:            fprintf(TDEST, "Trying...... The Wrong time format: %s\n", s);
                    408:        if ((int)strlen(s) < 24) {
                    409:            if (TRACE)
                    410:                fprintf(TDEST, "ERROR....... Not a valid time format \"%s\"\n",s);
                    411:            return 0;
                    412:        }
                    413:        tm.tm_mday = make_num(s+8);
                    414:        tm.tm_mon = make_month(s+4);
                    415:        tm.tm_year = make_num(s+22);
                    416:        tm.tm_hour = make_num(s+11);
                    417:        tm.tm_min = make_num(s+14);
                    418:        tm.tm_sec = make_num(s+17);
                    419:     }
                    420:     if (tm.tm_sec  < 0  ||  tm.tm_sec  > 59  ||
                    421:        tm.tm_min  < 0  ||  tm.tm_min  > 59  ||
                    422:        tm.tm_hour < 0  ||  tm.tm_hour > 23  ||
                    423:        tm.tm_mday < 1  ||  tm.tm_mday > 31  ||
                    424:        tm.tm_mon  < 0  ||  tm.tm_mon  > 11  ||
                    425:        tm.tm_year <70  ||  tm.tm_year >120) {
                    426:        if (TRACE) fprintf(TDEST,
                    427:        "ERROR....... Parsed illegal time: %02d.%02d.%02d %02d:%02d:%02d\n",
                    428:               tm.tm_mday, tm.tm_mon+1, tm.tm_year,
                    429:               tm.tm_hour, tm.tm_min, tm.tm_sec);
                    430:        return 0;
                    431:     }
                    432: 
2.14    ! frystyk   433: #ifdef HAS_ALTZONE
        !           434:     tm.tm_isdst = daylight;                   /* Already taken into account */
        !           435: #else
        !           436:     tm.tm_isdst = -1;
        !           437: #endif
        !           438: 
2.13      frystyk   439: #ifndef NO_MKTIME
                    440:     t = mktime(&tm);
                    441: #else
                    442: #ifndef NO_TIMEGM
                    443:     t = timegm(&tm);
                    444: #else
                    445:     if (TRACE) fprintf(TDEST,"TimeZone.... undefined\n");
                    446: #endif /* !NO_TIMEGM */
                    447: #endif /* !NO_MKTIME */
                    448: 
                    449:     t += (HTTimeZone);
                    450: 
                    451:     if (TRACE)
                    452:        fprintf(TDEST,
                    453:                "Time string. %s parsed to %ld seconds, or in local time: %s",
                    454:                str, (long) t, ctime(&t));
                    455:     return t;
1.1       timbl     456: }

Webmaster