📄 nanohttp.c
字号:
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.
*/
void
xmlNanoHTTPClose(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;
if (ctxt->query != NULL)
blen += strlen(ctxt->query) + 1;
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);
if (ctxt->query != NULL)
p += snprintf( p, blen - (p - bp), "?%s", ctxt->query);
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
*/
int
xmlNanoHTTPFetch(const char *URL, const char *filename, char **contentType) {
void *ctxt = NULL;
char *buf = NULL;
int fd;
int len;
if (filename == NULL) return(-1);
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.
*/
int
xmlNanoHTTPSave(void *ctxt, const char *filename) {
char *buf = NULL;
int fd;
int len;
if ((ctxt == NULL) || (filename == 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.
*/
int
xmlNanoHTTPReturnCode(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.
*/
int
xmlNanoHTTPContentLength( 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.
*/
static int
xmlNanoHTTPFetchContent( 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 STANDALONE
int 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 */
#define bottom_nanohttp
#include "elfgcchack.h"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -