get rid of the readline and libhistory dependancies by default, release

* configure.in: get rid of the readline and libhistory
  dependancies by default, release 2.4.1 with IA64 fix
* nanohttp.c tree.c xmlIO.c include/libxml/nanohttp.h
  include/libxml/tree.h include/libxml/xmlIO.h: incorporated
  John Kroll fixes to allow saving to HTTP via PUT (or
  POST of needed).
* doc/html/*.html: regenerated the docs
Daniel
diff --git a/nanohttp.c b/nanohttp.c
index fb4fbd0..c29cc7a 100644
--- a/nanohttp.c
+++ b/nanohttp.c
@@ -63,6 +63,7 @@
 #define SOCKET int
 #endif
 
+#include <libxml/xmlerror.h>
 #include <libxml/xmlmemory.h>
 #include <libxml/parser.h> /* for xmlStr(n)casecmp() */
 #include <libxml/nanohttp.h>
@@ -75,6 +76,7 @@
 #define SOCKET int
 #endif
 
+
 #ifdef STANDALONE
 #define DEBUG_HTTP
 #define xmlStrncasecmp(a, b, n) strncasecmp((char *)a, (char *)b, n)
@@ -106,6 +108,7 @@
     int inlen;		/* len of the input buffer */
     int last;		/* return code for last operation */
     int returnValue;	/* the protocol return value */
+    int ContentLength;  /* specified content length from HTTP header */
     char *contentType;	/* the MIME type for the input */
     char *location;	/* the new URL in case of redirect */
     char *authHeader;	/* contents of {WWW,Proxy}-Authenticate header */
@@ -116,6 +119,9 @@
 static int proxyPort;	/* the proxy port if any */
 static unsigned int timeout = 60;/* the select() timeout in seconds */
 
+int xmlNanoHTTPFetchContent( void * ctx, char ** ptr, int * len );
+int xmlNanoHTTPContentLength( void * ctx );
+
 /**
  * A portability function
  */
@@ -358,6 +364,7 @@
     ret->port = 80;
     ret->returnValue = 0;
     ret->fd = -1;
+    ret->ContentLength = -1;
 
     xmlNanoHTTPScanURL(ret, URL);
 
@@ -393,20 +400,52 @@
  * @ctxt:  an HTTP context
  *
  * Send the input needed to initiate the processing on the server side
+ * Returns number of bytes sent or -1 on error.
  */
 
