home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / infoserv / www / cern / proxy-support / Mosaic-2.4 / HTAccess.c.Z / HTAccess.c
Encoding:
C/C++ Source or Header  |  1994-05-11  |  13.2 KB  |  549 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://www.ncsa.uiuc.edu:8001/"
  25. #endif
  26.  
  27. /* Implements:
  28. */
  29. #include "HTAccess.h"
  30.  
  31. /* Uses:
  32. */
  33.  
  34. #include "HTParse.h"
  35. #include "HTUtils.h"
  36. #include "HTML.h"        /* SCW */
  37.  
  38. #include <stdio.h>
  39.  
  40. #include "HTList.h"
  41. #include "HText.h"    /* See bugs above */
  42. #include "HTAlert.h"
  43.  
  44. /* #define TRACE 1 */
  45.  
  46.  
  47. extern char *mo_check_for_proxy (char *);
  48.  
  49.  
  50.  
  51. /*    These flags may be set to modify the operation of this module
  52. */
  53. PUBLIC char * HTClientHost = 0;    /* Name of remote login host if any */
  54.  
  55. /*    To generate other things, play with these:
  56. */
  57.  
  58. PUBLIC HTFormat HTOutputFormat = NULL;
  59. PUBLIC HTStream* HTOutputStream = NULL;    /* For non-interactive, set this */ 
  60.  
  61. PUBLIC BOOL using_gateway = NO; /* are we using a gateway? */
  62. PUBLIC BOOL using_proxy = NO; /* are we using a proxy gateway? */
  63.  
  64.  
  65. PRIVATE HTList * protocols = NULL;   /* List of registered protocol descriptors */
  66.  
  67.  
  68. /*    Register a Protocol                HTRegisterProtocol
  69. **    -------------------
  70. */
  71.  
  72. PUBLIC BOOL HTRegisterProtocol(protocol)
  73.     HTProtocol * protocol;
  74. {
  75.     if (!protocols) protocols = HTList_new();
  76.     HTList_addObject(protocols, protocol);
  77.     return YES;
  78. }
  79.  
  80.  
  81. /*    Register all known protocols
  82. **    ----------------------------
  83. **
  84. **    Add to or subtract from this list if you add or remove protocol modules.
  85. **    This routine is called the first time the protocol list is needed,
  86. **    unless any protocols are already registered, in which case it is not called.
  87. **    Therefore the application can override this list.
  88. */
  89. PRIVATE void HTAccessInit NOARGS            /* Call me once */
  90. {
  91. extern HTProtocol HTTP, HTFile, HTTelnet, HTTn3270, HTRlogin;
  92. extern HTProtocol HTFTP, HTNews, HTGopher;
  93. #ifdef DIRECT_WAIS
  94. extern HTProtocol HTWAIS;
  95. #endif
  96.     HTRegisterProtocol(&HTFTP);
  97.     HTRegisterProtocol(&HTNews);
  98.     HTRegisterProtocol(&HTGopher);
  99. #ifdef DIRECT_WAIS
  100.     HTRegisterProtocol(&HTWAIS);
  101. #endif
  102.  
  103.     HTRegisterProtocol(&HTTP);
  104.     HTRegisterProtocol(&HTFile);
  105.     HTRegisterProtocol(&HTTelnet);
  106.     HTRegisterProtocol(&HTTn3270);
  107.     HTRegisterProtocol(&HTRlogin);
  108. }
  109.  
  110.  
  111. /*                            override_proxy()
  112. **
  113. **    Check the no_proxy environment variable to get the list
  114. **    of hosts for which proxy server is not consulted.
  115. **
  116. **    no_proxy is a comma- or space-separated list of machine
  117. **    or domain names, with optional :port part.  If no :port
  118. **    part is present, it applies to all ports on that domain.
  119. **
  120. **    Example:
  121. **        no_proxy="cern.ch,some.domain:8001"
  122. **
  123. */
  124. PRIVATE BOOL override_proxy ARGS1(CONST char *, addr)
  125. {
  126.     CONST char * no_proxy = getenv("no_proxy");
  127.     char * p = NULL;
  128.     char * host = NULL;
  129.     int port = 0;
  130.     int h_len = 0;
  131.  
  132.     if (!no_proxy || !addr || !(host = HTParse(addr, "", PARSE_HOST)))
  133.     return NO;
  134.     if (!*host) { free(host); return NO; }
  135.  
  136.     if (p = strchr(host, ':')) {    /* Port specified */
  137.     *p++ = 0;            /* Chop off port */
  138.     port = atoi(p);
  139.     }
  140.     else {                /* Use default port */
  141.     char * access = HTParse(addr, "", PARSE_ACCESS);
  142.     if (access) {
  143.         if        (!strcmp(access,"http"))    port = 80;
  144.         else if (!strcmp(access,"gopher"))    port = 70;
  145.         else if (!strcmp(access,"ftp"))    port = 21;
  146.         free(access);
  147.     }
  148.     }
  149.     if (!port) port = 80;        /* Default */
  150.     h_len = strlen(host);
  151.  
  152.     while (*no_proxy) {
  153.     CONST char * end;
  154.     CONST char * colon = NULL;
  155.     int templ_port = 0;
  156.     int t_len;
  157.  
  158.     while (*no_proxy && (WHITE(*no_proxy) || *no_proxy==','))
  159.         no_proxy++;            /* Skip whitespace and separators */
  160.  
  161.     end = no_proxy;
  162.     while (*end && !WHITE(*end) && *end != ',') {    /* Find separator */
  163.         if (*end==':') colon = end;            /* Port number given */
  164.         end++;
  165.     }
  166.  
  167.     if (colon) {
  168.         templ_port = atoi(colon+1);
  169.         t_len = colon - no_proxy;
  170.     }
  171.     else {
  172.         t_len = end - no_proxy;
  173.     }
  174.  
  175.     if ((!templ_port || templ_port == port)  &&
  176.         (t_len > 0  &&  t_len <= h_len  &&
  177.          !strncmp(host + h_len - t_len, no_proxy, t_len))) {
  178.         free(host);
  179.         return YES;
  180.     }
  181.     if (*end) no_proxy = end+1;
  182.     else break;
  183.     }
  184.  
  185.     free(host);
  186.     return NO;
  187. }
  188.  
  189.  
  190. /*        Find physical name and access protocol
  191. **        --------------------------------------
  192. **
  193. **
  194. ** On entry,
  195. **    addr        must point to the fully qualified hypertext reference.
  196. **    anchor        a pareent anchor with whose address is addr
  197. **
  198. ** On exit,
  199. **    returns        HT_NO_ACCESS        Error has occured.
  200. **            HT_OK            Success
  201. **
  202. */
  203. PRIVATE int get_physical ARGS2(
  204.     char *,        addr,
  205.     HTParentAnchor *,    anchor)
  206. {
  207.     char * access=0;    /* Name of access method */
  208.     char * physical = 0;
  209.     
  210.     HTAnchor_setPhysical(anchor, addr);
  211.  
  212.     access =  HTParse(HTAnchor_physical(anchor),
  213.             "file:", PARSE_ACCESS);
  214.  
  215. /*    Check whether gateway access has been set up for this
  216. */
  217. #define USE_GATEWAYS
  218. #ifdef USE_GATEWAYS
  219.  
  220.     /* make sure the using_proxy variable is false */
  221.     using_proxy = NO;
  222.  
  223.     if (!override_proxy(addr)) {
  224.     char *gateway_parameter, *gateway, *proxy;
  225.  
  226.     /* search for gateways */
  227.     gateway_parameter = (char *)malloc(strlen(access)+20);
  228.     if (gateway_parameter == NULL) outofmem(__FILE__, "HTLoad");
  229.     strcpy(gateway_parameter, "WWW_");
  230.     strcat(gateway_parameter, access);
  231.     strcat(gateway_parameter, "_GATEWAY");
  232.     gateway = (char *)getenv(gateway_parameter); /* coerce for decstation */
  233.  
  234.     /* search for proxy servers */
  235.     strcpy(gateway_parameter, access);
  236.     strcat(gateway_parameter, "_proxy");
  237.     proxy = (char *)getenv(gateway_parameter);
  238.     free(gateway_parameter);
  239.  
  240.     /*
  241.      * The environment variables have precedence over the X resources,
  242.      * But if we got no proxy from them, check the X resources now.
  243.      */
  244.     if ((proxy == NULL)||(proxy[0] == '\0'))
  245.     {
  246.         proxy = mo_check_for_proxy(access);
  247.     }
  248.     
  249. #ifndef DIRECT_WAIS
  250.     if (!gateway && 0==strcmp(access, "wais")) {
  251.         gateway = DEFAULT_WAIS_GATEWAY;
  252.     }
  253. #endif
  254.  
  255.     /* proxy servers have precedence over gateway servers */
  256.     if (proxy) {
  257.         char * gatewayed;
  258.  
  259.         gatewayed = NULL;
  260.         StrAllocCopy(gatewayed,proxy);
  261.         StrAllocCat(gatewayed,addr);
  262.         using_proxy = YES;
  263.         HTAnchor_setPhysical(anchor, gatewayed);
  264.         free(gatewayed);
  265.         free(access);
  266.  
  267.         access =  HTParse(HTAnchor_physical(anchor),
  268.             "http:", PARSE_ACCESS);
  269.     } else if (gateway) {
  270.         char * gatewayed;
  271.  
  272.         gatewayed = NULL;
  273.         StrAllocCopy(gatewayed,gateway);
  274.         StrAllocCat(gatewayed,addr);
  275.         using_gateway = YES;
  276.         HTAnchor_setPhysical(anchor, gatewayed);
  277.         free(gatewayed);
  278.         free(access);
  279.  
  280.         access =  HTParse(HTAnchor_physical(anchor),
  281.             "http:", PARSE_ACCESS);
  282.     } else {
  283.         using_proxy = NO;
  284.         using_gateway = NO;
  285.         }
  286.     }
  287. #endif
  288.  
  289.  
  290.  
  291. /*    Search registered protocols to find suitable one
  292. */
  293.     {
  294.     int i, n;
  295.         if (!protocols) HTAccessInit();
  296.     n = HTList_count(protocols);
  297.     for (i=0; i<n; i++) {
  298.         HTProtocol *p = HTList_objectAt(protocols, i);
  299.         if (strcmp(p->name, access)==0) {
  300.         HTAnchor_setProtocol(anchor, p);
  301.         free(access);
  302.         return (HT_OK);
  303.         }
  304.     }
  305.     }
  306.  
  307.     free(access);
  308.     return HT_NO_ACCESS;
  309. }
  310.  
  311.  
  312. /*        Load a document
  313. **        ---------------
  314. **
  315. **    This is an internal routine, which has an address AND a matching
  316. **    anchor.  (The public routines are called with one OR the other.)
  317. **
  318. ** On entry,
  319. **    addr        must point to the fully qualified hypertext reference.
  320. **    anchor        a pareent anchor with whose address is addr
  321. **
  322. ** On exit,
  323. **    returns        <0        Error has occured.
  324. **            HT_LOADED    Success
  325. **            HT_NO_DATA    Success, but no document loaded.
  326. **                    (telnet sesssion started etc)
  327. **
  328. */
  329. PRIVATE int HTLoad ARGS4(
  330.     CONST char *,        addr,
  331.     HTParentAnchor *,    anchor,
  332.     HTFormat,        format_out,
  333.     HTStream *,        sink)
  334. {
  335.     HTProtocol* p;
  336.     int status = get_physical(addr, anchor);
  337.     if (status < 0) return status;    /* Can't resolve or forbidden */
  338.     
  339.     p = HTAnchor_protocol(anchor);
  340.     return (*(p->load))(HTAnchor_physical(anchor),
  341.                 anchor, format_out, sink);
  342. }
  343.  
  344.  
  345. /*        Get a save stream for a document
  346. **        --------------------------------
  347. */
  348. PUBLIC HTStream *HTSaveStream ARGS1(HTParentAnchor *, anchor)
  349. {
  350.     HTProtocol * p = HTAnchor_protocol(anchor);
  351.     if (!p) return NULL;
  352.     
  353.     return (*p->saveStream)(anchor);
  354.     
  355. }
  356.  
  357.  
  358. /*        Load a document - with logging etc
  359. **        ----------------------------------
  360. **
  361. **    - Checks or documents already loaded
  362. **    - Logs the access
  363. **    - Allows stdin filter option
  364. **    - Trace ouput and error messages
  365. **
  366. **    On Entry,
  367. **      anchor        is the node_anchor for the document
  368. **        full_address      The address of the document to be accessed.
  369. **        filter            if YES, treat stdin as HTML
  370. **
  371. **    On Exit,
  372. **        returns    1     Success in opening document
  373. **                   0     Failure 
  374. **                   -1    Interrupted
  375. **
  376. */
  377.  
  378. /* This is exported all the way to gui-documents.c at the moment,
  379.    to tell mo_load_window_text when to use a redirected URL instead. */
  380. char *use_this_url_instead;
  381.  
  382. PRIVATE int HTLoadDocument ARGS4(
  383.     CONST char *,        full_address,
  384.     HTParentAnchor *,    anchor,
  385.     HTFormat,        format_out,
  386.     HTStream*,        sink)
  387. {
  388.     int            status;
  389.     HText *    text;
  390.  
  391.     use_this_url_instead = NULL;
  392.  
  393.     /* We LOVE goto's! */
  394.   try_again:
  395.     if (TRACE) fprintf (stderr,
  396.       "HTAccess: loading document %s\n", full_address);
  397.  
  398.     status = HTLoad(full_address, anchor, format_out, sink);
  399.     
  400.     if (status == HT_LOADED) {
  401.     if (TRACE) {
  402.         fprintf(stderr, "HTAccess: `%s' has been accessed.\n",
  403.         full_address);
  404.     }
  405.     return 1;
  406.     }
  407.  
  408.     if (status == HT_REDIRECTING)
  409.       {
  410.         /* Exported from HTMIME.c, of all places. */
  411.         extern char *redirecting_url;
  412.         if (TRACE)
  413.           {
  414.             fprintf (stderr, "HTAccess: '%s' is a redirection URL.\n", 
  415.                      full_address);
  416.             fprintf (stderr, "HTAccess: Redirecting to '%s'\n", 
  417.                      redirecting_url);
  418.           }
  419.         full_address = redirecting_url;
  420.         use_this_url_instead = full_address;
  421.         goto try_again;
  422.       }
  423.  
  424.     if (status == HT_INTERRUPTED)
  425.       {
  426.         if (TRACE)
  427.           fprintf (stderr,
  428.                    "HTAccess: We were interrupted.\n");
  429.         return -1;
  430.       }
  431.     
  432.     if (status == HT_NO_DATA) {
  433.     if (TRACE) {
  434.         fprintf(stderr, 
  435.         "HTAccess: `%s' has been accessed, No data left.\n",
  436.         full_address);
  437.     }
  438.     return 0;
  439.     }
  440.     
  441.     if (status<0) {              /* Failure in accessing a document */
  442.     if (TRACE) fprintf(stderr, 
  443.                            "HTAccess: Can't access `%s'\n", full_address);
  444.     return 0;
  445.     }
  446.  
  447.     /* If you get this, then please find which routine is returning
  448.        a positive unrecognised error code! */
  449.  
  450.     if (TRACE)
  451.       fprintf(stderr,
  452.               "**** HTAccess: socket or file number %d returned by obsolete load routine!\n", status);
  453.     return 0;
  454.  
  455. } /* HTLoadDocument */
  456.  
  457.  
  458.  
  459. /*        Load a document from absolute name
  460. **        ---------------
  461. **
  462. **    On Entry,
  463. **        addr     The absolute address of the document to be accessed.
  464. **        filter   if YES, treat document as HTML
  465. **
  466. **    On Exit,
  467. **        returns    1     Success in opening document
  468. **                   0      Failure 
  469. **                   -1      Interrupted
  470. **
  471. **
  472. */
  473.  
  474. PUBLIC int HTLoadAbsolute ARGS1(CONST char *,addr)
  475. {
  476.    return HTLoadDocument( addr,
  477.                HTAnchor_parent(HTAnchor_findAddress(addr)),
  478.                    HTOutputFormat ? HTOutputFormat : WWW_PRESENT,
  479.             HTOutputStream);
  480. }
  481.  
  482.  
  483. /*        Load a document from absolute name to stream
  484. **        --------------------------------------------
  485. **
  486. **    On Entry,
  487. **        addr     The absolute address of the document to be accessed.
  488. **        sink     if non-NULL, send data down this stream
  489. **
  490. **    On Exit,
  491. **        returns    YES     Success in opening document
  492. **                   NO      Failure 
  493. **
  494. **
  495. */
  496.  
  497. PUBLIC BOOL HTLoadToStream ARGS3(
  498.         CONST char *,    addr,
  499.         BOOL,         filter,
  500.         HTStream *,     sink)
  501. {
  502.    return HTLoadDocument(addr,
  503.                HTAnchor_parent(HTAnchor_findAddress(addr)),
  504.                    HTOutputFormat ? HTOutputFormat : WWW_PRESENT,
  505.             sink);
  506. }
  507.  
  508.  
  509.  
  510.  
  511. /*        Load a document from relative name
  512. **        ---------------
  513. **
  514. **    On Entry,
  515. **        relative_name     The relative address of the document
  516. **                  to be accessed.
  517. **
  518. **    On Exit,
  519. **        returns    YES     Success in opening document
  520. **                   NO      Failure 
  521. **
  522. **
  523. */
  524.  
  525. PUBLIC BOOL HTLoadRelative ARGS2(
  526.         CONST char *,        relative_name,
  527.         HTParentAnchor *,    here)
  528. {
  529.     char *         full_address = 0;
  530.     BOOL               result;
  531.     char *         mycopy = 0;
  532.     char *         stripped = 0;
  533.     char *        current_address =
  534.                     HTAnchor_address((HTAnchor*)here);
  535.  
  536.     StrAllocCopy(mycopy, relative_name);
  537.  
  538.     stripped = HTStrip(mycopy);
  539.     full_address = HTParse(stripped,
  540.                current_address,
  541.            PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
  542.     result = HTLoadAbsolute(full_address);
  543.     free(full_address);
  544.     free(current_address);
  545.     free(mycopy);
  546.     return result;
  547. }
  548.  
  549.