📄 nanohttp.c.svn-base
字号:
/** * xmlNanoHTTPOpenRedir: * @URL: The URL to load * @contentType: if available the Content-Type information will be * returned at that location * @redir: if available the redirected URL will be returned * * This function try to open a connection to the indicated resource * via HTTP GET. * * Returns NULL in case of failure, otherwise a request handler. * The contentType, if provided must be freed by the caller */void*xmlNanoHTTPOpenRedir(const char *URL, char **contentType, char **redir) { if (contentType != NULL) *contentType = NULL; if (redir != NULL) *redir = NULL; return(xmlNanoHTTPMethodRedir(URL, NULL, NULL, contentType, redir, NULL,0));}/** * xmlNanoHTTPRead: * @ctx: the HTTP context * @dest: a buffer * @len: the buffer length * * This function tries to read @len bytes from the existing HTTP connection * and saves them in @dest. This is a blocking call. * * Returns the number of byte read. 0 is an indication of an end of connection. * -1 indicates a parameter error. */intxmlNanoHTTPRead(void *ctx, void *dest, int len) { xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr) ctx; if (ctx == NULL) return(-1); if (dest == NULL) return(-1); if (len <= 0) return(0); while (ctxt->inptr - ctxt->inrptr < len) { if (xmlNanoHTTPRecv(ctxt) <= 0) break; } if (ctxt->inptr - ctxt->inrptr < len) len = ctxt->inptr - ctxt->inrptr; memcpy(dest, ctxt->inrptr, len); ctxt->inrptr += len; return(len);}/** * xmlNanoHTTPClose: * @ctx: the HTTP context * * This function closes an HTTP context, it ends up the connection and * free all data related to it. */voidxmlNanoHTTPClose(void *ctx) { xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr) ctx; if (ctx == NULL) return; xmlNanoHTTPFreeCtxt(ctxt);}/** * xmlNanoHTTPMethodRedir: * @URL: The URL to load * @method: the HTTP method to use * @input: the input string if any * @contentType: the Content-Type information IN and OUT * @redir: the redirected URL OUT * @headers: the extra headers * @ilen: input length * * This function try to open a connection to the indicated resource * via HTTP using the given @method, adding the given extra headers * and the input buffer for the request content. * * Returns NULL in case of failure, otherwise a request handler. * The contentType, or redir, if provided must be freed by the caller */void*xmlNanoHTTPMethodRedir(const char *URL, const char *method, const char *input, char **contentType, char **redir, const char *headers, int ilen ) { xmlNanoHTTPCtxtPtr ctxt; char *bp, *p; int blen, ret; int head; int nbRedirects = 0; char *redirURL = NULL;#ifdef DEBUG_HTTP int xmt_bytes;#endif if (URL == NULL) return(NULL); if (method == NULL) method = "GET"; xmlNanoHTTPInit();retry: if (redirURL == NULL) ctxt = xmlNanoHTTPNewCtxt(URL); else { ctxt = xmlNanoHTTPNewCtxt(redirURL); ctxt->location = xmlMemStrdup(redirURL); } if ( ctxt == NULL ) { return ( NULL ); } if ((ctxt->protocol == NULL) || (strcmp(ctxt->protocol, "http"))) { __xmlIOErr(XML_FROM_HTTP, XML_HTTP_URL_SYNTAX, "Not a valid HTTP URI"); xmlNanoHTTPFreeCtxt(ctxt); if (redirURL != NULL) xmlFree(redirURL); return(NULL); } if (ctxt->hostname == NULL) { __xmlIOErr(XML_FROM_HTTP, XML_HTTP_UNKNOWN_HOST, "Failed to identify host in URI"); xmlNanoHTTPFreeCtxt(ctxt); if (redirURL != NULL) xmlFree(redirURL); return(NULL); } if (proxy) { blen = strlen(ctxt->hostname) * 2 + 16; ret = xmlNanoHTTPConnectHost(proxy, proxyPort); } else { blen = strlen(ctxt->hostname); ret = xmlNanoHTTPConnectHost(ctxt->hostname, ctxt->port); } if (ret < 0) { xmlNanoHTTPFreeCtxt(ctxt); if (redirURL != NULL) xmlFree(redirURL); return(NULL); } ctxt->fd = ret; if (input == NULL) ilen = 0; else blen += 36; if (headers != NULL) blen += strlen(headers) + 2; if (contentType && *contentType) blen += strlen(*contentType) + 16; blen += strlen(method) + strlen(ctxt->path) + 24; bp = (char*)xmlMallocAtomic(blen); if ( bp == NULL ) { xmlNanoHTTPFreeCtxt( ctxt ); xmlHTTPErrMemory("allocating header buffer"); return ( NULL ); } p = bp; if (proxy) { if (ctxt->port != 80) { p += snprintf( p, blen - (p - bp), "%s http://%s:%d%s", method, ctxt->hostname, ctxt->port, ctxt->path ); } else p += snprintf( p, blen - (p - bp), "%s http://%s%s", method, ctxt->hostname, ctxt->path); } else p += snprintf( p, blen - (p - bp), "%s %s", method, ctxt->path); p += snprintf( p, blen - (p - bp), " HTTP/1.0\r\nHost: %s\r\n", ctxt->hostname); if (contentType != NULL && *contentType) p += snprintf(p, blen - (p - bp), "Content-Type: %s\r\n", *contentType); if (headers != NULL) p += snprintf( p, blen - (p - bp), "%s", headers ); if (input != NULL) snprintf(p, blen - (p - bp), "Content-Length: %d\r\n\r\n", ilen ); else snprintf(p, blen - (p - bp), "\r\n");#ifdef DEBUG_HTTP xmlGenericError(xmlGenericErrorContext, "-> %s%s", proxy? "(Proxy) " : "", bp); if ((blen -= strlen(bp)+1) < 0) xmlGenericError(xmlGenericErrorContext, "ERROR: overflowed buffer by %d bytes\n", -blen);#endif ctxt->outptr = ctxt->out = bp; ctxt->state = XML_NANO_HTTP_WRITE; blen = strlen( ctxt->out );#ifdef DEBUG_HTTP xmt_bytes = xmlNanoHTTPSend(ctxt, ctxt->out, blen ); if ( xmt_bytes != blen ) xmlGenericError( xmlGenericErrorContext, "xmlNanoHTTPMethodRedir: Only %d of %d %s %s\n", xmt_bytes, blen, "bytes of HTTP headers sent to host", ctxt->hostname );#else xmlNanoHTTPSend(ctxt, ctxt->out, blen );#endif if ( input != NULL ) {#ifdef DEBUG_HTTP xmt_bytes = xmlNanoHTTPSend( ctxt, input, ilen ); if ( xmt_bytes != ilen ) xmlGenericError( xmlGenericErrorContext, "xmlNanoHTTPMethodRedir: Only %d of %d %s %s\n", xmt_bytes, ilen, "bytes of HTTP content sent to host", ctxt->hostname );#else xmlNanoHTTPSend( ctxt, input, ilen );#endif } ctxt->state = XML_NANO_HTTP_READ; head = 1; while ((p = xmlNanoHTTPReadLine(ctxt)) != NULL) { if (head && (*p == 0)) { head = 0; ctxt->content = ctxt->inrptr; xmlFree(p); break; } xmlNanoHTTPScanAnswer(ctxt, p);#ifdef DEBUG_HTTP xmlGenericError(xmlGenericErrorContext, "<- %s\n", p);#endif xmlFree(p); } if ((ctxt->location != NULL) && (ctxt->returnValue >= 300) && (ctxt->returnValue < 400)) {#ifdef DEBUG_HTTP xmlGenericError(xmlGenericErrorContext, "\nRedirect to: %s\n", ctxt->location);#endif while ( xmlNanoHTTPRecv(ctxt) > 0 ) ; if (nbRedirects < XML_NANO_HTTP_MAX_REDIR) { nbRedirects++; if (redirURL != NULL) xmlFree(redirURL); redirURL = xmlMemStrdup(ctxt->location); xmlNanoHTTPFreeCtxt(ctxt); goto retry; } xmlNanoHTTPFreeCtxt(ctxt); if (redirURL != NULL) xmlFree(redirURL);#ifdef DEBUG_HTTP xmlGenericError(xmlGenericErrorContext, "xmlNanoHTTPMethodRedir: Too many redirects, aborting ...\n");#endif return(NULL); } if (contentType != NULL) { if (ctxt->contentType != NULL) *contentType = xmlMemStrdup(ctxt->contentType); else *contentType = NULL; } if ((redir != NULL) && (redirURL != NULL)) { *redir = redirURL; } else { if (redirURL != NULL) xmlFree(redirURL); if (redir != NULL) *redir = NULL; }#ifdef DEBUG_HTTP if (ctxt->contentType != NULL) xmlGenericError(xmlGenericErrorContext, "\nCode %d, content-type '%s'\n\n", ctxt->returnValue, ctxt->contentType); else xmlGenericError(xmlGenericErrorContext, "\nCode %d, no content-type\n\n", ctxt->returnValue);#endif return((void *) ctxt);}/** * xmlNanoHTTPMethod: * @URL: The URL to load * @method: the HTTP method to use * @input: the input string if any * @contentType: the Content-Type information IN and OUT * @headers: the extra headers * @ilen: input length * * This function try to open a connection to the indicated resource * via HTTP using the given @method, adding the given extra headers * and the input buffer for the request content. * * Returns NULL in case of failure, otherwise a request handler. * The contentType, if provided must be freed by the caller */void*xmlNanoHTTPMethod(const char *URL, const char *method, const char *input, char **contentType, const char *headers, int ilen) { return(xmlNanoHTTPMethodRedir(URL, method, input, contentType, NULL, headers, ilen));}/** * xmlNanoHTTPFetch: * @URL: The URL to load * @filename: the filename where the content should be saved * @contentType: if available the Content-Type information will be * returned at that location * * This function try to fetch the indicated resource via HTTP GET * and save it's content in the file. * * Returns -1 in case of failure, 0 incase of success. The contentType, * if provided must be freed by the caller */intxmlNanoHTTPFetch(const char *URL, const char *filename, char **contentType) { void *ctxt = NULL; char *buf = NULL; int fd; int len; ctxt = xmlNanoHTTPOpen(URL, contentType); if (ctxt == NULL) return(-1); if (!strcmp(filename, "-")) fd = 0; else { fd = open(filename, O_CREAT | O_WRONLY, 00644); if (fd < 0) { xmlNanoHTTPClose(ctxt); if ((contentType != NULL) && (*contentType != NULL)) { xmlFree(*contentType); *contentType = NULL; } return(-1); } } xmlNanoHTTPFetchContent( ctxt, &buf, &len ); if ( len > 0 ) { write(fd, buf, len); } xmlNanoHTTPClose(ctxt); close(fd); return(0);}#ifdef LIBXML_OUTPUT_ENABLED/** * xmlNanoHTTPSave: * @ctxt: the HTTP context * @filename: the filename where the content should be saved * * This function saves the output of the HTTP transaction to a file * It closes and free the context at the end * * Returns -1 in case of failure, 0 incase of success. */intxmlNanoHTTPSave(void *ctxt, const char *filename) { char *buf = NULL; int fd; int len; if (ctxt == NULL) return(-1); if (!strcmp(filename, "-")) fd = 0; else { fd = open(filename, O_CREAT | O_WRONLY); if (fd < 0) { xmlNanoHTTPClose(ctxt); return(-1); } } xmlNanoHTTPFetchContent( ctxt, &buf, &len ); if ( len > 0 ) { write(fd, buf, len); } xmlNanoHTTPClose(ctxt); close(fd); return(0);}#endif /* LIBXML_OUTPUT_ENABLED *//** * xmlNanoHTTPReturnCode: * @ctx: the HTTP context * * Get the latest HTTP return code received * * Returns the HTTP return code for the request. */intxmlNanoHTTPReturnCode(void *ctx) { xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr) ctx; if (ctxt == NULL) return(-1); return(ctxt->returnValue);}/** * xmlNanoHTTPAuthHeader: * @ctx: the HTTP context * * Get the authentication header of an HTTP context * * Returns the stashed value of the WWW-Authenticate or Proxy-Authenticate * header. */const char *xmlNanoHTTPAuthHeader(void *ctx) { xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr) ctx; if (ctxt == NULL) return(NULL); return(ctxt->authHeader);}/** * xmlNanoHTTPContentLength: * @ctx: the HTTP context * * Provides the specified content length from the HTTP header. * * Return the specified content length from the HTTP header. Note that * a value of -1 indicates that the content length element was not included in * the response header. */intxmlNanoHTTPContentLength( void * ctx ) { xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr)ctx; return ( ( ctxt == NULL ) ? -1 : ctxt->ContentLength );}/** * xmlNanoHTTPRedir: * @ctx: the HTTP context * * Provides the specified redirection URL if available from the HTTP header. * * Return the specified redirection URL or NULL if not redirected. */const char *xmlNanoHTTPRedir( void * ctx ) { xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr)ctx; return ( ( ctxt == NULL ) ? NULL : ctxt->location );}/** * xmlNanoHTTPEncoding: * @ctx: the HTTP context * * Provides the specified encoding if specified in the HTTP headers. * * Return the specified encoding or NULL if not available */const char *xmlNanoHTTPEncoding( void * ctx ) { xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr)ctx; return ( ( ctxt == NULL ) ? NULL : ctxt->encoding );}/** * xmlNanoHTTPMimeType: * @ctx: the HTTP context * * Provides the specified Mime-Type if specified in the HTTP headers. * * Return the specified Mime-Type or NULL if not available */const char *xmlNanoHTTPMimeType( void * ctx ) { xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr)ctx; return ( ( ctxt == NULL ) ? NULL : ctxt->mimeType );}/** * xmlNanoHTTPFetchContent: * @ctx: the HTTP context * @ptr: pointer to set to the content buffer. * @len: integer pointer to hold the length of the content * * Check if all the content was read * * Returns 0 if all the content was read and available, returns * -1 if received content length was less than specified or an error * occurred. */intxmlNanoHTTPFetchContent( void * ctx, char ** ptr, int * len ) { xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr)ctx; int rc = 0; int cur_lgth; int rcvd_lgth; int dummy_int; char * dummy_ptr = NULL; /* Dummy up return input parameters if not provided */ if ( len == NULL ) len = &dummy_int; if ( ptr == NULL ) ptr = &dummy_ptr; /* But can't work without the context pointer */ if ( ( ctxt == NULL ) || ( ctxt->content == NULL ) ) { *len = 0; *ptr = NULL; return ( -1 ); } rcvd_lgth = ctxt->inptr - ctxt->content; while ( (cur_lgth = xmlNanoHTTPRecv( ctxt )) > 0 ) { rcvd_lgth += cur_lgth; if ( (ctxt->ContentLength > 0) && (rcvd_lgth >= ctxt->ContentLength) ) break; } *ptr = ctxt->content; *len = rcvd_lgth; if ( ( ctxt->ContentLength > 0 ) && ( rcvd_lgth < ctxt->ContentLength ) ) rc = -1; else if ( rcvd_lgth == 0 ) rc = -1; return ( rc );}#ifdef STANDALONEint main(int argc, char **argv) { char *contentType = NULL; if (argv[1] != NULL) { if (argv[2] != NULL) xmlNanoHTTPFetch(argv[1], argv[2], &contentType); else xmlNanoHTTPFetch(argv[1], "-", &contentType); if (contentType != NULL) xmlFree(contentType); } else { xmlGenericError(xmlGenericErrorContext, "%s: minimal HTTP GET implementation\n", argv[0]); xmlGenericError(xmlGenericErrorContext, "\tusage %s [ URL [ filename ] ]\n", argv[0]); } xmlNanoHTTPCleanup(); xmlMemoryDump(); return(0);}#endif /* STANDALONE */#else /* !LIBXML_HTTP_ENABLED */#ifdef STANDALONE#include <stdio.h>int main(int argc, char **argv) { xmlGenericError(xmlGenericErrorContext, "%s : HTTP support not compiled in\n", argv[0]); return(0);}#endif /* STANDALONE */#endif /* LIBXML_HTTP_ENABLED */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -