Annotation of Amaya/amaya/AHTURLTools.c, revision 1.80
1.7 cvs 1: /*
2: *
3: * (c) COPYRIGHT MIT and INRIA, 1996.
4: * Please first read the full copyright statement in file COPYRIGHT.
5: *
6: */
1.9 cvs 7:
1.10 cvs 8: /*
9: * AHTURLTools.c: contains all the functions for testing, manipulating,
1.25 cvs 10: * and normalizing URLs. It also contains a local copy of the libWWW
11: * URL parsing functions.
1.10 cvs 12: *
13: * Authors: J. Kahan, I. Vatton
1.45 cvs 14: * R. Guetari (Stuff related to Windows).
1.10 cvs 15: *
16: */
1.7 cvs 17:
1.15 cvs 18: #define THOT_EXPORT extern
1.3 cvs 19: #include "amaya.h"
20:
1.8 cvs 21: #include "init_f.h"
22: #include "AHTURLTools_f.h"
23:
1.24 cvs 24: #define MAX_PRINT_URL_LENGTH 50
1.29 cvs 25: typedef struct _HTURI {
1.67 cvs 26: STRING access; /* Now known as "scheme" */
27: STRING host;
28: STRING absolute;
29: STRING relative;
30: STRING fragment;
1.29 cvs 31: } HTURI;
1.24 cvs 32:
1.28 cvs 33:
34: /*----------------------------------------------------------------------
35: ConvertToLowerCase
36: Converts a string to lowercase.
37: ----------------------------------------------------------------------*/
1.22 cvs 38: #ifdef __STDC__
1.67 cvs 39: void ConvertToLowerCase (STRING string)
1.28 cvs 40: #else /* __STDC__ */
1.38 cvs 41: void ConvertToLowerCase (string)
1.67 cvs 42: STRING string;
1.28 cvs 43:
44: #endif /* __STDC__ */
45: {
46: int i;
47:
48: if (!string)
49: return;
50:
51: for (i = 0; string[i] != EOS; i++)
1.67 cvs 52: string[i] = utolower (string[i]);
1.28 cvs 53: }
1.22 cvs 54:
1.8 cvs 55: /*----------------------------------------------------------------------
1.75 cvs 56: EscapeChar
57: writes the equivalent escape code of a char in a string
58: ----------------------------------------------------------------------*/
59: #ifdef __STDC__
60: void EscapeChar (STRING string, UCHAR_T c)
61: #else
62: void EscapeChar (string, c)
63: STRING string;
64: UCHAR_T c;
65:
66: #endif
67: {
68: c &= 0xFF; /* strange behavior under solaris? */
69: usprintf (string, TEXT("%02x"), (unsigned int) c);
70: }
71:
72: /*----------------------------------------------------------------------
73: EscapeURL
74: Takes a URL and escapes all protected chars into
75: %xx sequences. Also, removes any leading white spaces
76: Returns either NULL or a new buffer, which must be freed by the caller
77: ----------------------------------------------------------------------*/
78: #ifdef __STDC__
79: STRING EscapeURL (const STRING url)
80: #else
81: STRING EscapeURL (url)
82: STRING url;
83: #endif /* __STDC__ */
84: {
85: STRING buffer;
86: int buffer_len;
87: int buffer_free_mem;
88: PCHAR_T ptr;
89: int new_chars;
90: void *status;
91:
92: if (url && *url)
93: {
1.76 cvs 94: buffer_free_mem = ustrlen (url) + 20;
95: buffer = TtaAllocString (buffer_free_mem + 1);
1.75 cvs 96: ptr = url;
97: buffer_len = 0;
98:
99: while (*ptr)
100: {
101: switch (*ptr)
102: {
103: /* put here below all the chars that need to
104: be escaped into %xx */
105: case TEXT(0x27): /* & */
106: case TEXT(0x20): /* space */
107: new_chars = 3;
108: break;
109:
110: default:
111: new_chars = 1;
112: break;
113: }
114:
115: /* see if we need extra room in the buffer */
116: if (new_chars > buffer_free_mem)
117: {
1.76 cvs 118: buffer_free_mem = 20;
1.75 cvs 119: status = TtaRealloc (buffer, sizeof (CHAR_T)
120: * (buffer_len + buffer_free_mem + 1));
121: if (status)
122: buffer = (STRING) status;
123: else {
124: /* @@ maybe we should do some other behavior here, like
125: freeing the buffer and return a void thing */
1.76 cvs 126: buffer[buffer_len] = EOS;
1.75 cvs 127: break;
128: }
129: }
130: /* escape the char */
131: if (new_chars == 3)
132: {
133: buffer[buffer_len] = TEXT('%');
134: EscapeChar (&buffer[buffer_len+1], *ptr);
135: }
136: else
137: buffer[buffer_len] = *ptr;
138:
139: /* update the status */
140: buffer_len += new_chars;
141: buffer_free_mem -= new_chars;
142: /* examine the next char */
143: ptr++;
144: }
145: buffer[buffer_len] = EOS;
146: }
1.76 cvs 147: else
148: buffer = NULL;
149:
1.75 cvs 150: return (buffer);
151: }
152:
153:
154: /*----------------------------------------------------------------------
1.11 cvs 155: ExplodeURL
1.8 cvs 156: ----------------------------------------------------------------------*/
157: #ifdef __STDC__
158: void ExplodeURL (char *url, char **proto, char **host, char **dir, char **file)
159: #else
160: void ExplodeURL (url, proto, host, dir, file)
161: char *url;
162: char **proto;
163: char **host;
164: char **dir;
165: char **file;
166:
167: #endif
168: {
1.33 cvs 169: char *curr, *temp;
170: char used_sep;
1.32 cvs 171:
1.33 cvs 172: if (url && strchr (url, URL_SEP))
173: used_sep = URL_SEP;
174: else
175: used_sep = DIR_SEP;
1.8 cvs 176:
177: if ((url == NULL) || (proto == NULL) || (host == NULL) ||
178: (dir == NULL) || (file == NULL))
179: return;
180:
181: /* initialize every pointer */
182: *proto = *host = *dir = *file = NULL;
183:
184: /* skip any leading space */
185: while ((*url == SPACE) || (*url == TAB))
186: url++;
1.9 cvs 187: curr = url;
188: if (*curr == 0)
1.8 cvs 189: goto finished;
190:
191: /* go to the end of the URL */
1.68 cvs 192: while ((*curr != EOS) && (*curr != SPACE) && (*curr != BSPACE) &&
193: (*curr != __CR__) && (*curr != EOL))
1.9 cvs 194: curr++;
1.8 cvs 195:
196: /* mark the end of the chain */
1.9 cvs 197: *curr = EOS;
198: curr--;
199: if (curr <= url)
1.8 cvs 200: goto finished;
201:
202: /* search the next DIR_SEP indicating the beginning of the file name */
203: do
1.11 cvs 204: curr--;
1.33 cvs 205: while ((curr >= url) && (*curr != used_sep));
1.11 cvs 206:
1.9 cvs 207: if (curr < url)
1.8 cvs 208: goto finished;
1.9 cvs 209: *file = curr + 1;
1.8 cvs 210:
211: /* mark the end of the dir */
1.9 cvs 212: *curr = EOS;
213: curr--;
214: if (curr < url)
1.8 cvs 215: goto finished;
216:
1.29 cvs 217: /* search for the DIR_STR indicating the host name start */
1.33 cvs 218: while ((curr > url) && ((*curr != used_sep) || (*(curr + 1) != used_sep)))
1.9 cvs 219: curr--;
1.8 cvs 220:
221: /* if we found it, separate the host name from the directory */
1.33 cvs 222: if ((*curr == DIR_SEP) && (*(curr + 1) == used_sep))
1.8 cvs 223: {
1.9 cvs 224: *host = temp = curr + 2;
1.33 cvs 225: while ((*temp != 0) && (*temp != used_sep))
1.8 cvs 226: temp++;
1.33 cvs 227: if (*temp == used_sep)
1.8 cvs 228: {
229: *temp = EOS;
230: *dir = temp + 1;
231: }
232: }
233: else
1.11 cvs 234: *dir = curr;
235:
1.9 cvs 236: if (curr <= url)
1.8 cvs 237: goto finished;
238:
239: /* mark the end of the proto */
1.9 cvs 240: *curr = EOS;
241: curr--;
242: if (curr < url)
1.8 cvs 243: goto finished;
244:
1.67 cvs 245: if (*curr == TEXT(':'))
1.8 cvs 246: {
1.9 cvs 247: *curr = EOS;
248: curr--;
1.8 cvs 249: }
250: else
251: goto finished;
1.11 cvs 252:
1.9 cvs 253: if (curr < url)
1.8 cvs 254: goto finished;
1.9 cvs 255: while ((curr > url) && (isalpha (*curr)))
256: curr--;
257: *proto = curr;
1.8 cvs 258:
259: finished:;
260:
261: #ifdef AMAYA_DEBUG
262: fprintf (stderr, "ExplodeURL(%s)\n\t", url);
263: if (*proto)
264: fprintf (stderr, "proto : %s, ", *proto);
265: if (*host)
266: fprintf (stderr, "host : %s, ", *host);
267: if (*dir)
268: fprintf (stderr, "dir : %s, ", *dir);
269: if (*file)
270: fprintf (stderr, "file : %s ", *file);
271: fprintf (stderr, "\n");
272: #endif
273:
274: }
1.3 cvs 275:
1.61 cvs 276:
277: /*----------------------------------------------------------------------
278: ExtractSuffix extract suffix from document nane.
279: ----------------------------------------------------------------------*/
280: #ifdef __STDC__
281: void ExtractSuffix (STRING aName, STRING aSuffix)
282: #else
283: void ExtractSuffix (aName, aSuffix)
284: STRING aName;
285: STRING aSuffix;
286:
287: #endif
288: {
289: int lg, i;
290: STRING ptr, oldptr;
291:
292: if (!aSuffix || !aName)
293: /* bad suffix */
294: return;
295:
296: aSuffix[0] = EOS;
297: lg = ustrlen (aName);
298: if (lg)
299: {
300: /* the name is not empty */
301: oldptr = ptr = &aName[0];
302: do
303: {
1.67 cvs 304: ptr = ustrrchr (oldptr, TEXT('.'));
1.61 cvs 305: if (ptr)
306: oldptr = &ptr[1];
307: }
308: while (ptr);
309:
310: i = (int) (oldptr) - (int) (aName); /* name length */
311: if (i > 1)
312: {
313: aName[i - 1] = EOS;
314: if (i != lg)
315: ustrcpy (aSuffix, oldptr);
316: }
317: }
318: }
319:
1.4 cvs 320: /*----------------------------------------------------------------------
1.9 cvs 321: IsHTMLName
322: returns TRUE if path points to an HTML resource.
1.4 cvs 323: ----------------------------------------------------------------------*/
1.3 cvs 324: #ifdef __STDC__
1.67 cvs 325: ThotBool IsHTMLName (const STRING path)
1.3 cvs 326: #else /* __STDC__ */
1.67 cvs 327: ThotBool IsHTMLName (path)
328: const STRING path;
1.3 cvs 329: #endif /* __STDC__ */
330: {
1.67 cvs 331: CHAR_T temppath[MAX_LENGTH];
332: CHAR_T suffix[MAX_LENGTH];
333: CHAR_T nsuffix[MAX_LENGTH];
1.5 cvs 334: int i;
335:
336: if (!path)
1.37 cvs 337: return (FALSE);
1.5 cvs 338:
1.67 cvs 339: ustrcpy (temppath, path);
1.5 cvs 340: ExtractSuffix (temppath, suffix);
341:
342: /* Normalize the suffix */
343: i = 0;
1.39 cvs 344: while (suffix[i] != EOS && i < MAX_LENGTH -1)
1.13 cvs 345: {
1.67 cvs 346: nsuffix[i] = utolower (suffix[i]);
1.13 cvs 347: i++;
348: }
1.5 cvs 349: nsuffix[i] = EOS;
1.67 cvs 350: if (!ustrcmp (nsuffix, TEXT("html")) ||
351: !ustrcmp (nsuffix, TEXT("htm")) ||
352: !ustrcmp (nsuffix, TEXT("shtml")) ||
1.80 ! cvs 353: !ustrcmp (nsuffix, TEXT("jsp")) ||
1.67 cvs 354: !ustrcmp (nsuffix, TEXT("xht")) ||
355: !ustrcmp (nsuffix, TEXT("xhtm")) ||
356: !ustrcmp (nsuffix, TEXT("xhtml")))
1.39 cvs 357: return (TRUE);
1.67 cvs 358: else if (!ustrcmp (nsuffix, TEXT("gz")))
1.13 cvs 359: {
1.39 cvs 360: /* take into account compressed files */
1.13 cvs 361: ExtractSuffix (temppath, suffix);
362: /* Normalize the suffix */
363: i = 0;
1.39 cvs 364: while (suffix[i] != EOS && i < MAX_LENGTH -1)
1.13 cvs 365: {
1.25 cvs 366: nsuffix[i] = tolower (suffix[i]);
1.13 cvs 367: i++;
368: }
369: nsuffix[i] = EOS;
1.67 cvs 370: if (!ustrcmp (nsuffix, TEXT("html")) ||
371: !ustrcmp (nsuffix, TEXT("htm")) ||
372: !ustrcmp (nsuffix, TEXT("shtml")) ||
1.80 ! cvs 373: !ustrcmp (nsuffix, TEXT("jsp")) ||
1.67 cvs 374: !ustrcmp (nsuffix, TEXT("xht")) ||
375: !ustrcmp (nsuffix, TEXT("xhtm")) ||
376: !ustrcmp (nsuffix, TEXT("xhtml")))
1.63 cvs 377:
1.39 cvs 378: return (TRUE);
379: else
1.13 cvs 380: return (FALSE);
381: }
382: else
1.39 cvs 383: return (FALSE);
1.3 cvs 384: }
385:
1.4 cvs 386: /*----------------------------------------------------------------------
1.56 cvs 387: IsXMLName
388: returns TRUE if path points to an XML resource.
389: ----------------------------------------------------------------------*/
390: #ifdef __STDC__
1.67 cvs 391: ThotBool IsXMLName (const STRING path)
1.56 cvs 392: #else /* __STDC__ */
1.67 cvs 393: ThotBool IsXMLName (path)
394: const STRING path;
1.56 cvs 395: #endif /* __STDC__ */
396: {
1.67 cvs 397: CHAR_T temppath[MAX_LENGTH];
398: CHAR_T suffix[MAX_LENGTH];
1.56 cvs 399:
400: if (!path)
401: return (FALSE);
402:
1.67 cvs 403: ustrcpy (temppath, path);
1.56 cvs 404: ExtractSuffix (temppath, suffix);
405:
1.67 cvs 406: if (!ustrcasecmp (suffix, TEXT("xml")) ||
407: !ustrcasecmp (suffix, TEXT("xht")) ||
408: !ustrcmp (suffix, TEXT("xhtm")) ||
409: !ustrcmp (suffix, TEXT("xhtml")))
1.56 cvs 410: return (TRUE);
1.67 cvs 411: else if (!ustrcmp (suffix, TEXT("gz")))
1.56 cvs 412: {
413: /* take into account compressed files */
414: ExtractSuffix (temppath, suffix);
1.67 cvs 415: if (!ustrcasecmp (suffix, TEXT("xml")) ||
416: !ustrcasecmp (suffix, TEXT("xht")) ||
417: !ustrcmp (suffix, TEXT("xhtm")) ||
418: !ustrcmp (suffix, TEXT("xhtml")))
1.60 cvs 419: return (TRUE);
420: else
421: return (FALSE);
422: }
423: else
424: return (FALSE);
425: }
426:
427: /*----------------------------------------------------------------------
428: IsCSSName
429: returns TRUE if path points to an XML resource.
430: ----------------------------------------------------------------------*/
431: #ifdef __STDC__
1.67 cvs 432: ThotBool IsCSSName (const STRING path)
1.60 cvs 433: #else /* __STDC__ */
1.67 cvs 434: ThotBool IsCSSName (path)
435: const STRING path;
1.60 cvs 436: #endif /* __STDC__ */
437: {
1.67 cvs 438: CHAR_T temppath[MAX_LENGTH];
439: CHAR_T suffix[MAX_LENGTH];
1.60 cvs 440:
441: if (!path)
442: return (FALSE);
443:
1.67 cvs 444: ustrcpy (temppath, path);
1.60 cvs 445: ExtractSuffix (temppath, suffix);
446:
1.67 cvs 447: if (!ustrcasecmp (suffix, TEXT("css")))
1.60 cvs 448: return (TRUE);
1.67 cvs 449: else if (!ustrcmp (suffix, TEXT("gz")))
1.60 cvs 450: {
451: /* take into account compressed files */
452: ExtractSuffix (temppath, suffix);
1.67 cvs 453: if (!ustrcasecmp (suffix, TEXT("css")))
1.56 cvs 454: return (TRUE);
455: else
456: return (FALSE);
457: }
458: else
459: return (FALSE);
460: }
461:
462: /*----------------------------------------------------------------------
1.9 cvs 463: IsImageName
464: returns TRUE if path points to an image resource.
1.4 cvs 465: ----------------------------------------------------------------------*/
1.3 cvs 466: #ifdef __STDC__
1.67 cvs 467: ThotBool IsImageName (const STRING path)
1.3 cvs 468: #else /* __STDC__ */
1.67 cvs 469: ThotBool IsImageName (path)
470: const STRING path;
1.3 cvs 471: #endif /* __STDC__ */
472: {
1.67 cvs 473: CHAR_T temppath[MAX_LENGTH];
474: CHAR_T suffix[MAX_LENGTH];
475: CHAR_T nsuffix[MAX_LENGTH];
1.5 cvs 476: int i;
477:
478: if (!path)
1.13 cvs 479: return (FALSE);
1.5 cvs 480:
1.67 cvs 481: ustrcpy (temppath, path);
1.5 cvs 482: ExtractSuffix (temppath, suffix);
483:
484: /* Normalize the suffix */
485: i = 0;
1.39 cvs 486: while (suffix[i] != EOS && i < MAX_LENGTH -1)
1.13 cvs 487: {
1.67 cvs 488: nsuffix[i] = utolower (suffix[i]);
1.13 cvs 489: i++;
490: }
1.5 cvs 491: nsuffix[i] = EOS;
1.67 cvs 492: if ((!ustrcmp (nsuffix, TEXT("gif"))) || (!ustrcmp (nsuffix, TEXT("xbm"))) ||
493: (!ustrcmp (nsuffix, TEXT("xpm"))) || (!ustrcmp (nsuffix, TEXT("jpg"))) ||
494: (!ustrcmp (nsuffix, TEXT("png"))) || (!ustrcmp (nsuffix, TEXT("au"))))
1.39 cvs 495: return (TRUE);
496: return (FALSE);
1.3 cvs 497: }
498:
1.4 cvs 499: /*----------------------------------------------------------------------
1.58 cvs 500: IsImageType
501: returns TRUE if type points to an image resource.
502: ----------------------------------------------------------------------*/
503: #ifdef __STDC__
1.67 cvs 504: ThotBool IsImageType (const STRING type)
1.58 cvs 505: #else /* __STDC__ */
1.67 cvs 506: ThotBool IsImageType (type)
507: const STRING type;
1.58 cvs 508: #endif /* __STDC__ */
509: {
1.67 cvs 510: CHAR_T temptype[MAX_LENGTH];
1.58 cvs 511: int i;
512:
513: if (!type)
514: return (FALSE);
515:
1.67 cvs 516: ustrcpy (temptype, type);
1.58 cvs 517: /* Normalize the type */
518: i = 0;
519: while (temptype[i] != EOS)
520: {
521: temptype[i] = tolower (temptype[i]);
522: i++;
523: }
1.67 cvs 524: if ((!ustrcmp (temptype, TEXT("gif"))) || (!ustrcmp (temptype, TEXT("x-xbitmap"))) ||
525: (!ustrcmp (temptype, TEXT("x-xpixmap"))) || (!ustrcmp (temptype, TEXT("jpeg"))) ||
526: (!ustrcmp (temptype, TEXT("png"))))
1.58 cvs 527: return (TRUE);
528: return (FALSE);
529: }
530:
531: /*----------------------------------------------------------------------
1.9 cvs 532: IsTextName
1.4 cvs 533: ----------------------------------------------------------------------*/
1.3 cvs 534: #ifdef __STDC__
1.67 cvs 535: ThotBool IsTextName (const STRING path)
1.3 cvs 536: #else /* __STDC__ */
1.67 cvs 537: ThotBool IsTextName (path)
538: const STRING path;
1.3 cvs 539:
540: #endif /* __STDC__ */
541: {
1.67 cvs 542: CHAR_T temppath[MAX_LENGTH];
543: CHAR_T suffix[MAX_LENGTH];
544: CHAR_T nsuffix[MAX_LENGTH];
1.5 cvs 545: int i;
546:
547: if (!path)
1.13 cvs 548: return (FALSE);
1.5 cvs 549:
1.67 cvs 550: ustrcpy (temppath, path);
1.5 cvs 551: ExtractSuffix (temppath, suffix);
552:
553: /* Normalize the suffix */
554: i = 0;
1.39 cvs 555: while (suffix[i] != EOS && i < MAX_LENGTH -1)
1.5 cvs 556: {
1.25 cvs 557: nsuffix[i] = tolower (suffix[i]);
1.5 cvs 558: i++;
559: }
560: nsuffix[i] = EOS;
561:
1.67 cvs 562: if ((!ustrcmp (nsuffix, TEXT("txt"))) || (!ustrcmp (nsuffix, TEXT("dtd"))))
1.13 cvs 563: return (TRUE);
1.67 cvs 564: else if (!ustrcmp (nsuffix, TEXT("gz")))
1.13 cvs 565: {
1.39 cvs 566: /* take into account compressed files */
1.13 cvs 567: ExtractSuffix (temppath, suffix);
568: /* Normalize the suffix */
569: i = 0;
1.39 cvs 570: while (suffix[i] != EOS && i < MAX_LENGTH -1)
1.13 cvs 571: {
1.25 cvs 572: nsuffix[i] = tolower (suffix[i]);
1.13 cvs 573: i++;
574: }
575: nsuffix[i] = EOS;
1.67 cvs 576: if ((!ustrcmp (nsuffix, TEXT("txt"))) || (!ustrcmp (nsuffix, TEXT("dtd"))))
1.13 cvs 577: return (TRUE);
578: else
579: return (FALSE);
580: }
581: else
582: return (FALSE);
1.3 cvs 583: }
584:
1.4 cvs 585: /*----------------------------------------------------------------------
1.9 cvs 586: IsHTTPPath
587: returns TRUE if path is in fact an http URL.
1.4 cvs 588: ----------------------------------------------------------------------*/
1.3 cvs 589: #ifdef __STDC__
1.67 cvs 590: ThotBool IsHTTPPath (const STRING path)
1.3 cvs 591: #else /* __STDC__ */
1.67 cvs 592: ThotBool IsHTTPPath (path)
593: const STRING path;
1.3 cvs 594: #endif /* __STDC__ */
595: {
1.5 cvs 596: if (!path)
597: return FALSE;
1.3 cvs 598:
1.67 cvs 599: if ((!ustrncmp (path, TEXT("http:"), 5) != 0)
600: || !ustrncmp (path, TEXT("internal:"), 9))
1.58 cvs 601: return TRUE;
602: return FALSE;
1.3 cvs 603: }
604:
1.4 cvs 605: /*----------------------------------------------------------------------
1.9 cvs 606: IsWithParameters
607: returns TRUE if url has a concatenated query string.
1.4 cvs 608: ----------------------------------------------------------------------*/
1.3 cvs 609: #ifdef __STDC__
1.66 cvs 610: ThotBool IsWithParameters (const char *url)
1.3 cvs 611: #else /* __STDC__ */
1.66 cvs 612: ThotBool IsWithParameters (url)
1.34 cvs 613: const char *url;
1.3 cvs 614: #endif /* __STDC__ */
615: {
1.5 cvs 616: int i;
1.3 cvs 617:
1.9 cvs 618: if ((!url) || (url[0] == EOS))
1.5 cvs 619: return FALSE;
1.3 cvs 620:
1.9 cvs 621: i = strlen (url) - 1;
622: while (i > 0 && url[i--] != '?')
1.5 cvs 623: if (i < 0)
624: return FALSE;
1.3 cvs 625:
1.5 cvs 626: /* There is a parameter */
627: return TRUE;
1.3 cvs 628: }
629:
1.4 cvs 630: /*----------------------------------------------------------------------
1.9 cvs 631: IsW3Path
632: returns TRUE if path is in fact a URL.
1.4 cvs 633: ----------------------------------------------------------------------*/
1.3 cvs 634: #ifdef __STDC__
1.67 cvs 635: ThotBool IsW3Path (const STRING path)
1.3 cvs 636: #else /* __STDC__ */
1.67 cvs 637: ThotBool IsW3Path (path)
638: const STRING path;
1.3 cvs 639: #endif /* __STDC__ */
640: {
1.72 cvs 641: if (ustrncmp (path, TEXT("http:"), 5) && ustrncmp (path, TEXT("ftp:"), 4) &&
642: ustrncmp (path, TEXT("telnet:"), 7) && ustrncmp (path, TEXT("wais:"), 5) &&
643: ustrncmp (path, TEXT("news:"), 5) && ustrncmp (path, TEXT("gopher:"), 7) &&
644: ustrncmp (path, TEXT("mailto:"), 7) && ustrncmp (path, TEXT("archie:"), 7))
645: return FALSE;
646: return TRUE;
1.3 cvs 647: }
648:
1.4 cvs 649: /*----------------------------------------------------------------------
1.9 cvs 650: IsValidProtocol
651: returns true if the url protocol is supported by Amaya.
1.4 cvs 652: ----------------------------------------------------------------------*/
1.3 cvs 653: #ifdef __STDC__
1.67 cvs 654: ThotBool IsValidProtocol (const STRING url)
1.3 cvs 655: #else /* __STDC__ */
1.67 cvs 656: ThotBool IsValidProtocol (url)
657: const STRING url;
1.3 cvs 658: #endif /* __STDC__ */
659: {
1.67 cvs 660: if (!ustrncmp (url, TEXT("http:"), 5)
1.69 cvs 661: || !ustrncmp (url, TEXT("internal:"), 9)
1.70 cvs 662: || !ustrncmp (url, TEXT("ftp:"), 4))
1.22 cvs 663: /* experimental */
1.58 cvs 664: /*** || !strncmp (url, "ftp:", 4) ***/
1.24 cvs 665: /*** || !strncmp (path, "news:", 5)***/
1.8 cvs 666: return (TRUE);
1.5 cvs 667: else
1.8 cvs 668: return (FALSE);
1.3 cvs 669: }
670:
1.31 cvs 671:
672: /*----------------------------------------------------------------------
673: GetBaseURL
674: normalizes orgName according to a base associated with doc, and
675: following the standard URL format rules.
676: The function returns the base used to solve relative URL and SRC:
677: - the base of the document,
678: - or the document path (without document name).
679: ----------------------------------------------------------------------*/
680: #ifdef __STDC__
1.67 cvs 681: STRING GetBaseURL (Document doc)
1.31 cvs 682: #else /* __STDC__ */
1.67 cvs 683: STRING GetBaseURL (doc)
1.31 cvs 684: Document doc;
685: #endif /* __STDC__ */
686: {
687: Element el;
688: ElementType elType;
689: AttributeType attrType;
690: Attribute attr;
1.67 cvs 691: STRING ptr, basename;
1.31 cvs 692: int length;
693:
1.57 cvs 694: /* @@@ irene */
695: if (!DocumentURLs[doc])
696: return NULL;
1.67 cvs 697: basename = TtaAllocString (MAX_LENGTH);
698: ustrncpy (basename, DocumentURLs[doc], MAX_LENGTH-1);
1.39 cvs 699: basename[MAX_LENGTH-1] = EOS;
1.31 cvs 700: length = MAX_LENGTH -1;
701: /* get the root element */
702: el = TtaGetMainRoot (doc);
703: /* search the BASE element */
704: elType.ElSSchema = TtaGetDocumentSSchema (doc);
1.65 cvs 705: elType.ElTypeNum = HTML_EL_HEAD;
706: el = TtaSearchTypedElement (elType, SearchForward, el);
707: if (el)
708: {
709: elType.ElTypeNum = HTML_EL_BASE;
710: el = TtaSearchTypedElement (elType, SearchInTree, el);
711: }
1.31 cvs 712: if (el)
713: {
714: /* The document has a BASE element -> Get the HREF attribute */
715: attrType.AttrSSchema = elType.ElSSchema;
716: attrType.AttrTypeNum = HTML_ATTR_HREF_;
717: attr = TtaGetAttribute (el, attrType);
718: if (attr)
719: {
720: /* Use the base path of the document */
721: TtaGiveTextAttributeValue (attr, basename, &length);
722: /* base and orgName have to be separated by a DIR_SEP */
723: length--;
1.43 cvs 724: if (basename[0] != EOS && basename[length] != URL_SEP && basename[length] != DIR_SEP)
1.31 cvs 725: /* verify if the base has the form "protocol://server:port" */
726: {
1.67 cvs 727: ptr = AmayaParseUrl (basename, _EMPTYSTR_, AMAYA_PARSE_ACCESS |
1.33 cvs 728: AMAYA_PARSE_HOST |
729: AMAYA_PARSE_PUNCTUATION);
1.67 cvs 730: if (ptr && !ustrcmp (ptr, basename))
1.31 cvs 731: {
1.43 cvs 732: /* it has this form, we complete it by adding a URL_STR */
1.67 cvs 733: if (ustrchr (basename, DIR_SEP))
734: ustrcat (basename, DIR_STR);
1.43 cvs 735: else
1.67 cvs 736: ustrcat (basename, URL_STR);
1.31 cvs 737: length++;
738: }
739: if (ptr)
740: TtaFreeMemory (ptr);
741: }
742: }
1.33 cvs 743: }
744:
1.31 cvs 745: /* Remove anything after the last DIR_SEP char. If no such char is found,
746: * then search for the first ":" char, hoping that what's before that is a
747: * protocol. If found, end the string there. If neither char is found,
748: * then discard the whole base element.
749: */
1.67 cvs 750: length = ustrlen (basename) - 1;
1.31 cvs 751: /* search for the last DIR_SEP char */
1.43 cvs 752: while (length >= 0 && basename[length] != URL_SEP && basename[length] != DIR_SEP)
1.31 cvs 753: length--;
754: if (length >= 0)
755: /* found the last DIR_SEP char, end the string there */
756: basename[length + 1] = EOS;
757: else
758: /* search for the first PATH_STR char */
759: {
1.67 cvs 760: for (length = 0; basename[length] != TEXT(':') &&
1.31 cvs 761: basename[length] != EOS; length ++);
1.67 cvs 762: if (basename[length] == TEXT(':'))
1.31 cvs 763: /* found, so end the string there */
764: basename[length + 1] = EOS;
765: else
766: /* not found, discard the base */
767: basename[0] = EOS;
768: }
769: return (basename);
770: }
771:
772:
1.4 cvs 773: /*----------------------------------------------------------------------
1.40 cvs 774: GetLocalPath
775: Allocate and return the local document path associated to the url
776: ----------------------------------------------------------------------*/
777: #ifdef __STDC__
1.67 cvs 778: STRING GetLocalPath (Document doc, STRING url)
1.40 cvs 779: #else /* __STDC__ */
1.67 cvs 780: STRING GetLocalPath (doc, url)
1.40 cvs 781: Document doc;
1.67 cvs 782: STRING url;
1.40 cvs 783: #endif /* __STDC__ */
784: {
1.67 cvs 785: STRING ptr, n;
786: STRING documentname;
787: CHAR_T url_sep;
1.40 cvs 788: int len;
1.67 cvs 789: ThotBool noFile;
1.40 cvs 790:
791: if (url != NULL)
792: {
793: /* check whether the file name exists */
1.67 cvs 794: len = ustrlen (url) - 1;
1.71 cvs 795: if (IsW3Path (url))
1.67 cvs 796: url_sep = TEXT('/');
1.41 cvs 797: else
798: url_sep = DIR_SEP;
799: noFile = (url[len] == url_sep);
1.40 cvs 800: if (noFile)
801: url[len] = EOS;
1.78 cvs 802: ptr = TtaAllocString (MAX_LENGTH);
803: documentname = TtaAllocString (MAX_LENGTH);
804: TtaExtractName (url, ptr, documentname);
1.67 cvs 805: usprintf (ptr, TEXT("%s%s%d%s"), TempFileDirectory, DIR_STR, doc, DIR_STR);
1.40 cvs 806: if (!TtaCheckDirectory (ptr))
807: /* directory did not exist */
1.72 cvs 808: TtaMakeDirectory (ptr);
1.47 cvs 809:
810: /* don't include the query string within document name */
1.67 cvs 811: n = ustrrchr(documentname, TEXT('?'));
1.47 cvs 812: if (n != NULL)
813: *n = EOS;
1.46 cvs 814: /* don't include ':' within document name */
1.67 cvs 815: n = ustrchr (documentname, TEXT(':'));
1.46 cvs 816: if (n != NULL)
817: *n = EOS;
1.69 cvs 818: /* if after all this operations document name
819: is empty, let's use noname.html instead */
820: if (documentname[0] == EOS)
821: ustrcat (ptr, TEXT("noname.html"));
822: else
823: ustrcat (ptr, documentname);
1.40 cvs 824: TtaFreeMemory (documentname);
825: /* restore the url */
826: if (noFile)
1.41 cvs 827: url[len] = url_sep;
1.40 cvs 828: return (ptr);
829: }
830: else
831: return (NULL);
832: }
833:
1.73 cvs 834: /*----------------------------------------------------------------------
1.79 cvs 835: ExtractTarget extract the target name from document nane.
836: ----------------------------------------------------------------------*/
837: #ifdef __STDC__
838: void ExtractTarget (STRING aName, STRING target)
839: #else
840: void ExtractTarget (aName, target)
841: STRING aName;
842: STRING target;
843: #endif
844: {
845: int lg, i;
846: STRING ptr, oldptr;
847:
848: if (!target || !aName)
849: /* bad target */
850: return;
851:
852: target[0] = EOS;
853: lg = ustrlen (aName);
854: if (lg)
855: {
856: /* the name is not empty */
857: oldptr = ptr = &aName[0];
858: do
859: {
860: ptr = ustrrchr (oldptr, TEXT('#'));
861: if (ptr)
862: oldptr = &ptr[1];
863: }
864: while (ptr);
865:
866: i = (int) (oldptr) - (int) (aName); /* name length */
867: if (i > 1)
868: {
869: aName[i - 1] = EOS;
870: if (i != lg)
871: ustrcpy (target, oldptr);
872: }
873: }
874: }
875:
876: /*----------------------------------------------------------------------
1.73 cvs 877: ConvertFileURL
878: If the URL starts with file: prefix, it removes the protocol so that we
879: can use it as a local filename
880: ----------------------------------------------------------------------*/
881: #ifdef __STDC__
882: void ConvertFileURL (STRING url)
883: #else
884: void ConvertFileURL (url)
885: STRING url
886: #endif /* __STDC__ */
887: {
888: if (!ustrncasecmp (url, TEXT("file:"), 5))
889: ustrcpy (url, url + 5);
890: }
1.40 cvs 891:
892: /*----------------------------------------------------------------------
1.9 cvs 893: NormalizeURL
894: normalizes orgName according to a base associated with doc, and
895: following the standard URL format rules.
1.53 cvs 896: if doc is 0 and otherPath not NULL, normalizes orgName according to this
897: other path.
1.9 cvs 898: The function returns the new complete and normalized URL
1.12 cvs 899: or file name path (newName) and the name of the document (docName).
1.9 cvs 900: N.B. If the function can't find out what's the docName, it assigns
901: the name "noname.html".
1.4 cvs 902: ----------------------------------------------------------------------*/
1.3 cvs 903: #ifdef __STDC__
1.67 cvs 904: void NormalizeURL (STRING orgName, Document doc, STRING newName, STRING docName, STRING otherPath)
1.3 cvs 905: #else /* __STDC__ */
1.53 cvs 906: void NormalizeURL (orgName, doc, newName, docName, otherPath)
1.67 cvs 907: STRING orgName;
1.3 cvs 908: Document doc;
1.67 cvs 909: STRING newName;
910: STRING docName;
911: STRING otherPath;
1.3 cvs 912: #endif /* __STDC__ */
913: {
1.67 cvs 914: STRING basename;
915: CHAR_T tempOrgName[MAX_LENGTH];
916: STRING ptr;
917: CHAR_T used_sep;
918: int length;
1.66 cvs 919: ThotBool check;
1.5 cvs 920:
1.44 cvs 921: # ifdef _WINDOWS
922: int ndx;
923: # endif /* _WINDOWS */
924:
1.5 cvs 925: if (!newName || !docName)
926: return;
1.18 cvs 927:
1.32 cvs 928: if (doc != 0)
1.53 cvs 929: basename = GetBaseURL (doc);
930: else if (otherPath != NULL)
931: basename = TtaStrdup (otherPath);
1.32 cvs 932: else
1.53 cvs 933: basename = NULL;
1.32 cvs 934:
1.18 cvs 935: /*
1.31 cvs 936: * Clean orgName
937: * Make sure we have a complete orgName, without any leading or trailing
938: * white spaces, or trailinbg new lines
939: */
1.5 cvs 940: ptr = orgName;
1.18 cvs 941: /* skip leading white space and new line characters */
1.67 cvs 942: while ((*ptr == SPACE || *ptr == EOL) && *ptr++ != EOS);
943: ustrncpy (tempOrgName, ptr, MAX_LENGTH -1);
1.39 cvs 944: tempOrgName[MAX_LENGTH -1] = EOS;
1.18 cvs 945: /*
1.31 cvs 946: * Make orgName a complete URL
947: * If the URL does not include a protocol, then try to calculate
948: * one using the doc's base element (if it exists),
949: */
1.53 cvs 950: if (tempOrgName[0] == EOS)
951: {
952: newName[0] = EOS;
953: TtaFreeMemory (basename);
954: return;
955: }
1.49 cvs 956:
957: /* clean trailing white space */
1.67 cvs 958: length = ustrlen (tempOrgName) - 1;
1.53 cvs 959: while (tempOrgName[length] == SPACE && tempOrgName[length] == EOL)
960: {
961: tempOrgName[length] = EOS;
962: length--;
963: }
1.50 cvs 964:
1.55 cvs 965: /* remove extra dot (which dot???) */
966: /* ugly, but faster than a strcmp */
1.67 cvs 967: if (tempOrgName[length] == TEXT('.')
968: && (length == 0 || tempOrgName[length-1] != TEXT('.')))
1.55 cvs 969: tempOrgName[length] = EOS;
1.50 cvs 970:
1.53 cvs 971: if (IsW3Path (tempOrgName))
972: {
973: /* the name is complete, go to the Sixth Step */
1.67 cvs 974: ustrcpy (newName, tempOrgName);
1.53 cvs 975: SimplifyUrl (&newName);
976: /* verify if the URL has the form "protocol://server:port" */
1.67 cvs 977: ptr = AmayaParseUrl (newName, _EMPTYSTR_, AMAYA_PARSE_ACCESS | AMAYA_PARSE_HOST | AMAYA_PARSE_PUNCTUATION);
978: if (ptr && !ustrcmp (ptr, newName)) /* it has this form, we complete it by adding a DIR_STR */
979: ustrcat (newName, URL_STR);
1.49 cvs 980:
1.53 cvs 981: if (ptr)
1.50 cvs 982: TtaFreeMemory (ptr);
1.53 cvs 983: }
984: else if ( basename == NULL)
985: /* the name is complete, go to the Sixth Step */
1.67 cvs 986: ustrcpy (newName, tempOrgName);
1.53 cvs 987: else
988: {
1.31 cvs 989: /* Calculate the absolute URL, using the base or document URL */
1.44 cvs 990: # ifdef _WINDOWS
1.53 cvs 991: if (!IsW3Path (basename))
992: {
1.67 cvs 993: length = ustrlen (tempOrgName);
1.53 cvs 994: for (ndx = 0; ndx < length; ndx++)
1.67 cvs 995: if (tempOrgName [ndx] == TEXT('/'))
996: tempOrgName [ndx] = TEXT('\\');
1.53 cvs 997: }
1.44 cvs 998: # endif /* _WINDOWS */
1.25 cvs 999: ptr = AmayaParseUrl (tempOrgName, basename, AMAYA_PARSE_ALL);
1.53 cvs 1000: if (ptr)
1001: {
1002: SimplifyUrl (&ptr);
1.67 cvs 1003: ustrcpy (newName, ptr);
1.53 cvs 1004: TtaFreeMemory (ptr);
1005: }
1006: else
1007: newName[0] = EOS;
1008: }
1.36 cvs 1009:
1010: TtaFreeMemory (basename);
1.18 cvs 1011: /*
1.31 cvs 1012: * Prepare the docname that will refer to this ressource in the
1013: * .amaya directory. If the new URL finishes on DIR_SEP, then use
1014: * noname.html as a default ressource name
1.18 cvs 1015: */
1.53 cvs 1016: if (newName[0] != EOS)
1017: {
1.67 cvs 1018: length = ustrlen (newName) - 1;
1.53 cvs 1019: if (newName[length] == URL_SEP || newName[length] == DIR_SEP)
1020: {
1021: used_sep = newName[length];
1022: check = TRUE;
1023: while (check)
1024: {
1.50 cvs 1025: length--;
1026: while (length >= 0 && newName[length] != used_sep)
1.53 cvs 1027: length--;
1.67 cvs 1028: if (!ustrncmp (&newName[length+1], TEXT(".."), 2))
1.53 cvs 1029: {
1030: newName[length+1] = EOS;
1031: /* remove also previous directory */
1032: length--;
1033: while (length >= 0 && newName[length] != used_sep)
1034: length--;
1.67 cvs 1035: if (ustrncmp (&newName[length+1], TEXT("//"), 2))
1.53 cvs 1036: /* don't remove server name */
1.50 cvs 1037: newName[length+1] = EOS;
1.53 cvs 1038: }
1.67 cvs 1039: else if (!ustrncmp (&newName[length+1], TEXT("."), 1))
1.53 cvs 1040: newName[length+1] = EOS;
1.50 cvs 1041: else
1.53 cvs 1042: check = FALSE;
1043: }
1.67 cvs 1044: ustrcpy (docName, TEXT("noname.html"));
1.53 cvs 1045: /* docname was not comprised inside the URL, so let's */
1046: /* assign the default ressource name */
1.67 cvs 1047: ustrcpy (docName, TEXT("noname.html"));
1.53 cvs 1048: }
1049: else
1050: { /* docname is comprised inside the URL */
1.50 cvs 1051: while (length >= 0 && newName[length] != URL_SEP && newName[length] != DIR_SEP)
1.53 cvs 1052: length--;
1053: if (length < 0)
1.67 cvs 1054: ustrcpy (docName, newName);
1.53 cvs 1055: else
1.67 cvs 1056: ustrcpy (docName, &newName[length+1]);
1.53 cvs 1057: }
1058: }
1059: else
1060: docName[0] = EOS;
1.18 cvs 1061: }
1.3 cvs 1062:
1.4 cvs 1063: /*----------------------------------------------------------------------
1.9 cvs 1064: IsSameHost
1.4 cvs 1065: ----------------------------------------------------------------------*/
1.3 cvs 1066: #ifdef __STDC__
1.67 cvs 1067: ThotBool IsSameHost (const STRING url1, const STRING url2)
1.3 cvs 1068: #else /* __STDC__ */
1.67 cvs 1069: ThotBool IsSameHost (url1, url2)
1070: const STRING url1;
1071: const STRING url2;
1.3 cvs 1072: #endif /* __STDC__ */
1073: {
1.67 cvs 1074: STRING basename_ptr1, basename_ptr2;
1075: ThotBool result;
1.3 cvs 1076:
1.67 cvs 1077: basename_ptr1 = AmayaParseUrl (url1, _EMPTYSTR_, AMAYA_PARSE_ACCESS | AMAYA_PARSE_HOST | AMAYA_PARSE_PUNCTUATION);
1078: basename_ptr2 = AmayaParseUrl (url2, _EMPTYSTR_, AMAYA_PARSE_ACCESS | AMAYA_PARSE_HOST | AMAYA_PARSE_PUNCTUATION);
1.3 cvs 1079:
1.67 cvs 1080: if (ustrcmp (basename_ptr1, basename_ptr2))
1.8 cvs 1081: result = FALSE;
1.5 cvs 1082: else
1.8 cvs 1083: result = TRUE;
1.3 cvs 1084:
1.25 cvs 1085: TtaFreeMemory (basename_ptr1);
1086: TtaFreeMemory (basename_ptr2);
1.5 cvs 1087: return (result);
1.3 cvs 1088: }
1089:
1090:
1.4 cvs 1091: /*----------------------------------------------------------------------
1.22 cvs 1092: HasKnownFileSuffix
1093: returns TRUE if path points to a file ending with a suffix.
1094: ----------------------------------------------------------------------*/
1095: #ifdef __STDC__
1.67 cvs 1096: ThotBool HasKnownFileSuffix (const STRING path)
1.22 cvs 1097: #else /* __STDC__ */
1.67 cvs 1098: ThotBool HasKnownFileSuffix (path)
1099: const STRING path;
1.22 cvs 1100: #endif /* __STDC__ */
1101: {
1.67 cvs 1102: STRING root;
1103: CHAR_T temppath[MAX_LENGTH];
1104: CHAR_T suffix[MAX_LENGTH];
1.22 cvs 1105:
1.67 cvs 1106: if (!path || path[0] == EOS || path[ustrlen(path)] == DIR_SEP)
1.22 cvs 1107: return (FALSE);
1108:
1.67 cvs 1109: root = AmayaParseUrl(path, _EMPTYSTR_, AMAYA_PARSE_PATH | AMAYA_PARSE_PUNCTUATION);
1.22 cvs 1110:
1111: if (root)
1112: {
1.67 cvs 1113: ustrcpy (temppath, root);
1.25 cvs 1114: TtaFreeMemory (root);
1.22 cvs 1115: /* Get the suffix */
1116: ExtractSuffix (temppath, suffix);
1117:
1118: if( suffix[0] == EOS)
1119: /* no suffix */
1120: return (FALSE);
1121:
1122: /* Normalize the suffix */
1123: ConvertToLowerCase (suffix);
1124:
1.67 cvs 1125: if (!ustrcmp (suffix, TEXT("gz")))
1.22 cvs 1126: /* skip the compressed suffix */
1127: {
1128: ExtractSuffix (temppath, suffix);
1129: if(suffix[0] == EOS)
1130: /* no suffix */
1131: return (FALSE);
1132: /* Normalize the suffix */
1133: ConvertToLowerCase (suffix);
1134: }
1135:
1.67 cvs 1136: if (ustrcmp (suffix, TEXT("gif")) &&
1137: ustrcmp (suffix, TEXT("xbm")) &&
1138: ustrcmp (suffix, TEXT("xpm")) &&
1139: ustrcmp (suffix, TEXT("jpg")) &&
1140: ustrcmp (suffix, TEXT("pdf")) &&
1141: ustrcmp (suffix, TEXT("png")) &&
1142: ustrcmp (suffix, TEXT("tgz")) &&
1143: ustrcmp (suffix, TEXT("xpg")) &&
1144: ustrcmp (suffix, TEXT("xpd")) &&
1145: ustrcmp (suffix, TEXT("ps")) &&
1146: ustrcmp (suffix, TEXT("au")) &&
1147: ustrcmp (suffix, TEXT("html")) &&
1148: ustrcmp (suffix, TEXT("htm")) &&
1149: ustrcmp (suffix, TEXT("shtml")) &&
1150: ustrcmp (suffix, TEXT("xht")) &&
1151: ustrcmp (suffix, TEXT("xhtm")) &&
1152: ustrcmp (suffix, TEXT("xhtml")) &&
1153: ustrcmp (suffix, TEXT("txt")) &&
1154: ustrcmp (suffix, TEXT("css")) &&
1155: ustrcmp (suffix, TEXT("eps")))
1.22 cvs 1156: return (FALSE);
1157: else
1158: return (TRUE);
1159: }
1160: else
1161: return (FALSE);
1162: }
1163:
1164:
1165: /*----------------------------------------------------------------------
1.24 cvs 1166: ChopURL
1167: Gives back a URL no longer than MAX_PRINT_URL_LENGTH chars (outputURL).
1168: If inputURL is bigger than that size, outputURL receives
1169: MAX_PRINT_URL_LENGTH / 2 chars from the beginning of inputURL, "...",
1170: and MAX_PRINT_URL_LENGTH / 2 chars from the end of inputURL.
1171: If inputURL is not longer than MAX_PRINT_URL_LENGTH chars, it gets
1172: copied into outputURL.
1173: N.B.: outputURL must point to a memory block of MAX_PRINT_URL_LENGTH
1174: chars.
1175: ----------------------------------------------------------------------*/
1176: #ifdef __STDC__
1.34 cvs 1177: void ChopURL (char *outputURL, const char *inputURL)
1.24 cvs 1178: #else
1179: void ChopURL (outputURL, inputURL)
1.34 cvs 1180: char *outputURL;
1181: const char *inputURL;
1.24 cvs 1182: #endif
1.22 cvs 1183:
1.24 cvs 1184: {
1185: int len;
1.9 cvs 1186:
1.24 cvs 1187: len = strlen (inputURL);
1188: if (len <= MAX_PRINT_URL_LENGTH)
1.29 cvs 1189: strcpy (outputURL, inputURL);
1.24 cvs 1190: else
1191: /* make a truncated urlName on the status window */
1192: {
1193: strncpy (outputURL, inputURL, MAX_PRINT_URL_LENGTH / 2);
1194: outputURL [MAX_PRINT_URL_LENGTH / 2] = EOS;
1195: strcat (outputURL, "...");
1196: strcat (outputURL, &(inputURL[len - MAX_PRINT_URL_LENGTH / 2 ]));
1197: }
1.25 cvs 1198: }
1199:
1200:
1201: /*----------------------------------------------------------------------
1202: scan
1.47 cvs 1203: Scan a filename for its constituents
1.25 cvs 1204: -----------------------------------
1205:
1206: On entry,
1207: name points to a document name which may be incomplete.
1208: On exit,
1209: absolute or relative may be nonzero (but not both).
1210: host, fragment and access may be nonzero if they were specified.
1211: Any which are nonzero point to zero terminated strings.
1212: ----------------------------------------------------------------------*/
1213: #ifdef __STDC__
1.67 cvs 1214: static void scan (STRING name, HTURI * parts)
1.25 cvs 1215: #else /* __STDC__ */
1216: static void scan (name, parts)
1.67 cvs 1217: STRING name;
1218: HTURI *parts;
1.25 cvs 1219:
1220: #endif /* __STDC__ */
1221: {
1.67 cvs 1222: STRING p;
1223: STRING after_access = name;
1.32 cvs 1224:
1.43 cvs 1225: memset (parts, '\0', sizeof (HTURI));
1.28 cvs 1226: /* Look for fragment identifier */
1.67 cvs 1227: if ((p = ustrchr(name, TEXT('#'))) != NULL)
1.28 cvs 1228: {
1.67 cvs 1229: *p++ = TEXT('\0');
1.28 cvs 1230: parts->fragment = p;
1.25 cvs 1231: }
1232:
1.28 cvs 1233: for (p=name; *p; p++)
1234: {
1.67 cvs 1235: if (*p == URL_SEP || *p == DIR_SEP || *p == TEXT('#') || *p == TEXT('?'))
1.28 cvs 1236: break;
1.67 cvs 1237: if (*p == TEXT(':'))
1.28 cvs 1238: {
1239: *p = 0;
1240: parts->access = after_access; /* Scheme has been specified */
1241:
1242: /* The combination of gcc, the "-O" flag and the HP platform is
1243: unhealthy. The following three lines is a quick & dirty fix, but is
1244: not recommended. Rather, turn off "-O". */
1245:
1246: /* after_access = p;*/
1247: /* while (*after_access == 0)*/
1248: /* after_access++;*/
1249: after_access = p+1;
1.67 cvs 1250: if (!ustrcasecmp(TEXT("URL"), parts->access))
1.28 cvs 1251: /* Ignore IETF's URL: pre-prefix */
1252: parts->access = NULL;
1253: else
1.25 cvs 1254: break;
1255: }
1256: }
1257:
1258: p = after_access;
1.43 cvs 1259: if (*p == URL_SEP || *p == DIR_SEP)
1.28 cvs 1260: {
1.43 cvs 1261: if (p[1] == URL_SEP)
1.28 cvs 1262: {
1.25 cvs 1263: parts->host = p+2; /* host has been specified */
1.28 cvs 1264: *p = 0; /* Terminate access */
1265: /* look for end of host name if any */
1.67 cvs 1266: p = ustrchr (parts->host, URL_SEP);
1.28 cvs 1267: if (p)
1268: {
1.43 cvs 1269: *p = EOS; /* Terminate host */
1.25 cvs 1270: parts->absolute = p+1; /* Root has been found */
1.28 cvs 1271: }
1272: }
1273: else
1274: /* Root found but no host */
1275: parts->absolute = p+1;
1276: }
1277: else
1278: {
1.25 cvs 1279: parts->relative = (*after_access) ? after_access : 0; /* zero for "" */
1.28 cvs 1280: }
1.25 cvs 1281: }
1282:
1283:
1284: /*----------------------------------------------------------------------
1.28 cvs 1285: AmayaParseUrl: parse a Name relative to another name
1286:
1287: This returns those parts of a name which are given (and requested)
1288: substituting bits from the related name where necessary.
1.25 cvs 1289:
1.28 cvs 1290: On entry,
1.25 cvs 1291: aName A filename given
1292: relatedName A name relative to which aName is to be parsed. Give
1293: it an empty string if aName is absolute.
1294: wanted A mask for the bits which are wanted.
1295:
1.28 cvs 1296: On exit,
1.25 cvs 1297: returns A pointer to a malloc'd string which MUST BE FREED
1298: ----------------------------------------------------------------------*/
1299: #ifdef __STDC__
1.67 cvs 1300: STRING AmayaParseUrl (const STRING aName, STRING relatedName, int wanted)
1.25 cvs 1301: #else /* __STDC__ */
1.67 cvs 1302: STRING AmayaParseUrl (aName, relatedName, wanted)
1303: const STRING aName;
1304: STRING relatedName;
1.28 cvs 1305: int wanted;
1.25 cvs 1306:
1307: #endif /* __STDC__ */
1308: {
1.67 cvs 1309: STRING return_value;
1310: CHAR_T result[MAX_LENGTH];
1311: CHAR_T name[MAX_LENGTH];
1312: CHAR_T rel[MAX_LENGTH];
1313: STRING p, access;
1.29 cvs 1314: HTURI given, related;
1315: int len;
1.67 cvs 1316: CHAR_T used_sep;
1317: STRING used_str;
1.32 cvs 1318:
1.67 cvs 1319: if (ustrchr (aName, DIR_SEP) || ustrchr (relatedName, DIR_SEP))
1.33 cvs 1320: {
1.42 cvs 1321: used_str = DIR_STR;
1322: used_sep = DIR_SEP;
1.33 cvs 1323: }
1.32 cvs 1324: else
1.33 cvs 1325: {
1.42 cvs 1326: used_str = URL_STR;
1327: used_sep = URL_SEP;
1.33 cvs 1328: }
1.32 cvs 1329:
1.29 cvs 1330: /* Make working copies of input strings to cut up: */
1331: return_value = NULL;
1332: result[0] = 0; /* Clear string */
1.67 cvs 1333: ustrcpy (name, aName);
1.29 cvs 1334: if (relatedName != NULL)
1.67 cvs 1335: ustrcpy (rel, relatedName);
1.29 cvs 1336: else
1337: relatedName[0] = EOS;
1338:
1339: scan (name, &given);
1340: scan (rel, &related);
1341: access = given.access ? given.access : related.access;
1342: if (wanted & AMAYA_PARSE_ACCESS)
1343: if (access)
1344: {
1.67 cvs 1345: ustrcat (result, access);
1.29 cvs 1346: if(wanted & AMAYA_PARSE_PUNCTUATION)
1.67 cvs 1347: ustrcat (result, TEXT(":"));
1.29 cvs 1348: }
1349:
1350: if (given.access && related.access)
1351: /* If different, inherit nothing. */
1.67 cvs 1352: if (ustrcmp (given.access, related.access) != 0)
1.29 cvs 1353: {
1354: related.host = 0;
1355: related.absolute = 0;
1356: related.relative = 0;
1357: related.fragment = 0;
1358: }
1359:
1360: if (wanted & AMAYA_PARSE_HOST)
1361: if(given.host || related.host)
1362: {
1363: if(wanted & AMAYA_PARSE_PUNCTUATION)
1.67 cvs 1364: ustrcat (result, TEXT("//"));
1365: ustrcat (result, given.host ? given.host : related.host);
1.29 cvs 1366: }
1367:
1368: if (given.host && related.host)
1369: /* If different hosts, inherit no path. */
1.67 cvs 1370: if (ustrcmp (given.host, related.host) != 0)
1.29 cvs 1371: {
1372: related.absolute = 0;
1373: related.relative = 0;
1374: related.fragment = 0;
1375: }
1376:
1377: if (wanted & AMAYA_PARSE_PATH)
1378: {
1379: if (given.absolute)
1380: {
1381: /* All is given */
1382: if (wanted & AMAYA_PARSE_PUNCTUATION)
1.67 cvs 1383: ustrcat (result, used_str);
1384: ustrcat (result, given.absolute);
1.25 cvs 1385: }
1.29 cvs 1386: else if (related.absolute)
1387: {
1388: /* Adopt path not name */
1.67 cvs 1389: ustrcat (result, used_str);
1390: ustrcat (result, related.absolute);
1.29 cvs 1391: if (given.relative)
1392: {
1393: /* Search part? */
1.67 cvs 1394: p = ustrchr (result, TEXT('?'));
1.29 cvs 1395: if (!p)
1.67 cvs 1396: p=result+ustrlen(result)-1;
1.33 cvs 1397: for (; *p!=used_sep; p--); /* last / */
1.29 cvs 1398: /* Remove filename */
1399: p[1]=0;
1400: /* Add given one */
1.67 cvs 1401: ustrcat (result, given.relative);
1.25 cvs 1402: }
1403: }
1.29 cvs 1404: else if (given.relative)
1405: /* what we've got */
1.67 cvs 1406: ustrcat (result, given.relative);
1.29 cvs 1407: else if (related.relative)
1.67 cvs 1408: ustrcat (result, related.relative);
1.29 cvs 1409: else
1410: /* No inheritance */
1.67 cvs 1411: ustrcat (result, used_str);
1.25 cvs 1412: }
1.29 cvs 1413:
1414: if (wanted & AMAYA_PARSE_ANCHOR)
1415: if (given.fragment || related.fragment)
1416: {
1417: if (given.absolute && given.fragment)
1418: {
1419: /*Fixes for relURLs...*/
1420: if (wanted & AMAYA_PARSE_PUNCTUATION)
1.67 cvs 1421: ustrcat (result, TEXT("#"));
1422: ustrcat (result, given.fragment);
1.29 cvs 1423: }
1424: else if (!(given.absolute) && !(given.fragment))
1.67 cvs 1425: ustrcat (result, _EMPTYSTR_);
1.29 cvs 1426: else
1427: {
1428: if (wanted & AMAYA_PARSE_PUNCTUATION)
1.67 cvs 1429: ustrcat (result, TEXT("#"));
1430: ustrcat (result, given.fragment ? given.fragment : related.fragment);
1.29 cvs 1431: }
1432: }
1.67 cvs 1433: len = ustrlen (result);
1434: if ((return_value = TtaAllocString (len + 1)) != NULL)
1435: ustrcpy (return_value, result);
1.29 cvs 1436: return (return_value); /* exactly the right length */
1.25 cvs 1437: }
1438:
1439: /*----------------------------------------------------------------------
1440: HTCanon
1441: Canonicalizes the URL in the following manner starting from the host
1442: pointer:
1443:
1444: 1) The host name is converted to lowercase
1445: 2) Chop off port if `:80' (http), `:70' (gopher), or `:21' (ftp)
1446:
1447: Return: OK The position of the current path part of the URL
1448: which might be the old one or a new one.
1449:
1450: ----------------------------------------------------------------------*/
1451: #ifdef __STDC__
1.67 cvs 1452: static STRING HTCanon (STRING* filename, STRING host)
1.25 cvs 1453: #else /* __STDC__ */
1.67 cvs 1454: static STRING HTCanon (filename, host)
1455: STRING *filename;
1456: STRING host;
1.25 cvs 1457: #endif /* __STDC__ */
1458: {
1.67 cvs 1459: STRING newname = NULL;
1460: STRING port;
1461: STRING strptr;
1462: STRING path;
1463: STRING access = host-3;
1464: CHAR_T used_sep;
1.32 cvs 1465:
1466:
1.67 cvs 1467: if (*filename && ustrchr (*filename, URL_SEP))
1.33 cvs 1468: {
1469: used_sep = URL_SEP;
1470: }
1471: else
1472: {
1473: used_sep = DIR_SEP;
1474: }
1.32 cvs 1475:
1.33 cvs 1476: while (access>*filename && *(access-1)!= used_sep) /* Find access method */
1.25 cvs 1477: access--;
1.67 cvs 1478: if ((path = ustrchr(host, used_sep)) == NULL) /* Find path */
1479: path = host + ustrlen(host);
1480: if ((strptr = ustrchr(host, TEXT('@'))) != NULL && strptr<path) /* UserId */
1.25 cvs 1481: host = strptr;
1.67 cvs 1482: if ((port = ustrchr(host, TEXT(':'))) != NULL && port>path) /* Port number */
1.25 cvs 1483: port = NULL;
1484:
1485: strptr = host; /* Convert to lower-case */
1.33 cvs 1486: while (strptr<path)
1487: {
1.25 cvs 1488: *strptr = tolower(*strptr);
1489: strptr++;
1.33 cvs 1490: }
1.25 cvs 1491:
1492: /* Does the URL contain a full domain name? This also works for a
1493: numerical host name. The domain name is already made lower-case
1494: and without a trailing dot. */
1495: {
1.67 cvs 1496: STRING dot = port ? port : path;
1497: if (dot > *filename && *--dot == TEXT('.'))
1.33 cvs 1498: {
1.67 cvs 1499: STRING orig=dot, dest=dot+1;
1.33 cvs 1500: while((*orig++ = *dest++));
1501: if (port) port--;
1502: path--;
1.25 cvs 1503: }
1504: }
1505: /* Chop off port if `:', `:80' (http), `:70' (gopher), or `:21' (ftp) */
1.33 cvs 1506: if (port)
1507: {
1508: if (!*(port+1) || *(port+1)==used_sep)
1509: {
1510: if (!newname)
1511: {
1.67 cvs 1512: STRING orig=port, dest=port+1;
1.25 cvs 1513: while((*orig++ = *dest++));
1.33 cvs 1514: }
1515: }
1.67 cvs 1516: else if ((!ustrncmp(access, TEXT("http"), 4) &&
1517: (*(port+1) == TEXT('8') && *(port+2) == TEXT('0') && (*(port+3) == used_sep || !*(port + 3)))) ||
1518: (!ustrncmp (access, TEXT("gopher"), 6) &&
1519: (*(port+1) == TEXT('7') && *(port+2) == TEXT('0') && (*(port+3) == used_sep || !*(port+3)))) ||
1520: (!ustrncmp(access, TEXT("ftp"), 3) &&
1521: (*(port+1) == TEXT('2') && *(port + 2) == TEXT('1') && (*(port+3) == used_sep || !*(port+3))))) {
1.33 cvs 1522: if (!newname)
1523: {
1.67 cvs 1524: STRING orig=port, dest=port+3;
1.33 cvs 1525: while((*orig++ = *dest++));
1526: /* Update path position, Henry Minsky */
1527: path -= 3;
1.25 cvs 1528: }
1.33 cvs 1529: }
1530: else if (newname)
1.67 cvs 1531: ustrncat(newname, port, (int) (path-port));
1.33 cvs 1532: }
1.25 cvs 1533:
1.33 cvs 1534: if (newname)
1535: {
1.67 cvs 1536: STRING newpath = newname + ustrlen (newname);
1537: ustrcat(newname, path);
1.25 cvs 1538: path = newpath;
1.28 cvs 1539: /* Free old copy */
1540: TtaFreeMemory(*filename);
1.25 cvs 1541: *filename = newname;
1.33 cvs 1542: }
1.25 cvs 1543: return path;
1544: }
1545:
1546:
1547: /*----------------------------------------------------------------------
1.29 cvs 1548: SimplifyUrl: simplify a URI
1.32 cvs 1549: A URI is allowed to contain the sequence xxx/../ which may be
1550: replaced by "" , and the sequence "/./" which may be replaced by DIR_STR.
1.28 cvs 1551: Simplification helps us recognize duplicate URIs.
1.25 cvs 1552:
1.28 cvs 1553: Thus, /etc/junk/../fred becomes /etc/fred
1554: /etc/junk/./fred becomes /etc/junk/fred
1.25 cvs 1555:
1.28 cvs 1556: but we should NOT change
1557: http://fred.xxx.edu/../..
1.25 cvs 1558:
1559: or ../../albert.html
1560:
1.28 cvs 1561: In order to avoid empty URLs the following URLs become:
1.25 cvs 1562:
1563: /fred/.. becomes /fred/..
1564: /fred/././.. becomes /fred/..
1565: /fred/.././junk/.././ becomes /fred/..
1566:
1.28 cvs 1567: If more than one set of `://' is found (several proxies in cascade) then
1568: only the part after the last `://' is simplified.
1.25 cvs 1569:
1.28 cvs 1570: Returns: A string which might be the old one or a new one.
1.25 cvs 1571: ----------------------------------------------------------------------*/
1572: #ifdef __STDC__
1.67 cvs 1573: void SimplifyUrl (STRING* url)
1.25 cvs 1574: #else /* __STDC__ */
1.29 cvs 1575: void SimplifyUrl (url)
1.67 cvs 1576: STRING *url;
1.25 cvs 1577: #endif /* __STDC__ */
1578: {
1.67 cvs 1579: STRING path, p;
1580: STRING newptr, access;
1581: STRING orig, dest, end;
1.28 cvs 1582:
1.67 cvs 1583: CHAR_T used_sep;
1.77 cvs 1584: ThotBool ddot_simplify; /* used to desactivate the double dot simplifcation:
1585: something/../ simplification in relative URLs when they start with a ../ */
1.32 cvs 1586:
1587:
1.28 cvs 1588: if (!url || !*url)
1589: return;
1590:
1.67 cvs 1591: if (ustrchr (*url, URL_SEP))
1.33 cvs 1592: {
1593: used_sep = URL_SEP;
1594: }
1.32 cvs 1595: else
1.33 cvs 1596: {
1597: used_sep = DIR_SEP;
1598: }
1.32 cvs 1599:
1.77 cvs 1600: /* should we simplify double dot? */
1601: path = *url;
1602: if (*path == TEXT('.') && *(path + 1) == TEXT('.'))
1603: ddot_simplify = FALSE;
1604: else
1605: ddot_simplify = TRUE;
1606:
1.28 cvs 1607: /* Find any scheme name */
1.67 cvs 1608: if ((path = ustrstr(*url, TEXT("://"))) != NULL)
1.33 cvs 1609: {
1610: /* Find host name */
1.28 cvs 1611: access = *url;
1612: while (access<path && (*access=tolower(*access)))
1613: access++;
1614: path += 3;
1.67 cvs 1615: while ((newptr = ustrstr(path, TEXT("://"))) != NULL)
1.28 cvs 1616: /* For proxies */
1617: path = newptr+3;
1618: /* We have a host name */
1619: path = HTCanon(url, path);
1.25 cvs 1620: }
1.67 cvs 1621: else if ((path = ustrstr(*url, TEXT(":/"))) != NULL)
1.28 cvs 1622: path += 2;
1623: else
1624: path = *url;
1.25 cvs 1625:
1.33 cvs 1626: if (*path == used_sep && *(path+1)==used_sep)
1.28 cvs 1627: /* Some URLs start //<foo> */
1628: path += 1;
1.67 cvs 1629: else if (!ustrncmp(path, TEXT("news:"), 5))
1.28 cvs 1630: {
1.67 cvs 1631: newptr = ustrchr(path+5, TEXT('@'));
1.28 cvs 1632: if (!newptr)
1633: newptr = path + 5;
1634: while (*newptr)
1635: {
1636: /* Make group or host lower case */
1637: *newptr = tolower (*newptr);
1638: newptr++;
1.25 cvs 1639: }
1.28 cvs 1640: /* Doesn't need to do any more */
1641: return;
1.25 cvs 1642: }
1.28 cvs 1643:
1644: if ((p = path))
1645: {
1.67 cvs 1646: if (!((end = ustrchr (path, TEXT(';'))) || (end = ustrchr (path, TEXT('?'))) ||
1647: (end = ustrchr (path, TEXT('#')))))
1648: end = path + ustrlen (path);
1.28 cvs 1649:
1650: /* Parse string second time to simplify */
1651: p = path;
1652: while (p < end)
1653: {
1.77 cvs 1654: /* if we're pointing to a char, it's safe to reactivate the ../ convertion */
1655: if (!ddot_simplify && *p != TEXT('.') && *p != used_sep)
1656: ddot_simplify = TRUE;
1657:
1.33 cvs 1658: if (*p==used_sep)
1.28 cvs 1659: {
1.67 cvs 1660: if (p > *url && *(p+1) == TEXT('.') && (*(p+2) == used_sep || !*(p+2)))
1.28 cvs 1661: {
1662: orig = p + 1;
1.33 cvs 1663: dest = (*(p+2)!=used_sep) ? p+2 : p+3;
1.52 cvs 1664: while ((*orig++ = *dest++)); /* Remove a used_sep and a dot*/
1.28 cvs 1665: end = orig - 1;
1666: }
1.77 cvs 1667: else if (ddot_simplify && *(p+1) == TEXT('.') && *(p+2) == TEXT('.')
1668: && (*(p+3) == used_sep || !*(p+3)))
1.28 cvs 1669: {
1670: newptr = p;
1.52 cvs 1671: while (newptr>path && *--newptr!=used_sep); /* prev used_sep */
1672: if (*newptr == used_sep)
1673: orig = newptr + 1;
1.28 cvs 1674: else
1.52 cvs 1675: orig = newptr;
1676:
1677: dest = (*(p+3) != used_sep) ? p+3 : p+4;
1678: while ((*orig++ = *dest++)); /* Remove /xxx/.. */
1679: end = orig-1;
1680: /* Start again with prev slash */
1681: p = newptr;
1.28 cvs 1682: }
1.33 cvs 1683: else if (*(p+1) == used_sep)
1.28 cvs 1684: {
1.33 cvs 1685: while (*(p+1) == used_sep)
1.28 cvs 1686: {
1687: orig = p;
1688: dest = p + 1;
1689: while ((*orig++ = *dest++)); /* Remove multiple /'s */
1690: end = orig-1;
1691: }
1692: }
1693: else
1.25 cvs 1694: p++;
1.28 cvs 1695: }
1696: else
1697: p++;
1.25 cvs 1698: }
1699: }
1.51 cvs 1700:
1701: /*
1702: ** Check for host/../.. kind of things
1703: */
1.77 cvs 1704: if (*path == used_sep && *(path+1) == TEXT('.') && *(path+2) == TEXT('.')
1705: && (!*(path+3) || *(path+3) == used_sep))
1.51 cvs 1706: *(path+1) = EOS;
1707:
1.28 cvs 1708: return;
1709: }
1710:
1711:
1712: /*----------------------------------------------------------------------
1713: NormalizeFile normalizes local names.
1714: Return TRUE if target and src differ.
1715: ----------------------------------------------------------------------*/
1716: #ifdef __STDC__
1.67 cvs 1717: ThotBool NormalizeFile (STRING src, STRING target)
1.28 cvs 1718: #else
1.67 cvs 1719: ThotBool NormalizeFile (src, target)
1720: STRING src;
1721: STRING target;
1.28 cvs 1722:
1723: #endif
1724: {
1.67 cvs 1725: STRING s;
1.66 cvs 1726: ThotBool change;
1.28 cvs 1727:
1.54 cvs 1728: change = FALSE;
1.67 cvs 1729: if (ustrncmp (src, TEXT("file:"), 5) == 0)
1.28 cvs 1730: {
1731: /* remove the prefix file: */
1732: if (src[5] == EOS)
1.67 cvs 1733: ustrcpy (target, DIR_STR);
1734: else if (src[0] == TEXT('~'))
1.28 cvs 1735: {
1736: /* replace ~ */
1.74 cvs 1737: s = TtaGetEnvString ("HOME");
1.67 cvs 1738: ustrcpy (target, s);
1739: ustrcat (target, &src[5]);
1.28 cvs 1740: }
1741: else
1.67 cvs 1742: ustrcpy (target, &src[5]);
1.54 cvs 1743: change = TRUE;
1.28 cvs 1744: }
1.53 cvs 1745: # ifndef _WINDOWS
1.67 cvs 1746: else if (src[0] == TEXT('~'))
1.53 cvs 1747: {
1748: /* replace ~ */
1749: s = (char *) TtaGetEnvString ("HOME");
1750: strcpy (target, s);
1751: if (src[1] != DIR_SEP)
1752: strcat (target, DIR_STR);
1753: strcat (target, &src[1]);
1.54 cvs 1754: change = TRUE;
1.53 cvs 1755: }
1756: # endif /* _WINDOWS */
1.28 cvs 1757: else
1.67 cvs 1758: ustrcpy (target, src);
1.28 cvs 1759:
1760: /* remove /../ and /./ */
1.29 cvs 1761: SimplifyUrl (&target);
1.54 cvs 1762: if (!change)
1.67 cvs 1763: change = ustrcmp (src, target);
1.28 cvs 1764: return (change);
1.25 cvs 1765: }
1766:
1.28 cvs 1767:
1.25 cvs 1768: /*----------------------------------------------------------------------
1.31 cvs 1769: MakeRelativeURL: make relative name
1.25 cvs 1770:
1.28 cvs 1771: This function creates and returns a string which gives an expression of
1772: one address as related to another. Where there is no relation, an absolute
1773: address is retured.
1.25 cvs 1774:
1.28 cvs 1775: On entry,
1.25 cvs 1776: Both names must be absolute, fully qualified names of nodes
1777: (no fragment bits)
1778:
1.28 cvs 1779: On exit,
1.25 cvs 1780: The return result points to a newly allocated name which, if
1781: parsed by AmayaParseUrl relative to relatedName, will yield aName.
1782: The caller is responsible for freeing the resulting name later.
1783: ----------------------------------------------------------------------*/
1784: #ifdef __STDC__
1.67 cvs 1785: STRING MakeRelativeURL (STRING aName, STRING relatedName)
1.25 cvs 1786: #else /* __STDC__ */
1.67 cvs 1787: STRING MakeRelativeURL (aName, relatedName)
1788: STRING aName;
1789: STRING relatedName;
1.25 cvs 1790: #endif /* __STDC__ */
1791: {
1.67 cvs 1792: STRING return_value;
1793: CHAR_T result[MAX_LENGTH];
1794: STRING p;
1795: STRING q;
1796: STRING after_access;
1797: STRING last_slash = NULL;
1.29 cvs 1798: int slashes, levels, len;
1799:
1.44 cvs 1800: # ifdef _WINDOWS
1801: int ndx;
1802: # endif /* _WINDOWS */
1803:
1.29 cvs 1804: if (aName == NULL || relatedName == NULL)
1805: return (NULL);
1806:
1807: slashes = 0;
1808: after_access = NULL;
1809: p = aName;
1810: q = relatedName;
1811: for (; *p && (*p == *q); p++, q++)
1.27 cvs 1812: {
1813: /* Find extent of match */
1.67 cvs 1814: if (*p == TEXT(':'))
1.29 cvs 1815: after_access = p + 1;
1.28 cvs 1816: if (*p == DIR_SEP)
1.27 cvs 1817: {
1.29 cvs 1818: /* memorize the last slash position and count them */
1.27 cvs 1819: last_slash = p;
1820: slashes++;
1.25 cvs 1821: }
1822: }
1823:
1.31 cvs 1824: /* q, p point to the first non-matching character or zero */
1825: if (*q == EOS)
1826: {
1827: /* New name is a subset of the related name */
1828: /* exactly the right length */
1.67 cvs 1829: len = ustrlen (p);
1830: if ((return_value = TtaAllocString (len + 1)) != NULL)
1831: ustrcpy (return_value, p);
1.31 cvs 1832: }
1833: else if ((slashes < 2 && after_access == NULL)
1834: || (slashes < 3 && after_access != NULL))
1835: {
1836: /* Two names whitout common path */
1837: /* exactly the right length */
1.67 cvs 1838: len = ustrlen (aName);
1839: if ((return_value = TtaAllocString (len + 1)) != NULL)
1840: ustrcpy (return_value, aName);
1.31 cvs 1841: }
1842: else
1843: {
1844: /* Some path in common */
1.67 cvs 1845: if (slashes == 3 && ustrncmp (aName, TEXT("http:"), 5) == 0)
1.31 cvs 1846: /* just the same server */
1.67 cvs 1847: ustrcpy (result, last_slash);
1.31 cvs 1848: else
1849: {
1850: levels= 0;
1.67 cvs 1851: for (; *q && *q != TEXT('#') && *q != TEXT(';') && *q != TEXT('?'); q++)
1.31 cvs 1852: if (*q == DIR_SEP)
1853: levels++;
1854:
1.52 cvs 1855: result[0] = EOS;
1.31 cvs 1856: for (;levels; levels--)
1.67 cvs 1857: ustrcat (result, TEXT("../"));
1858: ustrcat (result, last_slash+1);
1.31 cvs 1859: }
1.52 cvs 1860:
1861: if (!*result)
1.67 cvs 1862: ustrcat (result, TEXT("./"));
1.52 cvs 1863:
1.31 cvs 1864: /* exactly the right length */
1.67 cvs 1865: len = ustrlen (result);
1866: if ((return_value = TtaAllocString (len + 1)) != NULL)
1867: ustrcpy (return_value, result);
1.52 cvs 1868:
1.25 cvs 1869: }
1.44 cvs 1870: # ifdef _WINDOWS
1.67 cvs 1871: len = ustrlen (return_value);
1.44 cvs 1872: for (ndx = 0; ndx < len; ndx ++)
1.67 cvs 1873: if (return_value[ndx] == TEXT('\\'))
1874: return_value[ndx] = TEXT('/') ;
1.44 cvs 1875: # endif /* _WINDOWS */
1.29 cvs 1876: return (return_value);
1.24 cvs 1877: }
1.35 cvs 1878:
1879:
Webmaster