Index: Library/Overview.html
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/Overview.html,v
retrieving revision 1.88
retrieving revision 1.90
diff -w -c -r1.88 -r1.90
*** Overview.html	1998/03/09 16:19:42	1.88
--- Overview.html	1998/03/10 17:35:18	1.90
***************
*** 11,24 ****
    Libwww - the W3C Sample Code Library
  </H1>
  <DIV class="intro">
!   Libwww is a general-purpose Web API written in C. With a highly extensible
!   and layered API, it can accommodate many different types of applications
!   including clients, robots, etc. The purpose of Libwww is to provide a sample
!   implementation of HTTP and other Internet protocols and to serve as a testbed
!   for protocol experiments. It has a rudimentary HTML parser which can only
!   do the very basics. Please have a look at the <A HREF="../Amaya/">Amaya Web
!   client</A> for a HTML browser/editor application and
!   <A HREF="../Jigsaw/">Jigsaw server</A> for a full-blown server application.
    <UL>
      <LI>
        <A HREF="#News">News, Updates, and Events </A>- <EM><STRONG>libwww is
--- 11,23 ----
    Libwww - the W3C Sample Code Library
  </H1>
  <DIV class="intro">
!   Libwww is a general-purpose Web API written in C for Unix and Windows. With
!   a highly extensible and layered API, it can accommodate many different types
!   of applications including clients, robots, etc. The purpose of Libwww is
!   to provide a sample implementation of HTTP and other Internet protocols and
!   to serve as a testbed for protocol experiments. It comes with a lot of
!   "plug-and-play" modules including a rudimentary HTML parser which can do
!   the very basics.
    <UL>
      <LI>
        <A HREF="#News">News, Updates, and Events </A>- <EM><STRONG>libwww is
***************
*** 36,45 ****
        <A HREF="#Authors">Authors and Contributors</A>
    </UL>
    <P>
    Also have a look at the <A HREF="Activity.html">W3C Libwww activity</A> statement
    on support, usability etc.
    <P>
