Annotation of libwww/Library/src/HTAccess.c, revision 1.88

1.61      frystyk     1: /*                                                                  HTAccess.c
                      2: **     ACCESS MANAGER
                      3: **
1.75      frystyk     4: **     (c) COPYRIGHT MIT 1995.
1.61      frystyk     5: **     Please first read the full copyright statement in the file COPYRIGH.
1.1       timbl       6: **
                      7: ** Authors
1.79      frystyk     8: **     TBL     Tim Berners-Lee timbl@w3.org
1.4       timbl       9: **     JFG     Jean-Francois Groff jfg@dxcern.cern.ch
1.1       timbl      10: **     DD      Denis DeLaRoca (310) 825-4580  <CSP1DWD@mvs.oac.ucla.edu>
                     11: ** History
                     12: **       8 Jun 92 Telnet hopping prohibited as telnet is not secure TBL
                     13: **     26 Jun 92 When over DECnet, suppressed FTP, Gopher and News. JFG
1.42      frystyk    14: **      6 Oct 92 Moved HTClientHost and HTlogfile into here. TBL
1.1       timbl      15: **     17 Dec 92 Tn3270 added, bug fix. DD
1.2       timbl      16: **      4 Feb 93 Access registration, Search escapes bad chars TBL
1.9       timbl      17: **               PARAMETERS TO HTSEARCH AND HTLOADRELATIVE CHANGED
                     18: **     28 May 93 WAIS gateway explicit if no WAIS library linked in.
1.19      timbl      19: **        Dec 93 Bug change around, more reentrant, etc
1.42      frystyk    20: **     09 May 94 logfile renamed to HTlogfile to avoid clash with WAIS
1.53      duns       21: **      8 Jul 94 Insulate free() from _free structure element.
1.88    ! frystyk    22: **        Sep 95 Rewritten, HFN
1.1       timbl      23: */
                     24: 
1.68      frystyk    25: #if !defined(HT_DIRECT_WAIS) && !defined(HT_DEFAULT_WAIS_GATEWAY)
                     26: #define HT_DEFAULT_WAIS_GATEWAY "http://www.w3.org:8001/"
1.54      frystyk    27: #endif
1.8       timbl      28: 
1.67      frystyk    29: /* Library include files */
1.88    ! frystyk    30: #include "WWWLib.h"
        !            31: #include "HTReqMan.h"       /* @@@@@@@@@@@@@@@@@@@@@@@@ */
        !            32: 
