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