about summary refs log tree commit diff stats
path: root/WWW/Library
diff options
context:
space:
mode:
Diffstat (limited to 'WWW/Library')
-rw-r--r--WWW/Library/Implementation/HTAccess.h2
-rw-r--r--WWW/Library/Implementation/HTAnchor.c338
-rw-r--r--WWW/Library/Implementation/HTAnchor.h33
-rw-r--r--WWW/Library/Implementation/HTFTP.c5
-rw-r--r--WWW/Library/Implementation/HTFile.c4
-rw-r--r--WWW/Library/Implementation/HTFinger.c193
-rw-r--r--WWW/Library/Implementation/HTGopher.c108
-rw-r--r--WWW/Library/Implementation/HTList.c8
-rw-r--r--WWW/Library/Implementation/HTNews.c2
-rw-r--r--WWW/Library/Implementation/HTParse.c109
-rw-r--r--WWW/Library/Implementation/HTParse.h6
-rw-r--r--WWW/Library/Implementation/HTString.c220
-rw-r--r--WWW/Library/Implementation/HTString.h32
-rw-r--r--WWW/Library/Implementation/HTStyle.c12
-rw-r--r--WWW/Library/Implementation/HTStyle.h57
-rw-r--r--WWW/Library/Implementation/HTTCP.c1
-rw-r--r--WWW/Library/Implementation/HTTP.c129
-rw-r--r--WWW/Library/Implementation/HTTelnet.c12
-rw-r--r--WWW/Library/Implementation/HTUtils.h28
-rw-r--r--WWW/Library/Implementation/HTVMSUtils.c7
-rw-r--r--WWW/Library/Implementation/HTWAIS.c2
-rw-r--r--WWW/Library/Implementation/SGML.c73
-rw-r--r--WWW/Library/Implementation/SGML.h14
-rw-r--r--WWW/Library/Implementation/makefile.in2
24 files changed, 817 insertions, 580 deletions
diff --git a/WWW/Library/Implementation/HTAccess.h b/WWW/Library/Implementation/HTAccess.h
index ab833272..be78361d 100644
--- a/WWW/Library/Implementation/HTAccess.h
+++ b/WWW/Library/Implementation/HTAccess.h
@@ -310,6 +310,6 @@ extern void LYUCPushAssumed PARAMS((
     HTParentAnchor *	anchor));
 extern int LYUCPopAssumed NOPARAMS;
 
-extern BOOL using_proxy;
+extern BOOL using_proxy;	/* Are we using an NNTP proxy? */
 
 #endif /* HTACCESS_H */
diff --git a/WWW/Library/Implementation/HTAnchor.c b/WWW/Library/Implementation/HTAnchor.c
index 2d40df15..57288037 100644
--- a/WWW/Library/Implementation/HTAnchor.c
+++ b/WWW/Library/Implementation/HTAnchor.c
@@ -18,6 +18,7 @@
 #include <HTUtils.h>
 #include <HTAnchor.h>
 #include <HTParse.h>
+#include <HTString.h>
 #include <UCAux.h>
 #include <UCMap.h>
 
@@ -79,6 +80,7 @@ PRIVATE HTParentAnchor * HTParentAnchor_new NOARGS
     newAnchor->isHEAD = FALSE;		/* HEAD request if TRUE. - FM */
     newAnchor->safe = FALSE;		/* Safe. - FM */
     newAnchor->no_cache = FALSE;	/* no-cache? - FM */
+    newAnchor->inBASE = FALSE;		/* duplicated from HTML.c/h */
     newAnchor->content_length = 0;	/* Content-Length. - FM */
     return(newAnchor);
 }
@@ -95,86 +97,83 @@ PRIVATE HTChildAnchor * HTChildAnchor_new NOARGS
 
 
 #ifdef CASE_INSENSITIVE_ANCHORS
-/*	Case insensitive string comparison
-**	----------------------------------
+/* Case insensitive string comparison */
+#define HT_EQUIV(a,b) (TOUPPER(a) == TOUPPER(b))
+#else
+/* Case sensitive string comparison */
+#define HT_EQUIV(a,b) ((a) == (b))
+#endif
+
+/*	Null-terminated string comparison
+**	---------------------------------
 ** On entry,
 **	s	Points to one string, null terminated
 **	t	points to the other.
 ** On exit,
-**	returns YES if the strings are equivalent ignoring case
-**		NO if they differ in more than	their case.
+**	returns YES if the strings are equivalent
+**		NO if they differ.
 */
