--- embedaddon/libxml2/xmlreader.c 2012/02/21 23:37:58 1.1 +++ embedaddon/libxml2/xmlreader.c 2014/06/15 19:53:29 1.1.1.3 @@ -44,6 +44,8 @@ #include #endif +#include "buf.h" + #define MAX_ERR_MSG_SIZE 64000 /* @@ -135,7 +137,7 @@ struct _xmlTextReader { int depth; /* depth of the current node */ xmlNodePtr faketext;/* fake xmlNs chld */ int preserve;/* preserve the resulting document */ - xmlBufferPtr buffer; /* used to return const xmlChar * */ + xmlBufPtr buffer; /* used to return const xmlChar * */ xmlDictPtr dict; /* the context dictionnary */ /* entity stack when traversing entities content */ @@ -152,6 +154,7 @@ struct _xmlTextReader { /* Handling of RelaxNG validation */ xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */ xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */ + int rngPreserveCtxt; /* 1 if the context was provided by the user */ int rngValidErrors;/* The number of errors detected */ xmlNodePtr rngFullNode; /* the node if RNG not progressive */ /* Handling of Schemas validation */ @@ -806,9 +809,10 @@ xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, */ static int xmlTextReaderPushData(xmlTextReaderPtr reader) { - xmlBufferPtr inbuf; + xmlBufPtr inbuf; int val, s; xmlTextReaderState oldstate; + int alloc; if ((reader->input == NULL) || (reader->input->buffer == NULL)) return(-1); @@ -816,17 +820,18 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) { oldstate = reader->state; reader->state = XML_TEXTREADER_NONE; inbuf = reader->input->buffer; + alloc = xmlBufGetAllocationScheme(inbuf); while (reader->state == XML_TEXTREADER_NONE) { - if (inbuf->use < reader->cur + CHUNK_SIZE) { + if (xmlBufUse(inbuf) < reader->cur + CHUNK_SIZE) { /* * Refill the buffer unless we are at the end of the stream */ if (reader->mode != XML_TEXTREADER_MODE_EOF) { val = xmlParserInputBufferRead(reader->input, 4096); if ((val == 0) && - (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) { - if (inbuf->use == reader->cur) { + (alloc == XML_BUFFER_ALLOC_IMMUTABLE)) { + if (xmlBufUse(inbuf) == reader->cur) { reader->mode = XML_TEXTREADER_MODE_EOF; reader->state = oldstate; } @@ -849,21 +854,23 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) { * parse by block of CHUNK_SIZE bytes, various tests show that * it's the best tradeoff at least on a 1.2GH Duron */ - if (inbuf->use >= reader->cur + CHUNK_SIZE) { + if (xmlBufUse(inbuf) >= reader->cur + CHUNK_SIZE) { val = xmlParseChunk(reader->ctxt, - (const char *) &inbuf->content[reader->cur], - CHUNK_SIZE, 0); + (const char *) xmlBufContent(inbuf) + reader->cur, + CHUNK_SIZE, 0); reader->cur += CHUNK_SIZE; - if ((val != 0) || (reader->ctxt->wellFormed == 0)) - return(-1); + if (val != 0) + reader->ctxt->wellFormed = 0; + if (reader->ctxt->wellFormed == 0) + break; } else { - s = inbuf->use - reader->cur; + s = xmlBufUse(inbuf) - reader->cur; val = xmlParseChunk(reader->ctxt, - (const char *) &inbuf->content[reader->cur], - s, 0); + (const char *) xmlBufContent(inbuf) + reader->cur, + s, 0); reader->cur += s; - if ((val != 0) || (reader->ctxt->wellFormed == 0)) - return(-1); + if (val != 0) + reader->ctxt->wellFormed = 0; break; } } @@ -872,10 +879,10 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) { * Discard the consumed input when needed and possible */ if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) { - if (inbuf->alloc != XML_BUFFER_ALLOC_IMMUTABLE) { + if (alloc != XML_BUFFER_ALLOC_IMMUTABLE) { if ((reader->cur >= 4096) && - (inbuf->use - reader->cur <= CHUNK_SIZE)) { - val = xmlBufferShrink(inbuf, reader->cur); + (xmlBufUse(inbuf) - reader->cur <= CHUNK_SIZE)) { + val = xmlBufShrink(inbuf, reader->cur); if (val >= 0) { reader->cur -= val; } @@ -889,17 +896,26 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) { */ else if (reader->mode == XML_TEXTREADER_MODE_EOF) { if (reader->state != XML_TEXTREADER_DONE) { - s = inbuf->use - reader->cur; + s = xmlBufUse(inbuf) - reader->cur; val = xmlParseChunk(reader->ctxt, - (const char *) &inbuf->content[reader->cur], - s, 1); - reader->cur = inbuf->use; + (const char *) xmlBufContent(inbuf) + reader->cur, + s, 1); + reader->cur = xmlBufUse(inbuf); reader->state = XML_TEXTREADER_DONE; - if ((val != 0) || (reader->ctxt->wellFormed == 0)) - return(-1); + if (val != 0) { + if (reader->ctxt->wellFormed) + reader->ctxt->wellFormed = 0; + else + return(-1); + } } } reader->state = oldstate; + if (reader->ctxt->wellFormed == 0) { + reader->mode = XML_TEXTREADER_MODE_EOF; + return(-1); + } + return(0); } @@ -968,7 +984,7 @@ printf("Expand failed !\n"); * xmlTextReaderValidateCData: * @reader: the xmlTextReaderPtr used * @data: pointer to the CData - * @len: lenght of the CData block in bytes. + * @len: length of the CData block in bytes. * * Push some CData for validation */ @@ -1212,6 +1228,9 @@ xmlTextReaderCollectSiblings(xmlNodePtr node) xmlBufferPtr buffer; xmlChar *ret; + if ((node == NULL) || (node->type == XML_NAMESPACE_DECL)) + return(NULL); + buffer = xmlBufferCreate(); if (buffer == NULL) return NULL; @@ -1264,8 +1283,6 @@ xmlTextReaderRead(xmlTextReaderPtr reader) { return(xmlTextReaderReadTree(reader)); if (reader->ctxt == NULL) return(-1); - if (reader->ctxt->wellFormed != 1) - return(-1); #ifdef DEBUG_READER fprintf(stderr, "\nREAD "); @@ -1392,8 +1409,7 @@ get_next_node: #endif (reader->entNr == 0) && (reader->node->prev != NULL) && - (reader->node->prev->type != XML_DTD_NODE) && - (reader->entNr == 0)) { + (reader->node->prev->type != XML_DTD_NODE)) { xmlNodePtr tmp = reader->node->prev; if ((tmp->extra & NODE_IS_PRESERVED) == 0) { xmlUnlinkNode(tmp); @@ -1442,8 +1458,7 @@ get_next_node: #endif (reader->entNr == 0) && (oldnode->type != XML_DTD_NODE) && - ((oldnode->extra & NODE_IS_PRESERVED) == 0) && - (reader->entNr == 0)) { + ((oldnode->extra & NODE_IS_PRESERVED) == 0)) { xmlUnlinkNode(oldnode); xmlTextReaderFreeNode(reader, oldnode); } @@ -1709,8 +1724,8 @@ xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTR * * Reads the contents of the current node, including child nodes and markup. * - * Returns a string containing the node and any XML content, or NULL if the - * current node cannot be serialized. The string must be deallocated + * Returns a string containing the node and any XML content, or NULL if the + * current node cannot be serialized. The string must be deallocated * by the caller. */ xmlChar * @@ -2055,7 +2070,7 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const ret->entMax = 0; ret->entNr = 0; ret->input = input; - ret->buffer = xmlBufferCreateSize(100); + ret->buffer = xmlBufCreateSize(100); if (ret->buffer == NULL) { xmlFree(ret); xmlGenericError(xmlGenericErrorContext, @@ -2064,7 +2079,7 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const } ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler)); if (ret->sax == NULL) { - xmlBufferFree(ret->buffer); + xmlBufFree(ret->buffer); xmlFree(ret); xmlGenericError(xmlGenericErrorContext, "xmlNewTextReader : malloc failed\n"); @@ -2097,12 +2112,13 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const ret->mode = XML_TEXTREADER_MODE_INITIAL; ret->node = NULL; ret->curnode = NULL; - if (ret->input->buffer->use < 4) { + if (xmlBufUse(ret->input->buffer) < 4) { xmlParserInputBufferRead(input, 4); } - if (ret->input->buffer->use >= 4) { + if (xmlBufUse(ret->input->buffer) >= 4) { ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, - (const char *) ret->input->buffer->content, 4, URI); + (const char *) xmlBufContent(ret->input->buffer), + 4, URI); ret->base = 0; ret->cur = 4; } else { @@ -2114,7 +2130,7 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const if (ret->ctxt == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlNewTextReader : malloc failed\n"); - xmlBufferFree(ret->buffer); + xmlBufFree(ret->buffer); xmlFree(ret->sax); xmlFree(ret); return(NULL); @@ -2187,7 +2203,8 @@ xmlFreeTextReader(xmlTextReaderPtr reader) { reader->rngSchemas = NULL; } if (reader->rngValidCtxt != NULL) { - xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); + if (! reader->rngPreserveCtxt) + xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); reader->rngValidCtxt = NULL; } if (reader->xsdPlug != NULL) { @@ -2243,7 +2260,7 @@ xmlFreeTextReader(xmlTextReaderPtr reader) { if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) xmlFreeParserInputBuffer(reader->input); if (reader->buffer != NULL) - xmlBufferFree(reader->buffer); + xmlBufFree(reader->buffer); if (reader->entTab != NULL) xmlFree(reader->entTab); if (reader->dict != NULL) @@ -3591,16 +3608,17 @@ xmlTextReaderConstValue(xmlTextReaderPtr reader) { (attr->children->next == NULL)) return(attr->children->content); else { - if (reader->buffer == NULL) - reader->buffer = xmlBufferCreateSize(100); if (reader->buffer == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlTextReaderSetup : malloc failed\n"); - return (NULL); - } - reader->buffer->use = 0; - xmlNodeBufGetContent(reader->buffer, node); - return(reader->buffer->content); + reader->buffer = xmlBufCreateSize(100); + if (reader->buffer == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlTextReaderSetup : malloc failed\n"); + return (NULL); + } + } else + xmlBufEmpty(reader->buffer); + xmlBufGetNodeContent(reader->buffer, node); + return(xmlBufContent(reader->buffer)); } break; } @@ -4095,9 +4113,11 @@ xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, reader->rngSchemas = NULL; } if (reader->rngValidCtxt != NULL) { - xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); + if (! reader->rngPreserveCtxt) + xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); reader->rngValidCtxt = NULL; } + reader->rngPreserveCtxt = 0; return(0); } if (reader->mode != XML_TEXTREADER_MODE_INITIAL) @@ -4107,9 +4127,11 @@ xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, reader->rngSchemas = NULL; } if (reader->rngValidCtxt != NULL) { - xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); + if (! reader->rngPreserveCtxt) + xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); reader->rngValidCtxt = NULL; } + reader->rngPreserveCtxt = 0; reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema); if (reader->rngValidCtxt == NULL) return(-1); @@ -4131,6 +4153,60 @@ xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, } /** + * xmlTextReaderLocator: + * @ctx: the xmlTextReaderPtr used + * @file: returned file information + * @line: returned line information + * + * Internal locator function for the readers + * + * Returns 0 in case the Schema validation could be (des)activated and + * -1 in case of error. + */ +static int +xmlTextReaderLocator(void *ctx, const char **file, unsigned long *line) { + xmlTextReaderPtr reader; + + if ((ctx == NULL) || ((file == NULL) && (line == NULL))) + return(-1); + + if (file != NULL) + *file = NULL; + if (line != NULL) + *line = 0; + + reader = (xmlTextReaderPtr) ctx; + if ((reader->ctxt != NULL) && (reader->ctxt->input != NULL)) { + if (file != NULL) + *file = reader->ctxt->input->filename; + if (line != NULL) + *line = reader->ctxt->input->line; + return(0); + } + if (reader->node != NULL) { + long res; + int ret = 0; + + if (line != NULL) { + res = xmlGetLineNo(reader->node); + if (res > 0) + *line = (unsigned long) res; + else + ret = -1; + } + if (file != NULL) { + xmlDocPtr doc = reader->node->doc; + if ((doc != NULL) && (doc->URL != NULL)) + *file = (const char *) doc->URL; + else + ret = -1; + } + return(ret); + } + return(-1); +} + +/** * xmlTextReaderSetSchema: * @reader: the xmlTextReaderPtr used * @schema: a precompiled Schema schema @@ -4197,6 +4273,10 @@ xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSch reader->xsdValidCtxt = NULL; return(-1); } + xmlSchemaValidateSetLocator(reader->xsdValidCtxt, + xmlTextReaderLocator, + (void *) reader); + if (reader->errorFunc != NULL) { xmlSchemaSetValidErrors(reader->xsdValidCtxt, xmlTextReaderValidityErrorRelay, @@ -4214,67 +4294,91 @@ xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSch } /** - * xmlTextReaderRelaxNGValidate: + * xmlTextReaderRelaxNGValidateInternal: * @reader: the xmlTextReaderPtr used * @rng: the path to a RelaxNG schema or NULL + * @ctxt: the RelaxNG schema validation context or NULL + * @options: options (not yet used) * * Use RelaxNG to validate the document as it is processed. * Activation is only possible before the first Read(). - * if @rng is NULL, then RelaxNG validation is deactivated. + * If both @rng and @ctxt are NULL, then RelaxNG validation is deactivated. * * Returns 0 in case the RelaxNG validation could be (de)activated and - * -1 in case of error. + * -1 in case of error. */ -int -xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) { - xmlRelaxNGParserCtxtPtr ctxt; - +static int +xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader, + const char *rng, + xmlRelaxNGValidCtxtPtr ctxt, + int options ATTRIBUTE_UNUSED) +{ if (reader == NULL) - return(-1); + return(-1); - if (rng == NULL) { - if (reader->rngValidCtxt != NULL) { + if ((rng != NULL) && (ctxt != NULL)) + return (-1); + + if (((rng != NULL) || (ctxt != NULL)) && + ((reader->mode != XML_TEXTREADER_MODE_INITIAL) || + (reader->ctxt == NULL))) + return(-1); + + /* Cleanup previous validation stuff. */ + if (reader->rngValidCtxt != NULL) { + if ( !reader->rngPreserveCtxt) xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); - reader->rngValidCtxt = NULL; - } - if (reader->rngSchemas != NULL) { - xmlRelaxNGFree(reader->rngSchemas); - reader->rngSchemas = NULL; - } - return(0); + reader->rngValidCtxt = NULL; } - if (reader->mode != XML_TEXTREADER_MODE_INITIAL) - return(-1); + reader->rngPreserveCtxt = 0; if (reader->rngSchemas != NULL) { xmlRelaxNGFree(reader->rngSchemas); reader->rngSchemas = NULL; } - if (reader->rngValidCtxt != NULL) { - xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); - reader->rngValidCtxt = NULL; + + if ((rng == NULL) && (ctxt == NULL)) { + /* We just want to deactivate the validation, so get out. */ + return(0); } - ctxt = xmlRelaxNGNewParserCtxt(rng); - if (reader->errorFunc != NULL) { - xmlRelaxNGSetParserErrors(ctxt, - xmlTextReaderValidityErrorRelay, - xmlTextReaderValidityWarningRelay, - reader); + + + if (rng != NULL) { + xmlRelaxNGParserCtxtPtr pctxt; + /* Parse the schema and create validation environment. */ + + pctxt = xmlRelaxNGNewParserCtxt(rng); + if (reader->errorFunc != NULL) { + xmlRelaxNGSetParserErrors(pctxt, + xmlTextReaderValidityErrorRelay, + xmlTextReaderValidityWarningRelay, + reader); + } + if (reader->sErrorFunc != NULL) { + xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, + xmlTextReaderValidityStructuredRelay, + reader); + } + reader->rngSchemas = xmlRelaxNGParse(pctxt); + xmlRelaxNGFreeParserCtxt(pctxt); + if (reader->rngSchemas == NULL) + return(-1); + reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas); + if (reader->rngValidCtxt == NULL) { + xmlRelaxNGFree(reader->rngSchemas); + reader->rngSchemas = NULL; + return(-1); + } + } else { + /* Use the given validation context. */ + reader->rngValidCtxt = ctxt; + reader->rngPreserveCtxt = 1; } - if (reader->sErrorFunc != NULL) { - xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, - xmlTextReaderValidityStructuredRelay, - reader); - } - reader->rngSchemas = xmlRelaxNGParse(ctxt); - xmlRelaxNGFreeParserCtxt(ctxt); - if (reader->rngSchemas == NULL) - return(-1); - reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas); - if (reader->rngValidCtxt == NULL) { - xmlRelaxNGFree(reader->rngSchemas); - reader->rngSchemas = NULL; - return(-1); - } + /* + * Redirect the validation context's error channels to use + * the reader channels. + * TODO: In case the user provides the validation context we + * could make this redirection optional. + */ if (reader->errorFunc != NULL) { xmlRelaxNGSetValidErrors(reader->rngValidCtxt, xmlTextReaderValidityErrorRelay, @@ -4387,6 +4491,9 @@ xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr r return(-1); } } + xmlSchemaValidateSetLocator(reader->xsdValidCtxt, + xmlTextReaderLocator, + (void *) reader); /* * Redirect the validation context's error channels to use * the reader channels. @@ -4447,6 +4554,46 @@ xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, c { return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0)); } + +/** + * xmlTextReaderRelaxNGValidateCtxt: + * @reader: the xmlTextReaderPtr used + * @ctxt: the RelaxNG schema validation context or NULL + * @options: options (not used yet) + * + * Use RelaxNG schema context to validate the document as it is processed. + * Activation is only possible before the first Read(). + * If @ctxt is NULL, then RelaxNG schema validation is deactivated. + * + * Returns 0 in case the schemas validation could be (de)activated and + * -1 in case of error. + */ +int +xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader, + xmlRelaxNGValidCtxtPtr ctxt, + int options) +{ + return(xmlTextReaderRelaxNGValidateInternal(reader, NULL, ctxt, options)); +} + +/** + * xmlTextReaderRelaxNGValidate: + * @reader: the xmlTextReaderPtr used + * @rng: the path to a RelaxNG schema or NULL + * + * Use RelaxNG schema to validate the document as it is processed. + * Activation is only possible before the first Read(). + * If @rng is NULL, then RelaxNG schema validation is deactivated. + * + * Returns 0 in case the schemas validation could be (de)activated and + * -1 in case of error. + */ +int +xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) +{ + return(xmlTextReaderRelaxNGValidateInternal(reader, rng, NULL, 0)); +} + #endif /** @@ -4964,7 +5111,7 @@ xmlTextReaderSetup(xmlTextReaderPtr reader, reader->allocs |= XML_TEXTREADER_INPUT; } if (reader->buffer == NULL) - reader->buffer = xmlBufferCreateSize(100); + reader->buffer = xmlBufCreateSize(100); if (reader->buffer == NULL) { xmlGenericError(xmlGenericErrorContext, "xmlTextReaderSetup : malloc failed\n"); @@ -5005,13 +5152,14 @@ xmlTextReaderSetup(xmlTextReaderPtr reader, reader->node = NULL; reader->curnode = NULL; if (input != NULL) { - if (reader->input->buffer->use < 4) { + if (xmlBufUse(reader->input->buffer) < 4) { xmlParserInputBufferRead(input, 4); } if (reader->ctxt == NULL) { - if (reader->input->buffer->use >= 4) { + if (xmlBufUse(reader->input->buffer) >= 4) { reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL, - (const char *) reader->input->buffer->content, 4, URL); + (const char *) xmlBufContent(reader->input->buffer), + 4, URL); reader->base = 0; reader->cur = 4; } else { @@ -5040,10 +5188,7 @@ xmlTextReaderSetup(xmlTextReaderPtr reader, inputStream->filename = (char *) xmlCanonicPath((const xmlChar *) URL); inputStream->buf = buf; - inputStream->base = inputStream->buf->buffer->content; - inputStream->cur = inputStream->buf->buffer->content; - inputStream->end = - &inputStream->buf->buffer->content[inputStream->buf->buffer->use]; + xmlBufResetInput(buf->buffer, inputStream); inputPush(reader->ctxt, inputStream); reader->cur = 0; @@ -5331,8 +5476,11 @@ xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCl input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, XML_CHAR_ENCODING_NONE); - if (input == NULL) + if (input == NULL) { + if (ioclose != NULL) + ioclose(ioctx); return (NULL); + } reader = xmlNewTextReader(input, URL); if (reader == NULL) { xmlFreeParserInputBuffer(input); @@ -5549,10 +5697,14 @@ xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCa input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, XML_CHAR_ENCODING_NONE); - if (input == NULL) + if (input == NULL) { + if (ioclose != NULL) + ioclose(ioctx); return (-1); + } return (xmlTextReaderSetup(reader, input, URL, encoding, options)); } + /************************************************************************ * * * Utilities *