"Fossies" - the Fresh Open Source Software Archive

Member "lynx2.9.0dev.1/WWW/Library/Implementation/HTFinger.c" (28 Nov 2013, 11051 Bytes) of package /linux/www/lynx2.9.0dev.1.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "HTFinger.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * $LynxId: HTFinger.c,v 1.31 2013/11/28 11:27:50 tom Exp $
    3  *
    4  *          FINGER ACCESS               HTFinger.c
    5  *          =============
    6  * Authors:
    7  *  ARB  Andrew Brooks
    8  *
    9  * History:
   10  *  21 Apr 94   First version (ARB, from HTNews.c by TBL)
   11  *  12 Mar 96   Made the URL and command buffering secure from
   12  *           stack modifications, beautified the HTLoadFinger()
   13  *           and response() functions, and added support for the
   14  *           following URL formats for sending a "", "/w",
   15  *           "username[@host]", or "/w username[@host]" command
   16  *           to the server:
   17  *          finger://host
   18  *          finger://host/
   19  *          finger://host/%2fw
   20  *          finger://host/%2fw%20username[@host]
   21  *          finger://host/w/username[@host]
   22  *          finger://host/username[@host]
   23  *          finger://host/username[@host]/w
   24  *          finger://username@host
   25  *          finger://username@host/
   26  *          finger://username@host/w
   27  *  15 Mar 96   Added support for port 79 gtype 0 gopher URLs
   28  *           relayed from HTLoadGopher. - FM
   29  */
   30 
   31 #include <HTUtils.h>
   32 
   33 #ifndef DISABLE_FINGER
   34 
   35 #include <HTAlert.h>
   36 #include <HTML.h>
   37 #include <HTParse.h>
   38 #include <HTFormat.h>
   39 #include <HTTCP.h>
   40 #include <HTString.h>
   41 #include <HTFinger.h>
   42 
   43 #include <LYUtils.h>
   44 #include <LYLeaks.h>
   45 
   46 #define FINGER_PORT 79      /* See rfc742 */
   47 #define BIG 1024        /* Bug */
   48 
   49 #define PUTC(c) (*targetClass.put_character)(target, c)
   50 #define PUTS(s) (*targetClass.put_string)(target, s)
   51 #define START(e) (*targetClass.start_element)(target, e, 0, 0, -1, 0)
   52 #define END(e) (*targetClass.end_element)(target, e, 0)
   53 #define FREE_TARGET (*targetClass._free)(target)
   54 #define NEXT_CHAR HTGetCharacter()
   55 
   56 /*  Module-wide variables
   57 */
   58 static int finger_fd;       /* Socket for FingerHost */
   59 
   60 struct _HTStructured {
   61     const HTStructuredClass *isa;   /* For gopher streams */
   62     /* ... */
   63 };
   64 
   65 static HTStructured *target;    /* The output sink */
   66 static HTStructuredClass targetClass;   /* Copy of fn addresses */
   67 
   68 /*  Initialisation for this module
   69  *  ------------------------------
   70  */
   71 static BOOL initialized = NO;
   72 static BOOL initialize(void)
   73 {
   74     finger_fd = -1;     /* Disconnected */
   75     return YES;
   76 }
   77 
   78 /*  Start anchor element
   79  *  --------------------
   80  */
   81 static void start_anchor(const char *href)
   82 {
   83     BOOL present[HTML_A_ATTRIBUTES];
   84     const char *value[HTML_A_ATTRIBUTES];
   85 
   86     {
   87     int i;
   88 
   89     for (i = 0; i < HTML_A_ATTRIBUTES; i++)
   90         present[i] = (BOOL) (i == HTML_A_HREF);
   91     }
   92     ((const char **) value)[HTML_A_HREF] = href;
   93     (*targetClass.start_element) (target, HTML_A, present,
   94                   (const char **) value, -1, 0);
   95 
   96 }
   97 
   98 /*  Send Finger Command line to remote host & Check Response
   99  *  --------------------------------------------------------
  100  *
  101  * On entry,
  102  *  command points to the command to be sent, including CRLF, or is null
  103  *      pointer if no command to be sent.
  104  * On exit,
  105  *  Negative status indicates transmission error, socket closed.
  106  *  Positive status is a Finger status.
  107  */
  108 
  109 static int response(char *command,
  110             char *sitename,
  111             HTParentAnchor *anAnchor,
  112             HTFormat format_out,
  113             HTStream *sink)
  114 {
  115     int status;
  116     int length = (int) strlen(command);
  117     int ch, i;
  118     char line[BIG], *l, *cmd = NULL;
  119     char *p = line, *href = NULL;
  120 
  121     if (length == 0)
  122     return (-1);
  123 
  124     /* Set up buffering.
  125      */
  126     HTInitInput(finger_fd);
  127 
  128     /* Send the command.
  129      */
  130     CTRACE((tfp, "HTFinger command to be sent: %s", command));
  131     status = (int) NETWRITE(finger_fd, (char *) command, (unsigned) length);
  132     if (status < 0) {
  133     CTRACE((tfp, "HTFinger: Unable to send command. Disconnecting.\n"));
  134     NETCLOSE(finger_fd);
  135     finger_fd = -1;
  136     return status;
  137     }
  138     /* if bad status */
  139     /* Make a hypertext object with an anchor list.
  140      */
  141     target = HTML_new(anAnchor, format_out, sink);
  142     targetClass = *target->isa; /* Copy routine entry points */
  143 
  144     /* Create the results report.
  145      */
  146     CTRACE((tfp, "HTFinger: Reading finger information\n"));
  147     START(HTML_HTML);
  148     PUTC('\n');
  149     START(HTML_HEAD);
  150     PUTC('\n');
  151     START(HTML_TITLE);
  152     PUTS("Finger server on ");
  153     PUTS(sitename);
  154     END(HTML_TITLE);
  155     PUTC('\n');
  156     END(HTML_HEAD);
  157     PUTC('\n');
  158     START(HTML_BODY);
  159     PUTC('\n');
  160     START(HTML_H1);
  161     PUTS("Finger server on ");
  162     START(HTML_EM);
  163     PUTS(sitename);
  164     END(HTML_EM);
  165     PUTS(": ");
  166     StrAllocCopy(cmd, command);
  167     for (i = ((int) strlen(cmd) - 1); i >= 0; i--) {
  168     if (cmd[i] == LF || cmd[i] == CR) {
  169         cmd[i] = '\0';
  170     } else {
  171         break;
  172     }
  173     }
  174     PUTS(cmd);
  175     FREE(cmd);
  176     END(HTML_H1);
  177     PUTC('\n');
  178     START(HTML_PRE);
  179 
  180     while ((ch = NEXT_CHAR) != EOF) {
  181 
  182     if (interrupted_in_htgetcharacter) {
  183         CTRACE((tfp,
  184             "HTFinger: Interrupted in HTGetCharacter, apparently.\n"));
  185         _HTProgress(CONNECTION_INTERRUPTED);
  186         goto end_html;
  187     }
  188 
  189     if (ch != LF) {
  190         *p = (char) ch; /* Put character in line */
  191         if (p < &line[BIG - 1]) {
  192         p++;
  193         }
  194     } else {
  195         *p = '\0';      /* Terminate line */
  196         /*
  197          * OK we now have a line.
  198          * Load it as 'l' and parse it.
  199          */
  200         p = l = line;
  201         while (*l) {
  202         if (StrNCmp(l, STR_NEWS_URL, LEN_NEWS_URL) &&
  203             StrNCmp(l, "snews://", 8) &&
  204             StrNCmp(l, "nntp://", 7) &&
  205             StrNCmp(l, "snewspost:", 10) &&
  206             StrNCmp(l, "snewsreply:", 11) &&
  207             StrNCmp(l, "newspost:", 9) &&
  208             StrNCmp(l, "newsreply:", 10) &&
  209             StrNCmp(l, "ftp://", 6) &&
  210             StrNCmp(l, "file:/", 6) &&
  211             StrNCmp(l, "finger://", 9) &&
  212             StrNCmp(l, "http://", 7) &&
  213             StrNCmp(l, "https://", 8) &&
  214             StrNCmp(l, "wais://", 7) &&
  215             StrNCmp(l, STR_MAILTO_URL, LEN_MAILTO_URL) &&
  216             StrNCmp(l, "cso://", 6) &&
  217             StrNCmp(l, "gopher://", 9))
  218             PUTC(*l++);
  219         else {
  220             StrAllocCopy(href, l);
  221             start_anchor(strtok(href, " \r\n\t,>)\""));
  222             while (*l && !StrChr(" \r\n\t,>)\"", *l))
  223             PUTC(*l++);
  224             END(HTML_A);
  225             FREE(href);
  226         }
  227         }
  228         PUTC('\n');
  229     }
  230     }
  231     NETCLOSE(finger_fd);
  232     finger_fd = -1;
  233 
  234   end_html:
  235     END(HTML_PRE);
  236     PUTC('\n');
  237     END(HTML_BODY);
  238     PUTC('\n');
  239     END(HTML_HTML);
  240     PUTC('\n');
  241     FREE_TARGET;
  242     return (0);
  243 }
  244 
  245 /*      Load by name                    HTLoadFinger
  246  *      ============
  247  */
  248 int HTLoadFinger(const char *arg,
  249          HTParentAnchor *anAnchor,
  250          HTFormat format_out,
  251          HTStream *stream)
  252 {
  253     static char empty[1];
  254 
  255     char *username, *sitename;  /* Fields extracted from URL */
  256     char *slash, *at_sign;  /* Fields extracted from URL */
  257     char *command, *str, *param;    /* Buffers */
  258     int port;           /* Port number from URL */
  259     int status;         /* tcp return */
  260     int result = HT_LOADED;
  261     BOOL IsGopherURL = FALSE;
  262     const char *p1 = arg;
  263 
  264     CTRACE((tfp, "HTFinger: Looking for %s\n", (arg ? arg : "NULL")));
  265 
  266     if (!(arg && *arg)) {
  267     HTAlert(COULD_NOT_LOAD_DATA);
  268     return HT_NOT_LOADED;   /* Ignore if no name */
  269     }
  270 
  271     if (!initialized)
  272     initialized = initialize();
  273     if (!initialized) {
  274     HTAlert(gettext("Could not set up finger connection."));
  275     return HT_NOT_LOADED;   /* FAIL */
  276     }
  277 
  278     /*  Set up the host and command fields.
  279      */
  280     if (!strncasecomp(arg, "finger://", 9)) {
  281     p1 = arg + 9;       /* Skip "finger://" prefix */
  282     } else if (!strncasecomp(arg, "gopher://", 9)) {
  283     p1 = arg + 9;       /* Skip "gopher://" prefix */
  284     IsGopherURL = TRUE;
  285     }
  286 
  287     param = 0;
  288     sitename = StrAllocCopy(param, p1);
  289     if (param == 0) {
  290     HTAlert(COULD_NOT_LOAD_DATA);
  291     return HT_NOT_LOADED;
  292     } else if ((slash = StrChr(sitename, '/')) != NULL) {
  293     *slash++ = '\0';
  294     HTUnEscape(slash);
  295     if (IsGopherURL) {
  296         if (*slash != '0') {
  297         HTAlert(COULD_NOT_LOAD_DATA);
  298         return HT_NOT_LOADED;   /* FAIL */
  299         }
  300         *slash++ = '\0';
  301     }
  302     }
  303 
  304     if ((at_sign = StrChr(sitename, '@')) != NULL) {
  305     if (IsGopherURL) {
  306         HTAlert(COULD_NOT_LOAD_DATA);
  307         return HT_NOT_LOADED;   /* FAIL */
  308     } else {
  309         *at_sign++ = '\0';
  310         username = sitename;
  311         sitename = at_sign;
  312         HTUnEscape(username);
  313     }
  314     } else if (slash) {
  315     username = slash;
  316     } else {
  317     username = empty;
  318     }
  319 
  320     if (*sitename == '\0') {
  321     HTAlert(gettext("Could not load data (no sitename in finger URL)"));
  322     result = HT_NOT_LOADED; /* Ignore if no name */
  323     } else if (HTParsePort(sitename, &port) != NULL) {
  324     if (port != 79) {
  325         HTAlert(gettext("Invalid port number - will only use port 79!"));
  326         result = HT_NOT_LOADED; /* Ignore if wrong port */
  327     }
  328     }
  329 
  330     if (result == HT_LOADED) {
  331     /* Load the string for making a connection/
  332      */
  333     str = 0;
  334     HTSprintf0(&str, "lose://%s/", sitename);
  335 
  336     /* Load the command for the finger server.
  337      */
  338     command = 0;
  339     if (at_sign && slash) {
  340         if (*slash == 'w' || *slash == 'W') {
  341         HTSprintf0(&command, "/w %s%c%c", username, CR, LF);
  342         } else {
  343         HTSprintf0(&command, "%s%c%c", username, CR, LF);
  344         }
  345     } else if (at_sign) {
  346         HTSprintf0(&command, "%s%c%c", username, CR, LF);
  347     } else if (*username == '/') {
  348         if ((slash = StrChr((username + 1), '/')) != NULL) {
  349         *slash = ' ';
  350         }
  351         HTSprintf0(&command, "%s%c%c", username, CR, LF);
  352     } else if ((*username == 'w' || *username == 'W') &&
  353            *(username + 1) == '/') {
  354         if (*username + 2 != '\0') {
  355         *(username + 1) = ' ';
  356         } else {
  357         *(username + 1) = '\0';
  358         }
  359         HTSprintf0(&command, "/%s%c%c", username, CR, LF);
  360     } else if ((*username == 'w' || *username == 'W') &&
  361            *(username + 1) == '\0') {
  362         HTSprintf0(&command, "/%s%c%c", username, CR, LF);
  363     } else if ((slash = StrChr(username, '/')) != NULL) {
  364         *slash++ = '\0';
  365         if (*slash == 'w' || *slash == 'W') {
  366         HTSprintf0(&command, "/w %s%c%c", username, CR, LF);
  367         } else {
  368         HTSprintf0(&command, "%s%c%c", username, CR, LF);
  369         }
  370     } else {
  371         HTSprintf0(&command, "%s%c%c", username, CR, LF);
  372     }
  373 
  374     /* Now, let's get a stream setup up from the FingerHost:
  375      * CONNECTING to finger host
  376      */
  377     CTRACE((tfp, "HTFinger: doing HTDoConnect on '%s'\n", str));
  378     status = HTDoConnect(str, "finger", FINGER_PORT, &finger_fd);
  379     CTRACE((tfp, "HTFinger: Done DoConnect; status %d\n", status));
  380 
  381     if (status == HT_INTERRUPTED) {
  382         /* Interrupt cleanly */
  383         CTRACE((tfp,
  384             "HTFinger: Interrupted on connect; recovering cleanly.\n"));
  385         HTProgress(CONNECTION_INTERRUPTED);
  386         result = HT_NOT_LOADED;
  387     } else if (status < 0) {
  388         NETCLOSE(finger_fd);
  389         finger_fd = -1;
  390         CTRACE((tfp, "HTFinger: Unable to connect to finger host.\n"));
  391         HTAlert(gettext("Could not access finger host."));
  392         result = HT_NOT_LOADED; /* FAIL */
  393     } else {
  394         CTRACE((tfp, "HTFinger: Connected to finger host '%s'.\n", str));
  395 
  396         /* Send the command, and process response if successful.
  397          */
  398         if (response(command, sitename, anAnchor, format_out, stream) != 0) {
  399         HTAlert(gettext("No response from finger server."));
  400         result = HT_NOT_LOADED;
  401         }
  402     }
  403     FREE(str);
  404     FREE(command);
  405     }
  406     FREE(param);
  407     return result;
  408 }
  409 
  410 #ifdef GLOBALDEF_IS_MACRO
  411 #define _HTFINGER_C_1_INIT { "finger", HTLoadFinger, NULL }
  412 GLOBALDEF(HTProtocol, HTFinger, _HTFINGER_C_1_INIT);
  413 #else
  414 GLOBALDEF HTProtocol HTFinger =
  415 {"finger", HTLoadFinger, NULL};
  416 #endif /* GLOBALDEF_IS_MACRO */
  417 
  418 #endif /* not DISABLE_FINGER */