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

2.10      frystyk     1: /*                                                                  HTString.c
                      2: **     DYNAMIC STRING UTILITIES
                      3: **
2.21      frystyk     4: **     (c) COPYRIGHT MIT 1995.
2.10      frystyk     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.26    ! frystyk    18: #include "HTParse.h"
2.8       frystyk    19: #include "HTString.h"                                   /* Implemented here */
1.1       timbl      20: 
2.12      frystyk    21: #ifdef NO_STDIO
                     22: PUBLIC FILE *WWWTrace = NULL;
                     23: #endif
                     24: 
1.1       timbl      25: PUBLIC int WWW_TraceFlag = 0;  /* Global trace flag for ALL W3 code */
                     26: 
                     27: #ifndef VC
                     28: #define VC "unknown"
                     29: #endif
                     30: 
                     31: PUBLIC CONST char * HTLibraryVersion = VC; /* String for help screen etc */
                     32: 
2.13      frystyk    33: PRIVATE long HTTimeZone = 0L;                 /* Offset from GMT in seconds */
2.26    ! frystyk    34: PRIVATE char * months[12] = {
        !            35:     "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
        !            36: };
        !            37: 
        !            38: #ifdef NO_STRFTIME
        !            39: PRIVATE char * wkdays[7] = {
        !            40:     "Mon","Tue","Wed","Thu","Fri","Sat","Sun"
        !            41: };
        !            42: #endif
2.13      frystyk    43: 
                     44: /* ------------------------------------------------------------------------- */
                     45: 
2.12      frystyk    46: #ifndef VM             /* VM has these already it seems */
1.1       timbl      47:        
                     48: /*     Strings of any length
                     49: **     ---------------------
                     50: */
                     51: PUBLIC int strcasecomp ARGS2 (CONST char*,a, CONST char *,b)
                     52: {
2.13      frystyk    53:     int diff;
                     54:     for( ; *a && *b; a++, b++) {
                     55:        if ((diff = TOLOWER(*a) - TOLOWER(*b)))
                     56:            return diff;
                     57:     }
                     58:     if (*a) return 1;                  /* a was longer than b */
                     59:     if (*b) return -1;                 /* a was shorter than b */
                     60:     return 0;                          /* Exact match */
1.1       timbl      61: }
                     62: 
                     63: 
                     64: /*     With count limit
                     65: **     ----------------
                     66: */
                     67: PUBLIC int strncasecomp ARGS3(CONST char*,a, CONST char *,b, int,n)
                     68: {
                     69:        CONST char *p =a;
                     70:        CONST char *q =b;
                     71:        
                     72:        for(p=a, q=b;; p++, q++) {
                     73:            int diff;
                     74:            if (p == a+n) return 0;     /*   Match up to n characters */
                     75:            if (!(*p && *q)) return *p - *q;
                     76:            diff = TOLOWER(*p) - TOLOWER(*q);
                     77:            if (diff) return diff;
                     78:        }
                     79:        /*NOTREACHED*/
                     80: }
                     81: #endif
                     82: 
2.7       luotonen   83: 
                     84: /*
                     85:  * strcasestr(s1,s2) -- like strstr(s1,s2) but case-insensitive.
                     86:  */
                     87: PUBLIC char * strcasestr ARGS2(char *, s1,
                     88:                               char *,  s2)
                     89: {
2.9       frystyk    90:     char * ptr = s1;
2.7       luotonen   91: 
                     92:     if (!s1 || !s2 || !*s2) return s1;
                     93: 
2.9       frystyk    94:     while (*ptr) {
                     95:        if (TOUPPER(*ptr) == TOUPPER(*s2)) {
                     96:            char * cur1 = ptr + 1;
2.7       luotonen   97:            char * cur2 = s2 + 1;
                     98:            while (*cur1 && *cur2 && TOUPPER(*cur1) == TOUPPER(*cur2)) {
                     99:                cur1++;
                    100:                cur2++;
                    101:            }
                    102:            if (!*cur2) {
2.13      frystyk   103:                if (TRACE)
2.12      frystyk   104:                    fprintf(TDEST, "Debug....... strcasestr(s1 = \"%s\", s2 = \"%s\") => \"%s\"\n",
                    105:                            s1,s2,ptr);
2.9       frystyk   106:                return ptr;
2.7       luotonen  107:            }
                    108:        }
2.9       frystyk   109:        ptr++;
2.7       luotonen  110:     }
2.12      frystyk   111:     if (TRACE)
                    112:        fprintf(TDEST,
                    113:                "Debug....... strcasestr(s1=\"%s\", s2=\"%s\") => No match\n",
                    114:                s1,s2);
2.7       luotonen  115:     return NULL;
                    116: }
                    117: 
                    118: 
                    119: 