-PRIVATE BOOL HTEquivalent ARGS2(
+PRIVATE BOOL HTSEquivalent ARGS2(
 	CONST char *,	s,
 	CONST char *,	t)
 {
     if (s && t) {  /* Make sure they point to something */
 	for (; *s && *t; s++, t++) {
-	    if (TOUPPER(*s) != TOUPPER(*t)) {
+	    if (!HT_EQUIV(*s, *t)) {
 		return(NO);
 	    }
 	}
-	return( TOUPPER(*s) == TOUPPER(*t));
+	return(HT_EQUIV(*s, *t));
     } else {
 	return(s == t);		/* Two NULLs are equivalent, aren't they ? */
     }
 }
 
-#else
-
-/*	Case sensitive string comparison
-**	----------------------------------
+/*	Binary string comparison
+**	------------------------
 ** On entry,
-**	s	Points to one string, null terminated
+**	s	Points to one bstring
 **	t	points to the other.
 ** On exit,
-**	returns YES if the strings are identical or both NULL
+**	returns YES if the strings are equivalent
 **		NO if they differ.
 */
-PRIVATE BOOL HTIdentical ARGS2(
-	CONST char *,	s,
-	CONST char *,	t)
-{
-    if (s && t) {  /* Make sure they point to something */
-	for (; *s && *t; s++, t++) {
-	    if (*s != *t) {
+PRIVATE BOOL HTBEquivalent ARGS2(
+	CONST bstring *,	s,
+	CONST bstring *,	t)
+{
+    if (!isBEmpty(s)
+     && !isBEmpty(t)
+     && BStrLen(s) == BStrLen(t)) {
+	int j;
+	int len = BStrLen(s);
+	for (j = 0; j < len; ++j) {
+	    if (!HT_EQUIV(BStrData(s)[j], BStrData(t)[j])) {
 		return(NO);
 	    }
 	}
-	return (BOOL) (*s == *t);
+	return (HT_EQUIV(BStrData(s)[j], BStrData(t)[j]));
     } else {
-	return (BOOL) (s == t);  /* Two NULLs are identical, aren't they ? */
+	return(s == t);		/* Two NULLs are equivalent, aren't they ? */
     }
 }
-#endif /* CASE_INSENSITIVE_ANCHORS */
 
 /*
  *  Three-way compare function
  */
-PRIVATE int compare ARGS2(
+PRIVATE int compare_anchors ARGS2(
 	void *, l,
 	void *, r)
 {
     CONST char* a = ((HTChildAnchor *)l)->tag;
     CONST char* b = ((HTChildAnchor *)r)->tag;
+    /* both tags are not NULL */
 
-    if (a && b) {  /* Make sure they point to something */
 #ifdef CASE_INSENSITIVE_ANCHORS
 	return strcasecomp(a, b); /* Case insensitive */
 #else
 	return strcmp(a, b);      /* Case sensitive - FM */
 #endif /* CASE_INSENSITIVE_ANCHORS */
-    } else {
-	/*  bring up an order when one or both strings are nulls */
-	if (a) {
-	    return 1;
-	} else if (b) {
-	    return -1;
-	} else {
-	    /* both nulls - assume equivalent */
-	    return 0;
-	}
-    }
 }
 
 
@@ -197,20 +196,20 @@ PUBLIC HTChildAnchor * HTAnchor_findChild ARGS2(
 
     if (tag && *tag) {	       /* TBL */
 	if (parent->children) {
-	   /*
-	   **  Parent has children.  Search them.
-	   */
-	   HTChildAnchor sample;
-	   sample.tag = (char*)tag;    /* for compare() only */
-
-	   child = (HTChildAnchor *)HTBTree_search(parent->children, &sample);
-	   if (child != NULL) {
-	       CTRACE((tfp, "Child anchor %p of parent %p with name `%s' already exists.\n",
-		       (void *)child, (void *)parent, tag));
-	       return(child);
+	    /*
+	    **  Parent has children.  Search them.
+	    */
+	    HTChildAnchor sample;
+	    sample.tag = (char*)tag;    /* for compare_anchors() only */
+
+	    child = (HTChildAnchor *)HTBTree_search(parent->children, &sample);
+	    if (child != NULL) {
+		CTRACE((tfp, "Child anchor %p of parent %p with name `%s' already exists.\n",
+				(void *)child, (void *)parent, tag));
+		return(child);
 	    }
 	} else {  /* parent doesn't have any children yet : create family */
-	   parent->children = HTBTree_new(compare);
+	    parent->children = HTBTree_new(compare_anchors);
 	}
     }
 
@@ -236,6 +235,11 @@ PUBLIC HTChildAnchor * HTAnchor_findChild ARGS2(
 PRIVATE HTParentAnchor * HTAnchor_findAddress_nofragment PARAMS((
 	CONST DocAddress *	newdoc));
 
+PRIVATE BOOL HTAnchor_link PARAMS((
+	HTChildAnchor *		child,
+	HTAnchor *		destination,
+	HTLinkType *		type));
+
 
 /*	Create or find a child anchor with a possible link
 **	--------------------------------------------------
@@ -265,21 +269,21 @@ PUBLIC HTChildAnchor * HTAnchor_findChildAndLink ARGS4(
 	if (ltype == HTInternalLink && *href == '#') {
 	    dest = parent;
 	} else {
-	    CONST char *relative_to = parent->address;
+	    CONST char *relative_to = (parent->inBASE && *href != '#') ?
+				parent->content_base : parent->address;
 	    DocAddress parsed_doc;
 	    parsed_doc.address = HTParse(href, relative_to,
-	       PARSE_ACCESS | PARSE_HOST | PARSE_PATH | PARSE_PUNCTUATION);
+					 PARSE_ALL_WITHOUT_ANCHOR);
+
 	    parsed_doc.post_data = NULL;
 	    parsed_doc.post_content_type = NULL;
-#ifndef DONT_TRACK_INTERNAL_LINKS
 	    if (ltype && parent->post_data && ltype == HTInternalLink) {
 		/* for internal links, find a destination with the same
 		   post data if the source of the link has post data. - kw
-		   not sure this ever happens when *href != '#' - LP */
+		   Example: LYNXIMGMAP: */
 		parsed_doc.post_data = parent->post_data;
 		parsed_doc.post_content_type = parent->post_content_type;
 	    }
-#endif
 	    parsed_doc.bookmark = NULL;
 	    parsed_doc.isHEAD = FALSE;
 	    parsed_doc.safe = FALSE;
@@ -298,28 +302,20 @@ PUBLIC HTChildAnchor * HTAnchor_findChildAndLink ARGS4(
 	if (*fragment)
 	    dest = (HTParentAnchor *)HTAnchor_findChild(dest, fragment);
 
-#define DUPLICATE_ANCHOR_NAME_WORKAROUND  /*it will not work without*/
 
-#ifdef DUPLICATE_ANCHOR_NAME_WORKAROUND
 	if (tag && *tag) {
-	    if (child->dest) {
+	    if (child->dest) { /* DUPLICATE_ANCHOR_NAME_WORKAROUND  - kw */
 		CTRACE((tfp,
-		       "*** Duplicate ChildAnchor %p named `%s'",
-		       child, tag));
-		if ((HTAnchor *)dest == child->dest && ltype == child->type) {
-		    CTRACE((tfp,", same dest %p and type, already linked\n",
-			   child->dest));
-		    /* skip HTAnchor_link() */
-		    return child;
-
-		} else {
-		    CTRACE((tfp,", different dest %p, creating unnamed child\n",
+			   "*** Duplicate ChildAnchor %p named `%s'",
+			   child, tag));
+		if ((HTAnchor *)dest != child->dest || ltype != child->type) {
+		    CTRACE((tfp,
+			   ", different dest %p or type, creating unnamed child\n",
 			   child->dest));
 		    child = HTAnchor_findChild(parent, 0);
 		}
 	    }
 	}
-#endif
 	HTAnchor_link(child, (HTAnchor *)dest, ltype);
     }
     return child;
@@ -384,7 +380,7 @@ PUBLIC HTAnchor * HTAnchor_findAddress ARGS1(
 	HTChildAnchor * foundAnchor;
 
 	parsed_doc.address = HTParse(newdoc->address, "",
-		PARSE_ACCESS | PARSE_HOST | PARSE_PATH | PARSE_PUNCTUATION);
+				     PARSE_ALL_WITHOUT_ANCHOR);
 	parsed_doc.post_data = newdoc->post_data;
 	parsed_doc.post_content_type = newdoc->post_content_type;
 	parsed_doc.bookmark = newdoc->bookmark;
@@ -431,15 +427,9 @@ PRIVATE HTParentAnchor * HTAnchor_findAddress_nofragment ARGS1(
 	grownups = adults;
 	while (NULL != (foundAnchor =
 			(HTParentAnchor *)HTList_nextObject(grownups))) {
-#ifdef CASE_INSENSITIVE_ANCHORS
-	    if (HTEquivalent(foundAnchor->address, newdoc->address) &&
-		HTEquivalent(foundAnchor->post_data, newdoc->post_data) &&
-		foundAnchor->isHEAD == newdoc->isHEAD)
-#else
-	    if (HTIdentical(foundAnchor->address, newdoc->address) &&
-		HTIdentical(foundAnchor->post_data, newdoc->post_data) &&
+	    if (HTSEquivalent(foundAnchor->address, newdoc->address) &&
+		HTBEquivalent(foundAnchor->post_data, newdoc->post_data) &&
 		foundAnchor->isHEAD == newdoc->isHEAD)
-#endif /* CASE_INSENSITIVE_ANCHORS */
 	    {
 		CTRACE((tfp, "Anchor %p with address `%s' already exists.\n",
 			    (void *)foundAnchor, newdoc->address));
@@ -455,7 +445,7 @@ PRIVATE HTParentAnchor * HTAnchor_findAddress_nofragment ARGS1(
 		    (void *)foundAnchor, hash, newdoc->address));
 	StrAllocCopy(foundAnchor->address, newdoc->address);
 	if (newdoc->post_data)
-	    StrAllocCopy(foundAnchor->post_data, newdoc->post_data);
+	    BStrCopy(foundAnchor->post_data, newdoc->post_data);
 	if (newdoc->post_content_type)
 	    StrAllocCopy(foundAnchor->post_content_type,
 			 newdoc->post_content_type);
@@ -489,14 +479,42 @@ PUBLIC HTAnchor * HTAnchor_findSimpleAddress ARGS1(
 }
 
 
+/*	Link me Anchor to another given one
+**	-------------------------------------
+*/
+PRIVATE BOOL HTAnchor_link ARGS3(
+	HTChildAnchor *,	child,
+	HTAnchor *,		destination,
+	HTLinkType *,		type)
+{
+    if (!(child && destination))
+	return(NO);  /* Can't link to/from non-existing anchor */
+
+    CTRACE((tfp, "Linking child %p to anchor %p\n", child, destination));
+    if (child->dest) {
+	CTRACE((tfp, "*** child anchor already has destination, exiting!\n"));
+	return(NO);
+    }
+
+    child->dest = destination;
+    child->type = type;
+
+    if (child->parent != destination->parent)
+	/* link only foreign children */
+	HTList_linkObject(&destination->parent->sources, child, &child->_add_sources);
+
+    return(YES);  /* Success */
+}
+
+
 /*	Delete an anchor and possibly related things (auto garbage collection)
 **	--------------------------------------------
 **
 **	The anchor is only deleted if the corresponding document is not loaded.
-**	All outgoing links from parent and children are deleted, and this anchor
-**	is removed from the sources list of its target.
+**	All outgoing links from children are deleted, and children are
+**	removed from the sources lists of theirs targets.
 **	We also try to delete the targets whose documents are not loaded.
-**	If this anchor's source list is empty, we delete it and its children.
+**	If this anchor's sources list is empty, we delete it and its children.
 */
 
 /*
@@ -508,28 +526,13 @@ PRIVATE void deleteLinks ARGS1(
 	HTChildAnchor *,	me)
 {
     /*
-     *	Memory leaks fixed.
-     *	05-27-94 Lynx 2-3-1 Garrett Arch Blythe
-     */
-
-    /*
-     *	Anchor is NULL, do nothing.
-     */
-    if (!me) {
-	return;
-    }
-
-    /*
      *	Unregister me with our destination anchor's parent.
      */
     if (me->dest) {
 	HTParentAnchor *parent = me->dest->parent;
 
 	/*
-	 *  Set the dest pointer to zero NOW.  If we don't,
-	 *  and we get somehow called recursively again for this
-	 *  same old me during the HTAnchor_delete below, weird
-	 *  things can occasionally happen. - kw
+	 *  Start.  Set the dest pointer to zero.
 	 */
 	 me->dest = NULL;
 
@@ -537,7 +540,7 @@ PRIVATE void deleteLinks ARGS1(
 	 *  Remove me from the parent's sources so that the
 	 *  parent knows one less anchor is its dest.
 	 */
-	if (!HTList_isEmpty(&parent->sources)) {
+	if ((me->parent != parent) && !HTList_isEmpty(&parent->sources)) {
 	    /*
 	     *	Really should only need to deregister once.
 	     */
@@ -545,19 +548,17 @@ PRIVATE void deleteLinks ARGS1(
 	}
 
 	/*
+	 *  Recursive call.
 	 *  Test here to avoid calling overhead.
-	 *  If the parent has no loaded document, then we should
-	 *  tell it to attempt to delete itself.
-	 *  Also, don't do this if the destination parent is our
-	 *  parent.
+	 *  Don't delete if document is loaded or being loaded.
 	 */
-	if (!parent->document &&
-	    me->parent != parent) {
+	if (!(parent->document || parent->underway)) {
 	    HTAnchor_delete(parent);
 	}
 
 	/*
-	 *  At this point, we haven't a destination.  Set it to be so.
+	 *  At this point, we haven't a destination.  Set it to be
+	 *  so.
 	 *  Leave the HTAtom pointed to by type up to other code to
 	 *  handle (reusable, near static).
 	 */
@@ -565,27 +566,6 @@ PRIVATE void deleteLinks ARGS1(
     }
 }
 
-#ifdef SOURCE_CACHE
-PUBLIC void HTAnchor_clearSourceCache ARGS1(
-	HTParentAnchor *,	me)
-{
-    /*
-     * Clean up the source cache, if any.
-     */
-    if (me->source_cache_file) {
-	CTRACE((tfp, "SourceCache: Removing file %s\n",
-	       me->source_cache_file));
-	LYRemoveTemp(me->source_cache_file);
-	FREE(me->source_cache_file);
-    }
-    if (me->source_cache_chunk) {
-	CTRACE((tfp, "SourceCache: Removing memory chunk %p\n",
-	       (void *)me->source_cache_chunk));
-	HTChunkFree(me->source_cache_chunk);
-	me->source_cache_chunk = NULL;
-    }
-}
-#endif /* SOURCE_CACHE */
 
 PUBLIC BOOL HTAnchor_delete ARGS1(
 	HTParentAnchor *,	me)
@@ -618,33 +598,37 @@ PUBLIC BOOL HTAnchor_delete ARGS1(
      */
     me->underway = TRUE;
 
-    /*
-     *	There are still incoming links to this one (we are the
-     *	destination of another anchor).
-     *	Don't actually delete this parent anchor, but children are OK to
-     *	delete their links.
-     */
-    if (!HTList_isEmpty(&me->sources)) {
+    {
 	/*
-	 *  Delete all outgoing links from children, do not
-	 *  delete the children, though.
+	 *  Delete all outgoing links from children.
+	 *  Do not delete named children itself (may have incoming links).
 	 */
 	if (!HTList_isEmpty(&me->children_notag)) {
 	    cur = &me->children_notag;
-	    while ((child = (HTChildAnchor *)HTList_nextObject(cur)) != 0) {
+	    while ((child =
+			(HTChildAnchor *)HTList_unlinkLastObject(cur)) != 0) {
 		deleteLinks(child);
+		FREE(child);
 	    }
 	}
 	if (me->children) {
 	    ele = HTBTree_next(me->children, NULL);
 	    while (ele != NULL) {
 		child = (HTChildAnchor *)HTBTree_object(ele);
-		deleteLinks(child);
+		if (child->dest)
+		    deleteLinks(child);
 		ele = HTBTree_next(me->children, ele);
 	    }
 	}
-	me->underway = FALSE;
+    }
+    me->underway = FALSE;
+
 
+    /*
+     * There are still incoming links to this one (we are the
+     * destination of another anchor).
+     */
+    if (!HTList_isEmpty(&me->sources)) {
 	/*
 	 *  Can't delete parent, still have sources.
 	 */
@@ -652,38 +636,19 @@ PUBLIC BOOL HTAnchor_delete ARGS1(
     }
 
     /*
-     *	No more incoming links : kill everything
-     *	First, recursively delete children and their links.
+     *	No more incoming and outgoing links : kill everything
+     *	First, delete named children.
      */
     if (me->children) {
 	ele = HTBTree_next(me->children, NULL);
 	while (ele != NULL) {
 	    child = (HTChildAnchor *)HTBTree_object(ele);
-	    deleteLinks(child);
 	    FREE(child->tag);
+	    FREE(child);
 	    ele = HTBTree_next(me->children, ele);
 	}
-	HTBTreeAndObject_free(me->children);
-	me->children = NULL;
+	HTBTree_free(me->children);
     }
-    /* ...and this kind of children */
-    if (!HTList_isEmpty(&me->children_notag)) {
-	while ((child = (HTChildAnchor *)HTList_unlinkLastObject(
-						       &me->children_notag)) != 0) {
-	   deleteLinks(child);
-	   FREE(child);
-	}
-    }
-    me->children_notag.object = NULL;
-    me->children_notag.next = NULL;
-
-    me->underway = FALSE;
-
-    /*
-     * Init our empty list of sources.
-     */
-    me->sources.object = NULL;
-    me->sources.next = NULL;
 
     /*
      *	Delete the methods list.
@@ -705,7 +670,7 @@ PUBLIC BOOL HTAnchor_delete ARGS1(
     FREE(me->isIndexPrompt);
     FREE(me->title);
     FREE(me->physical);
-    FREE(me->post_data);
+    BStrFree(me->post_data);
     FREE(me->post_content_type);
     FREE(me->bookmark);
     FREE(me->owner);
@@ -776,6 +741,28 @@ PUBLIC BOOL HTAnchor_delete ARGS1(
 }
 
 
+#ifdef SOURCE_CACHE
+PUBLIC void HTAnchor_clearSourceCache ARGS1(
+	HTParentAnchor *,	me)
+{
+    /*
+     * Clean up the source cache, if any.
+     */
+    if (me->source_cache_file) {
+	CTRACE((tfp, "SourceCache: Removing file %s\n",
+	       me->source_cache_file));
+	LYRemoveTemp(me->source_cache_file);
+	FREE(me->source_cache_file);
+    }
+    if (me->source_cache_chunk) {
+	CTRACE((tfp, "SourceCache: Removing memory chunk %p\n",
+	       (void *)me->source_cache_chunk));
+	HTChunkFree(me->source_cache_chunk);
+	me->source_cache_chunk = NULL;
+    }
+}
+#endif /* SOURCE_CACHE */
+
 /*	Data access functions
 **	---------------------
 */
@@ -833,7 +820,7 @@ PUBLIC HTFormat HTAnchor_format ARGS1(
 
 PUBLIC void HTAnchor_setIndex ARGS2(
 	HTParentAnchor *,	me,
-	char *,			address)
+	CONST char *,		address)
 {
     if (me) {
 	me->isIndex = YES;
@@ -843,7 +830,7 @@ PUBLIC void HTAnchor_setIndex ARGS2(
 
 PUBLIC void HTAnchor_setPrompt ARGS2(
 	HTParentAnchor *,	me,
-	char *,			prompt)
+	CONST char *,		prompt)
 {
     if (me) {
 	StrAllocCopy(me->isIndexPrompt, prompt);
@@ -1128,31 +1115,6 @@ PUBLIC BOOL HTAnchor_setSubject ARGS2(
     return TRUE;
 }
 
-/*	Link me Anchor to another given one
-**	-------------------------------------
-*/
-PUBLIC BOOL HTAnchor_link ARGS3(
-	HTChildAnchor *,	source,
-	HTAnchor *,		destination,
-	HTLinkType *,		type)
-{
-    if (!(source && destination))
-	return(NO);  /* Can't link to/from non-existing anchor */
-
-    CTRACE((tfp, "Linking anchor %p to anchor %p\n", source, destination));
-    if (source->dest) {
-	CTRACE((tfp, "*** ERR: child anchor already has destination!\n"));
-	return(NO);
-    }
-
-    source->dest = destination;
-    source->type = type;
-
-    HTList_linkObject(&destination->parent->sources, source, &source->_add_sources);
-    return(YES);  /* Success */
-}
-
-
 /*	Manipulation of links
 **	---------------------
 */
diff --git a/WWW/Library/Implementation/HTAnchor.h b/WWW/Library/Implementation/HTAnchor.h
index fea5b928..50a180aa 100644
--- a/WWW/Library/Implementation/HTAnchor.h
+++ b/WWW/Library/Implementation/HTAnchor.h
@@ -48,7 +48,7 @@ struct _HTParentAnchor {
 
   HyperDoc *	document;	/* The document within which this is an anchor */
   char *	address;	/* Absolute address of this node */
-  char *	post_data;	/* Posting data */
+  bstring *	post_data;	/* Posting data */
   char *	post_content_type;  /* Type of post data */
   char *	bookmark;	/* Bookmark filename */
   HTFormat	format;		/* Pointer to node format descriptor */
@@ -79,6 +79,7 @@ struct _HTParentAnchor {
   char *	SugFname;	/* Suggested filename */
   char *	cache_control;	/* Cache-Control */
   BOOL		no_cache;	/* Cache-Control, Pragma or META "no-cache"? */
+  BOOL		inBASE;		/* duplicated from HTStructured (HTML.c/h) */
   char *	content_type;		/* Content-Type */
   char *	content_language;	/* Content-Language */
   char *	content_encoding;	/* Compression algorithm */
@@ -119,12 +120,12 @@ typedef struct {
 **  needed information including posting data and post content type.
 */
 typedef struct _DocAddress {
-    char * address;
-    char * post_data;
-    char * post_content_type;
-    char * bookmark;
-    BOOL   isHEAD;
-    BOOL   safe;
+    char *	address;
+    bstring *	post_data;
+    char *	post_content_type;
+    char *	bookmark;
+    BOOL	isHEAD;
+    BOOL	safe;
 } DocAddress;
 
 /* "internal" means "within the same document, with certainty". */
@@ -177,10 +178,10 @@ extern HTAnchor * HTAnchor_findSimpleAddress PARAMS((
 **	--------------------------------------------
 **
 **	The anchor is only deleted if the corresponding document is not loaded.
-**	All outgoing links from parent and children are deleted, and this anchor
-**	is removed from the sources list of all its targets.
+**	All outgoing links from children are deleted, and children are
+**	removed from the sources lists of their targets.
 **	We also try to delete the targets whose documents are not loaded.
-**	If this anchor's source list is empty, we delete it and its children.
+**	If this anchor's sources list is empty, we delete it and its children.
 */
 extern BOOL HTAnchor_delete PARAMS((
 	HTParentAnchor *	me));
@@ -218,11 +219,11 @@ extern HTFormat HTAnchor_format PARAMS((
 
 extern void HTAnchor_setIndex PARAMS((
 	HTParentAnchor *	me,
-	char *		address));
+	CONST char *		address));
 
 extern void HTAnchor_setPrompt PARAMS((
 	HTParentAnchor *	me,
-	char *			prompt));
+	CONST char *		prompt));
 
 extern BOOL HTAnchor_isIndex PARAMS((
 	HTParentAnchor *	me));
@@ -355,14 +356,6 @@ extern BOOL HTAnchor_setSubject PARAMS((
 	HTParentAnchor *	me,
 	CONST char *		subject));
 
-/*	Link this Anchor to another given one
-**	-------------------------------------
-*/
-extern BOOL HTAnchor_link PARAMS((
-	HTChildAnchor *		source,
-	HTAnchor *		destination,
-	HTLinkType *		type));
-
 /*	Manipulation of links
 **	---------------------
 */
diff --git a/WWW/Library/Implementation/HTFTP.c b/WWW/Library/Implementation/HTFTP.c
index 555bb176..222baabf 100644
--- a/WWW/Library/Implementation/HTFTP.c
+++ b/WWW/Library/Implementation/HTFTP.c
@@ -122,11 +122,6 @@ PRIVATE char ThisYear[8];
 PRIVATE char LastYear[8];
 PRIVATE int TheDate;
 PRIVATE BOOLEAN HaveYears = FALSE;
-#ifdef SOCKS
-extern BOOLEAN socks_flag;
-extern unsigned long socks_bind_remoteAddr;
-#endif /* SOCKS */
-extern char *personal_mail_address;
 
 /*	Module-Wide Variables
 **	---------------------
diff --git a/WWW/Library/Implementation/HTFile.c b/WWW/Library/Implementation/HTFile.c
index 47754cd7..03f427b6 100644
--- a/WWW/Library/Implementation/HTFile.c
+++ b/WWW/Library/Implementation/HTFile.c
@@ -2781,11 +2781,11 @@ PUBLIC void HTSetProgramPath ARGS2(
  */
 PUBLIC void HTInitProgramPaths NOARGS
 {
-    ProgramPaths code;
+    int code;
     CONST char *path;
     CONST char *test;
 
-    for (code = ppUnknown + 1; code < pp_Last; ++code) {
+    for (code = (int) ppUnknown + 1; code < (int) pp_Last; ++code) {
 	switch (code) {
 #ifdef BZIP2_PATH
 	case ppBZIP2:
diff --git a/WWW/Library/Implementation/HTFinger.c b/WWW/Library/Implementation/HTFinger.c
index 46ec892b..08d0932d 100644
--- a/WWW/Library/Implementation/HTFinger.c
+++ b/WWW/Library/Implementation/HTFinger.c
@@ -53,7 +53,7 @@
 
 /*	Module-wide variables
 */
-PRIVATE int s;					/* Socket for FingerHost */
+PRIVATE int finger_fd;				/* Socket for FingerHost */
 
 struct _HTStructured {
 	CONST HTStructuredClass * isa;		/* For gopher streams */
@@ -69,7 +69,7 @@ PRIVATE HTStructuredClass targetClass;		/* Copy of fn addresses */
 PRIVATE BOOL initialized = NO;
 PRIVATE BOOL initialize NOARGS
 {
-  s = -1;		/* Disconnected */
+  finger_fd = -1;		/* Disconnected */
   return YES;
 }
 
@@ -124,16 +124,16 @@ PRIVATE int response ARGS5(
 
     /* Set up buffering.
     */
-    HTInitInput(s);
+    HTInitInput(finger_fd);
 
     /* Send the command.
     */
     CTRACE((tfp, "HTFinger command to be sent: %s", command));
-    status = NETWRITE(s, (char *)command, length);
+    status = NETWRITE(finger_fd, (char *)command, length);
     if (status < 0) {
 	CTRACE((tfp, "HTFinger: Unable to send command. Disconnecting.\n"));
-	NETCLOSE(s);
-	s = -1;
+	NETCLOSE(finger_fd);
+	finger_fd = -1;
 	return status;
     } /* if bad status */
 
@@ -232,8 +232,8 @@ PRIVATE int response ARGS5(
 	    PUTC('\n');
 	}
     }
-    NETCLOSE(s);
-    s = -1;
+    NETCLOSE(finger_fd);
+    finger_fd = -1;
 
 end_html:
     END(HTML_PRE);
@@ -258,9 +258,12 @@ PUBLIC int HTLoadFinger ARGS4(
 {
     char *username, *sitename, *colon;	/* Fields extracted from URL */
     char *slash, *at_sign;		/* Fields extracted from URL */
-    char *command, *str;		/* Buffers */
+    char *command, *str, *param;	/* Buffers */
     int port;				/* Port number from URL */
     int status;				/* tcp return */
+    int result = HT_LOADED;
+    BOOL IsGopherURL = FALSE;
+    CONST char * p1 = arg;
 
     CTRACE((tfp, "HTFinger: Looking for %s\n", (arg ? arg : "NULL")));
 
@@ -276,10 +279,6 @@ PUBLIC int HTLoadFinger ARGS4(
 	return HT_NOT_LOADED;	/* FAIL */
     }
 
-  {
-    CONST char * p1=arg;
-    BOOL IsGopherURL = FALSE;
-
     /*  Set up the host and command fields.
     */
     if (!strncasecomp(arg, "finger://", 9)) {
@@ -288,9 +287,13 @@ PUBLIC int HTLoadFinger ARGS4(
 	p1 = arg + 9;  /* Skip "gopher://" prefix */
 	IsGopherURL = TRUE;
     }
-    sitename = (char *)p1;
 
-    if ((slash = strchr(sitename, '/')) != NULL) {
+    param = 0;
+    sitename = StrAllocCopy(param, p1);
+    if (param == 0) {
+	HTAlert(COULD_NOT_LOAD_DATA);
+	return HT_NOT_LOADED;
+    } else if ((slash = strchr(sitename, '/')) != NULL) {
 	*slash++ = '\0';
 	HTUnEscape(slash);
 	if (IsGopherURL) {
@@ -301,15 +304,17 @@ PUBLIC int HTLoadFinger ARGS4(
 	    *slash++ = '\0';
 	}
     }
+
     if ((at_sign = strchr(sitename, '@')) != NULL) {
 	if (IsGopherURL) {
 	    HTAlert(COULD_NOT_LOAD_DATA);
 	    return HT_NOT_LOADED;	/* FAIL */
+	} else {
+	    *at_sign++ = '\0';
+	    username = sitename;
+	    sitename = at_sign;
+	    HTUnEscape(username);
 	}
-	*at_sign++ = '\0';
-	username = sitename;
-	sitename = at_sign;
-	HTUnEscape(username);
     } else if (slash) {
 	username = slash;
     } else {
@@ -318,99 +323,93 @@ PUBLIC int HTLoadFinger ARGS4(
 
     if (*sitename == '\0') {
 	HTAlert(gettext("Could not load data (no sitename in finger URL)"));
-	return HT_NOT_LOADED;		/* Ignore if no name */
-    }
-
-    if ((colon = strchr(sitename, ':')) != NULL) {
+	result = HT_NOT_LOADED;		/* Ignore if no name */
+    } else if ((colon = strchr(sitename, ':')) != NULL) {
 	*colon++ = '\0';
 	port = atoi(colon);
 	if (port != 79) {
 	    HTAlert(gettext("Invalid port number - will only use port 79!"));
-	    return HT_NOT_LOADED;	/* Ignore if wrong port */
+	    result = HT_NOT_LOADED;	/* Ignore if wrong port */
 	}
     }
 
-    /* Load the string for making a connection/
-    */
-    str = 0;
-    HTSprintf0(&str, "lose://%s/", sitename);
-
-    /* Load the command for the finger server.
-    */
-    command = 0;
-    if (at_sign && slash) {
-	if (*slash == 'w' || *slash == 'W') {
-	    HTSprintf0(&command, "/w %s%c%c", username, CR, LF);
-	} else {
+    if (result == HT_LOADED) {
+	/* Load the string for making a connection/
+	*/
+	str = 0;
+	HTSprintf0(&str, "lose://%s/", sitename);
+
+	/* Load the command for the finger server.
+	*/
+	command = 0;
+	if (at_sign && slash) {
+	    if (*slash == 'w' || *slash == 'W') {
+		HTSprintf0(&command, "/w %s%c%c", username, CR, LF);
+	    } else {
+		HTSprintf0(&command, "%s%c%c", username, CR, LF);
+	    }
+	} else if (at_sign) {
 	    HTSprintf0(&command, "%s%c%c", username, CR, LF);
-	}
-    } else if (at_sign) {
-	HTSprintf0(&command, "%s%c%c", username, CR, LF);
-    } else if (*username == '/') {
-	if ((slash = strchr((username+1), '/')) != NULL) {
-	    *slash = ' ';
-	}
-	HTSprintf0(&command, "%s%c%c", username, CR, LF);
-    } else if ((*username == 'w' || *username == 'W') &&
-	       *(username+1) == '/') {
-	if (*username+2 != '\0') {
-	    *(username+1) = ' ';
-	} else {
-	    *(username+1) = '\0';
-	}
-	HTSprintf0(&command, "/%s%c%c", username, CR, LF);
-    } else if ((*username == 'w' || *username == 'W') &&
-	       *(username+1) == '\0') {
-	HTSprintf0(&command, "/%s%c%c", username, CR, LF);
-    } else if ((slash = strchr(username, '/')) != NULL) {
-	*slash++ = '\0';
-	if (*slash == 'w' || *slash == 'W') {
-	    HTSprintf0(&command, "/w %s%c%c", username, CR, LF);
+	} else if (*username == '/') {
+	    if ((slash = strchr((username+1), '/')) != NULL) {
+		*slash = ' ';
+	    }
+	    HTSprintf0(&command, "%s%c%c", username, CR, LF);
+	} else if ((*username == 'w' || *username == 'W') &&
+		   *(username+1) == '/') {
+	    if (*username+2 != '\0') {
+		*(username+1) = ' ';
+	    } else {
+		*(username+1) = '\0';
+	    }
+	    HTSprintf0(&command, "/%s%c%c", username, CR, LF);
+	} else if ((*username == 'w' || *username == 'W') &&
+		   *(username+1) == '\0') {
+	    HTSprintf0(&command, "/%s%c%c", username, CR, LF);
+	} else if ((slash = strchr(username, '/')) != NULL) {
+	    *slash++ = '\0';
+	    if (*slash == 'w' || *slash == 'W') {
+		HTSprintf0(&command, "/w %s%c%c", username, CR, LF);
+	    } else {
+		HTSprintf0(&command, "%s%c%c", username, CR, LF);
+	    }
 	} else {
 	    HTSprintf0(&command, "%s%c%c", username, CR, LF);
 	}
-    } else {
-	HTSprintf0(&command, "%s%c%c", username, CR, LF);
-    }
-  } /* scope of p1 */
 
-    /* Now, let's get a stream setup up from the FingerHost:
-    ** CONNECTING to finger host
-    */
-    CTRACE((tfp, "HTFinger: doing HTDoConnect on '%s'\n", str));
-    status = HTDoConnect(str, "finger", FINGER_PORT, &s);
-    CTRACE((tfp, "HTFinger: Done DoConnect; status %d\n", status));
-
-    if (status == HT_INTERRUPTED) {
-	/* Interrupt cleanly */
-	CTRACE((tfp, "HTFinger: Interrupted on connect; recovering cleanly.\n"));
-	HTProgress (CONNECTION_INTERRUPTED);
-	FREE(str);
-	FREE(command);
-	return HT_NOT_LOADED;
-    }
-    if (status < 0) {
-	NETCLOSE(s);
-	s = -1;
-	CTRACE((tfp, "HTFinger: Unable to connect to finger host.\n"));
-	HTAlert(gettext("Could not access finger host."));
-	FREE(str);
-	FREE(command);
-	return HT_NOT_LOADED;	/* FAIL */
-    }
-    CTRACE((tfp, "HTFinger: Connected to finger host '%s'.\n", str));
-    FREE(str);
+	/* Now, let's get a stream setup up from the FingerHost:
+	** CONNECTING to finger host
+	*/
+	CTRACE((tfp, "HTFinger: doing HTDoConnect on '%s'\n", str));
+	status = HTDoConnect(str, "finger", FINGER_PORT, &finger_fd);
+	CTRACE((tfp, "HTFinger: Done DoConnect; status %d\n", status));
+
+	if (status == HT_INTERRUPTED) {
+	    /* Interrupt cleanly */
+	    CTRACE((tfp, "HTFinger: Interrupted on connect; recovering cleanly.\n"));
+	    HTProgress (CONNECTION_INTERRUPTED);
+	    result = HT_NOT_LOADED;
+	} else if (status < 0) {
+	    NETCLOSE(finger_fd);
+	    finger_fd = -1;
+	    CTRACE((tfp, "HTFinger: Unable to connect to finger host.\n"));
+	    HTAlert(gettext("Could not access finger host."));
+	    result = HT_NOT_LOADED;	/* FAIL */
+	} else {
+	    CTRACE((tfp, "HTFinger: Connected to finger host '%s'.\n", str));
 
-    /* Send the command, and process response if successful.
-    */
-    if (response(command, sitename, anAnchor, format_out, stream) != 0) {
-	HTAlert(gettext("No response from finger server."));
+	    /* Send the command, and process response if successful.
+	    */
+	    if (response(command, sitename, anAnchor, format_out, stream) != 0) {
+		HTAlert(gettext("No response from finger server."));
+		result = HT_NOT_LOADED;
+	    }
+	}
+	FREE(str);
 	FREE(command);
-	return HT_NOT_LOADED;
     }
-
-    FREE(command);
-    return HT_LOADED;
+    FREE(param);
+    return result;
 }
 
 #ifdef GLOBALDEF_IS_MACRO
diff --git a/WWW/Library/Implementation/HTGopher.c b/WWW/Library/Implementation/HTGopher.c
index 34d28772..b47822ff 100644
--- a/WWW/Library/Implementation/HTGopher.c
+++ b/WWW/Library/Implementation/HTGopher.c
@@ -1433,11 +1433,11 @@ PRIVATE int HTLoadCSO ARGS4(
 	HTStream*,		sink)
 {
     static CONST char end_form[] = "</BODY>\n</HTML>\n";
-    char *host, *cp;
+    char *host, *cp, *data;
     int port = CSO_PORT;
     int status;				/* tcp return */
-    char *command = NULL;
-    char *content = NULL;
+    bstring *command = NULL;
+    bstring *content = NULL;
     int len, i, j, start, finish, flen, ndx;
     int return_type, has_indexed;
     CSOfield_info *fld;
@@ -1474,12 +1474,15 @@ PRIVATE int HTLoadCSO ARGS4(
 
     HTInitInput(s);		/* Set up input buffering */
 
-    HTSprintf0(&command, "fields%c%c", CR, LF);
-    CTRACE((tfp, "HTLoadCSO: Connected, writing command `%s' to socket %d\n",
-		command, s));
+    HTBprintf(&command, "fields%c%c", CR, LF);
+    if (TRACE) {
+	CTRACE((tfp, "HTLoadCSO: Connected, writing command `"));
+	trace_bstring(command);
+	CTRACE((tfp, "' to socket %d\n", s));
+    }
     _HTProgress (GOPHER_SENDING_CSO_REQUEST);
-    status = NETWRITE(s, command, (int)strlen(command));
-    FREE(command);
+    status = NETWRITE(s, BStrData(command), BStrLen(command));
+    BStrFree(command);
     if (status < 0) {
 	CTRACE((tfp, "HTLoadCSO: Unable to send command.\n"));
 	return HTInetStatus("send");
@@ -1523,7 +1526,7 @@ PRIVATE int HTLoadCSO ARGS4(
 	}
     }
     anAnchor->safe = TRUE;
-    if (!(anAnchor->post_data && *anAnchor->post_data)) {
+    if (isBEmpty(anAnchor->post_data)) {
 	generate_cso_form(host, port, buf, Target);
 	(*Target->isa->_free)(Target);
 	FREE(host);
@@ -1532,66 +1535,72 @@ PRIVATE int HTLoadCSO ARGS4(
 	return HT_LOADED;
     }
 
-    HTSprintf0(&command,
+    HTBprintf(&command,
      "<HTML>\n<HEAD>\n<TITLE>CSO/PH Results on %s</TITLE>\n</HEAD>\n<BODY>\n",
 	    host);
-    (*Target->isa->put_block)(Target, command, strlen(command));
-    FREE(command);
+    (*Target->isa->put_block)(Target, BStrData(command), BStrLen(command));
+    BStrFree(command);
     FREE(host);
 
-    StrAllocCopy(content, anAnchor->post_data);
-    if (content[strlen(content)-1] != '&')
-	StrAllocCat(content, "&");
-    len = strlen(content);
+    BStrCopy(content, anAnchor->post_data);
+
+    if (BStrData(content)[BStrLen(content)-1] != '&')
+	BStrCat0(content, "&");
+
+    data = BStrData(content);
+    len = BStrLen(content);
     for (i = 0; i < len; i++) {
-	if (content[i] == '+') {
-	    content[i] = ' ';
+	if (data[i] == '+') {
+	    data[i] = ' ';
 	}
     }
-    HTUnEscape(content);
-    len = strlen(content);
+
+    data = BStrData(content);
+    HTUnEscape(data);		/* FIXME: could it have embedded null? */
+    len = BStrLen(content);
+
     return_type = 0;
     has_indexed = 0;
     start = finish = 0;
     for (i = 0; i < len; i++) {
-	if (!content[i] || content[i] == '&') {
+	if (!data[i] || data[i] == '&') {
 	    /*
 	    **	Value parsed.  Unescape characters and look for first '='
 	    **	to delimit field name from value.
 	    */
 	    flen = i - start;
 	    finish = start + flen;
-	    content[finish] = '\0';
+	    data[finish] = '\0';
 	    for (j = start; j < finish; j++) {
-		if (content[j] == '=') {
+		if (data[j] == '=') {
 		    /*
-		    **	content[start..j-1] is field name,
+		    **	data[start..j-1] is field name,
 		    **	[j+1..finish-1] is value.
 		    */
-		    if ((content[start+1] == '_') &&
-			((content[start] == 'r') || (content[start] == 'q'))) {
+		    if ((data[start+1] == '_') &&
+			((data[start] == 'r') || (data[start] == 'q'))) {
 			/*
 			**  Decode fields number and lookup field info.
 			*/
-			sscanf (&content[start+2], "%d=", &ndx);
+			sscanf (&data[start+2], "%d=", &ndx);
 			for (fld = CSOfields; fld; fld = fld->next) {
 			    if (ndx==fld->id) {
 				if ((j+1) >= finish)
 				    break;	/* ignore nulls */
-				if (content[start] == 'q') {
+				if (data[start] == 'q') {
 				    /*
 				     * Append field to query line.
 				     */
 				    if (fld->lookup) {
 					if (fld->indexed)
 					    has_indexed = 1;
-					if (command == 0 || *command == 0) {
-					    StrAllocCopy(command, "query ");
+					if (isBEmpty(command)) {
+					    BStrCopy0(command, "query ");
 					} else {
-					    StrAllocCat(command, " ");
+					    BStrCat0(command, " ");
 					}
-					HTSprintf(&command, "%s=\"%s\"",
-						  fld->name, &content[j+1]);
+					HTBprintf(&command, "%s=\"%s\"",
+						  fld->name, &data[j+1]);
 				    } else {
 					strcpy(buf,
 				"Warning: non-lookup field ignored<BR>\n");
@@ -1599,16 +1608,16 @@ PRIVATE int HTLoadCSO ARGS4(
 								  buf,
 								  strlen(buf));
 				    }
-				} else if (content[start] == 'r') {
+				} else if (data[start] == 'r') {
 				    fld->explicit_return = 1;
 				}
 				break;
 			    }
 			}
-		    } else if (!strncmp(&content[start],"return=",7)) {
-			if (!strcmp(&content[start+7],"all")) {
+		    } else if (!strncmp(&data[start], "return=", 7)) {
+			if (!strcmp(&data[start+7], "all")) {
 			    return_type = 1;
-			} else if (!strcmp(&content[start+7],"selected")) {
+			} else if (!strcmp(&data[start+7], "selected")) {
 			    return_type = 2;
 			}
 		    }
@@ -1617,8 +1626,8 @@ PRIVATE int HTLoadCSO ARGS4(
 	    start = i + 1;
 	}
     }
-    FREE(content);
-    if ((command == 0 || *command == 0) || !has_indexed) {
+    BStrFree(content);
+    if (isBEmpty(command) || !has_indexed) {
 	NETCLOSE(s);
 	strcpy(buf,
   "<EM>Error:</EM> At least one indexed field value must be specified!\n");
@@ -1633,25 +1642,28 @@ PRIVATE int HTLoadCSO ARGS4(
     **	Append return fields.
     */
     if (return_type == 1) {
-	StrAllocCat(command, " return all");
+	BStrCat0(command, " return all");
     } else if (return_type == 2) {
-	StrAllocCat(command, " return");
+	BStrCat0(command, " return");
 	for (fld = CSOfields; fld; fld = fld->next) {
 	    if (fld->explicit_return) {
-		HTSprintf(&command, " %s", fld->name);
+		HTBprintf(&command, " %s", fld->name);
 	    }
 	}
     }
-    HTSprintf(&command, "%c%c", CR, LF);
+    HTBprintf(&command, "%c%c", CR, LF);
     strcpy(buf, "<H2>\n<EM>CSO/PH command:</EM> ");
     (*Target->isa->put_block)(Target, buf, strlen(buf));
-    (*Target->isa->put_block)(Target, command, strlen(command));
+    (*Target->isa->put_block)(Target, BStrData(command), BStrLen(command));
     strcpy(buf, "</H2>\n");
     (*Target->isa->put_block)(Target, buf, strlen(buf));
-    CTRACE((tfp, "HTLoadCSO: Writing command `%s' to socket %d\n",
-		command, s));
-    status = NETWRITE(s, command, strlen(command));
-    FREE(command);
+    if (TRACE) {
+	CTRACE((tfp, "HTLoadCSO: Writing command `"));  
+	trace_bstring(command);
+	CTRACE((tfp, "' to socket %d\n", s));
+    }
+    status = NETWRITE(s, BStrData(command), BStrLen(command));
+    BStrFree(command);
     if (status < 0) {
 	CTRACE((tfp, "HTLoadCSO: Unable to send command.\n"));
 	free_CSOfields();
diff --git a/WWW/Library/Implementation/HTList.c b/WWW/Library/Implementation/HTList.c
index 35d865cf..7a517ec6 100644
--- a/WWW/Library/Implementation/HTList.c
+++ b/WWW/Library/Implementation/HTList.c
@@ -99,7 +99,7 @@ PUBLIC void HTList_linkObject ARGS3(
 	HTList *,	newNode)
 {
     if (me) {
-	if (newNode->object == 0 && newNode->next == 0) {
+	if (newNode->object == NULL && newNode->next == NULL) {
 	    /*  It is safe: */
 	    newNode->object = newObject;
 	    newNode->next = me->next;
@@ -107,7 +107,7 @@ PUBLIC void HTList_linkObject ARGS3(
 
 	} else {
 	    /*
-	     *  This node was already linked to some list (probably this one),
+	     *  This node is already linked to some list (probably this one),
 	     *  so refuse changing node pointers to keep the list valid!!!
 	     */
 	    CTRACE((tfp, "*** HTList: Refuse linking already linked obj "));
@@ -228,6 +228,8 @@ PUBLIC BOOL HTList_unlinkObject ARGS2(
 	    temp = temp->next;
 	    if (temp->object == oldObject) {
 		prevNode->next = temp->next;
+		temp->next = NULL;
+		temp->object = NULL;
 		return YES;  /* Success */
 	    }
 	}
@@ -305,6 +307,8 @@ PUBLIC void * HTList_unlinkLastObject ARGS1(
 	lastNode = me->next;
 	lastObject = lastNode->object;
 	me->next = lastNode->next;
+	lastNode->next = NULL;
+	lastNode->object = NULL;
 	return lastObject;
 
     } else {  /* Empty list */
diff --git a/WWW/Library/Implementation/HTNews.c b/WWW/Library/Implementation/HTNews.c
index 72ae27de..7864b52e 100644
--- a/WWW/Library/Implementation/HTNews.c
+++ b/WWW/Library/Implementation/HTNews.c
@@ -52,6 +52,7 @@ PRIVATE char HTNewsGetCharacter NOPARAMS;
 #endif /* USE_SSL */
 
 #include <HTML.h>
+#include <HTAccess.h>
 #include <HTParse.h>
 #include <HTFormat.h>
 #include <HTAlert.h>
@@ -74,7 +75,6 @@ struct _HTStream
 
 #define LINE_LENGTH 512			/* Maximum length of line of ARTICLE etc */
 #define GROUP_NAME_LENGTH	256	/* Maximum length of group name */
-extern BOOL using_proxy;	/* Are we using an NNTP proxy? */
 
 /*
 **  Module-wide variables.
diff --git a/WWW/Library/Implementation/HTParse.c b/WWW/Library/Implementation/HTParse.c
index 08480133..0157a3b5 100644
--- a/WWW/Library/Implementation/HTParse.c
+++ b/WWW/Library/Implementation/HTParse.c
@@ -8,6 +8,7 @@
 #include <LYUtils.h>
 #include <LYLeaks.h>
 #include <LYStrings.h>
+#include <LYCharUtils.h>
 
 #ifdef HAVE_ALLOCA_H
 #include <alloca.h>
@@ -153,7 +154,6 @@ PRIVATE void scan ARGS2(
     }
 } /*scan */
 
-
 #if defined(HAVE_ALLOCA) && !defined(LY_FIND_LEAKS)
 #define LYalloca(x)        alloca(x)
 #define LYalloca_free(x)   {}
@@ -226,16 +226,33 @@ PUBLIC char * HTParse ARGS3(
     rel = name + len1;
 
     /*
-    **	Make working copies of the input strings to cut up.
+    **	Make working copy of the input string to cut up.
     */
     memcpy(name, aName, len1);
-    memcpy(rel, relatedName, len2);
 
     /*
-    **	Cut up the strings into URL fields.
+    **	Cut up the string into URL fields.
     */
     scan(name, &given);
-    scan(rel,  &related);
+
+    /*
+    **	Now related string.
+    */
+    if ((given.access && given.host && given.absolute) || !*relatedName) {
+	/*
+	**  Inherit nothing!
+	*/
+	related.access = NULL;
+	related.host = NULL;
+	related.absolute = NULL;
+	related.relative = NULL;
+	related.search = NULL;
+	related.anchor = NULL;
+    } else {
+	memcpy(rel, relatedName, len2);
+	scan(rel,  &related);
+    }
+
 
     /*
     **	Handle the scheme (access) field.
@@ -302,11 +319,12 @@ PUBLIC char * HTParse ARGS3(
 	    /*
 	    **	Ignore default port numbers, and trailing dots on FQDNs,
 	    **	which will only cause identical addresses to look different.
+	    **  (related is already a clean url).
 	    */
 	    {
 		char *p2, *h;
 		if ((p2 = strchr(result, '@')) != NULL)
-		   tail = (p2 + 1);
+ 		   tail = (p2 + 1);
 		p2 = strchr(tail, ':');
 		if (p2 != NULL && !isdigit(UCH(p2[1])))
 		    /*
@@ -496,22 +514,57 @@ PUBLIC char * HTParse ARGS3(
      * See the discussion in LYLegitimizeHREF() for example.
      */
     if ((p = strchr(result, ' ')) != 0) {
-	do {
-	    char *q = p + strlen(p) + 2;
-	    while (q != p + 1) {
-		q[0] = q[-2];
-		--q;
-	    }
-	    p[0] = '%';
-	    p[1] = '2';
-	    p[2] = '0';
-	} while ((p = strchr(result, ' ')) != 0);
+	switch (is_url(result)) {
+	case NOT_A_URL_TYPE:
+	case UNKNOWN_URL_TYPE:
+	    CTRACE((tfp, "HTParse:      ignore:`%s'\n", result));
+	    break;
+	case LYNXEXEC_URL_TYPE:
+	case LYNXPROG_URL_TYPE:
+	case LYNXCGI_URL_TYPE:
+	case LYNXPRINT_URL_TYPE:
+	case LYNXHIST_URL_TYPE:
+	case LYNXDOWNLOAD_URL_TYPE:
+	case LYNXKEYMAP_URL_TYPE:
+	case LYNXIMGMAP_URL_TYPE:
+	case LYNXCOOKIE_URL_TYPE:
+	case LYNXDIRED_URL_TYPE:
+	case LYNXOPTIONS_URL_TYPE:
+	case LYNXCFG_URL_TYPE:
+	case LYNXCOMPILE_OPTS_URL_TYPE:
+	case LYNXMESSAGES_URL_TYPE:
+	    CTRACE((tfp, "HTParse:      spaces:`%s'\n", result));
+	    break;
+	default:
+	    CTRACE((tfp, "HTParse:      encode:`%s'\n", result));
+	    do {
+		char *q = p + strlen(p) + 2;
+		while (q != p + 1) {
+		    q[0] = q[-2];
+		    --q;
+		}
+		p[0] = '%';
+		p[1] = '2';
+		p[2] = '0';
+	    } while ((p = strchr(result, ' ')) != 0);
+	    break;
+	}
     }
-    CTRACE((tfp, "HTParse:      result:%s\n", result));
+    CTRACE((tfp, "HTParse:      result:`%s'\n", result));
 
     StrAllocCopy(return_value, result);
     LYalloca_free(result);
 
+    /* FIXME: could be optimized using HTParse() internals */
+    if (*relatedName &&
+	((wanted & PARSE_ALL_WITHOUT_ANCHOR) == PARSE_ALL_WITHOUT_ANCHOR)) {
+	/*
+	 *  Check whether to fill in localhost. - FM
+	 */
+	LYFillLocalFileURL(&return_value, relatedName);
+	CTRACE((tfp, "pass LYFillLocalFile:`%s'\n", return_value));
+    }
+
     return return_value;		/* exactly the right length */
 }
 
@@ -1012,17 +1065,21 @@ PRIVATE CONST unsigned char crfc[96] =
 
 /*
 **  Turn a string which is not a RFC 822 token into a quoted-string. - KW
+**  The "quoted" parameter tells whether we need the beginning/ending quote
+**  marks.  If not, the caller will provide them -TD
 */
-PUBLIC void HTMake822Word ARGS1(
-	char **,	str)
+PUBLIC void HTMake822Word ARGS2(
+	char **,	str,
+	int,		quoted)
 {
     CONST char * p;
     char * q;
     char * result;
     unsigned char a;
     int added = 0;
-    if (!(*str) || !(**str)) {
-	StrAllocCopy(*str, "\"\"");
+
+    if (isEmpty(*str)) {
+	StrAllocCopy(*str, quoted ? "\"\"" : "");
 	return;
     }
     for (p = *str; *p; p++) {
@@ -1044,14 +1101,17 @@ PUBLIC void HTMake822Word ARGS1(
     result = typecallocn(char, p-(*str) + added + 1);
     if (result == NULL)
 	outofmem(__FILE__, "HTMake822Word");
-    result[0] = '"';
+
+    q = result;
+    if (quoted)
+	*q++ = '"';
     /*
     ** Having converted the character to ASCII, we can't use symbolic
     ** escape codes, since they're in the host character set, which
     ** is not necessarily ASCII.  Thus we use octal escape codes instead.
     ** -- gil (Paul Gilmartin) <pg@sweng.stortek.com>
     */  /* S/390 -- gil -- 0268 */
-    for (q = result + 1, p = *str; *p; p++) {
+    for (p = *str; *p; p++) {
 	a = TOASCII(*p);
 	if ((a != '\011') && ((a & 127) < 32 ||
 			    ( a < 128 && ((crfc[a-32]) & 2))))
@@ -1060,7 +1120,8 @@ PUBLIC void HTMake822Word ARGS1(
 	if (a == '\012' || (a == '\015' && (TOASCII(*(p+1)) != '\012')))
 	    *q++ = ' ';
     }
-    *q++ = '"';
+    if (quoted)
+	*q++ = '"';
     *q++ = '\0';			/* Terminate */
     FREE(*str);
     *str = result;
diff --git a/WWW/Library/Implementation/HTParse.h b/WWW/Library/Implementation/HTParse.h
index eb334d52..8d3fae74 100644
--- a/WWW/Library/Implementation/HTParse.h
+++ b/WWW/Library/Implementation/HTParse.h
@@ -21,7 +21,10 @@
 #define PARSE_PATH               4
 #define PARSE_ANCHOR             2
 #define PARSE_PUNCTUATION        1
+
 #define PARSE_ALL               31
+#define PARSE_ALL_WITHOUT_ANCHOR  (PARSE_ALL ^ PARSE_ANCHOR)
+
 /*
 **  Additional flag bits for more details on components already
 **  covered by the above.  The PARSE_PATH above doesn't really
@@ -189,6 +192,7 @@ extern char * HTUnEscapeSome PARAMS((
 **  Turn a string which is not a RFC 822 token into a quoted-string. - KW
 */
 extern void HTMake822Word PARAMS((
-	char **		str));
+	char **		str,
+	int		quoted));
 
 #endif  /* HTPARSE_H */
diff --git a/WWW/Library/Implementation/HTString.c b/WWW/Library/Implementation/HTString.c
index 0aeaa821..e0b2a344 100644
--- a/WWW/Library/Implementation/HTString.c
+++ b/WWW/Library/Implementation/HTString.c
@@ -543,9 +543,9 @@ PRIVATE char *HTAlloc ARGS2(char *, ptr, size_t, length)
 #endif
 
 /*
- * Replacement for sprintf, allocates buffer on the fly according to what's needed
- * for its arguments.  Unlike sprintf, this always concatenates to the destination
- * buffer, so we do not have to provide both flavors.
+ * Replacement for sprintf, allocates buffer on the fly according to what's
+ * needed for its arguments.  Unlike sprintf, this always concatenates to the
+ * destination buffer, so we do not have to provide both flavors.
  */
 typedef enum { Flags, Width, Prec, Type, Format } PRINTF;
 
@@ -789,9 +789,9 @@ PUBLIC_IF_FIND_LEAKS char * StrAllocVsprintf ARGS4(
 #undef SAVE_TIME_NOT_SPACE
 
 /*
- * Replacement for sprintf, allocates buffer on the fly according to what's needed
- * for its arguments.  Unlike sprintf, this always concatenates to the destination
- * buffer.
+ * Replacement for sprintf, allocates buffer on the fly according to what's
+ * needed for its arguments.  Unlike sprintf, this always concatenates to the
+ * destination buffer.
  */
 /* Note: if making changes, also check the memory tracking version
  * LYLeakHTSprintf in LYLeaks.c. - kw */
@@ -1063,6 +1063,7 @@ PUBLIC void HTEndParam ARGS3(
 {
     CONST char *last;
     int count;
+
     count = HTCountCommandArgs (command);
     if (count < number)
 	number = count;
@@ -1074,11 +1075,11 @@ PUBLIC void HTEndParam ARGS3(
 }
 
 
-#ifdef EXP_FILE_UPLOAD
-/*	bstring Allocate and Concatenate
-*/
+/*	Binary-strings (may have embedded nulls).
+ *	Some modules (HTGopher) assume there is a null on the end, anyway.
+ */
 
-/*	Allocate a new copy of a bstring, and returns it
+/*	Allocate a new bstring, and return it.
 */
 PUBLIC void HTSABCopy ARGS3(
 	bstring**,	dest,
@@ -1086,51 +1087,198 @@ PUBLIC void HTSABCopy ARGS3(
 	int,		len)
 {
     bstring *t;
-    CTRACE((tfp, "HTSABCopy(%p, %p, %d)\n", dest, src, len));
-    /* if we already have a bstring ** ... */
-    if (dest) {
-	/* ... with a valid bstring *, free it ... */
-	if (*dest) {
-	    FREE((*dest)->str);
-	    FREE(*dest);
-	}
-	*dest = malloc(sizeof(bstring));
-	if (src) {
-	    CTRACE((tfp, "%% [%s]\n", src));
-	    t = (bstring*) malloc(sizeof(bstring));
-	    if (t == NULL)
-		outofmem(__FILE__, "HTSABCopy");
-	    t->str = (char *) malloc (len);
-	    if (t->str == NULL)
-		outofmem(__FILE__, "HTSABCopy");
-	    memcpy (t->str, src, len);
-	    t->len = len;
-	    *dest = t;
+    unsigned need = len + 1;
+
+    CTRACE2(TRACE_BSTRING, (tfp, "HTSABCopy(%p, %p, %d)\n", dest, src, len));
+    HTSABFree(dest);
+    if (src) {
+	if (TRACE_BSTRING) {
+	    CTRACE((tfp, "===    %4d:", len));
+	    trace_bstring2(src, len);
+	    CTRACE((tfp, "\n"));
 	}
+	if ((t = (bstring*) malloc(sizeof(bstring))) == NULL)
+	    outofmem(__FILE__, "HTSABCopy");
+	if ((t->str = (char *) malloc (need)) == NULL)
+	    outofmem(__FILE__, "HTSABCopy");
+	memcpy (t->str, src, len);
+	t->len = len;
+	t->str[t->len] = '\0';
+	*dest = t;
+    }
+    if (TRACE_BSTRING) {
+	CTRACE((tfp, "=>     %4d:", BStrLen(*dest)));
+	trace_bstring(*dest);
+	CTRACE((tfp, "\n"));
     }
 }
 
+/*
+ * Initialize with a null-terminated string (discards the null).
+ */
+PUBLIC void HTSABCopy0 ARGS2(
+	bstring**,	dest,
+	CONST char *,	src)
+{
+    HTSABCopy(dest, src, strlen(src));
+}
+
+/*
+ * Append a block of memory to a bstring.
+ */
 PUBLIC void HTSABCat ARGS3(
 	bstring **,	dest,
 	CONST char *,	src,
 	int,		len)
 {
     bstring *t = *dest;
+
+    CTRACE2(TRACE_BSTRING, (tfp, "HTSABCat(%p, %p, %d)\n", dest, src, len));
     if (src) {
+	unsigned need = len + 1;
+
+	if (TRACE_BSTRING) {
+	    CTRACE((tfp, "===    %4d:", len));
+	    trace_bstring2(src, len);
+	    CTRACE((tfp, "\n"));
+	}
 	if (t) {
-	    int length = t->len;
-	    t->str = (char *)realloc(t->str, length + len);
+	    unsigned length = t->len + need;
+	    if ((t->str = (char *)realloc(t->str, length)) == NULL)
+		outofmem(__FILE__, "HTSACat");
 	} else {
-	    t = typecalloc(bstring);
-	    if (t == NULL)
+	    if ((t = typecalloc(bstring)) == NULL)
 		outofmem(__FILE__, "HTSACat");
-	    t->str = (char *)malloc(len);
+	    t->str = (char *)malloc(need);
 	}
 	if (t->str == NULL)
 	    outofmem(__FILE__, "HTSACat");
 	memcpy (t->str + t->len, src, len);
 	t->len += len;
+	t->str[t->len] = '\0';
 	*dest = t;
     }
+    if (TRACE_BSTRING) {
+	CTRACE((tfp, "=>     %4d:", BStrLen(*dest)));
+	trace_bstring(*dest);
+	CTRACE((tfp, "\n"));
+    }
+}
+
+/*
+ * Append a null-terminated string (discards the null).
+ */
+PUBLIC void HTSABCat0 ARGS2(
+	bstring**,	dest,
+	CONST char *,	src)
+{
+    HTSABCat(dest, src, strlen(src));
+}
+
+/*
+ * Compare two bstring's for equality
+ */
+PUBLIC BOOL HTSABEql   ARGS2(
+	bstring *,	a,
+	bstring *,	b)
+{
+    unsigned len_a = (a != 0) ? a->len : 0;
+    unsigned len_b = (b != 0) ? b->len : 0;
+
+    if (len_a == len_b) {
+	if (len_a == 0
+	 || memcmp(a->str, b->str, a->len) == 0)
+	    return TRUE;
+    }
+    return FALSE;
+}
+
+/*
+ * Deallocate a bstring.
+ */
+PUBLIC void HTSABFree ARGS1(
+	bstring **,	ptr)
+{
+    if (*ptr != NULL) {
+	FREE((*ptr)->str);
+	FREE(*ptr);
+	*ptr = NULL;
+    }
+}
+
+/*
+ * Use this function to perform formatted sprintf's onto the end of a bstring.
+ * The bstring may contain embedded nulls; the formatted portions must not.
+ */
+#ifdef ANSI_VARARGS
+PUBLIC bstring * HTBprintf (bstring ** pstr, CONST char * fmt, ...)
+#else
+PUBLIC bstring * HTBprintf ()
+#endif
+{
+    bstring *result = 0;
+    char *temp = 0;
+    va_list ap;
+
+    LYva_start(ap,fmt);
+    {
+#if !ANSI_VARARGS
+	char **		pstr = va_arg(ap, char **);
+	CONST char *	fmt  = va_arg(ap, CONST char *);
+#endif
+	temp = StrAllocVsprintf(&temp, 0, fmt, &ap);
+	if (!isEmpty(temp)) {
+	    HTSABCat (pstr, temp, strlen(temp));
+	}
+	FREE(temp);
+	result = *pstr;
+    }
+    va_end(ap);
+
+    return (result);
+}
+
+/*
+ * Write binary-data to the logfile, making it safe for most editors to view.
+ * That is most, since we do not restrict line-length.  Nulls and other
+ * non-printing characters are addressed.
+ */
+PUBLIC void trace_bstring2 ARGS2(
+	CONST char *,	text,
+	int,		size)
+{
+    int n;
+
+    if (text != 0) {
+	for (n = 0; n < size; ++n) {
+	    int ch = UCH(text[n]);
+	    switch (ch) {
+	    case '\\':
+		fputs("\\\\", tfp);
+		break;
+	    case '\r':
+		fputs("\\r", tfp);
+		break;
+	    case '\t':
+		fputs("\\t", tfp);
+		break;
+	    case '\f':
+		fputs("\\f", tfp);
+		break;
+	    default:
+		if (isprint(ch) || isspace(ch)) {
+		    fputc(ch, tfp);
+		} else {
+		    fprintf(tfp, "\\%03o", ch);
+		}
+		break;
+	    }
+	}
+    }
+}
+
+PUBLIC void trace_bstring ARGS1(
+	bstring *,	data)
+{
+    trace_bstring2(BStrData(data), BStrLen(data));
 }
-#endif /* EXP_FILE_UPLOAD */
diff --git a/WWW/Library/Implementation/HTString.h b/WWW/Library/Implementation/HTString.h
index 0a6eaa18..a93f4a7e 100644
--- a/WWW/Library/Implementation/HTString.h
+++ b/WWW/Library/Implementation/HTString.h
@@ -118,15 +118,39 @@ extern void HTEndParam PARAMS((char ** result, CONST char * command, int number)
 #define HTOptParam(result, command, number, parameter) HTSACat(result, parameter)
 
 /* Binary copy and concat */
-#ifdef EXP_FILE_UPLOAD
-
 typedef struct {
 	char *str;
 	int len;
 } bstring;
 
-extern void HTSABCopy PARAMS((bstring** dest, CONST char * src, int len));
-extern void HTSABCat PARAMS((bstring ** dest, CONST char * src, int len));
+extern void HTSABCopy  PARAMS((bstring ** dest, CONST char * src, int len));
+extern void HTSABCopy0 PARAMS((bstring ** dest, CONST char * src));
+extern void HTSABCat   PARAMS((bstring ** dest, CONST char * src, int len));
+extern void HTSABCat0  PARAMS((bstring ** dest, CONST char * src));
+extern BOOL HTSABEql   PARAMS((bstring * a, bstring * b));
+extern void HTSABFree  PARAMS((bstring ** ptr));
+
+#define BStrLen(s)    (((s) != 0) ? (s)->len : 0)
+#define BStrData(s)   (((s) != 0) ? (s)->str : 0)
+
+#define BINEQ(a,b)    (HTSABEql(a,b))	/* like STREQ() */
+
+#define isBEmpty(p)   ((p) == 0 || BStrLen(p) == 0)
+
+#define BStrCopy(d,s)  HTSABCopy(  &(d), BStrData(s), BStrLen(s))
+#define BStrCopy0(d,s) HTSABCopy0( &(d), s)
+#define BStrCat(d,s)   HTSABCat(   &(d), BStrData(s), BStrLen(s))
+#define BStrCat0(d,s)  HTSABCat0(  &(d), s)
+#define BStrFree(d)    HTSABFree(  &(d))
+
+#ifdef ANSI_VARARGS
+extern bstring * HTBprintf (bstring ** pstr, CONST char * fmt, ...)
+			    GCC_PRINTFLIKE(2,3);
+#else
+extern bstring * HTBprintf () GCC_PRINTFLIKE(2,3);
 #endif
 
+extern void trace_bstring PARAMS((bstring *data));
+extern void trace_bstring2 PARAMS((CONST char *text, int size));
+
 #endif /* HTSTRING_H */
diff --git a/WWW/Library/Implementation/HTStyle.c b/WWW/Library/Implementation/HTStyle.c
index 2e8494d2..9e3bc8a5 100644
--- a/WWW/Library/Implementation/HTStyle.c
+++ b/WWW/Library/Implementation/HTStyle.c
@@ -18,10 +18,9 @@
 */
 PUBLIC HTStyle* HTStyleNew NOARGS
 {
-    HTStyle * self = (HTStyle *)malloc(sizeof(*self));
+    HTStyle * self = typecalloc(HTStyle);
     if (self == NULL)
 	outofmem(__FILE__, "HTStyleNew");
-    memset((void *)self, 0, sizeof(*self));
     return self;
 }
 
@@ -31,6 +30,7 @@ PUBLIC HTStyle* HTStyleNewNamed ARGS1 (CONST char *,name)
 {
     HTStyle * self = HTStyleNew();
     StrAllocCopy(self->name, name);
+    self->id = -1; /* <0 */
     return self;
 }
 
@@ -287,15 +287,9 @@ HTStyleSheet * HTStyleSheetRemoveStyle ARGS2
 
 HTStyleSheet * HTStyleSheetNew NOARGS
 {
-    HTStyleSheet * self = (HTStyleSheet *)malloc(sizeof(*self));
+    HTStyleSheet * self = typecalloc(HTStyleSheet);
     if (self == NULL)
 	outofmem(__FILE__, "HTStyleSheetNew");
-
-    memset((void*)self, 0, sizeof(*self));	/* ANSI */
-/* Harbison c ref man says (char*)self
-   but k&r ansii and abc books and Think_C say (void*) */
-
-/*    bzero(self, sizeof(*self)); */		/* BSD */
     return self;
 }
 
diff --git a/WWW/Library/Implementation/HTStyle.h b/WWW/Library/Implementation/HTStyle.h
index be958f07..cc23dd05 100644
--- a/WWW/Library/Implementation/HTStyle.h
+++ b/WWW/Library/Implementation/HTStyle.h
@@ -77,6 +77,7 @@ typedef struct _HTStyle {
 */
     struct _HTStyle     *next;          /* Link for putting into stylesheet */
     char *              name;           /* Style name */
+    int                 id;             /* equivalent of name, for speed */
     char *              SGMLTag;        /* Tag name to start */
 
 
@@ -158,6 +159,60 @@ extern HTStyleSheet * HTStyleSheetWrite PARAMS((HTStyleSheet * self,
 #define CLEAR_POINTER ((void *)-1)      /* Pointer value means "clear me" */
 
 /* DefaultStyle.c */
-extern HTStyleSheet * DefaultStyle NOPARAMS;
+extern HTStyleSheet * DefaultStyle PARAMS((HTStyle*** result_array));
+
+/* enum, use this instead of HTStyle name comparisons */
+enum HTStyle_Enum {
+	ST_Normal = 0,
+	ST_DivCenter,
+	ST_DivLeft,
+	ST_DivRight,
+	ST_Banner,
+	ST_Blockquote,
+	ST_Bq,
+	ST_Footnote,
+	ST_List,
+	ST_List1,
+	ST_List2,
+	ST_List3,
+	ST_List4,
+	ST_List5,
+	ST_List6,
+	ST_Menu,
+	ST_Menu1,
+	ST_Menu2,
+	ST_Menu3,
+	ST_Menu4,
+	ST_Menu5,
+	ST_Menu6,
+	ST_Glossary,
+	ST_Glossary1,
+	ST_Glossary2,
+	ST_Glossary3,
+	ST_Glossary4,
+	ST_Glossary5,
+	ST_Glossary6,
+	ST_GlossaryCompact,
+	ST_GlossaryCompact1,
+	ST_GlossaryCompact2,
+	ST_GlossaryCompact3,
+	ST_GlossaryCompact4,
+	ST_GlossaryCompact5,
+	ST_GlossaryCompact6,
+	ST_Example,
+	ST_Preformatted,
+	ST_Listing,
+	ST_Address,
+	ST_Note,
+	ST_Heading1,
+	ST_Heading2,
+	ST_Heading3,
+	ST_Heading4,
+	ST_Heading5,
+	ST_Heading6,
+	ST_HeadingCenter,
+	ST_HeadingLeft,
+	ST_HeadingRight
+};
 
 #endif /* HTStyle_H */
diff --git a/WWW/Library/Implementation/HTTCP.c b/WWW/Library/Implementation/HTTCP.c
index c07b6c6e..eef67b87 100644
--- a/WWW/Library/Implementation/HTTCP.c
+++ b/WWW/Library/Implementation/HTTCP.c
@@ -76,7 +76,6 @@ PRIVATE char *hostname = NULL;		/* The name of this host */
 **  PUBLIC VARIABLES
 */
 #ifdef SOCKS
-extern BOOLEAN socks_flag;
 PUBLIC unsigned long socks_bind_remoteAddr; /* for long Rbind */
 #endif /* SOCKS */
 
diff --git a/WWW/Library/Implementation/HTTP.c b/WWW/Library/Implementation/HTTP.c
index 87073b38..4f8f256f 100644
--- a/WWW/Library/Implementation/HTTP.c
+++ b/WWW/Library/Implementation/HTTP.c
@@ -54,14 +54,6 @@ PUBLIC char * redirecting_url = NULL;	    /* Location: value. */
 PUBLIC BOOL permanent_redirection = FALSE;  /* Got 301 status? */
 PUBLIC BOOL redirect_post_content = FALSE;  /* Don't convert to GET? */
 
-extern BOOLEAN LYUserSpecifiedURL; /* Is the URL a goto? */
-
-extern BOOL keep_mime_headers;	 /* Include mime headers and force source dump */
-extern BOOL no_url_redirection;  /* Don't follow Location: URL for */
-extern char *http_error_file;	 /* Store HTTP status code in this file */
-extern BOOL traversal;		 /* TRUE if we are doing a traversal */
-extern BOOL dump_output_immediately;  /* TRUE if no interactive user */
-
 #ifdef USE_SSL
 PUBLIC SSL_CTX * ssl_ctx = NULL;	/* SSL ctx */
 PUBLIC SSL * SSL_handle = NULL;
@@ -259,7 +251,6 @@ PUBLIC int ws_netread(int fd, char *buf, int len)
 
     extern int win32_check_interrupt(void);	/* LYUtil.c */
     extern int lynx_timeout;			/* LYMain.c */
-    extern int AlertSecs;			/* LYMain.c */
     extern CRITICAL_SECTION critSec_READ;	/* LYMain.c */
 
 #define TICK	5
@@ -390,7 +381,7 @@ PRIVATE int HTLoadHTTP ARGS4 (
 {
   int s;			/* Socket number for returned data */
   CONST char *url = arg;	/* The URL which get_physical() returned */
-  char *command = NULL;		/* The whole command */
+  bstring *command = NULL;	/* The whole command */
   char *eol;			/* End of line if found */
   char *start_of_data;		/* Start of body of reply */
   int status;			/* tcp return */
@@ -646,18 +637,18 @@ use_tunnel:
 #ifdef USE_SSL
     if (do_connect) {
 	METHOD = "CONNECT";
-	StrAllocCopy(command, "CONNECT ");
+	BStrCopy0(command, "CONNECT ");
     } else
 #endif /* USE_SSL */
     if (do_post) {
 	METHOD = "POST";
-	StrAllocCopy(command, "POST ");
+	BStrCopy0(command, "POST ");
     } else if (do_head) {
 	METHOD = "HEAD";
-	StrAllocCopy(command, "HEAD ");
+	BStrCopy0(command, "HEAD ");
     } else {
 	METHOD = "GET";
-	StrAllocCopy(command, "GET ");
+	BStrCopy0(command, "GET ");
     }
 
     /*
@@ -668,24 +659,24 @@ use_tunnel:
 #ifdef USE_SSL
     if (using_proxy && !did_connect) {
 	if (do_connect)
-	    StrAllocCat(command, connect_host);
+	    BStrCat0(command, connect_host);
 	else
-	    StrAllocCat(command, p1+1);
+	    BStrCat0(command, p1+1);
     }
 #else
     if (using_proxy)
-	StrAllocCat(command, p1+1);
+	BStrCat0(command, p1+1);
 #endif /* USE_SSL */
     else
-	StrAllocCat(command, p1);
+	BStrCat0(command, p1);
     FREE(p1);
   }
   if (extensions) {
-      StrAllocCat(command, " ");
-      StrAllocCat(command, HTTP_VERSION);
+      BStrCat0(command, " ");
+      BStrCat0(command, HTTP_VERSION);
   }
 
-  StrAllocCat(command, crlf);	/* CR LF, as in rfc 977 */
+  BStrCat0(command, crlf);	/* CR LF, as in rfc 977 */
 
   if (extensions) {
       int n, i;
@@ -693,7 +684,7 @@ use_tunnel:
 
       if ((host = HTParse(anAnchor->address, "", PARSE_HOST)) != NULL) {
 	  strip_userid(host);
-	  HTSprintf(&command, "Host: %s%c%c", host, CR,LF);
+	  HTBprintf(&command, "Host: %s%c%c", host, CR,LF);
 	  FREE(host);
       }
 
@@ -726,17 +717,17 @@ use_tunnel:
 			    temp);
 	      len += strlen(linebuf);
 	      if (len > 252 && !first_Accept) {
-		  StrAllocCat(command, crlf);
+		  BStrCat0(command, crlf);
 		  HTSprintf0(&linebuf, "Accept: %s%s",
 				HTAtom_name(pres->rep),
 				temp);
 		  len = strlen(linebuf);
 	      }
-	      StrAllocCat(command, linebuf);
+	      BStrCat0(command, linebuf);
 	      first_Accept = FALSE;
 	  }
       }
-      HTSprintf(&command, "%s*/*;q=0.01%c%c",
+      HTBprintf(&command, "%s*/*;q=0.01%c%c",
 		    (first_Accept ?
 		       "Accept: " : ", "), CR, LF);
       first_Accept = FALSE;
@@ -765,17 +756,17 @@ use_tunnel:
 	  StrAllocCat(list, "compress");
 #endif
 	  if (list != 0) {
-	      HTSprintf(&command, "Accept-Encoding: %s%c%c", list, CR, LF);
+	      HTBprintf(&command, "Accept-Encoding: %s%c%c", list, CR, LF);
 	      free(list);
 	  }
       }
 
       if (language && *language) {
-	  HTSprintf(&command, "Accept-Language: %s%c%c", language, CR, LF);
+	  HTBprintf(&command, "Accept-Language: %s%c%c", language, CR, LF);
       }
 
       if (pref_charset && *pref_charset) {
-	  StrAllocCat(command, "Accept-Charset: ");
+	  BStrCat0(command, "Accept-Charset: ");
 	  StrAllocCopy(linebuf, pref_charset);
 	  if (linebuf[strlen(linebuf)-1] == ',')
 	      linebuf[strlen(linebuf)-1] = '\0';
@@ -784,8 +775,8 @@ use_tunnel:
 	      StrAllocCat(linebuf, ", iso-8859-1;q=0.01");
 	  if (strstr(linebuf, "us-ascii") == NULL)
 	      StrAllocCat(linebuf, ", us-ascii;q=0.01");
-	  StrAllocCat(command, linebuf);
-	  HTSprintf(&command, "%c%c", CR, LF);
+	  BStrCat0(command, linebuf);
+	  HTBprintf(&command, "%c%c", CR, LF);
       }
 
 #if 0
@@ -812,7 +803,7 @@ use_tunnel:
       **  new-httpd@apache.org from Koen Holtman, Jan 1999.
       */
       if (!do_post) {
-	  HTSprintf(&command, "Negotiate: trans%c%c", CR, LF);
+	  HTBprintf(&command, "Negotiate: trans%c%c", CR, LF);
       }
 #endif /* 0 */
 
@@ -823,25 +814,25 @@ use_tunnel:
       **  Also send it as a Cache-Control header for HTTP/1.1. - FM
       */
       if (reloading) {
-	  HTSprintf(&command, "Pragma: no-cache%c%c", CR, LF);
-	  HTSprintf(&command, "Cache-Control: no-cache%c%c", CR, LF);
+	  HTBprintf(&command, "Pragma: no-cache%c%c", CR, LF);
+	  HTBprintf(&command, "Cache-Control: no-cache%c%c", CR, LF);
       }
 
       if (LYUserAgent && *LYUserAgent) {
 	  char *cp = LYSkipBlanks(LYUserAgent);
 	  /* Won't send it at all if all blank - kw */
 	  if (*cp != '\0')
-	      HTSprintf(&command, "User-Agent: %.*s%c%c",
+	      HTBprintf(&command, "User-Agent: %.*s%c%c",
 		      INIT_LINE_SIZE-15, LYUserAgent, CR, LF);
       } else {
-	  HTSprintf(&command, "User-Agent: %s/%s  libwww-FM/%s%c%c",
+	  HTBprintf(&command, "User-Agent: %s/%s  libwww-FM/%s%c%c",
 		  HTAppName ? HTAppName : "unknown",
 		  HTAppVersion ? HTAppVersion : "0.0",
 		  HTLibraryVersion, CR, LF);
       }
 
       if (personal_mail_address && !LYNoFromHeader) {
-	  HTSprintf(&command, "From: %s%c%c", personal_mail_address, CR,LF);
+	  HTBprintf(&command, "From: %s%c%c", personal_mail_address, CR,LF);
       }
 
       if (!(LYUserSpecifiedURL ||
@@ -849,15 +840,15 @@ use_tunnel:
 	  strcmp(HTLoadedDocumentURL(), "")) {
 	  char *cp = LYRequestReferer;
 	  if (!cp) cp = HTLoadedDocumentURL(); /* @@@ Try both? - kw */
-	  StrAllocCat(command, "Referer: ");
+	  BStrCat0(command, "Referer: ");
 	  if (isLYNXIMGMAP(cp)) {
 	      char *cp1 = trimPoundSelector(cp);
-	      StrAllocCat(command, cp + LEN_LYNXIMGMAP);
+	      BStrCat0(command, cp + LEN_LYNXIMGMAP);
 	      restorePoundSelector(cp1);
 	  } else {
-	      StrAllocCat(command, cp);
+	      BStrCat0(command, cp);
 	  }
-	  HTSprintf(&command, "%c%c", CR, LF);
+	  HTBprintf(&command, "%c%c", CR, LF);
       }
 
       {
@@ -919,7 +910,7 @@ use_tunnel:
 		**  If auth is not NULL nor zero-length, it's
 		**  an Authorization header to be included. - FM
 		*/
-		HTSprintf(&command, "%s%c%c", auth, CR, LF);
+		HTBprintf(&command, "%s%c%c", auth, CR, LF);
 		CTRACE((tfp, "HTTP: Sending authorization: %s\n", auth));
 	    } else if (auth && *auth == '\0') {
 		/*
@@ -937,7 +928,7 @@ use_tunnel:
 		    if (did_connect)
 			HTTP_NETCLOSE(s, handle);
 #endif /* USE_SSL */
-		    FREE(command);
+		    BStrFree(command);
 		    FREE(hostname);
 		    FREE(docname);
 		    FREE(abspath);
@@ -978,8 +969,8 @@ use_tunnel:
 		**  It's a historical cookie, so signal to the
 		**  server that we support modern cookies. - FM
 		*/
-		StrAllocCat(command, "Cookie2: $Version=\"1\"");
-		StrAllocCat(command, crlf);
+		BStrCat0(command, "Cookie2: $Version=\"1\"");
+		BStrCat0(command, crlf);
 		CTRACE((tfp, "HTTP: Sending Cookie2: $Version =\"1\"\n"));
 	    }
 	    if (*cookie != '\0') {
@@ -988,9 +979,9 @@ use_tunnel:
 		**  Note that any folding of long strings has been
 		**  done already in LYCookie.c. - FM
 		*/
-		StrAllocCat(command, "Cookie: ");
-		StrAllocCat(command, cookie);
-		StrAllocCat(command, crlf);
+		BStrCat0(command, "Cookie: ");
+		BStrCat0(command, cookie);
+		BStrCat0(command, crlf);
 		CTRACE((tfp, "HTTP: Sending Cookie: %s\n", cookie));
 	    }
 	    FREE(cookie);
@@ -1014,7 +1005,7 @@ use_tunnel:
 	    **	an Authorization or Proxy-Authorization
 	    **	header to be included. - FM
 	    */
-	    HTSprintf(&command, "%s%c%c", auth, CR, LF);
+	    HTBprintf(&command, "%s%c%c", auth, CR, LF);
 	    CTRACE((tfp, (auth_proxy ?
 			 "HTTP: Sending proxy authorization: %s\n" :
 			 "HTTP: Sending authorization: %s\n"),
@@ -1034,7 +1025,7 @@ use_tunnel:
 	    } else {
 		if (traversal || dump_output_immediately)
 		    HTAlert(FAILED_NEED_PASSWD);
-		FREE(command);
+		BStrFree(command);
 		FREE(hostname);
 		FREE(docname);
 		status = HT_NOT_LOADED;
@@ -1057,50 +1048,52 @@ use_tunnel:
 #endif /* USE_SSL */
 	do_post) {
 	CTRACE((tfp, "HTTP: Doing post, content-type '%s'\n",
-		     anAnchor->post_content_type ? anAnchor->post_content_type
-						 : "lose"));
-	HTSprintf(&command, "Content-type: %s%c%c",
+		     anAnchor->post_content_type
+		     ? anAnchor->post_content_type
+		     : "lose"));
+	HTBprintf(&command, "Content-type: %s%c%c",
 		   anAnchor->post_content_type
 		   ? anAnchor->post_content_type
 		   : "lose",
 		  CR, LF);
-	/*
-	 * FIXME: Ack!  This assumes non-binary data!  Icky!
-	 */
-	HTSprintf(&command, "Content-length: %d%c%c",
-		  (anAnchor->post_data)
-		   ? strlen (anAnchor->post_data)
+
+	HTBprintf(&command, "Content-length: %d%c%c",
+		  !isBEmpty(anAnchor->post_data)
+		   ? BStrLen(anAnchor->post_data)
 		   : 0,
 		  CR, LF);
 
-	StrAllocCat(command, crlf);	/* Blank line means "end" of headers */
+	BStrCat0(command, crlf);	/* Blank line means "end" of headers */
 
-	StrAllocCat(command, anAnchor->post_data);
+	BStrCat(command, anAnchor->post_data);
     }
     else
-	StrAllocCat(command, crlf);	/* Blank line means "end" of headers */
+	BStrCat0(command, crlf);	/* Blank line means "end" of headers */
 
+    if (TRACE) {
+	CTRACE((tfp, "Writing:\n"));
+	trace_bstring(command);
 #ifdef USE_SSL
-  CTRACE((tfp, "Writing:\n%s%s----------------------------------\n",
-	       command,
+	CTRACE((tfp, "%s",
 	       (anAnchor->post_data && !do_connect ? crlf : "")));
 #else
-  CTRACE((tfp, "Writing:\n%s%s----------------------------------\n",
-	       command,
+	CTRACE((tfp, "%s",
 	       (anAnchor->post_data ? crlf : "")));
 #endif /* USE_SSL */
+	CTRACE((tfp, "----------------------------------\n"));
+    }
 
   _HTProgress (gettext("Sending HTTP request."));
 
 #ifdef    NOT_ASCII  /* S/390 -- gil -- 0548 */
   {   char *p;
 
-      for ( p = command; p < command + strlen(command); p++ )
+      for ( p = BStrData(command); p < BStrData(command) + BStrLen(command); p++ )
 	  *p = TOASCII(*p);
   }
 #endif /* NOT_ASCII */
-  status = HTTP_NETWRITE(s, command, (int)strlen(command), handle);
-  FREE(command);
+  status = HTTP_NETWRITE(s, BStrData(command), BStrLen(command), handle);
+  BStrFree(command);
   FREE(linebuf);
   if (status <= 0) {
       if (status == 0) {
diff --git a/WWW/Library/Implementation/HTTelnet.c b/WWW/Library/Implementation/HTTelnet.c
index 5ff87b49..2fbb1565 100644
--- a/WWW/Library/Implementation/HTTelnet.c
+++ b/WWW/Library/Implementation/HTTelnet.c
@@ -32,6 +32,7 @@
 #include <HTAlert.h>
 
 #include <LYStrings.h>
+#include <LYClean.h>
 #include <LYLeaks.h>
 
 PRIVATE void do_system ARGS1(char *, command)
@@ -320,8 +321,6 @@ PRIVATE int remote_session ARGS2(char *, acc_method, char *, host)
 	    do_system(command);
 	}
 	else {
-	    extern BOOLEAN HadVMSInterrupt;
-
 	    printf(
 	"\nSorry, this browser was compiled without the %s access option.\n",
 		acc_method);
@@ -430,8 +429,6 @@ PRIVATE int remote_session ARGS2(char *, acc_method, char *, host)
 	    do_system(command);
 	}
 	else {
-	    extern BOOLEAN HadVMSInterrupt;
-
 	    printf(
 	  "\nSorry, this browser was compiled without the %s access option.\n",
 		acc_method);
@@ -449,8 +446,6 @@ PRIVATE int remote_session ARGS2(char *, acc_method, char *, host)
 	    do_system(command);
 	}
 	else {
-	    extern BOOLEAN HadVMSInterrupt;
-
 	    printf(
 	  "\nSorry, this browser was compiled without the %s access option.\n",
 		acc_method);
@@ -488,10 +483,7 @@ PRIVATE int remote_session ARGS2(char *, acc_method, char *, host)
 	    fflush(stdout);
 	    LYgetch();
 #ifdef VMS
-	    {
-		extern BOOLEAN HadVMSInterrupt;
-		HadVMSInterrupt = FALSE;
-	    }
+	    HadVMSInterrupt = FALSE;
 #endif /* VMS */
 	}
 #endif /* !TELNET_DONE */
diff --git a/WWW/Library/Implementation/HTUtils.h b/WWW/Library/Implementation/HTUtils.h
index 06ff3684..71a3f373 100644
--- a/WWW/Library/Implementation/HTUtils.h
+++ b/WWW/Library/Implementation/HTUtils.h
@@ -168,7 +168,7 @@ typedef unsigned short mode_t;
 #  define NO_EMPTY_HREFLESS_A
 #endif
 
-#if  defined(__EMX__) || defined(WIN_EX)
+#if  defined(__EMX__) || defined(WIN_EX) || defined(HAVE_POPEN)
 #  define CAN_CUT_AND_PASTE
 #endif
 
@@ -360,7 +360,7 @@ Booleans
 
 #ifndef _WINDOWS
 #ifndef BOOLEAN_DEFINED
-        typedef char    BOOLEAN;                /* Logical value */
+    typedef char    BOOLEAN;	/* Logical value */
 #ifndef CURSES
 #ifndef TRUE
 #define TRUE    (BOOLEAN)1
@@ -374,6 +374,7 @@ Booleans
 #ifndef BOOL
 #define BOOL BOOLEAN
 #endif
+
 #ifndef YES
 #define YES (BOOLEAN)1
 #define NO (BOOLEAN)0
@@ -523,6 +524,7 @@ extern int WWW_TraceMask;
 #define TRACE_STYLE     (TRACE_bit(1))
 #define TRACE_TRST      (TRACE_bit(2))
 #define TRACE_CFG       (TRACE_bit(3))
+#define TRACE_BSTRING   (TRACE_bit(4))
 
 #if defined(LY_TRACELINE)
 #define LY_SHOWWHERE fprintf( tfp, "%s: %d: ", __FILE__, LY_TRACELINE ),
@@ -590,17 +592,33 @@ extern FILE *TraceFP NOPARAMS;
 
 #ifdef USE_SSL
 #define free_func free__func
+
 #ifdef USE_OPENSSL_INCL
 #include <openssl/ssl.h>
 #include <openssl/crypto.h>
 #include <openssl/rand.h>
 #include <openssl/err.h>
+
 #else
+
+#ifdef USE_GNUTLS_INCL
+#include <gnutls/openssl.h>
+/*
+ * GNUTLS's implementation of OpenSSL is very incomplete and rudimentary.
+ * For a start, let's make it compile (TD - 2003/4/13).
+ */
+#ifndef SSL_VERIFY_PEER
+#define SSL_VERIFY_PEER			0x01
+#endif
+
+#else	/* assume SSLeay */
 #include <ssl.h>
 #include <crypto.h>
 #include <rand.h>
 #include <err.h>
 #endif
+#endif /* USE_OPENSSL_INCL */
+
 #undef free_func
 
 extern SSL * HTGetSSLHandle NOPARAMS;
@@ -612,17 +630,11 @@ extern char HTGetSSLCharacter PARAMS((void * handle));
 #ifdef HAVE_LIBDMALLOC
 #include <dmalloc.h>    /* Gray Watson's library */
 #define show_alloc() dmalloc_log_unfreed()
-#else
-#undef  HAVE_LIBDMALLOC
-#define HAVE_LIBDMALLOC 0
 #endif
 
 #ifdef HAVE_LIBDBMALLOC
 #include <dbmalloc.h>   /* Conor Cahill's library */
 #define show_alloc() malloc_dump(fileno(stderr))
-#else
-#undef  HAVE_LIBDBMALLOC
-#define HAVE_LIBDBMALLOC 0
 #endif
 
 #ifndef show_alloc
diff --git a/WWW/Library/Implementation/HTVMSUtils.c b/WWW/Library/Implementation/HTVMSUtils.c
index 49c03f0a..b9f50e3d 100644
--- a/WWW/Library/Implementation/HTVMSUtils.c
+++ b/WWW/Library/Implementation/HTVMSUtils.c
@@ -20,6 +20,7 @@
 #include <UCMap.h>
 #include <UCAux.h>
 #include <HTFTP.h>
+#include <HTTCP.h>
 #include <HTVMSUtils.h>
 #include <ssdef.h>
 #include <jpidef.h>
@@ -31,11 +32,12 @@
 #include <starlet.h>
 #include <rmsdef.h>
 
+#include <LYGlobalDefs.h>
 #include <LYUtils.h>
 #include <LYLeaks.h>
 #include <LYStrings.h>
 
-PUBLIC BOOL HTVMSFileVersions=FALSE; /* Include version numbers in listing? */
+PUBLIC BOOL HTVMSFileVersions = FALSE; /* Include version numbers in listing? */
 
 typedef struct {
    unsigned long BufferLength : 16;
@@ -44,8 +46,6 @@ typedef struct {
    unsigned long ReturnLengthAddress : 32;
 } ItemStruct;
 
-extern CONST char * HTHostName NOPARAMS;
-
 /* PUBLIC							HTVMS_authSysPrv()
 **		CHECKS IF THIS PROCESS IS AUTHORIZED TO ENABLE SYSPRV
 ** ON ENTRY:
@@ -754,7 +754,6 @@ PUBLIC int HTVMSBrowseDir ARGS4(
     static char ThisYear[8];
     VMSEntryInfo *entry_info = 0;
     char string_buffer[64];
-    extern BOOLEAN no_dotfiles, show_dotfiles;
 
     HTUnEscape(pathname);
     CTRACE((tfp,"HTVMSBrowseDir: Browsing `%s\'\n", pathname));
diff --git a/WWW/Library/Implementation/HTWAIS.c b/WWW/Library/Implementation/HTWAIS.c
index 035ebbe5..e9269af2 100644
--- a/WWW/Library/Implementation/HTWAIS.c
+++ b/WWW/Library/Implementation/HTWAIS.c
@@ -637,8 +637,6 @@ PUBLIC int HTLoadWAIS ARGS4(
     int return_status = HT_LOADED;
     int rv;
 
-    extern FILE * connect_to_server();
-
     if (!acceptable_inited)
 	init_acceptable();
 
diff --git a/WWW/Library/Implementation/SGML.c b/WWW/Library/Implementation/SGML.c
index 4c3b3b5a..9a1f7535 100644
--- a/WWW/Library/Implementation/SGML.c
+++ b/WWW/Library/Implementation/SGML.c
@@ -60,6 +60,11 @@ PRIVATE void fake_put_character ARGS2(
 
 #endif
 
+/* my_casecomp() - optimized by the first character, NOT_ASCII ok */
+#define my_casecomp(a,b)  ((TOUPPER(*a) == TOUPPER(*b)) ? \
+			AS_casecomp(a,b) : \
+			(TOASCII(TOUPPER(*a)) - TOASCII(TOUPPER(*b))))
+
  /* will use partially inlined version */
 #define orig_HTChunkPutUtf8Char HTChunkPutUtf8Char
 #undef HTChunkPutUtf8Char
@@ -502,7 +507,7 @@ PRIVATE void handle_attribute_name ARGS2(
 	 high > low;
 	 diff < 0 ? (low = i+1) : (high = i)) {
 	i = (low + (high-low)/2);
-	diff = strcasecomp(attributes[i].name, s);
+	diff = my_casecomp(attributes[i].name, s);
 	if (diff == 0) {		/* success: found it */
 	    context->current_attribute_number = i;
 #ifdef USE_PRETTYSRC
@@ -1292,8 +1297,10 @@ PRIVATE void start_element ARGS1(
     if (!context->inSELECT) {
 	/*
 	**  We are not in a SELECT block, so check if this starts one. - FM
+	**  (frequent case!)
 	*/
-	if (!strcasecomp(new_tag->name, "SELECT")) {
+	/* my_casecomp() - optimized by the first character */
+	if (!my_casecomp(new_tag->name, "SELECT")) {
 	    /*
 	    **	Set the inSELECT flag and fall through. - FM
 	    */
@@ -1324,7 +1331,7 @@ PRIVATE void start_element ARGS1(
 		*/
 		CTRACE((tfp, "SGML: ***Faking SELECT end tag before <%s> start tag.\n",
 			    new_tag->name));
-		end_element(context, SGMLFindUprTag(context->dtd, "SELECT"));
+		end_element(context, SGMLFindTag(context->dtd, "SELECT"));
 	    } else {
 		/*
 		**  Ignore the start tag. - FM
@@ -1371,29 +1378,36 @@ PRIVATE void start_element ARGS1(
 **
 ** On entry,
 **	dtd	points to dtd structure including valid tag list
-**	string	points to name of uppercased tag in question
+**	string	points to name of tag in question
 **
 ** On exit,
 **	returns:
 **		NULL		tag not found
 **		else		address of tag structure in dtd
 */
-PUBLIC HTTag * SGMLFindUprTag ARGS2(
+PUBLIC HTTag * SGMLFindTag ARGS2(
 	CONST SGML_dtd*,	dtd,
-	CONST char *,		string)
+	CONST char *,		s)
 {
     int high, low, i, diff;
+    static HTTag* last[64] = {NULL};  /*optimize using the previous results*/
+    HTTag** res = last + (UCH(*s) % 64);     /*pointer arithmetic*/
+
+    if (*res && !strcasecomp((*res)->name, s))
+	return *res;
 
     for (low = 0, high=dtd->number_of_tags;
-	 high > low;
-	 diff < 0 ? (low = i+1) : (high = i)) {	 /* Binary search */
+	  high > low;
+	  diff < 0 ? (low = i+1) : (high = i)) {	/* Binary search */
 	i = (low + (high-low)/2);
-	diff = AS_cmp(dtd->tags[i].name, string);	/* Case sensitive */
+	/* my_casecomp() - optimized by the first character, NOT_ASCII ok */
+	diff = my_casecomp(dtd->tags[i].name, s);	/* Case insensitive */
 	if (diff == 0) {		/* success: found it */
-	    return &dtd->tags[i];
+	    *res = &dtd->tags[i];
+	    return *res;
 	}
     }
-    if (IsNmStart(string[0])) {
+    if (IsNmStart(*s)) {
 	/*
 	**  Unrecognized, but may be valid. - KW
 	*/
@@ -1402,28 +1416,6 @@ PUBLIC HTTag * SGMLFindUprTag ARGS2(
     return NULL;
 }
 
-/*		Find Tag in DTD tag list
-**		------------------------
-**
-** On entry,
-**	dtd	points to dtd structure including valid tag list
-**	string	points to name of tag in question
-**
-** On exit,
-**	returns:
-**		NULL		tag not found
-**		else		address of tag structure in dtd
-*/
-PUBLIC HTTag * SGMLFindTag ARGS2(
-	CONST SGML_dtd*,	dtd,
-	char *,			string)
-{
-    char * p = string;
-    for ( ; *p; p++)
-	*p = TOUPPER(*p);
-    return SGMLFindUprTag(dtd, string);
-}
-
 /*________________________________________________________________________
 **			Public Methods
 */
@@ -3992,7 +3984,7 @@ top1:
 			    CTRACE((tfp, "SGML: ***Faking SELECT end tag before </%s> end tag.\n",
 					string->data));
 			    end_element(context,
-					SGMLFindUprTag(context->dtd, "SELECT"));
+					SGMLFindTag(context->dtd, "SELECT"));
 			    CTRACE((tfp, "SGML: End </%s>\n", string->data));
 
 #ifdef USE_PRETTYSRC
@@ -4459,6 +4451,19 @@ PUBLIC HTStream* SGML_new  ARGS3(
 	context->inUCLYhndl = HTAnchor_getUCLYhndl(anchor,
 						   UCT_STAGE_PARSER);
     }
+#ifdef CAN_SWITCH_DISPLAY_CHARSET /* Allow a switch to a more suitable display charset */
+    else if (anchor->UCStages
+	     && anchor->UCStages->s[UCT_STAGE_PARSER].LYhndl >= 0
+	     && anchor->UCStages->s[UCT_STAGE_PARSER].LYhndl != current_char_set ) {
+	int o = anchor->UCStages->s[UCT_STAGE_PARSER].LYhndl;
+
+	anchor->UCStages->s[UCT_STAGE_PARSER].LYhndl = -1; /* Force reset */
+	HTAnchor_resetUCInfoStage(anchor, o, UCT_STAGE_PARSER,
+				  /* Preserve change this: */
+				  anchor->UCStages->s[UCT_STAGE_PARSER].lock);
+    }
+#endif
+
     context->inUCI = HTAnchor_getUCInfoStage(anchor,
 					     UCT_STAGE_PARSER);
     set_chartrans_handling(context, anchor, -1);
diff --git a/WWW/Library/Implementation/SGML.h b/WWW/Library/Implementation/SGML.h
index 9e84cf9f..11b011d4 100644
--- a/WWW/Library/Implementation/SGML.h
+++ b/WWW/Library/Implementation/SGML.h
@@ -250,21 +250,9 @@ Find a Tag by Name
    Returns a pointer to the tag within the DTD.
 
  */
-extern HTTag * SGMLFindUprTag PARAMS((
-	CONST SGML_dtd *	dtd,
-	CONST char *		string));
-
-
-/*
-
-Find a Tag by Name
-
-   Returns a pointer to the tag within the DTD.
-
- */
 extern HTTag * SGMLFindTag PARAMS((
 	CONST SGML_dtd *	dtd,
-	char *			string));
+	CONST char *		string));
 
 
 /*
diff --git a/WWW/Library/Implementation/makefile.in b/WWW/Library/Implementation/makefile.in
index 26b11751..a2cc7424 100644
--- a/WWW/Library/Implementation/makefile.in
+++ b/WWW/Library/Implementation/makefile.in
@@ -173,7 +173,7 @@ $(LOB)/libwww.a : $(COMMON)
 #	Clean up everything generatable except final products
 clean :
 	rm -f core *.core *.leaks *.[oi] *.bak tags TAGS
-	rm $(LOB)/*$(_O)
+	rm -f $(LOB)/*$(_O)
 
 #			Common code
 #			-----------