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