Commit a840b692 authored by Daniel Veillard's avatar Daniel Veillard

Fixed the HTTP<->parser interraction, which should fix 2 long standing

* include/libxml/nanohttp.h include/libxml/parserInternals.h
  include/libxml/xmlIO.h nanohttp.c parserInternals.c xmlIO.c:
  Fixed the HTTP<->parser interraction, which should fix 2 long
  standing bugs #104790 and #124054 , this also fix the fact that
  HTTP error code (> 400) should not generate data, we usually
  don't want to parse the HTML error information instead of the
  resource looked at.
Daniel
parent fc60fc20
Sun Oct 19 15:31:43 CEST 2003 Daniel Veillard <daniel@veillard.com>
* include/libxml/nanohttp.h include/libxml/parserInternals.h
include/libxml/xmlIO.h nanohttp.c parserInternals.c xmlIO.c:
Fixed the HTTP<->parser interraction, which should fix 2 long
standing bugs #104790 and #124054 , this also fix the fact that
HTTP error code (> 400) should not generate data, we usually
don't want to parse the HTML error information instead of the
resource looked at.
Sun Oct 19 19:20:48 HKT 2003 William Brack <wbrack@mmm.com.hk>
* doc/Makefile.am: enhanced the installation of tutorial files
......
......@@ -53,9 +53,11 @@ XMLPUBFUN int XMLCALL
XMLPUBFUN const char * XMLCALL
xmlNanoHTTPAuthHeader (void *ctx);
XMLPUBFUN const char * XMLCALL
xmlNanoHTTPRedir (void * ctx);
xmlNanoHTTPRedir (void *ctx);
XMLPUBFUN const char * XMLCALL
xmlNanoHTTPEncoding (void * ctx);
xmlNanoHTTPEncoding (void *ctx);
XMLPUBFUN const char * XMLCALL
xmlNanoHTTPMimeType (void *ctx);
XMLPUBFUN int XMLCALL
xmlNanoHTTPRead (void *ctx,
void *dest,
......
......@@ -271,8 +271,21 @@ XMLPUBFUN int XMLCALL
xmlCharEncoding enc);
XMLPUBFUN int XMLCALL
xmlSwitchToEncoding (xmlParserCtxtPtr ctxt,
xmlCharEncodingHandlerPtr handler);
xmlCharEncodingHandlerPtr handler);
XMLPUBFUN int XMLCALL
xmlSwitchInputEncoding (xmlParserCtxtPtr ctxt,
xmlParserInputPtr input,
xmlCharEncodingHandlerPtr handler);
#ifdef IN_LIBXML
/* internal error reporting */
XMLPUBFUN void XMLCALL
__xmlErrEncoding (xmlParserCtxtPtr ctxt,
xmlParserErrors error,
const char *msg,
const xmlChar * str1,
const xmlChar * str2);
#endif
/**
* Entities
*/
......
......@@ -260,6 +260,9 @@ XMLPUBFUN void * XMLCALL
XMLPUBFUN void XMLCALL
xmlRegisterHTTPPostCallbacks (void );
#endif
XMLPUBFUN xmlParserInputPtr XMLCALL
xmlCheckHTTPInput (xmlParserCtxtPtr ctxt,
xmlParserInputPtr ret);
/*
* A predefined entity loader disabling network accesses
......
......@@ -150,6 +150,7 @@ typedef struct xmlNanoHTTPCtxt {
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;
......@@ -530,6 +531,7 @@ xmlNanoHTTPFreeCtxt(xmlNanoHTTPCtxtPtr ctxt) {
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;
......@@ -737,7 +739,7 @@ xmlNanoHTTPReadLine(xmlNanoHTTPCtxtPtr ctxt) {
* Try to extract useful informations from the server answer.
* We currently parse and process:
* - The HTTP revision/ return code
* - The Content-Type
* - The Content-Type, Mime-Type and charset used
* - The Location for redirect processing.
*
* Returns -1 in case of failure, the file descriptor number otherwise
......@@ -781,16 +783,56 @@ xmlNanoHTTPScanAnswer(xmlNanoHTTPCtxtPtr ctxt, const char *line) {
if ((*cur != 0) && (*cur != ' ') && (*cur != '\t')) return;
ctxt->returnValue = ret;
} else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"Content-Type:", 13)) {
const xmlChar *charset, *last, *mime;
cur += 13;
while ((*cur == ' ') || (*cur == '\t')) cur++;
if (ctxt->contentType != NULL)
xmlFree(ctxt->contentType);
ctxt->contentType = xmlMemStrdup(cur);
mime = (const xmlChar *) cur;
last = mime;
while ((*last != 0) && (*last != ' ') && (*last != '\t') &&
(*last != ';') && (*last != ','))
last++;
if (ctxt->mimeType != NULL)
xmlFree(ctxt->mimeType);
ctxt->mimeType = (char *) xmlStrndup(mime, last - mime);
charset = xmlStrstr(BAD_CAST ctxt->contentType, BAD_CAST "charset=");
if (charset != NULL) {
charset += 8;
last = charset;
while ((*last != 0) && (*last != ' ') && (*last != '\t') &&
(*last != ';') && (*last != ','))
last++;
if (ctxt->encoding != NULL)
xmlFree(ctxt->encoding);
ctxt->encoding = (char *) xmlStrndup(charset, last - charset);
}
} else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"ContentType:", 12)) {
const xmlChar *charset, *last, *mime;
cur += 12;
if (ctxt->contentType != NULL) return;
while ((*cur == ' ') || (*cur == '\t')) cur++;
ctxt->contentType = xmlMemStrdup(cur);
mime = (const xmlChar *) cur;
last = mime;
while ((*last != 0) && (*last != ' ') && (*last != '\t') &&
(*last != ';') && (*last != ','))
last++;
if (ctxt->mimeType != NULL)
xmlFree(ctxt->mimeType);
ctxt->mimeType = (char *) xmlStrndup(mime, last - mime);
charset = xmlStrstr(BAD_CAST ctxt->contentType, BAD_CAST "charset=");
if (charset != NULL) {
charset += 8;
last = charset;
while ((*last != 0) && (*last != ' ') && (*last != '\t') &&
(*last != ';') && (*last != ','))
last++;
if (ctxt->encoding != NULL)
xmlFree(ctxt->encoding);
ctxt->encoding = (char *) xmlStrndup(charset, last - charset);
}
} else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"Location:", 9)) {
cur += 9;
while ((*cur == ' ') || (*cur == '\t')) cur++;
......@@ -1227,6 +1269,7 @@ retry:
ctxt = xmlNanoHTTPNewCtxt(URL);
else {
ctxt = xmlNanoHTTPNewCtxt(redirURL);
ctxt->location = xmlMemStrdup(redirURL);
}
if ( ctxt == NULL ) {
......@@ -1608,6 +1651,21 @@ xmlNanoHTTPEncoding( void * 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 = ctx;
return ( ( ctxt == NULL ) ? NULL : ctxt->mimeType );
}
/**
* xmlNanoHTTPFetchContent:
* @ctx: the HTTP context
......
This diff is collapsed.
......@@ -2961,6 +2961,80 @@ xmlParserGetDirectory(const char *filename) {
* *
****************************************************************/
/**
* xmlCheckHTTPInput:
* @ctxt: an XML parser context
* @ret: an XML parser input
*
* Check an input in case it was created from an HTTP stream, in that
* case it will handle encoding and update of the base URL in case of
* redirection. It also checks for HTTP errors in which case the input
* is cleanly freed up and an appropriate error is raised in context
*
* Returns the input or NULL in case of HTTP error.
*/
xmlParserInputPtr
xmlCheckHTTPInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr ret) {
#ifdef LIBXML_HTTP_ENABLED
if ((ret != NULL) && (ret->buf != NULL) &&
(ret->buf->readcallback == xmlIOHTTPRead) &&
(ret->buf->context != NULL)) {
const char *encoding;
const char *redir;
const char *mime;
int code;
code = xmlNanoHTTPReturnCode(ret->buf->context);
if (code >= 400) {
/* fatal error */
if (ret->filename != NULL)
xmlLoaderErr(ctxt, "failed to load HTTP resource \"%s\"\n",
(const char *) ret->filename);
else
xmlLoaderErr(ctxt, "failed to load HTTP resource\n", NULL);
xmlFreeInputStream(ret);
ret = NULL;
} else {
mime = xmlNanoHTTPMimeType(ret->buf->context);
if ((xmlStrstr(BAD_CAST mime, BAD_CAST "/xml")) ||
(xmlStrstr(BAD_CAST mime, BAD_CAST "+xml"))) {
encoding = xmlNanoHTTPEncoding(ret->buf->context);
if (encoding != NULL) {
xmlCharEncodingHandlerPtr handler;
handler = xmlFindCharEncodingHandler(encoding);
if (handler != NULL) {
xmlSwitchInputEncoding(ctxt, ret, handler);
} else {
__xmlErrEncoding(ctxt, XML_ERR_UNKNOWN_ENCODING,
"Unknown encoding %s",
BAD_CAST encoding, NULL);
}
if (ret->encoding == NULL)
ret->encoding = xmlStrdup(BAD_CAST encoding);
}
#if 0
} else if (xmlStrstr(BAD_CAST mime, BAD_CAST "html")) {
#endif
}
redir = xmlNanoHTTPRedir(ret->buf->context);
if (redir != NULL) {
if (ret->filename != NULL)
xmlFree((xmlChar *) ret->filename);
if (ret->directory != NULL) {
xmlFree((xmlChar *) ret->directory);
ret->directory = NULL;
}
ret->filename =
(char *) xmlStrdup((const xmlChar *) redir);
}
}
}
#endif
return(ret);
}
static int xmlSysIDExists(const char *URL) {
#ifdef HAVE_STAT
int ret;
......@@ -3001,19 +3075,20 @@ static int xmlSysIDExists(const char *URL) {
*
* Returns a new allocated xmlParserInputPtr, or NULL.
*/
static
xmlParserInputPtr
static xmlParserInputPtr
xmlDefaultExternalEntityLoader(const char *URL, const char *ID,
xmlParserCtxtPtr ctxt) {
xmlParserCtxtPtr ctxt)
{
xmlParserInputPtr ret = NULL;
xmlChar *resource = NULL;
#ifdef LIBXML_CATALOG_ENABLED
xmlCatalogAllow pref;
#endif
#ifdef DEBUG_EXTERNAL_ENTITIES
xmlGenericError(xmlGenericErrorContext,
"xmlDefaultExternalEntityLoader(%s, xxx)\n", URL);
"xmlDefaultExternalEntityLoader(%s, xxx)\n", URL);
#endif
#ifdef LIBXML_CATALOG_ENABLED
/*
......@@ -3023,87 +3098,71 @@ xmlDefaultExternalEntityLoader(const char *URL, const char *ID,
pref = xmlCatalogGetDefaults();
if ((pref != XML_CATA_ALLOW_NONE) && (!xmlSysIDExists(URL))) {
/*
* Do a local lookup
*/
if ((ctxt->catalogs != NULL) &&
((pref == XML_CATA_ALLOW_ALL) ||
(pref == XML_CATA_ALLOW_DOCUMENT))) {
resource = xmlCatalogLocalResolve(ctxt->catalogs,
(const xmlChar *)ID,
(const xmlChar *)URL);
/*
* Do a local lookup
*/
if ((ctxt->catalogs != NULL) &&
((pref == XML_CATA_ALLOW_ALL) ||
(pref == XML_CATA_ALLOW_DOCUMENT))) {
resource = xmlCatalogLocalResolve(ctxt->catalogs,
(const xmlChar *) ID,
(const xmlChar *) URL);
}
/*
* Try a global lookup
*/
if ((resource == NULL) &&
((pref == XML_CATA_ALLOW_ALL) ||
(pref == XML_CATA_ALLOW_GLOBAL))) {
resource = xmlCatalogResolve((const xmlChar *)ID,
(const xmlChar *)URL);
}
if ((resource == NULL) && (URL != NULL))
resource = xmlStrdup((const xmlChar *) URL);
/*
* TODO: do an URI lookup on the reference
*/
if ((resource != NULL) && (!xmlSysIDExists((const char *)resource))) {
xmlChar *tmp = NULL;
/*
* Try a global lookup
*/
if ((resource == NULL) &&
((pref == XML_CATA_ALLOW_ALL) ||
(pref == XML_CATA_ALLOW_GLOBAL))) {
resource = xmlCatalogResolve((const xmlChar *) ID,
(const xmlChar *) URL);
}
if ((resource == NULL) && (URL != NULL))
resource = xmlStrdup((const xmlChar *) URL);
if ((ctxt->catalogs != NULL) &&
((pref == XML_CATA_ALLOW_ALL) ||
(pref == XML_CATA_ALLOW_DOCUMENT))) {
tmp = xmlCatalogLocalResolveURI(ctxt->catalogs, resource);
}
if ((tmp == NULL) &&
((pref == XML_CATA_ALLOW_ALL) ||
(pref == XML_CATA_ALLOW_GLOBAL))) {
tmp = xmlCatalogResolveURI(resource);
}
/*
* TODO: do an URI lookup on the reference
*/
if ((resource != NULL)
&& (!xmlSysIDExists((const char *) resource))) {
xmlChar *tmp = NULL;
if ((ctxt->catalogs != NULL) &&
((pref == XML_CATA_ALLOW_ALL) ||
(pref == XML_CATA_ALLOW_DOCUMENT))) {
tmp = xmlCatalogLocalResolveURI(ctxt->catalogs, resource);
}
if ((tmp == NULL) &&
((pref == XML_CATA_ALLOW_ALL) ||
(pref == XML_CATA_ALLOW_GLOBAL))) {
tmp = xmlCatalogResolveURI(resource);
}
if (tmp != NULL) {
xmlFree(resource);
resource = tmp;
}
}
if (tmp != NULL) {
xmlFree(resource);
resource = tmp;
}
}
}
#endif
if (resource == NULL)
resource = (xmlChar *) URL;
resource = (xmlChar *) URL;
if (resource == NULL) {
if (ID == NULL)
ID = "NULL";
xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n", ID);
return(NULL);
if (ID == NULL)
ID = "NULL";
xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n", ID);
return (NULL);
}
ret = xmlNewInputFromFile(ctxt, (const char *)resource);
ret = xmlNewInputFromFile(ctxt, (const char *) resource);
if (ret == NULL) {
xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n",
(const char *) resource);
return(NULL);
}
if ((ret->buf != NULL) && (ret->buf->readcallback == xmlIOHTTPRead)) {
const char *encoding;
const char *redir;
encoding = xmlNanoHTTPEncoding(ret->buf->context);
redir = xmlNanoHTTPRedir(ret->buf->context);
if (redir != NULL) {
if (ret->filename != NULL)
xmlFree((xmlChar *) ret->filename);
if (ret->directory != NULL) {
xmlFree((xmlChar *) ret->directory);
ret->directory = NULL;
}
ret->filename = (char *) xmlStrdup((const xmlChar *)redir);
}
xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n",
(const char *) resource);
}
if ((resource != NULL) && (resource != (xmlChar *) URL))
xmlFree(resource);
return(ret);
xmlFree(resource);
return (ret);
}
static xmlExternalEntityLoader xmlCurrentExternalEntityLoader =
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment