Diff for /Amaya/amaya/AHTURLTools.c between versions 1.194 and 1.195

version 1.194, 2005/08/18 10:26:00 version 1.195, 2005/12/29 14:16:18
Line 24 Line 24
 #define MAX_PRINT_URL_LENGTH 50  #define MAX_PRINT_URL_LENGTH 50
 typedef struct _HTURI  typedef struct _HTURI
 {  {
     char *access;               /* Now known as "scheme" */    char *access;         /* Now known as "scheme" */
     char *host;    char *host;
     char *absolute;    char *absolute;
     char *relative;    char *relative;
     char *fragment;    char *fragment;
 } HTURI;  } HTURI;
   
 #ifdef _WINDOWS  #ifdef _WINDOWS
Line 50  typedef struct _HTURI Line 50  typedef struct _HTURI
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 void ConvertToLowerCase (char *string)  void ConvertToLowerCase (char *string)
 {  {
  int i;    int i;
     
  if (!string)    if (!string)
    return;      return;
   
  for (i = 0; string[i] != EOS; i++)    for (i = 0; string[i] != EOS; i++)
    string[i] = tolower (string[i]);      string[i] = tolower (string[i]);
 }  }
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
Line 67  void EscapeChar (char *string, char c) Line 67  void EscapeChar (char *string, char c)
 {  {
   unsigned int i;    unsigned int i;
   
    i = (unsigned char) c & 0xFF;    i = (unsigned char) c & 0xFF;
    sprintf (string, "%02x", i);    sprintf (string, "%02x", i);
 }  }
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
Line 77  void EscapeChar (char *string, char c) Line 77  void EscapeChar (char *string, char c)
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 static char UnEscapeChar (char c)  static char UnEscapeChar (char c)
 {  {
     return  c >= '0' && c <= '9' ?  c - '0'    return  c >= '0' && c <= '9' ?  c - '0'
             : c >= 'A' && c <= 'F' ? c - 'A' + 10      : c >= 'A' && c <= 'F' ? c - 'A' + 10
             : c - 'a' + 10;   /* accept small letters just in case */      : c - 'a' + 10;   /* accept small letters just in case */
 }  }
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
Line 111  char *EscapeURL (const char *url) Line 111  char *EscapeURL (const char *url)
               /* put here below all the chars that need to                /* put here below all the chars that need to
                  be escaped into %xx */                   be escaped into %xx */
             case 0x20: /* space */              case 0x20: /* space */
               /*case 0x26:*/ /* &amp */                /*case 0x26:*/ /* &amp */
             case 0x27: /* antislash */              case 0x27: /* antislash */
               new_chars = 3;                 new_chars = 3; 
               break;                break;
   
             default:              default:
               if ((unsigned char )*ptr > 127)                if ((unsigned char )*ptr > 127)
                 new_chars = 3;                  new_chars = 3;
               else                else
                 new_chars = 1;                   new_chars = 1; 
               break;                break;
             }              }
   
Line 129  char *EscapeURL (const char *url) Line 129  char *EscapeURL (const char *url)
             {              {
               buffer_free_mem = 20;                buffer_free_mem = 20;
               status = TtaRealloc (buffer, sizeof (char)                 status = TtaRealloc (buffer, sizeof (char) 
                                    * (buffer_len + buffer_free_mem + 1));                                     * (buffer_len + buffer_free_mem + 1));
               if (status)                if (status)
                 buffer = (char *) status;                  buffer = (char *) status;
               else                else
                 {                  {
                   /* @@ maybe we should do some other behavior here, like                    /* @@ maybe we should do some other behavior here, like
                      freeing the buffer and return a void thing */                       freeing the buffer and return a void thing */
                   buffer[buffer_len] = EOS;                    buffer[buffer_len] = EOS;
                   break;                    break;
                 }                  }
             }              }
           /* escape the char */            /* escape the char */
           if (new_chars == 3)            if (new_chars == 3)
             {              {
               buffer[buffer_len] = '%';                buffer[buffer_len] = '%';
               EscapeChar (&buffer[buffer_len+1], *ptr);                EscapeChar (&buffer[buffer_len+1], *ptr);
             }              }
