Annotation of Amaya/amaya/AHTURLTools.c, revision 1.30
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
14: *
15: */
1.7 cvs 16:
1.15 cvs 17: #define THOT_EXPORT extern
1.3 cvs 18: #include "amaya.h"
19:
1.8 cvs 20: #include "init_f.h"
21: #include "AHTURLTools_f.h"
22:
1.24 cvs 23: #define MAX_PRINT_URL_LENGTH 50
1.29 cvs 24: typedef struct _HTURI {
25: char * access; /* Now known as "scheme" */
26: char * host;
27: char * absolute;
28: char * relative;
29: char * fragment;
30: } HTURI;
1.24 cvs 31:
1.28 cvs 32:
33: /*----------------------------------------------------------------------
34: ConvertToLowerCase
35: Converts a string to lowercase.
36: ----------------------------------------------------------------------*/
1.22 cvs 37: #ifdef __STDC__
1.28 cvs 38: static void ConvertToLowerCase (char *string)
39: #else /* __STDC__ */
40: static void ConvertToLowerCase (string)
41: char *string;
42:
43: #endif /* __STDC__ */
44: {
45: int i;
46:
47: if (!string)
48: return;
49:
50: for (i = 0; string[i] != EOS; i++)
51: string[i] = tolower (string[i]);
52: }
1.22 cvs 53:
1.8 cvs 54: /*----------------------------------------------------------------------
1.11 cvs 55: ExplodeURL
1.8 cvs 56: ----------------------------------------------------------------------*/
57: #ifdef __STDC__
58: void ExplodeURL (char *url, char **proto, char **host, char **dir, char **file)
59: #else
60: void ExplodeURL (url, proto, host, dir, file)
61: char *url;
62: char **proto;
63: char **host;
64: char **dir;
65: char **file;
66:
67: #endif
68: {
1.9 cvs 69: char *curr, *temp;
1.8 cvs 70:
71: if ((url == NULL) || (proto == NULL) || (host == NULL) ||
72: (dir == NULL) || (file == NULL))
73: return;
74:
75: /* initialize every pointer */
76: *proto = *host = *dir = *file = NULL;
77:
78: /* skip any leading space */
79: while ((*url == SPACE) || (*url == TAB))
80: url++;
1.9 cvs 81: curr = url;
82: if (*curr == 0)
1.8 cvs 83: goto finished;
84:
85: /* go to the end of the URL */
1.9 cvs 86: while ((*curr != 0) && (*curr != SPACE) && (*curr != '\b') &&
87: (*curr != '\r') && (*curr != EOL))
88: curr++;
1.8 cvs 89:
90: /* mark the end of the chain */
1.9 cvs 91: *curr = EOS;
92: curr--;
93: if (curr <= url)
1.8 cvs 94: goto finished;
95:
96: /* search the next DIR_SEP indicating the beginning of the file name */
97: do
1.11 cvs 98: curr--;
1.9 cvs 99: while ((curr >= url) && (*curr != DIR_SEP));
1.11 cvs 100:
1.9 cvs 101: if (curr < url)
1.8 cvs 102: goto finished;
1.9 cvs 103: *file = curr + 1;
1.8 cvs 104:
105: /* mark the end of the dir */
1.9 cvs 106: *curr = EOS;
107: curr--;
108: if (curr < url)
1.8 cvs 109: goto finished;
110:
1.29 cvs 111: /* search for the DIR_STR indicating the host name start */
1.9 cvs 112: while ((curr > url) && ((*curr != DIR_SEP) || (*(curr + 1) != DIR_SEP)))
113: curr--;
1.8 cvs 114:
115: /* if we found it, separate the host name from the directory */
1.9 cvs 116: if ((*curr == DIR_SEP) && (*(curr + 1) == DIR_SEP))
1.8 cvs 117: {
1.9 cvs 118: *host = temp = curr + 2;
1.8 cvs 119: while ((*temp != 0) && (*temp != DIR_SEP))
120: temp++;
121: if (*temp == DIR_SEP)
122: {
123: *temp = EOS;
124: *dir = temp + 1;
125: }
126: }
127: else
1.11 cvs 128: *dir = curr;
129:
1.9 cvs 130: if (curr <= url)
1.8 cvs 131: goto finished;
132:
133: /* mark the end of the proto */
1.9 cvs 134: *curr = EOS;
135: curr--;
136: if (curr < url)
1.8 cvs 137: goto finished;
138:
1.29 cvs 139: if (*curr == PATH_SEP)
1.8 cvs 140: {
1.9 cvs 141: *curr = EOS;
142: curr--;
1.8 cvs 143: }
144: else
145: goto finished;
1.11 cvs 146:
1.9 cvs 147: if (curr < url)
1.8 cvs 148: goto finished;
1.9 cvs 149: while ((curr > url) && (isalpha (*curr)))
150: curr--;
151: *proto = curr;
1.8 cvs 152:
153: finished:;
154:
155: #ifdef AMAYA_DEBUG
156: fprintf (stderr, "ExplodeURL(%s)\n\t", url);
157: if (*proto)
158: fprintf (stderr, "proto : %s, ", *proto);
159: if (*host)
160: fprintf (stderr, "host : %s, ", *host);
161: if (*dir)
162: fprintf (stderr, "dir : %s, ", *dir);
163: if (*file)
164: fprintf (stderr, "file : %s ", *file);
165: fprintf (stderr, "\n");
166: #endif
167:
168: }
1.3 cvs 169:
1.4 cvs 170: /*----------------------------------------------------------------------
1.9 cvs 171: IsHTMLName
172: returns TRUE if path points to an HTML resource.
1.4 cvs 173: ----------------------------------------------------------------------*/
1.3 cvs 174: #ifdef __STDC__
175: boolean IsHTMLName (char *path)
176: #else /* __STDC__ */
177: boolean IsHTMLName (path)
178: char *path;
179: #endif /* __STDC__ */
180: {
1.5 cvs 181: char temppath[MAX_LENGTH];
182: char suffix[MAX_LENGTH];
183: char nsuffix[MAX_LENGTH];
184: int i;
185:
186: if (!path)
1.13 cvs 187: return (FALSE);
1.5 cvs 188:
189: strcpy (temppath, path);
190: ExtractSuffix (temppath, suffix);
191:
192: /* Normalize the suffix */
193: i = 0;
194: while (suffix[i] != EOS)
1.13 cvs 195: {
1.25 cvs 196: nsuffix[i] = tolower (suffix[i]);
1.13 cvs 197: i++;
198: }
1.5 cvs 199: nsuffix[i] = EOS;
200: if ((strcmp (nsuffix, "html")) &&
201: (strcmp (nsuffix, "htm")) &&
202: (strcmp (nsuffix, "shtml")))
1.13 cvs 203: return (FALSE);
1.22 cvs 204: else if (!strcmp (nsuffix, "gz"))
1.13 cvs 205: {
206: /* take in account compressed files */
207: ExtractSuffix (temppath, suffix);
208: /* Normalize the suffix */
209: i = 0;
210: while (suffix[i] != EOS)
211: {
1.25 cvs 212: nsuffix[i] = tolower (suffix[i]);
1.13 cvs 213: i++;
214: }
215: nsuffix[i] = EOS;
216: if ((strcmp (nsuffix, "html")) &&
217: (strcmp (nsuffix, "htm")) &&
218: (strcmp (nsuffix, "shtml")))
219: return (FALSE);
220: else
221: return (TRUE);
222: }
223: else
224: return (TRUE);
1.3 cvs 225: }
226:
1.4 cvs 227: /*----------------------------------------------------------------------
1.9 cvs 228: IsImageName
229: returns TRUE if path points to an image resource.
1.4 cvs 230: ----------------------------------------------------------------------*/
1.3 cvs 231: #ifdef __STDC__
232: boolean IsImageName (char *path)
233: #else /* __STDC__ */
234: boolean IsImageName (path)
235: char *path;
236: #endif /* __STDC__ */
237: {
1.5 cvs 238: char temppath[MAX_LENGTH];
239: char suffix[MAX_LENGTH];
240: char nsuffix[MAX_LENGTH];
241: int i;
242:
243: if (!path)
1.13 cvs 244: return (FALSE);
1.5 cvs 245:
246: strcpy (temppath, path);
247: ExtractSuffix (temppath, suffix);
248:
249: /* Normalize the suffix */
250: i = 0;
251: while (suffix[i] != EOS)
1.13 cvs 252: {
1.25 cvs 253: nsuffix[i] = tolower (suffix[i]);
1.13 cvs 254: i++;
255: }
1.5 cvs 256: nsuffix[i] = EOS;
257: if ((strcmp (nsuffix, "gif")) && (strcmp (nsuffix, "xbm")) &&
258: (strcmp (nsuffix, "xpm")) && (strcmp (nsuffix, "jpg")) &&
259: (strcmp (nsuffix, "png")) && (strcmp (nsuffix, "au")))
1.13 cvs 260: return (FALSE);
261: return (TRUE);
1.3 cvs 262: }
263:
1.4 cvs 264: /*----------------------------------------------------------------------
1.9 cvs 265: IsTextName
1.4 cvs 266: ----------------------------------------------------------------------*/
1.3 cvs 267: #ifdef __STDC__
268: boolean IsTextName (char *path)
269: #else /* __STDC__ */
270: boolean IsTextName (path)
271: char *path;
272:
273: #endif /* __STDC__ */
274: {
1.5 cvs 275: char temppath[MAX_LENGTH];
276: char suffix[MAX_LENGTH];
277: char nsuffix[MAX_LENGTH];
278: int i;
279:
280: if (!path)
1.13 cvs 281: return (FALSE);
1.5 cvs 282:
283: strcpy (temppath, path);
284: ExtractSuffix (temppath, suffix);
285:
286: /* Normalize the suffix */
287: i = 0;
288: while (suffix[i] != EOS)
289: {
1.25 cvs 290: nsuffix[i] = tolower (suffix[i]);
1.5 cvs 291: i++;
292: }
293: nsuffix[i] = EOS;
294:
295: if ((strcmp (nsuffix, "gif")) && (strcmp (nsuffix, "xbm")) &&
296: (strcmp (nsuffix, "xpm")) && (strcmp (nsuffix, "jpg")) &&
297: (strcmp (nsuffix, "pdf")) && (strcmp (nsuffix, "png")) &&
1.22 cvs 298: (strcmp (nsuffix, "tgz")) && (strcmp (nsuffix, "tar")) &&
299: (strcmp (nsuffix, "xpg")) && (strcmp (nsuffix, "xpd")) &&
300: (strcmp (nsuffix, "ps")) && (strcmp (nsuffix, "au")))
1.13 cvs 301: return (TRUE);
1.22 cvs 302: else if (!strcmp (nsuffix, "gz"))
1.13 cvs 303: {
304: /* take in account compressed files */
305: ExtractSuffix (temppath, suffix);
306: /* Normalize the suffix */
307: i = 0;
308: while (suffix[i] != EOS)
309: {
1.25 cvs 310: nsuffix[i] = tolower (suffix[i]);
1.13 cvs 311: i++;
312: }
313: nsuffix[i] = EOS;
314: if ((!strcmp (nsuffix, "html")) ||
315: (!strcmp (nsuffix, "htm")) ||
316: (!strcmp (nsuffix, "shtml")))
317: return (TRUE);
318: else
319: return (FALSE);
320: }
321: else
322: return (FALSE);
1.3 cvs 323: }
324:
1.4 cvs 325: /*----------------------------------------------------------------------
1.9 cvs 326: IsHTTPPath
327: returns TRUE if path is in fact an http URL.
1.4 cvs 328: ----------------------------------------------------------------------*/
1.3 cvs 329: #ifdef __STDC__
330: boolean IsHTTPPath (char *path)
331: #else /* __STDC__ */
332: boolean IsHTTPPath (path)
333: char *path;
334: #endif /* __STDC__ */
335: {
1.5 cvs 336: if (!path)
337: return FALSE;
1.3 cvs 338:
1.5 cvs 339: if (strncmp (path, "http:", 5) != 0)
340: return FALSE;
341: return TRUE;
1.3 cvs 342: }
343:
1.4 cvs 344: /*----------------------------------------------------------------------
1.9 cvs 345: IsWithParameters
346: returns TRUE if url has a concatenated query string.
1.4 cvs 347: ----------------------------------------------------------------------*/
1.3 cvs 348: #ifdef __STDC__
1.9 cvs 349: boolean IsWithParameters (char *url)
1.3 cvs 350: #else /* __STDC__ */
1.9 cvs 351: boolean IsWithParameters (url)
352: char *url;
1.3 cvs 353: #endif /* __STDC__ */
354: {
1.5 cvs 355: int i;
1.3 cvs 356:
1.9 cvs 357: if ((!url) || (url[0] == EOS))
1.5 cvs 358: return FALSE;
1.3 cvs 359:
1.9 cvs 360: i = strlen (url) - 1;
361: while (i > 0 && url[i--] != '?')
1.5 cvs 362: if (i < 0)
363: return FALSE;
1.3 cvs 364:
1.5 cvs 365: /* There is a parameter */
366: return TRUE;
1.3 cvs 367: }
368:
1.4 cvs 369: /*----------------------------------------------------------------------
1.9 cvs 370: IsW3Path
371: returns TRUE if path is in fact a URL.
1.4 cvs 372: ----------------------------------------------------------------------*/
1.3 cvs 373: #ifdef __STDC__
374: boolean IsW3Path (char *path)
375: #else /* __STDC__ */
376: boolean IsW3Path (path)
377: char *path;
378: #endif /* __STDC__ */
379: {
1.5 cvs 380: if ((strncmp (path, "http:", 5)) && (strncmp (path, "ftp:", 4)) &&
381: (strncmp (path, "telnet:", 7)) && (strncmp (path, "wais:", 5)) &&
382: (strncmp (path, "news:", 5)) && (strncmp (path, "gopher:", 7)) &&
383: (strncmp (path, "mailto:", 7)) && (strncmp (path, "archie:", 7)))
384: return FALSE;
385: return TRUE;
1.3 cvs 386: }
387:
1.4 cvs 388: /*----------------------------------------------------------------------
1.9 cvs 389: IsValidProtocol
390: returns true if the url protocol is supported by Amaya.
1.4 cvs 391: ----------------------------------------------------------------------*/
1.3 cvs 392: #ifdef __STDC__
1.9 cvs 393: boolean IsValidProtocol (char *url)
1.3 cvs 394: #else /* __STDC__ */
1.9 cvs 395: boolean IsValidProtocol (url)
396: char *url;
1.3 cvs 397: #endif /* __STDC__ */
398: {
1.26 cvs 399: if (!strncmp (url, "http:", 5))
1.22 cvs 400: /* experimental */
1.26 cvs 401: /*** || !strncmp (url, "ftp:", 4)) ***/
1.24 cvs 402: /*** || !strncmp (path, "news:", 5)***/
1.8 cvs 403: return (TRUE);
1.5 cvs 404: else
1.8 cvs 405: return (FALSE);
1.3 cvs 406: }
407:
1.4 cvs 408: /*----------------------------------------------------------------------
1.9 cvs 409: NormalizeURL
410: normalizes orgName according to a base associated with doc, and
411: following the standard URL format rules.
412: The function returns the new complete and normalized URL
1.12 cvs 413: or file name path (newName) and the name of the document (docName).
1.9 cvs 414: N.B. If the function can't find out what's the docName, it assigns
415: the name "noname.html".
1.4 cvs 416: ----------------------------------------------------------------------*/
1.3 cvs 417: #ifdef __STDC__
418: void NormalizeURL (char *orgName, Document doc, char *newName, char *docName)
419: #else /* __STDC__ */
420: void NormalizeURL (orgName, doc, newName, docName)
421: char *orgName;
422: Document doc;
423: char *newName;
424: char *docName;
425: #endif /* __STDC__ */
426: {
1.5 cvs 427: char basename[MAX_LENGTH];
1.18 cvs 428: char tempOrgName[MAX_LENGTH];
1.5 cvs 429: char *ptr;
430: Element el;
431: ElementType elType;
432: AttributeType attrType;
1.18 cvs 433: Attribute attrHREF = NULL;
1.5 cvs 434: int length;
435:
436: if (!newName || !docName)
437: return;
1.18 cvs 438:
439: /*
440: ** First Step: Clean orgName
441: ** Make sure we have a complete orgName, without any leading or trailing
442: ** white spaces, or trailinbg new lines
443: */
444:
1.5 cvs 445: ptr = orgName;
1.18 cvs 446: /* skip leading white space and new line characters */
1.19 cvs 447: while ((*ptr == ' ' || *ptr == EOL) && *ptr++ != EOS);
1.18 cvs 448: strcpy (tempOrgName, ptr);
449: /* clean trailing white space */
450: ptr = strchr (tempOrgName, ' ');
451: if (ptr)
452: *ptr = EOS;
453: /* clean trailing new lines */
1.19 cvs 454: ptr = strchr (tempOrgName, EOL);
1.5 cvs 455: if (ptr)
456: *ptr = EOS;
457:
1.18 cvs 458: /*
459: ** Second Step: make orgName a complete URL
460: ** If the URL does not include a protocol, then
461: ** try to calculate one using the doc's base element
462: ** (if it exists),
463: */
1.21 cvs 464: if (tempOrgName[0] == EOS)
465: {
466: newName[0] = EOS;
467: return;
468: }
469: else if (IsW3Path (tempOrgName))
470: {
471: /* the name is complete, go to the Sixth Step */
472: strcpy (newName, tempOrgName);
473: /* verify if the URL has the form "protocol://server:port" */
1.25 cvs 474: ptr = AmayaParseUrl (newName, "", AMAYA_PARSE_ACCESS | AMAYA_PARSE_HOST |
475: AMAYA_PARSE_PUNCTUATION);
1.21 cvs 476: if (ptr && !strcmp (ptr, newName))
477: {
1.29 cvs 478: /* it has this form, we complete it by adding a DIR_STR */
479: strcat (newName, DIR_STR);
1.21 cvs 480: }
481: if (ptr)
1.25 cvs 482: TtaFreeMemory (ptr);
1.21 cvs 483: }
484: else if ( doc == 0)
1.19 cvs 485: /* the name is complete, go to the Sixth Step */
1.18 cvs 486: strcpy (newName, tempOrgName);
1.5 cvs 487: else
488: {
1.18 cvs 489: /* take into account the BASE element. */
1.22 cvs 490: length = MAX_LENGTH -1;
1.18 cvs 491: /* get the root element */
492: el = TtaGetMainRoot (doc);
493:
494: /* search the BASE element */
495: elType.ElSSchema = TtaGetDocumentSSchema (doc);
496: elType.ElTypeNum = HTML_EL_BASE;
497: el = TtaSearchTypedElement (elType, SearchInTree, el);
498: if (el)
1.17 cvs 499: {
1.18 cvs 500: /*
501: ** The document has a BASE element
502: ** Get the HREF attribute of the BASE Element
503: */
504: attrType.AttrSSchema = elType.ElSSchema;
505: attrType.AttrTypeNum = HTML_ATTR_HREF_;
506: attrHREF = TtaGetAttribute (el, attrType);
507: if (attrHREF)
1.14 cvs 508: {
1.18 cvs 509: /* Use the base path of the document */
510: TtaGiveTextAttributeValue (attrHREF, basename, &length);
511: /* base and orgName have to be separated by a DIR_SEP */
1.20 cvs 512: length--;
1.28 cvs 513: if (basename[0] != EOS && basename[length] != DIR_SEP)
1.18 cvs 514: /* verify if the base has the form "protocol://server:port" */
1.14 cvs 515: {
1.25 cvs 516: ptr = AmayaParseUrl (basename, "", AMAYA_PARSE_ACCESS | AMAYA_PARSE_HOST |
517: AMAYA_PARSE_PUNCTUATION);
1.18 cvs 518: if (ptr && !strcmp (ptr, basename))
1.14 cvs 519: {
1.29 cvs 520: /* it has this form, we complete it by adding a DIR_STR */
521: strcat (basename, DIR_STR);
1.18 cvs 522: length++;
1.14 cvs 523: }
1.18 cvs 524: if (ptr)
1.25 cvs 525: TtaFreeMemory (ptr);
1.14 cvs 526: }
1.19 cvs 527: /* Third Step: prepare the base
528: ** Removing anything after the
529: ** last DIR_SEP char. If no such char is found, then search for
530: ** the first ":" char, hoping that what's before that is a
531: ** protocol. If found, end the string there. If neither
532: ** char is found, then discard the whole base element.
533: */
534:
535: /* search for the last DIR_SEP char */
1.18 cvs 536: while (length >= 0 && basename[length] != DIR_SEP)
1.19 cvs 537: length--;
538: if (length >= 0)
539: /* found the last DIR_SEP char, end the string there */
540: basename[length + 1] = EOS;
541: else
1.29 cvs 542: /* search for the first PATH_STR char */
1.19 cvs 543: {
1.29 cvs 544: for (length = 0; basename[length] != PATH_SEP &&
1.20 cvs 545: basename[length] != EOS; length++);
1.29 cvs 546: if (basename[length] == PATH_SEP)
1.19 cvs 547: /* found, so end the string there */
548: basename[length + 1] = EOS;
549: else
550: /* not found, discard the base */
551: basename[0] = EOS;
552: }
1.14 cvs 553: }
554: else
555: basename[0] = EOS;
1.18 cvs 556: }
1.22 cvs 557:
1.18 cvs 558: /*
1.19 cvs 559: ** Fourth Step:
1.18 cvs 560: ** If there's no base element, and if we're following
1.19 cvs 561: ** a link, use the URL of the current document as a base.
1.18 cvs 562: */
563:
564: if (!attrHREF)
565: {
566: if (DocumentURLs[(int) doc])
1.14 cvs 567: {
1.18 cvs 568: strcpy (basename, DocumentURLs[(int) doc]);
569: /* base and orgName have to be separated by a DIR_SEP */
570: length = strlen (basename) - 1;
1.19 cvs 571: /* search for the last DIR_SEP char */
1.18 cvs 572: while (length >= 0 && basename[length] != DIR_SEP)
1.19 cvs 573: length--;
574: if (length >= 0)
575: /* found the last DIR_SEP char, end the string there */
576: basename[length + 1] = EOS;
577: else
1.29 cvs 578: /* search for the first PATH_STR char */
1.19 cvs 579: {
1.29 cvs 580: for (length = 0; basename[length] != PATH_SEP &&
1.19 cvs 581: basename[length] != EOS; length ++);
1.29 cvs 582: if (basename[length] == PATH_SEP)
1.19 cvs 583: /* found, so end the string there */
584: basename[length + 1] = EOS;
585: else
586: /* not found, discard the base */
587: basename[0] = EOS;
588: }
1.14 cvs 589: }
590: else
1.19 cvs 591: basename[0] = EOS;
1.14 cvs 592: }
1.22 cvs 593:
1.18 cvs 594: /*
1.19 cvs 595: ** Fifth Step, calculate the absolute URL, using the base
1.18 cvs 596: */
597:
1.25 cvs 598: ptr = AmayaParseUrl (tempOrgName, basename, AMAYA_PARSE_ALL);
1.16 cvs 599:
1.14 cvs 600: if (ptr)
601: {
1.29 cvs 602: SimplifyUrl (&ptr);
1.14 cvs 603: strcpy (newName, ptr);
1.25 cvs 604: TtaFreeMemory (ptr);
1.14 cvs 605: }
606: else
1.18 cvs 607: newName[0] = EOS;
1.5 cvs 608: }
609:
1.18 cvs 610: /*
1.19 cvs 611: ** Sixth and last Step:
1.18 cvs 612: ** Prepare the docname that will refer to this ressource in the
1.19 cvs 613: ** .amaya directory. If the new URL finishes on DIR_SEP, then use
1.18 cvs 614: ** noname.html as a default ressource name
615: */
1.19 cvs 616:
617: if (newName[0] != EOS)
1.5 cvs 618: {
1.19 cvs 619: length = strlen (newName) - 1;
1.18 cvs 620: if (newName[length] == DIR_SEP)
621: {
622: /* docname was not comprised inside the URL, so let's */
623: /* assign the default ressource name */
624: strcpy (docName, "noname.html");
625: /* remove DIR_SEP at the end of complete path */
1.23 cvs 626: /* newName[length] = EOS; */
1.18 cvs 627: }
1.14 cvs 628: else
1.18 cvs 629: {
630: /* docname is comprised inside the URL */
631: while (length >= 0 && newName[length] != DIR_SEP)
632: length--;
633: if (length < 0)
634: strcpy (docName, newName);
635: else
636: strcpy (docName, &newName[length+1]);
637: }
1.19 cvs 638:
1.5 cvs 639: }
1.18 cvs 640: else
641: docName[0] = EOS;
642: }
1.3 cvs 643:
1.4 cvs 644: /*----------------------------------------------------------------------
1.9 cvs 645: IsSameHost
1.4 cvs 646: ----------------------------------------------------------------------*/
1.3 cvs 647: #ifdef __STDC__
648: boolean IsSameHost (char *url1, char *url2)
649: #else /* __STDC__ */
650: boolean IsSameHost (url1, url2)
651: char *path;
652: #endif /* __STDC__ */
653: {
1.5 cvs 654: char *basename_ptr1, *basename_ptr2;
655: boolean result;
1.3 cvs 656:
1.25 cvs 657: basename_ptr1 = AmayaParseUrl (url1, "", AMAYA_PARSE_ACCESS | AMAYA_PARSE_HOST | AMAYA_PARSE_PUNCTUATION);
658: basename_ptr2 = AmayaParseUrl (url2, "", AMAYA_PARSE_ACCESS | AMAYA_PARSE_HOST | AMAYA_PARSE_PUNCTUATION);
1.3 cvs 659:
1.5 cvs 660: if (strcmp (basename_ptr1, basename_ptr2))
1.8 cvs 661: result = FALSE;
1.5 cvs 662: else
1.8 cvs 663: result = TRUE;
1.3 cvs 664:
1.25 cvs 665: TtaFreeMemory (basename_ptr1);
666: TtaFreeMemory (basename_ptr2);
1.5 cvs 667: return (result);
1.3 cvs 668: }
669:
670:
1.4 cvs 671: /*----------------------------------------------------------------------
1.22 cvs 672: HasKnownFileSuffix
673: returns TRUE if path points to a file ending with a suffix.
674: ----------------------------------------------------------------------*/
675: #ifdef __STDC__
676: boolean HasKnownFileSuffix (char *path)
677: #else /* __STDC__ */
678: boolean HasKnownFileSuffix (path)
679: char *path;
680: #endif /* __STDC__ */
681: {
1.29 cvs 682: char *root;
683: char temppath[MAX_LENGTH];
684: char suffix[MAX_LENGTH];
1.22 cvs 685:
1.24 cvs 686: if (!path || path[0] == EOS || path[strlen(path)] == DIR_SEP)
1.22 cvs 687: return (FALSE);
688:
1.29 cvs 689: root = AmayaParseUrl(path, "", AMAYA_PARSE_PATH | AMAYA_PARSE_PUNCTUATION);
1.22 cvs 690:
691: if (root)
692: {
693: strcpy (temppath, root);
1.25 cvs 694: TtaFreeMemory (root);
1.22 cvs 695: /* Get the suffix */
696: ExtractSuffix (temppath, suffix);
697:
698: if( suffix[0] == EOS)
699: /* no suffix */
700: return (FALSE);
701:
702: /* Normalize the suffix */
703: ConvertToLowerCase (suffix);
704:
1.23 cvs 705: if (!strcmp (suffix, "gz"))
1.22 cvs 706: /* skip the compressed suffix */
707: {
708: ExtractSuffix (temppath, suffix);
709: if(suffix[0] == EOS)
710: /* no suffix */
711: return (FALSE);
712: /* Normalize the suffix */
713: ConvertToLowerCase (suffix);
714: }
715:
716: if ((strcmp (suffix, "gif")) && (strcmp (suffix, "xbm")) &&
717: (strcmp (suffix, "xpm")) && (strcmp (suffix, "jpg")) &&
718: (strcmp (suffix, "pdf")) && (strcmp (suffix, "png")) &&
719: (strcmp (suffix, "tgz")) && (strcmp (suffix, "xpg")) &&
720: (strcmp (suffix, "xpd")) && (strcmp (suffix, "ps")) &&
721: (strcmp (suffix, "au")) && (strcmp (suffix, "html")) &&
722: (strcmp (suffix, "htm")) && (strcmp (suffix, "shtml")) &&
723: (strcmp (suffix, "txt")) && (strcmp (suffix, "css")) &&
724: (strcmp (suffix, "eps")))
725: return (FALSE);
726: else
727: return (TRUE);
728: }
729: else
730: return (FALSE);
731: }
732:
733:
734: /*----------------------------------------------------------------------
1.24 cvs 735: ChopURL
736: Gives back a URL no longer than MAX_PRINT_URL_LENGTH chars (outputURL).
737: If inputURL is bigger than that size, outputURL receives
738: MAX_PRINT_URL_LENGTH / 2 chars from the beginning of inputURL, "...",
739: and MAX_PRINT_URL_LENGTH / 2 chars from the end of inputURL.
740: If inputURL is not longer than MAX_PRINT_URL_LENGTH chars, it gets
741: copied into outputURL.
742: N.B.: outputURL must point to a memory block of MAX_PRINT_URL_LENGTH
743: chars.
744: ----------------------------------------------------------------------*/
745: #ifdef __STDC__
746: void ChopURL (char *outputURL, char *inputURL)
747: #else
748: void ChopURL (outputURL, inputURL)
749: char *outputURL;
750: char *inputURL;
751: #endif
1.22 cvs 752:
1.24 cvs 753: {
754: int len;
1.9 cvs 755:
1.24 cvs 756: len = strlen (inputURL);
757: if (len <= MAX_PRINT_URL_LENGTH)
1.29 cvs 758: strcpy (outputURL, inputURL);
1.24 cvs 759: else
760: /* make a truncated urlName on the status window */
761: {
762: strncpy (outputURL, inputURL, MAX_PRINT_URL_LENGTH / 2);
763: outputURL [MAX_PRINT_URL_LENGTH / 2] = EOS;
764: strcat (outputURL, "...");
765: strcat (outputURL, &(inputURL[len - MAX_PRINT_URL_LENGTH / 2 ]));
766: }
1.25 cvs 767: }
768:
769:
770: /*----------------------------------------------------------------------
771: scan
772: Scan a filename for its consituents
773: -----------------------------------
774:
775: On entry,
776: name points to a document name which may be incomplete.
777: On exit,
778: absolute or relative may be nonzero (but not both).
779: host, fragment and access may be nonzero if they were specified.
780: Any which are nonzero point to zero terminated strings.
781: ----------------------------------------------------------------------*/
782: #ifdef __STDC__
783: static void scan (char * name, HTURI * parts)
784: #else /* __STDC__ */
785: static void scan (name, parts)
786: char *name;
787: HTURI *parts;
788:
789: #endif /* __STDC__ */
790: {
1.28 cvs 791: char * p;
792: char * after_access = name;
1.25 cvs 793:
1.28 cvs 794: memset(parts, '\0', sizeof(HTURI));
795: /* Look for fragment identifier */
796: if ((p = strrchr(name, '#')) != NULL)
797: {
798: *p++ = '\0';
799: parts->fragment = p;
1.25 cvs 800: }
801:
1.28 cvs 802: for (p=name; *p; p++)
803: {
804: if (*p==DIR_SEP || *p=='#' || *p=='?')
805: break;
1.29 cvs 806: if (*p==PATH_SEP)
1.28 cvs 807: {
808: *p = 0;
809: parts->access = after_access; /* Scheme has been specified */
810:
811: /* The combination of gcc, the "-O" flag and the HP platform is
812: unhealthy. The following three lines is a quick & dirty fix, but is
813: not recommended. Rather, turn off "-O". */
814:
815: /* after_access = p;*/
816: /* while (*after_access == 0)*/
817: /* after_access++;*/
818: after_access = p+1;
819: if (0==strcasecmp("URL", parts->access))
820: /* Ignore IETF's URL: pre-prefix */
821: parts->access = NULL;
822: else
1.25 cvs 823: break;
824: }
825: }
826:
827: p = after_access;
1.28 cvs 828: if (*p==DIR_SEP)
829: {
830: if (p[1]==DIR_SEP)
831: {
1.25 cvs 832: parts->host = p+2; /* host has been specified */
1.28 cvs 833: *p = 0; /* Terminate access */
834: /* look for end of host name if any */
835: p = strchr(parts->host,DIR_SEP);
836: if (p)
837: {
1.25 cvs 838: *p=0; /* Terminate host */
839: parts->absolute = p+1; /* Root has been found */
1.28 cvs 840: }
841: }
842: else
843: /* Root found but no host */
844: parts->absolute = p+1;
845: }
846: else
847: {
1.25 cvs 848: parts->relative = (*after_access) ? after_access : 0; /* zero for "" */
1.28 cvs 849: }
1.25 cvs 850: }
851:
852:
853: /*----------------------------------------------------------------------
1.28 cvs 854: AmayaParseUrl: parse a Name relative to another name
855:
856: This returns those parts of a name which are given (and requested)
857: substituting bits from the related name where necessary.
1.25 cvs 858:
1.28 cvs 859: On entry,
1.25 cvs 860: aName A filename given
861: relatedName A name relative to which aName is to be parsed. Give
862: it an empty string if aName is absolute.
863: wanted A mask for the bits which are wanted.
864:
1.28 cvs 865: On exit,
1.25 cvs 866: returns A pointer to a malloc'd string which MUST BE FREED
867: ----------------------------------------------------------------------*/
868: #ifdef __STDC__
1.28 cvs 869: char *AmayaParseUrl (char *aName, char *relatedName, int wanted)
1.25 cvs 870: #else /* __STDC__ */
1.28 cvs 871: char *AmayaParseUrl (aName, relatedName, wanted)
872: char *aName;
873: char *relatedName;
874: int wanted;
1.25 cvs 875:
876: #endif /* __STDC__ */
877: {
1.29 cvs 878: char *return_value;
879: char result[MAX_LENGTH];
880: char name[MAX_LENGTH];
881: char rel[MAX_LENGTH];
882: char *p, *access;
883: HTURI given, related;
884: int len;
1.25 cvs 885:
1.29 cvs 886: /* Make working copies of input strings to cut up: */
887: return_value = NULL;
888: result[0] = 0; /* Clear string */
889: strcpy (name, aName);
890: if (relatedName != NULL)
891: strcpy (rel, relatedName);
892: else
893: relatedName[0] = EOS;
894:
895: scan (name, &given);
896: scan (rel, &related);
897: access = given.access ? given.access : related.access;
898: if (wanted & AMAYA_PARSE_ACCESS)
899: if (access)
900: {
901: strcat (result, access);
902: if(wanted & AMAYA_PARSE_PUNCTUATION)
903: strcat (result, PATH_STR);
904: }
905:
906: if (given.access && related.access)
907: /* If different, inherit nothing. */
908: if (strcmp (given.access, related.access) != 0)
909: {
910: related.host = 0;
911: related.absolute = 0;
912: related.relative = 0;
913: related.fragment = 0;
914: }
915:
916: if (wanted & AMAYA_PARSE_HOST)
917: if(given.host || related.host)
918: {
919: if(wanted & AMAYA_PARSE_PUNCTUATION)
920: strcat (result, "//");
921: strcat (result, given.host ? given.host : related.host);
922: }
923:
924: if (given.host && related.host)
925: /* If different hosts, inherit no path. */
926: if (strcmp(given.host, related.host) != 0)
927: {
928: related.absolute = 0;
929: related.relative = 0;
930: related.fragment = 0;
931: }
932:
933: if (wanted & AMAYA_PARSE_PATH)
934: {
935: if (given.absolute)
936: {
937: /* All is given */
938: if (wanted & AMAYA_PARSE_PUNCTUATION)
939: strcat (result, DIR_STR);
940: strcat (result, given.absolute);
1.25 cvs 941: }
1.29 cvs 942: else if (related.absolute)
943: {
944: /* Adopt path not name */
945: strcat (result, DIR_STR);
946: strcat (result, related.absolute);
947: if (given.relative)
948: {
949: /* Search part? */
950: p = strchr (result, '?');
951: if (!p)
952: p=result+strlen(result)-1;
953: for (; *p!=DIR_SEP; p--); /* last / */
954: /* Remove filename */
955: p[1]=0;
956: /* Add given one */
957: strcat (result, given.relative);
958: /*SimplifyUrl (&result);*/
1.25 cvs 959: }
960: }
1.29 cvs 961: else if (given.relative)
962: /* what we've got */
963: strcat (result, given.relative);
964: else if (related.relative)
965: strcat (result, related.relative);
966: else
967: /* No inheritance */
968: strcat (result, DIR_STR);
1.25 cvs 969: }
1.29 cvs 970:
971: if (wanted & AMAYA_PARSE_ANCHOR)
972: if (given.fragment || related.fragment)
973: {
974: if (given.absolute && given.fragment)
975: {
976: /*Fixes for relURLs...*/
977: if (wanted & AMAYA_PARSE_PUNCTUATION)
978: strcat (result, "#");
979: strcat (result, given.fragment);
980: }
981: else if (!(given.absolute) && !(given.fragment))
982: strcat (result, "");
983: else
984: {
985: if (wanted & AMAYA_PARSE_PUNCTUATION)
986: strcat (result, "#");
987: strcat (result, given.fragment ? given.fragment : related.fragment);
988: }
989: }
990: len = strlen (result);
991: if ((return_value = (char *) TtaGetMemory (len + 1)) != NULL)
992: strcpy (return_value, result);
993: return (return_value); /* exactly the right length */
1.25 cvs 994: }
995:
996: /*----------------------------------------------------------------------
997: HTCanon
998: Canonicalizes the URL in the following manner starting from the host
999: pointer:
1000:
1001: 1) The host name is converted to lowercase
1002: 2) Chop off port if `:80' (http), `:70' (gopher), or `:21' (ftp)
1003:
1004: Return: OK The position of the current path part of the URL
1005: which might be the old one or a new one.
1006:
1007: ----------------------------------------------------------------------*/
1008: #ifdef __STDC__
1.28 cvs 1009: static char *HTCanon (char ** filename, char * host)
1.25 cvs 1010: #else /* __STDC__ */
1.28 cvs 1011: static char *HTCanon (filename, host)
1012: char **filename;
1013: char *host;
1.25 cvs 1014: #endif /* __STDC__ */
1015: {
1016: char *newname = NULL;
1017: char *port;
1018: char *strptr;
1019: char *path;
1020: char *access = host-3;
1021:
1.28 cvs 1022: while (access>*filename && *(access-1)!=DIR_SEP) /* Find access method */
1.25 cvs 1023: access--;
1.28 cvs 1024: if ((path = strchr(host, DIR_SEP)) == NULL) /* Find path */
1.25 cvs 1025: path = host + strlen(host);
1026: if ((strptr = strchr(host, '@')) != NULL && strptr<path) /* UserId */
1027: host = strptr;
1.29 cvs 1028: if ((port = strchr(host, PATH_SEP)) != NULL && port>path) /* Port number */
1.25 cvs 1029: port = NULL;
1030:
1031: strptr = host; /* Convert to lower-case */
1032: while (strptr<path) {
1033: *strptr = tolower(*strptr);
1034: strptr++;
1035: }
1036:
1037: /* Does the URL contain a full domain name? This also works for a
1038: numerical host name. The domain name is already made lower-case
1039: and without a trailing dot. */
1040: {
1041: char *dot = port ? port : path;
1042: if (dot > *filename && *--dot=='.') {
1043: char *orig=dot, *dest=dot+1;
1044: while((*orig++ = *dest++));
1045: if (port) port--;
1046: path--;
1047: }
1048: }
1049: /* Chop off port if `:', `:80' (http), `:70' (gopher), or `:21' (ftp) */
1050: if (port) {
1.28 cvs 1051: if (!*(port+1) || *(port+1)==DIR_SEP) {
1.25 cvs 1052: if (!newname) {
1053: char *orig=port, *dest=port+1;
1054: while((*orig++ = *dest++));
1055: }
1056: } else if ((!strncmp(access, "http", 4) &&
1.28 cvs 1057: (*(port+1)=='8'&&*(port+2)=='0'&&(*(port+3)==DIR_SEP||!*(port+3)))) ||
1.25 cvs 1058: (!strncmp(access, "gopher", 6) &&
1.28 cvs 1059: (*(port+1)=='7'&&*(port+2)=='0'&&(*(port+3)==DIR_SEP||!*(port+3)))) ||
1.25 cvs 1060: (!strncmp(access, "ftp", 3) &&
1.28 cvs 1061: (*(port+1)=='2'&&*(port+2)=='1'&&(*(port+3)==DIR_SEP||!*(port+3))))) {
1.25 cvs 1062: if (!newname) {
1063: char *orig=port, *dest=port+3;
1064: while((*orig++ = *dest++));
1.28 cvs 1065: /* Update path position, Henry Minsky */
1066: path -= 3;
1.25 cvs 1067: }
1068: } else if (newname)
1069: strncat(newname, port, (int) (path-port));
1070: }
1071:
1072: if (newname) {
1073: char *newpath = newname+strlen(newname);
1074: strcat(newname, path);
1075: path = newpath;
1.28 cvs 1076: /* Free old copy */
1077: TtaFreeMemory(*filename);
1.25 cvs 1078: *filename = newname;
1079: }
1080: return path;
1081: }
1082:
1083:
1084: /*----------------------------------------------------------------------
1.29 cvs 1085: SimplifyUrl: simplify a URI
1.28 cvs 1086: A URI is allowed to contain the seqeunce xxx/../ which may be
1.29 cvs 1087: replaced by "" , and the seqeunce "/./" which may be replaced by DIR_STR.
1.28 cvs 1088: Simplification helps us recognize duplicate URIs.
1.25 cvs 1089:
1.28 cvs 1090: Thus, /etc/junk/../fred becomes /etc/fred
1091: /etc/junk/./fred becomes /etc/junk/fred
1.25 cvs 1092:
1.28 cvs 1093: but we should NOT change
1094: http://fred.xxx.edu/../..
1.25 cvs 1095:
1096: or ../../albert.html
1097:
1.28 cvs 1098: In order to avoid empty URLs the following URLs become:
1.25 cvs 1099:
1100: /fred/.. becomes /fred/..
1101: /fred/././.. becomes /fred/..
1102: /fred/.././junk/.././ becomes /fred/..
1103:
1.28 cvs 1104: If more than one set of `://' is found (several proxies in cascade) then
1105: only the part after the last `://' is simplified.
1.25 cvs 1106:
1.28 cvs 1107: Returns: A string which might be the old one or a new one.
1.25 cvs 1108: ----------------------------------------------------------------------*/
1109: #ifdef __STDC__
1.29 cvs 1110: void SimplifyUrl (char ** url)
1.25 cvs 1111: #else /* __STDC__ */
1.29 cvs 1112: void SimplifyUrl (url)
1.28 cvs 1113: char **url;
1.25 cvs 1114: #endif /* __STDC__ */
1115: {
1.28 cvs 1116: char *path, *p;
1117: char *newptr, *access;
1118: char *orig, *dest, *end;
1119:
1120: if (!url || !*url)
1121: return;
1122:
1123: /* Find any scheme name */
1124: if ((path = strstr(*url, "://")) != NULL)
1125: { /* Find host name */
1126: access = *url;
1127: while (access<path && (*access=tolower(*access)))
1128: access++;
1129: path += 3;
1130: while ((newptr = strstr(path, "://")) != NULL)
1131: /* For proxies */
1132: path = newptr+3;
1133: /* We have a host name */
1134: path = HTCanon(url, path);
1.25 cvs 1135: }
1.28 cvs 1136: else if ((path = strstr(*url, ":/")) != NULL)
1137: path += 2;
1138: else
1139: path = *url;
1.25 cvs 1140:
1.28 cvs 1141: if (*path == DIR_SEP && *(path+1)==DIR_SEP)
1142: /* Some URLs start //<foo> */
1143: path += 1;
1144: else if (!strncmp(path, "news:", 5))
1145: {
1146: newptr = strchr(path+5, '@');
1147: if (!newptr)
1148: newptr = path + 5;
1149: while (*newptr)
1150: {
1151: /* Make group or host lower case */
1152: *newptr = tolower (*newptr);
1153: newptr++;
1.25 cvs 1154: }
1.28 cvs 1155: /* Doesn't need to do any more */
1156: return;
1.25 cvs 1157: }
1.28 cvs 1158:
1159: if ((p = path))
1160: {
1161: if (!((end = strchr (path, ';')) || (end = strchr (path, '?')) ||
1162: (end = strchr (path, '#'))))
1163: end = path + strlen (path);
1164:
1165: /* Parse string second time to simplify */
1166: p = path;
1167: while (p < end)
1168: {
1169: if (*p==DIR_SEP)
1170: {
1171: if (p > *url && *(p+1) == '.' && (*(p+2) == DIR_SEP || !*(p+2)))
1172: {
1173: orig = p + 1;
1174: dest = (*(p+2)!=DIR_SEP) ? p+2 : p+3;
1175: while ((*orig++ = *dest++)); /* Remove a slash and a dot */
1176: end = orig - 1;
1177: }
1178: else if (*(p+1)=='.' && *(p+2)=='.' && (*(p+3)==DIR_SEP || !*(p+3)))
1179: {
1180: newptr = p;
1181: while (newptr>path && *--newptr!=DIR_SEP); /* prev slash */
1182: if (strncmp(newptr, "/../", 4))
1183: {
1184: orig = newptr + 1;
1185: dest = (*(p+3)!=DIR_SEP) ? p+3 : p+4;
1186: while ((*orig++ = *dest++)); /* Remove /xxx/.. */
1187: end = orig-1;
1188: /* Start again with prev slash */
1189: p = newptr;
1.25 cvs 1190: }
1.28 cvs 1191: else
1.25 cvs 1192: p++;
1.28 cvs 1193: }
1194: else if (*(p+1) == DIR_SEP)
1195: {
1196: while (*(p+1) == DIR_SEP)
1197: {
1198: orig = p;
1199: dest = p + 1;
1200: while ((*orig++ = *dest++)); /* Remove multiple /'s */
1201: end = orig-1;
1202: }
1203: }
1204: else
1.25 cvs 1205: p++;
1.28 cvs 1206: }
1207: else
1208: p++;
1.25 cvs 1209: }
1210: }
1.28 cvs 1211: return;
1212: }
1213:
1214:
1215: /*----------------------------------------------------------------------
1216: NormalizeFile normalizes local names.
1217: Return TRUE if target and src differ.
1218: ----------------------------------------------------------------------*/
1219: #ifdef __STDC__
1220: boolean NormalizeFile (char *src, char *target)
1221: #else
1222: boolean NormalizeFile (src, target)
1223: char *src;
1224: char *target;
1225:
1226: #endif
1227: {
1228: char *s;
1229: boolean change;
1230:
1231: change = FALSE;
1232: if (src[0] == '~')
1233: {
1234: /* replace ~ */
1235: s = (char *) TtaGetEnvString ("HOME");
1236: strcpy (target, s);
1237: strcat (target, &src[1]);
1238: change = TRUE;
1239: }
1240: else if (strncmp (src, "file:", 5) == 0)
1241: {
1242: /* remove the prefix file: */
1243: if (src[5] == EOS)
1244: strcpy (target, DIR_STR);
1245: else if (src[0] == '~')
1246: {
1247: /* replace ~ */
1248: s = (char *) TtaGetEnvString ("HOME");
1249: strcpy (target, s);
1250: strcat (target, &src[5]);
1251: }
1252: else
1253: strcpy (target, &src[5]);
1254: change = TRUE;
1255: }
1256: else
1257: strcpy (target, src);
1258:
1259: /* remove /../ and /./ */
1.29 cvs 1260: SimplifyUrl (&target);
1.28 cvs 1261: return (change);
1.25 cvs 1262: }
1263:
1.28 cvs 1264:
1.25 cvs 1265: /*----------------------------------------------------------------------
1.29 cvs 1266: MakeRelativeUrl: make relative name
1.25 cvs 1267:
1.28 cvs 1268: This function creates and returns a string which gives an expression of
1269: one address as related to another. Where there is no relation, an absolute
1270: address is retured.
1.25 cvs 1271:
1.28 cvs 1272: On entry,
1.25 cvs 1273: Both names must be absolute, fully qualified names of nodes
1274: (no fragment bits)
1275:
1.28 cvs 1276: On exit,
1.25 cvs 1277: The return result points to a newly allocated name which, if
1278: parsed by AmayaParseUrl relative to relatedName, will yield aName.
1279: The caller is responsible for freeing the resulting name later.
1280: ----------------------------------------------------------------------*/
1281: #ifdef __STDC__
1.29 cvs 1282: char *MakeRelativeUrl (char *aName, char *relatedName)
1.25 cvs 1283: #else /* __STDC__ */
1.29 cvs 1284: char *MakeRelativeUrl (aName, relatedName)
1.28 cvs 1285: char *aName;
1286: char *relatedName;
1.25 cvs 1287: #endif /* __STDC__ */
1288: {
1.29 cvs 1289: char *return_value;
1290: char result[MAX_LENGTH];
1291: char *p;
1292: char *q = relatedName;
1293: char *after_access;
1294: char *last_slash = NULL;
1295: int slashes, levels, len;
1296:
1297: if (aName == NULL || relatedName == NULL)
1298: return (NULL);
1299:
1300: slashes = 0;
1301: after_access = NULL;
1302: p = aName;
1303: q = relatedName;
1304: for (; *p && (*p == *q); p++, q++)
1.27 cvs 1305: {
1306: /* Find extent of match */
1.29 cvs 1307: if (*p == PATH_SEP)
1308: after_access = p + 1;
1.28 cvs 1309: if (*p == DIR_SEP)
1.27 cvs 1310: {
1.29 cvs 1311: /* memorize the last slash position and count them */
1.27 cvs 1312: last_slash = p;
1313: slashes++;
1.25 cvs 1314: }
1315: }
1316:
1317: /* q, p point to the first non-matching character or zero */
1.29 cvs 1318: if ((slashes < 2 && after_access == NULL)
1319: || (slashes < 3 && after_access != NULL))
1.27 cvs 1320: {
1.29 cvs 1321: /* Local files or remote files whitout common path */
1322: /* exactly the right length */
1323: len = strlen (aName);
1324: if ((return_value = (char *) TtaGetMemory (len + 1)) != NULL)
1325: strcpy (return_value, aName);
1.27 cvs 1326: }
1327: else
1328: {
1329: /* Some path in common */
1.30 ! cvs 1330: if (slashes == 3 && strncmp (aName, "http:", 5) == 0)
1.29 cvs 1331: /* just the same server */
1332: strcpy (result, last_slash);
1333: else
1334: {
1335: levels= 0;
1336: for (; *q && (*q != '#'); q++)
1337: if (*q == DIR_SEP)
1338: levels++;
1339:
1340: result[0] = 0;
1341: for (;levels; levels--)
1342: strcat (result, "../");
1343: strcat (result, last_slash+1);
1344: }
1345:
1346: /* exactly the right length */
1347: len = strlen (result);
1348: if ((return_value = (char *) TtaGetMemory (len + 1)) != NULL)
1349: strcpy (return_value, result);
1.25 cvs 1350: }
1.29 cvs 1351: return (return_value);
1.24 cvs 1352: }
Webmaster