xref: /aosp_15_r20/external/cronet/third_party/libxml/src/nanohttp.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker /*
2*6777b538SAndroid Build Coastguard Worker  * nanohttp.c: minimalist HTTP GET implementation to fetch external subsets.
3*6777b538SAndroid Build Coastguard Worker  *             focuses on size, streamability, reentrancy and portability
4*6777b538SAndroid Build Coastguard Worker  *
5*6777b538SAndroid Build Coastguard Worker  * This is clearly not a general purpose HTTP implementation
6*6777b538SAndroid Build Coastguard Worker  * If you look for one, check:
7*6777b538SAndroid Build Coastguard Worker  *         http://www.w3.org/Library/
8*6777b538SAndroid Build Coastguard Worker  *
9*6777b538SAndroid Build Coastguard Worker  * See Copyright for the status of this software.
10*6777b538SAndroid Build Coastguard Worker  *
11*6777b538SAndroid Build Coastguard Worker  * [email protected]
12*6777b538SAndroid Build Coastguard Worker  */
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker #define IN_LIBXML
15*6777b538SAndroid Build Coastguard Worker #include "libxml.h"
16*6777b538SAndroid Build Coastguard Worker 
17*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_HTTP_ENABLED
18*6777b538SAndroid Build Coastguard Worker #include <string.h>
19*6777b538SAndroid Build Coastguard Worker #include <ctype.h>
20*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
21*6777b538SAndroid Build Coastguard Worker #include <errno.h>
22*6777b538SAndroid Build Coastguard Worker 
23*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_UNISTD_H
24*6777b538SAndroid Build Coastguard Worker #include <unistd.h>
25*6777b538SAndroid Build Coastguard Worker #elif defined (_WIN32)
26*6777b538SAndroid Build Coastguard Worker #include <io.h>
27*6777b538SAndroid Build Coastguard Worker #endif
28*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_SYS_SOCKET_H
29*6777b538SAndroid Build Coastguard Worker #include <sys/socket.h>
30*6777b538SAndroid Build Coastguard Worker #endif
31*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_NETINET_IN_H
32*6777b538SAndroid Build Coastguard Worker #include <netinet/in.h>
33*6777b538SAndroid Build Coastguard Worker #endif
34*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_ARPA_INET_H
35*6777b538SAndroid Build Coastguard Worker #include <arpa/inet.h>
36*6777b538SAndroid Build Coastguard Worker #endif
37*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_NETDB_H
38*6777b538SAndroid Build Coastguard Worker #include <netdb.h>
39*6777b538SAndroid Build Coastguard Worker #endif
40*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_FCNTL_H
41*6777b538SAndroid Build Coastguard Worker #include <fcntl.h>
42*6777b538SAndroid Build Coastguard Worker #endif
43*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_SYS_TIME_H
44*6777b538SAndroid Build Coastguard Worker #include <sys/time.h>
45*6777b538SAndroid Build Coastguard Worker #endif
46*6777b538SAndroid Build Coastguard Worker #ifndef HAVE_POLL_H
47*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_SYS_SELECT_H
48*6777b538SAndroid Build Coastguard Worker #include <sys/select.h>
49*6777b538SAndroid Build Coastguard Worker #endif
50*6777b538SAndroid Build Coastguard Worker #else
51*6777b538SAndroid Build Coastguard Worker #include <poll.h>
52*6777b538SAndroid Build Coastguard Worker #endif
53*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_ZLIB_ENABLED
54*6777b538SAndroid Build Coastguard Worker #include <zlib.h>
55*6777b538SAndroid Build Coastguard Worker #endif
56*6777b538SAndroid Build Coastguard Worker 
57*6777b538SAndroid Build Coastguard Worker 
58*6777b538SAndroid Build Coastguard Worker #ifdef VMS
59*6777b538SAndroid Build Coastguard Worker #include <stropts>
60*6777b538SAndroid Build Coastguard Worker #define XML_SOCKLEN_T unsigned int
61*6777b538SAndroid Build Coastguard Worker #endif
62*6777b538SAndroid Build Coastguard Worker 
63*6777b538SAndroid Build Coastguard Worker #if defined(_WIN32)
64*6777b538SAndroid Build Coastguard Worker #include <wsockcompat.h>
65*6777b538SAndroid Build Coastguard Worker #endif
66*6777b538SAndroid Build Coastguard Worker 
67*6777b538SAndroid Build Coastguard Worker #include <libxml/xmlerror.h>
68*6777b538SAndroid Build Coastguard Worker #include <libxml/xmlmemory.h>
69*6777b538SAndroid Build Coastguard Worker #include <libxml/parser.h> /* for xmlStr(n)casecmp() */
70*6777b538SAndroid Build Coastguard Worker #include <libxml/nanohttp.h>
71*6777b538SAndroid Build Coastguard Worker #include <libxml/uri.h>
72*6777b538SAndroid Build Coastguard Worker 
73*6777b538SAndroid Build Coastguard Worker #include "private/error.h"
74*6777b538SAndroid Build Coastguard Worker #include "private/io.h"
75*6777b538SAndroid Build Coastguard Worker 
76*6777b538SAndroid Build Coastguard Worker /**
77*6777b538SAndroid Build Coastguard Worker  * A couple portability macros
78*6777b538SAndroid Build Coastguard Worker  */
79*6777b538SAndroid Build Coastguard Worker #ifndef _WINSOCKAPI_
80*6777b538SAndroid Build Coastguard Worker #define closesocket(s) close(s)
81*6777b538SAndroid Build Coastguard Worker #define SOCKET int
82*6777b538SAndroid Build Coastguard Worker #define INVALID_SOCKET (-1)
83*6777b538SAndroid Build Coastguard Worker #endif
84*6777b538SAndroid Build Coastguard Worker 
85*6777b538SAndroid Build Coastguard Worker #ifndef XML_SOCKLEN_T
86*6777b538SAndroid Build Coastguard Worker #define XML_SOCKLEN_T unsigned int
87*6777b538SAndroid Build Coastguard Worker #endif
88*6777b538SAndroid Build Coastguard Worker 
89*6777b538SAndroid Build Coastguard Worker #define GETHOSTBYNAME_ARG_CAST (char *)
90*6777b538SAndroid Build Coastguard Worker #define SEND_ARG2_CAST (char *)
91*6777b538SAndroid Build Coastguard Worker 
92*6777b538SAndroid Build Coastguard Worker #ifdef STANDALONE
93*6777b538SAndroid Build Coastguard Worker #define xmlStrncasecmp(a, b, n) strncasecmp((char *)a, (char *)b, n)
94*6777b538SAndroid Build Coastguard Worker #define xmlStrcasecmpi(a, b) strcasecmp((char *)a, (char *)b)
95*6777b538SAndroid Build Coastguard Worker #endif
96*6777b538SAndroid Build Coastguard Worker 
97*6777b538SAndroid Build Coastguard Worker #define XML_NANO_HTTP_MAX_REDIR	10
98*6777b538SAndroid Build Coastguard Worker 
99*6777b538SAndroid Build Coastguard Worker #define XML_NANO_HTTP_CHUNK	4096
100*6777b538SAndroid Build Coastguard Worker 
101*6777b538SAndroid Build Coastguard Worker #define XML_NANO_HTTP_CLOSED	0
102*6777b538SAndroid Build Coastguard Worker #define XML_NANO_HTTP_WRITE	1
103*6777b538SAndroid Build Coastguard Worker #define XML_NANO_HTTP_READ	2
104*6777b538SAndroid Build Coastguard Worker #define XML_NANO_HTTP_NONE	4
105*6777b538SAndroid Build Coastguard Worker 
106*6777b538SAndroid Build Coastguard Worker typedef struct xmlNanoHTTPCtxt {
107*6777b538SAndroid Build Coastguard Worker     char *protocol;	/* the protocol name */
108*6777b538SAndroid Build Coastguard Worker     char *hostname;	/* the host name */
109*6777b538SAndroid Build Coastguard Worker     int port;		/* the port */
110*6777b538SAndroid Build Coastguard Worker     char *path;		/* the path within the URL */
111*6777b538SAndroid Build Coastguard Worker     char *query;	/* the query string */
112*6777b538SAndroid Build Coastguard Worker     SOCKET fd;		/* the file descriptor for the socket */
113*6777b538SAndroid Build Coastguard Worker     int state;		/* WRITE / READ / CLOSED */
114*6777b538SAndroid Build Coastguard Worker     char *out;		/* buffer sent (zero terminated) */
115*6777b538SAndroid Build Coastguard Worker     char *outptr;	/* index within the buffer sent */
116*6777b538SAndroid Build Coastguard Worker     char *in;		/* the receiving buffer */
117*6777b538SAndroid Build Coastguard Worker     char *content;	/* the start of the content */
118*6777b538SAndroid Build Coastguard Worker     char *inptr;	/* the next byte to read from network */
119*6777b538SAndroid Build Coastguard Worker     char *inrptr;	/* the next byte to give back to the client */
120*6777b538SAndroid Build Coastguard Worker     int inlen;		/* len of the input buffer */
121*6777b538SAndroid Build Coastguard Worker     int last;		/* return code for last operation */
122*6777b538SAndroid Build Coastguard Worker     int returnValue;	/* the protocol return value */
123*6777b538SAndroid Build Coastguard Worker     int version;        /* the protocol version */
124*6777b538SAndroid Build Coastguard Worker     int ContentLength;  /* specified content length from HTTP header */
125*6777b538SAndroid Build Coastguard Worker     char *contentType;	/* the MIME type for the input */
126*6777b538SAndroid Build Coastguard Worker     char *location;	/* the new URL in case of redirect */
127*6777b538SAndroid Build Coastguard Worker     char *authHeader;	/* contents of {WWW,Proxy}-Authenticate header */
128*6777b538SAndroid Build Coastguard Worker     char *encoding;	/* encoding extracted from the contentType */
129*6777b538SAndroid Build Coastguard Worker     char *mimeType;	/* Mime-Type extracted from the contentType */
130*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_ZLIB_ENABLED
131*6777b538SAndroid Build Coastguard Worker     z_stream *strm;	/* Zlib stream object */
132*6777b538SAndroid Build Coastguard Worker     int usesGzip;	/* "Content-Encoding: gzip" was detected */
133*6777b538SAndroid Build Coastguard Worker #endif
134*6777b538SAndroid Build Coastguard Worker } xmlNanoHTTPCtxt, *xmlNanoHTTPCtxtPtr;
135*6777b538SAndroid Build Coastguard Worker 
136*6777b538SAndroid Build Coastguard Worker static int initialized = 0;
137*6777b538SAndroid Build Coastguard Worker static char *proxy = NULL;	 /* the proxy name if any */
138*6777b538SAndroid Build Coastguard Worker static int proxyPort;	/* the proxy port if any */
139*6777b538SAndroid Build Coastguard Worker static unsigned int timeout = 60;/* the select() timeout in seconds */
140*6777b538SAndroid Build Coastguard Worker 
141*6777b538SAndroid Build Coastguard Worker static int xmlNanoHTTPFetchContent( void * ctx, char ** ptr, int * len );
142*6777b538SAndroid Build Coastguard Worker 
143*6777b538SAndroid Build Coastguard Worker /**
144*6777b538SAndroid Build Coastguard Worker  * xmlHTTPErrMemory:
145*6777b538SAndroid Build Coastguard Worker  * @extra:  extra information
146*6777b538SAndroid Build Coastguard Worker  *
147*6777b538SAndroid Build Coastguard Worker  * Handle an out of memory condition
148*6777b538SAndroid Build Coastguard Worker  */
149*6777b538SAndroid Build Coastguard Worker static void
xmlHTTPErrMemory(void)150*6777b538SAndroid Build Coastguard Worker xmlHTTPErrMemory(void)
151*6777b538SAndroid Build Coastguard Worker {
152*6777b538SAndroid Build Coastguard Worker     xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_HTTP, NULL);
153*6777b538SAndroid Build Coastguard Worker }
154*6777b538SAndroid Build Coastguard Worker 
155*6777b538SAndroid Build Coastguard Worker /**
156*6777b538SAndroid Build Coastguard Worker  * A portability function
157*6777b538SAndroid Build Coastguard Worker  */
socket_errno(void)158*6777b538SAndroid Build Coastguard Worker static int socket_errno(void) {
159*6777b538SAndroid Build Coastguard Worker #ifdef _WINSOCKAPI_
160*6777b538SAndroid Build Coastguard Worker     int err = WSAGetLastError();
161*6777b538SAndroid Build Coastguard Worker     switch(err) {
162*6777b538SAndroid Build Coastguard Worker         case WSAECONNRESET:
163*6777b538SAndroid Build Coastguard Worker             return(ECONNRESET);
164*6777b538SAndroid Build Coastguard Worker         case WSAEINPROGRESS:
165*6777b538SAndroid Build Coastguard Worker             return(EINPROGRESS);
166*6777b538SAndroid Build Coastguard Worker         case WSAEINTR:
167*6777b538SAndroid Build Coastguard Worker             return(EINTR);
168*6777b538SAndroid Build Coastguard Worker         case WSAESHUTDOWN:
169*6777b538SAndroid Build Coastguard Worker             return(ESHUTDOWN);
170*6777b538SAndroid Build Coastguard Worker         case WSAEWOULDBLOCK:
171*6777b538SAndroid Build Coastguard Worker             return(EWOULDBLOCK);
172*6777b538SAndroid Build Coastguard Worker         default:
173*6777b538SAndroid Build Coastguard Worker             return(err);
174*6777b538SAndroid Build Coastguard Worker     }
175*6777b538SAndroid Build Coastguard Worker #else
176*6777b538SAndroid Build Coastguard Worker     return(errno);
177*6777b538SAndroid Build Coastguard Worker #endif
178*6777b538SAndroid Build Coastguard Worker }
179*6777b538SAndroid Build Coastguard Worker 
180*6777b538SAndroid Build Coastguard Worker /**
181*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPInit:
182*6777b538SAndroid Build Coastguard Worker  *
183*6777b538SAndroid Build Coastguard Worker  * Initialize the HTTP protocol layer.
184*6777b538SAndroid Build Coastguard Worker  * Currently it just checks for proxy information
185*6777b538SAndroid Build Coastguard Worker  */
186*6777b538SAndroid Build Coastguard Worker 
187*6777b538SAndroid Build Coastguard Worker void
xmlNanoHTTPInit(void)188*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPInit(void) {
189*6777b538SAndroid Build Coastguard Worker     const char *env;
190*6777b538SAndroid Build Coastguard Worker #ifdef _WINSOCKAPI_
191*6777b538SAndroid Build Coastguard Worker     WSADATA wsaData;
192*6777b538SAndroid Build Coastguard Worker #endif
193*6777b538SAndroid Build Coastguard Worker 
194*6777b538SAndroid Build Coastguard Worker     if (initialized)
195*6777b538SAndroid Build Coastguard Worker 	return;
196*6777b538SAndroid Build Coastguard Worker 
197*6777b538SAndroid Build Coastguard Worker #ifdef _WINSOCKAPI_
198*6777b538SAndroid Build Coastguard Worker     if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
199*6777b538SAndroid Build Coastguard Worker 	return;
200*6777b538SAndroid Build Coastguard Worker #endif
201*6777b538SAndroid Build Coastguard Worker 
202*6777b538SAndroid Build Coastguard Worker     if (proxy == NULL) {
203*6777b538SAndroid Build Coastguard Worker 	proxyPort = 80;
204*6777b538SAndroid Build Coastguard Worker 	env = getenv("no_proxy");
205*6777b538SAndroid Build Coastguard Worker 	if (env && ((env[0] == '*') && (env[1] == 0)))
206*6777b538SAndroid Build Coastguard Worker 	    goto done;
207*6777b538SAndroid Build Coastguard Worker 	env = getenv("http_proxy");
208*6777b538SAndroid Build Coastguard Worker 	if (env != NULL) {
209*6777b538SAndroid Build Coastguard Worker 	    xmlNanoHTTPScanProxy(env);
210*6777b538SAndroid Build Coastguard Worker 	    goto done;
211*6777b538SAndroid Build Coastguard Worker 	}
212*6777b538SAndroid Build Coastguard Worker 	env = getenv("HTTP_PROXY");
213*6777b538SAndroid Build Coastguard Worker 	if (env != NULL) {
214*6777b538SAndroid Build Coastguard Worker 	    xmlNanoHTTPScanProxy(env);
215*6777b538SAndroid Build Coastguard Worker 	    goto done;
216*6777b538SAndroid Build Coastguard Worker 	}
217*6777b538SAndroid Build Coastguard Worker     }
218*6777b538SAndroid Build Coastguard Worker done:
219*6777b538SAndroid Build Coastguard Worker     initialized = 1;
220*6777b538SAndroid Build Coastguard Worker }
221*6777b538SAndroid Build Coastguard Worker 
222*6777b538SAndroid Build Coastguard Worker /**
223*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPCleanup:
224*6777b538SAndroid Build Coastguard Worker  *
225*6777b538SAndroid Build Coastguard Worker  * Cleanup the HTTP protocol layer.
226*6777b538SAndroid Build Coastguard Worker  */
227*6777b538SAndroid Build Coastguard Worker 
228*6777b538SAndroid Build Coastguard Worker void
xmlNanoHTTPCleanup(void)229*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPCleanup(void) {
230*6777b538SAndroid Build Coastguard Worker     if (proxy != NULL) {
231*6777b538SAndroid Build Coastguard Worker 	xmlFree(proxy);
232*6777b538SAndroid Build Coastguard Worker 	proxy = NULL;
233*6777b538SAndroid Build Coastguard Worker     }
234*6777b538SAndroid Build Coastguard Worker #ifdef _WINSOCKAPI_
235*6777b538SAndroid Build Coastguard Worker     if (initialized)
236*6777b538SAndroid Build Coastguard Worker 	WSACleanup();
237*6777b538SAndroid Build Coastguard Worker #endif
238*6777b538SAndroid Build Coastguard Worker     initialized = 0;
239*6777b538SAndroid Build Coastguard Worker     return;
240*6777b538SAndroid Build Coastguard Worker }
241*6777b538SAndroid Build Coastguard Worker 
242*6777b538SAndroid Build Coastguard Worker /**
243*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPScanURL:
244*6777b538SAndroid Build Coastguard Worker  * @ctxt:  an HTTP context
245*6777b538SAndroid Build Coastguard Worker  * @URL:  The URL used to initialize the context
246*6777b538SAndroid Build Coastguard Worker  *
247*6777b538SAndroid Build Coastguard Worker  * (Re)Initialize an HTTP context by parsing the URL and finding
248*6777b538SAndroid Build Coastguard Worker  * the protocol host port and path it indicates.
249*6777b538SAndroid Build Coastguard Worker  */
250*6777b538SAndroid Build Coastguard Worker 
251*6777b538SAndroid Build Coastguard Worker static void
xmlNanoHTTPScanURL(xmlNanoHTTPCtxtPtr ctxt,const char * URL)252*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPScanURL(xmlNanoHTTPCtxtPtr ctxt, const char *URL) {
253*6777b538SAndroid Build Coastguard Worker     xmlURIPtr uri;
254*6777b538SAndroid Build Coastguard Worker     int len;
255*6777b538SAndroid Build Coastguard Worker 
256*6777b538SAndroid Build Coastguard Worker     /*
257*6777b538SAndroid Build Coastguard Worker      * Clear any existing data from the context
258*6777b538SAndroid Build Coastguard Worker      */
259*6777b538SAndroid Build Coastguard Worker     if (ctxt->protocol != NULL) {
260*6777b538SAndroid Build Coastguard Worker         xmlFree(ctxt->protocol);
261*6777b538SAndroid Build Coastguard Worker 	ctxt->protocol = NULL;
262*6777b538SAndroid Build Coastguard Worker     }
263*6777b538SAndroid Build Coastguard Worker     if (ctxt->hostname != NULL) {
264*6777b538SAndroid Build Coastguard Worker         xmlFree(ctxt->hostname);
265*6777b538SAndroid Build Coastguard Worker 	ctxt->hostname = NULL;
266*6777b538SAndroid Build Coastguard Worker     }
267*6777b538SAndroid Build Coastguard Worker     if (ctxt->path != NULL) {
268*6777b538SAndroid Build Coastguard Worker         xmlFree(ctxt->path);
269*6777b538SAndroid Build Coastguard Worker 	ctxt->path = NULL;
270*6777b538SAndroid Build Coastguard Worker     }
271*6777b538SAndroid Build Coastguard Worker     if (ctxt->query != NULL) {
272*6777b538SAndroid Build Coastguard Worker         xmlFree(ctxt->query);
273*6777b538SAndroid Build Coastguard Worker 	ctxt->query = NULL;
274*6777b538SAndroid Build Coastguard Worker     }
275*6777b538SAndroid Build Coastguard Worker     if (URL == NULL) return;
276*6777b538SAndroid Build Coastguard Worker 
277*6777b538SAndroid Build Coastguard Worker     uri = xmlParseURIRaw(URL, 1);
278*6777b538SAndroid Build Coastguard Worker     if (uri == NULL)
279*6777b538SAndroid Build Coastguard Worker 	return;
280*6777b538SAndroid Build Coastguard Worker 
281*6777b538SAndroid Build Coastguard Worker     if ((uri->scheme == NULL) || (uri->server == NULL)) {
282*6777b538SAndroid Build Coastguard Worker 	xmlFreeURI(uri);
283*6777b538SAndroid Build Coastguard Worker 	return;
284*6777b538SAndroid Build Coastguard Worker     }
285*6777b538SAndroid Build Coastguard Worker 
286*6777b538SAndroid Build Coastguard Worker     ctxt->protocol = xmlMemStrdup(uri->scheme);
287*6777b538SAndroid Build Coastguard Worker     /* special case of IPv6 addresses, the [] need to be removed */
288*6777b538SAndroid Build Coastguard Worker     if ((uri->server != NULL) && (*uri->server == '[')) {
289*6777b538SAndroid Build Coastguard Worker         len = strlen(uri->server);
290*6777b538SAndroid Build Coastguard Worker 	if ((len > 2) && (uri->server[len - 1] == ']')) {
291*6777b538SAndroid Build Coastguard Worker 	    ctxt->hostname = (char *) xmlCharStrndup(uri->server + 1, len -2);
292*6777b538SAndroid Build Coastguard Worker 	} else
293*6777b538SAndroid Build Coastguard Worker 	    ctxt->hostname = xmlMemStrdup(uri->server);
294*6777b538SAndroid Build Coastguard Worker     } else
295*6777b538SAndroid Build Coastguard Worker 	ctxt->hostname = xmlMemStrdup(uri->server);
296*6777b538SAndroid Build Coastguard Worker     if (uri->path != NULL)
297*6777b538SAndroid Build Coastguard Worker 	ctxt->path = xmlMemStrdup(uri->path);
298*6777b538SAndroid Build Coastguard Worker     else
299*6777b538SAndroid Build Coastguard Worker 	ctxt->path = xmlMemStrdup("/");
300*6777b538SAndroid Build Coastguard Worker     if (uri->query != NULL)
301*6777b538SAndroid Build Coastguard Worker 	ctxt->query = xmlMemStrdup(uri->query);
302*6777b538SAndroid Build Coastguard Worker     if (uri->port != 0)
303*6777b538SAndroid Build Coastguard Worker 	ctxt->port = uri->port;
304*6777b538SAndroid Build Coastguard Worker 
305*6777b538SAndroid Build Coastguard Worker     xmlFreeURI(uri);
306*6777b538SAndroid Build Coastguard Worker }
307*6777b538SAndroid Build Coastguard Worker 
308*6777b538SAndroid Build Coastguard Worker /**
309*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPScanProxy:
310*6777b538SAndroid Build Coastguard Worker  * @URL:  The proxy URL used to initialize the proxy context
311*6777b538SAndroid Build Coastguard Worker  *
312*6777b538SAndroid Build Coastguard Worker  * (Re)Initialize the HTTP Proxy context by parsing the URL and finding
313*6777b538SAndroid Build Coastguard Worker  * the protocol host port it indicates.
314*6777b538SAndroid Build Coastguard Worker  * Should be like http://myproxy/ or http://myproxy:3128/
315*6777b538SAndroid Build Coastguard Worker  * A NULL URL cleans up proxy information.
316*6777b538SAndroid Build Coastguard Worker  */
317*6777b538SAndroid Build Coastguard Worker 
318*6777b538SAndroid Build Coastguard Worker void
xmlNanoHTTPScanProxy(const char * URL)319*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPScanProxy(const char *URL) {
320*6777b538SAndroid Build Coastguard Worker     xmlURIPtr uri;
321*6777b538SAndroid Build Coastguard Worker 
322*6777b538SAndroid Build Coastguard Worker     if (proxy != NULL) {
323*6777b538SAndroid Build Coastguard Worker         xmlFree(proxy);
324*6777b538SAndroid Build Coastguard Worker 	proxy = NULL;
325*6777b538SAndroid Build Coastguard Worker     }
326*6777b538SAndroid Build Coastguard Worker     proxyPort = 0;
327*6777b538SAndroid Build Coastguard Worker 
328*6777b538SAndroid Build Coastguard Worker     if (URL == NULL) return;
329*6777b538SAndroid Build Coastguard Worker 
330*6777b538SAndroid Build Coastguard Worker     uri = xmlParseURIRaw(URL, 1);
331*6777b538SAndroid Build Coastguard Worker     if ((uri == NULL) || (uri->scheme == NULL) ||
332*6777b538SAndroid Build Coastguard Worker 	(strcmp(uri->scheme, "http")) || (uri->server == NULL)) {
333*6777b538SAndroid Build Coastguard Worker 	__xmlIOErr(XML_FROM_HTTP, XML_HTTP_URL_SYNTAX, "Syntax Error\n");
334*6777b538SAndroid Build Coastguard Worker 	if (uri != NULL)
335*6777b538SAndroid Build Coastguard Worker 	    xmlFreeURI(uri);
336*6777b538SAndroid Build Coastguard Worker 	return;
337*6777b538SAndroid Build Coastguard Worker     }
338*6777b538SAndroid Build Coastguard Worker 
339*6777b538SAndroid Build Coastguard Worker     proxy = xmlMemStrdup(uri->server);
340*6777b538SAndroid Build Coastguard Worker     if (uri->port != 0)
341*6777b538SAndroid Build Coastguard Worker 	proxyPort = uri->port;
342*6777b538SAndroid Build Coastguard Worker 
343*6777b538SAndroid Build Coastguard Worker     xmlFreeURI(uri);
344*6777b538SAndroid Build Coastguard Worker }
345*6777b538SAndroid Build Coastguard Worker 
346*6777b538SAndroid Build Coastguard Worker /**
347*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPNewCtxt:
348*6777b538SAndroid Build Coastguard Worker  * @URL:  The URL used to initialize the context
349*6777b538SAndroid Build Coastguard Worker  *
350*6777b538SAndroid Build Coastguard Worker  * Allocate and initialize a new HTTP context.
351*6777b538SAndroid Build Coastguard Worker  *
352*6777b538SAndroid Build Coastguard Worker  * Returns an HTTP context or NULL in case of error.
353*6777b538SAndroid Build Coastguard Worker  */
354*6777b538SAndroid Build Coastguard Worker 
355*6777b538SAndroid Build Coastguard Worker static xmlNanoHTTPCtxtPtr
xmlNanoHTTPNewCtxt(const char * URL)356*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPNewCtxt(const char *URL) {
357*6777b538SAndroid Build Coastguard Worker     xmlNanoHTTPCtxtPtr ret;
358*6777b538SAndroid Build Coastguard Worker 
359*6777b538SAndroid Build Coastguard Worker     ret = (xmlNanoHTTPCtxtPtr) xmlMalloc(sizeof(xmlNanoHTTPCtxt));
360*6777b538SAndroid Build Coastguard Worker     if (ret == NULL) {
361*6777b538SAndroid Build Coastguard Worker         xmlHTTPErrMemory();
362*6777b538SAndroid Build Coastguard Worker         return(NULL);
363*6777b538SAndroid Build Coastguard Worker     }
364*6777b538SAndroid Build Coastguard Worker 
365*6777b538SAndroid Build Coastguard Worker     memset(ret, 0, sizeof(xmlNanoHTTPCtxt));
366*6777b538SAndroid Build Coastguard Worker     ret->port = 80;
367*6777b538SAndroid Build Coastguard Worker     ret->returnValue = 0;
368*6777b538SAndroid Build Coastguard Worker     ret->fd = INVALID_SOCKET;
369*6777b538SAndroid Build Coastguard Worker     ret->ContentLength = -1;
370*6777b538SAndroid Build Coastguard Worker 
371*6777b538SAndroid Build Coastguard Worker     xmlNanoHTTPScanURL(ret, URL);
372*6777b538SAndroid Build Coastguard Worker 
373*6777b538SAndroid Build Coastguard Worker     return(ret);
374*6777b538SAndroid Build Coastguard Worker }
375*6777b538SAndroid Build Coastguard Worker 
376*6777b538SAndroid Build Coastguard Worker /**
377*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPFreeCtxt:
378*6777b538SAndroid Build Coastguard Worker  * @ctxt:  an HTTP context
379*6777b538SAndroid Build Coastguard Worker  *
380*6777b538SAndroid Build Coastguard Worker  * Frees the context after closing the connection.
381*6777b538SAndroid Build Coastguard Worker  */
382*6777b538SAndroid Build Coastguard Worker 
383*6777b538SAndroid Build Coastguard Worker static void
xmlNanoHTTPFreeCtxt(xmlNanoHTTPCtxtPtr ctxt)384*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPFreeCtxt(xmlNanoHTTPCtxtPtr ctxt) {
385*6777b538SAndroid Build Coastguard Worker     if (ctxt == NULL) return;
386*6777b538SAndroid Build Coastguard Worker     if (ctxt->hostname != NULL) xmlFree(ctxt->hostname);
387*6777b538SAndroid Build Coastguard Worker     if (ctxt->protocol != NULL) xmlFree(ctxt->protocol);
388*6777b538SAndroid Build Coastguard Worker     if (ctxt->path != NULL) xmlFree(ctxt->path);
389*6777b538SAndroid Build Coastguard Worker     if (ctxt->query != NULL) xmlFree(ctxt->query);
390*6777b538SAndroid Build Coastguard Worker     if (ctxt->out != NULL) xmlFree(ctxt->out);
391*6777b538SAndroid Build Coastguard Worker     if (ctxt->in != NULL) xmlFree(ctxt->in);
392*6777b538SAndroid Build Coastguard Worker     if (ctxt->contentType != NULL) xmlFree(ctxt->contentType);
393*6777b538SAndroid Build Coastguard Worker     if (ctxt->encoding != NULL) xmlFree(ctxt->encoding);
394*6777b538SAndroid Build Coastguard Worker     if (ctxt->mimeType != NULL) xmlFree(ctxt->mimeType);
395*6777b538SAndroid Build Coastguard Worker     if (ctxt->location != NULL) xmlFree(ctxt->location);
396*6777b538SAndroid Build Coastguard Worker     if (ctxt->authHeader != NULL) xmlFree(ctxt->authHeader);
397*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_ZLIB_ENABLED
398*6777b538SAndroid Build Coastguard Worker     if (ctxt->strm != NULL) {
399*6777b538SAndroid Build Coastguard Worker 	inflateEnd(ctxt->strm);
400*6777b538SAndroid Build Coastguard Worker 	xmlFree(ctxt->strm);
401*6777b538SAndroid Build Coastguard Worker     }
402*6777b538SAndroid Build Coastguard Worker #endif
403*6777b538SAndroid Build Coastguard Worker 
404*6777b538SAndroid Build Coastguard Worker     ctxt->state = XML_NANO_HTTP_NONE;
405*6777b538SAndroid Build Coastguard Worker     if (ctxt->fd != INVALID_SOCKET) closesocket(ctxt->fd);
406*6777b538SAndroid Build Coastguard Worker     ctxt->fd = INVALID_SOCKET;
407*6777b538SAndroid Build Coastguard Worker     xmlFree(ctxt);
408*6777b538SAndroid Build Coastguard Worker }
409*6777b538SAndroid Build Coastguard Worker 
410*6777b538SAndroid Build Coastguard Worker /**
411*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPSend:
412*6777b538SAndroid Build Coastguard Worker  * @ctxt:  an HTTP context
413*6777b538SAndroid Build Coastguard Worker  *
414*6777b538SAndroid Build Coastguard Worker  * Send the input needed to initiate the processing on the server side
415*6777b538SAndroid Build Coastguard Worker  * Returns number of bytes sent or -1 on error.
416*6777b538SAndroid Build Coastguard Worker  */
417*6777b538SAndroid Build Coastguard Worker 
418*6777b538SAndroid Build Coastguard Worker static int
xmlNanoHTTPSend(xmlNanoHTTPCtxtPtr ctxt,const char * xmt_ptr,int outlen)419*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPSend(xmlNanoHTTPCtxtPtr ctxt, const char *xmt_ptr, int outlen)
420*6777b538SAndroid Build Coastguard Worker {
421*6777b538SAndroid Build Coastguard Worker     int total_sent = 0;
422*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_POLL_H
423*6777b538SAndroid Build Coastguard Worker     struct pollfd p;
424*6777b538SAndroid Build Coastguard Worker #else
425*6777b538SAndroid Build Coastguard Worker     struct timeval tv;
426*6777b538SAndroid Build Coastguard Worker     fd_set wfd;
427*6777b538SAndroid Build Coastguard Worker #endif
428*6777b538SAndroid Build Coastguard Worker 
429*6777b538SAndroid Build Coastguard Worker     if ((ctxt->state & XML_NANO_HTTP_WRITE) && (xmt_ptr != NULL)) {
430*6777b538SAndroid Build Coastguard Worker         while (total_sent < outlen) {
431*6777b538SAndroid Build Coastguard Worker             int nsent = send(ctxt->fd, SEND_ARG2_CAST (xmt_ptr + total_sent),
432*6777b538SAndroid Build Coastguard Worker                              outlen - total_sent, 0);
433*6777b538SAndroid Build Coastguard Worker 
434*6777b538SAndroid Build Coastguard Worker             if (nsent > 0)
435*6777b538SAndroid Build Coastguard Worker                 total_sent += nsent;
436*6777b538SAndroid Build Coastguard Worker             else if ((nsent == -1) &&
437*6777b538SAndroid Build Coastguard Worker #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
438*6777b538SAndroid Build Coastguard Worker                      (socket_errno() != EAGAIN) &&
439*6777b538SAndroid Build Coastguard Worker #endif
440*6777b538SAndroid Build Coastguard Worker                      (socket_errno() != EWOULDBLOCK)) {
441*6777b538SAndroid Build Coastguard Worker                 __xmlIOErr(XML_FROM_HTTP, 0, "send failed\n");
442*6777b538SAndroid Build Coastguard Worker                 if (total_sent == 0)
443*6777b538SAndroid Build Coastguard Worker                     total_sent = -1;
444*6777b538SAndroid Build Coastguard Worker                 break;
445*6777b538SAndroid Build Coastguard Worker             } else {
446*6777b538SAndroid Build Coastguard Worker                 /*
447*6777b538SAndroid Build Coastguard Worker                  * No data sent
448*6777b538SAndroid Build Coastguard Worker                  * Since non-blocking sockets are used, wait for
449*6777b538SAndroid Build Coastguard Worker                  * socket to be writable or default timeout prior
450*6777b538SAndroid Build Coastguard Worker                  * to retrying.
451*6777b538SAndroid Build Coastguard Worker                  */
452*6777b538SAndroid Build Coastguard Worker #ifndef HAVE_POLL_H
453*6777b538SAndroid Build Coastguard Worker #ifndef _WINSOCKAPI_
454*6777b538SAndroid Build Coastguard Worker                 if (ctxt->fd > FD_SETSIZE)
455*6777b538SAndroid Build Coastguard Worker                     return -1;
456*6777b538SAndroid Build Coastguard Worker #endif
457*6777b538SAndroid Build Coastguard Worker 
458*6777b538SAndroid Build Coastguard Worker                 tv.tv_sec = timeout;
459*6777b538SAndroid Build Coastguard Worker                 tv.tv_usec = 0;
460*6777b538SAndroid Build Coastguard Worker                 FD_ZERO(&wfd);
461*6777b538SAndroid Build Coastguard Worker #ifdef _MSC_VER
462*6777b538SAndroid Build Coastguard Worker #pragma warning(push)
463*6777b538SAndroid Build Coastguard Worker #pragma warning(disable: 4018)
464*6777b538SAndroid Build Coastguard Worker #endif
465*6777b538SAndroid Build Coastguard Worker                 FD_SET(ctxt->fd, &wfd);
466*6777b538SAndroid Build Coastguard Worker #ifdef _MSC_VER
467*6777b538SAndroid Build Coastguard Worker #pragma warning(pop)
468*6777b538SAndroid Build Coastguard Worker #endif
469*6777b538SAndroid Build Coastguard Worker                 (void) select(ctxt->fd + 1, NULL, &wfd, NULL, &tv);
470*6777b538SAndroid Build Coastguard Worker #else
471*6777b538SAndroid Build Coastguard Worker                 p.fd = ctxt->fd;
472*6777b538SAndroid Build Coastguard Worker                 p.events = POLLOUT;
473*6777b538SAndroid Build Coastguard Worker                 (void) poll(&p, 1, timeout * 1000);
474*6777b538SAndroid Build Coastguard Worker #endif /* !HAVE_POLL_H */
475*6777b538SAndroid Build Coastguard Worker             }
476*6777b538SAndroid Build Coastguard Worker         }
477*6777b538SAndroid Build Coastguard Worker     }
478*6777b538SAndroid Build Coastguard Worker 
479*6777b538SAndroid Build Coastguard Worker     return total_sent;
480*6777b538SAndroid Build Coastguard Worker }
481*6777b538SAndroid Build Coastguard Worker 
482*6777b538SAndroid Build Coastguard Worker /**
483*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPRecv:
484*6777b538SAndroid Build Coastguard Worker  * @ctxt:  an HTTP context
485*6777b538SAndroid Build Coastguard Worker  *
486*6777b538SAndroid Build Coastguard Worker  * Read information coming from the HTTP connection.
487*6777b538SAndroid Build Coastguard Worker  * This is a blocking call (but it blocks in select(), not read()).
488*6777b538SAndroid Build Coastguard Worker  *
489*6777b538SAndroid Build Coastguard Worker  * Returns the number of byte read or -1 in case of error.
490*6777b538SAndroid Build Coastguard Worker  */
491*6777b538SAndroid Build Coastguard Worker 
492*6777b538SAndroid Build Coastguard Worker static int
xmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt)493*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt)
494*6777b538SAndroid Build Coastguard Worker {
495*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_POLL_H
496*6777b538SAndroid Build Coastguard Worker     struct pollfd p;
497*6777b538SAndroid Build Coastguard Worker #else
498*6777b538SAndroid Build Coastguard Worker     fd_set rfd;
499*6777b538SAndroid Build Coastguard Worker     struct timeval tv;
500*6777b538SAndroid Build Coastguard Worker #endif
501*6777b538SAndroid Build Coastguard Worker 
502*6777b538SAndroid Build Coastguard Worker 
503*6777b538SAndroid Build Coastguard Worker     while (ctxt->state & XML_NANO_HTTP_READ) {
504*6777b538SAndroid Build Coastguard Worker         if (ctxt->in == NULL) {
505*6777b538SAndroid Build Coastguard Worker             ctxt->in = (char *) xmlMallocAtomic(65000);
506*6777b538SAndroid Build Coastguard Worker             if (ctxt->in == NULL) {
507*6777b538SAndroid Build Coastguard Worker                 xmlHTTPErrMemory();
508*6777b538SAndroid Build Coastguard Worker                 ctxt->last = -1;
509*6777b538SAndroid Build Coastguard Worker                 return (-1);
510*6777b538SAndroid Build Coastguard Worker             }
511*6777b538SAndroid Build Coastguard Worker             ctxt->inlen = 65000;
512*6777b538SAndroid Build Coastguard Worker             ctxt->inptr = ctxt->content = ctxt->inrptr = ctxt->in;
513*6777b538SAndroid Build Coastguard Worker         }
514*6777b538SAndroid Build Coastguard Worker         if (ctxt->inrptr > ctxt->in + XML_NANO_HTTP_CHUNK) {
515*6777b538SAndroid Build Coastguard Worker             int delta = ctxt->inrptr - ctxt->in;
516*6777b538SAndroid Build Coastguard Worker             int len = ctxt->inptr - ctxt->inrptr;
517*6777b538SAndroid Build Coastguard Worker 
518*6777b538SAndroid Build Coastguard Worker             memmove(ctxt->in, ctxt->inrptr, len);
519*6777b538SAndroid Build Coastguard Worker             ctxt->inrptr -= delta;
520*6777b538SAndroid Build Coastguard Worker             ctxt->content -= delta;
521*6777b538SAndroid Build Coastguard Worker             ctxt->inptr -= delta;
522*6777b538SAndroid Build Coastguard Worker         }
523*6777b538SAndroid Build Coastguard Worker         if ((ctxt->in + ctxt->inlen) < (ctxt->inptr + XML_NANO_HTTP_CHUNK)) {
524*6777b538SAndroid Build Coastguard Worker             int d_inptr = ctxt->inptr - ctxt->in;
525*6777b538SAndroid Build Coastguard Worker             int d_content = ctxt->content - ctxt->in;
526*6777b538SAndroid Build Coastguard Worker             int d_inrptr = ctxt->inrptr - ctxt->in;
527*6777b538SAndroid Build Coastguard Worker             char *tmp_ptr = ctxt->in;
528*6777b538SAndroid Build Coastguard Worker 
529*6777b538SAndroid Build Coastguard Worker             ctxt->inlen *= 2;
530*6777b538SAndroid Build Coastguard Worker             ctxt->in = (char *) xmlRealloc(tmp_ptr, ctxt->inlen);
531*6777b538SAndroid Build Coastguard Worker             if (ctxt->in == NULL) {
532*6777b538SAndroid Build Coastguard Worker                 xmlHTTPErrMemory();
533*6777b538SAndroid Build Coastguard Worker                 xmlFree(tmp_ptr);
534*6777b538SAndroid Build Coastguard Worker                 ctxt->last = -1;
535*6777b538SAndroid Build Coastguard Worker                 return (-1);
536*6777b538SAndroid Build Coastguard Worker             }
537*6777b538SAndroid Build Coastguard Worker             ctxt->inptr = ctxt->in + d_inptr;
538*6777b538SAndroid Build Coastguard Worker             ctxt->content = ctxt->in + d_content;
539*6777b538SAndroid Build Coastguard Worker             ctxt->inrptr = ctxt->in + d_inrptr;
540*6777b538SAndroid Build Coastguard Worker         }
541*6777b538SAndroid Build Coastguard Worker         ctxt->last = recv(ctxt->fd, ctxt->inptr, XML_NANO_HTTP_CHUNK, 0);
542*6777b538SAndroid Build Coastguard Worker         if (ctxt->last > 0) {
543*6777b538SAndroid Build Coastguard Worker             ctxt->inptr += ctxt->last;
544*6777b538SAndroid Build Coastguard Worker             return (ctxt->last);
545*6777b538SAndroid Build Coastguard Worker         }
546*6777b538SAndroid Build Coastguard Worker         if (ctxt->last == 0) {
547*6777b538SAndroid Build Coastguard Worker             return (0);
548*6777b538SAndroid Build Coastguard Worker         }
549*6777b538SAndroid Build Coastguard Worker         if (ctxt->last == -1) {
550*6777b538SAndroid Build Coastguard Worker             switch (socket_errno()) {
551*6777b538SAndroid Build Coastguard Worker                 case EINPROGRESS:
552*6777b538SAndroid Build Coastguard Worker                 case EWOULDBLOCK:
553*6777b538SAndroid Build Coastguard Worker #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
554*6777b538SAndroid Build Coastguard Worker                 case EAGAIN:
555*6777b538SAndroid Build Coastguard Worker #endif
556*6777b538SAndroid Build Coastguard Worker                     break;
557*6777b538SAndroid Build Coastguard Worker 
558*6777b538SAndroid Build Coastguard Worker                 case ECONNRESET:
559*6777b538SAndroid Build Coastguard Worker                 case ESHUTDOWN:
560*6777b538SAndroid Build Coastguard Worker                     return (0);
561*6777b538SAndroid Build Coastguard Worker 
562*6777b538SAndroid Build Coastguard Worker                 default:
563*6777b538SAndroid Build Coastguard Worker                     __xmlIOErr(XML_FROM_HTTP, 0, "recv failed\n");
564*6777b538SAndroid Build Coastguard Worker                     return (-1);
565*6777b538SAndroid Build Coastguard Worker             }
566*6777b538SAndroid Build Coastguard Worker         }
567*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_POLL_H
568*6777b538SAndroid Build Coastguard Worker         p.fd = ctxt->fd;
569*6777b538SAndroid Build Coastguard Worker         p.events = POLLIN;
570*6777b538SAndroid Build Coastguard Worker         if ((poll(&p, 1, timeout * 1000) < 1)
571*6777b538SAndroid Build Coastguard Worker #if defined(EINTR)
572*6777b538SAndroid Build Coastguard Worker             && (errno != EINTR)
573*6777b538SAndroid Build Coastguard Worker #endif
574*6777b538SAndroid Build Coastguard Worker             )
575*6777b538SAndroid Build Coastguard Worker             return (0);
576*6777b538SAndroid Build Coastguard Worker #else /* !HAVE_POLL_H */
577*6777b538SAndroid Build Coastguard Worker #ifndef _WINSOCKAPI_
578*6777b538SAndroid Build Coastguard Worker         if (ctxt->fd > FD_SETSIZE)
579*6777b538SAndroid Build Coastguard Worker             return 0;
580*6777b538SAndroid Build Coastguard Worker #endif
581*6777b538SAndroid Build Coastguard Worker 
582*6777b538SAndroid Build Coastguard Worker         tv.tv_sec = timeout;
583*6777b538SAndroid Build Coastguard Worker         tv.tv_usec = 0;
584*6777b538SAndroid Build Coastguard Worker         FD_ZERO(&rfd);
585*6777b538SAndroid Build Coastguard Worker 
586*6777b538SAndroid Build Coastguard Worker #ifdef _MSC_VER
587*6777b538SAndroid Build Coastguard Worker #pragma warning(push)
588*6777b538SAndroid Build Coastguard Worker #pragma warning(disable: 4018)
589*6777b538SAndroid Build Coastguard Worker #endif
590*6777b538SAndroid Build Coastguard Worker 
591*6777b538SAndroid Build Coastguard Worker         FD_SET(ctxt->fd, &rfd);
592*6777b538SAndroid Build Coastguard Worker 
593*6777b538SAndroid Build Coastguard Worker #ifdef _MSC_VER
594*6777b538SAndroid Build Coastguard Worker #pragma warning(pop)
595*6777b538SAndroid Build Coastguard Worker #endif
596*6777b538SAndroid Build Coastguard Worker 
597*6777b538SAndroid Build Coastguard Worker         if ((select(ctxt->fd + 1, &rfd, NULL, NULL, &tv) < 1)
598*6777b538SAndroid Build Coastguard Worker #if defined(EINTR)
599*6777b538SAndroid Build Coastguard Worker             && (socket_errno() != EINTR)
600*6777b538SAndroid Build Coastguard Worker #endif
601*6777b538SAndroid Build Coastguard Worker             )
602*6777b538SAndroid Build Coastguard Worker             return (0);
603*6777b538SAndroid Build Coastguard Worker #endif /* !HAVE_POLL_H */
604*6777b538SAndroid Build Coastguard Worker     }
605*6777b538SAndroid Build Coastguard Worker     return (0);
606*6777b538SAndroid Build Coastguard Worker }
607*6777b538SAndroid Build Coastguard Worker 
608*6777b538SAndroid Build Coastguard Worker /**
609*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPReadLine:
610*6777b538SAndroid Build Coastguard Worker  * @ctxt:  an HTTP context
611*6777b538SAndroid Build Coastguard Worker  *
612*6777b538SAndroid Build Coastguard Worker  * Read one line in the HTTP server output, usually for extracting
613*6777b538SAndroid Build Coastguard Worker  * the HTTP protocol information from the answer header.
614*6777b538SAndroid Build Coastguard Worker  *
615*6777b538SAndroid Build Coastguard Worker  * Returns a newly allocated string with a copy of the line, or NULL
616*6777b538SAndroid Build Coastguard Worker  *         which indicate the end of the input.
617*6777b538SAndroid Build Coastguard Worker  */
618*6777b538SAndroid Build Coastguard Worker 
619*6777b538SAndroid Build Coastguard Worker static char *
xmlNanoHTTPReadLine(xmlNanoHTTPCtxtPtr ctxt)620*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPReadLine(xmlNanoHTTPCtxtPtr ctxt) {
621*6777b538SAndroid Build Coastguard Worker     char buf[4096];
622*6777b538SAndroid Build Coastguard Worker     char *bp = buf;
623*6777b538SAndroid Build Coastguard Worker     int	rc;
624*6777b538SAndroid Build Coastguard Worker 
625*6777b538SAndroid Build Coastguard Worker     while (bp - buf < 4095) {
626*6777b538SAndroid Build Coastguard Worker 	if (ctxt->inrptr == ctxt->inptr) {
627*6777b538SAndroid Build Coastguard Worker 	    if ( (rc = xmlNanoHTTPRecv(ctxt)) == 0) {
628*6777b538SAndroid Build Coastguard Worker 		if (bp == buf)
629*6777b538SAndroid Build Coastguard Worker 		    return(NULL);
630*6777b538SAndroid Build Coastguard Worker 		else
631*6777b538SAndroid Build Coastguard Worker 		    *bp = 0;
632*6777b538SAndroid Build Coastguard Worker 		return(xmlMemStrdup(buf));
633*6777b538SAndroid Build Coastguard Worker 	    }
634*6777b538SAndroid Build Coastguard Worker 	    else if ( rc == -1 ) {
635*6777b538SAndroid Build Coastguard Worker 	        return ( NULL );
636*6777b538SAndroid Build Coastguard Worker 	    }
637*6777b538SAndroid Build Coastguard Worker 	}
638*6777b538SAndroid Build Coastguard Worker 	*bp = *ctxt->inrptr++;
639*6777b538SAndroid Build Coastguard Worker 	if (*bp == '\n') {
640*6777b538SAndroid Build Coastguard Worker 	    *bp = 0;
641*6777b538SAndroid Build Coastguard Worker 	    return(xmlMemStrdup(buf));
642*6777b538SAndroid Build Coastguard Worker 	}
643*6777b538SAndroid Build Coastguard Worker 	if (*bp != '\r')
644*6777b538SAndroid Build Coastguard Worker 	    bp++;
645*6777b538SAndroid Build Coastguard Worker     }
646*6777b538SAndroid Build Coastguard Worker     buf[4095] = 0;
647*6777b538SAndroid Build Coastguard Worker     return(xmlMemStrdup(buf));
648*6777b538SAndroid Build Coastguard Worker }
649*6777b538SAndroid Build Coastguard Worker 
650*6777b538SAndroid Build Coastguard Worker 
651*6777b538SAndroid Build Coastguard Worker /**
652*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPScanAnswer:
653*6777b538SAndroid Build Coastguard Worker  * @ctxt:  an HTTP context
654*6777b538SAndroid Build Coastguard Worker  * @line:  an HTTP header line
655*6777b538SAndroid Build Coastguard Worker  *
656*6777b538SAndroid Build Coastguard Worker  * Try to extract useful information from the server answer.
657*6777b538SAndroid Build Coastguard Worker  * We currently parse and process:
658*6777b538SAndroid Build Coastguard Worker  *  - The HTTP revision/ return code
659*6777b538SAndroid Build Coastguard Worker  *  - The Content-Type, Mime-Type and charset used
660*6777b538SAndroid Build Coastguard Worker  *  - The Location for redirect processing.
661*6777b538SAndroid Build Coastguard Worker  *
662*6777b538SAndroid Build Coastguard Worker  * Returns -1 in case of failure, the file descriptor number otherwise
663*6777b538SAndroid Build Coastguard Worker  */
664*6777b538SAndroid Build Coastguard Worker 
665*6777b538SAndroid Build Coastguard Worker static void
xmlNanoHTTPScanAnswer(xmlNanoHTTPCtxtPtr ctxt,const char * line)666*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPScanAnswer(xmlNanoHTTPCtxtPtr ctxt, const char *line) {
667*6777b538SAndroid Build Coastguard Worker     const char *cur = line;
668*6777b538SAndroid Build Coastguard Worker 
669*6777b538SAndroid Build Coastguard Worker     if (line == NULL) return;
670*6777b538SAndroid Build Coastguard Worker 
671*6777b538SAndroid Build Coastguard Worker     if (!strncmp(line, "HTTP/", 5)) {
672*6777b538SAndroid Build Coastguard Worker         int version = 0;
673*6777b538SAndroid Build Coastguard Worker 	int ret = 0;
674*6777b538SAndroid Build Coastguard Worker 
675*6777b538SAndroid Build Coastguard Worker 	cur += 5;
676*6777b538SAndroid Build Coastguard Worker 	while ((*cur >= '0') && (*cur <= '9')) {
677*6777b538SAndroid Build Coastguard Worker 	    version *= 10;
678*6777b538SAndroid Build Coastguard Worker 	    version += *cur - '0';
679*6777b538SAndroid Build Coastguard Worker 	    cur++;
680*6777b538SAndroid Build Coastguard Worker 	}
681*6777b538SAndroid Build Coastguard Worker 	if (*cur == '.') {
682*6777b538SAndroid Build Coastguard Worker 	    cur++;
683*6777b538SAndroid Build Coastguard Worker 	    if ((*cur >= '0') && (*cur <= '9')) {
684*6777b538SAndroid Build Coastguard Worker 		version *= 10;
685*6777b538SAndroid Build Coastguard Worker 		version += *cur - '0';
686*6777b538SAndroid Build Coastguard Worker 		cur++;
687*6777b538SAndroid Build Coastguard Worker 	    }
688*6777b538SAndroid Build Coastguard Worker 	    while ((*cur >= '0') && (*cur <= '9'))
689*6777b538SAndroid Build Coastguard Worker 		cur++;
690*6777b538SAndroid Build Coastguard Worker 	} else
691*6777b538SAndroid Build Coastguard Worker 	    version *= 10;
692*6777b538SAndroid Build Coastguard Worker 	if ((*cur != ' ') && (*cur != '\t')) return;
693*6777b538SAndroid Build Coastguard Worker 	while ((*cur == ' ') || (*cur == '\t')) cur++;
694*6777b538SAndroid Build Coastguard Worker 	if ((*cur < '0') || (*cur > '9')) return;
695*6777b538SAndroid Build Coastguard Worker 	while ((*cur >= '0') && (*cur <= '9')) {
696*6777b538SAndroid Build Coastguard Worker 	    ret *= 10;
697*6777b538SAndroid Build Coastguard Worker 	    ret += *cur - '0';
698*6777b538SAndroid Build Coastguard Worker 	    cur++;
699*6777b538SAndroid Build Coastguard Worker 	}
700*6777b538SAndroid Build Coastguard Worker 	if ((*cur != 0) && (*cur != ' ') && (*cur != '\t')) return;
701*6777b538SAndroid Build Coastguard Worker 	ctxt->returnValue = ret;
702*6777b538SAndroid Build Coastguard Worker         ctxt->version = version;
703*6777b538SAndroid Build Coastguard Worker     } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"Content-Type:", 13)) {
704*6777b538SAndroid Build Coastguard Worker         const xmlChar *charset, *last, *mime;
705*6777b538SAndroid Build Coastguard Worker         cur += 13;
706*6777b538SAndroid Build Coastguard Worker 	while ((*cur == ' ') || (*cur == '\t')) cur++;
707*6777b538SAndroid Build Coastguard Worker 	if (ctxt->contentType != NULL)
708*6777b538SAndroid Build Coastguard Worker 	    xmlFree(ctxt->contentType);
709*6777b538SAndroid Build Coastguard Worker 	ctxt->contentType = xmlMemStrdup(cur);
710*6777b538SAndroid Build Coastguard Worker 	mime = (const xmlChar *) cur;
711*6777b538SAndroid Build Coastguard Worker 	last = mime;
712*6777b538SAndroid Build Coastguard Worker 	while ((*last != 0) && (*last != ' ') && (*last != '\t') &&
713*6777b538SAndroid Build Coastguard Worker 	       (*last != ';') && (*last != ','))
714*6777b538SAndroid Build Coastguard Worker 	    last++;
715*6777b538SAndroid Build Coastguard Worker 	if (ctxt->mimeType != NULL)
716*6777b538SAndroid Build Coastguard Worker 	    xmlFree(ctxt->mimeType);
717*6777b538SAndroid Build Coastguard Worker 	ctxt->mimeType = (char *) xmlStrndup(mime, last - mime);
718*6777b538SAndroid Build Coastguard Worker 	charset = xmlStrstr(BAD_CAST ctxt->contentType, BAD_CAST "charset=");
719*6777b538SAndroid Build Coastguard Worker 	if (charset != NULL) {
720*6777b538SAndroid Build Coastguard Worker 	    charset += 8;
721*6777b538SAndroid Build Coastguard Worker 	    last = charset;
722*6777b538SAndroid Build Coastguard Worker 	    while ((*last != 0) && (*last != ' ') && (*last != '\t') &&
723*6777b538SAndroid Build Coastguard Worker 	           (*last != ';') && (*last != ','))
724*6777b538SAndroid Build Coastguard Worker 		last++;
725*6777b538SAndroid Build Coastguard Worker 	    if (ctxt->encoding != NULL)
726*6777b538SAndroid Build Coastguard Worker 	        xmlFree(ctxt->encoding);
727*6777b538SAndroid Build Coastguard Worker 	    ctxt->encoding = (char *) xmlStrndup(charset, last - charset);
728*6777b538SAndroid Build Coastguard Worker 	}
729*6777b538SAndroid Build Coastguard Worker     } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"ContentType:", 12)) {
730*6777b538SAndroid Build Coastguard Worker         const xmlChar *charset, *last, *mime;
731*6777b538SAndroid Build Coastguard Worker         cur += 12;
732*6777b538SAndroid Build Coastguard Worker 	if (ctxt->contentType != NULL) return;
733*6777b538SAndroid Build Coastguard Worker 	while ((*cur == ' ') || (*cur == '\t')) cur++;
734*6777b538SAndroid Build Coastguard Worker 	ctxt->contentType = xmlMemStrdup(cur);
735*6777b538SAndroid Build Coastguard Worker 	mime = (const xmlChar *) cur;
736*6777b538SAndroid Build Coastguard Worker 	last = mime;
737*6777b538SAndroid Build Coastguard Worker 	while ((*last != 0) && (*last != ' ') && (*last != '\t') &&
738*6777b538SAndroid Build Coastguard Worker 	       (*last != ';') && (*last != ','))
739*6777b538SAndroid Build Coastguard Worker 	    last++;
740*6777b538SAndroid Build Coastguard Worker 	if (ctxt->mimeType != NULL)
741*6777b538SAndroid Build Coastguard Worker 	    xmlFree(ctxt->mimeType);
742*6777b538SAndroid Build Coastguard Worker 	ctxt->mimeType = (char *) xmlStrndup(mime, last - mime);
743*6777b538SAndroid Build Coastguard Worker 	charset = xmlStrstr(BAD_CAST ctxt->contentType, BAD_CAST "charset=");
744*6777b538SAndroid Build Coastguard Worker 	if (charset != NULL) {
745*6777b538SAndroid Build Coastguard Worker 	    charset += 8;
746*6777b538SAndroid Build Coastguard Worker 	    last = charset;
747*6777b538SAndroid Build Coastguard Worker 	    while ((*last != 0) && (*last != ' ') && (*last != '\t') &&
748*6777b538SAndroid Build Coastguard Worker 	           (*last != ';') && (*last != ','))
749*6777b538SAndroid Build Coastguard Worker 		last++;
750*6777b538SAndroid Build Coastguard Worker 	    if (ctxt->encoding != NULL)
751*6777b538SAndroid Build Coastguard Worker 	        xmlFree(ctxt->encoding);
752*6777b538SAndroid Build Coastguard Worker 	    ctxt->encoding = (char *) xmlStrndup(charset, last - charset);
753*6777b538SAndroid Build Coastguard Worker 	}
754*6777b538SAndroid Build Coastguard Worker     } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"Location:", 9)) {
755*6777b538SAndroid Build Coastguard Worker         cur += 9;
756*6777b538SAndroid Build Coastguard Worker 	while ((*cur == ' ') || (*cur == '\t')) cur++;
757*6777b538SAndroid Build Coastguard Worker 	if (ctxt->location != NULL)
758*6777b538SAndroid Build Coastguard Worker 	    xmlFree(ctxt->location);
759*6777b538SAndroid Build Coastguard Worker 	if (*cur == '/') {
760*6777b538SAndroid Build Coastguard Worker 	    xmlChar *tmp_http = xmlStrdup(BAD_CAST "http://");
761*6777b538SAndroid Build Coastguard Worker 	    xmlChar *tmp_loc =
762*6777b538SAndroid Build Coastguard Worker 	        xmlStrcat(tmp_http, (const xmlChar *) ctxt->hostname);
763*6777b538SAndroid Build Coastguard Worker 	    ctxt->location =
764*6777b538SAndroid Build Coastguard Worker 	        (char *) xmlStrcat (tmp_loc, (const xmlChar *) cur);
765*6777b538SAndroid Build Coastguard Worker 	} else {
766*6777b538SAndroid Build Coastguard Worker 	    ctxt->location = xmlMemStrdup(cur);
767*6777b538SAndroid Build Coastguard Worker 	}
768*6777b538SAndroid Build Coastguard Worker     } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"WWW-Authenticate:", 17)) {
769*6777b538SAndroid Build Coastguard Worker         cur += 17;
770*6777b538SAndroid Build Coastguard Worker 	while ((*cur == ' ') || (*cur == '\t')) cur++;
771*6777b538SAndroid Build Coastguard Worker 	if (ctxt->authHeader != NULL)
772*6777b538SAndroid Build Coastguard Worker 	    xmlFree(ctxt->authHeader);
773*6777b538SAndroid Build Coastguard Worker 	ctxt->authHeader = xmlMemStrdup(cur);
774*6777b538SAndroid Build Coastguard Worker     } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"Proxy-Authenticate:", 19)) {
775*6777b538SAndroid Build Coastguard Worker         cur += 19;
776*6777b538SAndroid Build Coastguard Worker 	while ((*cur == ' ') || (*cur == '\t')) cur++;
777*6777b538SAndroid Build Coastguard Worker 	if (ctxt->authHeader != NULL)
778*6777b538SAndroid Build Coastguard Worker 	    xmlFree(ctxt->authHeader);
779*6777b538SAndroid Build Coastguard Worker 	ctxt->authHeader = xmlMemStrdup(cur);
780*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_ZLIB_ENABLED
781*6777b538SAndroid Build Coastguard Worker     } else if ( !xmlStrncasecmp( BAD_CAST line, BAD_CAST"Content-Encoding:", 17) ) {
782*6777b538SAndroid Build Coastguard Worker 	cur += 17;
783*6777b538SAndroid Build Coastguard Worker 	while ((*cur == ' ') || (*cur == '\t')) cur++;
784*6777b538SAndroid Build Coastguard Worker 	if ( !xmlStrncasecmp( BAD_CAST cur, BAD_CAST"gzip", 4) ) {
785*6777b538SAndroid Build Coastguard Worker 	    ctxt->usesGzip = 1;
786*6777b538SAndroid Build Coastguard Worker 
787*6777b538SAndroid Build Coastguard Worker 	    ctxt->strm = xmlMalloc(sizeof(z_stream));
788*6777b538SAndroid Build Coastguard Worker 
789*6777b538SAndroid Build Coastguard Worker 	    if (ctxt->strm != NULL) {
790*6777b538SAndroid Build Coastguard Worker 		ctxt->strm->zalloc = Z_NULL;
791*6777b538SAndroid Build Coastguard Worker 		ctxt->strm->zfree = Z_NULL;
792*6777b538SAndroid Build Coastguard Worker 		ctxt->strm->opaque = Z_NULL;
793*6777b538SAndroid Build Coastguard Worker 		ctxt->strm->avail_in = 0;
794*6777b538SAndroid Build Coastguard Worker 		ctxt->strm->next_in = Z_NULL;
795*6777b538SAndroid Build Coastguard Worker 
796*6777b538SAndroid Build Coastguard Worker 		inflateInit2( ctxt->strm, 31 );
797*6777b538SAndroid Build Coastguard Worker 	    }
798*6777b538SAndroid Build Coastguard Worker 	}
799*6777b538SAndroid Build Coastguard Worker #endif
800*6777b538SAndroid Build Coastguard Worker     } else if ( !xmlStrncasecmp( BAD_CAST line, BAD_CAST"Content-Length:", 15) ) {
801*6777b538SAndroid Build Coastguard Worker 	cur += 15;
802*6777b538SAndroid Build Coastguard Worker 	ctxt->ContentLength = strtol( cur, NULL, 10 );
803*6777b538SAndroid Build Coastguard Worker     }
804*6777b538SAndroid Build Coastguard Worker }
805*6777b538SAndroid Build Coastguard Worker 
806*6777b538SAndroid Build Coastguard Worker /**
807*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPConnectAttempt:
808*6777b538SAndroid Build Coastguard Worker  * @addr:  a socket address structure
809*6777b538SAndroid Build Coastguard Worker  *
810*6777b538SAndroid Build Coastguard Worker  * Attempt a connection to the given IP:port endpoint. It forces
811*6777b538SAndroid Build Coastguard Worker  * non-blocking semantic on the socket, and allow 60 seconds for
812*6777b538SAndroid Build Coastguard Worker  * the host to answer.
813*6777b538SAndroid Build Coastguard Worker  *
814*6777b538SAndroid Build Coastguard Worker  * Returns -1 in case of failure, the file descriptor number otherwise
815*6777b538SAndroid Build Coastguard Worker  */
816*6777b538SAndroid Build Coastguard Worker 
817*6777b538SAndroid Build Coastguard Worker static SOCKET
xmlNanoHTTPConnectAttempt(struct sockaddr * addr)818*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPConnectAttempt(struct sockaddr *addr)
819*6777b538SAndroid Build Coastguard Worker {
820*6777b538SAndroid Build Coastguard Worker #ifndef HAVE_POLL_H
821*6777b538SAndroid Build Coastguard Worker     fd_set wfd;
822*6777b538SAndroid Build Coastguard Worker #ifdef _WINSOCKAPI_
823*6777b538SAndroid Build Coastguard Worker     fd_set xfd;
824*6777b538SAndroid Build Coastguard Worker #endif
825*6777b538SAndroid Build Coastguard Worker     struct timeval tv;
826*6777b538SAndroid Build Coastguard Worker #else /* !HAVE_POLL_H */
827*6777b538SAndroid Build Coastguard Worker     struct pollfd p;
828*6777b538SAndroid Build Coastguard Worker #endif /* !HAVE_POLL_H */
829*6777b538SAndroid Build Coastguard Worker     int status;
830*6777b538SAndroid Build Coastguard Worker 
831*6777b538SAndroid Build Coastguard Worker     int addrlen;
832*6777b538SAndroid Build Coastguard Worker 
833*6777b538SAndroid Build Coastguard Worker     SOCKET s;
834*6777b538SAndroid Build Coastguard Worker 
835*6777b538SAndroid Build Coastguard Worker #ifdef SUPPORT_IP6
836*6777b538SAndroid Build Coastguard Worker     if (addr->sa_family == AF_INET6) {
837*6777b538SAndroid Build Coastguard Worker         s = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
838*6777b538SAndroid Build Coastguard Worker         addrlen = sizeof(struct sockaddr_in6);
839*6777b538SAndroid Build Coastguard Worker     } else
840*6777b538SAndroid Build Coastguard Worker #endif
841*6777b538SAndroid Build Coastguard Worker     {
842*6777b538SAndroid Build Coastguard Worker         s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
843*6777b538SAndroid Build Coastguard Worker         addrlen = sizeof(struct sockaddr_in);
844*6777b538SAndroid Build Coastguard Worker     }
845*6777b538SAndroid Build Coastguard Worker     if (s == INVALID_SOCKET) {
846*6777b538SAndroid Build Coastguard Worker         __xmlIOErr(XML_FROM_HTTP, 0, "socket failed\n");
847*6777b538SAndroid Build Coastguard Worker         return INVALID_SOCKET;
848*6777b538SAndroid Build Coastguard Worker     }
849*6777b538SAndroid Build Coastguard Worker #ifdef _WINSOCKAPI_
850*6777b538SAndroid Build Coastguard Worker     {
851*6777b538SAndroid Build Coastguard Worker         u_long one = 1;
852*6777b538SAndroid Build Coastguard Worker 
853*6777b538SAndroid Build Coastguard Worker         status = ioctlsocket(s, FIONBIO, &one) == SOCKET_ERROR ? -1 : 0;
854*6777b538SAndroid Build Coastguard Worker     }
855*6777b538SAndroid Build Coastguard Worker #else /* _WINSOCKAPI_ */
856*6777b538SAndroid Build Coastguard Worker #if defined(VMS)
857*6777b538SAndroid Build Coastguard Worker     {
858*6777b538SAndroid Build Coastguard Worker         int enable = 1;
859*6777b538SAndroid Build Coastguard Worker 
860*6777b538SAndroid Build Coastguard Worker         status = ioctl(s, FIONBIO, &enable);
861*6777b538SAndroid Build Coastguard Worker     }
862*6777b538SAndroid Build Coastguard Worker #else /* VMS */
863*6777b538SAndroid Build Coastguard Worker     if ((status = fcntl(s, F_GETFL, 0)) != -1) {
864*6777b538SAndroid Build Coastguard Worker #ifdef O_NONBLOCK
865*6777b538SAndroid Build Coastguard Worker         status |= O_NONBLOCK;
866*6777b538SAndroid Build Coastguard Worker #else /* O_NONBLOCK */
867*6777b538SAndroid Build Coastguard Worker #ifdef F_NDELAY
868*6777b538SAndroid Build Coastguard Worker         status |= F_NDELAY;
869*6777b538SAndroid Build Coastguard Worker #endif /* F_NDELAY */
870*6777b538SAndroid Build Coastguard Worker #endif /* !O_NONBLOCK */
871*6777b538SAndroid Build Coastguard Worker         status = fcntl(s, F_SETFL, status);
872*6777b538SAndroid Build Coastguard Worker     }
873*6777b538SAndroid Build Coastguard Worker     if (status < 0) {
874*6777b538SAndroid Build Coastguard Worker         __xmlIOErr(XML_FROM_HTTP, 0, "error setting non-blocking IO\n");
875*6777b538SAndroid Build Coastguard Worker         closesocket(s);
876*6777b538SAndroid Build Coastguard Worker         return INVALID_SOCKET;
877*6777b538SAndroid Build Coastguard Worker     }
878*6777b538SAndroid Build Coastguard Worker #endif /* !VMS */
879*6777b538SAndroid Build Coastguard Worker #endif /* !_WINSOCKAPI_ */
880*6777b538SAndroid Build Coastguard Worker 
881*6777b538SAndroid Build Coastguard Worker     if (connect(s, addr, addrlen) == -1) {
882*6777b538SAndroid Build Coastguard Worker         switch (socket_errno()) {
883*6777b538SAndroid Build Coastguard Worker             case EINPROGRESS:
884*6777b538SAndroid Build Coastguard Worker             case EWOULDBLOCK:
885*6777b538SAndroid Build Coastguard Worker                 break;
886*6777b538SAndroid Build Coastguard Worker             default:
887*6777b538SAndroid Build Coastguard Worker                 __xmlIOErr(XML_FROM_HTTP, 0,
888*6777b538SAndroid Build Coastguard Worker                            "error connecting to HTTP server");
889*6777b538SAndroid Build Coastguard Worker                 closesocket(s);
890*6777b538SAndroid Build Coastguard Worker                 return INVALID_SOCKET;
891*6777b538SAndroid Build Coastguard Worker         }
892*6777b538SAndroid Build Coastguard Worker     }
893*6777b538SAndroid Build Coastguard Worker #ifndef HAVE_POLL_H
894*6777b538SAndroid Build Coastguard Worker     tv.tv_sec = timeout;
895*6777b538SAndroid Build Coastguard Worker     tv.tv_usec = 0;
896*6777b538SAndroid Build Coastguard Worker 
897*6777b538SAndroid Build Coastguard Worker #ifdef _MSC_VER
898*6777b538SAndroid Build Coastguard Worker #pragma warning(push)
899*6777b538SAndroid Build Coastguard Worker #pragma warning(disable: 4018)
900*6777b538SAndroid Build Coastguard Worker #endif
901*6777b538SAndroid Build Coastguard Worker #ifndef _WINSOCKAPI_
902*6777b538SAndroid Build Coastguard Worker     if (s > FD_SETSIZE)
903*6777b538SAndroid Build Coastguard Worker         return INVALID_SOCKET;
904*6777b538SAndroid Build Coastguard Worker #endif
905*6777b538SAndroid Build Coastguard Worker     FD_ZERO(&wfd);
906*6777b538SAndroid Build Coastguard Worker     FD_SET(s, &wfd);
907*6777b538SAndroid Build Coastguard Worker 
908*6777b538SAndroid Build Coastguard Worker #ifdef _WINSOCKAPI_
909*6777b538SAndroid Build Coastguard Worker     FD_ZERO(&xfd);
910*6777b538SAndroid Build Coastguard Worker     FD_SET(s, &xfd);
911*6777b538SAndroid Build Coastguard Worker 
912*6777b538SAndroid Build Coastguard Worker     switch (select(s + 1, NULL, &wfd, &xfd, &tv))
913*6777b538SAndroid Build Coastguard Worker #else
914*6777b538SAndroid Build Coastguard Worker     switch (select(s + 1, NULL, &wfd, NULL, &tv))
915*6777b538SAndroid Build Coastguard Worker #endif
916*6777b538SAndroid Build Coastguard Worker #ifdef _MSC_VER
917*6777b538SAndroid Build Coastguard Worker #pragma warning(pop)
918*6777b538SAndroid Build Coastguard Worker #endif
919*6777b538SAndroid Build Coastguard Worker 
920*6777b538SAndroid Build Coastguard Worker #else /* !HAVE_POLL_H */
921*6777b538SAndroid Build Coastguard Worker     p.fd = s;
922*6777b538SAndroid Build Coastguard Worker     p.events = POLLOUT;
923*6777b538SAndroid Build Coastguard Worker     switch (poll(&p, 1, timeout * 1000))
924*6777b538SAndroid Build Coastguard Worker #endif /* !HAVE_POLL_H */
925*6777b538SAndroid Build Coastguard Worker 
926*6777b538SAndroid Build Coastguard Worker     {
927*6777b538SAndroid Build Coastguard Worker         case 0:
928*6777b538SAndroid Build Coastguard Worker             /* Time out */
929*6777b538SAndroid Build Coastguard Worker             __xmlIOErr(XML_FROM_HTTP, 0, "Connect attempt timed out");
930*6777b538SAndroid Build Coastguard Worker             closesocket(s);
931*6777b538SAndroid Build Coastguard Worker             return INVALID_SOCKET;
932*6777b538SAndroid Build Coastguard Worker         case -1:
933*6777b538SAndroid Build Coastguard Worker             /* Ermm.. ?? */
934*6777b538SAndroid Build Coastguard Worker             __xmlIOErr(XML_FROM_HTTP, 0, "Connect failed");
935*6777b538SAndroid Build Coastguard Worker             closesocket(s);
936*6777b538SAndroid Build Coastguard Worker             return INVALID_SOCKET;
937*6777b538SAndroid Build Coastguard Worker     }
938*6777b538SAndroid Build Coastguard Worker 
939*6777b538SAndroid Build Coastguard Worker #ifndef HAVE_POLL_H
940*6777b538SAndroid Build Coastguard Worker     if (FD_ISSET(s, &wfd)
941*6777b538SAndroid Build Coastguard Worker #ifdef _WINSOCKAPI_
942*6777b538SAndroid Build Coastguard Worker         || FD_ISSET(s, &xfd)
943*6777b538SAndroid Build Coastguard Worker #endif
944*6777b538SAndroid Build Coastguard Worker         )
945*6777b538SAndroid Build Coastguard Worker #else /* !HAVE_POLL_H */
946*6777b538SAndroid Build Coastguard Worker     if (p.revents == POLLOUT)
947*6777b538SAndroid Build Coastguard Worker #endif /* !HAVE_POLL_H */
948*6777b538SAndroid Build Coastguard Worker     {
949*6777b538SAndroid Build Coastguard Worker         XML_SOCKLEN_T len;
950*6777b538SAndroid Build Coastguard Worker 
951*6777b538SAndroid Build Coastguard Worker         len = sizeof(status);
952*6777b538SAndroid Build Coastguard Worker #ifdef SO_ERROR
953*6777b538SAndroid Build Coastguard Worker         if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char *) &status, &len) <
954*6777b538SAndroid Build Coastguard Worker             0) {
955*6777b538SAndroid Build Coastguard Worker             /* Solaris error code */
956*6777b538SAndroid Build Coastguard Worker             __xmlIOErr(XML_FROM_HTTP, 0, "getsockopt failed\n");
957*6777b538SAndroid Build Coastguard Worker             closesocket(s);
958*6777b538SAndroid Build Coastguard Worker             return INVALID_SOCKET;
959*6777b538SAndroid Build Coastguard Worker         }
960*6777b538SAndroid Build Coastguard Worker #endif
961*6777b538SAndroid Build Coastguard Worker         if (status) {
962*6777b538SAndroid Build Coastguard Worker             __xmlIOErr(XML_FROM_HTTP, 0,
963*6777b538SAndroid Build Coastguard Worker                        "Error connecting to remote host");
964*6777b538SAndroid Build Coastguard Worker             closesocket(s);
965*6777b538SAndroid Build Coastguard Worker             errno = status;
966*6777b538SAndroid Build Coastguard Worker             return INVALID_SOCKET;
967*6777b538SAndroid Build Coastguard Worker         }
968*6777b538SAndroid Build Coastguard Worker     } else {
969*6777b538SAndroid Build Coastguard Worker         /* pbm */
970*6777b538SAndroid Build Coastguard Worker         __xmlIOErr(XML_FROM_HTTP, 0, "select failed\n");
971*6777b538SAndroid Build Coastguard Worker         closesocket(s);
972*6777b538SAndroid Build Coastguard Worker         return INVALID_SOCKET;
973*6777b538SAndroid Build Coastguard Worker     }
974*6777b538SAndroid Build Coastguard Worker 
975*6777b538SAndroid Build Coastguard Worker     return (s);
976*6777b538SAndroid Build Coastguard Worker }
977*6777b538SAndroid Build Coastguard Worker 
978*6777b538SAndroid Build Coastguard Worker /**
979*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPConnectHost:
980*6777b538SAndroid Build Coastguard Worker  * @host:  the host name
981*6777b538SAndroid Build Coastguard Worker  * @port:  the port number
982*6777b538SAndroid Build Coastguard Worker  *
983*6777b538SAndroid Build Coastguard Worker  * Attempt a connection to the given host:port endpoint. It tries
984*6777b538SAndroid Build Coastguard Worker  * the multiple IP provided by the DNS if available.
985*6777b538SAndroid Build Coastguard Worker  *
986*6777b538SAndroid Build Coastguard Worker  * Returns -1 in case of failure, the file descriptor number otherwise
987*6777b538SAndroid Build Coastguard Worker  */
988*6777b538SAndroid Build Coastguard Worker 
989*6777b538SAndroid Build Coastguard Worker static SOCKET
xmlNanoHTTPConnectHost(const char * host,int port)990*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPConnectHost(const char *host, int port)
991*6777b538SAndroid Build Coastguard Worker {
992*6777b538SAndroid Build Coastguard Worker     struct sockaddr *addr = NULL;
993*6777b538SAndroid Build Coastguard Worker     struct sockaddr_in sockin;
994*6777b538SAndroid Build Coastguard Worker 
995*6777b538SAndroid Build Coastguard Worker #ifdef SUPPORT_IP6
996*6777b538SAndroid Build Coastguard Worker     struct sockaddr_in6 sockin6;
997*6777b538SAndroid Build Coastguard Worker #endif
998*6777b538SAndroid Build Coastguard Worker     SOCKET s;
999*6777b538SAndroid Build Coastguard Worker 
1000*6777b538SAndroid Build Coastguard Worker     memset (&sockin, 0, sizeof(sockin));
1001*6777b538SAndroid Build Coastguard Worker 
1002*6777b538SAndroid Build Coastguard Worker #if defined(SUPPORT_IP6)
1003*6777b538SAndroid Build Coastguard Worker     {
1004*6777b538SAndroid Build Coastguard Worker 	int status;
1005*6777b538SAndroid Build Coastguard Worker 	struct addrinfo hints, *res, *result;
1006*6777b538SAndroid Build Coastguard Worker 
1007*6777b538SAndroid Build Coastguard Worker         memset (&sockin6, 0, sizeof(sockin6));
1008*6777b538SAndroid Build Coastguard Worker 
1009*6777b538SAndroid Build Coastguard Worker 	result = NULL;
1010*6777b538SAndroid Build Coastguard Worker 	memset (&hints, 0,sizeof(hints));
1011*6777b538SAndroid Build Coastguard Worker 	hints.ai_socktype = SOCK_STREAM;
1012*6777b538SAndroid Build Coastguard Worker 
1013*6777b538SAndroid Build Coastguard Worker 	status = getaddrinfo (host, NULL, &hints, &result);
1014*6777b538SAndroid Build Coastguard Worker 	if (status) {
1015*6777b538SAndroid Build Coastguard Worker 	    __xmlIOErr(XML_FROM_HTTP, 0, "getaddrinfo failed\n");
1016*6777b538SAndroid Build Coastguard Worker 	    return INVALID_SOCKET;
1017*6777b538SAndroid Build Coastguard Worker 	}
1018*6777b538SAndroid Build Coastguard Worker 
1019*6777b538SAndroid Build Coastguard Worker 	for (res = result; res; res = res->ai_next) {
1020*6777b538SAndroid Build Coastguard Worker 	    if (res->ai_family == AF_INET) {
1021*6777b538SAndroid Build Coastguard Worker 		if ((size_t)res->ai_addrlen > sizeof(sockin)) {
1022*6777b538SAndroid Build Coastguard Worker 		    __xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n");
1023*6777b538SAndroid Build Coastguard Worker 		    freeaddrinfo (result);
1024*6777b538SAndroid Build Coastguard Worker 		    return INVALID_SOCKET;
1025*6777b538SAndroid Build Coastguard Worker 		}
1026*6777b538SAndroid Build Coastguard Worker 		memcpy (&sockin, res->ai_addr, res->ai_addrlen);
1027*6777b538SAndroid Build Coastguard Worker 		sockin.sin_port = htons (port);
1028*6777b538SAndroid Build Coastguard Worker 		addr = (struct sockaddr *)&sockin;
1029*6777b538SAndroid Build Coastguard Worker 	    } else if (res->ai_family == AF_INET6) {
1030*6777b538SAndroid Build Coastguard Worker 		if ((size_t)res->ai_addrlen > sizeof(sockin6)) {
1031*6777b538SAndroid Build Coastguard Worker 		    __xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n");
1032*6777b538SAndroid Build Coastguard Worker 		    freeaddrinfo (result);
1033*6777b538SAndroid Build Coastguard Worker 		    return INVALID_SOCKET;
1034*6777b538SAndroid Build Coastguard Worker 		}
1035*6777b538SAndroid Build Coastguard Worker 		memcpy (&sockin6, res->ai_addr, res->ai_addrlen);
1036*6777b538SAndroid Build Coastguard Worker 		sockin6.sin6_port = htons (port);
1037*6777b538SAndroid Build Coastguard Worker 		addr = (struct sockaddr *)&sockin6;
1038*6777b538SAndroid Build Coastguard Worker 	    } else
1039*6777b538SAndroid Build Coastguard Worker 		continue;              /* for */
1040*6777b538SAndroid Build Coastguard Worker 
1041*6777b538SAndroid Build Coastguard Worker 	    s = xmlNanoHTTPConnectAttempt (addr);
1042*6777b538SAndroid Build Coastguard Worker 	    if (s != INVALID_SOCKET) {
1043*6777b538SAndroid Build Coastguard Worker 		freeaddrinfo (result);
1044*6777b538SAndroid Build Coastguard Worker 		return (s);
1045*6777b538SAndroid Build Coastguard Worker 	    }
1046*6777b538SAndroid Build Coastguard Worker 	}
1047*6777b538SAndroid Build Coastguard Worker 
1048*6777b538SAndroid Build Coastguard Worker 	if (result)
1049*6777b538SAndroid Build Coastguard Worker 	    freeaddrinfo (result);
1050*6777b538SAndroid Build Coastguard Worker     }
1051*6777b538SAndroid Build Coastguard Worker #else
1052*6777b538SAndroid Build Coastguard Worker     {
1053*6777b538SAndroid Build Coastguard Worker         struct hostent *h;
1054*6777b538SAndroid Build Coastguard Worker         struct in_addr ia;
1055*6777b538SAndroid Build Coastguard Worker         int i;
1056*6777b538SAndroid Build Coastguard Worker 
1057*6777b538SAndroid Build Coastguard Worker 	h = gethostbyname (GETHOSTBYNAME_ARG_CAST host);
1058*6777b538SAndroid Build Coastguard Worker 	if (h == NULL) {
1059*6777b538SAndroid Build Coastguard Worker 
1060*6777b538SAndroid Build Coastguard Worker /*
1061*6777b538SAndroid Build Coastguard Worker  * Okay, I got fed up by the non-portability of this error message
1062*6777b538SAndroid Build Coastguard Worker  * extraction code. it work on Linux, if it work on your platform
1063*6777b538SAndroid Build Coastguard Worker  * and one want to enable it, send me the defined(foobar) needed
1064*6777b538SAndroid Build Coastguard Worker  */
1065*6777b538SAndroid Build Coastguard Worker #if defined(HAVE_NETDB_H) && defined(HOST_NOT_FOUND) && defined(__linux__)
1066*6777b538SAndroid Build Coastguard Worker 	    const char *h_err_txt = "";
1067*6777b538SAndroid Build Coastguard Worker 
1068*6777b538SAndroid Build Coastguard Worker 	    switch (h_errno) {
1069*6777b538SAndroid Build Coastguard Worker 		case HOST_NOT_FOUND:
1070*6777b538SAndroid Build Coastguard Worker 		    h_err_txt = "Authoritative host not found";
1071*6777b538SAndroid Build Coastguard Worker 		    break;
1072*6777b538SAndroid Build Coastguard Worker 
1073*6777b538SAndroid Build Coastguard Worker 		case TRY_AGAIN:
1074*6777b538SAndroid Build Coastguard Worker 		    h_err_txt =
1075*6777b538SAndroid Build Coastguard Worker 			"Non-authoritative host not found or server failure.";
1076*6777b538SAndroid Build Coastguard Worker 		    break;
1077*6777b538SAndroid Build Coastguard Worker 
1078*6777b538SAndroid Build Coastguard Worker 		case NO_RECOVERY:
1079*6777b538SAndroid Build Coastguard Worker 		    h_err_txt =
1080*6777b538SAndroid Build Coastguard Worker 			"Non-recoverable errors:  FORMERR, REFUSED, or NOTIMP.";
1081*6777b538SAndroid Build Coastguard Worker 		    break;
1082*6777b538SAndroid Build Coastguard Worker 
1083*6777b538SAndroid Build Coastguard Worker #ifdef NO_ADDRESS
1084*6777b538SAndroid Build Coastguard Worker 		case NO_ADDRESS:
1085*6777b538SAndroid Build Coastguard Worker 		    h_err_txt =
1086*6777b538SAndroid Build Coastguard Worker 			"Valid name, no data record of requested type.";
1087*6777b538SAndroid Build Coastguard Worker 		    break;
1088*6777b538SAndroid Build Coastguard Worker #endif
1089*6777b538SAndroid Build Coastguard Worker 
1090*6777b538SAndroid Build Coastguard Worker 		default:
1091*6777b538SAndroid Build Coastguard Worker 		    h_err_txt = "No error text defined.";
1092*6777b538SAndroid Build Coastguard Worker 		    break;
1093*6777b538SAndroid Build Coastguard Worker 	    }
1094*6777b538SAndroid Build Coastguard Worker 	    __xmlIOErr(XML_FROM_HTTP, 0, h_err_txt);
1095*6777b538SAndroid Build Coastguard Worker #else
1096*6777b538SAndroid Build Coastguard Worker 	    __xmlIOErr(XML_FROM_HTTP, 0, "Failed to resolve host");
1097*6777b538SAndroid Build Coastguard Worker #endif
1098*6777b538SAndroid Build Coastguard Worker 	    return INVALID_SOCKET;
1099*6777b538SAndroid Build Coastguard Worker 	}
1100*6777b538SAndroid Build Coastguard Worker 
1101*6777b538SAndroid Build Coastguard Worker 	for (i = 0; h->h_addr_list[i]; i++) {
1102*6777b538SAndroid Build Coastguard Worker 	    if (h->h_addrtype == AF_INET) {
1103*6777b538SAndroid Build Coastguard Worker 		/* A records (IPv4) */
1104*6777b538SAndroid Build Coastguard Worker 		if ((unsigned int) h->h_length > sizeof(ia)) {
1105*6777b538SAndroid Build Coastguard Worker 		    __xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n");
1106*6777b538SAndroid Build Coastguard Worker 		    return INVALID_SOCKET;
1107*6777b538SAndroid Build Coastguard Worker 		}
1108*6777b538SAndroid Build Coastguard Worker 		memcpy (&ia, h->h_addr_list[i], h->h_length);
1109*6777b538SAndroid Build Coastguard Worker 		sockin.sin_family = h->h_addrtype;
1110*6777b538SAndroid Build Coastguard Worker 		sockin.sin_addr = ia;
1111*6777b538SAndroid Build Coastguard Worker 		sockin.sin_port = (unsigned short)htons ((unsigned short)port);
1112*6777b538SAndroid Build Coastguard Worker 		addr = (struct sockaddr *) &sockin;
1113*6777b538SAndroid Build Coastguard Worker 	    } else
1114*6777b538SAndroid Build Coastguard Worker 		break;              /* for */
1115*6777b538SAndroid Build Coastguard Worker 
1116*6777b538SAndroid Build Coastguard Worker 	    s = xmlNanoHTTPConnectAttempt (addr);
1117*6777b538SAndroid Build Coastguard Worker 	    if (s != INVALID_SOCKET)
1118*6777b538SAndroid Build Coastguard Worker 		return (s);
1119*6777b538SAndroid Build Coastguard Worker 	}
1120*6777b538SAndroid Build Coastguard Worker     }
1121*6777b538SAndroid Build Coastguard Worker #endif
1122*6777b538SAndroid Build Coastguard Worker 
1123*6777b538SAndroid Build Coastguard Worker     return INVALID_SOCKET;
1124*6777b538SAndroid Build Coastguard Worker }
1125*6777b538SAndroid Build Coastguard Worker 
1126*6777b538SAndroid Build Coastguard Worker 
1127*6777b538SAndroid Build Coastguard Worker /**
1128*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPOpen:
1129*6777b538SAndroid Build Coastguard Worker  * @URL:  The URL to load
1130*6777b538SAndroid Build Coastguard Worker  * @contentType:  if available the Content-Type information will be
1131*6777b538SAndroid Build Coastguard Worker  *                returned at that location
1132*6777b538SAndroid Build Coastguard Worker  *
1133*6777b538SAndroid Build Coastguard Worker  * This function try to open a connection to the indicated resource
1134*6777b538SAndroid Build Coastguard Worker  * via HTTP GET.
1135*6777b538SAndroid Build Coastguard Worker  *
1136*6777b538SAndroid Build Coastguard Worker  * Returns NULL in case of failure, otherwise a request handler.
1137*6777b538SAndroid Build Coastguard Worker  *     The contentType, if provided must be freed by the caller
1138*6777b538SAndroid Build Coastguard Worker  */
1139*6777b538SAndroid Build Coastguard Worker 
1140*6777b538SAndroid Build Coastguard Worker void*
xmlNanoHTTPOpen(const char * URL,char ** contentType)1141*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPOpen(const char *URL, char **contentType) {
1142*6777b538SAndroid Build Coastguard Worker     if (contentType != NULL) *contentType = NULL;
1143*6777b538SAndroid Build Coastguard Worker     return(xmlNanoHTTPMethod(URL, NULL, NULL, contentType, NULL, 0));
1144*6777b538SAndroid Build Coastguard Worker }
1145*6777b538SAndroid Build Coastguard Worker 
1146*6777b538SAndroid Build Coastguard Worker /**
1147*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPOpenRedir:
1148*6777b538SAndroid Build Coastguard Worker  * @URL:  The URL to load
1149*6777b538SAndroid Build Coastguard Worker  * @contentType:  if available the Content-Type information will be
1150*6777b538SAndroid Build Coastguard Worker  *                returned at that location
1151*6777b538SAndroid Build Coastguard Worker  * @redir: if available the redirected URL will be returned
1152*6777b538SAndroid Build Coastguard Worker  *
1153*6777b538SAndroid Build Coastguard Worker  * This function try to open a connection to the indicated resource
1154*6777b538SAndroid Build Coastguard Worker  * via HTTP GET.
1155*6777b538SAndroid Build Coastguard Worker  *
1156*6777b538SAndroid Build Coastguard Worker  * Returns NULL in case of failure, otherwise a request handler.
1157*6777b538SAndroid Build Coastguard Worker  *     The contentType, if provided must be freed by the caller
1158*6777b538SAndroid Build Coastguard Worker  */
1159*6777b538SAndroid Build Coastguard Worker 
1160*6777b538SAndroid Build Coastguard Worker void*
xmlNanoHTTPOpenRedir(const char * URL,char ** contentType,char ** redir)1161*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPOpenRedir(const char *URL, char **contentType, char **redir) {
1162*6777b538SAndroid Build Coastguard Worker     if (contentType != NULL) *contentType = NULL;
1163*6777b538SAndroid Build Coastguard Worker     if (redir != NULL) *redir = NULL;
1164*6777b538SAndroid Build Coastguard Worker     return(xmlNanoHTTPMethodRedir(URL, NULL, NULL, contentType, redir, NULL,0));
1165*6777b538SAndroid Build Coastguard Worker }
1166*6777b538SAndroid Build Coastguard Worker 
1167*6777b538SAndroid Build Coastguard Worker /**
1168*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPRead:
1169*6777b538SAndroid Build Coastguard Worker  * @ctx:  the HTTP context
1170*6777b538SAndroid Build Coastguard Worker  * @dest:  a buffer
1171*6777b538SAndroid Build Coastguard Worker  * @len:  the buffer length
1172*6777b538SAndroid Build Coastguard Worker  *
1173*6777b538SAndroid Build Coastguard Worker  * This function tries to read @len bytes from the existing HTTP connection
1174*6777b538SAndroid Build Coastguard Worker  * and saves them in @dest. This is a blocking call.
1175*6777b538SAndroid Build Coastguard Worker  *
1176*6777b538SAndroid Build Coastguard Worker  * Returns the number of byte read. 0 is an indication of an end of connection.
1177*6777b538SAndroid Build Coastguard Worker  *         -1 indicates a parameter error.
1178*6777b538SAndroid Build Coastguard Worker  */
1179*6777b538SAndroid Build Coastguard Worker int
xmlNanoHTTPRead(void * ctx,void * dest,int len)1180*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPRead(void *ctx, void *dest, int len) {
1181*6777b538SAndroid Build Coastguard Worker     xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr) ctx;
1182*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_ZLIB_ENABLED
1183*6777b538SAndroid Build Coastguard Worker     int bytes_read = 0;
1184*6777b538SAndroid Build Coastguard Worker     int orig_avail_in;
1185*6777b538SAndroid Build Coastguard Worker     int z_ret;
1186*6777b538SAndroid Build Coastguard Worker #endif
1187*6777b538SAndroid Build Coastguard Worker 
1188*6777b538SAndroid Build Coastguard Worker     if (ctx == NULL) return(-1);
1189*6777b538SAndroid Build Coastguard Worker     if (dest == NULL) return(-1);
1190*6777b538SAndroid Build Coastguard Worker     if (len <= 0) return(0);
1191*6777b538SAndroid Build Coastguard Worker 
1192*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_ZLIB_ENABLED
1193*6777b538SAndroid Build Coastguard Worker     if (ctxt->usesGzip == 1) {
1194*6777b538SAndroid Build Coastguard Worker         if (ctxt->strm == NULL) return(0);
1195*6777b538SAndroid Build Coastguard Worker 
1196*6777b538SAndroid Build Coastguard Worker         ctxt->strm->next_out = dest;
1197*6777b538SAndroid Build Coastguard Worker         ctxt->strm->avail_out = len;
1198*6777b538SAndroid Build Coastguard Worker 	ctxt->strm->avail_in = ctxt->inptr - ctxt->inrptr;
1199*6777b538SAndroid Build Coastguard Worker 
1200*6777b538SAndroid Build Coastguard Worker         while (ctxt->strm->avail_out > 0 &&
1201*6777b538SAndroid Build Coastguard Worker 	       (ctxt->strm->avail_in > 0 || xmlNanoHTTPRecv(ctxt) > 0)) {
1202*6777b538SAndroid Build Coastguard Worker             orig_avail_in = ctxt->strm->avail_in =
1203*6777b538SAndroid Build Coastguard Worker 			    ctxt->inptr - ctxt->inrptr - bytes_read;
1204*6777b538SAndroid Build Coastguard Worker             ctxt->strm->next_in = BAD_CAST (ctxt->inrptr + bytes_read);
1205*6777b538SAndroid Build Coastguard Worker 
1206*6777b538SAndroid Build Coastguard Worker             z_ret = inflate(ctxt->strm, Z_NO_FLUSH);
1207*6777b538SAndroid Build Coastguard Worker             bytes_read += orig_avail_in - ctxt->strm->avail_in;
1208*6777b538SAndroid Build Coastguard Worker 
1209*6777b538SAndroid Build Coastguard Worker             if (z_ret != Z_OK) break;
1210*6777b538SAndroid Build Coastguard Worker 	}
1211*6777b538SAndroid Build Coastguard Worker 
1212*6777b538SAndroid Build Coastguard Worker         ctxt->inrptr += bytes_read;
1213*6777b538SAndroid Build Coastguard Worker         return(len - ctxt->strm->avail_out);
1214*6777b538SAndroid Build Coastguard Worker     }
1215*6777b538SAndroid Build Coastguard Worker #endif
1216*6777b538SAndroid Build Coastguard Worker 
1217*6777b538SAndroid Build Coastguard Worker     while (ctxt->inptr - ctxt->inrptr < len) {
1218*6777b538SAndroid Build Coastguard Worker         if (xmlNanoHTTPRecv(ctxt) <= 0) break;
1219*6777b538SAndroid Build Coastguard Worker     }
1220*6777b538SAndroid Build Coastguard Worker     if (ctxt->inptr - ctxt->inrptr < len)
1221*6777b538SAndroid Build Coastguard Worker         len = ctxt->inptr - ctxt->inrptr;
1222*6777b538SAndroid Build Coastguard Worker     memcpy(dest, ctxt->inrptr, len);
1223*6777b538SAndroid Build Coastguard Worker     ctxt->inrptr += len;
1224*6777b538SAndroid Build Coastguard Worker     return(len);
1225*6777b538SAndroid Build Coastguard Worker }
1226*6777b538SAndroid Build Coastguard Worker 
1227*6777b538SAndroid Build Coastguard Worker /**
1228*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPClose:
1229*6777b538SAndroid Build Coastguard Worker  * @ctx:  the HTTP context
1230*6777b538SAndroid Build Coastguard Worker  *
1231*6777b538SAndroid Build Coastguard Worker  * This function closes an HTTP context, it ends up the connection and
1232*6777b538SAndroid Build Coastguard Worker  * free all data related to it.
1233*6777b538SAndroid Build Coastguard Worker  */
1234*6777b538SAndroid Build Coastguard Worker void
xmlNanoHTTPClose(void * ctx)1235*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPClose(void *ctx) {
1236*6777b538SAndroid Build Coastguard Worker     xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr) ctx;
1237*6777b538SAndroid Build Coastguard Worker 
1238*6777b538SAndroid Build Coastguard Worker     if (ctx == NULL) return;
1239*6777b538SAndroid Build Coastguard Worker 
1240*6777b538SAndroid Build Coastguard Worker     xmlNanoHTTPFreeCtxt(ctxt);
1241*6777b538SAndroid Build Coastguard Worker }
1242*6777b538SAndroid Build Coastguard Worker 
1243*6777b538SAndroid Build Coastguard Worker 
1244*6777b538SAndroid Build Coastguard Worker /**
1245*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPHostnameMatch:
1246*6777b538SAndroid Build Coastguard Worker  * @pattern: The pattern as it appears in no_proxy environment variable
1247*6777b538SAndroid Build Coastguard Worker  * @hostname: The hostname to test as it appears in the URL
1248*6777b538SAndroid Build Coastguard Worker  *
1249*6777b538SAndroid Build Coastguard Worker  * This function tests whether a given hostname matches a pattern. The pattern
1250*6777b538SAndroid Build Coastguard Worker  * usually is a token from the no_proxy environment variable. Wildcards in the
1251*6777b538SAndroid Build Coastguard Worker  * pattern are not supported.
1252*6777b538SAndroid Build Coastguard Worker  *
1253*6777b538SAndroid Build Coastguard Worker  * Returns true, iff hostname matches the pattern.
1254*6777b538SAndroid Build Coastguard Worker  */
1255*6777b538SAndroid Build Coastguard Worker 
1256*6777b538SAndroid Build Coastguard Worker static int
xmlNanoHTTPHostnameMatch(const char * pattern,const char * hostname)1257*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPHostnameMatch(const char *pattern, const char *hostname) {
1258*6777b538SAndroid Build Coastguard Worker     int idx_pattern, idx_hostname;
1259*6777b538SAndroid Build Coastguard Worker     const char * pattern_start;
1260*6777b538SAndroid Build Coastguard Worker 
1261*6777b538SAndroid Build Coastguard Worker     if (!pattern || *pattern == '\0' || !hostname)
1262*6777b538SAndroid Build Coastguard Worker 	return 0;
1263*6777b538SAndroid Build Coastguard Worker 
1264*6777b538SAndroid Build Coastguard Worker     /* Ignore trailing '.' */
1265*6777b538SAndroid Build Coastguard Worker     if (*pattern == '.') {
1266*6777b538SAndroid Build Coastguard Worker         idx_pattern = strlen(pattern) -1;
1267*6777b538SAndroid Build Coastguard Worker         pattern_start = pattern + 1;
1268*6777b538SAndroid Build Coastguard Worker     }
1269*6777b538SAndroid Build Coastguard Worker     else {
1270*6777b538SAndroid Build Coastguard Worker         idx_pattern = strlen(pattern);
1271*6777b538SAndroid Build Coastguard Worker         pattern_start = pattern;
1272*6777b538SAndroid Build Coastguard Worker     }
1273*6777b538SAndroid Build Coastguard Worker     idx_hostname = strlen(hostname);
1274*6777b538SAndroid Build Coastguard Worker 
1275*6777b538SAndroid Build Coastguard Worker     for (; idx_pattern >= 0 && idx_hostname >= 0;
1276*6777b538SAndroid Build Coastguard Worker            --idx_pattern, --idx_hostname) {
1277*6777b538SAndroid Build Coastguard Worker 	if (tolower(pattern_start[idx_pattern]) != tolower(hostname[idx_hostname]))
1278*6777b538SAndroid Build Coastguard Worker 	    break;
1279*6777b538SAndroid Build Coastguard Worker     }
1280*6777b538SAndroid Build Coastguard Worker 
1281*6777b538SAndroid Build Coastguard Worker     return idx_pattern == -1 && (idx_hostname == -1|| hostname[idx_hostname] == '.');
1282*6777b538SAndroid Build Coastguard Worker }
1283*6777b538SAndroid Build Coastguard Worker 
1284*6777b538SAndroid Build Coastguard Worker 
1285*6777b538SAndroid Build Coastguard Worker /**
1286*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPBypassProxy:
1287*6777b538SAndroid Build Coastguard Worker  * @hostname: The hostname as it appears in the URL
1288*6777b538SAndroid Build Coastguard Worker  *
1289*6777b538SAndroid Build Coastguard Worker  * This function evaluates the no_proxy environment variable and returns
1290*6777b538SAndroid Build Coastguard Worker  * whether the proxy server should be bypassed for a given host.
1291*6777b538SAndroid Build Coastguard Worker  *
1292*6777b538SAndroid Build Coastguard Worker  * Returns true, iff a proxy server should be bypassed for the given hostname.
1293*6777b538SAndroid Build Coastguard Worker  */
1294*6777b538SAndroid Build Coastguard Worker 
1295*6777b538SAndroid Build Coastguard Worker static int
xmlNanoHTTPBypassProxy(const char * hostname)1296*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPBypassProxy(const char *hostname) {
1297*6777b538SAndroid Build Coastguard Worker     size_t envlen;
1298*6777b538SAndroid Build Coastguard Worker     char *env = getenv("no_proxy"), *cpy=NULL, *p=NULL;
1299*6777b538SAndroid Build Coastguard Worker     if (!env)
1300*6777b538SAndroid Build Coastguard Worker 	return 0;
1301*6777b538SAndroid Build Coastguard Worker 
1302*6777b538SAndroid Build Coastguard Worker     /* (Avoid strdup because it's not portable.) */
1303*6777b538SAndroid Build Coastguard Worker     envlen = strlen(env) + 1;
1304*6777b538SAndroid Build Coastguard Worker     cpy = xmlMalloc(envlen);
1305*6777b538SAndroid Build Coastguard Worker     memcpy(cpy, env, envlen);
1306*6777b538SAndroid Build Coastguard Worker     env = cpy;
1307*6777b538SAndroid Build Coastguard Worker 
1308*6777b538SAndroid Build Coastguard Worker     /* The remainder of the function is basically a tokenizing: */
1309*6777b538SAndroid Build Coastguard Worker     while (isspace(*env))
1310*6777b538SAndroid Build Coastguard Worker     	++env;
1311*6777b538SAndroid Build Coastguard Worker     if (*env == '\0') {
1312*6777b538SAndroid Build Coastguard Worker     	xmlFree(cpy);
1313*6777b538SAndroid Build Coastguard Worker 	return 0;
1314*6777b538SAndroid Build Coastguard Worker     }
1315*6777b538SAndroid Build Coastguard Worker 
1316*6777b538SAndroid Build Coastguard Worker     p = env;
1317*6777b538SAndroid Build Coastguard Worker     while (*env) {
1318*6777b538SAndroid Build Coastguard Worker 
1319*6777b538SAndroid Build Coastguard Worker     	if (*env != ',') {
1320*6777b538SAndroid Build Coastguard Worker 	    ++env;
1321*6777b538SAndroid Build Coastguard Worker 	    continue;
1322*6777b538SAndroid Build Coastguard Worker 	}
1323*6777b538SAndroid Build Coastguard Worker 
1324*6777b538SAndroid Build Coastguard Worker 	*(env++) = '\0';
1325*6777b538SAndroid Build Coastguard Worker 	if (xmlNanoHTTPHostnameMatch(p, hostname)) {
1326*6777b538SAndroid Build Coastguard Worker 	    xmlFree(cpy);
1327*6777b538SAndroid Build Coastguard Worker 	    return 1;
1328*6777b538SAndroid Build Coastguard Worker 	}
1329*6777b538SAndroid Build Coastguard Worker 
1330*6777b538SAndroid Build Coastguard Worker 	while (isspace(*env))
1331*6777b538SAndroid Build Coastguard Worker 	    ++env;
1332*6777b538SAndroid Build Coastguard Worker 	p = env;
1333*6777b538SAndroid Build Coastguard Worker     }
1334*6777b538SAndroid Build Coastguard Worker     if (xmlNanoHTTPHostnameMatch(p, hostname)) {
1335*6777b538SAndroid Build Coastguard Worker     	xmlFree(cpy);
1336*6777b538SAndroid Build Coastguard Worker     	return 1;
1337*6777b538SAndroid Build Coastguard Worker     }
1338*6777b538SAndroid Build Coastguard Worker 
1339*6777b538SAndroid Build Coastguard Worker     xmlFree(cpy);
1340*6777b538SAndroid Build Coastguard Worker     return 0;
1341*6777b538SAndroid Build Coastguard Worker }
1342*6777b538SAndroid Build Coastguard Worker 
1343*6777b538SAndroid Build Coastguard Worker 
1344*6777b538SAndroid Build Coastguard Worker /**
1345*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPMethodRedir:
1346*6777b538SAndroid Build Coastguard Worker  * @URL:  The URL to load
1347*6777b538SAndroid Build Coastguard Worker  * @method:  the HTTP method to use
1348*6777b538SAndroid Build Coastguard Worker  * @input:  the input string if any
1349*6777b538SAndroid Build Coastguard Worker  * @contentType:  the Content-Type information IN and OUT
1350*6777b538SAndroid Build Coastguard Worker  * @redir:  the redirected URL OUT
1351*6777b538SAndroid Build Coastguard Worker  * @headers:  the extra headers
1352*6777b538SAndroid Build Coastguard Worker  * @ilen:  input length
1353*6777b538SAndroid Build Coastguard Worker  *
1354*6777b538SAndroid Build Coastguard Worker  * This function try to open a connection to the indicated resource
1355*6777b538SAndroid Build Coastguard Worker  * via HTTP using the given @method, adding the given extra headers
1356*6777b538SAndroid Build Coastguard Worker  * and the input buffer for the request content.
1357*6777b538SAndroid Build Coastguard Worker  *
1358*6777b538SAndroid Build Coastguard Worker  * Returns NULL in case of failure, otherwise a request handler.
1359*6777b538SAndroid Build Coastguard Worker  *     The contentType, or redir, if provided must be freed by the caller
1360*6777b538SAndroid Build Coastguard Worker  */
1361*6777b538SAndroid Build Coastguard Worker 
1362*6777b538SAndroid Build Coastguard Worker void*
xmlNanoHTTPMethodRedir(const char * URL,const char * method,const char * input,char ** contentType,char ** redir,const char * headers,int ilen)1363*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPMethodRedir(const char *URL, const char *method, const char *input,
1364*6777b538SAndroid Build Coastguard Worker                   char **contentType, char **redir,
1365*6777b538SAndroid Build Coastguard Worker 		  const char *headers, int ilen ) {
1366*6777b538SAndroid Build Coastguard Worker     xmlNanoHTTPCtxtPtr ctxt;
1367*6777b538SAndroid Build Coastguard Worker     char *bp, *p;
1368*6777b538SAndroid Build Coastguard Worker     int blen;
1369*6777b538SAndroid Build Coastguard Worker     SOCKET ret;
1370*6777b538SAndroid Build Coastguard Worker     int nbRedirects = 0;
1371*6777b538SAndroid Build Coastguard Worker     int use_proxy;
1372*6777b538SAndroid Build Coastguard Worker     char *redirURL = NULL;
1373*6777b538SAndroid Build Coastguard Worker 
1374*6777b538SAndroid Build Coastguard Worker     if (URL == NULL) return(NULL);
1375*6777b538SAndroid Build Coastguard Worker     if (method == NULL) method = "GET";
1376*6777b538SAndroid Build Coastguard Worker     xmlNanoHTTPInit();
1377*6777b538SAndroid Build Coastguard Worker 
1378*6777b538SAndroid Build Coastguard Worker retry:
1379*6777b538SAndroid Build Coastguard Worker     if (redirURL == NULL) {
1380*6777b538SAndroid Build Coastguard Worker 	ctxt = xmlNanoHTTPNewCtxt(URL);
1381*6777b538SAndroid Build Coastguard Worker 	if (ctxt == NULL)
1382*6777b538SAndroid Build Coastguard Worker 	    return(NULL);
1383*6777b538SAndroid Build Coastguard Worker     } else {
1384*6777b538SAndroid Build Coastguard Worker 	ctxt = xmlNanoHTTPNewCtxt(redirURL);
1385*6777b538SAndroid Build Coastguard Worker 	if (ctxt == NULL)
1386*6777b538SAndroid Build Coastguard Worker 	    return(NULL);
1387*6777b538SAndroid Build Coastguard Worker 	ctxt->location = xmlMemStrdup(redirURL);
1388*6777b538SAndroid Build Coastguard Worker     }
1389*6777b538SAndroid Build Coastguard Worker 
1390*6777b538SAndroid Build Coastguard Worker     if ((ctxt->protocol == NULL) || (strcmp(ctxt->protocol, "http"))) {
1391*6777b538SAndroid Build Coastguard Worker 	__xmlIOErr(XML_FROM_HTTP, XML_HTTP_URL_SYNTAX, "Not a valid HTTP URI");
1392*6777b538SAndroid Build Coastguard Worker         xmlNanoHTTPFreeCtxt(ctxt);
1393*6777b538SAndroid Build Coastguard Worker 	if (redirURL != NULL) xmlFree(redirURL);
1394*6777b538SAndroid Build Coastguard Worker         return(NULL);
1395*6777b538SAndroid Build Coastguard Worker     }
1396*6777b538SAndroid Build Coastguard Worker     if (ctxt->hostname == NULL) {
1397*6777b538SAndroid Build Coastguard Worker 	__xmlIOErr(XML_FROM_HTTP, XML_HTTP_UNKNOWN_HOST,
1398*6777b538SAndroid Build Coastguard Worker 	           "Failed to identify host in URI");
1399*6777b538SAndroid Build Coastguard Worker         xmlNanoHTTPFreeCtxt(ctxt);
1400*6777b538SAndroid Build Coastguard Worker 	if (redirURL != NULL) xmlFree(redirURL);
1401*6777b538SAndroid Build Coastguard Worker         return(NULL);
1402*6777b538SAndroid Build Coastguard Worker     }
1403*6777b538SAndroid Build Coastguard Worker     use_proxy = proxy && !xmlNanoHTTPBypassProxy(ctxt->hostname);
1404*6777b538SAndroid Build Coastguard Worker     if (use_proxy) {
1405*6777b538SAndroid Build Coastguard Worker 	blen = strlen(ctxt->hostname) * 2 + 16;
1406*6777b538SAndroid Build Coastguard Worker 	ret = xmlNanoHTTPConnectHost(proxy, proxyPort);
1407*6777b538SAndroid Build Coastguard Worker     }
1408*6777b538SAndroid Build Coastguard Worker     else {
1409*6777b538SAndroid Build Coastguard Worker 	blen = strlen(ctxt->hostname);
1410*6777b538SAndroid Build Coastguard Worker 	ret = xmlNanoHTTPConnectHost(ctxt->hostname, ctxt->port);
1411*6777b538SAndroid Build Coastguard Worker     }
1412*6777b538SAndroid Build Coastguard Worker     if (ret == INVALID_SOCKET) {
1413*6777b538SAndroid Build Coastguard Worker         xmlNanoHTTPFreeCtxt(ctxt);
1414*6777b538SAndroid Build Coastguard Worker 	if (redirURL != NULL) xmlFree(redirURL);
1415*6777b538SAndroid Build Coastguard Worker         return(NULL);
1416*6777b538SAndroid Build Coastguard Worker     }
1417*6777b538SAndroid Build Coastguard Worker     ctxt->fd = ret;
1418*6777b538SAndroid Build Coastguard Worker 
1419*6777b538SAndroid Build Coastguard Worker     if (input == NULL)
1420*6777b538SAndroid Build Coastguard Worker 	ilen = 0;
1421*6777b538SAndroid Build Coastguard Worker     else
1422*6777b538SAndroid Build Coastguard Worker 	blen += 36;
1423*6777b538SAndroid Build Coastguard Worker 
1424*6777b538SAndroid Build Coastguard Worker     if (headers != NULL)
1425*6777b538SAndroid Build Coastguard Worker 	blen += strlen(headers) + 2;
1426*6777b538SAndroid Build Coastguard Worker     if (contentType && *contentType)
1427*6777b538SAndroid Build Coastguard Worker 	/* reserve for string plus 'Content-Type: \r\n" */
1428*6777b538SAndroid Build Coastguard Worker 	blen += strlen(*contentType) + 16;
1429*6777b538SAndroid Build Coastguard Worker     if (ctxt->query != NULL)
1430*6777b538SAndroid Build Coastguard Worker 	/* 1 for '?' */
1431*6777b538SAndroid Build Coastguard Worker 	blen += strlen(ctxt->query) + 1;
1432*6777b538SAndroid Build Coastguard Worker     blen += strlen(method) + strlen(ctxt->path) + 24;
1433*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_ZLIB_ENABLED
1434*6777b538SAndroid Build Coastguard Worker     /* reserve for possible 'Accept-Encoding: gzip' string */
1435*6777b538SAndroid Build Coastguard Worker     blen += 23;
1436*6777b538SAndroid Build Coastguard Worker #endif
1437*6777b538SAndroid Build Coastguard Worker     if (ctxt->port != 80) {
1438*6777b538SAndroid Build Coastguard Worker 	/* reserve space for ':xxxxx', incl. potential proxy */
1439*6777b538SAndroid Build Coastguard Worker 	if (use_proxy)
1440*6777b538SAndroid Build Coastguard Worker 	    blen += 17;
1441*6777b538SAndroid Build Coastguard Worker 	else
1442*6777b538SAndroid Build Coastguard Worker 	    blen += 11;
1443*6777b538SAndroid Build Coastguard Worker     }
1444*6777b538SAndroid Build Coastguard Worker     bp = (char*)xmlMallocAtomic(blen);
1445*6777b538SAndroid Build Coastguard Worker     if ( bp == NULL ) {
1446*6777b538SAndroid Build Coastguard Worker         xmlNanoHTTPFreeCtxt( ctxt );
1447*6777b538SAndroid Build Coastguard Worker 	xmlHTTPErrMemory();
1448*6777b538SAndroid Build Coastguard Worker 	return ( NULL );
1449*6777b538SAndroid Build Coastguard Worker     }
1450*6777b538SAndroid Build Coastguard Worker 
1451*6777b538SAndroid Build Coastguard Worker     p = bp;
1452*6777b538SAndroid Build Coastguard Worker 
1453*6777b538SAndroid Build Coastguard Worker     if (use_proxy) {
1454*6777b538SAndroid Build Coastguard Worker 	if (ctxt->port != 80) {
1455*6777b538SAndroid Build Coastguard Worker 	    p += snprintf( p, blen - (p - bp), "%s http://%s:%d%s",
1456*6777b538SAndroid Build Coastguard Worker 			method, ctxt->hostname,
1457*6777b538SAndroid Build Coastguard Worker 			ctxt->port, ctxt->path );
1458*6777b538SAndroid Build Coastguard Worker 	}
1459*6777b538SAndroid Build Coastguard Worker 	else
1460*6777b538SAndroid Build Coastguard Worker 	    p += snprintf( p, blen - (p - bp), "%s http://%s%s", method,
1461*6777b538SAndroid Build Coastguard Worker 			ctxt->hostname, ctxt->path);
1462*6777b538SAndroid Build Coastguard Worker     }
1463*6777b538SAndroid Build Coastguard Worker     else
1464*6777b538SAndroid Build Coastguard Worker 	p += snprintf( p, blen - (p - bp), "%s %s", method, ctxt->path);
1465*6777b538SAndroid Build Coastguard Worker 
1466*6777b538SAndroid Build Coastguard Worker     if (ctxt->query != NULL)
1467*6777b538SAndroid Build Coastguard Worker 	p += snprintf( p, blen - (p - bp), "?%s", ctxt->query);
1468*6777b538SAndroid Build Coastguard Worker 
1469*6777b538SAndroid Build Coastguard Worker     if (ctxt->port == 80) {
1470*6777b538SAndroid Build Coastguard Worker         p += snprintf( p, blen - (p - bp), " HTTP/1.0\r\nHost: %s\r\n",
1471*6777b538SAndroid Build Coastguard Worker 		    ctxt->hostname);
1472*6777b538SAndroid Build Coastguard Worker     } else {
1473*6777b538SAndroid Build Coastguard Worker         p += snprintf( p, blen - (p - bp), " HTTP/1.0\r\nHost: %s:%d\r\n",
1474*6777b538SAndroid Build Coastguard Worker 		    ctxt->hostname, ctxt->port);
1475*6777b538SAndroid Build Coastguard Worker     }
1476*6777b538SAndroid Build Coastguard Worker 
1477*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_ZLIB_ENABLED
1478*6777b538SAndroid Build Coastguard Worker     p += snprintf(p, blen - (p - bp), "Accept-Encoding: gzip\r\n");
1479*6777b538SAndroid Build Coastguard Worker #endif
1480*6777b538SAndroid Build Coastguard Worker 
1481*6777b538SAndroid Build Coastguard Worker     if (contentType != NULL && *contentType)
1482*6777b538SAndroid Build Coastguard Worker 	p += snprintf(p, blen - (p - bp), "Content-Type: %s\r\n", *contentType);
1483*6777b538SAndroid Build Coastguard Worker 
1484*6777b538SAndroid Build Coastguard Worker     if (headers != NULL)
1485*6777b538SAndroid Build Coastguard Worker 	p += snprintf( p, blen - (p - bp), "%s", headers );
1486*6777b538SAndroid Build Coastguard Worker 
1487*6777b538SAndroid Build Coastguard Worker     if (input != NULL)
1488*6777b538SAndroid Build Coastguard Worker 	snprintf(p, blen - (p - bp), "Content-Length: %d\r\n\r\n", ilen );
1489*6777b538SAndroid Build Coastguard Worker     else
1490*6777b538SAndroid Build Coastguard Worker 	snprintf(p, blen - (p - bp), "\r\n");
1491*6777b538SAndroid Build Coastguard Worker 
1492*6777b538SAndroid Build Coastguard Worker     ctxt->outptr = ctxt->out = bp;
1493*6777b538SAndroid Build Coastguard Worker     ctxt->state = XML_NANO_HTTP_WRITE;
1494*6777b538SAndroid Build Coastguard Worker     blen = strlen( ctxt->out );
1495*6777b538SAndroid Build Coastguard Worker     xmlNanoHTTPSend(ctxt, ctxt->out, blen );
1496*6777b538SAndroid Build Coastguard Worker 
1497*6777b538SAndroid Build Coastguard Worker     if ( input != NULL ) {
1498*6777b538SAndroid Build Coastguard Worker 	xmlNanoHTTPSend( ctxt, input, ilen );
1499*6777b538SAndroid Build Coastguard Worker     }
1500*6777b538SAndroid Build Coastguard Worker 
1501*6777b538SAndroid Build Coastguard Worker     ctxt->state = XML_NANO_HTTP_READ;
1502*6777b538SAndroid Build Coastguard Worker 
1503*6777b538SAndroid Build Coastguard Worker     while ((p = xmlNanoHTTPReadLine(ctxt)) != NULL) {
1504*6777b538SAndroid Build Coastguard Worker         if (*p == 0) {
1505*6777b538SAndroid Build Coastguard Worker 	    ctxt->content = ctxt->inrptr;
1506*6777b538SAndroid Build Coastguard Worker 	    xmlFree(p);
1507*6777b538SAndroid Build Coastguard Worker 	    break;
1508*6777b538SAndroid Build Coastguard Worker 	}
1509*6777b538SAndroid Build Coastguard Worker 	xmlNanoHTTPScanAnswer(ctxt, p);
1510*6777b538SAndroid Build Coastguard Worker 
1511*6777b538SAndroid Build Coastguard Worker         xmlFree(p);
1512*6777b538SAndroid Build Coastguard Worker     }
1513*6777b538SAndroid Build Coastguard Worker 
1514*6777b538SAndroid Build Coastguard Worker     if ((ctxt->location != NULL) && (ctxt->returnValue >= 300) &&
1515*6777b538SAndroid Build Coastguard Worker         (ctxt->returnValue < 400)) {
1516*6777b538SAndroid Build Coastguard Worker 	while ( xmlNanoHTTPRecv(ctxt) > 0 )
1517*6777b538SAndroid Build Coastguard Worker             ;
1518*6777b538SAndroid Build Coastguard Worker         if (nbRedirects < XML_NANO_HTTP_MAX_REDIR) {
1519*6777b538SAndroid Build Coastguard Worker 	    nbRedirects++;
1520*6777b538SAndroid Build Coastguard Worker 	    if (redirURL != NULL)
1521*6777b538SAndroid Build Coastguard Worker 		xmlFree(redirURL);
1522*6777b538SAndroid Build Coastguard Worker 	    redirURL = xmlMemStrdup(ctxt->location);
1523*6777b538SAndroid Build Coastguard Worker 	    xmlNanoHTTPFreeCtxt(ctxt);
1524*6777b538SAndroid Build Coastguard Worker 	    goto retry;
1525*6777b538SAndroid Build Coastguard Worker 	}
1526*6777b538SAndroid Build Coastguard Worker 	xmlNanoHTTPFreeCtxt(ctxt);
1527*6777b538SAndroid Build Coastguard Worker 	if (redirURL != NULL) xmlFree(redirURL);
1528*6777b538SAndroid Build Coastguard Worker 	return(NULL);
1529*6777b538SAndroid Build Coastguard Worker     }
1530*6777b538SAndroid Build Coastguard Worker 
1531*6777b538SAndroid Build Coastguard Worker     if (contentType != NULL) {
1532*6777b538SAndroid Build Coastguard Worker 	if (ctxt->contentType != NULL)
1533*6777b538SAndroid Build Coastguard Worker 	    *contentType = xmlMemStrdup(ctxt->contentType);
1534*6777b538SAndroid Build Coastguard Worker 	else
1535*6777b538SAndroid Build Coastguard Worker 	    *contentType = NULL;
1536*6777b538SAndroid Build Coastguard Worker     }
1537*6777b538SAndroid Build Coastguard Worker 
1538*6777b538SAndroid Build Coastguard Worker     if ((redir != NULL) && (redirURL != NULL)) {
1539*6777b538SAndroid Build Coastguard Worker 	*redir = redirURL;
1540*6777b538SAndroid Build Coastguard Worker     } else {
1541*6777b538SAndroid Build Coastguard Worker 	if (redirURL != NULL)
1542*6777b538SAndroid Build Coastguard Worker 	    xmlFree(redirURL);
1543*6777b538SAndroid Build Coastguard Worker 	if (redir != NULL)
1544*6777b538SAndroid Build Coastguard Worker 	    *redir = NULL;
1545*6777b538SAndroid Build Coastguard Worker     }
1546*6777b538SAndroid Build Coastguard Worker 
1547*6777b538SAndroid Build Coastguard Worker     return((void *) ctxt);
1548*6777b538SAndroid Build Coastguard Worker }
1549*6777b538SAndroid Build Coastguard Worker 
1550*6777b538SAndroid Build Coastguard Worker /**
1551*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPMethod:
1552*6777b538SAndroid Build Coastguard Worker  * @URL:  The URL to load
1553*6777b538SAndroid Build Coastguard Worker  * @method:  the HTTP method to use
1554*6777b538SAndroid Build Coastguard Worker  * @input:  the input string if any
1555*6777b538SAndroid Build Coastguard Worker  * @contentType:  the Content-Type information IN and OUT
1556*6777b538SAndroid Build Coastguard Worker  * @headers:  the extra headers
1557*6777b538SAndroid Build Coastguard Worker  * @ilen:  input length
1558*6777b538SAndroid Build Coastguard Worker  *
1559*6777b538SAndroid Build Coastguard Worker  * This function try to open a connection to the indicated resource
1560*6777b538SAndroid Build Coastguard Worker  * via HTTP using the given @method, adding the given extra headers
1561*6777b538SAndroid Build Coastguard Worker  * and the input buffer for the request content.
1562*6777b538SAndroid Build Coastguard Worker  *
1563*6777b538SAndroid Build Coastguard Worker  * Returns NULL in case of failure, otherwise a request handler.
1564*6777b538SAndroid Build Coastguard Worker  *     The contentType, if provided must be freed by the caller
1565*6777b538SAndroid Build Coastguard Worker  */
1566*6777b538SAndroid Build Coastguard Worker 
1567*6777b538SAndroid Build Coastguard Worker void*
xmlNanoHTTPMethod(const char * URL,const char * method,const char * input,char ** contentType,const char * headers,int ilen)1568*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPMethod(const char *URL, const char *method, const char *input,
1569*6777b538SAndroid Build Coastguard Worker                   char **contentType, const char *headers, int ilen) {
1570*6777b538SAndroid Build Coastguard Worker     return(xmlNanoHTTPMethodRedir(URL, method, input, contentType,
1571*6777b538SAndroid Build Coastguard Worker 		                  NULL, headers, ilen));
1572*6777b538SAndroid Build Coastguard Worker }
1573*6777b538SAndroid Build Coastguard Worker 
1574*6777b538SAndroid Build Coastguard Worker /**
1575*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPFetch:
1576*6777b538SAndroid Build Coastguard Worker  * @URL:  The URL to load
1577*6777b538SAndroid Build Coastguard Worker  * @filename:  the filename where the content should be saved
1578*6777b538SAndroid Build Coastguard Worker  * @contentType:  if available the Content-Type information will be
1579*6777b538SAndroid Build Coastguard Worker  *                returned at that location
1580*6777b538SAndroid Build Coastguard Worker  *
1581*6777b538SAndroid Build Coastguard Worker  * This function try to fetch the indicated resource via HTTP GET
1582*6777b538SAndroid Build Coastguard Worker  * and save it's content in the file.
1583*6777b538SAndroid Build Coastguard Worker  *
1584*6777b538SAndroid Build Coastguard Worker  * Returns -1 in case of failure, 0 in case of success. The contentType,
1585*6777b538SAndroid Build Coastguard Worker  *     if provided must be freed by the caller
1586*6777b538SAndroid Build Coastguard Worker  */
1587*6777b538SAndroid Build Coastguard Worker int
xmlNanoHTTPFetch(const char * URL,const char * filename,char ** contentType)1588*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPFetch(const char *URL, const char *filename, char **contentType) {
1589*6777b538SAndroid Build Coastguard Worker     void *ctxt = NULL;
1590*6777b538SAndroid Build Coastguard Worker     char *buf = NULL;
1591*6777b538SAndroid Build Coastguard Worker     int fd;
1592*6777b538SAndroid Build Coastguard Worker     int len;
1593*6777b538SAndroid Build Coastguard Worker     int ret = 0;
1594*6777b538SAndroid Build Coastguard Worker 
1595*6777b538SAndroid Build Coastguard Worker     if (filename == NULL) return(-1);
1596*6777b538SAndroid Build Coastguard Worker     ctxt = xmlNanoHTTPOpen(URL, contentType);
1597*6777b538SAndroid Build Coastguard Worker     if (ctxt == NULL) return(-1);
1598*6777b538SAndroid Build Coastguard Worker 
1599*6777b538SAndroid Build Coastguard Worker     if (!strcmp(filename, "-"))
1600*6777b538SAndroid Build Coastguard Worker         fd = 0;
1601*6777b538SAndroid Build Coastguard Worker     else {
1602*6777b538SAndroid Build Coastguard Worker         fd = open(filename, O_CREAT | O_WRONLY, 00644);
1603*6777b538SAndroid Build Coastguard Worker 	if (fd < 0) {
1604*6777b538SAndroid Build Coastguard Worker 	    xmlNanoHTTPClose(ctxt);
1605*6777b538SAndroid Build Coastguard Worker 	    if ((contentType != NULL) && (*contentType != NULL)) {
1606*6777b538SAndroid Build Coastguard Worker 	        xmlFree(*contentType);
1607*6777b538SAndroid Build Coastguard Worker 		*contentType = NULL;
1608*6777b538SAndroid Build Coastguard Worker 	    }
1609*6777b538SAndroid Build Coastguard Worker 	    return(-1);
1610*6777b538SAndroid Build Coastguard Worker 	}
1611*6777b538SAndroid Build Coastguard Worker     }
1612*6777b538SAndroid Build Coastguard Worker 
1613*6777b538SAndroid Build Coastguard Worker     xmlNanoHTTPFetchContent( ctxt, &buf, &len );
1614*6777b538SAndroid Build Coastguard Worker     if ( len > 0 ) {
1615*6777b538SAndroid Build Coastguard Worker 	if (write(fd, buf, len) == -1) {
1616*6777b538SAndroid Build Coastguard Worker 	    ret = -1;
1617*6777b538SAndroid Build Coastguard Worker 	}
1618*6777b538SAndroid Build Coastguard Worker     }
1619*6777b538SAndroid Build Coastguard Worker 
1620*6777b538SAndroid Build Coastguard Worker     xmlNanoHTTPClose(ctxt);
1621*6777b538SAndroid Build Coastguard Worker     close(fd);
1622*6777b538SAndroid Build Coastguard Worker     return(ret);
1623*6777b538SAndroid Build Coastguard Worker }
1624*6777b538SAndroid Build Coastguard Worker 
1625*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_OUTPUT_ENABLED
1626*6777b538SAndroid Build Coastguard Worker /**
1627*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPSave:
1628*6777b538SAndroid Build Coastguard Worker  * @ctxt:  the HTTP context
1629*6777b538SAndroid Build Coastguard Worker  * @filename:  the filename where the content should be saved
1630*6777b538SAndroid Build Coastguard Worker  *
1631*6777b538SAndroid Build Coastguard Worker  * This function saves the output of the HTTP transaction to a file
1632*6777b538SAndroid Build Coastguard Worker  * It closes and free the context at the end
1633*6777b538SAndroid Build Coastguard Worker  *
1634*6777b538SAndroid Build Coastguard Worker  * Returns -1 in case of failure, 0 in case of success.
1635*6777b538SAndroid Build Coastguard Worker  */
1636*6777b538SAndroid Build Coastguard Worker int
xmlNanoHTTPSave(void * ctxt,const char * filename)1637*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPSave(void *ctxt, const char *filename) {
1638*6777b538SAndroid Build Coastguard Worker     char *buf = NULL;
1639*6777b538SAndroid Build Coastguard Worker     int fd;
1640*6777b538SAndroid Build Coastguard Worker     int len;
1641*6777b538SAndroid Build Coastguard Worker     int ret = 0;
1642*6777b538SAndroid Build Coastguard Worker 
1643*6777b538SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (filename == NULL)) return(-1);
1644*6777b538SAndroid Build Coastguard Worker 
1645*6777b538SAndroid Build Coastguard Worker     if (!strcmp(filename, "-"))
1646*6777b538SAndroid Build Coastguard Worker         fd = 0;
1647*6777b538SAndroid Build Coastguard Worker     else {
1648*6777b538SAndroid Build Coastguard Worker         fd = open(filename, O_CREAT | O_WRONLY, 0666);
1649*6777b538SAndroid Build Coastguard Worker 	if (fd < 0) {
1650*6777b538SAndroid Build Coastguard Worker 	    xmlNanoHTTPClose(ctxt);
1651*6777b538SAndroid Build Coastguard Worker 	    return(-1);
1652*6777b538SAndroid Build Coastguard Worker 	}
1653*6777b538SAndroid Build Coastguard Worker     }
1654*6777b538SAndroid Build Coastguard Worker 
1655*6777b538SAndroid Build Coastguard Worker     xmlNanoHTTPFetchContent( ctxt, &buf, &len );
1656*6777b538SAndroid Build Coastguard Worker     if ( len > 0 ) {
1657*6777b538SAndroid Build Coastguard Worker 	if (write(fd, buf, len) == -1) {
1658*6777b538SAndroid Build Coastguard Worker 	    ret = -1;
1659*6777b538SAndroid Build Coastguard Worker 	}
1660*6777b538SAndroid Build Coastguard Worker     }
1661*6777b538SAndroid Build Coastguard Worker 
1662*6777b538SAndroid Build Coastguard Worker     xmlNanoHTTPClose(ctxt);
1663*6777b538SAndroid Build Coastguard Worker     close(fd);
1664*6777b538SAndroid Build Coastguard Worker     return(ret);
1665*6777b538SAndroid Build Coastguard Worker }
1666*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_OUTPUT_ENABLED */
1667*6777b538SAndroid Build Coastguard Worker 
1668*6777b538SAndroid Build Coastguard Worker /**
1669*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPReturnCode:
1670*6777b538SAndroid Build Coastguard Worker  * @ctx:  the HTTP context
1671*6777b538SAndroid Build Coastguard Worker  *
1672*6777b538SAndroid Build Coastguard Worker  * Get the latest HTTP return code received
1673*6777b538SAndroid Build Coastguard Worker  *
1674*6777b538SAndroid Build Coastguard Worker  * Returns the HTTP return code for the request.
1675*6777b538SAndroid Build Coastguard Worker  */
1676*6777b538SAndroid Build Coastguard Worker int
xmlNanoHTTPReturnCode(void * ctx)1677*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPReturnCode(void *ctx) {
1678*6777b538SAndroid Build Coastguard Worker     xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr) ctx;
1679*6777b538SAndroid Build Coastguard Worker 
1680*6777b538SAndroid Build Coastguard Worker     if (ctxt == NULL) return(-1);
1681*6777b538SAndroid Build Coastguard Worker 
1682*6777b538SAndroid Build Coastguard Worker     return(ctxt->returnValue);
1683*6777b538SAndroid Build Coastguard Worker }
1684*6777b538SAndroid Build Coastguard Worker 
1685*6777b538SAndroid Build Coastguard Worker /**
1686*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPAuthHeader:
1687*6777b538SAndroid Build Coastguard Worker  * @ctx:  the HTTP context
1688*6777b538SAndroid Build Coastguard Worker  *
1689*6777b538SAndroid Build Coastguard Worker  * Get the authentication header of an HTTP context
1690*6777b538SAndroid Build Coastguard Worker  *
1691*6777b538SAndroid Build Coastguard Worker  * Returns the stashed value of the WWW-Authenticate or Proxy-Authenticate
1692*6777b538SAndroid Build Coastguard Worker  * header.
1693*6777b538SAndroid Build Coastguard Worker  */
1694*6777b538SAndroid Build Coastguard Worker const char *
xmlNanoHTTPAuthHeader(void * ctx)1695*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPAuthHeader(void *ctx) {
1696*6777b538SAndroid Build Coastguard Worker     xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr) ctx;
1697*6777b538SAndroid Build Coastguard Worker 
1698*6777b538SAndroid Build Coastguard Worker     if (ctxt == NULL) return(NULL);
1699*6777b538SAndroid Build Coastguard Worker 
1700*6777b538SAndroid Build Coastguard Worker     return(ctxt->authHeader);
1701*6777b538SAndroid Build Coastguard Worker }
1702*6777b538SAndroid Build Coastguard Worker 
1703*6777b538SAndroid Build Coastguard Worker /**
1704*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPContentLength:
1705*6777b538SAndroid Build Coastguard Worker  * @ctx:  the HTTP context
1706*6777b538SAndroid Build Coastguard Worker  *
1707*6777b538SAndroid Build Coastguard Worker  * Provides the specified content length from the HTTP header.
1708*6777b538SAndroid Build Coastguard Worker  *
1709*6777b538SAndroid Build Coastguard Worker  * Return the specified content length from the HTTP header.  Note that
1710*6777b538SAndroid Build Coastguard Worker  * a value of -1 indicates that the content length element was not included in
1711*6777b538SAndroid Build Coastguard Worker  * the response header.
1712*6777b538SAndroid Build Coastguard Worker  */
1713*6777b538SAndroid Build Coastguard Worker int
xmlNanoHTTPContentLength(void * ctx)1714*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPContentLength( void * ctx ) {
1715*6777b538SAndroid Build Coastguard Worker     xmlNanoHTTPCtxtPtr	ctxt = (xmlNanoHTTPCtxtPtr)ctx;
1716*6777b538SAndroid Build Coastguard Worker 
1717*6777b538SAndroid Build Coastguard Worker     return ( ( ctxt == NULL ) ? -1 : ctxt->ContentLength );
1718*6777b538SAndroid Build Coastguard Worker }
1719*6777b538SAndroid Build Coastguard Worker 
1720*6777b538SAndroid Build Coastguard Worker /**
1721*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPRedir:
1722*6777b538SAndroid Build Coastguard Worker  * @ctx:  the HTTP context
1723*6777b538SAndroid Build Coastguard Worker  *
1724*6777b538SAndroid Build Coastguard Worker  * Provides the specified redirection URL if available from the HTTP header.
1725*6777b538SAndroid Build Coastguard Worker  *
1726*6777b538SAndroid Build Coastguard Worker  * Return the specified redirection URL or NULL if not redirected.
1727*6777b538SAndroid Build Coastguard Worker  */
1728*6777b538SAndroid Build Coastguard Worker const char *
xmlNanoHTTPRedir(void * ctx)1729*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPRedir( void * ctx ) {
1730*6777b538SAndroid Build Coastguard Worker     xmlNanoHTTPCtxtPtr	ctxt = (xmlNanoHTTPCtxtPtr)ctx;
1731*6777b538SAndroid Build Coastguard Worker 
1732*6777b538SAndroid Build Coastguard Worker     return ( ( ctxt == NULL ) ? NULL : ctxt->location );
1733*6777b538SAndroid Build Coastguard Worker }
1734*6777b538SAndroid Build Coastguard Worker 
1735*6777b538SAndroid Build Coastguard Worker /**
1736*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPEncoding:
1737*6777b538SAndroid Build Coastguard Worker  * @ctx:  the HTTP context
1738*6777b538SAndroid Build Coastguard Worker  *
1739*6777b538SAndroid Build Coastguard Worker  * Provides the specified encoding if specified in the HTTP headers.
1740*6777b538SAndroid Build Coastguard Worker  *
1741*6777b538SAndroid Build Coastguard Worker  * Return the specified encoding or NULL if not available
1742*6777b538SAndroid Build Coastguard Worker  */
1743*6777b538SAndroid Build Coastguard Worker const char *
xmlNanoHTTPEncoding(void * ctx)1744*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPEncoding( void * ctx ) {
1745*6777b538SAndroid Build Coastguard Worker     xmlNanoHTTPCtxtPtr	ctxt = (xmlNanoHTTPCtxtPtr)ctx;
1746*6777b538SAndroid Build Coastguard Worker 
1747*6777b538SAndroid Build Coastguard Worker     return ( ( ctxt == NULL ) ? NULL : ctxt->encoding );
1748*6777b538SAndroid Build Coastguard Worker }
1749*6777b538SAndroid Build Coastguard Worker 
1750*6777b538SAndroid Build Coastguard Worker /**
1751*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPMimeType:
1752*6777b538SAndroid Build Coastguard Worker  * @ctx:  the HTTP context
1753*6777b538SAndroid Build Coastguard Worker  *
1754*6777b538SAndroid Build Coastguard Worker  * Provides the specified Mime-Type if specified in the HTTP headers.
1755*6777b538SAndroid Build Coastguard Worker  *
1756*6777b538SAndroid Build Coastguard Worker  * Return the specified Mime-Type or NULL if not available
1757*6777b538SAndroid Build Coastguard Worker  */
1758*6777b538SAndroid Build Coastguard Worker const char *
xmlNanoHTTPMimeType(void * ctx)1759*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPMimeType( void * ctx ) {
1760*6777b538SAndroid Build Coastguard Worker     xmlNanoHTTPCtxtPtr	ctxt = (xmlNanoHTTPCtxtPtr)ctx;
1761*6777b538SAndroid Build Coastguard Worker 
1762*6777b538SAndroid Build Coastguard Worker     return ( ( ctxt == NULL ) ? NULL : ctxt->mimeType );
1763*6777b538SAndroid Build Coastguard Worker }
1764*6777b538SAndroid Build Coastguard Worker 
1765*6777b538SAndroid Build Coastguard Worker /**
1766*6777b538SAndroid Build Coastguard Worker  * xmlNanoHTTPFetchContent:
1767*6777b538SAndroid Build Coastguard Worker  * @ctx:  the HTTP context
1768*6777b538SAndroid Build Coastguard Worker  * @ptr:  pointer to set to the content buffer.
1769*6777b538SAndroid Build Coastguard Worker  * @len:  integer pointer to hold the length of the content
1770*6777b538SAndroid Build Coastguard Worker  *
1771*6777b538SAndroid Build Coastguard Worker  * Check if all the content was read
1772*6777b538SAndroid Build Coastguard Worker  *
1773*6777b538SAndroid Build Coastguard Worker  * Returns 0 if all the content was read and available, returns
1774*6777b538SAndroid Build Coastguard Worker  * -1 if received content length was less than specified or an error
1775*6777b538SAndroid Build Coastguard Worker  * occurred.
1776*6777b538SAndroid Build Coastguard Worker  */
1777*6777b538SAndroid Build Coastguard Worker static int
xmlNanoHTTPFetchContent(void * ctx,char ** ptr,int * len)1778*6777b538SAndroid Build Coastguard Worker xmlNanoHTTPFetchContent( void * ctx, char ** ptr, int * len ) {
1779*6777b538SAndroid Build Coastguard Worker     xmlNanoHTTPCtxtPtr	ctxt = (xmlNanoHTTPCtxtPtr)ctx;
1780*6777b538SAndroid Build Coastguard Worker 
1781*6777b538SAndroid Build Coastguard Worker     int			rc = 0;
1782*6777b538SAndroid Build Coastguard Worker     int			cur_lgth;
1783*6777b538SAndroid Build Coastguard Worker     int			rcvd_lgth;
1784*6777b538SAndroid Build Coastguard Worker     int			dummy_int;
1785*6777b538SAndroid Build Coastguard Worker     char *		dummy_ptr = NULL;
1786*6777b538SAndroid Build Coastguard Worker 
1787*6777b538SAndroid Build Coastguard Worker     /*  Dummy up return input parameters if not provided  */
1788*6777b538SAndroid Build Coastguard Worker 
1789*6777b538SAndroid Build Coastguard Worker     if ( len == NULL )
1790*6777b538SAndroid Build Coastguard Worker         len = &dummy_int;
1791*6777b538SAndroid Build Coastguard Worker 
1792*6777b538SAndroid Build Coastguard Worker     if ( ptr == NULL )
1793*6777b538SAndroid Build Coastguard Worker         ptr = &dummy_ptr;
1794*6777b538SAndroid Build Coastguard Worker 
1795*6777b538SAndroid Build Coastguard Worker     /*  But can't work without the context pointer  */
1796*6777b538SAndroid Build Coastguard Worker 
1797*6777b538SAndroid Build Coastguard Worker     if ( ( ctxt == NULL ) || ( ctxt->content == NULL ) ) {
1798*6777b538SAndroid Build Coastguard Worker         *len = 0;
1799*6777b538SAndroid Build Coastguard Worker 	*ptr = NULL;
1800*6777b538SAndroid Build Coastguard Worker 	return ( -1 );
1801*6777b538SAndroid Build Coastguard Worker     }
1802*6777b538SAndroid Build Coastguard Worker 
1803*6777b538SAndroid Build Coastguard Worker     rcvd_lgth = ctxt->inptr - ctxt->content;
1804*6777b538SAndroid Build Coastguard Worker 
1805*6777b538SAndroid Build Coastguard Worker     while ( (cur_lgth = xmlNanoHTTPRecv( ctxt )) > 0 ) {
1806*6777b538SAndroid Build Coastguard Worker 
1807*6777b538SAndroid Build Coastguard Worker 	rcvd_lgth += cur_lgth;
1808*6777b538SAndroid Build Coastguard Worker 	if ( (ctxt->ContentLength > 0) && (rcvd_lgth >= ctxt->ContentLength) )
1809*6777b538SAndroid Build Coastguard Worker 	    break;
1810*6777b538SAndroid Build Coastguard Worker     }
1811*6777b538SAndroid Build Coastguard Worker 
1812*6777b538SAndroid Build Coastguard Worker     *ptr = ctxt->content;
1813*6777b538SAndroid Build Coastguard Worker     *len = rcvd_lgth;
1814*6777b538SAndroid Build Coastguard Worker 
1815*6777b538SAndroid Build Coastguard Worker     if ( ( ctxt->ContentLength > 0 ) && ( rcvd_lgth < ctxt->ContentLength ) )
1816*6777b538SAndroid Build Coastguard Worker         rc = -1;
1817*6777b538SAndroid Build Coastguard Worker     else if ( rcvd_lgth == 0 )
1818*6777b538SAndroid Build Coastguard Worker 	rc = -1;
1819*6777b538SAndroid Build Coastguard Worker 
1820*6777b538SAndroid Build Coastguard Worker     return ( rc );
1821*6777b538SAndroid Build Coastguard Worker }
1822*6777b538SAndroid Build Coastguard Worker 
1823*6777b538SAndroid Build Coastguard Worker #ifdef STANDALONE
main(int argc,char ** argv)1824*6777b538SAndroid Build Coastguard Worker int main(int argc, char **argv) {
1825*6777b538SAndroid Build Coastguard Worker     char *contentType = NULL;
1826*6777b538SAndroid Build Coastguard Worker 
1827*6777b538SAndroid Build Coastguard Worker     if (argv[1] != NULL) {
1828*6777b538SAndroid Build Coastguard Worker 	if (argv[2] != NULL)
1829*6777b538SAndroid Build Coastguard Worker 	    xmlNanoHTTPFetch(argv[1], argv[2], &contentType);
1830*6777b538SAndroid Build Coastguard Worker         else
1831*6777b538SAndroid Build Coastguard Worker 	    xmlNanoHTTPFetch(argv[1], "-", &contentType);
1832*6777b538SAndroid Build Coastguard Worker 	if (contentType != NULL) xmlFree(contentType);
1833*6777b538SAndroid Build Coastguard Worker     } else {
1834*6777b538SAndroid Build Coastguard Worker         fprintf(stderr,
1835*6777b538SAndroid Build Coastguard Worker 		"%s: minimal HTTP GET implementation\n", argv[0]);
1836*6777b538SAndroid Build Coastguard Worker         fprintf(stderr,
1837*6777b538SAndroid Build Coastguard Worker 		"\tusage %s [ URL [ filename ] ]\n", argv[0]);
1838*6777b538SAndroid Build Coastguard Worker     }
1839*6777b538SAndroid Build Coastguard Worker     xmlNanoHTTPCleanup();
1840*6777b538SAndroid Build Coastguard Worker     return(0);
1841*6777b538SAndroid Build Coastguard Worker }
1842*6777b538SAndroid Build Coastguard Worker #endif /* STANDALONE */
1843*6777b538SAndroid Build Coastguard Worker #else /* !LIBXML_HTTP_ENABLED */
1844*6777b538SAndroid Build Coastguard Worker #ifdef STANDALONE
1845*6777b538SAndroid Build Coastguard Worker #include <stdio.h>
main(int argc,char ** argv)1846*6777b538SAndroid Build Coastguard Worker int main(int argc, char **argv) {
1847*6777b538SAndroid Build Coastguard Worker     fprintf(stderr,
1848*6777b538SAndroid Build Coastguard Worker 	    "%s : HTTP support not compiled in\n", argv[0]);
1849*6777b538SAndroid Build Coastguard Worker     return(0);
1850*6777b538SAndroid Build Coastguard Worker }
1851*6777b538SAndroid Build Coastguard Worker #endif /* STANDALONE */
1852*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_HTTP_ENABLED */
1853