about summary refs log tree commit diff stats
path: root/WWW
diff options
context:
space:
mode:
authorThomas E. Dickey <dickey@invisible-island.net>1997-11-24 19:17:20 -0500
committerThomas E. Dickey <dickey@invisible-island.net>1997-11-24 19:17:20 -0500
commit97d3287af85e3890f03d2a48474de0d1a431b676 (patch)
tree7db3a7cebf5a3ddce7154e927a2f1d8f3a17fa8c /WWW
parente47cfd5646f55de9688ff42df3055fd9c09b503f (diff)
downloadlynx-snapshots-97d3287af85e3890f03d2a48474de0d1a431b676.tar.gz
snapshot of project "lynx", label v2-7-1ac_0-97
Diffstat (limited to 'WWW')
-rw-r--r--WWW/Library/Implementation/HTAABrow.c24
-rw-r--r--WWW/Library/Implementation/HTAABrow.h15
-rw-r--r--WWW/Library/Implementation/HTAccess.c25
-rw-r--r--WWW/Library/Implementation/HTFTP.c111
-rw-r--r--WWW/Library/Implementation/HTFTP.h5
-rw-r--r--WWW/Library/Implementation/HTFile.c11
-rw-r--r--WWW/Library/Implementation/HTNews.c65
-rw-r--r--WWW/Library/Implementation/HTNews.h5
-rw-r--r--WWW/Library/Implementation/HTParse.c88
-rw-r--r--WWW/Library/Implementation/HTPlain.c61
-rw-r--r--WWW/Library/Implementation/HTTCP.c22
-rw-r--r--WWW/Library/Implementation/HTTP.c3
-rw-r--r--WWW/Library/Implementation/HTUtils.h1
-rw-r--r--WWW/Library/Implementation/SGML.c219
14 files changed, 506 insertions, 149 deletions
diff --git a/WWW/Library/Implementation/HTAABrow.c b/WWW/Library/Implementation/HTAABrow.c
index aa8a19fd..2b50ed38 100644
--- a/WWW/Library/Implementation/HTAABrow.c
+++ b/WWW/Library/Implementation/HTAABrow.c
@@ -1283,3 +1283,27 @@ PUBLIC BOOL HTAA_shouldRetryWithAuth ARGS5(
     /* Never reached */
 }
 
+/*
+**  This function clears all authorization information by
+**  invoking the free_HTAAGlobals() function, which normally
+**  is invoked at exit.  It allows a browser command to do
+**  this at any time, for example, if the user is leaving
+**  the terminal for a period of time, but does not want
+**  to end the current session.  - FM
+*/
+PUBLIC void HTClearHTTPAuthInfo NOARGS
+{
+    /*
+    **  Need code to check cached documents against the
+    **  protention templates, and do something to ensure
+    **  that any protected documents no longer can be
+    **  accessed without a new retrieval. - FM
+    */
+
+    /*
+    **  Now free all of the authorization info, and
+    **  reset the free_HTAAGlobalsSet flag. - FM
+    */
+    free_HTAAGlobals();
+    free_HTAAGlobalsSet = FALSE;
+}
diff --git a/WWW/Library/Implementation/HTAABrow.h b/WWW/Library/Implementation/HTAABrow.h
index 2674ae6b..80da3e6e 100644
--- a/WWW/Library/Implementation/HTAABrow.h
+++ b/WWW/Library/Implementation/HTAABrow.h
@@ -78,7 +78,7 @@ Routines for Browser Side Recording of AA Info
 **
 **              As usual, this string is automatically freed.
 */
