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