Blame WWW/Library/Implementation/HTGopher.c

Packit f574b8
/*
Packit f574b8
 * $LynxId: HTGopher.c,v 1.68 2018/05/15 21:58:15 tom Exp $
Packit f574b8
 *
Packit f574b8
 *			GOPHER ACCESS				HTGopher.c
Packit f574b8
 *			=============
Packit f574b8
 *
Packit f574b8
 *  History:
Packit f574b8
 *	26 Sep 90	Adapted from other accesses (News, HTTP) TBL
Packit f574b8
 *	29 Nov 91	Downgraded to C, for portable implementation.
Packit f574b8
 *	10 Mar 96	Foteos Macrides (macrides@sci.wfbr.edu).  Added a
Packit f574b8
 *			  form-based CSO/PH gateway.  Can be invoked via a
Packit f574b8
 *			  "cso://host[:port]/" or "gopher://host:105/2"
Packit f574b8
 *			  URL.	If a gopher URL is used with a query token
Packit f574b8
 *			  ('?'), the old ISINDEX procedure will be used
Packit f574b8
 *			  instead of the form-based gateway.
Packit f574b8
 *	15 Mar 96	Foteos Macrides (macrides@sci.wfbr.edu).  Pass
Packit f574b8
 *			  port 79, gtype 0 gopher URLs to the finger
Packit f574b8
 *			  gateway.
Packit f574b8
 */
Packit f574b8
Packit f574b8
#define HTSTREAM_INTERNAL 1
Packit f574b8
Packit f574b8
#include <HTUtils.h>		/* Coding convention macros */
Packit f574b8
#include <HTFile.h>		/* For HTFileFormat() */
Packit f574b8
Packit f574b8
#ifndef DISABLE_GOPHER
Packit f574b8
#include <HTAlert.h>
Packit f574b8
#include <HTParse.h>
Packit f574b8
#include <HTTCP.h>
Packit f574b8
#include <HTFinger.h>
Packit f574b8
Packit f574b8
/*
Packit f574b8
 *  Implements.
Packit f574b8
 */
Packit f574b8
#include <HTGopher.h>
Packit f574b8
Packit f574b8
#define GOPHER_PORT 70		/* See protocol spec */
Packit f574b8
#define CSO_PORT 105		/* See protocol spec */
Packit f574b8
#define BIG 1024		/* Bug */
Packit f574b8
#define LINE_LENGTH 256		/* Bug */
Packit f574b8
Packit f574b8
/*
Packit f574b8
 *  Gopher entity types.
Packit f574b8
 */
Packit f574b8
#define GOPHER_TEXT		'0'
Packit f574b8
#define GOPHER_MENU		'1'
Packit f574b8
#define GOPHER_CSO		'2'
Packit f574b8
#define GOPHER_ERROR		'3'
Packit f574b8
#define GOPHER_MACBINHEX	'4'
Packit f574b8
#define GOPHER_PCBINARY		'5'
Packit f574b8
#define GOPHER_UUENCODED	'6'
Packit f574b8
#define GOPHER_INDEX		'7'
Packit f574b8
#define GOPHER_TELNET		'8'
Packit f574b8
#define GOPHER_BINARY		'9'
Packit f574b8
#define GOPHER_GIF		'g'
Packit f574b8
#define GOPHER_HTML		'h'	/* HTML */
Packit f574b8
#define GOPHER_CHTML		'H'	/* HTML */
Packit f574b8
#define GOPHER_SOUND		's'
Packit f574b8
#define GOPHER_WWW		'w'	/* W3 address */
Packit f574b8
#define GOPHER_IMAGE		'I'
Packit f574b8
#define GOPHER_TN3270		'T'
Packit f574b8
#define GOPHER_INFO		'i'
Packit f574b8
#define GOPHER_DUPLICATE	'+'
Packit f574b8
#define GOPHER_PLUS_IMAGE	':'	/* Addition from Gopher Plus */
Packit f574b8
#define GOPHER_PLUS_MOVIE	';'
Packit f574b8
#define GOPHER_PLUS_SOUND	'<'
Packit f574b8
#define GOPHER_PLUS_PDF		'P'
Packit f574b8
Packit f574b8
#include <HTFormat.h>
Packit f574b8
Packit f574b8
/*
Packit f574b8
 *  Hypertext object building machinery.
Packit f574b8
 */
Packit f574b8
#include <HTML.h>
Packit f574b8
Packit f574b8
#include <LYStrings.h>
Packit f574b8
#include <LYUtils.h>
Packit f574b8
#include <LYLeaks.h>
Packit f574b8
Packit f574b8
#define PUTC(c) (*targetClass.put_character)(target, c)
Packit f574b8
#define PUTS(s) (*targetClass.put_string)(target, s)
Packit f574b8
#define START(e) (*targetClass.start_element)(target, e, 0, 0, -1, 0)
Packit f574b8
#define END(e) (*targetClass.end_element)(target, e, 0)
Packit f574b8
#define FREE_TARGET (*targetClass._free)(target)
Packit f574b8
Packit f574b8
#define NEXT_CHAR HTGetCharacter()
Packit f574b8
Packit f574b8
/*
Packit f574b8
 *  Module-wide variables.
Packit f574b8
 */
Packit f574b8
static int s;			/* Socket for gopher or CSO host */
Packit f574b8
Packit f574b8
struct _HTStructured {
Packit f574b8
    const HTStructuredClass *isa;	/* For gopher streams */
Packit f574b8
    /* ... */
Packit f574b8
};
Packit f574b8
Packit f574b8
static HTStructured *target;	/* the new gopher hypertext */
Packit f574b8
static HTStructuredClass targetClass;	/* Its action routines */
Packit f574b8
Packit f574b8
struct _HTStream {
Packit f574b8
    HTStreamClass *isa;		/* For form-based CSO  gateway - FM */
Packit f574b8
};
Packit f574b8
Packit f574b8
typedef struct _CSOfield_info {	/* For form-based CSO gateway - FM */
Packit f574b8
    struct _CSOfield_info *next;
Packit f574b8
    char *name;
Packit f574b8
    char *attributes;
Packit f574b8
    char *description;
Packit f574b8
    int id;
Packit f574b8
    int lookup;
Packit f574b8
    int indexed;
Packit f574b8
    int url;
Packit f574b8
    int max_size;
Packit f574b8
    int defreturn;
Packit f574b8
    int explicit_return;
Packit f574b8
    int reserved;
Packit f574b8
    int gpublic;
Packit f574b8
    char name_buf[16];		/* Avoid malloc if we can */
Packit f574b8
    char desc_buf[32];		/* Avoid malloc if we can */
Packit f574b8
    char attr_buf[80];		/* Avoid malloc if we can */
Packit f574b8
} CSOfield_info;
Packit f574b8
Packit f574b8
static CSOfield_info *CSOfields = NULL;		/* For form-based CSO gateway - FM */
Packit f574b8
Packit f574b8
typedef struct _CSOformgen_context {	/* For form-based CSO gateway - FM */
Packit f574b8
    const char *host;
Packit f574b8
    const char *seek;
Packit f574b8
    CSOfield_info *fld;
Packit f574b8
    int port;
Packit f574b8
    int cur_line;
Packit f574b8
    int cur_off;
Packit f574b8
    int rep_line;
Packit f574b8
    int rep_off;
Packit f574b8
    int public_override;
Packit f574b8
    int field_select;
Packit f574b8
} CSOformgen_context;
Packit f574b8
Packit f574b8
/*	Matrix of allowed characters in filenames
Packit f574b8
 *	=========================================
Packit f574b8
 */
Packit f574b8
static BOOL acceptable[256];
Packit f574b8
static BOOL acceptable_inited = NO;
Packit f574b8
Packit f574b8
static void init_acceptable(void)
Packit f574b8
{
Packit f574b8
    unsigned int i;
Packit f574b8
    const char *good =
Packit f574b8
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./-_$";
Packit f574b8
Packit f574b8
    for (i = 0; i < 256; i++)
Packit f574b8
	acceptable[i] = NO;
Packit f574b8
    for (; *good; good++)
Packit f574b8
	acceptable[(unsigned int) *good] = YES;
Packit f574b8
    acceptable_inited = YES;
Packit f574b8
}
Packit f574b8
Packit f574b8
/*	Decode one hex character
Packit f574b8
 *	========================
Packit f574b8
 */
