pocxxeci 0.30.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of pocxxeci might be problematic. Click here for more details.

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