-static void
-xmlNanoHTTPSend(xmlNanoHTTPCtxtPtr ctxt) {
-    if (ctxt->state & XML_NANO_HTTP_WRITE) {
-        unsigned int total_sent = 0;
-        while (total_sent <strlen(ctxt->outptr)) {
-            unsigned int nsent = send(ctxt->fd, ctxt->outptr+total_sent,
-                                      strlen(ctxt->outptr)-total_sent, 0);
+static int
+xmlNanoHTTPSend(xmlNanoHTTPCtxtPtr ctxt, const char * xmt_ptr, int outlen) {
+
+    int 	total_sent = 0;
+
+    if ( (ctxt->state & XML_NANO_HTTP_WRITE) && (xmt_ptr != NULL ) ) {
+        while (total_sent < outlen) {
+            int nsent = send(ctxt->fd, xmt_ptr + total_sent,
+                                      outlen - total_sent, 0);
             if (nsent>0)
                 total_sent += nsent;
+	    else if ( ( nsent == -1 ) && 
+	    	      ( socket_errno( ) != EAGAIN ) &&
+		        ( socket_errno( ) != EWOULDBLOCK ) ) {
+	        xmlGenericError( xmlGenericErrorContext,
+				"xmlNanoHTTPSend error:  %s",
+				strerror( socket_errno( ) ) );
+
+		if ( total_sent == 0 )
+		    total_sent = -1;
+		break;
+	    }
+	    else {
+	        /*
+		**  No data sent
+		**  Since non-blocking sockets are used, wait for 
+		**  socket to be writable or default timeout prior
+		**  to retrying.
+		*/
+
+		struct timeval	tv;
+		fd_set		wfd;
+
+		tv.tv_sec = timeout;
+		tv.tv_usec = 0;
+		FD_ZERO( &wfd );
+		FD_SET( ctxt->fd, &wfd );
+		(void)select( ctxt->fd + 1, NULL, &wfd, NULL, &tv );
+	    }
 	}
-        ctxt->last = total_sent;
     }
+
+    return total_sent;
 }
 
 /**
@@ -430,6 +469,8 @@
 	    ctxt->in = (char *) xmlMalloc(65000 * sizeof(char));
 	    if (ctxt->in == NULL) {
 	        ctxt->last = -1;
+		xmlGenericError( xmlGenericErrorContext, 
+			"xmlNanoHTTPRecv:  Error allocating input memory." );
 		return(-1);
 	    }
 	    ctxt->inlen = 65000;
@@ -448,10 +489,16 @@
 	    int d_inptr = ctxt->inptr - ctxt->in;
 	    int d_content = ctxt->content - ctxt->in;
 	    int d_inrptr = ctxt->inrptr - ctxt->in;
+	    char *	tmp_ptr = ctxt->in;
 
 	    ctxt->inlen *= 2;
-            ctxt->in = (char *) xmlRealloc(ctxt->in, ctxt->inlen);
+            ctxt->in = (char *) xmlRealloc(tmp_ptr, ctxt->inlen);
 	    if (ctxt->in == NULL) {
+	        xmlGenericError( xmlGenericErrorContext,
+				"xmlNanoHTTPRecv:  %s %d bytes.",
+				"Failed to realloc input buffer to",
+				ctxt->inlen );
+		xmlFree( tmp_ptr );
 	        ctxt->last = -1;
 		return(-1);
 	    }
@@ -475,8 +522,16 @@
 		case EAGAIN:
 #endif
 		    break;
+
+		case ECONNRESET:
+		case ESHUTDOWN:
+		    return ( 0 );
+
 		default:
-		    return(0);
+		    xmlGenericError( xmlGenericErrorContext,
+		    		"xmlNanoHTTPRecv:  recv( ) failure - %s",
+				strerror( socket_errno( ) ) );
+		    return(-1);
 	    }
 	}
 
@@ -485,7 +540,7 @@
 	FD_ZERO(&rfd);
 	FD_SET(ctxt->fd, &rfd);
 	
-	if (select(ctxt->fd+1, &rfd, NULL, NULL, &tv)<1)
+	if ( (select(ctxt->fd+1, &rfd, NULL, NULL, &tv)<1) && (errno != EINTR) )
 		return(0);
     }
     return(0);
@@ -506,16 +561,20 @@
 xmlNanoHTTPReadLine(xmlNanoHTTPCtxtPtr ctxt) {
     char buf[4096];
     char *bp = buf;
+    int	rc;
     
     while (bp - buf < 4095) {
 	if (ctxt->inrptr == ctxt->inptr) {
-	    if (xmlNanoHTTPRecv(ctxt) == 0) {
+	    if ( (rc = xmlNanoHTTPRecv(ctxt)) == 0) {
 		if (bp == buf)
 		    return(NULL);
 		else
 		    *bp = 0;
 		return(xmlMemStrdup(buf));
 	    }
+	    else if ( rc == -1 ) {
+	        return ( NULL );
+	    }
 	}
 	*bp = *ctxt->inrptr++;
 	if (*bp == '\n') {
@@ -610,6 +669,9 @@
 	if (ctxt->authHeader != NULL)
 	    xmlFree(ctxt->authHeader);
 	ctxt->authHeader = xmlMemStrdup(cur);
+    } else if ( !xmlStrncasecmp( BAD_CAST line, BAD_CAST"Content-Length:", 15) ) {
+	cur += 15;
+	ctxt->ContentLength = strtol( cur, NULL, 10 );
     }
 }
 
@@ -636,6 +698,10 @@
 #ifdef DEBUG_HTTP
 	perror("socket");
 #endif
+	xmlGenericError( xmlGenericErrorContext,
+			"xmlNanoHTTPConnectAttempt: %s - %s",
+			"socket creation failure",
+			strerror( socket_errno( ) ) );
 	return(-1);
     }
     
@@ -666,20 +732,26 @@
 #ifdef DEBUG_HTTP
 	perror("nonblocking");
 #endif
+	xmlGenericError( xmlGenericErrorContext,
+			"xmlNanoHTTPConnectAttempt:  %s - %s",
+			"error setting non-blocking IO",
+			strerror( socket_errno( ) ) );
 	closesocket(s);
 	return(-1);
     }
 #endif /* !VMS */
 #endif /* !_WINSOCKAPI_ */
 
-
     if ((connect(s, addr, sizeof(*addr))==-1)) {
 	switch (socket_errno()) {
 	    case EINPROGRESS:
 	    case EWOULDBLOCK:
 		break;
 	    default:
-		perror("connect");
+		xmlGenericError( xmlGenericErrorContext,
+				"xmlNanoHTTPConnectAttempt:  %s - %s",
+				"error connecting to HTTP server",
+				strerror( socket_errno( ) ) );
 		closesocket(s);
 		return(-1);
 	}
@@ -695,13 +767,17 @@
     {
 	case 0:
 	    /* Time out */
+	    xmlGenericError( xmlGenericErrorContext, 
+	    			"xmlNanoHTTPConnectAttempt: %s",
+				"Connect attempt timed out." );
 	    closesocket(s);
 	    return(-1);
 	case -1:
 	    /* Ermm.. ?? */
-#ifdef DEBUG_HTTP
-	    perror("select");
-#endif
+	    xmlGenericError( xmlGenericErrorContext,
+	    			"xmlNanoHTTPConnectAttempt: %s - %s",
+				"Error connecting to host",
+				strerror( socket_errno( ) ) );
 	    closesocket(s);
 	    return(-1);
     }
@@ -711,15 +787,27 @@
 	len = sizeof(status);
 	if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&status, &len) < 0 ) {
 	    /* Solaris error code */
+	    xmlGenericError( xmlGenericErrorContext,
+	    			"xmlNanoHTTPConnectAttempt: %s - %s",
+				"Error retrieving pending socket errors",
+				strerror( socket_errno( ) ) );
 	    return (-1);
 	}
 	if ( status ) {
 	    closesocket(s);
 	    errno = status;
+	    xmlGenericError( xmlGenericErrorContext,
+	    			"xmlNanoHTTPConnectAttempt: %s - %s",
+				"Error connecting to remote host",
+				strerror( status ) );
 	    return (-1);
 	}
     } else {
 	/* pbm */
+	xmlGenericError( xmlGenericErrorContext,
+		"xmlNanoHTTPConnectAttempt:  %s\n",
+		"Select returned, but descriptor not set for connection.\n" );
+	closesocket(s);
 	return (-1);
     }
     
@@ -759,9 +847,34 @@
     h=gethostbyname(host);
     if (h==NULL)
     {
-#ifdef DEBUG_HTTP
-	xmlGenericError(xmlGenericErrorContext,"unable to resolve '%s'.\n", host);
-#endif
+        const char *	h_err_txt = "";
+	switch ( h_errno )
+	{
+	    case HOST_NOT_FOUND:
+	        h_err_txt = "Authoritive host not found";
+		break;
+	    
+	    case TRY_AGAIN:
+		h_err_txt =
+			"Non-authoritive host not found or server failure.";
+		break;
+
+	    case NO_RECOVERY:
+		h_err_txt =
+		    "Non-recoverable errors:  FORMERR, REFUSED, or NOTIMP.";
+		break;
+
+	    case NO_ADDRESS:
+		h_err_txt = "Valid name, no data record of requested type.";
+		break;
+
+	    default:
+	        h_err_txt = "No error text defined.";
+	        break;
+	}
+	xmlGenericError( xmlGenericErrorContext,
+			"xmlNanoHTTPConnectHost:  %s '%s' - %s",
+			"Failed to resolve host", host, h_err_txt );
 	return(-1);
     }
     
@@ -793,7 +906,7 @@
 
 #ifdef DEBUG_HTTP
     xmlGenericError(xmlGenericErrorContext,
-	    "unable to connect to '%s'.\n", host);
+	    "xmlNanoHTTPConnectHost:  unable to connect to '%s'.\n", host);
 #endif
     return(-1);
 }
