parser.c 428 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * 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
15
 * high level APIs to call the parser and a few miscellaneous functions.
16 17 18 19
 * 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
Daniel Veillard's avatar
Daniel Veillard committed
20
 * different ranges of character are actually implanted either in
21 22 23 24
 * 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
25
 * from the SAX callbacks or as standalone functions using a preparsed
26 27 28 29
 * document.
 *
 * See Copyright for the status of this software.
 *
30
 * daniel@veillard.com
31 32
 */

33
#define IN_LIBXML
Bjorn Reese's avatar
Bjorn Reese committed
34 35
#include "libxml.h"

36
#if defined(WIN32) && !defined (__CYGWIN__)
37 38 39 40 41 42
#define XML_DIR_SEP '\\'
#else
#define XML_DIR_SEP '/'
#endif

#include <stdlib.h>
43
#include <limits.h>
44
#include <string.h>
45
#include <stdarg.h>
46
#include <libxml/xmlmemory.h>
47 48
#include <libxml/threads.h>
#include <libxml/globals.h>
49 50 51 52 53 54 55 56 57
#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>
58 59 60
#ifdef LIBXML_CATALOG_ENABLED
#include <libxml/catalog.h>
#endif
61 62 63 64
#ifdef LIBXML_SCHEMAS_ENABLED
#include <libxml/xmlschemastypes.h>
#include <libxml/relaxng.h>
#endif
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
#ifdef HAVE_CTYPE_H
#include <ctype.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_ZLIB_H
#include <zlib.h>
#endif
83 84 85
#ifdef HAVE_LZMA_H
#include <lzma.h>
#endif
86

87 88 89
#include "buf.h"
#include "enc.h"

90 91 92
static void
xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info);

93 94 95 96
static xmlParserCtxtPtr
xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
	                  const xmlChar *base, xmlParserCtxtPtr pctx);

97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
/************************************************************************
 *									*
 *	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 eponential 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
124
xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
125
                     xmlEntityPtr ent, size_t replacement)
126
{
127
    size_t consumed = 0;
128 129 130 131 132

    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
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155

    /*
     * 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)) {
	unsigned long oldnbent = ctxt->nbentities;
	xmlChar *rep;

	ent->checked = 1;

	rep = xmlStringDecodeEntities(ctxt, ent->content,
				  XML_SUBSTITUTE_REF, 0, 0, 0);

	ent->checked = (ctxt->nbentities - oldnbent + 1) * 2;
	if (rep != NULL) {
	    if (xmlStrchr(rep, '<'))
		ent->checked |= 1;
	    xmlFree(rep);
	    rep = NULL;
	}
    }
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
    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) {
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
        /*
         * 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
         */
196
        size = ent->checked / 2;
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214

        /*
         * 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
215
         * strange we got no data for checking
216
         */
Daniel Veillard's avatar
Daniel Veillard committed
217 218 219 220
	if (((ctxt->lastError.code != XML_ERR_UNDECLARED_ENTITY) &&
	     (ctxt->lastError.code != XML_WAR_UNDECLARED_ENTITY)) ||
	    (ctxt->nbentities <= 10000))
	    return (0);
221 222 223 224 225
    }
    xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
    return (1);
}

226
/**
227
 * xmlParserMaxDepth:
228
 *
229 230 231 232
 * 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.
233
 */
234
unsigned int xmlParserMaxDepth = 256;
235

236

237 238

#define SAX2 1
239
#define XML_PARSER_BIG_BUFFER_SIZE 300
240
#define XML_PARSER_BUFFER_SIZE 100
241 242
#define SAX_COMPAT_MODE BAD_CAST "SAX compatibility mode document"

243 244 245 246 247 248 249 250 251 252 253
/**
 * 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

254 255 256 257
/*
 * List of XML prefixed PI allowed by W3C specs
 */

258
static const char *xmlW3CPIs[] = {
259
    "xml-stylesheet",
260
    "xml-model",
261 262 263
    NULL
};

264

265
/* DEPR void xmlParserHandleReference(xmlParserCtxtPtr ctxt); */
266 267
static xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt,
                                              const xmlChar **str);
268

269
static xmlParserErrors
270 271
xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
	              xmlSAXHandlerPtr sax,
272
		      void *user_data, int depth, const xmlChar *URL,
273
		      const xmlChar *ID, xmlNodePtr *list);
274

275 276 277
static int
xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options,
                          const char *encoding);
278
#ifdef LIBXML_LEGACY_ENABLED
279 280 281
static void
xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
                      xmlNodePtr lastNode);
282
#endif /* LIBXML_LEGACY_ENABLED */
283

284
static xmlParserErrors
285 286
xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
		      const xmlChar *string, void *user_data, xmlNodePtr *lst);
287

288 289 290
static int
xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity);

291 292
/************************************************************************
 *									*
Daniel Veillard's avatar
Daniel Veillard committed
293
 *		Some factorized error routines				*
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
 *									*
 ************************************************************************/

/**
 * 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)
{
309 310 311
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
        (ctxt->instate == XML_PARSER_EOF))
	return;
312 313
    if (ctxt != NULL)
	ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
314

315
    if (prefix == NULL)
316
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
317
                        XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
318 319
                        (const char *) localname, NULL, NULL, 0, 0,
                        "Attribute %s redefined\n", localname);
320
    else
321
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
322
                        XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
323 324 325
                        (const char *) prefix, (const char *) localname,
                        NULL, 0, 0, "Attribute %s:%s redefined\n", prefix,
                        localname);
326 327 328 329 330
    if (ctxt != NULL) {
	ctxt->wellFormed = 0;
	if (ctxt->recovery == 0)
	    ctxt->disableSAX = 1;
    }
331 332 333 334 335 336 337 338 339 340 341
}

/**
 * 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
342
xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
343 344
{
    const char *errmsg;
345
    char errstr[129] = "";
346

347 348 349
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
        (ctxt->instate == XML_PARSER_EOF))
	return;
350 351
    switch (error) {
        case XML_ERR_INVALID_HEX_CHARREF:
352
            errmsg = "CharRef: invalid hexadecimal value";
353
            break;
354
        case XML_ERR_INVALID_DEC_CHARREF:
355
            errmsg = "CharRef: invalid decimal value";
356
            break;
357
        case XML_ERR_INVALID_CHARREF:
358
            errmsg = "CharRef: invalid value";
359
            break;
360
        case XML_ERR_INTERNAL_ERROR:
361 362
            errmsg = "internal error";
            break;
363
        case XML_ERR_PEREF_AT_EOF:
364
            errmsg = "PEReference at end of document";
365
            break;
366
        case XML_ERR_PEREF_IN_PROLOG:
367
            errmsg = "PEReference in prolog";
368
            break;
369
        case XML_ERR_PEREF_IN_EPILOG:
370
            errmsg = "PEReference in epilog";
371
            break;
372
        case XML_ERR_PEREF_NO_NAME:
373
            errmsg = "PEReference: no name";
374
            break;
375
        case XML_ERR_PEREF_SEMICOL_MISSING:
376
            errmsg = "PEReference: expecting ';'";
377
            break;
378
        case XML_ERR_ENTITY_LOOP:
379
            errmsg = "Detected an entity reference loop";
380
            break;
381
        case XML_ERR_ENTITY_NOT_STARTED:
382
            errmsg = "EntityValue: \" or ' expected";
383
            break;
384
        case XML_ERR_ENTITY_PE_INTERNAL:
385
            errmsg = "PEReferences forbidden in internal subset";
386
            break;
387
        case XML_ERR_ENTITY_NOT_FINISHED:
388
            errmsg = "EntityValue: \" or ' expected";
389
            break;
390
        case XML_ERR_ATTRIBUTE_NOT_STARTED:
391
            errmsg = "AttValue: \" or ' expected";
392
            break;
393
        case XML_ERR_LT_IN_ATTRIBUTE:
394
            errmsg = "Unescaped '<' not allowed in attributes values";
395
            break;
396
        case XML_ERR_LITERAL_NOT_STARTED:
397
            errmsg = "SystemLiteral \" or ' expected";
398
            break;
399
        case XML_ERR_LITERAL_NOT_FINISHED:
400
            errmsg = "Unfinished System or Public ID \" or ' expected";
401
            break;
402
        case XML_ERR_MISPLACED_CDATA_END:
403
            errmsg = "Sequence ']]>' not allowed in content";
404
            break;
405
        case XML_ERR_URI_REQUIRED:
406
            errmsg = "SYSTEM or PUBLIC, the URI is missing";
407
            break;
408
        case XML_ERR_PUBID_REQUIRED:
409
            errmsg = "PUBLIC, the Public Identifier is missing";
410
            break;
411
        case XML_ERR_HYPHEN_IN_COMMENT:
412
            errmsg = "Comment must not contain '--' (double-hyphen)";
413
            break;
414
        case XML_ERR_PI_NOT_STARTED:
415
            errmsg = "xmlParsePI : no target name";
416
            break;
417
        case XML_ERR_RESERVED_XML_NAME:
418
            errmsg = "Invalid PI name";
419
            break;
420
        case XML_ERR_NOTATION_NOT_STARTED:
421
            errmsg = "NOTATION: Name expected here";
422
            break;
423
        case XML_ERR_NOTATION_NOT_FINISHED:
424
            errmsg = "'>' required to close NOTATION declaration";
425
            break;
426
        case XML_ERR_VALUE_REQUIRED:
427
            errmsg = "Entity value required";
428
            break;
429
        case XML_ERR_URI_FRAGMENT:
430 431
            errmsg = "Fragment not allowed";
            break;
432
        case XML_ERR_ATTLIST_NOT_STARTED:
433
            errmsg = "'(' required to start ATTLIST enumeration";
434
            break;
435
        case XML_ERR_NMTOKEN_REQUIRED:
436
            errmsg = "NmToken expected in ATTLIST enumeration";
437
            break;
438
        case XML_ERR_ATTLIST_NOT_FINISHED:
439
            errmsg = "')' required to finish ATTLIST enumeration";
440
            break;
441
        case XML_ERR_MIXED_NOT_STARTED:
442
            errmsg = "MixedContentDecl : '|' or ')*' expected";
443
            break;
444
        case XML_ERR_PCDATA_REQUIRED:
445
            errmsg = "MixedContentDecl : '#PCDATA' expected";
446
            break;
447
        case XML_ERR_ELEMCONTENT_NOT_STARTED:
448
            errmsg = "ContentDecl : Name or '(' expected";
449
            break;
450
        case XML_ERR_ELEMCONTENT_NOT_FINISHED:
451
            errmsg = "ContentDecl : ',' '|' or ')' expected";
452
            break;
453
        case XML_ERR_PEREF_IN_INT_SUBSET:
454
            errmsg =
455
                "PEReference: forbidden within markup decl in internal subset";
456
            break;
457
        case XML_ERR_GT_REQUIRED:
458
            errmsg = "expected '>'";
459
            break;
460
        case XML_ERR_CONDSEC_INVALID:
461
            errmsg = "XML conditional section '[' expected";
462
            break;
463
        case XML_ERR_EXT_SUBSET_NOT_FINISHED:
464
            errmsg = "Content error in the external subset";
465 466 467
            break;
        case XML_ERR_CONDSEC_INVALID_KEYWORD:
            errmsg =
468
                "conditional section INCLUDE or IGNORE keyword expected";
469
            break;
470
        case XML_ERR_CONDSEC_NOT_FINISHED:
471
            errmsg = "XML conditional section not closed";
472
            break;
473
        case XML_ERR_XMLDECL_NOT_STARTED:
474
            errmsg = "Text declaration '<?xml' required";
475
            break;
476
        case XML_ERR_XMLDECL_NOT_FINISHED:
477
            errmsg = "parsing XML declaration: '?>' expected";
478
            break;
479
        case XML_ERR_EXT_ENTITY_STANDALONE:
480
            errmsg = "external parsed entities cannot be standalone";
481
            break;
482
        case XML_ERR_ENTITYREF_SEMICOL_MISSING:
483
            errmsg = "EntityRef: expecting ';'";
484
            break;
485
        case XML_ERR_DOCTYPE_NOT_FINISHED:
486
            errmsg = "DOCTYPE improperly terminated";
487
            break;
488
        case XML_ERR_LTSLASH_REQUIRED:
489
            errmsg = "EndTag: '</' not found";
490
            break;
491
        case XML_ERR_EQUAL_REQUIRED:
492
            errmsg = "expected '='";
493
            break;
494
        case XML_ERR_STRING_NOT_CLOSED:
495
            errmsg = "String not closed expecting \" or '";
496
            break;
497
        case XML_ERR_STRING_NOT_STARTED:
498
            errmsg = "String not started expecting ' or \"";
499
            break;
500
        case XML_ERR_ENCODING_NAME:
501
            errmsg = "Invalid XML encoding name";
502
            break;
503
        case XML_ERR_STANDALONE_VALUE:
504
            errmsg = "standalone accepts only 'yes' or 'no'";
505
            break;
506
        case XML_ERR_DOCUMENT_EMPTY:
507
            errmsg = "Document is empty";
508
            break;
509
        case XML_ERR_DOCUMENT_END:
510
            errmsg = "Extra content at the end of the document";
511
            break;
512
        case XML_ERR_NOT_WELL_BALANCED:
513
            errmsg = "chunk is not well balanced";
514
            break;
515
        case XML_ERR_EXTRA_CONTENT:
516
            errmsg = "extra content at the end of well balanced chunk";
517
            break;
518
        case XML_ERR_VERSION_MISSING:
519
            errmsg = "Malformed declaration expecting version";
520
            break;
521
        case XML_ERR_NAME_TOO_LONG:
522
            errmsg = "Name too long use XML_PARSE_HUGE option";
523
            break;
524
#if 0
525
        case:
526
            errmsg = "";
527
            break;
528
#endif
529
        default:
530
            errmsg = "Unregistered error message";
531
    }
532 533 534 535
    if (info == NULL)
        snprintf(errstr, 128, "%s\n", errmsg);
    else
        snprintf(errstr, 128, "%s: %%s\n", errmsg);
536 537
    if (ctxt != NULL)
	ctxt->errNo = error;
538
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
539
                    XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, &errstr[0],
540
                    info);
541 542 543 544 545
    if (ctxt != NULL) {
	ctxt->wellFormed = 0;
	if (ctxt->recovery == 0)
	    ctxt->disableSAX = 1;
    }
546 547
}

548 549 550 551 552 553 554 555 556
/**
 * 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
557 558
xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
               const char *msg)
559
{
560 561 562
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
        (ctxt->instate == XML_PARSER_EOF))
	return;
563 564
    if (ctxt != NULL)
	ctxt->errNo = error;
565
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
566
                    XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
567 568 569 570 571
    if (ctxt != NULL) {
	ctxt->wellFormed = 0;
	if (ctxt->recovery == 0)
	    ctxt->disableSAX = 1;
    }
572 573
}

574 575 576 577 578 579 580 581 582 583 584 585 586 587
/**
 * 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
xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
              const char *msg, const xmlChar *str1, const xmlChar *str2)
{
Daniel Veillard's avatar
Daniel Veillard committed
588
    xmlStructuredErrorFunc schannel = NULL;
589

590 591 592
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
        (ctxt->instate == XML_PARSER_EOF))
	return;
593 594
    if ((ctxt != NULL) && (ctxt->sax != NULL) &&
        (ctxt->sax->initialized == XML_SAX2_MAGIC))
Daniel Veillard's avatar
Daniel Veillard committed
595
        schannel = ctxt->sax->serror;
596 597
    if (ctxt != NULL) {
        __xmlRaiseError(schannel,
598 599
                    (ctxt->sax) ? ctxt->sax->warning : NULL,
                    ctxt->userData,
600 601 602 603
                    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);
604 605 606 607 608 609 610
    } 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);
    }
611 612 613 614 615 616 617 618 619
}

/**
 * xmlValidityError:
 * @ctxt:  an XML parser context
 * @error:  the error number
 * @msg:  the error message
 * @str1:  extra data
 *
620
 * Handle a validity error.
621 622 623
 */
