|
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 */
|