summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFinger.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/usr.bin/lynx/WWW/Library/Implementation/HTFinger.c')
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTFinger.c441
1 files changed, 441 insertions, 0 deletions
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFinger.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFinger.c
new file mode 100644
index 00000000000..e714e0d20f0
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFinger.c
@@ -0,0 +1,441 @@
+/* FINGER ACCESS HTFinger.c
+** =============
+** Authors:
+** ARB Andrew Brooks
+**
+** History:
+** 21 Apr 94 First version (ARB, from HTNews.c by TBL)
+** 12 Mar 96 Made the URL and command buffering secure from
+** stack modifications, beautified the HTLoadFinger()
+** and response() functions, and added support for the
+** following URL formats for sending a "", "/w",
+** "username[@host]", or "/w username[@host]" command
+** to the server:
+** finger://host
+** finger://host/
+** finger://host/%2fw
+** finger://host/%2fw%20username[@host]
+** finger://host/w/username[@host]
+** finger://host/username[@host]
+** finger://host/username[@host]/w
+** finger://username@host
+** finger://username@host/
+** finger://username@host/w
+** 15 Mar 96 Added support for port 79 gtype 0 gopher URLs
+** relayed from HTLoadGopher. - FM
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTAlert.h"
+#include "HTML.h"
+#include "HTParse.h"
+#include "HTFormat.h"
+#include "HTTCP.h"
+#include "HTString.h"
+#include "HTFinger.h"
+
+#include "LYLeaks.h"
+
+/* #define TRACE 1 */
+
+#define FINGER_PORT 79 /* See rfc742 */
+#define BIG 1024 /* Bug */
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+#define PUTC(c) (*targetClass.put_character)(target, c)
+#define PUTS(s) (*targetClass.put_string)(target, s)
+#define START(e) (*targetClass.start_element)(target, e, 0, 0, -1, 0)
+#define END(e) (*targetClass.end_element)(target, e, 0)
+#define FREE_TARGET (*targetClass._free)(target)
+#define NEXT_CHAR HTGetCharacter()
+
+
+/* Module-wide variables
+*/
+PRIVATE int s; /* Socket for FingerHost */
+
+struct _HTStructured {
+ CONST HTStructuredClass * isa; /* For gopher streams */
+ /* ... */
+};
+
+PRIVATE HTStructured * target; /* The output sink */
+PRIVATE HTStructuredClass targetClass; /* Copy of fn addresses */
+
+/* Initialisation for this module
+** ------------------------------
+*/
+PRIVATE BOOL initialized = NO;
+PRIVATE BOOL initialize NOARGS
+{
+ s = -1; /* Disconnected */
+ return YES;
+}
+
+
+
+/* Start anchor element
+** --------------------
+*/
+PRIVATE void start_anchor ARGS1(CONST char *, href)
+{
+ BOOL present[HTML_A_ATTRIBUTES];
+ CONST char* value[HTML_A_ATTRIBUTES];
+
+ {
+ int i;
+ for(i=0; i<HTML_A_ATTRIBUTES; i++)
+ present[i] = (i==HTML_A_HREF);
+ }
+ ((CONST char **)value)[HTML_A_HREF] = href;
+ (*targetClass.start_element)(target, HTML_A, present,
+ (CONST char **)value, -1, 0);
+
+}
+
+/* Send Finger Command line to remote host & Check Response
+** --------------------------------------------------------
+**
+** On entry,
+** command points to the command to be sent, including CRLF, or is null
+** pointer if no command to be sent.
+** On exit,
+** Negative status indicates transmission error, socket closed.
+** Positive status is a Finger status.
+*/
+
+
+PRIVATE int response ARGS5(
+ CONST char *, command,
+ char *, sitename,
+ HTParentAnchor *, anAnchor,
+ HTFormat, format_out,
+ HTStream*, sink)
+{
+ int status;
+ int length = strlen(command);
+ int ch, i;
+ char line[BIG], *l, *cmd=NULL;
+ char *p = line, *href=NULL;
+
+ if (length == 0)
+ return(-1);
+
+ /* Set up buffering.
+ */
+ HTInitInput(s);
+
+ /* Send the command.
+ */
+ if (TRACE)
+ fprintf(stderr, "HTFinger command to be sent: %s", command);
+ status = NETWRITE(s, (char *)command, length);
+ if (status < 0) {
+ if (TRACE)
+ fprintf(stderr,
+ "HTFinger: Unable to send command. Disconnecting.\n");
+ NETCLOSE(s);
+ s = -1;
+ return status;
+ } /* if bad status */
+
+ /* Make a hypertext object with an anchor list.
+ */
+ target = HTML_new(anAnchor, format_out, sink);
+ targetClass = *target->isa; /* Copy routine entry points */
+
+ /* Create the results report.
+ */
+ if (TRACE)
+ fprintf(stderr,"HTFinger: Reading finger information\n");
+ START(HTML_HTML);
+ PUTS("\n");
+ START(HTML_HEAD);
+ PUTS("\n");
+ START(HTML_TITLE);
+ PUTS("Finger server on ");
+ PUTS(sitename);
+ END(HTML_TITLE);
+ PUTS("\n");
+ END(HTML_HEAD);
+ PUTS("\n");
+ START(HTML_BODY);
+ PUTS("\n");
+ START(HTML_H1);
+ PUTS("Finger server on ");
+ START(HTML_EM);
+ PUTS(sitename);
+ END(HTML_EM);
+ PUTS(": ");
+ if (command) {
+ StrAllocCopy(cmd, command);
+ } else {
+ StrAllocCopy(cmd, "");
+ }
+ for (i = (strlen(cmd) - 1); i >= 0; i--) {
+ if (cmd[i] == LF || cmd[i] == CR) {
+ cmd[i] = '\0';
+ } else {
+ break;
+ }
+ }
+ PUTS(cmd);
+ FREE(cmd);
+ END(HTML_H1);
+ PUTS("\n");
+ START(HTML_PRE);
+
+ while ((ch=NEXT_CHAR) != (char)EOF) {
+
+ if (interrupted_in_htgetcharacter) {
+ if (TRACE) {
+ fprintf(stderr,
+ "HTFinger: Interrupted in HTGetCharacter, apparently.\n");
+ }
+ _HTProgress ("Connection interrupted.");
+ goto end_html;
+ }
+
+ if (ch != LF) {
+ *p = ch; /* Put character in line */
+ if (p < &line[BIG-1]) {
+ p++;
+ }
+ } else {
+ *p = '\0'; /* Terminate line */
+ /*
+ * OK we now have a line.
+ * Load it as 'l' and parse it.
+ */
+ p = l = line;
+ while (*l) {
+ if (strncmp(l, "news:", 5) &&
+ strncmp(l, "snews://", 8) &&
+ strncmp(l, "nntp://", 7) &&
+ strncmp(l, "snewspost:", 10) &&
+ strncmp(l, "snewsreply:", 11) &&
+ strncmp(l, "newspost:", 9) &&
+ strncmp(l, "newsreply:", 10) &&
+ strncmp(l, "ftp://", 6) &&
+ strncmp(l, "file:/", 6) &&
+ strncmp(l, "finger://", 9) &&
+ strncmp(l, "http://", 7) &&
+ strncmp(l, "https://", 8) &&
+ strncmp(l, "wais://", 7) &&
+ strncmp(l, "mailto:", 7) &&
+ strncmp(l, "cso://", 6) &&
+ strncmp(l, "gopher://", 9))
+ PUTC(*l++);
+ else {
+ StrAllocCopy(href, l);
+ start_anchor(strtok(href, " \r\n\t,>)\""));
+ while (*l && !strchr(" \r\n\t,>)\"", *l))
+ PUTC(*l++);
+ END(HTML_A);
+ FREE(href);
+ }
+ }
+ PUTC('\n');
+ }
+ }
+ NETCLOSE(s);
+ s = -1;
+
+end_html:
+ END(HTML_PRE);
+ PUTS("\n");
+ END(HTML_BODY);
+ PUTS("\n");
+ END(HTML_HTML);
+ PUTS("\n");
+ FREE_TARGET;
+ return(0);
+}
+
+
+/* Load by name HTLoadFinger
+** ============
+*/
+PUBLIC int HTLoadFinger ARGS4(
+ CONST char *, arg,
+ HTParentAnchor *, anAnchor,
+ HTFormat, format_out,
+ HTStream*, stream)
+{
+ char *username, *sitename, *colon; /* Fields extracted from URL */
+ char *slash, *at_sign; /* Fields extracted from URL */
+ char *command, *str; /* Buffers */
+ int port; /* Port number from URL */
+ int status; /* tcp return */
+
+ if (TRACE) {
+ fprintf(stderr, "HTFinger: Looking for %s\n", (arg ? arg : "NULL"));
+ }
+
+ if (!(arg && *arg)) {
+ HTAlert("Could not load data.");
+ return HT_NOT_LOADED; /* Ignore if no name */
+ }
+
+ if (!initialized)
+ initialized = initialize();
+ if (!initialized) {
+ HTAlert ("Could not set up finger connection.");
+ return HT_NOT_LOADED; /* FAIL */
+ }
+
+ {
+ CONST char * p1=arg;
+ BOOL IsGopherURL = FALSE;
+
+ /* Set up the host and command fields.
+ */
+ if (!strncasecomp(arg, "finger://", 9)) {
+ p1 = arg + 9; /* Skip "finger://" prefix */
+ } else if (!strncasecomp(arg, "gopher://", 9)) {
+ p1 = arg + 9; /* Skip "gopher://" prefix */
+ IsGopherURL = TRUE;
+ }
+ sitename = (char *)p1;
+
+ if ((slash = strchr(sitename, '/')) != NULL) {
+ *slash++ = '\0';
+ HTUnEscape(slash);
+ if (IsGopherURL) {
+ if (*slash != '0') {
+ HTAlert("Could not load data.");
+ return HT_NOT_LOADED; /* FAIL */
+ }
+ *slash++ = '\0';
+ }
+ }
+ if ((at_sign = strchr(sitename, '@')) != NULL) {
+ if (IsGopherURL) {
+ HTAlert("Could not load data.");
+ return HT_NOT_LOADED; /* FAIL */
+ }
+ *at_sign++ = '\0';
+ username = sitename;
+ sitename = at_sign;
+ HTUnEscape(username);
+ } else if (slash) {
+ username = slash;
+ } else {
+ username = "";
+ }
+
+ if (*sitename == '\0') {
+ HTAlert("Could not load data (no sitename in finger URL)");
+ return HT_NOT_LOADED; /* Ignore if no name */
+ }
+
+ if ((colon = strchr(sitename, ':')) != NULL) {
+ *colon++ = '\0';
+ port = atoi(colon);
+ if (port != 79) {
+ HTAlert("Invalid port number - will only use port 79!");
+ return HT_NOT_LOADED; /* Ignore if wrong port */
+ }
+ }
+
+ /* Load the string for making a connection/
+ */
+ str = (char *)calloc(1, (strlen(sitename) + 10));
+ if (str == NULL)
+ outofmem(__FILE__, "HTLoadFinger");
+ sprintf(str, "lose://%s/", sitename);
+
+ /* Load the command for the finger server.
+ */
+ command = (char *)calloc(1, (strlen(username) + 10));
+ if (command == NULL)
+ outofmem(__FILE__, "HTLoadFinger");
+ if (at_sign && slash) {
+ if (*slash == 'w' || *slash == 'W') {
+ sprintf(command, "/w %s%c%c", username, CR, LF);
+ } else {
+ sprintf(command, "%s%c%c", username, CR, LF);
+ }
+ } else if (at_sign) {
+ sprintf(command, "%s%c%c", username, CR, LF);
+ } else if (*username == '/') {
+ if ((slash = strchr((username+1), '/')) != NULL) {
+ *slash = ' ';
+ }
+ sprintf(command, "%s%c%c", username, CR, LF);
+ } else if ((*username == 'w' || *username == 'W') &&
+ *(username+1) == '/') {
+ if (*username+2 != '\0') {
+ *(username+1) = ' ';
+ } else {
+ *(username+1) = '\0';
+ }
+ sprintf(command, "/%s%c%c", username, CR, LF);
+ } else if ((*username == 'w' || *username == 'W') &&
+ *(username+1) == '\0') {
+ sprintf(command, "/%s%c%c", username, CR, LF);
+ } else if ((slash = strchr(username, '/')) != NULL) {
+ *slash++ = '\0';
+ if (*slash == 'w' || *slash == 'W') {
+ sprintf(command, "/w %s%c%c", username, CR, LF);
+ } else {
+ sprintf(command, "%s%c%c", username, CR, LF);
+ }
+ } else {
+ sprintf(command, "%s%c%c", username, CR, LF);
+ }
+ } /* scope of p1 */
+
+ /* Now, let's get a stream setup up from the FingerHost:
+ ** CONNECTING to finger host
+ */
+ if (TRACE)
+ fprintf(stderr, "HTFinger: doing HTDoConnect on '%s'\n", str);
+ status = HTDoConnect(str, "finger", FINGER_PORT, &s);
+ if (TRACE)
+ fprintf(stderr, "HTFinger: Done DoConnect; status %d\n", status);
+
+ if (status == HT_INTERRUPTED) {
+ /* Interrupt cleanly */
+ if (TRACE)
+ fprintf(stderr,
+ "HTFinger: Interrupted on connect; recovering cleanly.\n");
+ HTProgress ("Connection interrupted.");
+ FREE(str);
+ FREE(command);
+ return HT_NOT_LOADED;
+ }
+ if (status < 0) {
+ NETCLOSE(s);
+ s = -1;
+ if (TRACE)
+ fprintf(stderr, "HTFinger: Unable to connect to finger host.\n");
+ HTAlert("Could not access finger host.");
+ FREE(str);
+ FREE(command);
+ return HT_NOT_LOADED; /* FAIL */
+ }
+ if (TRACE)
+ fprintf(stderr, "HTFinger: Connected to finger host '%s'.\n", str);
+ FREE(str);
+
+ /* Send the command, and process response if successful.
+ */
+ if (response(command, sitename, anAnchor, format_out, stream) != 0) {
+ HTAlert("No response from finger server.");
+ FREE(command);
+ return HT_NOT_LOADED;
+ }
+
+ FREE(command);
+ return HT_LOADED;
+}
+
+#ifdef GLOBALDEF_IS_MACRO
+#define _HTFINGER_C_1_INIT { "finger", HTLoadFinger, NULL }
+GLOBALDEF (HTProtocol, HTFinger, _HTFINGER_C_1_INIT);
+#else
+GLOBALDEF PUBLIC HTProtocol HTFinger = { "finger", HTLoadFinger, NULL };
+#endif /* GLOBALDEF_IS_MACRO */