⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nanohttp.c

📁 libxml,在UNIX/LINUX下非常重要的一个库,为XML相关应用提供方便.目前上载的是最新版本,若要取得最新版本,请参考里面的readme.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * nanohttp.c: minimalist HTTP GET implementation to fetch external subsets. *             focuses on size, streamability, reentrancy and portability * * This is clearly not a general purpose HTTP implementation * If you look for one, check: *         http://www.w3.org/Library/ * * See Copyright for the status of this software. * * daniel@veillard.com */ /* TODO add compression support, Send the Accept- , and decompress on the        fly with ZLIB if found at compile-time */#define NEED_SOCKETS#define IN_LIBXML#include "libxml.h"#ifdef LIBXML_HTTP_ENABLED#include <string.h>#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef HAVE_SYS_TYPES_H#include <sys/types.h>#endif#ifdef HAVE_SYS_SOCKET_H#include <sys/socket.h>#endif#ifdef HAVE_NETINET_IN_H#include <netinet/in.h>#endif#ifdef HAVE_ARPA_INET_H#include <arpa/inet.h>#endif#ifdef HAVE_NETDB_H#include <netdb.h>#endif#ifdef HAVE_RESOLV_H#ifdef HAVE_ARPA_NAMESER_H#include <arpa/nameser.h>#endif#include <resolv.h>#endif#ifdef HAVE_FCNTL_H#include <fcntl.h> #endif#ifdef HAVE_ERRNO_H#include <errno.h>#endif#ifdef HAVE_SYS_TIME_H#include <sys/time.h>#endif#ifdef HAVE_SYS_SELECT_H#include <sys/select.h>#endif#ifdef HAVE_STRINGS_H#include <strings.h>#endif#ifdef SUPPORT_IP6#include <resolv.h>#endif#ifdef VMS#include <stropts>#define XML_SOCKLEN_T unsigned int#define SOCKET int#endif#ifdef __MINGW32__#define _WINSOCKAPI_#include <wsockcompat.h>#include <winsock2.h>#undef XML_SOCKLEN_T#define XML_SOCKLEN_T unsigned int#endif#include <libxml/globals.h>#include <libxml/xmlerror.h>#include <libxml/xmlmemory.h>#include <libxml/parser.h> /* for xmlStr(n)casecmp() */#include <libxml/nanohttp.h>#include <libxml/globals.h>#include <libxml/uri.h>/** * A couple portability macros */#ifndef _WINSOCKAPI_#ifndef __BEOS__#define closesocket(s) close(s)#endif#define SOCKET int#endif#ifdef __BEOS__#ifndef PF_INET#define PF_INET AF_INET#endif#endif#ifndef XML_SOCKLEN_T#define XML_SOCKLEN_T unsigned int#endif#ifndef SOCKET#define SOCKET int#endif#ifdef STANDALONE#define DEBUG_HTTP#define xmlStrncasecmp(a, b, n) strncasecmp((char *)a, (char *)b, n)#define xmlStrcasecmpi(a, b) strcasecmp((char *)a, (char *)b)#endif#define XML_NANO_HTTP_MAX_REDIR	10#define XML_NANO_HTTP_CHUNK	4096#define XML_NANO_HTTP_CLOSED	0#define XML_NANO_HTTP_WRITE	1#define XML_NANO_HTTP_READ	2#define XML_NANO_HTTP_NONE	4typedef struct xmlNanoHTTPCtxt {    char *protocol;	/* the protocol name */    char *hostname;	/* the host name */    int port;		/* the port */    char *path;		/* the path within the URL */    SOCKET fd;		/* the file descriptor for the socket */    int state;		/* WRITE / READ / CLOSED */    char *out;		/* buffer sent (zero terminated) */    char *outptr;	/* index within the buffer sent */    char *in;		/* the receiving buffer */    char *content;	/* the start of the content */    char *inptr;	/* the next byte to read from network */    char *inrptr;	/* the next byte to give back to the client */    int inlen;		/* len of the input buffer */    int last;		/* return code for last operation */    int returnValue;	/* the protocol return value */    int ContentLength;  /* specified content length from HTTP header */    char *contentType;	/* the MIME type for the input */    char *location;	/* the new URL in case of redirect */    char *authHeader;	/* contents of {WWW,Proxy}-Authenticate header */    char *encoding;	/* encoding extracted from the contentType */    char *mimeType;	/* Mime-Type extracted from the contentType */} xmlNanoHTTPCtxt, *xmlNanoHTTPCtxtPtr;static int initialized = 0;static char *proxy = NULL;	 /* the proxy name if any */static int proxyPort;	/* the proxy port if any */static unsigned int timeout = 60;/* the select() timeout in seconds */static int xmlNanoHTTPFetchContent( void * ctx, char ** ptr, int * len );/** * xmlHTTPErrMemory: * @extra:  extra informations * * Handle an out of memory condition */static voidxmlHTTPErrMemory(const char *extra){    __xmlSimpleError(XML_FROM_HTTP, XML_ERR_NO_MEMORY, NULL, NULL, extra);}/** * A portability function */static int socket_errno(void) {#ifdef _WINSOCKAPI_    return(WSAGetLastError());#else    return(errno);#endif}#ifdef SUPPORT_IP6staticint have_ipv6(void) {    int s;    s = socket (AF_INET6, SOCK_STREAM, 0);    if (s != -1) {	close (s);	return (1);    }    return (0);}#endif/** * xmlNanoHTTPInit: * * Initialize the HTTP protocol layer. * Currently it just checks for proxy informations */voidxmlNanoHTTPInit(void) {    const char *env;#ifdef _WINSOCKAPI_    WSADATA wsaData;    #endif    if (initialized)	return;#ifdef _WINSOCKAPI_    if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)	return;#endif    if (proxy == NULL) {	proxyPort = 80;	env = getenv("no_proxy");	if (env && ((env[0] == '*') && (env[1] == 0)))	    goto done;	env = getenv("http_proxy");	if (env != NULL) {	    xmlNanoHTTPScanProxy(env);	    goto done;	}	env = getenv("HTTP_PROXY");	if (env != NULL) {	    xmlNanoHTTPScanProxy(env);	    goto done;	}    }done:    initialized = 1;}/** * xmlNanoHTTPCleanup: * * Cleanup the HTTP protocol layer. */voidxmlNanoHTTPCleanup(void) {    if (proxy != NULL)	xmlFree(proxy);#ifdef _WINSOCKAPI_    if (initialized)	WSACleanup();#endif    initialized = 0;    return;}/** * xmlNanoHTTPScanURL: * @ctxt:  an HTTP context * @URL:  The URL used to initialize the context * * (Re)Initialize an HTTP context by parsing the URL and finding * the protocol host port and path it indicates. */static voidxmlNanoHTTPScanURL(xmlNanoHTTPCtxtPtr ctxt, const char *URL) {    xmlURIPtr uri;    /*     * Clear any existing data from the context     */    if (ctxt->protocol != NULL) {         xmlFree(ctxt->protocol);	ctxt->protocol = NULL;    }    if (ctxt->hostname != NULL) {         xmlFree(ctxt->hostname);	ctxt->hostname = NULL;    }    if (ctxt->path != NULL) {         xmlFree(ctxt->path);	ctxt->path = NULL;    }    if (URL == NULL) return;    uri = xmlParseURI(URL);    if (uri == NULL)	return;    if ((uri->scheme == NULL) || (uri->server == NULL)) {	xmlFreeURI(uri);	return;    }        ctxt->protocol = xmlMemStrdup(uri->scheme);    ctxt->hostname = xmlMemStrdup(uri->server);    if (uri->path != NULL)	ctxt->path = xmlMemStrdup(uri->path);    else	ctxt->path = xmlMemStrdup("/");    if (uri->port != 0)	ctxt->port = uri->port;    xmlFreeURI(uri);}/** * xmlNanoHTTPScanProxy: * @URL:  The proxy URL used to initialize the proxy context * * (Re)Initialize the HTTP Proxy context by parsing the URL and finding * the protocol host port it indicates. * Should be like http://myproxy/ or http://myproxy:3128/ * A NULL URL cleans up proxy informations. */voidxmlNanoHTTPScanProxy(const char *URL) {    xmlURIPtr uri;    if (proxy != NULL) {         xmlFree(proxy);	proxy = NULL;    }    proxyPort = 0;#ifdef DEBUG_HTTP    if (URL == NULL)	xmlGenericError(xmlGenericErrorContext,		"Removing HTTP proxy info\n");    else	xmlGenericError(xmlGenericErrorContext,		"Using HTTP proxy %s\n", URL);#endif    if (URL == NULL) return;    uri = xmlParseURI(URL);    if ((uri == NULL) || (uri->scheme == NULL) ||	(strcmp(uri->scheme, "http")) || (uri->server == NULL)) {	__xmlIOErr(XML_FROM_HTTP, XML_HTTP_URL_SYNTAX, "Syntax Error\n");	if (uri != NULL)	    xmlFreeURI(uri);	return;    }        proxy = xmlMemStrdup(uri->server);    if (uri->port != 0)	proxyPort = uri->port;    xmlFreeURI(uri);}/** * xmlNanoHTTPNewCtxt: * @URL:  The URL used to initialize the context * * Allocate and initialize a new HTTP context. * * Returns an HTTP context or NULL in case of error. */static xmlNanoHTTPCtxtPtrxmlNanoHTTPNewCtxt(const char *URL) {    xmlNanoHTTPCtxtPtr ret;    ret = (xmlNanoHTTPCtxtPtr) xmlMalloc(sizeof(xmlNanoHTTPCtxt));    if (ret == NULL) {        xmlHTTPErrMemory("allocating context");        return(NULL);    }    memset(ret, 0, sizeof(xmlNanoHTTPCtxt));    ret->port = 80;    ret->returnValue = 0;    ret->fd = -1;    ret->ContentLength = -1;    xmlNanoHTTPScanURL(ret, URL);    return(ret);}/** * xmlNanoHTTPFreeCtxt: * @ctxt:  an HTTP context * * Frees the context after closing the connection. */static voidxmlNanoHTTPFreeCtxt(xmlNanoHTTPCtxtPtr ctxt) {    if (ctxt == NULL) return;    if (ctxt->hostname != NULL) xmlFree(ctxt->hostname);    if (ctxt->protocol != NULL) xmlFree(ctxt->protocol);    if (ctxt->path != NULL) xmlFree(ctxt->path);    if (ctxt->out != NULL) xmlFree(ctxt->out);    if (ctxt->in != NULL) xmlFree(ctxt->in);    if (ctxt->contentType != NULL) xmlFree(ctxt->contentType);    if (ctxt->encoding != NULL) xmlFree(ctxt->encoding);    if (ctxt->mimeType != NULL) xmlFree(ctxt->mimeType);    if (ctxt->location != NULL) xmlFree(ctxt->location);    if (ctxt->authHeader != NULL) xmlFree(ctxt->authHeader);    ctxt->state = XML_NANO_HTTP_NONE;    if (ctxt->fd >= 0) closesocket(ctxt->fd);    ctxt->fd = -1;    xmlFree(ctxt);}/** * xmlNanoHTTPSend: * @ctxt:  an HTTP context * * Send the input needed to initiate the processing on the server side * Returns number of bytes sent or -1 on error. */static intxmlNanoHTTPSend(xmlNanoHTTPCtxtPtr ctxt, const char * xmt_ptr, int outlen) {    int 	total_sent = 0;    if ( (ctxt->state & XML_NANO_HTTP_WRITE) && (xmt_ptr != NULL ) ) {        while (total_sent < outlen) {            int nsent = send(ctxt->fd, xmt_ptr + total_sent,                                      outlen - total_sent, 0);            if (nsent>0)                total_sent += nsent;	    else if ( ( nsent == -1 ) && #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK	    	      ( socket_errno( ) != EAGAIN ) &&#endif		        ( socket_errno( ) != EWOULDBLOCK ) ) {		__xmlIOErr(XML_FROM_HTTP, 0, "send failed\n");		if ( total_sent == 0 )		    total_sent = -1;		break;	    }	    else {	        /*		**  No data sent		**  Since non-blocking sockets are used, wait for 		**  socket to be writable or default timeout prior		**  to retrying.		*/		struct timeval	tv;		fd_set		wfd;		tv.tv_sec = timeout;		tv.tv_usec = 0;		FD_ZERO( &wfd );		FD_SET( ctxt->fd, &wfd );		(void)select( ctxt->fd + 1, NULL, &wfd, NULL, &tv );	    }	}    }    return total_sent;}/** * xmlNanoHTTPRecv: * @ctxt:  an HTTP context * * Read information coming from the HTTP connection. * This is a blocking call (but it blocks in select(), not read()). * * Returns the number of byte read or -1 in case of error. */static intxmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt) {    fd_set rfd;    struct timeval tv;    while (ctxt->state & XML_NANO_HTTP_READ) {	if (ctxt->in == NULL) {	    ctxt->in = (char *) xmlMallocAtomic(65000 * sizeof(char));	    if (ctxt->in == NULL) {		xmlHTTPErrMemory("allocating input");	        ctxt->last = -1;		return(-1);	    }	    ctxt->inlen = 65000;	    ctxt->inptr = ctxt->content = ctxt->inrptr = ctxt->in;	}	if (ctxt->inrptr > ctxt->in + XML_NANO_HTTP_CHUNK) {	    int delta = ctxt->inrptr - ctxt->in;	    int len = ctxt->inptr - ctxt->inrptr;	    	    memmove(ctxt->in, ctxt->inrptr, len);	    ctxt->inrptr -= delta;	    ctxt->content -= delta;	    ctxt->inptr -= delta;	}        if ((ctxt->in + ctxt->inlen) < (ctxt->inptr + XML_NANO_HTTP_CHUNK)) {	    int d_inptr = ctxt->inptr - ctxt->in;	    int d_content = ctxt->content - ctxt->in;	    int d_inrptr = ctxt->inrptr - ctxt->in;	    char *	tmp_ptr = ctxt->in;	    ctxt->inlen *= 2;            ctxt->in = (char *) xmlRealloc(tmp_ptr, ctxt->inlen);	    if (ctxt->in == NULL) {		xmlHTTPErrMemory("allocating input buffer");		xmlFree( tmp_ptr );	        ctxt->last = -1;		return(-1);	    }            ctxt->inptr = ctxt->in + d_inptr;            ctxt->content = ctxt->in + d_content;            ctxt->inrptr = ctxt->in + d_inrptr;	}	ctxt->last = recv(ctxt->fd, ctxt->inptr, XML_NANO_HTTP_CHUNK, 0);	if (ctxt->last > 0) {	    ctxt->inptr += ctxt->last;	    return(ctxt->last);	}	if (ctxt->last == 0) {	    return(0);	}	if (ctxt->last == -1) {	    switch (socket_errno()) {		case EINPROGRESS:		case EWOULDBLOCK:#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK		case EAGAIN:#endif		    break;		case ECONNRESET:		case ESHUTDOWN:		    return ( 0 );		default:		    __xmlIOErr(XML_FROM_HTTP, 0, "recv failed\n");		    return(-1);	    }	}	tv.tv_sec = timeout;	tv.tv_usec = 0;	FD_ZERO(&rfd);	FD_SET(ctxt->fd, &rfd);		if ( (select(ctxt->fd+1, &rfd, NULL, NULL, &tv)<1)#if defined(EINTR)		&& (errno != EINTR)#endif	)		return(0);    }    return(0);}/**

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -