ReactOS  0.4.13-dev-1148-g9b75b67
nanohttp.c
Go to the documentation of this file.
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 
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 
167 static void
168 xmlHTTPErrMemory(const char *extra)
169 {
170  __xmlSimpleError(XML_FROM_HTTP, XML_ERR_NO_MEMORY, NULL, NULL, extra);
171 }
172 
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 
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 
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 
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 
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)
363  "Removing HTTP proxy info\n");
364  else
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 
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 
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 
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 
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 
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 
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 
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) {
878  addrlen = sizeof(struct sockaddr_in6);
879  } else
880 #endif
881  {
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:
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  {
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) {
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 
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 
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 
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 = "Authoritive host not found";
1147  break;
1148 
1149  case TRY_AGAIN:
1150  h_err_txt =
1151  "Non-authoritive 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
1214  "xmlNanoHTTPConnectHost: unable to connect to '%s'.\n",
1215  host);
1216 #endif
1217  return INVALID_SOCKET;
1218 }
1219 
1220 
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 
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 
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 
1328 void
1329 xmlNanoHTTPClose(void *ctx) {
1330  xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr) ctx;
1331 
1332  if (ctx == NULL) return;
1333 
1334  xmlNanoHTTPFreeCtxt(ctxt);
1335 }
1336 
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) {
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
1488  "-> %s%s", proxy? "(Proxy) " : "", bp);
1489  if ((blen -= strlen(bp)+1) < 0)
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 )
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 )
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
1535 #endif
1536  xmlFree(p);
1537  }
1538 
1539  if ((ctxt->location != NULL) && (ctxt->returnValue >= 300) &&
1540  (ctxt->returnValue < 400)) {
1541 #ifdef DEBUG_HTTP
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
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)
1583  "\nCode %d, content-type '%s'\n\n",
1584  ctxt->returnValue, ctxt->contentType);
1585  else
1587  "\nCode %d, no content-type\n\n",
1588  ctxt->returnValue);
1589 #endif
1590 
1591  return((void *) ctxt);
1592 }
1593 
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 
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 
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 
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 
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 
1757 int
1758 xmlNanoHTTPContentLength( void * ctx ) {
1759  xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr)ctx;
1760 
1761  return ( ( ctxt == NULL ) ? -1 : ctxt->ContentLength );
1762 }
1763 
1772 const char *
1773 xmlNanoHTTPRedir( void * ctx ) {
1774  xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr)ctx;
1775 
1776  return ( ( ctxt == NULL ) ? NULL : ctxt->location );
1777 }
1778 
1787 const char *
1788 xmlNanoHTTPEncoding( void * ctx ) {
1789  xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr)ctx;
1790 
1791  return ( ( ctxt == NULL ) ? NULL : ctxt->encoding );
1792 }
1793 
1802 const char *
1803 xmlNanoHTTPMimeType( void * ctx ) {
1804  xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr)ctx;
1805 
1806  return ( ( ctxt == NULL ) ? NULL : ctxt->mimeType );
1807 }
1808 
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 {
1879  "%s: minimal HTTP GET implementation\n", argv[0]);
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) {
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"
Definition: winsock.h:66
namespace GUID const ADDRINFOEXW * hints
Definition: sock.c:80
#define SOCKET_ERROR
Definition: winsock.h:333
static int argc
Definition: ServiceArgs.c:12
XMLPUBVAR xmlMallocFunc xmlMallocAtomic
Definition: globals.h:248
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
int proxy
Definition: main.c:67
XMLPUBFUN const xmlChar *XMLCALL xmlStrstr(const xmlChar *str, const xmlChar *val)
Definition: xmlstring.c:341
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
SOCKET WSAAPI socket(IN INT af, IN INT type, IN INT protocol)
Definition: socklife.c:143
#define SEND_ARG2_CAST
Definition: config.h:258
#define freeaddrinfo
Definition: wspiapi.h:46
#define PF_INET6
Definition: winsock.h:395
CFF_Charset charset
Definition: cffcmap.c:138
unsigned long u_long
Definition: linux.h:269
const WCHAR * mime
Definition: mimefilter.c:512
#define open
Definition: acwin.h:95
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define MAKEWORD(a, b)
Definition: typedefs.h:247
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
POINT last
Definition: font.c:46
GLsizei const GLchar ** path
Definition: glext.h:7234
const char * uri
Definition: sec_mgr.c:1594
XMLPUBFUN xmlChar *XMLCALL xmlStrndup(const xmlChar *cur, int len)
Definition: xmlstring.c:41
int main(int argc, char *argv[])
Definition: atactl.cpp:1685
#define O_NONBLOCK
Definition: port.h:158
#define EINTR
Definition: acclib.h:80
char * host
Definition: whois.c:55
int ZEXPORT inflateEnd(z_streamp strm)
Definition: inflate.c:1277
INT WSAAPI WSACleanup(VOID)
Definition: startup.c:60
#define WSAEWOULDBLOCK
Definition: winerror.h:1948
#define snprintf
Definition: wintirpc.h:48
static int fd
Definition: io.c:51
vector< Header * > headers
Definition: sdkparse.cpp:39
#define EINPROGRESS
Definition: errno.h:126
Definition: dhcpd.h:245
XMLPUBFUN xmlChar *XMLCALL xmlCharStrndup(const char *cur, int len)
Definition: xmlstring.c:85
int errno
#define SOL_SOCKET
Definition: winsock.h:398
#define FD_ZERO(set)
Definition: winsock.h:96
#define argv
Definition: mplay32.c:18
const char * filename
Definition: ioapi.h:135
#define FD_SET(fd, set)
Definition: winsock.h:89
INT WSAAPI connect(IN SOCKET s, IN CONST struct sockaddr *name, IN INT namelen)
Definition: sockctrl.c:23
#define WSAEINPROGRESS
Definition: winerror.h:1949
GLbitfield GLuint64 timeout
Definition: glext.h:7164
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
static double one
Definition: j0_y0.c:80
char * hostname
Definition: ftp.c:88
#define write
Definition: acwin.h:97
unsigned short(__cdecl typeof(TIFFCurrentDirectory))(struct tiff *)
Definition: typeof.h:93
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define closesocket
Definition: main.c:39
_CRTIMP void __cdecl perror(_In_opt_z_ const char *_ErrMsg)
#define FD_ISSET(fd, set)
Definition: winsock.h:100
#define ECONNRESET
Definition: errno.h:115
INT WSAAPI select(IN INT s, IN OUT LPFD_SET readfds, IN OUT LPFD_SET writefds, IN OUT LPFD_SET exceptfds, IN CONST struct timeval *timeout)
Definition: select.c:41
#define O_WRONLY
Definition: acwin.h:111
#define ioctl
Definition: wintirpc.h:60
XMLPUBFUN xmlChar *XMLCALL xmlStrcat(xmlChar *cur, const xmlChar *add)
Definition: xmlstring.c:526
#define EWOULDBLOCK
Definition: errno.h:42
#define Z_OK
Definition: zlib.h:177
INT WSAAPI setsockopt(IN SOCKET s, IN INT level, IN INT optname, IN CONST CHAR FAR *optval, IN INT optlen)
Definition: sockctrl.c:421
static PVOID ptr
Definition: dispmode.c:27
content
Definition: atl_ax.c:994
XMLPUBVAR xmlGenericErrorFunc xmlGenericError
Definition: globals.h:346
INT WINAPI WSAStartup(IN WORD wVersionRequested, OUT LPWSADATA lpWSAData)
Definition: startup.c:113
smooth NULL
Definition: ftsmooth.c:416
static const WCHAR version[]
Definition: asmname.c:64
#define AF_INET6
Definition: winsock.h:369
#define SO_ERROR
Definition: winsock.h:194
Definition: parser.c:48
Definition: arc.h:35
#define ioctlsocket
Definition: main.c:40
#define BAD_CAST
Definition: xmlstring.h:35
#define PF_INET
Definition: winsock.h:373
XMLPUBVAR xmlReallocFunc xmlRealloc
Definition: globals.h:249
#define FD_SETSIZE
Definition: winsock.h:50
PHOSTENT WSAAPI gethostbyname(IN const char FAR *name)
Definition: getxbyxx.c:221
INT WSAAPI WSAGetLastError(VOID)
Definition: dllmain.c:112
#define INVALID_SOCKET
Definition: winsock.h:332
Definition: id3.c:18
INT WSAAPI send(IN SOCKET s, IN CONST CHAR FAR *buf, IN INT len, IN INT flags)
Definition: send.c:23
int poll(struct pollfd *ufds, int nfds, int timeout)
Definition: adnstest.c:68
Definition: tcpip.h:125
static BOOL initialized
Definition: syslog.c:39
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
#define inflateInit2(strm, windowBits)
Definition: zlib.h:1800
static FILE * out
Definition: regtests2xml.c:44
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:250
#define POLLIN
Definition: linux.h:1853
Definition: linux.h:1867
#define Z_NO_FLUSH
Definition: zlib.h:168
int ZEXPORT inflate(z_streamp strm, int flush)
Definition: inflate.c:622
method
Definition: dragdrop.c:53
XMLPUBFUN void XMLCALL xmlMemoryDump(void)
Definition: xmlmemory.c:931
int ret
char line[200]
Definition: main.c:97
GLenum const GLvoid * addr
Definition: glext.h:9621
XMLPUBFUN xmlURIPtr XMLCALL xmlParseURIRaw(const char *str, int raw)
Definition: uri.c:978
static int state
Definition: maze.c:121
unsigned char xmlChar
Definition: xmlstring.h:28
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
GLdouble s
Definition: gl.h:2039
#define close
Definition: acwin.h:98
#define err(...)
#define _WINSOCKAPI_
Definition: win32config.h:135
#define FIONBIO
Definition: winsock.h:149
ed encoding
Definition: write.c:2839
#define location(file, line)
Definition: kmtest.h:18
#define HOST_NOT_FOUND
Definition: winsock.h:226
#define XML_SOCKLEN_T
Definition: config.h:273
INT WSAAPI getsockopt(IN SOCKET s, IN INT level, IN INT optname, OUT CHAR FAR *optval, IN OUT INT FAR *optlen)
Definition: sockctrl.c:271
XMLPUBVAR xmlStrdupFunc xmlMemStrdup
Definition: globals.h:251
Definition: uri.h:33
#define NO_RECOVERY
Definition: winsock.h:228
GLboolean enable
Definition: glext.h:11120
#define GETHOSTBYNAME_ARG_CAST
Definition: config.h:5
_Check_return_ char *__cdecl getenv(_In_z_ const char *_VarName)
GLenum GLenum GLenum input
Definition: glext.h:9031
GLuint in
Definition: glext.h:9616
#define ESHUTDOWN
Definition: errno.h:119
#define TRY_AGAIN
Definition: winsock.h:227
#define WSAESHUTDOWN
Definition: winerror.h:1971
#define WSAECONNRESET
Definition: winerror.h:1967
XMLPUBFUN void XMLCALL xmlFreeURI(xmlURIPtr uri)
Definition: uri.c:1379
XMLPUBVAR xmlMallocFunc xmlMalloc
Definition: globals.h:247
static LPCWSTR LPCWSTR LPCWSTR env
Definition: db.cpp:168
_Check_return_ long __cdecl strtol(_In_z_ const char *_Str, _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix)
GLuint res
Definition: glext.h:9613
#define AF_INET
Definition: tcpip.h:117
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
void __xmlIOErr(int domain, int code, const char *extra)
static char * dest
Definition: rtl.c:135
UINT_PTR SOCKET
Definition: winsock.h:47
#define h_errno
Definition: winsock.h:225
XMLPUBFUN int XMLCALL xmlStrncasecmp(const xmlChar *str1, const xmlChar *str2, int len)
Definition: xmlstring.c:296
#define SOCK_STREAM
Definition: tcpip.h:118
GLfloat GLfloat p
Definition: glext.h:8902
#define htons(x)
Definition: module.h:213
USHORT port
Definition: uri.c:227
GLuint64EXT * result
Definition: glext.h:11304
#define memset(x, y, z)
Definition: compat.h:39
#define Z_NULL
Definition: zlib.h:212
#define POLLOUT
Definition: linux.h:1855
static SERVICE_STATUS status
Definition: service.c:31
#define O_CREAT
Definition: acwin.h:110
GLenum query
Definition: glext.h:7781
INT WSAAPI recv(IN SOCKET s, OUT CHAR FAR *buf, IN INT len, IN INT flags)
Definition: recv.c:23
XMLPUBFUN xmlChar *XMLCALL xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:66
#define WSAEINTR
Definition: winerror.h:1942
#define NO_ADDRESS
Definition: winsock2.h:221
XMLPUBVAR void * xmlGenericErrorContext
Definition: globals.h:362
#define getaddrinfo
Definition: wspiapi.h:44
Definition: ps.c:97