1.1       timbl     120: /*     Allocate a new copy of a string, and returns it
                    121: */
                    122: PUBLIC char * HTSACopy
                    123:   ARGS2 (char **,dest, CONST char *,src)
                    124: {
                    125:   if (*dest) free(*dest);
                    126:   if (! src)
                    127:     *dest = NULL;
                    128:   else {
                    129:     *dest = (char *) malloc (strlen(src) + 1);
                    130:     if (*dest == NULL) outofmem(__FILE__, "HTSACopy");
                    131:     strcpy (*dest, src);
                    132:   }
                    133:   return *dest;
                    134: }
                    135: 
2.6       timbl     136: /*     String Allocate and Concatenate
                    137: */
1.1       timbl     138: PUBLIC char * HTSACat
                    139:   ARGS2 (char **,dest, CONST char *,src)
                    140: {
                    141:   if (src && *src) {
                    142:     if (*dest) {
                    143:       int length = strlen (*dest);
                    144:       *dest = (char *) realloc (*dest, length + strlen(src) + 1);
                    145:       if (*dest == NULL) outofmem(__FILE__, "HTSACat");
                    146:       strcpy (*dest + length, src);
                    147:     } else {
                    148:       *dest = (char *) malloc (strlen(src) + 1);
                    149:       if (*dest == NULL) outofmem(__FILE__, "HTSACat");
                    150:       strcpy (*dest, src);
                    151:     }
                    152:   }
                    153:   return *dest;
2.6       timbl     154: }
                    155: 
                    156: 
                    157: /*     Find next Field
                    158: **     ---------------
                    159: **
                    160: ** On entry,
2.13      frystyk   161: **     *pstr   points to a string containing a word separated
2.20      frystyk   162: **             by white white space "," ";" or "=". The word
2.13      frystyk   163: **             can optionally be quoted using <"> or "<" ">"
                    164: **             Comments surrrounded by '(' ')' are filtered out
2.6       timbl     165: **
                    166: ** On exit,
                    167: **     *pstr   has been moved to the first delimiter past the
                    168: **             field
                    169: **             THE STRING HAS BEEN MUTILATED by a 0 terminator
                    170: **
2.13      frystyk   171: **     Returns a pointer to the first word or NULL on error
2.6       timbl     172: */
                    173: PUBLIC char * HTNextField ARGS1(char **, pstr)
                    174: {
                    175:     char * p = *pstr;
2.13      frystyk   176:     char * start;
                    177: 
                    178:     while (1) {
2.20      frystyk   179:        /* Strip white space and other delimiters */
                    180:        while (*p && (WHITE(*p) || *p==',' || *p==';' || *p=='=')) p++;
2.13      frystyk   181:        if (!*p) {
                    182:            *pstr = p;
                    183:            return NULL;                                         /* No field */
                    184:        }
2.20      frystyk   185: 
2.13      frystyk   186:        if (*p == '"') {                                     /* quoted field */
                    187:            start = ++p;
                    188:            for(;*p && *p!='"'; p++)
                    189:                if (*p == '\\' && *(p+1)) p++;         /* Skip escaped chars */
                    190:        } else if (*p == '<') {                              /* quoted field */
                    191:            for(;*p && *p!='>'; p++)
                    192:                if (*p == '\\' && *(p+1)) p++;         /* Skip escaped chars */
                    193:        } else if (*p == '(') {                                   /* Comment */
                    194:            for(;*p && *p!=')'; p++)
                    195:                if (*p == '\\' && *(p+1)) p++;         /* Skip escaped chars */
                    196:            p++;
2.20      frystyk   197:        } else {                                              /* Spool field */
2.13      frystyk   198:            start = p;
2.20      frystyk   199:            while(*p && !WHITE(*p) && *p!=',' && *p!=';' && *p!='=')
2.13      frystyk   200:                p++;
                    201:            break;                                                 /* Got it */
2.6       timbl     202:        }
                    203:     }
2.13      frystyk   204:     if (*p) *p++ = '\0';
2.6       timbl     205:     *pstr = p;
                    206:     return start;
2.13      frystyk   207: }
                    208: 
                    209: /*
                    210: **     Returns a Message-ID string including the open '<' and the closing '>'.
                    211: **     The format of the string is:
                    212: **
                    213: **             "<" time-in-sec "Z" process-id "@" FQDN ">"
                    214: **
                    215: **     or on systems that doesn't have process-id:
                    216: **
                    217: **             "<" time-in-sec "Z" user "@" FQDN ">"
                    218: **
                    219: **     Returns a pointer to the MessageID
                    220: */
                    221: PUBLIC CONST char *HTMessageIdStr NOARGS
                    222: {
                    223:     static char buf[80];
                    224:     time_t sectime = time(NULL);
                    225: #ifndef NO_GETPID
                    226:     CONST char *address = HTGetDomainName();
                    227: #else
                    228:     CONST char *address = HTGetMailAddress();
                    229: #endif /* NO_GETPID */
                    230:     if (!address) address = tmpnam(NULL);
                    231:     if ((!address || !*address) && sectime < 0) {
                    232:        if (TRACE)
                    233:            fprintf(TDEST, "MessageID...  Can't make a unique MessageID\n");
                    234:        return "";
                    235:     }
                    236: #ifndef NO_GETPID
                    237:     sprintf(buf, "<%ldZ%d@%s>", sectime, getpid(), address ? address : "@@@");
                    238: #else
                    239:     sprintf(buf, "<%ldZ%s>", sectime, address ? address : "@@@");
                    240: #endif /* NO_GETPID */
                    241: 
                    242:     *(buf+79) = '\0';
                    243:     return buf;
                    244: }
                    245: 
                    246: 
                    247: /*     Date and Time Parser
                    248: **     --------------------
                    249: **     These functions are taken from the server written by Ari Luotonen
                    250: */
                    251: 
                    252: PRIVATE int make_num ARGS1(CONST char *, s)
                    253: {
                    254:     if (*s >= '0' && *s <= '9')
                    255:        return 10 * (*s - '0') + *(s+1) - '0';
                    256:     else
                    257:        return *(s+1) - '0';
                    258: }
                    259: 
                    260: PRIVATE int make_month ARGS1(CONST char *, s)
                    261: {
                    262:     int i;
                    263:     for (i=0; i<12; i++)
2.26    ! frystyk   264:        if (!strncasecomp(months[i], s, 3))
2.13      frystyk   265:            return i;
                    266:     return 0;
                    267: }
                    268: 
                    269: /*     Timezone Offset
                    270: **     ---------------
                    271: **     Calculates the offset from GMT in seconds
                    272: */
                    273: PUBLIC long HTGetTimeZoneOffset NOARGS
                    274: {
                    275: #ifndef NO_TIMEZONE
                    276:     {
                    277:        time_t cur_t = time(NULL);
2.24      frystyk   278: #ifdef HT_REENTRANT
                    279:        struct tm loctime;
                    280:        struct tm *local = (struct tm *) localtime_r(&cur_t, &loctime);
                    281: #else
                    282:        struct tm *local = localtime(&cur_t);
                    283: #endif /* HT_REENTRANT */
2.22      frystyk   284:        if (daylight && local->tm_isdst>0) {               /* daylight time? */
                    285: #ifndef NO_ALTZONE
                    286:            HTTimeZone = altzone;
                    287: #else
                    288:            /* Assumes a fixed DST offset of 1 hour, which is probably wrong */
                    289:            HTTimeZone = timezone - 3600;
                    290: #endif
                    291:        } else {                                                       /* no */
                    292:            HTTimeZone = timezone;
                    293:        }
2.13      frystyk   294:        HTTimeZone = -HTTimeZone;
                    295:        if (TRACE)
2.14      frystyk   296:            fprintf(TDEST,"TimeZone.... GMT + (%02d) hours (including DST)\n",
2.13      frystyk   297:                    (int) HTTimeZone/3600);
                    298:     }
2.14      frystyk   299: #else
                    300: #ifndef NO_GMTOFF
                    301:     {
                    302:        time_t cur_t = time(NULL);
2.24      frystyk   303: #ifdef HT_REENTRANT
                    304:        struct tm loctime;
                    305:        localtime_r(&cur_t, &loctime);
                    306: #else
2.14      frystyk   307:        struct tm * local = localtime(&cur_t);
2.24      frystyk   308: #endif /* HT_REENTRANT */
2.14      frystyk   309:        HTTimeZone = local->tm_gmtoff;
2.22      frystyk   310:        if (TRACE)
                    311:            fprintf(TDEST,"TimeZone.... GMT + (%02d) hours (including DST)\n",
                    312:                    (int)local->tm_gmtoff / 3600);
2.14      frystyk   313:     }
                    314: #else
                    315:     if (TRACE) fprintf(TDEST,"TimeZone.... Not defined\n");
2.13      frystyk   316: #endif /* !NO_TIMEZONE */
                    317: #endif /* !NO_GMTOFF */
                    318:     return HTTimeZone;
                    319: }
                    320: 
                    321: /*
                    322: **     Parse a str in GMT format to a local time time_t representation
2.19      frystyk   323: **     Four formats are accepted:
                    324: **
                    325: **             Wkd, 00 Mon 0000 00:00:00 GMT           (rfc1123)
                    326: **             Weekday, 00-Mon-00 00:00:00 GMT         (rfc850)
                    327: **             Wkd Mon 00 00:00:00 0000 GMT            (ctime)
                    328: **             1*DIGIT                                 (delta-seconds)
2.13      frystyk   329: */
                    330: PUBLIC time_t HTParseTime ARGS1(CONST char *, str)
                    331: {
                    332:     CONST char * s;
                    333:     struct tm tm;
                    334:     time_t t;
                    335: 
                    336:     if (!str) return 0;
                    337: 
2.19      frystyk   338:     if ((s = strchr(str, ','))) {       /* Thursday, 10-Jun-93 01:29:59 GMT */
2.13      frystyk   339:        s++;                            /* or: Thu, 10 Jan 1993 01:29:59 GMT */
                    340:        while (*s && *s==' ') s++;
2.19      frystyk   341:        if (strchr(s,'-')) {                                 /* First format */
2.13      frystyk   342:            if (TRACE)
                    343:                fprintf(TDEST, "Format...... Weekday, 00-Mon-00 00:00:00 GMT\n");
                    344:            if ((int)strlen(s) < 18) {
                    345:                if (TRACE)
                    346:                    fprintf(TDEST,
                    347:                            "ERROR....... Not a valid time format \"%s\"\n",s);
                    348:                return 0;
                    349:            }
                    350:            tm.tm_mday = make_num(s);
                    351:            tm.tm_mon = make_month(s+3);
                    352:            tm.tm_year = make_num(s+7);
                    353:            tm.tm_hour = make_num(s+10);
                    354:            tm.tm_min = make_num(s+13);
                    355:            tm.tm_sec = make_num(s+16);
2.19      frystyk   356:        } else {                                            /* Second format */
2.13      frystyk   357:            if (TRACE)
                    358:                fprintf(TDEST, "Format...... Wkd, 00 Mon 0000 00:00:00 GMT\n");
                    359:            if ((int)strlen(s) < 20) {
                    360:                if (TRACE)
                    361:                    fprintf(TDEST,
                    362:                            "ERROR....... Not a valid time format \"%s\"\n",s);
                    363:                return 0;
                    364:            }
                    365:            tm.tm_mday = make_num(s);
                    366:            tm.tm_mon = make_month(s+3);
                    367:            tm.tm_year = (100*make_num(s+7) - 1900) + make_num(s+9);
                    368:            tm.tm_hour = make_num(s+12);
                    369:            tm.tm_min = make_num(s+15);
                    370:            tm.tm_sec = make_num(s+18);
                    371: 
                    372:        }
2.19      frystyk   373:     } else if (isdigit(*str)) {                                    /* delta seconds */
                    374:        t = time(NULL) + atol(str);           /* Current local calendar time */
2.24      frystyk   375:        if (TRACE) {
                    376: #ifdef HT_REENTRANT
                    377:            char buffer[CTIME_MAX];
                    378:            fprintf(TDEST, "Time string. Delta-time %s parsed to %ld seconds, or in local time: %s", str, (long) t, (char *) ctime_r(&t, buffer, CTIME_MAX));
                    379: #else
2.19      frystyk   380:            fprintf(TDEST, "Time string. Delta-time %s parsed to %ld seconds, or in local time: %s", str, (long) t, ctime(&t));
2.24      frystyk   381: #endif
                    382:        }
2.19      frystyk   383:        return t;
                    384: 
                    385:     } else {         /* Try the other format:  Wed Jun  9 01:29:59 1993 GMT */
2.13      frystyk   386:        if (TRACE)
                    387:            fprintf(TDEST, "Format...... Wkd Mon 00 00:00:00 0000 GMT\n");
                    388:        s = str;
                    389:        while (*s && *s==' ') s++;
                    390:        if (TRACE)
                    391:            fprintf(TDEST, "Trying...... The Wrong time format: %s\n", s);
                    392:        if ((int)strlen(s) < 24) {
                    393:            if (TRACE)
                    394:                fprintf(TDEST, "ERROR....... Not a valid time format \"%s\"\n",s);
                    395:            return 0;
                    396:        }
                    397:        tm.tm_mday = make_num(s+8);
                    398:        tm.tm_mon = make_month(s+4);
                    399:        tm.tm_year = make_num(s+22);
                    400:        tm.tm_hour = make_num(s+11);
                    401:        tm.tm_min = make_num(s+14);
                    402:        tm.tm_sec = make_num(s+17);
                    403:     }
                    404:     if (tm.tm_sec  < 0  ||  tm.tm_sec  > 59  ||
                    405:        tm.tm_min  < 0  ||  tm.tm_min  > 59  ||
                    406:        tm.tm_hour < 0  ||  tm.tm_hour > 23  ||
                    407:        tm.tm_mday < 1  ||  tm.tm_mday > 31  ||
                    408:        tm.tm_mon  < 0  ||  tm.tm_mon  > 11  ||
                    409:        tm.tm_year <70  ||  tm.tm_year >120) {
                    410:        if (TRACE) fprintf(TDEST,
                    411:        "ERROR....... Parsed illegal time: %02d.%02d.%02d %02d:%02d:%02d\n",
                    412:               tm.tm_mday, tm.tm_mon+1, tm.tm_year,
                    413:               tm.tm_hour, tm.tm_min, tm.tm_sec);
                    414:        return 0;
                    415:     }
                    416: 
2.16      frystyk   417: #if !defined(NO_TIMEZONE) && !defined(NO_ALTZONE)
2.14      frystyk   418:     tm.tm_isdst = daylight;                   /* Already taken into account */
                    419: #else
                    420:     tm.tm_isdst = -1;
                    421: #endif
                    422: 
2.13      frystyk   423: #ifndef NO_MKTIME
                    424:     t = mktime(&tm);
2.18      frystyk   425:     t += (HTTimeZone);
2.13      frystyk   426: #else
                    427: #ifndef NO_TIMEGM
                    428:     t = timegm(&tm);
                    429: #else
2.18      frystyk   430:     if (TRACE) fprintf(TDEST,"Time String. Can not be parsed\n");
2.13      frystyk   431: #endif /* !NO_TIMEGM */
                    432: #endif /* !NO_MKTIME */
                    433: 
                    434:     if (TRACE)
                    435:        fprintf(TDEST,
                    436:                "Time string. %s parsed to %ld seconds, or in local time: %s",
                    437:                str, (long) t, ctime(&t));
                    438:     return t;
1.1       timbl     439: }
2.23      frystyk   440: 
2.26    ! frystyk   441: /*
        !           442: **     Returns a string pointer to a static area of the current calendar
        !           443: **     time in RFC 1123 format, for example
        !           444: **
        !           445: **             Sun, 06 Nov 1994 08:49:37 GMT
        !           446: **
        !           447: **     The result can be given in both local and GMT dependent on the flag
        !           448: */
        !           449: PUBLIC CONST char *HTDateTimeStr ARGS2(time_t *, calendar, BOOL, local)
        !           450: {
        !           451:     static char buf[40];
        !           452: 
        !           453: #ifndef NO_STRFTIME
        !           454:     if (local) {
        !           455:        /*
        !           456:        ** Solaris 2.3 has a bug so we _must_ use reentrant version
        !           457:        ** Thomas Maslen <tmaslen@verity.com>
        !           458:        */
        !           459: #if defined(HT_REENTRANT) || defined(SOLARIS)
        !           460:        struct tm loctime;
        !           461:        localtime_r(calendar, &loctime);
        !           462:        strftime(buf, 40, "%a, %d %b %Y %H:%M:%S", &loctime);
        !           463: #else
        !           464:        struct tm *loctime = localtime(calendar);
        !           465:        strftime(buf, 40, "%a, %d %b %Y %H:%M:%S", loctime);
        !           466: #endif /* SOLARIS || HT_REENTRANT */
        !           467:     } else {
        !           468: #if defined(HT_REENTRANT) || defined(SOLARIS)
        !           469:        struct tm gmt;
        !           470:        gmtime_r(calendar, &gmt);
        !           471:        strftime(buf, 40, "%a, %d %b %Y %H:%M:%S GMT", &gmt);
        !           472: #else
        !           473:        struct tm *gmt = gmtime(calendar);
        !           474:        strftime(buf, 40, "%a, %d %b %Y %H:%M:%S GMT", gmt);
        !           475: #endif /* SOLARIS || HT_REENTRANT */
        !           476:     }
        !           477: #else
        !           478:     if (local) {
        !           479: #if defined(HT_REENTRANT)
        !           480:        struct tm loctime;
        !           481:        localtime_r(calendar, &loctime);
        !           482: #else
        !           483:        struct tm *loctime = localtime(calendar);
        !           484: #endif /* HT_REENTRANT */
        !           485:        sprintf(buf,"%s, %02d %s 19%02d %02d:%02d:%02d",
        !           486:                wkdays[gmt->tm_wday],
        !           487:                gmt->tm_mday,
        !           488:                months[gmt->tm_mon],
        !           489:                gmt->tm_year % 100,
        !           490:                gmt->tm_hour,
        !           491:                gmt->tm_min,
        !           492:                gmt->tm_sec);
        !           493:     } else {
        !           494: #if defined(HT_REENTRANT) || defined(SOLARIS)
        !           495:        struct tm gmt;
        !           496:        gmtime_r(calendar, &gmt);
        !           497: #else
        !           498:        struct tm *gmt = gmtime(calendar);
        !           499: #endif
        !           500:        sprintf(buf,"%s, %02d %s 19%02d %02d:%02d:%02d GMT",
        !           501:                wkdays[gmt->tm_wday],
        !           502:                gmt->tm_mday,
        !           503:                months[gmt->tm_mon],
        !           504:                gmt->tm_year % 100,
        !           505:                gmt->tm_hour,
        !           506:                gmt->tm_min,
        !           507:                gmt->tm_sec);
        !           508:     }
        !           509: #endif
        !           510:     return buf;
        !           511: }
        !           512: 
        !           513: /*     HTDateDirStr
        !           514: **     ------------
        !           515: **     Generates a date string used in directory listings
        !           516: */
        !           517: PUBLIC BOOL HTDateDirStr (time_t * time, char * str, int len)
        !           518: {
        !           519: #ifndef NO_STRFTIME
        !           520: #if defined(HT_REENTRANT) || defined(SOLARIS)
        !           521:     struct tm loctime;
        !           522:     localtime_r(time, &loctime);
        !           523:     strftime(str, len, "%d-%b-%y %H:%M", &loctime);
        !           524:     return YES;
        !           525: #else
        !           526:     strftime(str, len, "%d-%b-%y %H:%M", localtime(time));
        !           527:     return YES;
        !           528: #endif /* HT_REENTRANT || SOLARIS */
        !           529: #else
        !           530:     if (len >= 16) {
        !           531:        struct tm *loctime = localtime(time);
        !           532:        sprintf(bodyptr,"%02d-%s-%02d %02d:%02d",
        !           533:                loctime->tm_mday,
        !           534:                months[loctime->tm_mon],
        !           535:                loctime->tm_year % 100,
        !           536:                loctime->tm_hour,
        !           537:                loctime->tm_min);
        !           538:        return YES;
        !           539:     }
        !           540:     return NO;
        !           541: #endif /* NO_STRFTIME */               
        !           542: }