1.70      frystyk    33: #include "HTInit.h"
1.67      frystyk    34: #include "HTAccess.h"                                   /* Implemented here */
1.2       timbl      35: 
1.59      frystyk    36: /* --------------------------------------------------------------------------*/
1.61      frystyk    37: /*                Initialization and Termination of the Library             */
                     38: /* --------------------------------------------------------------------------*/
                     39: 
                     40: /*                                                                  HTLibInit
                     41: **
                     42: **     This function initiates the Library and it MUST be called when
                     43: **     starting up an application. See also HTLibTerminate()
                     44: */
                     45: PUBLIC BOOL HTLibInit NOARGS
                     46: {
1.67      frystyk    47: #ifdef NO_STDIO                                                  /* Open trace file */
                     48:     if ((TDEST = fopen(TRACE_FILE, "a")) != NULL) {
                     49:        if (setvbuf(TDEST, NULL, _IOLBF, 0) < 0) {  /* Change to line buffer */
1.70      frystyk    50:            printf("WWWLibInit.. Can't initialize TRACE buffer - no TRACE\n");
1.67      frystyk    51:            fclose(TDEST);
                     52:            TDEST = NULL;
                     53:            WWW_TraceFlag = 0;
                     54:        }
                     55:     } else
                     56:        WWW_TraceFlag = 0;
                     57: #endif
                     58: 
1.61      frystyk    59:     if (TRACE)
1.67      frystyk    60:        fprintf(TDEST, "WWWLibInit.. INITIALIZING LIBRARY OF COMMON CODE\n");
1.63      frystyk    61: 
1.77      frystyk    62:     /* Set up User preferences, but leave initialization to the application */
1.73      frystyk    63:     if (!HTConversions)
                     64:        HTConversions = HTList_new();
1.77      frystyk    65:     if (!HTEncodings)
                     66:        HTEncodings = HTList_new();
                     67:     if (!HTLanguages)
                     68:        HTLanguages = HTList_new();
                     69:     if (!HTCharsets)
                     70:        HTCharsets = HTList_new();
                     71: 
                     72:     /* Set up bindings to the local file system */
                     73:     HTBind_init();
1.73      frystyk    74: 
1.70      frystyk    75: #ifndef HT_NO_INIT
                     76:     HTAccessInit();             /* Bind access schemes and protocol modules */
                     77:     HTFileInit();                   /* Bind file extensions and media types */
1.63      frystyk    78: #endif
1.61      frystyk    79: 
1.77      frystyk    80: #ifndef HT_DIRECT_WAIS
                     81:     HTProxy_setGateway("wais", HT_DEFAULT_WAIS_GATEWAY);
                     82: #endif
                     83: 
1.88    ! frystyk    84:     /* Register a call back function for the Net Manager */
        !            85:     HTNet_register (HTLoad_terminate, HT_ALL);
        !            86: 
1.62      frystyk    87: #ifdef WWWLIB_SIG
1.61      frystyk    88:     /* On Solaris (and others?) we get a BROKEN PIPE signal when connecting
1.67      frystyk    89:     ** to a port where we should get `connection refused'. We ignore this 
1.61      frystyk    90:     ** using the following function call
                     91:     */
                     92:     HTSetSignal();                                /* Set signals in library */
1.1       timbl      93: #endif
                     94: 
1.67      frystyk    95: #ifdef _WINDOWS
                     96:     /*
                     97:     ** Initialise WinSock DLL. This must also be shut down! PMH
                     98:     */
                     99:     {
                    100:         WSADATA            wsadata;
                    101:        if (WSAStartup(DESIRED_WINSOCK_VERSION, &wsadata)) {
                    102:            if (TRACE)
                    103:                fprintf(TDEST, "WWWLibInit.. Can't initialize WinSoc\n");
                    104:             WSACleanup();
                    105:             return NO;
                    106:         }
                    107:         if (wsadata.wVersion < MINIMUM_WINSOCK_VERSION) {
                    108:             if (TRACE)
                    109:                fprintf(TDEST, "WWWLibInit.. Bad version of WinSoc\n");
                    110:             WSACleanup();
                    111:             return NO;
                    112:         }
                    113:     }
                    114: #endif /* _WINDOWS */
                    115: 
1.71      frystyk   116: #ifndef NO_TIMEGM
                    117:     HTGetTimeZoneOffset();        /* Find offset from GMT if using mktime() */
                    118: #endif
1.70      frystyk   119:     HTTmp_setRoot(NULL);                    /* Set up default tmp directory */
1.61      frystyk   120:     return YES;
                    121: }
                    122: 
                    123: 
                    124: /*                                                              HTLibTerminate
                    125: **
                    126: **     This function frees memory kept by the Library and should be called
1.63      frystyk   127: **     before exit of an application (if you are on a PC platform)
1.61      frystyk   128: */
                    129: PUBLIC BOOL HTLibTerminate NOARGS
                    130: {
                    131:     if (TRACE)
1.67      frystyk   132:        fprintf(TDEST, "WWWLibTerm.. Cleaning up LIBRARY OF COMMON CODE\n");
1.88    ! frystyk   133: #if 0
        !           134:     HTNet_deleteAll();                     /* Remove all remaining requests */
        !           135: #endif
1.63      frystyk   136:     HTAtom_deleteAll();
                    137:     HTDisposeConversions();
                    138:     HTTCPCacheRemoveAll();
1.73      frystyk   139: 
                    140: #ifndef HT_NO_INIT
1.81      frystyk   141:     HTProtocol_deleteAll();  /* Remove bindings between access and protocols */
1.73      frystyk   142:     HTBind_deleteAll();            /* Remove bindings between suffixes, media types */
                    143: #endif
                    144: 
1.77      frystyk   145:     HTProxy_deleteProxy();        /* Clean up lists of proxies and gateways */
                    146:     HTProxy_deleteNoProxy();
                    147:     HTProxy_deleteGateway();
                    148: 
                    149:     HTFreeHostName();                      /* Free up some internal strings */
1.63      frystyk   150:     HTFreeMailAddress();
1.70      frystyk   151:     HTCache_freeRoot();
1.84      frystyk   152:     HTCache_clearMem();                                  /* Keep the disk versions! */
1.70      frystyk   153:     HTTmp_freeRoot();
1.67      frystyk   154: 
                    155: #ifdef _WINDOWS
                    156:     WSACleanup();
                    157: #endif
                    158: 
                    159: #ifdef NO_STDIO                                                 /* Close trace file */
                    160:     if (TDEST) {
                    161:        fclose(TDEST);
                    162:        TDEST = NULL;
                    163:        WWW_TraceFlag = 0;
                    164:     }
                    165: #endif
1.61      frystyk   166:     return YES;
                    167: }
                    168: 