-PUBLIC char *HTAA_composeAuth PARAMS((
+extern char *HTAA_composeAuth PARAMS((
 	CONST char *	hostname,
 	CONST int	portnumber,
 	CONST char *	docname,
@@ -112,12 +112,19 @@ PUBLIC char *HTAA_composeAuth PARAMS((
 **                                field (in function HTAA_composeAuth()).
 **                      NO, otherwise.
 */
-PUBLIC BOOL HTAA_shouldRetryWithAuth PARAMS((
+extern BOOL HTAA_shouldRetryWithAuth PARAMS((
 	char *		start_of_headers,
 	int		length,
 	void *		handle,
 	int		soc,
 	BOOL		IsProxy));
+
+/*
+**  Function to allow clearing of all Authorization info
+**  via a browser command. - FM
+*/
+extern void HTClearHTTPAuthInfo NOPARAMS;
+
 /*
 
 Enabling Gateway httpds to Forward Authorization
@@ -129,10 +136,10 @@ Enabling Gateway httpds to Forward Authorization
    
  */
 
-PUBLIC void HTAAForwardAuth_set PARAMS((
+extern void HTAAForwardAuth_set PARAMS((
 	CONST char *	scheme_name,
 	CONST char *	scheme_specifics));
-PUBLIC void HTAAForwardAuth_reset NOPARAMS;
+extern void HTAAForwardAuth_reset NOPARAMS;
 /*
 
  */
diff --git a/WWW/Library/Implementation/HTAccess.c b/WWW/Library/Implementation/HTAccess.c
index 879b34c9..7a4f62ea 100644
--- a/WWW/Library/Implementation/HTAccess.c
+++ b/WWW/Library/Implementation/HTAccess.c
@@ -431,7 +431,7 @@ PRIVATE int get_physical ARGS2(
 	/*
 	**  Search for gateways.
 	*/
-	gateway_parameter = (char *)malloc(strlen(access) + 20);
+	gateway_parameter = (char *)calloc(1, (strlen(access) + 20));
 	if (gateway_parameter == NULL)
 	    outofmem(__FILE__, "HTLoad");
 	strcpy(gateway_parameter, "WWW_");
@@ -687,12 +687,15 @@ PRIVATE BOOL HTLoadDocument ARGS4(
     /*
     **  Make sure some yoyo doesn't send us 'round in circles
     **  with redirecting URLs that point back to themselves.
-    **  We'll set the HTTP/1.1 limit of 5 redirections per
-    **  requested URL from a user.  - FM
+    **  We'll set the original Lynx limit of 10 redirections
+    **  per requested URL from a user, because the HTTP/1.1
+    **  will no longer specify a restriction to 5, but will
+    **  leave it up to the browser's discretion, in deference
+    **  to MicroSoft.  - FM
     */
-    if (redirection_attempts > 5) {
+    if (redirection_attempts > 10) {
         redirection_attempts = 0;
-	HTAlert("Redirection limit of 5 URL's reached.");
+	HTAlert("Redirection limit of 10 URLs reached.");
         return NO;
     }
 
@@ -737,8 +740,8 @@ PRIVATE BOOL HTLoadDocument ARGS4(
 	    /*
 	    **  Don't exceed the redirection_attempts limit. - FM
 	    */
-	    if (++redirection_attempts > 5) {
-		HTAlert("Redirection limit of 5 URL's reached.");
+	    if (++redirection_attempts > 10) {
+		HTAlert("Redirection limit of 10 URLs reached.");
 		redirection_attempts = 0;
 		FREE(use_this_url_instead);
  		return NO;
@@ -1190,7 +1193,7 @@ PUBLIC BOOL HTSearch ARGS2(
     CONST char * p, *s, *e;		/* Pointers into keywords */
     char * address = NULL;
     BOOL result;
-    char * escaped = malloc((strlen(keywords)*3) + 1);
+    char * escaped = (char *)calloc(1, ((strlen(keywords)*3) + 1));
     static CONST BOOL isAcceptable[96] =
 
     /*   0 1 2 3 4 5 6 7 8 9 A B C D E F */
@@ -1309,7 +1312,7 @@ PUBLIC HTParentAnchor * HTHomeAnchor NOARGS
     	FILE * fp = fopen(REMOTE_POINTER, "r");
 	char * status;
 	if (fp) {
-	    my_home_document = (char*)malloc(MAX_FILE_NAME);
+	    my_home_document = (char*)calloc(1, MAX_FILE_NAME);
 	    if (my_home_document == NULL)
 	        outofmem(__FILE__, "HTHomeAnchor");
 	    status = fgets(my_home_document, MAX_FILE_NAME, fp);
@@ -1327,8 +1330,8 @@ PUBLIC HTParentAnchor * HTHomeAnchor NOARGS
 	FILE * fp = NULL;
 	CONST char * home =  (CONST char*)getenv("HOME");
 	if (home != null) { 
-	    my_home_document = (char *)malloc(
-		strlen(home) + 1 + strlen(PERSONAL_DEFAULT) + 1);
+	    my_home_document = (char *)calloc(1,
+		(strlen(home) + 1 + strlen(PERSONAL_DEFAULT) + 1));
 	    if (my_home_document == NULL)
 	        outofmem(__FILE__, "HTAnchorHome");
 	    sprintf(my_home_document, "%s/%s", home, PERSONAL_DEFAULT);
diff --git a/WWW/Library/Implementation/HTFTP.c b/WWW/Library/Implementation/HTFTP.c
index 701490e9..615ddcee 100644
--- a/WWW/Library/Implementation/HTFTP.c
+++ b/WWW/Library/Implementation/HTFTP.c
@@ -160,10 +160,12 @@ extern char *personal_mail_address;
 /*	Module-Wide Variables
 **	---------------------
 */
-PRIVATE connection * connections = 0;	/* Linked list of connections */
-PRIVATE char response_text[LINE_LENGTH+1];/* Last response from NewsHost */
-PRIVATE connection * control = NULL;		/* Current connection */
+PRIVATE connection * connections = NULL;/* Linked list of connections */
+PRIVATE char response_text[LINE_LENGTH+1];/* Last response from ftp host */
+PRIVATE connection * control = NULL;	/* Current connection */
 PRIVATE int data_soc = -1;		/* Socket for data transfer =invalid */
+PRIVATE char *user_entered_password = NULL;
+PRIVATE char *last_username_and_host = NULL;
 
 #define GENERIC_SERVER	   0
 #define MACHTEN_SERVER 	   1
@@ -207,8 +209,29 @@ PRIVATE char data_buffer[DATA_BUFFER_SIZE];		/* Input data buffer */
 PRIVATE char * data_read_pointer;
 PRIVATE char * data_write_pointer;
 #define NEXT_DATA_CHAR next_data_char()
+PRIVATE int close_connection PARAMS((
+	connection *	con));
 
 
+PRIVATE void cleanup_ftp NOARGS
+{
+    if (control) {
+	if (control->socket != -1)
+	    close_connection(control);
+	FREE(control);
+    }
+}
+
+/*
+**  This function frees module globals. - FM
+*/
+PRIVATE void free_FTPGlobals NOARGS
+{
+    FREE(user_entered_password);
+    FREE(last_username_and_host);
+    cleanup_ftp();
+}
+
 /* PUBLIC						HTMake_VMS_name()
 **		CONVERTS WWW name into a VMS name
 ** ON ENTRY:
@@ -342,15 +365,6 @@ PRIVATE int close_connection ARGS1(
     return -1;		/* very strange -- was not on list. */
 }
 
-PRIVATE void cleanup_ftp NOARGS
-{
-    if (control) {
-	if (control->socket != -1)
-	    close_connection(control);
-	FREE(control);
-    }
-}
-
 PRIVATE char *help_message_buffer = NULL;  /* global :( */
 
 PRIVATE void init_help_message_cache NOARGS
@@ -617,18 +631,24 @@ PRIVATE int get_connection ARGS2(
     int status;
     char * command;
     connection * con;
-    char * username=NULL;
-    char * password=NULL;
-    static char *user_entered_password=NULL;
-    static char *last_username_and_host=NULL;
+    char * username = NULL;
+    char * password = NULL;
     static BOOLEAN firstuse = TRUE;
 
     if (!arg) return -1;		/* Bad if no name sepcified	*/
     if (!*arg) return -1;		/* Bad if name had zero length	*/
 
+    if (firstuse) {
+	/*
+	**  Set up freeing at exit. - FM
+	*/
+	atexit(free_FTPGlobals);
+	firstuse = FALSE;
+    }
+
     if (control) {
 	/*
-	**  Reuse this object - kw
+	**  Reuse this object - KW
 	*/
 	if (control->socket != -1)
 	    NETCLOSE(control->socket);
@@ -640,10 +660,6 @@ PRIVATE int get_connection ARGS2(
 	con = (connection *)calloc(1, sizeof(connection));
 	if (con == NULL)
 	    outofmem(__FILE__, "get_connection");
-	if (firstuse) {
-	    atexit(cleanup_ftp);
-	    firstuse = FALSE;
-	}
     }
     con->socket = -1;
 
@@ -666,18 +682,20 @@ PRIVATE int get_connection ARGS2(
 	    if (*username)
 	        HTUnEscape(username);
 
-	    /* if the password doesn't exist then we are going to have
-	     * to ask the user for it.  The only problem is that we
-	     * don't want to ask for it every time, so we will store
-	     * away in a primitive fashion.
+	    /*
+	     *  If the password doesn't exist then we are going to have
+	     *  to ask the user for it.  The only problem is that we
+	     *  don't want to ask for it every time, so we will store
+	     *  away in a primitive fashion.
 	     */
 	    if (!password) {
 		char tmp[256];
 
 		sprintf(tmp, "%s@%s", username, p1);
-		/* if the user@host is not equal to the last time through
-		 * or user_entered_password has no data then we need
-		 * to ask the user for the password
+		/*
+		 *  If the user@host is not equal to the last time through
+		 *  or user_entered_password has no data then we need
+		 *  to ask the user for the password.
 		 */
 		if (!last_username_and_host ||
 		    strcmp(tmp, last_username_and_host) ||
@@ -732,9 +750,10 @@ PRIVATE int get_connection ARGS2(
       return status;                    /* Bad return */
     }
 
-    if (TRACE) 
+    if (TRACE) {
  	fprintf(stderr, "FTP connected, socket %d  control %ld\n",
 			con->socket, (long)con);
+    }
     control = con;		/* Current control connection */
 
     /* Initialise buffering for control connection */
@@ -2001,8 +2020,10 @@ PRIVATE EntryInfo * parse_dir_entry ARGS2(
             len = strlen(entry);
 	    if (*first) {
 		if (!strcmp(entry, "can not access directory .")) {
-		    /* don't reset *first, nothing real will follow - kw */
-		    entry_info->display=FALSE;
+		    /*
+		     *  Don't reset *first, nothing real will follow. - KW
+		     */
+		    entry_info->display = FALSE;
 		    return(entry_info);
 		}
 	        *first = FALSE;
@@ -2527,10 +2548,10 @@ AgainForMultiNet:
 
 	    entry_info = parse_dir_entry(chunk->data, &first);
 	    if (entry_info->display) {
-		 if (TRACE)
-		     fprintf(stderr, "Adding file to BTree: %s\n",
-		     		     entry_info->filename);
-	         HTBTree_add(bt, (EntryInfo *)entry_info);
+		if (TRACE)
+		    fprintf(stderr, "Adding file to BTree: %s\n",
+		     		    entry_info->filename);
+	        HTBTree_add(bt, (EntryInfo *)entry_info);
 	    } else {
 		FREE(entry_info);
 	    }
@@ -3367,3 +3388,23 @@ listen:
 	return HT_LOADED;
     }       
 } /* open_file_read */
+
+/*
+**  This function frees any user entered password, so that
+**  it must be entered again for a future request. - FM
+*/
+PUBLIC void HTClearFTPPassword NOARGS
+{
+    /*
+    **  Need code to check cached documents from
+    **  non-anonymous ftp accounts and do something
+    **  to ensure that they no longer can be accessed
+    **  without a new retrieval. - FM
+    */
+
+    /*
+    **  Now free the current user entered password,
+    **  if any. - FM
+    */
+    FREE(user_entered_password);
+}
diff --git a/WWW/Library/Implementation/HTFTP.h b/WWW/Library/Implementation/HTFTP.h
index 9fc4bf20..814772d4 100644
--- a/WWW/Library/Implementation/HTFTP.h
+++ b/WWW/Library/Implementation/HTFTP.h
@@ -57,6 +57,11 @@ extern int HTFTPLoad PARAMS
   HTStream*             sink
 ));
 
+/*
+**  This function frees any user entered password, so that
+**  it must be entered again for a future request. - FM
+*/
+extern void HTClearFTPPassword NOPARAMS;
 
 /*
 
diff --git a/WWW/Library/Implementation/HTFile.c b/WWW/Library/Implementation/HTFile.c
index 6ef0fde1..ac0d2874 100644
--- a/WWW/Library/Implementation/HTFile.c
+++ b/WWW/Library/Implementation/HTFile.c
@@ -1124,6 +1124,15 @@ PUBLIC float HTFileValue ARGS1(
 **	1.	No code for non-unix systems.
 **	2.	Isn't there a quicker way?
 */
+
+#if defined(HAVE_CONFIG_H)
+
+#ifndef HAVE_GETGROUPS
+#define NO_GROUPS
+#endif
+
+#else
+
 #ifdef VMS
 #define NO_GROUPS
 #endif /* VMS */
@@ -1137,6 +1146,8 @@ PUBLIC float HTFileValue ARGS1(
 #define NO_GROUPS
 #endif /* PCNFS */
 
+#endif	/* HAVE_CONFIG_H */
+
 PUBLIC BOOL HTEditable ARGS1(
 	CONST char *,	filename)
 {
diff --git a/WWW/Library/Implementation/HTNews.c b/WWW/Library/Implementation/HTNews.c
index bb3481d9..ff488f1f 100644
--- a/WWW/Library/Implementation/HTNews.c
+++ b/WWW/Library/Implementation/HTNews.c
@@ -953,15 +953,15 @@ PRIVATE int read_article NOARGS
 {
     char line[LINE_LENGTH+1];
     char *full_line = NULL;
-    char *subject=NULL;				/* Subject string	    */
-    char *from=NULL;				/* From string		    */
-    char *replyto=NULL;				/* Reply-to string	    */
-    char *date=NULL;				/* Date string		    */
-    char *organization=NULL;			/* Organization string	    */
-    char *references=NULL;			/* Hrefs for other articles */
-    char *newsgroups=NULL;			/* Newsgroups list	    */
-    char *followupto=NULL;			/* Followup list	    */
-    char *href=NULL;
+    char *subject = NULL;			/* Subject string	    */
+    char *from = NULL;				/* From string		    */
+    char *replyto = NULL;			/* Reply-to string	    */
+    char *date = NULL;				/* Date string		    */
+    char *organization = NULL;			/* Organization string	    */
+    char *references = NULL;			/* Hrefs for other articles */
+    char *newsgroups = NULL;			/* Newsgroups list	    */
+    char *followupto = NULL;			/* Followup list	    */
+    char *href = NULL;
     char *p = line;
     BOOL done = NO;
 
@@ -1009,8 +1009,11 @@ PRIVATE int read_article NOARGS
 		    StrAllocCopy(full_line, line);
 		}
 
-		if (full_line[0] == '.') {	
-		    if ((unsigned char)full_line[1] < ' ') {		/* End of article? */
+		if (full_line[0] == '.') {
+		    /*
+		    **  End of article?
+		    */
+		    if ((unsigned char)full_line[1] < ' ') {
 			done = YES;
 			break;
 		    }
@@ -1273,7 +1276,10 @@ PRIVATE int read_article NOARGS
 	    if (TRACE)
 	        fprintf(stderr, "B %s", line);
 	    if (line[0] == '.') {
-		if ((unsigned char)line[1] < ' ') {		/* End of article? */
+		/*
+		**  End of article?
+		*/
+		if ((unsigned char)line[1] < ' ') {
 		    done = YES;
 		    break;
 		} else {			/* Line starts with dot */
@@ -1506,7 +1512,7 @@ PRIVATE int read_list ARGS1(char *, arg)
 	    *p++ = ch;
 	}
 	if (ch == LF) {
-	    skip_rest_of_line = NO; /* done, reset flag */
+	    skip_rest_of_line = NO;	/* done, reset flag */
 	    *p = '\0';			/* Terminate the string */
 	    if (TRACE)
 	        fprintf(stderr, "B %s", line);
@@ -1709,7 +1715,10 @@ PRIVATE int read_group ARGS3(
 		    if (TRACE)
 		        fprintf(stderr, "X %s", line);
 		    if (line[0] == '.') {
-			if (line[1] < ' ') {	/* End of response? */
+			/*
+			**  End of response?
+			*/
+			if ((unsigned char)line[1] < ' ') {
 			    done = YES;
 			    break;
 			} else {		/* Line starts with dot */
@@ -1817,7 +1826,10 @@ PRIVATE int read_group ARGS3(
 			switch(line[0]) {
 
 			case '.':
-			    done = ((unsigned char)line[1] < ' ');  /* End of response? */
+			    /*
+			    **  End of response?
+			    */
+			    done = ((unsigned char)line[1] < ' ');
 			    break;
 
 			case 'S':
@@ -2778,6 +2790,29 @@ Send_NNTP_command:
     return HT_NOT_LOADED;
 }
 
+/*
+**  This function clears all authorization information by
+**  invoking the free_HTAAGlobals() function, which normally
+**  is invoked at exit.  It allows a browser command to do
+**  this at any time, for example, if the user is leaving
+**  the terminal for a period of time, but does not want
+**  to end the current session.  - FM
+*/
+PUBLIC void HTClearNNTPAuthInfo NOARGS
+{
+    /*
+    **  Need code to check cached documents and do
+    **  something to ensure that any protected
+    **  documents no longer can be accessed without
+    **  a new retrieval. - FM
+    */
+
+    /*
+    **  Now free all of the authorization info. - FM
+    */
+    free_NNTP_AuthInfo();
+}
+
 #ifdef GLOBALDEF_IS_MACRO
 #define _HTNEWS_C_1_INIT { "news", HTLoadNews, NULL }
 GLOBALDEF (HTProtocol,HTNews,_HTNEWS_C_1_INIT);
diff --git a/WWW/Library/Implementation/HTNews.h b/WWW/Library/Implementation/HTNews.h
index bffaeb1b..bc25fc87 100644
--- a/WWW/Library/Implementation/HTNews.h
+++ b/WWW/Library/Implementation/HTNews.h
@@ -31,10 +31,13 @@ GLOBALREF HTProtocol HTSNewsPost;
 GLOBALREF HTProtocol HTSNewsReply;
 #endif /* GLOBALREF_IS_MACRO */
 
-extern void HTSetNewsHost PARAMS((CONST char *value));
+extern void HTSetNewsHost PARAMS((
+	CONST char *	value));
 extern CONST char * HTGetNewsHost NOPARAMS;
 extern char * HTNewsHost;
 
+extern void HTClearNNTPAuthInfo NOPARAMS;
+
 #endif /* HTNEWS_H */
 
 
diff --git a/WWW/Library/Implementation/HTParse.c b/WWW/Library/Implementation/HTParse.c
index ab5149b0..129af946 100644
--- a/WWW/Library/Implementation/HTParse.c
+++ b/WWW/Library/Implementation/HTParse.c
@@ -174,7 +174,7 @@ PRIVATE void scan ARGS2(
 **      wanted          A mask for the bits which are wanted.
 **
 ** On exit,
-**	returns		A pointer to a malloc'd string which MUST BE FREED
+**	returns		A pointer to a calloc'd string which MUST BE FREED
 */
 PUBLIC char * HTParse ARGS3(
 	CONST char *,	aName,
@@ -198,10 +198,10 @@ PUBLIC char * HTParse ARGS3(
     **  Allocate the output string.
     */
     len = strlen(aName) + strlen(relatedName) + 10;
-    result = (char *)malloc(len);	/* Lots of space: more than enough */
-    if (result == NULL)
+    result = (char *)calloc(1, len);	/* Lots of space: more than enough */
+    if (result == NULL) {
         outofmem(__FILE__, "HTParse");
-    result[0] = '\0';		/* Clear string  */
+    }
 
     /*
     **  Make working copies of the input strings to cut up.
@@ -449,8 +449,30 @@ PUBLIC void HTSimplify ARGS1(
     if (filename == NULL)
 	return;
 
-    if ((filename[0] && filename[1]) && strchr(filename, '/') != NULL) {
+    if (!(filename[0] && filename[1]) ||
+	filename[0] == '?' || filename[1] == '?' || filename[2] == '?')
+	return;
+
+    if (strchr(filename, '/') != NULL) {
         for (p = (filename + 2); *p; p++) {
+	    if (*p == '?') {
+	        /*
+		**  We're still treating a ?searchpart as part of
+		**  the path in HTParse() and scan(), but if we
+		**  encounter a '?' here, assume it's the delimiter
+		**  and break.  We also could check for a parameter
+		**  delimiter (';') here, but the current Fielding
+		**  draft (wisely or ill-advisedly :) says that it
+		**  should be ignored and collapsing be allowed in
+		**  it's value).  The only defined parameter at
+		**  present is ;type=[A, I, or D] for ftp URLs, so
+		**  if there's a "/..", "/../", "/./", or terminal
+		**  '.' following the ';', it must be due to the
+		**  ';' being an unescaped path character and not
+		**  actually a parameter delimiter. - FM
+		*/
+		break;
+	    }
 	    if (*p == '/') {
 		if ((p[1] == '.') && (p[2] == '.') &&
 		    (p[3] == '/' || p[3] == '\0')) {
@@ -489,7 +511,7 @@ PUBLIC void HTSimplify ARGS1(
 		    }
 		} else if (p[1] == '.' && p[2] == '/') {
 		    /*
-		    **  Handle "./" by removing the characters.
+		    **  Handle "/." by removing the characters.
 		    */
 		    q = p;
 		    q1 = (p + 2);
@@ -505,6 +527,48 @@ PUBLIC void HTSimplify ARGS1(
 		}
 	    }
 	}
+	if (p >= filename + 2 && *p == '?' && *(p-1)  == '.') {
+	    if (*(p-2) == '/') {
+		/*
+		**  Handle "/.?" by removing the dot.
+		*/
+		q = p - 1;
+		q1 = p;
+		while (*q1 != '\0')
+		    *q++ = *q1++;
+		*q = '\0';
+	    } else if (*(p-2) == '.' &&
+		       p >= filename + 4 && *(p-3) == '/' &&
+		       (*(p-4) != '/' ||
+			(p > filename + 4 && *(p-5) != ':'))) {
+		    /*
+		    **  Handle "xxx/..?"
+		    */
+		for (q = (p - 4); (q > filename) && (*q != '/'); q--)
+			/*
+			**  Back up to previous slash or beginning of string.
+			*/
+		    ;
+		if (*q == '/') {
+		    if (q > filename && *(q-1) == '/' &&
+			!(q > filename + 1 && *(q-1) != ':'))
+			return;
+		    q++;
+		}
+		if (strncmp(q, "../", 3) && strncmp(q, "./", 2)) {
+			/*
+			**  Not after "//" at beginning of string or
+			**  after "://", and xxx is not ".." or ".",
+			**  so remove the "xxx/..".
+			*/
+		    q1 = p;
+		    p = q;
+		    while (*q1 != '\0')
+			*p++ = *q1++;
+		    *p = '\0';		/* terminate */
+		}
+	    }
+	}
     }
 }
 
@@ -563,7 +627,7 @@ PUBLIC char * HTRelative ARGS2(
         for (; *q && (*q != '#'); q++)
 	    if (*q == '/')
 	        levels++;
-	result = (char *)malloc(3*levels + strlen(last_slash) + 1);
+	result = (char *)calloc(1, (3*levels + strlen(last_slash) + 1));
         if (result == NULL)
 	    outofmem(__FILE__, "HTRelative");
 	result[0] = '\0';
@@ -585,7 +649,7 @@ PUBLIC char * HTRelative ARGS2(
 **	It returns a string which has these characters
 **	represented by a '%' character followed by two hex digits.
 **
-**	Unlike HTUnEscape(), this routine returns a malloced string.
+**	Unlike HTUnEscape(), this routine returns a calloced string.
 */
 PRIVATE CONST unsigned char isAcceptable[96] =
 
@@ -615,7 +679,7 @@ PUBLIC char * HTEscape ARGS2(
     for (p = str; *p; p++)
         if (!ACCEPTABLE((unsigned char)TOASCII(*p)))
 	    unacceptable++;
-    result = (char *) malloc(p-str + unacceptable+ unacceptable + 1);
+    result = (char *)calloc(1, (p-str + unacceptable + unacceptable + 1));
     if (result == NULL)
         outofmem(__FILE__, "HTEscape");
     for (q = result, p = str; *p; p++) {
@@ -640,7 +704,7 @@ PUBLIC char * HTEscape ARGS2(
 **	represented by a '%' character followed by two hex digits,
 **	except that spaces are converted to '+' instead of %2B.
 **
-**	Unlike HTUnEscape(), this routine returns a malloced string.
+**	Unlike HTUnEscape(), this routine returns a calloced string.
 */
 PUBLIC char * HTEscapeSP ARGS2(
 	CONST char *,	str,
@@ -653,7 +717,7 @@ PUBLIC char * HTEscapeSP ARGS2(
     for (p = str; *p; p++)
         if (!(*p == ' ' || ACCEPTABLE((unsigned char)TOASCII(*p))))
 	    unacceptable++;
-    result = (char *) malloc(p-str + unacceptable+ unacceptable + 1);
+    result = (char *)calloc(1, (p-str + unacceptable + unacceptable + 1));
     if (result == NULL)
         outofmem(__FILE__, "HTEscape");
     for (q = result, p = str; *p; p++) {
@@ -800,7 +864,7 @@ PUBLIC void HTMake822Word ARGS1(
     }
     if (!added)
 	return;
-    result = (char *) malloc(p-(*str) + added + 1);
+    result = (char *)calloc(1, (p-(*str) + added + 1));
     if (result == NULL)
         outofmem(__FILE__, "HTMake822Word");
     result[0] = '"';
diff --git a/WWW/Library/Implementation/HTPlain.c b/WWW/Library/Implementation/HTPlain.c
index 277a6ebf..824ac642 100644
--- a/WWW/Library/Implementation/HTPlain.c
+++ b/WWW/Library/Implementation/HTPlain.c
@@ -390,22 +390,6 @@ PRIVATE void HTPlain_write ARGS3(HTStream *, me, CONST char*, s, int, l)
 	*/
 	} else if (code == 8211 || code == 8212) {
 	    HText_appendCharacter(me->text, '-');
-	/*
-	**  Ignore 8204 (zwnj) or 8205 (zwj), for now. - FM
-	*/
-	} else if (code == 8204 || code == 8205) {
-	    if (TRACE) {
-		fprintf(stderr,
-			"HTPlain_write: Ignoring '%ld'.\n", code);
-	    }
-	/*
-	**  Ignore 8206 (lrm) or 8207 (rlm), for now. - FM
-	*/
-	} else if (code == 8206 || code == 8207) {
-	    if (TRACE) {
-		fprintf(stderr,
-			"HTPlain_write: Ignoring '%ld'.\n", code);
-	    }
 #endif /* NOTUSED_FOTEMODS */
 
 /******************************************************************
@@ -460,6 +444,51 @@ PRIVATE void HTPlain_write ARGS3(HTStream *, me, CONST char*, s, int, l)
 	    **  (somewhat) readable ASCII.
 	    */
 	    HText_appendCharacter(me->text, (char)(*p & 0x7f));
+#ifdef NOTUSED_FOTEMODS
+	    /*
+	    **  If we do not have the "7-bit approximations" as our
+	    **  output character set (in which case we did it already)
+	    **  seek a translation for that.  Otherwise, or if the
+	    **  translation fails, use UHHH notation. - FM
+	    */
+	} else if (chk &&
+		   (chk = (!HTPassEightBitRaw &&
+			   (me->htext_char_set !=
+			    UCGetLYhndl_byMIME("us-ascii")))) &&
+		   (uck = UCTransUniChar(code,
+					 UCGetLYhndl_byMIME("us-ascii")))
+				      >= 32 && uck < 127) {
+		/*
+		**  Got an ASCII character (yippey). - FM
+		*/
+	    c = ((char)(uck & 0xff));
+	    HText_appendCharacter(me->text, c);
+	} else if ((chk && uck == -4) &&
+		       (uck = UCTransUniCharStr(replace_buf,
+						60, code,
+						UCGetLYhndl_byMIME("us-ascii"),
+						0) >= 0)) {
+		/*
+		**  Got a repacement string (yippey). - FM
+		*/
+	    HText_appendText(me->text, replace_buf);
+	} else if (code == 8204 || code == 8205) {
+	    /*
+	    **  Ignore 8204 (zwnj) or 8205 (zwj), if we get to here. - FM
+	    */
+	    if (TRACE) {
+		fprintf(stderr,
+			"HTPlain_write: Ignoring '%ld'.\n", code);
+	    }
+	} else if (code == 8206 || code == 8207) {
+	    /*
+	    **  Ignore 8206 (lrm) or 8207 (rlm), if we get to here. - FM
+	    */
+	    if (TRACE) {
+		fprintf(stderr,
+			"HTPlain_write: Ignoring '%ld'.\n", code);
+	    }
+#endif /* NOTUSED_FOTEMODS */
 	} else if (me->T.trans_from_uni && code > 255) {
 	    if (PASSHI8BIT && PASSHICTRL && LYRawMode &&
 		(unsigned char)*p >= LYlowest_eightbit[me->htext_char_set]) {
diff --git a/WWW/Library/Implementation/HTTCP.c b/WWW/Library/Implementation/HTTCP.c
index 572cd36b..cbc43984 100644
--- a/WWW/Library/Implementation/HTTCP.c
+++ b/WWW/Library/Implementation/HTTCP.c
@@ -346,15 +346,15 @@ PUBLIC int HTParseInet ARGS2(
         if (port[0] >= '0' && port[0] <= '9') {
 #ifdef unix
 	    sin->sin_port = htons(atol(port));
-#else /* VMS */
+#else /* VMS: */
 #ifdef DECNET
-	    sin->sdn_objnum = (unsigned char) (strtol(port, (char**)0 , 10));
+	    sin->sdn_objnum = (unsigned char)(strtol(port, (char**)0, 10));
 #else
-	    sin->sin_port = htons((unsigned short) strtol(port,(char**)0,10));
+	    sin->sin_port = htons((unsigned short)strtol(port,(char**)0,10));
 #endif /* Decnet */
 #endif /* Unix vs. VMS */
-	} else {
 #ifdef SUPPRESS		/* 1. crashes!?!.  2. Not recommended */
+	} else {
 	    struct servent * serv = getservbyname(port, (char*)0);
 	    if (serv) {
 		sin->sin_port = serv->s_port;
@@ -371,25 +371,27 @@ PUBLIC int HTParseInet ARGS2(
     **  it's probably worth waiting until the Phase transition from IV to V.
     */
     sin->sdn_nam.n_len = min(DN_MAXNAML, strlen(host));  /* <=6 in phase 4 */
-    strncpy (sin->sdn_nam.n_name, host, sin->sdn_nam.n_len + 1);
+    strncpy(sin->sdn_nam.n_name, host, sin->sdn_nam.n_len + 1);
     if (TRACE) {
         fprintf(stderr,  
 		"DECnet: Parsed address as object number %d on host %.6s...\n",
 		sin->sdn_objnum, host);
     }
-#else  /* parse Internet host */
+#else  /* parse Internet host: */
 
     if (*host >= '0' && *host <= '9') {   /* Test for numeric node address: */
 	char *strptr = host;
 	while (*strptr) {
-	    if (*strptr == '.')
+	    if (*strptr == '.') {
 		dotcount_ip++;
-	    else if (!isdigit(*strptr))
+	    } else if (!isdigit(*strptr)) {
 		break;
+	    }
 	    strptr++;
 	}
-	if (*strptr)		/* found non-numeric, assume domain name */
+	if (*strptr) {		/* found non-numeric, assume domain name */
 	    dotcount_ip = 0;
+	}
     }
 
     /*
@@ -733,7 +735,7 @@ PUBLIC int HTDoConnect ARGS4(
     }
     FREE(p1);
 
-    line = (char *)malloc(strlen(host) + strlen(protocol) + 128);
+    line = (char *)calloc(1, (strlen(host) + strlen(protocol) + 128));
     if (line == NULL)
 	outofmem(__FILE__, "HTDoConnect");
     sprintf (line, "Looking up %s.", host);
diff --git a/WWW/Library/Implementation/HTTP.c b/WWW/Library/Implementation/HTTP.c
index 595f39bd..fc279af6 100644
--- a/WWW/Library/Implementation/HTTP.c
+++ b/WWW/Library/Implementation/HTTP.c
@@ -690,7 +690,8 @@ try_again:
                 if (TRACE)
                     fprintf (stderr, "HTTP: Interrupted initial read.\n");
                 _HTProgress ("Connection interrupted.");
-                status = HT_INTERRUPTED;
+                HTTP_NETCLOSE(s, handle);
+		status = HT_NO_DATA;
                 goto clean_up;
             } else if  (status < 0 &&
 			(SOCKET_ERRNO == ENOTCONN ||
diff --git a/WWW/Library/Implementation/HTUtils.h b/WWW/Library/Implementation/HTUtils.h
index ec7265fb..458b8171 100644
--- a/WWW/Library/Implementation/HTUtils.h
+++ b/WWW/Library/Implementation/HTUtils.h
@@ -16,6 +16,7 @@
 
 #ifdef HAVE_CONFIG_H
 #include <lynx_cfg.h>	/* generated by autoconf 'configure' script */
+#include <sys/types.h>
 #else
 
 /* Explicit system-configure */
diff --git a/WWW/Library/Implementation/SGML.c b/WWW/Library/Implementation/SGML.c
index 4af1fab9..b38a7dad 100644
--- a/WWW/Library/Implementation/SGML.c
+++ b/WWW/Library/Implementation/SGML.c
@@ -44,7 +44,8 @@ PUBLIC BOOL HTPassEightBitNum = FALSE;	/* Pass ^ numeric entities raw.	*/
 PUBLIC BOOL HTPassHighCtrlRaw = FALSE;	/* Pass 127-160,173,&#127; raw.	*/
 PUBLIC BOOL HTPassHighCtrlNum = FALSE;	/* Pass &#128;-&#159; raw.	*/
 
-extern UCode_t HTMLGetEntityUCValue PARAMS((CONST char *name));
+extern UCode_t HTMLGetEntityUCValue PARAMS((
+	CONST char *	name));
 extern int LYlowest_eightbit[];
 
 /*	The State (context) of the parser
@@ -323,23 +324,6 @@ PRIVATE BOOL put_special_unicodes ARGS2(
 	**  Use ASCII hyphen for ndash/endash or mdash/emdash.
 	*/
 	PUTC('-');
-#ifdef NOTUSED_FOTEMODS
-    } else if (code == 8204 || code == 8205) {
-	/*
-	**  Ignore zwnj or zwj, for now.  Note that zwnj may have
-	**  been handled as <WBR> by the calling function. - FM
-	*/
-	if (TRACE) {
-	    fprintf(stderr, "put_special_unicodes: Ignoring '%ld'.\n", code);
-	}
-    } else if (code == 8206 || code == 8207) {
-	/*
-	**  Ignore lrm or rlm, for now.
-	*/
-	if (TRACE) {
-	    fprintf(stderr, "put_special_unicodes: Ignoring '%ld'.\n", code);
-	}
-#endif /* NOTUSED_FOTEMODS */
     } else {
 	/*
 	**  Return NO if nothing done.
@@ -422,32 +406,6 @@ PRIVATE void handle_entity ARGS2(
 	FoundEntity = TRUE;
 	return;
     }
-
-    /*
-    **  Ignore zwnj (8204) and zwj (8205), for now.
-    **  Note that zwnj may have been handled as <WBR>
-    **  by the calling function. - FM
-    */
-    if (!strcmp(s, "zwnj") ||
-	!strcmp(s, "zwnj")) {
-	if (TRACE) {
-	    fprintf(stderr, "handle_entity: Ignoring '%s'.\n", s);
-	}
-	FoundEntity = TRUE;
-	return;
-    }
-
-    /*
-    **  Ignore lrm (8206), and rln (8207), for now. - FM
-    */
-    if (!strcmp(s, "lrm") ||
-	!strcmp(s, "rlm")) {
-	if (TRACE) {
-	    fprintf(stderr, "handle_entity: Ignoring '%s'.\n", s);
-	}
-	FoundEntity = TRUE;
-	return;
-    }
 #endif /* NOTUSED_FOTEMODS */
 
     /*
@@ -517,6 +475,33 @@ PRIVATE void handle_entity ARGS2(
 	    return;
 	}
     }
+#ifdef NOTUSED_FOTEMODS
+    /*
+    **  Ignore zwnj (8204) and zwj (8205), if we get to here.
+    **  Note that zwnj may have been handled as <WBR>
+    **  by the calling function. - FM
+    */
+    if (!strcmp(s, "zwnj") ||
+	!strcmp(s, "zwj")) {
+	if (TRACE) {
+	    fprintf(stderr, "handle_entity: Ignoring '%s'.\n", s);
+	}
+	FoundEntity = TRUE;
+	return;
+    }
+
+    /*
+    **  Ignore lrm (8206), and rlm (8207), if we get to here. - FM
+    */
+    if (!strcmp(s, "lrm") ||
+	!strcmp(s, "rlm")) {
+	if (TRACE) {
+	    fprintf(stderr, "handle_entity: Ignoring '%s'.\n", s);
+	}
+	FoundEntity = TRUE;
+	return;
+    }
+#endif /* NOTUSED_FOTEMODS */
 
     /*
     **  We haven't succeeded yet, so try the old LYCharSets
@@ -1770,6 +1755,133 @@ top1:
 	    HTChunkTerminate(string);
 	    if ((context->isHex ? sscanf(string->data, "%x", &value) :
 				  sscanf(string->data, "%d", &value)) == 1) {
+#ifdef NOTUSED_FOTEMODS
+		if ((code == 1) ||
+		    (code > 129 && code < 156)) {
+		    /*
+		    **  Assume these are MicroSoft code points,
+		    **  inflicted on us by FrontPage. - FM
+		    */
+		    switch (code) {
+			case 1:
+			    /*
+			    **  WHITE SMILING FACE
+			    */
+			    code = 0x263a;
+			    break;
+			case 130:
+			    /*
+			    **  SINGLE LOW-9 QUOTATION MARK (sbquo)
+			    */
+			    code = 0x201a;
+			    break;
+			case 132:
+			    /*
+			    **  DOUBLE LOW-9 QUOTATION MARK (bdquo)
+			    */
+			    code = 0x201e;
+			    break;
+			case 133:
+			    /*
+			    **  HORIZONTAL ELLIPSIS (hellip)
+			    */
+			    code = 0x2026;
+			    break;
+			case 134:
+			    /*
+			    **  DAGGER (dagger)
+			    */
+			    code = 0x2020;
+			    break;
+			case 135:
+			    /*
+			    **  DOUBLE DAGGER (Dagger)
+			    */
+			    code = 0x2021;
+			    break;
+			case 137:
+			    /*
+			    **  PER MILLE SIGN (permil)
+			    */
+			    code = 0x2030;
+			    break;
+			case 139:
+			    /*
+			    **  SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+			    **  (lsaquo)
+			    */
+			    code = 0x2039;
+			    break;
+			case 145:
+			    /*
+			    **  LEFT SINGLE QUOTATION MARK (lsquo)
+			    */
+			    code = 0x2018;
+			    break;
+			case 146:
+			    /*
+			    **  RIGHT SINGLE QUOTATION MARK (rsquo)
+			    */
+			    code = 0x2019;
+			    break;
+			case 147:
+			    /*
+			    **  LEFT DOUBLE QUOTATION MARK (ldquo)
+			    */
+			    code = 0x201c;
+			    break;
+			case 148:
+			    /*
+			    **  RIGHT DOUBLE QUOTATION MARK (rdquo)
+			    */
+			    code = 0x201d;
+			    break;
+			case 149:
+			    /*
+			    **  BULLET (bull)
+			    */
+			    code = 0x2022;
+			    break;
+			case 150:
+			    /*
+			    **  EN DASH (ndash)
+			    */
+			    code = 0x2013;
+			    break;
+			case 151:
+			    /*
+			    **  EM DASH (mdash)
+			    */
+			    code = 0x2014;
+			    break;
+			case 152:
+			    /*
+			    **  SMALL TILDE (tilde)
+			    */
+			    code = 0x02dc;
+			    break;
+			case 153:
+			    /*
+			    **  TRADE MARK SIGN (trade)
+			    */
+			    code = 0x2122;
+			    break;
+			case 155:
+			    /*
+			    **  SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+			    **  (rsaquo)
+			    */
+			    code = 0x203a;
+			    break;
+			default:
+			    /*
+			    **  Do not attempt a conversion
+			    **  to valid Unicode values.
+			    */
+			    break;
+		    }
+		}
+#endif /* NOTUSED_FOTEMODS */
 		/*
 		**  Check for special values. - FM
 		*/
@@ -1911,6 +2023,25 @@ top1:
 		    */
 		    for (p = replace_buf; *p; p++)
 			PUTC(*p);
+		/*
+		**  Ignore 8205 (zwj),
+		**  8206 (lrm), and 8207 (rln), if we get to here. - FM
+		*/
+		} else if (code == 8205 ||
+			   code == 8206 ||
+			   code == 8207) {
+		    if (TRACE) {
+			fprintf(stderr,
+				"SGML_character: Ignoring '%s%s'.\n",
+				(context->isHex ? "&#x" : "&#"),
+				string->data);
+		    }
+		    string->size = 0;
+		    context->isHex = FALSE;
+		    context->state = S_text;
+		    if (c != ';')
+			goto top1;
+		    break;
 #endif /* NOTUSED_FOTEMODS */
 	        /*
 		**  Show the numeric entity if we get to here