summaryrefslogtreecommitdiffstats
path: root/WWW/Library/Implementation/HTWSRC.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--WWW/Library/Implementation/HTWSRC.c486
1 files changed, 486 insertions, 0 deletions
diff --git a/WWW/Library/Implementation/HTWSRC.c b/WWW/Library/Implementation/HTWSRC.c
new file mode 100644
index 0000000..fe42a65
--- /dev/null
+++ b/WWW/Library/Implementation/HTWSRC.c
@@ -0,0 +1,486 @@
+/*
+ * $LynxId: HTWSRC.c,v 1.30 2016/11/24 15:29:50 tom Exp $
+ *
+ * Parse WAIS Source file HTWSRC.c
+ * ======================
+ *
+ * This module parses a stream with WAIS source file
+ * format information on it and creates a structured stream.
+ * That structured stream is then converted into whatever.
+ *
+ * 3 June 93 Bug fix: Won't crash if no description
+ */
+
+#define HTSTREAM_INTERNAL 1
+
+#include <HTUtils.h>
+
+#include <HTWSRC.h>
+#include <LYUtils.h>
+
+#include <HTML.h>
+#include <HTParse.h>
+
+#include <LYLeaks.h>
+
+#define BIG 10000 /* Arbitrary limit to value length */
+#define PARAM_MAX BIG
+#define CACHE_PERIOD (7*86400) /* Time to keep .src file in seconds */
+
+struct _HTStructured {
+ const HTStructuredClass *isa;
+ /* ... */
+};
+
+#define PUTC(c) (*me->target->isa->put_character)(me->target, c)
+#define PUTS(s) (*me->target->isa->put_string)(me->target, s)
+#define START(e) (*me->target->isa->start_element)(me->target, e, 0, 0, -1, 0)
+#define END(e) (*me->target->isa->end_element)(me->target, e, 0)
+#define MAYBE_END(e) if (HTML_dtd.tags[e].contents != SGML_EMPTY) \
+ (*me->target->isa->end_element)(me->target, e, 0)
+
+/* Here are the parameters which can be specified in a source file
+*/
+static const char *par_name[] =
+{
+ "version",
+ "ip-address",
+#define PAR_IP_NAME 2
+ "ip-name",
+#define PAR_TCP_PORT 3
+ "tcp-port",
+#define PAR_DATABASE_NAME 4
+ "database-name",
+#define PAR_COST 5
+ "cost",
+#define PAR_COST_UNIT 6
+ "cost-unit",
+#define PAR_FREE 7
+ "free",
+#define PAR_MAINTAINER 8
+ "maintainer",
+#define PAR_DESCRIPTION 9
+ "description",
+ "keyword-list",
+ "source",
+ "window-geometry",
+ "configuration",
+ "script",
+ "update-time",
+ "contact-at",
+ "last-contacted",
+ "confidence",
+ "num-docs-to-request",
+ "font",
+ "font-size",
+#define PAR_UNKNOWN 22
+ "unknown",
+ 0, /* Terminate list */
+#define PAR_COUNT 23
+};
+
+enum tokenstate {
+ beginning,
+ before_tag,
+ colon,
+ before_value,
+ value,
+ bracketed_value,
+ quoted_value,
+ escape_in_quoted,
+ done
+};
+
+/* Stream Object
+ * ------------
+ *
+ * The target is the structured stream down which the
+ * parsed results will go.
+ *
+ * all the static stuff below should go in here to make it reentrant
+ */
+
+struct _HTStream {
+ const HTStreamClass *isa;
+ HTStructured *target;
+ char *par_value[PAR_COUNT];
+ enum tokenstate state;
+ char param[BIG + 1];
+ int param_number;
+ int param_count;
+};
+
+/* Decode one hex character
+*/
+char from_hex(char c)
+{
+ return (char) ((c >= '0') && (c <= '9') ? c - '0'
+ : (c >= 'A') && (c <= 'F') ? c - 'A' + 10
+ : (c >= 'a') && (c <= 'f') ? c - 'a' + 10
+ : 0);
+}
+
+/* State machine
+ * -------------
+ *
+ * On entry,
+ * me->state is a valid state (see WSRC_init)
+ * c is the next character
+ * On exit,
+ * returns 1 Done with file
+ * 0 Continue. me->state is updated if necessary.
+ * -1 Syntax error error
+ */
+
+/* Treat One Character
+ * -------------------
+ */
+static void WSRCParser_put_character(HTStream *me, int c)
+{
+ switch (me->state) {
+ case beginning:
+ if (c == '(')
+ me->state = before_tag;
+ break;
+
+ case before_tag:
+ if (c == ')') {
+ me->state = done;
+ return; /* Done with input file */
+ } else if (c == ':') {
+ me->param_count = 0;
+ me->state = colon;
+ } /* Ignore other text */
+ break;
+
+ case colon:
+ if (WHITE(c)) {
+ me->param[me->param_count++] = 0; /* Terminate */
+ for (me->param_number = 0;
+ par_name[me->param_number];
+ me->param_number++) {
+ if (0 == strcmp(par_name[me->param_number], me->param)) {
+ break;
+ }
+ }
+ if (!par_name[me->param_number]) { /* Unknown field */
+ CTRACE((tfp, "HTWSRC: Unknown field `%s' in source file\n",
+ me->param));
+ me->param_number = PAR_UNKNOWN;
+ me->state = before_value; /* Could be better ignore */
+ return;
+ }
+ me->state = before_value;
+ } else {
+ if (me->param_count < PARAM_MAX)
+ me->param[me->param_count++] = (char) c;
+ }
+ break;
+
+ case before_value:
+ if (c == ')') {
+ me->state = done;
+ return; /* Done with input file */
+ }
+ if (WHITE(c))
+ return; /* Skip white space */
+ me->param_count = 0;
+ if (c == '"') {
+ me->state = quoted_value;
+ } else {
+ me->state = ((c == '(')
+ ? bracketed_value
+ : value);
+ me->param[me->param_count++] = (char) c; /* Don't miss first character */
+ }
+ break;
+
+ case value:
+ if (WHITE(c)) {
+ me->param[me->param_count] = 0;
+ StrAllocCopy(me->par_value[me->param_number], me->param);
+ me->state = before_tag;
+ } else {
+ if (me->param_count < PARAM_MAX)
+ me->param[me->param_count++] = (char) c;
+ }
+ break;
+
+ case bracketed_value:
+ if (c == ')') {
+ me->param[me->param_count] = 0;
+ StrAllocCopy(me->par_value[me->param_number], me->param);
+ me->state = before_tag;
+ break;
+ }
+ if (me->param_count < PARAM_MAX)
+ me->param[me->param_count++] = (char) c;
+ break;
+
+ case quoted_value:
+ if (c == '"') {
+ me->param[me->param_count] = 0;
+ StrAllocCopy(me->par_value[me->param_number], me->param);
+ me->state = before_tag;
+ break;
+ }
+
+ if (c == '\\') { /* Ignore escape but switch state */
+ me->state = escape_in_quoted;
+ break;
+ }
+ /* Fall through! */
+
+ case escape_in_quoted:
+ if (me->param_count < PARAM_MAX)
+ me->param[me->param_count++] = (char) c;
+ me->state = quoted_value;
+ break;
+
+ case done: /* Ignore anything after EOF */
+ return;
+
+ } /* switch me->state */
+}
+
+/* Open Cache file
+ * ===============
+ *
+ * Bugs: Maybe for filesystem-challenged platforms (MSDOS for example) we
+ * should make a hash code for the filename.
+ */
+
+#ifdef CACHE_FILE_PREFIX
+static BOOL write_cache(HTStream *me)
+{
+ FILE *fp;
+ char *cache_file_name = NULL;
+ char *www_database;
+ int result = NO;
+
+ if (!me->par_value[PAR_DATABASE_NAME]
+ || !me->par_value[PAR_IP_NAME]
+ )
+ return NO;
+
+ www_database = HTEscape(me->par_value[PAR_DATABASE_NAME], URL_XALPHAS);
+ HTSprintf0(&cache_file_name, "%sWSRC-%s:%s:%.100s.txt",
+ CACHE_FILE_PREFIX,
+ me->par_value[PAR_IP_NAME],
+ (me->par_value[PAR_TCP_PORT]
+ ? me->par_value[PAR_TCP_PORT]
+ : "210"),
+ www_database);
+
+ if ((fp = fopen(cache_file_name, TXT_W)) != 0) {
+ result = YES;
+ if (me->par_value[PAR_DESCRIPTION])
+ fputs(me->par_value[PAR_DESCRIPTION], fp);
+ else
+ fputs("Description not available\n", fp);
+ fclose(fp);
+ }
+ FREE(www_database);
+ FREE(cache_file_name);
+ return result;
+}
+#endif
+
+/* Output equivalent HTML
+ * ----------------------
+ *
+ */
+
+static void give_parameter(HTStream *me, int p)
+{
+ PUTS(par_name[p]);
+ if (me->par_value[p]) {
+ PUTS(": ");
+ PUTS(me->par_value[p]);
+ PUTS("; ");
+ } else {
+ PUTS(gettext(" NOT GIVEN in source file; "));
+ }
+}
+
+/* Generate Outout
+ * ===============
+ */
+static void WSRC_gen_html(HTStream *me, int source_file)
+{
+ if (me->par_value[PAR_DATABASE_NAME]) {
+ char *shortname = 0;
+ int l;
+
+ StrAllocCopy(shortname, me->par_value[PAR_DATABASE_NAME]);
+ l = (int) strlen(shortname);
+ if (l > 4 && !strcasecomp(shortname + l - 4, ".src")) {
+ shortname[l - 4] = 0; /* Chop of .src -- boring! */
+ }
+
+ START(HTML_HEAD);
+ PUTC('\n');
+ START(HTML_TITLE);
+ PUTS(shortname);
+ PUTS(source_file ? gettext(" WAIS source file") : INDEX_SEGMENT);
+ END(HTML_TITLE);
+ PUTC('\n');
+ END(HTML_HEAD);
+
+ START(HTML_H1);
+ PUTS(shortname);
+ PUTS(source_file ? gettext(" description") : INDEX_SEGMENT);
+ END(HTML_H1);
+ PUTC('\n');
+ FREE(shortname);
+ }
+
+ START(HTML_DL); /* Definition list of details */
+
+ if (source_file) {
+ START(HTML_DT);
+ PUTS(gettext("Access links"));
+ MAYBE_END(HTML_DT);
+ START(HTML_DD);
+ if (me->par_value[PAR_IP_NAME] &&
+ me->par_value[PAR_DATABASE_NAME]) {
+
+ char *WSRC_address = NULL;
+ char *www_database;
+
+ www_database = HTEscape(me->par_value[PAR_DATABASE_NAME],
+ URL_XALPHAS);
+ HTSprintf0(&WSRC_address, "%s//%s%s%s/%s",
+ STR_WAIS_URL,
+ me->par_value[PAR_IP_NAME],
+ me->par_value[PAR_TCP_PORT] ? ":" : "",
+ (me->par_value[PAR_TCP_PORT]
+ ? me->par_value[PAR_TCP_PORT]
+ : ""),
+ www_database);
+
+ HTStartAnchor(me->target, NULL, WSRC_address);
+ PUTS(gettext("Direct access"));
+ END(HTML_A);
+ /** Proxy will be used if defined, so let user know that - FM **/
+ PUTS(gettext(" (or via proxy server, if defined)"));
+
+ FREE(www_database);
+ FREE(WSRC_address);
+
+ } else {
+ give_parameter(me, PAR_IP_NAME);
+ give_parameter(me, PAR_DATABASE_NAME);
+ }
+ MAYBE_END(HTML_DD);
+
+ }
+ /* end if source_file */
+ if (me->par_value[PAR_MAINTAINER]) {
+ START(HTML_DT);
+ PUTS(gettext("Maintainer"));
+ MAYBE_END(HTML_DT);
+ START(HTML_DD);
+ PUTS(me->par_value[PAR_MAINTAINER]);
+ MAYBE_END(HTML_DD);
+ }
+ if (me->par_value[PAR_IP_NAME]) {
+ START(HTML_DT);
+ PUTS(gettext("Host"));
+ MAYBE_END(HTML_DT);
+ START(HTML_DD);
+ PUTS(me->par_value[PAR_IP_NAME]);
+ MAYBE_END(HTML_DD);
+ }
+
+ END(HTML_DL);
+
+ if (me->par_value[PAR_DESCRIPTION]) {
+ START(HTML_PRE); /* Preformatted description */
+ PUTS(me->par_value[PAR_DESCRIPTION]);
+ END(HTML_PRE);
+ }
+
+ (*me->target->isa->_free) (me->target);
+
+ return;
+} /* generate html */
+
+static void WSRCParser_put_string(HTStream *context, const char *str)
+{
+ const char *p;
+
+ for (p = str; *p; p++)
+ WSRCParser_put_character(context, *p);
+}
+
+static void WSRCParser_write(HTStream *context, const char *str,
+ int l)
+{
+ const char *p;
+ const char *e = str + l;
+
+ for (p = str; p < e; p++)
+ WSRCParser_put_character(context, *p);
+}
+
+static void WSRCParser_free(HTStream *me)
+{
+ WSRC_gen_html(me, YES);
+#ifdef CACHE_FILE_PREFIX
+ write_cache(me);
+#endif
+ {
+ int p;
+
+ for (p = 0; par_name[p]; p++) { /* Clear out old values */
+ FREE(me->par_value[p]);
+ }
+ }
+ FREE(me);
+}
+
+static void WSRCParser_abort(HTStream *me, HTError e GCC_UNUSED)
+{
+ WSRCParser_free(me);
+}
+
+/* Stream subclass -- method routines
+ * ---------------
+ */
+
+static HTStreamClass WSRCParserClass =
+{
+ "WSRCParser",
+ WSRCParser_free,
+ WSRCParser_abort,
+ WSRCParser_put_character,
+ WSRCParser_put_string,
+ WSRCParser_write
+};
+
+/* Converter from WAIS Source to whatever
+ * --------------------------------------
+ */
+HTStream *HTWSRCConvert(HTPresentation *pres, HTParentAnchor *anchor,
+ HTStream *sink)
+{
+ HTStream *me = (HTStream *) malloc(sizeof(*me));
+
+ if (!me)
+ outofmem(__FILE__, "HTWSRCConvert");
+
+ me->isa = &WSRCParserClass;
+ me->target = HTML_new(anchor, pres->rep_out, sink);
+
+ {
+ int p;
+
+ for (p = 0; p < PAR_COUNT; p++) { /* Clear out parameter values */
+ me->par_value[p] = 0;
+ }
+ }
+ me->state = beginning;
+
+ return me;
+}