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