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