ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

nanohttp.c
Go to the documentation of this file.
00001 /*
00002  * nanohttp.c: minimalist HTTP GET implementation to fetch external subsets.
00003  *             focuses on size, streamability, reentrancy and portability
00004  *
00005  * This is clearly not a general purpose HTTP implementation
00006  * If you look for one, check:
00007  *         http://www.w3.org/Library/
00008  *
00009  * See Copyright for the status of this software.
00010  *
00011  * daniel@veillard.com
00012  */
00013  
00014 #define NEED_SOCKETS
00015 #define IN_LIBXML
00016 #include "libxml.h"
00017 
00018 #ifdef LIBXML_HTTP_ENABLED
00019 #include <string.h>
00020 
00021 #ifdef HAVE_STDLIB_H
00022 #include <stdlib.h>
00023 #endif
00024 #ifdef HAVE_UNISTD_H
00025 #include <unistd.h>
00026 #endif
00027 #ifdef HAVE_SYS_TYPES_H
00028 #include <sys/types.h>
00029 #endif
00030 #ifdef HAVE_SYS_SOCKET_H
00031 #include <sys/socket.h>
00032 #endif
00033 #ifdef HAVE_NETINET_IN_H
00034 #include <netinet/in.h>
00035 #endif
00036 #ifdef HAVE_ARPA_INET_H
00037 #include <arpa/inet.h>
00038 #endif
00039 #ifdef HAVE_NETDB_H
00040 #include <netdb.h>
00041 #endif
00042 #ifdef HAVE_RESOLV_H
00043 #ifdef HAVE_ARPA_NAMESER_H
00044 #include <arpa/nameser.h>
00045 #endif
00046 #include <resolv.h>
00047 #endif
00048 #ifdef HAVE_FCNTL_H
00049 #include <fcntl.h> 
00050 #endif
00051 #ifdef HAVE_ERRNO_H
00052 #include <errno.h>
00053 #endif
00054 #ifdef HAVE_SYS_TIME_H
00055 #include <sys/time.h>
00056 #endif
00057 #ifndef HAVE_POLL_H
00058 #ifdef HAVE_SYS_SELECT_H
00059 #include <sys/select.h>
00060 #endif
00061 #else
00062 #include <poll.h>
00063 #endif
00064 #ifdef HAVE_STRINGS_H
00065 #include <strings.h>
00066 #endif
00067 #ifdef SUPPORT_IP6
00068 #include <resolv.h>
00069 #endif
00070 #ifdef HAVE_ZLIB_H
00071 #include <zlib.h>
00072 #endif
00073 
00074 
00075 #ifdef VMS
00076 #include <stropts>
00077 #define XML_SOCKLEN_T unsigned int
00078 #endif
00079 
00080 #if defined(__MINGW32__) || defined(_WIN32_WCE)
00081 #ifndef _WINSOCKAPI_
00082 #define _WINSOCKAPI_
00083 #endif
00084 #include <wsockcompat.h>
00085 #include <winsock2.h>
00086 #undef XML_SOCKLEN_T
00087 #define XML_SOCKLEN_T unsigned int
00088 #endif
00089 
00090 #include <libxml/globals.h>
00091 #include <libxml/xmlerror.h>
00092 #include <libxml/xmlmemory.h>
00093 #include <libxml/parser.h> /* for xmlStr(n)casecmp() */
00094 #include <libxml/nanohttp.h>
00095 #include <libxml/globals.h>
00096 #include <libxml/uri.h>
00097 
00101 #ifndef _WINSOCKAPI_
00102 #if !defined(__BEOS__) || defined(__HAIKU__)
00103 #define closesocket(s) close(s)
00104 #endif
00105 #define SOCKET int
00106 #define INVALID_SOCKET (-1)
00107 #endif
00108 
00109 #ifdef __BEOS__
00110 #ifndef PF_INET
00111 #define PF_INET AF_INET
00112 #endif
00113 #endif
00114 
00115 #ifndef XML_SOCKLEN_T
00116 #define XML_SOCKLEN_T unsigned int
00117 #endif
00118 
00119 #ifdef STANDALONE
00120 #define DEBUG_HTTP
00121 #define xmlStrncasecmp(a, b, n) strncasecmp((char *)a, (char *)b, n)
00122 #define xmlStrcasecmpi(a, b) strcasecmp((char *)a, (char *)b)
00123 #endif
00124 
00125 #define XML_NANO_HTTP_MAX_REDIR 10
00126 
00127 #define XML_NANO_HTTP_CHUNK 4096
00128 
00129 #define XML_NANO_HTTP_CLOSED    0
00130 #define XML_NANO_HTTP_WRITE 1
00131 #define XML_NANO_HTTP_READ  2
00132 #define XML_NANO_HTTP_NONE  4
00133 
00134 typedef struct xmlNanoHTTPCtxt {
00135     char *protocol; /* the protocol name */
00136     char *hostname; /* the host name */
00137     int port;       /* the port */
00138     char *path;     /* the path within the URL */
00139     char *query;    /* the query string */
00140     SOCKET fd;      /* the file descriptor for the socket */
00141     int state;      /* WRITE / READ / CLOSED */
00142     char *out;      /* buffer sent (zero terminated) */
00143     char *outptr;   /* index within the buffer sent */
00144     char *in;       /* the receiving buffer */
00145     char *content;  /* the start of the content */
00146     char *inptr;    /* the next byte to read from network */
00147     char *inrptr;   /* the next byte to give back to the client */
00148     int inlen;      /* len of the input buffer */
00149     int last;       /* return code for last operation */
00150     int returnValue;    /* the protocol return value */
00151     int version;        /* the protocol version */
00152     int ContentLength;  /* specified content length from HTTP header */
00153     char *contentType;  /* the MIME type for the input */
00154     char *location; /* the new URL in case of redirect */
00155     char *authHeader;   /* contents of {WWW,Proxy}-Authenticate header */
00156     char *encoding; /* encoding extracted from the contentType */
00157     char *mimeType; /* Mime-Type extracted from the contentType */
00158 #ifdef HAVE_ZLIB_H
00159     z_stream *strm; /* Zlib stream object */
00160     int usesGzip;   /* "Content-Encoding: gzip" was detected */
00161 #endif
00162 } xmlNanoHTTPCtxt, *xmlNanoHTTPCtxtPtr;
00163 
00164 static int initialized = 0;
00165 static char *proxy = NULL;   /* the proxy name if any */
00166 static int proxyPort;   /* the proxy port if any */
00167 static unsigned int timeout = 60;/* the select() timeout in seconds */
00168 
00169 static int xmlNanoHTTPFetchContent( void * ctx, char ** ptr, int * len );
00170 
00177 static void
00178 xmlHTTPErrMemory(const char *extra)
00179 {
00180     __xmlSimpleError(XML_FROM_HTTP, XML_ERR_NO_MEMORY, NULL, NULL, extra);
00181 }
00182 
00186 static int socket_errno(void) {
00187 #ifdef _WINSOCKAPI_
00188     return(WSAGetLastError());
00189 #else
00190     return(errno);
00191 #endif
00192 }
00193 
00194 #ifdef SUPPORT_IP6
00195 static
00196 int have_ipv6(void) {
00197     SOCKET s;
00198 
00199     s = socket (AF_INET6, SOCK_STREAM, 0);
00200     if (s != INVALID_SOCKET) {
00201     close (s);
00202     return (1);
00203     }
00204     return (0);
00205 }
00206 #endif
00207 
00215 void
00216 xmlNanoHTTPInit(void) {
00217     const char *env;
00218 #ifdef _WINSOCKAPI_
00219     WSADATA wsaData;    
00220 #endif
00221 
00222     if (initialized)
00223     return;
00224 
00225 #ifdef _WINSOCKAPI_
00226     if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
00227     return;
00228 #endif
00229 
00230     if (proxy == NULL) {
00231     proxyPort = 80;
00232     env = getenv("no_proxy");
00233     if (env && ((env[0] == '*') && (env[1] == 0)))
00234         goto done;
00235     env = getenv("http_proxy");
00236     if (env != NULL) {
00237         xmlNanoHTTPScanProxy(env);
00238         goto done;
00239     }
00240     env = getenv("HTTP_PROXY");
00241     if (env != NULL) {
00242         xmlNanoHTTPScanProxy(env);
00243         goto done;
00244     }
00245     }
00246 done:
00247     initialized = 1;
00248 }
00249 
00256 void
00257 xmlNanoHTTPCleanup(void) {
00258     if (proxy != NULL) {
00259     xmlFree(proxy);
00260     proxy = NULL;
00261     }
00262 #ifdef _WINSOCKAPI_
00263     if (initialized)
00264     WSACleanup();
00265 #endif
00266     initialized = 0;
00267     return;
00268 }
00269 
00279 static void
00280 xmlNanoHTTPScanURL(xmlNanoHTTPCtxtPtr ctxt, const char *URL) {
00281     xmlURIPtr uri;
00282     /*
00283      * Clear any existing data from the context
00284      */
00285     if (ctxt->protocol != NULL) { 
00286         xmlFree(ctxt->protocol);
00287     ctxt->protocol = NULL;
00288     }
00289     if (ctxt->hostname != NULL) { 
00290         xmlFree(ctxt->hostname);
00291     ctxt->hostname = NULL;
00292     }
00293     if (ctxt->path != NULL) { 
00294         xmlFree(ctxt->path);
00295     ctxt->path = NULL;
00296     }
00297     if (ctxt->query != NULL) { 
00298         xmlFree(ctxt->query);
00299     ctxt->query = NULL;
00300     }
00301     if (URL == NULL) return;
00302 
00303     uri = xmlParseURIRaw(URL, 1);
00304     if (uri == NULL)
00305     return;
00306 
00307     if ((uri->scheme == NULL) || (uri->server == NULL)) {
00308     xmlFreeURI(uri);
00309     return;
00310     }
00311     
00312     ctxt->protocol = xmlMemStrdup(uri->scheme);
00313     ctxt->hostname = xmlMemStrdup(uri->server);
00314     if (uri->path != NULL)
00315     ctxt->path = xmlMemStrdup(uri->path);
00316     else
00317     ctxt->path = xmlMemStrdup("/");
00318     if (uri->query != NULL)
00319     ctxt->query = xmlMemStrdup(uri->query);
00320     if (uri->port != 0)
00321     ctxt->port = uri->port;
00322 
00323     xmlFreeURI(uri);
00324 }
00325 
00336 void
00337 xmlNanoHTTPScanProxy(const char *URL) {
00338     xmlURIPtr uri;
00339 
00340     if (proxy != NULL) { 
00341         xmlFree(proxy);
00342     proxy = NULL;
00343     }
00344     proxyPort = 0;
00345 
00346 #ifdef DEBUG_HTTP
00347     if (URL == NULL)
00348     xmlGenericError(xmlGenericErrorContext,
00349         "Removing HTTP proxy info\n");
00350     else
00351     xmlGenericError(xmlGenericErrorContext,
00352         "Using HTTP proxy %s\n", URL);
00353 #endif
00354     if (URL == NULL) return;
00355 
00356     uri = xmlParseURIRaw(URL, 1);
00357     if ((uri == NULL) || (uri->scheme == NULL) ||
00358     (strcmp(uri->scheme, "http")) || (uri->server == NULL)) {
00359     __xmlIOErr(XML_FROM_HTTP, XML_HTTP_URL_SYNTAX, "Syntax Error\n");
00360     if (uri != NULL)
00361         xmlFreeURI(uri);
00362     return;
00363     }
00364     
00365     proxy = xmlMemStrdup(uri->server);
00366     if (uri->port != 0)
00367     proxyPort = uri->port;
00368 
00369     xmlFreeURI(uri);
00370 }
00371 
00381 static xmlNanoHTTPCtxtPtr
00382 xmlNanoHTTPNewCtxt(const char *URL) {
00383     xmlNanoHTTPCtxtPtr ret;
00384 
00385     ret = (xmlNanoHTTPCtxtPtr) xmlMalloc(sizeof(xmlNanoHTTPCtxt));
00386     if (ret == NULL) {
00387         xmlHTTPErrMemory("allocating context");
00388         return(NULL);
00389     }
00390 
00391     memset(ret, 0, sizeof(xmlNanoHTTPCtxt));
00392     ret->port = 80;
00393     ret->returnValue = 0;
00394     ret->fd = INVALID_SOCKET;
00395     ret->ContentLength = -1;
00396 
00397     xmlNanoHTTPScanURL(ret, URL);
00398 
00399     return(ret);
00400 }
00401 
00409 static void
00410 xmlNanoHTTPFreeCtxt(xmlNanoHTTPCtxtPtr ctxt) {
00411     if (ctxt == NULL) return;
00412     if (ctxt->hostname != NULL) xmlFree(ctxt->hostname);
00413     if (ctxt->protocol != NULL) xmlFree(ctxt->protocol);
00414     if (ctxt->path != NULL) xmlFree(ctxt->path);
00415     if (ctxt->query != NULL) xmlFree(ctxt->query);
00416     if (ctxt->out != NULL) xmlFree(ctxt->out);
00417     if (ctxt->in != NULL) xmlFree(ctxt->in);
00418     if (ctxt->contentType != NULL) xmlFree(ctxt->contentType);
00419     if (ctxt->encoding != NULL) xmlFree(ctxt->encoding);
00420     if (ctxt->mimeType != NULL) xmlFree(ctxt->mimeType);
00421     if (ctxt->location != NULL) xmlFree(ctxt->location);
00422     if (ctxt->authHeader != NULL) xmlFree(ctxt->authHeader);
00423 #ifdef HAVE_ZLIB_H
00424     if (ctxt->strm != NULL) {
00425     inflateEnd(ctxt->strm);
00426     xmlFree(ctxt->strm);
00427     }
00428 #endif
00429 
00430     ctxt->state = XML_NANO_HTTP_NONE;
00431     if (ctxt->fd != INVALID_SOCKET) closesocket(ctxt->fd);
00432     ctxt->fd = INVALID_SOCKET;
00433     xmlFree(ctxt);
00434 }
00435 
00444 static int
00445 xmlNanoHTTPSend(xmlNanoHTTPCtxtPtr ctxt, const char *xmt_ptr, int outlen)
00446 {
00447     int total_sent = 0;
00448 #ifdef HAVE_POLL_H
00449     struct pollfd p;
00450 #else
00451     struct timeval tv;
00452     fd_set wfd;
00453 #endif
00454 
00455     if ((ctxt->state & XML_NANO_HTTP_WRITE) && (xmt_ptr != NULL)) {
00456         while (total_sent < outlen) {
00457             int nsent = send(ctxt->fd, xmt_ptr + total_sent,
00458                              outlen - total_sent, 0);
00459 
00460             if (nsent > 0)
00461                 total_sent += nsent;
00462             else if ((nsent == -1) &&
00463 #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
00464                      (socket_errno() != EAGAIN) &&
00465 #endif
00466                      (socket_errno() != EWOULDBLOCK)) {
00467                 __xmlIOErr(XML_FROM_HTTP, 0, "send failed\n");
00468                 if (total_sent == 0)
00469                     total_sent = -1;
00470                 break;
00471             } else {
00472                 /*
00473                  * No data sent
00474                  * Since non-blocking sockets are used, wait for
00475                  * socket to be writable or default timeout prior
00476                  * to retrying.
00477                  */
00478 #ifndef HAVE_POLL_H
00479 #ifndef _WINSOCKAPI_
00480                 if (ctxt->fd > FD_SETSIZE)
00481                     return -1;
00482 #endif
00483 
00484                 tv.tv_sec = timeout;
00485                 tv.tv_usec = 0;
00486                 FD_ZERO(&wfd);
00487 #ifdef _MSC_VER
00488 #pragma warning(push)
00489 #pragma warning(disable: 4018)
00490 #endif
00491                 FD_SET(ctxt->fd, &wfd);
00492 #ifdef _MSC_VER
00493 #pragma warning(pop)
00494 #endif
00495                 (void) select(ctxt->fd + 1, NULL, &wfd, NULL, &tv);
00496 #else
00497                 p.fd = ctxt->fd;
00498                 p.events = POLLOUT;
00499                 (void) poll(&p, 1, timeout * 1000);
00500 #endif /* !HAVE_POLL_H */
00501             }
00502         }
00503     }
00504 
00505     return total_sent;
00506 }
00507 
00518 static int
00519 xmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt)
00520 {
00521 #ifdef HAVE_POLL_H
00522     struct pollfd p;
00523 #else
00524     fd_set rfd;
00525     struct timeval tv;
00526 #endif
00527 
00528 
00529     while (ctxt->state & XML_NANO_HTTP_READ) {
00530         if (ctxt->in == NULL) {
00531             ctxt->in = (char *) xmlMallocAtomic(65000 * sizeof(char));
00532             if (ctxt->in == NULL) {
00533                 xmlHTTPErrMemory("allocating input");
00534                 ctxt->last = -1;
00535                 return (-1);
00536             }
00537             ctxt->inlen = 65000;
00538             ctxt->inptr = ctxt->content = ctxt->inrptr = ctxt->in;
00539         }
00540         if (ctxt->inrptr > ctxt->in + XML_NANO_HTTP_CHUNK) {
00541             int delta = ctxt->inrptr - ctxt->in;
00542             int len = ctxt->inptr - ctxt->inrptr;
00543 
00544             memmove(ctxt->in, ctxt->inrptr, len);
00545             ctxt->inrptr -= delta;
00546             ctxt->content -= delta;
00547             ctxt->inptr -= delta;
00548         }
00549         if ((ctxt->in + ctxt->inlen) < (ctxt->inptr + XML_NANO_HTTP_CHUNK)) {
00550             int d_inptr = ctxt->inptr - ctxt->in;
00551             int d_content = ctxt->content - ctxt->in;
00552             int d_inrptr = ctxt->inrptr - ctxt->in;
00553             char *tmp_ptr = ctxt->in;
00554 
00555             ctxt->inlen *= 2;
00556             ctxt->in = (char *) xmlRealloc(tmp_ptr, ctxt->inlen);
00557             if (ctxt->in == NULL) {
00558                 xmlHTTPErrMemory("allocating input buffer");
00559                 xmlFree(tmp_ptr);
00560                 ctxt->last = -1;
00561                 return (-1);
00562             }
00563             ctxt->inptr = ctxt->in + d_inptr;
00564             ctxt->content = ctxt->in + d_content;
00565             ctxt->inrptr = ctxt->in + d_inrptr;
00566         }
00567         ctxt->last = recv(ctxt->fd, ctxt->inptr, XML_NANO_HTTP_CHUNK, 0);
00568         if (ctxt->last > 0) {
00569             ctxt->inptr += ctxt->last;
00570             return (ctxt->last);
00571         }
00572         if (ctxt->last == 0) {
00573             return (0);
00574         }
00575         if (ctxt->last == -1) {
00576             switch (socket_errno()) {
00577                 case EINPROGRESS:
00578                 case EWOULDBLOCK:
00579 #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
00580                 case EAGAIN:
00581 #endif
00582                     break;
00583 
00584                 case ECONNRESET:
00585                 case ESHUTDOWN:
00586                     return (0);
00587 
00588                 default:
00589                     __xmlIOErr(XML_FROM_HTTP, 0, "recv failed\n");
00590                     return (-1);
00591             }
00592         }
00593 #ifdef HAVE_POLL_H
00594         p.fd = ctxt->fd;
00595         p.events = POLLIN;
00596         if ((poll(&p, 1, timeout * 1000) < 1)
00597 #if defined(EINTR)
00598             && (errno != EINTR)
00599 #endif
00600             )
00601             return (0);
00602 #else /* !HAVE_POLL_H */
00603 #ifndef _WINSOCKAPI_
00604         if (ctxt->fd > FD_SETSIZE)
00605             return 0;
00606 #endif
00607 
00608         tv.tv_sec = timeout;
00609         tv.tv_usec = 0;
00610         FD_ZERO(&rfd);
00611 
00612 #ifdef _MSC_VER
00613 #pragma warning(push)
00614 #pragma warning(disable: 4018)
00615 #endif
00616 
00617         FD_SET(ctxt->fd, &rfd);
00618 
00619 #ifdef _MSC_VER
00620 #pragma warning(pop)
00621 #endif
00622 
00623         if ((select(ctxt->fd + 1, &rfd, NULL, NULL, &tv) < 1)
00624 #if defined(EINTR)
00625             && (errno != EINTR)
00626 #endif
00627             )
00628             return (0);
00629 #endif /* !HAVE_POLL_H */
00630     }
00631     return (0);
00632 }
00633 
00645 static char *
00646 xmlNanoHTTPReadLine(xmlNanoHTTPCtxtPtr ctxt) {
00647     char buf[4096];
00648     char *bp = buf;
00649     int rc;
00650     
00651     while (bp - buf < 4095) {
00652     if (ctxt->inrptr == ctxt->inptr) {
00653         if ( (rc = xmlNanoHTTPRecv(ctxt)) == 0) {
00654         if (bp == buf)
00655             return(NULL);
00656         else
00657             *bp = 0;
00658         return(xmlMemStrdup(buf));
00659         }
00660         else if ( rc == -1 ) {
00661             return ( NULL );
00662         }
00663     }
00664     *bp = *ctxt->inrptr++;
00665     if (*bp == '\n') {
00666         *bp = 0;
00667         return(xmlMemStrdup(buf));
00668     }
00669     if (*bp != '\r')
00670         bp++;
00671     }
00672     buf[4095] = 0;
00673     return(xmlMemStrdup(buf));
00674 }
00675 
00676 
00691 static void
00692 xmlNanoHTTPScanAnswer(xmlNanoHTTPCtxtPtr ctxt, const char *line) {
00693     const char *cur = line;
00694 
00695     if (line == NULL) return;
00696 
00697     if (!strncmp(line, "HTTP/", 5)) {
00698         int version = 0;
00699     int ret = 0;
00700 
00701     cur += 5;
00702     while ((*cur >= '0') && (*cur <= '9')) {
00703         version *= 10;
00704         version += *cur - '0';
00705         cur++;
00706     }
00707     if (*cur == '.') {
00708         cur++;
00709         if ((*cur >= '0') && (*cur <= '9')) {
00710         version *= 10;
00711         version += *cur - '0';
00712         cur++;
00713         }
00714         while ((*cur >= '0') && (*cur <= '9'))
00715         cur++;
00716     } else
00717         version *= 10;
00718     if ((*cur != ' ') && (*cur != '\t')) return;
00719     while ((*cur == ' ') || (*cur == '\t')) cur++;
00720     if ((*cur < '0') || (*cur > '9')) return;
00721     while ((*cur >= '0') && (*cur <= '9')) {
00722         ret *= 10;
00723         ret += *cur - '0';
00724         cur++;
00725     }
00726     if ((*cur != 0) && (*cur != ' ') && (*cur != '\t')) return;
00727     ctxt->returnValue = ret;
00728         ctxt->version = version;
00729     } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"Content-Type:", 13)) {
00730         const xmlChar *charset, *last, *mime;
00731         cur += 13;
00732     while ((*cur == ' ') || (*cur == '\t')) cur++;
00733     if (ctxt->contentType != NULL)
00734         xmlFree(ctxt->contentType);
00735     ctxt->contentType = xmlMemStrdup(cur);
00736     mime = (const xmlChar *) cur;
00737     last = mime;
00738     while ((*last != 0) && (*last != ' ') && (*last != '\t') &&
00739            (*last != ';') && (*last != ','))
00740         last++;
00741     if (ctxt->mimeType != NULL)
00742         xmlFree(ctxt->mimeType);
00743     ctxt->mimeType = (char *) xmlStrndup(mime, last - mime);
00744     charset = xmlStrstr(BAD_CAST ctxt->contentType, BAD_CAST "charset=");
00745     if (charset != NULL) {
00746         charset += 8;
00747         last = charset;
00748         while ((*last != 0) && (*last != ' ') && (*last != '\t') &&
00749                (*last != ';') && (*last != ','))
00750         last++;
00751         if (ctxt->encoding != NULL)
00752             xmlFree(ctxt->encoding);
00753         ctxt->encoding = (char *) xmlStrndup(charset, last - charset);
00754     }
00755     } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"ContentType:", 12)) {
00756         const xmlChar *charset, *last, *mime;
00757         cur += 12;
00758     if (ctxt->contentType != NULL) return;
00759     while ((*cur == ' ') || (*cur == '\t')) cur++;
00760     ctxt->contentType = xmlMemStrdup(cur);
00761     mime = (const xmlChar *) cur;
00762     last = mime;
00763     while ((*last != 0) && (*last != ' ') && (*last != '\t') &&
00764            (*last != ';') && (*last != ','))
00765         last++;
00766     if (ctxt->mimeType != NULL)
00767         xmlFree(ctxt->mimeType);
00768     ctxt->mimeType = (char *) xmlStrndup(mime, last - mime);
00769     charset = xmlStrstr(BAD_CAST ctxt->contentType, BAD_CAST "charset=");
00770     if (charset != NULL) {
00771         charset += 8;
00772         last = charset;
00773         while ((*last != 0) && (*last != ' ') && (*last != '\t') &&
00774                (*last != ';') && (*last != ','))
00775         last++;
00776         if (ctxt->encoding != NULL)
00777             xmlFree(ctxt->encoding);
00778         ctxt->encoding = (char *) xmlStrndup(charset, last - charset);
00779     }
00780     } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"Location:", 9)) {
00781         cur += 9;
00782     while ((*cur == ' ') || (*cur == '\t')) cur++;
00783     if (ctxt->location != NULL)
00784         xmlFree(ctxt->location);
00785     if (*cur == '/') {
00786         xmlChar *tmp_http = xmlStrdup(BAD_CAST "http://");
00787         xmlChar *tmp_loc = 
00788             xmlStrcat(tmp_http, (const xmlChar *) ctxt->hostname);
00789         ctxt->location = 
00790             (char *) xmlStrcat (tmp_loc, (const xmlChar *) cur);
00791     } else {
00792         ctxt->location = xmlMemStrdup(cur);
00793     }
00794     } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"WWW-Authenticate:", 17)) {
00795         cur += 17;
00796     while ((*cur == ' ') || (*cur == '\t')) cur++;
00797     if (ctxt->authHeader != NULL)
00798         xmlFree(ctxt->authHeader);
00799     ctxt->authHeader = xmlMemStrdup(cur);
00800     } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"Proxy-Authenticate:", 19)) {
00801         cur += 19;
00802     while ((*cur == ' ') || (*cur == '\t')) cur++;
00803     if (ctxt->authHeader != NULL)
00804         xmlFree(ctxt->authHeader);
00805     ctxt->authHeader = xmlMemStrdup(cur);
00806 #ifdef HAVE_ZLIB_H
00807     } else if ( !xmlStrncasecmp( BAD_CAST line, BAD_CAST"Content-Encoding:", 17) ) {
00808     cur += 17;
00809     while ((*cur == ' ') || (*cur == '\t')) cur++;
00810     if ( !xmlStrncasecmp( BAD_CAST cur, BAD_CAST"gzip", 4) ) {
00811         ctxt->usesGzip = 1;
00812 
00813         ctxt->strm = xmlMalloc(sizeof(z_stream));
00814 
00815         if (ctxt->strm != NULL) {
00816         ctxt->strm->zalloc = Z_NULL;
00817         ctxt->strm->zfree = Z_NULL;
00818         ctxt->strm->opaque = Z_NULL;
00819         ctxt->strm->avail_in = 0;
00820         ctxt->strm->next_in = Z_NULL;
00821 
00822         inflateInit2( ctxt->strm, 31 );
00823         }
00824     }
00825 #endif
00826     } else if ( !xmlStrncasecmp( BAD_CAST line, BAD_CAST"Content-Length:", 15) ) {
00827     cur += 15;
00828     ctxt->ContentLength = strtol( cur, NULL, 10 );
00829     }
00830 }
00831 
00843 static SOCKET
00844 xmlNanoHTTPConnectAttempt(struct sockaddr *addr)
00845 {
00846 #ifndef HAVE_POLL_H
00847     fd_set wfd;
00848 #ifdef _WINSOCKAPI_
00849     fd_set xfd;
00850 #endif
00851     struct timeval tv;
00852 #else /* !HAVE_POLL_H */
00853     struct pollfd p;
00854 #endif /* !HAVE_POLL_H */
00855     int status;
00856 
00857     int addrlen;
00858 
00859     SOCKET s;
00860 
00861 #ifdef SUPPORT_IP6
00862     if (addr->sa_family == AF_INET6) {
00863         s = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
00864         addrlen = sizeof(struct sockaddr_in6);
00865     } else
00866 #endif
00867     {
00868         s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
00869         addrlen = sizeof(struct sockaddr_in);
00870     }
00871     if (s == INVALID_SOCKET) {
00872 #ifdef DEBUG_HTTP
00873         perror("socket");
00874 #endif
00875         __xmlIOErr(XML_FROM_HTTP, 0, "socket failed\n");
00876         return INVALID_SOCKET;
00877     }
00878 #ifdef _WINSOCKAPI_
00879     {
00880         u_long one = 1;
00881 
00882         status = ioctlsocket(s, FIONBIO, &one) == SOCKET_ERROR ? -1 : 0;
00883     }
00884 #else /* _WINSOCKAPI_ */
00885 #if defined(VMS)
00886     {
00887         int enable = 1;
00888 
00889         status = ioctl(s, FIONBIO, &enable);
00890     }
00891 #else /* VMS */
00892 #if defined(__BEOS__) && !defined(__HAIKU__)
00893     {
00894         bool noblock = true;
00895 
00896         status =
00897             setsockopt(s, SOL_SOCKET, SO_NONBLOCK, &noblock,
00898                        sizeof(noblock));
00899     }
00900 #else /* __BEOS__ */
00901     if ((status = fcntl(s, F_GETFL, 0)) != -1) {
00902 #ifdef O_NONBLOCK
00903         status |= O_NONBLOCK;
00904 #else /* O_NONBLOCK */
00905 #ifdef F_NDELAY
00906         status |= F_NDELAY;
00907 #endif /* F_NDELAY */
00908 #endif /* !O_NONBLOCK */
00909         status = fcntl(s, F_SETFL, status);
00910     }
00911     if (status < 0) {
00912 #ifdef DEBUG_HTTP
00913         perror("nonblocking");
00914 #endif
00915         __xmlIOErr(XML_FROM_HTTP, 0, "error setting non-blocking IO\n");
00916         closesocket(s);
00917         return INVALID_SOCKET;
00918     }
00919 #endif /* !__BEOS__ */
00920 #endif /* !VMS */
00921 #endif /* !_WINSOCKAPI_ */
00922 
00923     if (connect(s, addr, addrlen) == -1) {
00924         switch (socket_errno()) {
00925             case EINPROGRESS:
00926             case EWOULDBLOCK:
00927                 break;
00928             default:
00929                 __xmlIOErr(XML_FROM_HTTP, 0,
00930                            "error connecting to HTTP server");
00931                 closesocket(s);
00932                 return INVALID_SOCKET;
00933         }
00934     }
00935 #ifndef HAVE_POLL_H
00936     tv.tv_sec = timeout;
00937     tv.tv_usec = 0;
00938 
00939 #ifdef _MSC_VER
00940 #pragma warning(push)
00941 #pragma warning(disable: 4018)
00942 #endif
00943 #ifndef _WINSOCKAPI_
00944     if (s > FD_SETSIZE)
00945         return INVALID_SOCKET;
00946 #endif
00947     FD_ZERO(&wfd);
00948     FD_SET(s, &wfd);
00949 
00950 #ifdef _WINSOCKAPI_
00951     FD_ZERO(&xfd);
00952     FD_SET(s, &xfd);
00953 
00954     switch (select(s + 1, NULL, &wfd, &xfd, &tv))
00955 #else
00956     switch (select(s + 1, NULL, &wfd, NULL, &tv))
00957 #endif
00958 #ifdef _MSC_VER
00959 #pragma warning(pop)
00960 #endif
00961 
00962 #else /* !HAVE_POLL_H */
00963     p.fd = s;
00964     p.events = POLLOUT;
00965     switch (poll(&p, 1, timeout * 1000))
00966 #endif /* !HAVE_POLL_H */
00967 
00968     {
00969         case 0:
00970             /* Time out */
00971             __xmlIOErr(XML_FROM_HTTP, 0, "Connect attempt timed out");
00972             closesocket(s);
00973             return INVALID_SOCKET;
00974         case -1:
00975             /* Ermm.. ?? */
00976             __xmlIOErr(XML_FROM_HTTP, 0, "Connect failed");
00977             closesocket(s);
00978             return INVALID_SOCKET;
00979     }
00980 
00981 #ifndef HAVE_POLL_H
00982     if (FD_ISSET(s, &wfd)
00983 #ifdef _WINSOCKAPI_
00984         || FD_ISSET(s, &xfd)
00985 #endif
00986         )
00987 #else /* !HAVE_POLL_H */
00988     if (p.revents == POLLOUT)
00989 #endif /* !HAVE_POLL_H */
00990     {
00991         XML_SOCKLEN_T len;
00992 
00993         len = sizeof(status);
00994 #ifdef SO_ERROR
00995         if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char *) &status, &len) <
00996             0) {
00997             /* Solaris error code */
00998             __xmlIOErr(XML_FROM_HTTP, 0, "getsockopt failed\n");
00999             return INVALID_SOCKET;
01000         }
01001 #endif
01002         if (status) {
01003             __xmlIOErr(XML_FROM_HTTP, 0,
01004                        "Error connecting to remote host");
01005             closesocket(s);
01006             errno = status;
01007             return INVALID_SOCKET;
01008         }
01009     } else {
01010         /* pbm */
01011         __xmlIOErr(XML_FROM_HTTP, 0, "select failed\n");
01012         closesocket(s);
01013         return INVALID_SOCKET;
01014     }
01015 
01016     return (s);
01017 }
01018 
01030 static SOCKET
01031 xmlNanoHTTPConnectHost(const char *host, int port)
01032 {
01033     struct hostent *h;
01034     struct sockaddr *addr = NULL;
01035     struct in_addr ia;
01036     struct sockaddr_in sockin;
01037 
01038 #ifdef SUPPORT_IP6
01039     struct in6_addr ia6;
01040     struct sockaddr_in6 sockin6;
01041 #endif
01042     int i;
01043     SOCKET s;
01044 
01045     memset (&sockin, 0, sizeof(sockin));
01046 #ifdef SUPPORT_IP6
01047     memset (&sockin6, 0, sizeof(sockin6));
01048 #endif
01049 
01050 #if !defined(HAVE_GETADDRINFO) && defined(SUPPORT_IP6) && defined(RES_USE_INET6)
01051     if (have_ipv6 ())
01052     {
01053     if (!(_res.options & RES_INIT))
01054         res_init();
01055     _res.options |= RES_USE_INET6;
01056     }
01057 #endif
01058 
01059 #if defined(HAVE_GETADDRINFO) && defined(SUPPORT_IP6) && !defined(_WIN32)
01060     if (have_ipv6 ())
01061 #endif
01062 #if defined(HAVE_GETADDRINFO) && (defined(SUPPORT_IP6) || defined(_WIN32))
01063     {
01064     int status;
01065     struct addrinfo hints, *res, *result;
01066 
01067     result = NULL;
01068     memset (&hints, 0,sizeof(hints));
01069     hints.ai_socktype = SOCK_STREAM;
01070 
01071     status = getaddrinfo (host, NULL, &hints, &result);
01072     if (status) {
01073         __xmlIOErr(XML_FROM_HTTP, 0, "getaddrinfo failed\n");
01074         return INVALID_SOCKET;
01075     }
01076 
01077     for (res = result; res; res = res->ai_next) {
01078         if (res->ai_family == AF_INET) {
01079         if (res->ai_addrlen > sizeof(sockin)) {
01080             __xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n");
01081             freeaddrinfo (result);
01082             return INVALID_SOCKET;
01083         }
01084         memcpy (&sockin, res->ai_addr, res->ai_addrlen);
01085         sockin.sin_port = htons (port);
01086         addr = (struct sockaddr *)&sockin;
01087 #ifdef SUPPORT_IP6
01088         } else if (have_ipv6 () && (res->ai_family == AF_INET6)) {
01089         if (res->ai_addrlen > sizeof(sockin6)) {
01090             __xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n");
01091             freeaddrinfo (result);
01092             return INVALID_SOCKET;
01093         }
01094         memcpy (&sockin6, res->ai_addr, res->ai_addrlen);
01095         sockin6.sin6_port = htons (port);
01096         addr = (struct sockaddr *)&sockin6;
01097 #endif
01098         } else
01099         continue;              /* for */
01100 
01101         s = xmlNanoHTTPConnectAttempt (addr);
01102         if (s != INVALID_SOCKET) {
01103         freeaddrinfo (result);
01104         return (s);
01105         }
01106     }
01107 
01108     if (result)
01109         freeaddrinfo (result);
01110     }
01111 #endif
01112 #if defined(HAVE_GETADDRINFO) && defined(SUPPORT_IP6) && !defined(_WIN32)
01113     else
01114 #endif
01115 #if !defined(HAVE_GETADDRINFO) || !defined(_WIN32)
01116     {
01117     h = gethostbyname (host);
01118     if (h == NULL) {
01119 
01120 /*
01121  * Okay, I got fed up by the non-portability of this error message
01122  * extraction code. it work on Linux, if it work on your platform
01123  * and one want to enable it, send me the defined(foobar) needed
01124  */
01125 #if defined(HAVE_NETDB_H) && defined(HOST_NOT_FOUND) && defined(linux)
01126         const char *h_err_txt = "";
01127 
01128         switch (h_errno) {
01129         case HOST_NOT_FOUND:
01130             h_err_txt = "Authoritive host not found";
01131             break;
01132 
01133         case TRY_AGAIN:
01134             h_err_txt =
01135             "Non-authoritive host not found or server failure.";
01136             break;
01137 
01138         case NO_RECOVERY:
01139             h_err_txt =
01140             "Non-recoverable errors:  FORMERR, REFUSED, or NOTIMP.";
01141             break;
01142 
01143         case NO_ADDRESS:
01144             h_err_txt =
01145             "Valid name, no data record of requested type.";
01146             break;
01147 
01148         default:
01149             h_err_txt = "No error text defined.";
01150             break;
01151         }
01152         __xmlIOErr(XML_FROM_HTTP, 0, h_err_txt);
01153 #else
01154         __xmlIOErr(XML_FROM_HTTP, 0, "Failed to resolve host");
01155 #endif
01156         return INVALID_SOCKET;
01157     }
01158 
01159     for (i = 0; h->h_addr_list[i]; i++) {
01160         if (h->h_addrtype == AF_INET) {
01161         /* A records (IPv4) */
01162         if ((unsigned int) h->h_length > sizeof(ia)) {
01163             __xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n");
01164             return INVALID_SOCKET;
01165         }
01166         memcpy (&ia, h->h_addr_list[i], h->h_length);
01167         sockin.sin_family = h->h_addrtype;
01168         sockin.sin_addr = ia;
01169         sockin.sin_port = (u_short)htons ((unsigned short)port);
01170         addr = (struct sockaddr *) &sockin;
01171 #ifdef SUPPORT_IP6
01172         } else if (have_ipv6 () && (h->h_addrtype == AF_INET6)) {
01173         /* AAAA records (IPv6) */
01174         if ((unsigned int) h->h_length > sizeof(ia6)) {
01175             __xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n");
01176             return INVALID_SOCKET;
01177         }
01178         memcpy (&ia6, h->h_addr_list[i], h->h_length);
01179         sockin6.sin6_family = h->h_addrtype;
01180         sockin6.sin6_addr = ia6;
01181         sockin6.sin6_port = htons (port);
01182         addr = (struct sockaddr *) &sockin6;
01183 #endif
01184         } else
01185         break;              /* for */
01186 
01187         s = xmlNanoHTTPConnectAttempt (addr);
01188         if (s != INVALID_SOCKET)
01189         return (s);
01190     }
01191     }
01192 #endif
01193 
01194 #ifdef DEBUG_HTTP
01195     xmlGenericError(xmlGenericErrorContext,
01196                     "xmlNanoHTTPConnectHost:  unable to connect to '%s'.\n",
01197                     host);
01198 #endif
01199     return INVALID_SOCKET;
01200 }
01201 
01202 
01216 void*
01217 xmlNanoHTTPOpen(const char *URL, char **contentType) {
01218     if (contentType != NULL) *contentType = NULL;
01219     return(xmlNanoHTTPMethod(URL, NULL, NULL, contentType, NULL, 0));
01220 }
01221 
01236 void*
01237 xmlNanoHTTPOpenRedir(const char *URL, char **contentType, char **redir) {
01238     if (contentType != NULL) *contentType = NULL;
01239     if (redir != NULL) *redir = NULL;
01240     return(xmlNanoHTTPMethodRedir(URL, NULL, NULL, contentType, redir, NULL,0));
01241 }
01242 
01255 int
01256 xmlNanoHTTPRead(void *ctx, void *dest, int len) {
01257     xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr) ctx;
01258 #ifdef HAVE_ZLIB_H
01259     int bytes_read = 0;
01260     int orig_avail_in;
01261     int z_ret;
01262 #endif
01263 
01264     if (ctx == NULL) return(-1);
01265     if (dest == NULL) return(-1);
01266     if (len <= 0) return(0);
01267 
01268 #ifdef HAVE_ZLIB_H
01269     if (ctxt->usesGzip == 1) {
01270         if (ctxt->strm == NULL) return(0);
01271  
01272         ctxt->strm->next_out = dest;
01273         ctxt->strm->avail_out = len;
01274     ctxt->strm->avail_in = ctxt->inptr - ctxt->inrptr;
01275 
01276         while (ctxt->strm->avail_out > 0 &&
01277            (ctxt->strm->avail_in > 0 || xmlNanoHTTPRecv(ctxt) > 0)) {
01278             orig_avail_in = ctxt->strm->avail_in =
01279                 ctxt->inptr - ctxt->inrptr - bytes_read;
01280             ctxt->strm->next_in = BAD_CAST (ctxt->inrptr + bytes_read);
01281 
01282             z_ret = inflate(ctxt->strm, Z_NO_FLUSH);
01283             bytes_read += orig_avail_in - ctxt->strm->avail_in;
01284 
01285             if (z_ret != Z_OK) break;
01286     }
01287 
01288         ctxt->inrptr += bytes_read;
01289         return(len - ctxt->strm->avail_out);
01290     }
01291 #endif
01292 
01293     while (ctxt->inptr - ctxt->inrptr < len) {
01294         if (xmlNanoHTTPRecv(ctxt) <= 0) break;
01295     }
01296     if (ctxt->inptr - ctxt->inrptr < len)
01297         len = ctxt->inptr - ctxt->inrptr;
01298     memcpy(dest, ctxt->inrptr, len);
01299     ctxt->inrptr += len;
01300     return(len);
01301 }
01302 
01310 void
01311 xmlNanoHTTPClose(void *ctx) {
01312     xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr) ctx;
01313 
01314     if (ctx == NULL) return;
01315 
01316     xmlNanoHTTPFreeCtxt(ctxt);
01317 }
01318 
01337 void*
01338 xmlNanoHTTPMethodRedir(const char *URL, const char *method, const char *input,
01339                   char **contentType, char **redir,
01340           const char *headers, int ilen ) {
01341     xmlNanoHTTPCtxtPtr ctxt;
01342     char *bp, *p;
01343     int blen;
01344     SOCKET ret;
01345     int nbRedirects = 0;
01346     char *redirURL = NULL;
01347 #ifdef DEBUG_HTTP
01348     int xmt_bytes;
01349 #endif
01350     
01351     if (URL == NULL) return(NULL);
01352     if (method == NULL) method = "GET";
01353     xmlNanoHTTPInit();
01354 
01355 retry:
01356     if (redirURL == NULL)
01357     ctxt = xmlNanoHTTPNewCtxt(URL);
01358     else {
01359     ctxt = xmlNanoHTTPNewCtxt(redirURL);
01360     ctxt->location = xmlMemStrdup(redirURL);
01361     }
01362 
01363     if ( ctxt == NULL ) {
01364     return ( NULL );
01365     }
01366 
01367     if ((ctxt->protocol == NULL) || (strcmp(ctxt->protocol, "http"))) {
01368     __xmlIOErr(XML_FROM_HTTP, XML_HTTP_URL_SYNTAX, "Not a valid HTTP URI");
01369         xmlNanoHTTPFreeCtxt(ctxt);
01370     if (redirURL != NULL) xmlFree(redirURL);
01371         return(NULL);
01372     }
01373     if (ctxt->hostname == NULL) {
01374     __xmlIOErr(XML_FROM_HTTP, XML_HTTP_UNKNOWN_HOST,
01375                "Failed to identify host in URI");
01376         xmlNanoHTTPFreeCtxt(ctxt);
01377     if (redirURL != NULL) xmlFree(redirURL);
01378         return(NULL);
01379     }
01380     if (proxy) {
01381     blen = strlen(ctxt->hostname) * 2 + 16;
01382     ret = xmlNanoHTTPConnectHost(proxy, proxyPort);
01383     }
01384     else {
01385     blen = strlen(ctxt->hostname);
01386     ret = xmlNanoHTTPConnectHost(ctxt->hostname, ctxt->port);
01387     }
01388     if (ret == INVALID_SOCKET) {
01389         xmlNanoHTTPFreeCtxt(ctxt);
01390     if (redirURL != NULL) xmlFree(redirURL);
01391         return(NULL);
01392     }
01393     ctxt->fd = ret;
01394 
01395     if (input == NULL)
01396     ilen = 0;
01397     else
01398     blen += 36;
01399 
01400     if (headers != NULL)
01401     blen += strlen(headers) + 2;
01402     if (contentType && *contentType)
01403     /* reserve for string plus 'Content-Type: \r\n" */
01404     blen += strlen(*contentType) + 16;
01405     if (ctxt->query != NULL)
01406     /* 1 for '?' */
01407     blen += strlen(ctxt->query) + 1;
01408     blen += strlen(method) + strlen(ctxt->path) + 24;
01409 #ifdef HAVE_ZLIB_H
01410     /* reserve for possible 'Accept-Encoding: gzip' string */
01411     blen += 23;
01412 #endif
01413     if (ctxt->port != 80) {
01414     /* reserve space for ':xxxxx', incl. potential proxy */
01415     if (proxy)
01416         blen += 12;
01417     else
01418         blen += 6;
01419     }
01420     bp = (char*)xmlMallocAtomic(blen);
01421     if ( bp == NULL ) {
01422         xmlNanoHTTPFreeCtxt( ctxt );
01423     xmlHTTPErrMemory("allocating header buffer");
01424     return ( NULL );
01425     }
01426 
01427     p = bp;
01428 
01429     if (proxy) {
01430     if (ctxt->port != 80) {
01431         p += snprintf( p, blen - (p - bp), "%s http://%s:%d%s", 
01432             method, ctxt->hostname,
01433             ctxt->port, ctxt->path );
01434     }
01435     else 
01436         p += snprintf( p, blen - (p - bp), "%s http://%s%s", method,
01437                 ctxt->hostname, ctxt->path);
01438     }
01439     else
01440     p += snprintf( p, blen - (p - bp), "%s %s", method, ctxt->path);
01441 
01442     if (ctxt->query != NULL)
01443     p += snprintf( p, blen - (p - bp), "?%s", ctxt->query);
01444 
01445     if (ctxt->port == 80) {
01446         p += snprintf( p, blen - (p - bp), " HTTP/1.0\r\nHost: %s\r\n", 
01447             ctxt->hostname);
01448     } else {
01449         p += snprintf( p, blen - (p - bp), " HTTP/1.0\r\nHost: %s:%d\r\n",
01450             ctxt->hostname, ctxt->port);
01451     }
01452 
01453 #ifdef HAVE_ZLIB_H
01454     p += snprintf(p, blen - (p - bp), "Accept-Encoding: gzip\r\n");
01455 #endif
01456 
01457     if (contentType != NULL && *contentType) 
01458     p += snprintf(p, blen - (p - bp), "Content-Type: %s\r\n", *contentType);
01459 
01460     if (headers != NULL)
01461     p += snprintf( p, blen - (p - bp), "%s", headers );
01462 
01463     if (input != NULL)
01464     snprintf(p, blen - (p - bp), "Content-Length: %d\r\n\r\n", ilen );
01465     else
01466     snprintf(p, blen - (p - bp), "\r\n");
01467 
01468 #ifdef DEBUG_HTTP
01469     xmlGenericError(xmlGenericErrorContext,
01470         "-> %s%s", proxy? "(Proxy) " : "", bp);
01471     if ((blen -= strlen(bp)+1) < 0)
01472     xmlGenericError(xmlGenericErrorContext,
01473         "ERROR: overflowed buffer by %d bytes\n", -blen);
01474 #endif
01475     ctxt->outptr = ctxt->out = bp;
01476     ctxt->state = XML_NANO_HTTP_WRITE;
01477     blen = strlen( ctxt->out );
01478 #ifdef DEBUG_HTTP
01479     xmt_bytes = xmlNanoHTTPSend(ctxt, ctxt->out, blen );
01480     if ( xmt_bytes != blen )
01481         xmlGenericError( xmlGenericErrorContext,
01482             "xmlNanoHTTPMethodRedir:  Only %d of %d %s %s\n",
01483             xmt_bytes, blen,
01484             "bytes of HTTP headers sent to host",
01485             ctxt->hostname );
01486 #else
01487     xmlNanoHTTPSend(ctxt, ctxt->out, blen );
01488 #endif
01489 
01490     if ( input != NULL ) {
01491 #ifdef DEBUG_HTTP
01492         xmt_bytes = xmlNanoHTTPSend( ctxt, input, ilen );
01493 
01494     if ( xmt_bytes != ilen )
01495         xmlGenericError( xmlGenericErrorContext,
01496                 "xmlNanoHTTPMethodRedir:  Only %d of %d %s %s\n",
01497             xmt_bytes, ilen,
01498             "bytes of HTTP content sent to host",
01499             ctxt->hostname );
01500 #else
01501     xmlNanoHTTPSend( ctxt, input, ilen );
01502 #endif
01503     }
01504 
01505     ctxt->state = XML_NANO_HTTP_READ;
01506 
01507     while ((p = xmlNanoHTTPReadLine(ctxt)) != NULL) {
01508         if (*p == 0) {
01509         ctxt->content = ctxt->inrptr;
01510         xmlFree(p);
01511         break;
01512     }
01513     xmlNanoHTTPScanAnswer(ctxt, p);
01514 
01515 #ifdef DEBUG_HTTP
01516     xmlGenericError(xmlGenericErrorContext, "<- %s\n", p);
01517 #endif
01518         xmlFree(p);
01519     }
01520 
01521     if ((ctxt->location != NULL) && (ctxt->returnValue >= 300) &&
01522         (ctxt->returnValue < 400)) {
01523 #ifdef DEBUG_HTTP
01524     xmlGenericError(xmlGenericErrorContext,
01525         "\nRedirect to: %s\n", ctxt->location);
01526 #endif
01527     while ( xmlNanoHTTPRecv(ctxt) > 0 ) ;
01528         if (nbRedirects < XML_NANO_HTTP_MAX_REDIR) {
01529         nbRedirects++;
01530         if (redirURL != NULL)
01531         xmlFree(redirURL);
01532         redirURL = xmlMemStrdup(ctxt->location);
01533         xmlNanoHTTPFreeCtxt(ctxt);
01534         goto retry;
01535     }
01536     xmlNanoHTTPFreeCtxt(ctxt);
01537     if (redirURL != NULL) xmlFree(redirURL);
01538 #ifdef DEBUG_HTTP
01539     xmlGenericError(xmlGenericErrorContext,
01540         "xmlNanoHTTPMethodRedir: Too many redirects, aborting ...\n");
01541 #endif
01542     return(NULL);
01543     }
01544 
01545     if (contentType != NULL) {
01546     if (ctxt->contentType != NULL)
01547         *contentType = xmlMemStrdup(ctxt->contentType);
01548     else
01549         *contentType = NULL;
01550     }
01551 
01552     if ((redir != NULL) && (redirURL != NULL)) {
01553     *redir = redirURL;
01554     } else {
01555     if (redirURL != NULL)
01556         xmlFree(redirURL);
01557     if (redir != NULL)
01558         *redir = NULL;
01559     }
01560 
01561 #ifdef DEBUG_HTTP
01562     if (ctxt->contentType != NULL)
01563     xmlGenericError(xmlGenericErrorContext,
01564         "\nCode %d, content-type '%s'\n\n",
01565            ctxt->returnValue, ctxt->contentType);
01566     else
01567     xmlGenericError(xmlGenericErrorContext,
01568         "\nCode %d, no content-type\n\n",
01569            ctxt->returnValue);
01570 #endif
01571 
01572     return((void *) ctxt);
01573 }
01574 
01592 void*
01593 xmlNanoHTTPMethod(const char *URL, const char *method, const char *input,
01594                   char **contentType, const char *headers, int ilen) {
01595     return(xmlNanoHTTPMethodRedir(URL, method, input, contentType,
01596                           NULL, headers, ilen));
01597 }
01598 
01612 int
01613 xmlNanoHTTPFetch(const char *URL, const char *filename, char **contentType) {
01614     void *ctxt = NULL;
01615     char *buf = NULL;
01616     int fd;
01617     int len;
01618     
01619     if (filename == NULL) return(-1);
01620     ctxt = xmlNanoHTTPOpen(URL, contentType);
01621     if (ctxt == NULL) return(-1);
01622 
01623     if (!strcmp(filename, "-")) 
01624         fd = 0;
01625     else {
01626         fd = open(filename, O_CREAT | O_WRONLY, 00644);
01627     if (fd < 0) {
01628         xmlNanoHTTPClose(ctxt);
01629         if ((contentType != NULL) && (*contentType != NULL)) {
01630             xmlFree(*contentType);
01631         *contentType = NULL;
01632         }
01633         return(-1);
01634     }
01635     }
01636 
01637     xmlNanoHTTPFetchContent( ctxt, &buf, &len );
01638     if ( len > 0 ) {
01639     write(fd, buf, len);
01640     }
01641 
01642     xmlNanoHTTPClose(ctxt);
01643     close(fd);
01644     return(0);
01645 }
01646 
01647 #ifdef LIBXML_OUTPUT_ENABLED
01648 
01658 int
01659 xmlNanoHTTPSave(void *ctxt, const char *filename) {
01660     char *buf = NULL;
01661     int fd;
01662     int len;
01663     
01664     if ((ctxt == NULL) || (filename == NULL)) return(-1);
01665 
01666     if (!strcmp(filename, "-")) 
01667         fd = 0;
01668     else {
01669         fd = open(filename, O_CREAT | O_WRONLY, 0666);
01670     if (fd < 0) {
01671         xmlNanoHTTPClose(ctxt);
01672         return(-1);
01673     }
01674     }
01675 
01676     xmlNanoHTTPFetchContent( ctxt, &buf, &len );
01677     if ( len > 0 ) {
01678     write(fd, buf, len);
01679     }
01680 
01681     xmlNanoHTTPClose(ctxt);
01682     close(fd);
01683     return(0);
01684 }
01685 #endif /* LIBXML_OUTPUT_ENABLED */
01686 
01695 int
01696 xmlNanoHTTPReturnCode(void *ctx) {
01697     xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr) ctx;
01698 
01699     if (ctxt == NULL) return(-1);
01700 
01701     return(ctxt->returnValue);
01702 }
01703 
01713 const char *
01714 xmlNanoHTTPAuthHeader(void *ctx) {
01715     xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr) ctx;
01716 
01717     if (ctxt == NULL) return(NULL);
01718 
01719     return(ctxt->authHeader);
01720 }
01721 
01732 int
01733 xmlNanoHTTPContentLength( void * ctx ) {
01734     xmlNanoHTTPCtxtPtr  ctxt = (xmlNanoHTTPCtxtPtr)ctx;
01735 
01736     return ( ( ctxt == NULL ) ? -1 : ctxt->ContentLength );
01737 }
01738 
01747 const char *
01748 xmlNanoHTTPRedir( void * ctx ) {
01749     xmlNanoHTTPCtxtPtr  ctxt = (xmlNanoHTTPCtxtPtr)ctx;
01750 
01751     return ( ( ctxt == NULL ) ? NULL : ctxt->location );
01752 }
01753 
01762 const char *
01763 xmlNanoHTTPEncoding( void * ctx ) {
01764     xmlNanoHTTPCtxtPtr  ctxt = (xmlNanoHTTPCtxtPtr)ctx;
01765 
01766     return ( ( ctxt == NULL ) ? NULL : ctxt->encoding );
01767 }
01768 
01777 const char *
01778 xmlNanoHTTPMimeType( void * ctx ) {
01779     xmlNanoHTTPCtxtPtr  ctxt = (xmlNanoHTTPCtxtPtr)ctx;
01780 
01781     return ( ( ctxt == NULL ) ? NULL : ctxt->mimeType );
01782 }
01783 
01796 static int
01797 xmlNanoHTTPFetchContent( void * ctx, char ** ptr, int * len ) {
01798     xmlNanoHTTPCtxtPtr  ctxt = (xmlNanoHTTPCtxtPtr)ctx;
01799 
01800     int         rc = 0;
01801     int         cur_lgth;
01802     int         rcvd_lgth;
01803     int         dummy_int;
01804     char *      dummy_ptr = NULL;
01805 
01806     /*  Dummy up return input parameters if not provided  */
01807 
01808     if ( len == NULL )
01809         len = &dummy_int;
01810 
01811     if ( ptr == NULL )
01812         ptr = &dummy_ptr;
01813 
01814     /*  But can't work without the context pointer  */
01815 
01816     if ( ( ctxt == NULL ) || ( ctxt->content == NULL ) ) {
01817         *len = 0;
01818     *ptr = NULL;
01819     return ( -1 );
01820     }
01821 
01822     rcvd_lgth = ctxt->inptr - ctxt->content;
01823 
01824     while ( (cur_lgth = xmlNanoHTTPRecv( ctxt )) > 0 ) {
01825 
01826     rcvd_lgth += cur_lgth;
01827     if ( (ctxt->ContentLength > 0) && (rcvd_lgth >= ctxt->ContentLength) )
01828         break;
01829     }
01830 
01831     *ptr = ctxt->content;
01832     *len = rcvd_lgth;
01833 
01834     if ( ( ctxt->ContentLength > 0 ) && ( rcvd_lgth < ctxt->ContentLength ) )
01835         rc = -1;
01836     else if ( rcvd_lgth == 0 )
01837     rc = -1;
01838 
01839     return ( rc );
01840 }
01841 
01842 #ifdef STANDALONE
01843 int main(int argc, char **argv) {
01844     char *contentType = NULL;
01845 
01846     if (argv[1] != NULL) {
01847     if (argv[2] != NULL) 
01848         xmlNanoHTTPFetch(argv[1], argv[2], &contentType);
01849         else
01850         xmlNanoHTTPFetch(argv[1], "-", &contentType);
01851     if (contentType != NULL) xmlFree(contentType);
01852     } else {
01853         xmlGenericError(xmlGenericErrorContext,
01854         "%s: minimal HTTP GET implementation\n", argv[0]);
01855         xmlGenericError(xmlGenericErrorContext,
01856         "\tusage %s [ URL [ filename ] ]\n", argv[0]);
01857     }
01858     xmlNanoHTTPCleanup();
01859     xmlMemoryDump();
01860     return(0);
01861 }
01862 #endif /* STANDALONE */
01863 #else /* !LIBXML_HTTP_ENABLED */
01864 #ifdef STANDALONE
01865 #include <stdio.h>
01866 int main(int argc, char **argv) {
01867     xmlGenericError(xmlGenericErrorContext,
01868         "%s : HTTP support not compiled in\n", argv[0]);
01869     return(0);
01870 }
01871 #endif /* STANDALONE */
01872 #endif /* LIBXML_HTTP_ENABLED */
01873 #define bottom_nanohttp
01874 #include "elfgcchack.h"

Generated on Sat May 26 2012 04:33:19 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.