static void
xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error,
624
              const char *msg, const xmlChar *str1, const xmlChar *str2)
625
{
Daniel Veillard's avatar
Daniel Veillard committed
626
    xmlStructuredErrorFunc schannel = NULL;
627 628 629 630

    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
        (ctxt->instate == XML_PARSER_EOF))
	return;
631 632 633 634 635
    if (ctxt != NULL) {
	ctxt->errNo = error;
	if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
	    schannel = ctxt->sax->serror;
    }
636 637
    if (ctxt != NULL) {
        __xmlRaiseError(schannel,
638
                    ctxt->vctxt.error, ctxt->vctxt.userData,
639 640
                    ctxt, NULL, XML_FROM_DTD, error,
                    XML_ERR_ERROR, NULL, 0, (const char *) str1,
641 642
		    (const char *) str2, NULL, 0, 0,
		    msg, (const char *) str1, (const char *) str2);
643
	ctxt->valid = 0;
644 645 646 647 648 649
    } 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);
650
    }
651 652
}

653 654 655 656 657 658 659 660 661 662 663
/**
 * 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
xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
664
                  const char *msg, int val)
665
{
666 667 668
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
        (ctxt->instate == XML_PARSER_EOF))
	return;
669 670
    if (ctxt != NULL)
	ctxt->errNo = error;
671
    __xmlRaiseError(NULL, NULL, NULL,
672 673
                    ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
                    NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
674 675 676 677 678
    if (ctxt != NULL) {
	ctxt->wellFormed = 0;
	if (ctxt->recovery == 0)
	    ctxt->disableSAX = 1;
    }
679 680
}

681 682 683 684 685 686 687 688 689 690 691 692 693
/**
 * 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
xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
Daniel Veillard's avatar
Daniel Veillard committed
694
                  const char *msg, const xmlChar *str1, int val,
695 696
		  const xmlChar *str2)
{
697 698 699
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
        (ctxt->instate == XML_PARSER_EOF))
	return;
700 701
    if (ctxt != NULL)
	ctxt->errNo = error;
702
    __xmlRaiseError(NULL, NULL, NULL,
703 704 705
                    ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
                    NULL, 0, (const char *) str1, (const char *) str2,
		    NULL, val, 0, msg, str1, val, str2);
706 707 708 709 710
    if (ctxt != NULL) {
	ctxt->wellFormed = 0;
	if (ctxt->recovery == 0)
	    ctxt->disableSAX = 1;
    }
711 712
}

713 714 715 716 717 718 719 720 721 722 723
/**
 * 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
xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
724
                  const char *msg, const xmlChar * val)
725
{
726 727 728
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
        (ctxt->instate == XML_PARSER_EOF))
	return;
729 730
    if (ctxt != NULL)
	ctxt->errNo = error;
731
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
732 733 734
                    XML_FROM_PARSER, error, XML_ERR_FATAL,
                    NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
                    val);
735 736 737 738 739
    if (ctxt != NULL) {
	ctxt->wellFormed = 0;
	if (ctxt->recovery == 0)
	    ctxt->disableSAX = 1;
    }
740 741
}

742 743 744 745 746 747 748 749 750 751 752 753 754
/**
 * 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
xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                  const char *msg, const xmlChar * val)
{
755 756 757
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
        (ctxt->instate == XML_PARSER_EOF))
	return;
758 759
    if (ctxt != NULL)
	ctxt->errNo = error;
760
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
761 762 763 764 765
                    XML_FROM_PARSER, error, XML_ERR_ERROR,
                    NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
                    val);
}

766 767 768 769 770 771 772 773 774 775 776 777 778
/**
 * 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
xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
         const char *msg,
779 780
         const xmlChar * info1, const xmlChar * info2,
         const xmlChar * info3)
781
{
782 783 784
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
        (ctxt->instate == XML_PARSER_EOF))
	return;
785 786
    if (ctxt != NULL)
	ctxt->errNo = error;
787
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
788 789 790
                    XML_ERR_ERROR, NULL, 0, (const char *) info1,
                    (const char *) info2, (const char *) info3, 0, 0, msg,
                    info1, info2, info3);
791 792
    if (ctxt != NULL)
	ctxt->nsWellFormed = 0;
793 794
}

795 796 797 798 799 800 801 802
/**
 * 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
803
 * Handle a namespace warning error
804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819
 */
