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