2.23      frystyk   543: 
                    544: /*     Strip white space off a string
                    545: **     ------------------------------
                    546: **
                    547: ** On exit,
                    548: **     Return value points to first non-white character, or to 0 if none.
                    549: **     All trailing white space is OVERWRITTEN with zero.
                    550: */
                    551: PUBLIC char * HTStrip ARGS1(char *, s)
                    552: {
                    553: #define SPACE(c) ((c==' ')||(c=='\t')||(c=='\n')) 
                    554:     char * p=s;
                    555:     if (!s) return NULL;       /* Doesn't dump core if NULL */
                    556:     for(p=s;*p;p++);           /* Find end of string */
                    557:     for(p--;p>=s;p--) {
                    558:        if(SPACE(*p)) *p=0;     /* Zap trailing blanks */
                    559:        else break;
                    560:     }
                    561:     while(SPACE(*s))s++;       /* Strip leading blanks */
                    562:     return s;
                    563: }
2.25      frystyk   564: 
                    565: 
                    566: /*                                                             HTNumToStr
                    567: **     Converts a long (byte count) to a string
                    568: **     ----------------------------------------
                    569: **     This function was a PAIN!  In computer-world 1K is 1024 bytes
                    570: **     and 1M is 1024K -- however, sprintf() still formats in base-10.
                    571: **     Therefore I output only until 999, and then start using the
                    572: **     next unit.  This doesn't work wrong, it's just a feature.
                    573: **     The "str" must be large enough to contain the result.
                    574: */