static void
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);
}

820 821
/************************************************************************
 *									*
Daniel Veillard's avatar
Daniel Veillard committed
822
 *		Library wide options					*
823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839
 *									*
 ************************************************************************/

/**
  * 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) {
840
	case XML_WITH_THREAD:
841 842 843 844 845
#ifdef LIBXML_THREAD_ENABLED
	    return(1);
#else
	    return(0);
#endif
846
        case XML_WITH_TREE:
847 848 849 850 851
#ifdef LIBXML_TREE_ENABLED
            return(1);
#else
            return(0);
#endif
852
        case XML_WITH_OUTPUT:
853 854 855 856 857
#ifdef LIBXML_OUTPUT_ENABLED
            return(1);
#else
            return(0);
#endif
858
        case XML_WITH_PUSH:
859 860 861 862 863
#ifdef LIBXML_PUSH_ENABLED
            return(1);
#else
            return(0);
#endif
864
        case XML_WITH_READER:
865 866 867 868 869
#ifdef LIBXML_READER_ENABLED
            return(1);
#else
            return(0);
#endif
870
        case XML_WITH_PATTERN:
871 872 873 874 875
#ifdef LIBXML_PATTERN_ENABLED
            return(1);
#else
            return(0);
#endif
876
        case XML_WITH_WRITER:
877 878 879 880 881
#ifdef LIBXML_WRITER_ENABLED
            return(1);
#else
            return(0);
#endif
882
        case XML_WITH_SAX1:
883 884 885 886 887
#ifdef LIBXML_SAX1_ENABLED
            return(1);
#else
            return(0);
#endif
888
        case XML_WITH_FTP:
889 890 891 892 893
#ifdef LIBXML_FTP_ENABLED
            return(1);
#else
            return(0);
#endif
Daniel Veillard's avatar