home *** CD-ROM | disk | FTP | other *** search
/ Collection of Internet / Collection of Internet.iso / msdos / lynx / source / www / library / implemen / htaccess.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-25  |  19.9 KB  |  764 lines

  1. /*        Access Manager                    HTAccess.c
  2. **        ==============
  3. **
  4. ** Authors
  5. **    TBL    Tim Berners-Lee timbl@info.cern.ch
  6. **    JFG    Jean-Francois Groff jfg@dxcern.cern.ch
  7. **    DD    Denis DeLaRoca (310) 825-4580  <CSP1DWD@mvs.oac.ucla.edu>
  8. ** History
  9. **       8 Jun 92 Telnet hopping prohibited as telnet is not secure TBL
  10. **    26 Jun 92 When over DECnet, suppressed FTP, Gopher and News. JFG
  11. **     6 Oct 92 Moved HTClientHost and logfile into here. TBL
  12. **    17 Dec 92 Tn3270 added, bug fix. DD
  13. **     4 Feb 93 Access registration, Search escapes bad chars TBL
  14. **          PARAMETERS TO HTSEARCH AND HTLOADRELATIVE CHANGED
  15. **    28 May 93 WAIS gateway explicit if no WAIS library linked in.
  16. **
  17. ** Bugs
  18. **    This module assumes that that the graphic object is hypertext, as it
  19. **    needs to select it when it has been loaded.  A superclass needs to be
  20. **    defined which accepts select and select_anchor.
  21. */
  22.  
  23. #ifndef DEFAULT_WAIS_GATEWAY
  24. /* #define DEFAULT_WAIS_GATEWAY "http://info.cern.ch:8001/" */
  25. #define DEFAULT_WAIS_GATEWAY "http://www.ncsa.uiuc.edu:8001/"
  26. #endif
  27.  
  28. /* Implements:
  29. */
  30. #include"capalloc.h"
  31. #include "HTAccess.h"
  32.  
  33. /* Uses:
  34. */
  35.  
  36. #include "HTParse.h"
  37. #include "HTUtils.h"
  38. #include "HTML.h"        /* SCW */
  39. #include"capstdio.h"
  40.  
  41. #ifndef NO_RULES
  42. #include "HTRules.h"
  43. #endif
  44.  
  45. #include <stdio.h>
  46.  
  47. #include "HTList.h"
  48. #include "HText.h"    /* See bugs above */
  49. #include "HTAlert.h"
  50.  
  51.  
  52. /*    These flags may be set to modify the operation of this module
  53. */
  54. PUBLIC char * HTClientHost = 0;    /* Name of remote login host if any */
  55. PUBLIC FILE * logfile = 0;    /* File to which to output one-liners */
  56. PUBLIC BOOL HTSecure = NO;    /* Disable access for telnet users? */
  57.  
  58. /*    To generate other things, play with these:
  59. */
  60.  
  61. PUBLIC HTFormat HTOutputFormat = NULL;
  62. PUBLIC HTStream* HTOutputStream = NULL;    /* For non-interactive, set this */ 
  63.  
  64. PRIVATE HTList * protocols = NULL;   /* List of registered protocol descriptors */
  65.  
  66.  
  67. /*    Register a Protocol                HTRegisterProtocol
  68. **    -------------------
  69. */
  70.  
  71. PUBLIC BOOL HTRegisterProtocol(protocol)
  72.     HTProtocol * protocol;
  73. {
  74.     if (!protocols) protocols = HTList_new();
  75.     HTList_addObject(protocols, protocol);
  76.     return YES;
  77. }
  78.  
  79.  
  80. /*    Register all known protocols
  81. **    ----------------------------
  82. **
  83. **    Add to or subtract from this list if you add or remove protocol modules.
  84. **    This routine is called the first time the protocol list is needed,
  85. **    unless any protocols are already registered, in which case it is not called.
  86. **    Therefore the application can override this list.
  87. **
  88. **    Compiling with NO_INIT prevents all known protocols from being forced
  89. **    in at link time.
  90. */
  91. #ifndef NO_INIT
  92. PRIVATE void HTAccessInit NOARGS            /* Call me once */
  93. {
  94. GLOBALREF HTProtocol HTTP, HTFile, HTTelnet, HTTn3270, HTRlogin;
  95. #ifndef DECNET
  96. GLOBALREF  HTProtocol HTFTP, HTNews, HTGopher;
  97. #ifdef DIRECT_WAIS
  98. GLOBALREF  HTProtocol HTWAIS;
  99. #endif
  100.     HTRegisterProtocol(&HTFTP);
  101.     HTRegisterProtocol(&HTNews);
  102.     HTRegisterProtocol(&HTGopher);
  103. #ifdef DIRECT_WAIS
  104.     HTRegisterProtocol(&HTWAIS);
  105. #endif
  106. #endif
  107.  
  108.     HTRegisterProtocol(&HTTP);
  109.     HTRegisterProtocol(&HTFile);
  110.     HTRegisterProtocol(&HTTelnet);
  111.     HTRegisterProtocol(&HTTn3270);
  112.     HTRegisterProtocol(&HTRlogin);
  113. }
  114. #endif
  115.  
  116.  
  117. /*        Find physical name and access protocol
  118. **        --------------------------------------
  119. **
  120. **
  121. ** On entry,
  122. **    addr        must point to the fully qualified hypertext reference.
  123. **    anchor        a pareent anchor with whose address is addr
  124. **
  125. ** On exit,
  126. **    returns        HT_NO_ACCESS        Error has occured.
  127. **            HT_OK            Success
  128. **
  129. */
  130. PRIVATE int get_physical ARGS2(
  131.     CONST char *,        addr,
  132.     HTParentAnchor *,    anchor)
  133. {
  134.     char * access=0;    /* Name of access method */
  135.     char * physical = 0;
  136.     
  137. #ifndef NO_RULES
  138.     physical = HTTranslate(addr);
  139.     if (!physical) {
  140.     return HT_FORBIDDEN;
  141.     }
  142.     HTAnchor_setPhysical(anchor, physical);
  143.     free(physical);            /* free our copy */
  144. #else
  145.     HTAnchor_setPhysical(anchor, addr);
  146. #endif
  147.  
  148.     access =  HTParse(HTAnchor_physical(anchor),
  149.             "file:", PARSE_ACCESS);
  150.  
  151. /*    Check whether gateway access has been set up for this
  152. **
  153. **    This function can be replaced by the rule system above.
  154. */
  155. #define USE_GATEWAYS
  156. #ifdef USE_GATEWAYS
  157.     {
  158.     /*
  159.      *    Scope in our global proxy variables.  Would include, but
  160.      *     CPP header.
  161.      */
  162.     extern char *cp_http_proxy;
  163.     extern char *cp_gopher_proxy;
  164.     extern char *cp_ftp_proxy;
  165.     extern char *cp_wais_proxy;
  166.     extern BOOL B_proxy;
  167.     auto char *cp_proxy = NULL;
  168.  
  169.     /*
  170.      *    Check for gateways.
  171.      */
  172.     char * gateway_parameter, *gateway;
  173.     gateway_parameter = (char *)malloc(strlen(access)+20);
  174.     if (gateway_parameter == NULL) outofmem(__FILE__, "HTLoad");
  175.     strcpy(gateway_parameter, "WWW_");
  176.     strcat(gateway_parameter, access);
  177.     strcat(gateway_parameter, "_GATEWAY");
  178.     gateway = (char *)getenv(gateway_parameter); /* coerce for decstation */
  179.     free(gateway_parameter);
  180.  
  181.     /*
  182.      *    Reset if we are using a proxy.
  183.      *     See if we are using a proxy server for this type of access.
  184.      */
  185.     B_proxy = FALSE;
  186.     if(cp_http_proxy != NULL && !strcmp(access, "http"))    {
  187.         cp_proxy = cp_http_proxy;
  188.     }
  189.     else if(cp_gopher_proxy != NULL && !strcmp(access, "gopher"))    {
  190.         cp_proxy = cp_http_proxy;
  191.     }
  192.     else if(cp_wais_proxy != NULL && !strcmp(access, "wais"))    {
  193.         cp_proxy = cp_http_proxy;
  194.     }
  195.     else if(cp_ftp_proxy != NULL && !strcmp(access, "ftp"))    {
  196.         cp_proxy = cp_http_proxy;
  197.     }
  198.  
  199. #ifndef DIRECT_WAIS
  200.     if (!gateway && 0==strcmp(access, "wais")) {
  201.         gateway = DEFAULT_WAIS_GATEWAY;
  202.     }
  203. #endif /* !DIRECT_WAIS */
  204.  
  205.     /*
  206.      *    Proxy servers have higher precedence than gateways.
  207.      */
  208.     if(cp_proxy != NULL)    {
  209.         auto char *cp_newaddr = NULL;
  210.  
  211.         StrAllocCopy(cp_newaddr, cp_proxy);
  212.         StrAllocCat(cp_newaddr, addr);
  213.         B_proxy = TRUE;
  214.         HTAnchor_setPhysical(anchor, cp_newaddr);
  215.         free(cp_newaddr);
  216.         free(access);
  217.  
  218.         access = HTParse(HTAnchor_physical(anchor), "http:",
  219.             PARSE_ACCESS);
  220.     }
  221.     else if(gateway) {
  222.         char * path = HTParse(addr, "",
  223.         PARSE_HOST + PARSE_PATH + PARSE_PUNCTUATION);
  224.         /* Chop leading / off to make host into part of path */
  225.         char * gatewayed = HTParse(path+1, gateway, PARSE_ALL);
  226.         free(path);
  227.             HTAnchor_setPhysical(anchor, gatewayed);
  228.         free(gatewayed);
  229.         free(access);
  230.         
  231.             access =  HTParse(HTAnchor_physical(anchor),
  232.             "http:", PARSE_ACCESS);
  233.     }
  234.     }
  235. #endif /* USE_GATEWAYS */
  236.  
  237.  
  238.  
  239. /*    Search registered protocols to find suitable one
  240. */
  241.     {
  242.     int i, n;
  243. #ifndef NO_INIT
  244.     if (!protocols) HTAccessInit();
  245. #endif
  246.     n = HTList_count(protocols);
  247.     for (i=0; i<n; i++) {
  248.         HTProtocol *p = HTList_objectAt(protocols, i);
  249.         if (strcmp(p->name, access)==0) {
  250.         HTAnchor_setProtocol(anchor, p);
  251.         free(access);
  252.         return (HT_OK);
  253.         }
  254.     }
  255.     }
  256.  
  257.     free(access);
  258.     return HT_NO_ACCESS;
  259. }
  260.  
  261.  
  262. /*        Load a document
  263. **        ---------------
  264. **
  265. **    This is an internal routine, which has an address AND a matching
  266. **    anchor.  (The public routines are called with one OR the other.)
  267. **
  268. ** On entry,
  269. **    addr        must point to the fully qualified hypertext reference.
  270. **    anchor        a pareent anchor with whose address is addr
  271. **
  272. ** On exit,
  273. **    returns        <0        Error has occured.
  274. **            HT_LOADED    Success
  275. **            HT_NO_DATA    Success, but no document loaded.
  276. **                    (telnet sesssion started etc)
  277. **
  278. */
  279. PRIVATE int HTLoad ARGS4(
  280.     CONST char *,        addr,
  281.     HTParentAnchor *,    anchor,
  282.     HTFormat,        format_out,
  283.     HTStream *,        sink)
  284. {
  285.     HTProtocol* p;
  286.     int status = get_physical(addr, anchor);
  287.     if (status == HT_FORBIDDEN) {
  288.         return HTLoadError(sink, 500, "Access forbidden by rule");
  289.     }
  290.     if (status < 0) return status;    /* Can't resolve or forbidden */
  291.     
  292.     p = HTAnchor_protocol(anchor);
  293.     return (*(p->load))(HTAnchor_physical(anchor),
  294.                 anchor, format_out, sink);
  295. }
  296.  
  297.  
  298. /*        Get a save stream for a document
  299. **        --------------------------------
  300. */
  301. PUBLIC HTStream *HTSaveStream ARGS1(HTParentAnchor *, anchor)
  302. {
  303.     HTProtocol * p = HTAnchor_protocol(anchor);
  304.     if (!p) return NULL;
  305.     
  306.     return (*p->saveStream)(anchor);
  307.     
  308. }
  309.  
  310.  
  311. /*        Load a document - with logging etc
  312. **        ----------------------------------
  313. **
  314. **    - Checks or documents already loaded
  315. **    - Logs the access
  316. **    - Allows stdin filter option
  317. **    - Trace ouput and error messages
  318. **
  319. **    On Entry,
  320. **      anchor        is the node_anchor for the document
  321. **        full_address      The address of the document to be accessed.
  322. **        filter            if YES, treat stdin as HTML
  323. **
  324. **    On Exit,
  325. **        returns    YES     Success in opening document
  326. **                   NO      Failure 
  327. **
  328. */
  329.  
  330. PRIVATE BOOL HTLoadDocument ARGS4(
  331.     CONST char *,        full_address,
  332.     HTParentAnchor *,    anchor,
  333.     HTFormat,        format_out,
  334.     HTStream*,        sink)
  335.  
  336. {
  337.     int            status;
  338.     HText *    text;
  339. #ifndef RELEASE
  340.     if (TRACE) fprintf (stderr,
  341.       "HTAccess: loading document %s\n", full_address);
  342. #endif /* RELEASE */
  343.     if (text=(HText *)HTAnchor_document(anchor)) {    /* Already loaded */
  344. #ifndef RELEASE
  345.     if (TRACE) fprintf(stderr, "HTAccess: Document already in memory.\n");
  346. #endif /* RELEASE */
  347.     HText_select(text);
  348.     return YES;
  349.     }
  350.  
  351.     status = HTLoad(full_address, anchor, format_out, sink);
  352.  
  353.     
  354. /*    Log the access if necessary
  355. */
  356.     if (logfile) {
  357.     time_t theTime;
  358.     time(&theTime);
  359.     fprintf(logfile, "%24.24s %s %s %s\n",
  360.         ctime(&theTime),
  361.         HTClientHost ? HTClientHost : "local",
  362.         status<0 ? "FAIL" : "GET",
  363.         full_address);
  364.     fflush(logfile);    /* Actually update it on disk */
  365. #ifndef RELEASE
  366.     if (TRACE) fprintf(stderr, "Log: %24.24s %s %s %s\n",
  367.         ctime(&theTime),
  368.         HTClientHost ? HTClientHost : "local",
  369.         status<0 ? "FAIL" : "GET",
  370.         full_address);
  371. #endif /* RELEASE */
  372.     }
  373.     
  374.  
  375.     if (status == HT_LOADED) {
  376. #ifndef RELEASE
  377.     if (TRACE) {
  378.         fprintf(stderr, "HTAccess: accessed `%s'.\n", full_address);
  379.     }
  380. #endif /* RELEASE */
  381.     return YES;
  382.     }
  383.  
  384.     if (status == HT_NO_DATA) {
  385. #ifndef RELEASE
  386.     if (TRACE) {
  387.         fprintf(stderr,
  388.         "HTAccess:  accessed no data left `%s'.\n", full_address);
  389.     }
  390. #endif /* RELEASE */
  391.     return NO;
  392.     }
  393.     
  394.     if (status<0) {              /* Failure in accessing a document */
  395. #ifdef CURSES
  396.     user_message("Can't access `%s'", full_address);
  397. #else
  398. #ifndef RELEASE
  399.     if (TRACE) fprintf(stderr,
  400.         "HTAccess: Can't access `%s'\n", full_address);
  401. #endif /* RELEASE */
  402. #endif
  403.     HTLoadError(sink, 500, "Unable to access document.");
  404.     return NO;
  405.     }
  406.  
  407.     /* If you get this, then please find which routine is returning
  408.        a positive unrecognised error code! */
  409.  
  410.     fprintf(stderr,
  411.     "**** HTAccess: socket or file number returned by obsolete load routine!\n");
  412.     fprintf(stderr,
  413.     "**** HTAccess: Internal software error. Please mail www-bug@info.cern.ch!\n");
  414. #ifndef MSDOS
  415.     exit(-6996);
  416. #else
  417.     fprintf(stderr, "WWW htaccess.c exit(-6996); denied by doslynx.\n");
  418.     fprintf(stderr, "Consider leaving the application.\n");
  419. #endif /* MSDOS */
  420.  
  421. } /* HTLoadDocument */
  422.  
  423.  
  424.  
  425. extern BOOL HTLoadAbsolute(const char *cp_addr)    {
  426. /*
  427.  *    Purpose:    Cause the load of a full URL (absolute address).
  428.  *    Arguments:    cp_addr    The full URL to load.
  429.  *    Return Value:    BOOL    YES    The URL was successfully loaded
  430.  *                    or is already currently loaded.
  431.  *                NO    The URL was not loaded and is not
  432.  *                    currently loaded.
  433.  *    Remarks/Portability/Dependencies/Restrictions:
  434.  *    Revision History:
  435.  *        ??-??-??    created
  436.  *        03-28-94    modified for DosLynx
  437.  */
  438.     return(HTLoadDocument(cp_addr, HTAnchor_parent(HTAnchor_findAddress(
  439.         cp_addr)), HTOutputFormat ? HTOutputFormat : WWW_PRESENT,
  440.         HTOutputStream));
  441. }
  442.  
  443.  
  444. /*        Load a document from absolute name to stream
  445. **        --------------------------------------------
  446. **
  447. **    On Entry,
  448. **        addr     The absolute address of the document to be accessed.
  449. **        sink     if non-NULL, send data down this stream
  450. **
  451. **    On Exit,
  452. **        returns    YES     Success in opening document
  453. **                   NO      Failure 
  454. **
  455. **
  456. */
  457.  
  458. PUBLIC BOOL HTLoadToStream ARGS3(
  459.         CONST char *,    addr,
  460.         BOOL,         filter,
  461.         HTStream *,     sink)
  462. {
  463.    return HTLoadDocument(addr,
  464.                HTAnchor_parent(HTAnchor_findAddress(addr)),
  465.                    HTOutputFormat ? HTOutputFormat : WWW_PRESENT,
  466.             sink);
  467. }
  468.  
  469.  
  470.  
  471.  
  472. /*        Load a document from relative name
  473. **        ---------------
  474. **
  475. **    On Entry,
  476. **        relative_name     The relative address of the document
  477. **                  to be accessed.
  478. **
  479. **    On Exit,
  480. **        returns    YES     Success in opening document
  481. **                   NO      Failure 
  482. **
  483. **
  484. */
  485.  
  486. PUBLIC BOOL HTLoadRelative ARGS2(
  487.         CONST char *,        relative_name,
  488.         HTParentAnchor *,    here)
  489. {
  490.     char *         full_address = 0;
  491.     BOOL               result;
  492.     char *         mycopy = 0;
  493.     char *         stripped = 0;
  494.     char *        current_address = HTAnchor_address((HTAnchor*)here);
  495.  
  496.     StrAllocCopy(mycopy, relative_name);
  497.  
  498.     stripped = HTStrip(mycopy);
  499.     full_address = HTParse(stripped,
  500.            current_address,
  501.            PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
  502.     result = HTLoadAbsolute(full_address);
  503.     free(full_address);
  504.     free(current_address);
  505.     free(mycopy);  /* Memory leak fixed 10/7/92 -- JFG */
  506.     return result;
  507. }
  508.  
  509.  
  510. /*        Load if necessary, and select an anchor
  511. **        --------------------------------------
  512. **
  513. **    On Entry,
  514. **        destination              The child or parenet anchor to be loaded.
  515. **
  516. **    On Exit,
  517. **        returns    YES     Success
  518. **                   NO      Failure 
  519. **
  520. */
  521.  
  522. PUBLIC BOOL HTLoadAnchor ARGS1(HTAnchor *,destination)
  523. {
  524.     HTParentAnchor * parent;
  525.     BOOL loaded = NO;
  526.     if (!destination) return NO;    /* No link */
  527.     
  528.     parent  = HTAnchor_parent(destination);
  529.     
  530.     if (HTAnchor_document(parent) == NULL) {    /* If not alread loaded */
  531.                             /* TBL 921202 */
  532.  
  533.         BOOL result;
  534.         char * address = HTAnchor_address((HTAnchor*) parent);
  535.     result = HTLoadDocument(address, parent,
  536.         HTOutputFormat ? HTOutputFormat : WWW_PRESENT,
  537.         HTOutputStream);
  538.     free(address);
  539.     if (!result) return NO;
  540.     loaded = YES;
  541.     }
  542.     
  543.     {
  544.     HText *text = (HText*)HTAnchor_document(parent);
  545.     if (destination != (HTAnchor *)parent) {  /* If child anchor */
  546.         HText_selectAnchor(text, 
  547.             (HTChildAnchor*)destination); /* Double display? @@ */
  548.     } else {
  549.         if (!loaded) HText_select(text);
  550.     }
  551.     }
  552.     return YES;
  553.     
  554. } /* HTLoadAnchor */
  555.  
  556.  
  557. /*        Search
  558. **        ------
  559. **  Performs a keyword search on word given by the user. Adds the keyword to 
  560. **  the end of the current address and attempts to open the new address.
  561. **
  562. **  On Entry,
  563. **       *keywords      space-separated keyword list or similar search list
  564. **    here        is anchor search is to be done on.
  565. */
  566.  
  567. PRIVATE char hex(i)
  568.     int i;
  569. {
  570.     char * hexchars = "0123456789ABCDEF";
  571.     return hexchars[i];
  572. }
  573.  
  574. extern BOOL HTSearch(const char *cp_keywords, HTParentAnchor *HTPAp_here)
  575. {
  576. #define acceptable \
  577. "1234567890abcdefghijlkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_"
  578.  
  579.     auto char *q, *u;
  580.     auto const char *p, *s, *e;        /* Pointers into keywords */
  581.     auto char *cp_address = NULL;
  582.     auto BOOL B_result;
  583.     auto char *cp_escaped = (char *)malloc(strlen(cp_keywords) * 3 + 1);
  584.  
  585.     static CONST BOOL isAcceptable[96] =
  586.     /*   0 1 2 3 4 5 6 7 8 9 A B C D E F */
  587.     {    0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,0,    /* 2x   !"#$%&'()*+,-./     */
  588.      1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,    /* 3x  0123456789:;<=>?     */
  589.      1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,    /* 4x  @ABCDEFGHIJKLMNO  */
  590.      1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,    /* 5X  PQRSTUVWXYZ[\]^_     */
  591.      0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,    /* 6x  `abcdefghijklmno     */
  592.      1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0 };    /* 7X  pqrstuvwxyz{\}~    DEL */
  593.  
  594.     if(cp_escaped == NULL)    {
  595.         outofmem(__FILE__, "HTSearch");
  596.     }
  597.  
  598.     /*    Convert spaces to + and hex escape unacceptable characters
  599.     */
  600.     for(s = cp_keywords; *s != '\0' && WHITE(*s); s++)    {
  601.         /* scan NULL body */;    /* Skip white space */
  602.     }
  603.     for(e = s + strlen(s); e > s && WHITE(*(e - 1)); e--)    {
  604.         /* scan NULL body */;    /* Skip trailers */
  605.     }
  606.  
  607.     for(q = cp_escaped, p = s; p < e; p++)    {    /* scan stripped field */
  608.         auto int c = (int)TOASCII(*p);
  609.  
  610.         if(WHITE(*p))    {
  611.             *q++ = '+';
  612.         }
  613.         else if(c >= 32 && c <= (char)127 && isAcceptable[c - 32])
  614.         {
  615.             *q++ = *p;        /* 930706 TBL for MVS bug */
  616.         }
  617.         else    {
  618.             *q++ = '%';
  619.             *q++ = hex(c / 16);
  620.             *q++ = hex(c % 16);
  621.         }
  622.     } /* Loop over string */
  623.  
  624.     *q = '\0';    /* teminate the string. */
  625.  
  626.     /*
  627.      *    Allocate a string to our index server.
  628.      */
  629.     StrAllocCopy(cp_address, HTPAp_here->isIndexAction);
  630.  
  631.     u = strchr(cp_address, '?');    /* Find old search string */
  632.     if(u != NULL)    {
  633.         *u = '\0';                /* Chop old search off */
  634.     }
  635.  
  636.     StrAllocCat(cp_address, "?");
  637.     StrAllocCat(cp_address, cp_escaped);
  638.  
  639.     free(cp_escaped);
  640.  
  641.     B_result = HTLoadRelative(cp_address, HTPAp_here);
  642.  
  643.     free(cp_address);
  644.  
  645.     return(B_result);
  646. }
  647.  
  648.  
  649. /*        Search Given Indexname
  650. **        ------
  651. **  Performs a keyword search on word given by the user. Adds the keyword to 
  652. **  the end of the current address and attempts to open the new address.
  653. **
  654. **  On Entry,
  655. **       *keywords      space-separated keyword list or similar search list
  656. **    *addres        is name of object search is to be done on.
  657. */
  658.  
  659. PUBLIC BOOL HTSearchAbsolute ARGS2(
  660.     CONST char *,     keywords,
  661.     CONST char *,     indexname)
  662. {
  663.     HTParentAnchor * anchor =
  664.         (HTParentAnchor*) HTAnchor_findAddress(indexname);
  665.     return HTSearch(keywords, anchor);
  666. }
  667.  
  668.  
  669. /*        Generate the anchor for the home page
  670. **        -------------------------------------
  671. **
  672. **    As it involves file access, this should only be done once
  673. **    when the program first runs.
  674. **    This is a default algorithm -- browser don't HAVE to use this.
  675. **    But consistency betwen browsers is STRONGLY recommended!
  676. **
  677. **    Priority order is:
  678. **
  679. **        1    WWW_HOME environment variable (logical name, etc)
  680. **        2    ~/WWW/default.html
  681. **        3    /usr/local/bin/default.html
  682. **        4    http://info.cern.ch/default.html
  683. **
  684. */
  685. PUBLIC HTParentAnchor * HTHomeAnchor NOARGS
  686. {
  687.     char * my_home_document = NULL;
  688.     char * home = (char *)getenv(LOGICAL_DEFAULT);
  689.     char * ref;
  690.     HTParentAnchor * anchor;
  691.     
  692.     if (home) {
  693.         StrAllocCopy(my_home_document, home);
  694.     
  695. /*     Someone telnets in, they get a special home.
  696. */
  697. #define MAX_FILE_NAME 1024                    /* @@@ */
  698.     } else  if (HTClientHost) {            /* Telnet server */
  699.         FILE * fp = fopen(REMOTE_POINTER, "r");
  700.     char * status;
  701.     if (fp) {
  702.         my_home_document = (char*) malloc(MAX_FILE_NAME);
  703.         status = fgets(my_home_document, MAX_FILE_NAME, fp);
  704.         if (!status) {
  705.             free(my_home_document);
  706.         my_home_document = NULL;
  707.         }
  708.         fclose(fp);
  709.     }
  710.     if (!my_home_document) StrAllocCopy(my_home_document, REMOTE_ADDRESS);
  711.     }
  712.  
  713.     
  714.  
  715. #ifdef unix
  716.  
  717.     if (!my_home_document) {
  718.     FILE * fp = NULL;
  719.     CONST char * home =  (CONST char*)getenv("HOME");
  720.     if (home) { 
  721.         my_home_document = (char *)malloc(
  722.         strlen(home)+1+ strlen(PERSONAL_DEFAULT)+1);
  723.         if (my_home_document == NULL) outofmem(__FILE__, "HTLocalName");
  724.         sprintf(my_home_document, "%s/%s", home, PERSONAL_DEFAULT);
  725.         fp = fopen(my_home_document, "r");
  726.     }
  727.     
  728.     if (!fp) {
  729.         StrAllocCopy(my_home_document, LOCAL_DEFAULT_FILE);
  730.         fp = fopen(my_home_document, "r");
  731.     }
  732.     if (fp) {
  733.         fclose(fp);
  734.     } else {
  735. #ifndef RELEASE
  736.     if (TRACE) fprintf(stderr,
  737.         "HTBrowse: No local home document ~/%s or %s\n",
  738.         PERSONAL_DEFAULT, LOCAL_DEFAULT_FILE);
  739.         free(my_home_document);
  740.         my_home_document = NULL;
  741. #endif /* RELEASE */
  742.     }
  743.     }
  744. #endif
  745.     ref = HTParse( my_home_document ?    my_home_document :
  746.                 HTClientHost ? REMOTE_ADDRESS
  747.                 : LAST_RESORT,
  748.             "file:",
  749.             PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
  750.     if (my_home_document) {
  751. #ifndef RELEASE
  752.     if (TRACE) fprintf(stderr,
  753.         "HTAccess: Using custom home page %s i.e. address %s\n",
  754.         my_home_document, ref);
  755. #endif /* RELEASE */
  756.     free(my_home_document);
  757.     }
  758.     anchor = (HTParentAnchor*) HTAnchor_findAddress(ref);
  759.     free(ref);
  760.     return anchor;
  761. }
  762.  
  763.  
  764.