@@ -815,7 +928,7 @@
 void*
 xmlNanoHTTPOpen(const char *URL, char **contentType) {
     if (contentType != NULL) *contentType = NULL;
-    return(xmlNanoHTTPMethod(URL, NULL, NULL, contentType, NULL));
+    return(xmlNanoHTTPMethod(URL, NULL, NULL, contentType, NULL, 0));
 }
 
 /**
@@ -836,7 +949,7 @@
 xmlNanoHTTPOpenRedir(const char *URL, char **contentType, char **redir) {
     if (contentType != NULL) *contentType = NULL;
     if (redir != NULL) *redir = NULL;
-    return(xmlNanoHTTPMethodRedir(URL, NULL, NULL, contentType, redir, NULL));
+    return(xmlNanoHTTPMethodRedir(URL, NULL, NULL, contentType, redir, NULL,0));
 }
 
 /**
@@ -860,7 +973,7 @@
     if (len <= 0) return(0);
 
     while (ctxt->inptr - ctxt->inrptr < len) {
-        if (xmlNanoHTTPRecv(ctxt) == 0) break;
+        if (xmlNanoHTTPRecv(ctxt) <= 0) break;
     }
     if (ctxt->inptr - ctxt->inrptr < len)
         len = ctxt->inptr - ctxt->inrptr;
@@ -904,11 +1017,13 @@
 
 void*
 xmlNanoHTTPMethodRedir(const char *URL, const char *method, const char *input,
-                  char **contentType, char **redir, const char *headers) {
+                  char **contentType, char **redir,
+		  const char *headers, int ilen ) {
     xmlNanoHTTPCtxtPtr ctxt;
     char *bp, *p;
-    int blen, ilen, ret;
+    int blen, ret;
     int head;
+    int xmt_bytes;
     int nbRedirects = 0;
     char *redirURL = NULL;
     
@@ -923,12 +1038,28 @@
 	ctxt = xmlNanoHTTPNewCtxt(redirURL);
     }
 
+    if ( ctxt == NULL ) {
+	xmlGenericError( xmlGenericErrorContext,
+			"xmlNanoHTTPMethodRedir:  %s %s.",
+			"Unable to allocate HTTP context to URI",
+			( ( redirURL == NULL ) ? URL : redirURL ) );
+	return ( NULL );
+    }
+
     if ((ctxt->protocol == NULL) || (strcmp(ctxt->protocol, "http"))) {
+	xmlGenericError( xmlGenericErrorContext,
+			"xmlNanoHTTPMethodRedir:  %s - %s.",
+			"Not a valid HTTP URI",
+			( ( redirURL == NULL ) ? URL : redirURL ) );
         xmlNanoHTTPFreeCtxt(ctxt);
 	if (redirURL != NULL) xmlFree(redirURL);
         return(NULL);
     }
     if (ctxt->hostname == NULL) {
+	xmlGenericError( xmlGenericErrorContext,
+			"xmlNanoHTTPMethodRedir:  %s - %s",
+			"Failed to identify host in URI",
+			( ( redirURL == NULL ) ? URL : redirURL ) );
         xmlNanoHTTPFreeCtxt(ctxt);
 	if (redirURL != NULL) xmlFree(redirURL);
         return(NULL);
@@ -948,43 +1079,52 @@
     }
     ctxt->fd = ret;
 
-    if (input != NULL) {
-	ilen = strlen(input);
-	blen += ilen + 32;
-    }
-    else
+    if (input == NULL)
 	ilen = 0;
+    else
+	blen += 36;
+
     if (headers != NULL)
-	blen += strlen(headers);
+	blen += strlen(headers) + 2;
     if (contentType && *contentType)
 	blen += strlen(*contentType) + 16;
-    blen += strlen(method) + strlen(ctxt->path) + 23;
+    blen += strlen(method) + strlen(ctxt->path) + 24;
     bp = xmlMalloc(blen);
+    if ( bp == NULL ) {
+        xmlNanoHTTPFreeCtxt( ctxt );
+	xmlGenericError( xmlGenericErrorContext,
+			"xmlNanoHTTPMethodRedir:  %s",
+			"Error allocating HTTP header buffer." );
+	return ( NULL );
+    }
+
+    p = bp;
+
     if (proxy) {
 	if (ctxt->port != 80) {
-	    sprintf(bp, "%s http://%s:%d%s", method, ctxt->hostname,
-		 ctxt->port, ctxt->path);
+	    p += sprintf( p, "%s http://%s:%d%s", method, ctxt->hostname,
+		 	ctxt->port, ctxt->path );
 	}
 	else
-	    sprintf(bp, "%s http://%s%s", method, ctxt->hostname, ctxt->path);
+	    p += sprintf( p, "%s http://%s%s", method,
+	    		ctxt->hostname, ctxt->path);
     }
     else
-	sprintf(bp, "%s %s", method, ctxt->path);
-    p = bp + strlen(bp);
-    sprintf(p, " HTTP/1.0\r\nHost: %s\r\n", ctxt->hostname);
-    p += strlen(p);
-    if (contentType != NULL && *contentType) {
-	sprintf(p, "Content-Type: %s\r\n", *contentType);
-	p += strlen(p);
-    }
-    if (headers != NULL) {
-	strcpy(p, headers);
-	p += strlen(p);
-    }
+	p += sprintf( p, "%s %s", method, ctxt->path);
+
+    p += sprintf(p, " HTTP/1.0\r\nHost: %s\r\n", ctxt->hostname);
+
+    if (contentType != NULL && *contentType) 
+	p += sprintf(p, "Content-Type: %s\r\n", *contentType);
+
+    if (headers != NULL)
+	p += sprintf( p, "%s", headers );
+
     if (input != NULL)
-	sprintf(p, "Content-Length: %d\r\n\r\n%s", ilen, input);
+	sprintf(p, "Content-Length: %d\r\n\r\n", ilen );
     else
 	strcpy(p, "\r\n");
+
 #ifdef DEBUG_HTTP
     xmlGenericError(xmlGenericErrorContext,
 	    "-> %s%s", proxy? "(Proxy) " : "", bp);
@@ -994,7 +1134,30 @@
 #endif
     ctxt->outptr = ctxt->out = bp;
     ctxt->state = XML_NANO_HTTP_WRITE;
-    xmlNanoHTTPSend(ctxt);
+    blen = strlen( ctxt->out );
+    xmt_bytes = xmlNanoHTTPSend(ctxt, ctxt->out, blen );
+#ifdef DEBUG_HTTP
+    if ( xmt_bytes != blen )
+        xmlGenericError( xmlGenericErrorContext,
+			"xmlNanoHTTPMethodRedir:  Only %d of %d %s %s\n",
+			xmt_bytes, blen,
+			"bytes of HTTP headers sent to host",
+			ctxt->hostname );
+#endif
+
+    if ( input != NULL ) {
+        xmt_bytes = xmlNanoHTTPSend( ctxt, input, ilen );
+
+#ifdef DEBUG_HTTP
+	if ( xmt_bytes != ilen )
+	    xmlGenericError( xmlGenericErrorContext,
+	    		"xmlNanoHTTPMethodRedir:  Only %d of %d %s %s\n",
+			xmt_bytes, ilen,
+			"bytes of HTTP content sent to host",
+			ctxt->hostname );
+#endif
+    }
+
     ctxt->state = XML_NANO_HTTP_READ;
     head = 1;
 
@@ -1019,7 +1182,7 @@
 	xmlGenericError(xmlGenericErrorContext,
 		"\nRedirect to: %s\n", ctxt->location);
 #endif
-	while (xmlNanoHTTPRecv(ctxt)) ;
+	while ( xmlNanoHTTPRecv(ctxt) > 0 ) ;
         if (nbRedirects < XML_NANO_HTTP_MAX_REDIR) {
 	    nbRedirects++;
 	    if (redirURL != NULL)
@@ -1032,10 +1195,9 @@
 	if (redirURL != NULL) xmlFree(redirURL);
 #ifdef DEBUG_HTTP
 	xmlGenericError(xmlGenericErrorContext,
-		"Too many redirects, aborting ...\n");
+		"xmlNanoHTTPMethodRedir: Too many redirects, aborting ...\n");
 #endif
 	return(NULL);
-
     }
 
     if (contentType != NULL) {
@@ -1086,9 +1248,9 @@
 
 void*
 xmlNanoHTTPMethod(const char *URL, const char *method, const char *input,
-                  char **contentType, const char *headers) {
+                  char **contentType, const char *headers, int ilen) {
     return(xmlNanoHTTPMethodRedir(URL, method, input, contentType,
-		                  NULL, headers));
+		                  NULL, headers, ilen));
 }
 
 /**
@@ -1106,8 +1268,8 @@
  */
 int
 xmlNanoHTTPFetch(const char *URL, const char *filename, char **contentType) {
-    void *ctxt;
-    char buf[4096];
+    void *ctxt = NULL;
+    char *buf = NULL;
     int fd;
     int len;
     
@@ -1128,7 +1290,8 @@
 	}
     }
 