Packit f574b8
static const char hex[17] = "0123456789abcdef";
Packit f574b8
Packit f574b8
static char from_hex(int c)
Packit f574b8
{
Packit f574b8
    return (char) ((c >= '0') && (c <= '9') ? c - '0'
Packit f574b8
		   : (c >= 'A') && (c <= 'F') ? c - 'A' + 10
Packit f574b8
		   : (c >= 'a') && (c <= 'f') ? c - 'a' + 10
Packit f574b8
		   : 0);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*	Paste in an Anchor
Packit f574b8
 *	==================
Packit f574b8
 *
Packit f574b8
 *	The title of the destination is set, as there is no way
Packit f574b8
 *	of knowing what the title is when we arrive.
Packit f574b8
 *
Packit f574b8
 * On entry,
Packit f574b8
 *	HT	is in append mode.
Packit f574b8
 *	text	points to the text to be put into the file, 0 terminated.
Packit f574b8
 *	addr	points to the hypertext refernce address 0 terminated.
Packit f574b8
 */
Packit f574b8
BOOLEAN HT_Is_Gopher_URL = FALSE;
Packit f574b8
Packit f574b8
static void write_anchor(const char *text, const char *addr)
Packit f574b8
{
Packit f574b8
    BOOL present[HTML_A_ATTRIBUTES];
Packit f574b8
    const char *value[HTML_A_ATTRIBUTES];
Packit f574b8
Packit f574b8
    int i;
Packit f574b8
Packit f574b8
    for (i = 0; i < HTML_A_ATTRIBUTES; i++)
Packit f574b8
	present[i] = 0;
Packit f574b8
    present[HTML_A_HREF] = YES;
Packit f574b8
    ((const char **) value)[HTML_A_HREF] = addr;
Packit f574b8
    present[HTML_A_TITLE] = YES;
Packit f574b8
    ((const char **) value)[HTML_A_TITLE] = text;
Packit f574b8
Packit f574b8
    CTRACE((tfp, "HTGopher: adding URL: %s\n", addr));
Packit f574b8
Packit f574b8
    HT_Is_Gopher_URL = TRUE;	/* tell HTML.c that this is a Gopher URL */
Packit f574b8
    (*targetClass.start_element) (target, HTML_A, present,
Packit f574b8
				  (const char **) value, -1, 0);
Packit f574b8
Packit f574b8
    PUTS(text);
Packit f574b8
    END(HTML_A);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*	Parse a Gopher Menu document
Packit f574b8
 *	============================
Packit f574b8
 */
Packit f574b8
static void parse_menu(const char *arg GCC_UNUSED,
Packit f574b8
		       HTParentAnchor *anAnchor)
Packit f574b8
{
Packit f574b8
    char gtype;
Packit f574b8
    char this_type;
Packit f574b8
    int ich;
Packit f574b8
    char line[BIG];
Packit f574b8
    char *name = NULL, *selector = NULL;	/* Gopher menu fields */
Packit f574b8
    char *host = NULL;
Packit f574b8
    char *port;
Packit f574b8
    char *p = line;
Packit f574b8
    const char *title;
Packit f574b8
    int bytes = 0;
Packit f574b8
    int BytesReported = 0;
Packit f574b8
    char buffer[128];
Packit f574b8
Packit f574b8
#define TAB		'\t'
Packit f574b8
#define HEX_ESCAPE	'%'
Packit f574b8
Packit f574b8
    START(HTML_HTML);
Packit f574b8
    PUTC('\n');
Packit f574b8
    START(HTML_HEAD);
Packit f574b8
    PUTC('\n');
Packit f574b8
    START(HTML_TITLE);
Packit f574b8
    if ((title = HTAnchor_title(anAnchor)))
Packit f574b8
	PUTS(title);
Packit f574b8
    else
Packit f574b8
	PUTS(GOPHER_MENU_TITLE);
Packit f574b8
    END(HTML_TITLE);
Packit f574b8
    PUTC('\n');
Packit f574b8
    END(HTML_HEAD);
Packit f574b8
    PUTC('\n');
Packit f574b8
Packit f574b8
    START(HTML_BODY);
Packit f574b8
    PUTC('\n');
Packit f574b8
    START(HTML_H1);
Packit f574b8
    if ((title = HTAnchor_title(anAnchor)))
Packit f574b8
	PUTS(title);
Packit f574b8
    else
Packit f574b8
	PUTS(GOPHER_MENU_TITLE);
Packit f574b8
    END(HTML_H1);
Packit f574b8
    PUTC('\n');
Packit f574b8
    START(HTML_PRE);
Packit f574b8
    PUTC('\n');			/* newline after HTML_PRE forces split-line */
Packit f574b8
    this_type = GOPHER_ERROR;
Packit f574b8
    while ((ich = NEXT_CHAR) != EOF) {
Packit f574b8
Packit f574b8
	if (interrupted_in_htgetcharacter) {
Packit f574b8
	    CTRACE((tfp,
Packit f574b8
		    "HTGopher: Interrupted in HTGetCharacter, apparently.\n"));
Packit f574b8
	    goto end_html;
Packit f574b8
	}
Packit f574b8
Packit f574b8
	if ((char) ich != LF) {
Packit f574b8
	    *p = (char) ich;	/* Put character in line */
Packit f574b8
	    if (p < &line[BIG - 1])
Packit f574b8
		p++;
Packit f574b8
Packit f574b8
	} else {
Packit f574b8
	    *p++ = '\0';	/* Terminate line */
Packit f574b8
	    bytes += (int) (p - line);	/* add size */
Packit f574b8
	    p = line;		/* Scan it to parse it */
Packit f574b8
	    port = 0;		/* Flag "not parsed" */
Packit f574b8
	    CTRACE((tfp, "HTGopher: Menu item: %s\n", line));
Packit f574b8
	    gtype = *p++;
Packit f574b8
Packit f574b8
	    if (bytes > BytesReported + 1024) {
Packit f574b8
		sprintf(buffer, TRANSFERRED_X_BYTES, bytes);
Packit f574b8
		HTProgress(buffer);
Packit f574b8
		BytesReported = bytes;
Packit f574b8
	    }
Packit f574b8
Packit f574b8
	    /* Break on line with a dot by itself */
Packit f574b8
	    if ((gtype == '.') && ((*p == '\r') || (*p == 0)))
Packit f574b8
		break;
Packit f574b8
Packit f574b8
	    if (gtype && *p) {
Packit f574b8
		name = p;
Packit f574b8
		selector = StrChr(name, TAB);
Packit f574b8
		if (selector) {
Packit f574b8
		    *selector++ = '\0';		/* Terminate name */
Packit f574b8
		    /*
Packit f574b8
		     * Gopher+ Type=0+ objects can be binary, and will
Packit f574b8
		     * have 9 or 5 beginning their selector.  Make sure
Packit f574b8
		     * we don't trash the terminal by treating them as
Packit f574b8
		     * text. - FM
Packit f574b8
		     */
Packit f574b8
		    if (gtype == GOPHER_TEXT && (*selector == GOPHER_BINARY ||
Packit f574b8
						 *selector == GOPHER_PCBINARY))
Packit f574b8
			gtype = *selector;
Packit f574b8
		    host = StrChr(selector, TAB);
Packit f574b8
		    if (host) {
Packit f574b8
			*host++ = '\0';		/* Terminate selector */
Packit f574b8
			port = StrChr(host, TAB);
Packit f574b8
			if (port) {
Packit f574b8
			    char *junk;
Packit f574b8
Packit f574b8
			    port[0] = ':';	/* delimit host a la W3 */
Packit f574b8
			    junk = StrChr(port, TAB);
Packit f574b8
			    if (junk)
Packit f574b8
				*junk = '\0';	/* Chop port */
Packit f574b8
			    if ((port[1] == '0') && (!port[2]))
Packit f574b8
				port[0] = '\0';		/* 0 means none */
Packit f574b8
			}	/* no port */
Packit f574b8
		    }		/* host ok */
Packit f574b8
		}		/* selector ok */
Packit f574b8
	    }
Packit f574b8
	    /* gtype and name ok */
Packit f574b8
	    /* Nameless files are a separator line */
Packit f574b8
	    if (name != NULL && gtype == GOPHER_TEXT) {
Packit f574b8
		int i = (int) strlen(name) - 1;
Packit f574b8
Packit f574b8
		while (name[i] == ' ' && i >= 0)
Packit f574b8
		    name[i--] = '\0';
Packit f574b8
		if (i < 0)
Packit f574b8
		    gtype = GOPHER_INFO;
Packit f574b8
	    }
Packit f574b8
Packit f574b8
	    if (gtype == GOPHER_WWW) {	/* Gopher pointer to W3 */
Packit f574b8
		PUTS("(HTML) ");
Packit f574b8
		write_anchor(name, selector);
Packit f574b8
Packit f574b8
	    } else if (gtype == GOPHER_INFO) {
Packit f574b8
		/* Information or separator line */
Packit f574b8
		PUTS("       ");
Packit f574b8
		PUTS(name);
Packit f574b8
Packit f574b8
	    } else if (port &&	/* Other types need port */
Packit f574b8
		       (gtype != GOPHER_DUPLICATE ||
Packit f574b8
			this_type != GOPHER_ERROR)) {
Packit f574b8
		char *address = 0;
Packit f574b8
		const char *format = *selector ? "%s//%s@%s/" : "%s//%s/";
Packit f574b8
Packit f574b8
		if (gtype == GOPHER_TELNET) {
Packit f574b8
		    PUTS(" (TEL) ");
Packit f574b8
		    HTSprintf0(&address, format, STR_TELNET_URL, selector, host);
Packit f574b8
		} else if (gtype == GOPHER_TN3270) {
Packit f574b8
		    PUTS("(3270) ");
Packit f574b8
		    HTSprintf0(&address, format, STR_TN3270_URL, selector, host);
Packit f574b8
		} else {	/* If parsed ok */
Packit f574b8
		    char *r;
Packit f574b8
Packit f574b8
		    switch (gtype) {
Packit f574b8
		    case GOPHER_TEXT:
Packit f574b8
			PUTS("(FILE) ");
Packit f574b8
			break;
Packit f574b8
		    case GOPHER_MENU:
Packit f574b8
			PUTS(" (DIR) ");
Packit f574b8
			break;
Packit f574b8
		    case GOPHER_DUPLICATE:
Packit f574b8
			PUTS(" (+++) ");
Packit f574b8
			break;
Packit f574b8
		    case GOPHER_CSO:
Packit f574b8
			PUTS(" (CSO) ");
Packit f574b8
			break;
Packit f574b8
		    case GOPHER_PCBINARY:
Packit f574b8
			PUTS(" (BIN) ");
Packit f574b8
			break;
Packit f574b8
		    case GOPHER_UUENCODED:
Packit f574b8
			PUTS(" (UUE) ");
Packit f574b8
			break;
Packit f574b8
		    case GOPHER_INDEX:
Packit f574b8
			PUTS("  (?)  ");
Packit f574b8
			break;
Packit f574b8
		    case GOPHER_BINARY:
Packit f574b8
			PUTS(" (BIN) ");
Packit f574b8
			break;
Packit f574b8
		    case GOPHER_GIF:
Packit f574b8
		    case GOPHER_IMAGE:
Packit f574b8
		    case GOPHER_PLUS_IMAGE:
Packit f574b8
			PUTS(" (IMG) ");
Packit f574b8
			break;
Packit f574b8
		    case GOPHER_SOUND:
Packit f574b8
		    case GOPHER_PLUS_SOUND:
Packit f574b8
			PUTS(" (SND) ");
Packit f574b8
			break;
Packit f574b8
		    case GOPHER_MACBINHEX:
Packit f574b8
			PUTS(" (HQX) ");
Packit f574b8
			break;
Packit f574b8
		    case GOPHER_HTML:
Packit f574b8
		    case GOPHER_CHTML:
Packit f574b8
			PUTS("(HTML) ");
Packit f574b8
			break;
Packit f574b8
		    case 'm':
Packit f574b8
			PUTS("(MIME) ");
Packit f574b8
			break;
Packit f574b8
		    case GOPHER_PLUS_MOVIE:
Packit f574b8
			PUTS(" (MOV) ");
Packit f574b8
			break;
Packit f574b8
		    case GOPHER_PLUS_PDF:
Packit f574b8
			PUTS(" (PDF) ");
Packit f574b8
			break;
Packit f574b8
		    default:
Packit f574b8
			PUTS("(UNKN) ");
Packit f574b8
			break;
Packit f574b8
		    }
Packit f574b8
Packit f574b8
		    if (gtype != GOPHER_DUPLICATE)
Packit f574b8
			this_type = gtype;
Packit f574b8
		    HTSprintf0(&address, "//%s/%c", host, this_type);
Packit f574b8
Packit f574b8
		    for (r = selector; *r; r++) {	/* Encode selector string */
Packit f574b8
			if (acceptable[UCH(*r)]) {
Packit f574b8
			    HTSprintf(&address, "%c", *r);
Packit f574b8
			} else {
Packit f574b8
			    HTSprintf(&address, "%c%c%c",
Packit f574b8
				      HEX_ESCAPE,	/* Means hex coming */
Packit f574b8
				      hex[(TOASCII(*r)) >> 4],
Packit f574b8
				      hex[(TOASCII(*r)) & 15]);
Packit f574b8
			}
Packit f574b8
		    }
Packit f574b8
		}
Packit f574b8
		/* Error response from Gopher doesn't deserve to
Packit f574b8
		   be a hyperlink. */
Packit f574b8
		if (strcmp(address, "gopher://error.host:1/0"))
Packit f574b8
		    write_anchor(name, address);
Packit f574b8
		else
Packit f574b8
		    PUTS(name);
Packit f574b8
		FREE(address);
Packit f574b8
	    } else {		/* parse error */
Packit f574b8
		CTRACE((tfp, "HTGopher: Bad menu item (type %d, port %s).\n",
Packit f574b8
			gtype, NonNull(port)));
Packit f574b8
		PUTS(line);
Packit f574b8
Packit f574b8
	    }			/* parse error */
Packit f574b8
Packit f574b8
	    PUTC('\n');
Packit f574b8
	    p = line;		/* Start again at beginning of line */
Packit f574b8
Packit f574b8
	}			/* if end of line */
Packit f574b8
Packit f574b8
    }				/* Loop over characters */
Packit f574b8
Packit f574b8
  end_html:
Packit f574b8
    END(HTML_PRE);
Packit f574b8
    PUTC('\n');
Packit f574b8
    END(HTML_BODY);
Packit f574b8
    PUTC('\n');
Packit f574b8
    END(HTML_HTML);
Packit f574b8
    PUTC('\n');
Packit f574b8
    FREE_TARGET;
Packit f574b8
Packit f574b8
    return;
Packit f574b8
}
Packit f574b8
Packit f574b8
/*	Parse a Gopher CSO document from an ISINDEX query.
Packit f574b8
 *	==================================================
Packit f574b8
 *
Packit f574b8
 *   Accepts an open socket to a CSO server waiting to send us
Packit f574b8
 *   data and puts it on the screen in a reasonable manner.
Packit f574b8
 *
Packit f574b8
 *   Perhaps this data can be automatically linked to some
Packit f574b8
 *   other source as well???
Packit f574b8
 *
Packit f574b8
 *  Taken from hacking by Lou Montulli@ukanaix.cc.ukans.edu
Packit f574b8
 *  on XMosaic-1.1, and put on libwww 2.11 by Arthur Secret,
Packit f574b8
 *  secret@dxcern.cern.ch .
Packit f574b8
 */
Packit f574b8
static void parse_cso(const char *arg,
Packit f574b8
		      HTParentAnchor *anAnchor)
Packit f574b8
{
Packit f574b8
    int ich;
Packit f574b8
    char line[BIG];
Packit f574b8
    char *p = line;
Packit f574b8
    char *first_colon, *second_colon, last_char = '\0';
Packit f574b8
    const char *title;
Packit f574b8
Packit f574b8
    START(HTML_HEAD);
Packit f574b8
    PUTC('\n');
Packit f574b8
    START(HTML_TITLE);
Packit f574b8
    if ((title = HTAnchor_title(anAnchor)))
Packit f574b8
	PUTS(title);
Packit f574b8
    else
Packit f574b8
	PUTS(GOPHER_CSO_SEARCH_RESULTS);
Packit f574b8
    END(HTML_TITLE);
Packit f574b8
    PUTC('\n');
Packit f574b8
    END(HTML_HEAD);
Packit f574b8
    PUTC('\n');
Packit f574b8
    START(HTML_H1);
Packit f574b8
    if ((title = HTAnchor_title(anAnchor)))
Packit f574b8
	PUTS(title);
Packit f574b8
    else {
Packit f574b8
	PUTS(arg);
Packit f574b8
	PUTS(GOPHER_SEARCH_RESULTS);
Packit f574b8
    }
Packit f574b8
    END(HTML_H1);
Packit f574b8
    PUTC('\n');
Packit f574b8
    START(HTML_PRE);
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Start grabbing chars from the network.
Packit f574b8
     */
Packit f574b8
    while ((ich = NEXT_CHAR) != EOF) {
Packit f574b8
	if ((char) ich != LF) {
Packit f574b8
	    *p = (char) ich;	/* Put character in line */
Packit f574b8
	    if (p < &line[BIG - 1])
Packit f574b8
		p++;
Packit f574b8
	} else {
Packit f574b8
	    *p = '\0';		/* Terminate line */
Packit f574b8
	    p = line;		/* Scan it to parse it */
Packit f574b8
	    /*
Packit f574b8
	     * OK we now have a line in 'p'.  Lets parse it and print it.
Packit f574b8
	     */
Packit f574b8
Packit f574b8
	    /*
Packit f574b8
	     * Break on line that begins with a 2.  It's the end of data.
Packit f574b8
	     */
Packit f574b8
	    if (*p == '2')
Packit f574b8
		break;
Packit f574b8
Packit f574b8
	    /*
Packit f574b8
	     * Lines beginning with 5 are errors.  Print them and quit.
Packit f574b8
	     */
Packit f574b8
	    if (*p == '5') {
Packit f574b8
		START(HTML_H2);
Packit f574b8
		PUTS(p + 4);
Packit f574b8
		END(HTML_H2);
Packit f574b8
		break;
Packit f574b8
	    }
Packit f574b8
Packit f574b8
	    if (*p == '-') {
Packit f574b8
		/*
Packit f574b8
		 * Data lines look like -200:#:
Packit f574b8
		 * where # is the search result number and can be multiple
Packit f574b8
		 * digits (infinite?).
Packit f574b8
		 * Find the second colon and check the digit to the left of it
Packit f574b8
		 * to see if they are diferent.  If they are then a different
Packit f574b8
		 * person is starting.  Make this line an 

.

Packit f574b8
		 */
Packit f574b8
Packit f574b8
		/*
Packit f574b8
		 * Find the second_colon.
Packit f574b8
		 */
Packit f574b8
		second_colon = NULL;
Packit f574b8
		first_colon = StrChr(p, ':');
Packit f574b8
		if (first_colon != NULL) {
Packit f574b8
		    second_colon = StrChr(first_colon + 1, ':');
Packit f574b8
		}
Packit f574b8
Packit f574b8
		if (second_colon != NULL) {	/* error check */
Packit f574b8
Packit f574b8
		    if (*(second_colon - 1) != last_char)
Packit f574b8
			/* print seperator */
Packit f574b8
		    {
Packit f574b8
			END(HTML_PRE);
Packit f574b8
			START(HTML_H2);
Packit f574b8
		    }
Packit f574b8
Packit f574b8
		    /*
Packit f574b8
		     * Right now the record appears with the alias (first line)
Packit f574b8
		     * as the header and the rest as 
 text.
Packit f574b8
		     *
Packit f574b8
		     * It might look better with the name as the header and the
Packit f574b8
		     * rest as a 
    with
  • tags. I'm not sure whether the
Packit f574b8
		     * name field comes in any special order or if its even
Packit f574b8
		     * required in a record, so for now the first line is the
Packit f574b8
		     * header no matter what it is (it's almost always the
Packit f574b8
		     * alias).
Packit f574b8
		     *
Packit f574b8
		     * A 
with the first line as the
and the rest as
Packit f574b8
		     * some form of 
might good also?
Packit f574b8
		     */
Packit f574b8
Packit f574b8
		    /*
Packit f574b8
		     * Print data.
Packit f574b8
		     */
Packit f574b8
		    PUTS(second_colon + 1);
Packit f574b8
		    PUTC('\n');
Packit f574b8
Packit f574b8
		    if (*(second_colon - 1) != last_char)
Packit f574b8
			/* end seperator */
Packit f574b8
		    {
Packit f574b8
			END(HTML_H2);
Packit f574b8
			START(HTML_PRE);
Packit f574b8
		    }
Packit f574b8
Packit f574b8
		    /*
Packit f574b8
		     * Save the char before the second colon for comparison on
Packit f574b8
		     * the next pass.
Packit f574b8
		     */
Packit f574b8
		    last_char = *(second_colon - 1);
Packit f574b8
Packit f574b8
		}		/* end if second_colon */
Packit f574b8
	    }			/* end if *p == '-' */
Packit f574b8
	}			/* if end of line */
Packit f574b8
Packit f574b8
    }				/* Loop over characters */
Packit f574b8
Packit f574b8
    /* end the text block */
Packit f574b8
    PUTC('\n');
Packit f574b8
    END(HTML_PRE);
Packit f574b8
    PUTC('\n');
Packit f574b8
    FREE_TARGET;
Packit f574b8
Packit f574b8
    return;			/* all done */
Packit f574b8
}				/* end of procedure */
Packit f574b8
Packit f574b8
/*	Display a Gopher CSO ISINDEX cover page.
Packit f574b8
 *	========================================
Packit f574b8
 */
Packit f574b8
static void display_cso(const char *arg,
Packit f574b8
			HTParentAnchor *anAnchor)
Packit f574b8
{
Packit f574b8
    const char *title;
Packit f574b8
Packit f574b8
    START(HTML_HEAD);
Packit f574b8
    PUTC('\n');
Packit f574b8
    START(HTML_TITLE);
Packit f574b8
    if ((title = HTAnchor_title(anAnchor)))
Packit f574b8
	PUTS(title);
Packit f574b8
    else
Packit f574b8
	PUTS(GOPHER_CSO_INDEX);
Packit f574b8
    END(HTML_TITLE);
Packit f574b8
    PUTC('\n');
Packit f574b8
    START(HTML_ISINDEX);
Packit f574b8
    PUTC('\n');
Packit f574b8
    END(HTML_HEAD);
Packit f574b8
    PUTC('\n');
Packit f574b8
    START(HTML_H1);
Packit f574b8
    if ((title = HTAnchor_title(anAnchor)))
Packit f574b8
	PUTS(title);
Packit f574b8
    else {
Packit f574b8
	PUTS(arg);
Packit f574b8
	PUTS(INDEX_SEGMENT);
Packit f574b8
    }
Packit f574b8
    END(HTML_H1);
Packit f574b8
    PUTS(GOPHER_CSO_INDEX_SUBTITLE);
Packit f574b8
    START(HTML_P);
Packit f574b8
    PUTS(GOPHER_CSO_SOLICIT_KEYWORDS);
Packit f574b8
    START(HTML_P);
Packit f574b8
    PUTS(SEGMENT_KEYWORDS_WILL);
Packit f574b8
    PUTS(SEGMENT_PERSONS_DB_NAME);
Packit f574b8
Packit f574b8
    if (!HTAnchor_title(anAnchor))
Packit f574b8
	HTAnchor_setTitle(anAnchor, arg);
Packit f574b8
Packit f574b8
    FREE_TARGET;
Packit f574b8
    return;
Packit f574b8
}
Packit f574b8
Packit f574b8
/*	Display a Gopher Index document.
Packit f574b8
 *	================================
Packit f574b8
 */
Packit f574b8
static void display_index(const char *arg,
Packit f574b8
			  HTParentAnchor *anAnchor)
Packit f574b8
{
Packit f574b8
    const char *title;
Packit f574b8
Packit f574b8
    START(HTML_HEAD);
Packit f574b8
    PUTC('\n');
Packit f574b8
    PUTC('\n');
Packit f574b8
    START(HTML_TITLE);
Packit f574b8
    if ((title = HTAnchor_title(anAnchor)))
Packit f574b8
	PUTS(title);
Packit f574b8
    else
Packit f574b8
	PUTS(GOPHER_INDEX_TITLE);
Packit f574b8
    END(HTML_TITLE);
Packit f574b8
    PUTC('\n');
Packit f574b8
    START(HTML_ISINDEX);
Packit f574b8
    PUTC('\n');
Packit f574b8
    END(HTML_HEAD);
Packit f574b8
    PUTC('\n');
Packit f574b8
    START(HTML_H1);
Packit f574b8
    if ((title = HTAnchor_title(anAnchor)))
Packit f574b8
	PUTS(title);
Packit f574b8
    else {
Packit f574b8
	PUTS(arg);
Packit f574b8
	PUTS(INDEX_SEGMENT);
Packit f574b8
    }
Packit f574b8
    END(HTML_H1);
Packit f574b8
    PUTS(GOPHER_INDEX_SUBTITLE);
Packit f574b8
    START(HTML_P);
Packit f574b8
    PUTS(GOPHER_SOLICIT_KEYWORDS);
Packit f574b8
Packit f574b8
    if (!HTAnchor_title(anAnchor))
Packit f574b8
	HTAnchor_setTitle(anAnchor, arg);
Packit f574b8
Packit f574b8
    FREE_TARGET;
Packit f574b8
    return;
Packit f574b8
}
Packit f574b8
Packit f574b8
/*	De-escape a selector into a command.
Packit f574b8
 *	====================================
Packit f574b8
 *
Packit f574b8
 *	The % hex escapes are converted. Otheriwse, the string is copied.
Packit f574b8
 */
Packit f574b8
static void de_escape(char *command, const char *selector)
Packit f574b8
{
Packit f574b8
    const char *p = selector;
Packit f574b8
    char *q;
Packit f574b8
Packit f574b8
    if (command == NULL)
Packit f574b8
	outofmem(__FILE__, "HTLoadGopher");
Packit f574b8
Packit f574b8
    q = command;
Packit f574b8
    while (*p) {		/* Decode hex */
Packit f574b8
	if (*p == HEX_ESCAPE) {
Packit f574b8
	    char c;
Packit f574b8
	    unsigned int b;
Packit f574b8
Packit f574b8
	    p++;
Packit f574b8
	    c = *p++;
Packit f574b8
	    b = UCH(from_hex(c));
Packit f574b8
	    c = *p++;
Packit f574b8
	    if (!c)
Packit f574b8
		break;		/* Odd number of chars! */
Packit f574b8
	    *q++ = (char) FROMASCII((b << 4) + UCH(from_hex(c)));
Packit f574b8
	} else {
Packit f574b8
	    *q++ = *p++;	/* Record */
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
    *q = '\0';			/* Terminate command */
Packit f574b8
}
Packit f574b8
Packit f574b8
/*	Free the CSOfields structures. - FM
Packit f574b8
 *	===================================
Packit f574b8
 */
Packit f574b8
static void free_CSOfields(void)
Packit f574b8
{
Packit f574b8
    CSOfield_info *cur = CSOfields;
Packit f574b8
    CSOfield_info *prev;
Packit f574b8
Packit f574b8
    while (cur) {
Packit f574b8
	if (cur->name != cur->name_buf)
Packit f574b8
	    FREE(cur->name);
Packit f574b8
	if (cur->attributes != cur->attr_buf)
Packit f574b8
	    FREE(cur->attributes);
Packit f574b8
	if (cur->description != cur->desc_buf)
Packit f574b8
	    FREE(cur->description);
Packit f574b8
	prev = cur;
Packit f574b8
	cur = cur->next;
Packit f574b8
	FREE(prev);
Packit f574b8
    }
Packit f574b8
Packit f574b8
    return;
Packit f574b8
}
Packit f574b8
Packit f574b8
/*	Interpret CSO/PH form template keys. - FM
Packit f574b8
 *	=========================================
Packit f574b8
 */
Packit f574b8
static void interpret_cso_key(const char *key,
Packit f574b8
			      char *buf,
Packit f574b8
			      size_t bufsize,
Packit f574b8
			      int *length,
Packit f574b8
			      CSOformgen_context * ctx,
Packit f574b8
			      HTStream *Target)
Packit f574b8
{
Packit f574b8
    CSOfield_info *fld;
Packit f574b8
Packit f574b8
    if ((fld = ctx->fld) != 0) {
Packit f574b8
	/*
Packit f574b8
	 * Most substitutions only recognized inside of loops.
Packit f574b8
	 */
Packit f574b8
	int error = 0;
Packit f574b8
Packit f574b8
	if (0 == StrNCmp(key, "$(FID)", 6)) {
Packit f574b8
	    sprintf(buf, "%d", fld->id);
Packit f574b8
	} else if (0 == StrNCmp(key, "$(FDESC)", 8)) {
Packit f574b8
	    sprintf(buf, "%.2046s", fld->description);
Packit f574b8
	} else if (0 == StrNCmp(key, "$(FDEF)", 7)) {
Packit f574b8
	    strcpy(buf, fld->defreturn ? " checked" : "");
Packit f574b8
	} else if (0 == StrNCmp(key, "$(FNDX)", 7)) {
Packit f574b8
	    strcpy(buf, fld->indexed ? "*" : "");
Packit f574b8
	} else if (0 == StrNCmp(key, "$(FSIZE)", 8)) {
Packit f574b8
	    sprintf(buf, " size=%d maxlength=%d",
Packit f574b8
		    fld->max_size > 55 ? 55 : fld->max_size,
Packit f574b8
		    fld->max_size);
Packit f574b8
	} else if (0 == StrNCmp(key, "$(FSIZE2)", 9)) {
Packit f574b8
	    sprintf(buf, " maxlength=%d", fld->max_size);
Packit f574b8
	} else {
Packit f574b8
	    error = 1;
Packit f574b8
	}
Packit f574b8
	if (!error) {
Packit f574b8
	    *length = (int) strlen(buf);
Packit f574b8
	    return;
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
    buf[0] = '\0';
Packit f574b8
    if (0 == StrNCmp(key, "$(NEXTFLD)", 10)) {
Packit f574b8
	if (!ctx->fld)
Packit f574b8
	    fld = CSOfields;
Packit f574b8
	else
Packit f574b8
	    fld = ctx->fld->next;
Packit f574b8
	switch (ctx->field_select) {
Packit f574b8
	case 0:
Packit f574b8
	    /*
Packit f574b8
	     * 'Query' fields, public and lookup attributes.
Packit f574b8
	     */
Packit f574b8
	    for (; fld; fld = fld->next)
Packit f574b8
		if (fld->gpublic && (fld->lookup == 1))
Packit f574b8
		    break;
Packit f574b8
	    break;
Packit f574b8
	case 1:
Packit f574b8
	    /*
Packit f574b8
	     * 'Query' fields, accept lookup attribute.
Packit f574b8
	     */
Packit f574b8
	    for (; fld; fld = fld->next)
Packit f574b8
		if (fld->lookup == 1)
Packit f574b8
		    break;
Packit f574b8
	    break;
Packit f574b8
	case 2:
Packit f574b8
	    /*
Packit f574b8
	     * 'Return' fields, public only.
Packit f574b8
	     */
Packit f574b8
	    for (; fld; fld = fld->next)
Packit f574b8
		if (fld->gpublic)
Packit f574b8
		    break;
Packit f574b8
	    break;
Packit f574b8
	case 3:
Packit f574b8
	    /*
Packit f574b8
	     * All fields.
Packit f574b8
	     */
Packit f574b8
	    break;
Packit f574b8
	}
Packit f574b8
	if (fld) {
Packit f574b8
	    ctx->cur_line = ctx->rep_line;
Packit f574b8
	    ctx->cur_off = ctx->rep_off;
Packit f574b8
	}
Packit f574b8
	ctx->fld = fld;
Packit f574b8
Packit f574b8
    } else if ((0 == StrNCmp(key, "$(QFIELDS)", 10)) ||
Packit f574b8
	       (0 == StrNCmp(key, "$(RFIELDS)", 10))) {
Packit f574b8
	/*
Packit f574b8
	 * Begin iteration sequence.
Packit f574b8
	 */
Packit f574b8
	ctx->rep_line = ctx->cur_line;
Packit f574b8
	ctx->rep_off = ctx->cur_off;
Packit f574b8
	ctx->fld = (CSOfield_info *) 0;
Packit f574b8
	ctx->seek = "$(NEXTFLD)";
Packit f574b8
	ctx->field_select = (key[2] == 'Q') ? 0 : 2;
Packit f574b8
	if (ctx->public_override)
Packit f574b8
	    ctx->field_select++;
Packit f574b8
Packit f574b8
    } else if (0 == StrNCmp(key, "$(NAMEFLD)", 10)) {
Packit f574b8
	/*
Packit f574b8
	 * Special, locate name field.  Flag lookup so QFIELDS will skip it.
Packit f574b8
	 */
Packit f574b8
	for (fld = CSOfields; fld; fld = fld->next)
Packit f574b8
	    if (strcmp(fld->name, "name") == 0 ||
Packit f574b8
		strcmp(fld->name, "Name") == 0) {
Packit f574b8
		if (fld->lookup)
Packit f574b8
		    fld->lookup = 2;
Packit f574b8
		break;
Packit f574b8
	    }
Packit f574b8
	ctx->fld = fld;
Packit f574b8
    } else if (0 == StrNCmp(key, "$(HOST)", 7)) {
Packit f574b8
	strcpy(buf, ctx->host);
Packit f574b8
    } else if (0 == StrNCmp(key, "$(PORT)", 7)) {
Packit f574b8
	sprintf(buf, "%d", ctx->port);
Packit f574b8
    } else {
Packit f574b8
	/*
Packit f574b8
	 * No match, dump key to buffer so client sees it for debugging.
Packit f574b8
	 */
Packit f574b8
	size_t out = 0;
Packit f574b8
Packit f574b8
	while (*key && (*key != ')')) {
Packit f574b8
	    buf[out++] = (*key++);
Packit f574b8
	    if (out > bufsize - 2) {
Packit f574b8
		buf[out] = '\0';
Packit f574b8
		(*Target->isa->put_block) (Target, buf, (int) strlen(buf));
Packit f574b8
		out = 0;
Packit f574b8
	    }
Packit f574b8
	}
Packit f574b8
	buf[out++] = ')';
Packit f574b8
	buf[out] = '\0';
Packit f574b8
    }
Packit f574b8
    *length = (int) strlen(buf);
Packit f574b8
    return;
Packit f574b8
}
Packit f574b8
Packit f574b8
/*	Parse the elements in a CSO/PH fields structure. - FM
Packit f574b8
 *	=====================================================
Packit f574b8
 */
Packit f574b8
static int parse_cso_field_info(CSOfield_info *blk)
Packit f574b8
{
Packit f574b8
    char *info, *max_spec;
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Initialize all fields to default values.
Packit f574b8
     */
Packit f574b8
    blk->indexed = blk->lookup = blk->reserved = blk->max_size = blk->url = 0;
Packit f574b8
    blk->defreturn = blk->explicit_return = blk->gpublic = 0;
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Search for keywords in info string and set values.  Attributes are
Packit f574b8
     * converted to all lower-case for comparison.
Packit f574b8
     */
Packit f574b8
    info = blk->attributes;
Packit f574b8
    LYLowerCase(info);
Packit f574b8
    if (strstr(info, "indexed "))
Packit f574b8
	blk->indexed = 1;
Packit f574b8
    if (strstr(info, "default "))
Packit f574b8
	blk->defreturn = 1;
Packit f574b8
    if (strstr(info, "public "))
Packit f574b8
	blk->gpublic = 1;
Packit f574b8
    if (strstr(info, "lookup "))
Packit f574b8
	blk->lookup = 1;
Packit f574b8
    if (strstr(info, "url ")) {
Packit f574b8
	blk->url = 1;
Packit f574b8
	blk->defreturn = 1;
Packit f574b8
    }
Packit f574b8
    max_spec = strstr(info, "max ");
Packit f574b8
    if (max_spec) {
Packit f574b8
	sscanf(&max_spec[4], "%d", &blk->max_size);
Packit f574b8
    } else {
Packit f574b8
	blk->max_size = 32;
Packit f574b8
    }
Packit f574b8
Packit f574b8
    return 0;
Packit f574b8
}
Packit f574b8
Packit f574b8
/*	Parse a reply from a CSO/PH fields request. - FM
Packit f574b8
 *	================================================
Packit f574b8
 */
Packit f574b8
static int parse_cso_fields(char *buf,
Packit f574b8
			    size_t size)
Packit f574b8
{
Packit f574b8
    int ich;
Packit f574b8
    char *p = buf;
Packit f574b8
    int i, code = 0, prev_code;
Packit f574b8
    size_t alen;
Packit f574b8
    char *indx, *name;
Packit f574b8
    CSOfield_info *last, *newf;
Packit f574b8
Packit f574b8
    last = CSOfields = (CSOfield_info *) 0;
Packit f574b8
    prev_code = -2555;
Packit f574b8
    buf[0] = '\0';
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Start grabbing chars from the network.
Packit f574b8
     */
Packit f574b8
    while ((ich = NEXT_CHAR) != EOF) {
Packit f574b8
	if (interrupted_in_htgetcharacter) {
Packit f574b8
	    CTRACE((tfp,
Packit f574b8
		    "HTLoadCSO: Interrupted in HTGetCharacter, apparently.\n"));
Packit f574b8
	    free_CSOfields();
Packit f574b8
	    buf[0] = '\0';
Packit f574b8
	    return HT_INTERRUPTED;
Packit f574b8
	}
Packit f574b8
Packit f574b8
	if ((char) ich != LF) {
Packit f574b8
	    *p = (char) ich;	/* Put character in buffer */
Packit f574b8
	    if (p < &buf[size - 1]) {
Packit f574b8
		p++;
Packit f574b8
	    }
Packit f574b8
	} else {
Packit f574b8
	    *p = '\0';		/* Terminate line */
Packit f574b8
	    p = buf;		/* Scan it to parse it */
Packit f574b8
Packit f574b8
	    /* OK we now have a line in 'p' lets parse it.
Packit f574b8
	     */
Packit f574b8
Packit f574b8
	    /*
Packit f574b8
	     * Break on line that begins with a 2.  It's the end of data.
Packit f574b8
	     */
Packit f574b8
	    if (*p == '2')
Packit f574b8
		break;
Packit f574b8
Packit f574b8
	    /*
Packit f574b8
	     * Lines beginning with 5 are errors.  Print them and quit.
Packit f574b8
	     */
Packit f574b8
	    if (*p == '5') {
Packit f574b8
		return 5;
Packit f574b8
	    }
Packit f574b8
Packit f574b8
	    if (*p == '-') {
Packit f574b8
		/*
Packit f574b8
		 * Data lines look like -200:#:
Packit f574b8
		 * where # is the search result number and can be multiple
Packit f574b8
		 * digits (infinite?).
Packit f574b8
		 */
Packit f574b8
Packit f574b8
		/*
Packit f574b8
		 * Check status, ignore any non-success.
Packit f574b8
		 */
Packit f574b8
		if (p[1] != '2')
Packit f574b8
		    continue;
Packit f574b8
Packit f574b8
		/*
Packit f574b8
		 * Parse fields within returned line into status, ndx, name,
Packit f574b8
		 * data.
Packit f574b8
		 */
Packit f574b8
		indx = NULL;
Packit f574b8
		name = NULL;
Packit f574b8
		for (i = 0; p[i]; i++) {
Packit f574b8
		    if (p[i] == ':') {
Packit f574b8
			p[i] = '\0';
Packit f574b8
			if (!indx) {
Packit f574b8
			    indx = (char *) &p[i + 1];
Packit f574b8
			    code = atoi(indx);
Packit f574b8
			} else if (!name) {
Packit f574b8
			    name = (char *) &p[i + 1];
Packit f574b8
			} else {
Packit f574b8
			    i++;
Packit f574b8
			    break;
Packit f574b8
			}
Packit f574b8
		    }
Packit f574b8
		}
Packit f574b8
		/*
Packit f574b8
		 * Add data to field structure.
Packit f574b8
		 */
Packit f574b8
		if (name) {
Packit f574b8
		    if (code == prev_code) {
Packit f574b8
			/*
Packit f574b8
			 * Remaining data are description.  Save in current
Packit f574b8
			 * info block.
Packit f574b8
			 */
Packit f574b8
			if (last != NULL) {
Packit f574b8
			    alen = strlen((char *) &p[i]) + 1;
Packit f574b8
			    if (alen > sizeof(last->desc_buf)) {
Packit f574b8
				if (last->description != last->desc_buf)
Packit f574b8
				    FREE(last->description);
Packit f574b8
				if (!(last->description = (char *) malloc(alen))) {
Packit f574b8
				    outofmem(__FILE__, "HTLoadCSO");
Packit f574b8
				}
Packit f574b8
			    }
Packit f574b8
			    strcpy(last->description, (char *) &p[i]);
Packit f574b8
			}
Packit f574b8
		    } else {
Packit f574b8
			/*
Packit f574b8
			 * Initialize new block, append to end of list to
Packit f574b8
			 * preserve order.
Packit f574b8
			 */
Packit f574b8
			newf = typecalloc(CSOfield_info);
Packit f574b8
Packit f574b8
			if (!newf) {
Packit f574b8
			    outofmem(__FILE__, "HTLoadCSO");
Packit f574b8
			}
Packit f574b8
Packit f574b8
			if (last)
Packit f574b8
			    last->next = newf;
Packit f574b8
			else
Packit f574b8
			    CSOfields = newf;
Packit f574b8
			last = newf;
Packit f574b8
Packit f574b8
			newf->next = (CSOfield_info *) 0;
Packit f574b8
			newf->name = newf->name_buf;
Packit f574b8
			alen = strlen(name) + 1;
Packit f574b8
			if (alen > sizeof(newf->name_buf)) {
Packit f574b8
			    if (!(newf->name = (char *) malloc(alen))) {
Packit f574b8
				outofmem(__FILE__, "HTLoadCSO");
Packit f574b8
			    }
Packit f574b8
			}
Packit f574b8
			strcpy(newf->name, name);
Packit f574b8
Packit f574b8
			newf->attributes = newf->attr_buf;
Packit f574b8
			alen = strlen((char *) &p[i]) + 2;
Packit f574b8
			if (alen > sizeof(newf->attr_buf)) {
Packit f574b8
			    if (!(newf->attributes = (char *) malloc(alen))) {
Packit f574b8
				outofmem(__FILE__, "HTLoadCSO");
Packit f574b8
			    }
Packit f574b8
			}
Packit f574b8
			strcpy(newf->attributes, (char *) &p[i]);
Packit f574b8
			strcpy((char *) &newf->attributes[alen - 2], " ");
Packit f574b8
			newf->description = newf->desc_buf;
Packit f574b8
			newf->desc_buf[0] = '\0';
Packit f574b8
			newf->id = atoi(indx);
Packit f574b8
			/*
Packit f574b8
			 * Scan for keywords.
Packit f574b8
			 */
Packit f574b8
			parse_cso_field_info(newf);
Packit f574b8
		    }
Packit f574b8
		    prev_code = code;
Packit f574b8
		} else
Packit f574b8
		    break;
Packit f574b8
	    }			/* end if *p == '-' */
Packit f574b8
	}			/* if end of line */
Packit f574b8
Packit f574b8
    }				/* Loop over characters */
Packit f574b8
Packit f574b8
    /* end the text block */
Packit f574b8
Packit f574b8
    if (buf[0] == '\0') {
Packit f574b8
	return -1;		/* no response */
Packit f574b8
    }
Packit f574b8
    buf[0] = '\0';
Packit f574b8
    return 0;			/* all done */
Packit f574b8
}				/* end of procedure */
Packit f574b8
Packit f574b8
/*	Generate a form for submitting CSO/PH searches. - FM
Packit f574b8
 *	====================================================
Packit f574b8
 */
Packit f574b8
static int generate_cso_form(char *host,
Packit f574b8
			     int port,
Packit f574b8
			     char *buf,
Packit f574b8
			     size_t bufsize,
Packit f574b8
			     HTStream *Target)
Packit f574b8
{
Packit f574b8
    int i, j, length;
Packit f574b8
    size_t out;
Packit f574b8
    int full_flag = 1;
Packit f574b8
    const char *key;
Packit f574b8
    const char *line;
Packit f574b8
    CSOformgen_context ctx;
Packit f574b8
    static const char *ctemplate[] =
Packit f574b8
    {
Packit f574b8
	"<HTML>\n<HEAD>\n<TITLE>CSO/PH Query Form for $(HOST)</TITLE>\n</HEAD>\n<BODY>",
Packit f574b8
	"

CSO/PH Query Form for $(HOST)

",
Packit f574b8
	"To search the database for a name, fill in one or more of the fields",
Packit f574b8
	"in the form below and activate the 'Submit query' button.  At least",
Packit f574b8
	"one of the entered fields must be flagged as indexed.",
Packit f574b8
	"
<FORM method=\"POST\" action=\"cso://$(HOST)/\">",
Packit f574b8
	"[ <input type=\"submit\" value=\"Submit query\"> | ",
Packit f574b8
	"<input type=\"reset\" value=\"Clear fields\"> ]",
Packit f574b8
	"

",
Packit f574b8
	"   
Search parameters (* indicates indexed field):",
Packit f574b8
	"   
",
Packit f574b8
	"$(NAMEFLD)    
\n
$(FDESC)$(FNDX)",
Packit f574b8
	"    
Last: <input name=\"q_$(FID)\" type=\"text\" size=49$(FSIZE2)>",
Packit f574b8
	"    
First: <input name=\"q_$(FID)\" type=\"text\" size=48$(FSIZE2)>",
Packit f574b8
	"$(QFIELDS)    
$(FDESC)$(FNDX)",
Packit f574b8
	"    
<input name=\"q_$(FID)\" type=\"text\" $(FSIZE)>\n$(NEXTFLD)",
Packit f574b8
	"    ",
Packit f574b8
	"   \n

",
Packit f574b8
	"   
Output format:",
Packit f574b8
	"   
Returned data option: <select name=\"return\">",
Packit f574b8
	"    <option>default<option selected>all<option>selected</select>
",
Packit f574b8
	"$(RFIELDS)    <input type=\"checkbox\" name=\"r_$(FID)\"$(FDEF)> $(FDESC)
",
Packit f574b8
	"$(NEXTFLD)    ",
Packit f574b8
	"   </FORM>
\n</BODY>\n</HTML>",
Packit f574b8
	(char *) 0
Packit f574b8
    };
Packit f574b8
Packit f574b8
    memset(&ctx, 0, sizeof(ctx));
Packit f574b8
    ctx.host = host;
Packit f574b8
    ctx.seek = (char *) 0;
Packit f574b8
    ctx.port = port;
Packit f574b8
    ctx.fld = (CSOfield_info *) 0;
Packit f574b8
    ctx.public_override = full_flag;
Packit f574b8
    /*
Packit f574b8
     * Parse the strings in the template array to produce HTML document to send
Packit f574b8
     * to client.  First line is skipped for 'full' lists.
Packit f574b8
     */
Packit f574b8
    out = 0;
Packit f574b8
    buf[out] = '\0';
Packit f574b8
    for (i = 0; ctemplate[i]; i++) {
Packit f574b8
	/*
Packit f574b8
	 * Search the current string for substitution, flagged by $(
Packit f574b8
	 */
Packit f574b8
	for (line = ctemplate[i], j = 0; line[j]; j++) {
Packit f574b8
	    if ((line[j] == '$') && (line[j + 1] == '(')) {
Packit f574b8
		/*
Packit f574b8
		 * Command detected, flush output buffer and find closing ')'
Packit f574b8
		 * that delimits the command.
Packit f574b8
		 */
Packit f574b8
		buf[out] = '\0';
Packit f574b8
		if (out > 0)
Packit f574b8
		    (*Target->isa->put_block) (Target, buf, (int) strlen(buf));
Packit f574b8
		for (key = &line[j]; line[j + 1] && (line[j] != ')'); j++) {
Packit f574b8
		    ;
Packit f574b8
		}
Packit f574b8
		/*
Packit f574b8
		 * Save context, interpet command and restore updated context.
Packit f574b8
		 */
Packit f574b8
		ctx.cur_line = i;
Packit f574b8
		ctx.cur_off = j;
Packit f574b8
		interpret_cso_key(key, buf, bufsize, &length, &ctx, Target);
Packit f574b8
		i = ctx.cur_line;
Packit f574b8
		j = ctx.cur_off;
Packit f574b8
		line = ctemplate[i];
Packit f574b8
		out = (size_t) length;
Packit f574b8
Packit f574b8
		if (ctx.seek) {
Packit f574b8
		    /*
Packit f574b8
		     * Command wants us to skip (forward) to indicated token. 
Packit f574b8
		     * Start at current position.
Packit f574b8
		     */
Packit f574b8
		    size_t slen = strlen(ctx.seek);
Packit f574b8
Packit f574b8
		    for (; ctemplate[i]; i++) {
Packit f574b8
			for (line = ctemplate[i]; line[j]; j++) {
Packit f574b8
			    if (line[j] == '$')
Packit f574b8
				if (0 == StrNCmp(ctx.seek, &line[j], slen)) {
Packit f574b8
				    if (j == 0)
Packit f574b8
					j = (int) strlen(ctemplate[--i]) - 1;
Packit f574b8
				    else
Packit f574b8
					--j;
Packit f574b8
				    line = ctemplate[i];
Packit f574b8
				    ctx.seek = (char *) 0;
Packit f574b8
				    break;
Packit f574b8
				}
Packit f574b8
			}
Packit f574b8
			if (!ctx.seek)
Packit f574b8
			    break;
Packit f574b8
			j = 0;
Packit f574b8
		    }
Packit f574b8
		    if (ctx.seek) {
Packit f574b8
			char *temp = 0;
Packit f574b8
Packit f574b8
			HTSprintf0(&temp, GOPHER_CSO_SEEK_FAILED, ctx.seek);
Packit f574b8
			(*Target->isa->put_block) (Target, temp, (int) strlen(temp));
Packit f574b8
			FREE(temp);
Packit f574b8
		    }
Packit f574b8
		}
Packit f574b8
	    } else {
Packit f574b8
		/*
Packit f574b8
		 * Non-command text, add to output buffer.
Packit f574b8
		 */
Packit f574b8
		buf[out++] = line[j];
Packit f574b8
		if (out > (bufsize - 3)) {
Packit f574b8
		    buf[out] = '\0';
Packit f574b8
		    (*Target->isa->put_block) (Target, buf, (int) strlen(buf));
Packit f574b8
		    out = 0;
Packit f574b8
		}
Packit f574b8
	    }
Packit f574b8
	}
Packit f574b8
	buf[out++] = '\n';
Packit f574b8
	buf[out] = '\0';
Packit f574b8
    }
Packit f574b8
    if (out > 0)
Packit f574b8
	(*Target->isa->put_block) (Target, buf, (int) strlen(buf));
Packit f574b8
Packit f574b8
    return 0;
Packit f574b8
}
Packit f574b8
Packit f574b8
/*	Generate a results report for CSO/PH form-based searches. - FM
Packit f574b8
 *	==============================================================
Packit f574b8
 */
Packit f574b8
static int generate_cso_report(HTStream *Target)
Packit f574b8
{
Packit f574b8
    int ich;
Packit f574b8
    char line[BIG];
Packit f574b8
    char *buf = 0;
Packit f574b8
    char *p = line, *href = NULL;
Packit f574b8
    int i, prev_ndx, ndx;
Packit f574b8
    char *rcode, *ndx_str, *fname, *fvalue, *l;
Packit f574b8
    CSOfield_info *fld;
Packit f574b8
    BOOL stop = FALSE;
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Read lines until non-negative status.
Packit f574b8
     */
Packit f574b8
    prev_ndx = -100;
Packit f574b8
    /*
Packit f574b8
     * Start grabbing chars from the network.
Packit f574b8
     */
Packit f574b8
    while (!stop && (ich = NEXT_CHAR) != EOF) {
Packit f574b8
	if (interrupted_in_htgetcharacter) {
Packit f574b8
	    CTRACE((tfp,
Packit f574b8
		    "HTLoadCSO: Interrupted in HTGetCharacter, apparently.\n"));
Packit f574b8
	    _HTProgress(CONNECTION_INTERRUPTED);
Packit f574b8
	    goto end_CSOreport;
Packit f574b8
	}
Packit f574b8
Packit f574b8
	if ((char) ich != LF) {
Packit f574b8
	    *p = (char) ich;	/* Put character in line */
Packit f574b8
	    if (p < &line[BIG - 1]) {
Packit f574b8
		p++;
Packit f574b8
	    }
Packit f574b8
	} else {
Packit f574b8
	    *p = '\0';		/* Terminate line */
Packit f574b8
	    /*
Packit f574b8
	     * OK we now have a line.  Load it as 'p' and parse it.
Packit f574b8
	     */
Packit f574b8
	    p = line;
Packit f574b8
	    if (p[0] != '-' && p[0] != '1') {
Packit f574b8
		stop = TRUE;
Packit f574b8
	    }
Packit f574b8
	    rcode = (p[0] == '-') ? &p[1] : p;
Packit f574b8
	    ndx_str = fname = NULL;
Packit f574b8
	    for (i = 0; p[i] != '\0'; i++) {
Packit f574b8
		if (p[i] == ':') {
Packit f574b8
		    p[i] = '\0';
Packit f574b8
		    fname = &p[i + 1];
Packit f574b8
		    if (ndx_str) {
Packit f574b8
			break;
Packit f574b8
		    }
Packit f574b8
		    ndx_str = fname;
Packit f574b8
		}
Packit f574b8
	    }
Packit f574b8
	    if (ndx_str) {
Packit f574b8
		ndx = atoi(ndx_str);
Packit f574b8
		if (prev_ndx != ndx) {
Packit f574b8
		    if (prev_ndx != -100) {
Packit f574b8
			HTSprintf0(&buf, "\n");
Packit f574b8
			(*Target->isa->put_block) (Target, buf, (int) strlen(buf));
Packit f574b8
		    }
Packit f574b8
		    if (ndx == 0) {
Packit f574b8
			HTSprintf0(&buf,
Packit f574b8
				   "
Information/status
\n");
Packit f574b8
			(*Target->isa->put_block) (Target, buf, (int) strlen(buf));
Packit f574b8
		    } else {
Packit f574b8
			HTSprintf0(&buf,
Packit f574b8
				   "
Entry %d:
\n", ndx);
Packit f574b8
			(*Target->isa->put_block) (Target, buf, (int) strlen(buf));
Packit f574b8
		    }
Packit f574b8
		    prev_ndx = ndx;
Packit f574b8
		}
Packit f574b8
	    } else {
Packit f574b8
		HTSprintf0(&buf, "
%s\n", rcode);
Packit f574b8
		(*Target->isa->put_block) (Target, buf, (int) strlen(buf));
Packit f574b8
		continue;
Packit f574b8
	    }
Packit f574b8
	    if ((*rcode >= '2') && (*rcode <= '5') && (fname != ndx_str)) {
Packit f574b8
		while (*fname == ' ') {
Packit f574b8
		    fname++;	/* trim leading spaces */
Packit f574b8
		}
Packit f574b8
		for (fvalue = fname; *fvalue; fvalue++) {
Packit f574b8
		    if (*fvalue == ':') {
Packit f574b8
			*fvalue++ = '\0';
Packit f574b8
			i = (int) strlen(fname) - 1;
Packit f574b8
			while (i >= 0 && fname[i] == ' ') {
Packit f574b8
			    fname[i--] = '\0';	/* trim trailing */
Packit f574b8
			}
Packit f574b8
			break;
Packit f574b8
		    }
Packit f574b8
		}
Packit f574b8
		if (fvalue) {
Packit f574b8
		    while (*fvalue == ' ') {
Packit f574b8
			fvalue++;	/* trim leading spaces */
Packit f574b8
		    }
Packit f574b8
		}
Packit f574b8
		if (*fname) {
Packit f574b8
		    for (fld = CSOfields; fld; fld = fld->next) {
Packit f574b8
			if (!strcmp(fld->name, fname)) {
Packit f574b8
			    if (fld->description) {
Packit f574b8
				fname = fld->description;
Packit f574b8
			    }
Packit f574b8
			    break;
Packit f574b8
			}
Packit f574b8
		    }
Packit f574b8
		    if (fld && fld->url) {
Packit f574b8
			HTSprintf0(&buf,
Packit f574b8
				   "
%s
%s\n",
Packit f574b8
				   fname, fvalue, fvalue);
Packit f574b8
			(*Target->isa->put_block) (Target, buf, (int) strlen(buf));
Packit f574b8
		    } else {
Packit f574b8
			HTSprintf0(&buf, "
%s
", fname);
Packit f574b8
			(*Target->isa->put_block) (Target, buf, (int) strlen(buf));
Packit f574b8
			buf[0] = '\0';
Packit f574b8
			l = fvalue;
Packit f574b8
			while (*l) {
Packit f574b8
			    if (*l == '<') {
Packit f574b8
				StrAllocCat(buf, "<");
Packit f574b8
				l++;
Packit f574b8
			    } else if (*l == '>') {
Packit f574b8
				StrAllocCat(buf, ">");
Packit f574b8
				l++;
Packit f574b8
			    } else if (StrNCmp(l, STR_NEWS_URL, LEN_NEWS_URL) &&
Packit f574b8
				       StrNCmp(l, "snews://", 8) &&
Packit f574b8
				       StrNCmp(l, "nntp://", 7) &&
Packit f574b8
				       StrNCmp(l, "snewspost:", 10) &&
Packit f574b8
				       StrNCmp(l, "snewsreply:", 11) &&
Packit f574b8
				       StrNCmp(l, "newspost:", 9) &&
Packit f574b8
				       StrNCmp(l, "newsreply:", 10) &&
Packit f574b8
				       StrNCmp(l, "ftp://", 6) &&
Packit f574b8
				       StrNCmp(l, "file:/", 6) &&
Packit f574b8
				       StrNCmp(l, "finger://", 9) &&
Packit f574b8
				       StrNCmp(l, "http://", 7) &&
Packit f574b8
				       StrNCmp(l, "https://", 8) &&
Packit f574b8
				       StrNCmp(l, "wais://", 7) &&
Packit f574b8
				       StrNCmp(l, STR_MAILTO_URL,
Packit f574b8
					       LEN_MAILTO_URL) &&
Packit f574b8
				       StrNCmp(l, "cso://", 6) &&
Packit f574b8
				       StrNCmp(l, "gopher://", 9)) {
Packit f574b8
				HTSprintf(&buf, "%c", *l++);
Packit f574b8
			    } else {
Packit f574b8
				StrAllocCat(buf, "
Packit f574b8
				StrAllocCopy(href, l);
Packit f574b8
				StrAllocCat(buf, strtok(href, " \r\n\t,>)\""));
Packit f574b8
				StrAllocCat(buf, "\">");
Packit f574b8
				while (*l && !StrChr(" \r\n\t,>)\"", *l)) {
Packit f574b8
				    HTSprintf(&buf, "%c", *l++);
Packit f574b8
				}
Packit f574b8
				StrAllocCat(buf, "");
Packit f574b8
				FREE(href);
Packit f574b8
			    }
Packit f574b8
			}
Packit f574b8
			StrAllocCat(buf, "\n");
Packit f574b8
			(*Target->isa->put_block) (Target, buf, (int) strlen(buf));
Packit f574b8
		    }
Packit f574b8
		} else {
Packit f574b8
		    HTSprintf0(&buf, "
");
Packit f574b8
		    (*Target->isa->put_block) (Target, buf, (int) strlen(buf));
Packit f574b8
		    buf[0] = '\0';
Packit f574b8
		    l = fvalue;
Packit f574b8
		    while (*l) {
Packit f574b8
			if (*l == '<') {
Packit f574b8
			    StrAllocCat(buf, "<");
Packit f574b8
			    l++;
Packit f574b8
			} else if (*l == '>') {
Packit f574b8
			    StrAllocCat(buf, ">");
Packit f574b8
			    l++;
Packit f574b8
			} else if (StrNCmp(l, STR_NEWS_URL, LEN_NEWS_URL) &&
Packit f574b8
				   StrNCmp(l, "snews://", 8) &&
Packit f574b8
				   StrNCmp(l, "nntp://", 7) &&
Packit f574b8
				   StrNCmp(l, "snewspost:", 10) &&
Packit f574b8
				   StrNCmp(l, "snewsreply:", 11) &&
Packit f574b8
				   StrNCmp(l, "newspost:", 9) &&
Packit f574b8
				   StrNCmp(l, "newsreply:", 10) &&
Packit f574b8
				   StrNCmp(l, "ftp://", 6) &&
Packit f574b8
				   StrNCmp(l, "file:/", 6) &&
Packit f574b8
				   StrNCmp(l, "finger://", 9) &&
Packit f574b8
				   StrNCmp(l, "http://", 7) &&
Packit f574b8
				   StrNCmp(l, "https://", 8) &&
Packit f574b8
				   StrNCmp(l, "wais://", 7) &&
Packit f574b8
				   StrNCmp(l, STR_MAILTO_URL, LEN_MAILTO_URL) &&
Packit f574b8
				   StrNCmp(l, "cso://", 6) &&
Packit f574b8
				   StrNCmp(l, "gopher://", 9)) {
Packit f574b8
			    HTSprintf(&buf, "%c", *l++);
Packit f574b8
			} else {
Packit f574b8
			    StrAllocCat(buf, "
Packit f574b8
			    StrAllocCopy(href, l);
Packit f574b8
			    StrAllocCat(buf, strtok(href, " \r\n\t,>)\""));
Packit f574b8
			    StrAllocCat(buf, "\">");
Packit f574b8
			    while (*l && !StrChr(" \r\n\t,>)\"", *l)) {
Packit f574b8
				HTSprintf(&buf, "%c", *l++);
Packit f574b8
			    }
Packit f574b8
			    StrAllocCat(buf, "");
Packit f574b8
			    FREE(href);
Packit f574b8
			}
Packit f574b8
		    }
Packit f574b8
		    StrAllocCat(buf, "\n");
Packit f574b8
		    (*Target->isa->put_block) (Target, buf, (int) strlen(buf));
Packit f574b8
		}
Packit f574b8
	    } else {
Packit f574b8
		HTSprintf0(&buf, "
%s\n", fname);
Packit f574b8
		(*Target->isa->put_block) (Target, buf, (int) strlen(buf));
Packit f574b8
	    }
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
  end_CSOreport:
Packit f574b8
    if (prev_ndx != -100) {
Packit f574b8
	HTSprintf0(&buf, "\n");
Packit f574b8
	(*Target->isa->put_block) (Target, buf, (int) strlen(buf));
Packit f574b8
    }
Packit f574b8
    FREE(buf);
Packit f574b8
    return 0;
Packit f574b8
}
Packit f574b8
Packit f574b8
/*	CSO/PH form-based search gateway - FM			HTLoadCSO
Packit f574b8
 *	=====================================
Packit f574b8
 */
Packit f574b8
static int HTLoadCSO(const char *arg,
Packit f574b8
		     HTParentAnchor *anAnchor,
Packit f574b8
		     HTFormat format_out,
Packit f574b8
		     HTStream *sink)
Packit f574b8
{
Packit f574b8
    static const char end_form[] = "</BODY>\n</HTML>\n";
Packit f574b8
    char *host, *cp, *data;
Packit f574b8
    int port = CSO_PORT;
Packit f574b8
    int status;			/* tcp return */
Packit f574b8
    bstring *command = NULL;
Packit f574b8
    bstring *content = NULL;
Packit f574b8
    int len, i, j, start, finish, flen, ndx;
Packit f574b8
    int return_type, has_indexed;
Packit f574b8
    CSOfield_info *fld;
Packit f574b8
    char buf[2048];
Packit f574b8
    HTFormat format_in = WWW_HTML;
Packit f574b8
    HTStream *Target = NULL;
Packit f574b8
Packit f574b8
    if (!acceptable_inited)
Packit f574b8
	init_acceptable();
Packit f574b8
Packit f574b8
    if (!arg)
Packit f574b8
	return -3;		/* Bad if no name sepcified     */
Packit f574b8
    if (!*arg)
Packit f574b8
	return -2;		/* Bad if name had zero length  */
Packit f574b8
    CTRACE((tfp, "HTLoadCSO: Looking for %s\n", arg));
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Set up a socket to the server for the data.
Packit f574b8
     */
Packit f574b8
    status = HTDoConnect(arg, "cso", CSO_PORT, &s);
Packit f574b8
    if (status == HT_INTERRUPTED) {
Packit f574b8
	/*
Packit f574b8
	 * Interrupt cleanly.
Packit f574b8
	 */
Packit f574b8
	CTRACE((tfp,
Packit f574b8
		"HTLoadCSO: Interrupted on connect; recovering cleanly.\n"));
Packit f574b8
	_HTProgress(CONNECTION_INTERRUPTED);
Packit f574b8
	return HT_NOT_LOADED;
Packit f574b8
    }
Packit f574b8
    if (status < 0) {
Packit f574b8
	CTRACE((tfp, "HTLoadCSO: Unable to connect to remote host for `%s'.\n",
Packit f574b8
		arg));
Packit f574b8
	return HTInetStatus("connect");
Packit f574b8
    }
Packit f574b8
Packit f574b8
    HTInitInput(s);		/* Set up input buffering */
Packit f574b8
Packit f574b8
    HTBprintf(&command, "fields%c%c", CR, LF);
Packit f574b8
    if (TRACE) {
Packit f574b8
	CTRACE((tfp, "HTLoadCSO: Connected, writing command `"));
Packit f574b8
	trace_bstring(command);
Packit f574b8
	CTRACE((tfp, "' to socket %d\n", s));
Packit f574b8
    }
Packit f574b8
    _HTProgress(GOPHER_SENDING_CSO_REQUEST);
Packit f574b8
    status = (int) NETWRITE(s, BStrData(command), BStrLen(command));
Packit f574b8
    BStrFree(command);
Packit f574b8
    if (status < 0) {
Packit f574b8
	CTRACE((tfp, "HTLoadCSO: Unable to send command.\n"));
Packit f574b8
	return HTInetStatus("send");
Packit f574b8
    }
Packit f574b8
    _HTProgress(GOPHER_SENT_CSO_REQUEST);
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Now read the data from the socket.
Packit f574b8
     */
Packit f574b8
    status = parse_cso_fields(buf, sizeof(buf));
Packit f574b8
    if (status) {
Packit f574b8
	NETCLOSE(s);
Packit f574b8
	if (status == HT_INTERRUPTED) {
Packit f574b8
	    _HTProgress(CONNECTION_INTERRUPTED);
Packit f574b8
	} else if (buf[0] != '\0') {
Packit f574b8
	    HTAlert(buf);
Packit f574b8
	} else {
Packit f574b8
	    HTAlert(FAILED_NO_RESPONSE);
Packit f574b8
	}
Packit f574b8
	return HT_NOT_LOADED;
Packit f574b8
    }
Packit f574b8
    Target = HTStreamStack(format_in,
Packit f574b8
			   format_out,
Packit f574b8
			   sink, anAnchor);
Packit f574b8
    if (Target == NULL) {
Packit f574b8
	char *temp = 0;
Packit f574b8
Packit f574b8
	HTSprintf0(&temp, CANNOT_CONVERT_I_TO_O,
Packit f574b8
		   HTAtom_name(format_in), HTAtom_name(format_out));
Packit f574b8
	HTAlert(temp);
Packit f574b8
	FREE(temp);
Packit f574b8
	NETCLOSE(s);
Packit f574b8
	return HT_NOT_LOADED;
Packit f574b8
    }
Packit f574b8
    host = HTParse(arg, "", PARSE_HOST);
Packit f574b8
    if ((cp = HTParsePort(host, &port)) != NULL) {
Packit f574b8
	if (port == CSO_PORT) {
Packit f574b8
	    *cp = '\0';
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
    anAnchor->safe = TRUE;
Packit f574b8
    if (isBEmpty(anAnchor->post_data)) {
Packit f574b8
	generate_cso_form(host, port, buf, sizeof(buf), Target);
Packit f574b8
	(*Target->isa->_free) (Target);
Packit f574b8
	FREE(host);
Packit f574b8
	NETCLOSE(s);
Packit f574b8
	free_CSOfields();
Packit f574b8
	return HT_LOADED;
Packit f574b8
    }
Packit f574b8
Packit f574b8
    HTBprintf(&command,
Packit f574b8
	      "<HTML>\n<HEAD>\n<TITLE>CSO/PH Results on %s</TITLE>\n</HEAD>\n<BODY>\n",
Packit f574b8
	      host);
Packit f574b8
    (*Target->isa->put_block) (Target, BStrData(command), BStrLen(command));
Packit f574b8
    BStrFree(command);
Packit f574b8
    FREE(host);
Packit f574b8
Packit f574b8
    BStrCopy(content, anAnchor->post_data);
Packit f574b8
    assert(content != NULL);
Packit f574b8
Packit f574b8
    if (BStrData(content)[BStrLen(content) - 1] != '&')
Packit f574b8
	BStrCat0(content, "&";;
Packit f574b8
Packit f574b8
    data = BStrData(content);
Packit f574b8
    len = BStrLen(content);
Packit f574b8
    for (i = 0; i < len; i++) {
Packit f574b8
	if (data[i] == '+') {
Packit f574b8
	    data[i] = ' ';
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
Packit f574b8
    data = BStrData(content);
Packit f574b8
    HTUnEscape(data);		/* FIXME: could it have embedded null? */
Packit f574b8
    len = BStrLen(content);
Packit f574b8
Packit f574b8
    return_type = 0;
Packit f574b8
    has_indexed = 0;
Packit f574b8
    start = 0;
Packit f574b8
    for (i = 0; i < len; i++) {
Packit f574b8
	if (!data[i] || data[i] == '&') {
Packit f574b8
	    /*
Packit f574b8
	     * Value parsed.  Unescape characters and look for first '=' to
Packit f574b8
	     * delimit field name from value.
Packit f574b8
	     */
Packit f574b8
	    flen = i - start;
Packit f574b8
	    finish = start + flen;
Packit f574b8
	    data[finish] = '\0';
Packit f574b8
	    for (j = start; j < finish; j++) {
Packit f574b8
		if (data[j] == '=') {
Packit f574b8
		    /*
Packit f574b8
		     * data[start..j-1] is field name,
Packit f574b8
		     * [j+1..finish-1] is value.
Packit f574b8
		     */
Packit f574b8
		    if ((data[start + 1] == '_') &&
Packit f574b8
			((data[start] == 'r') || (data[start] == 'q'))) {
Packit f574b8
			/*
Packit f574b8
			 * Decode fields number and lookup field info.
Packit f574b8
			 */
Packit f574b8
			sscanf(&data[start + 2], "%d=", &ndx;;
Packit f574b8
			for (fld = CSOfields; fld; fld = fld->next) {
Packit f574b8
			    if (ndx == fld->id) {
Packit f574b8
				if ((j + 1) >= finish)
Packit f574b8
				    break;	/* ignore nulls */
Packit f574b8
				if (data[start] == 'q') {
Packit f574b8
				    /*
Packit f574b8
				     * Append field to query line.
Packit f574b8
				     */
Packit f574b8
				    if (fld->lookup) {
Packit f574b8
					if (fld->indexed)
Packit f574b8
					    has_indexed = 1;
Packit f574b8
					if (isBEmpty(command)) {
Packit f574b8
					    BStrCopy0(command, "query ");
Packit f574b8
					} else {
Packit f574b8
					    BStrCat0(command, " ");
Packit f574b8
					}
Packit f574b8
					HTBprintf(&command, "%s=\"%s\"",
Packit f574b8
						  fld->name, &data[j + 1]);
Packit f574b8
				    } else {
Packit f574b8
					strcpy(buf,
Packit f574b8
					       "Warning: non-lookup field ignored
\n");
Packit f574b8
					(*Target->isa->put_block) (Target,
Packit f574b8
								   buf,
Packit f574b8
								   (int)
Packit f574b8
								   strlen(buf));
Packit f574b8
				    }
Packit f574b8
				} else if (data[start] == 'r') {
Packit f574b8
				    fld->explicit_return = 1;
Packit f574b8
				}
Packit f574b8
				break;
Packit f574b8
			    }
Packit f574b8
			}
Packit f574b8
		    } else if (!StrNCmp(&data[start], "return=", 7)) {
Packit f574b8
			if (!strcmp(&data[start + 7], "all")) {
Packit f574b8
			    return_type = 1;
Packit f574b8
			} else if (!strcmp(&data[start + 7], "selected")) {
Packit f574b8
			    return_type = 2;
Packit f574b8
			}
Packit f574b8
		    }
Packit f574b8
		}
Packit f574b8
	    }
Packit f574b8
	    start = i + 1;
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
    BStrFree(content);
Packit f574b8
    if (isBEmpty(command) || !has_indexed) {
Packit f574b8
	NETCLOSE(s);
Packit f574b8
	strcpy(buf,
Packit f574b8
	       "Error: At least one indexed field value must be specified!\n");
Packit f574b8
	(*Target->isa->put_block) (Target, buf, (int) strlen(buf));
Packit f574b8
	strcpy(buf, "</BODY>\n</HTML>\n");
Packit f574b8
	(*Target->isa->put_block) (Target, buf, (int) strlen(buf));
Packit f574b8
	(*Target->isa->_free) (Target);
Packit f574b8
	free_CSOfields();
Packit Service 5cb6ae
	BStrFree(command);
Packit f574b8
	return HT_LOADED;
Packit f574b8
    }
Packit f574b8
    /*
Packit f574b8
     * Append return fields.
Packit f574b8
     */
Packit f574b8
    if (return_type == 1) {
Packit f574b8
	BStrCat0(command, " return all");
Packit f574b8
    } else if (return_type == 2) {
Packit f574b8
	BStrCat0(command, " return");
Packit f574b8
	for (fld = CSOfields; fld; fld = fld->next) {
Packit f574b8
	    if (fld->explicit_return) {
Packit f574b8
		HTBprintf(&command, " %s", fld->name);
Packit f574b8
	    }
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
    HTBprintf(&command, "%c%c", CR, LF);
Packit f574b8
    strcpy(buf, "

\nCSO/PH command: ");

Packit f574b8
    (*Target->isa->put_block) (Target, buf, (int) strlen(buf));
Packit f574b8
    (*Target->isa->put_block) (Target, BStrData(command), BStrLen(command));
Packit f574b8
    strcpy(buf, "\n");
Packit f574b8
    (*Target->isa->put_block) (Target, buf, (int) strlen(buf));
Packit f574b8
    if (TRACE) {
Packit f574b8
	CTRACE((tfp, "HTLoadCSO: Writing command `"));
Packit f574b8
	trace_bstring(command);
Packit f574b8
	CTRACE((tfp, "' to socket %d\n", s));
Packit f574b8
    }
Packit f574b8
    status = (int) NETWRITE(s, BStrData(command), BStrLen(command));
Packit f574b8
    BStrFree(command);
Packit f574b8
    if (status < 0) {
Packit f574b8
	CTRACE((tfp, "HTLoadCSO: Unable to send command.\n"));
Packit f574b8
	free_CSOfields();
Packit f574b8
	return HTInetStatus("send");
Packit f574b8
    }
Packit f574b8
    generate_cso_report(Target);
Packit f574b8
    NETCLOSE(s);
Packit f574b8
    (*Target->isa->put_block) (Target, end_form, (int) sizeof(end_form) - 1);
Packit f574b8
    (*Target->isa->_free) (Target);
Packit f574b8
    FREE(host);
Packit f574b8
    free_CSOfields();
Packit f574b8
    return HT_LOADED;
Packit f574b8
}
Packit f574b8
Packit f574b8
static char *link_to_URL(const char *arg)
Packit f574b8
{
Packit f574b8
    char *result;
Packit f574b8
    char *next;
Packit f574b8
    char *temp = 0;
Packit f574b8
Packit f574b8
    StrAllocCopy(temp, arg);
Packit f574b8
    HTUnEscape(temp);
Packit f574b8
    result = temp;
Packit f574b8
Packit f574b8
    /* skip past method://host */
Packit f574b8
    if ((next = strstr(result, "://")) != 0) {
Packit f574b8
	result = next + 3;
Packit f574b8
    }
Packit f574b8
    if ((next = strchr(result, '/')) != 0) {
Packit f574b8
	result = next + 1;
Packit f574b8
    }
Packit f574b8
    /* check if the selector is the special html one */
Packit f574b8
    if (!strncmp(result, "hURL:", (size_t) 5)) {
Packit f574b8
	result += 5;
Packit f574b8
	next = result;
Packit f574b8
	result = temp;
Packit f574b8
	while ((*temp++ = *next++) != 0) ;
Packit f574b8
    } else {
Packit f574b8
	FREE(temp);
Packit f574b8
	result = 0;
Packit f574b8
    }
Packit f574b8
    return result;
Packit f574b8
}
Packit f574b8
Packit f574b8
/*	Load by name.						HTLoadGopher
Packit f574b8
 *	=============
Packit f574b8
 *
Packit f574b8
 */
Packit f574b8
static int HTLoadGopher(const char *arg,
Packit f574b8
			HTParentAnchor *anAnchor,
Packit f574b8
			HTFormat format_out,
Packit f574b8
			HTStream *sink)
Packit f574b8
{
Packit f574b8
    char *hURL;
Packit f574b8
    char *command;		/* The whole command */
Packit f574b8
    int status;			/* tcp return */
Packit f574b8
    char gtype;			/* Gopher Node type */
Packit f574b8
    char *selector;		/* Selector string */
Packit f574b8
Packit f574b8
    if (!acceptable_inited)
Packit f574b8
	init_acceptable();
Packit f574b8
Packit f574b8
    if (!arg)
Packit f574b8
	return -3;		/* Bad if no name sepcified     */
Packit f574b8
    if (!*arg)
Packit f574b8
	return -2;		/* Bad if name had zero length  */
Packit f574b8
    CTRACE((tfp, "HTGopher: Looking for %s\n", arg));
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * If it's a port 105 GOPHER_CSO gtype with no ISINDEX token ('?'), use the
Packit f574b8
     * form-based CSO gateway (otherwise, return an ISINDEX cover page or do
Packit f574b8
     * the ISINDEX search).  - FM
Packit f574b8
     */
Packit f574b8
    {
Packit f574b8
	size_t len;
Packit f574b8
Packit f574b8
	if ((len = strlen(arg)) > 5) {
Packit f574b8
	    if (0 == strcmp((const char *) &arg[len - 6], ":105/2")) {
Packit f574b8
		/* Use CSO gateway. */
Packit f574b8
		CTRACE((tfp, "HTGopher: Passing to CSO/PH gateway.\n"));
Packit f574b8
		return HTLoadCSO(arg, anAnchor, format_out, sink);
Packit f574b8
	    }
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * If it's a port 79/0[/...] URL, use the finger gateway.  - FM
Packit f574b8
     */
Packit f574b8
    if (strstr(arg, ":79/0") != NULL) {
Packit f574b8
#ifndef DISABLE_FINGER
Packit f574b8
	CTRACE((tfp, "HTGopher: Passing to finger gateway.\n"));
Packit f574b8
	return HTLoadFinger(arg, anAnchor, format_out, sink);
Packit f574b8
#else /* finger is disabled */
Packit f574b8
	HTAlert(COULD_NOT_ACCESS_DOCUMENT);
Packit f574b8
	return HT_NOT_LOADED;
Packit f574b8
#endif /* DISABLE_FINGER */
Packit f574b8
    }
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Get entity type, and selector string.
Packit f574b8
     */
Packit f574b8
    {
Packit f574b8
	char *p1 = HTParse(arg, "", PARSE_PATH | PARSE_PUNCTUATION);
Packit f574b8
Packit f574b8
	gtype = '1';		/* Default = menu */
Packit f574b8
	selector = p1;
Packit f574b8
	if ((*selector++ == '/') && (*selector)) {	/* Skip first slash */
Packit f574b8
	    gtype = *selector++;	/* Pick up gtype */
Packit f574b8
	}
Packit f574b8
	if (gtype == GOPHER_INDEX) {
Packit f574b8
	    char *query;
Packit f574b8
Packit f574b8
	    /*
Packit f574b8
	     * Search is allowed.
Packit f574b8
	     */
Packit f574b8
	    HTAnchor_setIndex(anAnchor, anAnchor->address);
Packit f574b8
	    query = StrChr(selector, '?');	/* Look for search string */
Packit f574b8
	    if (!query || !query[1]) {	/* No search required */
Packit f574b8
		target = HTML_new(anAnchor, format_out, sink);
Packit f574b8
		targetClass = *target->isa;
Packit f574b8
		display_index(arg, anAnchor);	/* Display "cover page" */
Packit f574b8
		return HT_LOADED;	/* Local function only */
Packit f574b8
	    }
Packit f574b8
	    *query++ = '\0';	/* Skip '?'     */
Packit f574b8
	    command =
Packit f574b8
		(char *) malloc(strlen(selector) + 1 + strlen(query) + 2 + 1);
Packit f574b8
	    if (command == NULL)
Packit f574b8
		outofmem(__FILE__, "HTLoadGopher");
Packit f574b8
Packit f574b8
	    de_escape(command, selector);	/* Bug fix TBL 921208 */
Packit f574b8
Packit f574b8
	    strcat(command, "\t");
Packit f574b8
Packit f574b8
	    {			/* Remove plus signs 921006 */
Packit f574b8
		char *p;
Packit f574b8
Packit f574b8
		for (p = query; *p; p++) {
Packit f574b8
		    if (*p == '+')
Packit f574b8
			*p = ' ';
Packit f574b8
		}
Packit f574b8
	    }
Packit f574b8
Packit f574b8
	    de_escape(&command[strlen(command)], query);	/* bug fix LJM 940415 */
Packit f574b8
	} else if (gtype == GOPHER_CSO) {
Packit f574b8
	    char *query;
Packit f574b8
Packit f574b8
	    /*
Packit f574b8
	     * Search is allowed.
Packit f574b8
	     */
Packit f574b8
	    query = StrChr(selector, '?');	/* Look for search string */
Packit f574b8
	    if (!query || !query[1]) {	/* No search required */
Packit f574b8
		target = HTML_new(anAnchor, format_out, sink);
Packit f574b8
		targetClass = *target->isa;
Packit f574b8
		display_cso(arg, anAnchor);	/* Display "cover page" */
Packit f574b8
		return HT_LOADED;	/* Local function only */
Packit f574b8
	    }
Packit f574b8
	    HTAnchor_setIndex(anAnchor, anAnchor->address);
Packit f574b8
	    *query++ = '\0';	/* Skip '?'     */
Packit f574b8
	    command = (char *) malloc(strlen("query") + 1 +
Packit f574b8
				      strlen(query) + 2 + 1);
Packit f574b8
	    if (command == NULL)
Packit f574b8
		outofmem(__FILE__, "HTLoadGopher");
Packit f574b8
Packit f574b8
	    de_escape(command, selector);	/* Bug fix TBL 921208 */
Packit f574b8
Packit f574b8
	    strcpy(command, "query ");
Packit f574b8
Packit f574b8
	    {			/* Remove plus signs 921006 */
Packit f574b8
		char *p;
Packit f574b8
Packit f574b8
		for (p = query; *p; p++) {
Packit f574b8
		    if (*p == '+')
Packit f574b8
			*p = ' ';
Packit f574b8
		}
Packit f574b8
	    }
Packit f574b8
	    de_escape(&command[strlen(command)], query);	/* bug fix LJM 940415 */
Packit f574b8
Packit f574b8
	} else {		/* Not index */
Packit f574b8
	    command = (char *) malloc(strlen(selector) + 2 + 1);
Packit f574b8
	    if (command == NULL)
Packit f574b8
		outofmem(__FILE__, "HTLoadGopher");
Packit f574b8
Packit f574b8
	    de_escape(command, selector);
Packit f574b8
	}
Packit f574b8
	FREE(p1);
Packit f574b8
    }
Packit f574b8
Packit f574b8
    {
Packit f574b8
	char *p = command + strlen(command);
Packit f574b8
Packit f574b8
	*p++ = CR;		/* Macros to be correct on Mac */
Packit f574b8
	*p++ = LF;
Packit f574b8
	*p = '\0';
Packit f574b8
    }
Packit f574b8
    /*
Packit f574b8
     * Check for link to URL
Packit f574b8
     */
Packit f574b8
    if ((hURL = link_to_URL(arg)) != 0) {
Packit f574b8
	CTRACE((tfp, "gopher found link to URL '%s'\n", hURL));
Packit f574b8
	free(hURL);
Packit f574b8
    }
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Set up a socket to the server for the data.
Packit f574b8
     */
Packit f574b8
    status = HTDoConnect(arg, "gopher", GOPHER_PORT, &s);
Packit f574b8
    if (status == HT_INTERRUPTED) {
Packit f574b8
	/*
Packit f574b8
	 * Interrupt cleanly.
Packit f574b8
	 */
Packit f574b8
	CTRACE((tfp, "HTGopher: Interrupted on connect; recovering cleanly.\n"));
Packit f574b8
	_HTProgress(CONNECTION_INTERRUPTED);
Packit f574b8
	FREE(command);
Packit f574b8
	return HT_NOT_LOADED;
Packit f574b8
    }
Packit f574b8
    if (status < 0) {
Packit f574b8
	CTRACE((tfp, "HTGopher: Unable to connect to remote host for `%s'.\n",
Packit f574b8
		arg));
Packit f574b8
	FREE(command);
Packit f574b8
	return HTInetStatus("connect");
Packit f574b8
    }
Packit f574b8
Packit f574b8
    HTInitInput(s);		/* Set up input buffering */
Packit f574b8
Packit f574b8
    CTRACE((tfp, "HTGopher: Connected, writing command `%s' to socket %d\n",
Packit f574b8
	    command, s));
Packit f574b8
Packit f574b8
#ifdef NOT_ASCII
Packit f574b8
    {
Packit f574b8
	char *p;
Packit f574b8
Packit f574b8
	for (p = command; *p; p++) {
Packit f574b8
	    *p = TOASCII(*p);
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
#endif
Packit f574b8
Packit f574b8
    _HTProgress(GOPHER_SENDING_REQUEST);
Packit f574b8
Packit f574b8
    status = (int) NETWRITE(s, command, (int) strlen(command));
Packit f574b8
    FREE(command);
Packit f574b8
    if (status < 0) {
Packit f574b8
	CTRACE((tfp, "HTGopher: Unable to send command.\n"));
Packit f574b8
	return HTInetStatus("send");
Packit f574b8
    }
Packit f574b8
Packit f574b8
    _HTProgress(GOPHER_SENT_REQUEST);
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Now read the data from the socket.
Packit f574b8
     */
Packit f574b8
    switch (gtype) {
Packit f574b8
Packit f574b8
    case GOPHER_TEXT:
Packit f574b8
	HTParseSocket(WWW_PLAINTEXT, format_out, anAnchor, s, sink);
Packit f574b8
	break;
Packit f574b8
Packit f574b8
    case GOPHER_HTML:
Packit f574b8
    case GOPHER_CHTML:
Packit f574b8
	HTParseSocket(WWW_HTML, format_out, anAnchor, s, sink);
Packit f574b8
	break;
Packit f574b8
Packit f574b8
    case GOPHER_GIF:
Packit f574b8
    case GOPHER_IMAGE:
Packit f574b8
    case GOPHER_PLUS_IMAGE:
Packit f574b8
	HTParseSocket(HTAtom_for("image/gif"),
Packit f574b8
		      format_out, anAnchor, s, sink);
Packit f574b8
	break;
Packit f574b8
Packit f574b8
    case GOPHER_MENU:
Packit f574b8
    case GOPHER_INDEX:
Packit f574b8
	target = HTML_new(anAnchor, format_out, sink);
Packit f574b8
	targetClass = *target->isa;
Packit f574b8
	parse_menu(arg, anAnchor);
Packit f574b8
	break;
Packit f574b8
Packit f574b8
    case GOPHER_CSO:
Packit f574b8
	target = HTML_new(anAnchor, format_out, sink);
Packit f574b8
	targetClass = *target->isa;
Packit f574b8
	parse_cso(arg, anAnchor);
Packit f574b8
	break;
Packit f574b8
Packit f574b8
    case GOPHER_SOUND:
Packit f574b8
    case GOPHER_PLUS_SOUND:
Packit f574b8
	HTParseSocket(WWW_AUDIO, format_out, anAnchor, s, sink);
Packit f574b8
	break;
Packit f574b8
Packit f574b8
    case GOPHER_PLUS_MOVIE:
Packit f574b8
	HTParseSocket(HTAtom_for("video/mpeg"), format_out, anAnchor, s, sink);
Packit f574b8
	break;
Packit f574b8
Packit f574b8
    case GOPHER_PLUS_PDF:
Packit f574b8
	HTParseSocket(HTAtom_for("application/pdf"), format_out, anAnchor,
Packit f574b8
		      s, sink);
Packit f574b8
	break;
Packit f574b8
Packit f574b8
    default:
Packit f574b8
	{
Packit f574b8
	    HTAtom *encoding = 0;
Packit f574b8
	    const char *desc = 0;
Packit f574b8
	    HTFormat format = HTFileFormat(arg, &encoding, &desc);
Packit f574b8
Packit f574b8
	    /*
Packit f574b8
	     * Ignore WWW_BINARY (since that is returned by HTFileFormat when
Packit f574b8
	     * it does not have a representation), but otherwise use the
Packit f574b8
	     * result.
Packit f574b8
	     */
Packit f574b8
	    if (format != WWW_BINARY) {
Packit f574b8
		HTParseSocket(format, format_out, anAnchor, s, sink);
Packit f574b8
		break;
Packit f574b8
	    }
Packit f574b8
	}
Packit f574b8
	/* FALL-THRU */
Packit f574b8
Packit f574b8
    case GOPHER_MACBINHEX:
Packit f574b8
    case GOPHER_PCBINARY:
Packit f574b8
    case GOPHER_UUENCODED:
Packit f574b8
    case GOPHER_BINARY:
Packit f574b8
	/*
Packit f574b8
	 * Specifying WWW_UNKNOWN forces dump to local disk.
Packit f574b8
	 */
Packit f574b8
	HTParseSocket(WWW_UNKNOWN, format_out, anAnchor, s, sink);
Packit f574b8
	break;
Packit f574b8
Packit f574b8
    }				/* switch(gtype) */
Packit f574b8
Packit f574b8
    NETCLOSE(s);
Packit f574b8
    return HT_LOADED;
Packit f574b8
}
Packit f574b8
Packit f574b8
#ifdef GLOBALDEF_IS_MACRO
Packit f574b8
#define _HTGOPHER_C_1_INIT { "gopher", HTLoadGopher, NULL }
Packit f574b8
GLOBALDEF(HTProtocol, HTGopher, _HTGOPHER_C_1_INIT);
Packit f574b8
#define _HTCSO_C_1_INIT { "cso", HTLoadCSO, NULL }
Packit f574b8
GLOBALDEF(HTProtocol, HTCSO, _HTCSO_C_1_INIT);
Packit f574b8
#else
Packit f574b8
GLOBALDEF HTProtocol HTGopher =
Packit f574b8
{"gopher", HTLoadGopher, NULL};
Packit f574b8
GLOBALDEF HTProtocol HTCSO =
Packit f574b8
{"cso", HTLoadCSO, NULL};
Packit f574b8
#endif /* GLOBALDEF_IS_MACRO */
Packit f574b8
Packit f574b8
#endif /* not DISABLE_GOPHER */