Annotation of libwww/Library/src/HTString.c, revision 2.27
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: */
2.27 ! frystyk 449: PUBLIC CONST char *HTDateTimeStr (time_t * calendar, BOOL local)
2.26 frystyk 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