Skip to content
Snippets Groups Projects
parser.c 430 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*
     * parser.c : an XML 1.0 parser, namespaces and validity support are mostly
     *            implemented on top of the SAX interfaces
     *
     * References:
     *   The XML specification:
     *     http://www.w3.org/TR/REC-xml
     *   Original 1.0 version:
     *     http://www.w3.org/TR/1998/REC-xml-19980210
     *   XML second edition working draft
     *     http://www.w3.org/TR/2000/WD-xml-2e-20000814
     *
     * Okay this is a big file, the parser core is around 7000 lines, then it
     * is followed by the progressive parser top routines, then the various
    
     * high level APIs to call the parser and a few miscellaneous functions.
    
     * A number of helper functions and deprecated ones have been moved to
     * parserInternals.c to reduce this file size.
     * As much as possible the functions are associated with their relative
     * production in the XML specification. A few productions defining the
    
     * different ranges of character are actually implanted either in
    
     * parserInternals.h or parserInternals.c
     * The DOM tree build is realized from the default SAX callbacks in
     * the module SAX.c.
     * The routines doing the validation checks are in valid.c and called either
    
     * from the SAX callbacks or as standalone functions using a preparsed
    
     * document.
     *
     * See Copyright for the status of this software.
     *
    
     * daniel@veillard.com
    
    /* To avoid EBCDIC trouble when parsing on zOS */
    #if defined(__MVS__)
    #pragma convert("ISO8859-1")
    #endif
    
    
    Bjorn Reese's avatar
    Bjorn Reese committed
    #include "libxml.h"
    
    
    #if defined(_WIN32)
    
    #define XML_DIR_SEP '\\'
    #else
    #define XML_DIR_SEP '/'
    #endif
    
    #include <stdlib.h>
    
    #include <limits.h>
    
    #include <string.h>
    
    #include <stddef.h>
    
    #include <ctype.h>
    #include <stdlib.h>
    
    #include <libxml/xmlmemory.h>
    
    #include <libxml/threads.h>
    #include <libxml/globals.h>
    
    #include <libxml/tree.h>
    #include <libxml/parser.h>
    #include <libxml/parserInternals.h>
    #include <libxml/valid.h>
    #include <libxml/entities.h>
    #include <libxml/xmlerror.h>
    #include <libxml/encoding.h>
    #include <libxml/xmlIO.h>
    #include <libxml/uri.h>
    
    #ifdef LIBXML_CATALOG_ENABLED
    #include <libxml/catalog.h>
    #endif
    
    #ifdef LIBXML_SCHEMAS_ENABLED
    #include <libxml/xmlschemastypes.h>
    #include <libxml/relaxng.h>
    #endif
    
    #include "buf.h"
    #include "enc.h"
    
    
    struct _xmlStartTag {
        const xmlChar *prefix;
        const xmlChar *URI;
        int line;
        int nsNr;
    };
    
    
    static void
    xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info);
    
    
    static xmlParserCtxtPtr
    xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
    	                  const xmlChar *base, xmlParserCtxtPtr pctx);
    
    
    static void xmlHaltParser(xmlParserCtxtPtr ctxt);
    
    
    static int
    xmlParseElementStart(xmlParserCtxtPtr ctxt);
    
    static void
    xmlParseElementEnd(xmlParserCtxtPtr ctxt);
    
    
    /************************************************************************
     *									*
     *	Arbitrary limits set in the parser. See XML_PARSE_HUGE		*
     *									*
     ************************************************************************/
    
    #define XML_PARSER_BIG_ENTITY 1000
    #define XML_PARSER_LOT_ENTITY 5000
    
    /*
     * XML_PARSER_NON_LINEAR is the threshold where the ratio of parsed entity
     *    replacement over the size in byte of the input indicates that you have
    
     *    and exponential behaviour. A value of 10 correspond to at least 3 entity
    
     *    replacement per byte of input.
     */
    #define XML_PARSER_NON_LINEAR 10
    
    /*
     * xmlParserEntityCheck
     *
     * Function to check non-linear entity expansion behaviour
     * This is here to detect and stop exponential linear entity expansion
     * This is not a limitation of the parser but a safety
     * boundary feature. It can be disabled with the XML_PARSE_HUGE
     * parser option.
     */
    static int
    
    xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
    
                         xmlEntityPtr ent, size_t replacement)
    
        size_t consumed = 0;
    
    
        if ((ctxt == NULL) || (ctxt->options & XML_PARSE_HUGE))
            return (0);
        if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
            return (1);
    
    Daniel Veillard's avatar
    Daniel Veillard committed
    
        /*
         * This may look absurd but is needed to detect
         * entities problems
         */
        if ((ent != NULL) && (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
    
    	(ent->content != NULL) && (ent->checked == 0) &&
    	(ctxt->errNo != XML_ERR_ENTITY_LOOP)) {
    
    	unsigned long oldnbent = ctxt->nbentities, diff;
    
    Daniel Veillard's avatar
    Daniel Veillard committed
    	xmlChar *rep;
    
    	ent->checked = 1;
    
    
    Daniel Veillard's avatar
    Daniel Veillard committed
    	rep = xmlStringDecodeEntities(ctxt, ent->content,
    				  XML_SUBSTITUTE_REF, 0, 0, 0);
    
    	if ((rep == NULL) || (ctxt->errNo == XML_ERR_ENTITY_LOOP)) {
    
    	    ent->content[0] = 0;
    	}
    
            diff = ctxt->nbentities - oldnbent + 1;
            if (diff > INT_MAX / 2)
                diff = INT_MAX / 2;
    	ent->checked = diff * 2;
    
    Daniel Veillard's avatar
    Daniel Veillard committed
    	if (rep != NULL) {
    	    if (xmlStrchr(rep, '<'))
    		ent->checked |= 1;
    	    xmlFree(rep);
    	    rep = NULL;
    	}
        }
    
    
        /*
         * Prevent entity exponential check, not just replacement while
         * parsing the DTD
         * The check is potentially costly so do that only once in a thousand
         */
        if ((ctxt->instate == XML_PARSER_DTD) && (ctxt->nbentities > 10000) &&
            (ctxt->nbentities % 1024 == 0)) {
    	for (i = 0;i < ctxt->inputNr;i++) {
    	    consumed += ctxt->inputTab[i]->consumed +
    	               (ctxt->inputTab[i]->cur - ctxt->inputTab[i]->base);
    	}
    	if (ctxt->nbentities > consumed * XML_PARSER_NON_LINEAR) {
    	    xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
    	    ctxt->instate = XML_PARSER_EOF;
    	    return (1);
    	}
    	consumed = 0;
        }
    
    
    
    
        if (replacement != 0) {
    	if (replacement < XML_MAX_TEXT_LENGTH)
    	    return(0);
    
            /*
    	 * If the volume of entity copy reaches 10 times the
    	 * amount of parsed data and over the large text threshold
    	 * then that's very likely to be an abuse.
    	 */
            if (ctxt->input != NULL) {
    	    consumed = ctxt->input->consumed +
    	               (ctxt->input->cur - ctxt->input->base);
    	}
            consumed += ctxt->sizeentities;
    
            if (replacement < XML_PARSER_NON_LINEAR * consumed)
    	    return(0);
        } else if (size != 0) {
    
            /*
             * Do the check based on the replacement size of the entity
             */
            if (size < XML_PARSER_BIG_ENTITY)
    	    return(0);
    
            /*
             * A limit on the amount of text data reasonably used
             */
            if (ctxt->input != NULL) {
                consumed = ctxt->input->consumed +
                    (ctxt->input->cur - ctxt->input->base);
            }
            consumed += ctxt->sizeentities;
    
            if ((size < XML_PARSER_NON_LINEAR * consumed) &&
    	    (ctxt->nbentities * 3 < XML_PARSER_NON_LINEAR * consumed))
                return (0);
        } else if (ent != NULL) {
            /*
             * use the number of parsed entities in the replacement
             */
    
            size = ent->checked / 2;
    
    
            /*
             * The amount of data parsed counting entities size only once
             */
            if (ctxt->input != NULL) {
                consumed = ctxt->input->consumed +
                    (ctxt->input->cur - ctxt->input->base);
            }
            consumed += ctxt->sizeentities;
    
            /*
             * Check the density of entities for the amount of data
    	 * knowing an entity reference will take at least 3 bytes
             */
            if (size * 3 < consumed * XML_PARSER_NON_LINEAR)
                return (0);
        } else {
            /*
    
    Daniel Veillard's avatar
    Daniel Veillard committed
             * strange we got no data for checking
    
    Daniel Veillard's avatar
    Daniel Veillard committed
    	if (((ctxt->lastError.code != XML_ERR_UNDECLARED_ENTITY) &&
    	     (ctxt->lastError.code != XML_WAR_UNDECLARED_ENTITY)) ||
    	    (ctxt->nbentities <= 10000))
    	    return (0);
    
        }
        xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
        return (1);
    }
    
    
     * arbitrary depth limit for the XML documents that we allow to
     * process. This is not a limitation of the parser but a safety
     * boundary feature. It can be disabled with the XML_PARSE_HUGE
     * parser option.
     */
    unsigned int xmlParserMaxDepth = 256;
    
    #define XML_PARSER_BIG_BUFFER_SIZE 300
    
    #define XML_PARSER_BUFFER_SIZE 100
    
    #define SAX_COMPAT_MODE BAD_CAST "SAX compatibility mode document"
    
    
    /**
     * XML_PARSER_CHUNK_SIZE
     *
     * When calling GROW that's the minimal amount of data
     * the parser expected to have received. It is not a hard
     * limit but an optimization when reading strings like Names
     * It is not strictly needed as long as inputs available characters
     * are followed by 0, which should be provided by the I/O level
     */
    #define XML_PARSER_CHUNK_SIZE 100
    
    
    /*
     * List of XML prefixed PI allowed by W3C specs
     */
    
    
    static const char* const xmlW3CPIs[] = {
    
        "xml-stylesheet",
    
    /* DEPR void xmlParserHandleReference(xmlParserCtxtPtr ctxt); */
    
    static xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt,
                                                  const xmlChar **str);
    
    xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
    	              xmlSAXHandlerPtr sax,
    
    		      void *user_data, int depth, const xmlChar *URL,
    
    		      const xmlChar *ID, xmlNodePtr *list);
    
    static int
    xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options,
                              const char *encoding);
    
    static void
    xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
                          xmlNodePtr lastNode);
    
    xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
    		      const xmlChar *string, void *user_data, xmlNodePtr *lst);
    
    static int
    xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity);
    
    
    /************************************************************************
     *									*
    
     *		Some factorized error routines				*
    
     *									*
     ************************************************************************/
    
    /**
     * xmlErrAttributeDup:
     * @ctxt:  an XML parser context
     * @prefix:  the attribute prefix
     * @localname:  the attribute localname
     *
     * Handle a redefinition of attribute error
     */
    static void
    xmlErrAttributeDup(xmlParserCtxtPtr ctxt, const xmlChar * prefix,
                       const xmlChar * localname)
    {
    
        if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
            (ctxt->instate == XML_PARSER_EOF))
    	return;
    
        if (ctxt != NULL)
    	ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
    
            __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
    
                            XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
    
                            (const char *) localname, NULL, NULL, 0, 0,
                            "Attribute %s redefined\n", localname);
    
            __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
    
                            XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
    
                            (const char *) prefix, (const char *) localname,
                            NULL, 0, 0, "Attribute %s:%s redefined\n", prefix,
                            localname);
    
        if (ctxt != NULL) {
    	ctxt->wellFormed = 0;
    	if (ctxt->recovery == 0)
    	    ctxt->disableSAX = 1;
        }
    
    }
    
    /**
     * xmlFatalErr:
     * @ctxt:  an XML parser context
     * @error:  the error number
     * @extra:  extra information string
     *
     * Handle a fatal parser error, i.e. violating Well-Formedness constraints
     */
    static void
    
    xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
    
        if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
            (ctxt->instate == XML_PARSER_EOF))
    	return;
    
        switch (error) {
            case XML_ERR_INVALID_HEX_CHARREF:
    
                errmsg = "CharRef: invalid hexadecimal value";
    
                errmsg = "CharRef: invalid decimal value";
    
                errmsg = "CharRef: invalid value";
    
                errmsg = "PEReference at end of document";
    
                errmsg = "PEReference in prolog";
    
                errmsg = "PEReference in epilog";
    
                errmsg = "PEReference: no name";
    
                errmsg = "PEReference: expecting ';'";
    
                errmsg = "Detected an entity reference loop";
    
                errmsg = "EntityValue: \" or ' expected";
    
                errmsg = "PEReferences forbidden in internal subset";
    
                errmsg = "EntityValue: \" or ' expected";
    
                errmsg = "AttValue: \" or ' expected";
    
                errmsg = "Unescaped '<' not allowed in attributes values";
    
                errmsg = "SystemLiteral \" or ' expected";
    
                errmsg = "Unfinished System or Public ID \" or ' expected";
    
                errmsg = "Sequence ']]>' not allowed in content";
    
                errmsg = "SYSTEM or PUBLIC, the URI is missing";
    
                errmsg = "PUBLIC, the Public Identifier is missing";
    
                errmsg = "Comment must not contain '--' (double-hyphen)";
    
                errmsg = "xmlParsePI : no target name";
    
                errmsg = "Invalid PI name";
    
                errmsg = "NOTATION: Name expected here";
    
                errmsg = "'>' required to close NOTATION declaration";
    
                errmsg = "Entity value required";
    
                errmsg = "Fragment not allowed";
                break;
    
                errmsg = "'(' required to start ATTLIST enumeration";
    
                errmsg = "NmToken expected in ATTLIST enumeration";
    
                errmsg = "')' required to finish ATTLIST enumeration";
    
                errmsg = "MixedContentDecl : '|' or ')*' expected";
    
                errmsg = "MixedContentDecl : '#PCDATA' expected";
    
            case XML_ERR_ELEMCONTENT_NOT_STARTED:
    
                errmsg = "ContentDecl : Name or '(' expected";
    
            case XML_ERR_ELEMCONTENT_NOT_FINISHED:
    
                errmsg = "ContentDecl : ',' '|' or ')' expected";
    
                    "PEReference: forbidden within markup decl in internal subset";
    
                errmsg = "expected '>'";
    
                errmsg = "XML conditional section '[' expected";
    
            case XML_ERR_EXT_SUBSET_NOT_FINISHED:
    
                errmsg = "Content error in the external subset";
    
                break;
            case XML_ERR_CONDSEC_INVALID_KEYWORD:
                errmsg =
    
                    "conditional section INCLUDE or IGNORE keyword expected";
    
                errmsg = "XML conditional section not closed";
    
                errmsg = "Text declaration '<?xml' required";
    
                errmsg = "parsing XML declaration: '?>' expected";
    
                errmsg = "external parsed entities cannot be standalone";
    
            case XML_ERR_ENTITYREF_SEMICOL_MISSING:
    
                errmsg = "EntityRef: expecting ';'";
    
                errmsg = "DOCTYPE improperly terminated";
    
                errmsg = "EndTag: '</' not found";
    
                errmsg = "expected '='";
    
                errmsg = "String not closed expecting \" or '";
    
                errmsg = "String not started expecting ' or \"";
    
                errmsg = "Invalid XML encoding name";
    
                errmsg = "standalone accepts only 'yes' or 'no'";
    
                errmsg = "Document is empty";
    
                errmsg = "Extra content at the end of the document";
    
                errmsg = "chunk is not well balanced";
    
                errmsg = "extra content at the end of well balanced chunk";
    
                errmsg = "Malformed declaration expecting version";
    
            case XML_ERR_NAME_TOO_LONG:
    
                errmsg = "Name too long use XML_PARSE_HUGE option";
    
                errmsg = "Unregistered error message";
        }
    
        if (ctxt != NULL)
    	ctxt->errNo = error;
    
        if (info == NULL) {
            __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
                            XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s\n",
                            errmsg);
        } else {
            __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
                            XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s: %s\n",
                            errmsg, info);
        }
    
        if (ctxt != NULL) {
    	ctxt->wellFormed = 0;
    	if (ctxt->recovery == 0)
    	    ctxt->disableSAX = 1;
        }
    
    /**
     * xmlFatalErrMsg:
     * @ctxt:  an XML parser context
     * @error:  the error number
     * @msg:  the error message
     *
     * Handle a fatal parser error, i.e. violating Well-Formedness constraints
     */
    
    static void LIBXML_ATTR_FORMAT(3,0)
    
    xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                   const char *msg)
    
        if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
            (ctxt->instate == XML_PARSER_EOF))
    	return;
    
        if (ctxt != NULL)
    	ctxt->errNo = error;
    
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
    
                        XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
    
        if (ctxt != NULL) {
    	ctxt->wellFormed = 0;
    	if (ctxt->recovery == 0)
    	    ctxt->disableSAX = 1;
        }
    
     * xmlWarningMsg:
     * @ctxt:  an XML parser context
     * @error:  the error number
     * @msg:  the error message
     * @str1:  extra data
     * @str2:  extra data
     *
     * Handle a warning.
     */
    
    static void LIBXML_ATTR_FORMAT(3,0)
    
    xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                  const char *msg, const xmlChar *str1, const xmlChar *str2)
    {
    
    Daniel Veillard's avatar
    Daniel Veillard committed
        xmlStructuredErrorFunc schannel = NULL;
    
        if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
            (ctxt->instate == XML_PARSER_EOF))
    	return;
    
        if ((ctxt != NULL) && (ctxt->sax != NULL) &&
            (ctxt->sax->initialized == XML_SAX2_MAGIC))
    
    Daniel Veillard's avatar
    Daniel Veillard committed
            schannel = ctxt->sax->serror;
    
        if (ctxt != NULL) {
            __xmlRaiseError(schannel,
    
                        (ctxt->sax) ? ctxt->sax->warning : NULL,
                        ctxt->userData,
    
                        ctxt, NULL, XML_FROM_PARSER, error,
                        XML_ERR_WARNING, NULL, 0,
    		    (const char *) str1, (const char *) str2, NULL, 0, 0,
    		    msg, (const char *) str1, (const char *) str2);
    
        } else {
            __xmlRaiseError(schannel, NULL, NULL,
                        ctxt, NULL, XML_FROM_PARSER, error,
                        XML_ERR_WARNING, NULL, 0,
    		    (const char *) str1, (const char *) str2, NULL, 0, 0,
    		    msg, (const char *) str1, (const char *) str2);
        }
    
    }
    
    /**
     * xmlValidityError:
     * @ctxt:  an XML parser context
     * @error:  the error number
     * @msg:  the error message
     * @str1:  extra data
     *
    
    static void LIBXML_ATTR_FORMAT(3,0)
    
    xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error,
    
                  const char *msg, const xmlChar *str1, const xmlChar *str2)
    
    Daniel Veillard's avatar
    Daniel Veillard committed
        xmlStructuredErrorFunc schannel = NULL;
    
    
        if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
            (ctxt->instate == XML_PARSER_EOF))
    	return;
    
        if (ctxt != NULL) {
    	ctxt->errNo = error;
    	if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
    	    schannel = ctxt->sax->serror;
        }
    
        if (ctxt != NULL) {
            __xmlRaiseError(schannel,
    
                        ctxt->vctxt.error, ctxt->vctxt.userData,
    
                        ctxt, NULL, XML_FROM_DTD, error,
                        XML_ERR_ERROR, NULL, 0, (const char *) str1,
    
    		    (const char *) str2, NULL, 0, 0,
    		    msg, (const char *) str1, (const char *) str2);
    
        } else {
            __xmlRaiseError(schannel, NULL, NULL,
                        ctxt, NULL, XML_FROM_DTD, error,
                        XML_ERR_ERROR, NULL, 0, (const char *) str1,
    		    (const char *) str2, NULL, 0, 0,
    		    msg, (const char *) str1, (const char *) str2);
    
     * xmlFatalErrMsgInt:
     * @ctxt:  an XML parser context
     * @error:  the error number
     * @msg:  the error message
     * @val:  an integer value
     *
     * Handle a fatal parser error, i.e. violating Well-Formedness constraints
     */
    
    static void LIBXML_ATTR_FORMAT(3,0)
    
    xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
    
        if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
            (ctxt->instate == XML_PARSER_EOF))
    	return;
    
        if (ctxt != NULL)
    	ctxt->errNo = error;
    
                        ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
                        NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
    
        if (ctxt != NULL) {
    	ctxt->wellFormed = 0;
    	if (ctxt->recovery == 0)
    	    ctxt->disableSAX = 1;
        }
    
     * xmlFatalErrMsgStrIntStr:
     * @ctxt:  an XML parser context
     * @error:  the error number
     * @msg:  the error message
     * @str1:  an string info
     * @val:  an integer value
     * @str2:  an string info
     *
     * Handle a fatal parser error, i.e. violating Well-Formedness constraints
     */
    
    static void LIBXML_ATTR_FORMAT(3,0)
    
    xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
    
                      const char *msg, const xmlChar *str1, int val,
    
        if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
            (ctxt->instate == XML_PARSER_EOF))
    	return;
    
        if (ctxt != NULL)
    	ctxt->errNo = error;
    
                        ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
                        NULL, 0, (const char *) str1, (const char *) str2,
    		    NULL, val, 0, msg, str1, val, str2);
    
        if (ctxt != NULL) {
    	ctxt->wellFormed = 0;
    	if (ctxt->recovery == 0)
    	    ctxt->disableSAX = 1;
        }
    
     * xmlFatalErrMsgStr:
     * @ctxt:  an XML parser context
     * @error:  the error number
     * @msg:  the error message
     * @val:  a string value
     *
     * Handle a fatal parser error, i.e. violating Well-Formedness constraints
     */
    
    static void LIBXML_ATTR_FORMAT(3,0)
    
    xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
    
                      const char *msg, const xmlChar * val)
    
        if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
            (ctxt->instate == XML_PARSER_EOF))
    	return;
    
        if (ctxt != NULL)
    	ctxt->errNo = error;
    
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
    
                        XML_FROM_PARSER, error, XML_ERR_FATAL,
                        NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
                        val);
    
        if (ctxt != NULL) {
    	ctxt->wellFormed = 0;
    	if (ctxt->recovery == 0)
    	    ctxt->disableSAX = 1;
        }
    
     * xmlErrMsgStr:
     * @ctxt:  an XML parser context
     * @error:  the error number
     * @msg:  the error message
     * @val:  a string value
     *
     * Handle a non fatal parser error
     */
    
    static void LIBXML_ATTR_FORMAT(3,0)
    
    xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                      const char *msg, const xmlChar * val)
    {
    
        if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
            (ctxt->instate == XML_PARSER_EOF))
    	return;
    
        if (ctxt != NULL)
    	ctxt->errNo = error;
    
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
    
                        XML_FROM_PARSER, error, XML_ERR_ERROR,
                        NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
                        val);
    }
    
    /**
    
     * xmlNsErr:
     * @ctxt:  an XML parser context
     * @error:  the error number
     * @msg:  the message
     * @info1:  extra information string
     * @info2:  extra information string
     *
     * Handle a fatal parser error, i.e. violating Well-Formedness constraints
     */
    
    static void LIBXML_ATTR_FORMAT(3,0)
    
    xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
             const char *msg,
    
             const xmlChar * info1, const xmlChar * info2,
             const xmlChar * info3)
    
        if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
            (ctxt->instate == XML_PARSER_EOF))
    	return;
    
        if (ctxt != NULL)
    	ctxt->errNo = error;
    
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
    
                        XML_ERR_ERROR, NULL, 0, (const char *) info1,
                        (const char *) info2, (const char *) info3, 0, 0, msg,
                        info1, info2, info3);
    
        if (ctxt != NULL)
    	ctxt->nsWellFormed = 0;
    
    /**
     * xmlNsWarn
     * @ctxt:  an XML parser context
     * @error:  the error number
     * @msg:  the message
     * @info1:  extra information string
     * @info2:  extra information string
     *
    
    Daniel Veillard's avatar
    Daniel Veillard committed
     * Handle a namespace warning error
    
    static void LIBXML_ATTR_FORMAT(3,0)
    
    xmlNsWarn(xmlParserCtxtPtr ctxt, xmlParserErrors error,
             const char *msg,
             const xmlChar * info1, const xmlChar * info2,
             const xmlChar * info3)
    {
        if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
            (ctxt->instate == XML_PARSER_EOF))
    	return;
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
                        XML_ERR_WARNING, NULL, 0, (const char *) info1,
                        (const char *) info2, (const char *) info3, 0, 0, msg,
                        info1, info2, info3);
    }
    
    
    /************************************************************************
     *									*
    
     *		Library wide options					*
    
     *									*
     ************************************************************************/
    
    /**
      * xmlHasFeature:
      * @feature: the feature to be examined
      *
      * Examines if the library has been compiled with a given feature.
      *
      * Returns a non-zero value if the feature exist, otherwise zero.
      * Returns zero (0) if the feature does not exist or an unknown
      * unknown feature is requested, non-zero otherwise.
      */
    int
    xmlHasFeature(xmlFeature feature)
    {
        switch (feature) {
    
    #ifdef LIBXML_THREAD_ENABLED
    	    return(1);
    #else
    	    return(0);
    #endif
    
    #ifdef LIBXML_TREE_ENABLED
                return(1);
    #else
                return(0);
    #endif
    
    #ifdef LIBXML_OUTPUT_ENABLED
                return(1);
    #else
                return(0);
    #endif
    
    #ifdef LIBXML_PUSH_ENABLED
                return(1);
    #else
                return(0);
    #endif
    
    #ifdef LIBXML_READER_ENABLED
                return(1);
    #else
                return(0);
    #endif
    
    #ifdef LIBXML_PATTERN_ENABLED
                return(1);
    #else
                return(0);
    #endif
    
    #ifdef LIBXML_WRITER_ENABLED
                return(1);
    #else
                return(0);
    #endif
    
    #ifdef LIBXML_SAX1_ENABLED
                return(1);
    #else
                return(0);
    #endif
    
    #ifdef LIBXML_FTP_ENABLED
                return(1);
    #else
                return(0);
    #endif
    
    #ifdef LIBXML_HTTP_ENABLED
                return(1);
    #else
                return(0);
    #endif
    
    #ifdef LIBXML_VALID_ENABLED
                return(1);
    #else
                return(0);
    #endif
    
    #ifdef LIBXML_HTML_ENABLED
                return(1);
    #else
                return(0);
    #endif
    
    #ifdef LIBXML_LEGACY_ENABLED
                return(1);
    #else
                return(0);
    #endif
    
    #ifdef LIBXML_C14N_ENABLED
                return(1);
    #else
                return(0);
    #endif
    
    #ifdef LIBXML_CATALOG_ENABLED
                return(1);
    #else
                return(0);
    #endif
    
    #ifdef LIBXML_XPATH_ENABLED
                return(1);
    #else
                return(0);
    #endif
    
    #ifdef LIBXML_XPTR_ENABLED
                return(1);
    #else
                return(0);
    #endif
    
    #ifdef LIBXML_XINCLUDE_ENABLED
                return(1);
    #else
                return(0);
    #endif
    
    #ifdef LIBXML_ICONV_ENABLED
                return(1);
    #else
                return(0);
    #endif
    
    #ifdef LIBXML_ISO8859X_ENABLED
                return(1);
    #else
                return(0);
    #endif
    
    #ifdef LIBXML_UNICODE_ENABLED
                return(1);
    #else
                return(0);
    #endif