2.26    ! frystyk   575: PUBLIC void HTNumToStr (unsigned long n, char * str, int len)
2.25      frystyk   576: {
                    577:     double size = n/1024.0;
2.26    ! frystyk   578:     if (len < 6) {
        !           579:        *str = '\0';
        !           580:        return;
        !           581:     }
2.25      frystyk   582:     if (n < 1000)
                    583:        sprintf(str, "%dK", n>0 ? 1 : 0);
                    584:     else if (size + 0.999 < 1000)
                    585:        sprintf(str, "%dK", (int)(size + 0.5));
                    586:     else if ((size /= 1024) < 9.9)
                    587:        sprintf(str, "%.1fM", (size + 0.05));
                    588:     else if (size < 1000)
                    589:        sprintf(str, "%dM", (int)(size + 0.5));
                    590:     else if ((size /= 1024) < 9.9)
                    591:        sprintf(str, "%.1fG", (size + 0.05));
                    592:     else
                    593:        sprintf(str, "%dG", (int)(size + 0.5));
                    594: }
                    595: 
2.26    ! frystyk   596: /*     Convert file URLs into a local representation
        !           597: **     ---------------------------------------------
        !           598: **     The URL has already been translated through the rules in get_physical
        !           599: **     in HTAccess.c and all we need to do now is to map the path to a local
        !           600: **     representation, for example if must translate '/' to the ones that
        !           601: **     turn the wrong way ;-)
        !           602: **     Returns:
        !           603: **             OK:     local file (that must be freed by caller)
        !           604: **             Error:  NULL
        !           605: */
        !           606: PUBLIC char * HTWWWToLocal (CONST char * url, CONST char * base)
        !           607: {
        !           608:     if (url) {
        !           609:        char * access = HTParse(url, base, PARSE_ACCESS);
        !           610:        char * host = HTParse(url, base, PARSE_HOST);
        !           611:        char * path = HTParse(url, base, PARSE_PATH+PARSE_PUNCTUATION);
        !           612:        CONST char *myhost = HTGetHostName();
        !           613: 
        !           614:        /* Find out if this is a reference to the local file system */
        !           615:        if ((*access && strcmp(access, "file")) ||
        !           616:            (*host && strcasecomp(host, "localhost") &&
        !           617:             myhost && strcmp(host, myhost))) {
        !           618:            if (PROT_TRACE)
        !           619:                fprintf(TDEST, "LocalName... Not on local file system\n");
        !           620:            free(access);
        !           621:            free(host);
        !           622:            free(path);
        !           623:            return NULL;
        !           624:        } else {
        !           625:            char *ptr;
        !           626:            if ((ptr = strchr(path, ';')) || (ptr = strchr(path, '?')))
        !           627:                *ptr = '\0';
        !           628:        
        !           629:            /*
        !           630:            ** Do whatever translation is required here in order to fit your
        !           631:            ** platform _before_ the path is unescaped.
        !           632:            */
        !           633: #ifdef VMS
        !           634:            HTVMS_checkDecnet(path);
        !           635: #endif
        !           636: #ifdef _WINDOWS
        !           637:            /* an absolute pathname with logical drive */
        !           638:            if (*path == '/' && path[2] == ':')    
        !           639:                /* NB. need memmove because overlaps */
        !           640:                memmove( path, path+1, strlen(path) + 1);
        !           641: #endif
        !           642:            
        !           643:            HTUnEscape(path);             /* Take out the escaped characters */
        !           644:            if (PROT_TRACE)
        !           645:                fprintf(TDEST, "Node........ `%s' means path `%s'\n",url,path);
        !           646:            free(access);
        !           647:            free(host);
        !           648:            return path;
        !           649:        }
        !           650:     }
        !           651:     return NULL;
        !           652: }
        !           653: 
        !           654: /*     Convert a local file name into a URL
        !           655: **     ------------------------------------
        !           656: **     Generates a WWW URL name from a local file name or NULL if error.
        !           657: **     Returns:
        !           658: **             OK:     local file (that must be freed by caller)
        !           659: **             Error:  NULL
        !           660: */
        !           661: PUBLIC char * HTLocalToWWW (CONST char * local)
        !           662: {
        !           663:     char * result = NULL;
        !           664:     if (local && *local) {
        !           665:        StrAllocCopy(result, "file:");       /* We get an absolute file name */
        !           666: #ifdef VMS 
        !           667:        /* convert directory name to Unix-style syntax */
        !           668:        {
        !           669:            char * disk = strchr (local, ':');
        !           670:            char * dir = strchr (local, '[');
        !           671:            if (disk) {
        !           672:                *disk = '\0';
        !           673:                StrAllocCat(result, "/"); /* needs delimiter */
        !           674:                StrAllocCat(result, local);
        !           675:            }
        !           676:            if (dir) {
        !           677:                char *p;
        !           678:                *dir = '/';     /* Convert leading '[' */
        !           679:                for (p = dir ; *p != ']'; ++p)
        !           680:                    if (*p == '.') *p = '/';
        !           681:                *p = '\0';      /* Cut on final ']' */
        !           682:                StrAllocCat(result, dir);
        !           683:            }
        !           684:        }
        !           685: #else  /* not VMS */
        !           686: #ifdef WIN32
        !           687:        {
        !           688:            char * p = local;                                     /* a colon */
        !           689:            StrAllocCat(result, "/");
        !           690:            while( *p != 0 ) { 
        !           691:                if (*p == '\\')                  /* change to one true slash */
        !           692:                    *p = '/' ;
        !           693:                p++;
        !           694:            }
        !           695:            StrAllocCat(result, local);
        !           696:        }
        !           697: #else /* not WIN32 */
        !           698:        StrAllocCat (result, local);
        !           699: #endif /* not WIN32 */
        !           700: #endif /* not VMS */
        !           701:     }
        !           702:     return result;
        !           703: }

Webmaster