nanohttp.c revision 50f3437111a6428b4852740e83db4848b0b09a97
13473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
23473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * nanohttp.c: minimalist HTTP GET implementation to fetch external subsets.
33473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *             focuses on size, streamability, reentrancy and portability
43473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
53473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * This is clearly not a general purpose HTTP implementation
63473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If you look for one, check:
73473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *         http://www.w3.org/Library/
83473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
93473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * See Copyright for the status of this software.
103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
11c5d64345cf19bfd72418eb0a837869b0462e9130Daniel Veillard * daniel@veillard.com
123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/* TODO add compression support, Send the Accept- , and decompress on the
153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        fly with ZLIB if found at compile-time */
163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
17f3afa7dd4e8daacfa62f7345b7d7071e0cb33423Daniel Veillard#define NEED_SOCKETS
1870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese#include "libxml.h"
193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_HTTP_ENABLED
213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <string.h>
223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_STDLIB_H
243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <stdlib.h>
253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_UNISTD_H
273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <unistd.h>
283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_SYS_SOCKET_H
303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <sys/socket.h>
313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_NETINET_IN_H
333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <netinet/in.h>
343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_ARPA_INET_H
363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <arpa/inet.h>
373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_NETDB_H
393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <netdb.h>
403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_FCNTL_H
423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <fcntl.h>
433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_ERRNO_H
453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <errno.h>
463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_SYS_TIME_H
483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <sys/time.h>
493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_SYS_SELECT_H
513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <sys/select.h>
523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_STRINGS_H
543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <strings.h>
553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef SUPPORT_IP6
573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <resolv.h>
583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef VMS
613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <stropts>
623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define SOCKLEN_T unsigned int
633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define SOCKET int
643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard#include <libxml/xmlerror.h>
673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/xmlmemory.h>
683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/parser.h> /* for xmlStr(n)casecmp() */
693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/nanohttp.h>
703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * A couple portability macros
733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifndef _WINSOCKAPI_
753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define closesocket(s) close(s)
763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define SOCKET int
773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
79f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef STANDALONE
813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define DEBUG_HTTP
823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define xmlStrncasecmp(a, b, n) strncasecmp((char *)a, (char *)b, n)
833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define xmlStrcasecmpi(a, b) strcasecmp((char *)a, (char *)b)
843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define XML_NANO_HTTP_MAX_REDIR	10
873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define XML_NANO_HTTP_CHUNK	4096
893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define XML_NANO_HTTP_CLOSED	0
913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define XML_NANO_HTTP_WRITE	1
923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define XML_NANO_HTTP_READ	2
933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define XML_NANO_HTTP_NONE	4
943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylortypedef struct xmlNanoHTTPCtxt {
963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char *protocol;	/* the protocol name */
973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char *hostname;	/* the host name */
983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int port;		/* the port */
993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char *path;		/* the path within the URL */
1003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SOCKET fd;		/* the file descriptor for the socket */
1013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int state;		/* WRITE / READ / CLOSED */
1023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char *out;		/* buffer sent (zero terminated) */
1033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char *outptr;	/* index within the buffer sent */
1043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char *in;		/* the receiving buffer */
1053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char *content;	/* the start of the content */
1063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char *inptr;	/* the next byte to read from network */
1073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char *inrptr;	/* the next byte to give back to the client */
1083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int inlen;		/* len of the input buffer */
1093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int last;		/* return code for last operation */
1103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int returnValue;	/* the protocol return value */
111f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    int ContentLength;  /* specified content length from HTTP header */
1123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char *contentType;	/* the MIME type for the input */
1133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char *location;	/* the new URL in case of redirect */
1143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char *authHeader;	/* contents of {WWW,Proxy}-Authenticate header */
1153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor} xmlNanoHTTPCtxt, *xmlNanoHTTPCtxtPtr;
1163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorstatic int initialized = 0;
1183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorstatic char *proxy = NULL;	 /* the proxy name if any */
1193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorstatic int proxyPort;	/* the proxy port if any */
1203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorstatic unsigned int timeout = 60;/* the select() timeout in seconds */
1213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
122f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillardint xmlNanoHTTPFetchContent( void * ctx, char ** ptr, int * len );
123f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillardint xmlNanoHTTPContentLength( void * ctx );
124f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
1253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
1263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * A portability function
1273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
12856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int socket_errno(void) {
1293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef _WINSOCKAPI_
1303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(WSAGetLastError());
1313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#else
1323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(errno);
1333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
1343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
1353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
1373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlNanoHTTPInit:
1383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Initialize the HTTP protocol layer.
1403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Currently it just checks for proxy informations
1413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
1423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
1443473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNanoHTTPInit(void) {
1453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    const char *env;
1463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef _WINSOCKAPI_
1473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    WSADATA wsaData;
1483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
1493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (initialized)
1513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
1523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef _WINSOCKAPI_
1543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
1553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
1563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
1573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (proxy == NULL) {
1593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	proxyPort = 80;
1603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	env = getenv("no_proxy");
1613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (env != NULL)
1623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    goto done;
1633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	env = getenv("http_proxy");
1643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (env != NULL) {
1653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlNanoHTTPScanProxy(env);
1663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    goto done;
1673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
1683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	env = getenv("HTTP_PROXY");
1693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (env != NULL) {
1703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlNanoHTTPScanProxy(env);
1713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    goto done;
1723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
1733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
1743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylordone:
1753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    initialized = 1;
1763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
1773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
1795e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * xmlNanoHTTPCleanup:
1803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Cleanup the HTTP protocol layer.
1823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
1833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
1853473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNanoHTTPCleanup(void) {
1863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (proxy != NULL)
1873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlFree(proxy);
1883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef _WINSOCKAPI_
1893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (initialized)
1903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	WSACleanup();
1913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
1923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    initialized = 0;
1933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return;
1943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
1953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
1973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlNanoHTTPScanURL:
1983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  an HTTP context
1993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @URL:  The URL used to initialize the context
2003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
2013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * (Re)Initialize an HTTP context by parsing the URL and finding
2023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the protocol host port and path it indicates.
2033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
2043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorstatic void
2063473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNanoHTTPScanURL(xmlNanoHTTPCtxtPtr ctxt, const char *URL) {
2073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    const char *cur = URL;
2083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char buf[4096];
20956a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard    int indx = 0;
2103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int port = 0;
2113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->protocol != NULL) {
2133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlFree(ctxt->protocol);
2143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->protocol = NULL;
2153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
2163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->hostname != NULL) {
2173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlFree(ctxt->hostname);
2183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->hostname = NULL;
2193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
2203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->path != NULL) {
2213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlFree(ctxt->path);
2223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->path = NULL;
2233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
2243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (URL == NULL) return;
22556a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard    buf[indx] = 0;
2263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (*cur != 0) {
2273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if ((cur[0] == ':') && (cur[1] == '/') && (cur[2] == '/')) {
22856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    buf[indx] = 0;
2293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ctxt->protocol = xmlMemStrdup(buf);
23056a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    indx = 0;
2313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            cur += 3;
2323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
2333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
23456a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	buf[indx++] = *cur++;
2353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
2363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (*cur == 0) return;
2373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
23856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard    buf[indx] = 0;
2393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (1) {
2403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur[0] == ':') {
24156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    buf[indx] = 0;
2423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ctxt->hostname = xmlMemStrdup(buf);
24356a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    indx = 0;
2443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    cur += 1;
2453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    while ((*cur >= '0') && (*cur <= '9')) {
2463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        port *= 10;
2473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		port += *cur - '0';
2483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		cur++;
2493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
2503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (port != 0) ctxt->port = port;
2513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    while ((cur[0] != '/') && (*cur != 0))
2523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        cur++;
2533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
2543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
2553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if ((*cur == '/') || (*cur == 0)) {
25656a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    buf[indx] = 0;
2573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ctxt->hostname = xmlMemStrdup(buf);
25856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    indx = 0;
2593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
2603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
26156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	buf[indx++] = *cur++;
2623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
2633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (*cur == 0)
2643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        ctxt->path = xmlMemStrdup("/");
2653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else {
26656a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard        indx = 0;
26756a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard        buf[indx] = 0;
2683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	while (*cur != 0)
26956a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    buf[indx++] = *cur++;
27056a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	buf[indx] = 0;
2713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->path = xmlMemStrdup(buf);
2723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
2733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
2743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
2763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlNanoHTTPScanProxy:
2773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @URL:  The proxy URL used to initialize the proxy context
2783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
2793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * (Re)Initialize the HTTP Proxy context by parsing the URL and finding
2803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the protocol host port it indicates.
2813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Should be like http://myproxy/ or http://myproxy:3128/
2823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * A NULL URL cleans up proxy informations.
2833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
2843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
2863473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNanoHTTPScanProxy(const char *URL) {
2873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    const char *cur = URL;
2883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char buf[4096];
28956a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard    int indx = 0;
2903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int port = 0;
2913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (proxy != NULL) {
2933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlFree(proxy);
2943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	proxy = NULL;
2953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
2963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (proxyPort != 0) {
2973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	proxyPort = 0;
2983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
2993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_HTTP
3003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (URL == NULL)
3013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
3023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"Removing HTTP proxy info\n");
3033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
3043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
3053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"Using HTTP proxy %s\n", URL);
3063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
3073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (URL == NULL) return;
30856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard    buf[indx] = 0;
3093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (*cur != 0) {
3103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if ((cur[0] == ':') && (cur[1] == '/') && (cur[2] == '/')) {
31156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    buf[indx] = 0;
31256a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    indx = 0;
3133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            cur += 3;
3143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
3153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
31656a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	buf[indx++] = *cur++;
3173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
3183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (*cur == 0) return;
3193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
32056a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard    buf[indx] = 0;
3213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (1) {
3223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur[0] == ':') {
32356a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    buf[indx] = 0;
3243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    proxy = xmlMemStrdup(buf);
32556a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    indx = 0;
3263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    cur += 1;
3273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    while ((*cur >= '0') && (*cur <= '9')) {
3283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        port *= 10;
3293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		port += *cur - '0';
3303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		cur++;
3313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
3323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (port != 0) proxyPort = port;
3333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    while ((cur[0] != '/') && (*cur != 0))
3343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        cur++;
3353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
3363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
3373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if ((*cur == '/') || (*cur == 0)) {
33856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    buf[indx] = 0;
3393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    proxy = xmlMemStrdup(buf);
34056a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    indx = 0;
3413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
3423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
34356a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	buf[indx++] = *cur++;
3443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
3453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
3463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
3473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
3483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlNanoHTTPNewCtxt:
3493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @URL:  The URL used to initialize the context
3503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
3513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Allocate and initialize a new HTTP context.
3523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
3533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns an HTTP context or NULL in case of error.
3543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
3553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
3563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorstatic xmlNanoHTTPCtxtPtr
3573473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNanoHTTPNewCtxt(const char *URL) {
3583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNanoHTTPCtxtPtr ret;
3593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
3603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlNanoHTTPCtxtPtr) xmlMalloc(sizeof(xmlNanoHTTPCtxt));
3613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) return(NULL);
3623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
3633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0, sizeof(xmlNanoHTTPCtxt));
3643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->port = 80;
3653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->returnValue = 0;
3663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->fd = -1;
367f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    ret->ContentLength = -1;
3683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
3693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNanoHTTPScanURL(ret, URL);
3703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
3713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
3723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
3733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
3743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
3753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlNanoHTTPFreeCtxt:
3763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  an HTTP context
3773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
3783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Frees the context after closing the connection.
3793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
3803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
3813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorstatic void
3823473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNanoHTTPFreeCtxt(xmlNanoHTTPCtxtPtr ctxt) {
3833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL) return;
3843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->hostname != NULL) xmlFree(ctxt->hostname);
3853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->protocol != NULL) xmlFree(ctxt->protocol);
3863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->path != NULL) xmlFree(ctxt->path);
3873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->out != NULL) xmlFree(ctxt->out);
3883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->in != NULL) xmlFree(ctxt->in);
3893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->contentType != NULL) xmlFree(ctxt->contentType);
3903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->location != NULL) xmlFree(ctxt->location);
3913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->authHeader != NULL) xmlFree(ctxt->authHeader);
3923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->state = XML_NANO_HTTP_NONE;
3933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->fd >= 0) closesocket(ctxt->fd);
3943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->fd = -1;
3953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(ctxt);
3963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
3973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
3983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
3993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlNanoHTTPSend:
4003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  an HTTP context
4013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
4023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Send the input needed to initiate the processing on the server side
403f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard * Returns number of bytes sent or -1 on error.
4043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
4053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
406f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillardstatic int
407f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel VeillardxmlNanoHTTPSend(xmlNanoHTTPCtxtPtr ctxt, const char * xmt_ptr, int outlen) {
408f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
409f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    int 	total_sent = 0;
410f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
411f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    if ( (ctxt->state & XML_NANO_HTTP_WRITE) && (xmt_ptr != NULL ) ) {
412f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard        while (total_sent < outlen) {
413f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard            int nsent = send(ctxt->fd, xmt_ptr + total_sent,
414f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard                                      outlen - total_sent, 0);
4153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            if (nsent>0)
4163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                total_sent += nsent;
417f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    else if ( ( nsent == -1 ) &&
418ba6db03c40b3ac223695fe08e96744ab389c6dabDaniel Veillard#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
419f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    	      ( socket_errno( ) != EAGAIN ) &&
420ba6db03c40b3ac223695fe08e96744ab389c6dabDaniel Veillard#endif
421f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		        ( socket_errno( ) != EWOULDBLOCK ) ) {
422f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	        xmlGenericError( xmlGenericErrorContext,
423f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard				"xmlNanoHTTPSend error:  %s",
424f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard				strerror( socket_errno( ) ) );
425f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
426f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		if ( total_sent == 0 )
427f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		    total_sent = -1;
428f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		break;
429f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    }
430f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    else {
431f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	        /*
432f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		**  No data sent
433f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		**  Since non-blocking sockets are used, wait for
434f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		**  socket to be writable or default timeout prior
435f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		**  to retrying.
436f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		*/
437f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
438f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		struct timeval	tv;
439f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		fd_set		wfd;
440f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
441f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		tv.tv_sec = timeout;
442f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		tv.tv_usec = 0;
443f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		FD_ZERO( &wfd );
444f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		FD_SET( ctxt->fd, &wfd );
445f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		(void)select( ctxt->fd + 1, NULL, &wfd, NULL, &tv );
446f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    }
44756a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	}
4483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
449f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
450f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    return total_sent;
4513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
4523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
4543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlNanoHTTPRecv:
4553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  an HTTP context
4563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
4573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Read information coming from the HTTP connection.
4583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * This is a blocking call (but it blocks in select(), not read()).
4593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
4603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the number of byte read or -1 in case of error.
4613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
4623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorstatic int
4643473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt) {
4653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    fd_set rfd;
4663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    struct timeval tv;
4673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (ctxt->state & XML_NANO_HTTP_READ) {
4703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->in == NULL) {
4713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ctxt->in = (char *) xmlMalloc(65000 * sizeof(char));
4723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (ctxt->in == NULL) {
4733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        ctxt->last = -1;
474f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		xmlGenericError( xmlGenericErrorContext,
475f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			"xmlNanoHTTPRecv:  Error allocating input memory." );
4763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(-1);
4773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
4783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ctxt->inlen = 65000;
4793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ctxt->inptr = ctxt->content = ctxt->inrptr = ctxt->in;
4803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
4813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->inrptr > ctxt->in + XML_NANO_HTTP_CHUNK) {
4823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    int delta = ctxt->inrptr - ctxt->in;
4833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    int len = ctxt->inptr - ctxt->inrptr;
4843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    memmove(ctxt->in, ctxt->inrptr, len);
4863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ctxt->inrptr -= delta;
4873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ctxt->content -= delta;
4883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ctxt->inptr -= delta;
4893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
4903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if ((ctxt->in + ctxt->inlen) < (ctxt->inptr + XML_NANO_HTTP_CHUNK)) {
4913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    int d_inptr = ctxt->inptr - ctxt->in;
4923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    int d_content = ctxt->content - ctxt->in;
4933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    int d_inrptr = ctxt->inrptr - ctxt->in;
494f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    char *	tmp_ptr = ctxt->in;
4953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ctxt->inlen *= 2;
497f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard            ctxt->in = (char *) xmlRealloc(tmp_ptr, ctxt->inlen);
4983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (ctxt->in == NULL) {
499f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	        xmlGenericError( xmlGenericErrorContext,
500f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard				"xmlNanoHTTPRecv:  %s %d bytes.",
501f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard				"Failed to realloc input buffer to",
502f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard				ctxt->inlen );
503f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		xmlFree( tmp_ptr );
5043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        ctxt->last = -1;
5053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(-1);
5063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
5073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            ctxt->inptr = ctxt->in + d_inptr;
5083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            ctxt->content = ctxt->in + d_content;
5093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            ctxt->inrptr = ctxt->in + d_inrptr;
5103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
5113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->last = recv(ctxt->fd, ctxt->inptr, XML_NANO_HTTP_CHUNK, 0);
5123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->last > 0) {
5133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ctxt->inptr += ctxt->last;
5143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(ctxt->last);
5153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
5163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->last == 0) {
5173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(0);
5183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
5193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->last == -1) {
5203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    switch (socket_errno()) {
5213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case EINPROGRESS:
5223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case EWOULDBLOCK:
5233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
5243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case EAGAIN:
5253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
5263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
527f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
528f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		case ECONNRESET:
529f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		case ESHUTDOWN:
530f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		    return ( 0 );
531f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
5323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		default:
533f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		    xmlGenericError( xmlGenericErrorContext,
534f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		    		"xmlNanoHTTPRecv:  recv( ) failure - %s",
535f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard				strerror( socket_errno( ) ) );
536f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		    return(-1);
5373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
5383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
5393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	tv.tv_sec = timeout;
5413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	tv.tv_usec = 0;
5423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	FD_ZERO(&rfd);
5433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	FD_SET(ctxt->fd, &rfd);
5443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
54550f3437111a6428b4852740e83db4848b0b09a97Daniel Veillard	if ( (select(ctxt->fd+1, &rfd, NULL, NULL, &tv)<1)
54650f3437111a6428b4852740e83db4848b0b09a97Daniel Veillard#if defined(EINTR)
54750f3437111a6428b4852740e83db4848b0b09a97Daniel Veillard		&& (errno != EINTR)
54850f3437111a6428b4852740e83db4848b0b09a97Daniel Veillard#endif
54950f3437111a6428b4852740e83db4848b0b09a97Daniel Veillard	)
5503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(0);
5513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
5523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(0);
5533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
5543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
5563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlNanoHTTPReadLine:
5573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  an HTTP context
5583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
5593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Read one line in the HTTP server output, usually for extracting
5603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the HTTP protocol informations from the answer header.
5613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
5623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns a newly allocated string with a copy of the line, or NULL
5633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *         which indicate the end of the input.
5643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
5653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorstatic char *
5673473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNanoHTTPReadLine(xmlNanoHTTPCtxtPtr ctxt) {
5683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char buf[4096];
5693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char *bp = buf;
570f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    int	rc;
5713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (bp - buf < 4095) {
5733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->inrptr == ctxt->inptr) {
574f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    if ( (rc = xmlNanoHTTPRecv(ctxt)) == 0) {
5753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (bp == buf)
5763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    return(NULL);
5773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		else
5783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    *bp = 0;
5793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(xmlMemStrdup(buf));
5803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
581f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    else if ( rc == -1 ) {
582f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	        return ( NULL );
583f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    }
5843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
5853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	*bp = *ctxt->inrptr++;
5863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (*bp == '\n') {
5873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *bp = 0;
5883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(xmlMemStrdup(buf));
5893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
5903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (*bp != '\r')
5913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    bp++;
5923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
5933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    buf[4095] = 0;
5943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlMemStrdup(buf));
5953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
5963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
5993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlNanoHTTPScanAnswer:
6003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  an HTTP context
6013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @line:  an HTTP header line
6023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
6033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Try to extract useful informations from the server answer.
6043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * We currently parse and process:
6053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - The HTTP revision/ return code
6063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - The Content-Type
6073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - The Location for redirrect processing.
6083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
6093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns -1 in case of failure, the file descriptor number otherwise
6103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
6113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorstatic void
6133473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNanoHTTPScanAnswer(xmlNanoHTTPCtxtPtr ctxt, const char *line) {
6143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    const char *cur = line;
6153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (line == NULL) return;
6173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (!strncmp(line, "HTTP/", 5)) {
6193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        int version = 0;
6203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	int ret = 0;
6213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur += 5;
6233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	while ((*cur >= '0') && (*cur <= '9')) {
6243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    version *= 10;
6253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    version += *cur - '0';
6263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    cur++;
6273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
6283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (*cur == '.') {
6293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    cur++;
6303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if ((*cur >= '0') && (*cur <= '9')) {
6313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		version *= 10;
6323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		version += *cur - '0';
6333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		cur++;
6343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
6353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    while ((*cur >= '0') && (*cur <= '9'))
6363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		cur++;
6373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else
6383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    version *= 10;
6393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((*cur != ' ') && (*cur != '\t')) return;
6403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	while ((*cur == ' ') || (*cur == '\t')) cur++;
6413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((*cur < '0') || (*cur > '9')) return;
6423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	while ((*cur >= '0') && (*cur <= '9')) {
6433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret *= 10;
6443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret += *cur - '0';
6453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    cur++;
6463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
6473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((*cur != 0) && (*cur != ' ') && (*cur != '\t')) return;
6483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->returnValue = ret;
6493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"Content-Type:", 13)) {
6503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur += 13;
6513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	while ((*cur == ' ') || (*cur == '\t')) cur++;
6523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->contentType != NULL)
6533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(ctxt->contentType);
6543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->contentType = xmlMemStrdup(cur);
6553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"ContentType:", 12)) {
6563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur += 12;
6573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->contentType != NULL) return;
6583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	while ((*cur == ' ') || (*cur == '\t')) cur++;
6593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->contentType = xmlMemStrdup(cur);
6603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"Location:", 9)) {
6613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur += 9;
6623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	while ((*cur == ' ') || (*cur == '\t')) cur++;
6633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->location != NULL)
6643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(ctxt->location);
6653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->location = xmlMemStrdup(cur);
6663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"WWW-Authenticate:", 17)) {
6673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur += 17;
6683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	while ((*cur == ' ') || (*cur == '\t')) cur++;
6693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->authHeader != NULL)
6703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(ctxt->authHeader);
6713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->authHeader = xmlMemStrdup(cur);
6723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"Proxy-Authenticate:", 19)) {
6733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur += 19;
6743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	while ((*cur == ' ') || (*cur == '\t')) cur++;
6753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->authHeader != NULL)
6763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(ctxt->authHeader);
6773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->authHeader = xmlMemStrdup(cur);
678f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    } else if ( !xmlStrncasecmp( BAD_CAST line, BAD_CAST"Content-Length:", 15) ) {
679f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	cur += 15;
680f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	ctxt->ContentLength = strtol( cur, NULL, 10 );
6813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
6823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
6833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
6853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlNanoHTTPConnectAttempt:
68656a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard * @addr:  a socket adress structure
6873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
6883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Attempt a connection to the given IP:port endpoint. It forces
6893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * non-blocking semantic on the socket, and allow 60 seconds for
6903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the host to answer.
6913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
6923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns -1 in case of failure, the file descriptor number otherwise
6933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
6943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorstatic int
69656a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlNanoHTTPConnectAttempt(struct sockaddr *addr)
6973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor{
6983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SOCKET s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
6993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    fd_set wfd;
7003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    struct timeval tv;
7013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int status;
7023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (s==-1) {
7043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_HTTP
7053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	perror("socket");
7063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
707f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	xmlGenericError( xmlGenericErrorContext,
708f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			"xmlNanoHTTPConnectAttempt: %s - %s",
709f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			"socket creation failure",
710f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			strerror( socket_errno( ) ) );
7113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
7123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef _WINSOCKAPI_
7153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    {
7163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	u_long one = 1;
7173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	status = ioctlsocket(s, FIONBIO, &one) == SOCKET_ERROR ? -1 : 0;
7193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#else /* _WINSOCKAPI_ */
7213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#if defined(VMS)
7223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    {
7233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	int enable = 1;
7243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	status = ioctl(s, FIONBIO, &enable);
7253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#else /* VMS */
7273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((status = fcntl(s, F_GETFL, 0)) != -1) {
7283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef O_NONBLOCK
7293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	status |= O_NONBLOCK;
7303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#else /* O_NONBLOCK */
7313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef F_NDELAY
7323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	status |= F_NDELAY;
7333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif /* F_NDELAY */
7343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif /* !O_NONBLOCK */
7353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	status = fcntl(s, F_SETFL, status);
7363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (status < 0) {
7383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_HTTP
7393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	perror("nonblocking");
7403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
741f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	xmlGenericError( xmlGenericErrorContext,
742f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			"xmlNanoHTTPConnectAttempt:  %s - %s",
743f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			"error setting non-blocking IO",
744f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			strerror( socket_errno( ) ) );
7453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	closesocket(s);
7463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
7473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif /* !VMS */
7493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif /* !_WINSOCKAPI_ */
7503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((connect(s, addr, sizeof(*addr))==-1)) {
7523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	switch (socket_errno()) {
7533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case EINPROGRESS:
7543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case EWOULDBLOCK:
7553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		break;
7563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    default:
757f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		xmlGenericError( xmlGenericErrorContext,
758f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard				"xmlNanoHTTPConnectAttempt:  %s - %s",
759f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard				"error connecting to HTTP server",
760f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard				strerror( socket_errno( ) ) );
7613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		closesocket(s);
7623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(-1);
7633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
7643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    tv.tv_sec = timeout;
7673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    tv.tv_usec = 0;
7683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    FD_ZERO(&wfd);
7703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    FD_SET(s, &wfd);
7713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch(select(s+1, NULL, &wfd, NULL, &tv))
7733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    {
7743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 0:
7753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    /* Time out */
776f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    xmlGenericError( xmlGenericErrorContext,
777f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    			"xmlNanoHTTPConnectAttempt: %s",
778f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard				"Connect attempt timed out." );
7793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    closesocket(s);
7803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(-1);
7813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case -1:
7823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    /* Ermm.. ?? */
783f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    xmlGenericError( xmlGenericErrorContext,
784f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    			"xmlNanoHTTPConnectAttempt: %s - %s",
785f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard				"Error connecting to host",
786f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard				strerror( socket_errno( ) ) );
7873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    closesocket(s);
7883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(-1);
7893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ( FD_ISSET(s, &wfd) ) {
7923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SOCKLEN_T len;
7933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	len = sizeof(status);
7943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&status, &len) < 0 ) {
7953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    /* Solaris error code */
796f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    xmlGenericError( xmlGenericErrorContext,
797f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    			"xmlNanoHTTPConnectAttempt: %s - %s",
798f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard				"Error retrieving pending socket errors",
799f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard				strerror( socket_errno( ) ) );
8003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return (-1);
8013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
8023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ( status ) {
8033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    closesocket(s);
8043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    errno = status;
805f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    xmlGenericError( xmlGenericErrorContext,
806f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    			"xmlNanoHTTPConnectAttempt: %s - %s",
807f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard				"Error connecting to remote host",
808f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard				strerror( status ) );
8093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return (-1);
8103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
8113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
8123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/* pbm */
813f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	xmlGenericError( xmlGenericErrorContext,
814f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		"xmlNanoHTTPConnectAttempt:  %s\n",
815f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		"Select returned, but descriptor not set for connection.\n" );
816f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	closesocket(s);
8173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return (-1);
8183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
8193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(s);
8213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
8223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlNanoHTTPConnectHost:
8253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @host:  the host name
8263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @port:  the port number
8273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Attempt a connection to the given host:port endpoint. It tries
8293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the multiple IP provided by the DNS if available.
8303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns -1 in case of failure, the file descriptor number otherwise
8323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorstatic int
8353473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNanoHTTPConnectHost(const char *host, int port)
8363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor{
8373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    struct hostent *h;
8383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    struct sockaddr *addr;
8393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    struct in_addr ia;
84056a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard    struct sockaddr_in sockin;
8413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef SUPPORT_IP6
8423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    struct in6_addr ia6;
84356a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard    struct sockaddr_in6 sockin6;
8443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
8453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
8463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int s;
8473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#if defined(SUPPORT_IP6) && defined(RES_USE_INET6)
8493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (!(_res.options & RES_INIT))
8503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res_init();
8513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    _res.options |= RES_USE_INET6;
8523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
8533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    h=gethostbyname(host);
8543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (h==NULL)
8553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    {
856f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard        const char *	h_err_txt = "";
857f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	switch ( h_errno )
858f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	{
859f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    case HOST_NOT_FOUND:
860f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	        h_err_txt = "Authoritive host not found";
861f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		break;
862f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
863f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    case TRY_AGAIN:
864f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		h_err_txt =
865f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			"Non-authoritive host not found or server failure.";
866f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		break;
867f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
868f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    case NO_RECOVERY:
869f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		h_err_txt =
870f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		    "Non-recoverable errors:  FORMERR, REFUSED, or NOTIMP.";
871f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		break;
872f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
873f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    case NO_ADDRESS:
874f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		h_err_txt = "Valid name, no data record of requested type.";
875f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		break;
876f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
877f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    default:
878f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	        h_err_txt = "No error text defined.";
879f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	        break;
880f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	}
881f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	xmlGenericError( xmlGenericErrorContext,
882f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			"xmlNanoHTTPConnectHost:  %s '%s' - %s",
883f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			"Failed to resolve host", host, h_err_txt );
8843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
8853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
8863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for(i=0; h->h_addr_list[i]; i++)
8883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    {
8893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (h->h_addrtype == AF_INET) {
8903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    /* A records (IPv4) */
8913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    memcpy(&ia, h->h_addr_list[i], h->h_length);
89256a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    sockin.sin_family = h->h_addrtype;
89356a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    sockin.sin_addr   = ia;
89456a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    sockin.sin_port   = htons(port);
89556a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    addr = (struct sockaddr *)&sockin;
8963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef SUPPORT_IP6
8973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (h->h_addrtype == AF_INET6) {
8983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    /* AAAA records (IPv6) */
8993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    memcpy(&ia6, h->h_addr_list[i], h->h_length);
90056a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    sockin6.sin_family = h->h_addrtype;
90156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    sockin6.sin_addr   = ia6;
90256a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    sockin6.sin_port   = htons(port);
90356a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    addr = (struct sockaddr *)&sockin6;
9043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
9053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else
9063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break; /* for */
9073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
90856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	s = xmlNanoHTTPConnectAttempt(addr);
9093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (s != -1)
9103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(s);
9113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
9123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
9133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_HTTP
9143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlGenericError(xmlGenericErrorContext,
915f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    "xmlNanoHTTPConnectHost:  unable to connect to '%s'.\n", host);
9163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
9173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(-1);
9183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
9193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
9203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
9213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
9223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlNanoHTTPOpen:
9233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @URL:  The URL to load
9243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @contentType:  if available the Content-Type information will be
9253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                returned at that location
9263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
9273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * This function try to open a connection to the indicated resource
9283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * via HTTP GET.
9293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
9303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns NULL in case of failure, otherwise a request handler.
9313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     The contentType, if provided must be freed by the caller
9323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
9333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
9343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid*
9353473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNanoHTTPOpen(const char *URL, char **contentType) {
9363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (contentType != NULL) *contentType = NULL;
937f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    return(xmlNanoHTTPMethod(URL, NULL, NULL, contentType, NULL, 0));
9389403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard}
9399403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard
9409403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard/**
9419403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard * xmlNanoHTTPOpenRedir:
9429403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard * @URL:  The URL to load
9439403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard * @contentType:  if available the Content-Type information will be
9449403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard *                returned at that location
9459403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard * @redir: if availble the redirected URL will be returned
9469403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard *
9479403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard * This function try to open a connection to the indicated resource
9489403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard * via HTTP GET.
9499403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard *
9509403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard * Returns NULL in case of failure, otherwise a request handler.
9519403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard *     The contentType, if provided must be freed by the caller
9529403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard */
9539403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard
9549403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillardvoid*
9559403a0495dcbdfa430b669b4e3d689d8e208c687Daniel VeillardxmlNanoHTTPOpenRedir(const char *URL, char **contentType, char **redir) {
9569403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard    if (contentType != NULL) *contentType = NULL;
9579403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard    if (redir != NULL) *redir = NULL;
958f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    return(xmlNanoHTTPMethodRedir(URL, NULL, NULL, contentType, redir, NULL,0));
9593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
9603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
9613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
9623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlNanoHTTPRead:
9633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctx:  the HTTP context
9643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @dest:  a buffer
9653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @len:  the buffer length
9663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
9673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * This function tries to read @len bytes from the existing HTTP connection
9683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and saves them in @dest. This is a blocking call.
9693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
9703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the number of byte read. 0 is an indication of an end of connection.
9713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *         -1 indicates a parameter error.
9723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
9733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
9743473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNanoHTTPRead(void *ctx, void *dest, int len) {
9753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr) ctx;
9763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
9773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctx == NULL) return(-1);
9783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (dest == NULL) return(-1);
9793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (len <= 0) return(0);
9803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
9813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (ctxt->inptr - ctxt->inrptr < len) {
982f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard        if (xmlNanoHTTPRecv(ctxt) <= 0) break;
9833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
9843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->inptr - ctxt->inrptr < len)
9853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        len = ctxt->inptr - ctxt->inrptr;
9863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memcpy(dest, ctxt->inrptr, len);
9873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->inrptr += len;
9883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(len);
9893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
9903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
9913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
9923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlNanoHTTPClose:
9933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctx:  the HTTP context
9943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
9953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * This function closes an HTTP context, it ends up the connection and
9963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * free all data related to it.
9973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
9983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
9993473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNanoHTTPClose(void *ctx) {
10003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr) ctx;
10013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
10023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctx == NULL) return;
10033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
10043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNanoHTTPFreeCtxt(ctxt);
10053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
10063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
10073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
10089403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard * xmlNanoHTTPMethodRedir:
10093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @URL:  The URL to load
10103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @method:  the HTTP method to use
10113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @input:  the input string if any
10123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @contentType:  the Content-Type information IN and OUT
10139403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard * @redir:  the redirected URL OUT
10143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @headers:  the extra headers
10153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
10163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * This function try to open a connection to the indicated resource
10173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * via HTTP using the given @method, adding the given extra headers
10183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and the input buffer for the request content.
10193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
10203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns NULL in case of failure, otherwise a request handler.
10219403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard *     The contentType, or redir, if provided must be freed by the caller
10223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
10233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
10243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid*
10259403a0495dcbdfa430b669b4e3d689d8e208c687Daniel VeillardxmlNanoHTTPMethodRedir(const char *URL, const char *method, const char *input,
1026f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard                  char **contentType, char **redir,
1027f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		  const char *headers, int ilen ) {
10283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNanoHTTPCtxtPtr ctxt;
10293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char *bp, *p;
1030f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    int blen, ret;
10313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int head;
1032f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    int xmt_bytes;
10333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int nbRedirects = 0;
10343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char *redirURL = NULL;
10353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
10363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (URL == NULL) return(NULL);
10373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (method == NULL) method = "GET";
10383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNanoHTTPInit();
10393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
10403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorretry:
10413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (redirURL == NULL)
10423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt = xmlNanoHTTPNewCtxt(URL);
10433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else {
10443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt = xmlNanoHTTPNewCtxt(redirURL);
10453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
10463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1047f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    if ( ctxt == NULL ) {
1048f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	xmlGenericError( xmlGenericErrorContext,
1049f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			"xmlNanoHTTPMethodRedir:  %s %s.",
1050f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			"Unable to allocate HTTP context to URI",
1051f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			( ( redirURL == NULL ) ? URL : redirURL ) );
1052f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	return ( NULL );
1053f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    }
1054f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
10553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->protocol == NULL) || (strcmp(ctxt->protocol, "http"))) {
1056f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	xmlGenericError( xmlGenericErrorContext,
1057f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			"xmlNanoHTTPMethodRedir:  %s - %s.",
1058f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			"Not a valid HTTP URI",
1059f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			( ( redirURL == NULL ) ? URL : redirURL ) );
10603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlNanoHTTPFreeCtxt(ctxt);
10613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (redirURL != NULL) xmlFree(redirURL);
10623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(NULL);
10633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
10643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->hostname == NULL) {
1065f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	xmlGenericError( xmlGenericErrorContext,
1066f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			"xmlNanoHTTPMethodRedir:  %s - %s",
1067f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			"Failed to identify host in URI",
1068f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			( ( redirURL == NULL ) ? URL : redirURL ) );
10693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlNanoHTTPFreeCtxt(ctxt);
10709403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard	if (redirURL != NULL) xmlFree(redirURL);
10713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(NULL);
10723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
10733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (proxy) {
10743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	blen = strlen(ctxt->hostname) * 2 + 16;
10753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret = xmlNanoHTTPConnectHost(proxy, proxyPort);
10763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
10773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else {
10783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	blen = strlen(ctxt->hostname);
10793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret = xmlNanoHTTPConnectHost(ctxt->hostname, ctxt->port);
10803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
10813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret < 0) {
10823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlNanoHTTPFreeCtxt(ctxt);
10839403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard	if (redirURL != NULL) xmlFree(redirURL);
10843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(NULL);
10853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
10863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->fd = ret;
10873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1088f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    if (input == NULL)
10893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ilen = 0;
1090f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    else
1091f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	blen += 36;
1092f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
10933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (headers != NULL)
1094f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	blen += strlen(headers) + 2;
10953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (contentType && *contentType)
10963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	blen += strlen(*contentType) + 16;
1097f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    blen += strlen(method) + strlen(ctxt->path) + 24;
10983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    bp = xmlMalloc(blen);
1099f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    if ( bp == NULL ) {
1100f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard        xmlNanoHTTPFreeCtxt( ctxt );
1101f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	xmlGenericError( xmlGenericErrorContext,
1102f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			"xmlNanoHTTPMethodRedir:  %s",
1103f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			"Error allocating HTTP header buffer." );
1104f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	return ( NULL );
1105f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    }
1106f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
1107f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    p = bp;
1108f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
11093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (proxy) {
11103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->port != 80) {
1111f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    p += sprintf( p, "%s http://%s:%d%s", method, ctxt->hostname,
1112f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		 	ctxt->port, ctxt->path );
11133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
11143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else
1115f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    p += sprintf( p, "%s http://%s%s", method,
1116f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    		ctxt->hostname, ctxt->path);
11173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
11183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
1119f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	p += sprintf( p, "%s %s", method, ctxt->path);
1120f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
1121f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    p += sprintf(p, " HTTP/1.0\r\nHost: %s\r\n", ctxt->hostname);
1122f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
1123f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    if (contentType != NULL && *contentType)
1124f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	p += sprintf(p, "Content-Type: %s\r\n", *contentType);
1125f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
1126f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    if (headers != NULL)
1127f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	p += sprintf( p, "%s", headers );
1128f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
11293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (input != NULL)
1130f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	sprintf(p, "Content-Length: %d\r\n\r\n", ilen );
11313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
11323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	strcpy(p, "\r\n");
1133f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
11343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_HTTP
11353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlGenericError(xmlGenericErrorContext,
11363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    "-> %s%s", proxy? "(Proxy) " : "", bp);
11373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((blen -= strlen(bp)+1) < 0)
11383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
11393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"ERROR: overflowed buffer by %d bytes\n", -blen);
11403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
11413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->outptr = ctxt->out = bp;
11423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->state = XML_NANO_HTTP_WRITE;
1143f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    blen = strlen( ctxt->out );
1144f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    xmt_bytes = xmlNanoHTTPSend(ctxt, ctxt->out, blen );
1145f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard#ifdef DEBUG_HTTP
1146f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    if ( xmt_bytes != blen )
1147f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard        xmlGenericError( xmlGenericErrorContext,
1148f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			"xmlNanoHTTPMethodRedir:  Only %d of %d %s %s\n",
1149f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			xmt_bytes, blen,
1150f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			"bytes of HTTP headers sent to host",
1151f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			ctxt->hostname );
1152f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard#endif
1153f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
1154f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    if ( input != NULL ) {
1155f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard        xmt_bytes = xmlNanoHTTPSend( ctxt, input, ilen );
1156f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
1157f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard#ifdef DEBUG_HTTP
1158f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	if ( xmt_bytes != ilen )
1159f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    xmlGenericError( xmlGenericErrorContext,
1160f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    		"xmlNanoHTTPMethodRedir:  Only %d of %d %s %s\n",
1161f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			xmt_bytes, ilen,
1162f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			"bytes of HTTP content sent to host",
1163f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard			ctxt->hostname );
1164f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard#endif
1165f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    }
1166f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
11673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->state = XML_NANO_HTTP_READ;
11683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    head = 1;
11693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
11703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((p = xmlNanoHTTPReadLine(ctxt)) != NULL) {
11713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (head && (*p == 0)) {
11723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    head = 0;
11733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ctxt->content = ctxt->inrptr;
11743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(p);
11753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
11763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
11773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlNanoHTTPScanAnswer(ctxt, p);
11783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
11793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_HTTP
11803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext, "<- %s\n", p);
11813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
11823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlFree(p);
11833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
11843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
11853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->location != NULL) && (ctxt->returnValue >= 300) &&
11863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        (ctxt->returnValue < 400)) {
11873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_HTTP
11883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
11893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"\nRedirect to: %s\n", ctxt->location);
11903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
1191f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	while ( xmlNanoHTTPRecv(ctxt) > 0 ) ;
11923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (nbRedirects < XML_NANO_HTTP_MAX_REDIR) {
11933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    nbRedirects++;
11949403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard	    if (redirURL != NULL)
11959403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard		xmlFree(redirURL);
11963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    redirURL = xmlMemStrdup(ctxt->location);
11973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlNanoHTTPFreeCtxt(ctxt);
11983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    goto retry;
11993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
12003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlNanoHTTPFreeCtxt(ctxt);
12019403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard	if (redirURL != NULL) xmlFree(redirURL);
12023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_HTTP
12033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
1204f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		"xmlNanoHTTPMethodRedir: Too many redirects, aborting ...\n");
12053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
12063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
12073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
12083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
12093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (contentType != NULL) {
12103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->contentType != NULL)
12113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *contentType = xmlMemStrdup(ctxt->contentType);
12123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else
12133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *contentType = NULL;
12143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
12153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
12169403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard    if ((redir != NULL) && (redirURL != NULL)) {
12179403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard	*redir = redirURL;
12189403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard    } else {
12199403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard	if (redirURL != NULL)
12209403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard	    xmlFree(redirURL);
12219403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard	if (redir != NULL)
12229403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard	    *redir = NULL;
12239403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard    }
12249403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard
12253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_HTTP
12263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->contentType != NULL)
12273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
12283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"\nCode %d, content-type '%s'\n\n",
12293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	       ctxt->returnValue, ctxt->contentType);
12303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
12313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
12323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"\nCode %d, no content-type\n\n",
12333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	       ctxt->returnValue);
12343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
12353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
12363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return((void *) ctxt);
12373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
12383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
12393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
12409403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard * xmlNanoHTTPMethod:
12419403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard * @URL:  The URL to load
12429403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard * @method:  the HTTP method to use
12439403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard * @input:  the input string if any
12449403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard * @contentType:  the Content-Type information IN and OUT
12459403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard * @headers:  the extra headers
12469403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard *
12479403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard * This function try to open a connection to the indicated resource
12489403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard * via HTTP using the given @method, adding the given extra headers
12499403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard * and the input buffer for the request content.
12509403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard *
12519403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard * Returns NULL in case of failure, otherwise a request handler.
12529403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard *     The contentType, if provided must be freed by the caller
12539403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard */
12549403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard
12559403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillardvoid*
12569403a0495dcbdfa430b669b4e3d689d8e208c687Daniel VeillardxmlNanoHTTPMethod(const char *URL, const char *method, const char *input,
1257f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard                  char **contentType, const char *headers, int ilen) {
12589403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard    return(xmlNanoHTTPMethodRedir(URL, method, input, contentType,
1259f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard		                  NULL, headers, ilen));
12609403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard}
12619403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard
12629403a0495dcbdfa430b669b4e3d689d8e208c687Daniel Veillard/**
12633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlNanoHTTPFetch:
12643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @URL:  The URL to load
12653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @filename:  the filename where the content should be saved
12663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @contentType:  if available the Content-Type information will be
12673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                returned at that location
12683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
12693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * This function try to fetch the indicated resource via HTTP GET
12703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and save it's content in the file.
12713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
12723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns -1 in case of failure, 0 incase of success. The contentType,
12733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     if provided must be freed by the caller
12743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
12753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
12763473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNanoHTTPFetch(const char *URL, const char *filename, char **contentType) {
1277f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    void *ctxt = NULL;
1278f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    char *buf = NULL;
12793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int fd;
12803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int len;
12813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
12823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt = xmlNanoHTTPOpen(URL, contentType);
12833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL) return(-1);
12843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
12853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (!strcmp(filename, "-"))
12863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        fd = 0;
12873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else {
12883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        fd = open(filename, O_CREAT | O_WRONLY, 00644);
12893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (fd < 0) {
12903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlNanoHTTPClose(ctxt);
12913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if ((contentType != NULL) && (*contentType != NULL)) {
12923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        xmlFree(*contentType);
12933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		*contentType = NULL;
12943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
12953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(-1);
12963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
12973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
12983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1299f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    xmlNanoHTTPFetchContent( ctxt, &buf, &len );
1300f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    if ( len > 0 ) {
13013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	write(fd, buf, len);
13023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
13033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNanoHTTPClose(ctxt);
13053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    close(fd);
13063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(0);
13073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
13083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
13103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlNanoHTTPSave:
13113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the HTTP context
13123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @filename:  the filename where the content should be saved
13133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
13143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * This function saves the output of the HTTP transaction to a file
13153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * It closes and free the context at the end
13163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
13173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns -1 in case of failure, 0 incase of success.
13183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
13193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
13203473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNanoHTTPSave(void *ctxt, const char *filename) {
1321e392497e4c4313382c3c20903d09a69f0948f721Daniel Veillard    char *buf = NULL;
13223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int fd;
13233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int len;
13243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL) return(-1);
13263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (!strcmp(filename, "-"))
13283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        fd = 0;
13293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else {
13303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        fd = open(filename, O_CREAT | O_WRONLY);
13313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (fd < 0) {
13323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlNanoHTTPClose(ctxt);
13333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(-1);
13343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
13353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
13363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1337f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    xmlNanoHTTPFetchContent( ctxt, &buf, &len );
1338f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    if ( len > 0 ) {
13393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	write(fd, buf, len);
13403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
13413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNanoHTTPClose(ctxt);
13433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(0);
13443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
13453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
13473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlNanoHTTPReturnCode:
13483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctx:  the HTTP context
13493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
13505e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * Get the latest HTTP return code received
13515e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard *
13523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the HTTP return code for the request.
13533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
13543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
13553473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNanoHTTPReturnCode(void *ctx) {
13563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr) ctx;
13573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL) return(-1);
13593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ctxt->returnValue);
13613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
13623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
13643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlNanoHTTPAuthHeader:
13653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctx:  the HTTP context
13663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
13675e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * Get the authentication header of an HTTP context
13685e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard *
13693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the stashed value of the WWW-Authenticate or Proxy-Authenticate
13703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * header.
13713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
13723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorconst char *
13733473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNanoHTTPAuthHeader(void *ctx) {
13743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr) ctx;
13753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL) return(NULL);
13773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ctxt->authHeader);
13793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
13803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1381f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard/**
1382f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard * xmlNanoHTTPContentLength
1383f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard * @ctx:  the HTTP context
1384f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard *
1385f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard * Return the specified content length from the HTTP header.  Note that
1386f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard * a value of -1 indicates that the content length element was not included in
1387f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard * the response header.
1388f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard */
1389f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillardint
1390f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel VeillardxmlNanoHTTPContentLength( void * ctx ) {
1391f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    xmlNanoHTTPCtxtPtr	ctxt = ctx;
1392f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
1393f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    return ( ( ctxt == NULL ) ? -1 : ctxt->ContentLength );
1394f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard}
1395f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
1396f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard/**
1397f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard * xmlNanoHTTPFetchContent
1398f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard * @ctx:  the HTTP context
1399f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard * @ptr:  pointer to set to the content buffer.
1400f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard * @len:  integer pointer to hold the length of the content
1401f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard *
1402f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard * Returns 0 if all the content was read and available, returns
1403f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard * -1 if received content length was less than specified or an error
1404f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard * occurred.
1405f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard */
1406f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillardint
1407f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel VeillardxmlNanoHTTPFetchContent( void * ctx, char ** ptr, int * len ) {
1408f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    xmlNanoHTTPCtxtPtr	ctxt = ctx;
1409f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
1410f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    int			rc = 0;
1411f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    int			cur_lgth;
1412f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    int			rcvd_lgth;
1413f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    int			dummy_int;
1414f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    char *		dummy_ptr = NULL;
1415f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
1416f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    /*  Dummy up return input parameters if not provided  */
1417f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
1418f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    if ( len == NULL )
1419f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard        len = &dummy_int;
1420f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
1421f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    if ( ptr == NULL )
1422f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard        ptr = &dummy_ptr;
1423f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
1424f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    /*  But can't work without the context pointer  */
1425f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
1426f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    if ( ( ctxt == NULL ) || ( ctxt->content == NULL ) ) {
1427f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard        *len = 0;
1428f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	*ptr = NULL;
1429f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	return ( -1 );
1430f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    }
1431f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
1432f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    rcvd_lgth = ctxt->inptr - ctxt->content;
1433f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
1434f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    while ( (cur_lgth = xmlNanoHTTPRecv( ctxt )) > 0 ) {
1435f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
1436f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	rcvd_lgth += cur_lgth;
1437f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	if ( (ctxt->ContentLength > 0) && (rcvd_lgth >= ctxt->ContentLength) )
1438f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	    break;
1439f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    }
1440f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
1441f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    *ptr = ctxt->content;
1442f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    *len = rcvd_lgth;
1443f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
1444f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    if ( ( ctxt->ContentLength > 0 ) && ( rcvd_lgth < ctxt->ContentLength ) )
1445f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard        rc = -1;
1446f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    else if ( rcvd_lgth == 0 )
1447f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard	rc = -1;
1448f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
1449f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard    return ( rc );
1450f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard}
1451f012a64d13d85d53eac0d4d6625508109e7c9e9dDaniel Veillard
14523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef STANDALONE
14533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint main(int argc, char **argv) {
14543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char *contentType = NULL;
14553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
14563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (argv[1] != NULL) {
14573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (argv[2] != NULL)
14583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlNanoHTTPFetch(argv[1], argv[2], &contentType);
14593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        else
14603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlNanoHTTPFetch(argv[1], "-", &contentType);
14613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (contentType != NULL) xmlFree(contentType);
14623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
14633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
14643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"%s: minimal HTTP GET implementation\n", argv[0]);
14653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
14663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"\tusage %s [ URL [ filename ] ]\n", argv[0]);
14673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
14683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNanoHTTPCleanup();
14693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlMemoryDump();
14703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(0);
14713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
14723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif /* STANDALONE */
14733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#else /* !LIBXML_HTTP_ENABLED */
14743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef STANDALONE
14753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <stdio.h>
14763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint main(int argc, char **argv) {
14773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlGenericError(xmlGenericErrorContext,
14783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    "%s : HTTP support not compiled in\n", argv[0]);
14793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(0);
14803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
14813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif /* STANDALONE */
14823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif /* LIBXML_HTTP_ENABLED */
1483