Line 190  char *EscapeXML (const char *string) Line 190  char *EscapeXML (const char *string)
         {          {
           switch (*ptr)            switch (*ptr)
             {              {
              case 0x26: /* &amp */              case 0x26: /* &amp */
                entity = "&amp;";                entity = "&amp;";
                new_chars = sizeof (entity) - 1;                     new_chars = sizeof (entity) - 1;      
                break;                break;
                                 
             case '<':  /* &lt; */              case '<':  /* &lt; */
               entity = "&lt;";                entity = "&lt;";
               new_chars = sizeof (entity) - 1;                      new_chars = sizeof (entity) - 1;      
               break;                break;
   
             case '>':  /* &gt; */              case '>':  /* &gt; */
               entity = "&gt;";                entity = "&gt;";
               new_chars = sizeof (entity) - 1;                      new_chars = sizeof (entity) - 1;      
               break;                break;
   
             case '"':  /* &quote; */              case '"':  /* &quote; */
               entity = "&quote;";                entity = "&quote;";
               new_chars = sizeof (entity) - 1;                      new_chars = sizeof (entity) - 1;      
               break;                break;
   
             default:              default:
               new_chars = 1;                 new_chars = 1; 
               break;                break;
             }              }
   
Line 220  char *EscapeXML (const char *string) Line 220  char *EscapeXML (const char *string)
             {              {
               buffer_free_mem = 20;                buffer_free_mem = 20;
               status = TtaRealloc (buffer, sizeof (char)                 status = TtaRealloc (buffer, sizeof (char) 
                                    * (buffer_len + buffer_free_mem + 1));                                     * (buffer_len + buffer_free_mem + 1));
               if (status)                if (status)
                 buffer = (char *) status;                  buffer = (char *) status;
               else                else
                 {                  {
                   /* @@ maybe we should do some other behavior here, like                    /* @@ maybe we should do some other behavior here, like
                      freeing the buffer and return a void thing */                       freeing the buffer and return a void thing */
                   buffer[buffer_len] = EOS;                    buffer[buffer_len] = EOS;
                   break;                    break;
                 }                  }
               }
             /* escape the char */
             if (entity)
               {
                 sprintf (&buffer[buffer_len], "%s", entity);
                 entity = NULL;
             }              }
           /* escape the char */  
           if (entity)  
             {  
               sprintf (&buffer[buffer_len], "%s", entity);  
               entity = NULL;  
             }  
           else            else
             buffer[buffer_len] = *ptr;              buffer[buffer_len] = *ptr;
   
Line 259  char *EscapeXML (const char *string) Line 259  char *EscapeXML (const char *string)
   ExplodeURL     ExplodeURL 
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 void ExplodeURL (char *url, char **proto, char **host, char **dir,  void ExplodeURL (char *url, char **proto, char **host, char **dir,
                  char **file)                   char **file)
 {  {
    char            *curr, *temp;    char            *curr, *temp;
    char             used_sep;    char             used_sep;
   
    if (url && strchr (url, URL_SEP))    if (url && strchr (url, URL_SEP))
      used_sep = URL_SEP;      used_sep = URL_SEP;
    else    else
      used_sep = DIR_SEP;      used_sep = DIR_SEP;
   
    if ((url == NULL) || (proto == NULL) || (host == NULL) ||    if ((url == NULL) || (proto == NULL) || (host == NULL) ||
        (dir == NULL) || (file == NULL))        (dir == NULL) || (file == NULL))
       return;      return;
   
    /* initialize every pointer */    /* initialize every pointer */
    *proto = *host = *dir = *file = NULL;    *proto = *host = *dir = *file = NULL;
   
    /* skip any leading space */    /* skip any leading space */
    while ((*url == SPACE) || (*url == TAB))    while ((*url == SPACE) || (*url == TAB))
       url++;      url++;
    curr = url;    curr = url;
    if (*curr == 0)    if (*curr == 0)
       goto finished;      goto finished;
   
    /* go to the end of the URL */    /* go to the end of the URL */
    while ((*curr != EOS) && (*curr != SPACE) && (*curr != BSPACE) &&    while ((*curr != EOS) && (*curr != SPACE) && (*curr != BSPACE) &&
           (*curr != __CR__) && (*curr != EOL))           (*curr != __CR__) && (*curr != EOL))
       curr++;      curr++;
   
    /* mark the end of the chain */    /* mark the end of the chain */
    *curr = EOS;    *curr = EOS;
    curr--;    curr--;
    if (curr <= url)    if (curr <= url)
       goto finished;      goto finished;
   
    /* search the next DIR_SEP indicating the beginning of the file name */    /* search the next DIR_SEP indicating the beginning of the file name */
    do    do
      curr--;      curr--;
    while ((curr >= url) && (*curr != used_sep));    while ((curr >= url) && (*curr != used_sep));
   
    if (curr < url)    if (curr < url)
       goto finished;      goto finished;
    *file = curr + 1;    *file = curr + 1;
   
    /* mark the end of the dir */    /* mark the end of the dir */
    *curr = EOS;    *curr = EOS;
    curr--;    curr--;
    if (curr < url)    if (curr < url)
       goto finished;      goto finished;
   
     /* search for the DIR_STR indicating the host name start */
     while ((curr > url) && ((*curr != used_sep) || (*(curr + 1) != used_sep)))
       curr--;
   
     /* if we found it, separate the host name from the directory */
     if ((*curr == used_sep) && (*(curr + 1) == used_sep))
       {
         *host = temp = curr + 2;
         while ((*temp != 0) && (*temp != used_sep))
           temp++;
         if (*temp == used_sep)
           {
             *temp = EOS;
             *dir = temp + 1;
           }
       }
     else
       *dir = curr;
   
    /* search for the DIR_STR indicating the host name start */    if (curr <= url)
    while ((curr > url) && ((*curr != used_sep) || (*(curr + 1) != used_sep)))      goto finished;
       curr--;  
     /* mark the end of the proto */
     *curr = EOS;
     curr--;
     if (curr < url)
       goto finished;
   
    /* if we found it, separate the host name from the directory */    if (*curr == ':')
    if ((*curr == used_sep) && (*(curr + 1) == used_sep))      {
      {        *curr = EOS;
         *host = temp = curr + 2;  
         while ((*temp != 0) && (*temp != used_sep))  
            temp++;  
         if (*temp == used_sep)  
           {  
              *temp = EOS;  
              *dir = temp + 1;  
           }  
      }  
    else  
      *dir = curr;  
   
    if (curr <= url)  
       goto finished;  
   
    /* mark the end of the proto */  
    *curr = EOS;  
    curr--;  
    if (curr < url)  
       goto finished;  
   
    if (*curr == ':')  
      {  
         *curr = EOS;  
         curr--;  
      }  
    else  
       goto finished;  
   
    if (curr < url)  
       goto finished;  
    while ((curr > url) && (isalpha (*curr)))  
       curr--;        curr--;
    *proto = curr;      }
     else
       goto finished;
   
     if (curr < url)
       goto finished;
     while ((curr > url) && (isalpha (*curr)))
       curr--;
     *proto = curr;
   
  finished:;   finished:;
   
 #ifdef AMAYA_DEBUG  #ifdef AMAYA_DEBUG
    fprintf (stderr, "ExplodeURL(%s)\n\t", url);    fprintf (stderr, "ExplodeURL(%s)\n\t", url);
    if (*proto)    if (*proto)
       fprintf (stderr, "proto : %s, ", *proto);      fprintf (stderr, "proto : %s, ", *proto);
    if (*host)    if (*host)
       fprintf (stderr, "host : %s, ", *host);      fprintf (stderr, "host : %s, ", *host);
    if (*dir)    if (*dir)
       fprintf (stderr, "dir : %s, ", *dir);      fprintf (stderr, "dir : %s, ", *dir);
    if (*file)    if (*file)
       fprintf (stderr, "file : %s ", *file);      fprintf (stderr, "file : %s ", *file);
    fprintf (stderr, "\n");    fprintf (stderr, "\n");
 #endif  #endif
   
 }  }
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
    PicTypeToMime    PicTypeToMime
    Converts a Thot PicType into the equivalent MIME type. If no convertion    Converts a Thot PicType into the equivalent MIME type. If no convertion
    is possible, it returns NULL.    is possible, it returns NULL.
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 char *PicTypeToMIME (PicType contentType)  char *PicTypeToMIME (PicType contentType)
 {  {
Line 385  char *PicTypeToMIME (PicType contentType Line 385  char *PicTypeToMIME (PicType contentType
     case eps_type:      case eps_type:
       mime_type ="application/postscript";        mime_type ="application/postscript";
       break;        break;
    case xpm_type:      case xpm_type:
       mime_type ="image/x-xpicmap";        mime_type ="image/x-xpicmap";
      break;        break;
     case gif_type:      case gif_type:
       mime_type ="image/gif";        mime_type ="image/gif";
       break;        break;
Line 406  char *PicTypeToMIME (PicType contentType Line 406  char *PicTypeToMIME (PicType contentType
     case mathml_type:      case mathml_type:
       mime_type = AM_MATHML_MIME_TYPE;        mime_type = AM_MATHML_MIME_TYPE;
       break;        break;
    case unknown_type:      case unknown_type:
    default:      default:
      mime_type = NULL;        mime_type = NULL;
    }      }
   
   return mime_type;    return mime_type;
 }  }
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
    ImageElement    ImageElement
    Returns the element (image parameter) and URL (url parameter) of an    Returns the element (image parameter) and URL (url parameter) of an
    image in a docImage document. The user must free the memory associated    image in a docImage document. The user must free the memory associated
    with the url parameter if the function is succesful.     with the url parameter if the function is succesful. 
    If the url parameter is NULL, we won't initialize it.    If the url parameter is NULL, we won't initialize it.
    Returns TRUE if succesful, FALSE otherwise.    Returns TRUE if succesful, FALSE otherwise.
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 ThotBool ImageElement (Document doc, char **url, Element *image)  ThotBool ImageElement (Document doc, char **url, Element *image)
 {  {
Line 450  ThotBool ImageElement (Document doc, cha Line 450  ThotBool ImageElement (Document doc, cha
       utf8value = (char *)TtaGetMemory (length);        utf8value = (char *)TtaGetMemory (length);
       TtaGiveTextAttributeValue (srcAttr, utf8value, &length);        TtaGiveTextAttributeValue (srcAttr, utf8value, &length);
       *url = (char *)TtaConvertMbsToByte ((unsigned char *)utf8value,        *url = (char *)TtaConvertMbsToByte ((unsigned char *)utf8value,
                                           TtaGetDefaultCharset ());                                            TtaGetDefaultCharset ());
       TtaFreeMemory (utf8value);        TtaFreeMemory (utf8value);
     }      }
   return TRUE;    return TRUE;
 }  }
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
    DocImageMimeType    DocImageMimeType
    Returns the MIME type of a docImage document.    Returns the MIME type of a docImage document.
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 char *DocImageMimeType (Document doc)  char *DocImageMimeType (Document doc)
 {  {
Line 475  char *DocImageMimeType (Document doc) Line 475  char *DocImageMimeType (Document doc)
     {      {
       /* it is a local image */        /* it is a local image */
       if (ImageElement (doc, NULL, &image))        if (ImageElement (doc, NULL, &image))
         {          {
           type = TtaGetPictureType (image);            type = TtaGetPictureType (image);
           mime_type = PicTypeToMIME (type);            mime_type = PicTypeToMIME (type);
         }          }
     }      }
   else    else
     {      {
       /* find the value of the src attribute */        /* find the value of the src attribute */
       pImage = ImageURLs;        pImage = ImageURLs;
       while (pImage != NULL)        while (pImage != NULL)
         {          {
           if (pImage->document == doc)            if (pImage->document == doc)
             {              {
               if (pImage->content_type)                if (pImage->content_type)
                 mime_type = pImage->content_type;                  mime_type = pImage->content_type;
               else if (pImage->elImage && pImage->elImage->currentElement)                else if (pImage->elImage && pImage->elImage->currentElement)
                 {                  {
                   type = TtaGetPictureType (pImage->elImage->currentElement);                    type = TtaGetPictureType (pImage->elImage->currentElement);
                   mime_type = PicTypeToMIME (type);                    mime_type = PicTypeToMIME (type);
                 }                  }
               break;                break;
             }                }  
         }          }
     }      }
   return (mime_type);    return (mime_type);
 }  }
Line 525  ThotBool IsHTMLName (const char *path) Line 525  ThotBool IsHTMLName (const char *path)
       /* Normalize the suffix */        /* Normalize the suffix */
       i = 0;        i = 0;
       while (suffix[i] != EOS && i < MAX_LENGTH -1)        while (suffix[i] != EOS && i < MAX_LENGTH -1)
         {          {
           nsuffix[i] = tolower (suffix[i]);            nsuffix[i] = tolower (suffix[i]);
           i++;            i++;
         }          }
       nsuffix[i] = EOS;        nsuffix[i] = EOS;
       if (!strcmp (nsuffix, "html") ||        if (!strcmp (nsuffix, "html") ||
           !strcmp (nsuffix, "htm") ||            !strcmp (nsuffix, "htm") ||
           !strcmp (nsuffix, "shtml") ||            !strcmp (nsuffix, "shtml") ||
           !strcmp (nsuffix, "jsp") ||            !strcmp (nsuffix, "jsp") ||
           !strcmp (nsuffix, "tpl") ||            !strcmp (nsuffix, "tpl") ||
           !strcmp (nsuffix, "xht") ||            !strcmp (nsuffix, "xht") ||
           !strcmp (nsuffix, "xhtm") ||            !strcmp (nsuffix, "xhtm") ||
           !strcmp (nsuffix, "lhtml") ||            !strcmp (nsuffix, "lhtml") ||
           !strcmp (nsuffix, "xhtml"))            !strcmp (nsuffix, "xhtml"))
         {          {
           TtaFreeMemory (temppath);            TtaFreeMemory (temppath);
           TtaFreeMemory (suffix);            TtaFreeMemory (suffix);
           return (TRUE);            return (TRUE);
         }          }
       else if (!strcmp (nsuffix, "gz"))        else if (!strcmp (nsuffix, "gz"))
         {          {
           /* take into account compressed files */            /* take into account compressed files */
           TtaExtractSuffix (temppath, suffix);                   TtaExtractSuffix (temppath, suffix);       
           /* Normalize the suffix */            /* Normalize the suffix */
           i = 0;            i = 0;
           while (suffix[i] != EOS && i < MAX_LENGTH -1)            while (suffix[i] != EOS && i < MAX_LENGTH -1)
             {              {
               nsuffix[i] = tolower (suffix[i]);                nsuffix[i] = tolower (suffix[i]);
               i++;                i++;
             }              }
           nsuffix[i] = EOS;            nsuffix[i] = EOS;
           TtaFreeMemory (temppath);            TtaFreeMemory (temppath);
           TtaFreeMemory (suffix);            TtaFreeMemory (suffix);
           if (!strcmp (nsuffix, "html") ||            if (!strcmp (nsuffix, "html") ||
               !strcmp (nsuffix, "htm") ||                !strcmp (nsuffix, "htm") ||
               !strcmp (nsuffix, "shtml") ||                !strcmp (nsuffix, "shtml") ||
               !strcmp (nsuffix, "jsp") ||                !strcmp (nsuffix, "jsp") ||
               !strcmp (nsuffix, "tpl") ||                !strcmp (nsuffix, "tpl") ||
               !strcmp (nsuffix, "xht") ||                !strcmp (nsuffix, "xht") ||
               !strcmp (nsuffix, "xhtm") ||                !strcmp (nsuffix, "xhtm") ||
               !strcmp (nsuffix, "lhtml") ||                !strcmp (nsuffix, "lhtml") ||
               !strcmp (nsuffix, "xhtml"))                !strcmp (nsuffix, "xhtml"))
             return (TRUE);              return (TRUE);
           else            else
             return (FALSE);              return (FALSE);
         }          }
       else        else
         /* check if there is another suffix */          /* check if there is another suffix */
         TtaExtractSuffix (temppath, suffix);          TtaExtractSuffix (temppath, suffix);
     }      }
   TtaFreeMemory (temppath);    TtaFreeMemory (temppath);
   TtaFreeMemory (suffix);    TtaFreeMemory (suffix);
Line 586  ThotBool IsHTMLName (const char *path) Line 586  ThotBool IsHTMLName (const char *path)
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 ThotBool IsMathMLName (const char *path)  ThotBool IsMathMLName (const char *path)
 {  {
    char        *temppath;    char        *temppath;
    char        *suffix;    char        *suffix;
    ThotBool    ret;    ThotBool    ret;
   
    if (!path)    if (!path)
      return (FALSE);      return (FALSE);
   
    temppath = TtaStrdup ((char *)path);    temppath = TtaStrdup ((char *)path);
    suffix = (char *)TtaGetMemory (strlen (path) + 1);    suffix = (char *)TtaGetMemory (strlen (path) + 1);
    TtaExtractSuffix (temppath, suffix);    TtaExtractSuffix (temppath, suffix);
   
    if (!strcasecmp (suffix, "mml"))    if (!strcasecmp (suffix, "mml"))
      ret = TRUE;      ret = TRUE;
    else if (!strcmp (suffix, "gz"))    else if (!strcmp (suffix, "gz"))
      {      {
        /* take into account compressed files */        /* take into account compressed files */
        TtaExtractSuffix (temppath, suffix);               TtaExtractSuffix (temppath, suffix);       
        if (!strcasecmp (suffix, "mml"))        if (!strcasecmp (suffix, "mml"))
          ret = TRUE;          ret = TRUE;
        else        else
          ret = FALSE;          ret = FALSE;
      }      }
    else    else
      ret = FALSE;      ret = FALSE;
   
   TtaFreeMemory (temppath);    TtaFreeMemory (temppath);
   TtaFreeMemory (suffix);    TtaFreeMemory (suffix);
Line 622  ThotBool IsMathMLName (const char *path) Line 622  ThotBool IsMathMLName (const char *path)
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 ThotBool IsSVGName (const char *path)  ThotBool IsSVGName (const char *path)
 {  {
    char        *temppath;    char        *temppath;
    char        *suffix;    char        *suffix;
    ThotBool    ret;    ThotBool    ret;
   
    if (!path)    if (!path)
       return (FALSE);      return (FALSE);
   
    temppath = TtaStrdup ((char *)path);    temppath = TtaStrdup ((char *)path);
    suffix = (char *)TtaGetMemory (strlen (path) + 1);    suffix = (char *)TtaGetMemory (strlen (path) + 1);
    TtaExtractSuffix (temppath, suffix);    TtaExtractSuffix (temppath, suffix);
   
    if (!strcasecmp (suffix, "svg") || !strcasecmp (suffix, "svgz"))    if (!strcasecmp (suffix, "svg") || !strcasecmp (suffix, "svgz"))
      ret = TRUE;      ret = TRUE;
    else if (!strcmp (suffix, "gz"))    else if (!strcmp (suffix, "gz"))
      {      {
        /* take into account compressed files */        /* take into account compressed files */
        TtaExtractSuffix (temppath, suffix);               TtaExtractSuffix (temppath, suffix);       
        if (!strcasecmp (suffix, "svg"))        if (!strcasecmp (suffix, "svg"))
          ret = TRUE;          ret = TRUE;
        else        else
          ret = FALSE;          ret = FALSE;
      }      }
    else    else
      ret = FALSE;      ret = FALSE;
   
   TtaFreeMemory (temppath);    TtaFreeMemory (temppath);
   TtaFreeMemory (suffix);    TtaFreeMemory (suffix);
Line 658  ThotBool IsSVGName (const char *path) Line 658  ThotBool IsSVGName (const char *path)
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 ThotBool IsXMLName (const char *path)  ThotBool IsXMLName (const char *path)
 {  {
    char        *temppath;    char        *temppath;
    char        *suffix;    char        *suffix;
    ThotBool    ret;    ThotBool    ret;
   
    if (!path)    if (!path)
       return (FALSE);      return (FALSE);
   
    temppath = TtaStrdup ((char *)path);    temppath = TtaStrdup ((char *)path);
    suffix = (char *)TtaGetMemory (strlen (path) + 1);    suffix = (char *)TtaGetMemory (strlen (path) + 1);
    TtaExtractSuffix (temppath, suffix);    TtaExtractSuffix (temppath, suffix);
   
    if (!strcasecmp (suffix, "xml") ||    if (!strcasecmp (suffix, "xml") ||
        !strcasecmp (suffix, "xht") ||        !strcasecmp (suffix, "xht") ||
        !strcmp (suffix, "xhtm") ||        !strcmp (suffix, "xhtm") ||
        !strcmp (suffix, "xhtml") ||        !strcmp (suffix, "xhtml") ||
        !strcmp (suffix, "smi") ||        !strcmp (suffix, "smi") ||
        !strcmp (suffix, "zsl"))        !strcmp (suffix, "zsl"))
      ret = TRUE;      ret = TRUE;
    else if (!strcmp (suffix, "gz"))    else if (!strcmp (suffix, "gz"))
      {      {
        /* take into account compressed files */        /* take into account compressed files */
        TtaExtractSuffix (temppath, suffix);               TtaExtractSuffix (temppath, suffix);       
        if (!strcasecmp (suffix, "xml") ||        if (!strcasecmp (suffix, "xml") ||
            !strcasecmp (suffix, "xht") ||            !strcasecmp (suffix, "xht") ||
            !strcmp (suffix, "xhtm") ||            !strcmp (suffix, "xhtm") ||
            !strcmp (suffix, "xhtml") ||            !strcmp (suffix, "xhtml") ||
            !strcmp (suffix, "smi") |            !strcmp (suffix, "smi") |
            !strcmp (suffix, "xsl"))            !strcmp (suffix, "xsl"))
          ret = TRUE;          ret = TRUE;
        else        else
          ret = FALSE;          ret = FALSE;
      }      }
    else    else
      ret = FALSE;      ret = FALSE;
   
   TtaFreeMemory (temppath);    TtaFreeMemory (temppath);
   TtaFreeMemory (suffix);    TtaFreeMemory (suffix);
Line 704  ThotBool IsXMLName (const char *path) Line 704  ThotBool IsXMLName (const char *path)
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 ThotBool IsUndisplayedName (const char *path)  ThotBool IsUndisplayedName (const char *path)
 {  {
    char                *temppath;    char                *temppath;
    char                *suffix;    char                *suffix;
    ThotBool            ret;    ThotBool            ret;
   
    if (!path)    if (!path)
       return (FALSE);      return (FALSE);
   
    temppath = TtaStrdup ((char *)path);    temppath = TtaStrdup ((char *)path);
    suffix = (char *)TtaGetMemory (strlen (path) + 1);    suffix = (char *)TtaGetMemory (strlen (path) + 1);
    TtaExtractSuffix (temppath, suffix);    TtaExtractSuffix (temppath, suffix);
   
    if (!strcasecmp (suffix, "exe") ||    if (!strcasecmp (suffix, "exe") ||
        !strcasecmp (suffix, "zip") ||        !strcasecmp (suffix, "zip") ||
        !strcasecmp (suffix, "ppt") ||        !strcasecmp (suffix, "ppt") ||
        !strcasecmp (suffix, "pdf") ||        !strcasecmp (suffix, "pdf") ||
        !strcasecmp (suffix, "ps")  ||        !strcasecmp (suffix, "ps")  ||
        !strcasecmp (suffix, "eps") ||        !strcasecmp (suffix, "eps") ||
        !strcasecmp (suffix, "tar") ||        !strcasecmp (suffix, "tar") ||
        !strcasecmp (suffix, "tgz") ||        !strcasecmp (suffix, "tgz") ||
        !strcasecmp (suffix, "ddl") ||        !strcasecmp (suffix, "ddl") ||
        !strcasecmp (suffix, "ddl") ||        !strcasecmp (suffix, "ddl") ||
        !strcasecmp (suffix, "mpg") ||        !strcasecmp (suffix, "mpg") ||
        !strcasecmp (suffix, "mpeg") ||        !strcasecmp (suffix, "mpeg") ||
        !strcasecmp (suffix, "wmv") ||        !strcasecmp (suffix, "wmv") ||
        !strcasecmp (suffix, "wma") ||        !strcasecmp (suffix, "wma") ||
        !strcasecmp (suffix, "o"))        !strcasecmp (suffix, "o"))
      ret = TRUE;      ret = TRUE;
    else if (!strcmp (suffix, "gz"))    else if (!strcmp (suffix, "gz"))
      {      {
        /* take into account compressed files */        /* take into account compressed files */
        TtaExtractSuffix (temppath, suffix);               TtaExtractSuffix (temppath, suffix);       
        if (!strcasecmp (suffix, "exe") ||        if (!strcasecmp (suffix, "exe") ||
            !strcasecmp (suffix, "zip") ||            !strcasecmp (suffix, "zip") ||
            !strcasecmp (suffix, "ppt") ||            !strcasecmp (suffix, "ppt") ||
            !strcasecmp (suffix, "pdf") ||            !strcasecmp (suffix, "pdf") ||
            !strcasecmp (suffix, "ps")  ||            !strcasecmp (suffix, "ps")  ||
            !strcasecmp (suffix, "eps") ||            !strcasecmp (suffix, "eps") ||
            !strcasecmp (suffix, "tar") ||            !strcasecmp (suffix, "tar") ||
            !strcasecmp (suffix, "ddl") ||            !strcasecmp (suffix, "ddl") ||
            !strcasecmp (suffix, "mpg") ||            !strcasecmp (suffix, "mpg") ||
            !strcasecmp (suffix, "mpeg") ||            !strcasecmp (suffix, "mpeg") ||
            !strcasecmp (suffix, "wmv") ||            !strcasecmp (suffix, "wmv") ||
            !strcasecmp (suffix, "wma") ||            !strcasecmp (suffix, "wma") ||
            !strcasecmp (suffix, "o"))            !strcasecmp (suffix, "o"))
          ret = TRUE;          ret = TRUE;
        else        else
          ret = FALSE;          ret = FALSE;
      }      }
    else    else
      ret = FALSE;      ret = FALSE;
   
    TtaFreeMemory (temppath);    TtaFreeMemory (temppath);
    TtaFreeMemory (suffix);    TtaFreeMemory (suffix);
    return (ret);    return (ret);
 }  }
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
Line 766  ThotBool IsUndisplayedName (const char * Line 766  ThotBool IsUndisplayedName (const char *
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 ThotBool IsCSSName (const char *path)  ThotBool IsCSSName (const char *path)
 {  {
    char                *temppath;    char                *temppath;
    char                *suffix;    char                *suffix;
    ThotBool            ret;    ThotBool            ret;
   
    if (!path)    if (!path)
      return (FALSE);      return (FALSE);
   
    temppath = TtaStrdup ((char *)path);    temppath = TtaStrdup ((char *)path);
    suffix = (char *)TtaGetMemory (strlen (path) + 1);    suffix = (char *)TtaGetMemory (strlen (path) + 1);
    TtaExtractSuffix (temppath, suffix);    TtaExtractSuffix (temppath, suffix);
   
    if (!strcasecmp (suffix, "css"))    if (!strcasecmp (suffix, "css"))
      ret = TRUE;      ret = TRUE;
    else if (!strcmp (suffix, "gz"))    else if (!strcmp (suffix, "gz"))
      {      {
        /* take into account compressed files */        /* take into account compressed files */
        TtaExtractSuffix (temppath, suffix);               TtaExtractSuffix (temppath, suffix);       
        if (!strcasecmp (suffix, "css"))        if (!strcasecmp (suffix, "css"))
          ret = TRUE;          ret = TRUE;
        else        else
          ret = FALSE;          ret = FALSE;
      }      }
    else    else
      ret = FALSE;      ret = FALSE;
   
    TtaFreeMemory (temppath);    TtaFreeMemory (temppath);
    TtaFreeMemory (suffix);    TtaFreeMemory (suffix);
    return (ret);    return (ret);
 }  }
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
Line 816  ThotBool MultipleBookmarks (void) Line 816  ThotBool MultipleBookmarks (void)
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 ThotBool IsRDFName (const char *path)  ThotBool IsRDFName (const char *path)
 {  {
    char                *temppath;    char                *temppath;
    char                *suffix;    char                *suffix;
    ThotBool            ret;    ThotBool            ret;
   
    /* temporarily disabling this function */    /* temporarily disabling this function */
    if (!MultipleBookmarks ())    if (!MultipleBookmarks ())
      return (FALSE);      return (FALSE);
   
    if (!path)    if (!path)
      return (FALSE);      return (FALSE);
   
    temppath = TtaStrdup ((char *)path);    temppath = TtaStrdup ((char *)path);
    suffix = (char *)TtaGetMemory (strlen (path) + 1);    suffix = (char *)TtaGetMemory (strlen (path) + 1);
    TtaExtractSuffix (temppath, suffix);    TtaExtractSuffix (temppath, suffix);
   
    if (!strcasecmp (suffix, "rdf"))    if (!strcasecmp (suffix, "rdf"))
      ret = TRUE;      ret = TRUE;
    else if (!strcmp (suffix, "gz"))    else if (!strcmp (suffix, "gz"))
      {      {
        /* take into account compressed files */        /* take into account compressed files */
        TtaExtractSuffix (temppath, suffix);               TtaExtractSuffix (temppath, suffix);       
        if (!strcasecmp (suffix, "rdf"))        if (!strcasecmp (suffix, "rdf"))
          ret = TRUE;          ret = TRUE;
        else        else
          ret = FALSE;          ret = FALSE;
      }      }
    else    else
      ret = FALSE;      ret = FALSE;
         
    TtaFreeMemory (temppath);    TtaFreeMemory (temppath);
    TtaFreeMemory (suffix);    TtaFreeMemory (suffix);
    return (ret);    return (ret);
 }  }
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
Line 856  ThotBool IsRDFName (const char *path) Line 856  ThotBool IsRDFName (const char *path)
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 ThotBool IsImageName (const char *path)  ThotBool IsImageName (const char *path)
 {  {
    char                *temppath;    char                *temppath;
    char                *suffix;    char                *suffix;
    char                nsuffix[MAX_LENGTH];    char                nsuffix[MAX_LENGTH];
    int                 i;    int                 i;
    ThotBool            ret;    ThotBool            ret;
   
    if (!path)    if (!path)
       return (FALSE);      return (FALSE);
   
    temppath = TtaStrdup ((char *)path);    temppath = TtaStrdup ((char *)path);
    suffix = (char *)TtaGetMemory (strlen (path) + 1);    suffix = (char *)TtaGetMemory (strlen (path) + 1);
    TtaExtractSuffix (temppath, suffix);    TtaExtractSuffix (temppath, suffix);
   
    /* Normalize the suffix */    /* Normalize the suffix */
    i = 0;    i = 0;
    while (suffix[i] != EOS && i < MAX_LENGTH -1)    while (suffix[i] != EOS && i < MAX_LENGTH -1)
      {      {
        nsuffix[i] = tolower (suffix[i]);        nsuffix[i] = tolower (suffix[i]);
        i++;        i++;
      }      }
    nsuffix[i] = EOS;    nsuffix[i] = EOS;
    if ((!strcmp (nsuffix, "gif")) || (!strcmp (nsuffix, "xbm")) ||    if ((!strcmp (nsuffix, "gif")) || (!strcmp (nsuffix, "xbm")) ||
        (!strcmp (nsuffix, "xpm")) || (!strcmp (nsuffix, "jpg")) ||        (!strcmp (nsuffix, "xpm")) || (!strcmp (nsuffix, "jpg")) ||
        (!strcmp (nsuffix, "png")) || (!strcmp (nsuffix, "au")))        (!strcmp (nsuffix, "png")) || (!strcmp (nsuffix, "au")))
       ret = TRUE;      ret = TRUE;
    else    else
       ret = FALSE;      ret = FALSE;
   
    TtaFreeMemory (temppath);    TtaFreeMemory (temppath);
    TtaFreeMemory (suffix);    TtaFreeMemory (suffix);
    return (ret);    return (ret);
 }  }
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
Line 895  ThotBool IsImageName (const char *path) Line 895  ThotBool IsImageName (const char *path)
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 ThotBool IsImageType (const char *type)  ThotBool IsImageType (const char *type)
 {  {
    char                *temptype;    char                *temptype;
    int                 i;    int                 i;
    ThotBool            ret;    ThotBool            ret;
   
    if (!type)    if (!type)
       return (FALSE);      return (FALSE);
   
    temptype = TtaStrdup ((char *)type);    temptype = TtaStrdup ((char *)type);
    /* Normalize the type */    /* Normalize the type */
    i = 0;    i = 0;
    while (temptype[i] != EOS)    while (temptype[i] != EOS)
      {      {
        temptype[i] = tolower (temptype[i]);        temptype[i] = tolower (temptype[i]);
        i++;        i++;
      }      }
   if (!strncmp (temptype, "image/", sizeof ("image/") - 1))    if (!strncmp (temptype, "image/", sizeof ("image/") - 1))
      i = sizeof ("image/") - 1;      i = sizeof ("image/") - 1;
    else    else
      i = 0;      i = 0;
    if (!strcmp (&temptype[i], "gif") ||    if (!strcmp (&temptype[i], "gif") ||
        !strcmp (&temptype[i], "x-xbitmap") ||        !strcmp (&temptype[i], "x-xbitmap") ||
        !strcmp (&temptype[i], "x-xpixmap") ||        !strcmp (&temptype[i], "x-xpixmap") ||
        !strcmp (&temptype[i], "jpeg") ||        !strcmp (&temptype[i], "jpeg") ||
        !strcmp (&temptype[i], "png"))        !strcmp (&temptype[i], "png"))
      ret = TRUE;      ret = TRUE;
    else    else
      ret = FALSE;      ret = FALSE;
    TtaFreeMemory (temptype);    TtaFreeMemory (temptype);
    return (ret);    return (ret);
 }  }
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
Line 931  ThotBool IsImageType (const char *type) Line 931  ThotBool IsImageType (const char *type)
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 ThotBool IsTextName (const char *path)  ThotBool IsTextName (const char *path)
 {  {
    char                *temppath;    char                *temppath;
    char                *suffix;    char                *suffix;
    char                nsuffix[MAX_LENGTH];    char                nsuffix[MAX_LENGTH];
    int                 i;    int                 i;
    ThotBool            ret;    ThotBool            ret;
   
    if (!path)    if (!path)
      return (FALSE);      return (FALSE);
   
    temppath = TtaStrdup ((char *)path);    temppath = TtaStrdup ((char *)path);
    suffix = (char *)TtaGetMemory (strlen (path) + 1);    suffix = (char *)TtaGetMemory (strlen (path) + 1);
    TtaExtractSuffix (temppath, suffix);    TtaExtractSuffix (temppath, suffix);
   
    /* Normalize the suffix */    /* Normalize the suffix */
    i = 0;    i = 0;
    while (suffix[i] != EOS && i < MAX_LENGTH -1)    while (suffix[i] != EOS && i < MAX_LENGTH -1)
      {      {
         nsuffix[i] = tolower (suffix[i]);        nsuffix[i] = tolower (suffix[i]);
         i++;        i++;
      }      }
    nsuffix[i] = EOS;    nsuffix[i] = EOS;
   
    if (!strcmp (nsuffix, "txt") ||    if (!strcmp (nsuffix, "txt") ||
        !strcmp (nsuffix, "dtd"))        !strcmp (nsuffix, "dtd"))
       ret = TRUE;      ret = TRUE;
    else if (!strcmp (nsuffix, "gz"))    else if (!strcmp (nsuffix, "gz"))
      {      {
        /* take into account compressed files */        /* take into account compressed files */
        TtaExtractSuffix (temppath, suffix);               TtaExtractSuffix (temppath, suffix);       
        /* Normalize the suffix */        /* Normalize the suffix */
        i = 0;        i = 0;
        while (suffix[i] != EOS && i < MAX_LENGTH -1)        while (suffix[i] != EOS && i < MAX_LENGTH -1)
          {          {
            nsuffix[i] = tolower (suffix[i]);            nsuffix[i] = tolower (suffix[i]);
            i++;            i++;
          }          }
        nsuffix[i] = EOS;        nsuffix[i] = EOS;
        if (!strcmp (nsuffix, "txt") ||        if (!strcmp (nsuffix, "txt") ||
            !strcmp (nsuffix, "dtd"))            !strcmp (nsuffix, "dtd"))
          ret = TRUE;          ret = TRUE;
        else        else
          ret = FALSE;          ret = FALSE;
      }      }
    else    else
      ret = FALSE;      ret = FALSE;
   
    TtaFreeMemory (temppath);    TtaFreeMemory (temppath);
    TtaFreeMemory (suffix);    TtaFreeMemory (suffix);
    return (ret);    return (ret);
 }  }
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
Line 988  ThotBool IsTextName (const char *path) Line 988  ThotBool IsTextName (const char *path)
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 ThotBool IsHTTPPath (const char *path)  ThotBool IsHTTPPath (const char *path)
 {  {
    if (!path)    if (!path)
       return FALSE;      return FALSE;
   
    if ((!strncmp (path, "http:", 5) != 0)    if ((!strncmp (path, "http:", 5) != 0)
        || (AHTFTPURL_flag () && !strncmp (path, "ftp:", 4))        || (AHTFTPURL_flag () && !strncmp (path, "ftp:", 4))
        || !strncmp (path, "internal:", 9))        || !strncmp (path, "internal:", 9))
       return TRUE;      return TRUE;
    return FALSE;    return FALSE;
 }  }
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
Line 1004  ThotBool IsHTTPPath (const char *path) Line 1004  ThotBool IsHTTPPath (const char *path)
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 ThotBool IsWithParameters (const char *url)  ThotBool IsWithParameters (const char *url)
 {  {
    int                 i;    int                 i;
   
    if ((!url) || (url[0] == EOS))    if ((!url) || (url[0] == EOS))
       return FALSE;      return FALSE;
   
    i = strlen (url) - 1;    i = strlen (url) - 1;
    while (i > 0 && url[i--] != '?')    while (i > 0 && url[i--] != '?')
       if (i < 0)      if (i < 0)
          return FALSE;        return FALSE;
   
    /* There is a parameter */    /* There is a parameter */
    return TRUE;    return TRUE;
 }  }
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
Line 1056  ThotBool IsFilePath (const char *path) Line 1056  ThotBool IsFilePath (const char *path)
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 ThotBool IsValidProtocol (const char *url)  ThotBool IsValidProtocol (const char *url)
 {  {
    if (!strncmp (url, "http:", 5)    if (!strncmp (url, "http:", 5)
       || !strncmp (url, "internal:", 9)        || !strncmp (url, "internal:", 9)
       || (AHTFTPURL_flag () && !strncmp (url, "ftp:", 4)))        || (AHTFTPURL_flag () && !strncmp (url, "ftp:", 4)))
        /* experimental */      /* experimental */
      /*** || !strncmp (path, "news:", 5)***/       /*** || !strncmp (path, "news:", 5)***/ 
       return (TRUE);      return (TRUE);
    else    else
       return (FALSE);      return (FALSE);
 }  }
   
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
    GetBaseURL    GetBaseURL
    normalizes orgName according to a base associated with doc, and    normalizes orgName according to a base associated with doc, and
    following the standard URL format rules.    following the standard URL format rules.
    The function returns the base used to solve relative URL and SRC:    The function returns the base used to solve relative URL and SRC:
       - the base of the document,    - the base of the document,
       - or the document path (without document name).    - or the document path (without document name).
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 char  *GetBaseURL (Document doc)  char  *GetBaseURL (Document doc)
 {  {
Line 1086  char  *GetBaseURL (Document doc) Line 1086  char  *GetBaseURL (Document doc)
   ThotBool            hasDocBase;    ThotBool            hasDocBase;
   
   if (doc == 0 || !DocumentURLs[doc])    if (doc == 0 || !DocumentURLs[doc])
      return NULL;      return NULL;
   /* the other functions expect basename to have no more than MAX_LENGTH chars */    /* the other functions expect basename to have no more than MAX_LENGTH chars */
   basename = (char *)TtaGetMemory (MAX_LENGTH);    basename = (char *)TtaGetMemory (MAX_LENGTH);
   basename[0] = EOS;    basename[0] = EOS;
Line 1107  char  *GetBaseURL (Document doc) Line 1107  char  *GetBaseURL (Document doc)
       elType.ElTypeNum = HTML_EL_HEAD;        elType.ElTypeNum = HTML_EL_HEAD;
       el = TtaSearchTypedElement (elType, SearchForward, el);        el = TtaSearchTypedElement (elType, SearchForward, el);
       if (el)        if (el)
         /* there is a HEAD element */          /* there is a HEAD element */
         {          {
           /* look for a BASE element within the HEAD */            /* look for a BASE element within the HEAD */
           elType.ElTypeNum = HTML_EL_BASE;            elType.ElTypeNum = HTML_EL_BASE;
           el = TtaSearchTypedElement (elType, SearchInTree, el);            el = TtaSearchTypedElement (elType, SearchInTree, el);
         }          }
       if (el)        if (el)
         {          {
           /*  The document has a BASE element. Get the HREF attribute of the            /*  The document has a BASE element. Get the HREF attribute of the
               BASE element */                BASE element */
           hasDocBase = TRUE;            hasDocBase = TRUE;
           attrType.AttrSSchema = elType.ElSSchema;            attrType.AttrSSchema = elType.ElSSchema;
           attrType.AttrTypeNum = HTML_ATTR_HREF_;            attrType.AttrTypeNum = HTML_ATTR_HREF_;
           attr = TtaGetAttribute (el, attrType);            attr = TtaGetAttribute (el, attrType);
           if (attr)            if (attr)
             {              {
               /* Use the base path of the document */                /* Use the base path of the document */
               TtaGiveTextAttributeValue (attr, basename, &length);                TtaGiveTextAttributeValue (attr, basename, &length);
               utf8path = basename;                utf8path = (char *)TtaConvertMbsToByte ((unsigned char *)basename,
               basename = (char *)TtaConvertMbsToByte ((unsigned char *)utf8path,                                                         TtaGetDefaultCharset ());
                                                       TtaGetDefaultCharset ());                strncpy (basename, utf8path, MAX_LENGTH-1);
               TtaFreeMemory (utf8path);                TtaFreeMemory (utf8path);
             }              }
         }          }
     }      }
   
   /* there was no BASE. Do we have a location header? */    /* there was no BASE. Do we have a location header? */
Line 1147  char  *GetBaseURL (Document doc) Line 1147  char  *GetBaseURL (Document doc)
       /* base and orgName have to be separated by a DIR_SEP */        /* base and orgName have to be separated by a DIR_SEP */
       length--;        length--;
       if (basename[0] != EOS && basename[length] != URL_SEP &&        if (basename[0] != EOS && basename[length] != URL_SEP &&
           basename[length] != DIR_SEP)             basename[length] != DIR_SEP) 
         /* verify if the base has the form "protocol://server:port" */          /* verify if the base has the form "protocol://server:port" */
         {          {
           ptr = AmayaParseUrl (basename, "", AMAYA_PARSE_ACCESS |            ptr = AmayaParseUrl (basename, "", AMAYA_PARSE_ACCESS |
                                AMAYA_PARSE_HOST |                                 AMAYA_PARSE_HOST |
                                AMAYA_PARSE_PUNCTUATION);                                 AMAYA_PARSE_PUNCTUATION);
           if (ptr && !strcmp (ptr, basename))            if (ptr && !strcmp (ptr, basename))
             {              {
               /* it has this form, complete it by adding a URL_STR  */                /* it has this form, complete it by adding a URL_STR  */
               if (strchr (basename, DIR_SEP))                if (strchr (basename, DIR_SEP))
                 strcat (basename, DIR_STR);                  strcat (basename, DIR_STR);
               else                else
                 strcat (basename, URL_STR);                  strcat (basename, URL_STR);
               length++;                length++;
             }              }
           else if (!ptr || ptr[0] == EOS)            else if (!ptr || ptr[0] == EOS)
             {              {
               /* no host was detected, we may have a relative URL. We test                /* no host was detected, we may have a relative URL. We test
                  if it begins with a URL_SEP, DIR_SEP or period. If yes, it's                   if it begins with a URL_SEP, DIR_SEP or period. If yes, it's
                  relative. */                   relative. */
               if (! (basename[0] == '.' || basename[0] == URL_SEP                 if (! (basename[0] == '.' || basename[0] == URL_SEP 
                      || basename[0] == DIR_SEP))                       || basename[0] == DIR_SEP))
                 basename[0] = EOS;                  basename[0] = EOS;
             }              }
           if (ptr)            if (ptr)
             TtaFreeMemory (ptr);              TtaFreeMemory (ptr);
         }          }
     }      }
   
   /* there was no base element and no location header, we use the DocumentURL  */    /* there was no base element and no location header, we use the DocumentURL  */
Line 1199  char  *GetBaseURL (Document doc) Line 1199  char  *GetBaseURL (Document doc)
     /* search for the first PATH_STR char */      /* search for the first PATH_STR char */
     {      {
       for (length = 0; basename[length] != ':' &&         for (length = 0; basename[length] != ':' && 
              basename[length] != EOS; length ++);               basename[length] != EOS; length ++);
       if (basename[length] == ':')        if (basename[length] == ':')
         /* found, so end the string there */          /* found, so end the string there */
         basename[length + 1] = EOS;          basename[length + 1] = EOS;
       else        else
         /* not found, discard the base */          /* not found, discard the base */
         basename[0] = EOS;          basename[0] = EOS;
     }      }
   return (basename);    return (basename);
 }  }
   
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
    GetLocalPath    GetLocalPath
    Allocate and return the local document path associated to the url    Allocate and return the local document path associated to the url
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 char *GetLocalPath (Document doc, char  *url)  char *GetLocalPath (Document doc, char  *url)
 {  {
Line 1229  char *GetLocalPath (Document doc, char Line 1229  char *GetLocalPath (Document doc, char
       /* check whether the file name exists */        /* check whether the file name exists */
       len = strlen (url) - 1;        len = strlen (url) - 1;
       if (IsW3Path (url))        if (IsW3Path (url))
          url_sep = URL_SEP;          url_sep = URL_SEP;
       else         else 
           url_sep = DIR_SEP;          url_sep = DIR_SEP;
       noFile = (url[len] == url_sep);        noFile = (url[len] == url_sep);
       if (noFile)        if (noFile)
          url[len] = EOS;          url[len] = EOS;
       ptr = (char *)TtaGetMemory (MAX_LENGTH);        ptr = (char *)TtaGetMemory (MAX_LENGTH);
       documentname = (char *)TtaGetMemory (MAX_LENGTH);        documentname = (char *)TtaGetMemory (MAX_LENGTH);
       TtaExtractName (url, ptr, documentname);        TtaExtractName (url, ptr, documentname);
       sprintf (ptr, "%s%s%d%s", TempFileDirectory, DIR_STR, doc, DIR_STR);        sprintf (ptr, "%s%s%d%s", TempFileDirectory, DIR_STR, doc, DIR_STR);
       if (!TtaCheckDirectory (ptr))        if (!TtaCheckDirectory (ptr))
         /* directory did not exist */          /* directory did not exist */
         TtaMakeDirectory (ptr);          TtaMakeDirectory (ptr);
   
       if (doc == 0)        if (doc == 0)
         {          {
           n = strrchr (documentname, '.');            n = strrchr (documentname, '.');
           if (n)            if (n)
             *n = EOS;              *n = EOS;
           if (documentname[0] == EOS)            if (documentname[0] == EOS)
             strcpy (documentname, "noname");              strcpy (documentname, "noname");
           n = GetTempName (ptr, documentname);            n = GetTempName (ptr, documentname);
           TtaFreeMemory (ptr);            TtaFreeMemory (ptr);
           ptr = n;            ptr = n;
         }          }
       else        else
         {          {
           /* don't include the query string within document name */            /* don't include the query string within document name */
           n = strrchr (documentname, '?');            n = strrchr (documentname, '?');
           if (n)            if (n)
             *n = EOS;              *n = EOS;
           /* don't include ':' within document name */            /* don't include ':' within document name */
           n = strchr (documentname, ':');            n = strchr (documentname, ':');
           if (n)            if (n)
             *n = EOS;              *n = EOS;
           /* if after all this operations document name            /* if after all this operations document name
              is empty, let's use noname.html instead */               is empty, let's use noname.html instead */
           if (documentname[0] == EOS)            if (documentname[0] == EOS)
             strcat (ptr, "noname.html");              strcat (ptr, "noname.html");
           else            else
             strcat (ptr, documentname);              strcat (ptr, documentname);
         }          }
       TtaFreeMemory (documentname);        TtaFreeMemory (documentname);
       /* substitute invalid chars in file names by a _ */        /* substitute invalid chars in file names by a _ */
       n = strrchr(ptr,DIR_SEP);        n = strrchr(ptr,DIR_SEP);
       while (*n)        while (*n)
         {          {
           if (*n == '*' || *n == ',')            if (*n == '*' || *n == ',')
             *n = '_';              *n = '_';
           if ((unsigned char)*n >= 0x80) /* avoid non-ASCII */            if ((unsigned char)*n >= 0x80) /* avoid non-ASCII */
                   *n = 'A' + ((unsigned char)*n % 26);              *n = 'A' + ((unsigned char)*n % 26);
           n++;            n++;
         }          }
       /* restore the url */        /* restore the url */
       if (noFile)        if (noFile)
         url[len] = url_sep;          url[len] = url_sep;
       return (ptr);        return (ptr);
     }      }
   else    else
Line 1292  char *GetLocalPath (Document doc, char Line 1292  char *GetLocalPath (Document doc, char
 }  }
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
    ExtractTarget extract the target name from document nane.            ExtractTarget extract the target name from document nane.        
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 void ExtractTarget (char *aName, char *target)  void ExtractTarget (char *aName, char *target)
 {  {
    long int    lg, i;    long int    lg, i;
    char  *ptr;    char  *ptr;
    char  *oldptr;    char  *oldptr;
   
    if (!target || !aName)    if (!target || !aName)
      /* bad target */      /* bad target */
      return;      return;
   
    target[0] = EOS;    target[0] = EOS;
    lg = strlen (aName);    lg = strlen (aName);
    if (lg)    if (lg)
      {      {
         /* the name is not empty */        /* the name is not empty */
         oldptr = ptr = &aName[0];        oldptr = ptr = &aName[0];
         do        do
           {          {
              ptr = strrchr (oldptr, '#');            ptr = strrchr (oldptr, '#');
              if (ptr)            if (ptr)
                 oldptr = &ptr[1];              oldptr = &ptr[1];
           }          }
         while (ptr);        while (ptr);
   
         i = (long int) (oldptr) - (long int) (aName);   /* name length */        i = (long int) (oldptr) - (long int) (aName);     /* name length */
         if (i > 1)        if (i > 1)
           {          {
              aName[i - 1] = EOS;            aName[i - 1] = EOS;
              if (i != lg)            if (i != lg)
                 strcpy (target, oldptr);              strcpy (target, oldptr);
           }          }
      }      }
 }  }
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
    RemoveNewLines (text)    RemoveNewLines (text)
    Removes any '\n' chars that are found in text.     Removes any '\n' chars that are found in text. 
    Returns TRUE if it did the operation, FALSE otherwise.    Returns TRUE if it did the operation, FALSE otherwise.
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 ThotBool RemoveNewLines (char *text)  ThotBool RemoveNewLines (char *text)
 {  {
Line 1352  ThotBool RemoveNewLines (char *text) Line 1352  ThotBool RemoveNewLines (char *text)
   while (*src)    while (*src)
     {      {
       switch (*src)        switch (*src)
         {          {
         case '\n':          case '\n':
           /* don't copy the newline */            /* don't copy the newline */
           change = 1;            change = 1;
           break;            break;
         default:          default:
           *dest = *src;            *dest = *src;
           dest++;            dest++;
           break;            break;
         }          }
       src++;        src++;
     }      }
   /* copy the last EOS char */    /* copy the last EOS char */
Line 1371  ThotBool RemoveNewLines (char *text) Line 1371  ThotBool RemoveNewLines (char *text)
 }  }
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
    CleanCopyFileURL    CleanCopyFileURL
    Copies a file url from a src string to destination string.    Copies a file url from a src string to destination string.
    convertion says which type of convertion (none, %xx, URL_SEP into DIR_SEP    convertion says which type of convertion (none, %xx, URL_SEP into DIR_SEP
    we want to do).    we want to do).
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 static void CleanCopyFileURL (char *dest, char *src,  static void CleanCopyFileURL (char *dest, char *src,
                               ConvertionType convertion)                                ConvertionType convertion)
 {  {
   while (*src)    while (*src)
     {      {
       switch (*src)        switch (*src)
         {          {
 #ifdef _WINDOWS  #ifdef _WINDOWS
         case URL_SEP:          case URL_SEP:
           /* make DIR_SEP transformation */            /* make DIR_SEP transformation */
           if (convertion & AM_CONV_URL_SEP)            if (convertion & AM_CONV_URL_SEP)
             *dest = DIR_SEP;              *dest = DIR_SEP;
           else            else
             *dest = *src;              *dest = *src;
           dest++;            dest++;
           src++;            src++;
           break;            break;
 #endif /* _WINDOWS */  #endif /* _WINDOWS */
   
         case '%':          case '%':
           if (convertion & AM_CONV_PERCENT)            if (convertion & AM_CONV_PERCENT)
             {              {
               /* (code adapted from libwww's HTUnEscape function */                /* (code adapted from libwww's HTUnEscape function */
               src++;                src++;
               if (*src != EOS)                if (*src != EOS)
                 {                  {
                   *dest = UnEscapeChar (*src) * 16;                    *dest = UnEscapeChar (*src) * 16;
                   src++;                    src++;
                 }                  }
               if (*src != EOS)                if (*src != EOS)
                 {                  {
                   *dest = *dest + UnEscapeChar (*src);                    *dest = *dest + UnEscapeChar (*src);
                   src++;                    src++;
                 }                  }
               dest++;                dest++;
             }              }
           else            else
             {              {
               *dest = *src;                *dest = *src;
               dest++;                dest++;
               src++;                src++;
             }              }
           break;            break;
   
         default:          default:
           *dest = *src;            *dest = *src;
           dest++;            dest++;
           src++;            src++;
           break;            break;
         }          }
     }      }
   /* copy the EOS char */    /* copy the EOS char */
   *dest = *src;    *dest = *src;
 }  }
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
    NormalizeURL    NormalizeURL
    normalizes orgName according to a base associated with doc, and    normalizes orgName according to a base associated with doc, and
    following the standard URL format rules.    following the standard URL format rules.
    if doc is < 0, use as a base the URL of the document that contains    if doc is < 0, use as a base the URL of the document that contains
    (or contained) the elements that are now in the copy/cut buffer.    (or contained) the elements that are now in the copy/cut buffer.
    if doc is 0 and otherPath not NULL, normalizes orgName according to this    if doc is 0 and otherPath not NULL, normalizes orgName according to this
    other path.    other path.
    The function returns the new complete and normalized URL     The function returns the new complete and normalized URL 
    or file name path (newName) and the name of the document (docName).            or file name path (newName) and the name of the document (docName).        
    N.B. If the function can't find out what's the docName, it assigns    N.B. If the function can't find out what's the docName, it assigns
    the name "noname.html".    the name "noname.html".
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 void NormalizeURL (char *orgName, Document doc, char *newName,  void NormalizeURL (char *orgName, Document doc, char *newName,
                    char *docName, char *otherPath)                     char *docName, char *otherPath)
 {  {
    char          *basename;    char          *basename;
    char           tempOrgName[MAX_LENGTH];    char           tempOrgName[MAX_LENGTH];
    char          *ptr;    char          *ptr;
    char           used_sep;    char           used_sep;
    int            length;    int            length;
    ThotBool       check;    ThotBool       check;
   
 #ifdef _WINDOWS  #ifdef _WINDOWS
    int ndx;    int ndx;
 #endif /* _WINDOWS */  #endif /* _WINDOWS */
   
    if (!newName || !docName)    if (!newName || !docName)
       return;
   
     if (doc < 0)
       basename = TtaStrdup (SavedDocumentURL);
     else if (doc > 0)
       basename = GetBaseURL (doc);
     else if (otherPath != NULL)
       basename = TtaStrdup (otherPath);
     else
       basename = NULL;
   
     /*
      * Clean orgName
      * Make sure we have a complete orgName, without any leading or trailing
      * white spaces, or trailinbg new lines
      */
     ptr = orgName;
     /* skip leading white space and new line characters */
     while ((*ptr == SPACE || *ptr == EOL) && *ptr++ != EOS);
     strncpy (tempOrgName, ptr, MAX_LENGTH -1);
     tempOrgName[MAX_LENGTH -1] = EOS;
     /*
      * Make orgName a complete URL
      * If the URL does not include a protocol, then try to calculate
      * one using the doc's base element (if it exists),
      */
     if (tempOrgName[0] == EOS)
       {
         newName[0] = EOS;
         docName[0] = EOS;
         TtaFreeMemory (basename);
       return;        return;
       }
   
     /* clean trailing white space */
     length = strlen (tempOrgName) - 1;
     while (tempOrgName[length] == SPACE && tempOrgName[length] == EOL)
       {
         tempOrgName[length] = EOS;
         length--;
       }
   
    if (doc < 0)    /* remove extra dot (which dot???) */
      basename = TtaStrdup (SavedDocumentURL);    /* ugly, but faster than a strcmp */
    else if (doc > 0)    if (tempOrgName[length] == '.'
      basename = GetBaseURL (doc);        && (length == 0 || tempOrgName[length-1] != '.'))
    else if (otherPath != NULL)      tempOrgName[length] = EOS;
      basename = TtaStrdup (otherPath);  
    else    if (IsW3Path (tempOrgName))
      basename = NULL;      {
         /* the name is complete, go to the Sixth Step */
    /*        strcpy (newName, tempOrgName);
     * Clean orgName        SimplifyUrl (&newName);
     * Make sure we have a complete orgName, without any leading or trailing        /* verify if the URL has the form "protocol://server:port" */
     * white spaces, or trailinbg new lines        ptr = AmayaParseUrl (newName, "", AMAYA_PARSE_ACCESS |
     */                             AMAYA_PARSE_HOST |
    ptr = orgName;                             AMAYA_PARSE_PUNCTUATION);
    /* skip leading white space and new line characters */        if (ptr && !strcmp (ptr, newName))
    while ((*ptr == SPACE || *ptr == EOL) && *ptr++ != EOS);          /* it has this form, we complete it by adding a DIR_STR  */
    strncpy (tempOrgName, ptr, MAX_LENGTH -1);          strcat (newName, URL_STR);
    tempOrgName[MAX_LENGTH -1] = EOS;  
    /*        if (ptr)
     * Make orgName a complete URL          TtaFreeMemory (ptr);
     * If the URL does not include a protocol, then try to calculate      }
     * one using the doc's base element (if it exists),    else if (basename == NULL)
     */      /* the name is complete, go to the Sixth Step */
    if (tempOrgName[0] == EOS)      strcpy (newName, tempOrgName);
      {    else
        newName[0] = EOS;      {
        docName[0] = EOS;        /* Calculate the absolute URL, using the base or document URL */
        TtaFreeMemory (basename);  
        return;  
      }  
   
    /* clean trailing white space */  
    length = strlen (tempOrgName) - 1;  
    while (tempOrgName[length] == SPACE && tempOrgName[length] == EOL)  
      {  
        tempOrgName[length] = EOS;  
        length--;  
      }  
   
    /* remove extra dot (which dot???) */  
    /* ugly, but faster than a strcmp */  
    if (tempOrgName[length] == '.'  
        && (length == 0 || tempOrgName[length-1] != '.'))  
          tempOrgName[length] = EOS;  
   
    if (IsW3Path (tempOrgName))  
      {  
        /* the name is complete, go to the Sixth Step */  
        strcpy (newName, tempOrgName);  
        SimplifyUrl (&newName);  
        /* verify if the URL has the form "protocol://server:port" */  
        ptr = AmayaParseUrl (newName, "", AMAYA_PARSE_ACCESS |  
                                          AMAYA_PARSE_HOST |  
                                          AMAYA_PARSE_PUNCTUATION);  
        if (ptr && !strcmp (ptr, newName))  
          /* it has this form, we complete it by adding a DIR_STR  */  
          strcat (newName, URL_STR);  
   
        if (ptr)  
          TtaFreeMemory (ptr);  
      }  
    else if (basename == NULL)  
      /* the name is complete, go to the Sixth Step */  
      strcpy (newName, tempOrgName);  
    else  
      {  
        /* Calculate the absolute URL, using the base or document URL */  
 #ifdef _WINDOWS  #ifdef _WINDOWS
        if (!IsW3Path (basename))        if (!IsW3Path (basename))
          {          {
            length = strlen (tempOrgName);            length = strlen (tempOrgName);
            for (ndx = 0; ndx < length; ndx++)            for (ndx = 0; ndx < length; ndx++)
              if (tempOrgName [ndx] == '/')              if (tempOrgName [ndx] == '/')
                tempOrgName [ndx] = '\\';                tempOrgName [ndx] = '\\';
          }          }
 #endif /* _WINDOWS */  #endif /* _WINDOWS */
        ptr = AmayaParseUrl (tempOrgName, basename, AMAYA_PARSE_ALL);        ptr = AmayaParseUrl (tempOrgName, basename, AMAYA_PARSE_ALL);
        if (ptr)        if (ptr)
          {          {
            SimplifyUrl (&ptr);            SimplifyUrl (&ptr);
            strcpy (newName, ptr);            strcpy (newName, ptr);
            TtaFreeMemory (ptr);            TtaFreeMemory (ptr);
          }          }
        else        else
          newName[0] = EOS;          newName[0] = EOS;
      }      }
   
    TtaFreeMemory (basename);    TtaFreeMemory (basename);
    /*    /*
     * Prepare the docname that will refer to this ressource in the     * Prepare the docname that will refer to this ressource in the
     * .amaya directory. If the new URL finishes on DIR_SEP, then use     * .amaya directory. If the new URL finishes on DIR_SEP, then use
     * noname.html as a default ressource name     * noname.html as a default ressource name
    */     */
    if (newName[0] != EOS)    if (newName[0] != EOS)
      {      {
        length = strlen (newName) - 1;        length = strlen (newName) - 1;
        if (newName[length] == URL_SEP || newName[length] == DIR_SEP)        if (newName[length] == URL_SEP || newName[length] == DIR_SEP)
          {          {
            used_sep = newName[length];            used_sep = newName[length];
            check = TRUE;            check = TRUE;
            while (check)            while (check)
              {              {
                length--;                length--;
                while (length >= 0 && newName[length] != used_sep)                while (length >= 0 && newName[length] != used_sep)
                  length--;                  length--;
                if (!strncmp (&newName[length+1], "..", 2))                if (!strncmp (&newName[length+1], "..", 2))
                  {                  {
                    newName[length+1] = EOS;                    newName[length+1] = EOS;
                    /* remove also previous directory */                    /* remove also previous directory */
                    length--;                    length--;
                    while (length >= 0 && newName[length] != used_sep)                    while (length >= 0 && newName[length] != used_sep)
                      length--;                      length--;
                    if (strncmp (&newName[length+1], "//", 2))                    if (strncmp (&newName[length+1], "//", 2))
                      /* don't remove server name */                      /* don't remove server name */
                      newName[length+1] = EOS;                      newName[length+1] = EOS;
                  }                  }
                else if (!strncmp (&newName[length+1], ".", 1))                else if (!strncmp (&newName[length+1], ".", 1))
                  newName[length+1] = EOS;                  newName[length+1] = EOS;
                else                else
                  check = FALSE;                  check = FALSE;
              }              }
            /* docname was not comprised inside the URL, so let's */            /* docname was not comprised inside the URL, so let's */
            /* assign the default ressource name */            /* assign the default ressource name */
            strcpy (docName, "noname.html");            strcpy (docName, "noname.html");
          }          }
        else        else
          { /* docname is comprised inside the URL */          { /* docname is comprised inside the URL */
            while (length >= 0 && newName[length] != URL_SEP &&            while (length >= 0 && newName[length] != URL_SEP &&
                   newName[length] != DIR_SEP)                   newName[length] != DIR_SEP)
              length--;              length--;
            if (length < 0)            if (length < 0)
              strcpy (docName, newName);              strcpy (docName, newName);
            else            else
              strcpy (docName, &newName[length+1]);              strcpy (docName, &newName[length+1]);
          }          }
      }      }
    else    else
      docName[0] = EOS;      docName[0] = EOS;
 }   } 
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
Line 1611  ThotBool IsSameHost (const char *url1, c Line 1611  ThotBool IsSameHost (const char *url1, c
   ThotBool       result;    ThotBool       result;
   
   basename_ptr1 = AmayaParseUrl (url1, "",    basename_ptr1 = AmayaParseUrl (url1, "",
              AMAYA_PARSE_ACCESS | AMAYA_PARSE_HOST | AMAYA_PARSE_PUNCTUATION);                                   AMAYA_PARSE_ACCESS | AMAYA_PARSE_HOST | AMAYA_PARSE_PUNCTUATION);
   basename_ptr2 = AmayaParseUrl (url2, "",    basename_ptr2 = AmayaParseUrl (url2, "",
              AMAYA_PARSE_ACCESS | AMAYA_PARSE_HOST | AMAYA_PARSE_PUNCTUATION);                                   AMAYA_PARSE_ACCESS | AMAYA_PARSE_HOST | AMAYA_PARSE_PUNCTUATION);
   
   if (strcmp (basename_ptr1, basename_ptr2))    if (strcmp (basename_ptr1, basename_ptr2))
     result = FALSE;      result = FALSE;
Line 1631  ThotBool IsSameHost (const char *url1, c Line 1631  ThotBool IsSameHost (const char *url1, c
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 ThotBool HasKnownFileSuffix (const char *path)  ThotBool HasKnownFileSuffix (const char *path)
 {  {
    char       *root;    char       *root;
    char        temppath[MAX_LENGTH];    char        temppath[MAX_LENGTH];
    char        suffix[MAX_LENGTH];    char        suffix[MAX_LENGTH];
   
    if (!path || path[0] == EOS || path[strlen(path)] == DIR_SEP)    if (!path || path[0] == EOS || path[strlen(path)] == DIR_SEP)
      return (FALSE);      return (FALSE);
   
    root = AmayaParseUrl(path, "", AMAYA_PARSE_PATH | AMAYA_PARSE_PUNCTUATION);    root = AmayaParseUrl(path, "", AMAYA_PARSE_PATH | AMAYA_PARSE_PUNCTUATION);
   
    if (root)     if (root) 
      {      {
        strcpy (temppath, root);        strcpy (temppath, root);
        TtaFreeMemory (root);        TtaFreeMemory (root);
        /* Get the suffix */        /* Get the suffix */
        TtaExtractSuffix (temppath, suffix);         TtaExtractSuffix (temppath, suffix); 
   
        if( suffix[0] == EOS)        if( suffix[0] == EOS)
          /* no suffix */          /* no suffix */
          return (FALSE);          return (FALSE);
   
        /* Normalize the suffix */        /* Normalize the suffix */
        ConvertToLowerCase (suffix);        ConvertToLowerCase (suffix);
   
        if (!strcmp (suffix, "gz"))        if (!strcmp (suffix, "gz"))
          /* skip the compressed suffix */          /* skip the compressed suffix */
          {          {
          TtaExtractSuffix (temppath, suffix);            TtaExtractSuffix (temppath, suffix);
          if(suffix[0] == EOS)            if(suffix[0] == EOS)
            /* no suffix */              /* no suffix */
            return (FALSE);              return (FALSE);
          /* Normalize the suffix */            /* Normalize the suffix */
          ConvertToLowerCase (suffix);            ConvertToLowerCase (suffix);
          }          }
   
        if (strcmp (suffix, "gif") &&        if (strcmp (suffix, "gif") &&
            strcmp (suffix, "xbm") &&            strcmp (suffix, "xbm") &&
            strcmp (suffix, "xpm") &&            strcmp (suffix, "xpm") &&
            strcmp (suffix, "jpg") &&            strcmp (suffix, "jpg") &&
            strcmp (suffix, "pdf") &&            strcmp (suffix, "pdf") &&
            strcmp (suffix, "png") &&            strcmp (suffix, "png") &&
            strcmp (suffix, "tgz") &&            strcmp (suffix, "tgz") &&
            strcmp (suffix, "xpg") &&            strcmp (suffix, "xpg") &&
            strcmp (suffix, "xpd") &&            strcmp (suffix, "xpd") &&
            strcmp (suffix, "ps") &&            strcmp (suffix, "ps") &&
            strcmp (suffix, "au") &&            strcmp (suffix, "au") &&
            strcmp (suffix, "html") &&            strcmp (suffix, "html") &&
            strcmp (suffix, "htm") &&            strcmp (suffix, "htm") &&
            strcmp (suffix, "shtml") &&            strcmp (suffix, "shtml") &&
            strcmp (suffix, "xht") &&            strcmp (suffix, "xht") &&
            strcmp (suffix, "xhtm") &&            strcmp (suffix, "xhtm") &&
            strcmp (suffix, "xhtml") &&            strcmp (suffix, "xhtml") &&
            strcmp (suffix, "txt") &&            strcmp (suffix, "txt") &&
            strcmp (suffix, "css") &&            strcmp (suffix, "css") &&
            strcmp (suffix, "eps"))            strcmp (suffix, "eps"))
          return (FALSE);          return (FALSE);
        else        else
          return (TRUE);          return (TRUE);
      }      }
    else    else
      return (FALSE);      return (FALSE);
 }  }
   
   
Line 1724  void ChopURL (char *outputURL, const cha Line 1724  void ChopURL (char *outputURL, const cha
   
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
    scan    scan
         Scan a filename for its constituents    Scan a filename for its constituents
         -----------------------------------    -----------------------------------
       
    On entry,    On entry,
         name    points to a document name which may be incomplete.    name  points to a document name which may be incomplete.
    On exit,    On exit,
         absolute or relative may be nonzero (but not both).    absolute or relative may be nonzero (but not both).
         host, fragment and access may be nonzero if they were specified.    host, fragment and access may be nonzero if they were specified.
         Any which are nonzero point to zero terminated strings.    Any which are nonzero point to zero terminated strings.
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 static void scan (char *name, HTURI *parts)  static void scan (char *name, HTURI *parts)
 {  {
Line 1751  static void scan (char *name, HTURI *par Line 1751  static void scan (char *name, HTURI *par
   for (p=name; *p; p++)    for (p=name; *p; p++)
     {      {
       if (*p == URL_SEP || *p == DIR_SEP || *p == '#' || *p == '?')        if (*p == URL_SEP || *p == DIR_SEP || *p == '#' || *p == '?')
         break;          break;
       if (*p == ':')        if (*p == ':')
         {          {
           *p = 0;            *p = 0;
           parts->access = after_access; /* Scheme has been specified */            parts->access = after_access; /* Scheme has been specified */
   
           /* The combination of gcc, the "-O" flag and the HP platform is            /* The combination of gcc, the "-O" flag and the HP platform is
              unhealthy. The following three lines is a quick & dirty fix, but is               unhealthy. The following three lines is a quick & dirty fix, but is
              not recommended. Rather, turn off "-O". */               not recommended. Rather, turn off "-O". */
   
           /*            after_access = p;*/            /*            after_access = p;*/
           /*            while (*after_access == 0)*/            /*            while (*after_access == 0)*/
           /*                after_access++;*/            /*                after_access++;*/
           after_access = p+1;            after_access = p+1;
           if (!strcasecmp("URL", parts->access))            if (!strcasecmp("URL", parts->access))
             /* Ignore IETF's URL: pre-prefix */              /* Ignore IETF's URL: pre-prefix */
             parts->access = NULL;              parts->access = NULL;
           else            else
             break;              break;
         }          }
     }      }
           
     p = after_access;    p = after_access;
     if (*p == URL_SEP || *p == DIR_SEP)    if (*p == URL_SEP || *p == DIR_SEP)
       {      {
         if (p[1] == URL_SEP)        if (p[1] == URL_SEP)
           {          {
             parts->host = p+2;          /* host has been specified      */            parts->host = p+2;            /* host has been specified      */
             *p = 0;                     /* Terminate access             */            *p = 0;                       /* Terminate access             */
             /* look for end of host name if any */            /* look for end of host name if any */
             p = strchr (parts->host, URL_SEP);            p = strchr (parts->host, URL_SEP);
             if (p)            if (p)
               {              {
                 *p = EOS;                       /* Terminate host */                *p = EOS;                 /* Terminate host */
                 parts->absolute = p+1;          /* Root has been found */                parts->absolute = p+1;            /* Root has been found */
               }              }
           }          }
         else        else
           /* Root found but no host */          /* Root found but no host */
           parts->absolute = p+1;          parts->absolute = p+1;
       }      }
     else    else
       {      {
         parts->relative = (*after_access) ? after_access : 0; /* zero for "" */        parts->relative = (*after_access) ? after_access : 0; /* zero for "" */
       }      }
 }  }
   
   
Line 1806  static void scan (char *name, HTURI *par Line 1806  static void scan (char *name, HTURI *par
   substituting bits from the related name where necessary.    substituting bits from the related name where necessary.
       
   On entry,    On entry,
         aName           A filename given    aName         A filename given
         relatedName     A name relative to which aName is to be parsed. Give    relatedName     A name relative to which aName is to be parsed. Give
                         it an empty string if aName is absolute.    it an empty string if aName is absolute.
         wanted          A mask for the bits which are wanted.    wanted          A mask for the bits which are wanted.
       
   On exit,    On exit,
         returns         A pointer to a malloc'd string which MUST BE FREED    returns               A pointer to a malloc'd string which MUST BE FREED
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 char   *AmayaParseUrl (const char *aName, char *relatedName, int wanted)  char   *AmayaParseUrl (const char *aName, char *relatedName, int wanted)
 {  {
Line 1857  char   *AmayaParseUrl (const char *aName Line 1857  char   *AmayaParseUrl (const char *aName
   if (wanted & AMAYA_PARSE_ACCESS)    if (wanted & AMAYA_PARSE_ACCESS)
     if (access)      if (access)
       {        {
         strcat (result, access);          strcat (result, access);
         if(wanted & AMAYA_PARSE_PUNCTUATION)          if(wanted & AMAYA_PARSE_PUNCTUATION)
                 strcat (result, ":");            strcat (result, ":");
       }        }
       
   if (given.access && related.access)    if (given.access && related.access)
     /* If different, inherit nothing. */      /* If different, inherit nothing. */
     if (strcmp (given.access, related.access) != 0)      if (strcmp (given.access, related.access) != 0)
       {        {
         related.host = 0;          related.host = 0;
         related.absolute = 0;          related.absolute = 0;
         related.relative = 0;          related.relative = 0;
         related.fragment = 0;          related.fragment = 0;
       }        }
       
   if (wanted & AMAYA_PARSE_HOST)    if (wanted & AMAYA_PARSE_HOST)
     if(given.host || related.host)      if(given.host || related.host)
       {        {
         if(wanted & AMAYA_PARSE_PUNCTUATION)          if(wanted & AMAYA_PARSE_PUNCTUATION)
           strcat (result, "//");            strcat (result, "//");
         strcat (result, given.host ? given.host : related.host);          strcat (result, given.host ? given.host : related.host);
       }        }
       
   if (given.host && related.host)    if (given.host && related.host)
     /* If different hosts, inherit no path. */      /* If different hosts, inherit no path. */
     if (strcmp (given.host, related.host) != 0)      if (strcmp (given.host, related.host) != 0)
       {        {
         related.absolute = 0;          related.absolute = 0;
         related.relative = 0;          related.relative = 0;
         related.fragment = 0;          related.fragment = 0;
       }        }
       
   if (wanted & AMAYA_PARSE_PATH)    if (wanted & AMAYA_PARSE_PATH)
     {      {
       if (given.absolute)        if (given.absolute)
         {          {
           /* All is given */            /* All is given */
           if (wanted & AMAYA_PARSE_PUNCTUATION)            if (wanted & AMAYA_PARSE_PUNCTUATION)
             strcat (result, used_str);              strcat (result, used_str);
           strcat (result, given.absolute);            strcat (result, given.absolute);
         }          }
       else if (related.absolute)        else if (related.absolute)
         {          {
           /* Adopt path not name */            /* Adopt path not name */
           strcat (result, used_str);            strcat (result, used_str);
           strcat (result, related.absolute);            strcat (result, related.absolute);
           if (given.relative)            if (given.relative)
             {              {
               /* Search part? */                /* Search part? */
               p = strchr (result, '?');                p = strchr (result, '?');
               if (!p)                if (!p)
                 p=result+strlen(result)-1;                  p=result+strlen(result)-1;
               for (; *p!=used_sep; p--);        /* last / */                for (; *p!=used_sep; p--);        /* last / */
               /* Remove filename */                /* Remove filename */
               p[1]=0;                p[1]=0;
               /* Add given one */                /* Add given one */
               strcat (result, given.relative);                strcat (result, given.relative);
             }              }
         }          }
       else if (given.relative)        else if (given.relative)
         /* what we've got */          /* what we've got */
         strcat (result, given.relative);          strcat (result, given.relative);
       else if (related.relative)        else if (related.relative)
         strcat (result, related.relative);          strcat (result, related.relative);
       else        else
         /* No inheritance */          /* No inheritance */
         strcat (result, used_str);          strcat (result, used_str);
     }      }
       
   if (wanted & AMAYA_PARSE_ANCHOR)    if (wanted & AMAYA_PARSE_ANCHOR)
     if (given.fragment || related.fragment)      if (given.fragment || related.fragment)
       {        {
         if (given.absolute && given.fragment)          if (given.absolute && given.fragment)
           {            {
             /*Fixes for relURLs...*/              /*Fixes for relURLs...*/
             if (wanted & AMAYA_PARSE_PUNCTUATION)              if (wanted & AMAYA_PARSE_PUNCTUATION)
               strcat (result, "#");                strcat (result, "#");
             strcat (result, given.fragment);               strcat (result, given.fragment); 
           }            }
         else if (!(given.absolute) && !(given.fragment))          else if (!(given.absolute) && !(given.fragment))
           strcat (result, "");            strcat (result, "");
         else          else
           {            {
            if (wanted & AMAYA_PARSE_PUNCTUATION)              if (wanted & AMAYA_PARSE_PUNCTUATION)
               strcat (result, "#");                strcat (result, "#");
            strcat (result, given.fragment ? given.fragment : related.fragment);               strcat (result, given.fragment ? given.fragment : related.fragment); 
           }            }
       }        }
   len = strlen (result);    len = strlen (result);
   if ((return_value = (char *)TtaGetMemory (len + 1)) != NULL)    if ((return_value = (char *)TtaGetMemory (len + 1)) != NULL)
Line 1952  char   *AmayaParseUrl (const char *aName Line 1952  char   *AmayaParseUrl (const char *aName
 }  }
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
      HTCanon    HTCanon
         Canonicalizes the URL in the following manner starting from the host    Canonicalizes the URL in the following manner starting from the host
         pointer:    pointer:
       
         1) The host name is converted to lowercase    1) The host name is converted to lowercase
         2) Chop off port if `:80' (http), `:70' (gopher), or `:21' (ftp)    2) Chop off port if `:80' (http), `:70' (gopher), or `:21' (ftp)
       
         Return: OK      The position of the current path part of the URL    Return: OK    The position of the current path part of the URL
                         which might be the old one or a new one.    which might be the old one or a new one.
       
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 static char   *HTCanon (char **filename, char *host)  static char   *HTCanon (char **filename, char *host)
 {  {
     char   *newname = NULL;    char   *newname = NULL;
     char    used_sep;    char    used_sep;
     char   *path;    char   *path;
     char   *strptr;    char   *strptr;
     char   *port;    char   *port;
     char   *access = host-3;    char   *access = host-3;
       
      if (*filename && strchr (*filename, URL_SEP))    if (*filename && strchr (*filename, URL_SEP))
          used_sep = URL_SEP;      used_sep = URL_SEP;
      else    else
          used_sep = DIR_SEP;      used_sep = DIR_SEP;
       
     while (access > *filename && *(access - 1) != used_sep) /* Find access method */    while (access > *filename && *(access - 1) != used_sep) /* Find access method */
         access--;      access--;
     if ((path = strchr (host, used_sep)) == NULL)               /* Find path */    if ((path = strchr (host, used_sep)) == NULL)         /* Find path */
        path = host + strlen (host);      path = host + strlen (host);
     if ((strptr = strchr (host, '@')) != NULL && strptr < path)    /* UserId */    if ((strptr = strchr (host, '@')) != NULL && strptr < path)      /* UserId */
        host = strptr;      host = strptr;
     if ((port = strchr (host, ':')) != NULL && port > path)   /* Port number */    if ((port = strchr (host, ':')) != NULL && port > path)   /* Port number */
        port = NULL;      port = NULL;
   
     strptr = host;                                  /* Convert to lower-case */    strptr = host;                                    /* Convert to lower-case */
     while (strptr < path)    while (strptr < path)
       {      {
          *strptr = tolower (*strptr);        *strptr = tolower (*strptr);
          strptr++;        strptr++;
       }  
       
     /* Does the URL contain a full domain name? This also works for a  
        numerical host name. The domain name is already made lower-case  
        and without a trailing dot. */  
     {  
       char  *dot = port ? port : path;  
       if (dot > *filename && *--dot == '.')  
         {  
           char  *orig = dot;  
           char  *dest = dot + 1;  
           while ((*orig++ = *dest++));  
             if (port) port--;  
           path--;  
         }  
     }      }
     /* Chop off port if `:', `:80' (http), `:70' (gopher), or `:21' (ftp) */      
     if (port)    /* Does the URL contain a full domain name? This also works for a
        numerical host name. The domain name is already made lower-case
        and without a trailing dot. */
     {
       char  *dot = port ? port : path;
       if (dot > *filename && *--dot == '.')
       {        {
         if (!*(port+1) || *(port+1) == used_sep)          char  *orig = dot;
           {          char  *dest = dot + 1;
             if (!newname)          while ((*orig++ = *dest++));
               {          if (port) port--;
                 char  *orig = port;           path--;
                 char  *dest = port + 1;  
                 while ((*orig++ = *dest++));  
               }  
           }  
         else if ((!strncmp (access, "http", 4)   &&  
              (*(port + 1) == '8'                    &&   
              *(port+2) == '0'                       &&   
              (*(port+3) == used_sep || !*(port + 3))))       ||  
              (!strncmp (access, "gopher", 6) &&  
              (*(port+1) == '7'                      &&   
              *(port+2) == '0'                       &&   
              (*(port+3) == used_sep || !*(port+3))))         ||  
              (!strncmp (access, "ftp", 3)    &&  
              (*(port+1) == '2'                      &&   
              *(port + 2) == '1'                     &&   
              (*(port+3) == used_sep || !*(port+3))))) {  
           if (!newname)  
             {  
               char  *orig = port;   
               char  *dest = port + 3;  
               while((*orig++ = *dest++));  
               /* Update path position, Henry Minsky */  
               path -= 3;  
             }  
         }  
         else if (newname)  
           strncat (newname, port, (int) (path - port));  
       }        }
     }
     if (newname)    /* Chop off port if `:', `:80' (http), `:70' (gopher), or `:21' (ftp) */
       {    if (port)
         char  *newpath = newname + strlen (newname);      {
         strcat (newname, path);        if (!*(port+1) || *(port+1) == used_sep)
         path = newpath;          {
         /* Free old copy */            if (!newname)
         TtaFreeMemory(*filename);              {
         *filename = newname;                char  *orig = port; 
                 char  *dest = port + 1;
                 while ((*orig++ = *dest++));
               }
           }
         else if ((!strncmp (access, "http", 4)   &&
                   (*(port + 1) == '8'                    && 
                    *(port+2) == '0'                       && 
                    (*(port+3) == used_sep || !*(port + 3))))       ||
                  (!strncmp (access, "gopher", 6) &&
                   (*(port+1) == '7'                      && 
                    *(port+2) == '0'                       && 
                    (*(port+3) == used_sep || !*(port+3))))         ||
                  (!strncmp (access, "ftp", 3)    &&
                   (*(port+1) == '2'                      && 
                    *(port + 2) == '1'                     && 
                    (*(port+3) == used_sep || !*(port+3))))) {
           if (!newname)
             {
               char  *orig = port; 
               char  *dest = port + 3;
               while((*orig++ = *dest++));
               /* Update path position, Henry Minsky */
               path -= 3;
             }
       }        }
     return path;        else if (newname)
           strncat (newname, port, (int) (path - port));
       }
   
     if (newname)
       {
         char  *newpath = newname + strlen (newname);
         strcat (newname, path);
         path = newpath;
         /* Free old copy */
         TtaFreeMemory(*filename);
         *filename = newname;
       }
     return path;
 }  }
   
   
Line 2064  static char   *HTCanon (char **filename, Line 2064  static char   *HTCanon (char **filename,
   Simplification helps us recognize duplicate URIs.     Simplification helps us recognize duplicate URIs. 
       
   Thus,         /etc/junk/../fred       becomes /etc/fred    Thus,         /etc/junk/../fred       becomes /etc/fred
                 /etc/junk/./fred        becomes /etc/junk/fred    /etc/junk/./fred      becomes /etc/junk/fred
       
   but we should NOT change    but we should NOT change
                 http://fred.xxx.edu/../..    http://fred.xxx.edu/../..
       
         or      ../../albert.html    or    ../../albert.html
       
   In order to avoid empty URLs the following URLs become:    In order to avoid empty URLs the following URLs become:
       
                 /fred/..                becomes /fred/..    /fred/..              becomes /fred/..
                 /fred/././..            becomes /fred/..    /fred/././..          becomes /fred/..
                 /fred/.././junk/.././   becomes /fred/..    /fred/.././junk/.././ becomes /fred/..
       
   If more than one set of `://' is found (several proxies in cascade) then    If more than one set of `://' is found (several proxies in cascade) then
   only the part after the last `://' is simplified.    only the part after the last `://' is simplified.
Line 2092  void         SimplifyUrl (char **url) Line 2092  void         SimplifyUrl (char **url)
   
   char      used_sep;    char      used_sep;
   ThotBool ddot_simplify; /* used to desactivate the double dot simplifcation:    ThotBool ddot_simplify; /* used to desactivate the double dot simplifcation:
                              something/../ simplification in relative URLs when they start with a ../ */                               something/../ simplification in relative URLs when they start with a ../ */
   
   if (!url || !*url)    if (!url || !*url)
     return;      return;
   
   if (strchr (*url, URL_SEP))    if (strchr (*url, URL_SEP))
       used_sep = URL_SEP;      used_sep = URL_SEP;
   else    else
       used_sep = DIR_SEP;      used_sep = DIR_SEP;
   
   /* should we simplify double dot? */    /* should we simplify double dot? */
   path = *url;    path = *url;
Line 2115  void         SimplifyUrl (char **url) Line 2115  void         SimplifyUrl (char **url)
       /* Find host name */        /* Find host name */
       access = *url;        access = *url;
       while (access < path && (*access = tolower (*access)))        while (access < path && (*access = tolower (*access)))
             access++;          access++;
       path += 3;        path += 3;
       while ((newptr = strstr (path, "://")) != NULL)        while ((newptr = strstr (path, "://")) != NULL)
             /* For proxies */          /* For proxies */
             path = newptr + 3;          path = newptr + 3;
      /* We have a host name */        /* We have a host name */
       path = HTCanon (url, path);        path = HTCanon (url, path);
     }      }
   else if ((path = strstr (*url, ":/")) != NULL)    else if ((path = strstr (*url, ":/")) != NULL)
Line 2139  void         SimplifyUrl (char **url) Line 2139  void         SimplifyUrl (char **url)
     {      {
       newptr = strchr (path+5, '@');        newptr = strchr (path+5, '@');
       if (!newptr)        if (!newptr)
         newptr = path + 5;          newptr = path + 5;
       while (*newptr)        while (*newptr)
         {          {
           /* Make group or host lower case */            /* Make group or host lower case */
           *newptr = tolower (*newptr);            *newptr = tolower (*newptr);
           newptr++;            newptr++;
         }          }
       /* Doesn't need to do any more */        /* Doesn't need to do any more */
       return;        return;
     }      }
Line 2155  void         SimplifyUrl (char **url) Line 2155  void         SimplifyUrl (char **url)
   if (path != *url && *p == used_sep && *path == used_sep)    if (path != *url && *p == used_sep && *path == used_sep)
     {      {
       while (*path == used_sep)        while (*path == used_sep)
         {          {
           orig = path;            orig = path;
           dest = path + 1;            dest = path + 1;
           while ((*orig++ = *dest++));  /* Remove multiple /'s */            while ((*orig++ = *dest++));  /* Remove multiple /'s */
           end = orig-1;            end = orig-1;
         }          }
     }      }
   
   if (path)    if (path)
     {      {
       if (!((end = strchr (path, ';')) || (end = strchr (path, '?')) ||        if (!((end = strchr (path, ';')) || (end = strchr (path, '?')) ||
             (end = strchr (path, '#'))))              (end = strchr (path, '#'))))
         end = path + strlen (path);          end = path + strlen (path);
               
       /* Parse string second time to simplify */        /* Parse string second time to simplify */
       p = path;        p = path;
       while (p < end)        while (p < end)
         {          {
           /* if we're pointing to a char, it's safe to reactivate the             /* if we're pointing to a char, it's safe to reactivate the 
              ../ convertion */               ../ convertion */
           if (!ddot_simplify && *p != '.' && *p != used_sep)            if (!ddot_simplify && *p != '.' && *p != used_sep)
             ddot_simplify = TRUE;              ddot_simplify = TRUE;
   
           if (*p==used_sep)            if (*p==used_sep)
             {              {
               if (p > *url && *(p+1) == '.' && (*(p+2) == used_sep || !*(p+2)))                if (p > *url && *(p+1) == '.' && (*(p+2) == used_sep || !*(p+2)))
                 {                  {
                   orig = p + 1;                    orig = p + 1;
                   dest = (*(p+2) != used_sep) ? p+2 : p+3;                    dest = (*(p+2) != used_sep) ? p+2 : p+3;
                   while ((*orig++ = *dest++)); /* Remove a used_sep and a dot*/                    while ((*orig++ = *dest++)); /* Remove a used_sep and a dot*/
                   end = orig - 1;                    end = orig - 1;
                 }                  }
               else if (ddot_simplify && *(p+1) == '.' && *(p+2) == '.'                 else if (ddot_simplify && *(p+1) == '.' && *(p+2) == '.' 
                        && (*(p+3) == used_sep || !*(p+3)))                         && (*(p+3) == used_sep || !*(p+3)))
                 {                  {
                   newptr = p;                    newptr = p;
                   while (newptr>path && *--newptr!=used_sep); /* prev used_sep */                    while (newptr>path && *--newptr!=used_sep); /* prev used_sep */
                   if (*newptr == used_sep)                    if (*newptr == used_sep)
                     orig = newptr + 1;                      orig = newptr + 1;
                   else                    else
                     orig = newptr;                      orig = newptr;
   
                   dest = (*(p+3) != used_sep) ? p+3 : p+4;                    dest = (*(p+3) != used_sep) ? p+3 : p+4;
                   while ((*orig++ = *dest++)); /* Remove /xxx/.. */                    while ((*orig++ = *dest++)); /* Remove /xxx/.. */
                   end = orig-1;                    end = orig-1;
                   /* Start again with prev slash */                    /* Start again with prev slash */
                   p = newptr;                    p = newptr;
                 }                  }
               else if (*(p+1) == used_sep)                else if (*(p+1) == used_sep)
                 {                  {
                   while (*(p+1) == used_sep)                    while (*(p+1) == used_sep)
                     {                      {
                       orig = p;                        orig = p;
                       dest = p + 1;                        dest = p + 1;
                       while ((*orig++ = *dest++));  /* Remove multiple /'s */                        while ((*orig++ = *dest++));  /* Remove multiple /'s */
                       end = orig-1;                        end = orig-1;
                     }                      }
                 }                  }
               else                else
                 p++;                  p++;
             }              }
           else            else
             p++;              p++;
         }          }
     }      }
     /*    /*
     **  Check for host/../.. kind of things    **  Check for host/../.. kind of things
     */    */
     if (*path == used_sep && *(path+1) == '.' && *(path+2) == '.'     if (*path == used_sep && *(path+1) == '.' && *(path+2) == '.' 
         && (!*(path+3) || *(path+3) == used_sep))        && (!*(path+3) || *(path+3) == used_sep))
         *(path+1) = EOS;      *(path+1) = EOS;
   return;    return;
 }  }
   
   
 /*----------------------------------------------------------------------  /*----------------------------------------------------------------------
    NormalizeFile normalizes local names.                                 NormalizeFile normalizes local names.                             
    Return TRUE if target and src differ.                               Return TRUE if target and src differ.                           
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 ThotBool NormalizeFile (char *src, char *target, ConvertionType convertion)  ThotBool NormalizeFile (char *src, char *target, ConvertionType convertion)
 {  {
 #ifndef _WINDOWS  #ifndef _WINDOWS
    char             *s;    char             *s;
    int               i;    int               i;
 #endif /* _WINDOWS */  #endif /* _WINDOWS */
    ThotBool          change;    ThotBool          change;
    int               start_index; /* the first char that we'll copy */    int               start_index; /* the first char that we'll copy */
   
    change = FALSE;    change = FALSE;
    start_index = 0;    start_index = 0;
   
    if (!src || src[0] == EOS)    if (!src || src[0] == EOS)
      {      {
        target[0] = EOS;        target[0] = EOS;
        return FALSE;        return FALSE;
      }      }
   
    /* @@ do I need file: or file:/ here? */    /* @@ do I need file: or file:/ here? */
    if (strncmp (src, "file:", 5) == 0)    if (strncmp (src, "file:", 5) == 0)
      {      {
        /* remove the prefix file: */        /* remove the prefix file: */
        start_index += 5;        start_index += 5;
         
        /* remove the localhost prefix */        /* remove the localhost prefix */
        if (strncmp (&src[start_index], "//localhost/", 12) == 0)        if (strncmp (&src[start_index], "//localhost/", 12) == 0)
            start_index += 11;          start_index += 11;
                 
        /* remove the first two slashes in / / /path */        /* remove the first two slashes in / / /path */
        while (src[start_index] &&        while (src[start_index] &&
               src[start_index] == '/'                src[start_index] == '/' 
               && src[start_index + 1] == '/')               && src[start_index + 1] == '/')
          start_index++;          start_index++;
   
 #ifdef _WINDOWS  #ifdef _WINDOWS
        /* remove any extra slash before the drive name */        /* remove any extra slash before the drive name */
        if (src[start_index] == '/'        if (src[start_index] == '/'
            &&src[start_index+2] == ':')            &&src[start_index+2] == ':')
          start_index++;          start_index++;
 #endif /* _WINDOWS */  #endif /* _WINDOWS */
   
        if (src[start_index] == EOS)        if (src[start_index] == EOS)
        /* if there's nothing afterwards, add a DIR_STR */          /* if there's nothing afterwards, add a DIR_STR */
          strcpy (target, DIR_STR);          strcpy (target, DIR_STR);
        else        else
          /* as we're inside a file: URL, we'll apply all the convertions          /* as we're inside a file: URL, we'll apply all the convertions
             we know */             we know */
          CleanCopyFileURL (target, &src[start_index], AM_CONV_ALL);          CleanCopyFileURL (target, &src[start_index], AM_CONV_ALL);
   
        change = TRUE;        change = TRUE;
      }      }
    else if (convertion != AM_CONV_NONE)    else if (convertion != AM_CONV_NONE)
      {      {
        /* we are following a "local" relative link, we do all the        /* we are following a "local" relative link, we do all the
           convertions except for the HOME_DIR ~ one */           convertions except for the HOME_DIR ~ one */
        CleanCopyFileURL (target, src, convertion);        CleanCopyFileURL (target, src, convertion);
      }      }
 #ifndef _WINDOWS  #ifndef _WINDOWS
    else if (src[0] == '~')    else if (src[0] == '~')
      {      {
        /* it must be a URL typed in a text input field */        /* it must be a URL typed in a text input field */
        /* do the HOME_DIR ~ substitution */        /* do the HOME_DIR ~ substitution */
         s = TtaGetEnvString ("HOME");        s = TtaGetEnvString ("HOME");
         strcpy (target, s);        strcpy (target, s);
 #if 0  #if 0
         /* JK: invalidated this part of the code as it's simpler        /* JK: invalidated this part of the code as it's simpler
            to add the DIR_SEP whenever we have something to add           to add the DIR_SEP whenever we have something to add
            to the path rather than adding it systematically */           to the path rather than adding it systematically */
         if (src[1] != DIR_SEP)        if (src[1] != DIR_SEP)
           strcat (target, DIR_STR);          strcat (target, DIR_STR);
 #endif  #endif
         i = strlen (target);        i = strlen (target);
         strcpy (&target[i], &src[1]);        strcpy (&target[i], &src[1]);
         change = TRUE;        change = TRUE;
      }      }
 #endif /* _WINDOWS */  #endif /* _WINDOWS */
    else    else
    /* leave it as it is */      /* leave it as it is */
      strcpy (target, src);      strcpy (target, src);
         
    /* remove /../ and /./ */    /* remove /../ and /./ */
    SimplifyUrl (&target);    SimplifyUrl (&target);
    if (!change)    if (!change)
      change = (strcmp (src, target) != 0);      change = (strcmp (src, target) != 0);
    return (change);    return (change);
 }  }
   
   
Line 2330  ThotBool NormalizeFile (char *src, char Line 2330  ThotBool NormalizeFile (char *src, char
   address is retured.    address is retured.
       
   On entry,    On entry,
         Both names must be absolute, fully qualified names of nodes    Both names must be absolute, fully qualified names of nodes
         (no fragment bits)    (no fragment bits)
       
   On exit,    On exit,
         The return result points to a newly allocated name which, if    The return result points to a newly allocated name which, if
         parsed by AmayaParseUrl relative to relatedName, will yield aName.    parsed by AmayaParseUrl relative to relatedName, will yield aName.
         The caller is responsible for freeing the resulting name later.    The caller is responsible for freeing the resulting name later.
   ----------------------------------------------------------------------*/    ----------------------------------------------------------------------*/
 char      *MakeRelativeURL (char *aName, char *relatedName)  char      *MakeRelativeURL (char *aName, char *relatedName)
 {  {
Line 2363  char      *MakeRelativeURL (char *aName, Line 2363  char      *MakeRelativeURL (char *aName,
     {      {
       /* Find extent of match */        /* Find extent of match */
       if (*p == ':')        if (*p == ':')
           {          {
                 after_access = p + 1;            after_access = p + 1;
 #ifdef _WINDOWS  #ifdef _WINDOWS
             if (len == 1)            if (len == 1)
                 {              {
               /* it's a local Windows path like c:... */                /* it's a local Windows path like c:... */
               slashes+=2;                slashes+=2;
                 }              }
 #endif /* _WINDOWS */  #endif /* _WINDOWS */
           }          }
       if (*p == DIR_SEP)        if (*p == DIR_SEP)
           {          {
             /* memorize the last slash position and count them */            /* memorize the last slash position and count them */
             last_slash = p;            last_slash = p;
             slashes++;            slashes++;
           }          }
     }      }
           
   /* q, p point to the first non-matching character or zero */    /* q, p point to the first non-matching character or zero */
Line 2388  char      *MakeRelativeURL (char *aName, Line 2388  char      *MakeRelativeURL (char *aName,
       /* exactly the right length */        /* exactly the right length */
       len = strlen (p);        len = strlen (p);
       if ((return_value = (char *)TtaGetMemory (len + 1)) != NULL)        if ((return_value = (char *)TtaGetMemory (len + 1)) != NULL)
         strcpy (return_value, p);          strcpy (return_value, p);
     }      }
   else if ((slashes < 2 && after_access == NULL)    else if ((slashes < 2 && after_access == NULL)
       || (slashes < 3 && after_access != NULL))             || (slashes < 3 && after_access != NULL))
    {      {
       /* Two names whitout common path */        /* Two names whitout common path */
       /* exactly the right length */        /* exactly the right length */
       len = strlen (aName);        len = strlen (aName);
       if ((return_value = (char *)TtaGetMemory (len + 1)) != NULL)        if ((return_value = (char *)TtaGetMemory (len + 1)) != NULL)
         strcpy (return_value, aName);          strcpy (return_value, aName);
     }      }
   else    else
     {      {
       /* Some path in common */        /* Some path in common */
       if (slashes == 3 && strncmp (aName, "http:", 5) == 0)        if (slashes == 3 && strncmp (aName, "http:", 5) == 0)
         /* just the same server */          /* just the same server */
         strcpy (result, last_slash);          strcpy (result, last_slash);
       else        else
         {          {
           levels= 0;             levels= 0; 
           for (; *q && *q != '#' && *q != ';' && *q != '?'; q++)            for (; *q && *q != '#' && *q != ';' && *q != '?'; q++)
             if (*q == DIR_SEP)              if (*q == DIR_SEP)
               levels++;                levels++;
                       
           result[0] = EOS;            result[0] = EOS;
           for (;levels; levels--)            for (;levels; levels--)
             strcat (result, "../");              strcat (result, "../");
           strcat (result, last_slash+1);            strcat (result, last_slash+1);
         }           } 
   
       if (!*result)        if (!*result)
         strcat (result, "./");          strcat (result, "./");
   
       /* exactly the right length */        /* exactly the right length */
       len = strlen (result);        len = strlen (result);
       if ((return_value = (char *)TtaGetMemory (len + 1)) != NULL)        if ((return_value = (char *)TtaGetMemory (len + 1)) != NULL)
         strcpy (return_value, result);          strcpy (return_value, result);
   
     }      }
 #ifdef _WINDOWS  #ifdef _WINDOWS
   len = strlen (return_value);    len = strlen (return_value);
    for (ndx = 0; ndx < len; ndx ++)    for (ndx = 0; ndx < len; ndx ++)
           if (return_value[ndx] == '\\')            if (return_value[ndx] == '\\')
              return_value[ndx] = '/' ;        return_value[ndx] = '/' ;
 #endif /* _WINDOWS */  #endif /* _WINDOWS */
   return (return_value);    return (return_value);
 }  }
Line 2549  AM_gen_tempname (char *tmpl) Line 2549  AM_gen_tempname (char *tmpl)
       XXXXXX[5] = letters[v % 62];        XXXXXX[5] = letters[v % 62];
   
       /* This case is backward from the other three.  AM_gen_tempname        /* This case is backward from the other three.  AM_gen_tempname
          succeeds if __xstat fails because the name does not exist.           succeeds if __xstat fails because the name does not exist.
          Note the continue to bypass the common logic at the bottom           Note the continue to bypass the common logic at the bottom
          of the loop.  */           of the loop.  */
       if (stat (tmpl, &st) < 0)        if (stat (tmpl, &st) < 0)
           break;          break;
   
       continue;        continue;
     }      }
Line 2587  char *GetTempName (const char *dir, cons Line 2587  char *GetTempName (const char *dir, cons
     return NULL;      return NULL;
   
   /* make sure that the name is no bigger than PATH_MAX + the 6 tempname chars we    /* make sure that the name is no bigger than PATH_MAX + the 6 tempname chars we
    will add */       will add */
   
   len = strlen (dir);    len = strlen (dir);
   if (len + 6 > PATH_MAX)    if (len + 6 > PATH_MAX)
Line 2597  char *GetTempName (const char *dir, cons Line 2597  char *GetTempName (const char *dir, cons
   if (dir[strlen (dir) - 1] == DIR_SEP)    if (dir[strlen (dir) - 1] == DIR_SEP)
     strcpy (tmpbufmem, dir);      strcpy (tmpbufmem, dir);
   else    else
   {      {
     sprintf (tmpbufmem, "%s%c", dir, DIR_SEP);        sprintf (tmpbufmem, "%s%c", dir, DIR_SEP);
         len++;        len++;
   }      }
   
   /* copy the prefix (no more than L_tmpnam chars, to respect POSIX). Save    /* copy the prefix (no more than L_tmpnam chars, to respect POSIX). Save
      space for the 6 X and EOS chars that will become the random bits */       space for the 6 X and EOS chars that will become the random bits */
   if (prefix)    if (prefix)
   {       { 
       i = 0;        i = 0;
           while (prefix[i] != EOS && i < L_tmpnam - 8)        while (prefix[i] != EOS && i < L_tmpnam - 8)
             tmpbufmem[len++] = prefix[i++];          tmpbufmem[len++] = prefix[i++];
           tmpbufmem[len] = EOS;        tmpbufmem[len] = EOS;
   }      }
   
   /* Add the 6 X chars */    /* Add the 6 X chars */
   len = strlen (tmpbufmem);    len = strlen (tmpbufmem);
   i = 0;    i = 0;
   while (i < 6)    while (i < 6)
   {      {
         tmpbufmem[len++] = 'X';        tmpbufmem[len++] = 'X';
         i++;        i++;
   }            }    
   tmpbufmem[len] = EOS;    tmpbufmem[len] = EOS;
   
   AM_gen_tempname (tmpbufmem);    AM_gen_tempname (tmpbufmem);

Removed from v.1.194  
changed lines
  Added in v.1.195


Webmaster