Annotation of Amaya/amaya/AHTURLTools.c, revision 1.28

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

Webmaster