!   @(#) $Id: Overview.html,v 1.88 1998/03/09 16:19:42 frystyk Exp $
  </DIV>
  <P>
    <HR>
--- 35,58 ----
        <A HREF="#Authors">Authors and Contributors</A>
    </UL>
    <P>
+   Nearby you can find the following example applications that you get when
+   you download the libwww distribution:
+   <UL>
+     <LI>
+       The <A HREF="../Robot/">Mini Robot</A> - a fast robot that allows you to
+       check links etc.
+     <LI>
+       The <A HREF="../LineMode/">Line Mode Browser</A> - a terminal based, simple
+       browser
+     <LI>
+       The <A HREF="../ComLine/">Command Line Tool</A> - a quick too to do all your
+       Web work
+   </UL>
+   <P>
    Also have a look at the <A HREF="Activity.html">W3C Libwww activity</A> statement
    on support, usability etc.
    <P>
!   @(#) $Id: Overview.html,v 1.90 1998/03/10 17:35:18 frystyk Exp $
  </DIV>
  <P>
    <HR>
***************
*** 80,90 ****
      <STRONG>Dec 24, 1997</STRONG>: <A NAME="Home">Libwww is looking for a new
      home!</A>
    <DD>
!     Version 5.1 is the last major release of Libwww and we are looking for volunteers
!     to take over the maintenance and development of the source base including
!     libwww, the<A HREF="../Robot/"> Webbot</A>, <A HREF="../LineMode/">Line Mode
!     Browser</A>, and the <A HREF="../ComLine/">Command Line Tool</A>. Interested
!     parties can <A HREF="mailto:frystyk@w3.org">contact Henrik</A> for details!
  </DL>
  <H2>
    <A HREF="../Consortium/Prospectus/ActivityList.html"><IMG BORDER="0" SRC="../Icons/WWW/activity_48x48"
--- 93,105 ----
      <STRONG>Dec 24, 1997</STRONG>: <A NAME="Home">Libwww is looking for a new
      home!</A>
    <DD>
!     W3C is looking for volunteers to either help or to take over the maintenance
!     and development of the source base including libwww, the Mini Robot
!     (<A HREF="../Robot/">webbot)</A>, the terminal based
!     <A HREF="../LineMode/">Line Mode Browser</A>, and the
!     <A HREF="../ComLine/">Command Line Tool</A> which can be used in batch tools
!     etc. Interested parties can <A HREF="mailto:frystyk@w3.org">contact Henrik</A>
!     for details!
  </DL>
  <H2>
    <A HREF="../Consortium/Prospectus/ActivityList.html"><IMG BORDER="0" SRC="../Icons/WWW/activity_48x48"
***************
*** 257,263 ****
    <BR>
    Henrik Frystyk Nielsen,
    <A HREF="mailto:libwww@w3.org">libwww@w3.org</A>,<BR>
!   @(#) $Id: Overview.html,v 1.88 1998/03/09 16:19:42 frystyk Exp $
  </ADDRESS>
  <P class=policyfooter>
  <SMALL><A href="../Consortium/Legal/ipr-notice.html#Copyright">Copyright</A>
--- 272,278 ----
    <BR>
    Henrik Frystyk Nielsen,
    <A HREF="mailto:libwww@w3.org">libwww@w3.org</A>,<BR>
!   @(#) $Id: Overview.html,v 1.90 1998/03/10 17:35:18 frystyk Exp $
  </ADDRESS>
  <P class=policyfooter>
  <SMALL><A href="../Consortium/Legal/ipr-notice.html#Copyright">Copyright</A>
Index: Library/User/ReleaseNotes.html
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/User/ReleaseNotes.html,v
retrieving revision 1.51
retrieving revision 1.55
diff -w -c -r1.51 -r1.55
*** ReleaseNotes.html	1998/03/09 16:19:48	1.51
--- ReleaseNotes.html	1998/03/20 17:52:45	1.55
***************
*** 38,43 ****
--- 38,70 ----
  <P>
    <HR>
  <H2>
+   Release 5.1k (To be released)
+ </H2>
+ <P>
+ This is the set of things that have been done for the next release.
+ <H3>
+   New Features
+ </H3>
+ <UL>
+ <LI>
+ Improved support in the configure script for determining whether the WAIS libraries are available for direct WAIS access.
+   <LI>
+     Added a simple "single user lock" on the persistent cache as it gets confused
+     if multiple users are using it.
+ </UL>
+ <H3>
+   Bug Fixes
+ </H3>
+ <UL>
+ <LI>
+ Fixed a problem where libwww may loop if several requests are coming on a connection that is not yet established.
+   <LI>
+ Fixed the mapping rules for internal icons used when presenting local file directory listings. The icons are installed as part of the libwww distibution package
+   <LI>
+     <A HREF="Patch/5.1j/">These are the patches</A> that I have recieved for
+     the current release. They have all (with minor modifications) been applied to this upcoming release.
+ </UL>
+ <H2>
    Release 5.1j March 9 1998
  </H2>
  <H3>
***************
*** 252,257 ****
  <ADDRESS>
    Henrik Frystyk Nielsen,
    <A HREF="mailto:libwww@w3.org">libwww@w3.org</A>,<BR>
!   @(#) $Id: ReleaseNotes.html,v 1.51 1998/03/09 16:19:48 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
--- 279,284 ----
  <ADDRESS>
    Henrik Frystyk Nielsen,
    <A HREF="mailto:libwww@w3.org">libwww@w3.org</A>,<BR>
!   @(#) $Id: ReleaseNotes.html,v 1.55 1998/03/20 17:52:45 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
Index: Library/User/Patch/Overview.html
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/User/Patch/Overview.html,v
retrieving revision 1.37
retrieving revision 1.38
diff -w -c -r1.37 -r1.38
*** Overview.html	1997/12/29 16:17:50	1.37
--- Overview.html	1998/03/18 14:19:11	1.38
***************
*** 36,44 ****
  </OL>
  <P>
    <HR>
! <H2>
    Version 5.1d
! </H2>
  <DL>
    <DT>
      Contribution from Rick Curry (not a patch)
--- 36,52 ----
  </OL>
  <P>
    <HR>
! <H3>
!   Version 5.1j
! </H3>
! <UL>
!   <LI>
!     <A HREF="5.1j/">These are the patches</A> that I have received for this release
!     and that I will apply before the next release.
! </UL>
! <H3>
    Version 5.1d
! </H3>
  <DL>
    <DT>
      Contribution from Rick Curry (not a patch)
***************
*** 46,54 ****
      A new version of <A HREF="HTWWWStr.c">HTWWWStr</A> with a better date stamp
      string parser
  </DL>
! <H2>
    Version 5.1b
! </H2>
  <DL>
    <DT>
      <A HREF="http://lists.w3.org/Archives/Public/www-lib-bugs/msg00256.html">Patch
--- 54,62 ----
      A new version of <A HREF="HTWWWStr.c">HTWWWStr</A> with a better date stamp
      string parser
  </DL>
! <H3>
    Version 5.1b
! </H3>
  <DL>
    <DT>
      <A HREF="http://lists.w3.org/Archives/Public/www-lib-bugs/msg00256.html">Patch
***************
*** 62,70 ****
    <DD>
      Gecse Roland pointed out these problems on FreeBSD
  </DL>
! <H2>
    Version 5.0a
! </H2>
  <P>
  Bulding on <B>SunOS</B>: Sun uses the symbol "<CODE>__STDC__</CODE>" in their
  headers, not "<CODE>STDC_HEADERS</CODE>" which the configure script is looking
--- 70,78 ----
    <DD>
      Gecse Roland pointed out these problems on FreeBSD
  </DL>
! <H3>
    Version 5.0a
! </H3>
  <P>
  Bulding on <B>SunOS</B>: Sun uses the symbol "<CODE>__STDC__</CODE>" in their
  headers, not "<CODE>STDC_HEADERS</CODE>" which the configure script is looking
***************
*** 75,83 ****
  <PRE>	BASH&gt; CFLAGS='-g -Wall -DSTDC_HEADERS' ./configure
  	CSH&gt; env CFLAGS='-g -Wall -DSTDC_HEADERS' ./configure
  </PRE>
! <H2>
    Version 5.0
! </H2>
  <DL>
    <DT>
      <A HREF="lib_5.0_1.fix">Patch 1</A>
--- 83,91 ----
  <PRE>	BASH&gt; CFLAGS='-g -Wall -DSTDC_HEADERS' ./configure
  	CSH&gt; env CFLAGS='-g -Wall -DSTDC_HEADERS' ./configure
  </PRE>
! <H3>
    Version 5.0
! </H3>
  <DL>
    <DT>
      <A HREF="lib_5.0_1.fix">Patch 1</A>
***************
*** 118,129 ****
  	persistent connection (thanks to Markku Savela)
      </UL>
  </DL>
- <H2>
-   Version 4.0D
- </H2>
  <H3>
!   Library
  </H3>
  <DL>
    <DT>
      New Multiple T stream (May 27 1996)
--- 126,137 ----
  	persistent connection (thanks to Markku Savela)
      </UL>
  </DL>
  <H3>
!   Version 4.0D
  </H3>
+ <H4>
+   Library
+ </H4>
  <DL>
    <DT>
      New Multiple T stream (May 27 1996)
***************
*** 135,143 ****
      <A HREF="lib_4.0_2.fix">Patch for better logging</A>
    <DD>
  </DL>
! <H3>
    Mini Server
! </H3>
  <DL>
    <DT>
      Event Loop and Timeouts
--- 143,151 ----
      <A HREF="lib_4.0_2.fix">Patch for better logging</A>
    <DD>
  </DL>
! <H4>
    Mini Server
! </H4>
  <DL>
    <DT>
      Event Loop and Timeouts
***************
*** 158,166 ****
      server may block as we only have a single process and a single stack. The
      solution is of course to have a non-blocking DNS resolver library.
  </DL>
! <H2>
    Version 4.0C
! </H2>
  <DL>
    <DT>
      <A HREF="lib_4.0C_1.fix">Patch for PUT and POST</A>
--- 166,174 ----
      server may block as we only have a single process and a single stack. The
      solution is of course to have a non-blocking DNS resolver library.
  </DL>
! <H3>
    Version 4.0C
! </H3>
  <DL>
    <DT>
      <A HREF="lib_4.0C_1.fix">Patch for PUT and POST</A>
***************
*** 210,218 ****
  	traversing the Web.
      </UL>
  </DL>
! <H2>
    Library 4.0
! </H2>
  <UL>
    <LI>
      <A HREF="lib_4.0_1.fix">SGML fix from Maciej Puzio for better error
--- 218,226 ----
  	traversing the Web.
      </UL>
  </DL>
! <H3>
    Library 4.0
! </H3>
  <UL>
    <LI>
      <A HREF="lib_4.0_1.fix">SGML fix from Maciej Puzio for better error
***************
*** 232,240 ****
    <LI>
      Directory listings do not work completely on Windows NT
  </UL>
! <H2>
    Library 3.1
! </H2>
  <DL>
    <DT>
      Bug in time stamp on files in FTP directory listings
--- 240,248 ----
    <LI>
      Directory listings do not work completely on Windows NT
  </UL>
! <H3>
    Library 3.1
! </H3>
  <DL>
    <DT>
      Bug in time stamp on files in FTP directory listings
***************
*** 251,259 ****
      A bug which makes the HTML parser crash if is gets more than 20 nested HTML
      tags. Thanks to Robert M. Fleischman for pointing this out!
  </DL>
! <H2>
    Library 3.0
! </H2>
  <DL>
    <DT>
      <A HREF="lib_3.0_1.fix">Problems with redirection</A>
--- 259,267 ----
      A bug which makes the HTML parser crash if is gets more than 20 nested HTML
      tags. Thanks to Robert M. Fleischman for pointing this out!
  </DL>
! <H3>
    Library 3.0
! </H3>
  <DL>
    <DT>
      <A HREF="lib_3.0_1.fix">Problems with redirection</A>
***************
*** 271,278 ****
  <P>
    <HR>
  <ADDRESS>
!   Henrik Frystyk Nielsen,
!   <A HREF="mailto:libwww@w3.org">libwww@w3.org</A>,<BR>
!   @(#) $Id: Overview.html,v 1.37 1997/12/29 16:17:50 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
--- 279,285 ----
  <P>
    <HR>
  <ADDRESS>
!   <A HREF="../../../People/Frystyk/">Henrik Frystyk Nielsen</A>,<BR>
!   @(#) $Id: Overview.html,v 1.38 1998/03/18 14:19:11 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
Index: Library/src/HTAlert.html
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTAlert.html,v
retrieving revision 2.47
retrieving revision 2.48
diff -w -c -r2.47 -r2.48
*** HTAlert.html	1997/04/05 00:25:17	2.47
--- HTAlert.html	1998/03/20 17:52:46	2.48
***************
*** 112,117 ****
--- 112,118 ----
      HT_MSG_DESTINATION_MOVED,
      HT_MSG_REDIRECTION,
      HT_MSG_PROXY,
+     HT_MSG_CACHE_LOCK,
      HT_MSG_ELEMENTS		            /* This MUST be the last element */
  } HTAlertMsg;
  
***************
*** 135,141 ****
      "The destination document for this operation has moved - continue \
  operation with new location?", \
      "A redirection may change the behavior of this method - proceed anyway?", \
!     "An automatic request for changing proxy has been encountered - continue?"
  </PRE>
  <H2>
    Enable or Disable Messages
--- 136,144 ----
      "The destination document for this operation has moved - continue \
  operation with new location?", \
      "A redirection may change the behavior of this method - proceed anyway?", \
!     "An automatic request for changing proxy has been encountered - continue?", \
!     "The persistent cache is already in use by another user. If this is not \
! the case then you can manually delete this lock and restart."
  </PRE>
  <H2>
    Enable or Disable Messages
***************
*** 255,260 ****
  <P>
    <HR>
  <ADDRESS>
!   @(#) $Id: HTAlert.html,v 2.47 1997/04/05 00:25:17 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
--- 258,263 ----
  <P>
    <HR>
  <ADDRESS>
!   @(#) $Id: HTAlert.html,v 2.48 1998/03/20 17:52:46 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
Index: Library/src/HTAnchor.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTAnchor.c,v
retrieving revision 1.73
retrieving revision 1.74
diff -w -c -r1.73 -r1.74
*** HTAnchor.c	1998/03/05 21:56:10	1.73
--- HTAnchor.c	1998/03/22 21:39:32	1.74
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTAnchor.c,v 1.73 1998/03/05 21:56:10 frystyk Exp $
  **
  **	An anchor represents a region of a hypertext document which is
  **	linked to another anchor in the same or a different document.
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTAnchor.c,v 1.74 1998/03/22 21:39:32 frystyk Exp $
  **
  **	An anchor represents a region of a hypertext document which is
  **	linked to another anchor in the same or a different document.
***************
*** 634,639 ****
--- 634,656 ----
  PUBLIC BOOL HTAnchor_hasChildren  (HTParentAnchor * me)
  {
      return (me && me->children);
+ }
+ 
+ /*
+ ** Fix up a simple routine to see if this anchor is a (ChildAnchor *)
+ ** Seem to be doing it all over the place, so simplify!
+ */
+ PUBLIC BOOL HTAnchor_isChild (HTAnchor * me)
+ {
+     return (me && (HTParentAnchor *) me != me->parent);
+ }
+ 
+ PUBLIC char * HTAnchor_view (HTAnchor * me)
+ {
+     char * view = NULL;
+     if (me && (HTParentAnchor *) me != me->parent && ((HTChildAnchor *) me)->tag)
+ 	StrAllocCopy(view, ((HTChildAnchor *) me)->tag);
+     return view;
  }
  
  /* ------------------------------------------------------------------------- */
Index: Library/src/HTAnchor.html
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTAnchor.html,v
retrieving revision 2.55
retrieving revision 2.56
diff -w -c -r2.55 -r2.56
*** HTAnchor.html	1998/03/05 21:56:11	2.55
--- HTAnchor.html	1998/03/22 21:39:33	2.56
***************
*** 227,232 ****
--- 227,252 ----
  Does this parent anchor have any children
  <PRE>extern BOOL HTAnchor_hasChildren	(HTParentAnchor *me);
  </PRE>
+ <H3>
+   Is this anchor a Child?
+ </H3>
+ <PRE>
+ extern BOOL HTAnchor_isChild (HTAnchor * me);
+ </PRE>
+ 
+ <H3>
+   Get the Tag/Fragment/View of this anchor
+ </H3>
+ 
+ If this is a child anchor then it has a tag (often also called a "fragment"), which
+ is essentially a specific <B>view</B> of a document. This is why I like to call it
+ a view instead of a fragment. The string returned (if non-NULL) must be freed by the
+ caller.
+ 
+ <PRE>
+ extern char * HTAnchor_view (HTAnchor * me);
+ </PRE>
+ 
  <H2>
    Anchor Addresses
  </H2>
***************
*** 544,549 ****
  <P>
    <HR>
  <ADDRESS>
!   @(#) $Id: HTAnchor.html,v 2.55 1998/03/05 21:56:11 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
--- 564,569 ----
  <P>
    <HR>
  <ADDRESS>
!   @(#) $Id: HTAnchor.html,v 2.56 1998/03/22 21:39:33 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
Index: Library/src/HTBufWrt.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTBufWrt.c,v
retrieving revision 2.18
retrieving revision 2.19
diff -w -c -r2.18 -r2.19
*** HTBufWrt.c	1998/02/27 18:35:44	2.18
--- HTBufWrt.c	1998/03/22 21:39:34	2.19
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTBufWrt.c,v 2.18 1998/02/27 18:35:44 frystyk Exp $
  **
  **	A buffered output stream. This stream lets you write characters to a
  **	stream without causing a write every time.  The data is first written
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTBufWrt.c,v 2.19 1998/03/22 21:39:34 frystyk Exp $
  **
  **	A buffered output stream. This stream lets you write characters to a
  **	stream without causing a write every time.  The data is first written
***************
*** 59,65 ****
  PRIVATE int FlushEvent (HTTimer * timer, void * param, HTEventType type)
  {
      HTOutputStream * me = (HTOutputStream *) param;
!     if (timer != me->timer) HTDebugBreak();
      if (PROT_TRACE) HTTrace("Buffer...... Timeout flushing %p with timer %p\n", me, timer);
  
      /*
--- 59,66 ----
  PRIVATE int FlushEvent (HTTimer * timer, void * param, HTEventType type)
  {
      HTOutputStream * me = (HTOutputStream *) param;
!     if (timer != me->timer)
! 	HTDebugBreak(__FILE__, __LINE__, "Buffer Writer timer %p not in sync\n", timer);
      if (PROT_TRACE) HTTrace("Buffer...... Timeout flushing %p with timer %p\n", me, timer);
  
      /*
Index: Library/src/HTCache.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTCache.c,v
retrieving revision 2.47
retrieving revision 2.49
diff -w -c -r2.47 -r2.49
*** HTCache.c	1998/02/25 20:48:21	2.47
--- HTCache.c	1998/03/22 21:39:35	2.49
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTCache.c,v 2.47 1998/02/25 20:48:21 frystyk Exp $
  **
  **	This modules manages the cache
  **
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTCache.c,v 2.49 1998/03/22 21:39:35 frystyk Exp $
  **
  **	This modules manages the cache
  **
***************
*** 26,31 ****
--- 26,32 ----
  #define HT_CACHE_LOC	"/tmp/"
  #define HT_CACHE_ROOT	"w3c-cache/"
  #define HT_CACHE_INDEX	".index"
+ #define HT_CACHE_LOCK	".lock"
  #define HT_CACHE_META	".meta"
  #define HT_CACHE_ETAG	"@w3c@"
  
***************
*** 108,113 ****
--- 109,115 ----
  
  /* Cache parameters */ 
  PRIVATE BOOL		HTCacheEnable = NO;	      /* Disabled by default */
+ PRIVATE BOOL		HTCacheInitialized = NO;
  PRIVATE char *		HTCacheRoot = NULL;  	    /* Destination for cache */
  PRIVATE HTExpiresMode	HTExpMode = HT_EXPIRES_IGNORE;
  PRIVATE HTDisconnectedMode DisconnectedMode = HT_DISCONNECT_NONE;
***************
*** 287,301 ****
  				    pres->url,
  				    pres->cachename,
  				    pres->etag ? pres->etag : HT_CACHE_ETAG,
! 				    pres->lm,
! 				    pres->expires,
  				    pres->size,
  				    pres->range+0x30,
  				    pres->hash,
  				    pres->hits,
! 				    pres->freshness_lifetime,
! 				    pres->response_time,
! 				    pres->corrected_initial_age,
  				    pres->must_revalidate+0x30) < 0) {
  			    if (CACHE_TRACE)
  				HTTrace("Cache Index. Error writing cache index\n");
--- 289,303 ----
  				    pres->url,
  				    pres->cachename,
  				    pres->etag ? pres->etag : HT_CACHE_ETAG,
! 				    (long) (pres->lm),
! 				    (long) (pres->expires),
  				    pres->size,
  				    pres->range+0x30,
  				    pres->hash,
  				    pres->hits,
! 				    (long) (pres->freshness_lifetime),
! 				    (long) (pres->response_time),
! 				    (long) (pres->corrected_initial_age),
  				    pres->must_revalidate+0x30) < 0) {
  			    if (CACHE_TRACE)
  				HTTrace("Cache Index. Error writing cache index\n");
***************
*** 337,352 ****
  	    StrAllocCopy(cache->cachename, cachename);
  	    if (strcmp(etag, HT_CACHE_ETAG)) StrAllocCopy(cache->etag, etag);
  	}
! #if SIZEOF_LONG==8
  	/*
  	**  On some 64 bit machines (alpha) time_t is of type int and not long.
  	**  This means that we have to adjust sscanf accordingly so that we
  	**  know what we are looking for. Otherwise er may get unalignment
  	**  problems.
  	*/
- 	if (sscanf(line, "%d %d %d %c %d %d %d %d %d %c",
- #else
  	if (sscanf(line, "%ld %ld %ld %c %d %d %ld %ld %ld %c",
  #endif
  		   &cache->lm,
  		   &cache->expires,
--- 339,354 ----
  	    StrAllocCopy(cache->cachename, cachename);
  	    if (strcmp(etag, HT_CACHE_ETAG)) StrAllocCopy(cache->etag, etag);
  	}
! #ifdef HAVE_LONG_TIME_T
  	/*
  	**  On some 64 bit machines (alpha) time_t is of type int and not long.
  	**  This means that we have to adjust sscanf accordingly so that we
  	**  know what we are looking for. Otherwise er may get unalignment
  	**  problems.
  	*/
  	if (sscanf(line, "%ld %ld %ld %c %d %d %ld %ld %ld %c",
+ #else
+ 	if (sscanf(line, "%d %d %ld %c %d %d %d %d %d %c",
  #endif
  		   &cache->lm,
  		   &cache->expires,
***************
*** 625,630 ****
--- 627,683 ----
  }
  
  /*
+ **	As this is a single user cache, we have to lock it when in use.
+ */
+ PRIVATE BOOL HTCache_getSingleUserLock (const char * root)
+ {
+     if (root) {
+ 	FILE * fp;
+ 	char * location = NULL;
+ 	if ((location = (char *)
+ 	     HT_MALLOC(strlen(root) + strlen(HT_CACHE_LOCK) + 1)) == NULL)
+ 	    HT_OUTOFMEM("HTCache_getLock");
+ 	strcpy(location, root);
+ 	strcat(location, HT_CACHE_LOCK);
+ 	if ((fp = fopen(location, "r")) != NULL) {
+ 	    HTAlertCallback *cbf = HTAlert_find(HT_A_CONFIRM);
+ 	    HTTrace("Cache....... In `%s\' is already in use\n", root);
+     	    if (cbf) (*cbf)(NULL, HT_A_CONFIRM, HT_MSG_CACHE_LOCK,NULL,location,NULL);
+ 	    fclose(fp);
+ 	    HT_FREE(location);
+ 	    return NO;
+ 	}
+ 	if ((fp = fopen(location, "w")) == NULL) {
+ 	    HTTrace("Cache....... Can't open `%s\' for writing\n", location);
+ 	    HT_FREE(location);
+ 	    return NO;
+ 	}
+ 	HT_FREE(location);
+ 	return YES;
+     }
+     return NO;
+ }
+ 
+ /*
+ **	Release the single user lock
+ */
+ PRIVATE BOOL HTCache_deleteSingleUserLock (const char * root)
+ {
+     if (root) {
+ 	char * location = NULL;
+ 	if ((location = (char *)
+ 	     HT_MALLOC(strlen(root) + strlen(HT_CACHE_LOCK) + 1)) == NULL)
+ 	    HT_OUTOFMEM("HTCache_deleteLock");
+ 	strcpy(location, root);
+ 	strcat(location, HT_CACHE_LOCK);
+ 	REMOVE(location);
+ 	HT_FREE(location);
+ 	return YES;
+     }
+     return NO;
+ }
+ 
+ /*
  **	If `cache_root' is NULL then reuse old value or use HT_CACHE_ROOT.
  **	An empty string will make '/' as cache root
  **	We can only enable the cache if the HTSecure flag is not set. This
***************
*** 645,650 ****
--- 698,710 ----
  	HTCacheMode_setMaxSize(size);
  
  	/*
+ 	**  Set a lock on the cache so that multiple users
+ 	**  don't step on each other.
+ 	*/
+ 	if (HTCache_getSingleUserLock(HTCacheRoot) == NO)
+ 	    return NO;
+ 
+ 	/*
  	**  Look for the cache index and read the contents
  	*/
  	HTCacheIndex_read(HTCacheRoot);
***************
*** 653,658 ****
--- 713,719 ----
  	**  Do caching from now on
  	*/
  	HTCacheEnable = YES;
+ 	HTCacheInitialized = YES;
  	return YES;
      }
      return NO;
***************
*** 663,674 ****
--- 724,743 ----
  */
  PUBLIC BOOL HTCacheTerminate (void)
  {
+     if (HTCacheInitialized) {
+ 
  	/*
  	**  Write the index to file
  	*/
  	HTCacheIndex_write(HTCacheRoot);
  
  	/*
+ 	**  Set a lock on the cache so that multiple users
+ 	**  don't step on each other.
+ 	*/
+ 	HTCache_deleteSingleUserLock(HTCacheRoot);
+ 
+ 	/*
  	**  Cleanup memory by deleting all HTCache objects
  	*/
  	HTCache_deleteAll();
***************
*** 680,685 ****
--- 749,756 ----
  	HTCacheEnable = NO;
  	return YES;
      }
+     return NO;
+ }
  
  /*
  **	The cache can be temporarily suspended by using the enable/disable
***************
*** 1640,1646 ****
      
      HTResponse * response = HTRequest_response(request);
      HTParentAnchor * anchor = HTRequest_anchor(request);
!     if (!HTCacheEnable) {
  	if (CACHE_TRACE) HTTrace("Cache....... Not enabled\n");
  	return NULL;
      }
--- 1711,1717 ----
      
      HTResponse * response = HTRequest_response(request);
      HTParentAnchor * anchor = HTRequest_anchor(request);
!     if (!HTCacheEnable || !HTCacheInitialized) {
  	if (CACHE_TRACE) HTTrace("Cache....... Not enabled\n");
  	return NULL;
      }
Index: Library/src/HTError.html
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTError.html,v
retrieving revision 2.45
retrieving revision 2.46
diff -w -c -r2.45 -r2.46
*** HTError.html	1997/11/26 16:05:15	2.45
--- HTError.html	1998/03/20 17:52:49	2.46
***************
*** 111,116 ****
--- 111,117 ----
  	HTERR_NO_FILE,
  	HTERR_FTP_SERVER,
  	HTERR_FTP_NO_RESPONSE,
+         HTERR_FTP_LOGIN_FAILURE,
  	HTERR_TIME_OUT,
  	HTERR_GOPHER_SERVER,
  	HTERR_INTERRUPTED,
***************
*** 233,240 ****
      { 0,   "Can't locate remote host", 			"internal" }, \
      { 0,   "No host name found", 			"internal" }, \
      { 0,   "No file name found or file not accessible", "internal" }, \
!     { 0,   "FTP-server replies", 			"internal" }, \
!     { 0,   "FTP-server doesn't reply", 			"internal" }, \
      { 0,   "Server timed out", 				"internal" }, \
      { 0,   "Gopher-server replies", 			"internal" }, \
      { 0,   "Data transfer interrupted", 		"internal" }, \
--- 234,242 ----
      { 0,   "Can't locate remote host", 			"internal" }, \
      { 0,   "No host name found", 			"internal" }, \
      { 0,   "No file name found or file not accessible", "internal" }, \
!     { 0,   "FTP server replies", 			"internal" }, \
!     { 0,   "FTP server doesn't reply", 			"internal" }, \
!     { 0,   "FTP login failure", 			"internal" }, \
      { 0,   "Server timed out", 				"internal" }, \
      { 0,   "Gopher-server replies", 			"internal" }, \
      { 0,   "Data transfer interrupted", 		"internal" }, \
***************
*** 380,385 ****
  <P>
    <HR>
  <ADDRESS>
!   @(#) $Id: HTError.html,v 2.45 1997/11/26 16:05:15 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
--- 382,387 ----
  <P>
    <HR>
  <ADDRESS>
!   @(#) $Id: HTError.html,v 2.46 1998/03/20 17:52:49 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
Index: Library/src/HTEscape.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTEscape.c,v
retrieving revision 2.15
retrieving revision 2.16
diff -w -c -r2.15 -r2.16
*** HTEscape.c	1996/12/05 23:19:53	2.15
--- HTEscape.c	1998/03/20 17:52:49	2.16
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTEscape.c,v 2.15 1996/12/05 23:19:53 eric Exp $
  **
  ** history:
  **	Nov 13 94	Spawned from HTParse, as it then can be used in utility
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTEscape.c,v 2.16 1998/03/20 17:52:49 frystyk Exp $
  **
  ** history:
  **	Nov 13 94	Spawned from HTParse, as it then can be used in utility
***************
*** 82,87 ****
--- 82,94 ----
  }
  
  
+ PUBLIC char HTAsciiHexToChar (char c)
+ {
+     return  c >= '0' && c <= '9' ?  c - '0' 
+     	    : c >= 'A' && c <= 'F'? c - 'A' + 10
+     	    : c - 'a' + 10;	/* accept small letters just in case */
+ }
+ 
  /*		Decode %xx escaped characters			HTUnEscape()
  **		-----------------------------
  **
***************
*** 90,103 ****
  **	the acsii hex code for character 16x+y.
  **	The string is converted in place, as it will never grow.
  */
- 
- PRIVATE char from_hex (char c)
- {
-     return  c >= '0' && c <= '9' ?  c - '0' 
-     	    : c >= 'A' && c <= 'F'? c - 'A' + 10
-     	    : c - 'a' + 10;	/* accept small letters just in case */
- }
- 
  PUBLIC char * HTUnEscape (char * str)
  {
      char * p = str;
--- 97,102 ----
***************
*** 111,124 ****
      while(*p) {
          if (*p == HEX_ESCAPE) {
  	    p++;
! 	    if (*p) *q = from_hex(*p++) * 16;
! #ifdef UNTESTED /* suggestion from Markku Savela - I just copied it in - EGP */
! 	    if (*p) *q = FROMASCII(*q + from_hex(*p)), ++p;
  	    q++;
! #else /* UNTESTED */
! 	    if (*p) *q = FROMASCII(*q + from_hex(*p));
  	    p++, q++;
! #endif /* !UNTESTED */
  	} else {
  	    *q++ = *p++; 
  	}
--- 110,124 ----
      while(*p) {
          if (*p == HEX_ESCAPE) {
  	    p++;
! 	    if (*p) *q = HTAsciiHexToChar(*p++) * 16;
! #if 1
! 	    /* Suggestion from Markku Savela */
! 	    if (*p) *q = FROMASCII(*q + HTAsciiHexToChar(*p)), ++p;
  	    q++;
! #else 
! 	    if (*p) *q = FROMASCII(*q + HTAsciiHexToChar(*p));
  	    p++, q++;
! #endif
  	} else {
  	    *q++ = *p++; 
  	}
Index: Library/src/HTEscape.html
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTEscape.html,v
retrieving revision 2.13
retrieving revision 2.14
diff -w -c -r2.13 -r2.14
*** HTEscape.html	1997/02/16 18:42:11	2.13
--- HTEscape.html	1998/03/20 17:52:50	2.14
***************
*** 48,53 ****
--- 48,62 ----
  
  extern char * HTEscape (const char * str, HTURIEncoding mask);
  </PRE>
+ 
+ <H2>
+   Convert a single Character from Ascii Hex to Char
+ </H2>
+ 
+ <PRE>
+ extern char HTAsciiHexToChar (char c);
+ </PRE>
+ 
  <H2>
    Decode %xy Escaped Characters
  </H2>
***************
*** 65,70 ****
  <P>
    <HR>
  <ADDRESS>
!   @(#) $Id: HTEscape.html,v 2.13 1997/02/16 18:42:11 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
--- 74,79 ----
  <P>
    <HR>
  <ADDRESS>
!   @(#) $Id: HTEscape.html,v 2.14 1998/03/20 17:52:50 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
Index: Library/src/HTEvtLst.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTEvtLst.c,v
retrieving revision 2.19
retrieving revision 2.20
diff -w -c -r2.19 -r2.20
*** HTEvtLst.c	1997/12/04 16:54:48	2.19
--- HTEvtLst.c	1998/03/22 21:39:36	2.20
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTEvtLst.c,v 2.19 1997/12/04 16:54:48 frystyk Exp $
  **
  **	Updated HTEvent module 
  **	This new module combines the functions of the old HTEvent module and 
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTEvtLst.c,v 2.20 1998/03/22 21:39:36 frystyk Exp $
  **
  **	Updated HTEvent module 
  **	This new module combines the functions of the old HTEvent module and 
***************
*** 738,744 ****
      case FD_CONNECT: type = HTEvent_CONNECT; break;
      case FD_OOB: type = HTEvent_OOB; break;
      case FD_CLOSE: type = HTEvent_CLOSE; break;
!     default: HTDebugBreak();
      }
      if (HTEventList_dispatch((int)sock, type, now) != HT_OK)
  	HTEndLoop = -1;
--- 738,744 ----
      case FD_CONNECT: type = HTEvent_CONNECT; break;
      case FD_OOB: type = HTEvent_OOB; break;
      case FD_CLOSE: type = HTEvent_CLOSE; break;
!     default: HTDebugBreak(__FILE__, __LINE__, "Unknown event %d\n", event);
      }
      if (HTEventList_dispatch((int)sock, type, now) != HT_OK)
  	HTEndLoop = -1;
***************
*** 828,833 ****
--- 828,849 ----
  	if (THD_TRACE) HTTrace("Event Loop.. select returns %d\n", active_sockets);
  
          if (active_sockets == -1) {
+ #ifdef EINTR
+ 	    if (socerrno == EINTR) {
+ 		/*
+ 		** EINTR     The select() function was interrupted  before  any
+ 		**           of  the  selected  events  occurred and before the
+ 		**           timeout interval expired.
+ 		**
+ 		**           If SA_RESTART has been set  for  the  interrupting
+ 		**           signal,  it  is  implementation-dependent  whether
+ 		**	     select() restarts or returns with EINTR.
+ 		*/
+ 		if (THD_TRACE)
+ 		    HTTrace("Event Loop.. select was interruted - try again\n");
+ 		continue;
+ 	    }
+ #endif /* EINTR */
  	    HTRequest_addSystemError(theRequest, ERR_FATAL, socerrno, NO, "select");
  	    EventList_dump();
  	    return HT_ERROR;
***************
*** 877,884 ****
  	sockp->timeouts[0] != timer && 
  	sockp->timeouts[1] != timer && 
  	sockp->timeouts[2] != timer) {
! 	if (THD_TRACE) HTTrace("Timer....... bad timer %p.\n", timer);
! 	HTDebugBreak();
      }
  }
  
--- 893,899 ----
  	sockp->timeouts[0] != timer && 
  	sockp->timeouts[1] != timer && 
  	sockp->timeouts[2] != timer) {
! 	HTDebugBreak(__FILE__, __LINE__, "Bad timer %p\n", timer);
      }
  }
  
Index: Library/src/HTFTP.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTFTP.c,v
retrieving revision 1.94
retrieving revision 1.95
diff -w -c -r1.94 -r1.95
*** HTFTP.c	1998/02/01 19:04:04	1.94
--- HTFTP.c	1998/03/20 17:52:52	1.95
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTFTP.c,v 1.94 1998/02/01 19:04:04 frystyk Exp $
  **
  **	A cache of control connections is kept.
  **
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTFTP.c,v 1.95 1998/03/20 17:52:52 frystyk Exp $
  **
  **	A cache of control connections is kept.
  **
***************
*** 51,56 ****
--- 51,57 ----
  **			sent to an FTP server.
  **	Sep 95	HFN	Rewritten to support streams and persistent conenctions
  **			and multiplexed IO
+ **	Mar 1998 NG	Neil Griffin - Bug fixes and additions for FTP support on NT.
  ** Notes:
  **     			Portions Copyright 1994 Trustees of Dartmouth College
  ** 			Code for recognizing different FTP servers and
***************
*** 118,123 ****
--- 119,128 ----
      FTPServerType	server;		         	   /* Type of server */
      HTNet *		cnet;			       /* Control connection */
      HTNet *		dnet;			   	  /* Data connection */
+ /* begin _GM_ */
+ /* Note: libwww bug ID: GM3 */
+     BOOL		alreadyLoggedIn;
+ /* end _GM_ */
  } ftp_ctrl;
  
  typedef struct _ftp_data {
***************
*** 155,160 ****
--- 160,168 ----
  
  PRIVATE FTPDataCon FTPMode = FTP_DATA_PASV;
  
+ /* Added by Neil Griffin */
+ PRIVATE FTPTransferMode g_FTPTransferMode = FTP_DEFAULT_TRANSFER_MODE;
+ 
  /* ------------------------------------------------------------------------- */
  /* 			    FTP Status Line Stream			     */
  /* ------------------------------------------------------------------------- */
***************
*** 216,221 ****
--- 224,233 ----
      char cont = '\0';
      char *ptr = me->buffer+4;
      *(me->buffer+me->buflen) = '\0';
+ /* begin _GM_ */
+ /* Note: libwww bug ID: GM3 */
+     me->ctrl->alreadyLoggedIn = NO;
+ /* end _GM_ */
      if (isdigit((int) *(me->buffer))) sscanf(me->buffer, "%d%c", &reply, &cont);
      if (me->first_line) {
  	if (PROT_TRACE) HTTrace("FTP Rx...... `%s\'\n", me->buffer);
***************
*** 223,228 ****
--- 235,248 ----
  	me->first_line = NO;
  	me->ctrl->repcode = reply;
  	StrAllocCopy(me->ctrl->reply, ptr);
+ /* begin _GM_ */
+ /* Note: libwww bug ID: GM3 */
+ 	if ( (reply == 530) && (strcasestr(me->buffer, "already") != NULL) ) {
+ 	    me->ctrl->alreadyLoggedIn = YES;
+ 	} else {
+ 	    me->ctrl->alreadyLoggedIn = NO;
+ 	}
+ /* end _GM_ */
      } else {
  	HTChunk_puts(me->welcome, ptr);
  	HTChunk_putc(me->welcome, '\n');
***************
*** 397,402 ****
--- 417,431 ----
  	else
  	    StrAllocCopy(ctrl->passwd, WWW_FTP_CLIENT);
      }
+ /* begin _GM_ */
+ /* Note: libwww bug ID: GM6 */
+     {
+ 	char tempParams[512];
+ 	sprintf(tempParams, "Username='%s', Password='%s'", ctrl->uid, ctrl->passwd);
+ 	HTRequest_addError(request, ERR_INFO, NO, HTERR_OK,
+ 			   tempParams, strlen(tempParams), "HTFTPParseURL");
+     }
+ /* end _GM_ */
      if (PROT_TRACE)
  	HTTrace("FTPParse.... uid `%s\' pw `%s\'\n",
  		ctrl->uid ? ctrl->uid : "<null>",
***************
*** 531,540 ****
--- 560,574 ----
      while (1) {
  	switch ((state) ctrl->substate) {
  	  case NEED_SELECT:
+ 	    if (PROT_TRACE) HTTrace("FTP Login.. now in state NEED_SELECT\n");
  	    ctrl->substate = ctrl->reset ? NEED_REIN : NEED_GREETING;
+ #if 0
+ 	    ctrl->substate = ctrl->reset ? NEED_UID : NEED_GREETING;
+ #endif
  	    break;
  
  	  case NEED_GREETING:
+ 	    if (PROT_TRACE) HTTrace("FTP Login.. now in state NEED_GREETING\n");
  	    status = HTHost_read(HTNet_host(cnet), cnet);
  	    if (status == HT_WOULD_BLOCK)
  		return HT_WOULD_BLOCK;
***************
*** 542,554 ****
  		if (ctrl->repcode/100 == 2) {
  		    ctrl->substate = (ctrl->uid && *ctrl->uid) ?
  			NEED_UID : PROMPT_USER;
! 		} else
  		    ctrl->substate = SUB_ERROR;
! 	    } else
  		ctrl->substate = SUB_ERROR;
  	    break;
  
  	  case NEED_REIN:
  	    if (!ctrl->sent) {
  		status = SendCommand(request, ctrl, "REIN", NULL);
  		if (status == HT_WOULD_BLOCK)
--- 576,591 ----
  		if (ctrl->repcode/100 == 2) {
  		    ctrl->substate = (ctrl->uid && *ctrl->uid) ?
  			NEED_UID : PROMPT_USER;
! 		} else {
  		    ctrl->substate = SUB_ERROR;
! 		}
! 	    } else {
  		ctrl->substate = SUB_ERROR;
+ 	    }
  	    break;
  
  	  case NEED_REIN:
+ 	    if (PROT_TRACE) HTTrace("FTP Login.. now in state NEED_REIN\n");
  	    if (!ctrl->sent) {
  		status = SendCommand(request, ctrl, "REIN", NULL);
  		if (status == HT_WOULD_BLOCK)
***************
*** 561,578 ****
  		if (status == HT_WOULD_BLOCK)
  		    return HT_WOULD_BLOCK;
  		else if (status == HT_LOADED) {
! 		    if (ctrl->repcode/100 == 2) {
  			ctrl->substate = (ctrl->uid && *ctrl->uid) ?
  			    NEED_UID : PROMPT_USER;
! 		    } else
  			ctrl->substate = SUB_SUCCESS;	    /* hope the best */
! 		} else
  		    ctrl->substate = SUB_ERROR;
  		ctrl->sent = NO;
  	    }
  	    break;
  
  	  case NEED_UID:
  	    if (!ctrl->sent) {
  		status = SendCommand(request, ctrl, "USER", ctrl->uid);
  		if (status == HT_WOULD_BLOCK)
--- 598,624 ----
  		if (status == HT_WOULD_BLOCK)
  		    return HT_WOULD_BLOCK;
  		else if (status == HT_LOADED) {
! /* begin _GM_ */
! /* Note: libwww bug ID: GM8 */
! 		    /* if (ctrl->repcode/100 == 2) { */
! 		    /* If the FTP server doesn't support the REIN command, then
! 		       the return code will be 502 */
! 		    if ((ctrl->repcode/100 == 2) || (ctrl->repcode == 502)) {
! /* end _GM_ */
  			ctrl->substate = (ctrl->uid && *ctrl->uid) ?
  			    NEED_UID : PROMPT_USER;
! 		    } else {
  			ctrl->substate = SUB_SUCCESS;	    /* hope the best */
! 		    }
! 		} else {
  		    ctrl->substate = SUB_ERROR;
+ 		}
  		ctrl->sent = NO;
  	    }
  	    break;
  
  	  case NEED_UID:
+ 	    if (PROT_TRACE) HTTrace("FTP Login.. now in state NEED_UID\n");
  	    if (!ctrl->sent) {
  		status = SendCommand(request, ctrl, "USER", ctrl->uid);
  		if (status == HT_WOULD_BLOCK)
***************
*** 591,598 ****
  		    else if (code == 3) {	 	/* Password demanded */
  			ctrl->substate = (ctrl->passwd && *ctrl->passwd) ?
  			    NEED_PASSWD : PROMPT_USER;
! 		    } else if (ctrl->repcode == 530)
! 			ctrl->substate = PROMPT_USER;        /* User unknown */
  		    else
  			ctrl->substate = SUB_ERROR;
  		} else
--- 637,656 ----
  		    else if (code == 3) {	 	/* Password demanded */
  			ctrl->substate = (ctrl->passwd && *ctrl->passwd) ?
  			    NEED_PASSWD : PROMPT_USER;
! /* begin _GM_ */
! /* Note: libwww bug ID: GM3 */
! 		    /* } else if (ctrl->repcode == 530) */
! 			/* ctrl->substate = PROMPT_USER;*/        /* User unknown */
! 		    } else if (ctrl->repcode == 530) {
! 			if (ctrl->alreadyLoggedIn == YES) {
! 			    ctrl->substate = SUB_SUCCESS;
! 			    if (PROT_TRACE) HTTrace("FTP Login.. Already logged in\n");
! 			} else {
! 			    ctrl->substate = PROMPT_USER;
! 			    if (PROT_TRACE) HTTrace("FTP Login.. User Unknown\n");
! 			}
! 		    }
! /* end _GM_ */
  		    else
  			ctrl->substate = SUB_ERROR;
  		} else
***************
*** 602,607 ****
--- 660,666 ----
  	    break;
  
  	  case NEED_PASSWD:
+ 	    if (PROT_TRACE) HTTrace("FTP Login.. now in state NEED_PASSWD\n");
  	    if (!ctrl->sent) {
  		status = SendCommand(request, ctrl, "PASS", ctrl->passwd);
  		if (status == HT_WOULD_BLOCK)
***************
*** 638,643 ****
--- 697,703 ----
  	    break;
  
  	  case NEED_ACCOUNT:
+ 	    if (PROT_TRACE) HTTrace("FTP Login.. now in state NEED_ACCOUNT\n");
  	    if (!ctrl->sent) {
  		status = SendCommand(request, ctrl, "ACCT", ctrl->account);
  		if (status == HT_WOULD_BLOCK)
***************
*** 662,667 ****
--- 722,728 ----
  	    break;
  
  	  case PROMPT_USER:
+ 	    if (PROT_TRACE) HTTrace("FTP Login.. now in state PROMPT_USER\n");
  	    {
  		HTAlertCallback *cbf = HTAlert_find(HT_A_USER_PW);
  		HTAlertPar * reply = HTAlert_newReply();
***************
*** 681,695 ****
  	    break;
  
  	  case SUB_ERROR:
! 	    if (PROT_TRACE)
! 		HTTrace("FTP......... Login failed\n");
  	    ctrl->substate = 0;
  	    return HT_ERROR;
  	    break;
  
  	  case SUB_SUCCESS:
! 	    if (PROT_TRACE)
! 		HTTrace("FTP......... Logged in as `%s\'\n", ctrl->uid);
  	    ctrl->substate = 0;
  	    return HT_OK;
  	    break;
--- 742,758 ----
  	    break;
  
  	  case SUB_ERROR:
! 	    if (PROT_TRACE) HTTrace("FTP Login.. now in state SUB_ERROR\n");
! 	    HTRequest_addError(request, ERR_FATAL, NO,
! 			       HTERR_FTP_LOGIN_FAILURE, NULL, 0, "HTFTPLogin");
! 	    if (PROT_TRACE) HTTrace("FTP......... Login failed\n");
  	    ctrl->substate = 0;
  	    return HT_ERROR;
  	    break;
  
  	  case SUB_SUCCESS:
! 	    if (PROT_TRACE) HTTrace("FTP Login.. now in state SUB_SUCCESS\n");
! 	    if (PROT_TRACE) HTTrace("FTP......... Logged in as `%s\'\n", ctrl->uid);
  	    ctrl->substate = 0;
  	    return HT_OK;
  	    break;
***************
*** 721,726 ****
--- 784,790 ----
      while (1) {
  	switch ((state) ctrl->substate) {
  	  case NEED_TYPE:
+ 	    if (PROT_TRACE) HTTrace("FTP Data.... now in state NEED_TYPE\n");
  	    if(!data->type|| data->pasv || data->type=='N' || data->type=='L'){
  		ctrl->substate = NEED_SELECT;
  		break;
***************
*** 751,756 ****
--- 815,821 ----
  	    break;
  	    
  	  case NEED_SELECT:
+ 	    if (PROT_TRACE) HTTrace("FTP Data.... now in state NEED_SELECT\n");
  	    if (FTPMode & FTP_DATA_PASV && !data->pasv)
  		ctrl->substate = NEED_PASV;
  	    else if (ListenSocket(cnet, dnet, data))
***************
*** 760,765 ****
--- 825,831 ----
  	    break;
  
  	  case NEED_PASV:
+ 	    if (PROT_TRACE) HTTrace("FTP Data.... now in state NEED_PASV\n");
  	    if (!ctrl->sent) {
  		status = SendCommand(request, ctrl, "PASV", NULL);
  		if (status == HT_WOULD_BLOCK)
***************
*** 785,791 ****
  			if (!*host || sscanf(--host, "%d,%d,%d,%d,%d,%d",
  					     &h0,&h1,&h2,&h3,&p0,&p1) < 6) {
  			    if (PROT_TRACE)
! 				HTTrace("FTP......... PASV No addr\n");
  			    ctrl->substate = SUB_ERROR;
  			    break;
  			} else {
--- 851,857 ----
  			if (!*host || sscanf(--host, "%d,%d,%d,%d,%d,%d",
  					     &h0,&h1,&h2,&h3,&p0,&p1) < 6) {
  			    if (PROT_TRACE)
! 				HTTrace("FTP Data.... PASV No addr\n");
  			    ctrl->substate = SUB_ERROR;
  			    break;
  			} else {
***************
*** 806,811 ****
--- 872,878 ----
  	    break;
  
  	  case NEED_PORT:
+ 	    if (PROT_TRACE) HTTrace("FTP Data.... now in state NEED_PORT\n");
  	    if (!ctrl->sent) {
  		status = SendCommand(request, ctrl, "PORT", data->host);
  		if (status == HT_WOULD_BLOCK)
***************
*** 828,842 ****
  	    break;
  
  	  case SUB_ERROR:
  	    if (PROT_TRACE)
! 		HTTrace("FTP......... Can't setup data connection\n");
  	    ctrl->substate = 0;
  	    return HT_ERROR;
  	    break;
  
  	  case SUB_SUCCESS:
  	    if (PROT_TRACE)
! 		HTTrace("FTP......... Data connection negotiated\n");
  	    ctrl->substate = 0;
  	    return HT_OK;
  	    break;
--- 895,911 ----
  	    break;
  
  	  case SUB_ERROR:
+ 	    if (PROT_TRACE) HTTrace("FTP Data.... now in state SUB_ERROR\n");
  	    if (PROT_TRACE)
! 		HTTrace("FTP Data.... Can't setup data connection\n");
  	    ctrl->substate = 0;
  	    return HT_ERROR;
  	    break;
  
  	  case SUB_SUCCESS:
+ 	    if (PROT_TRACE) HTTrace("FTP Data.... now in state SUB_SUCCESS\n");
  	    if (PROT_TRACE)
! 		HTTrace("FTP Data.... Data connection negotiated\n");
  	    ctrl->substate = 0;
  	    return HT_OK;
  	    break;
***************
*** 870,875 ****
--- 939,945 ----
      while (1) {
  	switch ((state) ctrl->substate) {
  	  case NEED_SYST:
+ 	    if (PROT_TRACE) HTTrace("FTP Server.. now in state NEED_SYST\n");
  	    if (!ctrl->sent) {		
  		if (ctrl->server != FTP_UNSURE) {
  		    FTPListType(data, ctrl->server);
***************
*** 894,904 ****
  	    break;
  
  	  case CHECK_SYST:
  	    {
  		char *reply = ctrl->reply;
  		if (!*reply) {
  		    if (PROT_TRACE)
! 			HTTrace("FTP......... No server info?\n");
  		    ctrl->substate = NEED_PWD;
  		    break;
  		}
--- 964,975 ----
  	    break;
  
  	  case CHECK_SYST:
+ 	    if (PROT_TRACE) HTTrace("FTP Server.. now in state CHECK_SYST\n");
  	    {
  		char *reply = ctrl->reply;
  		if (!*reply) {
  		    if (PROT_TRACE)
! 			HTTrace("FTP Server.. No server info?\n");
  		    ctrl->substate = NEED_PWD;
  		    break;
  		}
***************
*** 931,936 ****
--- 1002,1008 ----
  	    break;
  
  	  case NEED_PWD:
+ 	    if (PROT_TRACE) HTTrace("FTP Server.. now in state NEED_PWD\n");
  	    if (!ctrl->sent) {
  		status = SendCommand(request, ctrl, "PWD", NULL);
  		if (status == HT_WOULD_BLOCK)
***************
*** 952,963 ****
  	    break;
  
  	  case CHECK_PWD:
  	    {
  		char *start = strchr(ctrl->reply, '"');
  		char *end;
  		if (!start || (end = strchr(++start, '"')) == NULL) {
  		    if (PROT_TRACE)
! 			HTTrace("FTP......... No current directory?\n");
  		    ctrl->server = FTP_GENERIC;
  		} else {
  		    *end = '\0';
--- 1024,1036 ----
  	    break;
  
  	  case CHECK_PWD:
+ 	    if (PROT_TRACE) HTTrace("FTP Server.. now in state CHECK_PWD\n");
  	    {
  		char *start = strchr(ctrl->reply, '"');
  		char *end;
  		if (!start || (end = strchr(++start, '"')) == NULL) {
  		    if (PROT_TRACE)
! 			HTTrace("FTP Server.. No current directory?\n");
  		    ctrl->server = FTP_GENERIC;
  		} else {
  		    *end = '\0';
***************
*** 977,990 ****
  	    break;
  
  	  case SUB_ERROR:
  	    if (PROT_TRACE)
! 		HTTrace("FTP......... Can't get server information\n");
  	    ctrl->substate = 0;
  	    ctrl->server = FTP_GENERIC;
  	    return HT_ERROR;
  	    break;
  
  	  case SUB_SUCCESS:
  	  {
  	      HTHost * host = HTNet_host(cnet);
  	      if (PROT_TRACE)
--- 1050,1065 ----
  	    break;
  
  	  case SUB_ERROR:
+ 	    if (PROT_TRACE) HTTrace("FTP Server.. now in state SUB_ERROR\n");
  	    if (PROT_TRACE)
! 		HTTrace("FTP Server.. Can't get server information\n");
  	    ctrl->substate = 0;
  	    ctrl->server = FTP_GENERIC;
  	    return HT_ERROR;
  	    break;
  
  	  case SUB_SUCCESS:
+ 	    if (PROT_TRACE) HTTrace("FTP Server.. now in state SUB_SUCCESS\n");
  	    {
  	      HTHost * host = HTNet_host(cnet);
  	      if (PROT_TRACE)
***************
*** 1031,1046 ****
      while (1) {
  	switch ((state) ctrl->substate) {
  	  case NEED_SELECT:
  	    ctrl->substate = data->pasv ? NEED_CONNECT : NEED_ACTION;
  	    break;
  
  	  case NEED_CONNECT:
  	    status = HTHost_connect(HTNet_host(dnet), dnet, data->host, FTP_DATA);
  	    if (status == HT_WOULD_BLOCK)
  		return HT_WOULD_BLOCK;
  	    else if (status == HT_OK) {
  		if (PROT_TRACE)
! 		    HTTrace("FTP Data.... Active data socket %d\n", HTNet_socket(dnet));
  #if 0
  		/*		HTNet_setPersistent(dnet, YES, HT_TP_INTERLEAVE); */
  		HTNet_setPersistent(dnet, YES, HT_TP_SINGLE);
--- 1106,1124 ----
      while (1) {
  	switch ((state) ctrl->substate) {
  	  case NEED_SELECT:
+ 	    if (PROT_TRACE) HTTrace("FTP Get Data now in state NEED_SELECT\n");
  	    ctrl->substate = data->pasv ? NEED_CONNECT : NEED_ACTION;
  	    break;
  
  	  case NEED_CONNECT:
+ 	    if (PROT_TRACE) HTTrace("FTP Get Data now in state NEED_CONNECT\n");
  	    status = HTHost_connect(HTNet_host(dnet), dnet, data->host, FTP_DATA);
  	    if (status == HT_WOULD_BLOCK)
  		return HT_WOULD_BLOCK;
  	    else if (status == HT_OK) {
  		if (PROT_TRACE)
! 		    HTTrace("FTP Get Data.... Active data socket %d\n",
! 			    HTNet_socket(dnet));
  #if 0
  		/*		HTNet_setPersistent(dnet, YES, HT_TP_INTERLEAVE); */
  		HTNet_setPersistent(dnet, YES, HT_TP_SINGLE);
***************
*** 1050,1056 ****
  		NETCLOSE(HTNet_socket(dnet));
  		HTNet_setSocket(dnet, INVSOC);
  		if (PROT_TRACE)
! 		    HTTrace("FTP......... Swap to PORT on the fly\n");
  		ctrl->substate = NEED_SELECT;
  		HT_FREE(segment);
  		return HT_OK;
--- 1128,1134 ----
  		NETCLOSE(HTNet_socket(dnet));
  		HTNet_setSocket(dnet, INVSOC);
  		if (PROT_TRACE)
! 		    HTTrace("FTP Get Data Swap to PORT on the fly\n");
  		ctrl->substate = NEED_SELECT;
  		HT_FREE(segment);
  		return HT_OK;
***************
*** 1058,1063 ****
--- 1136,1142 ----
  	    break;
  
  	  case NEED_ACCEPT:
+ 	    if (PROT_TRACE) HTTrace("FTP Get Data now in state NEED_ACCEPT\n");
  	    {
  		status = HTDoAccept(ctrl->dnet, &ctrl->dnet);
  		dnet = ctrl->dnet;
***************
*** 1065,1071 ****
  		    return HT_WOULD_BLOCK;
  		else if (status == HT_OK) {
  		    if (PROT_TRACE)
! 			HTTrace("FTP Data.... Passive data socket %d\n",
  				HTNet_socket(dnet));
  		    ctrl->substate = NEED_STREAM;
  		} else
--- 1144,1150 ----
  		    return HT_WOULD_BLOCK;
  		else if (status == HT_OK) {
  		    if (PROT_TRACE)
! 			HTTrace("FTP Get Data.... Passive data socket %d\n",
  				HTNet_socket(dnet));
  		    ctrl->substate = NEED_STREAM;
  		} else
***************
*** 1074,1079 ****
--- 1153,1159 ----
  	    break;
  
  	  case NEED_ACTION:
+ 	    if (PROT_TRACE) HTTrace("FTP Get Data now in state NEED_ACTION\n");
  	    if (!ctrl->sent) {
  		char *cmd = (data->type=='L') ? "LIST" :
  		    (data->type=='N') ? "NLST" : "RETR";
***************
*** 1097,1104 ****
  			ctrl->substate = data->pasv ? NEED_STREAM : NEED_ACCEPT;
  		    else if (code/100==5 && !ctrl->cwd)
  			ctrl->substate = NEED_SEGMENT;
! 		    else
  			ctrl->substate = SUB_ERROR;			
  		} else
  		    ctrl->substate = SUB_ERROR;
  		ctrl->sent = NO;
--- 1177,1194 ----
  			ctrl->substate = data->pasv ? NEED_STREAM : NEED_ACCEPT;
  		    else if (code/100==5 && !ctrl->cwd)
  			ctrl->substate = NEED_SEGMENT;
! /* begin _GM_ */
! /* Note: libwww bug ID: GM9 */
! 		    /* else */
! 		    /* 	ctrl->substate = SUB_ERROR; */
! 		    else {
! 			if (ctrl->repcode == 550) {
! 			    if (PROT_TRACE) HTTrace("FTP Get Data no such file or directory\n");
! 			    data->stream_error = YES;
! 			}
  		    	ctrl->substate = SUB_ERROR;
+ 		    }
+ /* end _GM_ */
  		} else
  		    ctrl->substate = SUB_ERROR;
  		ctrl->sent = NO;
***************
*** 1106,1111 ****
--- 1196,1202 ----
  	    break;
  
  	  case NEED_SEGMENT:
+ 	    if (PROT_TRACE) HTTrace("FTP Get Data now in state NEED_SEGMENT\n");
  	    {
  		char *ptr;
  		if (data->offset == data->file) {
***************
*** 1133,1138 ****
--- 1224,1230 ----
  	    break;
  
  	  case NEED_CWD:
+ 	    if (PROT_TRACE) HTTrace("FTP Get Data now in state NEED_CWD\n");
  	    if (!ctrl->sent) {
  		status = SendCommand(request, ctrl, "CWD", segment);
  		HT_FREE(segment);
***************
*** 1158,1163 ****
--- 1250,1256 ----
  	    break;
  
  	case NEED_STREAM:
+ 	    if (PROT_TRACE) HTTrace("FTP Get Data now in state NEED_STREAM\n");
  	    /* 
  	    ** Create the stream pipe FROM the channel to the application.
  	    ** The target for the input stream pipe is set up using the
***************
*** 1178,1183 ****
--- 1271,1277 ----
  	    break;
  
  	  case NEED_BODY:
+ 	      if (PROT_TRACE) HTTrace("FTP Get Data now in state NEED_BODY\n");
  	      if (data_is_active) {
  		  status = HTHost_read(HTNet_host(dnet), dnet);
  		  if (status == HT_WOULD_BLOCK)
***************
*** 1211,1224 ****
  	      break;
  
  	  case SUB_ERROR:
! 	    if (PROT_TRACE) HTTrace("FTP......... Can't retrieve object\n");
  	    ctrl->substate = 0;
  	    HT_FREE(segment);
  	    return HT_ERROR;
  	    break;
  
  	  case SUB_SUCCESS:
! 	    if (PROT_TRACE) HTTrace("FTP......... Object is loaded\n");
  	    ctrl->substate = 0;
  	    HT_FREE(segment);
  	    return HT_LOADED;
--- 1305,1320 ----
  	      break;
  
  	  case SUB_ERROR:
! 	    if (PROT_TRACE) HTTrace("FTP Get Data now in state SUB_ERROR\n");
! 	    HTRequest_addError(request, ERR_FATAL, NO, HTERR_NOT_FOUND,
! 			       NULL, 0, "HTFTPGetData");
  	    ctrl->substate = 0;
  	    HT_FREE(segment);
  	    return HT_ERROR;
  	    break;
  
  	  case SUB_SUCCESS:
! 	    if (PROT_TRACE) HTTrace("FTP Get Data now in state SUB_SUCCESS\n");
  	    ctrl->substate = 0;
  	    HT_FREE(segment);
  	    return HT_LOADED;
***************
*** 1300,1317 ****
      while (1) {
  	switch (ctrl->state) {
  	  case FTP_BEGIN:
  	    HTFTPParseURL(request, url, ctrl, data);
! 	    if (data->type != 'N') {
! 		HTBind_getAnchorBindings(anchor);
! #if 0
! 		if (HTAnchor_encoding(anchor) != HTAtom_for("7bit"))
! #endif
! 		    data->type = 'I';
  	    }
! 	    ctrl->state = FTP_NEED_CCON;
! 	    break;
  
  	  case FTP_NEED_CCON:
  	    status = HTDoConnect(cnet, url, FTP_PORT);
  	    if (status == HT_OK) {
  		HTHost * host = HTNet_host(cnet);
--- 1396,1441 ----
      while (1) {
  	switch (ctrl->state) {
  	  case FTP_BEGIN:
+ 	      if (PROT_TRACE) HTTrace("FTP Event... now in state FTP_BEGIN\n");
  	      HTFTPParseURL(request, url, ctrl, data);
! 
! 	      /* The following is added by Neil Griffin, GAIN Software */
! 
! 	      /*
! 	      ** If the user hasn't specified a permanent transfer type, then
! 	      ** use the transfer type specified at the end of the URL.
! 	      */
! 	      if (g_FTPTransferMode == FTP_DEFAULT_TRANSFER_MODE) {
! 		  switch (data->type) {
! 		  case 'a' : data->type = 'A'; break;
! 		  case 'A' : data->type = 'A'; break;
! 		  case 'i' : data->type = 'I'; break;
! 		  case 'I' : data->type = 'I'; break;
! 		  case 'd' : FTPListType(data, ctrl->server); break;
! 		  case 'D' : FTPListType(data, ctrl->server); break;
! 		  default  : data->type = 'I'; break;
! 		  }
! 
! 		  /* Otherwise, use the permanent transfer type specified by the user. */
! 	      } else {
! 		  switch (g_FTPTransferMode) {
! 		  case FTP_ASCII_TRANSFER_MODE  : data->type = 'A'; break;
! 		  case FTP_BINARY_TRANSFER_MODE : data->type = 'I'; break;
! 		  case FTP_DIR_TRANSFER_MODE    : FTPListType(data, ctrl->server); break;
! 		  default                       : data->type = 'I'; break;
  		  }
! 	      }
! 
! 	      if (PROT_TRACE)
! 		  HTTrace("FTP Event... Transfer mode set to '%c'\n", data->type);
! 
! 	      /*
! 	      **  See if we can get any hints to what we might expect content wise.
! 	      */
! 	      if (!FTP_DIR(data)) HTBind_getAnchorBindings(anchor);
  
  	case FTP_NEED_CCON:
+ 	    if (PROT_TRACE) HTTrace("FTP Event... now in state FTP_NEED_CONN\n");
  	    status = HTDoConnect(cnet, url, FTP_PORT);
  	    if (status == HT_OK) {
  		HTHost * host = HTNet_host(cnet);
***************
*** 1340,1363 ****
  		    ctrl->reset = 1;
  		} else
  		    HTNet_setPersistent(cnet, YES, HT_TP_SINGLE);
- #if 0
- 		char *s_class = HTDNS_serverClass(cnet->dns);
- 		if (s_class && strcasecomp(s_class, "ftp")) {
- 		    HTRequest_addError(request, ERR_FATAL, NO, HTERR_CLASS,
- 				       NULL, 0, "HTLoadFTP");
- 		    ctrl->state = FTP_ERROR;
- 		    break;
- 		}
- 		HTDNS_setServerClass(cnet->dns, "ftp");
- 		if (HTDNS_socket(cnet->dns) != INVSOC) {
- 		    ctrl->server = HTDNS_serverVersion(cnet->dns);
- 		    if (PROT_TRACE)
- 			HTTrace("FTP Server.. We know from cache that this is a type %d server\n",
- 				ctrl->server);
- 		    ctrl->reset = 1;
- 		} else
- 		    HTDNS_setSocket(cnet->dns, HTNet_socket(cnet));
- #endif
  
  		/* 
  		** Create the stream pipe FROM the channel to the application.
--- 1464,1469 ----
***************
*** 1398,1409 ****
--- 1504,1517 ----
  	    break;
  
  	  case FTP_NEED_LOGIN:
+ 	    if (PROT_TRACE) HTTrace("FTP Event... now in state FTP_NEED_LOGIN\n");
  	    status = HTFTPLogin(request, cnet, ctrl);
   	    if (status == HT_WOULD_BLOCK) return HT_OK;
  	    ctrl->state = (status == HT_OK) ? FTP_NEED_DCON : FTP_ERROR;
  	    break;
  
  	  case FTP_NEED_DCON:
+ 	    if (PROT_TRACE) HTTrace("FTP Event... now in state FTP_NEED_DCON\n");
  	    status = HTFTPDataConnection(request, cnet, ctrl, data);
  	    if (status == HT_WOULD_BLOCK) return HT_OK;
  	    if (status == HT_OK)
***************
*** 1414,1419 ****
--- 1522,1528 ----
  	    break;
  
  	  case FTP_NEED_DATA:
+ 	    if (PROT_TRACE) HTTrace("FTP Event... now in state FTP_NEED_DATA\n");
  	    status = HTFTPGetData(request, cnet, soc, ctrl, data);
   	    if (status == HT_WOULD_BLOCK) return HT_OK;
  	    if (status == HT_LOADED)
***************
*** 1428,1468 ****
  	    break;
  
  	  case FTP_NEED_SERVER:
  	    status = HTFTPServerInfo(request, cnet, ctrl, data);
   	    if (status == HT_WOULD_BLOCK) return HT_OK;
  	    ctrl->state = FTP_NEED_DATA;
  	    break;
  
  	  case FTP_SUCCESS:
! 	    if (HTRequest_isPostWeb(request)) {
! 		BOOL main_dest = HTRequest_isMainDestination(request);
! 		if (HTRequest_isDestination(request)) {
! 		    HTRequest * source = HTRequest_source(request);
! 		    HTLink *link = HTLink_find((HTAnchor *) HTRequest_anchor(source),
! 					       (HTAnchor *) anchor);
! 		    HTLink_setResult(link, HT_LINK_OK);
! 		}
! 		HTRequest_removeDestination(request);
! 		FTPCleanup(request, main_dest ? HT_LOADED : HT_IGNORE);
! 	    } else
  		FTPCleanup(request, HT_LOADED);
  	    return HT_OK;
  	    break;
  	    
  	  case FTP_ERROR:
! 	    /* Clean up the other connections or just this one */
! 	    if (HTRequest_isPostWeb(request)) {
! 		BOOL main_dest = HTRequest_isMainDestination(request);
! 		HTRequest_killPostWeb(request);
! 		if (HTRequest_isDestination(request)) {
! 		    HTRequest * source = HTRequest_source(request);
! 		    HTLink *link = HTLink_find((HTAnchor *) HTRequest_anchor(source),
! 					       (HTAnchor *) anchor);
! 		    HTLink_setResult(link, HT_LINK_ERROR);
! 		}
! 		HTRequest_removeDestination(request);
! 		FTPCleanup(request, main_dest ? HT_ERROR : HT_IGNORE);
! 	    } else
  		FTPCleanup(request, HT_ERROR);
  	    return HT_OK;
  	    break;
--- 1537,1556 ----
  	    break;
  
  	  case FTP_NEED_SERVER:
+ 	    if (PROT_TRACE) HTTrace("FTP Event... now in state FTP_NEED_SERVER\n");
  	    status = HTFTPServerInfo(request, cnet, ctrl, data);
  	    if (status == HT_WOULD_BLOCK) return HT_OK;
  	    ctrl->state = FTP_NEED_DATA;
  	    break;
  
  	  case FTP_SUCCESS:
! 	    if (PROT_TRACE) HTTrace("FTP Event... now in state FTP_SUCCESS\n");
  	    FTPCleanup(request, HT_LOADED);
  	    return HT_OK;
  	    break;
  	    
  	  case FTP_ERROR:
! 	    if (PROT_TRACE) HTTrace("FTP Event... now in state FTP_ERROR\n");
  	    FTPCleanup(request, HT_ERROR);
  	    return HT_OK;
  	    break;
***************
*** 1470,1472 ****
--- 1558,1569 ----
      } /* End of while(1) */
  }
  
+ PUBLIC void HTFTP_setTransferMode(FTPTransferMode mode)
+ {
+     g_FTPTransferMode = mode;
+ }
+ 
+ PUBLIC FTPTransferMode HTFTP_transferMode (void)
+ {
+     return g_FTPTransferMode;
+ }
Index: Library/src/HTFTP.html
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTFTP.html,v
retrieving revision 2.37
retrieving revision 2.38
diff -w -c -r2.37 -r2.38
*** HTFTP.html	1997/02/16 18:42:14	2.37
--- HTFTP.html	1998/03/20 17:52:53	2.38
***************
*** 46,58 ****
  #define MAX_FTP_LINE	128			 /* Don't use more than this */
  </PRE>
  
  <PRE>
  #endif
  </PRE>
  
  <HR>
  <ADDRESS>
! @(#) $Id: HTFTP.html,v 2.37 1997/02/16 18:42:14 frystyk Exp $
  </ADDRESS>
  </BODY>
  </HTML>
--- 46,78 ----
  #define MAX_FTP_LINE	128			 /* Don't use more than this */
  </PRE>
  
+ <H2>
+   Global Transfer Mode
+ </H2>
+ 
+ Can be used to set the default transfer mode overruling what may be
+ indicated in the FTP URL.<P>
+ Added by Neil Griffin, <a href="http://www.gainsoft.com">GAIN Software</a>
+ 
+ <PRE>
+ typedef enum _FTPTransferMode {
+     FTP_DEFAULT_TRANSFER_MODE   = 0,
+     FTP_ASCII_TRANSFER_MODE     = 1,
+     FTP_BINARY_TRANSFER_MODE    = 2,
+     FTP_DIR_TRANSFER_MODE       = 3
+ } FTPTransferMode;
+ 
+ extern FTPTransferMode HTFTP_transferMode (void);
+ extern void HTFTP_setTransferMode (FTPTransferMode mode);
+ </PRE>
+ 
  <PRE>
  #endif
  </PRE>
  
  <HR>
  <ADDRESS>
! @(#) $Id: HTFTP.html,v 2.38 1998/03/20 17:52:53 frystyk Exp $
  </ADDRESS>
  </BODY>
  </HTML>
Index: Library/src/HTFile.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTFile.c,v
retrieving revision 1.140
retrieving revision 1.141
diff -w -c -r1.140 -r1.141
*** HTFile.c	1998/03/04 15:46:19	1.140
--- HTFile.c	1998/03/22 21:39:38	1.141
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTFile.c,v 1.140 1998/03/04 15:46:19 frystyk Exp $
  **
  **	This is unix-specific code in general, with some VMS bits.
  **	These are routines for file access used by browsers.
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTFile.c,v 1.141 1998/03/22 21:39:38 frystyk Exp $
  **
  **	This is unix-specific code in general, with some VMS bits.
  **	These are routines for file access used by browsers.
***************
*** 351,357 ****
  PRIVATE int ReturnEvent (HTTimer * timer, void * param, HTEventType type)
  {
      file_info * file = (file_info *) param;
!     if (timer != file->timer) HTDebugBreak();
      if (PROT_TRACE) HTTrace("HTLoadFile.. Continuing %p with timer %p\n", file, timer);
  
      /*
--- 351,358 ----
  PRIVATE int ReturnEvent (HTTimer * timer, void * param, HTEventType type)
  {
      file_info * file = (file_info *) param;
!     if (timer != file->timer)
! 	HTDebugBreak(__FILE__, __LINE__, "File timer %p not in sync\n", timer);
      if (PROT_TRACE) HTTrace("HTLoadFile.. Continuing %p with timer %p\n", file, timer);
  
      /*
Index: Library/src/HTFilter.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTFilter.c,v
retrieving revision 2.25
retrieving revision 2.26
diff -w -c -r2.25 -r2.26
*** HTFilter.c	1998/03/09 15:31:54	2.25
--- HTFilter.c	1998/03/20 17:52:54	2.26
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTFilter.c,v 2.25 1998/03/09 15:31:54 frystyk Exp $
  **
  **	This module implrments a set of default filters that can be registerd
  **	as BEFORE and AFTER filters to the Net manager
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTFilter.c,v 2.26 1998/03/20 17:52:54 frystyk Exp $
  **
  **	This module implrments a set of default filters that can be registerd
  **	as BEFORE and AFTER filters to the Net manager
***************
*** 56,62 ****
  	*/
  	char * path =
  	    HTParse(addr, "", PARSE_HOST + PARSE_PATH + PARSE_PUNCTUATION);
! 	char * gatewayed = HTParse(path+1, physical, PARSE_ALL);
  	HTAnchor_setPhysical(anchor, gatewayed);
  	HT_FREE(path);
  	HT_FREE(gatewayed);
--- 56,62 ----
  	*/
  	char * path =
  	    HTParse(addr, "", PARSE_HOST + PARSE_PATH + PARSE_PUNCTUATION);
! 	char * gatewayed = HTParse((*path=='/') ? path+1 : path, physical, PARSE_ALL);
  	HTAnchor_setPhysical(anchor, gatewayed);
  	HT_FREE(path);
  	HT_FREE(gatewayed);
Index: Library/src/HTHome.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTHome.c,v
retrieving revision 2.26
retrieving revision 2.27
diff -w -c -r2.26 -r2.27
*** HTHome.c	1996/11/30 23:31:26	2.26
--- HTHome.c	1998/03/20 17:52:54	2.27
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTHome.c,v 2.26 1996/11/30 23:31:26 frystyk Exp $
  **
  ** Authors
  **	TBL	Tim Berners-Lee timbl@w3.org
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTHome.c,v 2.27 1998/03/20 17:52:54 frystyk Exp $
  **
  ** Authors
  **	TBL	Tim Berners-Lee timbl@w3.org
***************
*** 198,204 ****
--- 198,208 ----
  	char * result;
  	if (!(result = (char *) HT_MALLOC(strlen(tmpurl)+20)))
  	    HT_OUTOFMEM("HTTmpAnchor");
+ #ifdef HAVE_LONG_TIME_T
  	sprintf(result, "%s.%ld.%d", tmpurl, t, offset++);
+ #else
+ 	sprintf(result, "%s.%d.%d", tmpurl, t, offset++);
+ #endif
  	if (APP_TRACE) HTTrace("Tmp Anchor.. With location `%s\'\n", result);
  	return HTAnchor_parent(HTAnchor_findAddress(result));
  	HT_FREE(result);
Index: Library/src/HTHost.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTHost.c,v
retrieving revision 2.41
retrieving revision 2.43
diff -w -c -r2.41 -r2.43
*** HTHost.c	1998/03/05 21:56:16	2.41
--- HTHost.c	1998/03/22 21:39:39	2.43
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTHost.c,v 2.41 1998/03/05 21:56:16 frystyk Exp $
  **
  **	This object manages the information that we know about a remote host.
  **	This can for example be what type of host it is, and what version
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTHost.c,v 2.43 1998/03/22 21:39:39 frystyk Exp $
  **
  **	This object manages the information that we know about a remote host.
  **	This can for example be what type of host it is, and what version
***************
*** 172,179 ****
  			HTAnchor_physical(HTRequest_anchor(HTNet_request(targetNet))));
  	    return (*targetNet->event.cbf)(HTChannel_socket(host->channel), targetNet->event.param, type);
  	}
! 	HTTrace("Host Event.. Who wants to write to `%s\'?\n", host->hostname);
  	return HT_ERROR;
      } else if (type == HTEvent_TIMEOUT) {
  
  	if (CORE_TRACE)
--- 172,184 ----
  			HTAnchor_physical(HTRequest_anchor(HTNet_request(targetNet))));
  	    return (*targetNet->event.cbf)(HTChannel_socket(host->channel), targetNet->event.param, type);
  	}
! #if 0
! 	HTDebugBreak(__FILE__, __LINE__, "Host %p (%s) has no target\n",
! 		     host, host->hostname ? host->hostname : "<none>");
  	return HT_ERROR;
+ #else
+ 	return HT_OK;
+ #endif
      } else if (type == HTEvent_TIMEOUT) {
  
  	if (CORE_TRACE)
***************
*** 181,188 ****
  		    host->hostname);
  
      } else {
! 	HTTrace("Don't know how to handle OOB data from `%s\'?\n", 
! 		host->hostname);
      }
      return HT_OK;
  }
--- 186,192 ----
  		    host->hostname);
  
      } else {
! 	HTDebugBreak(__FILE__, __LINE__, "Don't know how to handle OOB data from `%s\'?\n", host->hostname);
      }
      return HT_OK;
  }
***************
*** 428,434 ****
  }
  
  /*
! **	Get and set the cache timeout for persistent entries.
  **	The default value is TCP_TIMEOUT
  */
  PUBLIC void HTHost_setPersistTimeout (time_t timeout)
--- 432,438 ----
  }
  
  /*
! **	Get and set the cache timeout fHTor persistent entries.
  **	The default value is TCP_TIMEOUT
  */
  PUBLIC void HTHost_setPersistTimeout (time_t timeout)
***************
*** 882,887 ****
--- 886,892 ----
      if (host && net) {
  	int status = HT_OK;
  	BOOL doit = (host->doit==net);
+ 	BOOL connector = (!host->lock || (host->lock && host->lock==net));
  
  	/*
  	**  If we don't have a socket already then check to see if we can get
***************
*** 898,904 ****
  	/*
  	**  Add net object to either active or pending queue.
  	*/
! 	if (_roomInPipe(host) && (HTList_isEmpty(host->pending) || doit)) {
  	    if (doit) host->doit = NULL;
  	    if (!host->pipeline) host->pipeline = HTList_new();
  	    HTList_addObject(host->pipeline, net);
--- 903,909 ----
  	/*
  	**  Add net object to either active or pending queue.
  	*/
! 	if (_roomInPipe(host) && (HTList_isEmpty(host->pending) || doit) && connector) {
  	    if (doit) host->doit = NULL;
  	    if (!host->pipeline) host->pipeline = HTList_new();
  	    HTList_addObject(host->pipeline, net);
***************
*** 989,994 ****
--- 994,1000 ----
              return YES;
          } else {
              if (CORE_TRACE) HTTrace("Host Object. closing socket %d\n", HTChannel_socket(host->channel));
+ 	    HTChannel_setSemaphore(host->channel, 0);
  	    HTHost_clearChannel(host, status);
          }
      }
***************
*** 998,1006 ****
  PUBLIC BOOL HTHost_deleteNet (HTHost * host, HTNet * net)
  {
      if (host && net) {
-         if (CORE_TRACE) HTTrace("Host info... Remove %p from pipe\n", net);
  	HTList_removeObject(host->pipeline, net);
  	HTList_removeObject(host->pending, net); /* just to make sure */
  	return YES;
      }
      return NO;
--- 1004,1012 ----
  PUBLIC BOOL HTHost_deleteNet (HTHost * host, HTNet * net)
  {
      if (host && net) {
  	HTList_removeObject(host->pipeline, net);
  	HTList_removeObject(host->pending, net); /* just to make sure */
+ 	if (CORE_TRACE) HTTrace("Host info... Removed %p from pipe\n", net);
  	return YES;
      }
      return NO;
***************
*** 1152,1162 ****
  */
  PUBLIC int HTHost_connect (HTHost * host, HTNet * net, char * url, HTProtocolId port)
  {
      int status;
      status = HTDoConnect(net, url, port);
!     if (status == HT_OK) return HT_OK;
!     if (status == HT_WOULD_BLOCK || status == HT_PENDING)
  	return HT_WOULD_BLOCK;
      return HT_ERROR; /* @@@ - some more deletion and stuff here? */
  }
  
--- 1158,1192 ----
  */
  PUBLIC int HTHost_connect (HTHost * host, HTNet * net, char * url, HTProtocolId port)
  {
+     HTRequest * request = HTNet_request(net);
      int status;
+     if (!host) {
+ 	HTProtocol * protocol = HTNet_protocol(net);
+ 	if ((host = HTHost_newWParse(request, url, HTProtocol_id(protocol))) == NULL)
+ 	    return NO;
+ 	if (!host->channel) {
+ 	    host->forceWriteFlush = YES;
+ 	    host->lock = net;
+ 	}
+ 	HTNet_setHost(net, host);
+     }
+ 
+     if (!host->lock || (host->lock && host->lock == net)) {
  	status = HTDoConnect(net, url, port);
! 	if (status == HT_OK) {
! 	    host->lock = NULL;
! 	    return HT_OK;
! 	}
! 	if (status == HT_WOULD_BLOCK) {
! 	    host->lock = net;
  	    return HT_WOULD_BLOCK;
+ 	}
+ 	if (status == HT_PENDING) return HT_WOULD_BLOCK;
+     } else {
+ 	if ((status = HTHost_addNet(host, net)) == HT_PENDING) {
+ 	    return HT_PENDING;
+ 	}
+     }
      return HT_ERROR; /* @@@ - some more deletion and stuff here? */
  }
  
***************
*** 1478,1484 ****
    HTRequest *request;
  
    if (!ActivateReqCBF) {
!     if (CORE_TRACE) HTTrace("HTHost....... No ActivateRequest "
                              "callback handler registered\n");
      return -1;
    }
--- 1508,1514 ----
    HTRequest *request;
  
    if (!ActivateReqCBF) {
!     if (CORE_TRACE) HTTrace("HTHost...... No ActivateRequest "
                              "callback handler registered\n");
      return -1;
    }
Index: Library/src/HTHstMan.html
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTHstMan.html,v
retrieving revision 2.12
retrieving revision 2.13
diff -w -c -r2.12 -r2.13
*** HTHstMan.html	1998/02/05 21:25:03	2.12
--- HTHstMan.html	1998/03/20 17:52:56	2.13
***************
*** 71,76 ****
--- 71,77 ----
      HTList *		pipeline;		 /* Pipe line of net objects */
      HTList *		pending;	      /* List of pending Net objects */
      HTNet *             doit;               /* Transfer from pending to pipe */ 
+     HTNet *             lock;             /* This is a kludge! */
      BOOL		persistent;
      HTTransportMode	mode;	      			   /* Supported mode */
      HTTimer *           timer;         /* Timer for handling idle connection */
***************
*** 114,119 ****
  <P>
    <HR>
  <ADDRESS>
!   @(#) $Id: HTHstMan.html,v 2.12 1998/02/05 21:25:03 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
--- 115,120 ----
  <P>
    <HR>
  <ADDRESS>
!   @(#) $Id: HTHstMan.html,v 2.13 1998/03/20 17:52:56 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
Index: Library/src/HTInit.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTInit.c,v
retrieving revision 2.86
retrieving revision 2.87
diff -w -c -r2.86 -r2.87
*** HTInit.c	1998/03/09 15:31:56	2.86
--- HTInit.c	1998/03/20 17:52:57	2.87
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTInit.c,v 2.86 1998/03/09 15:31:56 frystyk Exp $
  **
  **	Define a basic set of suffixes and presentations
  */
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTInit.c,v 2.87 1998/03/20 17:52:57 frystyk Exp $
  **
  **	Define a basic set of suffixes and presentations
  */
***************
*** 20,29 ****
  #include "HTInit.h"				         /* Implemented here */
  
  #ifndef W3C_ICONS
! #define W3C_ICONS	"/usr/local/share/w3c-icons"
  #endif
  
! #define ICON_LOCATION	"/internal-icon/"
  
  /* ------------------------------------------------------------------------- */
  
--- 20,29 ----
  #include "HTInit.h"				         /* Implemented here */
  
  #ifndef W3C_ICONS
! #define W3C_ICONS	"w3c-icons"
  #endif
  
! #define ICON_LOCATION	"/icons/"
  
  /* ------------------------------------------------------------------------- */
  
***************
*** 337,343 ****
      HTIcon_add("unknown.xbm",	prefix,	"TN",	"application/x-gopher-tn3270");
  
      /* Add global  mapping to where to find the internal icons */
!     HTRule_addGlobal(HT_Pass, ICON_LOCATION, W3C_ICONS);
  }
  
  /*	REGISTER ALL HTTP/1.1 MIME HEADERS
--- 337,365 ----
      HTIcon_add("unknown.xbm",	prefix,	"TN",	"application/x-gopher-tn3270");
  
      /* Add global  mapping to where to find the internal icons */
!     {
! 	char * curdir = HTGetCurrentDirectoryURL();
! 	char * virtual = HTParse(ICON_LOCATION, curdir,
! 				 PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
! 	char * physical = NULL;
! 	StrAllocCat(virtual, "*");
! 
! 	{
! 	    char * str = NULL;
! 	    if ((str = (char *) HT_MALLOC(strlen(W3C_ICONS) + 4)) == NULL)
! 		HT_OUTOFMEM("HTIconInit");
! 	    strcpy(str, W3C_ICONS);
! 	    if (*(str + strlen(str) - 1) != '/') strcat(str, "/");
! 	    strcat(str, "*");
! 	    physical = HTParse(str, curdir,
! 			       PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
! 	    HT_FREE(str);
! 	}
! 	HTRule_addGlobal(HT_Pass, virtual, physical);
! 	HT_FREE(virtual);
! 	HT_FREE(physical);
! 	HT_FREE(curdir);
!     }
  }
  
  /*	REGISTER ALL HTTP/1.1 MIME HEADERS
Index: Library/src/HTList.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTList.c,v
retrieving revision 2.29
retrieving revision 2.30
diff -w -c -r2.29 -r2.30
*** HTList.c	1997/02/16 17:49:20	2.29
--- HTList.c	1998/03/20 17:52:58	2.30
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTList.c,v 2.29 1997/02/16 17:49:20 frystyk Exp $
  **
  **	A list is represented as a sequence of linked nodes of type HTList.
  **	The first node is a header which contains no object.
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTList.c,v 2.30 1998/03/20 17:52:58 frystyk Exp $
  **
  **	A list is represented as a sequence of linked nodes of type HTList.
  **	The first node is a header which contains no object.
***************
*** 95,112 ****
  PUBLIC BOOL HTList_removeObjectAll (HTList * me, void * oldObject)
  {
      BOOL found = NO;
!     if (me) {
! 	HTList *previous;
! 	while (me->next) {
! 	    previous = me;
! 	    me = me->next;
! 	    if (me->object == oldObject) {
! 		previous->next = me->next;
! 		HT_FREE(me);
  		found = YES;	/* At least one object found */
  	    }
  	}
      }
      return found;
  }
  
--- 95,120 ----
  PUBLIC BOOL HTList_removeObjectAll (HTList * me, void * oldObject)
  {
   BOOL found = NO;
! 
!  if (me)
!    {
!     HTList* i;
! 
!     while ((i = me->next))
!       {
!        if (i->object == oldObject)
! 	 {
! 	  me->next = i->next;
! 	  HT_FREE(i);
  	  found = YES;	/* At least one object found */
  	 }
+         else
+ 	 {
+ 	  me = i;
+ 	 }
        }
     }
+ 
   return found;
  }
  
Index: Library/src/HTMIME.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTMIME.c,v
retrieving revision 2.83
retrieving revision 2.85
diff -w -c -r2.83 -r2.85
*** HTMIME.c	1998/03/05 21:56:19	2.83
--- HTMIME.c	1998/03/22 21:39:40	2.85
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTMIME.c,v 2.83 1998/03/05 21:56:19 frystyk Exp $
  **
  **	This is RFC 1341-specific code.
  **	The input stream pushed into this parser is assumed to be
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTMIME.c,v 2.85 1998/03/22 21:39:40 frystyk Exp $
  **
  **	This is RFC 1341-specific code.
  **	The input stream pushed into this parser is assumed to be
***************
*** 106,112 ****
      */
      {
  	HTHost * host = HTNet_host(me->net);
! 	if (length<=0 && te==NULL &&
  	    HTHost_isPersistent(host) && !HTHost_closeNotification(host)) {
  	    if (format != WWW_UNKNOWN) {
  		if (STREAM_TRACE) HTTrace("MIME Parser. BAD - there seems to be a body but no length. This must be an HTTP/1.0 server pretending that it is HTTP/1.1\n");
--- 106,112 ----
      */
      {
  	HTHost * host = HTNet_host(me->net);
! 	if (length<0 && te==NULL &&
  	    HTHost_isPersistent(host) && !HTHost_closeNotification(host)) {
  	    if (format != WWW_UNKNOWN) {
  		if (STREAM_TRACE) HTTrace("MIME Parser. BAD - there seems to be a body but no length. This must be an HTTP/1.0 server pretending that it is HTTP/1.1\n");
***************
*** 200,205 ****
--- 200,210 ----
  	    me->target = target;
      }
  
+ 
+     /*
+     ** If we for some reason couldn't find a target stream
+     */
+     if (!me->target) me->target = HTBlackHole();
      return HT_OK;
  }
  
Index: Library/src/HTML.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTML.c,v
retrieving revision 1.70
retrieving revision 1.71
diff -w -c -r1.70 -r1.71
*** HTML.c	1998/02/25 20:48:31	1.70
--- HTML.c	1998/03/20 17:53:00	1.71
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTML.c,v 1.70 1998/02/25 20:48:31 frystyk Exp $
  **
  **	This generates of a hypertext object.  It converts from the
  **	structured stream interface fro HTMl events into the style-
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTML.c,v 1.71 1998/03/20 17:53:00 frystyk Exp $
  **
  **	This generates of a hypertext object.  It converts from the
  **	structured stream interface fro HTMl events into the style-
***************
*** 34,40 ****
  PRIVATE HTStyle *styles[HTMLP_ELEMENTS];
  PRIVATE HTStyle *default_style;
  
! #define TAB	'\0'
  
  /*		HTML Object
  **		-----------
--- 34,40 ----
  PRIVATE HTStyle *styles[HTMLP_ELEMENTS];
  PRIVATE HTStyle *default_style;
  
! #define HTTAB	'\0'
  
  /*		HTML Object
  **		-----------
***************
*** 304,311 ****
  **			A C T I O N 	R O U T I N E S
  */
  
! PRIVATE int HTML_put_character (HTStructured * me, char c)
  {
      switch (me->sp[0].tag_number) {
      case HTML_COMMENT:
      	break;					/* Do Nothing */
--- 304,313 ----
  **			A C T I O N 	R O U T I N E S
  */
  
! PRIVATE int HTML_write (HTStructured * me, const char * b, int l)
  {
+     while (l-- > 0) {
+ 	const char c = *b++;
  	switch (me->sp[0].tag_number) {
  	case HTML_COMMENT:
  	    break;					/* Do Nothing */
***************
*** 314,326 ****
      	HTChunk_putb(me->title, &c, 1);
  	break;
  
- 	
      case HTML_LISTING:				/* Litteral text */
      case HTML_XMP:
      case HTML_PLAINTEXT:
      case HTML_PRE:
! /*	We guarrantee that the style is up-to-date in begin_litteral
! */
      	HText_appendCharacter(me->text, c);
  	break;
  	
--- 316,326 ----
  	    HTChunk_putb(me->title, &c, 1);
  	    break;
  	
  	case HTML_LISTING:				/* Litteral text */
  	case HTML_XMP:
  	case HTML_PLAINTEXT:
  	case HTML_PRE:
! 	    /* We guarrantee that the style is up-to-date in begin_litteral */
  	    HText_appendCharacter(me->text, c);
  	    break;
  	
***************
*** 329,335 ****
  	    if ((c=='\n') || (c==' ')) return HT_OK;	/* Ignore it */
  	    UPDATE_STYLE;
  	}
! 	if (c == TAB)
  	    HText_appendCharacter(me->text, '\t');
  	else if (isspace((int) c)) {
  	    if (me->in_word) {
--- 329,335 ----
  		if ((c=='\n') || (c==' ')) return HT_OK;	/* Ignore it */
  		UPDATE_STYLE;
  	    }
! 	    if (c == HTTAB)
  		HText_appendCharacter(me->text, '\t');
  	    else if (isspace((int) c)) {
  		if (me->in_word) {
***************
*** 340,360 ****
  	    HText_appendCharacter(me->text, c);
  	    me->in_word = YES;
  	}
!     } /* end switch */
      return HT_OK;
  }
  
! 
! PRIVATE int HTML_write (HTStructured * me, const char * b, int l)
  {
!     while (l-- > 0) HTML_put_character(me, *b++);
!     return HT_OK;
  }
  
  PRIVATE int HTML_put_string (HTStructured * me, const char* s)
  {
!     while (*s) HTML_put_character(me, *s++);
!     return HT_OK;
  }
  
  /*	Start Element
--- 340,359 ----
  		HText_appendCharacter(me->text, c);
  		me->in_word = YES;
  	    }
! 	}
!     }
      return HT_OK;
  }
  
! PRIVATE int HTML_put_character (HTStructured * me, char c)
  {
!     return HTML_write(me, &c, sizeof(char));
  }
  
+ 
  PRIVATE int HTML_put_string (HTStructured * me, const char* s)
  {
!     return HTML_write(me, s, (int) strlen(s));
  }
  
  /*	Start Element
***************
*** 499,505 ****
  	
      case HTML_DD:
          UPDATE_STYLE;
! 	HTML_put_character(me, TAB);	/* Just tab out one stop */
  	me->in_word = NO;
  	break;
  
--- 498,504 ----
  	
      case HTML_DD:
          UPDATE_STYLE;
! 	HTML_put_character(me, HTTAB);	/* Just tab out one stop */
  	me->in_word = NO;
  	break;
  
***************
*** 515,521 ****
  	if (me->sp[0].tag_number != HTML_DIR)
  	    HText_appendParagraph(me->text);
  	else
! 	    HText_appendCharacter(me->text, TAB);
  	me->in_word = NO;
  	break;
  	
--- 514,520 ----
  	if (me->sp[0].tag_number != HTML_DIR)
  	    HText_appendParagraph(me->text);
  	else
! 	    HText_appendCharacter(me->text, HTTAB);
  	me->in_word = NO;
  	break;
  	
Index: Library/src/HTMemLog.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTMemLog.c,v
retrieving revision 2.15
retrieving revision 2.16
diff -w -c -r2.15 -r2.16
*** HTMemLog.c	1998/02/25 20:48:35	2.15
--- HTMemLog.c	1998/03/20 17:53:01	2.16
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1996.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTMemLog.c,v 2.15 1998/02/25 20:48:35 frystyk Exp $
  **
  **      26 Nov 96 (EGP)	started
  */
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1996.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTMemLog.c,v 2.16 1998/03/20 17:53:01 frystyk Exp $
  **
  **      26 Nov 96 (EGP)	started
  */
***************
*** 163,170 ****
      syslog(LOG_DEBUG, "%s\n", buff);
  #else /* USE_SYSLOG */
      HTMemLog_addTime();
! 
      ret = sprintf(buff, " %d ", len);
      HTMemLog_add(buff, ret);
  
      if (fmt) {
--- 163,173 ----
      syslog(LOG_DEBUG, "%s\n", buff);
  #else /* USE_SYSLOG */
      HTMemLog_addTime();
! #ifdef HAVE_LONG_SIZE_T
!     ret = sprintf(buff, " %ld ", len);
! #else
      ret = sprintf(buff, " %d ", len);
+ #endif
      HTMemLog_add(buff, ret);
  
      if (fmt) {
Index: Library/src/HTMemory.html
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTMemory.html,v
retrieving revision 2.10
retrieving revision 2.11
diff -w -c -r2.10 -r2.11
*** HTMemory.html	1997/02/16 18:42:37	2.10
--- HTMemory.html	1998/03/22 21:39:41	2.11
***************
*** 41,46 ****
--- 41,48 ----
  <PRE>
  #ifndef HTMEMORY_H
  #define HTMEMORY_H
+ 
+ #include "<A HREF="HTUtils.html">HTUtils.h</A>"
  </PRE>
  <H2>
    <A NAME="Allocation">Allocation, Reallocation and De-allocation</A>
***************
*** 64,77 ****
  malloc and alloc then you can just use that instead of the HTMemory_* function.
  You can of course also provide your own methods as well.
  <PRE>
- #ifndef __FILE__
- #define __FILE__ ""
- #endif
- 
- #ifndef __LINE__
- #define __LINE__ 0L
- #endif
- 
  #define HT_MALLOC(size)		HTMemory_malloc((size))
  #define HT_CALLOC(count, size)	HTMemory_calloc((count), (size))
  #define HT_REALLOC(ptr, size)	HTMemory_realloc((ptr), (size))
--- 66,71 ----
***************
*** 152,157 ****
  <P>
    <HR>
  <ADDRESS>
!   @(#) $Id: HTMemory.html,v 2.10 1997/02/16 18:42:37 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
--- 146,151 ----
  <P>
    <HR>
  <ADDRESS>
!   @(#) $Id: HTMemory.html,v 2.11 1998/03/22 21:39:41 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
Index: Library/src/HTParse.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTParse.c,v
retrieving revision 2.73
retrieving revision 2.74
diff -w -c -r2.73 -r2.74
*** HTParse.c	1998/01/22 21:15:00	2.73
--- HTParse.c	1998/03/22 21:39:42	2.74
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTParse.c,v 2.73 1998/01/22 21:15:00 frystyk Exp $
  **
  ** history:
  **	May 12 94	TAB added as legal char in HTCleanTelnetString
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTParse.c,v 2.74 1998/03/22 21:39:42 frystyk Exp $
  **
  ** history:
  **	May 12 94	TAB added as legal char in HTCleanTelnetString
***************
*** 45,57 ****
  	parts->fragment = p;
      }
      
!     /* 
!     ** Look for any spaces. This is very bad for pipelining as it
!     ** makes the request invalid
!     */
      if ((p = strchr(name, ' ')) != NULL) *p++ = '\0';
      
      for(p=name; *p; p++) {
  	if (*p=='/' || *p=='#' || *p=='?')
  	    break;
  	if (*p==':') {
--- 45,64 ----
  	parts->fragment = p;
      }
      
!     
      if ((p = strchr(name, ' ')) != NULL) *p++ = '\0';    
      
      for(p=name; *p; p++) {
+ 
+ 	/* 
+ 	** Look for any whitespace. This is very bad for pipelining as it
+ 	** makes the request invalid
+ 	*/
+ 	if (isspace(*p)) {
+ 	    char *orig=p, *dest=p+1;
+ 	    while ((*orig++ = *dest++));
+ 	    p = p-1;
+ 	}
  	if (*p=='/' || *p=='#' || *p=='?')
  	    break;
  	if (*p==':') {
Index: Library/src/HTProfil.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTProfil.c,v
retrieving revision 2.15
retrieving revision 2.16
diff -w -c -r2.15 -r2.16
*** HTProfil.c	1997/12/16 21:09:25	2.15
--- HTProfil.c	1998/03/20 17:53:02	2.16
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTProfil.c,v 2.15 1997/12/16 21:09:25 frystyk Exp $
  **
  **	Defines a set of application profiles
  */
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTProfil.c,v 2.16 1998/03/20 17:53:02 frystyk Exp $
  **
  **	Defines a set of application profiles
  */
***************
*** 44,49 ****
--- 44,53 ----
      /* If the Library is not already initialized then do it */
      if (!HTLib_isInitialized()) HTLibInit(AppName, AppVersion);
  
+     /* Register the default set of messages and dialog functions */
+     HTAlertInit();
+     HTAlert_setInteractive(YES);
+ 
      if (!converters) converters = HTList_new();
      if (!transfer_encodings) transfer_encodings = HTList_new();
      if (!content_encodings) content_encodings = HTList_new();
***************
*** 94,103 ****
  
      /* Register the default set of Icons for directory listings */
      HTIconInit(NULL);
- 
-     /* Register the default set of messages and dialog functions */
-     HTAlertInit();
-     HTAlert_setInteractive(YES);
  }
  
  PUBLIC void HTProfile_newClient (const char * AppName, const char * AppVersion)
--- 98,103 ----
Index: Library/src/HTReq.html
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTReq.html,v
retrieving revision 2.54
retrieving revision 2.55
diff -w -c -r2.54 -r2.55
*** HTReq.html	1998/03/05 21:56:22	2.54
--- HTReq.html	1998/03/20 17:53:04	2.55
***************
*** 256,261 ****
--- 256,262 ----
  <PRE>
  extern HTList * HTRequest_error (HTRequest * request);
  extern void HTRequest_setError	(HTRequest * request, HTList * list);
+ extern void HTRequest_deleteAllErrors (HTRequest * request);
  </PRE>
  <P>
  These are the cover functions that go directly to the
***************
*** 1031,1036 ****
  <P>
    <HR>
  <ADDRESS>
!   @(#) $Id: HTReq.html,v 2.54 1998/03/05 21:56:22 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
--- 1032,1037 ----
  <P>
    <HR>
  <ADDRESS>
!   @(#) $Id: HTReq.html,v 2.55 1998/03/20 17:53:04 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
Index: Library/src/HTReqMan.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTReqMan.c,v
retrieving revision 2.65
retrieving revision 2.66
diff -w -c -r2.65 -r2.66
*** HTReqMan.c	1998/02/27 23:42:11	2.65
--- HTReqMan.c	1998/03/20 17:53:05	2.66
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTReqMan.c,v 2.65 1998/02/27 23:42:11 frystyk Exp $
  **
  ** Authors
  **	TBL	Tim Berners-Lee timbl@w3.org
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTReqMan.c,v 2.66 1998/03/20 17:53:05 frystyk Exp $
  **
  ** Authors
  **	TBL	Tim Berners-Lee timbl@w3.org
***************
*** 368,373 ****
--- 368,382 ----
  {
      if (me) me->error_stack = list;
  }
+ 
+ /* begin _GM_ */
+ /* Note: libwww bug ID: GM11 */
+ PUBLIC void HTRequest_deleteAllErrors (HTRequest * request)
+ {
+     HTError_deleteAll(request->error_stack);
+     HTRequest_setError(request, NULL);
+ }
+ /* end _GM_ */
  
  PUBLIC BOOL HTRequest_addError (HTRequest * 	me,
  				HTSeverity	severity,
Index: Library/src/HTTCP.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTTCP.c,v
retrieving revision 2.106
retrieving revision 2.107
diff -w -c -r2.106 -r2.107
*** HTTCP.c	1998/02/07 23:59:25	2.106
--- HTTCP.c	1998/03/20 17:53:06	2.107
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTTCP.c,v 2.106 1998/02/07 23:59:25 frystyk Exp $
  **
  **	This code is in common between client and server sides.
  **
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTTCP.c,v 2.107 1998/03/20 17:53:06 frystyk Exp $
  **
  **	This code is in common between client and server sides.
  **
***************
*** 186,202 ****
      char * hostname = HTHost_name(me);
  
      /* Jump into the state machine */
-     if (!me) {
- 	char * proxy = HTRequest_proxy(request);
- 	HTProtocol * protocol = HTNet_protocol(net);
- 
- 	/* Check to see whether we connect directly or via a proxy */
- 	if ((me = HTHost_newWParse(request, proxy ? proxy : url, 
- 				   HTProtocol_id(protocol))) == NULL)
- 	    return NO;
- 
- 	net->host = me;
-     }
      while (1) {
  	switch (me->tcpstate) {
  	  case TCP_BEGIN:
--- 186,191 ----
Index: Library/src/HTTChunk.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTTChunk.c,v
retrieving revision 2.12
retrieving revision 2.13
diff -w -c -r2.12 -r2.13
*** HTTChunk.c	1998/03/05 21:56:25	2.12
--- HTTChunk.c	1998/03/22 21:39:43	2.13
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTTChunk.c,v 2.12 1998/03/05 21:56:25 frystyk Exp $
  **
  **	This stream parses a chunked transfer encoding using multiple chunks.
  **
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTTChunk.c,v 2.13 1998/03/22 21:39:43 frystyk Exp $
  **
  **	This stream parses a chunked transfer encoding using multiple chunks.
  **
***************
*** 51,60 ****
  	char *errstr = NULL;
  	me->left = strtol(line, &errstr, 16);    /* hex! */
  	if (STREAM_TRACE) HTTrace("Chunked..... `%s\' chunk size: %X\n", line, me->left);
! 	if (errstr == line) {
! 	    HTTrace("Chunked..... Received illigal chunk size: `%s\'\n", line);
! 	    return NO;
! 	}
  	if (me->left > 0) {
  	    me->total += me->left;
  
--- 51,58 ----
  	char *errstr = NULL;
  	me->left = strtol(line, &errstr, 16);    /* hex! */
  	if (STREAM_TRACE) HTTrace("Chunked..... `%s\' chunk size: %X\n", line, me->left);
! 	if (errstr == line)
! 	    HTDebugBreak(__FILE__, __LINE__, "Chunk decoder received illigal chunk size: `%s\'\n", line);
  	if (me->left > 0) {
  	    me->total += me->left;
  
Index: Library/src/HTTP.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTTP.c,v
retrieving revision 1.158
retrieving revision 1.160
diff -w -c -r1.158 -r1.160
*** HTTP.c	1998/03/04 15:46:24	1.158
--- HTTP.c	1998/03/22 21:39:45	1.160
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTTP.c,v 1.158 1998/03/04 15:46:24 frystyk Exp $
  **
  **	This module implments the HTTP protocol as a state machine
  **
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTTP.c,v 1.160 1998/03/22 21:39:45 frystyk Exp $
  **
  **	This module implments the HTTP protocol as a state machine
  **
***************
*** 771,776 ****
--- 771,777 ----
  	    /* Update where we are in the stream */
  	    l = HTHost_remainingRead(HTNet_host(HTRequest_net(me->request)));
  	    b += (length-l);
+ 	    length = l;
  
  	} else {
  	    *(me->buffer+me->buflen++) = *b;
***************
*** 793,798 ****
--- 794,802 ----
  	}
      }
  
+     if (!me->transparent && length != l)
+ 	HTHost_setConsumed(HTNet_host(HTRequest_net(me->request)), length-l);
+ 
      if (l > 0) return PUTBLOCK(b, l);
      return status;
  }
***************
*** 914,920 ****
      HTStream * input = HTRequest_inputStream(http->request);
      HTPostCallback * pcbf = HTRequest_postCallback(http->request);
  
!     if (timer != http->timer) HTDebugBreak();
      if (PROT_TRACE) HTTrace("Uploading... Flushing %p with timer %p\n", http, timer);
  
      /*
--- 918,925 ----
      HTStream * input = HTRequest_inputStream(http->request);
      HTPostCallback * pcbf = HTRequest_postCallback(http->request);
  
!     if (timer != http->timer)
! 	HTDebugBreak(__FILE__, __LINE__, "HTTP timer %p not in sync\n", timer);
      if (PROT_TRACE) HTTrace("Uploading... Flushing %p with timer %p\n", http, timer);
  
      /*
***************
*** 1000,1008 ****
  
  		/* Jump to next state */
  		http->state = HTTP_NEED_STREAM;
! 	    } else if (status == HT_WOULD_BLOCK || status == HT_PENDING)
  		return HT_OK;
! 	    else	
  		http->state = HTTP_ERROR;	       /* Error or interrupt */
  	    break;
  	    
--- 1005,1013 ----
  
  		/* Jump to next state */
  		http->state = HTTP_NEED_STREAM;
! 	    } else if (status == HT_WOULD_BLOCK || status == HT_PENDING) {
  		return HT_OK;
! 	    } else	
  		http->state = HTTP_ERROR;	       /* Error or interrupt */
  	    break;
  	    
***************
*** 1187,1194 ****
  	      break;
  
  	default:
! 	    HTTrace("bad http state %d.\n", http->state);
! 	    HTDebugBreak();
  	}
      } /* End of while(1) */
  }    
--- 1192,1198 ----
  	      break;
  
  	default:
! 	    HTDebugBreak(__FILE__, __LINE__, "Bad http state %d\n", http->state);
  	}
      } /* End of while(1) */
  }    
Index: Library/src/HTTimer.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTTimer.c,v
retrieving revision 2.18
retrieving revision 2.19
diff -w -c -r2.18 -r2.19
*** HTTimer.c	1998/02/01 19:04:20	2.18
--- HTTimer.c	1998/03/22 21:39:46	2.19
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTTimer.c,v 2.18 1998/02/01 19:04:20 frystyk Exp $
  **
  **	Updated HTEvent module 
  **	This new module combines the functions of the old HTEvent module and 
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTTimer.c,v 2.19 1998/03/22 21:39:46 frystyk Exp $
  **
  **	Updated HTEvent module 
  **	This new module combines the functions of the old HTEvent module and 
***************
*** 39,46 ****
  #if 0 /* WATCH_RECURSION */
  
  PRIVATE HTTimer * InTimer = NULL;
! #define CHECKME(timer) if (InTimer != NULL) HTDebugBreak(); InTimer = timer;
! #define CLEARME(timer) if (InTimer != timer) HTDebugBreak(); InTimer = NULL;
  #define SETME(timer) InTimer = timer;
  
  #else /* WATCH_RECURSION */
--- 39,46 ----
  #if 0 /* WATCH_RECURSION */
  
  PRIVATE HTTimer * InTimer = NULL;
! #define CHECKME(timer) if (InTimer != NULL) HTDebugBreak(__FILE__, __LINE__, "\n"); InTimer = timer;
! #define CLEARME(timer) if (InTimer != timer) HTDebugBreak(__FILE, __LINE__, "\n"); InTimer = NULL;
  #define SETME(timer) InTimer = timer;
  
  #else /* WATCH_RECURSION */
***************
*** 128,134 ****
  	/*	if a timer is specified, it should already exist
  	 */
  	if ((cur = HTList_elementOf(Timers, (void *)timer, &last)) == NULL) {
! 	    HTDebugBreak();
  	    CLEARME(timer);
  	    return NULL;
  	}
--- 128,134 ----
  	/*	if a timer is specified, it should already exist
  	 */
  	if ((cur = HTList_elementOf(Timers, (void *)timer, &last)) == NULL) {
! 	    HTDebugBreak(__FILE__, __LINE__, "Timer %p not found\n", timer);
  	    CLEARME(timer);
  	    return NULL;
  	}
***************
*** 237,243 ****
  
      timer = (HTTimer *)HTList_objectOf(cur);
      if (timer == NULL) {
! 	HTDebugBreak();
  	CLEARME(timer);
  	return HT_ERROR;
      }
--- 237,243 ----
  
      timer = (HTTimer *)HTList_objectOf(cur);
      if (timer == NULL) {
! 	HTDebugBreak(__FILE__, __LINE__, "Timer dispatch couldn't find a timer\n");
  	CLEARME(timer);
  	return HT_ERROR;
      }
Index: Library/src/HTTrace.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTTrace.c,v
retrieving revision 2.4
retrieving revision 2.5
diff -w -c -r2.4 -r2.5
*** HTTrace.c	1997/01/03 01:03:40	2.4
--- HTTrace.c	1998/03/22 21:39:47	2.5
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1996.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTTrace.c,v 2.4 1997/01/03 01:03:40 eric Exp $
  **
  **      26 Nov 96 (EGP)	moved HTTrace stuff here from HTString.c and
  **			added HTTrace_data
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1996.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTTrace.c,v 2.5 1998/03/22 21:39:47 frystyk Exp $
  **
  **      26 Nov 96 (EGP)	moved HTTrace stuff here from HTString.c and
  **			added HTTrace_data
***************
*** 71,84 ****
      return (0);
  }
  
! PUBLIC void HTDebugBreak (void)
  {
  #ifdef WWW_MSWINDOWS
      DebugBreak();
  #else /* WWW_MSWINDOWS */
!     int i;
!     i = 1/0;
!     i = 1/1;
  #endif /* !WWW_MSWINDOWS */
      return;
  }
--- 71,86 ----
      return (0);
  }
  
! PUBLIC void HTDebugBreak (char * file, unsigned long line, const char * fmt, ...)
  {
+     va_list pArgs;
+     va_start(pArgs, fmt);
+     HTTrace("%s:%ld ", file ? file : "", line);
+     HTTrace(fmt, pArgs);
  #ifdef WWW_MSWINDOWS
      DebugBreak();
  #else /* WWW_MSWINDOWS */
!     abort();
  #endif /* !WWW_MSWINDOWS */
      return;
  }
Index: Library/src/HTUtils.html
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTUtils.html,v
retrieving revision 2.80
retrieving revision 2.81
diff -w -c -r2.80 -r2.81
*** HTUtils.html	1998/02/01 19:04:21	2.80
--- HTUtils.html	1998/03/22 21:39:48	2.81
***************
*** 1,6 ****
  <HTML>
  <HEAD>
-   <!-- Changed by: Henrik Frystyk Nielsen,  6-Apr-1996 -->
    <TITLE>W3C Sample Code Library libwww General Purpose Macros</TITLE>
  </HEAD>
  <BODY>
--- 1,5 ----
***************
*** 31,37 ****
  <PRE>
  #ifndef DEBUG
  #define DEBUG	/* No one ever turns this off as trace is too important */
! extern void HTDebugBreak(void);
  #endif
  </PRE>
  <H3>
--- 30,38 ----
  <PRE>
  #ifndef DEBUG
  #define DEBUG	/* No one ever turns this off as trace is too important */
! 
! /* Call this function and the program halts */
! extern void HTDebugBreak (char * file, unsigned long line, const char * fmt, ...);
  #endif
  </PRE>
  <H3>
***************
*** 245,250 ****
--- 246,267 ----
  #endif
  </PRE>
  <H2>
+   C Preprocessor defines
+ </H2>
+ 
+ Make sure that the following macros are defined
+ 
+ <PRE>
+ #ifndef __FILE__
+ #define __FILE__ ""
+ #endif
+ 
+ #ifndef __LINE__
+ #define __LINE__ 0L
+ #endif
+ </PRE>
+ 
+ <H2>
    Max and Min values for Integers and Floating Point
  </H2>
  <PRE>
***************
*** 280,285 ****
  <P>
    <HR>
  <ADDRESS>
!   @(#) $Id: HTUtils.html,v 2.80 1998/02/01 19:04:21 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
--- 297,302 ----
  <P>
    <HR>
  <ADDRESS>
!   @(#) $Id: HTUtils.html,v 2.81 1998/03/22 21:39:48 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
Index: Library/src/HTWAIS.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTWAIS.c,v
retrieving revision 2.53
retrieving revision 2.54
diff -w -c -r2.53 -r2.54
*** HTWAIS.c	1997/11/26 16:06:02	2.53
--- HTWAIS.c	1998/03/20 17:53:10	2.54
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTWAIS.c,v 2.53 1997/11/26 16:06:02 frystyk Exp $
  **
  **	This module allows a WWW server or client to read data from a
  **	remote  WAIS server, and provide that data to a WWW client in
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTWAIS.c,v 2.54 1998/03/20 17:53:10 frystyk Exp $
  **
  **	This module allows a WWW server or client to read data from a
  **	remote  WAIS server, and provide that data to a WWW client in
***************
*** 14,25 ****
--- 14,30 ----
  **	BK	Brewster Kahle, Thinking Machines, <Brewster@think.com>
  **	TBL	Tim Berners-Lee, CERN <timbl@w3.org>
  **
+ ** Contributors
+ **	QL	QingLong, Yggdrasil Inc., <qinglong@Yggdrasil.com>
+ **
  ** History
  **	   Sep 91	TBL adapted shell-ui.c (BK) with HTRetrieve.c from WWW.
  **	   Feb 91	TBL Generated HTML cleaned up a bit (quotes, escaping)
  **			    Refers to lists of sources. 
  **	   Mar 93	TBL   Lib 2.0 compatible module made.	
  **	   May 95       CHJ modified for freeWAIS-0.5
+ **	   Jun 97	QL  modified for w3c-libwww-5.0a.
+ **	   Mar 98	QL  modified for w3c-libwww-5.1i.
  **
  ** Bugs
  **	Uses C stream i/o to read and write sockets, which won't work
***************
*** 52,94 ****
  
  
  #define DIRECTORY "/cnidr.org:210/directory-of-servers"
- /* define DIRECTORY "/quake.think.com:210/directory-of-servers" */
  
  #define BIG 1024	/* identifier size limit  @@@@@ */
  
! /*			From WAIS
! **			---------
! */
! #if 0
  #include "wais.h"
  #endif
  
  #define MAX_MESSAGE_LEN 100000
  #define CHARS_PER_PAGE 10000 /* number of chars retrieved in each request */
  #define WAISSEARCH_DATE "Fri Jul 19 1991"
  
- 
  /*			FROM WWW
  **			--------
  */
  #define BUFFER_SIZE 4096	/* Arbitrary size for efficiency */
  
  #define HEX_ESCAPE '%'
  
- /* Library include files */
- #include "sysdep.h"
- #include "WWWUtil.h"
- #include "WWWCore.h"
- #include "WWWHTML.h"
-  
  extern FILE * logfile;		/* Log file output */
  
  PRIVATE int HTMaxWAISLines = 200;/* Max number of entries from a search */
  
- PRIVATE BOOL	as_gate;	/* Client is using us as gateway */
- 
- PRIVATE char	line[2048];	/* For building strings to display */
- 				/* Must be able to take id */
  
  /* Hypertext object building machinery */
  #define PUTC(c) (*target->isa->put_character)(target, c)
--- 57,106 ----
  
  
  #define DIRECTORY "/cnidr.org:210/directory-of-servers"
  
  #define BIG 1024	/* identifier size limit  @@@@@ */
  
! /* Library include files */
! #include "sysdep.h"
! #include "WWWUtil.h"
! #include "WWWCore.h"
! #include "WWWHTML.h"
! #include "HTReqMan.h"
!  
! #ifdef HAVE_WAIS_H
  #include "wais.h"
+ #else
+ #ifdef HAVE_WAIS_WAIS_H
+ #include "wais/wais.h"
+ #else
+ #ifdef WAIS_INCLUDE
+ #include WAIS_INCLUDE
+ #endif
+ #endif
  #endif
  
+ /*			From WAIS
+ **			---------
+ */
+ #undef MAX_MESSAGE_LEN
  #define MAX_MESSAGE_LEN 100000
+ #undef CHARS_PER_PAGE
  #define CHARS_PER_PAGE   10000 /* number of chars retrieved in each request */
+ #undef WAISSEARCH_DATE
  #define WAISSEARCH_DATE "Fri Jul 19 1991"
  
  /*			FROM WWW
  **			--------
  */
  #define      BUFFER_SIZE 4096	/* Arbitrary size for efficiency */
+ #define LINE_BUFFER_SIZE 2048
  
  #define HEX_ESCAPE '%'
  
  extern FILE * logfile;            /* Log file output */
  
  PRIVATE int HTMaxWAISLines = 200; /* Max number of entries from a search */
  
  
  /* Hypertext object building machinery */
  #define PUTC(c)     (*target->isa->put_character)(target, c)
***************
*** 97,118 ****
  #define END(e) (*target->isa->end_element)(target, e)
  #define FREE_TARGET (*target->isa->_free)(target)
  
! struct _HTStructured {
! 	const HTStructuredClass *	isa;
  	/* ... */
  };
  
! struct _HTStream {
! 	const HTStreamClass *	isa;
  	/* ... */
  };
  
  
! /*								showDiags
  */
  /* modified from Jonny G's version in ui/question.c */
  
! void showDiags (
  	HTStream * 		target,
  	diagnosticRecord ** 	d)
  {
--- 109,190 ----
  #define END(e)      (*target->isa->end_element)(target, e)
  #define FREE_TARGET (*target->isa->_free)(target)
  
! 
! 
! /*
!  * Type definitions and global variables etc. local to this module
!  */
! 
! 
! /* Final states have negative value */
! typedef enum _HTWAISState
! {
!   HTWAIS_ERROR            = -2,
!   HTWAIS_OK               = -1,
!   HTWAIS_BEGIN            =  0,
!   HTWAIS_PARSING_URL      =  1,
!   HTWAIS_NEED_CONNECTION  =  2,
!   HTWAIS_NEED_REQUEST     =  3,
!   HTWAIS_NEED_RESPONSE    =  4,
!   HTWAIS_PARSING_RESPONSE =  5,
!   HTWAIS_FETCH_DOCUMENT   =  6,
!   HTWAIS_CLEANUP          =  7
! } HTWAISState;
! 
! 
! /*
!  * This is the context structure for this module
!  */
! typedef struct _wais_info
! {
!   BOOL        as_gate;          /* Client is using us as gateway */
!   HTWAISState state;            /* Current State */
!   int         result;           /* Result to report to the after filter */
!   HTNet*      net;		/* Net object */
!   FILE*       connection;
!   char*       names;            /* Copy of arg to be hacked up */
!   char*       basetitle;
!   char*       wais_database;    /* name of current database */
!   char*        www_database;    /* Same name escaped */
!   char*       request_message;  /* arbitrary message limit */
!   char*       response_message; /* arbitrary message limit */
! } wais_info;
! 
! 
! struct _HTStream
! {
!   const HTStreamClass* isa;
!   HTStream*            target;
!   HTRequest*           request;
!   wais_info*           wais;
!   int                  status;
    /* ... */
  };
  
! 
! struct _HTInputStream
! {
!   const HTInputStreamClass *	isa;
! };
! 
! 
! struct _HTStructured
! {
!   const HTStructuredClass *	isa;
    /* ... */
  };
  
  
! /* ------------------------------------------------------------------------- */
! /* 			      Auxilliary Functions			     */
! /* ------------------------------------------------------------------------- */
! 
! 
! /*								HTshowDiags
   */
  /* modified from Jonny G's version in ui/question.c */
  
! void HTshowDiags (
  	HTStream * 		target,
  	diagnosticRecord ** 	d)
  {
***************
*** 141,151 ****
      unsigned int i;
      char * good = 
        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./-_$";
!     for(i=0; i<256; i++) acceptable[i] = NO;
      for(;*good; good++) acceptable[(unsigned int)*good] = YES;
      acceptable_inited = YES;
  }
  
  /*	Transform file identifier into WWW address
  **	------------------------------------------
  **
--- 213,227 ----
   unsigned int i;
   char * good = 
           "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./-_$";
! 
!  if (acceptable_inited == YES) return;
! 
!  for(i=256; i--; ) acceptable[i] = NO;
   for(;*good; good++) acceptable[(unsigned int)*good] = YES;
   acceptable_inited = YES;
  }
  
+ 
  /*	Transform file identifier into WWW address
  **	------------------------------------------
  **
***************
*** 172,177 ****
--- 248,254 ----
      return result;
  } /* WWW_from_archie */
  
+ 
  /*	Transform document identifier into URL
  **	--------------------------------------
  **
***************
*** 183,189 ****
  **			pointer to malloced string (must be freed) if ok
  */
  PRIVATE char hex [17] = "0123456789ABCDEF";
- extern char from_hex (char a);			/* In HTWSRC @@ */
  
  PRIVATE char * WWW_from_WAIS (any * docid)
  
--- 260,265 ----
***************
*** 332,342 ****
  		    unsigned int b;
  		    p++;
  		    c = *p++;
! 		    b = from_hex(c);
  		    c = *p++;
  		    if (!c) 
  			break;	/* Odd number of chars! */
! 		    *z++ = (b<<4) + from_hex(c);
  		} else {
  		    *z++ = *p++;	/* Record */
  		}
--- 408,418 ----
  		    unsigned int b;
  		    p++;
  		    c = *p++;
! 		    b = HTAsciiHexToChar(c);
  		    c = *p++;
  		    if (!c) 
  			break;	/* Odd number of chars! */
! 		    *z++ = (b<<4) + HTAsciiHexToChar(c);
  		} else {
  		    *z++ = *p++;	/* Record */
  		}
***************
*** 362,372 ****
  		unsigned int b;
  		p++;
  		c = *p++;
! 		b = from_hex(c);
  		c = *p++;
  		if (!c) 
  		    break;	/* Odd number of chars! */
! 		*z++ = (b<<4) + from_hex(c);
  	    } else {
  		*z++ = *p++;	/* Record */
  	    }
--- 438,448 ----
  		unsigned int b;
  		p++;
  		c = *p++;
! 		b = HTAsciiHexToChar(c);
  		c = *p++;
  		if (!c) 
  		    break;	/* Odd number of chars! */
! 		*z++ = (b<<4) + HTAsciiHexToChar(c);
  	    } else {
  		*z++ = *p++;	/* Record */
  	    }
***************
*** 400,409 ****
  		unsigned int b;
  		p++;
  	        c = *p++;
! 		b =   from_hex(c);
  		c = *p++;
  		if (!c) break;	/* Odd number of chars! */
! 		*z++ = (b<<4) + from_hex(c);
  	    } else {
  	        *z++ = *p++;	/* Record */
  	    }
--- 476,485 ----
  		unsigned int b;
  		p++;
  	        c = *p++;
! 		b =   HTAsciiHexToChar(c);
  		c = *p++;
  		if (!c) break;	/* Odd number of chars! */
! 		*z++ = (b<<4) + HTAsciiHexToChar(c);
  	    } else {
  	        *z++ = *p++;	/* Record */
  	    }
***************
*** 478,486 ****
--- 554,564 ----
  {
    WAISSearchResponse  *info;
    long i, k;
+   char line[LINE_BUFFER_SIZE];	/* For building strings to display */
    
    BOOL archie =  strstr(database, "archie")!=0;	/* Specical handling */
  
+   
    if (PROT_TRACE) HTTrace("WAIS........ Displaying search response\n");
    sprintf(line,
  	  "Index %s contains the following %d item%s relevant to '%s'.\n",
***************
*** 498,504 ****
      i =0; 
  
      if (info->Diagnostics != NULL)
!       showDiags((HTStream*)target, info->Diagnostics);
  
      if ( info->DocHeaders != 0 ) {
        for (k=0; info->DocHeaders[k] != 0; k++ ) {
--- 576,582 ----
      i =0; 
  
      if (info->Diagnostics != NULL)
!       HTshowDiags((HTStream*)target, info->Diagnostics);
  
      if ( info->DocHeaders != 0 ) {
        for (k=0; info->DocHeaders[k] != 0; k++ ) {
***************
*** 628,633 ****
--- 706,814 ----
  }
  
  
+ /*	HTWAISCleanup
+ **	-----------
+ **      This function closes the connection and frees memory.
+ **      Returns YES on OK, else NO
+ */
+ PRIVATE int HTWAISCleanup (HTRequest *req, int status)
+ {
+  HTNet* net;
+  HTStream* input;
+  wais_info* theWAISinfo = NULL;
+ 
+ 
+  if (req)
+    {
+     net = HTRequest_net(req);
+     input = HTRequest_inputStream(req);
+ 
+     /* Free stream with data TO network */
+     if (HTRequest_isDestination(req))
+       HTRequest_removeDestination(req);
+      else
+       if (input)
+ 	{
+ 	 if (status == HT_INTERRUPTED)
+ 	   (*input->isa->abort)(input, NULL);
+ 	  else
+ 	   (*input->isa->_free)(input);
+ 
+ 	 HTRequest_setInputStream(req, NULL);
+ 	}
+ 
+     if (net)
+       {
+        if ((theWAISinfo = (wais_info*)HTNet_context(net)))
+ 	 {
+ 	  theWAISinfo->state = HTWAIS_CLEANUP;
+ 
+ 	  if (theWAISinfo->connection)
+ 	    close_connection_to_server(theWAISinfo->connection);
+ 
+ 	  if (theWAISinfo->wais_database)
+ 	    HT_FREE(theWAISinfo->wais_database);
+ 
+ 	  if (theWAISinfo->request_message)
+ 	    s_free(theWAISinfo->request_message);
+ 
+ 	  if (theWAISinfo->response_message)
+ 	    s_free(theWAISinfo->response_message);
+ 
+ 	  HT_FREE(theWAISinfo->names);
+ 	  HT_FREE(theWAISinfo->basetitle);
+ 
+ 	  if (status < 0)
+ 	    {
+ 	     HTParentAnchor* anchor;
+ 	     char* unescaped = NULL;
+ 	     void* err_par;
+ 	     unsigned int err_par_length;
+ 
+ 	     if ((anchor = HTRequest_anchor(req)))   /* Be robust */
+ 	       {
+ 		char* arg;
+ 
+ 		if ((arg = HTAnchor_physical(anchor)))
+ 		  {
+ 		   StrAllocCopy(unescaped, arg);
+ 		   HTUnEscape(unescaped);
+ 		  }
+ 	       }
+ 
+ 	     if (unescaped)
+ 	       {
+ 		err_par = (void*)unescaped;
+ 		err_par_length = (unsigned int)(strlen(unescaped));
+ 	       }
+ 	      else
+ 	       {
+ 		err_par = (void*)"???";
+ 		err_par_length = 3;
+ 	       }
+ 
+ 	     HTRequest_addError(req, ERR_FATAL, NO, HTERR_INTERNAL,
+ 				err_par, err_par_length, "HTLoadWAIS");
+ 	     if (unescaped) HT_FREE(unescaped);
+ 	    }
+ 
+ 	  /* Free and remove our own context structure for wais */
+ 	  HT_FREE(theWAISinfo);
+ 	  HTNet_setContext(net, NULL);
+ 	 }
+        /* End ``if (theWAISinfo)'' */
+ 
+        /* Remove the request object */
+        HTNet_delete(net, status);
+       }
+ 
+     return YES;
+    }
+   else
+    return NO;
+ }
+ 
+ 
  
  
  /*	Load Document from WAIS Server				HTLoadWAIS()
***************
*** 639,688 ****
  **	returns		<0		Error has occured
  **			HT_LOADED	OK
  */
- PUBLIC int HTLoadWAIS (SOCKET soc, HTRequest * request, HTEventType type)
  
  #define MAX_KEYWORDS_LENGTH 4000
  #define MAX_SERVER_LENGTH 1000
  #define MAX_DATABASE_LENGTH 1000
  #define MAX_SERVICE_LENGTH 1000
  
  {
!     HTParentAnchor * anchor = HTRequest_anchor(request);
!     const char * arg = HTAnchor_physical(anchor);
!     HTFormat		format_out = HTRequest_outputFormat(request);
!     HTStream*		sink = HTRequest_outputStream(request);
  #if 0    
!     static const char * error_header =
! "<h1>Access error</h1>\nThe following error occured in accesing a WAIS server:<P>\n";
  #endif
      char * key;			  /* pointer to keywords in URL */
-     char* request_message = NULL; /* arbitrary message limit */
-     char* response_message = NULL; /* arbitrary message limit */
      long request_buffer_length;	/* how of the request is left */
      SearchResponseAPDU  *retrieval_response = 0;
      char keywords[MAX_KEYWORDS_LENGTH + 1];
!     char *server_name;	
!     char *wais_database = NULL;		/* name of current database */
!     char *www_database;			/* Same name escaped */
      char *service;
!     char *doctype;
!     char *doclength;
!     long document_length;
!     char *docname;
      FILE *connection = 0;
      char * names;		/* Copy of arg to be hacked up */
-     BOOL ok = NO;
-     int status = -1;
      char *basetitle = NULL;
      
  #if 0
      extern FILE * connect_to_server();
  #endif
      
-     if (PROT_TRACE)
- 	HTTrace("HTLoadWAIS.. Looking for `%s\'\n", arg);
       
!     if (!acceptable_inited) init_acceptable();
      
          
  /*	Decipher and check syntax of WWW address:
--- 820,909 ----
  **	returns		<0		Error has occured
  **			HT_LOADED	OK
  */
  
  #define MAX_KEYWORDS_LENGTH 4000
  #define MAX_SERVER_LENGTH   1000
  #define MAX_DATABASE_LENGTH 1000
  #define MAX_SERVICE_LENGTH  1000
  
+ PRIVATE int HTWAISEvent(SOCKET soc, void * pVoid, HTEventType type)
  {
!  wais_info* theWAISinfo;  /* Specific protocol information */
!  HTNet* net;              /* Generic protocol information */
!  HTRequest* request;
!  HTParentAnchor* anchor;
!  const char * arg;
!  HTStream* sink;
!  HTFormat format_out;
  #if 0
!  static const char * error_header = "<h1>Access error</h1>\n<p>The following error occured in accesing a WAIS server:\n</p>\n";
  #endif
   char* key;			  /* pointer to keywords in URL */
   long request_buffer_length;	/* how of the request is left */
   SearchResponseAPDU* retrieval_response = 0;
   char keywords[MAX_KEYWORDS_LENGTH + 1];
!  char* server_name = NULL;
   char* service;
!  char* docname = NULL;
!  char* doctype = NULL;
!  long document_length = -1;
!  BOOL ok = NO;
!  int status = HT_ERROR;
! 
! #if 0
   FILE* connection = 0;
   char* names;		/* Copy of arg to be hacked up */
   char* basetitle = NULL;
+  char* wais_database = NULL;    /* name of current database */
+  char*  www_database = NULL;    /* Same name escaped */
+  char*  request_message = NULL; /* arbitrary message limit */
+  char* response_message = NULL; /* arbitrary message limit */
+ #endif
      
  #if 0
   extern FILE * connect_to_server();
  #endif
  
  
!  if ((theWAISinfo = (wais_info*)pVoid))   /* Be robust */
!    {
!     if ((net = theWAISinfo->net) == NULL) return HT_ERROR;
!     if ((request = HTNet_request(net)) == NULL) return HT_ERROR;
!     if ((anchor = HTRequest_anchor(request)))
!       arg = HTAnchor_physical(anchor);
!      else
!       return HT_ERROR;
! 
!     sink = HTRequest_outputStream(request);
!     format_out = HTRequest_outputFormat(request);
!    }
!   else
!    return HT_ERROR;
!     
! 
!  if (type == HTEvent_BEGIN)
!    {
!     theWAISinfo->state  = HTWAIS_BEGIN;
!     theWAISinfo->result = HT_ERROR;
!    }
!   else
!    if (type == HTEvent_CLOSE)
!      {
!      /* Interrupted */
!       char interrupted[] = "request interruption";
! 
!       HTRequest_addError(request, ERR_FATAL, NO, HTERR_INTERRUPTED,
! 			 (void*)interrupted, (unsigned int)strlen(interrupted),
! 			 "HTLoadWAIS");
!       HTWAISCleanup(request, HT_INTERRUPTED);
!       return HT_OK;
!      }
!     else
!      if (type == HTEvent_END)
!        {
! 	HTWAISCleanup(request, (theWAISinfo ? theWAISinfo->result : HT_ERROR));
! 	return HT_OK;
!        }
  
  
   /*	Decipher and check syntax of WWW address:
***************
*** 690,845 ****
  **
  **	First we remove the "wais:" if it was spcified.  920110
  */  
-     names = HTParse(arg, "", PARSE_HOST | PARSE_PATH | PARSE_PUNCTUATION);
-     key = strchr(names, '?');
      
!     if (key) {
      	char * p;
  	*key++ = 0;	/* Split off keywords */
  	for (p=key; *p; p++) if (*p == '+') *p = ' ';
  	HTUnEscape(key);
      }
!     if (names[0]== '/') {
! 	server_name = names+1;
! 	if ((as_gate =(*server_name == '/')))
! 	    server_name++;	/* Accept one or two */
! 	www_database = strchr(server_name,'/');
! 	if (www_database) {
! 	    *www_database++ = 0;		/* Separate database name */
! 	    doctype = strchr(www_database, '/');
! 	    if (key) ok = YES;	/* Don't need doc details */
! 	    else if (doctype) {	/* If not search parse doc details */
  		*doctype++ = 0;	/* Separate rest of doc address */
  		doclength = strchr(doctype, '/');
! 		if(doclength) {
  		    *doclength++ = 0;
  		    document_length = atol(doclength);
! 		    if (document_length) {
  			docname=strchr(doclength, '/');
! 			if (docname) {
  			    *docname++ = 0;
  			    ok = YES;	/* To avoid a goto! */
  			} /* if docname */
  		    } /* if document_length valid */
  		} /* if doclength */
! 	    } else { /* no doctype?  Assume index required */
  	        if (!key) key = "";
  		ok = YES;
  	    } /* if doctype */
  	} /* if database */
       }
       
!     if (!ok) {
  	char *unescaped = NULL;
  	StrAllocCopy(unescaped, arg);
  	HTUnEscape(unescaped);
  	HTRequest_addError(request, ERR_FATAL, NO, HTERR_BAD_REQUEST,
  		   (void *) unescaped, (int) strlen(unescaped),
  		   "HTLoadWAIS");
  	HT_FREE(unescaped);
! 	HT_FREE(names);
  	return -1;
      }
      
      if (PROT_TRACE) HTTrace("HTLoadWAIS.. URL Parsed OK\n");
       
!      service = strchr(names, ':');
!      if (service)  *service++ = 0;
!      else service = "210";
       
!      if (server_name[0] == 0)
!         connection = NULL;
  
!      else if (!(key && !*key))
!       if ((connection=connect_to_server(server_name,atoi(service))) == NULL)  {
  	  char *host = HTParse(arg, "", PARSE_HOST);
  	  if (PROT_TRACE)
! 	      HTTrace("HTLoadWAIS.. Can't open connection to %s via service %s.\n",
  		       server_name, service);
  	  HTRequest_addError(request, ERR_FATAL, NO, HTERR_WAIS_NO_CONNECT,
  		     (void *) host, (int) strlen(host), "HTLoadWAIS");
! 	  goto cleanup;
        }
  
-     StrAllocCopy(wais_database,www_database);
-     HTUnEscape(wais_database);
  
      /* Make title name without the .src */
      {
  	char *srcstr;
! 	StrAllocCopy(basetitle, wais_database);
! 	if ((srcstr = strstr(basetitle, ".src")) != NULL)
  	    *srcstr = '\0';
      }
      
      /* This below fixed size stuff is terrible */
!     if ((request_message = (char*)s_malloc((size_t)MAX_MESSAGE_LEN * sizeof(char))) == NULL)
  	HT_OUTOFMEM("WAIS request message");
!     if ((response_message = (char*)s_malloc((size_t)MAX_MESSAGE_LEN * sizeof(char))) == NULL)
  	HT_OUTOFMEM("WAIS response message");
  
  /*	If keyword search is performed but there are no keywords,
! **	the user has followed a link to the index itself. It would be
! **	appropriate at this point to send him the .SRC file - how?
  */
  
!     if (key && !*key) {				/* I N D E X */
!     
! #ifdef CACHE_FILE_PREFIX
! 	char filename[256];
! 	FILE * fp;
! #endif
! 	HTStructured * target = HTMLGenerator(request, NULL,
! 					WWW_HTML, format_out, sink);
! 	
  	{
! 	    START(HTML_HTML);
! 	    START(HTML_HEAD);
! 	    START(HTML_TITLE);
! 	    PUTS(basetitle);
! 	    PUTS(" Index");
! 	    END(HTML_TITLE);
! 	    END(HTML_HEAD);
! 	    
! 	    START(HTML_BODY);
! 	    START(HTML_H1);
! 	    PUTS("WAIS Index: ");
! 	    PUTS(basetitle);
! 	    END(HTML_H1);
! 	    
! 	}
! 	START(HTML_ISINDEX);
! 
! 	/* If we have seen a source file for this database, use that: */
! 
! #ifdef CACHE_FILE_PREFIX
! 	sprintf(filename, "%sWSRC-%s:%s:%.100s.txt",
! 		CACHE_FILE_PREFIX,
! 		server_name, service, www_database);
! 
! 	fp = fopen(filename, "r");	/* Have we found this already? */
! 	if (PROT_TRACE) HTTrace(
! 		"HTLoadWAIS.. Description of server %s %s.\n",
! 		filename,
! 		fp ? "exists already" : "does NOT exist!");
! 
! 	if (fp) {
! 	    int c;
! 	    START(HTML_PRE);			 /* Preformatted description */
! 	    while((c=getc(fp)) != EOF)
! 		PUTC(c);				    /* Transfer file */
! 	    END(HTML_PRE);
! 	    fclose(fp);
! 	}
! #endif
! 	END(HTML_BODY);
! 	END(HTML_HTML);
! 	FREE_TARGET;
! 	
!     } else if (key) {					/* S E A R C H */
  	char *p;
  	HTStructured * target;
  	
  	strncpy(keywords, key, MAX_KEYWORDS_LENGTH);
  	while ((p = strchr(keywords,'+'))) *p = ' ';
      
--- 911,1074 ----
   **
   **	First we remove the "wais:" if it was spcified.  920110
   */
  
!  if (!acceptable_inited) init_acceptable();
!  theWAISinfo->state = HTWAIS_PARSING_URL;
!  if (PROT_TRACE) HTTrace("HTLoadWAIS.. Looking for \"%s\"\n", arg);
! 
!  theWAISinfo->names = HTParse(arg, "",
! 			      PARSE_HOST | PARSE_PATH | PARSE_PUNCTUATION);
!  key = strchr(theWAISinfo->names, '?');
! 
!  if (key)
!    {
      char* p;
+ 
      *key++ = 0;	/* Split off keywords */
+ 
      for (p=key; *p; p++) if (*p == '+') *p = ' ';
      HTUnEscape(key);
     }
! 
!  if (theWAISinfo->names[0] == '/')
!    {
!     server_name = theWAISinfo->names+1;
! 
! 	/* Accept one or two */
!     if ((theWAISinfo->as_gate = (*server_name == '/'))) server_name++;
! 
!     if ((theWAISinfo->www_database = strchr(server_name, '/')))
!       {
!        *(theWAISinfo->www_database)++ = 0;  /* Separate database name */
!        doctype = strchr(theWAISinfo->www_database, '/');
! 
!        if (key)
! 	 ok = YES;	/* Don't need doc details */
!         else
! 	 if (doctype)
! 	   {	/* If not search parse doc details */
! 	    char* doclength;
! 
  	    *doctype++ = 0;	/* Separate rest of doc address */
  	    doclength = strchr(doctype, '/');
! 	    if (doclength)
! 	      {
  	       *doclength++ = 0;
  	       document_length = atol(doclength);
! 	       if (document_length)
! 		 {
  		  docname = strchr(doclength, '/');
! 		  if (docname)
! 		    {
  		     *docname++ = 0;
  		     ok = YES;	/* To avoid a goto! */
  		    } /* if docname */
  		 } /* if document_length valid */
  	      } /* if doclength */
! 	   }
! 	  else
! 	   { /* no doctype?  Assume index required */
  	    if (!key) key = "";
  	    ok = YES;
  	   } /* if doctype */
        } /* if database */
     }
       
!  if (!ok)
!    {
      char *unescaped = NULL;
+ 
      StrAllocCopy(unescaped, arg);
      HTUnEscape(unescaped);
      HTRequest_addError(request, ERR_FATAL, NO, HTERR_BAD_REQUEST,
  		       (void *) unescaped, (int) strlen(unescaped),
  		       "HTLoadWAIS");
      HT_FREE(unescaped);
!     HT_FREE(theWAISinfo->names);
      return -1;
     }
      
   if (PROT_TRACE) HTTrace("HTLoadWAIS.. URL Parsed OK\n");
+  theWAISinfo->state = HTWAIS_NEED_CONNECTION;
  
!  if ((service = strchr(theWAISinfo->names, ':')))
!    *service++ = 0;
!   else
!    service = "210";
  
!  if ((server_name ? server_name[0] : 0))
!    {
!     boolean do_need_to_connect_to_server = true;
  
!     if (key) if ((*key) == 0) do_need_to_connect_to_server = false;
! 
!     if (do_need_to_connect_to_server)
!       {
!        if ((theWAISinfo->connection = connect_to_server(server_name,
! 							atoi(service)))
! 	   == NULL)
! 	 {
  	  char* host = HTParse(arg, "", PARSE_HOST);
+ 
  	  if (PROT_TRACE)
! 	    HTTrace("HTLoadWAIS.."
! 		    " Can't open connection to %s via service %s.\n",
  		    server_name, service);
+ 
  	  HTRequest_addError(request, ERR_FATAL, NO, HTERR_WAIS_NO_CONNECT,
  			     (void *) host, (int) strlen(host), "HTLoadWAIS");
! 	  theWAISinfo->result = HT_ERROR;
! 	  HTWAISCleanup(request, status);
! 	  return status;
! 	 }
!       }
     }
+   else
+    theWAISinfo->connection = NULL;
+ 
+  StrAllocCopy(theWAISinfo->wais_database, theWAISinfo->www_database);
+  HTUnEscape(theWAISinfo->wais_database);
  
  
   /* Make title name without the .src */
   {
    char *srcstr;
! 
!   StrAllocCopy(theWAISinfo->basetitle, theWAISinfo->wais_database);
!   if ((srcstr = strstr(theWAISinfo->basetitle, ".src")) != NULL)
      *srcstr = '\0';
   }
      
+ 
   /* This below fixed size stuff is terrible */
!  if ((theWAISinfo->request_message =
!                        (char*)s_malloc((size_t)MAX_MESSAGE_LEN * sizeof(char)))
!      == NULL)
     HT_OUTOFMEM("WAIS request message");
! 
!  if ((theWAISinfo->response_message =
!                        (char*)s_malloc((size_t)MAX_MESSAGE_LEN * sizeof(char)))
!      == NULL)
     HT_OUTOFMEM("WAIS response message");
  
+ 
   /*	If keyword search is performed but there are no keywords,
!  **	the user has followed a link to the index itself.
!  **     It would be appropriate at this point to send him the .SRC file - how?
   */
  
!  if (key)
     {
!     if (*key)
!       {
!       /*
!        *   S E A R C H   (nonempty key (*key != 0))
!        */
         char *p;
         HTStructured* target;
  
+        theWAISinfo->state = HTWAIS_NEED_RESPONSE;
+ 
         strncpy(keywords, key, MAX_KEYWORDS_LENGTH);
         while ((p = strchr(keywords,'+'))) *p = ' ';
  
***************
*** 852,858 ****
  	START(HTML_TITLE);
  	PUTS(keywords);
  	PUTS(" in ");
! 	PUTS(basetitle);
  	END(HTML_TITLE);
  	END(HTML_HEAD);
  	
--- 1081,1087 ----
         START(HTML_TITLE);
         PUTS(keywords);
         PUTS(" in ");
!        PUTS(theWAISinfo->basetitle);
         END(HTML_TITLE);
         END(HTML_HEAD);
  
***************
*** 861,867 ****
  	PUTS("WAIS Search of \"");
  	PUTS(keywords);
  	PUTS("\" in ");
! 	PUTS(basetitle);
  	END(HTML_H1);
  
  	START(HTML_ISINDEX);
--- 1090,1096 ----
         PUTS("WAIS Search of \"");
         PUTS(keywords);
         PUTS("\" in ");
!        PUTS(theWAISinfo->basetitle);
         END(HTML_H1);
  
         START(HTML_ISINDEX);
***************
*** 869,905 ****
  	request_buffer_length = MAX_MESSAGE_LEN; /* Amount left */
  	if (PROT_TRACE)
  	    HTTrace("HTLoadWAIS.. Search for `%s' in `%s'\n",
! 		    keywords, wais_database);
! 	if(generate_search_apdu(request_message + HEADER_LENGTH, 
  				&request_buffer_length, 
! 				keywords, wais_database, NULL,
! 				HTMaxWAISLines) == NULL) {
  	    if (PROT_TRACE)
  		HTTrace("WAIS Search. Too many lines in response\n");
  	    HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_OVERFLOW, 
  		       NULL, 0, "HTLoadWAIS");
  	}
  
! 	if(!interpret_message(request_message, 
  				MAX_MESSAGE_LEN - request_buffer_length, 
! 				response_message,
  				MAX_MESSAGE_LEN,
! 				connection,
  				false	/* true verbose */
! 				)) {
  	    if (PROT_TRACE)
  		HTTrace("WAIS Search. Too many lines in response\n");
  	    HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_OVERFLOW, 
  		       NULL, 0, "HTLoadWAIS");
!         } else {	/* returned message ok */
  	    SearchResponseAPDU  *query_response = 0;
  	    readSearchResponseAPDU(&query_response,
! 	    	response_message + HEADER_LENGTH);
  	    display_search_response(target, 
! 	    	query_response, wais_database, keywords);
  	    if (query_response->DatabaseDiagnosticRecords)
! 		freeWAISSearchResponse(
! 			query_response->DatabaseDiagnosticRecords);         
  	    freeSearchResponseAPDU( query_response);
  	}	/* returned message not too large */
      
--- 1098,1143 ----
         request_buffer_length = MAX_MESSAGE_LEN; /* Amount left */
         if (PROT_TRACE)
  	 HTTrace("HTLoadWAIS.. Search for `%s' in `%s'\n",
! 		 keywords, theWAISinfo->wais_database);
! 
!        if (generate_search_apdu(theWAISinfo->request_message + HEADER_LENGTH, 
  				&request_buffer_length, 
! 				keywords, theWAISinfo->wais_database, NULL,
! 				HTMaxWAISLines) == NULL)
! 	 {
  	  if (PROT_TRACE)
  	    HTTrace("WAIS Search. Too many lines in response\n");
+ 
  	  HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_OVERFLOW, 
  			     NULL, 0, "HTLoadWAIS");
  	 }
  
!        if (!interpret_message(theWAISinfo->request_message, 
  			      MAX_MESSAGE_LEN - request_buffer_length, 
! 			      theWAISinfo->response_message,
  			      MAX_MESSAGE_LEN,
! 			      theWAISinfo->connection,
  			      false	/* true verbose */
! 			      ))
! 	 {
  	  if (PROT_TRACE)
  	    HTTrace("WAIS Search. Too many lines in response\n");
+ 
  	  HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_OVERFLOW, 
  			     NULL, 0, "HTLoadWAIS");
! 	 }
!         else
! 	 {	/* returned message ok */
  	  SearchResponseAPDU  *query_response = 0;
+ 
  	  readSearchResponseAPDU(&query_response,
! 				theWAISinfo->response_message + HEADER_LENGTH);
  	  display_search_response(target, 
! 				  query_response, theWAISinfo->wais_database,
! 				  keywords);
  	  if (query_response->DatabaseDiagnosticRecords)
! 	    freeWAISSearchResponse(query_response->DatabaseDiagnosticRecords);
! 
  	  freeSearchResponseAPDU(query_response);
  	 }	/* returned message not too large */
  
***************
*** 907,1030 ****
  	END(HTML_HTML);
  	FREE_TARGET;
  
!     } else {			/* D O C U M E N T    F E T C H */
      
! 	boolean binary;     /* how to transfer stuff coming over */
  	HTStream * target;
  	long count;
  	any   doc_chunk;
  	any * docid = &doc_chunk;
  	if (PROT_TRACE)
! 	    HTTrace(
! 		    "HTLoadWAIS.. Retrieve document `%s'\n............ type `%s' length %ld\n", docname, doctype, document_length);
  		
! 	HTAnchor_setFormat(anchor,
! 	  !strcmp(doctype, "WSRC") ? HTAtom_for("application/x-wais-source") :
! 	  !strcmp(doctype, "TEXT") ? WWW_UNKNOWN :
! 	  !strcmp(doctype, "HTML") ? WWW_HTML:
! 	  !strcmp(doctype, "GIF")  ? WWW_GIF:
! 	   		             HTAtom_for("application/octet-stream"));
! 	binary = 
! 	  0 != strcmp(doctype, "WSRC") &&
! 	  0 != strcmp(doctype, "TEXT") &&
! 	  0 != strcmp(doctype, "HTML") ;
  
  	/* Guess on TEXT format as it might be HTML */
  	if ((target = HTStreamStack(HTAnchor_format(anchor),
  				    HTRequest_outputFormat(request),
  				    HTRequest_outputStream(request),
! 				    request, YES)) == NULL) {
  	    status = -1;
! 	    goto cleanup;
  	}
  
  	/* Decode hex or litteral format for document ID */
  	WAIS_from_WWW(docid, docname);
  
  	/* Loop over slices of the document */
! 	for (count = 0; count * CHARS_PER_PAGE < document_length; count++) {
  	    char *type = s_strdup(doctype);
  	    request_buffer_length = MAX_MESSAGE_LEN;	      /* Amount left */
! 	    if (PROT_TRACE) HTTrace("HTLoadWAIS.. Slice number %ld\n",
! 			       count);
! 	    if (generate_retrieval_apdu(request_message + HEADER_LENGTH,
  					&request_buffer_length, 
  					docid, CT_byte,
  					count * CHARS_PER_PAGE,
  					HTMIN((count + 1) * CHARS_PER_PAGE,
  					      document_length),
  					type,
! 					wais_database) == 0) {
  		HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_OVERFLOW, 
  			   NULL, 0, "HTLoadWAIS");
  	    }
  	    HT_FREE(type);
  	    
  	    /* Actually do the transaction given by request_message */   
! 	    if (interpret_message(request_message, 
  				  MAX_MESSAGE_LEN - request_buffer_length, 
! 				  response_message,
  				  MAX_MESSAGE_LEN,
! 				  connection,
  				  false /* true verbose */	
! 				  ) == 0) {
  		HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_OVERFLOW, 
  			   NULL, 0, "HTLoadWAIS");
  	    }
  	    
  	    /* Parse the result which came back into memory. */
  	    readSearchResponseAPDU(&retrieval_response, 
! 				   response_message + HEADER_LENGTH);
  	    {
  		WAISSearchResponse *searchres = (WAISSearchResponse *) retrieval_response->DatabaseDiagnosticRecords;
! 		if (!searchres->Text) {
! 		    if (searchres->Diagnostics && *searchres->Diagnostics &&
! 			(*searchres->Diagnostics)->ADDINFO) {
  			char *errmsg = (*searchres->Diagnostics)->ADDINFO;
  			HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_MODULE,
  				   (void *) errmsg, (int) strlen(errmsg),
  				   "HTLoadWAIS");
! 		    } else {
  			HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_MODULE,
  				   NULL, 0, "HTLoadWAIS");
  		    }
  		    (*target->isa->_free)(target);
  		    HTRequest_setOutputStream(request, NULL);
  		    HT_FREE(docid->bytes);
  		    freeWAISSearchResponse(retrieval_response->DatabaseDiagnosticRecords); 
  		    freeSearchResponseAPDU( retrieval_response);
! 		    goto cleanup;
! 		} else {
  		    output_text_record(target, *searchres->Text,
  				       false, binary);
  		    freeWAISSearchResponse( retrieval_response->DatabaseDiagnosticRecords);
  		    freeSearchResponseAPDU( retrieval_response);
  		} /* If text existed */
  	    }
- 	    
  	} /* Loop over slices */
  
  	(*target->isa->_free)(target);
  	HTRequest_setOutputStream(request, NULL);
  	HT_FREE(docid->bytes);
-     } /* If document rather than search */
-     status = HT_LOADED;
  
!   cleanup:
!     if (connection) close_connection_to_server(connection);
!     if (wais_database) HT_FREE(wais_database);
!     if (request_message) s_free(request_message);
!     if (response_message) s_free(response_message);
!     HT_FREE(names);
!     HT_FREE(basetitle);
!     if (status < 0) {
! 	char *unescaped = NULL;
! 	StrAllocCopy(unescaped, arg);
! 	HTUnEscape(unescaped);
! 	HTRequest_addError(request, ERR_FATAL, NO, HTERR_INTERNAL, (void *) unescaped,
! 		   (int) strlen(unescaped), "HTLoadWAIS");
! 	HT_FREE(unescaped);
      }
      return status;
  }
  
--- 1145,1412 ----
         END(HTML_HTML);
         FREE_TARGET;
  
!        HTAnchor_setFormat(anchor, WWW_HTML);
  
!        theWAISinfo->result = status = HT_LOADED;
!       }
!      else
!       {
!       /*
!        *   I N D E X   (key is empty (*key = 0))
!        */
! #ifdef CACHE_FILE_PREFIX
!        char filename[256];
!        FILE * fp;
! #endif
!        HTStructured* target = HTMLGenerator(request, NULL,
! 					    WWW_HTML, format_out, sink);
! 
!        theWAISinfo->state = HTWAIS_NEED_REQUEST;
! 
!        {
! 	START(HTML_HTML);
! 	START(HTML_HEAD);
! 	START(HTML_TITLE);
! 	PUTS(theWAISinfo->basetitle);
! 	PUTS(" Index");
! 	END(HTML_TITLE);
! 	END(HTML_HEAD);
! 
! 	START(HTML_BODY);
! 	START(HTML_H1);
! 	PUTS("WAIS Index: ");
! 	PUTS(theWAISinfo->basetitle);
! 	END(HTML_H1);
!        }
! 
!        START(HTML_ISINDEX);
! 
!        /* If we have seen a source file for this database, use that: */
! 
! #ifdef CACHE_FILE_PREFIX
!        sprintf(filename,
! 	       "%sWSRC-%s:%s:%.100s.txt",
! 	       CACHE_FILE_PREFIX,
! 	       server_name, service, theWAISinfo->www_database);
! 
!        fp = fopen(filename, "r");	/* Have we found this already? */
!        if (PROT_TRACE)
! 	 HTTrace("HTLoadWAIS.. Description of server %s %s.\n",
! 		 filename,
! 		 fp ? "exists already" : "does NOT exist!");
! 
!        if (fp)
! 	 {
! 	  int c;
! 
! 	  START(HTML_PRE);   /* Preformatted description */
! 	  while((c=getc(fp)) != EOF) PUTC(c);   /* Transfer file */
! 	  END(HTML_PRE);
! 	  fclose(fp);
! 	 }
! #endif
! 
!        END(HTML_BODY);
!        END(HTML_HTML);
!        FREE_TARGET;
!       }
! 
!     HTAnchor_setFormat(anchor, WWW_HTML);
! 
!     theWAISinfo->result = status = HT_LOADED;
!    }
!   else
!    {/* document rather than search */
!    /*
!     *   D O C U M E N T    F E T C H   (no key (key == NULL))
!     */
!     boolean binary = true;     /* how to transfer stuff coming over */
      HTStream* target;
+     HTAtom* document_type_atom = HTAtom_for("application/octet-stream");
      long count;
      any   doc_chunk;
      any * docid = &doc_chunk;
+ 
+     theWAISinfo->state = HTWAIS_FETCH_DOCUMENT;
      if (PROT_TRACE)
!       HTTrace("HTLoadWAIS.. Retrieve document `%s'\n"
! 	      "............ type `%s' length %ld\n",
! 	      (docname ? docname : "unknown"),
! 	      (doctype ? doctype : "unknown"),
! 	      document_length);
  
!     if (doctype)
!       {
!        if (strcmp(doctype, "WSRC") == 0)
! 	 {
! 	  document_type_atom = HTAtom_for("application/x-wais-source");
! 	  binary = false;
! 	 }
!         else
! 	 if (strcmp(doctype, "TEXT") == 0)
! 	   {
! 	    document_type_atom = WWW_UNKNOWN;
! 	    binary = false;
! 	   }
! 	  else
! 	   if (strcmp(doctype, "HTML") == 0)
! 	     {
! 	      document_type_atom = WWW_HTML;
! 	      binary = false;
! 	     }
! 	    else
! 	     if (strcmp(doctype, "GIF") == 0) document_type_atom = WWW_GIF;
!       }
! 
!     HTAnchor_setFormat(anchor, document_type_atom);
  
      /* Guess on TEXT format as it might be HTML */
      if ((target = HTStreamStack(HTAnchor_format(anchor),
  				HTRequest_outputFormat(request),
  				HTRequest_outputStream(request),
! 				request, YES))
! 	== NULL)
!       {
!        theWAISinfo->result = HT_ERROR;
         status = -1;
!        HTWAISCleanup(request, status);
!        return status;
        }
  
      /* Decode hex or litteral format for document ID */
      WAIS_from_WWW(docid, docname);
  
      /* Loop over slices of the document */
!     for (count = 0; count * CHARS_PER_PAGE < document_length; count++)
!       {
         char *type = s_strdup(doctype);
+ 
         request_buffer_length = MAX_MESSAGE_LEN;	      /* Amount left */
!        if (PROT_TRACE) HTTrace("HTLoadWAIS.. Slice number %ld\n", count);
!        if (generate_retrieval_apdu(theWAISinfo->request_message + HEADER_LENGTH,
  				   &request_buffer_length, 
  				   docid, CT_byte,
  				   count * CHARS_PER_PAGE,
  				   HTMIN((count + 1) * CHARS_PER_PAGE,
  					 document_length),
  				     type,
! 				   theWAISinfo->wais_database) == 0)
! 	 {
  	  HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_OVERFLOW, 
  			     NULL, 0, "HTLoadWAIS");
  	 }
+ 
         HT_FREE(type);
  
         /* Actually do the transaction given by request_message */   
!        if (interpret_message(theWAISinfo->request_message, 
  			     MAX_MESSAGE_LEN - request_buffer_length, 
! 			     theWAISinfo->response_message,
  			     MAX_MESSAGE_LEN,
! 			     theWAISinfo->connection,
  			     false /* true verbose */	
! 			     )
! 	   == 0)
! 	 {
  	  HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_OVERFLOW, 
  			     NULL, 0, "HTLoadWAIS");
  	 }
  
         /* Parse the result which came back into memory. */
         readSearchResponseAPDU(&retrieval_response, 
! 			      theWAISinfo->response_message + HEADER_LENGTH);
         {
  	WAISSearchResponse* searchres = (WAISSearchResponse*)retrieval_response->DatabaseDiagnosticRecords;
! 
! 	if (!searchres->Text)
! 	  {
! 	   if (searchres->Diagnostics &&
! 	       *searchres->Diagnostics &&
! 	       (*searchres->Diagnostics)->ADDINFO)
! 	     {
  	      char *errmsg = (*searchres->Diagnostics)->ADDINFO;
+ 
  	      HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_MODULE,
  				 (void *) errmsg, (int) strlen(errmsg),
  				 "HTLoadWAIS");
! 	     }
! 	    else
! 	     {
  	      HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_MODULE,
  				 NULL, 0, "HTLoadWAIS");
  	     }
+ 
  	   (*target->isa->_free)(target);
  	   HTRequest_setOutputStream(request, NULL);
  	   HT_FREE(docid->bytes);
  	   freeWAISSearchResponse(retrieval_response->DatabaseDiagnosticRecords); 
  	   freeSearchResponseAPDU(retrieval_response);
! 	   theWAISinfo->result = HT_OK;
! 	   HTWAISCleanup(request, status);
! 	  }
! 	 else
! 	  {
  	   output_text_record(target, *searchres->Text,
  			      false, binary);
  	   freeWAISSearchResponse(retrieval_response->DatabaseDiagnosticRecords);
  	   freeSearchResponseAPDU(retrieval_response);
  	  } /* If text existed */
         }
        } /* Loop over slices */
  
      (*target->isa->_free)(target);
      HTRequest_setOutputStream(request, NULL);
      HT_FREE(docid->bytes);
  
!     theWAISinfo->result = status = HT_LOADED;
     }
+  /* End ``if (key)'' */
+ 
+  HTWAISCleanup(request, status);
+ 
   return status;
  }
  
+ 
+ PUBLIC int HTLoadWAIS (SOCKET soc, HTRequest* request)
+ {
+  wais_info* theWAISinfo;  /* Specific protocol information */
+  HTNet* net;              /* Generic protocol information */
+  HTParentAnchor* anchor;
+ 
+  /*
+   * Initiate a new wais structure and bind to request structure.
+   * This is actually state HTWAIS_BEGIN,
+   * but it can't be in the state machine,
+   * as we need the structure first.
+   */
+ 
+  if (request)
+    {
+     if ((anchor = HTRequest_anchor(request)) == NULL) return HT_ERROR;
+     if ((net = HTRequest_net(request)) == NULL) return HT_ERROR;
+    }
+   else
+    return HT_ERROR;
+ 
+  if (PROT_TRACE)
+    HTTrace("HTWAIS...... Looking for `%s\'\n", HTAnchor_physical(anchor));
+ 
+                      /* Get existing copy */
+  if ((theWAISinfo = (wais_info*)HTNet_context(net)) == NULL)
+    {
+     if ((theWAISinfo = (wais_info*)HT_CALLOC(1, sizeof(wais_info))) == NULL)
+       HT_OUTOFMEM("HTLoadWAIS");
+ 
+     HTNet_setEventCallback(net, HTWAISEvent);
+     HTNet_setEventParam(net, theWAISinfo);  /* callbacks get theWAISinfo* */
+     HTNet_setContext(net, theWAISinfo);
+ 
+     theWAISinfo->state  = HTWAIS_BEGIN;
+     theWAISinfo->result = HT_ERROR;
+     theWAISinfo->net    = net;
+    }
+ 
+  /* get it started - ops is ignored */
+  return HTWAISEvent(soc, theWAISinfo, HTEvent_BEGIN);
+ }
Index: Library/src/HTWWWStr.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/HTWWWStr.c,v
retrieving revision 2.22
retrieving revision 2.23
diff -w -c -r2.22 -r2.23
*** HTWWWStr.c	1998/02/07 23:59:29	2.22
--- HTWWWStr.c	1998/03/20 17:53:11	2.23
***************
*** 3,9 ****
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTWWWStr.c,v 2.22 1998/02/07 23:59:29 frystyk Exp $
  **
  **      Now 13 95	Spwaned from HTString.c
  */
--- 3,9 ----
  **
  **	(c) COPYRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTWWWStr.c,v 2.23 1998/03/20 17:53:11 frystyk Exp $
  **
  **      Now 13 95	Spwaned from HTString.c
  */
***************
*** 278,284 ****
  	return "";
      }
  #ifdef HAVE_GETPID
!     sprintf(buf, "<%ldZ%ld@%s>", sectime, (long)getpid(), address ? address : "@@@");
  #else
      sprintf(buf, "<%ldZ%s>", sectime, address ? address : "@@@");
  #endif /* HAVE_GETPID */
--- 278,284 ----
  	return "";
      }
  #ifdef HAVE_GETPID
!     sprintf(buf, "<%ldZ%ld@%s>", (long)sectime, (long)getpid(), address ? address : "@@@");
  #else
      sprintf(buf, "<%ldZ%s>", sectime, address ? address : "@@@");
  #endif /* HAVE_GETPID */
Index: Library/src/Makefile.am
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/Makefile.am,v
retrieving revision 2.30
retrieving revision 2.32
diff -w -c -r2.30 -r2.32
*** Makefile.am	1998/02/07 23:59:31	2.30
--- Makefile.am	1998/03/22 21:39:48	2.32
***************
*** 10,15 ****
--- 10,18 ----
  .html.h:
  	www -w90 -na -p -to text/x-c $(srcdir)/$(*F).html > $(srcdir)/$(*F).h
  
+ icondir = @icondir@
+ CPPFLAGS := $(CPPFLAGS) -DW3C_ICONS=\"$(icondir)\"
+ 
  inc: $(BUILT_SOURCES)
  	@echo Generated built sources
  
***************
*** 108,113 ****
--- 111,118 ----
  	HTMux.h		HTDemux.h	HTMuxTx.h \
  	HTMuxCh.h 	HTHstMan.h	HTMemLog.h \
  	HTTimer.h	HTWAIS.h	HTZip.h
+ 
+ pkginclude_HEADERS = $(BUILT_SOURCES)
  
  DOCS :=	$(wildcard *.html)
  
Index: Library/src/sysdep.html
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/sysdep.html,v
retrieving revision 2.111
retrieving revision 2.112
diff -w -c -r2.111 -r2.112
*** sysdep.html	1997/12/16 21:09:37	2.111
--- sysdep.html	1998/03/20 17:53:13	2.112
***************
*** 707,712 ****
--- 707,720 ----
  #endif
  #endif
  
+ /* Patch for problems in glibc6 */
+ #if defined(__GLIBC__)
+ #undef S_IFMT
+ #undef S_IFDIR
+ #define S_IFMT __S_IFMT
+ #define S_IFDIR __S_IFDIR
+ #endif
+ 
  /* tcp.h */
  #ifdef HAVE_NETINET_TCP_H
  #include &lt;netinet/tcp.h&gt;
***************
*** 1012,1017 ****
--- 1020,1040 ----
  #endif
  </PRE>
  <H2>
+   Integers
+ </H2>
+ If we don't have these (for some mysterious reason) then define them. This should
+ (is?) be handled by the configure script already.
+ <PRE>
+ #ifndef u_short
+ #define u_short unsigned short
+ #endif
+ 
+ #ifndef u_long
+ #define u_long unsigned long
+ #endif
+ </PRE>
+ 
+ <H2>
    NULL Definition
  </H2>
  <PRE>
***************
*** 1312,1317 ****
  <P>
    <HR>
  <ADDRESS>
!   @(#) $Id: sysdep.html,v 2.111 1997/12/16 21:09:37 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
--- 1335,1340 ----
  <P>
    <HR>
  <ADDRESS>
!   @(#) $Id: sysdep.html,v 2.112 1998/03/20 17:53:13 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
Index: Library/src/windows/config.h
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Library/src/windows/config.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -w -c -r1.10 -r1.11
*** config.h	1998/03/04 15:46:27	1.10
--- config.h	1998/03/20 17:53:16	1.11
***************
*** 97,103 ****
  #define W3C_PACKAGE "w3c-libwww"
  
  /* Define to be the version. */
! #define W3C_VERSION "5.1j"
  
  /* Define to be the location of the W3C Icons */
  #define W3C_ICONS "/usr/local/share/w3c-icons"
--- 97,103 ----
  #define W3C_PACKAGE "w3c-libwww"
  
  /* Define to be the version. */
! #define W3C_VERSION "5.1k"
  
  /* Define to be the location of the W3C Icons */
  #define W3C_ICONS "/usr/local/share/w3c-icons"
***************
*** 146,151 ****
--- 146,163 ----
  
  /* Define this if it isn't in the header files.  */
  /* #undef u_long */
+ 
+ /* Define if time_t is of type long */
+ #define HAVE_LONG_TIME_T 1
+ 
+ /* Define if size_t is of type long */
+ /* undef HAVE_LONG_SIZE_T */
+ 
+ /* The number of bytes in a char.  */
+ #define SIZEOF_CHAR 1
+ 
+ /* The number of bytes in a char *.  */
+ #define SIZEOF_CHAR_P 4
  
  /* The number of bytes in a int.  */
  #define SIZEOF_INT 4
Index: LineMode/User/CommandLine.html
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/LineMode/User/CommandLine.html,v
retrieving revision 1.20
retrieving revision 1.21
diff -w -c -r1.20 -r1.21
*** CommandLine.html	1997/01/27 22:52:17	1.20
--- CommandLine.html	1998/03/22 21:39:52	1.21
***************
*** 242,251 ****
      makes selective directory listings and places a README file at the top
  </DL>
  <H3>
!   Configuration Options
  </H3>
  <DL>
    <DT>
      <B>-x</B> 1*( i | n | a )
    <DD>
      There are various ways of handling Expires header when met in a history list
--- 242,262 ----
      makes selective directory listings and places a README file at the top
  </DL>
  <H3>
!   Persistent Cache
  </H3>
+ 
  <DL>
    <DT>
+     <B>-nocache</B>
+   <DD>
+     Disables the persistent cache. By default the cache is used so use this flag
+     if you really don't want it.
+   <DT>
+     <B>-disconnected</B>
+   <DD>
+     Sets the persistent cache to run in disconnected mode. That is, if the object
+     is not already cached then we don't go get it.
+   <DT>
      <B>-x</B> 1*( i | n | a )
    <DD>
      There are various ways of handling Expires header when met in a history list
***************
*** 253,258 ****
--- 264,288 ----
      can be <B>N</B>otified with a warning, or the document can be reloaded
      <B>A</B>utomatically. The default action is to ignore expired documents.
    <DT>
+     <B>-r</B> &lt;file&gt;
+   <DD>
+     Rule file, a.k.a.
+     <A HREF="../../Library/User/Using/RuleSyntax.html">configuration file</A>.
+     If this is specified, a rule file may be used to map URLs, and to set up
+     other aspects of the behavior of the browser. Many rule files may be given
+     with successive -r options, and a default rule file name may be given using
+     the <B>WWW_CONFIG</B> environment variable.
+   <DT>
+     <B>-timeout</B> &lt;n&gt;
+   <DD>
+     Timeout in milli-seconds on sockets
+ </DL>
+ 
+ <H3>
+   Configuration Options
+ </H3>
+ <DL>
+   <DT>
      <B>-l</B> [ file ]
    <DD>
      Specifies a log file with a list of visited documents. The default value
***************
*** 291,296 ****
  <ADDRESS>
    <A HREF="../../People.html#Frystyk">Henrik Frystyk Nielsen</A>,
    <A HREF="mailto:libwww@w3.org">libwww@w3.org</A>,<BR>
!   @(#) $Id: CommandLine.html,v 1.20 1997/01/27 22:52:17 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
--- 321,326 ----
  <ADDRESS>
    <A HREF="../../People.html#Frystyk">Henrik Frystyk Nielsen</A>,
    <A HREF="mailto:libwww@w3.org">libwww@w3.org</A>,<BR>
!   @(#) $Id: CommandLine.html,v 1.21 1998/03/22 21:39:52 frystyk Exp $
  </ADDRESS>
  </BODY></HTML>
Index: LineMode/src/HTBrowse.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/LineMode/src/HTBrowse.c,v
retrieving revision 1.174
retrieving revision 1.175
diff -w -c -r1.174 -r1.175
*** HTBrowse.c	1998/03/09 15:32:02	1.174
--- HTBrowse.c	1998/03/22 21:39:54	1.175
***************
*** 3,9 ****
  **
  **	(c) COPRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTBrowse.c,v 1.174 1998/03/09 15:32:02 frystyk Exp $
  **
  **  Authors:
  **	NP:  Nicola Pellow  Tech.Student CERN 1990-91
--- 3,9 ----
  **
  **	(c) COPRIGHT MIT 1995.
  **	Please first read the full copyright statement in the file COPYRIGH.
! **	@(#) $Id: HTBrowse.c,v 1.175 1998/03/22 21:39:54 frystyk Exp $
  **
  **  Authors:
  **	NP:  Nicola Pellow  Tech.Student CERN 1990-91
***************
*** 1813,1818 ****
--- 1813,1822 ----
  	    /* Disconnected operation */
  	    } else if (!strncmp(argv[arg], "-discon", 7)) {
  		HTCacheMode_setDisconnected(HT_DISCONNECT_NORMAL);
+ 
+ 	    /* Disable the cache */
+ 	    } else if (!strncmp(argv[arg], "-nocache", 8)) {
+ 		HTCacheMode_setEnabled(NO);
  
  	    /* Handling of Expire (cache) */
  	    } else if (!strncmp(argv[arg], "-x", 2)) { 
Index: Robot/src/HTRobot.c
===================================================================
RCS file: /afs/w3.org/CVS-Repository/WWW/Robot/src/HTRobot.c,v
retrieving revision 1.66
retrieving revision 1.67
diff -w -c -r1.66 -r1.67
*** HTRobot.c	1998/02/27 18:36:04	1.66
--- HTRobot.c	1998/03/20 17:53:18	1.67
***************
*** 1471,1478 ****
      if (mr->flags & MR_TIME) {
  	if (SHOW_REAL_QUIET(mr)) {
  	    time_t local = time(NULL);
! 	    HTTrace("Welcome to the W3C mini Robot - started on %s\n",
! 		    HTDateTimeStr(&local, YES));
  	}
      }
  
--- 1471,1478 ----
      if (mr->flags & MR_TIME) {
  	if (SHOW_REAL_QUIET(mr)) {
  	    time_t local = time(NULL);
! 	    HTTrace("Welcome to the W3C mini Robot version %s - started on %s\n",
! 		    APP_VERSION, HTDateTimeStr(&local, YES));
  	}
      }
  
