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

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

Webmaster