Annotation of Amaya/amaya/AHTURLTools.c, revision 1.212
1.7 cvs 1: /*
2: *
1.204 vatton 3: * (c) COPYRIGHT INRIA and W3C, 1996-2008
1.7 cvs 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.106 cvs 14: * R. Guetari: Windows.
1.10 cvs 15: *
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.106 cvs 24: typedef struct _HTURI
25: {
1.195 vatton 26: char *access; /* Now known as "scheme" */
27: char *host;
28: char *absolute;
29: char *relative;
30: char *fragment;
1.29 cvs 31: } HTURI;
1.24 cvs 32:
1.175 cvs 33: #ifdef _WINDOWS
1.164 kahan 34: #ifndef PATH_MAX
1.163 cvs 35: #define PATH_MAX MAX_PATH
1.164 kahan 36: #endif
1.155 cvs 37: #define stat _stat
38: #define uint64_t unsigned __int64
39: #define getpid _getpid
1.175 cvs 40: #else /* _WINDOWS */
1.161 kahan 41: #if HAVE_STDINT_H
42: #include <stdint.h>
43: #endif /* HAVE_STDINT_H */
1.175 cvs 44: #endif /* _WINDOWS */
1.28 cvs 45:
46: /*----------------------------------------------------------------------
47: ConvertToLowerCase
48: Converts a string to lowercase.
49: ----------------------------------------------------------------------*/
1.124 vatton 50: void ConvertToLowerCase (char *string)
1.28 cvs 51: {
1.195 vatton 52: int i;
1.93 cvs 53:
1.195 vatton 54: if (!string)
55: return;
1.28 cvs 56:
1.195 vatton 57: for (i = 0; string[i] != EOS; i++)
58: string[i] = tolower (string[i]);
1.28 cvs 59: }
1.22 cvs 60:
1.8 cvs 61: /*----------------------------------------------------------------------
1.75 cvs 62: EscapeChar
63: writes the equivalent escape code of a char in a string
64: ----------------------------------------------------------------------*/
1.109 cvs 65: void EscapeChar (char *string, char c)
1.75 cvs 66: {
1.109 cvs 67: unsigned int i;
68:
1.195 vatton 69: i = (unsigned char) c & 0xFF;
70: sprintf (string, "%02x", i);
1.75 cvs 71: }
72:
73: /*----------------------------------------------------------------------
1.96 cvs 74: UnEscapeChar
75: writes the equivalent hex code to a %xx coded char
76: ----------------------------------------------------------------------*/
1.109 cvs 77: static char UnEscapeChar (char c)
1.96 cvs 78: {
1.195 vatton 79: return c >= '0' && c <= '9' ? c - '0'
80: : c >= 'A' && c <= 'F' ? c - 'A' + 10
81: : c - 'a' + 10; /* accept small letters just in case */
1.96 cvs 82: }
83:
84: /*----------------------------------------------------------------------
1.75 cvs 85: EscapeURL
86: Takes a URL and escapes all protected chars into
87: %xx sequences. Also, removes any leading white spaces
88: Returns either NULL or a new buffer, which must be freed by the caller
89: ----------------------------------------------------------------------*/
1.106 cvs 90: char *EscapeURL (const char *url)
91: {
92: char *buffer;
1.208 vatton 93: char *ptr, *server, *param;
94: int buffer_len, par_len;
95: int new_chars, len, url_len;
1.106 cvs 96: int buffer_free_mem;
1.75 cvs 97: void *status;
98:
99: if (url && *url)
100: {
1.208 vatton 101: url_len = strlen (url);
102: buffer_free_mem = url_len + 20;
103: // a patch for sweetwiki
1.211 vatton 104: server = TtaStrdup ("http://sweetwiki.inria.fr/");
1.212 ! vatton 105: param = TtaStrdup ("?templateoff=true&xslname=queryoff");
1.208 vatton 106: len = strlen(server);
107: par_len = strlen (param);
108: if (strncmp (url, server, len) ||
109: // or already included
1.210 vatton 110: url_len < 4 ||
1.208 vatton 111: strncmp (&url[url_len-4], ".jsp", 4))
112: // it's not necessary to add these parameters
113: par_len = 0;
114:
115: buffer_free_mem += par_len;
1.171 gully 116: buffer = (char *)TtaGetMemory (buffer_free_mem + 1);
1.107 kahan 117: ptr = (char *) url;
1.75 cvs 118: buffer_len = 0;
119: while (*ptr)
120: {
121: switch (*ptr)
122: {
123: /* put here below all the chars that need to
124: be escaped into %xx */
1.81 cvs 125: case 0x20: /* space */
1.195 vatton 126: /*case 0x26:*/ /* & */
1.140 kahan 127: case 0x27: /* antislash */
1.75 cvs 128: new_chars = 3;
129: break;
130:
131: default:
1.195 vatton 132: if ((unsigned char )*ptr > 127)
133: new_chars = 3;
134: else
135: new_chars = 1;
1.75 cvs 136: break;
137: }
138:
139: /* see if we need extra room in the buffer */
140: if (new_chars > buffer_free_mem)
141: {
1.76 cvs 142: buffer_free_mem = 20;
1.106 cvs 143: status = TtaRealloc (buffer, sizeof (char)
1.195 vatton 144: * (buffer_len + buffer_free_mem + 1));
1.75 cvs 145: if (status)
1.114 cvs 146: buffer = (char *) status;
1.106 cvs 147: else
1.195 vatton 148: {
149: /* @@ maybe we should do some other behavior here, like
150: freeing the buffer and return a void thing */
151: buffer[buffer_len] = EOS;
152: break;
153: }
1.75 cvs 154: }
1.195 vatton 155: /* escape the char */
156: if (new_chars == 3)
157: {
1.106 cvs 158: buffer[buffer_len] = '%';
1.75 cvs 159: EscapeChar (&buffer[buffer_len+1], *ptr);
160: }
1.140 kahan 161: else
162: buffer[buffer_len] = *ptr;
163:
164: /* update the status */
165: buffer_len += new_chars;
166: buffer_free_mem -= new_chars;
167: /* examine the next char */
168: ptr++;
1.208 vatton 169:
170: if (*ptr == EOS && par_len)
171: {
172: // add parameters
173: ptr = param;
174: par_len = 0;
175: }
1.140 kahan 176: }
177: buffer[buffer_len] = EOS;
1.211 vatton 178: TtaFreeMemory (server);
179: TtaFreeMemory (param);
1.140 kahan 180: }
181: else
182: buffer = NULL;
183:
184: return (buffer);
185: }
186:
187: /*----------------------------------------------------------------------
188: EscapeXML
189: Takes a string and escapes all protected chars into entity
190: sequences.
191: Returns either NULL or a new buffer, which must be freed by the caller
192: ----------------------------------------------------------------------*/
193: char *EscapeXML (const char *string)
194: {
195: char *buffer;
196: int buffer_len;
197: int buffer_free_mem;
198: char *ptr;
1.203 vatton 199: const char *entity = NULL;
1.140 kahan 200: int new_chars;
201: void *status;
202:
203: if (string && *string)
204: {
205: buffer_free_mem = strlen (string) + 20;
1.171 gully 206: buffer = (char *)TtaGetMemory (buffer_free_mem + 1);
1.140 kahan 207: ptr = (char *) string;
208: buffer_len = 0;
209:
210: while (*ptr)
211: {
212: switch (*ptr)
213: {
1.195 vatton 214: case 0x26: /* & */
215: entity = "&";
216: new_chars = sizeof (entity) - 1;
217: break;
1.140 kahan 218:
1.195 vatton 219: case '<': /* < */
220: entity = "<";
221: new_chars = sizeof (entity) - 1;
222: break;
223:
224: case '>': /* > */
225: entity = ">";
226: new_chars = sizeof (entity) - 1;
227: break;
228:
229: case '"': /* "e; */
230: entity = ""e;";
231: new_chars = sizeof (entity) - 1;
232: break;
1.140 kahan 233:
234: default:
1.195 vatton 235: new_chars = 1;
1.140 kahan 236: break;
237: }
238:
239: /* see if we need extra room in the buffer */
240: if (new_chars > buffer_free_mem)
241: {
242: buffer_free_mem = 20;
243: status = TtaRealloc (buffer, sizeof (char)
1.195 vatton 244: * (buffer_len + buffer_free_mem + 1));
1.140 kahan 245: if (status)
246: buffer = (char *) status;
247: else
1.195 vatton 248: {
249: /* @@ maybe we should do some other behavior here, like
250: freeing the buffer and return a void thing */
251: buffer[buffer_len] = EOS;
252: break;
253: }
254: }
255: /* escape the char */
256: if (entity)
257: {
258: sprintf (&buffer[buffer_len], "%s", entity);
259: entity = NULL;
1.140 kahan 260: }
1.75 cvs 261: else
262: buffer[buffer_len] = *ptr;
263:
264: /* update the status */
265: buffer_len += new_chars;
266: buffer_free_mem -= new_chars;
267: /* examine the next char */
268: ptr++;
269: }
1.106 cvs 270: buffer[buffer_len] = EOS;
1.75 cvs 271: }
1.76 cvs 272: else
273: buffer = NULL;
274:
1.75 cvs 275: return (buffer);
1.122 kahan 276: }
277:
1.75 cvs 278:
279: /*----------------------------------------------------------------------
1.11 cvs 280: ExplodeURL
1.8 cvs 281: ----------------------------------------------------------------------*/
1.106 cvs 282: void ExplodeURL (char *url, char **proto, char **host, char **dir,
1.195 vatton 283: char **file)
1.8 cvs 284: {
1.195 vatton 285: char *curr, *temp;
286: char used_sep;
1.32 cvs 287:
1.195 vatton 288: if (url && strchr (url, URL_SEP))
289: used_sep = URL_SEP;
290: else
291: used_sep = DIR_SEP;
292:
293: if ((url == NULL) || (proto == NULL) || (host == NULL) ||
294: (dir == NULL) || (file == NULL))
295: return;
1.8 cvs 296:
1.195 vatton 297: /* initialize every pointer */
298: *proto = *host = *dir = *file = NULL;
299:
300: /* skip any leading space */
301: while ((*url == SPACE) || (*url == TAB))
302: url++;
303: curr = url;
304: if (*curr == 0)
305: goto finished;
306:
307: /* go to the end of the URL */
308: while ((*curr != EOS) && (*curr != SPACE) && (*curr != BSPACE) &&
309: (*curr != __CR__) && (*curr != EOL))
310: curr++;
311:
312: /* mark the end of the chain */
313: *curr = EOS;
314: curr--;
315: if (curr <= url)
316: goto finished;
317:
318: /* search the next DIR_SEP indicating the beginning of the file name */
319: do
320: curr--;
321: while ((curr >= url) && (*curr != used_sep));
322:
323: if (curr < url)
324: goto finished;
325: *file = curr + 1;
326:
327: /* mark the end of the dir */
328: *curr = EOS;
329: curr--;
330: if (curr < url)
331: goto finished;
332:
333: /* search for the DIR_STR indicating the host name start */
334: while ((curr > url) && ((*curr != used_sep) || (*(curr + 1) != used_sep)))
335: curr--;
336:
337: /* if we found it, separate the host name from the directory */
338: if ((*curr == used_sep) && (*(curr + 1) == used_sep))
339: {
340: *host = temp = curr + 2;
341: while ((*temp != 0) && (*temp != used_sep))
342: temp++;
343: if (*temp == used_sep)
344: {
345: *temp = EOS;
346: *dir = temp + 1;
347: }
348: }
349: else
350: *dir = curr;
1.8 cvs 351:
1.195 vatton 352: if (curr <= url)
353: goto finished;
1.8 cvs 354:
1.195 vatton 355: /* mark the end of the proto */
356: *curr = EOS;
357: curr--;
358: if (curr < url)
359: goto finished;
1.8 cvs 360:
1.195 vatton 361: if (*curr == ':')
362: {
363: *curr = EOS;
1.9 cvs 364: curr--;
1.195 vatton 365: }
366: else
367: goto finished;
1.8 cvs 368:
1.195 vatton 369: if (curr < url)
370: goto finished;
371: while ((curr > url) && (isalpha (*curr)))
372: curr--;
373: *proto = curr;
1.8 cvs 374:
375: finished:;
376:
377: #ifdef AMAYA_DEBUG
1.195 vatton 378: fprintf (stderr, "ExplodeURL(%s)\n\t", url);
379: if (*proto)
380: fprintf (stderr, "proto : %s, ", *proto);
381: if (*host)
382: fprintf (stderr, "host : %s, ", *host);
383: if (*dir)
384: fprintf (stderr, "dir : %s, ", *dir);
385: if (*file)
386: fprintf (stderr, "file : %s ", *file);
387: fprintf (stderr, "\n");
1.8 cvs 388: #endif
389:
390: }
1.3 cvs 391:
1.116 kahan 392: /*----------------------------------------------------------------------
1.195 vatton 393: PicTypeToMime
394: Converts a Thot PicType into the equivalent MIME type. If no convertion
395: is possible, it returns NULL.
1.116 kahan 396: ----------------------------------------------------------------------*/
1.203 vatton 397: const char *PicTypeToMIME (PicType contentType)
1.116 kahan 398: {
1.203 vatton 399: const char *mime_type;
1.116 kahan 400:
401: switch (contentType)
402: {
1.179 vatton 403: case xbm_type:
404: mime_type ="image/x-xbitmap";
405: break;
1.116 kahan 406: case eps_type:
407: mime_type ="application/postscript";
408: break;
1.195 vatton 409: case xpm_type:
1.116 kahan 410: mime_type ="image/x-xpicmap";
1.195 vatton 411: break;
1.116 kahan 412: case gif_type:
413: mime_type ="image/gif";
414: break;
415: case jpeg_type:
416: mime_type ="image/jpeg";
417: break;
418: case png_type:
419: mime_type ="image/png";
420: break;
421: case svg_type:
1.165 cvs 422: mime_type = AM_SVG_MIME_TYPE;
423: break;
424: case html_type:
425: mime_type = AM_XHTML_MIME_TYPE;
426: break;
427: case mathml_type:
428: mime_type = AM_MATHML_MIME_TYPE;
1.116 kahan 429: break;
1.195 vatton 430: case unknown_type:
431: default:
432: mime_type = NULL;
433: }
1.116 kahan 434:
435: return mime_type;
436: }
1.61 cvs 437:
438: /*----------------------------------------------------------------------
1.195 vatton 439: ImageElement
440: Returns the element (image parameter) and URL (url parameter) of an
441: image in a docImage document. The user must free the memory associated
442: with the url parameter if the function is succesful.
443: If the url parameter is NULL, we won't initialize it.
444: Returns TRUE if succesful, FALSE otherwise.
1.117 kahan 445: ----------------------------------------------------------------------*/
446: ThotBool ImageElement (Document doc, char **url, Element *image)
447: {
448: Element el, imgEl;
449: Attribute attr, srcAttr;
450: AttributeType attrType;
451: int length;
1.176 vatton 452: char *utf8value;
1.117 kahan 453:
454: if (DocumentTypes[doc] != docImage)
455: return FALSE;
456:
457: /* find the value of the src attribute */
458: attrType.AttrSSchema = TtaGetSSchema ("HTML", doc);
459: attrType.AttrTypeNum = HTML_ATTR_SRC;
460: el = TtaGetRootElement (doc);
461: TtaSearchAttribute (attrType, SearchInTree, el, &imgEl, &srcAttr);
462:
463: if (!imgEl)
464: return FALSE;
465: *image = imgEl;
466:
1.120 kahan 467: if (url)
468: {
469: attr = TtaGetAttribute (imgEl, attrType);
470: length = TtaGetTextAttributeLength (srcAttr) + 1;
1.176 vatton 471: utf8value = (char *)TtaGetMemory (length);
472: TtaGiveTextAttributeValue (srcAttr, utf8value, &length);
473: *url = (char *)TtaConvertMbsToByte ((unsigned char *)utf8value,
1.195 vatton 474: TtaGetDefaultCharset ());
1.176 vatton 475: TtaFreeMemory (utf8value);
1.120 kahan 476: }
1.117 kahan 477: return TRUE;
478: }
479:
480: /*----------------------------------------------------------------------
1.195 vatton 481: DocImageMimeType
482: Returns the MIME type of a docImage document.
1.117 kahan 483: ----------------------------------------------------------------------*/
1.203 vatton 484: const char *DocImageMimeType (Document doc)
1.117 kahan 485: {
1.203 vatton 486: const char *mime_type;
1.117 kahan 487: LoadedImageDesc *pImage;
488: PicType type;
489: Element image;
490:
491: if (DocumentTypes[doc] != docImage)
492: return NULL;
493:
494: mime_type = NULL;
495: if (!IsHTTPPath (DocumentURLs[doc]))
496: {
497: /* it is a local image */
1.120 kahan 498: if (ImageElement (doc, NULL, &image))
1.195 vatton 499: {
500: type = TtaGetPictureType (image);
501: mime_type = PicTypeToMIME (type);
502: }
1.117 kahan 503: }
504: else
505: {
506: /* find the value of the src attribute */
507: pImage = ImageURLs;
508: while (pImage != NULL)
1.195 vatton 509: {
510: if (pImage->document == doc)
511: {
512: if (pImage->content_type)
513: mime_type = pImage->content_type;
514: else if (pImage->elImage && pImage->elImage->currentElement)
515: {
516: type = TtaGetPictureType (pImage->elImage->currentElement);
517: mime_type = PicTypeToMIME (type);
518: }
519: break;
520: }
521: }
1.117 kahan 522: }
523: return (mime_type);
524: }
525:
1.4 cvs 526: /*----------------------------------------------------------------------
1.9 cvs 527: IsHTMLName
528: returns TRUE if path points to an HTML resource.
1.4 cvs 529: ----------------------------------------------------------------------*/
1.109 cvs 530: ThotBool IsHTMLName (const char *path)
1.106 cvs 531: {
1.183 quint 532: char *temppath;
533: char *suffix;
1.136 cvs 534: char nsuffix[MAX_LENGTH];
535: int i;
1.5 cvs 536:
1.101 cvs 537: if (!path)
538: return (FALSE);
1.5 cvs 539:
1.183 quint 540: temppath = TtaStrdup ((char *)path);
541: suffix = (char *)TtaGetMemory (strlen (path) + 1);
1.124 vatton 542: TtaExtractSuffix (temppath, suffix);
1.101 cvs 543: i = 0;
1.106 cvs 544: while (suffix[i] != EOS)
1.101 cvs 545: {
546: /* Normalize the suffix */
547: i = 0;
1.106 cvs 548: while (suffix[i] != EOS && i < MAX_LENGTH -1)
1.195 vatton 549: {
550: nsuffix[i] = tolower (suffix[i]);
551: i++;
552: }
1.106 cvs 553: nsuffix[i] = EOS;
554: if (!strcmp (nsuffix, "html") ||
1.195 vatton 555: !strcmp (nsuffix, "htm") ||
556: !strcmp (nsuffix, "shtml") ||
1.197 vatton 557: !strcmp (nsuffix, "asp") ||
1.195 vatton 558: !strcmp (nsuffix, "jsp") ||
559: !strcmp (nsuffix, "tpl") ||
560: !strcmp (nsuffix, "xht") ||
561: !strcmp (nsuffix, "xhtm") ||
562: !strcmp (nsuffix, "lhtml") ||
563: !strcmp (nsuffix, "xhtml"))
564: {
565: TtaFreeMemory (temppath);
566: TtaFreeMemory (suffix);
567: return (TRUE);
568: }
1.106 cvs 569: else if (!strcmp (nsuffix, "gz"))
1.195 vatton 570: {
571: /* take into account compressed files */
572: TtaExtractSuffix (temppath, suffix);
573: /* Normalize the suffix */
574: i = 0;
575: while (suffix[i] != EOS && i < MAX_LENGTH -1)
576: {
577: nsuffix[i] = tolower (suffix[i]);
578: i++;
579: }
580: nsuffix[i] = EOS;
581: TtaFreeMemory (temppath);
582: TtaFreeMemory (suffix);
583: if (!strcmp (nsuffix, "html") ||
584: !strcmp (nsuffix, "htm") ||
585: !strcmp (nsuffix, "shtml") ||
1.197 vatton 586: !strcmp (nsuffix, "asp") ||
1.195 vatton 587: !strcmp (nsuffix, "jsp") ||
588: !strcmp (nsuffix, "tpl") ||
589: !strcmp (nsuffix, "xht") ||
590: !strcmp (nsuffix, "xhtm") ||
591: !strcmp (nsuffix, "lhtml") ||
592: !strcmp (nsuffix, "xhtml"))
593: return (TRUE);
594: else
595: return (FALSE);
596: }
1.101 cvs 597: else
1.195 vatton 598: /* check if there is another suffix */
599: TtaExtractSuffix (temppath, suffix);
1.101 cvs 600: }
1.183 quint 601: TtaFreeMemory (temppath);
602: TtaFreeMemory (suffix);
603: return (FALSE);
1.3 cvs 604: }
605:
1.4 cvs 606: /*----------------------------------------------------------------------
1.136 cvs 607: IsMathMLName
608: returns TRUE if path points to an MathML resource.
1.56 cvs 609: ----------------------------------------------------------------------*/
1.136 cvs 610: ThotBool IsMathMLName (const char *path)
1.56 cvs 611: {
1.195 vatton 612: char *temppath;
613: char *suffix;
614: ThotBool ret;
615:
616: if (!path)
617: return (FALSE);
618:
619: temppath = TtaStrdup ((char *)path);
620: suffix = (char *)TtaGetMemory (strlen (path) + 1);
621: TtaExtractSuffix (temppath, suffix);
622:
623: if (!strcasecmp (suffix, "mml"))
624: ret = TRUE;
625: else if (!strcmp (suffix, "gz"))
626: {
627: /* take into account compressed files */
628: TtaExtractSuffix (temppath, suffix);
629: if (!strcasecmp (suffix, "mml"))
630: ret = TRUE;
631: else
632: ret = FALSE;
633: }
634: else
635: ret = FALSE;
1.183 quint 636:
637: TtaFreeMemory (temppath);
638: TtaFreeMemory (suffix);
639: return (ret);
1.60 cvs 640: }
641:
642: /*----------------------------------------------------------------------
1.136 cvs 643: IsSVGName
644: returns TRUE if path points to an SVG resource.
1.133 vatton 645: ----------------------------------------------------------------------*/
1.136 cvs 646: ThotBool IsSVGName (const char *path)
1.133 vatton 647: {
1.195 vatton 648: char *temppath;
649: char *suffix;
650: ThotBool ret;
651:
652: if (!path)
653: return (FALSE);
654:
655: temppath = TtaStrdup ((char *)path);
656: suffix = (char *)TtaGetMemory (strlen (path) + 1);
657: TtaExtractSuffix (temppath, suffix);
658:
659: if (!strcasecmp (suffix, "svg") || !strcasecmp (suffix, "svgz"))
660: ret = TRUE;
661: else if (!strcmp (suffix, "gz"))
662: {
663: /* take into account compressed files */
664: TtaExtractSuffix (temppath, suffix);
665: if (!strcasecmp (suffix, "svg"))
666: ret = TRUE;
667: else
668: ret = FALSE;
669: }
670: else
671: ret = FALSE;
1.183 quint 672:
673: TtaFreeMemory (temppath);
674: TtaFreeMemory (suffix);
675: return (ret);
1.133 vatton 676: }
677:
678: /*----------------------------------------------------------------------
1.136 cvs 679: IsXMLName
680: returns TRUE if path points to an XML resource.
1.103 cvs 681: ----------------------------------------------------------------------*/
1.136 cvs 682: ThotBool IsXMLName (const char *path)
1.103 cvs 683: {
1.195 vatton 684: char *temppath;
685: char *suffix;
686: ThotBool ret;
687:
688: if (!path)
689: return (FALSE);
690:
691: temppath = TtaStrdup ((char *)path);
692: suffix = (char *)TtaGetMemory (strlen (path) + 1);
693: TtaExtractSuffix (temppath, suffix);
694:
695: if (!strcasecmp (suffix, "xml") ||
696: !strcasecmp (suffix, "xht") ||
1.197 vatton 697: !strcasecmp (suffix, "xtd") ||
1.200 kia 698: !strcasecmp (suffix, "xtl") ||
1.195 vatton 699: !strcmp (suffix, "xhtm") ||
700: !strcmp (suffix, "xhtml") ||
701: !strcmp (suffix, "smi") ||
1.201 vatton 702: !strcmp (suffix, "xsd") |
703: !strcmp (suffix, "xslt") |
704: !strcmp (suffix, "xsl") |
1.195 vatton 705: !strcmp (suffix, "zsl"))
706: ret = TRUE;
707: else if (!strcmp (suffix, "gz"))
708: {
709: /* take into account compressed files */
710: TtaExtractSuffix (temppath, suffix);
711: if (!strcasecmp (suffix, "xml") ||
712: !strcasecmp (suffix, "xht") ||
1.197 vatton 713: !strcasecmp (suffix, "xtd") ||
1.200 kia 714: !strcasecmp (suffix, "xtl") ||
1.195 vatton 715: !strcmp (suffix, "xhtm") ||
716: !strcmp (suffix, "xhtml") ||
1.201 vatton 717: !strcmp (suffix, "xsd") |
718: !strcmp (suffix, "xslt") |
719: !strcmp (suffix, "xsl") |
720: !strcmp (suffix, "smi"))
721: ret = TRUE;
722: else
723: ret = FALSE;
724: }
725: else
726: ret = FALSE;
727:
728: TtaFreeMemory (temppath);
729: TtaFreeMemory (suffix);
730: return (ret);
731: }
732:
733: /*----------------------------------------------------------------------
734: IsXMLStruct
735: returns TRUE if path points to an XML transformation or schema.
736: ----------------------------------------------------------------------*/
737: ThotBool IsXMLStruct (const char *path)
738: {
739: char *temppath;
740: char *suffix;
741: ThotBool ret;
742:
743: if (!path)
744: return (FALSE);
745:
746: temppath = TtaStrdup ((char *)path);
747: suffix = (char *)TtaGetMemory (strlen (path) + 1);
748: TtaExtractSuffix (temppath, suffix);
749:
750: if (!strcmp (suffix, "xsd") |
751: !strcmp (suffix, "xslt") |
752: !strcmp (suffix, "xsl"))
753: ret = TRUE;
754: else if (!strcmp (suffix, "gz"))
755: {
756: /* take into account compressed files */
757: TtaExtractSuffix (temppath, suffix);
758: if (!strcmp (suffix, "xsd") |
759: !strcmp (suffix, "xslt") |
1.195 vatton 760: !strcmp (suffix, "xsl"))
761: ret = TRUE;
762: else
763: ret = FALSE;
764: }
765: else
766: ret = FALSE;
1.183 quint 767:
768: TtaFreeMemory (temppath);
769: TtaFreeMemory (suffix);
770: return (ret);
1.103 cvs 771: }
772:
773: /*----------------------------------------------------------------------
1.207 kia 774: IsXTigerLibrary
775: returns TRUE if path points to an XTiger resource.
776: ----------------------------------------------------------------------*/
777: ThotBool IsXTigerLibrary (const char *path)
778: {
779: char *temppath;
780: char *suffix;
781: ThotBool ret;
782:
783: if (!path)
784: return (FALSE);
785:
786: temppath = TtaStrdup ((char *)path);
787: suffix = (char *)TtaGetMemory (strlen (path) + 1);
788: TtaExtractSuffix (temppath, suffix);
789:
790: if (!strcasecmp (suffix, "xtl"))
791: ret = TRUE;
792: else if (!strcmp (suffix, "gz"))
793: {
794: /* take into account compressed files */
795: TtaExtractSuffix (temppath, suffix);
796: if (!strcasecmp (suffix, "xtl"))
797: ret = TRUE;
798: else
799: ret = FALSE;
800: }
801: else
802: ret = FALSE;
803:
804: TtaFreeMemory (temppath);
805: TtaFreeMemory (suffix);
806: return (ret);
807: }
808:
809: /*----------------------------------------------------------------------
810: IsXTiger
1.199 vatton 811: returns TRUE if path points to an XTiger resource.
812: ----------------------------------------------------------------------*/
813: ThotBool IsXTiger (const char *path)
814: {
815: char *temppath;
816: char *suffix;
817: ThotBool ret;
818:
819: if (!path)
820: return (FALSE);
821:
822: temppath = TtaStrdup ((char *)path);
823: suffix = (char *)TtaGetMemory (strlen (path) + 1);
824: TtaExtractSuffix (temppath, suffix);
825:
1.207 kia 826: if (!strcasecmp (suffix, "xtd"))
1.199 vatton 827: ret = TRUE;
828: else if (!strcmp (suffix, "gz"))
829: {
830: /* take into account compressed files */
831: TtaExtractSuffix (temppath, suffix);
1.207 kia 832: if (!strcasecmp (suffix, "xtd"))
1.199 vatton 833: ret = TRUE;
834: else
835: ret = FALSE;
836: }
837: else
838: ret = FALSE;
839:
840: TtaFreeMemory (temppath);
841: TtaFreeMemory (suffix);
842: return (ret);
843: }
844:
845: /*----------------------------------------------------------------------
1.136 cvs 846: IsUndisplayedName
847: returns TRUE if path points to an undisplayed resource.
1.103 cvs 848: ----------------------------------------------------------------------*/
1.136 cvs 849: ThotBool IsUndisplayedName (const char *path)
1.103 cvs 850: {
1.195 vatton 851: char *temppath;
852: char *suffix;
853: ThotBool ret;
854:
855: if (!path)
856: return (FALSE);
857:
858: temppath = TtaStrdup ((char *)path);
859: suffix = (char *)TtaGetMemory (strlen (path) + 1);
860: TtaExtractSuffix (temppath, suffix);
861:
862: if (!strcasecmp (suffix, "exe") ||
863: !strcasecmp (suffix, "zip") ||
864: !strcasecmp (suffix, "ppt") ||
865: !strcasecmp (suffix, "pdf") ||
866: !strcasecmp (suffix, "ps") ||
867: !strcasecmp (suffix, "eps") ||
868: !strcasecmp (suffix, "tar") ||
869: !strcasecmp (suffix, "tgz") ||
870: !strcasecmp (suffix, "ddl") ||
1.196 vatton 871: !strcasecmp (suffix, "deb") ||
872: !strcasecmp (suffix, "dmg") ||
1.195 vatton 873: !strcasecmp (suffix, "mpg") ||
874: !strcasecmp (suffix, "mpeg") ||
1.196 vatton 875: !strcasecmp (suffix, "rpm") ||
1.195 vatton 876: !strcasecmp (suffix, "wmv") ||
877: !strcasecmp (suffix, "wma") ||
878: !strcasecmp (suffix, "o"))
879: ret = TRUE;
880: else if (!strcmp (suffix, "gz"))
881: {
882: /* take into account compressed files */
883: TtaExtractSuffix (temppath, suffix);
884: if (!strcasecmp (suffix, "exe") ||
885: !strcasecmp (suffix, "zip") ||
886: !strcasecmp (suffix, "ppt") ||
887: !strcasecmp (suffix, "pdf") ||
888: !strcasecmp (suffix, "ps") ||
889: !strcasecmp (suffix, "eps") ||
890: !strcasecmp (suffix, "tar") ||
891: !strcasecmp (suffix, "ddl") ||
1.196 vatton 892: !strcasecmp (suffix, "dmg") ||
1.195 vatton 893: !strcasecmp (suffix, "mpg") ||
894: !strcasecmp (suffix, "mpeg") ||
895: !strcasecmp (suffix, "wmv") ||
896: !strcasecmp (suffix, "wma") ||
897: !strcasecmp (suffix, "o"))
898: ret = TRUE;
899: else
900: ret = FALSE;
901: }
902: else
903: ret = FALSE;
904:
905: TtaFreeMemory (temppath);
906: TtaFreeMemory (suffix);
907: return (ret);
1.103 cvs 908: }
909:
910: /*----------------------------------------------------------------------
1.60 cvs 911: IsCSSName
912: returns TRUE if path points to an XML resource.
913: ----------------------------------------------------------------------*/
1.111 cvs 914: ThotBool IsCSSName (const char *path)
1.60 cvs 915: {
1.195 vatton 916: char *temppath;
917: char *suffix;
918: ThotBool ret;
919:
920: if (!path)
921: return (FALSE);
922:
923: temppath = TtaStrdup ((char *)path);
924: suffix = (char *)TtaGetMemory (strlen (path) + 1);
925: TtaExtractSuffix (temppath, suffix);
926:
927: if (!strcasecmp (suffix, "css"))
928: ret = TRUE;
929: else if (!strcmp (suffix, "gz"))
930: {
931: /* take into account compressed files */
932: TtaExtractSuffix (temppath, suffix);
933: if (!strcasecmp (suffix, "css"))
934: ret = TRUE;
935: else
936: ret = FALSE;
937: }
938: else
939: ret = FALSE;
940:
941: TtaFreeMemory (temppath);
942: TtaFreeMemory (suffix);
943: return (ret);
1.56 cvs 944: }
945:
946: /*----------------------------------------------------------------------
1.177 kahan 947: MultipleBookmarks
948: returns the value of the multiple bookmarks environment variable.
949: (TRUE if enabled).
950: ----------------------------------------------------------------------*/
951: ThotBool MultipleBookmarks (void)
952: {
953: ThotBool multiple_bm;
954:
1.180 kahan 955: TtaGetEnvBoolean ("DISABLE_MULTIPLE_BM", &multiple_bm);
1.177 kahan 956:
1.180 kahan 957: return (multiple_bm == FALSE);
1.177 kahan 958: }
959:
960: /*----------------------------------------------------------------------
1.172 kahan 961: IsRDFName
962: returns TRUE if path points to an RDF resource.
963: ----------------------------------------------------------------------*/
964: ThotBool IsRDFName (const char *path)
965: {
1.195 vatton 966: char *temppath;
967: char *suffix;
968: ThotBool ret;
969:
970: /* temporarily disabling this function */
971: if (!MultipleBookmarks ())
972: return (FALSE);
973:
974: if (!path)
975: return (FALSE);
976:
977: temppath = TtaStrdup ((char *)path);
978: suffix = (char *)TtaGetMemory (strlen (path) + 1);
979: TtaExtractSuffix (temppath, suffix);
980:
981: if (!strcasecmp (suffix, "rdf"))
982: ret = TRUE;
983: else if (!strcmp (suffix, "gz"))
984: {
985: /* take into account compressed files */
986: TtaExtractSuffix (temppath, suffix);
987: if (!strcasecmp (suffix, "rdf"))
988: ret = TRUE;
989: else
990: ret = FALSE;
991: }
992: else
993: ret = FALSE;
1.183 quint 994:
1.195 vatton 995: TtaFreeMemory (temppath);
996: TtaFreeMemory (suffix);
997: return (ret);
1.172 kahan 998: }
999:
1000: /*----------------------------------------------------------------------
1.9 cvs 1001: IsImageName
1002: returns TRUE if path points to an image resource.
1.4 cvs 1003: ----------------------------------------------------------------------*/
1.111 cvs 1004: ThotBool IsImageName (const char *path)
1.106 cvs 1005: {
1.195 vatton 1006: char *temppath;
1007: char *suffix;
1008: char nsuffix[MAX_LENGTH];
1009: int i;
1010: ThotBool ret;
1011:
1012: if (!path)
1013: return (FALSE);
1014:
1015: temppath = TtaStrdup ((char *)path);
1016: suffix = (char *)TtaGetMemory (strlen (path) + 1);
1017: TtaExtractSuffix (temppath, suffix);
1018:
1019: /* Normalize the suffix */
1020: i = 0;
1021: while (suffix[i] != EOS && i < MAX_LENGTH -1)
1022: {
1023: nsuffix[i] = tolower (suffix[i]);
1024: i++;
1025: }
1026: nsuffix[i] = EOS;
1027: if ((!strcmp (nsuffix, "gif")) || (!strcmp (nsuffix, "xbm")) ||
1028: (!strcmp (nsuffix, "xpm")) || (!strcmp (nsuffix, "jpg")) ||
1029: (!strcmp (nsuffix, "png")) || (!strcmp (nsuffix, "au")))
1030: ret = TRUE;
1031: else
1032: ret = FALSE;
1033:
1034: TtaFreeMemory (temppath);
1035: TtaFreeMemory (suffix);
1036: return (ret);
1.3 cvs 1037: }
1038:
1.4 cvs 1039: /*----------------------------------------------------------------------
1.58 cvs 1040: IsImageType
1041: returns TRUE if type points to an image resource.
1042: ----------------------------------------------------------------------*/
1.111 cvs 1043: ThotBool IsImageType (const char *type)
1.58 cvs 1044: {
1.195 vatton 1045: char *temptype;
1046: int i;
1047: ThotBool ret;
1048:
1049: if (!type)
1050: return (FALSE);
1051:
1052: temptype = TtaStrdup ((char *)type);
1053: /* Normalize the type */
1054: i = 0;
1055: while (temptype[i] != EOS)
1056: {
1057: temptype[i] = tolower (temptype[i]);
1058: i++;
1059: }
1.166 vatton 1060: if (!strncmp (temptype, "image/", sizeof ("image/") - 1))
1.195 vatton 1061: i = sizeof ("image/") - 1;
1062: else
1063: i = 0;
1064: if (!strcmp (&temptype[i], "gif") ||
1065: !strcmp (&temptype[i], "x-xbitmap") ||
1066: !strcmp (&temptype[i], "x-xpixmap") ||
1067: !strcmp (&temptype[i], "jpeg") ||
1068: !strcmp (&temptype[i], "png"))
1069: ret = TRUE;
1070: else
1071: ret = FALSE;
1072: TtaFreeMemory (temptype);
1073: return (ret);
1.58 cvs 1074: }
1075:
1076: /*----------------------------------------------------------------------
1.9 cvs 1077: IsTextName
1.4 cvs 1078: ----------------------------------------------------------------------*/
1.111 cvs 1079: ThotBool IsTextName (const char *path)
1.106 cvs 1080: {
1.195 vatton 1081: char *temppath;
1082: char *suffix;
1083: char nsuffix[MAX_LENGTH];
1084: int i;
1085: ThotBool ret;
1086:
1087: if (!path)
1088: return (FALSE);
1089:
1090: temppath = TtaStrdup ((char *)path);
1091: suffix = (char *)TtaGetMemory (strlen (path) + 1);
1092: TtaExtractSuffix (temppath, suffix);
1093:
1094: /* Normalize the suffix */
1095: i = 0;
1096: while (suffix[i] != EOS && i < MAX_LENGTH -1)
1097: {
1098: nsuffix[i] = tolower (suffix[i]);
1099: i++;
1100: }
1101: nsuffix[i] = EOS;
1102:
1103: if (!strcmp (nsuffix, "txt") ||
1104: !strcmp (nsuffix, "dtd"))
1105: ret = TRUE;
1106: else if (!strcmp (nsuffix, "gz"))
1107: {
1108: /* take into account compressed files */
1109: TtaExtractSuffix (temppath, suffix);
1110: /* Normalize the suffix */
1111: i = 0;
1112: while (suffix[i] != EOS && i < MAX_LENGTH -1)
1113: {
1114: nsuffix[i] = tolower (suffix[i]);
1115: i++;
1116: }
1117: nsuffix[i] = EOS;
1118: if (!strcmp (nsuffix, "txt") ||
1119: !strcmp (nsuffix, "dtd"))
1120: ret = TRUE;
1121: else
1122: ret = FALSE;
1123: }
1124: else
1125: ret = FALSE;
1126:
1127: TtaFreeMemory (temppath);
1128: TtaFreeMemory (suffix);
1129: return (ret);
1.3 cvs 1130: }
1131:
1.4 cvs 1132: /*----------------------------------------------------------------------
1.9 cvs 1133: IsHTTPPath
1134: returns TRUE if path is in fact an http URL.
1.4 cvs 1135: ----------------------------------------------------------------------*/
1.112 cvs 1136: ThotBool IsHTTPPath (const char *path)
1.3 cvs 1137: {
1.195 vatton 1138: if (!path)
1139: return FALSE;
1.3 cvs 1140:
1.195 vatton 1141: if ((!strncmp (path, "http:", 5) != 0)
1.204 vatton 1142: || !strncmp (path, "ftp:", 4)
1.195 vatton 1143: || !strncmp (path, "internal:", 9))
1144: return TRUE;
1145: return FALSE;
1.3 cvs 1146: }
1147:
1.4 cvs 1148: /*----------------------------------------------------------------------
1.9 cvs 1149: IsWithParameters
1150: returns TRUE if url has a concatenated query string.
1.4 cvs 1151: ----------------------------------------------------------------------*/
1.133 vatton 1152: ThotBool IsWithParameters (const char *url)
1.3 cvs 1153: {
1.195 vatton 1154: int i;
1155:
1156: if ((!url) || (url[0] == EOS))
1157: return FALSE;
1.3 cvs 1158:
1.195 vatton 1159: i = strlen (url) - 1;
1160: while (i > 0 && url[i--] != '?')
1161: if (i < 0)
1.5 cvs 1162: return FALSE;
1.3 cvs 1163:
1.195 vatton 1164: /* There is a parameter */
1165: return TRUE;
1.3 cvs 1166: }
1167:
1.4 cvs 1168: /*----------------------------------------------------------------------
1.9 cvs 1169: IsW3Path
1170: returns TRUE if path is in fact a URL.
1.4 cvs 1171: ----------------------------------------------------------------------*/
1.133 vatton 1172: ThotBool IsW3Path (const char *path)
1.106 cvs 1173: {
1.170 quint 1174: if (path == NULL)
1175: return FALSE;
1.106 cvs 1176: if (strncmp (path, "http:", 5) &&
1177: strncmp (path, "ftp:", 4) &&
1178: strncmp (path, "telnet:", 7) &&
1179: strncmp (path, "wais:", 5) &&
1180: strncmp (path, "news:", 5) &&
1181: strncmp (path, "gopher:", 7) &&
1182: strncmp (path, "mailto:", 7) &&
1.132 cheyroul 1183: strncmp (path, "archie:", 7) &&
1184: strncmp (path, "https:", 6))
1.72 cvs 1185: return FALSE;
1186: return TRUE;
1.3 cvs 1187: }
1188:
1.4 cvs 1189: /*----------------------------------------------------------------------
1.90 cvs 1190: IsFilePath
1191: returns TRUE if path is in fact a URL.
1192: ----------------------------------------------------------------------*/
1.133 vatton 1193: ThotBool IsFilePath (const char *path)
1.90 cvs 1194: {
1.106 cvs 1195: if (strncmp (path, "file:", 5))
1.90 cvs 1196: return FALSE;
1197: return TRUE;
1198: }
1199:
1200: /*----------------------------------------------------------------------
1.9 cvs 1201: IsValidProtocol
1202: returns true if the url protocol is supported by Amaya.
1.4 cvs 1203: ----------------------------------------------------------------------*/
1.133 vatton 1204: ThotBool IsValidProtocol (const char *url)
1.106 cvs 1205: {
1.195 vatton 1206: if (!strncmp (url, "http:", 5)
1.106 cvs 1207: || !strncmp (url, "internal:", 9)
1.204 vatton 1208: || !strncmp (url, "ftp:", 4))
1.195 vatton 1209: /* experimental */
1210: /*** || !strncmp (path, "news:", 5)***/
1211: return (TRUE);
1212: else
1213: return (FALSE);
1.3 cvs 1214: }
1215:
1.31 cvs 1216:
1217: /*----------------------------------------------------------------------
1.195 vatton 1218: GetBaseURL
1219: normalizes orgName according to a base associated with doc, and
1220: following the standard URL format rules.
1221: The function returns the base used to solve relative URL and SRC:
1222: - the base of the document,
1223: - or the document path (without document name).
1.31 cvs 1224: ----------------------------------------------------------------------*/
1.106 cvs 1225: char *GetBaseURL (Document doc)
1.31 cvs 1226: {
1227: Element el;
1228: ElementType elType;
1229: AttributeType attrType;
1230: Attribute attr;
1.176 vatton 1231: char *ptr, *basename, *utf8path;
1.31 cvs 1232: int length;
1.151 kahan 1233: ThotBool hasDocBase;
1.31 cvs 1234:
1.113 cvs 1235: if (doc == 0 || !DocumentURLs[doc])
1.195 vatton 1236: return NULL;
1.148 kahan 1237: /* the other functions expect basename to have no more than MAX_LENGTH chars */
1.171 gully 1238: basename = (char *)TtaGetMemory (MAX_LENGTH);
1.148 kahan 1239: basename[0] = EOS;
1.31 cvs 1240: length = MAX_LENGTH -1;
1.151 kahan 1241: hasDocBase = FALSE;
1242:
1243: /* If the document has a base URL, it has a priority over the headers. */
1244: /* @@ We need to do this too when we support XML:base */
1245:
1246: /* is it a HTML document ? */
1247: elType.ElSSchema = TtaGetDocumentSSchema (doc);
1248: if (!strcmp (TtaGetSSchemaName (elType.ElSSchema), "HTML"))
1249: /* it's a HTML document */
1250: {
1251: /* get the document element */
1252: el = TtaGetMainRoot (doc);
1253: /* search the BASE element */
1254: elType.ElTypeNum = HTML_EL_HEAD;
1255: el = TtaSearchTypedElement (elType, SearchForward, el);
1256: if (el)
1.195 vatton 1257: /* there is a HEAD element */
1258: {
1259: /* look for a BASE element within the HEAD */
1260: elType.ElTypeNum = HTML_EL_BASE;
1261: el = TtaSearchTypedElement (elType, SearchInTree, el);
1262: }
1.151 kahan 1263: if (el)
1.195 vatton 1264: {
1265: /* The document has a BASE element. Get the HREF attribute of the
1266: BASE element */
1267: hasDocBase = TRUE;
1268: attrType.AttrSSchema = elType.ElSSchema;
1269: attrType.AttrTypeNum = HTML_ATTR_HREF_;
1270: attr = TtaGetAttribute (el, attrType);
1271: if (attr)
1272: {
1273: /* Use the base path of the document */
1274: TtaGiveTextAttributeValue (attr, basename, &length);
1275: utf8path = (char *)TtaConvertMbsToByte ((unsigned char *)basename,
1276: TtaGetDefaultCharset ());
1277: strncpy (basename, utf8path, MAX_LENGTH-1);
1278: TtaFreeMemory (utf8path);
1279: }
1280: }
1.151 kahan 1281: }
1282:
1283: /* there was no BASE. Do we have a location header? */
1284: if (!hasDocBase && DocumentMeta[doc] && DocumentMeta[doc]->full_content_location
1.148 kahan 1285: && DocumentMeta[doc]->full_content_location[0] != EOS)
1.65 cvs 1286: {
1.148 kahan 1287: strncpy (basename, DocumentMeta[doc]->full_content_location, MAX_LENGTH-1);
1288: basename[MAX_LENGTH-1] = EOS;
1289: length = strlen (basename);
1290: }
1291:
1292: if (basename[0] != EOS)
1293: {
1294: /* base and orgName have to be separated by a DIR_SEP */
1295: length--;
1296: if (basename[0] != EOS && basename[length] != URL_SEP &&
1.195 vatton 1297: basename[length] != DIR_SEP)
1298: /* verify if the base has the form "protocol://server:port" */
1299: {
1300: ptr = AmayaParseUrl (basename, "", AMAYA_PARSE_ACCESS |
1301: AMAYA_PARSE_HOST |
1302: AMAYA_PARSE_PUNCTUATION);
1303: if (ptr && !strcmp (ptr, basename))
1304: {
1305: /* it has this form, complete it by adding a URL_STR */
1306: if (strchr (basename, DIR_SEP))
1307: strcat (basename, DIR_STR);
1308: else
1309: strcat (basename, URL_STR);
1310: length++;
1311: }
1312: else if (!ptr || ptr[0] == EOS)
1313: {
1314: /* no host was detected, we may have a relative URL. We test
1315: if it begins with a URL_SEP, DIR_SEP or period. If yes, it's
1316: relative. */
1317: if (! (basename[0] == '.' || basename[0] == URL_SEP
1318: || basename[0] == DIR_SEP))
1319: basename[0] = EOS;
1320: }
1321: if (ptr)
1322: TtaFreeMemory (ptr);
1323: }
1.113 cvs 1324: }
1325:
1.148 kahan 1326: /* there was no base element and no location header, we use the DocumentURL */
1327: if (basename[0] == EOS)
1328: {
1329: strncpy (basename, DocumentURLs[doc], MAX_LENGTH-1);
1330: basename[MAX_LENGTH-1] = EOS;
1331: }
1332:
1.31 cvs 1333: /* Remove anything after the last DIR_SEP char. If no such char is found,
1334: * then search for the first ":" char, hoping that what's before that is a
1335: * protocol. If found, end the string there. If neither char is found,
1336: * then discard the whole base element.
1337: */
1.106 cvs 1338: length = strlen (basename) - 1;
1.31 cvs 1339: /* search for the last DIR_SEP char */
1.106 cvs 1340: while (length >= 0 && basename[length] != URL_SEP && basename[length] != DIR_SEP)
1.31 cvs 1341: length--;
1342: if (length >= 0)
1343: /* found the last DIR_SEP char, end the string there */
1.106 cvs 1344: basename[length + 1] = EOS;
1.31 cvs 1345: else
1346: /* search for the first PATH_STR char */
1347: {
1.106 cvs 1348: for (length = 0; basename[length] != ':' &&
1.195 vatton 1349: basename[length] != EOS; length ++);
1.106 cvs 1350: if (basename[length] == ':')
1.195 vatton 1351: /* found, so end the string there */
1352: basename[length + 1] = EOS;
1.31 cvs 1353: else
1.195 vatton 1354: /* not found, discard the base */
1355: basename[0] = EOS;
1.31 cvs 1356: }
1357: return (basename);
1358: }
1359:
1360:
1.4 cvs 1361: /*----------------------------------------------------------------------
1.195 vatton 1362: GetLocalPath
1363: Allocate and return the local document path associated to the url
1.40 cvs 1364: ----------------------------------------------------------------------*/
1.150 vatton 1365: char *GetLocalPath (Document doc, char *url)
1.106 cvs 1366: {
1367: char *ptr;
1368: char *n;
1369: char *documentname;
1370: char url_sep;
1.83 cvs 1371: int len;
1.67 cvs 1372: ThotBool noFile;
1.40 cvs 1373:
1.153 vatton 1374: if (url)
1.40 cvs 1375: {
1376: /* check whether the file name exists */
1.106 cvs 1377: len = strlen (url) - 1;
1.71 cvs 1378: if (IsW3Path (url))
1.195 vatton 1379: url_sep = URL_SEP;
1.41 cvs 1380: else
1.195 vatton 1381: url_sep = DIR_SEP;
1.41 cvs 1382: noFile = (url[len] == url_sep);
1.40 cvs 1383: if (noFile)
1.195 vatton 1384: url[len] = EOS;
1.171 gully 1385: ptr = (char *)TtaGetMemory (MAX_LENGTH);
1386: documentname = (char *)TtaGetMemory (MAX_LENGTH);
1.78 cvs 1387: TtaExtractName (url, ptr, documentname);
1.106 cvs 1388: sprintf (ptr, "%s%s%d%s", TempFileDirectory, DIR_STR, doc, DIR_STR);
1.40 cvs 1389: if (!TtaCheckDirectory (ptr))
1.195 vatton 1390: /* directory did not exist */
1391: TtaMakeDirectory (ptr);
1.47 cvs 1392:
1.153 vatton 1393: if (doc == 0)
1.195 vatton 1394: {
1395: n = strrchr (documentname, '.');
1396: if (n)
1397: *n = EOS;
1398: if (documentname[0] == EOS)
1399: strcpy (documentname, "noname");
1400: n = GetTempName (ptr, documentname);
1401: TtaFreeMemory (ptr);
1402: ptr = n;
1403: }
1.69 cvs 1404: else
1.195 vatton 1405: {
1406: /* don't include the query string within document name */
1407: n = strrchr (documentname, '?');
1408: if (n)
1409: *n = EOS;
1410: /* don't include ':' within document name */
1411: n = strchr (documentname, ':');
1412: if (n)
1413: *n = EOS;
1414: /* if after all this operations document name
1415: is empty, let's use noname.html instead */
1416: if (documentname[0] == EOS)
1417: strcat (ptr, "noname.html");
1418: else
1419: strcat (ptr, documentname);
1420: }
1.40 cvs 1421: TtaFreeMemory (documentname);
1.157 kahan 1422: /* substitute invalid chars in file names by a _ */
1.188 gully 1423: n = strrchr(ptr,DIR_SEP);
1.157 kahan 1424: while (*n)
1.195 vatton 1425: {
1426: if (*n == '*' || *n == ',')
1427: *n = '_';
1428: if ((unsigned char)*n >= 0x80) /* avoid non-ASCII */
1429: *n = 'A' + ((unsigned char)*n % 26);
1430: n++;
1431: }
1.40 cvs 1432: /* restore the url */
1433: if (noFile)
1.195 vatton 1434: url[len] = url_sep;
1.40 cvs 1435: return (ptr);
1436: }
1437: else
1438: return (NULL);
1439: }
1440:
1.73 cvs 1441: /*----------------------------------------------------------------------
1.195 vatton 1442: ExtractTarget extract the target name from document nane.
1.79 cvs 1443: ----------------------------------------------------------------------*/
1.150 vatton 1444: void ExtractTarget (char *aName, char *target)
1.79 cvs 1445: {
1.195 vatton 1446: long int lg, i;
1447: char *ptr;
1448: char *oldptr;
1449:
1450: if (!target || !aName)
1451: /* bad target */
1452: return;
1453:
1454: target[0] = EOS;
1455: lg = strlen (aName);
1456: if (lg)
1457: {
1458: /* the name is not empty */
1459: oldptr = ptr = &aName[0];
1460: do
1461: {
1462: ptr = strrchr (oldptr, '#');
1463: if (ptr)
1464: oldptr = &ptr[1];
1465: }
1466: while (ptr);
1467:
1468: i = (long int) (oldptr) - (long int) (aName); /* name length */
1469: if (i > 1)
1470: {
1471: aName[i - 1] = EOS;
1472: if (i != lg)
1473: strcpy (target, oldptr);
1474: }
1475: }
1.79 cvs 1476: }
1477:
1478: /*----------------------------------------------------------------------
1.195 vatton 1479: RemoveNewLines (text)
1480: Removes any '\n' chars that are found in text.
1481: Returns TRUE if it did the operation, FALSE otherwise.
1.73 cvs 1482: ----------------------------------------------------------------------*/
1.106 cvs 1483: ThotBool RemoveNewLines (char *text)
1484: {
1485: ThotBool change = FALSE;
1486: char *src;
1487: char *dest;
1.90 cvs 1488:
1489: src = text;
1490: dest = text;
1.115 kahan 1491:
1492: /* remove any preceding whitespace */
1493: while (*src && *src == ' ')
1494: {
1495: src++;
1496: change = 1;
1497: }
1498:
1.90 cvs 1499: while (*src)
1500: {
1501: switch (*src)
1.195 vatton 1502: {
1503: case '\n':
1504: /* don't copy the newline */
1505: change = 1;
1506: break;
1507: default:
1508: *dest = *src;
1509: dest++;
1510: break;
1511: }
1.90 cvs 1512: src++;
1513: }
1514: /* copy the last EOS char */
1515: *dest = *src;
1516:
1517: return (change);
1518: }
1519:
1520: /*----------------------------------------------------------------------
1.195 vatton 1521: CleanCopyFileURL
1522: Copies a file url from a src string to destination string.
1523: convertion says which type of convertion (none, %xx, URL_SEP into DIR_SEP
1524: we want to do).
1.90 cvs 1525: ----------------------------------------------------------------------*/
1.106 cvs 1526: static void CleanCopyFileURL (char *dest, char *src,
1.195 vatton 1527: ConvertionType convertion)
1.90 cvs 1528: {
1529: while (*src)
1.89 cvs 1530: {
1.90 cvs 1531: switch (*src)
1.195 vatton 1532: {
1.184 gully 1533: #ifdef _WINDOWS
1.195 vatton 1534: case URL_SEP:
1535: /* make DIR_SEP transformation */
1536: if (convertion & AM_CONV_URL_SEP)
1537: *dest = DIR_SEP;
1538: else
1539: *dest = *src;
1540: dest++;
1541: src++;
1542: break;
1.184 gully 1543: #endif /* _WINDOWS */
1.96 cvs 1544:
1.195 vatton 1545: case '%':
1546: if (convertion & AM_CONV_PERCENT)
1547: {
1548: /* (code adapted from libwww's HTUnEscape function */
1549: src++;
1550: if (*src != EOS)
1551: {
1552: *dest = UnEscapeChar (*src) * 16;
1553: src++;
1554: }
1555: if (*src != EOS)
1556: {
1557: *dest = *dest + UnEscapeChar (*src);
1558: src++;
1559: }
1560: dest++;
1561: }
1562: else
1563: {
1564: *dest = *src;
1565: dest++;
1566: src++;
1567: }
1568: break;
1569:
1570: default:
1571: *dest = *src;
1572: dest++;
1573: src++;
1574: break;
1575: }
1.89 cvs 1576: }
1.90 cvs 1577: /* copy the EOS char */
1578: *dest = *src;
1.73 cvs 1579: }
1.40 cvs 1580:
1581: /*----------------------------------------------------------------------
1.195 vatton 1582: NormalizeURL
1583: normalizes orgName according to a base associated with doc, and
1584: following the standard URL format rules.
1585: if doc is < 0, use as a base the URL of the document that contains
1586: (or contained) the elements that are now in the copy/cut buffer.
1587: if doc is 0 and otherPath not NULL, normalizes orgName according to this
1588: other path.
1589: The function returns the new complete and normalized URL
1590: or file name path (newName) and the name of the document (docName).
1591: N.B. If the function can't find out what's the docName, it assigns
1592: the name "noname.html".
1.4 cvs 1593: ----------------------------------------------------------------------*/
1.106 cvs 1594: void NormalizeURL (char *orgName, Document doc, char *newName,
1.206 kia 1595: char *docName, const char *otherPath)
1.106 cvs 1596: {
1.195 vatton 1597: char *basename;
1598: char tempOrgName[MAX_LENGTH];
1599: char *ptr;
1600: char used_sep;
1601: int length;
1602: ThotBool check;
1.5 cvs 1603:
1.184 gully 1604: #ifdef _WINDOWS
1.195 vatton 1605: int ndx;
1.184 gully 1606: #endif /* _WINDOWS */
1.44 cvs 1607:
1.195 vatton 1608: if (!newName || !docName)
1609: return;
1610:
1611: if (doc < 0)
1612: basename = TtaStrdup (SavedDocumentURL);
1613: else if (doc > 0)
1614: basename = GetBaseURL (doc);
1615: else if (otherPath != NULL)
1616: basename = TtaStrdup (otherPath);
1617: else
1618: basename = NULL;
1619:
1620: /*
1621: * Clean orgName
1622: * Make sure we have a complete orgName, without any leading or trailing
1623: * white spaces, or trailinbg new lines
1624: */
1625: ptr = orgName;
1626: /* skip leading white space and new line characters */
1627: while ((*ptr == SPACE || *ptr == EOL) && *ptr++ != EOS);
1628: strncpy (tempOrgName, ptr, MAX_LENGTH -1);
1629: tempOrgName[MAX_LENGTH -1] = EOS;
1630: /*
1631: * Make orgName a complete URL
1632: * If the URL does not include a protocol, then try to calculate
1633: * one using the doc's base element (if it exists),
1634: */
1635: if (tempOrgName[0] == EOS)
1636: {
1637: newName[0] = EOS;
1638: docName[0] = EOS;
1639: TtaFreeMemory (basename);
1.5 cvs 1640: return;
1.195 vatton 1641: }
1642:
1643: /* clean trailing white space */
1644: length = strlen (tempOrgName) - 1;
1645: while (tempOrgName[length] == SPACE && tempOrgName[length] == EOL)
1646: {
1647: tempOrgName[length] = EOS;
1648: length--;
1649: }
1.18 cvs 1650:
1.195 vatton 1651: /* remove extra dot (which dot???) */
1652: /* ugly, but faster than a strcmp */
1653: if (tempOrgName[length] == '.'
1654: && (length == 0 || tempOrgName[length-1] != '.'))
1655: tempOrgName[length] = EOS;
1656:
1657: if (IsW3Path (tempOrgName))
1658: {
1659: /* the name is complete, go to the Sixth Step */
1660: strcpy (newName, tempOrgName);
1661: SimplifyUrl (&newName);
1662: /* verify if the URL has the form "protocol://server:port" */
1663: ptr = AmayaParseUrl (newName, "", AMAYA_PARSE_ACCESS |
1664: AMAYA_PARSE_HOST |
1665: AMAYA_PARSE_PUNCTUATION);
1666: if (ptr && !strcmp (ptr, newName))
1667: /* it has this form, we complete it by adding a DIR_STR */
1668: strcat (newName, URL_STR);
1669:
1670: if (ptr)
1671: TtaFreeMemory (ptr);
1672: }
1673: else if (basename == NULL)
1674: /* the name is complete, go to the Sixth Step */
1675: strcpy (newName, tempOrgName);
1676: else
1677: {
1678: /* Calculate the absolute URL, using the base or document URL */
1.184 gully 1679: #ifdef _WINDOWS
1.195 vatton 1680: if (!IsW3Path (basename))
1681: {
1682: length = strlen (tempOrgName);
1683: for (ndx = 0; ndx < length; ndx++)
1.211 vatton 1684: if (tempOrgName[ndx] == '/')
1685: tempOrgName[ndx] = '\\';
1.195 vatton 1686: }
1.184 gully 1687: #endif /* _WINDOWS */
1.195 vatton 1688: ptr = AmayaParseUrl (tempOrgName, basename, AMAYA_PARSE_ALL);
1689: if (ptr)
1690: {
1691: SimplifyUrl (&ptr);
1692: strcpy (newName, ptr);
1693: TtaFreeMemory (ptr);
1694: }
1695: else
1696: newName[0] = EOS;
1697: }
1698:
1699: TtaFreeMemory (basename);
1700: /*
1701: * Prepare the docname that will refer to this ressource in the
1702: * .amaya directory. If the new URL finishes on DIR_SEP, then use
1703: * noname.html as a default ressource name
1.18 cvs 1704: */
1.195 vatton 1705: if (newName[0] != EOS)
1706: {
1707: length = strlen (newName) - 1;
1708: if (newName[length] == URL_SEP || newName[length] == DIR_SEP)
1709: {
1710: used_sep = newName[length];
1711: check = TRUE;
1712: while (check)
1713: {
1714: length--;
1715: while (length >= 0 && newName[length] != used_sep)
1716: length--;
1717: if (!strncmp (&newName[length+1], "..", 2))
1718: {
1719: newName[length+1] = EOS;
1720: /* remove also previous directory */
1721: length--;
1722: while (length >= 0 && newName[length] != used_sep)
1723: length--;
1724: if (strncmp (&newName[length+1], "//", 2))
1725: /* don't remove server name */
1726: newName[length+1] = EOS;
1727: }
1728: else if (!strncmp (&newName[length+1], ".", 1))
1729: newName[length+1] = EOS;
1730: else
1731: check = FALSE;
1732: }
1733: /* docname was not comprised inside the URL, so let's */
1734: /* assign the default ressource name */
1735: strcpy (docName, "noname.html");
1736: }
1737: else
1738: { /* docname is comprised inside the URL */
1739: while (length >= 0 && newName[length] != URL_SEP &&
1740: newName[length] != DIR_SEP)
1741: length--;
1742: if (length < 0)
1743: strcpy (docName, newName);
1744: else
1745: strcpy (docName, &newName[length+1]);
1746: }
1747: }
1748: else
1749: docName[0] = EOS;
1.18 cvs 1750: }
1.3 cvs 1751:
1.4 cvs 1752: /*----------------------------------------------------------------------
1.9 cvs 1753: IsSameHost
1.4 cvs 1754: ----------------------------------------------------------------------*/
1.106 cvs 1755: ThotBool IsSameHost (const char *url1, const char *url2)
1.3 cvs 1756: {
1.106 cvs 1757: char *basename_ptr1, *basename_ptr2;
1758: ThotBool result;
1.3 cvs 1759:
1.106 cvs 1760: basename_ptr1 = AmayaParseUrl (url1, "",
1.195 vatton 1761: AMAYA_PARSE_ACCESS | AMAYA_PARSE_HOST | AMAYA_PARSE_PUNCTUATION);
1.106 cvs 1762: basename_ptr2 = AmayaParseUrl (url2, "",
1.195 vatton 1763: AMAYA_PARSE_ACCESS | AMAYA_PARSE_HOST | AMAYA_PARSE_PUNCTUATION);
1.3 cvs 1764:
1.106 cvs 1765: if (strcmp (basename_ptr1, basename_ptr2))
1766: result = FALSE;
1767: else
1768: result = TRUE;
1769: TtaFreeMemory (basename_ptr1);
1770: TtaFreeMemory (basename_ptr2);
1771: return (result);
1.3 cvs 1772: }
1773:
1774:
1.4 cvs 1775: /*----------------------------------------------------------------------
1.22 cvs 1776: HasKnownFileSuffix
1777: returns TRUE if path points to a file ending with a suffix.
1778: ----------------------------------------------------------------------*/
1.153 vatton 1779: ThotBool HasKnownFileSuffix (const char *path)
1.106 cvs 1780: {
1.195 vatton 1781: char *root;
1782: char temppath[MAX_LENGTH];
1783: char suffix[MAX_LENGTH];
1784:
1785: if (!path || path[0] == EOS || path[strlen(path)] == DIR_SEP)
1786: return (FALSE);
1787:
1788: root = AmayaParseUrl(path, "", AMAYA_PARSE_PATH | AMAYA_PARSE_PUNCTUATION);
1789:
1790: if (root)
1791: {
1792: strcpy (temppath, root);
1793: TtaFreeMemory (root);
1794: /* Get the suffix */
1795: TtaExtractSuffix (temppath, suffix);
1796:
1797: if( suffix[0] == EOS)
1798: /* no suffix */
1799: return (FALSE);
1800:
1801: /* Normalize the suffix */
1802: ConvertToLowerCase (suffix);
1803:
1804: if (!strcmp (suffix, "gz"))
1805: /* skip the compressed suffix */
1806: {
1807: TtaExtractSuffix (temppath, suffix);
1808: if(suffix[0] == EOS)
1809: /* no suffix */
1810: return (FALSE);
1811: /* Normalize the suffix */
1812: ConvertToLowerCase (suffix);
1813: }
1814:
1815: if (strcmp (suffix, "gif") &&
1816: strcmp (suffix, "xbm") &&
1817: strcmp (suffix, "xpm") &&
1818: strcmp (suffix, "jpg") &&
1819: strcmp (suffix, "pdf") &&
1820: strcmp (suffix, "png") &&
1821: strcmp (suffix, "tgz") &&
1822: strcmp (suffix, "xpg") &&
1823: strcmp (suffix, "xpd") &&
1824: strcmp (suffix, "ps") &&
1825: strcmp (suffix, "au") &&
1826: strcmp (suffix, "html") &&
1827: strcmp (suffix, "htm") &&
1828: strcmp (suffix, "shtml") &&
1829: strcmp (suffix, "xht") &&
1830: strcmp (suffix, "xhtm") &&
1831: strcmp (suffix, "xhtml") &&
1832: strcmp (suffix, "txt") &&
1833: strcmp (suffix, "css") &&
1834: strcmp (suffix, "eps"))
1835: return (FALSE);
1836: else
1837: return (TRUE);
1838: }
1839: else
1840: return (FALSE);
1.22 cvs 1841: }
1842:
1843:
1844: /*----------------------------------------------------------------------
1.24 cvs 1845: ChopURL
1846: Gives back a URL no longer than MAX_PRINT_URL_LENGTH chars (outputURL).
1847: If inputURL is bigger than that size, outputURL receives
1848: MAX_PRINT_URL_LENGTH / 2 chars from the beginning of inputURL, "...",
1849: and MAX_PRINT_URL_LENGTH / 2 chars from the end of inputURL.
1850: If inputURL is not longer than MAX_PRINT_URL_LENGTH chars, it gets
1851: copied into outputURL.
1852: N.B.: outputURL must point to a memory block of MAX_PRINT_URL_LENGTH
1853: chars.
1854: ----------------------------------------------------------------------*/
1.106 cvs 1855: void ChopURL (char *outputURL, const char *inputURL)
1.24 cvs 1856: {
1857: int len;
1.9 cvs 1858:
1.106 cvs 1859: len = strlen (inputURL);
1.24 cvs 1860: if (len <= MAX_PRINT_URL_LENGTH)
1.106 cvs 1861: strcpy (outputURL, inputURL);
1.24 cvs 1862: else
1863: /* make a truncated urlName on the status window */
1864: {
1.106 cvs 1865: strncpy (outputURL, inputURL, MAX_PRINT_URL_LENGTH / 2);
1866: outputURL [MAX_PRINT_URL_LENGTH / 2] = EOS;
1867: strcat (outputURL, "...");
1868: strcat (outputURL, &(inputURL[len - MAX_PRINT_URL_LENGTH / 2 ]));
1.24 cvs 1869: }
1.25 cvs 1870: }
1871:
1872:
1873: /*----------------------------------------------------------------------
1.195 vatton 1874: scan
1875: Scan a filename for its constituents
1876: -----------------------------------
1877:
1878: On entry,
1879: name points to a document name which may be incomplete.
1880: On exit,
1881: absolute or relative may be nonzero (but not both).
1882: host, fragment and access may be nonzero if they were specified.
1883: Any which are nonzero point to zero terminated strings.
1.25 cvs 1884: ----------------------------------------------------------------------*/
1.106 cvs 1885: static void scan (char *name, HTURI *parts)
1.25 cvs 1886: {
1.106 cvs 1887: char * p;
1888: char * after_access = name;
1.32 cvs 1889:
1.211 vatton 1890: memset (parts, 0, sizeof (HTURI));
1.28 cvs 1891: /* Look for fragment identifier */
1.106 cvs 1892: if ((p = strchr(name, '#')) != NULL)
1.28 cvs 1893: {
1.211 vatton 1894: *p++ = EOS;
1.28 cvs 1895: parts->fragment = p;
1.25 cvs 1896: }
1897:
1.28 cvs 1898: for (p=name; *p; p++)
1899: {
1.106 cvs 1900: if (*p == URL_SEP || *p == DIR_SEP || *p == '#' || *p == '?')
1.195 vatton 1901: break;
1.106 cvs 1902: if (*p == ':')
1.195 vatton 1903: {
1904: *p = 0;
1905: parts->access = after_access; /* Scheme has been specified */
1906:
1907: /* The combination of gcc, the "-O" flag and the HP platform is
1908: unhealthy. The following three lines is a quick & dirty fix, but is
1909: not recommended. Rather, turn off "-O". */
1910:
1911: /* after_access = p;*/
1912: /* while (*after_access == 0)*/
1913: /* after_access++;*/
1914: after_access = p+1;
1915: if (!strcasecmp("URL", parts->access))
1916: /* Ignore IETF's URL: pre-prefix */
1917: parts->access = NULL;
1918: else
1919: break;
1920: }
1.25 cvs 1921: }
1922:
1.195 vatton 1923: p = after_access;
1924: if (*p == URL_SEP || *p == DIR_SEP)
1925: {
1926: if (p[1] == URL_SEP)
1927: {
1928: parts->host = p+2; /* host has been specified */
1929: *p = 0; /* Terminate access */
1930: /* look for end of host name if any */
1931: p = strchr (parts->host, URL_SEP);
1932: if (p)
1933: {
1934: *p = EOS; /* Terminate host */
1935: parts->absolute = p+1; /* Root has been found */
1936: }
1937: }
1938: else
1939: /* Root found but no host */
1940: parts->absolute = p+1;
1941: }
1942: else
1943: {
1944: parts->relative = (*after_access) ? after_access : 0; /* zero for "" */
1945: }
1.25 cvs 1946: }
1947:
1948:
1949: /*----------------------------------------------------------------------
1.28 cvs 1950: AmayaParseUrl: parse a Name relative to another name
1951:
1952: This returns those parts of a name which are given (and requested)
1953: substituting bits from the related name where necessary.
1.25 cvs 1954:
1.28 cvs 1955: On entry,
1.195 vatton 1956: aName A filename given
1957: relatedName A name relative to which aName is to be parsed. Give
1958: it an empty string if aName is absolute.
1959: wanted A mask for the bits which are wanted.
1.25 cvs 1960:
1.28 cvs 1961: On exit,
1.195 vatton 1962: returns A pointer to a malloc'd string which MUST BE FREED
1.25 cvs 1963: ----------------------------------------------------------------------*/
1.206 kia 1964: char *AmayaParseUrl (const char *aName, const char *relatedName, int wanted)
1.106 cvs 1965: {
1966: char *return_value;
1967: char result[MAX_LENGTH];
1968: char name[MAX_LENGTH];
1969: char rel[MAX_LENGTH];
1970: char *p, *access;
1.29 cvs 1971: HTURI given, related;
1.205 vatton 1972: int len, l;
1.106 cvs 1973: char used_sep;
1.206 kia 1974: const char*used_str;
1.32 cvs 1975:
1.106 cvs 1976: if (strchr (aName, DIR_SEP) || strchr (relatedName, DIR_SEP))
1.33 cvs 1977: {
1.106 cvs 1978: used_str = DIR_STR;
1979: used_sep = DIR_SEP;
1.33 cvs 1980: }
1.32 cvs 1981: else
1.33 cvs 1982: {
1.106 cvs 1983: used_str = URL_STR;
1984: used_sep = URL_SEP;
1.33 cvs 1985: }
1.32 cvs 1986:
1.29 cvs 1987: /* Make working copies of input strings to cut up: */
1988: return_value = NULL;
1989: result[0] = 0; /* Clear string */
1.169 quint 1990: rel[0] = EOS;
1991: strncpy (name, aName, MAX_LENGTH - 1);
1992: name[MAX_LENGTH - 1] = EOS;
1993: if (relatedName != NULL)
1994: {
1995: strncpy (rel, relatedName, MAX_LENGTH - 1);
1996: rel[MAX_LENGTH - 1] = EOS;
1997: }
1.29 cvs 1998:
1999: scan (name, &given);
2000: scan (rel, &related);
2001: access = given.access ? given.access : related.access;
2002: if (wanted & AMAYA_PARSE_ACCESS)
2003: if (access)
2004: {
1.195 vatton 2005: strcat (result, access);
1.211 vatton 2006: if (wanted & AMAYA_PARSE_PUNCTUATION)
1.195 vatton 2007: strcat (result, ":");
1.29 cvs 2008: }
2009:
2010: if (given.access && related.access)
2011: /* If different, inherit nothing. */
1.106 cvs 2012: if (strcmp (given.access, related.access) != 0)
1.29 cvs 2013: {
1.195 vatton 2014: related.host = 0;
2015: related.absolute = 0;
2016: related.relative = 0;
2017: related.fragment = 0;
1.29 cvs 2018: }
2019:
2020: if (wanted & AMAYA_PARSE_HOST)
1.211 vatton 2021: if (given.host || related.host)
1.29 cvs 2022: {
1.211 vatton 2023: if (wanted & AMAYA_PARSE_PUNCTUATION)
1.195 vatton 2024: strcat (result, "//");
2025: strcat (result, given.host ? given.host : related.host);
1.29 cvs 2026: }
2027:
2028: if (given.host && related.host)
2029: /* If different hosts, inherit no path. */
1.106 cvs 2030: if (strcmp (given.host, related.host) != 0)
1.29 cvs 2031: {
1.195 vatton 2032: related.absolute = 0;
2033: related.relative = 0;
2034: related.fragment = 0;
1.29 cvs 2035: }
2036:
1.205 vatton 2037: len = MAX_LENGTH - 1 - strlen (result);
1.29 cvs 2038: if (wanted & AMAYA_PARSE_PATH)
2039: {
2040: if (given.absolute)
1.195 vatton 2041: {
2042: /* All is given */
2043: if (wanted & AMAYA_PARSE_PUNCTUATION)
1.205 vatton 2044: {
2045: strcat (result, used_str);
2046: len--;
2047: }
2048: l = strlen (given.absolute);
2049: if (l <= len)
2050: {
2051: strcat (result, given.absolute);
2052: len -= l;
2053: }
1.195 vatton 2054: }
1.29 cvs 2055: else if (related.absolute)
1.195 vatton 2056: {
2057: /* Adopt path not name */
2058: strcat (result, used_str);
1.205 vatton 2059: len--;
2060: l = strlen (related.absolute);
2061: if (l <= len)
2062: {
2063: strcat (result, related.absolute);
2064: len -= l;
2065: }
1.195 vatton 2066: if (given.relative)
2067: {
2068: /* Search part? */
2069: p = strchr (result, '?');
2070: if (!p)
1.205 vatton 2071: p = result + strlen(result) - 1;
2072: for (; *p != used_sep; p--); /* last / */
1.195 vatton 2073: /* Remove filename */
1.205 vatton 2074: p[1] = EOS;
1.195 vatton 2075: /* Add given one */
1.205 vatton 2076: l = strlen (given.relative);
2077: if (l <= len)
2078: {
2079: strcat (result, given.relative);
2080: len -= l;
2081: }
2082: }
2083: }
2084: else if (given.relative)
2085: {
2086: /* what we've got */
2087: l = strlen (given.relative);
2088: if (l <= len)
2089: {
1.195 vatton 2090: strcat (result, given.relative);
1.205 vatton 2091: len -= l;
1.195 vatton 2092: }
2093: }
1.29 cvs 2094: else if (related.relative)
1.205 vatton 2095: {
2096: l = strlen (related.relative);
2097: if (l <= len)
2098: {
2099: strcat (result, related.relative);
2100: len -= l;
2101: }
2102: }
1.29 cvs 2103: else
1.205 vatton 2104: {
2105: /* No inheritance */
2106: strcat (result, used_str);
2107: len--;
2108: }
1.25 cvs 2109: }
1.29 cvs 2110:
2111: if (wanted & AMAYA_PARSE_ANCHOR)
1.205 vatton 2112: if (len && (given.fragment || related.fragment))
1.29 cvs 2113: {
1.195 vatton 2114: if (given.absolute && given.fragment)
2115: {
2116: /*Fixes for relURLs...*/
2117: if (wanted & AMAYA_PARSE_PUNCTUATION)
1.205 vatton 2118: {
2119: strcat (result, "#");
2120: len --;
2121: }
2122: l = strlen (given.fragment);
2123: if (l <= len)
2124: strcat (result, given.fragment);
1.195 vatton 2125: }
1.205 vatton 2126: else if (given.absolute || given.fragment)
1.195 vatton 2127: {
2128: if (wanted & AMAYA_PARSE_PUNCTUATION)
1.205 vatton 2129: {
2130: strcat (result, "#");
2131: len--;
2132: }
2133: if (given.fragment)
2134: {
2135: l = strlen (given.fragment);
2136: if (l <= len)
2137: strcat (result, given.fragment);
2138: }
2139: else
2140: {
2141: l = strlen (given.fragment);
2142: if (l <= len)
2143: strcat (result, related.fragment);
2144: }
1.195 vatton 2145: }
1.29 cvs 2146: }
1.205 vatton 2147: return_value = TtaStrdup (result);
1.29 cvs 2148: return (return_value); /* exactly the right length */
1.25 cvs 2149: }
2150:
2151: /*----------------------------------------------------------------------
1.195 vatton 2152: HTCanon
2153: Canonicalizes the URL in the following manner starting from the host
2154: pointer:
1.25 cvs 2155:
1.195 vatton 2156: 1) The host name is converted to lowercase
2157: 2) Chop off port if `:80' (http), `:70' (gopher), or `:21' (ftp)
1.25 cvs 2158:
1.195 vatton 2159: Return: OK The position of the current path part of the URL
2160: which might be the old one or a new one.
1.25 cvs 2161:
2162: ----------------------------------------------------------------------*/
1.106 cvs 2163: static char *HTCanon (char **filename, char *host)
2164: {
1.195 vatton 2165: char *newname = NULL;
2166: char used_sep;
2167: char *path;
2168: char *strptr;
2169: char *port;
2170: char *access = host-3;
2171:
2172: if (*filename && strchr (*filename, URL_SEP))
2173: used_sep = URL_SEP;
2174: else
2175: used_sep = DIR_SEP;
2176:
2177: while (access > *filename && *(access - 1) != used_sep) /* Find access method */
2178: access--;
2179: if ((path = strchr (host, used_sep)) == NULL) /* Find path */
2180: path = host + strlen (host);
2181: if ((strptr = strchr (host, '@')) != NULL && strptr < path) /* UserId */
2182: host = strptr;
2183: if ((port = strchr (host, ':')) != NULL && port > path) /* Port number */
2184: port = NULL;
1.25 cvs 2185:
1.195 vatton 2186: strptr = host; /* Convert to lower-case */
2187: while (strptr < path)
2188: {
2189: *strptr = tolower (*strptr);
2190: strptr++;
2191: }
2192:
2193: /* Does the URL contain a full domain name? This also works for a
2194: numerical host name. The domain name is already made lower-case
2195: and without a trailing dot. */
2196: {
2197: char *dot = port ? port : path;
2198: if (dot > *filename && *--dot == '.')
1.33 cvs 2199: {
1.195 vatton 2200: char *orig = dot;
2201: char *dest = dot + 1;
2202: while ((*orig++ = *dest++));
2203: if (port) port--;
2204: path--;
2205: }
2206: }
2207: /* Chop off port if `:', `:80' (http), `:70' (gopher), or `:21' (ftp) */
2208: if (port)
2209: {
2210: if (!*(port+1) || *(port+1) == used_sep)
2211: {
2212: if (!newname)
2213: {
2214: char *orig = port;
2215: char *dest = port + 1;
2216: while ((*orig++ = *dest++));
2217: }
2218: }
2219: else if ((!strncmp (access, "http", 4) &&
2220: (*(port + 1) == '8' &&
2221: *(port+2) == '0' &&
2222: (*(port+3) == used_sep || !*(port + 3)))) ||
2223: (!strncmp (access, "gopher", 6) &&
2224: (*(port+1) == '7' &&
2225: *(port+2) == '0' &&
2226: (*(port+3) == used_sep || !*(port+3)))) ||
2227: (!strncmp (access, "ftp", 3) &&
2228: (*(port+1) == '2' &&
2229: *(port + 2) == '1' &&
2230: (*(port+3) == used_sep || !*(port+3))))) {
2231: if (!newname)
2232: {
2233: char *orig = port;
2234: char *dest = port + 3;
2235: while((*orig++ = *dest++));
2236: /* Update path position, Henry Minsky */
2237: path -= 3;
2238: }
1.33 cvs 2239: }
1.195 vatton 2240: else if (newname)
2241: strncat (newname, port, (int) (path - port));
1.25 cvs 2242: }
2243:
1.195 vatton 2244: if (newname)
2245: {
2246: char *newpath = newname + strlen (newname);
2247: strcat (newname, path);
2248: path = newpath;
2249: /* Free old copy */
2250: TtaFreeMemory(*filename);
2251: *filename = newname;
2252: }
2253: return path;
1.25 cvs 2254: }
2255:
2256:
2257: /*----------------------------------------------------------------------
1.29 cvs 2258: SimplifyUrl: simplify a URI
1.32 cvs 2259: A URI is allowed to contain the sequence xxx/../ which may be
2260: replaced by "" , and the sequence "/./" which may be replaced by DIR_STR.
1.28 cvs 2261: Simplification helps us recognize duplicate URIs.
1.25 cvs 2262:
1.28 cvs 2263: Thus, /etc/junk/../fred becomes /etc/fred
1.195 vatton 2264: /etc/junk/./fred becomes /etc/junk/fred
1.25 cvs 2265:
1.28 cvs 2266: but we should NOT change
1.195 vatton 2267: http://fred.xxx.edu/../..
1.25 cvs 2268:
1.195 vatton 2269: or ../../albert.html
1.25 cvs 2270:
1.28 cvs 2271: In order to avoid empty URLs the following URLs become:
1.25 cvs 2272:
1.195 vatton 2273: /fred/.. becomes /fred/..
2274: /fred/././.. becomes /fred/..
2275: /fred/.././junk/.././ becomes /fred/..
1.25 cvs 2276:
1.28 cvs 2277: If more than one set of `://' is found (several proxies in cascade) then
2278: only the part after the last `://' is simplified.
1.25 cvs 2279:
1.28 cvs 2280: Returns: A string which might be the old one or a new one.
1.25 cvs 2281: ----------------------------------------------------------------------*/
1.106 cvs 2282: void SimplifyUrl (char **url)
2283: {
2284: char *path;
2285: char *access;
2286: char *newptr;
2287: char *p;
2288: char *orig, *dest, *end;
1.28 cvs 2289:
1.106 cvs 2290: char used_sep;
1.77 cvs 2291: ThotBool ddot_simplify; /* used to desactivate the double dot simplifcation:
1.195 vatton 2292: something/../ simplification in relative URLs when they start with a ../ */
1.32 cvs 2293:
1.28 cvs 2294: if (!url || !*url)
2295: return;
2296:
1.106 cvs 2297: if (strchr (*url, URL_SEP))
1.195 vatton 2298: used_sep = URL_SEP;
1.32 cvs 2299: else
1.195 vatton 2300: used_sep = DIR_SEP;
1.32 cvs 2301:
1.77 cvs 2302: /* should we simplify double dot? */
2303: path = *url;
1.106 cvs 2304: if (*path == '.' && *(path + 1) == '.')
1.77 cvs 2305: ddot_simplify = FALSE;
2306: else
2307: ddot_simplify = TRUE;
2308:
1.28 cvs 2309: /* Find any scheme name */
1.106 cvs 2310: if ((path = strstr (*url, "://")) != NULL)
1.33 cvs 2311: {
2312: /* Find host name */
1.28 cvs 2313: access = *url;
1.123 vatton 2314: while (access < path && (*access = tolower (*access)))
1.195 vatton 2315: access++;
1.28 cvs 2316: path += 3;
1.106 cvs 2317: while ((newptr = strstr (path, "://")) != NULL)
1.195 vatton 2318: /* For proxies */
2319: path = newptr + 3;
2320: /* We have a host name */
1.84 cvs 2321: path = HTCanon (url, path);
1.25 cvs 2322: }
1.106 cvs 2323: else if ((path = strstr (*url, ":/")) != NULL)
1.28 cvs 2324: path += 2;
2325: else
2326: path = *url;
1.84 cvs 2327: if (*path == used_sep && *(path+1) == used_sep)
1.28 cvs 2328: /* Some URLs start //<foo> */
2329: path += 1;
1.94 cvs 2330: else if (IsFilePath (path))
2331: {
2332: /* doesn't need to do anything more */
2333: return;
2334: }
1.106 cvs 2335: else if (!strncmp (path, "news:", 5))
1.28 cvs 2336: {
1.106 cvs 2337: newptr = strchr (path+5, '@');
1.28 cvs 2338: if (!newptr)
1.195 vatton 2339: newptr = path + 5;
1.28 cvs 2340: while (*newptr)
1.195 vatton 2341: {
2342: /* Make group or host lower case */
2343: *newptr = tolower (*newptr);
2344: newptr++;
2345: }
1.28 cvs 2346: /* Doesn't need to do any more */
2347: return;
1.25 cvs 2348: }
1.126 cheyroul 2349:
1.189 vatton 2350: /* remove initial multiple /'s */
2351: p = path - 1;
2352: if (path != *url && *p == used_sep && *path == used_sep)
2353: {
2354: while (*path == used_sep)
1.195 vatton 2355: {
2356: orig = path;
2357: dest = path + 1;
2358: while ((*orig++ = *dest++)); /* Remove multiple /'s */
2359: end = orig-1;
2360: }
1.189 vatton 2361: }
2362:
2363: if (path)
1.28 cvs 2364: {
1.106 cvs 2365: if (!((end = strchr (path, ';')) || (end = strchr (path, '?')) ||
1.195 vatton 2366: (end = strchr (path, '#'))))
2367: end = path + strlen (path);
1.28 cvs 2368:
2369: /* Parse string second time to simplify */
2370: p = path;
2371: while (p < end)
1.195 vatton 2372: {
2373: /* if we're pointing to a char, it's safe to reactivate the
2374: ../ convertion */
2375: if (!ddot_simplify && *p != '.' && *p != used_sep)
2376: ddot_simplify = TRUE;
2377:
2378: if (*p==used_sep)
2379: {
2380: if (p > *url && *(p+1) == '.' && (*(p+2) == used_sep || !*(p+2)))
2381: {
2382: orig = p + 1;
2383: dest = (*(p+2) != used_sep) ? p+2 : p+3;
2384: while ((*orig++ = *dest++)); /* Remove a used_sep and a dot*/
2385: end = orig - 1;
2386: }
2387: else if (ddot_simplify && *(p+1) == '.' && *(p+2) == '.'
2388: && (*(p+3) == used_sep || !*(p+3)))
2389: {
2390: newptr = p;
2391: while (newptr>path && *--newptr!=used_sep); /* prev used_sep */
2392: if (*newptr == used_sep)
2393: orig = newptr + 1;
2394: else
2395: orig = newptr;
2396:
2397: dest = (*(p+3) != used_sep) ? p+3 : p+4;
2398: while ((*orig++ = *dest++)); /* Remove /xxx/.. */
2399: end = orig-1;
2400: /* Start again with prev slash */
2401: p = newptr;
2402: }
2403: else if (*(p+1) == used_sep)
2404: {
2405: while (*(p+1) == used_sep)
2406: {
2407: orig = p;
2408: dest = p + 1;
2409: while ((*orig++ = *dest++)); /* Remove multiple /'s */
2410: end = orig-1;
2411: }
2412: }
2413: else
2414: p++;
2415: }
2416: else
2417: p++;
2418: }
2419: }
2420: /*
2421: ** Check for host/../.. kind of things
2422: */
2423: if (*path == used_sep && *(path+1) == '.' && *(path+2) == '.'
2424: && (!*(path+3) || *(path+3) == used_sep))
2425: *(path+1) = EOS;
1.28 cvs 2426: return;
2427: }
2428:
2429:
2430: /*----------------------------------------------------------------------
1.202 vatton 2431: NormalizeFile normalizes local names.
2432: convertion is AM_CONV_NONE or AM_CONV_ALL
1.195 vatton 2433: Return TRUE if target and src differ.
1.28 cvs 2434: ----------------------------------------------------------------------*/
1.106 cvs 2435: ThotBool NormalizeFile (char *src, char *target, ConvertionType convertion)
1.28 cvs 2436: {
1.195 vatton 2437: char *s;
2438: int i;
1.198 cvs 2439: int start_index; /* the first char that we'll copy */
1.195 vatton 2440: ThotBool change;
1.28 cvs 2441:
1.195 vatton 2442: change = FALSE;
2443: start_index = 0;
1.90 cvs 2444:
1.195 vatton 2445: if (!src || src[0] == EOS)
2446: {
2447: target[0] = EOS;
2448: return FALSE;
2449: }
2450:
2451: /* @@ do I need file: or file:/ here? */
2452: if (strncmp (src, "file:", 5) == 0)
2453: {
2454: /* remove the prefix file: */
2455: start_index += 5;
1.90 cvs 2456:
1.195 vatton 2457: /* remove the localhost prefix */
2458: if (strncmp (&src[start_index], "//localhost/", 12) == 0)
2459: start_index += 11;
1.94 cvs 2460:
1.211 vatton 2461: #ifdef _IV
1.195 vatton 2462: /* remove the first two slashes in / / /path */
2463: while (src[start_index] &&
2464: src[start_index] == '/'
2465: && src[start_index + 1] == '/')
2466: start_index++;
1.211 vatton 2467: #endif /* IV */
1.94 cvs 2468:
1.211 vatton 2469: #ifdef _IV
1.195 vatton 2470: /* remove any extra slash before the drive name */
1.211 vatton 2471: if (src[start_index] == '/' &&src[start_index+2] == ':')
1.195 vatton 2472: start_index++;
1.184 gully 2473: #endif /* _WINDOWS */
1.90 cvs 2474:
1.195 vatton 2475: if (src[start_index] == EOS)
2476: /* if there's nothing afterwards, add a DIR_STR */
2477: strcpy (target, DIR_STR);
2478: else
2479: /* as we're inside a file: URL, we'll apply all the convertions
2480: we know */
2481: CleanCopyFileURL (target, &src[start_index], AM_CONV_ALL);
2482:
2483: change = TRUE;
2484: }
2485: else if (convertion != AM_CONV_NONE)
2486: {
2487: /* we are following a "local" relative link, we do all the
2488: convertions except for the HOME_DIR ~ one */
2489: CleanCopyFileURL (target, src, convertion);
2490: }
1.198 cvs 2491: #ifdef _WINDOWS
1.211 vatton 2492: #ifdef IV
1.198 cvs 2493: else if (src[0] == DIR_SEP && src[1] == DIR_SEP)
2494: {
2495: s = getenv ("HOMEDRIVE");
2496: strcpy (target, s);
2497: i = strlen (target);
2498: strcpy (&target[i], &src[1]);
2499: change = TRUE;
2500: }
1.211 vatton 2501: #endif /* IV */
1.198 cvs 2502: #else /* _WINDOWS */
1.195 vatton 2503: else if (src[0] == '~')
2504: {
2505: /* it must be a URL typed in a text input field */
2506: /* do the HOME_DIR ~ substitution */
2507: s = TtaGetEnvString ("HOME");
2508: strcpy (target, s);
2509: i = strlen (target);
2510: strcpy (&target[i], &src[1]);
2511: change = TRUE;
2512: }
1.184 gully 2513: #endif /* _WINDOWS */
1.195 vatton 2514: else
2515: /* leave it as it is */
2516: strcpy (target, src);
1.96 cvs 2517:
1.195 vatton 2518: /* remove /../ and /./ */
2519: SimplifyUrl (&target);
2520: if (!change)
2521: change = (strcmp (src, target) != 0);
2522: return (change);
1.25 cvs 2523: }
2524:
1.28 cvs 2525:
1.25 cvs 2526: /*----------------------------------------------------------------------
1.31 cvs 2527: MakeRelativeURL: make relative name
1.25 cvs 2528:
1.28 cvs 2529: This function creates and returns a string which gives an expression of
2530: one address as related to another. Where there is no relation, an absolute
2531: address is retured.
1.25 cvs 2532:
1.28 cvs 2533: On entry,
1.195 vatton 2534: Both names must be absolute, fully qualified names of nodes
2535: (no fragment bits)
1.25 cvs 2536:
1.28 cvs 2537: On exit,
1.195 vatton 2538: The return result points to a newly allocated name which, if
2539: parsed by AmayaParseUrl relative to relatedName, will yield aName.
2540: The caller is responsible for freeing the resulting name later.
1.25 cvs 2541: ----------------------------------------------------------------------*/
1.206 kia 2542: char *MakeRelativeURL (const char *aName, const char *relatedName)
1.106 cvs 2543: {
1.206 kia 2544: char *return_value;
2545: char result[MAX_LENGTH];
2546: const char *p;
2547: const char *q;
2548: const char *after_access;
2549: const char *last_slash = NULL;
2550: int slashes, levels, len;
1.184 gully 2551: #ifdef _WINDOWS
1.44 cvs 2552: int ndx;
1.184 gully 2553: #endif /* _WINDOWS */
1.44 cvs 2554:
1.29 cvs 2555: if (aName == NULL || relatedName == NULL)
2556: return (NULL);
2557:
2558: slashes = 0;
2559: after_access = NULL;
2560: p = aName;
2561: q = relatedName;
1.147 vatton 2562: len = 0;
2563: for (; *p && !strncasecmp (p, q, 1); p++, q++, len++)
1.27 cvs 2564: {
2565: /* Find extent of match */
1.106 cvs 2566: if (*p == ':')
1.195 vatton 2567: {
2568: after_access = p + 1;
1.184 gully 2569: #ifdef _WINDOWS
1.195 vatton 2570: if (len == 1)
2571: {
2572: /* it's a local Windows path like c:... */
2573: slashes+=2;
2574: }
1.184 gully 2575: #endif /* _WINDOWS */
1.195 vatton 2576: }
1.168 cvs 2577: if (*p == DIR_SEP)
1.195 vatton 2578: {
2579: /* memorize the last slash position and count them */
2580: last_slash = p;
2581: slashes++;
2582: }
1.25 cvs 2583: }
2584:
1.31 cvs 2585: /* q, p point to the first non-matching character or zero */
1.106 cvs 2586: if (*q == EOS)
1.31 cvs 2587: {
2588: /* New name is a subset of the related name */
2589: /* exactly the right length */
1.106 cvs 2590: len = strlen (p);
1.171 gully 2591: if ((return_value = (char *)TtaGetMemory (len + 1)) != NULL)
1.195 vatton 2592: strcpy (return_value, p);
1.31 cvs 2593: }
2594: else if ((slashes < 2 && after_access == NULL)
1.195 vatton 2595: || (slashes < 3 && after_access != NULL))
2596: {
1.31 cvs 2597: /* Two names whitout common path */
2598: /* exactly the right length */
1.106 cvs 2599: len = strlen (aName);
1.171 gully 2600: if ((return_value = (char *)TtaGetMemory (len + 1)) != NULL)
1.195 vatton 2601: strcpy (return_value, aName);
1.31 cvs 2602: }
2603: else
2604: {
2605: /* Some path in common */
1.106 cvs 2606: if (slashes == 3 && strncmp (aName, "http:", 5) == 0)
1.195 vatton 2607: /* just the same server */
2608: strcpy (result, last_slash);
1.31 cvs 2609: else
1.195 vatton 2610: {
2611: levels= 0;
2612: for (; *q && *q != '#' && *q != ';' && *q != '?'; q++)
2613: if (*q == DIR_SEP)
2614: levels++;
1.31 cvs 2615:
1.195 vatton 2616: result[0] = EOS;
2617: for (;levels; levels--)
2618: strcat (result, "../");
2619: strcat (result, last_slash+1);
2620: }
1.52 cvs 2621:
2622: if (!*result)
1.195 vatton 2623: strcat (result, "./");
1.52 cvs 2624:
1.31 cvs 2625: /* exactly the right length */
1.106 cvs 2626: len = strlen (result);
1.171 gully 2627: if ((return_value = (char *)TtaGetMemory (len + 1)) != NULL)
1.195 vatton 2628: strcpy (return_value, result);
1.52 cvs 2629:
1.25 cvs 2630: }
1.184 gully 2631: #ifdef _WINDOWS
1.106 cvs 2632: len = strlen (return_value);
1.195 vatton 2633: for (ndx = 0; ndx < len; ndx ++)
1.106 cvs 2634: if (return_value[ndx] == '\\')
1.195 vatton 2635: return_value[ndx] = '/' ;
1.184 gully 2636: #endif /* _WINDOWS */
1.29 cvs 2637: return (return_value);
1.24 cvs 2638: }
1.35 cvs 2639:
1.104 kahan 2640: /*----------------------------------------------------------------------
2641: AM_GetFileSize
2642: Returns TRUE and the filesize in the 2nd parameter.
2643: Otherwise, in case of a system error, returns FALSE, with a
2644: filesize of 0L.
2645: ---------------------------------------------------------------------*/
1.206 kia 2646: ThotBool AM_GetFileSize (const char *filename, unsigned long *file_size)
1.104 kahan 2647: {
2648: if (!TtaFileExist (filename))
2649: return FALSE;
1.185 vatton 2650: *file_size = TtaGetFileSize (filename);
2651: return TRUE;
1.104 kahan 2652: }
1.139 kahan 2653:
2654: /*----------------------------------------------------------------------
2655: AM_UseXHTMLMimeType
2656: Returns TRUE if the user has configured Amaya to use this MIME type,
2657: FALSE otherwise.
2658: ---------------------------------------------------------------------*/
2659: ThotBool AM_UseXHTMLMimeType (void)
2660: {
2661: ThotBool xhtml_mimetype;
2662:
2663: /* does the user wants to use the new MIME type? */
2664: TtaGetEnvBoolean ("ENABLE_XHTML_MIMETYPE", &xhtml_mimetype);
2665:
2666: return (xhtml_mimetype);
1.152 kahan 2667: }
2668:
1.154 kahan 2669:
2670: /********************************************
2671: The following routines were adapted from the GNU libc functions
2672: for generating a tmpnam.
2673: *********************************************/
2674:
2675: /* These are the characters used in temporary filenames. */
2676: static const char letters[] =
2677: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
2678:
2679: /* Generate a temporary file name based on TMPL. TMPL must match the
2680: rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed
2681: does not exist at the time of the call to __gen_tempname. TMPL is
2682: overwritten with the result.
2683:
2684: We use a clever algorithm to get hard-to-predict names. */
2685: void
2686: AM_gen_tempname (char *tmpl)
2687: {
2688: int len;
2689: char *XXXXXX;
2690: static uint64_t value;
2691: uint64_t random_time_bits;
2692: unsigned int count;
2693: int save_errno = errno;
2694: struct stat st;
2695:
2696: /* A lower bound on the number of temporary files to attempt to
2697: generate. The maximum total number of temporary file names that
2698: can exist for a given template is 62**6. It should never be
2699: necessary to try all these combinations. Instead if a reasonable
2700: number of names is tried (we define reasonable as 62**3) fail to
2701: give the system administrator the chance to remove the problems. */
2702: unsigned int attempts_min = 62 * 62 * 62;
2703:
2704: /* The number of times to attempt to generate a temporary file. To
2705: conform to POSIX, this must be no smaller than TMP_MAX. */
2706: unsigned int attempts = attempts_min < TMP_MAX ? TMP_MAX : attempts_min;
2707:
2708: len = strlen (tmpl);
2709: if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
2710: {
2711: /* @@ JK ? */
2712: errno = EINVAL;
2713: return;
2714: }
2715:
2716: /* This is where the Xs start. */
2717: XXXXXX = &tmpl[len - 6];
2718:
2719: /* Get some more or less random data. */
2720: #ifdef RANDOM_BITS
2721: RANDOM_BITS (random_time_bits);
2722: #else
2723: # if HAVE_GETTIMEOFDAY || _LIBC
2724: {
2725: struct timeval tv;
2726: gettimeofday (&tv, NULL);
2727: random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec;
2728: }
2729: # else
2730: random_time_bits = time (NULL);
2731: # endif
2732: #endif
2733: value += random_time_bits ^ getpid ();
2734:
2735: for (count = 0; count < attempts; value += 7777, ++count)
2736: {
2737: uint64_t v = value;
2738:
2739: /* Fill in the random bits. */
2740: XXXXXX[0] = letters[v % 62];
2741: v /= 62;
2742: XXXXXX[1] = letters[v % 62];
2743: v /= 62;
2744: XXXXXX[2] = letters[v % 62];
2745: v /= 62;
2746: XXXXXX[3] = letters[v % 62];
2747: v /= 62;
2748: XXXXXX[4] = letters[v % 62];
2749: v /= 62;
2750: XXXXXX[5] = letters[v % 62];
2751:
2752: /* This case is backward from the other three. AM_gen_tempname
1.195 vatton 2753: succeeds if __xstat fails because the name does not exist.
2754: Note the continue to bypass the common logic at the bottom
2755: of the loop. */
1.154 kahan 2756: if (stat (tmpl, &st) < 0)
1.195 vatton 2757: break;
1.154 kahan 2758:
2759: continue;
2760: }
2761:
2762: if (count == attempts || errno != ENOENT)
2763: tmpl[0] = EOS;
2764: else
2765: errno = save_errno;
2766:
2767: return;
2768: }
2769:
2770: #define JOSE 1
2771:
1.152 kahan 2772: /*-----------------------------------------------------------------------
2773: GetTempName
2774: Front end to the Unix tempnam function, which is independent of the
2775: value of the TMPDIR env value
2776: Returns a dynamically allocated string with a tempname. The user
2777: must free this memory.
2778: -----------------------------------------------------------------------*/
2779: char *GetTempName (const char *dir, const char *prefix)
2780: {
1.154 kahan 2781: #ifdef JOSE
2782:
1.162 kahan 2783: static char tmpbufmem[PATH_MAX + 1];
1.154 kahan 2784: int len;
2785: int i;
2786:
1.155 cvs 2787: if (!dir || *dir == EOS || !TtaDirExists (dir))
1.154 kahan 2788: return NULL;
2789:
1.162 kahan 2790: /* make sure that the name is no bigger than PATH_MAX + the 6 tempname chars we
1.195 vatton 2791: will add */
1.154 kahan 2792:
1.156 cvs 2793: len = strlen (dir);
1.162 kahan 2794: if (len + 6 > PATH_MAX)
1.154 kahan 2795: return NULL;
2796:
2797: /* copy the dir name, and add a DIR_SEP if it's missing */
2798: if (dir[strlen (dir) - 1] == DIR_SEP)
2799: strcpy (tmpbufmem, dir);
2800: else
1.195 vatton 2801: {
2802: sprintf (tmpbufmem, "%s%c", dir, DIR_SEP);
2803: len++;
2804: }
1.154 kahan 2805:
1.161 kahan 2806: /* copy the prefix (no more than L_tmpnam chars, to respect POSIX). Save
1.156 cvs 2807: space for the 6 X and EOS chars that will become the random bits */
2808: if (prefix)
1.195 vatton 2809: {
1.156 cvs 2810: i = 0;
1.195 vatton 2811: while (prefix[i] != EOS && i < L_tmpnam - 8)
2812: tmpbufmem[len++] = prefix[i++];
2813: tmpbufmem[len] = EOS;
2814: }
1.156 cvs 2815:
2816: /* Add the 6 X chars */
2817: len = strlen (tmpbufmem);
2818: i = 0;
2819: while (i < 6)
1.195 vatton 2820: {
2821: tmpbufmem[len++] = 'X';
2822: i++;
2823: }
1.156 cvs 2824: tmpbufmem[len] = EOS;
1.154 kahan 2825:
2826: AM_gen_tempname (tmpbufmem);
2827:
2828: if (tmpbufmem[0] == EOS)
2829: return NULL;
2830: else
2831: return (TtaStrdup (tmpbufmem));
2832:
2833: #else
1.152 kahan 2834: char *tmpdir;
1.181 vatton 2835: char *tmp = NULL;
1.152 kahan 2836: char *name = NULL;
2837:
2838: /* save the value of TMPDIR */
1.181 vatton 2839: tmpdir = getenv ("TMPDIR");
1.152 kahan 2840: if (tmpdir)
2841: {
1.181 vatton 2842: /* remove TMPDIR from the environment */
2843: tmp = TtaGetMemory (strlen (tmpdir) + 20);
2844: sprintf (tmp, "TMPDIR=");
1.184 gully 2845: #ifdef _WINDOWS
1.152 kahan 2846: _putenv (tmp);
2847: #else
2848: putenv (tmp);
1.184 gully 2849: #endif /* _WINDOWS */
1.181 vatton 2850: /* prepare the string to restore the value of TMPDIR */
2851: strrcat (tmp, tmpdir);
1.152 kahan 2852: }
2853:
2854: /* create the tempname */
1.184 gully 2855: #ifdef _WINDOWS
1.152 kahan 2856: /* Under Windows, _tempnam returns the same name until the file is created */
2857: {
2858: char *altprefix;
2859: name = tmpnam (NULL); /* get a possibly unique string */
1.181 vatton 2860: altprefix = TtaGetMemory (strlen (prefix) + strlen(name) + 1);
1.152 kahan 2861: sprintf (altprefix, "%s%s", prefix, name + strlen(_P_tmpdir));
2862: name = _tempnam (dir, altprefix); /* get a name that isn't yet in use */
2863: TtaFreeMemory (altprefix);
2864: }
2865: #else
2866: name = tempnam (dir, prefix);
1.184 gully 2867: #endif /* _WINDOWS */
1.152 kahan 2868:
2869: if (tmpdir)
2870: {
1.181 vatton 2871: /* restore the value of TMPDIR */
1.184 gully 2872: #ifdef _WINDOWS
1.152 kahan 2873: _putenv (tmpdir);
2874: #else
2875: putenv (tmpdir);
1.184 gully 2876: #endif /* _WINDOWS */
1.181 vatton 2877: TtaFreeMemory (tmpdir);
1.152 kahan 2878: }
2879: return (name);
1.154 kahan 2880: #endif
1.139 kahan 2881: }
Webmaster