1.59      frystyk   169: /* --------------------------------------------------------------------------*/
1.88    ! frystyk   170: /*                             Access functions                             */
1.59      frystyk   171: /* --------------------------------------------------------------------------*/
1.33      luotonen  172: 
1.88    ! frystyk   173: /*     Load a document
        !           174: **     ---------------
1.2       timbl     175: **
                    176: **     - Checks or documents already loaded
                    177: **     - Logs the access
                    178: **     - Trace ouput and error messages
                    179: **
1.1       timbl     180: **    On Entry,
1.19      timbl     181: **        request->anchor      valid for of the document to be accessed.
                    182: **      request->childAnchor   optional anchor within doc to be selected
                    183: **
1.15      timbl     184: **       request->anchor   is the node_anchor for the document
                    185: **       request->output_format is valid
                    186: **
1.88    ! frystyk   187: **     returns
        !           188: **             YES     if request has been registered (success)
        !           189: **             NO      an error occured
        !           190: */
        !           191: PRIVATE int HTLoadDocument ARGS2(HTRequest *, request, BOOL, recursive)
        !           192: {
        !           193:     if (PROT_TRACE) {
        !           194:        char * full_address = HTAnchor_address((HTAnchor *) request->anchor);
        !           195:        fprintf (TDEST, "HTAccess.... Accessing document %s\n", full_address);
        !           196:        free(full_address);
        !           197:     }
        !           198:     if (!request->output_format)
        !           199:        request->output_format = WWW_PRESENT;
        !           200:     return HTLoad(request, recursive, 0);             /* @@@@ PRIORITY @@@@ */
1.58      frystyk   201: }
1.1       timbl     202: 
                    203: 
                    204: /*             Load a document from absolute name
                    205: **             ---------------
                    206: **
1.59      frystyk   207: ** On Entry,
1.1       timbl     208: **        addr     The absolute address of the document to be accessed.
                    209: **
1.59      frystyk   210: ** On exit,
                    211: **     returns         HT_WOULD_BLOCK  An I/O operation would block
                    212: **                     HT_ERROR        Error has occured
                    213: **                     HT_LOADED       Success
                    214: **                     HT_NO_DATA      Success, but no document loaded.
                    215: **                                     (telnet sesssion started etc)
1.72      frystyk   216: **                     HT_RETRY        if service isn't available before
                    217: **                                     request->retry_after
1.1       timbl     218: */
1.59      frystyk   219: PUBLIC int HTLoadAbsolute ARGS2(CONST char *,addr, HTRequest*, request)
1.2       timbl     220: {
1.19      timbl     221:    HTAnchor * anchor = HTAnchor_findAddress(addr);
                    222:    request->anchor = HTAnchor_parent(anchor);
                    223:    request->childAnchor = ((HTAnchor*)request->anchor == anchor) ?
                    224:                        NULL : (HTChildAnchor*) anchor;
1.52      frystyk   225:    return HTLoadDocument(request, NO);
1.2       timbl     226: }
                    227: 
                    228: 
                    229: /*             Load a document from absolute name to stream
                    230: **             --------------------------------------------
                    231: **
1.59      frystyk   232: ** On Entry,
1.2       timbl     233: **        addr     The absolute address of the document to be accessed.
1.15      timbl     234: **        request->output_stream     if non-NULL, send data down this stream
1.2       timbl     235: **
1.59      frystyk   236: ** On exit,
                    237: **     returns         HT_WOULD_BLOCK  An I/O operation would block
                    238: **                     HT_ERROR        Error has occured
                    239: **                     HT_LOADED       Success
                    240: **                     HT_NO_DATA      Success, but no document loaded.
                    241: **                                     (telnet sesssion started etc)
1.72      frystyk   242: **                     HT_RETRY        if service isn't available before
                    243: **                                     request->retry_after
1.2       timbl     244: */
1.59      frystyk   245: PUBLIC int HTLoadToStream ARGS3(CONST char *,  addr,
                    246:                                BOOL,           filter,
                    247:                                HTRequest*,     request)
1.1       timbl     248: {
1.63      frystyk   249:     HTAnchor * anchor = HTAnchor_findAddress(addr);
                    250:     request->anchor = HTAnchor_parent(anchor);
                    251:     request->childAnchor = ((HTAnchor*)request->anchor == anchor) ? NULL :
1.19      timbl     252:        (HTChildAnchor*) anchor;
1.15      timbl     253:     request->output_stream = request->output_stream;
1.52      frystyk   254:     return HTLoadDocument(request, NO);
1.1       timbl     255: }
                    256: 
                    257: 
                    258: /*             Load a document from relative name
                    259: **             ---------------
                    260: **
1.59      frystyk   261: ** On Entry,
1.2       timbl     262: **        relative_name     The relative address of the document
                    263: **                         to be accessed.
1.1       timbl     264: **
1.59      frystyk   265: ** On exit,
                    266: **     returns         HT_WOULD_BLOCK  An I/O operation would block
                    267: **                     HT_ERROR        Error has occured
                    268: **                     HT_LOADED       Success
                    269: **                     HT_NO_DATA      Success, but no document loaded.
                    270: **                                     (telnet sesssion started etc)
1.72      frystyk   271: **                     HT_RETRY        if service isn't available before
                    272: **                                     request->retry_after
1.1       timbl     273: */
1.59      frystyk   274: PUBLIC int HTLoadRelative ARGS3(CONST char *,          relative_name,
                    275:                                HTParentAnchor *,       here,
                    276:                                HTRequest *,            request)