-    while ((len = xmlNanoHTTPRead(ctxt, buf, sizeof(buf))) > 0) {
+    xmlNanoHTTPFetchContent( ctxt, &buf, &len );
+    if ( len > 0 ) {
 	write(fd, buf, len);
     }
 
@@ -1165,7 +1328,8 @@
 	}
     }
 
-    while ((len = xmlNanoHTTPRead(ctxt, buf, sizeof(buf))) > 0) {
+    xmlNanoHTTPFetchContent( ctxt, &buf, &len );
+    if ( len > 0 ) {
 	write(fd, buf, len);
     }
 
@@ -1208,6 +1372,77 @@
     return(ctxt->authHeader);
 }
 
+/**
+ * xmlNanoHTTPContentLength
+ * @ctx:  the HTTP context
+ *
+ * Return the specified content length from the HTTP header.  Note that
+ * a value of -1 indicates that the content length element was not included in
+ * the response header.
+ */
+int
+xmlNanoHTTPContentLength( void * ctx ) {
+    xmlNanoHTTPCtxtPtr	ctxt = ctx;
+
+    return ( ( ctxt == NULL ) ? -1 : ctxt->ContentLength );
+}
+
+/**
+ * xmlNanoHTTPFetchContent
+ * @ctx:  the HTTP context
+ * @ptr:  pointer to set to the content buffer.
+ * @len:  integer pointer to hold the length of the content
+ *
+ * Returns 0 if all the content was read and available, returns
+ * -1 if received content length was less than specified or an error 
+ * occurred.
+ */
+int
+xmlNanoHTTPFetchContent( void * ctx, char ** ptr, int * len ) {
+    xmlNanoHTTPCtxtPtr	ctxt = ctx;
+
+    int			rc = 0;
+    int			cur_lgth;
+    int			rcvd_lgth;
+    int			dummy_int;
+    char *		dummy_ptr = NULL;
+
+    /*  Dummy up return input parameters if not provided  */
+
+    if ( len == NULL )
+        len = &dummy_int;
+
+    if ( ptr == NULL )
+        ptr = &dummy_ptr;
+
+    /*  But can't work without the context pointer  */
+
+    if ( ( ctxt == NULL ) || ( ctxt->content == NULL ) ) {
+        *len = 0;
+	*ptr = NULL;
+	return ( -1 );
+    }
+
+    rcvd_lgth = ctxt->inptr - ctxt->content;
+
+    while ( (cur_lgth = xmlNanoHTTPRecv( ctxt )) > 0 ) {
+
+	rcvd_lgth += cur_lgth;
+	if ( (ctxt->ContentLength > 0) && (rcvd_lgth >= ctxt->ContentLength) )
+	    break;
+    }
+
+    *ptr = ctxt->content;
+    *len = rcvd_lgth;
+
+    if ( ( ctxt->ContentLength > 0 ) && ( rcvd_lgth < ctxt->ContentLength ) )
+        rc = -1;
+    else if ( rcvd_lgth == 0 )
+	rc = -1;
+
+    return ( rc );
+}
+
 #ifdef STANDALONE
 int main(int argc, char **argv) {
     char *contentType = NULL;