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