1.1       timbl     277: {
                    278:     char *             full_address = 0;
1.65      frystyk   279:     int                result;
1.1       timbl     280:     char *             mycopy = 0;
                    281:     char *             stripped = 0;
                    282:     char *             current_address =
1.2       timbl     283:                                HTAnchor_address((HTAnchor*)here);
1.1       timbl     284: 
                    285:     StrAllocCopy(mycopy, relative_name);
                    286: 
                    287:     stripped = HTStrip(mycopy);
                    288:     full_address = HTParse(stripped,
                    289:                   current_address,
                    290:                   PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
1.15      timbl     291:     result = HTLoadAbsolute(full_address, request);
1.1       timbl     292:     free(full_address);
                    293:     free(current_address);
                    294:     free(mycopy);  /* Memory leak fixed 10/7/92 -- JFG */
                    295:     return result;
                    296: }
                    297: 
                    298: 
                    299: /*             Load if necessary, and select an anchor
                    300: **             --------------------------------------
                    301: **
1.59      frystyk   302: ** On Entry,
1.1       timbl     303: **        destination              The child or parenet anchor to be loaded.
                    304: **
1.59      frystyk   305: ** On exit,
                    306: **     returns         HT_WOULD_BLOCK  An I/O operation would block
                    307: **                     HT_ERROR        Error has occured
                    308: **                     HT_LOADED       Success
                    309: **                     HT_NO_DATA      Success, but no document loaded.
                    310: **                                     (telnet sesssion started etc)
1.72      frystyk   311: **                     HT_RETRY        if service isn't available before
                    312: **                                     request->retry_after
1.1       timbl     313: */
1.59      frystyk   314: PUBLIC int HTLoadAnchor ARGS2(HTAnchor*, anchor, HTRequest *, request)
1.1       timbl     315: {
1.70      frystyk   316:     if (!anchor || !request)
                    317:        return HT_ERROR;
                    318:     request->anchor = HTAnchor_parent(anchor);
1.59      frystyk   319:     request->childAnchor = ((HTAnchor *) request->anchor == anchor) ?
                    320:        NULL : (HTChildAnchor*) anchor;
                    321:     return HTLoadDocument(request, NO);
                    322: }
1.52      frystyk   323: 
                    324: 
                    325: /*             Load if necessary, and select an anchor
                    326: **             --------------------------------------
                    327: **
                    328: **     This function is almost identical to HTLoadAnchor, but it doesn't
                    329: **     clear the error stack so that the information in there is kept.
                    330: **
1.59      frystyk   331: ** On Entry,
1.52      frystyk   332: **        destination              The child or parenet anchor to be loaded.
                    333: **
1.59      frystyk   334: ** On exit,
                    335: **     returns         HT_WOULD_BLOCK  An I/O operation would block
                    336: **                     HT_ERROR        Error has occured
                    337: **                     HT_LOADED       Success
                    338: **                     HT_NO_DATA      Success, but no document loaded.
                    339: **                                     (telnet sesssion started etc)
1.72      frystyk   340: **                     HT_RETRY        if service isn't available before
                    341: **                                     request->retry_after
1.52      frystyk   342: */
1.59      frystyk   343: PUBLIC int HTLoadAnchorRecursive ARGS2(HTAnchor*,      anchor,
                    344:                                       HTRequest *,     request)
1.52      frystyk   345: {
1.59      frystyk   346:     if (!anchor) return HT_ERROR;                                /* No link */
1.52      frystyk   347:     
                    348:     request->anchor  = HTAnchor_parent(anchor);
1.59      frystyk   349:     request->childAnchor = ((HTAnchor *) request->anchor == anchor) ?
                    350:        NULL : (HTChildAnchor*) anchor;
1.52      frystyk   351:     
1.59      frystyk   352:     return HTLoadDocument(request, YES);
                    353: }
1.1       timbl     354: 
                    355: 
                    356: /*             Search
                    357: **             ------
                    358: **  Performs a keyword search on word given by the user. Adds the keyword to 
                    359: **  the end of the current address and attempts to open the new address.
                    360: **
                    361: **  On Entry,
                    362: **       *keywords     space-separated keyword list or similar search list
1.2       timbl     363: **     here            is anchor search is to be done on.
1.59      frystyk   364: **
                    365: ** On exit,
                    366: **     returns         HT_WOULD_BLOCK  An I/O operation would block
                    367: **                     HT_ERROR        Error has occured
                    368: **                     HT_LOADED       Success
                    369: **                     HT_NO_DATA      Success, but no document loaded.
                    370: **                                     (telnet sesssion started etc)
1.72      frystyk   371: **                     HT_RETRY        if service isn't available before
                    372: **                                     request->retry_after
1.1       timbl     373: */
1.56      frystyk   374: PRIVATE char hex ARGS1(int, i)
1.2       timbl     375: {
1.13      timbl     376:     char * hexchars = "0123456789ABCDEF";
                    377:     return hexchars[i];
1.2       timbl     378: }
1.1       timbl     379: 
1.59      frystyk   380: PUBLIC int HTSearch ARGS3(CONST char *,                keywords,
                    381:                          HTParentAnchor *,     here,
                    382:                          HTRequest *,          request)
1.1       timbl     383: {
1.2       timbl     384: 
                    385: #define acceptable \
                    386: "1234567890abcdefghijlkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_"
                    387: 
                    388:     char *q, *u;
                    389:     CONST char * p, *s, *e;            /* Pointers into keywords */
                    390:     char * address = HTAnchor_address((HTAnchor*)here);
1.65      frystyk   391:     int result;
1.56      frystyk   392:     char * escaped = (char *) malloc(strlen(keywords)*3+1);
1.2       timbl     393: 
1.29      frystyk   394:     /* static CONST BOOL isAcceptable[96] = */
                    395:     /* static AND const is not good for a gnu compiler! Frystyk 25/02-94 */
1.30      luotonen  396:     static BOOL isAcceptable[96] =
1.2       timbl     397:     /*   0 1 2 3 4 5 6 7 8 9 A B C D E F */
                    398:     {    0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,0,      /* 2x   !"#$%&'()*+,-./  */
                    399:          1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,      /* 3x  0123456789:;<=>?  */
                    400:         1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,       /* 4x  @ABCDEFGHIJKLMNO  */
                    401:         1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,       /* 5X  PQRSTUVWXYZ[\]^_  */
                    402:         0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,       /* 6x  `abcdefghijklmno  */
                    403:         1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0 };     /* 7X  pqrstuvwxyz{\}~  DEL */
                    404: 
                    405:     if (escaped == NULL) outofmem(__FILE__, "HTSearch");
                    406:     
1.29      frystyk   407: /* Convert spaces to + and hex escape unacceptable characters */
1.2       timbl     408: 
1.29      frystyk   409:     for(s=keywords; *s && WHITE(*s); s++); /*scan */    /* Skip white space */
                    410:     for(e = s + strlen(s); e>s && WHITE(*(e-1)) ; e--);     /* Skip trailers */
                    411:     for(q=escaped, p=s; p<e; p++) {                  /* scan stripped field */
1.2       timbl     412:         int c = (int)TOASCII(*p);
                    413:         if (WHITE(*p)) {
                    414:            *q++ = '+';
1.29      frystyk   415:        } else if (c>=32 && c<=127 && isAcceptable[c-32] != 0) {
1.13      timbl     416:            *q++ = *p;                  /* 930706 TBL for MVS bug */
1.2       timbl     417:        } else {
                    418:            *q++ = '%';
                    419:            *q++ = hex(c / 16);
                    420:            *q++ = hex(c % 16);
                    421:        }
                    422:     } /* Loop over string */
1.1       timbl     423:     
1.2       timbl     424:     *q=0;
                    425:                                /* terminate escaped sctring */
                    426:     u=strchr(address, '?');            /* Find old search string */
                    427:     if (u) *u = 0;                             /* Chop old search off */
1.1       timbl     428: 
                    429:     StrAllocCat(address, "?");
1.2       timbl     430:     StrAllocCat(address, escaped);
                    431:     free(escaped);
1.15      timbl     432:     result = HTLoadRelative(address, here, request);
1.1       timbl     433:     free(address);
1.2       timbl     434:     
1.1       timbl     435:     return result;
1.2       timbl     436: }
                    437: 
                    438: 
                    439: /*             Search Given Indexname
                    440: **             ------
                    441: **  Performs a keyword search on word given by the user. Adds the keyword to 
                    442: **  the end of the current address and attempts to open the new address.
                    443: **
1.59      frystyk   444: ** On Entry,
1.2       timbl     445: **       *keywords     space-separated keyword list or similar search list
                    446: **     *addres         is name of object search is to be done on.
1.59      frystyk   447: ** On exit,
                    448: **     returns         HT_WOULD_BLOCK  An I/O operation would block
                    449: **                     HT_ERROR        Error has occured
                    450: **                     HT_LOADED       Success
                    451: **                     HT_NO_DATA      Success, but no document loaded.
                    452: **                                     (telnet sesssion started etc)
1.72      frystyk   453: **                     HT_RETRY        if service isn't available before
                    454: **                                     request->retry_after
1.2       timbl     455: */
1.59      frystyk   456: PUBLIC int HTSearchAbsolute ARGS3(CONST char *,        keywords,
                    457:                                  CONST char *,         indexname,
                    458:                                  HTRequest *,          request)
1.2       timbl     459: {
                    460:     HTParentAnchor * anchor =
                    461:        (HTParentAnchor*) HTAnchor_findAddress(indexname);
1.15      timbl     462:     return HTSearch(keywords, anchor, request);
1.57      howcome   463: }
                    464: 
1.70      frystyk   465: /* --------------------------------------------------------------------------*/
                    466: /*                             Document Poster                              */
                    467: /* --------------------------------------------------------------------------*/
                    468: 
1.88    ! frystyk   469: #if 0
1.70      frystyk   470: /*             Get a save stream for a document
                    471: **             --------------------------------
                    472: */
                    473: PUBLIC HTStream *HTSaveStream ARGS1(HTRequest *, request)
                    474: {
                    475:     HTProtocol * p;
                    476:     int status;
                    477:     request->method = METHOD_PUT;
                    478:     status = get_physical(request);
                    479:     if (status == HT_FORBIDDEN) {
                    480:        char *url = HTAnchor_address((HTAnchor *) request->anchor);
                    481:        if (url) {
                    482:            HTUnEscape(url);
                    483:            HTErrorAdd(request, ERR_FATAL, NO, HTERR_FORBIDDEN,
1.88    ! frystyk   484:                       (void *) url, (int) strlen(url), "HTSaveStream");
1.70      frystyk   485:            free(url);
                    486:        } else {
                    487:            HTErrorAdd(request, ERR_FATAL, NO, HTERR_FORBIDDEN,
1.88    ! frystyk   488:                       NULL, 0, "HTSaveStream");
1.70      frystyk   489:        }
                    490:        return NULL;    /* should return error status? */
                    491:     }
                    492:     if (status < 0) return NULL; /* @@ error. Can't resolve or forbidden */
                    493:     
                    494:     p = (HTProtocol *) HTAnchor_protocol(request->anchor);
                    495:     if (!p) return NULL;
                    496:     
                    497:     return (*p->saveStream)(request);
                    498:     
                    499: }
1.88    ! frystyk   500: #endif
1.70      frystyk   501: 
                    502: /*     COPY AN ANCHOR
                    503: **     --------------
                    504: **  Fetch the URL (possibly local file URL) and send it using either PUT
                    505: **  or POST to the remote destination using HTTP. The caller can decide the
                    506: **  exact method used and which HTTP header fields to transmit by setting the
                    507: **  user fields in the request structure.
                    508: **
1.80      frystyk   509: **  BUGS: Should take ALL links in the destination anchor and PUT/POST to
                    510: **  all of them!
                    511: **
1.70      frystyk   512: **     returns         HT_WOULD_BLOCK  An I/O operation would block
                    513: **                     HT_ERROR        Error has occured
                    514: **                     HT_LOADED       Success
                    515: **                     HT_NO_DATA      Success, but no document loaded.
1.72      frystyk   516: **                     HT_RETRY        if service isn't available before
                    517: **                                     request->retry_after
1.70      frystyk   518: */
1.80      frystyk   519: PUBLIC int HTCopyAnchor ARGS2(HTAnchor *,      src_anchor,
1.85      frystyk   520:                              HTRequest *,      main_req)
1.80      frystyk   521: { 
1.78      frystyk   522:     HTRequest *src_req;
1.85      frystyk   523:     if (!src_anchor || !main_req)
1.70      frystyk   524:        return HT_ERROR;
                    525: 
1.80      frystyk   526:     /* Build the POST web if not already there */
1.85      frystyk   527:     if (!main_req->source) {
1.80      frystyk   528:        src_req = HTRequest_new();                /* First set up the source */
                    529:        HTAnchor_clearHeader((HTParentAnchor *) src_anchor);
1.85      frystyk   530:        src_req->reload = HT_MEM_REFRESH;
1.80      frystyk   531:        src_req->source = src_req;                        /* Point to myself */
                    532:        src_req->output_format = WWW_SOURCE;     /* We want source (for now) */
                    533: 
                    534:        /* Set up the main link in the source anchor */
                    535:        {
1.85      frystyk   536:            HTLink *main_link = HTAnchor_findMainLink(src_anchor);
                    537:            HTAnchor *main_anchor = HTAnchor_linkDest(main_link);
                    538:            HTMethod method = HTAnchor_linkMethod(main_link);
                    539:            if (!main_link || method==METHOD_INVALID) {
1.80      frystyk   540:                if (TRACE)
                    541:                    fprintf(TDEST, "Copy Anchor. No destination found or unspecified method");
                    542:                HTRequest_delete(src_req);
                    543:                return HT_ERROR;
                    544:            }
1.85      frystyk   545:            if (HTAnchor_linkResult(main_link) == HT_LINK_NONE) {
                    546:                main_req->GenMask |= HT_DATE;            /* Send date header */
                    547:                main_req->source = src_req;
                    548:                main_req->reload = HT_CACHE_REFRESH;
                    549:                main_req->method = method;
                    550:                HTRequest_addDestination(src_req, main_req);
                    551:                main_req->input_format = WWW_SOURCE;      /* for now :-( @@@ */
                    552:                if (HTLoadAnchor(main_anchor, main_req) == HT_ERROR)
                    553:                    return HT_ERROR;
                    554:            }
1.80      frystyk   555:        }
1.78      frystyk   556: 
1.80      frystyk   557:        /* For all other links in the source anchor */
                    558:        if (src_anchor->links) {
                    559:            HTList *cur = src_anchor->links;
                    560:            HTLink *pres;
1.85      frystyk   561:            while ((pres = (HTLink *) HTList_nextObject(cur)) &&
                    562:                   HTAnchor_linkResult(pres) == HT_LINK_NONE) {
                    563:                HTAnchor *dest = HTAnchor_linkDest(pres);
                    564:                HTMethod method = HTAnchor_linkMethod(pres);
1.80      frystyk   565:                HTRequest *dest_req;
                    566:                if (!dest || method==METHOD_INVALID) {
                    567:                    if (TRACE)
                    568:                        fprintf(TDEST, "Copy Anchor. Bad anchor setup %p\n",
                    569:                                dest);
                    570:                    return HT_ERROR;
                    571:                }
                    572:                dest_req = HTRequest_new();
1.85      frystyk   573:                dest_req->GenMask |= HT_DATE;            /* Send date header */
1.80      frystyk   574:                dest_req->source = src_req;
1.85      frystyk   575:                dest_req->reload = HT_CACHE_REFRESH;
1.80      frystyk   576:                dest_req->method = method;
                    577:                HTRequest_addDestination(src_req, dest_req);
                    578:                dest_req->input_format = WWW_SOURCE;      /* for now :-( @@@ */
                    579:                if (HTLoadAnchor(dest, dest_req) == HT_ERROR)
                    580:                    return HT_ERROR;
                    581:            }
                    582:        }
                    583:     } else {                    /* Use the existing Post Web and restart it */
1.85      frystyk   584:        src_req = main_req->source;
1.80      frystyk   585:        if (src_req->mainDestination)
1.85      frystyk   586:            if (HTLoadDocument(main_req, NO) == HT_ERROR)
1.80      frystyk   587:                return HT_ERROR;
                    588:        if (src_req->destinations) {
                    589:            HTList *cur = src_anchor->links;
                    590:            HTRequest *pres;
                    591:            while ((pres = (HTRequest *) HTList_nextObject(cur)) != NULL) {
                    592:                if (HTLoadDocument(pres, NO) == HT_ERROR)
                    593:                    return HT_ERROR;
                    594:            }
                    595:        }
1.78      frystyk   596:     }
                    597: 
1.80      frystyk   598:     /* Now open the source */
                    599:     return HTLoadAnchor(src_anchor, src_req);
1.70      frystyk   600: }
                    601: 
                    602: 
                    603: /*     UPLOAD AN ANCHOR
                    604: **     ----------------
                    605: **  Send the contents (in hyperdoc) of the source anchor using either PUT
                    606: **  or POST to the remote destination using HTTP. The caller can decide the
                    607: **  exact method used and which HTTP header fields to transmit by setting the
                    608: **  user fields in the request structure.
                    609: **
                    610: **     returns         HT_WOULD_BLOCK  An I/O operation would block
                    611: **                     HT_ERROR        Error has occured
                    612: **                     HT_LOADED       Success
                    613: **                     HT_NO_DATA      Success, but no document loaded.
1.72      frystyk   614: **                     HT_RETRY        if service isn't available before
                    615: **                                     request->retry_after
1.70      frystyk   616: */
                    617: PUBLIC int HTUploadAnchor ARGS3(HTAnchor *,            src_anchor,
                    618:                                HTParentAnchor *,       dest_anchor,
                    619:                                HTRequest *,            dest_req)
                    620: {
                    621:     if (!(src_anchor && dest_anchor && dest_req))
                    622:        return HT_ERROR;
                    623: 
                    624:     if (!(dest_anchor->methods & dest_req->method)) {
                    625:        char buf[80];
                    626:        sprintf(buf, "It might not be allowed to %s to this destination, continue?", HTMethod_name(dest_req->method));
1.86      frystyk   627:        if (!HTConfirm(dest_req, buf))
1.70      frystyk   628:            return HT_ERROR;
                    629:     }
1.77      frystyk   630: 
                    631:     /* @@@ NOT FINISHED @@@ */
1.70      frystyk   632: 
                    633:     return HT_ERROR;
                    634: }
                    635: 
                    636: /* --------------------------------------------------------------------------*/
                    637: /*                             Anchor help routines                         */
                    638: /* --------------------------------------------------------------------------*/
1.57      howcome   639: 
                    640: /*
                    641: **             Find Related Name
                    642: **
                    643: **  Creates a string that can be used as a related name when 
                    644: **  calling HTParse initially. 
                    645: **  
                    646: **  The code for this routine originates from the Linemode 
1.79      frystyk   647: **  browser and was moved here by howcome@w3.org
1.57      howcome   648: **  in order for all clients to take advantage.
                    649: **
1.59      frystyk   650: **  The string returned must be freed by the caller
1.57      howcome   651: */
                    652: PUBLIC char * HTFindRelatedName NOARGS
                    653: {
1.59      frystyk   654:     char* default_default = NULL;            /* Parse home relative to this */
                    655:     CONST char *host = HTGetHostName(); 
1.57      howcome   656:     StrAllocCopy(default_default, "file://");
1.59      frystyk   657:     if (host)
                    658:        StrAllocCat(default_default, host);
                    659:     else
                    660:        StrAllocCat(default_default, "localhost");
                    661:     {
                    662:        char wd[HT_MAX_PATH+1];
1.67      frystyk   663: 
                    664: #ifdef NO_GETWD
                    665: #ifdef HAS_GETCWD            /* System V variant SIGN CHANGED TBL 921006 !! */
                    666:        char *result = (char *) getcwd(wd, sizeof(wd)); 
                    667: #else
                    668:        char *result = NULL;
                    669:        HTAlert("This platform does not support neither getwd nor getcwd\n");
                    670: #endif
                    671: #else
                    672:        char *result = (char *) getwd(wd);
                    673: #endif
1.59      frystyk   674:        *(wd+HT_MAX_PATH) = '\0';
1.57      howcome   675:        if (result) {
                    676: #ifdef VMS 
                    677:             /* convert directory name to Unix-style syntax */
                    678:            char * disk = strchr (wd, ':');
                    679:            char * dir = strchr (wd, '[');
                    680:            if (disk) {
                    681:                *disk = '\0';
                    682:                StrAllocCat (default_default, "/");  /* needs delimiter */
                    683:                StrAllocCat (default_default, wd);
                    684:            }
                    685:            if (dir) {
                    686:                char *p;
                    687:                *dir = '/';  /* Convert leading '[' */
                    688:                for (p = dir ; *p != ']'; ++p)
                    689:                        if (*p == '.') *p = '/';
                    690:                *p = '\0';  /* Cut on final ']' */
                    691:                StrAllocCat (default_default, dir);
                    692:            }
1.74      frystyk   693: #else  /* not VMS */
1.70      frystyk   694: #ifdef WIN32
                    695:            char * p = wd ;     /* a colon */
                    696:            StrAllocCat(default_default, "/");
                    697:            while( *p != 0 ) { 
                    698:                if (*p == '\\')                  /* change to one true slash */
                    699:                    *p = '/' ;
                    700:                p++;
                    701:            }
1.74      frystyk   702:            StrAllocCat( default_default, wd);
                    703: #else /* not WIN32 */
1.57      howcome   704:            StrAllocCat (default_default, wd);
1.70      frystyk   705: #endif /* not WIN32 */
1.67      frystyk   706: #endif /* not VMS */
1.57      howcome   707:        }
1.67      frystyk   708:     }
1.57      howcome   709:     StrAllocCat(default_default, "/default.html");
                    710:     return default_default;
1.2       timbl     711: }
                    712: 
                    713: 
                    714: /*             Generate the anchor for the home page
                    715: **             -------------------------------------
                    716: **
                    717: **     As it involves file access, this should only be done once
                    718: **     when the program first runs.
1.10      timbl     719: **     This is a default algorithm -- browser don't HAVE to use this.
                    720: **     But consistency betwen browsers is STRONGLY recommended!
1.2       timbl     721: **
1.10      timbl     722: **     Priority order is:
                    723: **
                    724: **             1       WWW_HOME environment variable (logical name, etc)
                    725: **             2       ~/WWW/default.html
                    726: **             3       /usr/local/bin/default.html
1.70      frystyk   727: **             4       http://www.w3.org/default.html
1.10      timbl     728: **
1.2       timbl     729: */
                    730: PUBLIC HTParentAnchor * HTHomeAnchor NOARGS
                    731: {
1.12      timbl     732:     char * my_home_document = NULL;
1.70      frystyk   733:     char * home = (char *) getenv(LOGICAL_DEFAULT);
1.2       timbl     734:     char * ref;
                    735:     HTParentAnchor * anchor;
1.1       timbl     736:     
1.70      frystyk   737:     /* Someone telnets in, they get a special home */
1.12      timbl     738:     if (home) {
                    739:         StrAllocCopy(my_home_document, home);
1.70      frystyk   740:     } else  if (HTClientHost) {                                    /* Telnet server */
1.12      timbl     741:        FILE * fp = fopen(REMOTE_POINTER, "r");
                    742:        char * status;
                    743:        if (fp) {
1.59      frystyk   744:            my_home_document = (char*) malloc(HT_MAX_PATH);
                    745:            status = fgets(my_home_document, HT_MAX_PATH, fp);
1.12      timbl     746:            if (!status) {
                    747:                free(my_home_document);
                    748:                my_home_document = NULL;
                    749:            }
                    750:            fclose(fp);
                    751:        }
                    752:        if (!my_home_document) StrAllocCopy(my_home_document, REMOTE_ADDRESS);
                    753:     }
                    754: 
1.67      frystyk   755: #ifdef unix
1.10      timbl     756:     if (!my_home_document) {
                    757:        FILE * fp = NULL;
1.70      frystyk   758:        char * home = (char *) getenv("HOME");
1.10      timbl     759:        if (home) { 
                    760:            my_home_document = (char *)malloc(
                    761:                strlen(home)+1+ strlen(PERSONAL_DEFAULT)+1);
                    762:            if (my_home_document == NULL) outofmem(__FILE__, "HTLocalName");
                    763:            sprintf(my_home_document, "%s/%s", home, PERSONAL_DEFAULT);
                    764:            fp = fopen(my_home_document, "r");
                    765:        }
                    766:        
                    767:        if (!fp) {
                    768:            StrAllocCopy(my_home_document, LOCAL_DEFAULT_FILE);
                    769:            fp = fopen(my_home_document, "r");
                    770:        }
1.2       timbl     771:        if (fp) {
                    772:            fclose(fp);
                    773:        } else {
1.62      frystyk   774:            if (TRACE)
1.67      frystyk   775:                fprintf(TDEST,
1.62      frystyk   776:                        "HTBrowse: No local home document ~/%s or %s\n",
                    777:                        PERSONAL_DEFAULT, LOCAL_DEFAULT_FILE);
1.11      timbl     778:            free(my_home_document);
                    779:            my_home_document = NULL;
1.2       timbl     780:        }
                    781:     }
1.67      frystyk   782: #endif
1.70      frystyk   783:     ref = HTParse(my_home_document ? my_home_document :
                    784:                  HTClientHost ? REMOTE_ADDRESS : LAST_RESORT, "file:",
                    785:                  PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
1.10      timbl     786:     if (my_home_document) {
1.62      frystyk   787:        if (TRACE)
1.67      frystyk   788:            fprintf(TDEST,
1.62      frystyk   789:                   "HTAccess.... `%s\' used for custom home page as\n`%s\'\n",
                    790:                    my_home_document, ref);
1.10      timbl     791:        free(my_home_document);
1.2       timbl     792:     }
                    793:     anchor = (HTParentAnchor*) HTAnchor_findAddress(ref);
                    794:     free(ref);
                    795:     return anchor;
1.1       timbl     796: }
1.26      frystyk   797: 

Webmaster