~ubuntu-branches/ubuntu/utopic/libxml2/utopic

« back to all changes in this revision

Viewing changes to .pc/0007-Fix-a-parsing-bug-on-non-ascii-element-and-CR-LF-usa.patch/parser.c

  • Committer: Package Import Robot
  • Author(s): Aron Xu, Christian Svensson, Daniel Schepler, Helmut Grohne, Adam Conrad, Matthias Klose, Aron Xu
  • Date: 2014-07-09 05:40:15 UTC
  • mfrom: (43.2.6 sid)
  • Revision ID: package-import@ubuntu.com-20140709054015-1q7dyagza4p2gkm0
Tags: 2.9.1+dfsg1-4
[ Christian Svensson ]
* Do not build-depend on readline (Closes: #742350)

[ Daniel Schepler ]
* Patch to bootstrap without python (Closes: #738080)

[ Helmut Grohne ]
* Drop unneeded B-D on perl and binutils (Closes: #753005)

[ Adam Conrad ]
* Actually run dh_autoreconf, which the old/new mixed rules file misses.

[ Matthias Klose ]
* Add patch to fix python multiarch issue
* Allow the package to cross-build by tweaking B-Ds on python
* Set PYTHON_LIBS for cross builds

[ Aron Xu ]
* Use correct $CC
* Configure udeb without python
* New round of cherry-picking upstream fixes
  - Includes fixes for CVE-2014-0191 (Closes: #747309).
* Call prename with -vf
* Require python-all-dev (>= 2.7.5-5~)
* Bump std-ver: 3.9.4 -> 3.9.5, no change

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * parser.c : an XML 1.0 parser, namespaces and validity support are mostly
 
3
 *            implemented on top of the SAX interfaces
 
4
 *
 
5
 * References:
 
6
 *   The XML specification:
 
7
 *     http://www.w3.org/TR/REC-xml
 
8
 *   Original 1.0 version:
 
9
 *     http://www.w3.org/TR/1998/REC-xml-19980210
 
10
 *   XML second edition working draft
 
11
 *     http://www.w3.org/TR/2000/WD-xml-2e-20000814
 
12
 *
 
13
 * Okay this is a big file, the parser core is around 7000 lines, then it
 
14
 * 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
 * A number of helper functions and deprecated ones have been moved to
 
17
 * parserInternals.c to reduce this file size.
 
18
 * As much as possible the functions are associated with their relative
 
19
 * production in the XML specification. A few productions defining the
 
20
 * different ranges of character are actually implanted either in
 
21
 * parserInternals.h or parserInternals.c
 
22
 * The DOM tree build is realized from the default SAX callbacks in
 
23
 * the module SAX.c.
 
24
 * 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
 * document.
 
27
 *
 
28
 * See Copyright for the status of this software.
 
29
 *
 
30
 * daniel@veillard.com
 
31
 */
 
32
 
 
33
#define IN_LIBXML
 
34
#include "libxml.h"
 
35
 
 
36
#if defined(WIN32) && !defined (__CYGWIN__)
 
37
#define XML_DIR_SEP '\\'
 
38
#else
 
39
#define XML_DIR_SEP '/'
 
40
#endif
 
41
 
 
42
#include <stdlib.h>
 
43
#include <limits.h>
 
44
#include <string.h>
 
45
#include <stdarg.h>
 
46
#include <libxml/xmlmemory.h>
 
47
#include <libxml/threads.h>
 
48
#include <libxml/globals.h>
 
49
#include <libxml/tree.h>
 
50
#include <libxml/parser.h>
 
51
#include <libxml/parserInternals.h>
 
52
#include <libxml/valid.h>
 
53
#include <libxml/entities.h>
 
54
#include <libxml/xmlerror.h>
 
55
#include <libxml/encoding.h>
 
56
#include <libxml/xmlIO.h>
 
57
#include <libxml/uri.h>
 
58
#ifdef LIBXML_CATALOG_ENABLED
 
59
#include <libxml/catalog.h>
 
60
#endif
 
61
#ifdef LIBXML_SCHEMAS_ENABLED
 
62
#include <libxml/xmlschemastypes.h>
 
63
#include <libxml/relaxng.h>
 
64
#endif
 
65
#ifdef HAVE_CTYPE_H
 
66
#include <ctype.h>
 
67
#endif
 
68
#ifdef HAVE_STDLIB_H
 
69
#include <stdlib.h>
 
70
#endif
 
71
#ifdef HAVE_SYS_STAT_H
 
72
#include <sys/stat.h>
 
73
#endif
 
74
#ifdef HAVE_FCNTL_H
 
75
#include <fcntl.h>
 
76
#endif
 
77
#ifdef HAVE_UNISTD_H
 
78
#include <unistd.h>
 
79
#endif
 
80
#ifdef HAVE_ZLIB_H
 
81
#include <zlib.h>
 
82
#endif
 
83
#ifdef HAVE_LZMA_H
 
84
#include <lzma.h>
 
85
#endif
 
86
 
 
87
#include "buf.h"
 
88
#include "enc.h"
 
89
 
 
90
static void
 
91
xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info);
 
92
 
 
93
static xmlParserCtxtPtr
 
94
xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
 
95
                          const xmlChar *base, xmlParserCtxtPtr pctx);
 
96
 
 
97
/************************************************************************
 
98
 *                                                                      *
 
99
 *      Arbitrary limits set in the parser. See XML_PARSE_HUGE          *
 
100
 *                                                                      *
 
101
 ************************************************************************/
 
102
 
 
103
#define XML_PARSER_BIG_ENTITY 1000
 
104
#define XML_PARSER_LOT_ENTITY 5000
 
105
 
 
106
/*
 
107
 * XML_PARSER_NON_LINEAR is the threshold where the ratio of parsed entity
 
108
 *    replacement over the size in byte of the input indicates that you have
 
109
 *    and eponential behaviour. A value of 10 correspond to at least 3 entity
 
110
 *    replacement per byte of input.
 
111
 */
 
112
#define XML_PARSER_NON_LINEAR 10
 
113
 
 
114
/*
 
115
 * xmlParserEntityCheck
 
116
 *
 
117
 * Function to check non-linear entity expansion behaviour
 
118
 * This is here to detect and stop exponential linear entity expansion
 
119
 * This is not a limitation of the parser but a safety
 
120
 * boundary feature. It can be disabled with the XML_PARSE_HUGE
 
121
 * parser option.
 
122
 */
 
123
static int
 
124
xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
 
125
                     xmlEntityPtr ent, size_t replacement)
 
126
{
 
127
    size_t consumed = 0;
 
128
 
 
129
    if ((ctxt == NULL) || (ctxt->options & XML_PARSE_HUGE))
 
130
        return (0);
 
131
    if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
 
132
        return (1);
 
133
    if (replacement != 0) {
 
134
        if (replacement < XML_MAX_TEXT_LENGTH)
 
135
            return(0);
 
136
 
 
137
        /*
 
138
         * If the volume of entity copy reaches 10 times the
 
139
         * amount of parsed data and over the large text threshold
 
140
         * then that's very likely to be an abuse.
 
141
         */
 
142
        if (ctxt->input != NULL) {
 
143
            consumed = ctxt->input->consumed +
 
144
                       (ctxt->input->cur - ctxt->input->base);
 
145
        }
 
146
        consumed += ctxt->sizeentities;
 
147
 
 
148
        if (replacement < XML_PARSER_NON_LINEAR * consumed)
 
149
            return(0);
 
150
    } else if (size != 0) {
 
151
        /*
 
152
         * Do the check based on the replacement size of the entity
 
153
         */
 
154
        if (size < XML_PARSER_BIG_ENTITY)
 
155
            return(0);
 
156
 
 
157
        /*
 
158
         * A limit on the amount of text data reasonably used
 
159
         */
 
160
        if (ctxt->input != NULL) {
 
161
            consumed = ctxt->input->consumed +
 
162
                (ctxt->input->cur - ctxt->input->base);
 
163
        }
 
164
        consumed += ctxt->sizeentities;
 
165
 
 
166
        if ((size < XML_PARSER_NON_LINEAR * consumed) &&
 
167
            (ctxt->nbentities * 3 < XML_PARSER_NON_LINEAR * consumed))
 
168
            return (0);
 
169
    } else if (ent != NULL) {
 
170
        /*
 
171
         * use the number of parsed entities in the replacement
 
172
         */
 
173
        size = ent->checked / 2;
 
174
 
 
175
        /*
 
176
         * The amount of data parsed counting entities size only once
 
177
         */
 
178
        if (ctxt->input != NULL) {
 
179
            consumed = ctxt->input->consumed +
 
180
                (ctxt->input->cur - ctxt->input->base);
 
181
        }
 
182
        consumed += ctxt->sizeentities;
 
183
 
 
184
        /*
 
185
         * Check the density of entities for the amount of data
 
186
         * knowing an entity reference will take at least 3 bytes
 
187
         */
 
188
        if (size * 3 < consumed * XML_PARSER_NON_LINEAR)
 
189
            return (0);
 
190
    } else {
 
191
        /*
 
192
         * strange we got no data for checking just return
 
193
         */
 
194
        return (0);
 
195
    }
 
196
    xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
 
197
    return (1);
 
198
}
 
199
 
 
200
/**
 
201
 * xmlParserMaxDepth:
 
202
 *
 
203
 * arbitrary depth limit for the XML documents that we allow to
 
204
 * process. This is not a limitation of the parser but a safety
 
205
 * boundary feature. It can be disabled with the XML_PARSE_HUGE
 
206
 * parser option.
 
207
 */
 
208
unsigned int xmlParserMaxDepth = 256;
 
209
 
 
210
 
 
211
 
 
212
#define SAX2 1
 
213
#define XML_PARSER_BIG_BUFFER_SIZE 300
 
214
#define XML_PARSER_BUFFER_SIZE 100
 
215
#define SAX_COMPAT_MODE BAD_CAST "SAX compatibility mode document"
 
216
 
 
217
/**
 
218
 * XML_PARSER_CHUNK_SIZE
 
219
 *
 
220
 * When calling GROW that's the minimal amount of data
 
221
 * the parser expected to have received. It is not a hard
 
222
 * limit but an optimization when reading strings like Names
 
223
 * It is not strictly needed as long as inputs available characters
 
224
 * are followed by 0, which should be provided by the I/O level
 
225
 */
 
226
#define XML_PARSER_CHUNK_SIZE 100
 
227
 
 
228
/*
 
229
 * List of XML prefixed PI allowed by W3C specs
 
230
 */
 
231
 
 
232
static const char *xmlW3CPIs[] = {
 
233
    "xml-stylesheet",
 
234
    "xml-model",
 
235
    NULL
 
236
};
 
237
 
 
238
 
 
239
/* DEPR void xmlParserHandleReference(xmlParserCtxtPtr ctxt); */
 
240
static xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt,
 
241
                                              const xmlChar **str);
 
242
 
 
243
static xmlParserErrors
 
244
xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
 
245
                      xmlSAXHandlerPtr sax,
 
246
                      void *user_data, int depth, const xmlChar *URL,
 
247
                      const xmlChar *ID, xmlNodePtr *list);
 
248
 
 
249
static int
 
250
xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options,
 
251
                          const char *encoding);
 
252
#ifdef LIBXML_LEGACY_ENABLED
 
253
static void
 
254
xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
 
255
                      xmlNodePtr lastNode);
 
256
#endif /* LIBXML_LEGACY_ENABLED */
 
257
 
 
258
static xmlParserErrors
 
259
xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
 
260
                      const xmlChar *string, void *user_data, xmlNodePtr *lst);
 
261
 
 
262
static int
 
263
xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity);
 
264
 
 
265
/************************************************************************
 
266
 *                                                                      *
 
267
 *              Some factorized error routines                          *
 
268
 *                                                                      *
 
269
 ************************************************************************/
 
270
 
 
271
/**
 
272
 * xmlErrAttributeDup:
 
273
 * @ctxt:  an XML parser context
 
274
 * @prefix:  the attribute prefix
 
275
 * @localname:  the attribute localname
 
276
 *
 
277
 * Handle a redefinition of attribute error
 
278
 */
 
279
static void
 
280
xmlErrAttributeDup(xmlParserCtxtPtr ctxt, const xmlChar * prefix,
 
281
                   const xmlChar * localname)
 
282
{
 
283
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
 
284
        (ctxt->instate == XML_PARSER_EOF))
 
285
        return;
 
286
    if (ctxt != NULL)
 
287
        ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
 
288
 
 
289
    if (prefix == NULL)
 
290
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
 
291
                        XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
 
292
                        (const char *) localname, NULL, NULL, 0, 0,
 
293
                        "Attribute %s redefined\n", localname);
 
294
    else
 
295
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
 
296
                        XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
 
297
                        (const char *) prefix, (const char *) localname,
 
298
                        NULL, 0, 0, "Attribute %s:%s redefined\n", prefix,
 
299
                        localname);
 
300
    if (ctxt != NULL) {
 
301
        ctxt->wellFormed = 0;
 
302
        if (ctxt->recovery == 0)
 
303
            ctxt->disableSAX = 1;
 
304
    }
 
305
}
 
306
 
 
307
/**
 
308
 * xmlFatalErr:
 
309
 * @ctxt:  an XML parser context
 
310
 * @error:  the error number
 
311
 * @extra:  extra information string
 
312
 *
 
313
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
 
314
 */
 
315
static void
 
316
xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
 
317
{
 
318
    const char *errmsg;
 
319
    char errstr[129] = "";
 
320
 
 
321
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
 
322
        (ctxt->instate == XML_PARSER_EOF))
 
323
        return;
 
324
    switch (error) {
 
325
        case XML_ERR_INVALID_HEX_CHARREF:
 
326
            errmsg = "CharRef: invalid hexadecimal value";
 
327
            break;
 
328
        case XML_ERR_INVALID_DEC_CHARREF:
 
329
            errmsg = "CharRef: invalid decimal value";
 
330
            break;
 
331
        case XML_ERR_INVALID_CHARREF:
 
332
            errmsg = "CharRef: invalid value";
 
333
            break;
 
334
        case XML_ERR_INTERNAL_ERROR:
 
335
            errmsg = "internal error";
 
336
            break;
 
337
        case XML_ERR_PEREF_AT_EOF:
 
338
            errmsg = "PEReference at end of document";
 
339
            break;
 
340
        case XML_ERR_PEREF_IN_PROLOG:
 
341
            errmsg = "PEReference in prolog";
 
342
            break;
 
343
        case XML_ERR_PEREF_IN_EPILOG:
 
344
            errmsg = "PEReference in epilog";
 
345
            break;
 
346
        case XML_ERR_PEREF_NO_NAME:
 
347
            errmsg = "PEReference: no name";
 
348
            break;
 
349
        case XML_ERR_PEREF_SEMICOL_MISSING:
 
350
            errmsg = "PEReference: expecting ';'";
 
351
            break;
 
352
        case XML_ERR_ENTITY_LOOP:
 
353
            errmsg = "Detected an entity reference loop";
 
354
            break;
 
355
        case XML_ERR_ENTITY_NOT_STARTED:
 
356
            errmsg = "EntityValue: \" or ' expected";
 
357
            break;
 
358
        case XML_ERR_ENTITY_PE_INTERNAL:
 
359
            errmsg = "PEReferences forbidden in internal subset";
 
360
            break;
 
361
        case XML_ERR_ENTITY_NOT_FINISHED:
 
362
            errmsg = "EntityValue: \" or ' expected";
 
363
            break;
 
364
        case XML_ERR_ATTRIBUTE_NOT_STARTED:
 
365
            errmsg = "AttValue: \" or ' expected";
 
366
            break;
 
367
        case XML_ERR_LT_IN_ATTRIBUTE:
 
368
            errmsg = "Unescaped '<' not allowed in attributes values";
 
369
            break;
 
370
        case XML_ERR_LITERAL_NOT_STARTED:
 
371
            errmsg = "SystemLiteral \" or ' expected";
 
372
            break;
 
373
        case XML_ERR_LITERAL_NOT_FINISHED:
 
374
            errmsg = "Unfinished System or Public ID \" or ' expected";
 
375
            break;
 
376
        case XML_ERR_MISPLACED_CDATA_END:
 
377
            errmsg = "Sequence ']]>' not allowed in content";
 
378
            break;
 
379
        case XML_ERR_URI_REQUIRED:
 
380
            errmsg = "SYSTEM or PUBLIC, the URI is missing";
 
381
            break;
 
382
        case XML_ERR_PUBID_REQUIRED:
 
383
            errmsg = "PUBLIC, the Public Identifier is missing";
 
384
            break;
 
385
        case XML_ERR_HYPHEN_IN_COMMENT:
 
386
            errmsg = "Comment must not contain '--' (double-hyphen)";
 
387
            break;
 
388
        case XML_ERR_PI_NOT_STARTED:
 
389
            errmsg = "xmlParsePI : no target name";
 
390
            break;
 
391
        case XML_ERR_RESERVED_XML_NAME:
 
392
            errmsg = "Invalid PI name";
 
393
            break;
 
394
        case XML_ERR_NOTATION_NOT_STARTED:
 
395
            errmsg = "NOTATION: Name expected here";
 
396
            break;
 
397
        case XML_ERR_NOTATION_NOT_FINISHED:
 
398
            errmsg = "'>' required to close NOTATION declaration";
 
399
            break;
 
400
        case XML_ERR_VALUE_REQUIRED:
 
401
            errmsg = "Entity value required";
 
402
            break;
 
403
        case XML_ERR_URI_FRAGMENT:
 
404
            errmsg = "Fragment not allowed";
 
405
            break;
 
406
        case XML_ERR_ATTLIST_NOT_STARTED:
 
407
            errmsg = "'(' required to start ATTLIST enumeration";
 
408
            break;
 
409
        case XML_ERR_NMTOKEN_REQUIRED:
 
410
            errmsg = "NmToken expected in ATTLIST enumeration";
 
411
            break;
 
412
        case XML_ERR_ATTLIST_NOT_FINISHED:
 
413
            errmsg = "')' required to finish ATTLIST enumeration";
 
414
            break;
 
415
        case XML_ERR_MIXED_NOT_STARTED:
 
416
            errmsg = "MixedContentDecl : '|' or ')*' expected";
 
417
            break;
 
418
        case XML_ERR_PCDATA_REQUIRED:
 
419
            errmsg = "MixedContentDecl : '#PCDATA' expected";
 
420
            break;
 
421
        case XML_ERR_ELEMCONTENT_NOT_STARTED:
 
422
            errmsg = "ContentDecl : Name or '(' expected";
 
423
            break;
 
424
        case XML_ERR_ELEMCONTENT_NOT_FINISHED:
 
425
            errmsg = "ContentDecl : ',' '|' or ')' expected";
 
426
            break;
 
427
        case XML_ERR_PEREF_IN_INT_SUBSET:
 
428
            errmsg =
 
429
                "PEReference: forbidden within markup decl in internal subset";
 
430
            break;
 
431
        case XML_ERR_GT_REQUIRED:
 
432
            errmsg = "expected '>'";
 
433
            break;
 
434
        case XML_ERR_CONDSEC_INVALID:
 
435
            errmsg = "XML conditional section '[' expected";
 
436
            break;
 
437
        case XML_ERR_EXT_SUBSET_NOT_FINISHED:
 
438
            errmsg = "Content error in the external subset";
 
439
            break;
 
440
        case XML_ERR_CONDSEC_INVALID_KEYWORD:
 
441
            errmsg =
 
442
                "conditional section INCLUDE or IGNORE keyword expected";
 
443
            break;
 
444
        case XML_ERR_CONDSEC_NOT_FINISHED:
 
445
            errmsg = "XML conditional section not closed";
 
446
            break;
 
447
        case XML_ERR_XMLDECL_NOT_STARTED:
 
448
            errmsg = "Text declaration '<?xml' required";
 
449
            break;
 
450
        case XML_ERR_XMLDECL_NOT_FINISHED:
 
451
            errmsg = "parsing XML declaration: '?>' expected";
 
452
            break;
 
453
        case XML_ERR_EXT_ENTITY_STANDALONE:
 
454
            errmsg = "external parsed entities cannot be standalone";
 
455
            break;
 
456
        case XML_ERR_ENTITYREF_SEMICOL_MISSING:
 
457
            errmsg = "EntityRef: expecting ';'";
 
458
            break;
 
459
        case XML_ERR_DOCTYPE_NOT_FINISHED:
 
460
            errmsg = "DOCTYPE improperly terminated";
 
461
            break;
 
462
        case XML_ERR_LTSLASH_REQUIRED:
 
463
            errmsg = "EndTag: '</' not found";
 
464
            break;
 
465
        case XML_ERR_EQUAL_REQUIRED:
 
466
            errmsg = "expected '='";
 
467
            break;
 
468
        case XML_ERR_STRING_NOT_CLOSED:
 
469
            errmsg = "String not closed expecting \" or '";
 
470
            break;
 
471
        case XML_ERR_STRING_NOT_STARTED:
 
472
            errmsg = "String not started expecting ' or \"";
 
473
            break;
 
474
        case XML_ERR_ENCODING_NAME:
 
475
            errmsg = "Invalid XML encoding name";
 
476
            break;
 
477
        case XML_ERR_STANDALONE_VALUE:
 
478
            errmsg = "standalone accepts only 'yes' or 'no'";
 
479
            break;
 
480
        case XML_ERR_DOCUMENT_EMPTY:
 
481
            errmsg = "Document is empty";
 
482
            break;
 
483
        case XML_ERR_DOCUMENT_END:
 
484
            errmsg = "Extra content at the end of the document";
 
485
            break;
 
486
        case XML_ERR_NOT_WELL_BALANCED:
 
487
            errmsg = "chunk is not well balanced";
 
488
            break;
 
489
        case XML_ERR_EXTRA_CONTENT:
 
490
            errmsg = "extra content at the end of well balanced chunk";
 
491
            break;
 
492
        case XML_ERR_VERSION_MISSING:
 
493
            errmsg = "Malformed declaration expecting version";
 
494
            break;
 
495
        case XML_ERR_NAME_TOO_LONG:
 
496
            errmsg = "Name too long use XML_PARSE_HUGE option";
 
497
            break;
 
498
#if 0
 
499
        case:
 
500
            errmsg = "";
 
501
            break;
 
502
#endif
 
503
        default:
 
504
            errmsg = "Unregistered error message";
 
505
    }
 
506
    if (info == NULL)
 
507
        snprintf(errstr, 128, "%s\n", errmsg);
 
508
    else
 
509
        snprintf(errstr, 128, "%s: %%s\n", errmsg);
 
510
    if (ctxt != NULL)
 
511
        ctxt->errNo = error;
 
512
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
 
513
                    XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, &errstr[0],
 
514
                    info);
 
515
    if (ctxt != NULL) {
 
516
        ctxt->wellFormed = 0;
 
517
        if (ctxt->recovery == 0)
 
518
            ctxt->disableSAX = 1;
 
519
    }
 
520
}
 
521
 
 
522
/**
 
523
 * xmlFatalErrMsg:
 
524
 * @ctxt:  an XML parser context
 
525
 * @error:  the error number
 
526
 * @msg:  the error message
 
527
 *
 
528
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
 
529
 */
 
530
static void
 
531
xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
 
532
               const char *msg)
 
533
{
 
534
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
 
535
        (ctxt->instate == XML_PARSER_EOF))
 
536
        return;
 
537
    if (ctxt != NULL)
 
538
        ctxt->errNo = error;
 
539
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
 
540
                    XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
 
541
    if (ctxt != NULL) {
 
542
        ctxt->wellFormed = 0;
 
543
        if (ctxt->recovery == 0)
 
544
            ctxt->disableSAX = 1;
 
545
    }
 
546
}
 
547
 
 
548
/**
 
549
 * xmlWarningMsg:
 
550
 * @ctxt:  an XML parser context
 
551
 * @error:  the error number
 
552
 * @msg:  the error message
 
553
 * @str1:  extra data
 
554
 * @str2:  extra data
 
555
 *
 
556
 * Handle a warning.
 
557
 */
 
558
static void
 
559
xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
 
560
              const char *msg, const xmlChar *str1, const xmlChar *str2)
 
561
{
 
562
    xmlStructuredErrorFunc schannel = NULL;
 
563
 
 
564
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
 
565
        (ctxt->instate == XML_PARSER_EOF))
 
566
        return;
 
567
    if ((ctxt != NULL) && (ctxt->sax != NULL) &&
 
568
        (ctxt->sax->initialized == XML_SAX2_MAGIC))
 
569
        schannel = ctxt->sax->serror;
 
570
    if (ctxt != NULL) {
 
571
        __xmlRaiseError(schannel,
 
572
                    (ctxt->sax) ? ctxt->sax->warning : NULL,
 
573
                    ctxt->userData,
 
574
                    ctxt, NULL, XML_FROM_PARSER, error,
 
575
                    XML_ERR_WARNING, NULL, 0,
 
576
                    (const char *) str1, (const char *) str2, NULL, 0, 0,
 
577
                    msg, (const char *) str1, (const char *) str2);
 
578
    } else {
 
579
        __xmlRaiseError(schannel, NULL, NULL,
 
580
                    ctxt, NULL, XML_FROM_PARSER, error,
 
581
                    XML_ERR_WARNING, NULL, 0,
 
582
                    (const char *) str1, (const char *) str2, NULL, 0, 0,
 
583
                    msg, (const char *) str1, (const char *) str2);
 
584
    }
 
585
}
 
586
 
 
587
/**
 
588
 * xmlValidityError:
 
589
 * @ctxt:  an XML parser context
 
590
 * @error:  the error number
 
591
 * @msg:  the error message
 
592
 * @str1:  extra data
 
593
 *
 
594
 * Handle a validity error.
 
595
 */
 
596
static void
 
597
xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error,
 
598
              const char *msg, const xmlChar *str1, const xmlChar *str2)
 
599
{
 
600
    xmlStructuredErrorFunc schannel = NULL;
 
601
 
 
602
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
 
603
        (ctxt->instate == XML_PARSER_EOF))
 
604
        return;
 
605
    if (ctxt != NULL) {
 
606
        ctxt->errNo = error;
 
607
        if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
 
608
            schannel = ctxt->sax->serror;
 
609
    }
 
610
    if (ctxt != NULL) {
 
611
        __xmlRaiseError(schannel,
 
612
                    ctxt->vctxt.error, ctxt->vctxt.userData,
 
613
                    ctxt, NULL, XML_FROM_DTD, error,
 
614
                    XML_ERR_ERROR, NULL, 0, (const char *) str1,
 
615
                    (const char *) str2, NULL, 0, 0,
 
616
                    msg, (const char *) str1, (const char *) str2);
 
617
        ctxt->valid = 0;
 
618
    } else {
 
619
        __xmlRaiseError(schannel, NULL, NULL,
 
620
                    ctxt, NULL, XML_FROM_DTD, error,
 
621
                    XML_ERR_ERROR, NULL, 0, (const char *) str1,
 
622
                    (const char *) str2, NULL, 0, 0,
 
623
                    msg, (const char *) str1, (const char *) str2);
 
624
    }
 
625
}
 
626
 
 
627
/**
 
628
 * xmlFatalErrMsgInt:
 
629
 * @ctxt:  an XML parser context
 
630
 * @error:  the error number
 
631
 * @msg:  the error message
 
632
 * @val:  an integer value
 
633
 *
 
634
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
 
635
 */
 
636
static void
 
637
xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
 
638
                  const char *msg, int val)
 
639
{
 
640
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
 
641
        (ctxt->instate == XML_PARSER_EOF))
 
642
        return;
 
643
    if (ctxt != NULL)
 
644
        ctxt->errNo = error;
 
645
    __xmlRaiseError(NULL, NULL, NULL,
 
646
                    ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
 
647
                    NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
 
648
    if (ctxt != NULL) {
 
649
        ctxt->wellFormed = 0;
 
650
        if (ctxt->recovery == 0)
 
651
            ctxt->disableSAX = 1;
 
652
    }
 
653
}
 
654
 
 
655
/**
 
656
 * xmlFatalErrMsgStrIntStr:
 
657
 * @ctxt:  an XML parser context
 
658
 * @error:  the error number
 
659
 * @msg:  the error message
 
660
 * @str1:  an string info
 
661
 * @val:  an integer value
 
662
 * @str2:  an string info
 
663
 *
 
664
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
 
665
 */
 
666
static void
 
667
xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
 
668
                  const char *msg, const xmlChar *str1, int val,
 
669
                  const xmlChar *str2)
 
670
{
 
671
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
 
672
        (ctxt->instate == XML_PARSER_EOF))
 
673
        return;
 
674
    if (ctxt != NULL)
 
675
        ctxt->errNo = error;
 
676
    __xmlRaiseError(NULL, NULL, NULL,
 
677
                    ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
 
678
                    NULL, 0, (const char *) str1, (const char *) str2,
 
679
                    NULL, val, 0, msg, str1, val, str2);
 
680
    if (ctxt != NULL) {
 
681
        ctxt->wellFormed = 0;
 
682
        if (ctxt->recovery == 0)
 
683
            ctxt->disableSAX = 1;
 
684
    }
 
685
}
 
686
 
 
687
/**
 
688
 * xmlFatalErrMsgStr:
 
689
 * @ctxt:  an XML parser context
 
690
 * @error:  the error number
 
691
 * @msg:  the error message
 
692
 * @val:  a string value
 
693
 *
 
694
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
 
695
 */
 
696
static void
 
697
xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
 
698
                  const char *msg, const xmlChar * val)
 
699
{
 
700
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
 
701
        (ctxt->instate == XML_PARSER_EOF))
 
702
        return;
 
703
    if (ctxt != NULL)
 
704
        ctxt->errNo = error;
 
705
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
 
706
                    XML_FROM_PARSER, error, XML_ERR_FATAL,
 
707
                    NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
 
708
                    val);
 
709
    if (ctxt != NULL) {
 
710
        ctxt->wellFormed = 0;
 
711
        if (ctxt->recovery == 0)
 
712
            ctxt->disableSAX = 1;
 
713
    }
 
714
}
 
715
 
 
716
/**
 
717
 * xmlErrMsgStr:
 
718
 * @ctxt:  an XML parser context
 
719
 * @error:  the error number
 
720
 * @msg:  the error message
 
721
 * @val:  a string value
 
722
 *
 
723
 * Handle a non fatal parser error
 
724
 */
 
725
static void
 
726
xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
 
727
                  const char *msg, const xmlChar * val)
 
728
{
 
729
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
 
730
        (ctxt->instate == XML_PARSER_EOF))
 
731
        return;
 
732
    if (ctxt != NULL)
 
733
        ctxt->errNo = error;
 
734
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
 
735
                    XML_FROM_PARSER, error, XML_ERR_ERROR,
 
736
                    NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
 
737
                    val);
 
738
}
 
739
 
 
740
/**
 
741
 * xmlNsErr:
 
742
 * @ctxt:  an XML parser context
 
743
 * @error:  the error number
 
744
 * @msg:  the message
 
745
 * @info1:  extra information string
 
746
 * @info2:  extra information string
 
747
 *
 
748
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
 
749
 */
 
750
static void
 
751
xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
 
752
         const char *msg,
 
753
         const xmlChar * info1, const xmlChar * info2,
 
754
         const xmlChar * info3)
 
755
{
 
756
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
 
757
        (ctxt->instate == XML_PARSER_EOF))
 
758
        return;
 
759
    if (ctxt != NULL)
 
760
        ctxt->errNo = error;
 
761
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
 
762
                    XML_ERR_ERROR, NULL, 0, (const char *) info1,
 
763
                    (const char *) info2, (const char *) info3, 0, 0, msg,
 
764
                    info1, info2, info3);
 
765
    if (ctxt != NULL)
 
766
        ctxt->nsWellFormed = 0;
 
767
}
 
768
 
 
769
/**
 
770
 * xmlNsWarn
 
771
 * @ctxt:  an XML parser context
 
772
 * @error:  the error number
 
773
 * @msg:  the message
 
774
 * @info1:  extra information string
 
775
 * @info2:  extra information string
 
776
 *
 
777
 * Handle a namespace warning error
 
778
 */
 
779
static void
 
780
xmlNsWarn(xmlParserCtxtPtr ctxt, xmlParserErrors error,
 
781
         const char *msg,
 
782
         const xmlChar * info1, const xmlChar * info2,
 
783
         const xmlChar * info3)
 
784
{
 
785
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
 
786
        (ctxt->instate == XML_PARSER_EOF))
 
787
        return;
 
788
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
 
789
                    XML_ERR_WARNING, NULL, 0, (const char *) info1,
 
790
                    (const char *) info2, (const char *) info3, 0, 0, msg,
 
791
                    info1, info2, info3);
 
792
}
 
793
 
 
794
/************************************************************************
 
795
 *                                                                      *
 
796
 *              Library wide options                                    *
 
797
 *                                                                      *
 
798
 ************************************************************************/
 
799
 
 
800
/**
 
801
  * xmlHasFeature:
 
802
  * @feature: the feature to be examined
 
803
  *
 
804
  * Examines if the library has been compiled with a given feature.
 
805
  *
 
806
  * Returns a non-zero value if the feature exist, otherwise zero.
 
807
  * Returns zero (0) if the feature does not exist or an unknown
 
808
  * unknown feature is requested, non-zero otherwise.
 
809
  */
 
810
int
 
811
xmlHasFeature(xmlFeature feature)
 
812
{
 
813
    switch (feature) {
 
814
        case XML_WITH_THREAD:
 
815
#ifdef LIBXML_THREAD_ENABLED
 
816
            return(1);
 
817
#else
 
818
            return(0);
 
819
#endif
 
820
        case XML_WITH_TREE:
 
821
#ifdef LIBXML_TREE_ENABLED
 
822
            return(1);
 
823
#else
 
824
            return(0);
 
825
#endif
 
826
        case XML_WITH_OUTPUT:
 
827
#ifdef LIBXML_OUTPUT_ENABLED
 
828
            return(1);
 
829
#else
 
830
            return(0);
 
831
#endif
 
832
        case XML_WITH_PUSH:
 
833
#ifdef LIBXML_PUSH_ENABLED
 
834
            return(1);
 
835
#else
 
836
            return(0);
 
837
#endif
 
838
        case XML_WITH_READER:
 
839
#ifdef LIBXML_READER_ENABLED
 
840
            return(1);
 
841
#else
 
842
            return(0);
 
843
#endif
 
844
        case XML_WITH_PATTERN:
 
845
#ifdef LIBXML_PATTERN_ENABLED
 
846
            return(1);
 
847
#else
 
848
            return(0);
 
849
#endif
 
850
        case XML_WITH_WRITER:
 
851
#ifdef LIBXML_WRITER_ENABLED
 
852
            return(1);
 
853
#else
 
854
            return(0);
 
855
#endif
 
856
        case XML_WITH_SAX1:
 
857
#ifdef LIBXML_SAX1_ENABLED
 
858
            return(1);
 
859
#else
 
860
            return(0);
 
861
#endif
 
862
        case XML_WITH_FTP:
 
863
#ifdef LIBXML_FTP_ENABLED
 
864
            return(1);
 
865
#else
 
866
            return(0);
 
867
#endif
 
868
        case XML_WITH_HTTP:
 
869
#ifdef LIBXML_HTTP_ENABLED
 
870
            return(1);
 
871
#else
 
872
            return(0);
 
873
#endif
 
874
        case XML_WITH_VALID:
 
875
#ifdef LIBXML_VALID_ENABLED
 
876
            return(1);
 
877
#else
 
878
            return(0);
 
879
#endif
 
880
        case XML_WITH_HTML:
 
881
#ifdef LIBXML_HTML_ENABLED
 
882
            return(1);
 
883
#else
 
884
            return(0);
 
885
#endif
 
886
        case XML_WITH_LEGACY:
 
887
#ifdef LIBXML_LEGACY_ENABLED
 
888
            return(1);
 
889
#else
 
890
            return(0);
 
891
#endif
 
892
        case XML_WITH_C14N:
 
893
#ifdef LIBXML_C14N_ENABLED
 
894
            return(1);
 
895
#else
 
896
            return(0);
 
897
#endif
 
898
        case XML_WITH_CATALOG:
 
899
#ifdef LIBXML_CATALOG_ENABLED
 
900
            return(1);
 
901
#else
 
902
            return(0);
 
903
#endif
 
904
        case XML_WITH_XPATH:
 
905
#ifdef LIBXML_XPATH_ENABLED
 
906
            return(1);
 
907
#else
 
908
            return(0);
 
909
#endif
 
910
        case XML_WITH_XPTR:
 
911
#ifdef LIBXML_XPTR_ENABLED
 
912
            return(1);
 
913
#else
 
914
            return(0);
 
915
#endif
 
916
        case XML_WITH_XINCLUDE:
 
917
#ifdef LIBXML_XINCLUDE_ENABLED
 
918
            return(1);
 
919
#else
 
920
            return(0);
 
921
#endif
 
922
        case XML_WITH_ICONV:
 
923
#ifdef LIBXML_ICONV_ENABLED
 
924
            return(1);
 
925
#else
 
926
            return(0);
 
927
#endif
 
928
        case XML_WITH_ISO8859X:
 
929
#ifdef LIBXML_ISO8859X_ENABLED
 
930
            return(1);
 
931
#else
 
932
            return(0);
 
933
#endif
 
934
        case XML_WITH_UNICODE:
 
935
#ifdef LIBXML_UNICODE_ENABLED
 
936
            return(1);
 
937
#else
 
938
            return(0);
 
939
#endif
 
940
        case XML_WITH_REGEXP:
 
941
#ifdef LIBXML_REGEXP_ENABLED
 
942
            return(1);
 
943
#else
 
944
            return(0);
 
945
#endif
 
946
        case XML_WITH_AUTOMATA:
 
947
#ifdef LIBXML_AUTOMATA_ENABLED
 
948
            return(1);
 
949
#else
 
950
            return(0);
 
951
#endif
 
952
        case XML_WITH_EXPR:
 
953
#ifdef LIBXML_EXPR_ENABLED
 
954
            return(1);
 
955
#else
 
956
            return(0);
 
957
#endif
 
958
        case XML_WITH_SCHEMAS:
 
959
#ifdef LIBXML_SCHEMAS_ENABLED
 
960
            return(1);
 
961
#else
 
962
            return(0);
 
963
#endif
 
964
        case XML_WITH_SCHEMATRON:
 
965
#ifdef LIBXML_SCHEMATRON_ENABLED
 
966
            return(1);
 
967
#else
 
968
            return(0);
 
969
#endif
 
970
        case XML_WITH_MODULES:
 
971
#ifdef LIBXML_MODULES_ENABLED
 
972
            return(1);
 
973
#else
 
974
            return(0);
 
975
#endif
 
976
        case XML_WITH_DEBUG:
 
977
#ifdef LIBXML_DEBUG_ENABLED
 
978
            return(1);
 
979
#else
 
980
            return(0);
 
981
#endif
 
982
        case XML_WITH_DEBUG_MEM:
 
983
#ifdef DEBUG_MEMORY_LOCATION
 
984
            return(1);
 
985
#else
 
986
            return(0);
 
987
#endif
 
988
        case XML_WITH_DEBUG_RUN:
 
989
#ifdef LIBXML_DEBUG_RUNTIME
 
990
            return(1);
 
991
#else
 
992
            return(0);
 
993
#endif
 
994
        case XML_WITH_ZLIB:
 
995
#ifdef LIBXML_ZLIB_ENABLED
 
996
            return(1);
 
997
#else
 
998
            return(0);
 
999
#endif
 
1000
        case XML_WITH_LZMA:
 
1001
#ifdef LIBXML_LZMA_ENABLED
 
1002
            return(1);
 
1003
#else
 
1004
            return(0);
 
1005
#endif
 
1006
        case XML_WITH_ICU:
 
1007
#ifdef LIBXML_ICU_ENABLED
 
1008
            return(1);
 
1009
#else
 
1010
            return(0);
 
1011
#endif
 
1012
        default:
 
1013
            break;
 
1014
     }
 
1015
     return(0);
 
1016
}
 
1017
 
 
1018
/************************************************************************
 
1019
 *                                                                      *
 
1020
 *              SAX2 defaulted attributes handling                      *
 
1021
 *                                                                      *
 
1022
 ************************************************************************/
 
1023
 
 
1024
/**
 
1025
 * xmlDetectSAX2:
 
1026
 * @ctxt:  an XML parser context
 
1027
 *
 
1028
 * Do the SAX2 detection and specific intialization
 
1029
 */
 
1030
static void
 
1031
xmlDetectSAX2(xmlParserCtxtPtr ctxt) {
 
1032
    if (ctxt == NULL) return;
 
1033
#ifdef LIBXML_SAX1_ENABLED
 
1034
    if ((ctxt->sax) &&  (ctxt->sax->initialized == XML_SAX2_MAGIC) &&
 
1035
        ((ctxt->sax->startElementNs != NULL) ||
 
1036
         (ctxt->sax->endElementNs != NULL))) ctxt->sax2 = 1;
 
1037
#else
 
1038
    ctxt->sax2 = 1;
 
1039
#endif /* LIBXML_SAX1_ENABLED */
 
1040
 
 
1041
    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
 
1042
    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
 
1043
    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
 
1044
    if ((ctxt->str_xml==NULL) || (ctxt->str_xmlns==NULL) ||
 
1045
                (ctxt->str_xml_ns == NULL)) {
 
1046
        xmlErrMemory(ctxt, NULL);
 
1047
    }
 
1048
}
 
1049
 
 
1050
typedef struct _xmlDefAttrs xmlDefAttrs;
 
1051
typedef xmlDefAttrs *xmlDefAttrsPtr;
 
1052
struct _xmlDefAttrs {
 
1053
    int nbAttrs;        /* number of defaulted attributes on that element */
 
1054
    int maxAttrs;       /* the size of the array */
 
1055
    const xmlChar *values[5]; /* array of localname/prefix/values/external */
 
1056
};
 
1057
 
 
1058
/**
 
1059
 * xmlAttrNormalizeSpace:
 
1060
 * @src: the source string
 
1061
 * @dst: the target string
 
1062
 *
 
1063
 * Normalize the space in non CDATA attribute values:
 
1064
 * If the attribute type is not CDATA, then the XML processor MUST further
 
1065
 * process the normalized attribute value by discarding any leading and
 
1066
 * trailing space (#x20) characters, and by replacing sequences of space
 
1067
 * (#x20) characters by a single space (#x20) character.
 
1068
 * Note that the size of dst need to be at least src, and if one doesn't need
 
1069
 * to preserve dst (and it doesn't come from a dictionary or read-only) then
 
1070
 * passing src as dst is just fine.
 
1071
 *
 
1072
 * Returns a pointer to the normalized value (dst) or NULL if no conversion
 
1073
 *         is needed.
 
1074
 */
 
1075
static xmlChar *
 
1076
xmlAttrNormalizeSpace(const xmlChar *src, xmlChar *dst)
 
1077
{
 
1078
    if ((src == NULL) || (dst == NULL))
 
1079
        return(NULL);
 
1080
 
 
1081
    while (*src == 0x20) src++;
 
1082
    while (*src != 0) {
 
1083
        if (*src == 0x20) {
 
1084
            while (*src == 0x20) src++;
 
1085
            if (*src != 0)
 
1086
                *dst++ = 0x20;
 
1087
        } else {
 
1088
            *dst++ = *src++;
 
1089
        }
 
1090
    }
 
1091
    *dst = 0;
 
1092
    if (dst == src)
 
1093
       return(NULL);
 
1094
    return(dst);
 
1095
}
 
1096
 
 
1097
/**
 
1098
 * xmlAttrNormalizeSpace2:
 
1099
 * @src: the source string
 
1100
 *
 
1101
 * Normalize the space in non CDATA attribute values, a slightly more complex
 
1102
 * front end to avoid allocation problems when running on attribute values
 
1103
 * coming from the input.
 
1104
 *
 
1105
 * Returns a pointer to the normalized value (dst) or NULL if no conversion
 
1106
 *         is needed.
 
1107
 */
 
1108
static const xmlChar *
 
1109
xmlAttrNormalizeSpace2(xmlParserCtxtPtr ctxt, xmlChar *src, int *len)
 
1110
{
 
1111
    int i;
 
1112
    int remove_head = 0;
 
1113
    int need_realloc = 0;
 
1114
    const xmlChar *cur;
 
1115
 
 
1116
    if ((ctxt == NULL) || (src == NULL) || (len == NULL))
 
1117
        return(NULL);
 
1118
    i = *len;
 
1119
    if (i <= 0)
 
1120
        return(NULL);
 
1121
 
 
1122
    cur = src;
 
1123
    while (*cur == 0x20) {
 
1124
        cur++;
 
1125
        remove_head++;
 
1126
    }
 
1127
    while (*cur != 0) {
 
1128
        if (*cur == 0x20) {
 
1129
            cur++;
 
1130
            if ((*cur == 0x20) || (*cur == 0)) {
 
1131
                need_realloc = 1;
 
1132
                break;
 
1133
            }
 
1134
        } else
 
1135
            cur++;
 
1136
    }
 
1137
    if (need_realloc) {
 
1138
        xmlChar *ret;
 
1139
 
 
1140
        ret = xmlStrndup(src + remove_head, i - remove_head + 1);
 
1141
        if (ret == NULL) {
 
1142
            xmlErrMemory(ctxt, NULL);
 
1143
            return(NULL);
 
1144
        }
 
1145
        xmlAttrNormalizeSpace(ret, ret);
 
1146
        *len = (int) strlen((const char *)ret);
 
1147
        return(ret);
 
1148
    } else if (remove_head) {
 
1149
        *len -= remove_head;
 
1150
        memmove(src, src + remove_head, 1 + *len);
 
1151
        return(src);
 
1152
    }
 
1153
    return(NULL);
 
1154
}
 
1155
 
 
1156
/**
 
1157
 * xmlAddDefAttrs:
 
1158
 * @ctxt:  an XML parser context
 
1159
 * @fullname:  the element fullname
 
1160
 * @fullattr:  the attribute fullname
 
1161
 * @value:  the attribute value
 
1162
 *
 
1163
 * Add a defaulted attribute for an element
 
1164
 */
 
1165
static void
 
1166
xmlAddDefAttrs(xmlParserCtxtPtr ctxt,
 
1167
               const xmlChar *fullname,
 
1168
               const xmlChar *fullattr,
 
1169
               const xmlChar *value) {
 
1170
    xmlDefAttrsPtr defaults;
 
1171
    int len;
 
1172
    const xmlChar *name;
 
1173
    const xmlChar *prefix;
 
1174
 
 
1175
    /*
 
1176
     * Allows to detect attribute redefinitions
 
1177
     */
 
1178
    if (ctxt->attsSpecial != NULL) {
 
1179
        if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL)
 
1180
            return;
 
1181
    }
 
1182
 
 
1183
    if (ctxt->attsDefault == NULL) {
 
1184
        ctxt->attsDefault = xmlHashCreateDict(10, ctxt->dict);
 
1185
        if (ctxt->attsDefault == NULL)
 
1186
            goto mem_error;
 
1187
    }
 
1188
 
 
1189
    /*
 
1190
     * split the element name into prefix:localname , the string found
 
1191
     * are within the DTD and then not associated to namespace names.
 
1192
     */
 
1193
    name = xmlSplitQName3(fullname, &len);
 
1194
    if (name == NULL) {
 
1195
        name = xmlDictLookup(ctxt->dict, fullname, -1);
 
1196
        prefix = NULL;
 
1197
    } else {
 
1198
        name = xmlDictLookup(ctxt->dict, name, -1);
 
1199
        prefix = xmlDictLookup(ctxt->dict, fullname, len);
 
1200
    }
 
1201
 
 
1202
    /*
 
1203
     * make sure there is some storage
 
1204
     */
 
1205
    defaults = xmlHashLookup2(ctxt->attsDefault, name, prefix);
 
1206
    if (defaults == NULL) {
 
1207
        defaults = (xmlDefAttrsPtr) xmlMalloc(sizeof(xmlDefAttrs) +
 
1208
                           (4 * 5) * sizeof(const xmlChar *));
 
1209
        if (defaults == NULL)
 
1210
            goto mem_error;
 
1211
        defaults->nbAttrs = 0;
 
1212
        defaults->maxAttrs = 4;
 
1213
        if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix,
 
1214
                                defaults, NULL) < 0) {
 
1215
            xmlFree(defaults);
 
1216
            goto mem_error;
 
1217
        }
 
1218
    } else if (defaults->nbAttrs >= defaults->maxAttrs) {
 
1219
        xmlDefAttrsPtr temp;
 
1220
 
 
1221
        temp = (xmlDefAttrsPtr) xmlRealloc(defaults, sizeof(xmlDefAttrs) +
 
1222
                       (2 * defaults->maxAttrs * 5) * sizeof(const xmlChar *));
 
1223
        if (temp == NULL)
 
1224
            goto mem_error;
 
1225
        defaults = temp;
 
1226
        defaults->maxAttrs *= 2;
 
1227
        if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix,
 
1228
                                defaults, NULL) < 0) {
 
1229
            xmlFree(defaults);
 
1230
            goto mem_error;
 
1231
        }
 
1232
    }
 
1233
 
 
1234
    /*
 
1235
     * Split the element name into prefix:localname , the string found
 
1236
     * are within the DTD and hen not associated to namespace names.
 
1237
     */
 
1238
    name = xmlSplitQName3(fullattr, &len);
 
1239
    if (name == NULL) {
 
1240
        name = xmlDictLookup(ctxt->dict, fullattr, -1);
 
1241
        prefix = NULL;
 
1242
    } else {
 
1243
        name = xmlDictLookup(ctxt->dict, name, -1);
 
1244
        prefix = xmlDictLookup(ctxt->dict, fullattr, len);
 
1245
    }
 
1246
 
 
1247
    defaults->values[5 * defaults->nbAttrs] = name;
 
1248
    defaults->values[5 * defaults->nbAttrs + 1] = prefix;
 
1249
    /* intern the string and precompute the end */
 
1250
    len = xmlStrlen(value);
 
1251
    value = xmlDictLookup(ctxt->dict, value, len);
 
1252
    defaults->values[5 * defaults->nbAttrs + 2] = value;
 
1253
    defaults->values[5 * defaults->nbAttrs + 3] = value + len;
 
1254
    if (ctxt->external)
 
1255
        defaults->values[5 * defaults->nbAttrs + 4] = BAD_CAST "external";
 
1256
    else
 
1257
        defaults->values[5 * defaults->nbAttrs + 4] = NULL;
 
1258
    defaults->nbAttrs++;
 
1259
 
 
1260
    return;
 
1261
 
 
1262
mem_error:
 
1263
    xmlErrMemory(ctxt, NULL);
 
1264
    return;
 
1265
}
 
1266
 
 
1267
/**
 
1268
 * xmlAddSpecialAttr:
 
1269
 * @ctxt:  an XML parser context
 
1270
 * @fullname:  the element fullname
 
1271
 * @fullattr:  the attribute fullname
 
1272
 * @type:  the attribute type
 
1273
 *
 
1274
 * Register this attribute type
 
1275
 */
 
1276
static void
 
1277
xmlAddSpecialAttr(xmlParserCtxtPtr ctxt,
 
1278
                  const xmlChar *fullname,
 
1279
                  const xmlChar *fullattr,
 
1280
                  int type)
 
1281
{
 
1282
    if (ctxt->attsSpecial == NULL) {
 
1283
        ctxt->attsSpecial = xmlHashCreateDict(10, ctxt->dict);
 
1284
        if (ctxt->attsSpecial == NULL)
 
1285
            goto mem_error;
 
1286
    }
 
1287
 
 
1288
    if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL)
 
1289
        return;
 
1290
 
 
1291
    xmlHashAddEntry2(ctxt->attsSpecial, fullname, fullattr,
 
1292
                     (void *) (long) type);
 
1293
    return;
 
1294
 
 
1295
mem_error:
 
1296
    xmlErrMemory(ctxt, NULL);
 
1297
    return;
 
1298
}
 
1299
 
 
1300
/**
 
1301
 * xmlCleanSpecialAttrCallback:
 
1302
 *
 
1303
 * Removes CDATA attributes from the special attribute table
 
1304
 */
 
1305
static void
 
1306
xmlCleanSpecialAttrCallback(void *payload, void *data,
 
1307
                            const xmlChar *fullname, const xmlChar *fullattr,
 
1308
                            const xmlChar *unused ATTRIBUTE_UNUSED) {
 
1309
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) data;
 
1310
 
 
1311
    if (((long) payload) == XML_ATTRIBUTE_CDATA) {
 
1312
        xmlHashRemoveEntry2(ctxt->attsSpecial, fullname, fullattr, NULL);
 
1313
    }
 
1314
}
 
1315
 
 
1316
/**
 
1317
 * xmlCleanSpecialAttr:
 
1318
 * @ctxt:  an XML parser context
 
1319
 *
 
1320
 * Trim the list of attributes defined to remove all those of type
 
1321
 * CDATA as they are not special. This call should be done when finishing
 
1322
 * to parse the DTD and before starting to parse the document root.
 
1323
 */
 
1324
static void
 
1325
xmlCleanSpecialAttr(xmlParserCtxtPtr ctxt)
 
1326
{
 
1327
    if (ctxt->attsSpecial == NULL)
 
1328
        return;
 
1329
 
 
1330
    xmlHashScanFull(ctxt->attsSpecial, xmlCleanSpecialAttrCallback, ctxt);
 
1331
 
 
1332
    if (xmlHashSize(ctxt->attsSpecial) == 0) {
 
1333
        xmlHashFree(ctxt->attsSpecial, NULL);
 
1334
        ctxt->attsSpecial = NULL;
 
1335
    }
 
1336
    return;
 
1337
}
 
1338
 
 
1339
/**
 
1340
 * xmlCheckLanguageID:
 
1341
 * @lang:  pointer to the string value
 
1342
 *
 
1343
 * Checks that the value conforms to the LanguageID production:
 
1344
 *
 
1345
 * NOTE: this is somewhat deprecated, those productions were removed from
 
1346
 *       the XML Second edition.
 
1347
 *
 
1348
 * [33] LanguageID ::= Langcode ('-' Subcode)*
 
1349
 * [34] Langcode ::= ISO639Code |  IanaCode |  UserCode
 
1350
 * [35] ISO639Code ::= ([a-z] | [A-Z]) ([a-z] | [A-Z])
 
1351
 * [36] IanaCode ::= ('i' | 'I') '-' ([a-z] | [A-Z])+
 
1352
 * [37] UserCode ::= ('x' | 'X') '-' ([a-z] | [A-Z])+
 
1353
 * [38] Subcode ::= ([a-z] | [A-Z])+
 
1354
 *
 
1355
 * The current REC reference the sucessors of RFC 1766, currently 5646
 
1356
 *
 
1357
 * http://www.rfc-editor.org/rfc/rfc5646.txt
 
1358
 * langtag       = language
 
1359
 *                 ["-" script]
 
1360
 *                 ["-" region]
 
1361
 *                 *("-" variant)
 
1362
 *                 *("-" extension)
 
1363
 *                 ["-" privateuse]
 
1364
 * language      = 2*3ALPHA            ; shortest ISO 639 code
 
1365
 *                 ["-" extlang]       ; sometimes followed by
 
1366
 *                                     ; extended language subtags
 
1367
 *               / 4ALPHA              ; or reserved for future use
 
1368
 *               / 5*8ALPHA            ; or registered language subtag
 
1369
 *
 
1370
 * extlang       = 3ALPHA              ; selected ISO 639 codes
 
1371
 *                 *2("-" 3ALPHA)      ; permanently reserved
 
1372
 *
 
1373
 * script        = 4ALPHA              ; ISO 15924 code
 
1374
 *
 
1375
 * region        = 2ALPHA              ; ISO 3166-1 code
 
1376
 *               / 3DIGIT              ; UN M.49 code
 
1377
 *
 
1378
 * variant       = 5*8alphanum         ; registered variants
 
1379
 *               / (DIGIT 3alphanum)
 
1380
 *
 
1381
 * extension     = singleton 1*("-" (2*8alphanum))
 
1382
 *
 
1383
 *                                     ; Single alphanumerics
 
1384
 *                                     ; "x" reserved for private use
 
1385
 * singleton     = DIGIT               ; 0 - 9
 
1386
 *               / %x41-57             ; A - W
 
1387
 *               / %x59-5A             ; Y - Z
 
1388
 *               / %x61-77             ; a - w
 
1389
 *               / %x79-7A             ; y - z
 
1390
 *
 
1391
 * it sounds right to still allow Irregular i-xxx IANA and user codes too
 
1392
 * The parser below doesn't try to cope with extension or privateuse
 
1393
 * that could be added but that's not interoperable anyway
 
1394
 *
 
1395
 * Returns 1 if correct 0 otherwise
 
1396
 **/
 
1397
int
 
1398
xmlCheckLanguageID(const xmlChar * lang)
 
1399
{
 
1400
    const xmlChar *cur = lang, *nxt;
 
1401
 
 
1402
    if (cur == NULL)
 
1403
        return (0);
 
1404
    if (((cur[0] == 'i') && (cur[1] == '-')) ||
 
1405
        ((cur[0] == 'I') && (cur[1] == '-')) ||
 
1406
        ((cur[0] == 'x') && (cur[1] == '-')) ||
 
1407
        ((cur[0] == 'X') && (cur[1] == '-'))) {
 
1408
        /*
 
1409
         * Still allow IANA code and user code which were coming
 
1410
         * from the previous version of the XML-1.0 specification
 
1411
         * it's deprecated but we should not fail
 
1412
         */
 
1413
        cur += 2;
 
1414
        while (((cur[0] >= 'A') && (cur[0] <= 'Z')) ||
 
1415
               ((cur[0] >= 'a') && (cur[0] <= 'z')))
 
1416
            cur++;
 
1417
        return(cur[0] == 0);
 
1418
    }
 
1419
    nxt = cur;
 
1420
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
 
1421
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
 
1422
           nxt++;
 
1423
    if (nxt - cur >= 4) {
 
1424
        /*
 
1425
         * Reserved
 
1426
         */
 
1427
        if ((nxt - cur > 8) || (nxt[0] != 0))
 
1428
            return(0);
 
1429
        return(1);
 
1430
    }
 
1431
    if (nxt - cur < 2)
 
1432
        return(0);
 
1433
    /* we got an ISO 639 code */
 
1434
    if (nxt[0] == 0)
 
1435
        return(1);
 
1436
    if (nxt[0] != '-')
 
1437
        return(0);
 
1438
 
 
1439
    nxt++;
 
1440
    cur = nxt;
 
1441
    /* now we can have extlang or script or region or variant */
 
1442
    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
 
1443
        goto region_m49;
 
1444
 
 
1445
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
 
1446
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
 
1447
           nxt++;
 
1448
    if (nxt - cur == 4)
 
1449
        goto script;
 
1450
    if (nxt - cur == 2)
 
1451
        goto region;
 
1452
    if ((nxt - cur >= 5) && (nxt - cur <= 8))
 
1453
        goto variant;
 
1454
    if (nxt - cur != 3)
 
1455
        return(0);
 
1456
    /* we parsed an extlang */
 
1457
    if (nxt[0] == 0)
 
1458
        return(1);
 
1459
    if (nxt[0] != '-')
 
1460
        return(0);
 
1461
 
 
1462
    nxt++;
 
1463
    cur = nxt;
 
1464
    /* now we can have script or region or variant */
 
1465
    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
 
1466
        goto region_m49;
 
1467
 
 
1468
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
 
1469
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
 
1470
           nxt++;
 
1471
    if (nxt - cur == 2)
 
1472
        goto region;
 
1473
    if ((nxt - cur >= 5) && (nxt - cur <= 8))
 
1474
        goto variant;
 
1475
    if (nxt - cur != 4)
 
1476
        return(0);
 
1477
    /* we parsed a script */
 
1478
script:
 
1479
    if (nxt[0] == 0)
 
1480
        return(1);
 
1481
    if (nxt[0] != '-')
 
1482
        return(0);
 
1483
 
 
1484
    nxt++;
 
1485
    cur = nxt;
 
1486
    /* now we can have region or variant */
 
1487
    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
 
1488
        goto region_m49;
 
1489
 
 
1490
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
 
1491
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
 
1492
           nxt++;
 
1493
 
 
1494
    if ((nxt - cur >= 5) && (nxt - cur <= 8))
 
1495
        goto variant;
 
1496
    if (nxt - cur != 2)
 
1497
        return(0);
 
1498
    /* we parsed a region */
 
1499
region:
 
1500
    if (nxt[0] == 0)
 
1501
        return(1);
 
1502
    if (nxt[0] != '-')
 
1503
        return(0);
 
1504
 
 
1505
    nxt++;
 
1506
    cur = nxt;
 
1507
    /* now we can just have a variant */
 
1508
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
 
1509
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
 
1510
           nxt++;
 
1511
 
 
1512
    if ((nxt - cur < 5) || (nxt - cur > 8))
 
1513
        return(0);
 
1514
 
 
1515
    /* we parsed a variant */
 
1516
variant:
 
1517
    if (nxt[0] == 0)
 
1518
        return(1);
 
1519
    if (nxt[0] != '-')
 
1520
        return(0);
 
1521
    /* extensions and private use subtags not checked */
 
1522
    return (1);
 
1523
 
 
1524
region_m49:
 
1525
    if (((nxt[1] >= '0') && (nxt[1] <= '9')) &&
 
1526
        ((nxt[2] >= '0') && (nxt[2] <= '9'))) {
 
1527
        nxt += 3;
 
1528
        goto region;
 
1529
    }
 
1530
    return(0);
 
1531
}
 
1532
 
 
1533
/************************************************************************
 
1534
 *                                                                      *
 
1535
 *              Parser stacks related functions and macros              *
 
1536
 *                                                                      *
 
1537
 ************************************************************************/
 
1538
 
 
1539
static xmlEntityPtr xmlParseStringEntityRef(xmlParserCtxtPtr ctxt,
 
1540
                                            const xmlChar ** str);
 
1541
 
 
1542
#ifdef SAX2
 
1543
/**
 
1544
 * nsPush:
 
1545
 * @ctxt:  an XML parser context
 
1546
 * @prefix:  the namespace prefix or NULL
 
1547
 * @URL:  the namespace name
 
1548
 *
 
1549
 * Pushes a new parser namespace on top of the ns stack
 
1550
 *
 
1551
 * Returns -1 in case of error, -2 if the namespace should be discarded
 
1552
 *         and the index in the stack otherwise.
 
1553
 */
 
1554
static int
 
1555
nsPush(xmlParserCtxtPtr ctxt, const xmlChar *prefix, const xmlChar *URL)
 
1556
{
 
1557
    if (ctxt->options & XML_PARSE_NSCLEAN) {
 
1558
        int i;
 
1559
        for (i = ctxt->nsNr - 2;i >= 0;i -= 2) {
 
1560
            if (ctxt->nsTab[i] == prefix) {
 
1561
                /* in scope */
 
1562
                if (ctxt->nsTab[i + 1] == URL)
 
1563
                    return(-2);
 
1564
                /* out of scope keep it */
 
1565
                break;
 
1566
            }
 
1567
        }
 
1568
    }
 
1569
    if ((ctxt->nsMax == 0) || (ctxt->nsTab == NULL)) {
 
1570
        ctxt->nsMax = 10;
 
1571
        ctxt->nsNr = 0;
 
1572
        ctxt->nsTab = (const xmlChar **)
 
1573
                      xmlMalloc(ctxt->nsMax * sizeof(xmlChar *));
 
1574
        if (ctxt->nsTab == NULL) {
 
1575
            xmlErrMemory(ctxt, NULL);
 
1576
            ctxt->nsMax = 0;
 
1577
            return (-1);
 
1578
        }
 
1579
    } else if (ctxt->nsNr >= ctxt->nsMax) {
 
1580
        const xmlChar ** tmp;
 
1581
        ctxt->nsMax *= 2;
 
1582
        tmp = (const xmlChar **) xmlRealloc((char *) ctxt->nsTab,
 
1583
                                    ctxt->nsMax * sizeof(ctxt->nsTab[0]));
 
1584
        if (tmp == NULL) {
 
1585
            xmlErrMemory(ctxt, NULL);
 
1586
            ctxt->nsMax /= 2;
 
1587
            return (-1);
 
1588
        }
 
1589
        ctxt->nsTab = tmp;
 
1590
    }
 
1591
    ctxt->nsTab[ctxt->nsNr++] = prefix;
 
1592
    ctxt->nsTab[ctxt->nsNr++] = URL;
 
1593
    return (ctxt->nsNr);
 
1594
}
 
1595
/**
 
1596
 * nsPop:
 
1597
 * @ctxt: an XML parser context
 
1598
 * @nr:  the number to pop
 
1599
 *
 
1600
 * Pops the top @nr parser prefix/namespace from the ns stack
 
1601
 *
 
1602
 * Returns the number of namespaces removed
 
1603
 */
 
1604
static int
 
1605
nsPop(xmlParserCtxtPtr ctxt, int nr)
 
1606
{
 
1607
    int i;
 
1608
 
 
1609
    if (ctxt->nsTab == NULL) return(0);
 
1610
    if (ctxt->nsNr < nr) {
 
1611
        xmlGenericError(xmlGenericErrorContext, "Pbm popping %d NS\n", nr);
 
1612
        nr = ctxt->nsNr;
 
1613
    }
 
1614
    if (ctxt->nsNr <= 0)
 
1615
        return (0);
 
1616
 
 
1617
    for (i = 0;i < nr;i++) {
 
1618
         ctxt->nsNr--;
 
1619
         ctxt->nsTab[ctxt->nsNr] = NULL;
 
1620
    }
 
1621
    return(nr);
 
1622
}
 
1623
#endif
 
1624
 
 
1625
static int
 
1626
xmlCtxtGrowAttrs(xmlParserCtxtPtr ctxt, int nr) {
 
1627
    const xmlChar **atts;
 
1628
    int *attallocs;
 
1629
    int maxatts;
 
1630
 
 
1631
    if (ctxt->atts == NULL) {
 
1632
        maxatts = 55; /* allow for 10 attrs by default */
 
1633
        atts = (const xmlChar **)
 
1634
               xmlMalloc(maxatts * sizeof(xmlChar *));
 
1635
        if (atts == NULL) goto mem_error;
 
1636
        ctxt->atts = atts;
 
1637
        attallocs = (int *) xmlMalloc((maxatts / 5) * sizeof(int));
 
1638
        if (attallocs == NULL) goto mem_error;
 
1639
        ctxt->attallocs = attallocs;
 
1640
        ctxt->maxatts = maxatts;
 
1641
    } else if (nr + 5 > ctxt->maxatts) {
 
1642
        maxatts = (nr + 5) * 2;
 
1643
        atts = (const xmlChar **) xmlRealloc((void *) ctxt->atts,
 
1644
                                     maxatts * sizeof(const xmlChar *));
 
1645
        if (atts == NULL) goto mem_error;
 
1646
        ctxt->atts = atts;
 
1647
        attallocs = (int *) xmlRealloc((void *) ctxt->attallocs,
 
1648
                                     (maxatts / 5) * sizeof(int));
 
1649
        if (attallocs == NULL) goto mem_error;
 
1650
        ctxt->attallocs = attallocs;
 
1651
        ctxt->maxatts = maxatts;
 
1652
    }
 
1653
    return(ctxt->maxatts);
 
1654
mem_error:
 
1655
    xmlErrMemory(ctxt, NULL);
 
1656
    return(-1);
 
1657
}
 
1658
 
 
1659
/**
 
1660
 * inputPush:
 
1661
 * @ctxt:  an XML parser context
 
1662
 * @value:  the parser input
 
1663
 *
 
1664
 * Pushes a new parser input on top of the input stack
 
1665
 *
 
1666
 * Returns -1 in case of error, the index in the stack otherwise
 
1667
 */
 
1668
int
 
1669
inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value)
 
1670
{
 
1671
    if ((ctxt == NULL) || (value == NULL))
 
1672
        return(-1);
 
1673
    if (ctxt->inputNr >= ctxt->inputMax) {
 
1674
        ctxt->inputMax *= 2;
 
1675
        ctxt->inputTab =
 
1676
            (xmlParserInputPtr *) xmlRealloc(ctxt->inputTab,
 
1677
                                             ctxt->inputMax *
 
1678
                                             sizeof(ctxt->inputTab[0]));
 
1679
        if (ctxt->inputTab == NULL) {
 
1680
            xmlErrMemory(ctxt, NULL);
 
1681
            xmlFreeInputStream(value);
 
1682
            ctxt->inputMax /= 2;
 
1683
            value = NULL;
 
1684
            return (-1);
 
1685
        }
 
1686
    }
 
1687
    ctxt->inputTab[ctxt->inputNr] = value;
 
1688
    ctxt->input = value;
 
1689
    return (ctxt->inputNr++);
 
1690
}
 
1691
/**
 
1692
 * inputPop:
 
1693
 * @ctxt: an XML parser context
 
1694
 *
 
1695
 * Pops the top parser input from the input stack
 
1696
 *
 
1697
 * Returns the input just removed
 
1698
 */
 
1699
xmlParserInputPtr
 
1700
inputPop(xmlParserCtxtPtr ctxt)
 
1701
{
 
1702
    xmlParserInputPtr ret;
 
1703
 
 
1704
    if (ctxt == NULL)
 
1705
        return(NULL);
 
1706
    if (ctxt->inputNr <= 0)
 
1707
        return (NULL);
 
1708
    ctxt->inputNr--;
 
1709
    if (ctxt->inputNr > 0)
 
1710
        ctxt->input = ctxt->inputTab[ctxt->inputNr - 1];
 
1711
    else
 
1712
        ctxt->input = NULL;
 
1713
    ret = ctxt->inputTab[ctxt->inputNr];
 
1714
    ctxt->inputTab[ctxt->inputNr] = NULL;
 
1715
    return (ret);
 
1716
}
 
1717
/**
 
1718
 * nodePush:
 
1719
 * @ctxt:  an XML parser context
 
1720
 * @value:  the element node
 
1721
 *
 
1722
 * Pushes a new element node on top of the node stack
 
1723
 *
 
1724
 * Returns -1 in case of error, the index in the stack otherwise
 
1725
 */
 
1726
int
 
1727
nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value)
 
1728
{
 
1729
    if (ctxt == NULL) return(0);
 
1730
    if (ctxt->nodeNr >= ctxt->nodeMax) {
 
1731
        xmlNodePtr *tmp;
 
1732
 
 
1733
        tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
 
1734
                                      ctxt->nodeMax * 2 *
 
1735
                                      sizeof(ctxt->nodeTab[0]));
 
1736
        if (tmp == NULL) {
 
1737
            xmlErrMemory(ctxt, NULL);
 
1738
            return (-1);
 
1739
        }
 
1740
        ctxt->nodeTab = tmp;
 
1741
        ctxt->nodeMax *= 2;
 
1742
    }
 
1743
    if ((((unsigned int) ctxt->nodeNr) > xmlParserMaxDepth) &&
 
1744
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
1745
        xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
 
1746
                 "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
 
1747
                          xmlParserMaxDepth);
 
1748
        ctxt->instate = XML_PARSER_EOF;
 
1749
        return(-1);
 
1750
    }
 
1751
    ctxt->nodeTab[ctxt->nodeNr] = value;
 
1752
    ctxt->node = value;
 
1753
    return (ctxt->nodeNr++);
 
1754
}
 
1755
 
 
1756
/**
 
1757
 * nodePop:
 
1758
 * @ctxt: an XML parser context
 
1759
 *
 
1760
 * Pops the top element node from the node stack
 
1761
 *
 
1762
 * Returns the node just removed
 
1763
 */
 
1764
xmlNodePtr
 
1765
nodePop(xmlParserCtxtPtr ctxt)
 
1766
{
 
1767
    xmlNodePtr ret;
 
1768
 
 
1769
    if (ctxt == NULL) return(NULL);
 
1770
    if (ctxt->nodeNr <= 0)
 
1771
        return (NULL);
 
1772
    ctxt->nodeNr--;
 
1773
    if (ctxt->nodeNr > 0)
 
1774
        ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1];
 
1775
    else
 
1776
        ctxt->node = NULL;
 
1777
    ret = ctxt->nodeTab[ctxt->nodeNr];
 
1778
    ctxt->nodeTab[ctxt->nodeNr] = NULL;
 
1779
    return (ret);
 
1780
}
 
1781
 
 
1782
#ifdef LIBXML_PUSH_ENABLED
 
1783
/**
 
1784
 * nameNsPush:
 
1785
 * @ctxt:  an XML parser context
 
1786
 * @value:  the element name
 
1787
 * @prefix:  the element prefix
 
1788
 * @URI:  the element namespace name
 
1789
 *
 
1790
 * Pushes a new element name/prefix/URL on top of the name stack
 
1791
 *
 
1792
 * Returns -1 in case of error, the index in the stack otherwise
 
1793
 */
 
1794
static int
 
1795
nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
 
1796
           const xmlChar *prefix, const xmlChar *URI, int nsNr)
 
1797
{
 
1798
    if (ctxt->nameNr >= ctxt->nameMax) {
 
1799
        const xmlChar * *tmp;
 
1800
        void **tmp2;
 
1801
        ctxt->nameMax *= 2;
 
1802
        tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
 
1803
                                    ctxt->nameMax *
 
1804
                                    sizeof(ctxt->nameTab[0]));
 
1805
        if (tmp == NULL) {
 
1806
            ctxt->nameMax /= 2;
 
1807
            goto mem_error;
 
1808
        }
 
1809
        ctxt->nameTab = tmp;
 
1810
        tmp2 = (void **) xmlRealloc((void * *)ctxt->pushTab,
 
1811
                                    ctxt->nameMax * 3 *
 
1812
                                    sizeof(ctxt->pushTab[0]));
 
1813
        if (tmp2 == NULL) {
 
1814
            ctxt->nameMax /= 2;
 
1815
            goto mem_error;
 
1816
        }
 
1817
        ctxt->pushTab = tmp2;
 
1818
    }
 
1819
    ctxt->nameTab[ctxt->nameNr] = value;
 
1820
    ctxt->name = value;
 
1821
    ctxt->pushTab[ctxt->nameNr * 3] = (void *) prefix;
 
1822
    ctxt->pushTab[ctxt->nameNr * 3 + 1] = (void *) URI;
 
1823
    ctxt->pushTab[ctxt->nameNr * 3 + 2] = (void *) (long) nsNr;
 
1824
    return (ctxt->nameNr++);
 
1825
mem_error:
 
1826
    xmlErrMemory(ctxt, NULL);
 
1827
    return (-1);
 
1828
}
 
1829
/**
 
1830
 * nameNsPop:
 
1831
 * @ctxt: an XML parser context
 
1832
 *
 
1833
 * Pops the top element/prefix/URI name from the name stack
 
1834
 *
 
1835
 * Returns the name just removed
 
1836
 */
 
1837
static const xmlChar *
 
1838
nameNsPop(xmlParserCtxtPtr ctxt)
 
1839
{
 
1840
    const xmlChar *ret;
 
1841
 
 
1842
    if (ctxt->nameNr <= 0)
 
1843
        return (NULL);
 
1844
    ctxt->nameNr--;
 
1845
    if (ctxt->nameNr > 0)
 
1846
        ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
 
1847
    else
 
1848
        ctxt->name = NULL;
 
1849
    ret = ctxt->nameTab[ctxt->nameNr];
 
1850
    ctxt->nameTab[ctxt->nameNr] = NULL;
 
1851
    return (ret);
 
1852
}
 
1853
#endif /* LIBXML_PUSH_ENABLED */
 
1854
 
 
1855
/**
 
1856
 * namePush:
 
1857
 * @ctxt:  an XML parser context
 
1858
 * @value:  the element name
 
1859
 *
 
1860
 * Pushes a new element name on top of the name stack
 
1861
 *
 
1862
 * Returns -1 in case of error, the index in the stack otherwise
 
1863
 */
 
1864
int
 
1865
namePush(xmlParserCtxtPtr ctxt, const xmlChar * value)
 
1866
{
 
1867
    if (ctxt == NULL) return (-1);
 
1868
 
 
1869
    if (ctxt->nameNr >= ctxt->nameMax) {
 
1870
        const xmlChar * *tmp;
 
1871
        tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
 
1872
                                    ctxt->nameMax * 2 *
 
1873
                                    sizeof(ctxt->nameTab[0]));
 
1874
        if (tmp == NULL) {
 
1875
            goto mem_error;
 
1876
        }
 
1877
        ctxt->nameTab = tmp;
 
1878
        ctxt->nameMax *= 2;
 
1879
    }
 
1880
    ctxt->nameTab[ctxt->nameNr] = value;
 
1881
    ctxt->name = value;
 
1882
    return (ctxt->nameNr++);
 
1883
mem_error:
 
1884
    xmlErrMemory(ctxt, NULL);
 
1885
    return (-1);
 
1886
}
 
1887
/**
 
1888
 * namePop:
 
1889
 * @ctxt: an XML parser context
 
1890
 *
 
1891
 * Pops the top element name from the name stack
 
1892
 *
 
1893
 * Returns the name just removed
 
1894
 */
 
1895
const xmlChar *
 
1896
namePop(xmlParserCtxtPtr ctxt)
 
1897
{
 
1898
    const xmlChar *ret;
 
1899
 
 
1900
    if ((ctxt == NULL) || (ctxt->nameNr <= 0))
 
1901
        return (NULL);
 
1902
    ctxt->nameNr--;
 
1903
    if (ctxt->nameNr > 0)
 
1904
        ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
 
1905
    else
 
1906
        ctxt->name = NULL;
 
1907
    ret = ctxt->nameTab[ctxt->nameNr];
 
1908
    ctxt->nameTab[ctxt->nameNr] = NULL;
 
1909
    return (ret);
 
1910
}
 
1911
 
 
1912
static int spacePush(xmlParserCtxtPtr ctxt, int val) {
 
1913
    if (ctxt->spaceNr >= ctxt->spaceMax) {
 
1914
        int *tmp;
 
1915
 
 
1916
        ctxt->spaceMax *= 2;
 
1917
        tmp = (int *) xmlRealloc(ctxt->spaceTab,
 
1918
                                 ctxt->spaceMax * sizeof(ctxt->spaceTab[0]));
 
1919
        if (tmp == NULL) {
 
1920
            xmlErrMemory(ctxt, NULL);
 
1921
            ctxt->spaceMax /=2;
 
1922
            return(-1);
 
1923
        }
 
1924
        ctxt->spaceTab = tmp;
 
1925
    }
 
1926
    ctxt->spaceTab[ctxt->spaceNr] = val;
 
1927
    ctxt->space = &ctxt->spaceTab[ctxt->spaceNr];
 
1928
    return(ctxt->spaceNr++);
 
1929
}
 
1930
 
 
1931
static int spacePop(xmlParserCtxtPtr ctxt) {
 
1932
    int ret;
 
1933
    if (ctxt->spaceNr <= 0) return(0);
 
1934
    ctxt->spaceNr--;
 
1935
    if (ctxt->spaceNr > 0)
 
1936
        ctxt->space = &ctxt->spaceTab[ctxt->spaceNr - 1];
 
1937
    else
 
1938
        ctxt->space = &ctxt->spaceTab[0];
 
1939
    ret = ctxt->spaceTab[ctxt->spaceNr];
 
1940
    ctxt->spaceTab[ctxt->spaceNr] = -1;
 
1941
    return(ret);
 
1942
}
 
1943
 
 
1944
/*
 
1945
 * Macros for accessing the content. Those should be used only by the parser,
 
1946
 * and not exported.
 
1947
 *
 
1948
 * Dirty macros, i.e. one often need to make assumption on the context to
 
1949
 * use them
 
1950
 *
 
1951
 *   CUR_PTR return the current pointer to the xmlChar to be parsed.
 
1952
 *           To be used with extreme caution since operations consuming
 
1953
 *           characters may move the input buffer to a different location !
 
1954
 *   CUR     returns the current xmlChar value, i.e. a 8 bit value if compiled
 
1955
 *           This should be used internally by the parser
 
1956
 *           only to compare to ASCII values otherwise it would break when
 
1957
 *           running with UTF-8 encoding.
 
1958
 *   RAW     same as CUR but in the input buffer, bypass any token
 
1959
 *           extraction that may have been done
 
1960
 *   NXT(n)  returns the n'th next xmlChar. Same as CUR is should be used only
 
1961
 *           to compare on ASCII based substring.
 
1962
 *   SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
 
1963
 *           strings without newlines within the parser.
 
1964
 *   NEXT1(l) Skip 1 xmlChar, and must also be used only to skip 1 non-newline ASCII
 
1965
 *           defined char within the parser.
 
1966
 * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
 
1967
 *
 
1968
 *   NEXT    Skip to the next character, this does the proper decoding
 
1969
 *           in UTF-8 mode. It also pop-up unfinished entities on the fly.
 
1970
 *   NEXTL(l) Skip the current unicode character of l xmlChars long.
 
1971
 *   CUR_CHAR(l) returns the current unicode character (int), set l
 
1972
 *           to the number of xmlChars used for the encoding [0-5].
 
1973
 *   CUR_SCHAR  same but operate on a string instead of the context
 
1974
 *   COPY_BUF  copy the current unicode char to the target buffer, increment
 
1975
 *            the index
 
1976
 *   GROW, SHRINK  handling of input buffers
 
1977
 */
 
1978
 
 
1979
#define RAW (*ctxt->input->cur)
 
1980
#define CUR (*ctxt->input->cur)
 
1981
#define NXT(val) ctxt->input->cur[(val)]
 
1982
#define CUR_PTR ctxt->input->cur
 
1983
 
 
1984
#define CMP4( s, c1, c2, c3, c4 ) \
 
1985
  ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char *) s)[ 1 ] == c2 && \
 
1986
    ((unsigned char *) s)[ 2 ] == c3 && ((unsigned char *) s)[ 3 ] == c4 )
 
1987
#define CMP5( s, c1, c2, c3, c4, c5 ) \
 
1988
  ( CMP4( s, c1, c2, c3, c4 ) && ((unsigned char *) s)[ 4 ] == c5 )
 
1989
#define CMP6( s, c1, c2, c3, c4, c5, c6 ) \
 
1990
  ( CMP5( s, c1, c2, c3, c4, c5 ) && ((unsigned char *) s)[ 5 ] == c6 )
 
1991
#define CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) \
 
1992
  ( CMP6( s, c1, c2, c3, c4, c5, c6 ) && ((unsigned char *) s)[ 6 ] == c7 )
 
1993
#define CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) \
 
1994
  ( CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) && ((unsigned char *) s)[ 7 ] == c8 )
 
1995
#define CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) \
 
1996
  ( CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) && \
 
1997
    ((unsigned char *) s)[ 8 ] == c9 )
 
1998
#define CMP10( s, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 ) \
 
1999
  ( CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) && \
 
2000
    ((unsigned char *) s)[ 9 ] == c10 )
 
2001
 
 
2002
#define SKIP(val) do {                                                  \
 
2003
    ctxt->nbChars += (val),ctxt->input->cur += (val),ctxt->input->col+=(val);                   \
 
2004
    if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);     \
 
2005
    if ((*ctxt->input->cur == 0) &&                                     \
 
2006
        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))            \
 
2007
            xmlPopInput(ctxt);                                          \
 
2008
  } while (0)
 
2009
 
 
2010
#define SKIPL(val) do {                                                 \
 
2011
    int skipl;                                                          \
 
2012
    for(skipl=0; skipl<val; skipl++) {                                  \
 
2013
        if (*(ctxt->input->cur) == '\n') {                              \
 
2014
        ctxt->input->line++; ctxt->input->col = 1;                      \
 
2015
        } else ctxt->input->col++;                                      \
 
2016
        ctxt->nbChars++;                                                \
 
2017
        ctxt->input->cur++;                                             \
 
2018
    }                                                                   \
 
2019
    if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);     \
 
2020
    if ((*ctxt->input->cur == 0) &&                                     \
 
2021
        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))            \
 
2022
            xmlPopInput(ctxt);                                          \
 
2023
  } while (0)
 
2024
 
 
2025
#define SHRINK if ((ctxt->progressive == 0) &&                          \
 
2026
                   (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \
 
2027
                   (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \
 
2028
        xmlSHRINK (ctxt);
 
2029
 
 
2030
static void xmlSHRINK (xmlParserCtxtPtr ctxt) {
 
2031
    xmlParserInputShrink(ctxt->input);
 
2032
    if ((*ctxt->input->cur == 0) &&
 
2033
        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
 
2034
            xmlPopInput(ctxt);
 
2035
  }
 
2036
 
 
2037
#define GROW if ((ctxt->progressive == 0) &&                            \
 
2038
                 (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK))   \
 
2039
        xmlGROW (ctxt);
 
2040
 
 
2041
static void xmlGROW (xmlParserCtxtPtr ctxt) {
 
2042
    if ((((ctxt->input->end - ctxt->input->cur) > XML_MAX_LOOKUP_LIMIT) ||
 
2043
         ((ctxt->input->cur - ctxt->input->base) > XML_MAX_LOOKUP_LIMIT)) &&
 
2044
         ((ctxt->input->buf) && (ctxt->input->buf->readcallback != (xmlInputReadCallback) xmlNop)) &&
 
2045
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
2046
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
 
2047
        ctxt->instate = XML_PARSER_EOF;
 
2048
    }
 
2049
    xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
 
2050
    if ((ctxt->input->cur != NULL) && (*ctxt->input->cur == 0) &&
 
2051
        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
 
2052
            xmlPopInput(ctxt);
 
2053
}
 
2054
 
 
2055
#define SKIP_BLANKS xmlSkipBlankChars(ctxt)
 
2056
 
 
2057
#define NEXT xmlNextChar(ctxt)
 
2058
 
 
2059
#define NEXT1 {                                                         \
 
2060
        ctxt->input->col++;                                             \
 
2061
        ctxt->input->cur++;                                             \
 
2062
        ctxt->nbChars++;                                                \
 
2063
        if (*ctxt->input->cur == 0)                                     \
 
2064
            xmlParserInputGrow(ctxt->input, INPUT_CHUNK);               \
 
2065
    }
 
2066
 
 
2067
#define NEXTL(l) do {                                                   \
 
2068
    if (*(ctxt->input->cur) == '\n') {                                  \
 
2069
        ctxt->input->line++; ctxt->input->col = 1;                      \
 
2070
    } else ctxt->input->col++;                                          \
 
2071
    ctxt->input->cur += l;                              \
 
2072
    if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);     \
 
2073
  } while (0)
 
2074
 
 
2075
#define CUR_CHAR(l) xmlCurrentChar(ctxt, &l)
 
2076
#define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l)
 
2077
 
 
2078
#define COPY_BUF(l,b,i,v)                                               \
 
2079
    if (l == 1) b[i++] = (xmlChar) v;                                   \
 
2080
    else i += xmlCopyCharMultiByte(&b[i],v)
 
2081
 
 
2082
/**
 
2083
 * xmlSkipBlankChars:
 
2084
 * @ctxt:  the XML parser context
 
2085
 *
 
2086
 * skip all blanks character found at that point in the input streams.
 
2087
 * It pops up finished entities in the process if allowable at that point.
 
2088
 *
 
2089
 * Returns the number of space chars skipped
 
2090
 */
 
2091
 
 
2092
int
 
2093
xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
 
2094
    int res = 0;
 
2095
 
 
2096
    /*
 
2097
     * It's Okay to use CUR/NEXT here since all the blanks are on
 
2098
     * the ASCII range.
 
2099
     */
 
2100
    if ((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) {
 
2101
        const xmlChar *cur;
 
2102
        /*
 
2103
         * if we are in the document content, go really fast
 
2104
         */
 
2105
        cur = ctxt->input->cur;
 
2106
        while (IS_BLANK_CH(*cur)) {
 
2107
            if (*cur == '\n') {
 
2108
                ctxt->input->line++; ctxt->input->col = 1;
 
2109
            }
 
2110
            cur++;
 
2111
            res++;
 
2112
            if (*cur == 0) {
 
2113
                ctxt->input->cur = cur;
 
2114
                xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
 
2115
                cur = ctxt->input->cur;
 
2116
            }
 
2117
        }
 
2118
        ctxt->input->cur = cur;
 
2119
    } else {
 
2120
        int cur;
 
2121
        do {
 
2122
            cur = CUR;
 
2123
            while (IS_BLANK_CH(cur)) { /* CHECKED tstblanks.xml */
 
2124
                NEXT;
 
2125
                cur = CUR;
 
2126
                res++;
 
2127
            }
 
2128
            while ((cur == 0) && (ctxt->inputNr > 1) &&
 
2129
                   (ctxt->instate != XML_PARSER_COMMENT)) {
 
2130
                xmlPopInput(ctxt);
 
2131
                cur = CUR;
 
2132
            }
 
2133
            /*
 
2134
             * Need to handle support of entities branching here
 
2135
             */
 
2136
            if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);
 
2137
        } while (IS_BLANK(cur)); /* CHECKED tstblanks.xml */
 
2138
    }
 
2139
    return(res);
 
2140
}
 
2141
 
 
2142
/************************************************************************
 
2143
 *                                                                      *
 
2144
 *              Commodity functions to handle entities                  *
 
2145
 *                                                                      *
 
2146
 ************************************************************************/
 
2147
 
 
2148
/**
 
2149
 * xmlPopInput:
 
2150
 * @ctxt:  an XML parser context
 
2151
 *
 
2152
 * xmlPopInput: the current input pointed by ctxt->input came to an end
 
2153
 *          pop it and return the next char.
 
2154
 *
 
2155
 * Returns the current xmlChar in the parser context
 
2156
 */
 
2157
xmlChar
 
2158
xmlPopInput(xmlParserCtxtPtr ctxt) {
 
2159
    if ((ctxt == NULL) || (ctxt->inputNr <= 1)) return(0);
 
2160
    if (xmlParserDebugEntities)
 
2161
        xmlGenericError(xmlGenericErrorContext,
 
2162
                "Popping input %d\n", ctxt->inputNr);
 
2163
    xmlFreeInputStream(inputPop(ctxt));
 
2164
    if ((*ctxt->input->cur == 0) &&
 
2165
        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
 
2166
            return(xmlPopInput(ctxt));
 
2167
    return(CUR);
 
2168
}
 
2169
 
 
2170
/**
 
2171
 * xmlPushInput:
 
2172
 * @ctxt:  an XML parser context
 
2173
 * @input:  an XML parser input fragment (entity, XML fragment ...).
 
2174
 *
 
2175
 * xmlPushInput: switch to a new input stream which is stacked on top
 
2176
 *               of the previous one(s).
 
2177
 * Returns -1 in case of error or the index in the input stack
 
2178
 */
 
2179
int
 
2180
xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
 
2181
    int ret;
 
2182
    if (input == NULL) return(-1);
 
2183
 
 
2184
    if (xmlParserDebugEntities) {
 
2185
        if ((ctxt->input != NULL) && (ctxt->input->filename))
 
2186
            xmlGenericError(xmlGenericErrorContext,
 
2187
                    "%s(%d): ", ctxt->input->filename,
 
2188
                    ctxt->input->line);
 
2189
        xmlGenericError(xmlGenericErrorContext,
 
2190
                "Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur);
 
2191
    }
 
2192
    ret = inputPush(ctxt, input);
 
2193
    if (ctxt->instate == XML_PARSER_EOF)
 
2194
        return(-1);
 
2195
    GROW;
 
2196
    return(ret);
 
2197
}
 
2198
 
 
2199
/**
 
2200
 * xmlParseCharRef:
 
2201
 * @ctxt:  an XML parser context
 
2202
 *
 
2203
 * parse Reference declarations
 
2204
 *
 
2205
 * [66] CharRef ::= '&#' [0-9]+ ';' |
 
2206
 *                  '&#x' [0-9a-fA-F]+ ';'
 
2207
 *
 
2208
 * [ WFC: Legal Character ]
 
2209
 * Characters referred to using character references must match the
 
2210
 * production for Char.
 
2211
 *
 
2212
 * Returns the value parsed (as an int), 0 in case of error
 
2213
 */
 
2214
int
 
2215
xmlParseCharRef(xmlParserCtxtPtr ctxt) {
 
2216
    unsigned int val = 0;
 
2217
    int count = 0;
 
2218
    unsigned int outofrange = 0;
 
2219
 
 
2220
    /*
 
2221
     * Using RAW/CUR/NEXT is okay since we are working on ASCII range here
 
2222
     */
 
2223
    if ((RAW == '&') && (NXT(1) == '#') &&
 
2224
        (NXT(2) == 'x')) {
 
2225
        SKIP(3);
 
2226
        GROW;
 
2227
        while (RAW != ';') { /* loop blocked by count */
 
2228
            if (count++ > 20) {
 
2229
                count = 0;
 
2230
                GROW;
 
2231
                if (ctxt->instate == XML_PARSER_EOF)
 
2232
                    return(0);
 
2233
            }
 
2234
            if ((RAW >= '0') && (RAW <= '9'))
 
2235
                val = val * 16 + (CUR - '0');
 
2236
            else if ((RAW >= 'a') && (RAW <= 'f') && (count < 20))
 
2237
                val = val * 16 + (CUR - 'a') + 10;
 
2238
            else if ((RAW >= 'A') && (RAW <= 'F') && (count < 20))
 
2239
                val = val * 16 + (CUR - 'A') + 10;
 
2240
            else {
 
2241
                xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
 
2242
                val = 0;
 
2243
                break;
 
2244
            }
 
2245
            if (val > 0x10FFFF)
 
2246
                outofrange = val;
 
2247
 
 
2248
            NEXT;
 
2249
            count++;
 
2250
        }
 
2251
        if (RAW == ';') {
 
2252
            /* on purpose to avoid reentrancy problems with NEXT and SKIP */
 
2253
            ctxt->input->col++;
 
2254
            ctxt->nbChars ++;
 
2255
            ctxt->input->cur++;
 
2256
        }
 
2257
    } else if  ((RAW == '&') && (NXT(1) == '#')) {
 
2258
        SKIP(2);
 
2259
        GROW;
 
2260
        while (RAW != ';') { /* loop blocked by count */
 
2261
            if (count++ > 20) {
 
2262
                count = 0;
 
2263
                GROW;
 
2264
                if (ctxt->instate == XML_PARSER_EOF)
 
2265
                    return(0);
 
2266
            }
 
2267
            if ((RAW >= '0') && (RAW <= '9'))
 
2268
                val = val * 10 + (CUR - '0');
 
2269
            else {
 
2270
                xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
 
2271
                val = 0;
 
2272
                break;
 
2273
            }
 
2274
            if (val > 0x10FFFF)
 
2275
                outofrange = val;
 
2276
 
 
2277
            NEXT;
 
2278
            count++;
 
2279
        }
 
2280
        if (RAW == ';') {
 
2281
            /* on purpose to avoid reentrancy problems with NEXT and SKIP */
 
2282
            ctxt->input->col++;
 
2283
            ctxt->nbChars ++;
 
2284
            ctxt->input->cur++;
 
2285
        }
 
2286
    } else {
 
2287
        xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
 
2288
    }
 
2289
 
 
2290
    /*
 
2291
     * [ WFC: Legal Character ]
 
2292
     * Characters referred to using character references must match the
 
2293
     * production for Char.
 
2294
     */
 
2295
    if ((IS_CHAR(val) && (outofrange == 0))) {
 
2296
        return(val);
 
2297
    } else {
 
2298
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
 
2299
                          "xmlParseCharRef: invalid xmlChar value %d\n",
 
2300
                          val);
 
2301
    }
 
2302
    return(0);
 
2303
}
 
2304
 
 
2305
/**
 
2306
 * xmlParseStringCharRef:
 
2307
 * @ctxt:  an XML parser context
 
2308
 * @str:  a pointer to an index in the string
 
2309
 *
 
2310
 * parse Reference declarations, variant parsing from a string rather
 
2311
 * than an an input flow.
 
2312
 *
 
2313
 * [66] CharRef ::= '&#' [0-9]+ ';' |
 
2314
 *                  '&#x' [0-9a-fA-F]+ ';'
 
2315
 *
 
2316
 * [ WFC: Legal Character ]
 
2317
 * Characters referred to using character references must match the
 
2318
 * production for Char.
 
2319
 *
 
2320
 * Returns the value parsed (as an int), 0 in case of error, str will be
 
2321
 *         updated to the current value of the index
 
2322
 */
 
2323
static int
 
2324
xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
 
2325
    const xmlChar *ptr;
 
2326
    xmlChar cur;
 
2327
    unsigned int val = 0;
 
2328
    unsigned int outofrange = 0;
 
2329
 
 
2330
    if ((str == NULL) || (*str == NULL)) return(0);
 
2331
    ptr = *str;
 
2332
    cur = *ptr;
 
2333
    if ((cur == '&') && (ptr[1] == '#') && (ptr[2] == 'x')) {
 
2334
        ptr += 3;
 
2335
        cur = *ptr;
 
2336
        while (cur != ';') { /* Non input consuming loop */
 
2337
            if ((cur >= '0') && (cur <= '9'))
 
2338
                val = val * 16 + (cur - '0');
 
2339
            else if ((cur >= 'a') && (cur <= 'f'))
 
2340
                val = val * 16 + (cur - 'a') + 10;
 
2341
            else if ((cur >= 'A') && (cur <= 'F'))
 
2342
                val = val * 16 + (cur - 'A') + 10;
 
2343
            else {
 
2344
                xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
 
2345
                val = 0;
 
2346
                break;
 
2347
            }
 
2348
            if (val > 0x10FFFF)
 
2349
                outofrange = val;
 
2350
 
 
2351
            ptr++;
 
2352
            cur = *ptr;
 
2353
        }
 
2354
        if (cur == ';')
 
2355
            ptr++;
 
2356
    } else if  ((cur == '&') && (ptr[1] == '#')){
 
2357
        ptr += 2;
 
2358
        cur = *ptr;
 
2359
        while (cur != ';') { /* Non input consuming loops */
 
2360
            if ((cur >= '0') && (cur <= '9'))
 
2361
                val = val * 10 + (cur - '0');
 
2362
            else {
 
2363
                xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
 
2364
                val = 0;
 
2365
                break;
 
2366
            }
 
2367
            if (val > 0x10FFFF)
 
2368
                outofrange = val;
 
2369
 
 
2370
            ptr++;
 
2371
            cur = *ptr;
 
2372
        }
 
2373
        if (cur == ';')
 
2374
            ptr++;
 
2375
    } else {
 
2376
        xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
 
2377
        return(0);
 
2378
    }
 
2379
    *str = ptr;
 
2380
 
 
2381
    /*
 
2382
     * [ WFC: Legal Character ]
 
2383
     * Characters referred to using character references must match the
 
2384
     * production for Char.
 
2385
     */
 
2386
    if ((IS_CHAR(val) && (outofrange == 0))) {
 
2387
        return(val);
 
2388
    } else {
 
2389
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
 
2390
                          "xmlParseStringCharRef: invalid xmlChar value %d\n",
 
2391
                          val);
 
2392
    }
 
2393
    return(0);
 
2394
}
 
2395
 
 
2396
/**
 
2397
 * xmlNewBlanksWrapperInputStream:
 
2398
 * @ctxt:  an XML parser context
 
2399
 * @entity:  an Entity pointer
 
2400
 *
 
2401
 * Create a new input stream for wrapping
 
2402
 * blanks around a PEReference
 
2403
 *
 
2404
 * Returns the new input stream or NULL
 
2405
 */
 
2406
 
 
2407
static void deallocblankswrapper (xmlChar *str) {xmlFree(str);}
 
2408
 
 
2409
static xmlParserInputPtr
 
2410
xmlNewBlanksWrapperInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
 
2411
    xmlParserInputPtr input;
 
2412
    xmlChar *buffer;
 
2413
    size_t length;
 
2414
    if (entity == NULL) {
 
2415
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
2416
                    "xmlNewBlanksWrapperInputStream entity\n");
 
2417
        return(NULL);
 
2418
    }
 
2419
    if (xmlParserDebugEntities)
 
2420
        xmlGenericError(xmlGenericErrorContext,
 
2421
                "new blanks wrapper for entity: %s\n", entity->name);
 
2422
    input = xmlNewInputStream(ctxt);
 
2423
    if (input == NULL) {
 
2424
        return(NULL);
 
2425
    }
 
2426
    length = xmlStrlen(entity->name) + 5;
 
2427
    buffer = xmlMallocAtomic(length);
 
2428
    if (buffer == NULL) {
 
2429
        xmlErrMemory(ctxt, NULL);
 
2430
        xmlFree(input);
 
2431
        return(NULL);
 
2432
    }
 
2433
    buffer [0] = ' ';
 
2434
    buffer [1] = '%';
 
2435
    buffer [length-3] = ';';
 
2436
    buffer [length-2] = ' ';
 
2437
    buffer [length-1] = 0;
 
2438
    memcpy(buffer + 2, entity->name, length - 5);
 
2439
    input->free = deallocblankswrapper;
 
2440
    input->base = buffer;
 
2441
    input->cur = buffer;
 
2442
    input->length = length;
 
2443
    input->end = &buffer[length];
 
2444
    return(input);
 
2445
}
 
2446
 
 
2447
/**
 
2448
 * xmlParserHandlePEReference:
 
2449
 * @ctxt:  the parser context
 
2450
 *
 
2451
 * [69] PEReference ::= '%' Name ';'
 
2452
 *
 
2453
 * [ WFC: No Recursion ]
 
2454
 * A parsed entity must not contain a recursive
 
2455
 * reference to itself, either directly or indirectly.
 
2456
 *
 
2457
 * [ WFC: Entity Declared ]
 
2458
 * In a document without any DTD, a document with only an internal DTD
 
2459
 * subset which contains no parameter entity references, or a document
 
2460
 * with "standalone='yes'", ...  ... The declaration of a parameter
 
2461
 * entity must precede any reference to it...
 
2462
 *
 
2463
 * [ VC: Entity Declared ]
 
2464
 * In a document with an external subset or external parameter entities
 
2465
 * with "standalone='no'", ...  ... The declaration of a parameter entity
 
2466
 * must precede any reference to it...
 
2467
 *
 
2468
 * [ WFC: In DTD ]
 
2469
 * Parameter-entity references may only appear in the DTD.
 
2470
 * NOTE: misleading but this is handled.
 
2471
 *
 
2472
 * A PEReference may have been detected in the current input stream
 
2473
 * the handling is done accordingly to
 
2474
 *      http://www.w3.org/TR/REC-xml#entproc
 
2475
 * i.e.
 
2476
 *   - Included in literal in entity values
 
2477
 *   - Included as Parameter Entity reference within DTDs
 
2478
 */
 
2479
void
 
2480
xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
 
2481
    const xmlChar *name;
 
2482
    xmlEntityPtr entity = NULL;
 
2483
    xmlParserInputPtr input;
 
2484
 
 
2485
    if (RAW != '%') return;
 
2486
    switch(ctxt->instate) {
 
2487
        case XML_PARSER_CDATA_SECTION:
 
2488
            return;
 
2489
        case XML_PARSER_COMMENT:
 
2490
            return;
 
2491
        case XML_PARSER_START_TAG:
 
2492
            return;
 
2493
        case XML_PARSER_END_TAG:
 
2494
            return;
 
2495
        case XML_PARSER_EOF:
 
2496
            xmlFatalErr(ctxt, XML_ERR_PEREF_AT_EOF, NULL);
 
2497
            return;
 
2498
        case XML_PARSER_PROLOG:
 
2499
        case XML_PARSER_START:
 
2500
        case XML_PARSER_MISC:
 
2501
            xmlFatalErr(ctxt, XML_ERR_PEREF_IN_PROLOG, NULL);
 
2502
            return;
 
2503
        case XML_PARSER_ENTITY_DECL:
 
2504
        case XML_PARSER_CONTENT:
 
2505
        case XML_PARSER_ATTRIBUTE_VALUE:
 
2506
        case XML_PARSER_PI:
 
2507
        case XML_PARSER_SYSTEM_LITERAL:
 
2508
        case XML_PARSER_PUBLIC_LITERAL:
 
2509
            /* we just ignore it there */
 
2510
            return;
 
2511
        case XML_PARSER_EPILOG:
 
2512
            xmlFatalErr(ctxt, XML_ERR_PEREF_IN_EPILOG, NULL);
 
2513
            return;
 
2514
        case XML_PARSER_ENTITY_VALUE:
 
2515
            /*
 
2516
             * NOTE: in the case of entity values, we don't do the
 
2517
             *       substitution here since we need the literal
 
2518
             *       entity value to be able to save the internal
 
2519
             *       subset of the document.
 
2520
             *       This will be handled by xmlStringDecodeEntities
 
2521
             */
 
2522
            return;
 
2523
        case XML_PARSER_DTD:
 
2524
            /*
 
2525
             * [WFC: Well-Formedness Constraint: PEs in Internal Subset]
 
2526
             * In the internal DTD subset, parameter-entity references
 
2527
             * can occur only where markup declarations can occur, not
 
2528
             * within markup declarations.
 
2529
             * In that case this is handled in xmlParseMarkupDecl
 
2530
             */
 
2531
            if ((ctxt->external == 0) && (ctxt->inputNr == 1))
 
2532
                return;
 
2533
            if (IS_BLANK_CH(NXT(1)) || NXT(1) == 0)
 
2534
                return;
 
2535
            break;
 
2536
        case XML_PARSER_IGNORE:
 
2537
            return;
 
2538
    }
 
2539
 
 
2540
    NEXT;
 
2541
    name = xmlParseName(ctxt);
 
2542
    if (xmlParserDebugEntities)
 
2543
        xmlGenericError(xmlGenericErrorContext,
 
2544
                "PEReference: %s\n", name);
 
2545
    if (name == NULL) {
 
2546
        xmlFatalErr(ctxt, XML_ERR_PEREF_NO_NAME, NULL);
 
2547
    } else {
 
2548
        if (RAW == ';') {
 
2549
            NEXT;
 
2550
            if ((ctxt->sax != NULL) && (ctxt->sax->getParameterEntity != NULL))
 
2551
                entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
 
2552
            if (ctxt->instate == XML_PARSER_EOF)
 
2553
                return;
 
2554
            if (entity == NULL) {
 
2555
 
 
2556
                /*
 
2557
                 * [ WFC: Entity Declared ]
 
2558
                 * In a document without any DTD, a document with only an
 
2559
                 * internal DTD subset which contains no parameter entity
 
2560
                 * references, or a document with "standalone='yes'", ...
 
2561
                 * ... The declaration of a parameter entity must precede
 
2562
                 * any reference to it...
 
2563
                 */
 
2564
                if ((ctxt->standalone == 1) ||
 
2565
                    ((ctxt->hasExternalSubset == 0) &&
 
2566
                     (ctxt->hasPErefs == 0))) {
 
2567
                    xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
 
2568
                         "PEReference: %%%s; not found\n", name);
 
2569
                } else {
 
2570
                    /*
 
2571
                     * [ VC: Entity Declared ]
 
2572
                     * In a document with an external subset or external
 
2573
                     * parameter entities with "standalone='no'", ...
 
2574
                     * ... The declaration of a parameter entity must precede
 
2575
                     * any reference to it...
 
2576
                     */
 
2577
                    if ((ctxt->validate) && (ctxt->vctxt.error != NULL)) {
 
2578
                        xmlValidityError(ctxt, XML_WAR_UNDECLARED_ENTITY,
 
2579
                                         "PEReference: %%%s; not found\n",
 
2580
                                         name, NULL);
 
2581
                    } else
 
2582
                        xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
 
2583
                                      "PEReference: %%%s; not found\n",
 
2584
                                      name, NULL);
 
2585
                    ctxt->valid = 0;
 
2586
                }
 
2587
            } else if (ctxt->input->free != deallocblankswrapper) {
 
2588
                    input = xmlNewBlanksWrapperInputStream(ctxt, entity);
 
2589
                    if (xmlPushInput(ctxt, input) < 0)
 
2590
                        return;
 
2591
            } else {
 
2592
                if ((entity->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
 
2593
                    (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY)) {
 
2594
                    xmlChar start[4];
 
2595
                    xmlCharEncoding enc;
 
2596
 
 
2597
                    /*
 
2598
                     * handle the extra spaces added before and after
 
2599
                     * c.f. http://www.w3.org/TR/REC-xml#as-PE
 
2600
                     * this is done independently.
 
2601
                     */
 
2602
                    input = xmlNewEntityInputStream(ctxt, entity);
 
2603
                    if (xmlPushInput(ctxt, input) < 0)
 
2604
                        return;
 
2605
 
 
2606
                    /*
 
2607
                     * Get the 4 first bytes and decode the charset
 
2608
                     * if enc != XML_CHAR_ENCODING_NONE
 
2609
                     * plug some encoding conversion routines.
 
2610
                     * Note that, since we may have some non-UTF8
 
2611
                     * encoding (like UTF16, bug 135229), the 'length'
 
2612
                     * is not known, but we can calculate based upon
 
2613
                     * the amount of data in the buffer.
 
2614
                     */
 
2615
                    GROW
 
2616
                    if (ctxt->instate == XML_PARSER_EOF)
 
2617
                        return;
 
2618
                    if ((ctxt->input->end - ctxt->input->cur)>=4) {
 
2619
                        start[0] = RAW;
 
2620
                        start[1] = NXT(1);
 
2621
                        start[2] = NXT(2);
 
2622
                        start[3] = NXT(3);
 
2623
                        enc = xmlDetectCharEncoding(start, 4);
 
2624
                        if (enc != XML_CHAR_ENCODING_NONE) {
 
2625
                            xmlSwitchEncoding(ctxt, enc);
 
2626
                        }
 
2627
                    }
 
2628
 
 
2629
                    if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
 
2630
                        (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l' )) &&
 
2631
                        (IS_BLANK_CH(NXT(5)))) {
 
2632
                        xmlParseTextDecl(ctxt);
 
2633
                    }
 
2634
                } else {
 
2635
                    xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
 
2636
                             "PEReference: %s is not a parameter entity\n",
 
2637
                                      name);
 
2638
                }
 
2639
            }
 
2640
        } else {
 
2641
            xmlFatalErr(ctxt, XML_ERR_PEREF_SEMICOL_MISSING, NULL);
 
2642
        }
 
2643
    }
 
2644
}
 
2645
 
 
2646
/*
 
2647
 * Macro used to grow the current buffer.
 
2648
 * buffer##_size is expected to be a size_t
 
2649
 * mem_error: is expected to handle memory allocation failures
 
2650
 */
 
2651
#define growBuffer(buffer, n) {                                         \
 
2652
    xmlChar *tmp;                                                       \
 
2653
    size_t new_size = buffer##_size * 2 + n;                            \
 
2654
    if (new_size < buffer##_size) goto mem_error;                       \
 
2655
    tmp = (xmlChar *) xmlRealloc(buffer, new_size);                     \
 
2656
    if (tmp == NULL) goto mem_error;                                    \
 
2657
    buffer = tmp;                                                       \
 
2658
    buffer##_size = new_size;                                           \
 
2659
}
 
2660
 
 
2661
/**
 
2662
 * xmlStringLenDecodeEntities:
 
2663
 * @ctxt:  the parser context
 
2664
 * @str:  the input string
 
2665
 * @len: the string length
 
2666
 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
 
2667
 * @end:  an end marker xmlChar, 0 if none
 
2668
 * @end2:  an end marker xmlChar, 0 if none
 
2669
 * @end3:  an end marker xmlChar, 0 if none
 
2670
 *
 
2671
 * Takes a entity string content and process to do the adequate substitutions.
 
2672
 *
 
2673
 * [67] Reference ::= EntityRef | CharRef
 
2674
 *
 
2675
 * [69] PEReference ::= '%' Name ';'
 
2676
 *
 
2677
 * Returns A newly allocated string with the substitution done. The caller
 
2678
 *      must deallocate it !
 
2679
 */
 
2680
xmlChar *
 
2681
xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
 
2682
                      int what, xmlChar end, xmlChar  end2, xmlChar end3) {
 
2683
    xmlChar *buffer = NULL;
 
2684
    size_t buffer_size = 0;
 
2685
    size_t nbchars = 0;
 
2686
 
 
2687
    xmlChar *current = NULL;
 
2688
    xmlChar *rep = NULL;
 
2689
    const xmlChar *last;
 
2690
    xmlEntityPtr ent;
 
2691
    int c,l;
 
2692
 
 
2693
    if ((ctxt == NULL) || (str == NULL) || (len < 0))
 
2694
        return(NULL);
 
2695
    last = str + len;
 
2696
 
 
2697
    if (((ctxt->depth > 40) &&
 
2698
         ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
 
2699
        (ctxt->depth > 1024)) {
 
2700
        xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
 
2701
        return(NULL);
 
2702
    }
 
2703
 
 
2704
    /*
 
2705
     * allocate a translation buffer.
 
2706
     */
 
2707
    buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
 
2708
    buffer = (xmlChar *) xmlMallocAtomic(buffer_size);
 
2709
    if (buffer == NULL) goto mem_error;
 
2710
 
 
2711
    /*
 
2712
     * OK loop until we reach one of the ending char or a size limit.
 
2713
     * we are operating on already parsed values.
 
2714
     */
 
2715
    if (str < last)
 
2716
        c = CUR_SCHAR(str, l);
 
2717
    else
 
2718
        c = 0;
 
2719
    while ((c != 0) && (c != end) && /* non input consuming loop */
 
2720
           (c != end2) && (c != end3)) {
 
2721
 
 
2722
        if (c == 0) break;
 
2723
        if ((c == '&') && (str[1] == '#')) {
 
2724
            int val = xmlParseStringCharRef(ctxt, &str);
 
2725
            if (val != 0) {
 
2726
                COPY_BUF(0,buffer,nbchars,val);
 
2727
            }
 
2728
            if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
 
2729
                growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
 
2730
            }
 
2731
        } else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) {
 
2732
            if (xmlParserDebugEntities)
 
2733
                xmlGenericError(xmlGenericErrorContext,
 
2734
                        "String decoding Entity Reference: %.30s\n",
 
2735
                        str);
 
2736
            ent = xmlParseStringEntityRef(ctxt, &str);
 
2737
            if ((ctxt->lastError.code == XML_ERR_ENTITY_LOOP) ||
 
2738
                (ctxt->lastError.code == XML_ERR_INTERNAL_ERROR))
 
2739
                goto int_error;
 
2740
            if (ent != NULL)
 
2741
                ctxt->nbentities += ent->checked / 2;
 
2742
            if ((ent != NULL) &&
 
2743
                (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
 
2744
                if (ent->content != NULL) {
 
2745
                    COPY_BUF(0,buffer,nbchars,ent->content[0]);
 
2746
                    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
 
2747
                        growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
 
2748
                    }
 
2749
                } else {
 
2750
                    xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
 
2751
                            "predefined entity has no content\n");
 
2752
                }
 
2753
            } else if ((ent != NULL) && (ent->content != NULL)) {
 
2754
                ctxt->depth++;
 
2755
                rep = xmlStringDecodeEntities(ctxt, ent->content, what,
 
2756
                                              0, 0, 0);
 
2757
                ctxt->depth--;
 
2758
 
 
2759
                if (rep != NULL) {
 
2760
                    current = rep;
 
2761
                    while (*current != 0) { /* non input consuming loop */
 
2762
                        buffer[nbchars++] = *current++;
 
2763
                        if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
 
2764
                            if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
 
2765
                                goto int_error;
 
2766
                            growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
 
2767
                        }
 
2768
                    }
 
2769
                    xmlFree(rep);
 
2770
                    rep = NULL;
 
2771
                }
 
2772
            } else if (ent != NULL) {
 
2773
                int i = xmlStrlen(ent->name);
 
2774
                const xmlChar *cur = ent->name;
 
2775
 
 
2776
                buffer[nbchars++] = '&';
 
2777
                if (nbchars + i + XML_PARSER_BUFFER_SIZE > buffer_size) {
 
2778
                    growBuffer(buffer, i + XML_PARSER_BUFFER_SIZE);
 
2779
                }
 
2780
                for (;i > 0;i--)
 
2781
                    buffer[nbchars++] = *cur++;
 
2782
                buffer[nbchars++] = ';';
 
2783
            }
 
2784
        } else if (c == '%' && (what & XML_SUBSTITUTE_PEREF)) {
 
2785
            if (xmlParserDebugEntities)
 
2786
                xmlGenericError(xmlGenericErrorContext,
 
2787
                        "String decoding PE Reference: %.30s\n", str);
 
2788
            ent = xmlParseStringPEReference(ctxt, &str);
 
2789
            if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
 
2790
                goto int_error;
 
2791
            if (ent != NULL)
 
2792
                ctxt->nbentities += ent->checked / 2;
 
2793
            if (ent != NULL) {
 
2794
                if (ent->content == NULL) {
 
2795
                    xmlLoadEntityContent(ctxt, ent);
 
2796
                }
 
2797
                ctxt->depth++;
 
2798
                rep = xmlStringDecodeEntities(ctxt, ent->content, what,
 
2799
                                              0, 0, 0);
 
2800
                ctxt->depth--;
 
2801
                if (rep != NULL) {
 
2802
                    current = rep;
 
2803
                    while (*current != 0) { /* non input consuming loop */
 
2804
                        buffer[nbchars++] = *current++;
 
2805
                        if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
 
2806
                            if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
 
2807
                                goto int_error;
 
2808
                            growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
 
2809
                        }
 
2810
                    }
 
2811
                    xmlFree(rep);
 
2812
                    rep = NULL;
 
2813
                }
 
2814
            }
 
2815
        } else {
 
2816
            COPY_BUF(l,buffer,nbchars,c);
 
2817
            str += l;
 
2818
            if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
 
2819
                growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
 
2820
            }
 
2821
        }
 
2822
        if (str < last)
 
2823
            c = CUR_SCHAR(str, l);
 
2824
        else
 
2825
            c = 0;
 
2826
    }
 
2827
    buffer[nbchars] = 0;
 
2828
    return(buffer);
 
2829
 
 
2830
mem_error:
 
2831
    xmlErrMemory(ctxt, NULL);
 
2832
int_error:
 
2833
    if (rep != NULL)
 
2834
        xmlFree(rep);
 
2835
    if (buffer != NULL)
 
2836
        xmlFree(buffer);
 
2837
    return(NULL);
 
2838
}
 
2839
 
 
2840
/**
 
2841
 * xmlStringDecodeEntities:
 
2842
 * @ctxt:  the parser context
 
2843
 * @str:  the input string
 
2844
 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
 
2845
 * @end:  an end marker xmlChar, 0 if none
 
2846
 * @end2:  an end marker xmlChar, 0 if none
 
2847
 * @end3:  an end marker xmlChar, 0 if none
 
2848
 *
 
2849
 * Takes a entity string content and process to do the adequate substitutions.
 
2850
 *
 
2851
 * [67] Reference ::= EntityRef | CharRef
 
2852
 *
 
2853
 * [69] PEReference ::= '%' Name ';'
 
2854
 *
 
2855
 * Returns A newly allocated string with the substitution done. The caller
 
2856
 *      must deallocate it !
 
2857
 */
 
2858
xmlChar *
 
2859
xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what,
 
2860
                        xmlChar end, xmlChar  end2, xmlChar end3) {
 
2861
    if ((ctxt == NULL) || (str == NULL)) return(NULL);
 
2862
    return(xmlStringLenDecodeEntities(ctxt, str, xmlStrlen(str), what,
 
2863
           end, end2, end3));
 
2864
}
 
2865
 
 
2866
/************************************************************************
 
2867
 *                                                                      *
 
2868
 *              Commodity functions, cleanup needed ?                   *
 
2869
 *                                                                      *
 
2870
 ************************************************************************/
 
2871
 
 
2872
/**
 
2873
 * areBlanks:
 
2874
 * @ctxt:  an XML parser context
 
2875
 * @str:  a xmlChar *
 
2876
 * @len:  the size of @str
 
2877
 * @blank_chars: we know the chars are blanks
 
2878
 *
 
2879
 * Is this a sequence of blank chars that one can ignore ?
 
2880
 *
 
2881
 * Returns 1 if ignorable 0 otherwise.
 
2882
 */
 
2883
 
 
2884
static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
 
2885
                     int blank_chars) {
 
2886
    int i, ret;
 
2887
    xmlNodePtr lastChild;
 
2888
 
 
2889
    /*
 
2890
     * Don't spend time trying to differentiate them, the same callback is
 
2891
     * used !
 
2892
     */
 
2893
    if (ctxt->sax->ignorableWhitespace == ctxt->sax->characters)
 
2894
        return(0);
 
2895
 
 
2896
    /*
 
2897
     * Check for xml:space value.
 
2898
     */
 
2899
    if ((ctxt->space == NULL) || (*(ctxt->space) == 1) ||
 
2900
        (*(ctxt->space) == -2))
 
2901
        return(0);
 
2902
 
 
2903
    /*
 
2904
     * Check that the string is made of blanks
 
2905
     */
 
2906
    if (blank_chars == 0) {
 
2907
        for (i = 0;i < len;i++)
 
2908
            if (!(IS_BLANK_CH(str[i]))) return(0);
 
2909
    }
 
2910
 
 
2911
    /*
 
2912
     * Look if the element is mixed content in the DTD if available
 
2913
     */
 
2914
    if (ctxt->node == NULL) return(0);
 
2915
    if (ctxt->myDoc != NULL) {
 
2916
        ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name);
 
2917
        if (ret == 0) return(1);
 
2918
        if (ret == 1) return(0);
 
2919
    }
 
2920
 
 
2921
    /*
 
2922
     * Otherwise, heuristic :-\
 
2923
     */
 
2924
    if ((RAW != '<') && (RAW != 0xD)) return(0);
 
2925
    if ((ctxt->node->children == NULL) &&
 
2926
        (RAW == '<') && (NXT(1) == '/')) return(0);
 
2927
 
 
2928
    lastChild = xmlGetLastChild(ctxt->node);
 
2929
    if (lastChild == NULL) {
 
2930
        if ((ctxt->node->type != XML_ELEMENT_NODE) &&
 
2931
            (ctxt->node->content != NULL)) return(0);
 
2932
    } else if (xmlNodeIsText(lastChild))
 
2933
        return(0);
 
2934
    else if ((ctxt->node->children != NULL) &&
 
2935
             (xmlNodeIsText(ctxt->node->children)))
 
2936
        return(0);
 
2937
    return(1);
 
2938
}
 
2939
 
 
2940
/************************************************************************
 
2941
 *                                                                      *
 
2942
 *              Extra stuff for namespace support                       *
 
2943
 *      Relates to http://www.w3.org/TR/WD-xml-names                    *
 
2944
 *                                                                      *
 
2945
 ************************************************************************/
 
2946
 
 
2947
/**
 
2948
 * xmlSplitQName:
 
2949
 * @ctxt:  an XML parser context
 
2950
 * @name:  an XML parser context
 
2951
 * @prefix:  a xmlChar **
 
2952
 *
 
2953
 * parse an UTF8 encoded XML qualified name string
 
2954
 *
 
2955
 * [NS 5] QName ::= (Prefix ':')? LocalPart
 
2956
 *
 
2957
 * [NS 6] Prefix ::= NCName
 
2958
 *
 
2959
 * [NS 7] LocalPart ::= NCName
 
2960
 *
 
2961
 * Returns the local part, and prefix is updated
 
2962
 *   to get the Prefix if any.
 
2963
 */
 
2964
 
 
2965
xmlChar *
 
2966
xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
 
2967
    xmlChar buf[XML_MAX_NAMELEN + 5];
 
2968
    xmlChar *buffer = NULL;
 
2969
    int len = 0;
 
2970
    int max = XML_MAX_NAMELEN;
 
2971
    xmlChar *ret = NULL;
 
2972
    const xmlChar *cur = name;
 
2973
    int c;
 
2974
 
 
2975
    if (prefix == NULL) return(NULL);
 
2976
    *prefix = NULL;
 
2977
 
 
2978
    if (cur == NULL) return(NULL);
 
2979
 
 
2980
#ifndef XML_XML_NAMESPACE
 
2981
    /* xml: prefix is not really a namespace */
 
2982
    if ((cur[0] == 'x') && (cur[1] == 'm') &&
 
2983
        (cur[2] == 'l') && (cur[3] == ':'))
 
2984
        return(xmlStrdup(name));
 
2985
#endif
 
2986
 
 
2987
    /* nasty but well=formed */
 
2988
    if (cur[0] == ':')
 
2989
        return(xmlStrdup(name));
 
2990
 
 
2991
    c = *cur++;
 
2992
    while ((c != 0) && (c != ':') && (len < max)) { /* tested bigname.xml */
 
2993
        buf[len++] = c;
 
2994
        c = *cur++;
 
2995
    }
 
2996
    if (len >= max) {
 
2997
        /*
 
2998
         * Okay someone managed to make a huge name, so he's ready to pay
 
2999
         * for the processing speed.
 
3000
         */
 
3001
        max = len * 2;
 
3002
 
 
3003
        buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
 
3004
        if (buffer == NULL) {
 
3005
            xmlErrMemory(ctxt, NULL);
 
3006
            return(NULL);
 
3007
        }
 
3008
        memcpy(buffer, buf, len);
 
3009
        while ((c != 0) && (c != ':')) { /* tested bigname.xml */
 
3010
            if (len + 10 > max) {
 
3011
                xmlChar *tmp;
 
3012
 
 
3013
                max *= 2;
 
3014
                tmp = (xmlChar *) xmlRealloc(buffer,
 
3015
                                                max * sizeof(xmlChar));
 
3016
                if (tmp == NULL) {
 
3017
                    xmlFree(buffer);
 
3018
                    xmlErrMemory(ctxt, NULL);
 
3019
                    return(NULL);
 
3020
                }
 
3021
                buffer = tmp;
 
3022
            }
 
3023
            buffer[len++] = c;
 
3024
            c = *cur++;
 
3025
        }
 
3026
        buffer[len] = 0;
 
3027
    }
 
3028
 
 
3029
    if ((c == ':') && (*cur == 0)) {
 
3030
        if (buffer != NULL)
 
3031
            xmlFree(buffer);
 
3032
        *prefix = NULL;
 
3033
        return(xmlStrdup(name));
 
3034
    }
 
3035
 
 
3036
    if (buffer == NULL)
 
3037
        ret = xmlStrndup(buf, len);
 
3038
    else {
 
3039
        ret = buffer;
 
3040
        buffer = NULL;
 
3041
        max = XML_MAX_NAMELEN;
 
3042
    }
 
3043
 
 
3044
 
 
3045
    if (c == ':') {
 
3046
        c = *cur;
 
3047
        *prefix = ret;
 
3048
        if (c == 0) {
 
3049
            return(xmlStrndup(BAD_CAST "", 0));
 
3050
        }
 
3051
        len = 0;
 
3052
 
 
3053
        /*
 
3054
         * Check that the first character is proper to start
 
3055
         * a new name
 
3056
         */
 
3057
        if (!(((c >= 0x61) && (c <= 0x7A)) ||
 
3058
              ((c >= 0x41) && (c <= 0x5A)) ||
 
3059
              (c == '_') || (c == ':'))) {
 
3060
            int l;
 
3061
            int first = CUR_SCHAR(cur, l);
 
3062
 
 
3063
            if (!IS_LETTER(first) && (first != '_')) {
 
3064
                xmlFatalErrMsgStr(ctxt, XML_NS_ERR_QNAME,
 
3065
                            "Name %s is not XML Namespace compliant\n",
 
3066
                                  name);
 
3067
            }
 
3068
        }
 
3069
        cur++;
 
3070
 
 
3071
        while ((c != 0) && (len < max)) { /* tested bigname2.xml */
 
3072
            buf[len++] = c;
 
3073
            c = *cur++;
 
3074
        }
 
3075
        if (len >= max) {
 
3076
            /*
 
3077
             * Okay someone managed to make a huge name, so he's ready to pay
 
3078
             * for the processing speed.
 
3079
             */
 
3080
            max = len * 2;
 
3081
 
 
3082
            buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
 
3083
            if (buffer == NULL) {
 
3084
                xmlErrMemory(ctxt, NULL);
 
3085
                return(NULL);
 
3086
            }
 
3087
            memcpy(buffer, buf, len);
 
3088
            while (c != 0) { /* tested bigname2.xml */
 
3089
                if (len + 10 > max) {
 
3090
                    xmlChar *tmp;
 
3091
 
 
3092
                    max *= 2;
 
3093
                    tmp = (xmlChar *) xmlRealloc(buffer,
 
3094
                                                    max * sizeof(xmlChar));
 
3095
                    if (tmp == NULL) {
 
3096
                        xmlErrMemory(ctxt, NULL);
 
3097
                        xmlFree(buffer);
 
3098
                        return(NULL);
 
3099
                    }
 
3100
                    buffer = tmp;
 
3101
                }
 
3102
                buffer[len++] = c;
 
3103
                c = *cur++;
 
3104
            }
 
3105
            buffer[len] = 0;
 
3106
        }
 
3107
 
 
3108
        if (buffer == NULL)
 
3109
            ret = xmlStrndup(buf, len);
 
3110
        else {
 
3111
            ret = buffer;
 
3112
        }
 
3113
    }
 
3114
 
 
3115
    return(ret);
 
3116
}
 
3117
 
 
3118
/************************************************************************
 
3119
 *                                                                      *
 
3120
 *                      The parser itself                               *
 
3121
 *      Relates to http://www.w3.org/TR/REC-xml                         *
 
3122
 *                                                                      *
 
3123
 ************************************************************************/
 
3124
 
 
3125
/************************************************************************
 
3126
 *                                                                      *
 
3127
 *      Routines to parse Name, NCName and NmToken                      *
 
3128
 *                                                                      *
 
3129
 ************************************************************************/
 
3130
#ifdef DEBUG
 
3131
static unsigned long nbParseName = 0;
 
3132
static unsigned long nbParseNmToken = 0;
 
3133
static unsigned long nbParseNCName = 0;
 
3134
static unsigned long nbParseNCNameComplex = 0;
 
3135
static unsigned long nbParseNameComplex = 0;
 
3136
static unsigned long nbParseStringName = 0;
 
3137
#endif
 
3138
 
 
3139
/*
 
3140
 * The two following functions are related to the change of accepted
 
3141
 * characters for Name and NmToken in the Revision 5 of XML-1.0
 
3142
 * They correspond to the modified production [4] and the new production [4a]
 
3143
 * changes in that revision. Also note that the macros used for the
 
3144
 * productions Letter, Digit, CombiningChar and Extender are not needed
 
3145
 * anymore.
 
3146
 * We still keep compatibility to pre-revision5 parsing semantic if the
 
3147
 * new XML_PARSE_OLD10 option is given to the parser.
 
3148
 */
 
3149
static int
 
3150
xmlIsNameStartChar(xmlParserCtxtPtr ctxt, int c) {
 
3151
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
 
3152
        /*
 
3153
         * Use the new checks of production [4] [4a] amd [5] of the
 
3154
         * Update 5 of XML-1.0
 
3155
         */
 
3156
        if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
 
3157
            (((c >= 'a') && (c <= 'z')) ||
 
3158
             ((c >= 'A') && (c <= 'Z')) ||
 
3159
             (c == '_') || (c == ':') ||
 
3160
             ((c >= 0xC0) && (c <= 0xD6)) ||
 
3161
             ((c >= 0xD8) && (c <= 0xF6)) ||
 
3162
             ((c >= 0xF8) && (c <= 0x2FF)) ||
 
3163
             ((c >= 0x370) && (c <= 0x37D)) ||
 
3164
             ((c >= 0x37F) && (c <= 0x1FFF)) ||
 
3165
             ((c >= 0x200C) && (c <= 0x200D)) ||
 
3166
             ((c >= 0x2070) && (c <= 0x218F)) ||
 
3167
             ((c >= 0x2C00) && (c <= 0x2FEF)) ||
 
3168
             ((c >= 0x3001) && (c <= 0xD7FF)) ||
 
3169
             ((c >= 0xF900) && (c <= 0xFDCF)) ||
 
3170
             ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
 
3171
             ((c >= 0x10000) && (c <= 0xEFFFF))))
 
3172
            return(1);
 
3173
    } else {
 
3174
        if (IS_LETTER(c) || (c == '_') || (c == ':'))
 
3175
            return(1);
 
3176
    }
 
3177
    return(0);
 
3178
}
 
3179
 
 
3180
static int
 
3181
xmlIsNameChar(xmlParserCtxtPtr ctxt, int c) {
 
3182
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
 
3183
        /*
 
3184
         * Use the new checks of production [4] [4a] amd [5] of the
 
3185
         * Update 5 of XML-1.0
 
3186
         */
 
3187
        if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
 
3188
            (((c >= 'a') && (c <= 'z')) ||
 
3189
             ((c >= 'A') && (c <= 'Z')) ||
 
3190
             ((c >= '0') && (c <= '9')) || /* !start */
 
3191
             (c == '_') || (c == ':') ||
 
3192
             (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
 
3193
             ((c >= 0xC0) && (c <= 0xD6)) ||
 
3194
             ((c >= 0xD8) && (c <= 0xF6)) ||
 
3195
             ((c >= 0xF8) && (c <= 0x2FF)) ||
 
3196
             ((c >= 0x300) && (c <= 0x36F)) || /* !start */
 
3197
             ((c >= 0x370) && (c <= 0x37D)) ||
 
3198
             ((c >= 0x37F) && (c <= 0x1FFF)) ||
 
3199
             ((c >= 0x200C) && (c <= 0x200D)) ||
 
3200
             ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
 
3201
             ((c >= 0x2070) && (c <= 0x218F)) ||
 
3202
             ((c >= 0x2C00) && (c <= 0x2FEF)) ||
 
3203
             ((c >= 0x3001) && (c <= 0xD7FF)) ||
 
3204
             ((c >= 0xF900) && (c <= 0xFDCF)) ||
 
3205
             ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
 
3206
             ((c >= 0x10000) && (c <= 0xEFFFF))))
 
3207
             return(1);
 
3208
    } else {
 
3209
        if ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
 
3210
            (c == '.') || (c == '-') ||
 
3211
            (c == '_') || (c == ':') ||
 
3212
            (IS_COMBINING(c)) ||
 
3213
            (IS_EXTENDER(c)))
 
3214
            return(1);
 
3215
    }
 
3216
    return(0);
 
3217
}
 
3218
 
 
3219
static xmlChar * xmlParseAttValueInternal(xmlParserCtxtPtr ctxt,
 
3220
                                          int *len, int *alloc, int normalize);
 
3221
 
 
3222
static const xmlChar *
 
3223
xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
 
3224
    int len = 0, l;
 
3225
    int c;
 
3226
    int count = 0;
 
3227
 
 
3228
#ifdef DEBUG
 
3229
    nbParseNameComplex++;
 
3230
#endif
 
3231
 
 
3232
    /*
 
3233
     * Handler for more complex cases
 
3234
     */
 
3235
    GROW;
 
3236
    if (ctxt->instate == XML_PARSER_EOF)
 
3237
        return(NULL);
 
3238
    c = CUR_CHAR(l);
 
3239
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
 
3240
        /*
 
3241
         * Use the new checks of production [4] [4a] amd [5] of the
 
3242
         * Update 5 of XML-1.0
 
3243
         */
 
3244
        if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
 
3245
            (!(((c >= 'a') && (c <= 'z')) ||
 
3246
               ((c >= 'A') && (c <= 'Z')) ||
 
3247
               (c == '_') || (c == ':') ||
 
3248
               ((c >= 0xC0) && (c <= 0xD6)) ||
 
3249
               ((c >= 0xD8) && (c <= 0xF6)) ||
 
3250
               ((c >= 0xF8) && (c <= 0x2FF)) ||
 
3251
               ((c >= 0x370) && (c <= 0x37D)) ||
 
3252
               ((c >= 0x37F) && (c <= 0x1FFF)) ||
 
3253
               ((c >= 0x200C) && (c <= 0x200D)) ||
 
3254
               ((c >= 0x2070) && (c <= 0x218F)) ||
 
3255
               ((c >= 0x2C00) && (c <= 0x2FEF)) ||
 
3256
               ((c >= 0x3001) && (c <= 0xD7FF)) ||
 
3257
               ((c >= 0xF900) && (c <= 0xFDCF)) ||
 
3258
               ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
 
3259
               ((c >= 0x10000) && (c <= 0xEFFFF))))) {
 
3260
            return(NULL);
 
3261
        }
 
3262
        len += l;
 
3263
        NEXTL(l);
 
3264
        c = CUR_CHAR(l);
 
3265
        while ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
 
3266
               (((c >= 'a') && (c <= 'z')) ||
 
3267
                ((c >= 'A') && (c <= 'Z')) ||
 
3268
                ((c >= '0') && (c <= '9')) || /* !start */
 
3269
                (c == '_') || (c == ':') ||
 
3270
                (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
 
3271
                ((c >= 0xC0) && (c <= 0xD6)) ||
 
3272
                ((c >= 0xD8) && (c <= 0xF6)) ||
 
3273
                ((c >= 0xF8) && (c <= 0x2FF)) ||
 
3274
                ((c >= 0x300) && (c <= 0x36F)) || /* !start */
 
3275
                ((c >= 0x370) && (c <= 0x37D)) ||
 
3276
                ((c >= 0x37F) && (c <= 0x1FFF)) ||
 
3277
                ((c >= 0x200C) && (c <= 0x200D)) ||
 
3278
                ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
 
3279
                ((c >= 0x2070) && (c <= 0x218F)) ||
 
3280
                ((c >= 0x2C00) && (c <= 0x2FEF)) ||
 
3281
                ((c >= 0x3001) && (c <= 0xD7FF)) ||
 
3282
                ((c >= 0xF900) && (c <= 0xFDCF)) ||
 
3283
                ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
 
3284
                ((c >= 0x10000) && (c <= 0xEFFFF))
 
3285
                )) {
 
3286
            if (count++ > XML_PARSER_CHUNK_SIZE) {
 
3287
                count = 0;
 
3288
                GROW;
 
3289
                if (ctxt->instate == XML_PARSER_EOF)
 
3290
                    return(NULL);
 
3291
            }
 
3292
            len += l;
 
3293
            NEXTL(l);
 
3294
            c = CUR_CHAR(l);
 
3295
        }
 
3296
    } else {
 
3297
        if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
 
3298
            (!IS_LETTER(c) && (c != '_') &&
 
3299
             (c != ':'))) {
 
3300
            return(NULL);
 
3301
        }
 
3302
        len += l;
 
3303
        NEXTL(l);
 
3304
        c = CUR_CHAR(l);
 
3305
 
 
3306
        while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
 
3307
               ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
 
3308
                (c == '.') || (c == '-') ||
 
3309
                (c == '_') || (c == ':') ||
 
3310
                (IS_COMBINING(c)) ||
 
3311
                (IS_EXTENDER(c)))) {
 
3312
            if (count++ > XML_PARSER_CHUNK_SIZE) {
 
3313
                count = 0;
 
3314
                GROW;
 
3315
                if (ctxt->instate == XML_PARSER_EOF)
 
3316
                    return(NULL);
 
3317
            }
 
3318
            len += l;
 
3319
            NEXTL(l);
 
3320
            c = CUR_CHAR(l);
 
3321
            if (c == 0) {
 
3322
                count = 0;
 
3323
                GROW;
 
3324
                if (ctxt->instate == XML_PARSER_EOF)
 
3325
                    return(NULL);
 
3326
                c = CUR_CHAR(l);
 
3327
            }
 
3328
        }
 
3329
    }
 
3330
    if ((len > XML_MAX_NAME_LENGTH) &&
 
3331
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
3332
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
 
3333
        return(NULL);
 
3334
    }
 
3335
    if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r'))
 
3336
        return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len));
 
3337
    return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
 
3338
}
 
3339
 
 
3340
/**
 
3341
 * xmlParseName:
 
3342
 * @ctxt:  an XML parser context
 
3343
 *
 
3344
 * parse an XML name.
 
3345
 *
 
3346
 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
 
3347
 *                  CombiningChar | Extender
 
3348
 *
 
3349
 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
 
3350
 *
 
3351
 * [6] Names ::= Name (#x20 Name)*
 
3352
 *
 
3353
 * Returns the Name parsed or NULL
 
3354
 */
 
3355
 
 
3356
const xmlChar *
 
3357
xmlParseName(xmlParserCtxtPtr ctxt) {
 
3358
    const xmlChar *in;
 
3359
    const xmlChar *ret;
 
3360
    int count = 0;
 
3361
 
 
3362
    GROW;
 
3363
 
 
3364
#ifdef DEBUG
 
3365
    nbParseName++;
 
3366
#endif
 
3367
 
 
3368
    /*
 
3369
     * Accelerator for simple ASCII names
 
3370
     */
 
3371
    in = ctxt->input->cur;
 
3372
    if (((*in >= 0x61) && (*in <= 0x7A)) ||
 
3373
        ((*in >= 0x41) && (*in <= 0x5A)) ||
 
3374
        (*in == '_') || (*in == ':')) {
 
3375
        in++;
 
3376
        while (((*in >= 0x61) && (*in <= 0x7A)) ||
 
3377
               ((*in >= 0x41) && (*in <= 0x5A)) ||
 
3378
               ((*in >= 0x30) && (*in <= 0x39)) ||
 
3379
               (*in == '_') || (*in == '-') ||
 
3380
               (*in == ':') || (*in == '.'))
 
3381
            in++;
 
3382
        if ((*in > 0) && (*in < 0x80)) {
 
3383
            count = in - ctxt->input->cur;
 
3384
            if ((count > XML_MAX_NAME_LENGTH) &&
 
3385
                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
3386
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
 
3387
                return(NULL);
 
3388
            }
 
3389
            ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
 
3390
            ctxt->input->cur = in;
 
3391
            ctxt->nbChars += count;
 
3392
            ctxt->input->col += count;
 
3393
            if (ret == NULL)
 
3394
                xmlErrMemory(ctxt, NULL);
 
3395
            return(ret);
 
3396
        }
 
3397
    }
 
3398
    /* accelerator for special cases */
 
3399
    return(xmlParseNameComplex(ctxt));
 
3400
}
 
3401
 
 
3402
static const xmlChar *
 
3403
xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
 
3404
    int len = 0, l;
 
3405
    int c;
 
3406
    int count = 0;
 
3407
 
 
3408
#ifdef DEBUG
 
3409
    nbParseNCNameComplex++;
 
3410
#endif
 
3411
 
 
3412
    /*
 
3413
     * Handler for more complex cases
 
3414
     */
 
3415
    GROW;
 
3416
    c = CUR_CHAR(l);
 
3417
    if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
 
3418
        (!xmlIsNameStartChar(ctxt, c) || (c == ':'))) {
 
3419
        return(NULL);
 
3420
    }
 
3421
 
 
3422
    while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
 
3423
           (xmlIsNameChar(ctxt, c) && (c != ':'))) {
 
3424
        if (count++ > XML_PARSER_CHUNK_SIZE) {
 
3425
            if ((len > XML_MAX_NAME_LENGTH) &&
 
3426
                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
3427
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
 
3428
                return(NULL);
 
3429
            }
 
3430
            count = 0;
 
3431
            GROW;
 
3432
            if (ctxt->instate == XML_PARSER_EOF)
 
3433
                return(NULL);
 
3434
        }
 
3435
        len += l;
 
3436
        NEXTL(l);
 
3437
        c = CUR_CHAR(l);
 
3438
        if (c == 0) {
 
3439
            count = 0;
 
3440
            GROW;
 
3441
            if (ctxt->instate == XML_PARSER_EOF)
 
3442
                return(NULL);
 
3443
            c = CUR_CHAR(l);
 
3444
        }
 
3445
    }
 
3446
    if ((len > XML_MAX_NAME_LENGTH) &&
 
3447
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
3448
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
 
3449
        return(NULL);
 
3450
    }
 
3451
    return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
 
3452
}
 
3453
 
 
3454
/**
 
3455
 * xmlParseNCName:
 
3456
 * @ctxt:  an XML parser context
 
3457
 * @len:  length of the string parsed
 
3458
 *
 
3459
 * parse an XML name.
 
3460
 *
 
3461
 * [4NS] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
 
3462
 *                      CombiningChar | Extender
 
3463
 *
 
3464
 * [5NS] NCName ::= (Letter | '_') (NCNameChar)*
 
3465
 *
 
3466
 * Returns the Name parsed or NULL
 
3467
 */
 
3468
 
 
3469
static const xmlChar *
 
3470
xmlParseNCName(xmlParserCtxtPtr ctxt) {
 
3471
    const xmlChar *in;
 
3472
    const xmlChar *ret;
 
3473
    int count = 0;
 
3474
 
 
3475
#ifdef DEBUG
 
3476
    nbParseNCName++;
 
3477
#endif
 
3478
 
 
3479
    /*
 
3480
     * Accelerator for simple ASCII names
 
3481
     */
 
3482
    in = ctxt->input->cur;
 
3483
    if (((*in >= 0x61) && (*in <= 0x7A)) ||
 
3484
        ((*in >= 0x41) && (*in <= 0x5A)) ||
 
3485
        (*in == '_')) {
 
3486
        in++;
 
3487
        while (((*in >= 0x61) && (*in <= 0x7A)) ||
 
3488
               ((*in >= 0x41) && (*in <= 0x5A)) ||
 
3489
               ((*in >= 0x30) && (*in <= 0x39)) ||
 
3490
               (*in == '_') || (*in == '-') ||
 
3491
               (*in == '.'))
 
3492
            in++;
 
3493
        if ((*in > 0) && (*in < 0x80)) {
 
3494
            count = in - ctxt->input->cur;
 
3495
            if ((count > XML_MAX_NAME_LENGTH) &&
 
3496
                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
3497
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
 
3498
                return(NULL);
 
3499
            }
 
3500
            ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
 
3501
            ctxt->input->cur = in;
 
3502
            ctxt->nbChars += count;
 
3503
            ctxt->input->col += count;
 
3504
            if (ret == NULL) {
 
3505
                xmlErrMemory(ctxt, NULL);
 
3506
            }
 
3507
            return(ret);
 
3508
        }
 
3509
    }
 
3510
    return(xmlParseNCNameComplex(ctxt));
 
3511
}
 
3512
 
 
3513
/**
 
3514
 * xmlParseNameAndCompare:
 
3515
 * @ctxt:  an XML parser context
 
3516
 *
 
3517
 * parse an XML name and compares for match
 
3518
 * (specialized for endtag parsing)
 
3519
 *
 
3520
 * Returns NULL for an illegal name, (xmlChar*) 1 for success
 
3521
 * and the name for mismatch
 
3522
 */
 
3523
 
 
3524
static const xmlChar *
 
3525
xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) {
 
3526
    register const xmlChar *cmp = other;
 
3527
    register const xmlChar *in;
 
3528
    const xmlChar *ret;
 
3529
 
 
3530
    GROW;
 
3531
    if (ctxt->instate == XML_PARSER_EOF)
 
3532
        return(NULL);
 
3533
 
 
3534
    in = ctxt->input->cur;
 
3535
    while (*in != 0 && *in == *cmp) {
 
3536
        ++in;
 
3537
        ++cmp;
 
3538
        ctxt->input->col++;
 
3539
    }
 
3540
    if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
 
3541
        /* success */
 
3542
        ctxt->input->cur = in;
 
3543
        return (const xmlChar*) 1;
 
3544
    }
 
3545
    /* failure (or end of input buffer), check with full function */
 
3546
    ret = xmlParseName (ctxt);
 
3547
    /* strings coming from the dictionnary direct compare possible */
 
3548
    if (ret == other) {
 
3549
        return (const xmlChar*) 1;
 
3550
    }
 
3551
    return ret;
 
3552
}
 
3553
 
 
3554
/**
 
3555
 * xmlParseStringName:
 
3556
 * @ctxt:  an XML parser context
 
3557
 * @str:  a pointer to the string pointer (IN/OUT)
 
3558
 *
 
3559
 * parse an XML name.
 
3560
 *
 
3561
 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
 
3562
 *                  CombiningChar | Extender
 
3563
 *
 
3564
 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
 
3565
 *
 
3566
 * [6] Names ::= Name (#x20 Name)*
 
3567
 *
 
3568
 * Returns the Name parsed or NULL. The @str pointer
 
3569
 * is updated to the current location in the string.
 
3570
 */
 
3571
 
 
3572
static xmlChar *
 
3573
xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
 
3574
    xmlChar buf[XML_MAX_NAMELEN + 5];
 
3575
    const xmlChar *cur = *str;
 
3576
    int len = 0, l;
 
3577
    int c;
 
3578
 
 
3579
#ifdef DEBUG
 
3580
    nbParseStringName++;
 
3581
#endif
 
3582
 
 
3583
    c = CUR_SCHAR(cur, l);
 
3584
    if (!xmlIsNameStartChar(ctxt, c)) {
 
3585
        return(NULL);
 
3586
    }
 
3587
 
 
3588
    COPY_BUF(l,buf,len,c);
 
3589
    cur += l;
 
3590
    c = CUR_SCHAR(cur, l);
 
3591
    while (xmlIsNameChar(ctxt, c)) {
 
3592
        COPY_BUF(l,buf,len,c);
 
3593
        cur += l;
 
3594
        c = CUR_SCHAR(cur, l);
 
3595
        if (len >= XML_MAX_NAMELEN) { /* test bigentname.xml */
 
3596
            /*
 
3597
             * Okay someone managed to make a huge name, so he's ready to pay
 
3598
             * for the processing speed.
 
3599
             */
 
3600
            xmlChar *buffer;
 
3601
            int max = len * 2;
 
3602
 
 
3603
            buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
 
3604
            if (buffer == NULL) {
 
3605
                xmlErrMemory(ctxt, NULL);
 
3606
                return(NULL);
 
3607
            }
 
3608
            memcpy(buffer, buf, len);
 
3609
            while (xmlIsNameChar(ctxt, c)) {
 
3610
                if (len + 10 > max) {
 
3611
                    xmlChar *tmp;
 
3612
 
 
3613
                    if ((len > XML_MAX_NAME_LENGTH) &&
 
3614
                        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
3615
                        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
 
3616
                        xmlFree(buffer);
 
3617
                        return(NULL);
 
3618
                    }
 
3619
                    max *= 2;
 
3620
                    tmp = (xmlChar *) xmlRealloc(buffer,
 
3621
                                                    max * sizeof(xmlChar));
 
3622
                    if (tmp == NULL) {
 
3623
                        xmlErrMemory(ctxt, NULL);
 
3624
                        xmlFree(buffer);
 
3625
                        return(NULL);
 
3626
                    }
 
3627
                    buffer = tmp;
 
3628
                }
 
3629
                COPY_BUF(l,buffer,len,c);
 
3630
                cur += l;
 
3631
                c = CUR_SCHAR(cur, l);
 
3632
            }
 
3633
            buffer[len] = 0;
 
3634
            *str = cur;
 
3635
            return(buffer);
 
3636
        }
 
3637
    }
 
3638
    if ((len > XML_MAX_NAME_LENGTH) &&
 
3639
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
3640
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
 
3641
        return(NULL);
 
3642
    }
 
3643
    *str = cur;
 
3644
    return(xmlStrndup(buf, len));
 
3645
}
 
3646
 
 
3647
/**
 
3648
 * xmlParseNmtoken:
 
3649
 * @ctxt:  an XML parser context
 
3650
 *
 
3651
 * parse an XML Nmtoken.
 
3652
 *
 
3653
 * [7] Nmtoken ::= (NameChar)+
 
3654
 *
 
3655
 * [8] Nmtokens ::= Nmtoken (#x20 Nmtoken)*
 
3656
 *
 
3657
 * Returns the Nmtoken parsed or NULL
 
3658
 */
 
3659
 
 
3660
xmlChar *
 
3661
xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
 
3662
    xmlChar buf[XML_MAX_NAMELEN + 5];
 
3663
    int len = 0, l;
 
3664
    int c;
 
3665
    int count = 0;
 
3666
 
 
3667
#ifdef DEBUG
 
3668
    nbParseNmToken++;
 
3669
#endif
 
3670
 
 
3671
    GROW;
 
3672
    if (ctxt->instate == XML_PARSER_EOF)
 
3673
        return(NULL);
 
3674
    c = CUR_CHAR(l);
 
3675
 
 
3676
    while (xmlIsNameChar(ctxt, c)) {
 
3677
        if (count++ > XML_PARSER_CHUNK_SIZE) {
 
3678
            count = 0;
 
3679
            GROW;
 
3680
        }
 
3681
        COPY_BUF(l,buf,len,c);
 
3682
        NEXTL(l);
 
3683
        c = CUR_CHAR(l);
 
3684
        if (c == 0) {
 
3685
            count = 0;
 
3686
            GROW;
 
3687
            if (ctxt->instate == XML_PARSER_EOF)
 
3688
                return(NULL);
 
3689
            c = CUR_CHAR(l);
 
3690
        }
 
3691
        if (len >= XML_MAX_NAMELEN) {
 
3692
            /*
 
3693
             * Okay someone managed to make a huge token, so he's ready to pay
 
3694
             * for the processing speed.
 
3695
             */
 
3696
            xmlChar *buffer;
 
3697
            int max = len * 2;
 
3698
 
 
3699
            buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
 
3700
            if (buffer == NULL) {
 
3701
                xmlErrMemory(ctxt, NULL);
 
3702
                return(NULL);
 
3703
            }
 
3704
            memcpy(buffer, buf, len);
 
3705
            while (xmlIsNameChar(ctxt, c)) {
 
3706
                if (count++ > XML_PARSER_CHUNK_SIZE) {
 
3707
                    count = 0;
 
3708
                    GROW;
 
3709
                    if (ctxt->instate == XML_PARSER_EOF) {
 
3710
                        xmlFree(buffer);
 
3711
                        return(NULL);
 
3712
                    }
 
3713
                }
 
3714
                if (len + 10 > max) {
 
3715
                    xmlChar *tmp;
 
3716
 
 
3717
                    if ((max > XML_MAX_NAME_LENGTH) &&
 
3718
                        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
3719
                        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
 
3720
                        xmlFree(buffer);
 
3721
                        return(NULL);
 
3722
                    }
 
3723
                    max *= 2;
 
3724
                    tmp = (xmlChar *) xmlRealloc(buffer,
 
3725
                                                    max * sizeof(xmlChar));
 
3726
                    if (tmp == NULL) {
 
3727
                        xmlErrMemory(ctxt, NULL);
 
3728
                        xmlFree(buffer);
 
3729
                        return(NULL);
 
3730
                    }
 
3731
                    buffer = tmp;
 
3732
                }
 
3733
                COPY_BUF(l,buffer,len,c);
 
3734
                NEXTL(l);
 
3735
                c = CUR_CHAR(l);
 
3736
            }
 
3737
            buffer[len] = 0;
 
3738
            return(buffer);
 
3739
        }
 
3740
    }
 
3741
    if (len == 0)
 
3742
        return(NULL);
 
3743
    if ((len > XML_MAX_NAME_LENGTH) &&
 
3744
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
3745
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
 
3746
        return(NULL);
 
3747
    }
 
3748
    return(xmlStrndup(buf, len));
 
3749
}
 
3750
 
 
3751
/**
 
3752
 * xmlParseEntityValue:
 
3753
 * @ctxt:  an XML parser context
 
3754
 * @orig:  if non-NULL store a copy of the original entity value
 
3755
 *
 
3756
 * parse a value for ENTITY declarations
 
3757
 *
 
3758
 * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
 
3759
 *                     "'" ([^%&'] | PEReference | Reference)* "'"
 
3760
 *
 
3761
 * Returns the EntityValue parsed with reference substituted or NULL
 
3762
 */
 
3763
 
 
3764
xmlChar *
 
3765
xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
 
3766
    xmlChar *buf = NULL;
 
3767
    int len = 0;
 
3768
    int size = XML_PARSER_BUFFER_SIZE;
 
3769
    int c, l;
 
3770
    xmlChar stop;
 
3771
    xmlChar *ret = NULL;
 
3772
    const xmlChar *cur = NULL;
 
3773
    xmlParserInputPtr input;
 
3774
 
 
3775
    if (RAW == '"') stop = '"';
 
3776
    else if (RAW == '\'') stop = '\'';
 
3777
    else {
 
3778
        xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_STARTED, NULL);
 
3779
        return(NULL);
 
3780
    }
 
3781
    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
3782
    if (buf == NULL) {
 
3783
        xmlErrMemory(ctxt, NULL);
 
3784
        return(NULL);
 
3785
    }
 
3786
 
 
3787
    /*
 
3788
     * The content of the entity definition is copied in a buffer.
 
3789
     */
 
3790
 
 
3791
    ctxt->instate = XML_PARSER_ENTITY_VALUE;
 
3792
    input = ctxt->input;
 
3793
    GROW;
 
3794
    if (ctxt->instate == XML_PARSER_EOF) {
 
3795
        xmlFree(buf);
 
3796
        return(NULL);
 
3797
    }
 
3798
    NEXT;
 
3799
    c = CUR_CHAR(l);
 
3800
    /*
 
3801
     * NOTE: 4.4.5 Included in Literal
 
3802
     * When a parameter entity reference appears in a literal entity
 
3803
     * value, ... a single or double quote character in the replacement
 
3804
     * text is always treated as a normal data character and will not
 
3805
     * terminate the literal.
 
3806
     * In practice it means we stop the loop only when back at parsing
 
3807
     * the initial entity and the quote is found
 
3808
     */
 
3809
    while (((IS_CHAR(c)) && ((c != stop) || /* checked */
 
3810
            (ctxt->input != input))) && (ctxt->instate != XML_PARSER_EOF)) {
 
3811
        if (len + 5 >= size) {
 
3812
            xmlChar *tmp;
 
3813
 
 
3814
            size *= 2;
 
3815
            tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
 
3816
            if (tmp == NULL) {
 
3817
                xmlErrMemory(ctxt, NULL);
 
3818
                xmlFree(buf);
 
3819
                return(NULL);
 
3820
            }
 
3821
            buf = tmp;
 
3822
        }
 
3823
        COPY_BUF(l,buf,len,c);
 
3824
        NEXTL(l);
 
3825
        /*
 
3826
         * Pop-up of finished entities.
 
3827
         */
 
3828
        while ((RAW == 0) && (ctxt->inputNr > 1)) /* non input consuming */
 
3829
            xmlPopInput(ctxt);
 
3830
 
 
3831
        GROW;
 
3832
        c = CUR_CHAR(l);
 
3833
        if (c == 0) {
 
3834
            GROW;
 
3835
            c = CUR_CHAR(l);
 
3836
        }
 
3837
    }
 
3838
    buf[len] = 0;
 
3839
    if (ctxt->instate == XML_PARSER_EOF) {
 
3840
        xmlFree(buf);
 
3841
        return(NULL);
 
3842
    }
 
3843
 
 
3844
    /*
 
3845
     * Raise problem w.r.t. '&' and '%' being used in non-entities
 
3846
     * reference constructs. Note Charref will be handled in
 
3847
     * xmlStringDecodeEntities()
 
3848
     */
 
3849
    cur = buf;
 
3850
    while (*cur != 0) { /* non input consuming */
 
3851
        if ((*cur == '%') || ((*cur == '&') && (cur[1] != '#'))) {
 
3852
            xmlChar *name;
 
3853
            xmlChar tmp = *cur;
 
3854
 
 
3855
            cur++;
 
3856
            name = xmlParseStringName(ctxt, &cur);
 
3857
            if ((name == NULL) || (*cur != ';')) {
 
3858
                xmlFatalErrMsgInt(ctxt, XML_ERR_ENTITY_CHAR_ERROR,
 
3859
            "EntityValue: '%c' forbidden except for entities references\n",
 
3860
                                  tmp);
 
3861
            }
 
3862
            if ((tmp == '%') && (ctxt->inSubset == 1) &&
 
3863
                (ctxt->inputNr == 1)) {
 
3864
                xmlFatalErr(ctxt, XML_ERR_ENTITY_PE_INTERNAL, NULL);
 
3865
            }
 
3866
            if (name != NULL)
 
3867
                xmlFree(name);
 
3868
            if (*cur == 0)
 
3869
                break;
 
3870
        }
 
3871
        cur++;
 
3872
    }
 
3873
 
 
3874
    /*
 
3875
     * Then PEReference entities are substituted.
 
3876
     */
 
3877
    if (c != stop) {
 
3878
        xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL);
 
3879
        xmlFree(buf);
 
3880
    } else {
 
3881
        NEXT;
 
3882
        /*
 
3883
         * NOTE: 4.4.7 Bypassed
 
3884
         * When a general entity reference appears in the EntityValue in
 
3885
         * an entity declaration, it is bypassed and left as is.
 
3886
         * so XML_SUBSTITUTE_REF is not set here.
 
3887
         */
 
3888
        ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF,
 
3889
                                      0, 0, 0);
 
3890
        if (orig != NULL)
 
3891
            *orig = buf;
 
3892
        else
 
3893
            xmlFree(buf);
 
3894
    }
 
3895
 
 
3896
    return(ret);
 
3897
}
 
3898
 
 
3899
/**
 
3900
 * xmlParseAttValueComplex:
 
3901
 * @ctxt:  an XML parser context
 
3902
 * @len:   the resulting attribute len
 
3903
 * @normalize:  wether to apply the inner normalization
 
3904
 *
 
3905
 * parse a value for an attribute, this is the fallback function
 
3906
 * of xmlParseAttValue() when the attribute parsing requires handling
 
3907
 * of non-ASCII characters, or normalization compaction.
 
3908
 *
 
3909
 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
 
3910
 */
 
3911
static xmlChar *
 
3912
xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
 
3913
    xmlChar limit = 0;
 
3914
    xmlChar *buf = NULL;
 
3915
    xmlChar *rep = NULL;
 
3916
    size_t len = 0;
 
3917
    size_t buf_size = 0;
 
3918
    int c, l, in_space = 0;
 
3919
    xmlChar *current = NULL;
 
3920
    xmlEntityPtr ent;
 
3921
 
 
3922
    if (NXT(0) == '"') {
 
3923
        ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
 
3924
        limit = '"';
 
3925
        NEXT;
 
3926
    } else if (NXT(0) == '\'') {
 
3927
        limit = '\'';
 
3928
        ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
 
3929
        NEXT;
 
3930
    } else {
 
3931
        xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
 
3932
        return(NULL);
 
3933
    }
 
3934
 
 
3935
    /*
 
3936
     * allocate a translation buffer.
 
3937
     */
 
3938
    buf_size = XML_PARSER_BUFFER_SIZE;
 
3939
    buf = (xmlChar *) xmlMallocAtomic(buf_size);
 
3940
    if (buf == NULL) goto mem_error;
 
3941
 
 
3942
    /*
 
3943
     * OK loop until we reach one of the ending char or a size limit.
 
3944
     */
 
3945
    c = CUR_CHAR(l);
 
3946
    while (((NXT(0) != limit) && /* checked */
 
3947
            (IS_CHAR(c)) && (c != '<')) &&
 
3948
            (ctxt->instate != XML_PARSER_EOF)) {
 
3949
        /*
 
3950
         * Impose a reasonable limit on attribute size, unless XML_PARSE_HUGE
 
3951
         * special option is given
 
3952
         */
 
3953
        if ((len > XML_MAX_TEXT_LENGTH) &&
 
3954
            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
3955
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
 
3956
                           "AttValue length too long\n");
 
3957
            goto mem_error;
 
3958
        }
 
3959
        if (c == 0) break;
 
3960
        if (c == '&') {
 
3961
            in_space = 0;
 
3962
            if (NXT(1) == '#') {
 
3963
                int val = xmlParseCharRef(ctxt);
 
3964
 
 
3965
                if (val == '&') {
 
3966
                    if (ctxt->replaceEntities) {
 
3967
                        if (len + 10 > buf_size) {
 
3968
                            growBuffer(buf, 10);
 
3969
                        }
 
3970
                        buf[len++] = '&';
 
3971
                    } else {
 
3972
                        /*
 
3973
                         * The reparsing will be done in xmlStringGetNodeList()
 
3974
                         * called by the attribute() function in SAX.c
 
3975
                         */
 
3976
                        if (len + 10 > buf_size) {
 
3977
                            growBuffer(buf, 10);
 
3978
                        }
 
3979
                        buf[len++] = '&';
 
3980
                        buf[len++] = '#';
 
3981
                        buf[len++] = '3';
 
3982
                        buf[len++] = '8';
 
3983
                        buf[len++] = ';';
 
3984
                    }
 
3985
                } else if (val != 0) {
 
3986
                    if (len + 10 > buf_size) {
 
3987
                        growBuffer(buf, 10);
 
3988
                    }
 
3989
                    len += xmlCopyChar(0, &buf[len], val);
 
3990
                }
 
3991
            } else {
 
3992
                ent = xmlParseEntityRef(ctxt);
 
3993
                ctxt->nbentities++;
 
3994
                if (ent != NULL)
 
3995
                    ctxt->nbentities += ent->owner;
 
3996
                if ((ent != NULL) &&
 
3997
                    (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
 
3998
                    if (len + 10 > buf_size) {
 
3999
                        growBuffer(buf, 10);
 
4000
                    }
 
4001
                    if ((ctxt->replaceEntities == 0) &&
 
4002
                        (ent->content[0] == '&')) {
 
4003
                        buf[len++] = '&';
 
4004
                        buf[len++] = '#';
 
4005
                        buf[len++] = '3';
 
4006
                        buf[len++] = '8';
 
4007
                        buf[len++] = ';';
 
4008
                    } else {
 
4009
                        buf[len++] = ent->content[0];
 
4010
                    }
 
4011
                } else if ((ent != NULL) &&
 
4012
                           (ctxt->replaceEntities != 0)) {
 
4013
                    if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
 
4014
                        rep = xmlStringDecodeEntities(ctxt, ent->content,
 
4015
                                                      XML_SUBSTITUTE_REF,
 
4016
                                                      0, 0, 0);
 
4017
                        if (rep != NULL) {
 
4018
                            current = rep;
 
4019
                            while (*current != 0) { /* non input consuming */
 
4020
                                if ((*current == 0xD) || (*current == 0xA) ||
 
4021
                                    (*current == 0x9)) {
 
4022
                                    buf[len++] = 0x20;
 
4023
                                    current++;
 
4024
                                } else
 
4025
                                    buf[len++] = *current++;
 
4026
                                if (len + 10 > buf_size) {
 
4027
                                    growBuffer(buf, 10);
 
4028
                                }
 
4029
                            }
 
4030
                            xmlFree(rep);
 
4031
                            rep = NULL;
 
4032
                        }
 
4033
                    } else {
 
4034
                        if (len + 10 > buf_size) {
 
4035
                            growBuffer(buf, 10);
 
4036
                        }
 
4037
                        if (ent->content != NULL)
 
4038
                            buf[len++] = ent->content[0];
 
4039
                    }
 
4040
                } else if (ent != NULL) {
 
4041
                    int i = xmlStrlen(ent->name);
 
4042
                    const xmlChar *cur = ent->name;
 
4043
 
 
4044
                    /*
 
4045
                     * This may look absurd but is needed to detect
 
4046
                     * entities problems
 
4047
                     */
 
4048
                    if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
 
4049
                        (ent->content != NULL) && (ent->checked == 0)) {
 
4050
                        unsigned long oldnbent = ctxt->nbentities;
 
4051
 
 
4052
                        rep = xmlStringDecodeEntities(ctxt, ent->content,
 
4053
                                                  XML_SUBSTITUTE_REF, 0, 0, 0);
 
4054
 
 
4055
                        ent->checked = (ctxt->nbentities - oldnbent + 1) * 2;
 
4056
                        if (rep != NULL) {
 
4057
                            if (xmlStrchr(rep, '<'))
 
4058
                                ent->checked |= 1;
 
4059
                            xmlFree(rep);
 
4060
                            rep = NULL;
 
4061
                        }
 
4062
                    }
 
4063
 
 
4064
                    /*
 
4065
                     * Just output the reference
 
4066
                     */
 
4067
                    buf[len++] = '&';
 
4068
                    while (len + i + 10 > buf_size) {
 
4069
                        growBuffer(buf, i + 10);
 
4070
                    }
 
4071
                    for (;i > 0;i--)
 
4072
                        buf[len++] = *cur++;
 
4073
                    buf[len++] = ';';
 
4074
                }
 
4075
            }
 
4076
        } else {
 
4077
            if ((c == 0x20) || (c == 0xD) || (c == 0xA) || (c == 0x9)) {
 
4078
                if ((len != 0) || (!normalize)) {
 
4079
                    if ((!normalize) || (!in_space)) {
 
4080
                        COPY_BUF(l,buf,len,0x20);
 
4081
                        while (len + 10 > buf_size) {
 
4082
                            growBuffer(buf, 10);
 
4083
                        }
 
4084
                    }
 
4085
                    in_space = 1;
 
4086
                }
 
4087
            } else {
 
4088
                in_space = 0;
 
4089
                COPY_BUF(l,buf,len,c);
 
4090
                if (len + 10 > buf_size) {
 
4091
                    growBuffer(buf, 10);
 
4092
                }
 
4093
            }
 
4094
            NEXTL(l);
 
4095
        }
 
4096
        GROW;
 
4097
        c = CUR_CHAR(l);
 
4098
    }
 
4099
    if (ctxt->instate == XML_PARSER_EOF)
 
4100
        goto error;
 
4101
 
 
4102
    if ((in_space) && (normalize)) {
 
4103
        while ((len > 0) && (buf[len - 1] == 0x20)) len--;
 
4104
    }
 
4105
    buf[len] = 0;
 
4106
    if (RAW == '<') {
 
4107
        xmlFatalErr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, NULL);
 
4108
    } else if (RAW != limit) {
 
4109
        if ((c != 0) && (!IS_CHAR(c))) {
 
4110
            xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
 
4111
                           "invalid character in attribute value\n");
 
4112
        } else {
 
4113
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
 
4114
                           "AttValue: ' expected\n");
 
4115
        }
 
4116
    } else
 
4117
        NEXT;
 
4118
 
 
4119
    /*
 
4120
     * There we potentially risk an overflow, don't allow attribute value of
 
4121
     * length more than INT_MAX it is a very reasonnable assumption !
 
4122
     */
 
4123
    if (len >= INT_MAX) {
 
4124
        xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
 
4125
                       "AttValue length too long\n");
 
4126
        goto mem_error;
 
4127
    }
 
4128
 
 
4129
    if (attlen != NULL) *attlen = (int) len;
 
4130
    return(buf);
 
4131
 
 
4132
mem_error:
 
4133
    xmlErrMemory(ctxt, NULL);
 
4134
error:
 
4135
    if (buf != NULL)
 
4136
        xmlFree(buf);
 
4137
    if (rep != NULL)
 
4138
        xmlFree(rep);
 
4139
    return(NULL);
 
4140
}
 
4141
 
 
4142
/**
 
4143
 * xmlParseAttValue:
 
4144
 * @ctxt:  an XML parser context
 
4145
 *
 
4146
 * parse a value for an attribute
 
4147
 * Note: the parser won't do substitution of entities here, this
 
4148
 * will be handled later in xmlStringGetNodeList
 
4149
 *
 
4150
 * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |
 
4151
 *                   "'" ([^<&'] | Reference)* "'"
 
4152
 *
 
4153
 * 3.3.3 Attribute-Value Normalization:
 
4154
 * Before the value of an attribute is passed to the application or
 
4155
 * checked for validity, the XML processor must normalize it as follows:
 
4156
 * - a character reference is processed by appending the referenced
 
4157
 *   character to the attribute value
 
4158
 * - an entity reference is processed by recursively processing the
 
4159
 *   replacement text of the entity
 
4160
 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
 
4161
 *   appending #x20 to the normalized value, except that only a single
 
4162
 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
 
4163
 *   parsed entity or the literal entity value of an internal parsed entity
 
4164
 * - other characters are processed by appending them to the normalized value
 
4165
 * If the declared value is not CDATA, then the XML processor must further
 
4166
 * process the normalized attribute value by discarding any leading and
 
4167
 * trailing space (#x20) characters, and by replacing sequences of space
 
4168
 * (#x20) characters by a single space (#x20) character.
 
4169
 * All attributes for which no declaration has been read should be treated
 
4170
 * by a non-validating parser as if declared CDATA.
 
4171
 *
 
4172
 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
 
4173
 */
 
4174
 
 
4175
 
 
4176
xmlChar *
 
4177
xmlParseAttValue(xmlParserCtxtPtr ctxt) {
 
4178
    if ((ctxt == NULL) || (ctxt->input == NULL)) return(NULL);
 
4179
    return(xmlParseAttValueInternal(ctxt, NULL, NULL, 0));
 
4180
}
 
4181
 
 
4182
/**
 
4183
 * xmlParseSystemLiteral:
 
4184
 * @ctxt:  an XML parser context
 
4185
 *
 
4186
 * parse an XML Literal
 
4187
 *
 
4188
 * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
 
4189
 *
 
4190
 * Returns the SystemLiteral parsed or NULL
 
4191
 */
 
4192
 
 
4193
xmlChar *
 
4194
xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
 
4195
    xmlChar *buf = NULL;
 
4196
    int len = 0;
 
4197
    int size = XML_PARSER_BUFFER_SIZE;
 
4198
    int cur, l;
 
4199
    xmlChar stop;
 
4200
    int state = ctxt->instate;
 
4201
    int count = 0;
 
4202
 
 
4203
    SHRINK;
 
4204
    if (RAW == '"') {
 
4205
        NEXT;
 
4206
        stop = '"';
 
4207
    } else if (RAW == '\'') {
 
4208
        NEXT;
 
4209
        stop = '\'';
 
4210
    } else {
 
4211
        xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
 
4212
        return(NULL);
 
4213
    }
 
4214
 
 
4215
    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
4216
    if (buf == NULL) {
 
4217
        xmlErrMemory(ctxt, NULL);
 
4218
        return(NULL);
 
4219
    }
 
4220
    ctxt->instate = XML_PARSER_SYSTEM_LITERAL;
 
4221
    cur = CUR_CHAR(l);
 
4222
    while ((IS_CHAR(cur)) && (cur != stop)) { /* checked */
 
4223
        if (len + 5 >= size) {
 
4224
            xmlChar *tmp;
 
4225
 
 
4226
            if ((size > XML_MAX_NAME_LENGTH) &&
 
4227
                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
4228
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral");
 
4229
                xmlFree(buf);
 
4230
                ctxt->instate = (xmlParserInputState) state;
 
4231
                return(NULL);
 
4232
            }
 
4233
            size *= 2;
 
4234
            tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
 
4235
            if (tmp == NULL) {
 
4236
                xmlFree(buf);
 
4237
                xmlErrMemory(ctxt, NULL);
 
4238
                ctxt->instate = (xmlParserInputState) state;
 
4239
                return(NULL);
 
4240
            }
 
4241
            buf = tmp;
 
4242
        }
 
4243
        count++;
 
4244
        if (count > 50) {
 
4245
            GROW;
 
4246
            count = 0;
 
4247
            if (ctxt->instate == XML_PARSER_EOF) {
 
4248
                xmlFree(buf);
 
4249
                return(NULL);
 
4250
            }
 
4251
        }
 
4252
        COPY_BUF(l,buf,len,cur);
 
4253
        NEXTL(l);
 
4254
        cur = CUR_CHAR(l);
 
4255
        if (cur == 0) {
 
4256
            GROW;
 
4257
            SHRINK;
 
4258
            cur = CUR_CHAR(l);
 
4259
        }
 
4260
    }
 
4261
    buf[len] = 0;
 
4262
    ctxt->instate = (xmlParserInputState) state;
 
4263
    if (!IS_CHAR(cur)) {
 
4264
        xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
 
4265
    } else {
 
4266
        NEXT;
 
4267
    }
 
4268
    return(buf);
 
4269
}
 
4270
 
 
4271
/**
 
4272
 * xmlParsePubidLiteral:
 
4273
 * @ctxt:  an XML parser context
 
4274
 *
 
4275
 * parse an XML public literal
 
4276
 *
 
4277
 * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
 
4278
 *
 
4279
 * Returns the PubidLiteral parsed or NULL.
 
4280
 */
 
4281
 
 
4282
xmlChar *
 
4283
xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
 
4284
    xmlChar *buf = NULL;
 
4285
    int len = 0;
 
4286
    int size = XML_PARSER_BUFFER_SIZE;
 
4287
    xmlChar cur;
 
4288
    xmlChar stop;
 
4289
    int count = 0;
 
4290
    xmlParserInputState oldstate = ctxt->instate;
 
4291
 
 
4292
    SHRINK;
 
4293
    if (RAW == '"') {
 
4294
        NEXT;
 
4295
        stop = '"';
 
4296
    } else if (RAW == '\'') {
 
4297
        NEXT;
 
4298
        stop = '\'';
 
4299
    } else {
 
4300
        xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
 
4301
        return(NULL);
 
4302
    }
 
4303
    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
4304
    if (buf == NULL) {
 
4305
        xmlErrMemory(ctxt, NULL);
 
4306
        return(NULL);
 
4307
    }
 
4308
    ctxt->instate = XML_PARSER_PUBLIC_LITERAL;
 
4309
    cur = CUR;
 
4310
    while ((IS_PUBIDCHAR_CH(cur)) && (cur != stop)) { /* checked */
 
4311
        if (len + 1 >= size) {
 
4312
            xmlChar *tmp;
 
4313
 
 
4314
            if ((size > XML_MAX_NAME_LENGTH) &&
 
4315
                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
4316
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Public ID");
 
4317
                xmlFree(buf);
 
4318
                return(NULL);
 
4319
            }
 
4320
            size *= 2;
 
4321
            tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
 
4322
            if (tmp == NULL) {
 
4323
                xmlErrMemory(ctxt, NULL);
 
4324
                xmlFree(buf);
 
4325
                return(NULL);
 
4326
            }
 
4327
            buf = tmp;
 
4328
        }
 
4329
        buf[len++] = cur;
 
4330
        count++;
 
4331
        if (count > 50) {
 
4332
            GROW;
 
4333
            count = 0;
 
4334
            if (ctxt->instate == XML_PARSER_EOF) {
 
4335
                xmlFree(buf);
 
4336
                return(NULL);
 
4337
            }
 
4338
        }
 
4339
        NEXT;
 
4340
        cur = CUR;
 
4341
        if (cur == 0) {
 
4342
            GROW;
 
4343
            SHRINK;
 
4344
            cur = CUR;
 
4345
        }
 
4346
    }
 
4347
    buf[len] = 0;
 
4348
    if (cur != stop) {
 
4349
        xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
 
4350
    } else {
 
4351
        NEXT;
 
4352
    }
 
4353
    ctxt->instate = oldstate;
 
4354
    return(buf);
 
4355
}
 
4356
 
 
4357
static void xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata);
 
4358
 
 
4359
/*
 
4360
 * used for the test in the inner loop of the char data testing
 
4361
 */
 
4362
static const unsigned char test_char_data[256] = {
 
4363
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4364
    0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9, CR/LF separated */
 
4365
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4366
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4367
    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x00, 0x27, /* & */
 
4368
    0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
 
4369
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
 
4370
    0x38, 0x39, 0x3A, 0x3B, 0x00, 0x3D, 0x3E, 0x3F, /* < */
 
4371
    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
 
4372
    0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
 
4373
    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
 
4374
    0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x00, 0x5E, 0x5F, /* ] */
 
4375
    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
 
4376
    0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
 
4377
    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
 
4378
    0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
 
4379
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* non-ascii */
 
4380
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4381
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4382
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4383
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4384
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4385
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4386
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4387
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4388
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4389
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4390
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4391
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4392
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4393
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4394
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 
4395
};
 
4396
 
 
4397
/**
 
4398
 * xmlParseCharData:
 
4399
 * @ctxt:  an XML parser context
 
4400
 * @cdata:  int indicating whether we are within a CDATA section
 
4401
 *
 
4402
 * parse a CharData section.
 
4403
 * if we are within a CDATA section ']]>' marks an end of section.
 
4404
 *
 
4405
 * The right angle bracket (>) may be represented using the string "&gt;",
 
4406
 * and must, for compatibility, be escaped using "&gt;" or a character
 
4407
 * reference when it appears in the string "]]>" in content, when that
 
4408
 * string is not marking the end of a CDATA section.
 
4409
 *
 
4410
 * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
 
4411
 */
 
4412
 
 
4413
void
 
4414
xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) {
 
4415
    const xmlChar *in;
 
4416
    int nbchar = 0;
 
4417
    int line = ctxt->input->line;
 
4418
    int col = ctxt->input->col;
 
4419
    int ccol;
 
4420
 
 
4421
    SHRINK;
 
4422
    GROW;
 
4423
    /*
 
4424
     * Accelerated common case where input don't need to be
 
4425
     * modified before passing it to the handler.
 
4426
     */
 
4427
    if (!cdata) {
 
4428
        in = ctxt->input->cur;
 
4429
        do {
 
4430
get_more_space:
 
4431
            while (*in == 0x20) { in++; ctxt->input->col++; }
 
4432
            if (*in == 0xA) {
 
4433
                do {
 
4434
                    ctxt->input->line++; ctxt->input->col = 1;
 
4435
                    in++;
 
4436
                } while (*in == 0xA);
 
4437
                goto get_more_space;
 
4438
            }
 
4439
            if (*in == '<') {
 
4440
                nbchar = in - ctxt->input->cur;
 
4441
                if (nbchar > 0) {
 
4442
                    const xmlChar *tmp = ctxt->input->cur;
 
4443
                    ctxt->input->cur = in;
 
4444
 
 
4445
                    if ((ctxt->sax != NULL) &&
 
4446
                        (ctxt->sax->ignorableWhitespace !=
 
4447
                         ctxt->sax->characters)) {
 
4448
                        if (areBlanks(ctxt, tmp, nbchar, 1)) {
 
4449
                            if (ctxt->sax->ignorableWhitespace != NULL)
 
4450
                                ctxt->sax->ignorableWhitespace(ctxt->userData,
 
4451
                                                       tmp, nbchar);
 
4452
                        } else {
 
4453
                            if (ctxt->sax->characters != NULL)
 
4454
                                ctxt->sax->characters(ctxt->userData,
 
4455
                                                      tmp, nbchar);
 
4456
                            if (*ctxt->space == -1)
 
4457
                                *ctxt->space = -2;
 
4458
                        }
 
4459
                    } else if ((ctxt->sax != NULL) &&
 
4460
                               (ctxt->sax->characters != NULL)) {
 
4461
                        ctxt->sax->characters(ctxt->userData,
 
4462
                                              tmp, nbchar);
 
4463
                    }
 
4464
                }
 
4465
                return;
 
4466
            }
 
4467
 
 
4468
get_more:
 
4469
            ccol = ctxt->input->col;
 
4470
            while (test_char_data[*in]) {
 
4471
                in++;
 
4472
                ccol++;
 
4473
            }
 
4474
            ctxt->input->col = ccol;
 
4475
            if (*in == 0xA) {
 
4476
                do {
 
4477
                    ctxt->input->line++; ctxt->input->col = 1;
 
4478
                    in++;
 
4479
                } while (*in == 0xA);
 
4480
                goto get_more;
 
4481
            }
 
4482
            if (*in == ']') {
 
4483
                if ((in[1] == ']') && (in[2] == '>')) {
 
4484
                    xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
 
4485
                    ctxt->input->cur = in;
 
4486
                    return;
 
4487
                }
 
4488
                in++;
 
4489
                ctxt->input->col++;
 
4490
                goto get_more;
 
4491
            }
 
4492
            nbchar = in - ctxt->input->cur;
 
4493
            if (nbchar > 0) {
 
4494
                if ((ctxt->sax != NULL) &&
 
4495
                    (ctxt->sax->ignorableWhitespace !=
 
4496
                     ctxt->sax->characters) &&
 
4497
                    (IS_BLANK_CH(*ctxt->input->cur))) {
 
4498
                    const xmlChar *tmp = ctxt->input->cur;
 
4499
                    ctxt->input->cur = in;
 
4500
 
 
4501
                    if (areBlanks(ctxt, tmp, nbchar, 0)) {
 
4502
                        if (ctxt->sax->ignorableWhitespace != NULL)
 
4503
                            ctxt->sax->ignorableWhitespace(ctxt->userData,
 
4504
                                                           tmp, nbchar);
 
4505
                    } else {
 
4506
                        if (ctxt->sax->characters != NULL)
 
4507
                            ctxt->sax->characters(ctxt->userData,
 
4508
                                                  tmp, nbchar);
 
4509
                        if (*ctxt->space == -1)
 
4510
                            *ctxt->space = -2;
 
4511
                    }
 
4512
                    line = ctxt->input->line;
 
4513
                    col = ctxt->input->col;
 
4514
                } else if (ctxt->sax != NULL) {
 
4515
                    if (ctxt->sax->characters != NULL)
 
4516
                        ctxt->sax->characters(ctxt->userData,
 
4517
                                              ctxt->input->cur, nbchar);
 
4518
                    line = ctxt->input->line;
 
4519
                    col = ctxt->input->col;
 
4520
                }
 
4521
                /* something really bad happened in the SAX callback */
 
4522
                if (ctxt->instate != XML_PARSER_CONTENT)
 
4523
                    return;
 
4524
            }
 
4525
            ctxt->input->cur = in;
 
4526
            if (*in == 0xD) {
 
4527
                in++;
 
4528
                if (*in == 0xA) {
 
4529
                    ctxt->input->cur = in;
 
4530
                    in++;
 
4531
                    ctxt->input->line++; ctxt->input->col = 1;
 
4532
                    continue; /* while */
 
4533
                }
 
4534
                in--;
 
4535
            }
 
4536
            if (*in == '<') {
 
4537
                return;
 
4538
            }
 
4539
            if (*in == '&') {
 
4540
                return;
 
4541
            }
 
4542
            SHRINK;
 
4543
            GROW;
 
4544
            if (ctxt->instate == XML_PARSER_EOF)
 
4545
                return;
 
4546
            in = ctxt->input->cur;
 
4547
        } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09));
 
4548
        nbchar = 0;
 
4549
    }
 
4550
    ctxt->input->line = line;
 
4551
    ctxt->input->col = col;
 
4552
    xmlParseCharDataComplex(ctxt, cdata);
 
4553
}
 
4554
 
 
4555
/**
 
4556
 * xmlParseCharDataComplex:
 
4557
 * @ctxt:  an XML parser context
 
4558
 * @cdata:  int indicating whether we are within a CDATA section
 
4559
 *
 
4560
 * parse a CharData section.this is the fallback function
 
4561
 * of xmlParseCharData() when the parsing requires handling
 
4562
 * of non-ASCII characters.
 
4563
 */
 
4564
static void
 
4565
xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) {
 
4566
    xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE + 5];
 
4567
    int nbchar = 0;
 
4568
    int cur, l;
 
4569
    int count = 0;
 
4570
 
 
4571
    SHRINK;
 
4572
    GROW;
 
4573
    cur = CUR_CHAR(l);
 
4574
    while ((cur != '<') && /* checked */
 
4575
           (cur != '&') &&
 
4576
           (IS_CHAR(cur))) /* test also done in xmlCurrentChar() */ {
 
4577
        if ((cur == ']') && (NXT(1) == ']') &&
 
4578
            (NXT(2) == '>')) {
 
4579
            if (cdata) break;
 
4580
            else {
 
4581
                xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
 
4582
            }
 
4583
        }
 
4584
        COPY_BUF(l,buf,nbchar,cur);
 
4585
        if (nbchar >= XML_PARSER_BIG_BUFFER_SIZE) {
 
4586
            buf[nbchar] = 0;
 
4587
 
 
4588
            /*
 
4589
             * OK the segment is to be consumed as chars.
 
4590
             */
 
4591
            if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
 
4592
                if (areBlanks(ctxt, buf, nbchar, 0)) {
 
4593
                    if (ctxt->sax->ignorableWhitespace != NULL)
 
4594
                        ctxt->sax->ignorableWhitespace(ctxt->userData,
 
4595
                                                       buf, nbchar);
 
4596
                } else {
 
4597
                    if (ctxt->sax->characters != NULL)
 
4598
                        ctxt->sax->characters(ctxt->userData, buf, nbchar);
 
4599
                    if ((ctxt->sax->characters !=
 
4600
                         ctxt->sax->ignorableWhitespace) &&
 
4601
                        (*ctxt->space == -1))
 
4602
                        *ctxt->space = -2;
 
4603
                }
 
4604
            }
 
4605
            nbchar = 0;
 
4606
            /* something really bad happened in the SAX callback */
 
4607
            if (ctxt->instate != XML_PARSER_CONTENT)
 
4608
                return;
 
4609
        }
 
4610
        count++;
 
4611
        if (count > 50) {
 
4612
            GROW;
 
4613
            count = 0;
 
4614
            if (ctxt->instate == XML_PARSER_EOF)
 
4615
                return;
 
4616
        }
 
4617
        NEXTL(l);
 
4618
        cur = CUR_CHAR(l);
 
4619
    }
 
4620
    if (nbchar != 0) {
 
4621
        buf[nbchar] = 0;
 
4622
        /*
 
4623
         * OK the segment is to be consumed as chars.
 
4624
         */
 
4625
        if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
 
4626
            if (areBlanks(ctxt, buf, nbchar, 0)) {
 
4627
                if (ctxt->sax->ignorableWhitespace != NULL)
 
4628
                    ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
 
4629
            } else {
 
4630
                if (ctxt->sax->characters != NULL)
 
4631
                    ctxt->sax->characters(ctxt->userData, buf, nbchar);
 
4632
                if ((ctxt->sax->characters != ctxt->sax->ignorableWhitespace) &&
 
4633
                    (*ctxt->space == -1))
 
4634
                    *ctxt->space = -2;
 
4635
            }
 
4636
        }
 
4637
    }
 
4638
    if ((cur != 0) && (!IS_CHAR(cur))) {
 
4639
        /* Generate the error and skip the offending character */
 
4640
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
 
4641
                          "PCDATA invalid Char value %d\n",
 
4642
                          cur);
 
4643
        NEXTL(l);
 
4644
    }
 
4645
}
 
4646
 
 
4647
/**
 
4648
 * xmlParseExternalID:
 
4649
 * @ctxt:  an XML parser context
 
4650
 * @publicID:  a xmlChar** receiving PubidLiteral
 
4651
 * @strict: indicate whether we should restrict parsing to only
 
4652
 *          production [75], see NOTE below
 
4653
 *
 
4654
 * Parse an External ID or a Public ID
 
4655
 *
 
4656
 * NOTE: Productions [75] and [83] interact badly since [75] can generate
 
4657
 *       'PUBLIC' S PubidLiteral S SystemLiteral
 
4658
 *
 
4659
 * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
 
4660
 *                   | 'PUBLIC' S PubidLiteral S SystemLiteral
 
4661
 *
 
4662
 * [83] PublicID ::= 'PUBLIC' S PubidLiteral
 
4663
 *
 
4664
 * Returns the function returns SystemLiteral and in the second
 
4665
 *                case publicID receives PubidLiteral, is strict is off
 
4666
 *                it is possible to return NULL and have publicID set.
 
4667
 */
 
4668
 
 
4669
xmlChar *
 
4670
xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
 
4671
    xmlChar *URI = NULL;
 
4672
 
 
4673
    SHRINK;
 
4674
 
 
4675
    *publicID = NULL;
 
4676
    if (CMP6(CUR_PTR, 'S', 'Y', 'S', 'T', 'E', 'M')) {
 
4677
        SKIP(6);
 
4678
        if (!IS_BLANK_CH(CUR)) {
 
4679
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
4680
                           "Space required after 'SYSTEM'\n");
 
4681
        }
 
4682
        SKIP_BLANKS;
 
4683
        URI = xmlParseSystemLiteral(ctxt);
 
4684
        if (URI == NULL) {
 
4685
            xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
 
4686
        }
 
4687
    } else if (CMP6(CUR_PTR, 'P', 'U', 'B', 'L', 'I', 'C')) {
 
4688
        SKIP(6);
 
4689
        if (!IS_BLANK_CH(CUR)) {
 
4690
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
4691
                    "Space required after 'PUBLIC'\n");
 
4692
        }
 
4693
        SKIP_BLANKS;
 
4694
        *publicID = xmlParsePubidLiteral(ctxt);
 
4695
        if (*publicID == NULL) {
 
4696
            xmlFatalErr(ctxt, XML_ERR_PUBID_REQUIRED, NULL);
 
4697
        }
 
4698
        if (strict) {
 
4699
            /*
 
4700
             * We don't handle [83] so "S SystemLiteral" is required.
 
4701
             */
 
4702
            if (!IS_BLANK_CH(CUR)) {
 
4703
                xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
4704
                        "Space required after the Public Identifier\n");
 
4705
            }
 
4706
        } else {
 
4707
            /*
 
4708
             * We handle [83] so we return immediately, if
 
4709
             * "S SystemLiteral" is not detected. From a purely parsing
 
4710
             * point of view that's a nice mess.
 
4711
             */
 
4712
            const xmlChar *ptr;
 
4713
            GROW;
 
4714
 
 
4715
            ptr = CUR_PTR;
 
4716
            if (!IS_BLANK_CH(*ptr)) return(NULL);
 
4717
 
 
4718
            while (IS_BLANK_CH(*ptr)) ptr++; /* TODO: dangerous, fix ! */
 
4719
            if ((*ptr != '\'') && (*ptr != '"')) return(NULL);
 
4720
        }
 
4721
        SKIP_BLANKS;
 
4722
        URI = xmlParseSystemLiteral(ctxt);
 
4723
        if (URI == NULL) {
 
4724
            xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
 
4725
        }
 
4726
    }
 
4727
    return(URI);
 
4728
}
 
4729
 
 
4730
/**
 
4731
 * xmlParseCommentComplex:
 
4732
 * @ctxt:  an XML parser context
 
4733
 * @buf:  the already parsed part of the buffer
 
4734
 * @len:  number of bytes filles in the buffer
 
4735
 * @size:  allocated size of the buffer
 
4736
 *
 
4737
 * Skip an XML (SGML) comment <!-- .... -->
 
4738
 *  The spec says that "For compatibility, the string "--" (double-hyphen)
 
4739
 *  must not occur within comments. "
 
4740
 * This is the slow routine in case the accelerator for ascii didn't work
 
4741
 *
 
4742
 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
 
4743
 */
 
4744
static void
 
4745
xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
 
4746
                       size_t len, size_t size) {
 
4747
    int q, ql;
 
4748
    int r, rl;
 
4749
    int cur, l;
 
4750
    size_t count = 0;
 
4751
    int inputid;
 
4752
 
 
4753
    inputid = ctxt->input->id;
 
4754
 
 
4755
    if (buf == NULL) {
 
4756
        len = 0;
 
4757
        size = XML_PARSER_BUFFER_SIZE;
 
4758
        buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
4759
        if (buf == NULL) {
 
4760
            xmlErrMemory(ctxt, NULL);
 
4761
            return;
 
4762
        }
 
4763
    }
 
4764
    GROW;       /* Assure there's enough input data */
 
4765
    q = CUR_CHAR(ql);
 
4766
    if (q == 0)
 
4767
        goto not_terminated;
 
4768
    if (!IS_CHAR(q)) {
 
4769
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
 
4770
                          "xmlParseComment: invalid xmlChar value %d\n",
 
4771
                          q);
 
4772
        xmlFree (buf);
 
4773
        return;
 
4774
    }
 
4775
    NEXTL(ql);
 
4776
    r = CUR_CHAR(rl);
 
4777
    if (r == 0)
 
4778
        goto not_terminated;
 
4779
    if (!IS_CHAR(r)) {
 
4780
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
 
4781
                          "xmlParseComment: invalid xmlChar value %d\n",
 
4782
                          q);
 
4783
        xmlFree (buf);
 
4784
        return;
 
4785
    }
 
4786
    NEXTL(rl);
 
4787
    cur = CUR_CHAR(l);
 
4788
    if (cur == 0)
 
4789
        goto not_terminated;
 
4790
    while (IS_CHAR(cur) && /* checked */
 
4791
           ((cur != '>') ||
 
4792
            (r != '-') || (q != '-'))) {
 
4793
        if ((r == '-') && (q == '-')) {
 
4794
            xmlFatalErr(ctxt, XML_ERR_HYPHEN_IN_COMMENT, NULL);
 
4795
        }
 
4796
        if ((len > XML_MAX_TEXT_LENGTH) &&
 
4797
            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
4798
            xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
 
4799
                         "Comment too big found", NULL);
 
4800
            xmlFree (buf);
 
4801
            return;
 
4802
        }
 
4803
        if (len + 5 >= size) {
 
4804
            xmlChar *new_buf;
 
4805
            size_t new_size;
 
4806
 
 
4807
            new_size = size * 2;
 
4808
            new_buf = (xmlChar *) xmlRealloc(buf, new_size);
 
4809
            if (new_buf == NULL) {
 
4810
                xmlFree (buf);
 
4811
                xmlErrMemory(ctxt, NULL);
 
4812
                return;
 
4813
            }
 
4814
            buf = new_buf;
 
4815
            size = new_size;
 
4816
        }
 
4817
        COPY_BUF(ql,buf,len,q);
 
4818
        q = r;
 
4819
        ql = rl;
 
4820
        r = cur;
 
4821
        rl = l;
 
4822
 
 
4823
        count++;
 
4824
        if (count > 50) {
 
4825
            GROW;
 
4826
            count = 0;
 
4827
            if (ctxt->instate == XML_PARSER_EOF) {
 
4828
                xmlFree(buf);
 
4829
                return;
 
4830
            }
 
4831
        }
 
4832
        NEXTL(l);
 
4833
        cur = CUR_CHAR(l);
 
4834
        if (cur == 0) {
 
4835
            SHRINK;
 
4836
            GROW;
 
4837
            cur = CUR_CHAR(l);
 
4838
        }
 
4839
    }
 
4840
    buf[len] = 0;
 
4841
    if (cur == 0) {
 
4842
        xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
 
4843
                             "Comment not terminated \n<!--%.50s\n", buf);
 
4844
    } else if (!IS_CHAR(cur)) {
 
4845
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
 
4846
                          "xmlParseComment: invalid xmlChar value %d\n",
 
4847
                          cur);
 
4848
    } else {
 
4849
        if (inputid != ctxt->input->id) {
 
4850
            xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
4851
                "Comment doesn't start and stop in the same entity\n");
 
4852
        }
 
4853
        NEXT;
 
4854
        if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
 
4855
            (!ctxt->disableSAX))
 
4856
            ctxt->sax->comment(ctxt->userData, buf);
 
4857
    }
 
4858
    xmlFree(buf);
 
4859
    return;
 
4860
not_terminated:
 
4861
    xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
 
4862
                         "Comment not terminated\n", NULL);
 
4863
    xmlFree(buf);
 
4864
    return;
 
4865
}
 
4866
 
 
4867
/**
 
4868
 * xmlParseComment:
 
4869
 * @ctxt:  an XML parser context
 
4870
 *
 
4871
 * Skip an XML (SGML) comment <!-- .... -->
 
4872
 *  The spec says that "For compatibility, the string "--" (double-hyphen)
 
4873
 *  must not occur within comments. "
 
4874
 *
 
4875
 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
 
4876
 */
 
4877
void
 
4878
xmlParseComment(xmlParserCtxtPtr ctxt) {
 
4879
    xmlChar *buf = NULL;
 
4880
    size_t size = XML_PARSER_BUFFER_SIZE;
 
4881
    size_t len = 0;
 
4882
    xmlParserInputState state;
 
4883
    const xmlChar *in;
 
4884
    size_t nbchar = 0;
 
4885
    int ccol;
 
4886
    int inputid;
 
4887
 
 
4888
    /*
 
4889
     * Check that there is a comment right here.
 
4890
     */
 
4891
    if ((RAW != '<') || (NXT(1) != '!') ||
 
4892
        (NXT(2) != '-') || (NXT(3) != '-')) return;
 
4893
    state = ctxt->instate;
 
4894
    ctxt->instate = XML_PARSER_COMMENT;
 
4895
    inputid = ctxt->input->id;
 
4896
    SKIP(4);
 
4897
    SHRINK;
 
4898
    GROW;
 
4899
 
 
4900
    /*
 
4901
     * Accelerated common case where input don't need to be
 
4902
     * modified before passing it to the handler.
 
4903
     */
 
4904
    in = ctxt->input->cur;
 
4905
    do {
 
4906
        if (*in == 0xA) {
 
4907
            do {
 
4908
                ctxt->input->line++; ctxt->input->col = 1;
 
4909
                in++;
 
4910
            } while (*in == 0xA);
 
4911
        }
 
4912
get_more:
 
4913
        ccol = ctxt->input->col;
 
4914
        while (((*in > '-') && (*in <= 0x7F)) ||
 
4915
               ((*in >= 0x20) && (*in < '-')) ||
 
4916
               (*in == 0x09)) {
 
4917
                    in++;
 
4918
                    ccol++;
 
4919
        }
 
4920
        ctxt->input->col = ccol;
 
4921
        if (*in == 0xA) {
 
4922
            do {
 
4923
                ctxt->input->line++; ctxt->input->col = 1;
 
4924
                in++;
 
4925
            } while (*in == 0xA);
 
4926
            goto get_more;
 
4927
        }
 
4928
        nbchar = in - ctxt->input->cur;
 
4929
        /*
 
4930
         * save current set of data
 
4931
         */
 
4932
        if (nbchar > 0) {
 
4933
            if ((ctxt->sax != NULL) &&
 
4934
                (ctxt->sax->comment != NULL)) {
 
4935
                if (buf == NULL) {
 
4936
                    if ((*in == '-') && (in[1] == '-'))
 
4937
                        size = nbchar + 1;
 
4938
                    else
 
4939
                        size = XML_PARSER_BUFFER_SIZE + nbchar;
 
4940
                    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
4941
                    if (buf == NULL) {
 
4942
                        xmlErrMemory(ctxt, NULL);
 
4943
                        ctxt->instate = state;
 
4944
                        return;
 
4945
                    }
 
4946
                    len = 0;
 
4947
                } else if (len + nbchar + 1 >= size) {
 
4948
                    xmlChar *new_buf;
 
4949
                    size  += len + nbchar + XML_PARSER_BUFFER_SIZE;
 
4950
                    new_buf = (xmlChar *) xmlRealloc(buf,
 
4951
                                                     size * sizeof(xmlChar));
 
4952
                    if (new_buf == NULL) {
 
4953
                        xmlFree (buf);
 
4954
                        xmlErrMemory(ctxt, NULL);
 
4955
                        ctxt->instate = state;
 
4956
                        return;
 
4957
                    }
 
4958
                    buf = new_buf;
 
4959
                }
 
4960
                memcpy(&buf[len], ctxt->input->cur, nbchar);
 
4961
                len += nbchar;
 
4962
                buf[len] = 0;
 
4963
            }
 
4964
        }
 
4965
        if ((len > XML_MAX_TEXT_LENGTH) &&
 
4966
            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
4967
            xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
 
4968
                         "Comment too big found", NULL);
 
4969
            xmlFree (buf);
 
4970
            return;
 
4971
        }
 
4972
        ctxt->input->cur = in;
 
4973
        if (*in == 0xA) {
 
4974
            in++;
 
4975
            ctxt->input->line++; ctxt->input->col = 1;
 
4976
        }
 
4977
        if (*in == 0xD) {
 
4978
            in++;
 
4979
            if (*in == 0xA) {
 
4980
                ctxt->input->cur = in;
 
4981
                in++;
 
4982
                ctxt->input->line++; ctxt->input->col = 1;
 
4983
                continue; /* while */
 
4984
            }
 
4985
            in--;
 
4986
        }
 
4987
        SHRINK;
 
4988
        GROW;
 
4989
        if (ctxt->instate == XML_PARSER_EOF) {
 
4990
            xmlFree(buf);
 
4991
            return;
 
4992
        }
 
4993
        in = ctxt->input->cur;
 
4994
        if (*in == '-') {
 
4995
            if (in[1] == '-') {
 
4996
                if (in[2] == '>') {
 
4997
                    if (ctxt->input->id != inputid) {
 
4998
                        xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
4999
                        "comment doesn't start and stop in the same entity\n");
 
5000
                    }
 
5001
                    SKIP(3);
 
5002
                    if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
 
5003
                        (!ctxt->disableSAX)) {
 
5004
                        if (buf != NULL)
 
5005
                            ctxt->sax->comment(ctxt->userData, buf);
 
5006
                        else
 
5007
                            ctxt->sax->comment(ctxt->userData, BAD_CAST "");
 
5008
                    }
 
5009
                    if (buf != NULL)
 
5010
                        xmlFree(buf);
 
5011
                    if (ctxt->instate != XML_PARSER_EOF)
 
5012
                        ctxt->instate = state;
 
5013
                    return;
 
5014
                }
 
5015
                if (buf != NULL) {
 
5016
                    xmlFatalErrMsgStr(ctxt, XML_ERR_HYPHEN_IN_COMMENT,
 
5017
                                      "Double hyphen within comment: "
 
5018
                                      "<!--%.50s\n",
 
5019
                                      buf);
 
5020
                } else
 
5021
                    xmlFatalErrMsgStr(ctxt, XML_ERR_HYPHEN_IN_COMMENT,
 
5022
                                      "Double hyphen within comment\n", NULL);
 
5023
                in++;
 
5024
                ctxt->input->col++;
 
5025
            }
 
5026
            in++;
 
5027
            ctxt->input->col++;
 
5028
            goto get_more;
 
5029
        }
 
5030
    } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09));
 
5031
    xmlParseCommentComplex(ctxt, buf, len, size);
 
5032
    ctxt->instate = state;
 
5033
    return;
 
5034
}
 
5035
 
 
5036
 
 
5037
/**
 
5038
 * xmlParsePITarget:
 
5039
 * @ctxt:  an XML parser context
 
5040
 *
 
5041
 * parse the name of a PI
 
5042
 *
 
5043
 * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
 
5044
 *
 
5045
 * Returns the PITarget name or NULL
 
5046
 */
 
5047
 
 
5048
const xmlChar *
 
5049
xmlParsePITarget(xmlParserCtxtPtr ctxt) {
 
5050
    const xmlChar *name;
 
5051
 
 
5052
    name = xmlParseName(ctxt);
 
5053
    if ((name != NULL) &&
 
5054
        ((name[0] == 'x') || (name[0] == 'X')) &&
 
5055
        ((name[1] == 'm') || (name[1] == 'M')) &&
 
5056
        ((name[2] == 'l') || (name[2] == 'L'))) {
 
5057
        int i;
 
5058
        if ((name[0] == 'x') && (name[1] == 'm') &&
 
5059
            (name[2] == 'l') && (name[3] == 0)) {
 
5060
            xmlFatalErrMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
 
5061
                 "XML declaration allowed only at the start of the document\n");
 
5062
            return(name);
 
5063
        } else if (name[3] == 0) {
 
5064
            xmlFatalErr(ctxt, XML_ERR_RESERVED_XML_NAME, NULL);
 
5065
            return(name);
 
5066
        }
 
5067
        for (i = 0;;i++) {
 
5068
            if (xmlW3CPIs[i] == NULL) break;
 
5069
            if (xmlStrEqual(name, (const xmlChar *)xmlW3CPIs[i]))
 
5070
                return(name);
 
5071
        }
 
5072
        xmlWarningMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
 
5073
                      "xmlParsePITarget: invalid name prefix 'xml'\n",
 
5074
                      NULL, NULL);
 
5075
    }
 
5076
    if ((name != NULL) && (xmlStrchr(name, ':') != NULL)) {
 
5077
        xmlNsErr(ctxt, XML_NS_ERR_COLON,
 
5078
                 "colon are forbidden from PI names '%s'\n", name, NULL, NULL);
 
5079
    }
 
5080
    return(name);
 
5081
}
 
5082
 
 
5083
#ifdef LIBXML_CATALOG_ENABLED
 
5084
/**
 
5085
 * xmlParseCatalogPI:
 
5086
 * @ctxt:  an XML parser context
 
5087
 * @catalog:  the PI value string
 
5088
 *
 
5089
 * parse an XML Catalog Processing Instruction.
 
5090
 *
 
5091
 * <?oasis-xml-catalog catalog="http://example.com/catalog.xml"?>
 
5092
 *
 
5093
 * Occurs only if allowed by the user and if happening in the Misc
 
5094
 * part of the document before any doctype informations
 
5095
 * This will add the given catalog to the parsing context in order
 
5096
 * to be used if there is a resolution need further down in the document
 
5097
 */
 
5098
 
 
5099
static void
 
5100
xmlParseCatalogPI(xmlParserCtxtPtr ctxt, const xmlChar *catalog) {
 
5101
    xmlChar *URL = NULL;
 
5102
    const xmlChar *tmp, *base;
 
5103
    xmlChar marker;
 
5104
 
 
5105
    tmp = catalog;
 
5106
    while (IS_BLANK_CH(*tmp)) tmp++;
 
5107
    if (xmlStrncmp(tmp, BAD_CAST"catalog", 7))
 
5108
        goto error;
 
5109
    tmp += 7;
 
5110
    while (IS_BLANK_CH(*tmp)) tmp++;
 
5111
    if (*tmp != '=') {
 
5112
        return;
 
5113
    }
 
5114
    tmp++;
 
5115
    while (IS_BLANK_CH(*tmp)) tmp++;
 
5116
    marker = *tmp;
 
5117
    if ((marker != '\'') && (marker != '"'))
 
5118
        goto error;
 
5119
    tmp++;
 
5120
    base = tmp;
 
5121
    while ((*tmp != 0) && (*tmp != marker)) tmp++;
 
5122
    if (*tmp == 0)
 
5123
        goto error;
 
5124
    URL = xmlStrndup(base, tmp - base);
 
5125
    tmp++;
 
5126
    while (IS_BLANK_CH(*tmp)) tmp++;
 
5127
    if (*tmp != 0)
 
5128
        goto error;
 
5129
 
 
5130
    if (URL != NULL) {
 
5131
        ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
 
5132
        xmlFree(URL);
 
5133
    }
 
5134
    return;
 
5135
 
 
5136
error:
 
5137
    xmlWarningMsg(ctxt, XML_WAR_CATALOG_PI,
 
5138
                  "Catalog PI syntax error: %s\n",
 
5139
                  catalog, NULL);
 
5140
    if (URL != NULL)
 
5141
        xmlFree(URL);
 
5142
}
 
5143
#endif
 
5144
 
 
5145
/**
 
5146
 * xmlParsePI:
 
5147
 * @ctxt:  an XML parser context
 
5148
 *
 
5149
 * parse an XML Processing Instruction.
 
5150
 *
 
5151
 * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
 
5152
 *
 
5153
 * The processing is transfered to SAX once parsed.
 
5154
 */
 
5155
 
 
5156
void
 
5157
xmlParsePI(xmlParserCtxtPtr ctxt) {
 
5158
    xmlChar *buf = NULL;
 
5159
    size_t len = 0;
 
5160
    size_t size = XML_PARSER_BUFFER_SIZE;
 
5161
    int cur, l;
 
5162
    const xmlChar *target;
 
5163
    xmlParserInputState state;
 
5164
    int count = 0;
 
5165
 
 
5166
    if ((RAW == '<') && (NXT(1) == '?')) {
 
5167
        xmlParserInputPtr input = ctxt->input;
 
5168
        state = ctxt->instate;
 
5169
        ctxt->instate = XML_PARSER_PI;
 
5170
        /*
 
5171
         * this is a Processing Instruction.
 
5172
         */
 
5173
        SKIP(2);
 
5174
        SHRINK;
 
5175
 
 
5176
        /*
 
5177
         * Parse the target name and check for special support like
 
5178
         * namespace.
 
5179
         */
 
5180
        target = xmlParsePITarget(ctxt);
 
5181
        if (target != NULL) {
 
5182
            if ((RAW == '?') && (NXT(1) == '>')) {
 
5183
                if (input != ctxt->input) {
 
5184
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
5185
            "PI declaration doesn't start and stop in the same entity\n");
 
5186
                }
 
5187
                SKIP(2);
 
5188
 
 
5189
                /*
 
5190
                 * SAX: PI detected.
 
5191
                 */
 
5192
                if ((ctxt->sax) && (!ctxt->disableSAX) &&
 
5193
                    (ctxt->sax->processingInstruction != NULL))
 
5194
                    ctxt->sax->processingInstruction(ctxt->userData,
 
5195
                                                     target, NULL);
 
5196
                if (ctxt->instate != XML_PARSER_EOF)
 
5197
                    ctxt->instate = state;
 
5198
                return;
 
5199
            }
 
5200
            buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
5201
            if (buf == NULL) {
 
5202
                xmlErrMemory(ctxt, NULL);
 
5203
                ctxt->instate = state;
 
5204
                return;
 
5205
            }
 
5206
            cur = CUR;
 
5207
            if (!IS_BLANK(cur)) {
 
5208
                xmlFatalErrMsgStr(ctxt, XML_ERR_SPACE_REQUIRED,
 
5209
                          "ParsePI: PI %s space expected\n", target);
 
5210
            }
 
5211
            SKIP_BLANKS;
 
5212
            cur = CUR_CHAR(l);
 
5213
            while (IS_CHAR(cur) && /* checked */
 
5214
                   ((cur != '?') || (NXT(1) != '>'))) {
 
5215
                if (len + 5 >= size) {
 
5216
                    xmlChar *tmp;
 
5217
                    size_t new_size = size * 2;
 
5218
                    tmp = (xmlChar *) xmlRealloc(buf, new_size);
 
5219
                    if (tmp == NULL) {
 
5220
                        xmlErrMemory(ctxt, NULL);
 
5221
                        xmlFree(buf);
 
5222
                        ctxt->instate = state;
 
5223
                        return;
 
5224
                    }
 
5225
                    buf = tmp;
 
5226
                    size = new_size;
 
5227
                }
 
5228
                count++;
 
5229
                if (count > 50) {
 
5230
                    GROW;
 
5231
                    if (ctxt->instate == XML_PARSER_EOF) {
 
5232
                        xmlFree(buf);
 
5233
                        return;
 
5234
                    }
 
5235
                    count = 0;
 
5236
                    if ((len > XML_MAX_TEXT_LENGTH) &&
 
5237
                        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
5238
                        xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
 
5239
                                          "PI %s too big found", target);
 
5240
                        xmlFree(buf);
 
5241
                        ctxt->instate = state;
 
5242
                        return;
 
5243
                    }
 
5244
                }
 
5245
                COPY_BUF(l,buf,len,cur);
 
5246
                NEXTL(l);
 
5247
                cur = CUR_CHAR(l);
 
5248
                if (cur == 0) {
 
5249
                    SHRINK;
 
5250
                    GROW;
 
5251
                    cur = CUR_CHAR(l);
 
5252
                }
 
5253
            }
 
5254
            if ((len > XML_MAX_TEXT_LENGTH) &&
 
5255
                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
5256
                xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
 
5257
                                  "PI %s too big found", target);
 
5258
                xmlFree(buf);
 
5259
                ctxt->instate = state;
 
5260
                return;
 
5261
            }
 
5262
            buf[len] = 0;
 
5263
            if (cur != '?') {
 
5264
                xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
 
5265
                      "ParsePI: PI %s never end ...\n", target);
 
5266
            } else {
 
5267
                if (input != ctxt->input) {
 
5268
                    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5269
            "PI declaration doesn't start and stop in the same entity\n");
 
5270
                }
 
5271
                SKIP(2);
 
5272
 
 
5273
#ifdef LIBXML_CATALOG_ENABLED
 
5274
                if (((state == XML_PARSER_MISC) ||
 
5275
                     (state == XML_PARSER_START)) &&
 
5276
                    (xmlStrEqual(target, XML_CATALOG_PI))) {
 
5277
                    xmlCatalogAllow allow = xmlCatalogGetDefaults();
 
5278
                    if ((allow == XML_CATA_ALLOW_DOCUMENT) ||
 
5279
                        (allow == XML_CATA_ALLOW_ALL))
 
5280
                        xmlParseCatalogPI(ctxt, buf);
 
5281
                }
 
5282
#endif
 
5283
 
 
5284
 
 
5285
                /*
 
5286
                 * SAX: PI detected.
 
5287
                 */
 
5288
                if ((ctxt->sax) && (!ctxt->disableSAX) &&
 
5289
                    (ctxt->sax->processingInstruction != NULL))
 
5290
                    ctxt->sax->processingInstruction(ctxt->userData,
 
5291
                                                     target, buf);
 
5292
            }
 
5293
            xmlFree(buf);
 
5294
        } else {
 
5295
            xmlFatalErr(ctxt, XML_ERR_PI_NOT_STARTED, NULL);
 
5296
        }
 
5297
        if (ctxt->instate != XML_PARSER_EOF)
 
5298
            ctxt->instate = state;
 
5299
    }
 
5300
}
 
5301
 
 
5302
/**
 
5303
 * xmlParseNotationDecl:
 
5304
 * @ctxt:  an XML parser context
 
5305
 *
 
5306
 * parse a notation declaration
 
5307
 *
 
5308
 * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID |  PublicID) S? '>'
 
5309
 *
 
5310
 * Hence there is actually 3 choices:
 
5311
 *     'PUBLIC' S PubidLiteral
 
5312
 *     'PUBLIC' S PubidLiteral S SystemLiteral
 
5313
 * and 'SYSTEM' S SystemLiteral
 
5314
 *
 
5315
 * See the NOTE on xmlParseExternalID().
 
5316
 */
 
5317
 
 
5318
void
 
5319
xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
 
5320
    const xmlChar *name;
 
5321
    xmlChar *Pubid;
 
5322
    xmlChar *Systemid;
 
5323
 
 
5324
    if (CMP10(CUR_PTR, '<', '!', 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
 
5325
        xmlParserInputPtr input = ctxt->input;
 
5326
        SHRINK;
 
5327
        SKIP(10);
 
5328
        if (!IS_BLANK_CH(CUR)) {
 
5329
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5330
                           "Space required after '<!NOTATION'\n");
 
5331
            return;
 
5332
        }
 
5333
        SKIP_BLANKS;
 
5334
 
 
5335
        name = xmlParseName(ctxt);
 
5336
        if (name == NULL) {
 
5337
            xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
 
5338
            return;
 
5339
        }
 
5340
        if (!IS_BLANK_CH(CUR)) {
 
5341
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5342
                     "Space required after the NOTATION name'\n");
 
5343
            return;
 
5344
        }
 
5345
        if (xmlStrchr(name, ':') != NULL) {
 
5346
            xmlNsErr(ctxt, XML_NS_ERR_COLON,
 
5347
                     "colon are forbidden from notation names '%s'\n",
 
5348
                     name, NULL, NULL);
 
5349
        }
 
5350
        SKIP_BLANKS;
 
5351
 
 
5352
        /*
 
5353
         * Parse the IDs.
 
5354
         */
 
5355
        Systemid = xmlParseExternalID(ctxt, &Pubid, 0);
 
5356
        SKIP_BLANKS;
 
5357
 
 
5358
        if (RAW == '>') {
 
5359
            if (input != ctxt->input) {
 
5360
                xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5361
        "Notation declaration doesn't start and stop in the same entity\n");
 
5362
            }
 
5363
            NEXT;
 
5364
            if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
 
5365
                (ctxt->sax->notationDecl != NULL))
 
5366
                ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
 
5367
        } else {
 
5368
            xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
 
5369
        }
 
5370
        if (Systemid != NULL) xmlFree(Systemid);
 
5371
        if (Pubid != NULL) xmlFree(Pubid);
 
5372
    }
 
5373
}
 
5374
 
 
5375
/**
 
5376
 * xmlParseEntityDecl:
 
5377
 * @ctxt:  an XML parser context
 
5378
 *
 
5379
 * parse <!ENTITY declarations
 
5380
 *
 
5381
 * [70] EntityDecl ::= GEDecl | PEDecl
 
5382
 *
 
5383
 * [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
 
5384
 *
 
5385
 * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
 
5386
 *
 
5387
 * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
 
5388
 *
 
5389
 * [74] PEDef ::= EntityValue | ExternalID
 
5390
 *
 
5391
 * [76] NDataDecl ::= S 'NDATA' S Name
 
5392
 *
 
5393
 * [ VC: Notation Declared ]
 
5394
 * The Name must match the declared name of a notation.
 
5395
 */
 
5396
 
 
5397
void
 
5398
xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
 
5399
    const xmlChar *name = NULL;
 
5400
    xmlChar *value = NULL;
 
5401
    xmlChar *URI = NULL, *literal = NULL;
 
5402
    const xmlChar *ndata = NULL;
 
5403
    int isParameter = 0;
 
5404
    xmlChar *orig = NULL;
 
5405
    int skipped;
 
5406
 
 
5407
    /* GROW; done in the caller */
 
5408
    if (CMP8(CUR_PTR, '<', '!', 'E', 'N', 'T', 'I', 'T', 'Y')) {
 
5409
        xmlParserInputPtr input = ctxt->input;
 
5410
        SHRINK;
 
5411
        SKIP(8);
 
5412
        skipped = SKIP_BLANKS;
 
5413
        if (skipped == 0) {
 
5414
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5415
                           "Space required after '<!ENTITY'\n");
 
5416
        }
 
5417
 
 
5418
        if (RAW == '%') {
 
5419
            NEXT;
 
5420
            skipped = SKIP_BLANKS;
 
5421
            if (skipped == 0) {
 
5422
                xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5423
                               "Space required after '%'\n");
 
5424
            }
 
5425
            isParameter = 1;
 
5426
        }
 
5427
 
 
5428
        name = xmlParseName(ctxt);
 
5429
        if (name == NULL) {
 
5430
            xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
5431
                           "xmlParseEntityDecl: no name\n");
 
5432
            return;
 
5433
        }
 
5434
        if (xmlStrchr(name, ':') != NULL) {
 
5435
            xmlNsErr(ctxt, XML_NS_ERR_COLON,
 
5436
                     "colon are forbidden from entities names '%s'\n",
 
5437
                     name, NULL, NULL);
 
5438
        }
 
5439
        skipped = SKIP_BLANKS;
 
5440
        if (skipped == 0) {
 
5441
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5442
                           "Space required after the entity name\n");
 
5443
        }
 
5444
 
 
5445
        ctxt->instate = XML_PARSER_ENTITY_DECL;
 
5446
        /*
 
5447
         * handle the various case of definitions...
 
5448
         */
 
5449
        if (isParameter) {
 
5450
            if ((RAW == '"') || (RAW == '\'')) {
 
5451
                value = xmlParseEntityValue(ctxt, &orig);
 
5452
                if (value) {
 
5453
                    if ((ctxt->sax != NULL) &&
 
5454
                        (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
 
5455
                        ctxt->sax->entityDecl(ctxt->userData, name,
 
5456
                                    XML_INTERNAL_PARAMETER_ENTITY,
 
5457
                                    NULL, NULL, value);
 
5458
                }
 
5459
            } else {
 
5460
                URI = xmlParseExternalID(ctxt, &literal, 1);
 
5461
                if ((URI == NULL) && (literal == NULL)) {
 
5462
                    xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
 
5463
                }
 
5464
                if (URI) {
 
5465
                    xmlURIPtr uri;
 
5466
 
 
5467
                    uri = xmlParseURI((const char *) URI);
 
5468
                    if (uri == NULL) {
 
5469
                        xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
 
5470
                                     "Invalid URI: %s\n", URI);
 
5471
                        /*
 
5472
                         * This really ought to be a well formedness error
 
5473
                         * but the XML Core WG decided otherwise c.f. issue
 
5474
                         * E26 of the XML erratas.
 
5475
                         */
 
5476
                    } else {
 
5477
                        if (uri->fragment != NULL) {
 
5478
                            /*
 
5479
                             * Okay this is foolish to block those but not
 
5480
                             * invalid URIs.
 
5481
                             */
 
5482
                            xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
 
5483
                        } else {
 
5484
                            if ((ctxt->sax != NULL) &&
 
5485
                                (!ctxt->disableSAX) &&
 
5486
                                (ctxt->sax->entityDecl != NULL))
 
5487
                                ctxt->sax->entityDecl(ctxt->userData, name,
 
5488
                                            XML_EXTERNAL_PARAMETER_ENTITY,
 
5489
                                            literal, URI, NULL);
 
5490
                        }
 
5491
                        xmlFreeURI(uri);
 
5492
                    }
 
5493
                }
 
5494
            }
 
5495
        } else {
 
5496
            if ((RAW == '"') || (RAW == '\'')) {
 
5497
                value = xmlParseEntityValue(ctxt, &orig);
 
5498
                if ((ctxt->sax != NULL) &&
 
5499
                    (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
 
5500
                    ctxt->sax->entityDecl(ctxt->userData, name,
 
5501
                                XML_INTERNAL_GENERAL_ENTITY,
 
5502
                                NULL, NULL, value);
 
5503
                /*
 
5504
                 * For expat compatibility in SAX mode.
 
5505
                 */
 
5506
                if ((ctxt->myDoc == NULL) ||
 
5507
                    (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
 
5508
                    if (ctxt->myDoc == NULL) {
 
5509
                        ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
 
5510
                        if (ctxt->myDoc == NULL) {
 
5511
                            xmlErrMemory(ctxt, "New Doc failed");
 
5512
                            return;
 
5513
                        }
 
5514
                        ctxt->myDoc->properties = XML_DOC_INTERNAL;
 
5515
                    }
 
5516
                    if (ctxt->myDoc->intSubset == NULL)
 
5517
                        ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
 
5518
                                            BAD_CAST "fake", NULL, NULL);
 
5519
 
 
5520
                    xmlSAX2EntityDecl(ctxt, name, XML_INTERNAL_GENERAL_ENTITY,
 
5521
                                      NULL, NULL, value);
 
5522
                }
 
5523
            } else {
 
5524
                URI = xmlParseExternalID(ctxt, &literal, 1);
 
5525
                if ((URI == NULL) && (literal == NULL)) {
 
5526
                    xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
 
5527
                }
 
5528
                if (URI) {
 
5529
                    xmlURIPtr uri;
 
5530
 
 
5531
                    uri = xmlParseURI((const char *)URI);
 
5532
                    if (uri == NULL) {
 
5533
                        xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
 
5534
                                     "Invalid URI: %s\n", URI);
 
5535
                        /*
 
5536
                         * This really ought to be a well formedness error
 
5537
                         * but the XML Core WG decided otherwise c.f. issue
 
5538
                         * E26 of the XML erratas.
 
5539
                         */
 
5540
                    } else {
 
5541
                        if (uri->fragment != NULL) {
 
5542
                            /*
 
5543
                             * Okay this is foolish to block those but not
 
5544
                             * invalid URIs.
 
5545
                             */
 
5546
                            xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
 
5547
                        }
 
5548
                        xmlFreeURI(uri);
 
5549
                    }
 
5550
                }
 
5551
                if ((RAW != '>') && (!IS_BLANK_CH(CUR))) {
 
5552
                    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5553
                                   "Space required before 'NDATA'\n");
 
5554
                }
 
5555
                SKIP_BLANKS;
 
5556
                if (CMP5(CUR_PTR, 'N', 'D', 'A', 'T', 'A')) {
 
5557
                    SKIP(5);
 
5558
                    if (!IS_BLANK_CH(CUR)) {
 
5559
                        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5560
                                       "Space required after 'NDATA'\n");
 
5561
                    }
 
5562
                    SKIP_BLANKS;
 
5563
                    ndata = xmlParseName(ctxt);
 
5564
                    if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
 
5565
                        (ctxt->sax->unparsedEntityDecl != NULL))
 
5566
                        ctxt->sax->unparsedEntityDecl(ctxt->userData, name,
 
5567
                                    literal, URI, ndata);
 
5568
                } else {
 
5569
                    if ((ctxt->sax != NULL) &&
 
5570
                        (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
 
5571
                        ctxt->sax->entityDecl(ctxt->userData, name,
 
5572
                                    XML_EXTERNAL_GENERAL_PARSED_ENTITY,
 
5573
                                    literal, URI, NULL);
 
5574
                    /*
 
5575
                     * For expat compatibility in SAX mode.
 
5576
                     * assuming the entity repalcement was asked for
 
5577
                     */
 
5578
                    if ((ctxt->replaceEntities != 0) &&
 
5579
                        ((ctxt->myDoc == NULL) ||
 
5580
                        (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE)))) {
 
5581
                        if (ctxt->myDoc == NULL) {
 
5582
                            ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
 
5583
                            if (ctxt->myDoc == NULL) {
 
5584
                                xmlErrMemory(ctxt, "New Doc failed");
 
5585
                                return;
 
5586
                            }
 
5587
                            ctxt->myDoc->properties = XML_DOC_INTERNAL;
 
5588
                        }
 
5589
 
 
5590
                        if (ctxt->myDoc->intSubset == NULL)
 
5591
                            ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
 
5592
                                                BAD_CAST "fake", NULL, NULL);
 
5593
                        xmlSAX2EntityDecl(ctxt, name,
 
5594
                                          XML_EXTERNAL_GENERAL_PARSED_ENTITY,
 
5595
                                          literal, URI, NULL);
 
5596
                    }
 
5597
                }
 
5598
            }
 
5599
        }
 
5600
        if (ctxt->instate == XML_PARSER_EOF)
 
5601
            return;
 
5602
        SKIP_BLANKS;
 
5603
        if (RAW != '>') {
 
5604
            xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
 
5605
                    "xmlParseEntityDecl: entity %s not terminated\n", name);
 
5606
        } else {
 
5607
            if (input != ctxt->input) {
 
5608
                xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
5609
        "Entity declaration doesn't start and stop in the same entity\n");
 
5610
            }
 
5611
            NEXT;
 
5612
        }
 
5613
        if (orig != NULL) {
 
5614
            /*
 
5615
             * Ugly mechanism to save the raw entity value.
 
5616
             */
 
5617
            xmlEntityPtr cur = NULL;
 
5618
 
 
5619
            if (isParameter) {
 
5620
                if ((ctxt->sax != NULL) &&
 
5621
                    (ctxt->sax->getParameterEntity != NULL))
 
5622
                    cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
 
5623
            } else {
 
5624
                if ((ctxt->sax != NULL) &&
 
5625
                    (ctxt->sax->getEntity != NULL))
 
5626
                    cur = ctxt->sax->getEntity(ctxt->userData, name);
 
5627
                if ((cur == NULL) && (ctxt->userData==ctxt)) {
 
5628
                    cur = xmlSAX2GetEntity(ctxt, name);
 
5629
                }
 
5630
            }
 
5631
            if (cur != NULL) {
 
5632
                if (cur->orig != NULL)
 
5633
                    xmlFree(orig);
 
5634
                else
 
5635
                    cur->orig = orig;
 
5636
            } else
 
5637
                xmlFree(orig);
 
5638
        }
 
5639
        if (value != NULL) xmlFree(value);
 
5640
        if (URI != NULL) xmlFree(URI);
 
5641
        if (literal != NULL) xmlFree(literal);
 
5642
    }
 
5643
}
 
5644
 
 
5645
/**
 
5646
 * xmlParseDefaultDecl:
 
5647
 * @ctxt:  an XML parser context
 
5648
 * @value:  Receive a possible fixed default value for the attribute
 
5649
 *
 
5650
 * Parse an attribute default declaration
 
5651
 *
 
5652
 * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
 
5653
 *
 
5654
 * [ VC: Required Attribute ]
 
5655
 * if the default declaration is the keyword #REQUIRED, then the
 
5656
 * attribute must be specified for all elements of the type in the
 
5657
 * attribute-list declaration.
 
5658
 *
 
5659
 * [ VC: Attribute Default Legal ]
 
5660
 * The declared default value must meet the lexical constraints of
 
5661
 * the declared attribute type c.f. xmlValidateAttributeDecl()
 
5662
 *
 
5663
 * [ VC: Fixed Attribute Default ]
 
5664
 * if an attribute has a default value declared with the #FIXED
 
5665
 * keyword, instances of that attribute must match the default value.
 
5666
 *
 
5667
 * [ WFC: No < in Attribute Values ]
 
5668
 * handled in xmlParseAttValue()
 
5669
 *
 
5670
 * returns: XML_ATTRIBUTE_NONE, XML_ATTRIBUTE_REQUIRED, XML_ATTRIBUTE_IMPLIED
 
5671
 *          or XML_ATTRIBUTE_FIXED.
 
5672
 */
 
5673
 
 
5674
int
 
5675
xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
 
5676
    int val;
 
5677
    xmlChar *ret;
 
5678
 
 
5679
    *value = NULL;
 
5680
    if (CMP9(CUR_PTR, '#', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D')) {
 
5681
        SKIP(9);
 
5682
        return(XML_ATTRIBUTE_REQUIRED);
 
5683
    }
 
5684
    if (CMP8(CUR_PTR, '#', 'I', 'M', 'P', 'L', 'I', 'E', 'D')) {
 
5685
        SKIP(8);
 
5686
        return(XML_ATTRIBUTE_IMPLIED);
 
5687
    }
 
5688
    val = XML_ATTRIBUTE_NONE;
 
5689
    if (CMP6(CUR_PTR, '#', 'F', 'I', 'X', 'E', 'D')) {
 
5690
        SKIP(6);
 
5691
        val = XML_ATTRIBUTE_FIXED;
 
5692
        if (!IS_BLANK_CH(CUR)) {
 
5693
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5694
                           "Space required after '#FIXED'\n");
 
5695
        }
 
5696
        SKIP_BLANKS;
 
5697
    }
 
5698
    ret = xmlParseAttValue(ctxt);
 
5699
    ctxt->instate = XML_PARSER_DTD;
 
5700
    if (ret == NULL) {
 
5701
        xmlFatalErrMsg(ctxt, (xmlParserErrors)ctxt->errNo,
 
5702
                       "Attribute default value declaration error\n");
 
5703
    } else
 
5704
        *value = ret;
 
5705
    return(val);
 
5706
}
 
5707
 
 
5708
/**
 
5709
 * xmlParseNotationType:
 
5710
 * @ctxt:  an XML parser context
 
5711
 *
 
5712
 * parse an Notation attribute type.
 
5713
 *
 
5714
 * Note: the leading 'NOTATION' S part has already being parsed...
 
5715
 *
 
5716
 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
 
5717
 *
 
5718
 * [ VC: Notation Attributes ]
 
5719
 * Values of this type must match one of the notation names included
 
5720
 * in the declaration; all notation names in the declaration must be declared.
 
5721
 *
 
5722
 * Returns: the notation attribute tree built while parsing
 
5723
 */
 
5724
 
 
5725
xmlEnumerationPtr
 
5726
xmlParseNotationType(xmlParserCtxtPtr ctxt) {
 
5727
    const xmlChar *name;
 
5728
    xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
 
5729
 
 
5730
    if (RAW != '(') {
 
5731
        xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
 
5732
        return(NULL);
 
5733
    }
 
5734
    SHRINK;
 
5735
    do {
 
5736
        NEXT;
 
5737
        SKIP_BLANKS;
 
5738
        name = xmlParseName(ctxt);
 
5739
        if (name == NULL) {
 
5740
            xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
5741
                           "Name expected in NOTATION declaration\n");
 
5742
            xmlFreeEnumeration(ret);
 
5743
            return(NULL);
 
5744
        }
 
5745
        tmp = ret;
 
5746
        while (tmp != NULL) {
 
5747
            if (xmlStrEqual(name, tmp->name)) {
 
5748
                xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
 
5749
          "standalone: attribute notation value token %s duplicated\n",
 
5750
                                 name, NULL);
 
5751
                if (!xmlDictOwns(ctxt->dict, name))
 
5752
                    xmlFree((xmlChar *) name);
 
5753
                break;
 
5754
            }
 
5755
            tmp = tmp->next;
 
5756
        }
 
5757
        if (tmp == NULL) {
 
5758
            cur = xmlCreateEnumeration(name);
 
5759
            if (cur == NULL) {
 
5760
                xmlFreeEnumeration(ret);
 
5761
                return(NULL);
 
5762
            }
 
5763
            if (last == NULL) ret = last = cur;
 
5764
            else {
 
5765
                last->next = cur;
 
5766
                last = cur;
 
5767
            }
 
5768
        }
 
5769
        SKIP_BLANKS;
 
5770
    } while (RAW == '|');
 
5771
    if (RAW != ')') {
 
5772
        xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
 
5773
        xmlFreeEnumeration(ret);
 
5774
        return(NULL);
 
5775
    }
 
5776
    NEXT;
 
5777
    return(ret);
 
5778
}
 
5779
 
 
5780
/**
 
5781
 * xmlParseEnumerationType:
 
5782
 * @ctxt:  an XML parser context
 
5783
 *
 
5784
 * parse an Enumeration attribute type.
 
5785
 *
 
5786
 * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
 
5787
 *
 
5788
 * [ VC: Enumeration ]
 
5789
 * Values of this type must match one of the Nmtoken tokens in
 
5790
 * the declaration
 
5791
 *
 
5792
 * Returns: the enumeration attribute tree built while parsing
 
5793
 */
 
5794
 
 
5795
xmlEnumerationPtr
 
5796
xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
 
5797
    xmlChar *name;
 
5798
    xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
 
5799
 
 
5800
    if (RAW != '(') {
 
5801
        xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_STARTED, NULL);
 
5802
        return(NULL);
 
5803
    }
 
5804
    SHRINK;
 
5805
    do {
 
5806
        NEXT;
 
5807
        SKIP_BLANKS;
 
5808
        name = xmlParseNmtoken(ctxt);
 
5809
        if (name == NULL) {
 
5810
            xmlFatalErr(ctxt, XML_ERR_NMTOKEN_REQUIRED, NULL);
 
5811
            return(ret);
 
5812
        }
 
5813
        tmp = ret;
 
5814
        while (tmp != NULL) {
 
5815
            if (xmlStrEqual(name, tmp->name)) {
 
5816
                xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
 
5817
          "standalone: attribute enumeration value token %s duplicated\n",
 
5818
                                 name, NULL);
 
5819
                if (!xmlDictOwns(ctxt->dict, name))
 
5820
                    xmlFree(name);
 
5821
                break;
 
5822
            }
 
5823
            tmp = tmp->next;
 
5824
        }
 
5825
        if (tmp == NULL) {
 
5826
            cur = xmlCreateEnumeration(name);
 
5827
            if (!xmlDictOwns(ctxt->dict, name))
 
5828
                xmlFree(name);
 
5829
            if (cur == NULL) {
 
5830
                xmlFreeEnumeration(ret);
 
5831
                return(NULL);
 
5832
            }
 
5833
            if (last == NULL) ret = last = cur;
 
5834
            else {
 
5835
                last->next = cur;
 
5836
                last = cur;
 
5837
            }
 
5838
        }
 
5839
        SKIP_BLANKS;
 
5840
    } while (RAW == '|');
 
5841
    if (RAW != ')') {
 
5842
        xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_FINISHED, NULL);
 
5843
        return(ret);
 
5844
    }
 
5845
    NEXT;
 
5846
    return(ret);
 
5847
}
 
5848
 
 
5849
/**
 
5850
 * xmlParseEnumeratedType:
 
5851
 * @ctxt:  an XML parser context
 
5852
 * @tree:  the enumeration tree built while parsing
 
5853
 *
 
5854
 * parse an Enumerated attribute type.
 
5855
 *
 
5856
 * [57] EnumeratedType ::= NotationType | Enumeration
 
5857
 *
 
5858
 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
 
5859
 *
 
5860
 *
 
5861
 * Returns: XML_ATTRIBUTE_ENUMERATION or XML_ATTRIBUTE_NOTATION
 
5862
 */
 
5863
 
 
5864
int
 
5865
xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
 
5866
    if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
 
5867
        SKIP(8);
 
5868
        if (!IS_BLANK_CH(CUR)) {
 
5869
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5870
                           "Space required after 'NOTATION'\n");
 
5871
            return(0);
 
5872
        }
 
5873
        SKIP_BLANKS;
 
5874
        *tree = xmlParseNotationType(ctxt);
 
5875
        if (*tree == NULL) return(0);
 
5876
        return(XML_ATTRIBUTE_NOTATION);
 
5877
    }
 
5878
    *tree = xmlParseEnumerationType(ctxt);
 
5879
    if (*tree == NULL) return(0);
 
5880
    return(XML_ATTRIBUTE_ENUMERATION);
 
5881
}
 
5882
 
 
5883
/**
 
5884
 * xmlParseAttributeType:
 
5885
 * @ctxt:  an XML parser context
 
5886
 * @tree:  the enumeration tree built while parsing
 
5887
 *
 
5888
 * parse the Attribute list def for an element
 
5889
 *
 
5890
 * [54] AttType ::= StringType | TokenizedType | EnumeratedType
 
5891
 *
 
5892
 * [55] StringType ::= 'CDATA'
 
5893
 *
 
5894
 * [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' |
 
5895
 *                        'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
 
5896
 *
 
5897
 * Validity constraints for attribute values syntax are checked in
 
5898
 * xmlValidateAttributeValue()
 
5899
 *
 
5900
 * [ VC: ID ]
 
5901
 * Values of type ID must match the Name production. A name must not
 
5902
 * appear more than once in an XML document as a value of this type;
 
5903
 * i.e., ID values must uniquely identify the elements which bear them.
 
5904
 *
 
5905
 * [ VC: One ID per Element Type ]
 
5906
 * No element type may have more than one ID attribute specified.
 
5907
 *
 
5908
 * [ VC: ID Attribute Default ]
 
5909
 * An ID attribute must have a declared default of #IMPLIED or #REQUIRED.
 
5910
 *
 
5911
 * [ VC: IDREF ]
 
5912
 * Values of type IDREF must match the Name production, and values
 
5913
 * of type IDREFS must match Names; each IDREF Name must match the value
 
5914
 * of an ID attribute on some element in the XML document; i.e. IDREF
 
5915
 * values must match the value of some ID attribute.
 
5916
 *
 
5917
 * [ VC: Entity Name ]
 
5918
 * Values of type ENTITY must match the Name production, values
 
5919
 * of type ENTITIES must match Names; each Entity Name must match the
 
5920
 * name of an unparsed entity declared in the DTD.
 
5921
 *
 
5922
 * [ VC: Name Token ]
 
5923
 * Values of type NMTOKEN must match the Nmtoken production; values
 
5924
 * of type NMTOKENS must match Nmtokens.
 
5925
 *
 
5926
 * Returns the attribute type
 
5927
 */
 
5928
int
 
5929
xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
 
5930
    SHRINK;
 
5931
    if (CMP5(CUR_PTR, 'C', 'D', 'A', 'T', 'A')) {
 
5932
        SKIP(5);
 
5933
        return(XML_ATTRIBUTE_CDATA);
 
5934
     } else if (CMP6(CUR_PTR, 'I', 'D', 'R', 'E', 'F', 'S')) {
 
5935
        SKIP(6);
 
5936
        return(XML_ATTRIBUTE_IDREFS);
 
5937
     } else if (CMP5(CUR_PTR, 'I', 'D', 'R', 'E', 'F')) {
 
5938
        SKIP(5);
 
5939
        return(XML_ATTRIBUTE_IDREF);
 
5940
     } else if ((RAW == 'I') && (NXT(1) == 'D')) {
 
5941
        SKIP(2);
 
5942
        return(XML_ATTRIBUTE_ID);
 
5943
     } else if (CMP6(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'Y')) {
 
5944
        SKIP(6);
 
5945
        return(XML_ATTRIBUTE_ENTITY);
 
5946
     } else if (CMP8(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S')) {
 
5947
        SKIP(8);
 
5948
        return(XML_ATTRIBUTE_ENTITIES);
 
5949
     } else if (CMP8(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S')) {
 
5950
        SKIP(8);
 
5951
        return(XML_ATTRIBUTE_NMTOKENS);
 
5952
     } else if (CMP7(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N')) {
 
5953
        SKIP(7);
 
5954
        return(XML_ATTRIBUTE_NMTOKEN);
 
5955
     }
 
5956
     return(xmlParseEnumeratedType(ctxt, tree));
 
5957
}
 
5958
 
 
5959
/**
 
5960
 * xmlParseAttributeListDecl:
 
5961
 * @ctxt:  an XML parser context
 
5962
 *
 
5963
 * : parse the Attribute list def for an element
 
5964
 *
 
5965
 * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
 
5966
 *
 
5967
 * [53] AttDef ::= S Name S AttType S DefaultDecl
 
5968
 *
 
5969
 */
 
5970
void
 
5971
xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
 
5972
    const xmlChar *elemName;
 
5973
    const xmlChar *attrName;
 
5974
    xmlEnumerationPtr tree;
 
5975
 
 
5976
    if (CMP9(CUR_PTR, '<', '!', 'A', 'T', 'T', 'L', 'I', 'S', 'T')) {
 
5977
        xmlParserInputPtr input = ctxt->input;
 
5978
 
 
5979
        SKIP(9);
 
5980
        if (!IS_BLANK_CH(CUR)) {
 
5981
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5982
                                 "Space required after '<!ATTLIST'\n");
 
5983
        }
 
5984
        SKIP_BLANKS;
 
5985
        elemName = xmlParseName(ctxt);
 
5986
        if (elemName == NULL) {
 
5987
            xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
5988
                           "ATTLIST: no name for Element\n");
 
5989
            return;
 
5990
        }
 
5991
        SKIP_BLANKS;
 
5992
        GROW;
 
5993
        while ((RAW != '>') && (ctxt->instate != XML_PARSER_EOF)) {
 
5994
            const xmlChar *check = CUR_PTR;
 
5995
            int type;
 
5996
            int def;
 
5997
            xmlChar *defaultValue = NULL;
 
5998
 
 
5999
            GROW;
 
6000
            tree = NULL;
 
6001
            attrName = xmlParseName(ctxt);
 
6002
            if (attrName == NULL) {
 
6003
                xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
6004
                               "ATTLIST: no name for Attribute\n");
 
6005
                break;
 
6006
            }
 
6007
            GROW;
 
6008
            if (!IS_BLANK_CH(CUR)) {
 
6009
                xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
6010
                        "Space required after the attribute name\n");
 
6011
                break;
 
6012
            }
 
6013
            SKIP_BLANKS;
 
6014
 
 
6015
            type = xmlParseAttributeType(ctxt, &tree);
 
6016
            if (type <= 0) {
 
6017
                break;
 
6018
            }
 
6019
 
 
6020
            GROW;
 
6021
            if (!IS_BLANK_CH(CUR)) {
 
6022
                xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
6023
                               "Space required after the attribute type\n");
 
6024
                if (tree != NULL)
 
6025
                    xmlFreeEnumeration(tree);
 
6026
                break;
 
6027
            }
 
6028
            SKIP_BLANKS;
 
6029
 
 
6030
            def = xmlParseDefaultDecl(ctxt, &defaultValue);
 
6031
            if (def <= 0) {
 
6032
                if (defaultValue != NULL)
 
6033
                    xmlFree(defaultValue);
 
6034
                if (tree != NULL)
 
6035
                    xmlFreeEnumeration(tree);
 
6036
                break;
 
6037
            }
 
6038
            if ((type != XML_ATTRIBUTE_CDATA) && (defaultValue != NULL))
 
6039
                xmlAttrNormalizeSpace(defaultValue, defaultValue);
 
6040
 
 
6041
            GROW;
 
6042
            if (RAW != '>') {
 
6043
                if (!IS_BLANK_CH(CUR)) {
 
6044
                    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
6045
                        "Space required after the attribute default value\n");
 
6046
                    if (defaultValue != NULL)
 
6047
                        xmlFree(defaultValue);
 
6048
                    if (tree != NULL)
 
6049
                        xmlFreeEnumeration(tree);
 
6050
                    break;
 
6051
                }
 
6052
                SKIP_BLANKS;
 
6053
            }
 
6054
            if (check == CUR_PTR) {
 
6055
                xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
6056
                            "in xmlParseAttributeListDecl\n");
 
6057
                if (defaultValue != NULL)
 
6058
                    xmlFree(defaultValue);
 
6059
                if (tree != NULL)
 
6060
                    xmlFreeEnumeration(tree);
 
6061
                break;
 
6062
            }
 
6063
            if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
 
6064
                (ctxt->sax->attributeDecl != NULL))
 
6065
                ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
 
6066
                                type, def, defaultValue, tree);
 
6067
            else if (tree != NULL)
 
6068
                xmlFreeEnumeration(tree);
 
6069
 
 
6070
            if ((ctxt->sax2) && (defaultValue != NULL) &&
 
6071
                (def != XML_ATTRIBUTE_IMPLIED) &&
 
6072
                (def != XML_ATTRIBUTE_REQUIRED)) {
 
6073
                xmlAddDefAttrs(ctxt, elemName, attrName, defaultValue);
 
6074
            }
 
6075
            if (ctxt->sax2) {
 
6076
                xmlAddSpecialAttr(ctxt, elemName, attrName, type);
 
6077
            }
 
6078
            if (defaultValue != NULL)
 
6079
                xmlFree(defaultValue);
 
6080
            GROW;
 
6081
        }
 
6082
        if (RAW == '>') {
 
6083
            if (input != ctxt->input) {
 
6084
                xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
6085
    "Attribute list declaration doesn't start and stop in the same entity\n",
 
6086
                                 NULL, NULL);
 
6087
            }
 
6088
            NEXT;
 
6089
        }
 
6090
    }
 
6091
}
 
6092
 
 
6093
/**
 
6094
 * xmlParseElementMixedContentDecl:
 
6095
 * @ctxt:  an XML parser context
 
6096
 * @inputchk:  the input used for the current entity, needed for boundary checks
 
6097
 *
 
6098
 * parse the declaration for a Mixed Element content
 
6099
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
 
6100
 *
 
6101
 * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' |
 
6102
 *                '(' S? '#PCDATA' S? ')'
 
6103
 *
 
6104
 * [ VC: Proper Group/PE Nesting ] applies to [51] too (see [49])
 
6105
 *
 
6106
 * [ VC: No Duplicate Types ]
 
6107
 * The same name must not appear more than once in a single
 
6108
 * mixed-content declaration.
 
6109
 *
 
6110
 * returns: the list of the xmlElementContentPtr describing the element choices
 
6111
 */
 
6112
xmlElementContentPtr
 
6113
xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
 
6114
    xmlElementContentPtr ret = NULL, cur = NULL, n;
 
6115
    const xmlChar *elem = NULL;
 
6116
 
 
6117
    GROW;
 
6118
    if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
 
6119
        SKIP(7);
 
6120
        SKIP_BLANKS;
 
6121
        SHRINK;
 
6122
        if (RAW == ')') {
 
6123
            if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
 
6124
                xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
6125
"Element content declaration doesn't start and stop in the same entity\n",
 
6126
                                 NULL, NULL);
 
6127
            }
 
6128
            NEXT;
 
6129
            ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
 
6130
            if (ret == NULL)
 
6131
                return(NULL);
 
6132
            if (RAW == '*') {
 
6133
                ret->ocur = XML_ELEMENT_CONTENT_MULT;
 
6134
                NEXT;
 
6135
            }
 
6136
            return(ret);
 
6137
        }
 
6138
        if ((RAW == '(') || (RAW == '|')) {
 
6139
            ret = cur = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
 
6140
            if (ret == NULL) return(NULL);
 
6141
        }
 
6142
        while ((RAW == '|') && (ctxt->instate != XML_PARSER_EOF)) {
 
6143
            NEXT;
 
6144
            if (elem == NULL) {
 
6145
                ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
 
6146
                if (ret == NULL) return(NULL);
 
6147
                ret->c1 = cur;
 
6148
                if (cur != NULL)
 
6149
                    cur->parent = ret;
 
6150
                cur = ret;
 
6151
            } else {
 
6152
                n = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
 
6153
                if (n == NULL) return(NULL);
 
6154
                n->c1 = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
 
6155
                if (n->c1 != NULL)
 
6156
                    n->c1->parent = n;
 
6157
                cur->c2 = n;
 
6158
                if (n != NULL)
 
6159
                    n->parent = cur;
 
6160
                cur = n;
 
6161
            }
 
6162
            SKIP_BLANKS;
 
6163
            elem = xmlParseName(ctxt);
 
6164
            if (elem == NULL) {
 
6165
                xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
6166
                        "xmlParseElementMixedContentDecl : Name expected\n");
 
6167
                xmlFreeDocElementContent(ctxt->myDoc, cur);
 
6168
                return(NULL);
 
6169
            }
 
6170
            SKIP_BLANKS;
 
6171
            GROW;
 
6172
        }
 
6173
        if ((RAW == ')') && (NXT(1) == '*')) {
 
6174
            if (elem != NULL) {
 
6175
                cur->c2 = xmlNewDocElementContent(ctxt->myDoc, elem,
 
6176
                                               XML_ELEMENT_CONTENT_ELEMENT);
 
6177
                if (cur->c2 != NULL)
 
6178
                    cur->c2->parent = cur;
 
6179
            }
 
6180
            if (ret != NULL)
 
6181
                ret->ocur = XML_ELEMENT_CONTENT_MULT;
 
6182
            if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
 
6183
                xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
6184
"Element content declaration doesn't start and stop in the same entity\n",
 
6185
                                 NULL, NULL);
 
6186
            }
 
6187
            SKIP(2);
 
6188
        } else {
 
6189
            xmlFreeDocElementContent(ctxt->myDoc, ret);
 
6190
            xmlFatalErr(ctxt, XML_ERR_MIXED_NOT_STARTED, NULL);
 
6191
            return(NULL);
 
6192
        }
 
6193
 
 
6194
    } else {
 
6195
        xmlFatalErr(ctxt, XML_ERR_PCDATA_REQUIRED, NULL);
 
6196
    }
 
6197
    return(ret);
 
6198
}
 
6199
 
 
6200
/**
 
6201
 * xmlParseElementChildrenContentDeclPriv:
 
6202
 * @ctxt:  an XML parser context
 
6203
 * @inputchk:  the input used for the current entity, needed for boundary checks
 
6204
 * @depth: the level of recursion
 
6205
 *
 
6206
 * parse the declaration for a Mixed Element content
 
6207
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
 
6208
 *
 
6209
 *
 
6210
 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
 
6211
 *
 
6212
 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
 
6213
 *
 
6214
 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
 
6215
 *
 
6216
 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
 
6217
 *
 
6218
 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
 
6219
 * TODO Parameter-entity replacement text must be properly nested
 
6220
 *      with parenthesized groups. That is to say, if either of the
 
6221
 *      opening or closing parentheses in a choice, seq, or Mixed
 
6222
 *      construct is contained in the replacement text for a parameter
 
6223
 *      entity, both must be contained in the same replacement text. For
 
6224
 *      interoperability, if a parameter-entity reference appears in a
 
6225
 *      choice, seq, or Mixed construct, its replacement text should not
 
6226
 *      be empty, and neither the first nor last non-blank character of
 
6227
 *      the replacement text should be a connector (| or ,).
 
6228
 *
 
6229
 * Returns the tree of xmlElementContentPtr describing the element
 
6230
 *          hierarchy.
 
6231
 */
 
6232
static xmlElementContentPtr
 
6233
xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
 
6234
                                       int depth) {
 
6235
    xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
 
6236
    const xmlChar *elem;
 
6237
    xmlChar type = 0;
 
6238
 
 
6239
    if (((depth > 128) && ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
 
6240
        (depth >  2048)) {
 
6241
        xmlFatalErrMsgInt(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED,
 
6242
"xmlParseElementChildrenContentDecl : depth %d too deep, use XML_PARSE_HUGE\n",
 
6243
                          depth);
 
6244
        return(NULL);
 
6245
    }
 
6246
    SKIP_BLANKS;
 
6247
    GROW;
 
6248
    if (RAW == '(') {
 
6249
        int inputid = ctxt->input->id;
 
6250
 
 
6251
        /* Recurse on first child */
 
6252
        NEXT;
 
6253
        SKIP_BLANKS;
 
6254
        cur = ret = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
 
6255
                                                           depth + 1);
 
6256
        SKIP_BLANKS;
 
6257
        GROW;
 
6258
    } else {
 
6259
        elem = xmlParseName(ctxt);
 
6260
        if (elem == NULL) {
 
6261
            xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
 
6262
            return(NULL);
 
6263
        }
 
6264
        cur = ret = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
 
6265
        if (cur == NULL) {
 
6266
            xmlErrMemory(ctxt, NULL);
 
6267
            return(NULL);
 
6268
        }
 
6269
        GROW;
 
6270
        if (RAW == '?') {
 
6271
            cur->ocur = XML_ELEMENT_CONTENT_OPT;
 
6272
            NEXT;
 
6273
        } else if (RAW == '*') {
 
6274
            cur->ocur = XML_ELEMENT_CONTENT_MULT;
 
6275
            NEXT;
 
6276
        } else if (RAW == '+') {
 
6277
            cur->ocur = XML_ELEMENT_CONTENT_PLUS;
 
6278
            NEXT;
 
6279
        } else {
 
6280
            cur->ocur = XML_ELEMENT_CONTENT_ONCE;
 
6281
        }
 
6282
        GROW;
 
6283
    }
 
6284
    SKIP_BLANKS;
 
6285
    SHRINK;
 
6286
    while ((RAW != ')') && (ctxt->instate != XML_PARSER_EOF)) {
 
6287
        /*
 
6288
         * Each loop we parse one separator and one element.
 
6289
         */
 
6290
        if (RAW == ',') {
 
6291
            if (type == 0) type = CUR;
 
6292
 
 
6293
            /*
 
6294
             * Detect "Name | Name , Name" error
 
6295
             */
 
6296
            else if (type != CUR) {
 
6297
                xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
 
6298
                    "xmlParseElementChildrenContentDecl : '%c' expected\n",
 
6299
                                  type);
 
6300
                if ((last != NULL) && (last != ret))
 
6301
                    xmlFreeDocElementContent(ctxt->myDoc, last);
 
6302
                if (ret != NULL)
 
6303
                    xmlFreeDocElementContent(ctxt->myDoc, ret);
 
6304
                return(NULL);
 
6305
            }
 
6306
            NEXT;
 
6307
 
 
6308
            op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_SEQ);
 
6309
            if (op == NULL) {
 
6310
                if ((last != NULL) && (last != ret))
 
6311
                    xmlFreeDocElementContent(ctxt->myDoc, last);
 
6312
                xmlFreeDocElementContent(ctxt->myDoc, ret);
 
6313
                return(NULL);
 
6314
            }
 
6315
            if (last == NULL) {
 
6316
                op->c1 = ret;
 
6317
                if (ret != NULL)
 
6318
                    ret->parent = op;
 
6319
                ret = cur = op;
 
6320
            } else {
 
6321
                cur->c2 = op;
 
6322
                if (op != NULL)
 
6323
                    op->parent = cur;
 
6324
                op->c1 = last;
 
6325
                if (last != NULL)
 
6326
                    last->parent = op;
 
6327
                cur =op;
 
6328
                last = NULL;
 
6329
            }
 
6330
        } else if (RAW == '|') {
 
6331
            if (type == 0) type = CUR;
 
6332
 
 
6333
            /*
 
6334
             * Detect "Name , Name | Name" error
 
6335
             */
 
6336
            else if (type != CUR) {
 
6337
                xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
 
6338
                    "xmlParseElementChildrenContentDecl : '%c' expected\n",
 
6339
                                  type);
 
6340
                if ((last != NULL) && (last != ret))
 
6341
                    xmlFreeDocElementContent(ctxt->myDoc, last);
 
6342
                if (ret != NULL)
 
6343
                    xmlFreeDocElementContent(ctxt->myDoc, ret);
 
6344
                return(NULL);
 
6345
            }
 
6346
            NEXT;
 
6347
 
 
6348
            op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
 
6349
            if (op == NULL) {
 
6350
                if ((last != NULL) && (last != ret))
 
6351
                    xmlFreeDocElementContent(ctxt->myDoc, last);
 
6352
                if (ret != NULL)
 
6353
                    xmlFreeDocElementContent(ctxt->myDoc, ret);
 
6354
                return(NULL);
 
6355
            }
 
6356
            if (last == NULL) {
 
6357
                op->c1 = ret;
 
6358
                if (ret != NULL)
 
6359
                    ret->parent = op;
 
6360
                ret = cur = op;
 
6361
            } else {
 
6362
                cur->c2 = op;
 
6363
                if (op != NULL)
 
6364
                    op->parent = cur;
 
6365
                op->c1 = last;
 
6366
                if (last != NULL)
 
6367
                    last->parent = op;
 
6368
                cur =op;
 
6369
                last = NULL;
 
6370
            }
 
6371
        } else {
 
6372
            xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED, NULL);
 
6373
            if ((last != NULL) && (last != ret))
 
6374
                xmlFreeDocElementContent(ctxt->myDoc, last);
 
6375
            if (ret != NULL)
 
6376
                xmlFreeDocElementContent(ctxt->myDoc, ret);
 
6377
            return(NULL);
 
6378
        }
 
6379
        GROW;
 
6380
        SKIP_BLANKS;
 
6381
        GROW;
 
6382
        if (RAW == '(') {
 
6383
            int inputid = ctxt->input->id;
 
6384
            /* Recurse on second child */
 
6385
            NEXT;
 
6386
            SKIP_BLANKS;
 
6387
            last = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
 
6388
                                                          depth + 1);
 
6389
            SKIP_BLANKS;
 
6390
        } else {
 
6391
            elem = xmlParseName(ctxt);
 
6392
            if (elem == NULL) {
 
6393
                xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
 
6394
                if (ret != NULL)
 
6395
                    xmlFreeDocElementContent(ctxt->myDoc, ret);
 
6396
                return(NULL);
 
6397
            }
 
6398
            last = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
 
6399
            if (last == NULL) {
 
6400
                if (ret != NULL)
 
6401
                    xmlFreeDocElementContent(ctxt->myDoc, ret);
 
6402
                return(NULL);
 
6403
            }
 
6404
            if (RAW == '?') {
 
6405
                last->ocur = XML_ELEMENT_CONTENT_OPT;
 
6406
                NEXT;
 
6407
            } else if (RAW == '*') {
 
6408
                last->ocur = XML_ELEMENT_CONTENT_MULT;
 
6409
                NEXT;
 
6410
            } else if (RAW == '+') {
 
6411
                last->ocur = XML_ELEMENT_CONTENT_PLUS;
 
6412
                NEXT;
 
6413
            } else {
 
6414
                last->ocur = XML_ELEMENT_CONTENT_ONCE;
 
6415
            }
 
6416
        }
 
6417
        SKIP_BLANKS;
 
6418
        GROW;
 
6419
    }
 
6420
    if ((cur != NULL) && (last != NULL)) {
 
6421
        cur->c2 = last;
 
6422
        if (last != NULL)
 
6423
            last->parent = cur;
 
6424
    }
 
6425
    if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
 
6426
        xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
6427
"Element content declaration doesn't start and stop in the same entity\n",
 
6428
                         NULL, NULL);
 
6429
    }
 
6430
    NEXT;
 
6431
    if (RAW == '?') {
 
6432
        if (ret != NULL) {
 
6433
            if ((ret->ocur == XML_ELEMENT_CONTENT_PLUS) ||
 
6434
                (ret->ocur == XML_ELEMENT_CONTENT_MULT))
 
6435
                ret->ocur = XML_ELEMENT_CONTENT_MULT;
 
6436
            else
 
6437
                ret->ocur = XML_ELEMENT_CONTENT_OPT;
 
6438
        }
 
6439
        NEXT;
 
6440
    } else if (RAW == '*') {
 
6441
        if (ret != NULL) {
 
6442
            ret->ocur = XML_ELEMENT_CONTENT_MULT;
 
6443
            cur = ret;
 
6444
            /*
 
6445
             * Some normalization:
 
6446
             * (a | b* | c?)* == (a | b | c)*
 
6447
             */
 
6448
            while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
 
6449
                if ((cur->c1 != NULL) &&
 
6450
                    ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
 
6451
                     (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT)))
 
6452
                    cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
 
6453
                if ((cur->c2 != NULL) &&
 
6454
                    ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
 
6455
                     (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT)))
 
6456
                    cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
 
6457
                cur = cur->c2;
 
6458
            }
 
6459
        }
 
6460
        NEXT;
 
6461
    } else if (RAW == '+') {
 
6462
        if (ret != NULL) {
 
6463
            int found = 0;
 
6464
 
 
6465
            if ((ret->ocur == XML_ELEMENT_CONTENT_OPT) ||
 
6466
                (ret->ocur == XML_ELEMENT_CONTENT_MULT))
 
6467
                ret->ocur = XML_ELEMENT_CONTENT_MULT;
 
6468
            else
 
6469
                ret->ocur = XML_ELEMENT_CONTENT_PLUS;
 
6470
            /*
 
6471
             * Some normalization:
 
6472
             * (a | b*)+ == (a | b)*
 
6473
             * (a | b?)+ == (a | b)*
 
6474
             */
 
6475
            while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
 
6476
                if ((cur->c1 != NULL) &&
 
6477
                    ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
 
6478
                     (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT))) {
 
6479
                    cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
 
6480
                    found = 1;
 
6481
                }
 
6482
                if ((cur->c2 != NULL) &&
 
6483
                    ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
 
6484
                     (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT))) {
 
6485
                    cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
 
6486
                    found = 1;
 
6487
                }
 
6488
                cur = cur->c2;
 
6489
            }
 
6490
            if (found)
 
6491
                ret->ocur = XML_ELEMENT_CONTENT_MULT;
 
6492
        }
 
6493
        NEXT;
 
6494
    }
 
6495
    return(ret);
 
6496
}
 
6497
 
 
6498
/**
 
6499
 * xmlParseElementChildrenContentDecl:
 
6500
 * @ctxt:  an XML parser context
 
6501
 * @inputchk:  the input used for the current entity, needed for boundary checks
 
6502
 *
 
6503
 * parse the declaration for a Mixed Element content
 
6504
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
 
6505
 *
 
6506
 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
 
6507
 *
 
6508
 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
 
6509
 *
 
6510
 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
 
6511
 *
 
6512
 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
 
6513
 *
 
6514
 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
 
6515
 * TODO Parameter-entity replacement text must be properly nested
 
6516
 *      with parenthesized groups. That is to say, if either of the
 
6517
 *      opening or closing parentheses in a choice, seq, or Mixed
 
6518
 *      construct is contained in the replacement text for a parameter
 
6519
 *      entity, both must be contained in the same replacement text. For
 
6520
 *      interoperability, if a parameter-entity reference appears in a
 
6521
 *      choice, seq, or Mixed construct, its replacement text should not
 
6522
 *      be empty, and neither the first nor last non-blank character of
 
6523
 *      the replacement text should be a connector (| or ,).
 
6524
 *
 
6525
 * Returns the tree of xmlElementContentPtr describing the element
 
6526
 *          hierarchy.
 
6527
 */
 
6528
xmlElementContentPtr
 
6529
xmlParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
 
6530
    /* stub left for API/ABI compat */
 
6531
    return(xmlParseElementChildrenContentDeclPriv(ctxt, inputchk, 1));
 
6532
}
 
6533
 
 
6534
/**
 
6535
 * xmlParseElementContentDecl:
 
6536
 * @ctxt:  an XML parser context
 
6537
 * @name:  the name of the element being defined.
 
6538
 * @result:  the Element Content pointer will be stored here if any
 
6539
 *
 
6540
 * parse the declaration for an Element content either Mixed or Children,
 
6541
 * the cases EMPTY and ANY are handled directly in xmlParseElementDecl
 
6542
 *
 
6543
 * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
 
6544
 *
 
6545
 * returns: the type of element content XML_ELEMENT_TYPE_xxx
 
6546
 */
 
6547
 
 
6548
int
 
6549
xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, const xmlChar *name,
 
6550
                           xmlElementContentPtr *result) {
 
6551
 
 
6552
    xmlElementContentPtr tree = NULL;
 
6553
    int inputid = ctxt->input->id;
 
6554
    int res;
 
6555
 
 
6556
    *result = NULL;
 
6557
 
 
6558
    if (RAW != '(') {
 
6559
        xmlFatalErrMsgStr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
 
6560
                "xmlParseElementContentDecl : %s '(' expected\n", name);
 
6561
        return(-1);
 
6562
    }
 
6563
    NEXT;
 
6564
    GROW;
 
6565
    if (ctxt->instate == XML_PARSER_EOF)
 
6566
        return(-1);
 
6567
    SKIP_BLANKS;
 
6568
    if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
 
6569
        tree = xmlParseElementMixedContentDecl(ctxt, inputid);
 
6570
        res = XML_ELEMENT_TYPE_MIXED;
 
6571
    } else {
 
6572
        tree = xmlParseElementChildrenContentDeclPriv(ctxt, inputid, 1);
 
6573
        res = XML_ELEMENT_TYPE_ELEMENT;
 
6574
    }
 
6575
    SKIP_BLANKS;
 
6576
    *result = tree;
 
6577
    return(res);
 
6578
}
 
6579
 
 
6580
/**
 
6581
 * xmlParseElementDecl:
 
6582
 * @ctxt:  an XML parser context
 
6583
 *
 
6584
 * parse an Element declaration.
 
6585
 *
 
6586
 * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
 
6587
 *
 
6588
 * [ VC: Unique Element Type Declaration ]
 
6589
 * No element type may be declared more than once
 
6590
 *
 
6591
 * Returns the type of the element, or -1 in case of error
 
6592
 */
 
6593
int
 
6594
xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
 
6595
    const xmlChar *name;
 
6596
    int ret = -1;
 
6597
    xmlElementContentPtr content  = NULL;
 
6598
 
 
6599
    /* GROW; done in the caller */
 
6600
    if (CMP9(CUR_PTR, '<', '!', 'E', 'L', 'E', 'M', 'E', 'N', 'T')) {
 
6601
        xmlParserInputPtr input = ctxt->input;
 
6602
 
 
6603
        SKIP(9);
 
6604
        if (!IS_BLANK_CH(CUR)) {
 
6605
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
6606
                           "Space required after 'ELEMENT'\n");
 
6607
        }
 
6608
        SKIP_BLANKS;
 
6609
        name = xmlParseName(ctxt);
 
6610
        if (name == NULL) {
 
6611
            xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
6612
                           "xmlParseElementDecl: no name for Element\n");
 
6613
            return(-1);
 
6614
        }
 
6615
        while ((RAW == 0) && (ctxt->inputNr > 1))
 
6616
            xmlPopInput(ctxt);
 
6617
        if (!IS_BLANK_CH(CUR)) {
 
6618
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
6619
                           "Space required after the element name\n");
 
6620
        }
 
6621
        SKIP_BLANKS;
 
6622
        if (CMP5(CUR_PTR, 'E', 'M', 'P', 'T', 'Y')) {
 
6623
            SKIP(5);
 
6624
            /*
 
6625
             * Element must always be empty.
 
6626
             */
 
6627
            ret = XML_ELEMENT_TYPE_EMPTY;
 
6628
        } else if ((RAW == 'A') && (NXT(1) == 'N') &&
 
6629
                   (NXT(2) == 'Y')) {
 
6630
            SKIP(3);
 
6631
            /*
 
6632
             * Element is a generic container.
 
6633
             */
 
6634
            ret = XML_ELEMENT_TYPE_ANY;
 
6635
        } else if (RAW == '(') {
 
6636
            ret = xmlParseElementContentDecl(ctxt, name, &content);
 
6637
        } else {
 
6638
            /*
 
6639
             * [ WFC: PEs in Internal Subset ] error handling.
 
6640
             */
 
6641
            if ((RAW == '%') && (ctxt->external == 0) &&
 
6642
                (ctxt->inputNr == 1)) {
 
6643
                xmlFatalErrMsg(ctxt, XML_ERR_PEREF_IN_INT_SUBSET,
 
6644
          "PEReference: forbidden within markup decl in internal subset\n");
 
6645
            } else {
 
6646
                xmlFatalErrMsg(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
 
6647
                      "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
 
6648
            }
 
6649
            return(-1);
 
6650
        }
 
6651
 
 
6652
        SKIP_BLANKS;
 
6653
        /*
 
6654
         * Pop-up of finished entities.
 
6655
         */
 
6656
        while ((RAW == 0) && (ctxt->inputNr > 1))
 
6657
            xmlPopInput(ctxt);
 
6658
        SKIP_BLANKS;
 
6659
 
 
6660
        if (RAW != '>') {
 
6661
            xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
 
6662
            if (content != NULL) {
 
6663
                xmlFreeDocElementContent(ctxt->myDoc, content);
 
6664
            }
 
6665
        } else {
 
6666
            if (input != ctxt->input) {
 
6667
                xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
6668
    "Element declaration doesn't start and stop in the same entity\n");
 
6669
            }
 
6670
 
 
6671
            NEXT;
 
6672
            if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
 
6673
                (ctxt->sax->elementDecl != NULL)) {
 
6674
                if (content != NULL)
 
6675
                    content->parent = NULL;
 
6676
                ctxt->sax->elementDecl(ctxt->userData, name, ret,
 
6677
                                       content);
 
6678
                if ((content != NULL) && (content->parent == NULL)) {
 
6679
                    /*
 
6680
                     * this is a trick: if xmlAddElementDecl is called,
 
6681
                     * instead of copying the full tree it is plugged directly
 
6682
                     * if called from the parser. Avoid duplicating the
 
6683
                     * interfaces or change the API/ABI
 
6684
                     */
 
6685
                    xmlFreeDocElementContent(ctxt->myDoc, content);
 
6686
                }
 
6687
            } else if (content != NULL) {
 
6688
                xmlFreeDocElementContent(ctxt->myDoc, content);
 
6689
            }
 
6690
        }
 
6691
    }
 
6692
    return(ret);
 
6693
}
 
6694
 
 
6695
/**
 
6696
 * xmlParseConditionalSections
 
6697
 * @ctxt:  an XML parser context
 
6698
 *
 
6699
 * [61] conditionalSect ::= includeSect | ignoreSect
 
6700
 * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
 
6701
 * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
 
6702
 * [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
 
6703
 * [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
 
6704
 */
 
6705
 
 
6706
static void
 
6707
xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
 
6708
    int id = ctxt->input->id;
 
6709
 
 
6710
    SKIP(3);
 
6711
    SKIP_BLANKS;
 
6712
    if (CMP7(CUR_PTR, 'I', 'N', 'C', 'L', 'U', 'D', 'E')) {
 
6713
        SKIP(7);
 
6714
        SKIP_BLANKS;
 
6715
        if (RAW != '[') {
 
6716
            xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
 
6717
        } else {
 
6718
            if (ctxt->input->id != id) {
 
6719
                xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
6720
            "All markup of the conditional section is not in the same entity\n",
 
6721
                                     NULL, NULL);
 
6722
            }
 
6723
            NEXT;
 
6724
        }
 
6725
        if (xmlParserDebugEntities) {
 
6726
            if ((ctxt->input != NULL) && (ctxt->input->filename))
 
6727
                xmlGenericError(xmlGenericErrorContext,
 
6728
                        "%s(%d): ", ctxt->input->filename,
 
6729
                        ctxt->input->line);
 
6730
            xmlGenericError(xmlGenericErrorContext,
 
6731
                    "Entering INCLUDE Conditional Section\n");
 
6732
        }
 
6733
 
 
6734
        while (((RAW != 0) && ((RAW != ']') || (NXT(1) != ']') ||
 
6735
                (NXT(2) != '>'))) && (ctxt->instate != XML_PARSER_EOF)) {
 
6736
            const xmlChar *check = CUR_PTR;
 
6737
            unsigned int cons = ctxt->input->consumed;
 
6738
 
 
6739
            if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
 
6740
                xmlParseConditionalSections(ctxt);
 
6741
            } else if (IS_BLANK_CH(CUR)) {
 
6742
                NEXT;
 
6743
            } else if (RAW == '%') {
 
6744
                xmlParsePEReference(ctxt);
 
6745
            } else
 
6746
                xmlParseMarkupDecl(ctxt);
 
6747
 
 
6748
            /*
 
6749
             * Pop-up of finished entities.
 
6750
             */
 
6751
            while ((RAW == 0) && (ctxt->inputNr > 1))
 
6752
                xmlPopInput(ctxt);
 
6753
 
 
6754
            if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
 
6755
                xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
 
6756
                break;
 
6757
            }
 
6758
        }
 
6759
        if (xmlParserDebugEntities) {
 
6760
            if ((ctxt->input != NULL) && (ctxt->input->filename))
 
6761
                xmlGenericError(xmlGenericErrorContext,
 
6762
                        "%s(%d): ", ctxt->input->filename,
 
6763
                        ctxt->input->line);
 
6764
            xmlGenericError(xmlGenericErrorContext,
 
6765
                    "Leaving INCLUDE Conditional Section\n");
 
6766
        }
 
6767
 
 
6768
    } else if (CMP6(CUR_PTR, 'I', 'G', 'N', 'O', 'R', 'E')) {
 
6769
        int state;
 
6770
        xmlParserInputState instate;
 
6771
        int depth = 0;
 
6772
 
 
6773
        SKIP(6);
 
6774
        SKIP_BLANKS;
 
6775
        if (RAW != '[') {
 
6776
            xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
 
6777
        } else {
 
6778
            if (ctxt->input->id != id) {
 
6779
                xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
6780
            "All markup of the conditional section is not in the same entity\n",
 
6781
                                     NULL, NULL);
 
6782
            }
 
6783
            NEXT;
 
6784
        }
 
6785
        if (xmlParserDebugEntities) {
 
6786
            if ((ctxt->input != NULL) && (ctxt->input->filename))
 
6787
                xmlGenericError(xmlGenericErrorContext,
 
6788
                        "%s(%d): ", ctxt->input->filename,
 
6789
                        ctxt->input->line);
 
6790
            xmlGenericError(xmlGenericErrorContext,
 
6791
                    "Entering IGNORE Conditional Section\n");
 
6792
        }
 
6793
 
 
6794
        /*
 
6795
         * Parse up to the end of the conditional section
 
6796
         * But disable SAX event generating DTD building in the meantime
 
6797
         */
 
6798
        state = ctxt->disableSAX;
 
6799
        instate = ctxt->instate;
 
6800
        if (ctxt->recovery == 0) ctxt->disableSAX = 1;
 
6801
        ctxt->instate = XML_PARSER_IGNORE;
 
6802
 
 
6803
        while (((depth >= 0) && (RAW != 0)) &&
 
6804
               (ctxt->instate != XML_PARSER_EOF)) {
 
6805
          if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
 
6806
            depth++;
 
6807
            SKIP(3);
 
6808
            continue;
 
6809
          }
 
6810
          if ((RAW == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
 
6811
            if (--depth >= 0) SKIP(3);
 
6812
            continue;
 
6813
          }
 
6814
          NEXT;
 
6815
          continue;
 
6816
        }
 
6817
 
 
6818
        ctxt->disableSAX = state;
 
6819
        ctxt->instate = instate;
 
6820
 
 
6821
        if (xmlParserDebugEntities) {
 
6822
            if ((ctxt->input != NULL) && (ctxt->input->filename))
 
6823
                xmlGenericError(xmlGenericErrorContext,
 
6824
                        "%s(%d): ", ctxt->input->filename,
 
6825
                        ctxt->input->line);
 
6826
            xmlGenericError(xmlGenericErrorContext,
 
6827
                    "Leaving IGNORE Conditional Section\n");
 
6828
        }
 
6829
 
 
6830
    } else {
 
6831
        xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
 
6832
    }
 
6833
 
 
6834
    if (RAW == 0)
 
6835
        SHRINK;
 
6836
 
 
6837
    if (RAW == 0) {
 
6838
        xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
 
6839
    } else {
 
6840
        if (ctxt->input->id != id) {
 
6841
            xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
6842
        "All markup of the conditional section is not in the same entity\n",
 
6843
                                 NULL, NULL);
 
6844
        }
 
6845
        SKIP(3);
 
6846
    }
 
6847
}
 
6848
 
 
6849
/**
 
6850
 * xmlParseMarkupDecl:
 
6851
 * @ctxt:  an XML parser context
 
6852
 *
 
6853
 * parse Markup declarations
 
6854
 *
 
6855
 * [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
 
6856
 *                     NotationDecl | PI | Comment
 
6857
 *
 
6858
 * [ VC: Proper Declaration/PE Nesting ]
 
6859
 * Parameter-entity replacement text must be properly nested with
 
6860
 * markup declarations. That is to say, if either the first character
 
6861
 * or the last character of a markup declaration (markupdecl above) is
 
6862
 * contained in the replacement text for a parameter-entity reference,
 
6863
 * both must be contained in the same replacement text.
 
6864
 *
 
6865
 * [ WFC: PEs in Internal Subset ]
 
6866
 * In the internal DTD subset, parameter-entity references can occur
 
6867
 * only where markup declarations can occur, not within markup declarations.
 
6868
 * (This does not apply to references that occur in external parameter
 
6869
 * entities or to the external subset.)
 
6870
 */
 
6871
void
 
6872
xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
 
6873
    GROW;
 
6874
    if (CUR == '<') {
 
6875
        if (NXT(1) == '!') {
 
6876
            switch (NXT(2)) {
 
6877
                case 'E':
 
6878
                    if (NXT(3) == 'L')
 
6879
                        xmlParseElementDecl(ctxt);
 
6880
                    else if (NXT(3) == 'N')
 
6881
                        xmlParseEntityDecl(ctxt);
 
6882
                    break;
 
6883
                case 'A':
 
6884
                    xmlParseAttributeListDecl(ctxt);
 
6885
                    break;
 
6886
                case 'N':
 
6887
                    xmlParseNotationDecl(ctxt);
 
6888
                    break;
 
6889
                case '-':
 
6890
                    xmlParseComment(ctxt);
 
6891
                    break;
 
6892
                default:
 
6893
                    /* there is an error but it will be detected later */
 
6894
                    break;
 
6895
            }
 
6896
        } else if (NXT(1) == '?') {
 
6897
            xmlParsePI(ctxt);
 
6898
        }
 
6899
    }
 
6900
    /*
 
6901
     * This is only for internal subset. On external entities,
 
6902
     * the replacement is done before parsing stage
 
6903
     */
 
6904
    if ((ctxt->external == 0) && (ctxt->inputNr == 1))
 
6905
        xmlParsePEReference(ctxt);
 
6906
 
 
6907
    /*
 
6908
     * Conditional sections are allowed from entities included
 
6909
     * by PE References in the internal subset.
 
6910
     */
 
6911
    if ((ctxt->external == 0) && (ctxt->inputNr > 1)) {
 
6912
        if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
 
6913
            xmlParseConditionalSections(ctxt);
 
6914
        }
 
6915
    }
 
6916
 
 
6917
    ctxt->instate = XML_PARSER_DTD;
 
6918
}
 
6919
 
 
6920
/**
 
6921
 * xmlParseTextDecl:
 
6922
 * @ctxt:  an XML parser context
 
6923
 *
 
6924
 * parse an XML declaration header for external entities
 
6925
 *
 
6926
 * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
 
6927
 */
 
6928
 
 
6929
void
 
6930
xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
 
6931
    xmlChar *version;
 
6932
    const xmlChar *encoding;
 
6933
 
 
6934
    /*
 
6935
     * We know that '<?xml' is here.
 
6936
     */
 
6937
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
 
6938
        SKIP(5);
 
6939
    } else {
 
6940
        xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_STARTED, NULL);
 
6941
        return;
 
6942
    }
 
6943
 
 
6944
    if (!IS_BLANK_CH(CUR)) {
 
6945
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
6946
                       "Space needed after '<?xml'\n");
 
6947
    }
 
6948
    SKIP_BLANKS;
 
6949
 
 
6950
    /*
 
6951
     * We may have the VersionInfo here.
 
6952
     */
 
6953
    version = xmlParseVersionInfo(ctxt);
 
6954
    if (version == NULL)
 
6955
        version = xmlCharStrdup(XML_DEFAULT_VERSION);
 
6956
    else {
 
6957
        if (!IS_BLANK_CH(CUR)) {
 
6958
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
6959
                           "Space needed here\n");
 
6960
        }
 
6961
    }
 
6962
    ctxt->input->version = version;
 
6963
 
 
6964
    /*
 
6965
     * We must have the encoding declaration
 
6966
     */
 
6967
    encoding = xmlParseEncodingDecl(ctxt);
 
6968
    if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
 
6969
        /*
 
6970
         * The XML REC instructs us to stop parsing right here
 
6971
         */
 
6972
        return;
 
6973
    }
 
6974
    if ((encoding == NULL) && (ctxt->errNo == XML_ERR_OK)) {
 
6975
        xmlFatalErrMsg(ctxt, XML_ERR_MISSING_ENCODING,
 
6976
                       "Missing encoding in text declaration\n");
 
6977
    }
 
6978
 
 
6979
    SKIP_BLANKS;
 
6980
    if ((RAW == '?') && (NXT(1) == '>')) {
 
6981
        SKIP(2);
 
6982
    } else if (RAW == '>') {
 
6983
        /* Deprecated old WD ... */
 
6984
        xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
 
6985
        NEXT;
 
6986
    } else {
 
6987
        xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
 
6988
        MOVETO_ENDTAG(CUR_PTR);
 
6989
        NEXT;
 
6990
    }
 
6991
}
 
6992
 
 
6993
/**
 
6994
 * xmlParseExternalSubset:
 
6995
 * @ctxt:  an XML parser context
 
6996
 * @ExternalID: the external identifier
 
6997
 * @SystemID: the system identifier (or URL)
 
6998
 *
 
6999
 * parse Markup declarations from an external subset
 
7000
 *
 
7001
 * [30] extSubset ::= textDecl? extSubsetDecl
 
7002
 *
 
7003
 * [31] extSubsetDecl ::= (markupdecl | conditionalSect | PEReference | S) *
 
7004
 */
 
7005
void
 
7006
xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
 
7007
                       const xmlChar *SystemID) {
 
7008
    xmlDetectSAX2(ctxt);
 
7009
    GROW;
 
7010
 
 
7011
    if ((ctxt->encoding == NULL) &&
 
7012
        (ctxt->input->end - ctxt->input->cur >= 4)) {
 
7013
        xmlChar start[4];
 
7014
        xmlCharEncoding enc;
 
7015
 
 
7016
        start[0] = RAW;
 
7017
        start[1] = NXT(1);
 
7018
        start[2] = NXT(2);
 
7019
        start[3] = NXT(3);
 
7020
        enc = xmlDetectCharEncoding(start, 4);
 
7021
        if (enc != XML_CHAR_ENCODING_NONE)
 
7022
            xmlSwitchEncoding(ctxt, enc);
 
7023
    }
 
7024
 
 
7025
    if (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) {
 
7026
        xmlParseTextDecl(ctxt);
 
7027
        if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
 
7028
            /*
 
7029
             * The XML REC instructs us to stop parsing right here
 
7030
             */
 
7031
            ctxt->instate = XML_PARSER_EOF;
 
7032
            return;
 
7033
        }
 
7034
    }
 
7035
    if (ctxt->myDoc == NULL) {
 
7036
        ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
 
7037
        if (ctxt->myDoc == NULL) {
 
7038
            xmlErrMemory(ctxt, "New Doc failed");
 
7039
            return;
 
7040
        }
 
7041
        ctxt->myDoc->properties = XML_DOC_INTERNAL;
 
7042
    }
 
7043
    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
 
7044
        xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
 
7045
 
 
7046
    ctxt->instate = XML_PARSER_DTD;
 
7047
    ctxt->external = 1;
 
7048
    while (((RAW == '<') && (NXT(1) == '?')) ||
 
7049
           ((RAW == '<') && (NXT(1) == '!')) ||
 
7050
           (RAW == '%') || IS_BLANK_CH(CUR)) {
 
7051
        const xmlChar *check = CUR_PTR;
 
7052
        unsigned int cons = ctxt->input->consumed;
 
7053
 
 
7054
        GROW;
 
7055
        if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
 
7056
            xmlParseConditionalSections(ctxt);
 
7057
        } else if (IS_BLANK_CH(CUR)) {
 
7058
            NEXT;
 
7059
        } else if (RAW == '%') {
 
7060
            xmlParsePEReference(ctxt);
 
7061
        } else
 
7062
            xmlParseMarkupDecl(ctxt);
 
7063
 
 
7064
        /*
 
7065
         * Pop-up of finished entities.
 
7066
         */
 
7067
        while ((RAW == 0) && (ctxt->inputNr > 1))
 
7068
            xmlPopInput(ctxt);
 
7069
 
 
7070
        if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
 
7071
            xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
 
7072
            break;
 
7073
        }
 
7074
    }
 
7075
 
 
7076
    if (RAW != 0) {
 
7077
        xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
 
7078
    }
 
7079
 
 
7080
}
 
7081
 
 
7082
/**
 
7083
 * xmlParseReference:
 
7084
 * @ctxt:  an XML parser context
 
7085
 *
 
7086
 * parse and handle entity references in content, depending on the SAX
 
7087
 * interface, this may end-up in a call to character() if this is a
 
7088
 * CharRef, a predefined entity, if there is no reference() callback.
 
7089
 * or if the parser was asked to switch to that mode.
 
7090
 *
 
7091
 * [67] Reference ::= EntityRef | CharRef
 
7092
 */
 
7093
void
 
7094
xmlParseReference(xmlParserCtxtPtr ctxt) {
 
7095
    xmlEntityPtr ent;
 
7096
    xmlChar *val;
 
7097
    int was_checked;
 
7098
    xmlNodePtr list = NULL;
 
7099
    xmlParserErrors ret = XML_ERR_OK;
 
7100
 
 
7101
 
 
7102
    if (RAW != '&')
 
7103
        return;
 
7104
 
 
7105
    /*
 
7106
     * Simple case of a CharRef
 
7107
     */
 
7108
    if (NXT(1) == '#') {
 
7109
        int i = 0;
 
7110
        xmlChar out[10];
 
7111
        int hex = NXT(2);
 
7112
        int value = xmlParseCharRef(ctxt);
 
7113
 
 
7114
        if (value == 0)
 
7115
            return;
 
7116
        if (ctxt->charset != XML_CHAR_ENCODING_UTF8) {
 
7117
            /*
 
7118
             * So we are using non-UTF-8 buffers
 
7119
             * Check that the char fit on 8bits, if not
 
7120
             * generate a CharRef.
 
7121
             */
 
7122
            if (value <= 0xFF) {
 
7123
                out[0] = value;
 
7124
                out[1] = 0;
 
7125
                if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
 
7126
                    (!ctxt->disableSAX))
 
7127
                    ctxt->sax->characters(ctxt->userData, out, 1);
 
7128
            } else {
 
7129
                if ((hex == 'x') || (hex == 'X'))
 
7130
                    snprintf((char *)out, sizeof(out), "#x%X", value);
 
7131
                else
 
7132
                    snprintf((char *)out, sizeof(out), "#%d", value);
 
7133
                if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
 
7134
                    (!ctxt->disableSAX))
 
7135
                    ctxt->sax->reference(ctxt->userData, out);
 
7136
            }
 
7137
        } else {
 
7138
            /*
 
7139
             * Just encode the value in UTF-8
 
7140
             */
 
7141
            COPY_BUF(0 ,out, i, value);
 
7142
            out[i] = 0;
 
7143
            if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
 
7144
                (!ctxt->disableSAX))
 
7145
                ctxt->sax->characters(ctxt->userData, out, i);
 
7146
        }
 
7147
        return;
 
7148
    }
 
7149
 
 
7150
    /*
 
7151
     * We are seeing an entity reference
 
7152
     */
 
7153
    ent = xmlParseEntityRef(ctxt);
 
7154
    if (ent == NULL) return;
 
7155
    if (!ctxt->wellFormed)
 
7156
        return;
 
7157
    was_checked = ent->checked;
 
7158
 
 
7159
    /* special case of predefined entities */
 
7160
    if ((ent->name == NULL) ||
 
7161
        (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
 
7162
        val = ent->content;
 
7163
        if (val == NULL) return;
 
7164
        /*
 
7165
         * inline the entity.
 
7166
         */
 
7167
        if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
 
7168
            (!ctxt->disableSAX))
 
7169
            ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
 
7170
        return;
 
7171
    }
 
7172
 
 
7173
    /*
 
7174
     * The first reference to the entity trigger a parsing phase
 
7175
     * where the ent->children is filled with the result from
 
7176
     * the parsing.
 
7177
     * Note: external parsed entities will not be loaded, it is not
 
7178
     * required for a non-validating parser, unless the parsing option
 
7179
     * of validating, or substituting entities were given. Doing so is
 
7180
     * far more secure as the parser will only process data coming from
 
7181
     * the document entity by default.
 
7182
     */
 
7183
    if ((ent->checked == 0) &&
 
7184
        ((ent->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY) ||
 
7185
         (ctxt->options & (XML_PARSE_NOENT | XML_PARSE_DTDVALID)))) {
 
7186
        unsigned long oldnbent = ctxt->nbentities;
 
7187
 
 
7188
        /*
 
7189
         * This is a bit hackish but this seems the best
 
7190
         * way to make sure both SAX and DOM entity support
 
7191
         * behaves okay.
 
7192
         */
 
7193
        void *user_data;
 
7194
        if (ctxt->userData == ctxt)
 
7195
            user_data = NULL;
 
7196
        else
 
7197
            user_data = ctxt->userData;
 
7198
 
 
7199
        /*
 
7200
         * Check that this entity is well formed
 
7201
         * 4.3.2: An internal general parsed entity is well-formed
 
7202
         * if its replacement text matches the production labeled
 
7203
         * content.
 
7204
         */
 
7205
        if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
 
7206
            ctxt->depth++;
 
7207
            ret = xmlParseBalancedChunkMemoryInternal(ctxt, ent->content,
 
7208
                                                      user_data, &list);
 
7209
            ctxt->depth--;
 
7210
 
 
7211
        } else if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
 
7212
            ctxt->depth++;
 
7213
            ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt, ctxt->sax,
 
7214
                                           user_data, ctxt->depth, ent->URI,
 
7215
                                           ent->ExternalID, &list);
 
7216
            ctxt->depth--;
 
7217
        } else {
 
7218
            ret = XML_ERR_ENTITY_PE_INTERNAL;
 
7219
            xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
 
7220
                         "invalid entity type found\n", NULL);
 
7221
        }
 
7222
 
 
7223
        /*
 
7224
         * Store the number of entities needing parsing for this entity
 
7225
         * content and do checkings
 
7226
         */
 
7227
        ent->checked = (ctxt->nbentities - oldnbent + 1) * 2;
 
7228
        if ((ent->content != NULL) && (xmlStrchr(ent->content, '<')))
 
7229
            ent->checked |= 1;
 
7230
        if (ret == XML_ERR_ENTITY_LOOP) {
 
7231
            xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
 
7232
            xmlFreeNodeList(list);
 
7233
            return;
 
7234
        }
 
7235
        if (xmlParserEntityCheck(ctxt, 0, ent, 0)) {
 
7236
            xmlFreeNodeList(list);
 
7237
            return;
 
7238
        }
 
7239
 
 
7240
        if ((ret == XML_ERR_OK) && (list != NULL)) {
 
7241
            if (((ent->etype == XML_INTERNAL_GENERAL_ENTITY) ||
 
7242
             (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY))&&
 
7243
                (ent->children == NULL)) {
 
7244
                ent->children = list;
 
7245
                if (ctxt->replaceEntities) {
 
7246
                    /*
 
7247
                     * Prune it directly in the generated document
 
7248
                     * except for single text nodes.
 
7249
                     */
 
7250
                    if (((list->type == XML_TEXT_NODE) &&
 
7251
                         (list->next == NULL)) ||
 
7252
                        (ctxt->parseMode == XML_PARSE_READER)) {
 
7253
                        list->parent = (xmlNodePtr) ent;
 
7254
                        list = NULL;
 
7255
                        ent->owner = 1;
 
7256
                    } else {
 
7257
                        ent->owner = 0;
 
7258
                        while (list != NULL) {
 
7259
                            list->parent = (xmlNodePtr) ctxt->node;
 
7260
                            list->doc = ctxt->myDoc;
 
7261
                            if (list->next == NULL)
 
7262
                                ent->last = list;
 
7263
                            list = list->next;
 
7264
                        }
 
7265
                        list = ent->children;
 
7266
#ifdef LIBXML_LEGACY_ENABLED
 
7267
                        if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
 
7268
                          xmlAddEntityReference(ent, list, NULL);
 
7269
#endif /* LIBXML_LEGACY_ENABLED */
 
7270
                    }
 
7271
                } else {
 
7272
                    ent->owner = 1;
 
7273
                    while (list != NULL) {
 
7274
                        list->parent = (xmlNodePtr) ent;
 
7275
                        xmlSetTreeDoc(list, ent->doc);
 
7276
                        if (list->next == NULL)
 
7277
                            ent->last = list;
 
7278
                        list = list->next;
 
7279
                    }
 
7280
                }
 
7281
            } else {
 
7282
                xmlFreeNodeList(list);
 
7283
                list = NULL;
 
7284
            }
 
7285
        } else if ((ret != XML_ERR_OK) &&
 
7286
                   (ret != XML_WAR_UNDECLARED_ENTITY)) {
 
7287
            xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
 
7288
                     "Entity '%s' failed to parse\n", ent->name);
 
7289
        } else if (list != NULL) {
 
7290
            xmlFreeNodeList(list);
 
7291
            list = NULL;
 
7292
        }
 
7293
        if (ent->checked == 0)
 
7294
            ent->checked = 2;
 
7295
    } else if (ent->checked != 1) {
 
7296
        ctxt->nbentities += ent->checked / 2;
 
7297
    }
 
7298
 
 
7299
    /*
 
7300
     * Now that the entity content has been gathered
 
7301
     * provide it to the application, this can take different forms based
 
7302
     * on the parsing modes.
 
7303
     */
 
7304
    if (ent->children == NULL) {
 
7305
        /*
 
7306
         * Probably running in SAX mode and the callbacks don't
 
7307
         * build the entity content. So unless we already went
 
7308
         * though parsing for first checking go though the entity
 
7309
         * content to generate callbacks associated to the entity
 
7310
         */
 
7311
        if (was_checked != 0) {
 
7312
            void *user_data;
 
7313
            /*
 
7314
             * This is a bit hackish but this seems the best
 
7315
             * way to make sure both SAX and DOM entity support
 
7316
             * behaves okay.
 
7317
             */
 
7318
            if (ctxt->userData == ctxt)
 
7319
                user_data = NULL;
 
7320
            else
 
7321
                user_data = ctxt->userData;
 
7322
 
 
7323
            if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
 
7324
                ctxt->depth++;
 
7325
                ret = xmlParseBalancedChunkMemoryInternal(ctxt,
 
7326
                                   ent->content, user_data, NULL);
 
7327
                ctxt->depth--;
 
7328
            } else if (ent->etype ==
 
7329
                       XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
 
7330
                ctxt->depth++;
 
7331
                ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt,
 
7332
                           ctxt->sax, user_data, ctxt->depth,
 
7333
                           ent->URI, ent->ExternalID, NULL);
 
7334
                ctxt->depth--;
 
7335
            } else {
 
7336
                ret = XML_ERR_ENTITY_PE_INTERNAL;
 
7337
                xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
 
7338
                             "invalid entity type found\n", NULL);
 
7339
            }
 
7340
            if (ret == XML_ERR_ENTITY_LOOP) {
 
7341
                xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
 
7342
                return;
 
7343
            }
 
7344
        }
 
7345
        if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
 
7346
            (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
 
7347
            /*
 
7348
             * Entity reference callback comes second, it's somewhat
 
7349
             * superfluous but a compatibility to historical behaviour
 
7350
             */
 
7351
            ctxt->sax->reference(ctxt->userData, ent->name);
 
7352
        }
 
7353
        return;
 
7354
    }
 
7355
 
 
7356
    /*
 
7357
     * If we didn't get any children for the entity being built
 
7358
     */
 
7359
    if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
 
7360
        (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
 
7361
        /*
 
7362
         * Create a node.
 
7363
         */
 
7364
        ctxt->sax->reference(ctxt->userData, ent->name);
 
7365
        return;
 
7366
    }
 
7367
 
 
7368
    if ((ctxt->replaceEntities) || (ent->children == NULL))  {
 
7369
        /*
 
7370
         * There is a problem on the handling of _private for entities
 
7371
         * (bug 155816): Should we copy the content of the field from
 
7372
         * the entity (possibly overwriting some value set by the user
 
7373
         * when a copy is created), should we leave it alone, or should
 
7374
         * we try to take care of different situations?  The problem
 
7375
         * is exacerbated by the usage of this field by the xmlReader.
 
7376
         * To fix this bug, we look at _private on the created node
 
7377
         * and, if it's NULL, we copy in whatever was in the entity.
 
7378
         * If it's not NULL we leave it alone.  This is somewhat of a
 
7379
         * hack - maybe we should have further tests to determine
 
7380
         * what to do.
 
7381
         */
 
7382
        if ((ctxt->node != NULL) && (ent->children != NULL)) {
 
7383
            /*
 
7384
             * Seems we are generating the DOM content, do
 
7385
             * a simple tree copy for all references except the first
 
7386
             * In the first occurrence list contains the replacement.
 
7387
             */
 
7388
            if (((list == NULL) && (ent->owner == 0)) ||
 
7389
                (ctxt->parseMode == XML_PARSE_READER)) {
 
7390
                xmlNodePtr nw = NULL, cur, firstChild = NULL;
 
7391
 
 
7392
                /*
 
7393
                 * We are copying here, make sure there is no abuse
 
7394
                 */
 
7395
                ctxt->sizeentcopy += ent->length;
 
7396
                if (xmlParserEntityCheck(ctxt, 0, ent, ctxt->sizeentcopy))
 
7397
                    return;
 
7398
 
 
7399
                /*
 
7400
                 * when operating on a reader, the entities definitions
 
7401
                 * are always owning the entities subtree.
 
7402
                if (ctxt->parseMode == XML_PARSE_READER)
 
7403
                    ent->owner = 1;
 
7404
                 */
 
7405
 
 
7406
                cur = ent->children;
 
7407
                while (cur != NULL) {
 
7408
                    nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
 
7409
                    if (nw != NULL) {
 
7410
                        if (nw->_private == NULL)
 
7411
                            nw->_private = cur->_private;
 
7412
                        if (firstChild == NULL){
 
7413
                            firstChild = nw;
 
7414
                        }
 
7415
                        nw = xmlAddChild(ctxt->node, nw);
 
7416
                    }
 
7417
                    if (cur == ent->last) {
 
7418
                        /*
 
7419
                         * needed to detect some strange empty
 
7420
                         * node cases in the reader tests
 
7421
                         */
 
7422
                        if ((ctxt->parseMode == XML_PARSE_READER) &&
 
7423
                            (nw != NULL) &&
 
7424
                            (nw->type == XML_ELEMENT_NODE) &&
 
7425
                            (nw->children == NULL))
 
7426
                            nw->extra = 1;
 
7427
 
 
7428
                        break;
 
7429
                    }
 
7430
                    cur = cur->next;
 
7431
                }
 
7432
#ifdef LIBXML_LEGACY_ENABLED
 
7433
                if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
 
7434
                  xmlAddEntityReference(ent, firstChild, nw);
 
7435
#endif /* LIBXML_LEGACY_ENABLED */
 
7436
            } else if ((list == NULL) || (ctxt->inputNr > 0)) {
 
7437
                xmlNodePtr nw = NULL, cur, next, last,
 
7438
                           firstChild = NULL;
 
7439
 
 
7440
                /*
 
7441
                 * We are copying here, make sure there is no abuse
 
7442
                 */
 
7443
                ctxt->sizeentcopy += ent->length;
 
7444
                if (xmlParserEntityCheck(ctxt, 0, ent, ctxt->sizeentcopy))
 
7445
                    return;
 
7446
 
 
7447
                /*
 
7448
                 * Copy the entity child list and make it the new
 
7449
                 * entity child list. The goal is to make sure any
 
7450
                 * ID or REF referenced will be the one from the
 
7451
                 * document content and not the entity copy.
 
7452
                 */
 
7453
                cur = ent->children;
 
7454
                ent->children = NULL;
 
7455
                last = ent->last;
 
7456
                ent->last = NULL;
 
7457
                while (cur != NULL) {
 
7458
                    next = cur->next;
 
7459
                    cur->next = NULL;
 
7460
                    cur->parent = NULL;
 
7461
                    nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
 
7462
                    if (nw != NULL) {
 
7463
                        if (nw->_private == NULL)
 
7464
                            nw->_private = cur->_private;
 
7465
                        if (firstChild == NULL){
 
7466
                            firstChild = cur;
 
7467
                        }
 
7468
                        xmlAddChild((xmlNodePtr) ent, nw);
 
7469
                        xmlAddChild(ctxt->node, cur);
 
7470
                    }
 
7471
                    if (cur == last)
 
7472
                        break;
 
7473
                    cur = next;
 
7474
                }
 
7475
                if (ent->owner == 0)
 
7476
                    ent->owner = 1;
 
7477
#ifdef LIBXML_LEGACY_ENABLED
 
7478
                if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
 
7479
                  xmlAddEntityReference(ent, firstChild, nw);
 
7480
#endif /* LIBXML_LEGACY_ENABLED */
 
7481
            } else {
 
7482
                const xmlChar *nbktext;
 
7483
 
 
7484
                /*
 
7485
                 * the name change is to avoid coalescing of the
 
7486
                 * node with a possible previous text one which
 
7487
                 * would make ent->children a dangling pointer
 
7488
                 */
 
7489
                nbktext = xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
 
7490
                                        -1);
 
7491
                if (ent->children->type == XML_TEXT_NODE)
 
7492
                    ent->children->name = nbktext;
 
7493
                if ((ent->last != ent->children) &&
 
7494
                    (ent->last->type == XML_TEXT_NODE))
 
7495
                    ent->last->name = nbktext;
 
7496
                xmlAddChildList(ctxt->node, ent->children);
 
7497
            }
 
7498
 
 
7499
            /*
 
7500
             * This is to avoid a nasty side effect, see
 
7501
             * characters() in SAX.c
 
7502
             */
 
7503
            ctxt->nodemem = 0;
 
7504
            ctxt->nodelen = 0;
 
7505
            return;
 
7506
        }
 
7507
    }
 
7508
}
 
7509
 
 
7510
/**
 
7511
 * xmlParseEntityRef:
 
7512
 * @ctxt:  an XML parser context
 
7513
 *
 
7514
 * parse ENTITY references declarations
 
7515
 *
 
7516
 * [68] EntityRef ::= '&' Name ';'
 
7517
 *
 
7518
 * [ WFC: Entity Declared ]
 
7519
 * In a document without any DTD, a document with only an internal DTD
 
7520
 * subset which contains no parameter entity references, or a document
 
7521
 * with "standalone='yes'", the Name given in the entity reference
 
7522
 * must match that in an entity declaration, except that well-formed
 
7523
 * documents need not declare any of the following entities: amp, lt,
 
7524
 * gt, apos, quot.  The declaration of a parameter entity must precede
 
7525
 * any reference to it.  Similarly, the declaration of a general entity
 
7526
 * must precede any reference to it which appears in a default value in an
 
7527
 * attribute-list declaration. Note that if entities are declared in the
 
7528
 * external subset or in external parameter entities, a non-validating
 
7529
 * processor is not obligated to read and process their declarations;
 
7530
 * for such documents, the rule that an entity must be declared is a
 
7531
 * well-formedness constraint only if standalone='yes'.
 
7532
 *
 
7533
 * [ WFC: Parsed Entity ]
 
7534
 * An entity reference must not contain the name of an unparsed entity
 
7535
 *
 
7536
 * Returns the xmlEntityPtr if found, or NULL otherwise.
 
7537
 */
 
7538
xmlEntityPtr
 
7539
xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
 
7540
    const xmlChar *name;
 
7541
    xmlEntityPtr ent = NULL;
 
7542
 
 
7543
    GROW;
 
7544
    if (ctxt->instate == XML_PARSER_EOF)
 
7545
        return(NULL);
 
7546
 
 
7547
    if (RAW != '&')
 
7548
        return(NULL);
 
7549
    NEXT;
 
7550
    name = xmlParseName(ctxt);
 
7551
    if (name == NULL) {
 
7552
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
7553
                       "xmlParseEntityRef: no name\n");
 
7554
        return(NULL);
 
7555
    }
 
7556
    if (RAW != ';') {
 
7557
        xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
 
7558
        return(NULL);
 
7559
    }
 
7560
    NEXT;
 
7561
 
 
7562
    /*
 
7563
     * Predefined entities override any extra definition
 
7564
     */
 
7565
    if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
 
7566
        ent = xmlGetPredefinedEntity(name);
 
7567
        if (ent != NULL)
 
7568
            return(ent);
 
7569
    }
 
7570
 
 
7571
    /*
 
7572
     * Increase the number of entity references parsed
 
7573
     */
 
7574
    ctxt->nbentities++;
 
7575
 
 
7576
    /*
 
7577
     * Ask first SAX for entity resolution, otherwise try the
 
7578
     * entities which may have stored in the parser context.
 
7579
     */
 
7580
    if (ctxt->sax != NULL) {
 
7581
        if (ctxt->sax->getEntity != NULL)
 
7582
            ent = ctxt->sax->getEntity(ctxt->userData, name);
 
7583
        if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
 
7584
            (ctxt->options & XML_PARSE_OLDSAX))
 
7585
            ent = xmlGetPredefinedEntity(name);
 
7586
        if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
 
7587
            (ctxt->userData==ctxt)) {
 
7588
            ent = xmlSAX2GetEntity(ctxt, name);
 
7589
        }
 
7590
    }
 
7591
    if (ctxt->instate == XML_PARSER_EOF)
 
7592
        return(NULL);
 
7593
    /*
 
7594
     * [ WFC: Entity Declared ]
 
7595
     * In a document without any DTD, a document with only an
 
7596
     * internal DTD subset which contains no parameter entity
 
7597
     * references, or a document with "standalone='yes'", the
 
7598
     * Name given in the entity reference must match that in an
 
7599
     * entity declaration, except that well-formed documents
 
7600
     * need not declare any of the following entities: amp, lt,
 
7601
     * gt, apos, quot.
 
7602
     * The declaration of a parameter entity must precede any
 
7603
     * reference to it.
 
7604
     * Similarly, the declaration of a general entity must
 
7605
     * precede any reference to it which appears in a default
 
7606
     * value in an attribute-list declaration. Note that if
 
7607
     * entities are declared in the external subset or in
 
7608
     * external parameter entities, a non-validating processor
 
7609
     * is not obligated to read and process their declarations;
 
7610
     * for such documents, the rule that an entity must be
 
7611
     * declared is a well-formedness constraint only if
 
7612
     * standalone='yes'.
 
7613
     */
 
7614
    if (ent == NULL) {
 
7615
        if ((ctxt->standalone == 1) ||
 
7616
            ((ctxt->hasExternalSubset == 0) &&
 
7617
             (ctxt->hasPErefs == 0))) {
 
7618
            xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
 
7619
                     "Entity '%s' not defined\n", name);
 
7620
        } else {
 
7621
            xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
 
7622
                     "Entity '%s' not defined\n", name);
 
7623
            if ((ctxt->inSubset == 0) &&
 
7624
                (ctxt->sax != NULL) &&
 
7625
                (ctxt->sax->reference != NULL)) {
 
7626
                ctxt->sax->reference(ctxt->userData, name);
 
7627
            }
 
7628
        }
 
7629
        ctxt->valid = 0;
 
7630
    }
 
7631
 
 
7632
    /*
 
7633
     * [ WFC: Parsed Entity ]
 
7634
     * An entity reference must not contain the name of an
 
7635
     * unparsed entity
 
7636
     */
 
7637
    else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
 
7638
        xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
 
7639
                 "Entity reference to unparsed entity %s\n", name);
 
7640
    }
 
7641
 
 
7642
    /*
 
7643
     * [ WFC: No External Entity References ]
 
7644
     * Attribute values cannot contain direct or indirect
 
7645
     * entity references to external entities.
 
7646
     */
 
7647
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
 
7648
             (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
 
7649
        xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
 
7650
             "Attribute references external entity '%s'\n", name);
 
7651
    }
 
7652
    /*
 
7653
     * [ WFC: No < in Attribute Values ]
 
7654
     * The replacement text of any entity referred to directly or
 
7655
     * indirectly in an attribute value (other than "&lt;") must
 
7656
     * not contain a <.
 
7657
     */
 
7658
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
 
7659
             (ent != NULL) && 
 
7660
             (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
 
7661
        if ((ent->checked & 1) || ((ent->checked == 0) &&
 
7662
             (ent->content != NULL) &&(xmlStrchr(ent->content, '<')))) {
 
7663
            xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
 
7664
        "'<' in entity '%s' is not allowed in attributes values\n", name);
 
7665
        }
 
7666
    }
 
7667
 
 
7668
    /*
 
7669
     * Internal check, no parameter entities here ...
 
7670
     */
 
7671
    else {
 
7672
        switch (ent->etype) {
 
7673
            case XML_INTERNAL_PARAMETER_ENTITY:
 
7674
            case XML_EXTERNAL_PARAMETER_ENTITY:
 
7675
            xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
 
7676
             "Attempt to reference the parameter entity '%s'\n",
 
7677
                              name);
 
7678
            break;
 
7679
            default:
 
7680
            break;
 
7681
        }
 
7682
    }
 
7683
 
 
7684
    /*
 
7685
     * [ WFC: No Recursion ]
 
7686
     * A parsed entity must not contain a recursive reference
 
7687
     * to itself, either directly or indirectly.
 
7688
     * Done somewhere else
 
7689
     */
 
7690
    return(ent);
 
7691
}
 
7692
 
 
7693
/**
 
7694
 * xmlParseStringEntityRef:
 
7695
 * @ctxt:  an XML parser context
 
7696
 * @str:  a pointer to an index in the string
 
7697
 *
 
7698
 * parse ENTITY references declarations, but this version parses it from
 
7699
 * a string value.
 
7700
 *
 
7701
 * [68] EntityRef ::= '&' Name ';'
 
7702
 *
 
7703
 * [ WFC: Entity Declared ]
 
7704
 * In a document without any DTD, a document with only an internal DTD
 
7705
 * subset which contains no parameter entity references, or a document
 
7706
 * with "standalone='yes'", the Name given in the entity reference
 
7707
 * must match that in an entity declaration, except that well-formed
 
7708
 * documents need not declare any of the following entities: amp, lt,
 
7709
 * gt, apos, quot.  The declaration of a parameter entity must precede
 
7710
 * any reference to it.  Similarly, the declaration of a general entity
 
7711
 * must precede any reference to it which appears in a default value in an
 
7712
 * attribute-list declaration. Note that if entities are declared in the
 
7713
 * external subset or in external parameter entities, a non-validating
 
7714
 * processor is not obligated to read and process their declarations;
 
7715
 * for such documents, the rule that an entity must be declared is a
 
7716
 * well-formedness constraint only if standalone='yes'.
 
7717
 *
 
7718
 * [ WFC: Parsed Entity ]
 
7719
 * An entity reference must not contain the name of an unparsed entity
 
7720
 *
 
7721
 * Returns the xmlEntityPtr if found, or NULL otherwise. The str pointer
 
7722
 * is updated to the current location in the string.
 
7723
 */
 
7724
static xmlEntityPtr
 
7725
xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
 
7726
    xmlChar *name;
 
7727
    const xmlChar *ptr;
 
7728
    xmlChar cur;
 
7729
    xmlEntityPtr ent = NULL;
 
7730
 
 
7731
    if ((str == NULL) || (*str == NULL))
 
7732
        return(NULL);
 
7733
    ptr = *str;
 
7734
    cur = *ptr;
 
7735
    if (cur != '&')
 
7736
        return(NULL);
 
7737
 
 
7738
    ptr++;
 
7739
    name = xmlParseStringName(ctxt, &ptr);
 
7740
    if (name == NULL) {
 
7741
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
7742
                       "xmlParseStringEntityRef: no name\n");
 
7743
        *str = ptr;
 
7744
        return(NULL);
 
7745
    }
 
7746
    if (*ptr != ';') {
 
7747
        xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
 
7748
        xmlFree(name);
 
7749
        *str = ptr;
 
7750
        return(NULL);
 
7751
    }
 
7752
    ptr++;
 
7753
 
 
7754
 
 
7755
    /*
 
7756
     * Predefined entites override any extra definition
 
7757
     */
 
7758
    if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
 
7759
        ent = xmlGetPredefinedEntity(name);
 
7760
        if (ent != NULL) {
 
7761
            xmlFree(name);
 
7762
            *str = ptr;
 
7763
            return(ent);
 
7764
        }
 
7765
    }
 
7766
 
 
7767
    /*
 
7768
     * Increate the number of entity references parsed
 
7769
     */
 
7770
    ctxt->nbentities++;
 
7771
 
 
7772
    /*
 
7773
     * Ask first SAX for entity resolution, otherwise try the
 
7774
     * entities which may have stored in the parser context.
 
7775
     */
 
7776
    if (ctxt->sax != NULL) {
 
7777
        if (ctxt->sax->getEntity != NULL)
 
7778
            ent = ctxt->sax->getEntity(ctxt->userData, name);
 
7779
        if ((ent == NULL) && (ctxt->options & XML_PARSE_OLDSAX))
 
7780
            ent = xmlGetPredefinedEntity(name);
 
7781
        if ((ent == NULL) && (ctxt->userData==ctxt)) {
 
7782
            ent = xmlSAX2GetEntity(ctxt, name);
 
7783
        }
 
7784
    }
 
7785
    if (ctxt->instate == XML_PARSER_EOF) {
 
7786
        xmlFree(name);
 
7787
        return(NULL);
 
7788
    }
 
7789
 
 
7790
    /*
 
7791
     * [ WFC: Entity Declared ]
 
7792
     * In a document without any DTD, a document with only an
 
7793
     * internal DTD subset which contains no parameter entity
 
7794
     * references, or a document with "standalone='yes'", the
 
7795
     * Name given in the entity reference must match that in an
 
7796
     * entity declaration, except that well-formed documents
 
7797
     * need not declare any of the following entities: amp, lt,
 
7798
     * gt, apos, quot.
 
7799
     * The declaration of a parameter entity must precede any
 
7800
     * reference to it.
 
7801
     * Similarly, the declaration of a general entity must
 
7802
     * precede any reference to it which appears in a default
 
7803
     * value in an attribute-list declaration. Note that if
 
7804
     * entities are declared in the external subset or in
 
7805
     * external parameter entities, a non-validating processor
 
7806
     * is not obligated to read and process their declarations;
 
7807
     * for such documents, the rule that an entity must be
 
7808
     * declared is a well-formedness constraint only if
 
7809
     * standalone='yes'.
 
7810
     */
 
7811
    if (ent == NULL) {
 
7812
        if ((ctxt->standalone == 1) ||
 
7813
            ((ctxt->hasExternalSubset == 0) &&
 
7814
             (ctxt->hasPErefs == 0))) {
 
7815
            xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
 
7816
                     "Entity '%s' not defined\n", name);
 
7817
        } else {
 
7818
            xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
 
7819
                          "Entity '%s' not defined\n",
 
7820
                          name);
 
7821
        }
 
7822
        /* TODO ? check regressions ctxt->valid = 0; */
 
7823
    }
 
7824
 
 
7825
    /*
 
7826
     * [ WFC: Parsed Entity ]
 
7827
     * An entity reference must not contain the name of an
 
7828
     * unparsed entity
 
7829
     */
 
7830
    else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
 
7831
        xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
 
7832
                 "Entity reference to unparsed entity %s\n", name);
 
7833
    }
 
7834
 
 
7835
    /*
 
7836
     * [ WFC: No External Entity References ]
 
7837
     * Attribute values cannot contain direct or indirect
 
7838
     * entity references to external entities.
 
7839
     */
 
7840
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
 
7841
             (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
 
7842
        xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
 
7843
         "Attribute references external entity '%s'\n", name);
 
7844
    }
 
7845
    /*
 
7846
     * [ WFC: No < in Attribute Values ]
 
7847
     * The replacement text of any entity referred to directly or
 
7848
     * indirectly in an attribute value (other than "&lt;") must
 
7849
     * not contain a <.
 
7850
     */
 
7851
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
 
7852
             (ent != NULL) && (ent->content != NULL) &&
 
7853
             (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
 
7854
             (xmlStrchr(ent->content, '<'))) {
 
7855
        xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
 
7856
     "'<' in entity '%s' is not allowed in attributes values\n",
 
7857
                          name);
 
7858
    }
 
7859
 
 
7860
    /*
 
7861
     * Internal check, no parameter entities here ...
 
7862
     */
 
7863
    else {
 
7864
        switch (ent->etype) {
 
7865
            case XML_INTERNAL_PARAMETER_ENTITY:
 
7866
            case XML_EXTERNAL_PARAMETER_ENTITY:
 
7867
                xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
 
7868
             "Attempt to reference the parameter entity '%s'\n",
 
7869
                                  name);
 
7870
            break;
 
7871
            default:
 
7872
            break;
 
7873
        }
 
7874
    }
 
7875
 
 
7876
    /*
 
7877
     * [ WFC: No Recursion ]
 
7878
     * A parsed entity must not contain a recursive reference
 
7879
     * to itself, either directly or indirectly.
 
7880
     * Done somewhere else
 
7881
     */
 
7882
 
 
7883
    xmlFree(name);
 
7884
    *str = ptr;
 
7885
    return(ent);
 
7886
}
 
7887
 
 
7888
/**
 
7889
 * xmlParsePEReference:
 
7890
 * @ctxt:  an XML parser context
 
7891
 *
 
7892
 * parse PEReference declarations
 
7893
 * The entity content is handled directly by pushing it's content as
 
7894
 * a new input stream.
 
7895
 *
 
7896
 * [69] PEReference ::= '%' Name ';'
 
7897
 *
 
7898
 * [ WFC: No Recursion ]
 
7899
 * A parsed entity must not contain a recursive
 
7900
 * reference to itself, either directly or indirectly.
 
7901
 *
 
7902
 * [ WFC: Entity Declared ]
 
7903
 * In a document without any DTD, a document with only an internal DTD
 
7904
 * subset which contains no parameter entity references, or a document
 
7905
 * with "standalone='yes'", ...  ... The declaration of a parameter
 
7906
 * entity must precede any reference to it...
 
7907
 *
 
7908
 * [ VC: Entity Declared ]
 
7909
 * In a document with an external subset or external parameter entities
 
7910
 * with "standalone='no'", ...  ... The declaration of a parameter entity
 
7911
 * must precede any reference to it...
 
7912
 *
 
7913
 * [ WFC: In DTD ]
 
7914
 * Parameter-entity references may only appear in the DTD.
 
7915
 * NOTE: misleading but this is handled.
 
7916
 */
 
7917
void
 
7918
xmlParsePEReference(xmlParserCtxtPtr ctxt)
 
7919
{
 
7920
    const xmlChar *name;
 
7921
    xmlEntityPtr entity = NULL;
 
7922
    xmlParserInputPtr input;
 
7923
 
 
7924
    if (RAW != '%')
 
7925
        return;
 
7926
    NEXT;
 
7927
    name = xmlParseName(ctxt);
 
7928
    if (name == NULL) {
 
7929
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
7930
                       "xmlParsePEReference: no name\n");
 
7931
        return;
 
7932
    }
 
7933
    if (RAW != ';') {
 
7934
        xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
 
7935
        return;
 
7936
    }
 
7937
 
 
7938
    NEXT;
 
7939
 
 
7940
    /*
 
7941
     * Increate the number of entity references parsed
 
7942
     */
 
7943
    ctxt->nbentities++;
 
7944
 
 
7945
    /*
 
7946
     * Request the entity from SAX
 
7947
     */
 
7948
    if ((ctxt->sax != NULL) &&
 
7949
        (ctxt->sax->getParameterEntity != NULL))
 
7950
        entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
 
7951
    if (ctxt->instate == XML_PARSER_EOF)
 
7952
        return;
 
7953
    if (entity == NULL) {
 
7954
        /*
 
7955
         * [ WFC: Entity Declared ]
 
7956
         * In a document without any DTD, a document with only an
 
7957
         * internal DTD subset which contains no parameter entity
 
7958
         * references, or a document with "standalone='yes'", ...
 
7959
         * ... The declaration of a parameter entity must precede
 
7960
         * any reference to it...
 
7961
         */
 
7962
        if ((ctxt->standalone == 1) ||
 
7963
            ((ctxt->hasExternalSubset == 0) &&
 
7964
             (ctxt->hasPErefs == 0))) {
 
7965
            xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
 
7966
                              "PEReference: %%%s; not found\n",
 
7967
                              name);
 
7968
        } else {
 
7969
            /*
 
7970
             * [ VC: Entity Declared ]
 
7971
             * In a document with an external subset or external
 
7972
             * parameter entities with "standalone='no'", ...
 
7973
             * ... The declaration of a parameter entity must
 
7974
             * precede any reference to it...
 
7975
             */
 
7976
            xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
 
7977
                          "PEReference: %%%s; not found\n",
 
7978
                          name, NULL);
 
7979
            ctxt->valid = 0;
 
7980
        }
 
7981
    } else {
 
7982
        /*
 
7983
         * Internal checking in case the entity quest barfed
 
7984
         */
 
7985
        if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
 
7986
            (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
 
7987
            xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
 
7988
                  "Internal: %%%s; is not a parameter entity\n",
 
7989
                          name, NULL);
 
7990
        } else if (ctxt->input->free != deallocblankswrapper) {
 
7991
            input = xmlNewBlanksWrapperInputStream(ctxt, entity);
 
7992
            if (xmlPushInput(ctxt, input) < 0)
 
7993
                return;
 
7994
        } else {
 
7995
            /*
 
7996
             * TODO !!!
 
7997
             * handle the extra spaces added before and after
 
7998
             * c.f. http://www.w3.org/TR/REC-xml#as-PE
 
7999
             */
 
8000
            input = xmlNewEntityInputStream(ctxt, entity);
 
8001
            if (xmlPushInput(ctxt, input) < 0)
 
8002
                return;
 
8003
            if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
 
8004
                (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) &&
 
8005
                (IS_BLANK_CH(NXT(5)))) {
 
8006
                xmlParseTextDecl(ctxt);
 
8007
                if (ctxt->errNo ==
 
8008
                    XML_ERR_UNSUPPORTED_ENCODING) {
 
8009
                    /*
 
8010
                     * The XML REC instructs us to stop parsing
 
8011
                     * right here
 
8012
                     */
 
8013
                    ctxt->instate = XML_PARSER_EOF;
 
8014
                    return;
 
8015
                }
 
8016
            }
 
8017
        }
 
8018
    }
 
8019
    ctxt->hasPErefs = 1;
 
8020
}
 
8021
 
 
8022
/**
 
8023
 * xmlLoadEntityContent:
 
8024
 * @ctxt:  an XML parser context
 
8025
 * @entity: an unloaded system entity
 
8026
 *
 
8027
 * Load the original content of the given system entity from the
 
8028
 * ExternalID/SystemID given. This is to be used for Included in Literal
 
8029
 * http://www.w3.org/TR/REC-xml/#inliteral processing of entities references
 
8030
 *
 
8031
 * Returns 0 in case of success and -1 in case of failure
 
8032
 */
 
8033
static int
 
8034
xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
 
8035
    xmlParserInputPtr input;
 
8036
    xmlBufferPtr buf;
 
8037
    int l, c;
 
8038
    int count = 0;
 
8039
 
 
8040
    if ((ctxt == NULL) || (entity == NULL) ||
 
8041
        ((entity->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
 
8042
         (entity->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY)) ||
 
8043
        (entity->content != NULL)) {
 
8044
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
8045
                    "xmlLoadEntityContent parameter error");
 
8046
        return(-1);
 
8047
    }
 
8048
 
 
8049
    if (xmlParserDebugEntities)
 
8050
        xmlGenericError(xmlGenericErrorContext,
 
8051
                "Reading %s entity content input\n", entity->name);
 
8052
 
 
8053
    buf = xmlBufferCreate();
 
8054
    if (buf == NULL) {
 
8055
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
8056
                    "xmlLoadEntityContent parameter error");
 
8057
        return(-1);
 
8058
    }
 
8059
 
 
8060
    input = xmlNewEntityInputStream(ctxt, entity);
 
8061
    if (input == NULL) {
 
8062
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
8063
                    "xmlLoadEntityContent input error");
 
8064
        xmlBufferFree(buf);
 
8065
        return(-1);
 
8066
    }
 
8067
 
 
8068
    /*
 
8069
     * Push the entity as the current input, read char by char
 
8070
     * saving to the buffer until the end of the entity or an error
 
8071
     */
 
8072
    if (xmlPushInput(ctxt, input) < 0) {
 
8073
        xmlBufferFree(buf);
 
8074
        return(-1);
 
8075
    }
 
8076
 
 
8077
    GROW;
 
8078
    c = CUR_CHAR(l);
 
8079
    while ((ctxt->input == input) && (ctxt->input->cur < ctxt->input->end) &&
 
8080
           (IS_CHAR(c))) {
 
8081
        xmlBufferAdd(buf, ctxt->input->cur, l);
 
8082
        if (count++ > XML_PARSER_CHUNK_SIZE) {
 
8083
            count = 0;
 
8084
            GROW;
 
8085
            if (ctxt->instate == XML_PARSER_EOF) {
 
8086
                xmlBufferFree(buf);
 
8087
                return(-1);
 
8088
            }
 
8089
        }
 
8090
        NEXTL(l);
 
8091
        c = CUR_CHAR(l);
 
8092
        if (c == 0) {
 
8093
            count = 0;
 
8094
            GROW;
 
8095
            if (ctxt->instate == XML_PARSER_EOF) {
 
8096
                xmlBufferFree(buf);
 
8097
                return(-1);
 
8098
            }
 
8099
            c = CUR_CHAR(l);
 
8100
        }
 
8101
    }
 
8102
 
 
8103
    if ((ctxt->input == input) && (ctxt->input->cur >= ctxt->input->end)) {
 
8104
        xmlPopInput(ctxt);
 
8105
    } else if (!IS_CHAR(c)) {
 
8106
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
 
8107
                          "xmlLoadEntityContent: invalid char value %d\n",
 
8108
                          c);
 
8109
        xmlBufferFree(buf);
 
8110
        return(-1);
 
8111
    }
 
8112
    entity->content = buf->content;
 
8113
    buf->content = NULL;
 
8114
    xmlBufferFree(buf);
 
8115
 
 
8116
    return(0);
 
8117
}
 
8118
 
 
8119
/**
 
8120
 * xmlParseStringPEReference:
 
8121
 * @ctxt:  an XML parser context
 
8122
 * @str:  a pointer to an index in the string
 
8123
 *
 
8124
 * parse PEReference declarations
 
8125
 *
 
8126
 * [69] PEReference ::= '%' Name ';'
 
8127
 *
 
8128
 * [ WFC: No Recursion ]
 
8129
 * A parsed entity must not contain a recursive
 
8130
 * reference to itself, either directly or indirectly.
 
8131
 *
 
8132
 * [ WFC: Entity Declared ]
 
8133
 * In a document without any DTD, a document with only an internal DTD
 
8134
 * subset which contains no parameter entity references, or a document
 
8135
 * with "standalone='yes'", ...  ... The declaration of a parameter
 
8136
 * entity must precede any reference to it...
 
8137
 *
 
8138
 * [ VC: Entity Declared ]
 
8139
 * In a document with an external subset or external parameter entities
 
8140
 * with "standalone='no'", ...  ... The declaration of a parameter entity
 
8141
 * must precede any reference to it...
 
8142
 *
 
8143
 * [ WFC: In DTD ]
 
8144
 * Parameter-entity references may only appear in the DTD.
 
8145
 * NOTE: misleading but this is handled.
 
8146
 *
 
8147
 * Returns the string of the entity content.
 
8148
 *         str is updated to the current value of the index
 
8149
 */
 
8150
static xmlEntityPtr
 
8151
xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
 
8152
    const xmlChar *ptr;
 
8153
    xmlChar cur;
 
8154
    xmlChar *name;
 
8155
    xmlEntityPtr entity = NULL;
 
8156
 
 
8157
    if ((str == NULL) || (*str == NULL)) return(NULL);
 
8158
    ptr = *str;
 
8159
    cur = *ptr;
 
8160
    if (cur != '%')
 
8161
        return(NULL);
 
8162
    ptr++;
 
8163
    name = xmlParseStringName(ctxt, &ptr);
 
8164
    if (name == NULL) {
 
8165
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
8166
                       "xmlParseStringPEReference: no name\n");
 
8167
        *str = ptr;
 
8168
        return(NULL);
 
8169
    }
 
8170
    cur = *ptr;
 
8171
    if (cur != ';') {
 
8172
        xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
 
8173
        xmlFree(name);
 
8174
        *str = ptr;
 
8175
        return(NULL);
 
8176
    }
 
8177
    ptr++;
 
8178
 
 
8179
    /*
 
8180
     * Increate the number of entity references parsed
 
8181
     */
 
8182
    ctxt->nbentities++;
 
8183
 
 
8184
    /*
 
8185
     * Request the entity from SAX
 
8186
     */
 
8187
    if ((ctxt->sax != NULL) &&
 
8188
        (ctxt->sax->getParameterEntity != NULL))
 
8189
        entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
 
8190
    if (ctxt->instate == XML_PARSER_EOF) {
 
8191
        xmlFree(name);
 
8192
        return(NULL);
 
8193
    }
 
8194
    if (entity == NULL) {
 
8195
        /*
 
8196
         * [ WFC: Entity Declared ]
 
8197
         * In a document without any DTD, a document with only an
 
8198
         * internal DTD subset which contains no parameter entity
 
8199
         * references, or a document with "standalone='yes'", ...
 
8200
         * ... The declaration of a parameter entity must precede
 
8201
         * any reference to it...
 
8202
         */
 
8203
        if ((ctxt->standalone == 1) ||
 
8204
            ((ctxt->hasExternalSubset == 0) && (ctxt->hasPErefs == 0))) {
 
8205
            xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
 
8206
                 "PEReference: %%%s; not found\n", name);
 
8207
        } else {
 
8208
            /*
 
8209
             * [ VC: Entity Declared ]
 
8210
             * In a document with an external subset or external
 
8211
             * parameter entities with "standalone='no'", ...
 
8212
             * ... The declaration of a parameter entity must
 
8213
             * precede any reference to it...
 
8214
             */
 
8215
            xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
 
8216
                          "PEReference: %%%s; not found\n",
 
8217
                          name, NULL);
 
8218
            ctxt->valid = 0;
 
8219
        }
 
8220
    } else {
 
8221
        /*
 
8222
         * Internal checking in case the entity quest barfed
 
8223
         */
 
8224
        if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
 
8225
            (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
 
8226
            xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
 
8227
                          "%%%s; is not a parameter entity\n",
 
8228
                          name, NULL);
 
8229
        }
 
8230
    }
 
8231
    ctxt->hasPErefs = 1;
 
8232
    xmlFree(name);
 
8233
    *str = ptr;
 
8234
    return(entity);
 
8235
}
 
8236
 
 
8237
/**
 
8238
 * xmlParseDocTypeDecl:
 
8239
 * @ctxt:  an XML parser context
 
8240
 *
 
8241
 * parse a DOCTYPE declaration
 
8242
 *
 
8243
 * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
 
8244
 *                      ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
 
8245
 *
 
8246
 * [ VC: Root Element Type ]
 
8247
 * The Name in the document type declaration must match the element
 
8248
 * type of the root element.
 
8249
 */
 
8250
 
 
8251
void
 
8252
xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
 
8253
    const xmlChar *name = NULL;
 
8254
    xmlChar *ExternalID = NULL;
 
8255
    xmlChar *URI = NULL;
 
8256
 
 
8257
    /*
 
8258
     * We know that '<!DOCTYPE' has been detected.
 
8259
     */
 
8260
    SKIP(9);
 
8261
 
 
8262
    SKIP_BLANKS;
 
8263
 
 
8264
    /*
 
8265
     * Parse the DOCTYPE name.
 
8266
     */
 
8267
    name = xmlParseName(ctxt);
 
8268
    if (name == NULL) {
 
8269
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
8270
                       "xmlParseDocTypeDecl : no DOCTYPE name !\n");
 
8271
    }
 
8272
    ctxt->intSubName = name;
 
8273
 
 
8274
    SKIP_BLANKS;
 
8275
 
 
8276
    /*
 
8277
     * Check for SystemID and ExternalID
 
8278
     */
 
8279
    URI = xmlParseExternalID(ctxt, &ExternalID, 1);
 
8280
 
 
8281
    if ((URI != NULL) || (ExternalID != NULL)) {
 
8282
        ctxt->hasExternalSubset = 1;
 
8283
    }
 
8284
    ctxt->extSubURI = URI;
 
8285
    ctxt->extSubSystem = ExternalID;
 
8286
 
 
8287
    SKIP_BLANKS;
 
8288
 
 
8289
    /*
 
8290
     * Create and update the internal subset.
 
8291
     */
 
8292
    if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL) &&
 
8293
        (!ctxt->disableSAX))
 
8294
        ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
 
8295
    if (ctxt->instate == XML_PARSER_EOF)
 
8296
        return;
 
8297
 
 
8298
    /*
 
8299
     * Is there any internal subset declarations ?
 
8300
     * they are handled separately in xmlParseInternalSubset()
 
8301
     */
 
8302
    if (RAW == '[')
 
8303
        return;
 
8304
 
 
8305
    /*
 
8306
     * We should be at the end of the DOCTYPE declaration.
 
8307
     */
 
8308
    if (RAW != '>') {
 
8309
        xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
 
8310
    }
 
8311
    NEXT;
 
8312
}
 
8313
 
 
8314
/**
 
8315
 * xmlParseInternalSubset:
 
8316
 * @ctxt:  an XML parser context
 
8317
 *
 
8318
 * parse the internal subset declaration
 
8319
 *
 
8320
 * [28 end] ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
 
8321
 */
 
8322
 
 
8323
static void
 
8324
xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
 
8325
    /*
 
8326
     * Is there any DTD definition ?
 
8327
     */
 
8328
    if (RAW == '[') {
 
8329
        ctxt->instate = XML_PARSER_DTD;
 
8330
        NEXT;
 
8331
        /*
 
8332
         * Parse the succession of Markup declarations and
 
8333
         * PEReferences.
 
8334
         * Subsequence (markupdecl | PEReference | S)*
 
8335
         */
 
8336
        while ((RAW != ']') && (ctxt->instate != XML_PARSER_EOF)) {
 
8337
            const xmlChar *check = CUR_PTR;
 
8338
            unsigned int cons = ctxt->input->consumed;
 
8339
 
 
8340
            SKIP_BLANKS;
 
8341
            xmlParseMarkupDecl(ctxt);
 
8342
            xmlParsePEReference(ctxt);
 
8343
 
 
8344
            /*
 
8345
             * Pop-up of finished entities.
 
8346
             */
 
8347
            while ((RAW == 0) && (ctxt->inputNr > 1))
 
8348
                xmlPopInput(ctxt);
 
8349
 
 
8350
            if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
 
8351
                xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
8352
             "xmlParseInternalSubset: error detected in Markup declaration\n");
 
8353
                break;
 
8354
            }
 
8355
        }
 
8356
        if (RAW == ']') {
 
8357
            NEXT;
 
8358
            SKIP_BLANKS;
 
8359
        }
 
8360
    }
 
8361
 
 
8362
    /*
 
8363
     * We should be at the end of the DOCTYPE declaration.
 
8364
     */
 
8365
    if (RAW != '>') {
 
8366
        xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
 
8367
    }
 
8368
    NEXT;
 
8369
}
 
8370
 
 
8371
#ifdef LIBXML_SAX1_ENABLED
 
8372
/**
 
8373
 * xmlParseAttribute:
 
8374
 * @ctxt:  an XML parser context
 
8375
 * @value:  a xmlChar ** used to store the value of the attribute
 
8376
 *
 
8377
 * parse an attribute
 
8378
 *
 
8379
 * [41] Attribute ::= Name Eq AttValue
 
8380
 *
 
8381
 * [ WFC: No External Entity References ]
 
8382
 * Attribute values cannot contain direct or indirect entity references
 
8383
 * to external entities.
 
8384
 *
 
8385
 * [ WFC: No < in Attribute Values ]
 
8386
 * The replacement text of any entity referred to directly or indirectly in
 
8387
 * an attribute value (other than "&lt;") must not contain a <.
 
8388
 *
 
8389
 * [ VC: Attribute Value Type ]
 
8390
 * The attribute must have been declared; the value must be of the type
 
8391
 * declared for it.
 
8392
 *
 
8393
 * [25] Eq ::= S? '=' S?
 
8394
 *
 
8395
 * With namespace:
 
8396
 *
 
8397
 * [NS 11] Attribute ::= QName Eq AttValue
 
8398
 *
 
8399
 * Also the case QName == xmlns:??? is handled independently as a namespace
 
8400
 * definition.
 
8401
 *
 
8402
 * Returns the attribute name, and the value in *value.
 
8403
 */
 
8404
 
 
8405
const xmlChar *
 
8406
xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
 
8407
    const xmlChar *name;
 
8408
    xmlChar *val;
 
8409
 
 
8410
    *value = NULL;
 
8411
    GROW;
 
8412
    name = xmlParseName(ctxt);
 
8413
    if (name == NULL) {
 
8414
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
8415
                       "error parsing attribute name\n");
 
8416
        return(NULL);
 
8417
    }
 
8418
 
 
8419
    /*
 
8420
     * read the value
 
8421
     */
 
8422
    SKIP_BLANKS;
 
8423
    if (RAW == '=') {
 
8424
        NEXT;
 
8425
        SKIP_BLANKS;
 
8426
        val = xmlParseAttValue(ctxt);
 
8427
        ctxt->instate = XML_PARSER_CONTENT;
 
8428
    } else {
 
8429
        xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
 
8430
               "Specification mandate value for attribute %s\n", name);
 
8431
        return(NULL);
 
8432
    }
 
8433
 
 
8434
    /*
 
8435
     * Check that xml:lang conforms to the specification
 
8436
     * No more registered as an error, just generate a warning now
 
8437
     * since this was deprecated in XML second edition
 
8438
     */
 
8439
    if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "xml:lang"))) {
 
8440
        if (!xmlCheckLanguageID(val)) {
 
8441
            xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
 
8442
                          "Malformed value for xml:lang : %s\n",
 
8443
                          val, NULL);
 
8444
        }
 
8445
    }
 
8446
 
 
8447
    /*
 
8448
     * Check that xml:space conforms to the specification
 
8449
     */
 
8450
    if (xmlStrEqual(name, BAD_CAST "xml:space")) {
 
8451
        if (xmlStrEqual(val, BAD_CAST "default"))
 
8452
            *(ctxt->space) = 0;
 
8453
        else if (xmlStrEqual(val, BAD_CAST "preserve"))
 
8454
            *(ctxt->space) = 1;
 
8455
        else {
 
8456
                xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
 
8457
"Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
 
8458
                                 val, NULL);
 
8459
        }
 
8460
    }
 
8461
 
 
8462
    *value = val;
 
8463
    return(name);
 
8464
}
 
8465
 
 
8466
/**
 
8467
 * xmlParseStartTag:
 
8468
 * @ctxt:  an XML parser context
 
8469
 *
 
8470
 * parse a start of tag either for rule element or
 
8471
 * EmptyElement. In both case we don't parse the tag closing chars.
 
8472
 *
 
8473
 * [40] STag ::= '<' Name (S Attribute)* S? '>'
 
8474
 *
 
8475
 * [ WFC: Unique Att Spec ]
 
8476
 * No attribute name may appear more than once in the same start-tag or
 
8477
 * empty-element tag.
 
8478
 *
 
8479
 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
 
8480
 *
 
8481
 * [ WFC: Unique Att Spec ]
 
8482
 * No attribute name may appear more than once in the same start-tag or
 
8483
 * empty-element tag.
 
8484
 *
 
8485
 * With namespace:
 
8486
 *
 
8487
 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
 
8488
 *
 
8489
 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
 
8490
 *
 
8491
 * Returns the element name parsed
 
8492
 */
 
8493
 
 
8494
const xmlChar *
 
8495
xmlParseStartTag(xmlParserCtxtPtr ctxt) {
 
8496
    const xmlChar *name;
 
8497
    const xmlChar *attname;
 
8498
    xmlChar *attvalue;
 
8499
    const xmlChar **atts = ctxt->atts;
 
8500
    int nbatts = 0;
 
8501
    int maxatts = ctxt->maxatts;
 
8502
    int i;
 
8503
 
 
8504
    if (RAW != '<') return(NULL);
 
8505
    NEXT1;
 
8506
 
 
8507
    name = xmlParseName(ctxt);
 
8508
    if (name == NULL) {
 
8509
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
8510
             "xmlParseStartTag: invalid element name\n");
 
8511
        return(NULL);
 
8512
    }
 
8513
 
 
8514
    /*
 
8515
     * Now parse the attributes, it ends up with the ending
 
8516
     *
 
8517
     * (S Attribute)* S?
 
8518
     */
 
8519
    SKIP_BLANKS;
 
8520
    GROW;
 
8521
 
 
8522
    while (((RAW != '>') &&
 
8523
           ((RAW != '/') || (NXT(1) != '>')) &&
 
8524
           (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) {
 
8525
        const xmlChar *q = CUR_PTR;
 
8526
        unsigned int cons = ctxt->input->consumed;
 
8527
 
 
8528
        attname = xmlParseAttribute(ctxt, &attvalue);
 
8529
        if ((attname != NULL) && (attvalue != NULL)) {
 
8530
            /*
 
8531
             * [ WFC: Unique Att Spec ]
 
8532
             * No attribute name may appear more than once in the same
 
8533
             * start-tag or empty-element tag.
 
8534
             */
 
8535
            for (i = 0; i < nbatts;i += 2) {
 
8536
                if (xmlStrEqual(atts[i], attname)) {
 
8537
                    xmlErrAttributeDup(ctxt, NULL, attname);
 
8538
                    xmlFree(attvalue);
 
8539
                    goto failed;
 
8540
                }
 
8541
            }
 
8542
            /*
 
8543
             * Add the pair to atts
 
8544
             */
 
8545
            if (atts == NULL) {
 
8546
                maxatts = 22; /* allow for 10 attrs by default */
 
8547
                atts = (const xmlChar **)
 
8548
                       xmlMalloc(maxatts * sizeof(xmlChar *));
 
8549
                if (atts == NULL) {
 
8550
                    xmlErrMemory(ctxt, NULL);
 
8551
                    if (attvalue != NULL)
 
8552
                        xmlFree(attvalue);
 
8553
                    goto failed;
 
8554
                }
 
8555
                ctxt->atts = atts;
 
8556
                ctxt->maxatts = maxatts;
 
8557
            } else if (nbatts + 4 > maxatts) {
 
8558
                const xmlChar **n;
 
8559
 
 
8560
                maxatts *= 2;
 
8561
                n = (const xmlChar **) xmlRealloc((void *) atts,
 
8562
                                             maxatts * sizeof(const xmlChar *));
 
8563
                if (n == NULL) {
 
8564
                    xmlErrMemory(ctxt, NULL);
 
8565
                    if (attvalue != NULL)
 
8566
                        xmlFree(attvalue);
 
8567
                    goto failed;
 
8568
                }
 
8569
                atts = n;
 
8570
                ctxt->atts = atts;
 
8571
                ctxt->maxatts = maxatts;
 
8572
            }
 
8573
            atts[nbatts++] = attname;
 
8574
            atts[nbatts++] = attvalue;
 
8575
            atts[nbatts] = NULL;
 
8576
            atts[nbatts + 1] = NULL;
 
8577
        } else {
 
8578
            if (attvalue != NULL)
 
8579
                xmlFree(attvalue);
 
8580
        }
 
8581
 
 
8582
failed:
 
8583
 
 
8584
        GROW
 
8585
        if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
 
8586
            break;
 
8587
        if (!IS_BLANK_CH(RAW)) {
 
8588
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
8589
                           "attributes construct error\n");
 
8590
        }
 
8591
        SKIP_BLANKS;
 
8592
        if ((cons == ctxt->input->consumed) && (q == CUR_PTR) &&
 
8593
            (attname == NULL) && (attvalue == NULL)) {
 
8594
            xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
 
8595
                           "xmlParseStartTag: problem parsing attributes\n");
 
8596
            break;
 
8597
        }
 
8598
        SHRINK;
 
8599
        GROW;
 
8600
    }
 
8601
 
 
8602
    /*
 
8603
     * SAX: Start of Element !
 
8604
     */
 
8605
    if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL) &&
 
8606
        (!ctxt->disableSAX)) {
 
8607
        if (nbatts > 0)
 
8608
            ctxt->sax->startElement(ctxt->userData, name, atts);
 
8609
        else
 
8610
            ctxt->sax->startElement(ctxt->userData, name, NULL);
 
8611
    }
 
8612
 
 
8613
    if (atts != NULL) {
 
8614
        /* Free only the content strings */
 
8615
        for (i = 1;i < nbatts;i+=2)
 
8616
            if (atts[i] != NULL)
 
8617
               xmlFree((xmlChar *) atts[i]);
 
8618
    }
 
8619
    return(name);
 
8620
}
 
8621
 
 
8622
/**
 
8623
 * xmlParseEndTag1:
 
8624
 * @ctxt:  an XML parser context
 
8625
 * @line:  line of the start tag
 
8626
 * @nsNr:  number of namespaces on the start tag
 
8627
 *
 
8628
 * parse an end of tag
 
8629
 *
 
8630
 * [42] ETag ::= '</' Name S? '>'
 
8631
 *
 
8632
 * With namespace
 
8633
 *
 
8634
 * [NS 9] ETag ::= '</' QName S? '>'
 
8635
 */
 
8636
 
 
8637
static void
 
8638
xmlParseEndTag1(xmlParserCtxtPtr ctxt, int line) {
 
8639
    const xmlChar *name;
 
8640
 
 
8641
    GROW;
 
8642
    if ((RAW != '<') || (NXT(1) != '/')) {
 
8643
        xmlFatalErrMsg(ctxt, XML_ERR_LTSLASH_REQUIRED,
 
8644
                       "xmlParseEndTag: '</' not found\n");
 
8645
        return;
 
8646
    }
 
8647
    SKIP(2);
 
8648
 
 
8649
    name = xmlParseNameAndCompare(ctxt,ctxt->name);
 
8650
 
 
8651
    /*
 
8652
     * We should definitely be at the ending "S? '>'" part
 
8653
     */
 
8654
    GROW;
 
8655
    SKIP_BLANKS;
 
8656
    if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
 
8657
        xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
 
8658
    } else
 
8659
        NEXT1;
 
8660
 
 
8661
    /*
 
8662
     * [ WFC: Element Type Match ]
 
8663
     * The Name in an element's end-tag must match the element type in the
 
8664
     * start-tag.
 
8665
     *
 
8666
     */
 
8667
    if (name != (xmlChar*)1) {
 
8668
        if (name == NULL) name = BAD_CAST "unparseable";
 
8669
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
 
8670
                     "Opening and ending tag mismatch: %s line %d and %s\n",
 
8671
                                ctxt->name, line, name);
 
8672
    }
 
8673
 
 
8674
    /*
 
8675
     * SAX: End of Tag
 
8676
     */
 
8677
    if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
 
8678
        (!ctxt->disableSAX))
 
8679
        ctxt->sax->endElement(ctxt->userData, ctxt->name);
 
8680
 
 
8681
    namePop(ctxt);
 
8682
    spacePop(ctxt);
 
8683
    return;
 
8684
}
 
8685
 
 
8686
/**
 
8687
 * xmlParseEndTag:
 
8688
 * @ctxt:  an XML parser context
 
8689
 *
 
8690
 * parse an end of tag
 
8691
 *
 
8692
 * [42] ETag ::= '</' Name S? '>'
 
8693
 *
 
8694
 * With namespace
 
8695
 *
 
8696
 * [NS 9] ETag ::= '</' QName S? '>'
 
8697
 */
 
8698
 
 
8699
void
 
8700
xmlParseEndTag(xmlParserCtxtPtr ctxt) {
 
8701
    xmlParseEndTag1(ctxt, 0);
 
8702
}
 
8703
#endif /* LIBXML_SAX1_ENABLED */
 
8704
 
 
8705
/************************************************************************
 
8706
 *                                                                      *
 
8707
 *                    SAX 2 specific operations                         *
 
8708
 *                                                                      *
 
8709
 ************************************************************************/
 
8710
 
 
8711
/*
 
8712
 * xmlGetNamespace:
 
8713
 * @ctxt:  an XML parser context
 
8714
 * @prefix:  the prefix to lookup
 
8715
 *
 
8716
 * Lookup the namespace name for the @prefix (which ca be NULL)
 
8717
 * The prefix must come from the @ctxt->dict dictionnary
 
8718
 *
 
8719
 * Returns the namespace name or NULL if not bound
 
8720
 */
 
8721
static const xmlChar *
 
8722
xmlGetNamespace(xmlParserCtxtPtr ctxt, const xmlChar *prefix) {
 
8723
    int i;
 
8724
 
 
8725
    if (prefix == ctxt->str_xml) return(ctxt->str_xml_ns);
 
8726
    for (i = ctxt->nsNr - 2;i >= 0;i-=2)
 
8727
        if (ctxt->nsTab[i] == prefix) {
 
8728
            if ((prefix == NULL) && (*ctxt->nsTab[i + 1] == 0))
 
8729
                return(NULL);
 
8730
            return(ctxt->nsTab[i + 1]);
 
8731
        }
 
8732
    return(NULL);
 
8733
}
 
8734
 
 
8735
/**
 
8736
 * xmlParseQName:
 
8737
 * @ctxt:  an XML parser context
 
8738
 * @prefix:  pointer to store the prefix part
 
8739
 *
 
8740
 * parse an XML Namespace QName
 
8741
 *
 
8742
 * [6]  QName  ::= (Prefix ':')? LocalPart
 
8743
 * [7]  Prefix  ::= NCName
 
8744
 * [8]  LocalPart  ::= NCName
 
8745
 *
 
8746
 * Returns the Name parsed or NULL
 
8747
 */
 
8748
 
 
8749
static const xmlChar *
 
8750
xmlParseQName(xmlParserCtxtPtr ctxt, const xmlChar **prefix) {
 
8751
    const xmlChar *l, *p;
 
8752
 
 
8753
    GROW;
 
8754
 
 
8755
    l = xmlParseNCName(ctxt);
 
8756
    if (l == NULL) {
 
8757
        if (CUR == ':') {
 
8758
            l = xmlParseName(ctxt);
 
8759
            if (l != NULL) {
 
8760
                xmlNsErr(ctxt, XML_NS_ERR_QNAME,
 
8761
                         "Failed to parse QName '%s'\n", l, NULL, NULL);
 
8762
                *prefix = NULL;
 
8763
                return(l);
 
8764
            }
 
8765
        }
 
8766
        return(NULL);
 
8767
    }
 
8768
    if (CUR == ':') {
 
8769
        NEXT;
 
8770
        p = l;
 
8771
        l = xmlParseNCName(ctxt);
 
8772
        if (l == NULL) {
 
8773
            xmlChar *tmp;
 
8774
 
 
8775
            xmlNsErr(ctxt, XML_NS_ERR_QNAME,
 
8776
                     "Failed to parse QName '%s:'\n", p, NULL, NULL);
 
8777
            l = xmlParseNmtoken(ctxt);
 
8778
            if (l == NULL)
 
8779
                tmp = xmlBuildQName(BAD_CAST "", p, NULL, 0);
 
8780
            else {
 
8781
                tmp = xmlBuildQName(l, p, NULL, 0);
 
8782
                xmlFree((char *)l);
 
8783
            }
 
8784
            p = xmlDictLookup(ctxt->dict, tmp, -1);
 
8785
            if (tmp != NULL) xmlFree(tmp);
 
8786
            *prefix = NULL;
 
8787
            return(p);
 
8788
        }
 
8789
        if (CUR == ':') {
 
8790
            xmlChar *tmp;
 
8791
 
 
8792
            xmlNsErr(ctxt, XML_NS_ERR_QNAME,
 
8793
                     "Failed to parse QName '%s:%s:'\n", p, l, NULL);
 
8794
            NEXT;
 
8795
            tmp = (xmlChar *) xmlParseName(ctxt);
 
8796
            if (tmp != NULL) {
 
8797
                tmp = xmlBuildQName(tmp, l, NULL, 0);
 
8798
                l = xmlDictLookup(ctxt->dict, tmp, -1);
 
8799
                if (tmp != NULL) xmlFree(tmp);
 
8800
                *prefix = p;
 
8801
                return(l);
 
8802
            }
 
8803
            tmp = xmlBuildQName(BAD_CAST "", l, NULL, 0);
 
8804
            l = xmlDictLookup(ctxt->dict, tmp, -1);
 
8805
            if (tmp != NULL) xmlFree(tmp);
 
8806
            *prefix = p;
 
8807
            return(l);
 
8808
        }
 
8809
        *prefix = p;
 
8810
    } else
 
8811
        *prefix = NULL;
 
8812
    return(l);
 
8813
}
 
8814
 
 
8815
/**
 
8816
 * xmlParseQNameAndCompare:
 
8817
 * @ctxt:  an XML parser context
 
8818
 * @name:  the localname
 
8819
 * @prefix:  the prefix, if any.
 
8820
 *
 
8821
 * parse an XML name and compares for match
 
8822
 * (specialized for endtag parsing)
 
8823
 *
 
8824
 * Returns NULL for an illegal name, (xmlChar*) 1 for success
 
8825
 * and the name for mismatch
 
8826
 */
 
8827
 
 
8828
static const xmlChar *
 
8829
xmlParseQNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *name,
 
8830
                        xmlChar const *prefix) {
 
8831
    const xmlChar *cmp;
 
8832
    const xmlChar *in;
 
8833
    const xmlChar *ret;
 
8834
    const xmlChar *prefix2;
 
8835
 
 
8836
    if (prefix == NULL) return(xmlParseNameAndCompare(ctxt, name));
 
8837
 
 
8838
    GROW;
 
8839
    in = ctxt->input->cur;
 
8840
 
 
8841
    cmp = prefix;
 
8842
    while (*in != 0 && *in == *cmp) {
 
8843
        ++in;
 
8844
        ++cmp;
 
8845
    }
 
8846
    if ((*cmp == 0) && (*in == ':')) {
 
8847
        in++;
 
8848
        cmp = name;
 
8849
        while (*in != 0 && *in == *cmp) {
 
8850
            ++in;
 
8851
            ++cmp;
 
8852
        }
 
8853
        if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
 
8854
            /* success */
 
8855
            ctxt->input->cur = in;
 
8856
            return((const xmlChar*) 1);
 
8857
        }
 
8858
    }
 
8859
    /*
 
8860
     * all strings coms from the dictionary, equality can be done directly
 
8861
     */
 
8862
    ret = xmlParseQName (ctxt, &prefix2);
 
8863
    if ((ret == name) && (prefix == prefix2))
 
8864
        return((const xmlChar*) 1);
 
8865
    return ret;
 
8866
}
 
8867
 
 
8868
/**
 
8869
 * xmlParseAttValueInternal:
 
8870
 * @ctxt:  an XML parser context
 
8871
 * @len:  attribute len result
 
8872
 * @alloc:  whether the attribute was reallocated as a new string
 
8873
 * @normalize:  if 1 then further non-CDATA normalization must be done
 
8874
 *
 
8875
 * parse a value for an attribute.
 
8876
 * NOTE: if no normalization is needed, the routine will return pointers
 
8877
 *       directly from the data buffer.
 
8878
 *
 
8879
 * 3.3.3 Attribute-Value Normalization:
 
8880
 * Before the value of an attribute is passed to the application or
 
8881
 * checked for validity, the XML processor must normalize it as follows:
 
8882
 * - a character reference is processed by appending the referenced
 
8883
 *   character to the attribute value
 
8884
 * - an entity reference is processed by recursively processing the
 
8885
 *   replacement text of the entity
 
8886
 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
 
8887
 *   appending #x20 to the normalized value, except that only a single
 
8888
 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
 
8889
 *   parsed entity or the literal entity value of an internal parsed entity
 
8890
 * - other characters are processed by appending them to the normalized value
 
8891
 * If the declared value is not CDATA, then the XML processor must further
 
8892
 * process the normalized attribute value by discarding any leading and
 
8893
 * trailing space (#x20) characters, and by replacing sequences of space
 
8894
 * (#x20) characters by a single space (#x20) character.
 
8895
 * All attributes for which no declaration has been read should be treated
 
8896
 * by a non-validating parser as if declared CDATA.
 
8897
 *
 
8898
 * Returns the AttValue parsed or NULL. The value has to be freed by the
 
8899
 *     caller if it was copied, this can be detected by val[*len] == 0.
 
8900
 */
 
8901
 
 
8902
static xmlChar *
 
8903
xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
 
8904
                         int normalize)
 
8905
{
 
8906
    xmlChar limit = 0;
 
8907
    const xmlChar *in = NULL, *start, *end, *last;
 
8908
    xmlChar *ret = NULL;
 
8909
 
 
8910
    GROW;
 
8911
    in = (xmlChar *) CUR_PTR;
 
8912
    if (*in != '"' && *in != '\'') {
 
8913
        xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
 
8914
        return (NULL);
 
8915
    }
 
8916
    ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
 
8917
 
 
8918
    /*
 
8919
     * try to handle in this routine the most common case where no
 
8920
     * allocation of a new string is required and where content is
 
8921
     * pure ASCII.
 
8922
     */
 
8923
    limit = *in++;
 
8924
    end = ctxt->input->end;
 
8925
    start = in;
 
8926
    if (in >= end) {
 
8927
        const xmlChar *oldbase = ctxt->input->base;
 
8928
        GROW;
 
8929
        if (oldbase != ctxt->input->base) {
 
8930
            long delta = ctxt->input->base - oldbase;
 
8931
            start = start + delta;
 
8932
            in = in + delta;
 
8933
        }
 
8934
        end = ctxt->input->end;
 
8935
    }
 
8936
    if (normalize) {
 
8937
        /*
 
8938
         * Skip any leading spaces
 
8939
         */
 
8940
        while ((in < end) && (*in != limit) &&
 
8941
               ((*in == 0x20) || (*in == 0x9) ||
 
8942
                (*in == 0xA) || (*in == 0xD))) {
 
8943
            in++;
 
8944
            start = in;
 
8945
            if (in >= end) {
 
8946
                const xmlChar *oldbase = ctxt->input->base;
 
8947
                GROW;
 
8948
                if (ctxt->instate == XML_PARSER_EOF)
 
8949
                    return(NULL);
 
8950
                if (oldbase != ctxt->input->base) {
 
8951
                    long delta = ctxt->input->base - oldbase;
 
8952
                    start = start + delta;
 
8953
                    in = in + delta;
 
8954
                }
 
8955
                end = ctxt->input->end;
 
8956
                if (((in - start) > XML_MAX_TEXT_LENGTH) &&
 
8957
                    ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
8958
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
 
8959
                                   "AttValue length too long\n");
 
8960
                    return(NULL);
 
8961
                }
 
8962
            }
 
8963
        }
 
8964
        while ((in < end) && (*in != limit) && (*in >= 0x20) &&
 
8965
               (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
 
8966
            if ((*in++ == 0x20) && (*in == 0x20)) break;
 
8967
            if (in >= end) {
 
8968
                const xmlChar *oldbase = ctxt->input->base;
 
8969
                GROW;
 
8970
                if (ctxt->instate == XML_PARSER_EOF)
 
8971
                    return(NULL);
 
8972
                if (oldbase != ctxt->input->base) {
 
8973
                    long delta = ctxt->input->base - oldbase;
 
8974
                    start = start + delta;
 
8975
                    in = in + delta;
 
8976
                }
 
8977
                end = ctxt->input->end;
 
8978
                if (((in - start) > XML_MAX_TEXT_LENGTH) &&
 
8979
                    ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
8980
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
 
8981
                                   "AttValue length too long\n");
 
8982
                    return(NULL);
 
8983
                }
 
8984
            }
 
8985
        }
 
8986
        last = in;
 
8987
        /*
 
8988
         * skip the trailing blanks
 
8989
         */
 
8990
        while ((last[-1] == 0x20) && (last > start)) last--;
 
8991
        while ((in < end) && (*in != limit) &&
 
8992
               ((*in == 0x20) || (*in == 0x9) ||
 
8993
                (*in == 0xA) || (*in == 0xD))) {
 
8994
            in++;
 
8995
            if (in >= end) {
 
8996
                const xmlChar *oldbase = ctxt->input->base;
 
8997
                GROW;
 
8998
                if (ctxt->instate == XML_PARSER_EOF)
 
8999
                    return(NULL);
 
9000
                if (oldbase != ctxt->input->base) {
 
9001
                    long delta = ctxt->input->base - oldbase;
 
9002
                    start = start + delta;
 
9003
                    in = in + delta;
 
9004
                    last = last + delta;
 
9005
                }
 
9006
                end = ctxt->input->end;
 
9007
                if (((in - start) > XML_MAX_TEXT_LENGTH) &&
 
9008
                    ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
9009
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
 
9010
                                   "AttValue length too long\n");
 
9011
                    return(NULL);
 
9012
                }
 
9013
            }
 
9014
        }
 
9015
        if (((in - start) > XML_MAX_TEXT_LENGTH) &&
 
9016
            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
9017
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
 
9018
                           "AttValue length too long\n");
 
9019
            return(NULL);
 
9020
        }
 
9021
        if (*in != limit) goto need_complex;
 
9022
    } else {
 
9023
        while ((in < end) && (*in != limit) && (*in >= 0x20) &&
 
9024
               (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
 
9025
            in++;
 
9026
            if (in >= end) {
 
9027
                const xmlChar *oldbase = ctxt->input->base;
 
9028
                GROW;
 
9029
                if (ctxt->instate == XML_PARSER_EOF)
 
9030
                    return(NULL);
 
9031
                if (oldbase != ctxt->input->base) {
 
9032
                    long delta = ctxt->input->base - oldbase;
 
9033
                    start = start + delta;
 
9034
                    in = in + delta;
 
9035
                }
 
9036
                end = ctxt->input->end;
 
9037
                if (((in - start) > XML_MAX_TEXT_LENGTH) &&
 
9038
                    ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
9039
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
 
9040
                                   "AttValue length too long\n");
 
9041
                    return(NULL);
 
9042
                }
 
9043
            }
 
9044
        }
 
9045
        last = in;
 
9046
        if (((in - start) > XML_MAX_TEXT_LENGTH) &&
 
9047
            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
9048
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
 
9049
                           "AttValue length too long\n");
 
9050
            return(NULL);
 
9051
        }
 
9052
        if (*in != limit) goto need_complex;
 
9053
    }
 
9054
    in++;
 
9055
    if (len != NULL) {
 
9056
        *len = last - start;
 
9057
        ret = (xmlChar *) start;
 
9058
    } else {
 
9059
        if (alloc) *alloc = 1;
 
9060
        ret = xmlStrndup(start, last - start);
 
9061
    }
 
9062
    CUR_PTR = in;
 
9063
    if (alloc) *alloc = 0;
 
9064
    return ret;
 
9065
need_complex:
 
9066
    if (alloc) *alloc = 1;
 
9067
    return xmlParseAttValueComplex(ctxt, len, normalize);
 
9068
}
 
9069
 
 
9070
/**
 
9071
 * xmlParseAttribute2:
 
9072
 * @ctxt:  an XML parser context
 
9073
 * @pref:  the element prefix
 
9074
 * @elem:  the element name
 
9075
 * @prefix:  a xmlChar ** used to store the value of the attribute prefix
 
9076
 * @value:  a xmlChar ** used to store the value of the attribute
 
9077
 * @len:  an int * to save the length of the attribute
 
9078
 * @alloc:  an int * to indicate if the attribute was allocated
 
9079
 *
 
9080
 * parse an attribute in the new SAX2 framework.
 
9081
 *
 
9082
 * Returns the attribute name, and the value in *value, .
 
9083
 */
 
9084
 
 
9085
static const xmlChar *
 
9086
xmlParseAttribute2(xmlParserCtxtPtr ctxt,
 
9087
                   const xmlChar * pref, const xmlChar * elem,
 
9088
                   const xmlChar ** prefix, xmlChar ** value,
 
9089
                   int *len, int *alloc)
 
9090
{
 
9091
    const xmlChar *name;
 
9092
    xmlChar *val, *internal_val = NULL;
 
9093
    int normalize = 0;
 
9094
 
 
9095
    *value = NULL;
 
9096
    GROW;
 
9097
    name = xmlParseQName(ctxt, prefix);
 
9098
    if (name == NULL) {
 
9099
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
9100
                       "error parsing attribute name\n");
 
9101
        return (NULL);
 
9102
    }
 
9103
 
 
9104
    /*
 
9105
     * get the type if needed
 
9106
     */
 
9107
    if (ctxt->attsSpecial != NULL) {
 
9108
        int type;
 
9109
 
 
9110
        type = (int) (long) xmlHashQLookup2(ctxt->attsSpecial,
 
9111
                                            pref, elem, *prefix, name);
 
9112
        if (type != 0)
 
9113
            normalize = 1;
 
9114
    }
 
9115
 
 
9116
    /*
 
9117
     * read the value
 
9118
     */
 
9119
    SKIP_BLANKS;
 
9120
    if (RAW == '=') {
 
9121
        NEXT;
 
9122
        SKIP_BLANKS;
 
9123
        val = xmlParseAttValueInternal(ctxt, len, alloc, normalize);
 
9124
        if (normalize) {
 
9125
            /*
 
9126
             * Sometimes a second normalisation pass for spaces is needed
 
9127
             * but that only happens if charrefs or entities refernces
 
9128
             * have been used in the attribute value, i.e. the attribute
 
9129
             * value have been extracted in an allocated string already.
 
9130
             */
 
9131
            if (*alloc) {
 
9132
                const xmlChar *val2;
 
9133
 
 
9134
                val2 = xmlAttrNormalizeSpace2(ctxt, val, len);
 
9135
                if ((val2 != NULL) && (val2 != val)) {
 
9136
                    xmlFree(val);
 
9137
                    val = (xmlChar *) val2;
 
9138
                }
 
9139
            }
 
9140
        }
 
9141
        ctxt->instate = XML_PARSER_CONTENT;
 
9142
    } else {
 
9143
        xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
 
9144
                          "Specification mandate value for attribute %s\n",
 
9145
                          name);
 
9146
        return (NULL);
 
9147
    }
 
9148
 
 
9149
    if (*prefix == ctxt->str_xml) {
 
9150
        /*
 
9151
         * Check that xml:lang conforms to the specification
 
9152
         * No more registered as an error, just generate a warning now
 
9153
         * since this was deprecated in XML second edition
 
9154
         */
 
9155
        if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "lang"))) {
 
9156
            internal_val = xmlStrndup(val, *len);
 
9157
            if (!xmlCheckLanguageID(internal_val)) {
 
9158
                xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
 
9159
                              "Malformed value for xml:lang : %s\n",
 
9160
                              internal_val, NULL);
 
9161
            }
 
9162
        }
 
9163
 
 
9164
        /*
 
9165
         * Check that xml:space conforms to the specification
 
9166
         */
 
9167
        if (xmlStrEqual(name, BAD_CAST "space")) {
 
9168
            internal_val = xmlStrndup(val, *len);
 
9169
            if (xmlStrEqual(internal_val, BAD_CAST "default"))
 
9170
                *(ctxt->space) = 0;
 
9171
            else if (xmlStrEqual(internal_val, BAD_CAST "preserve"))
 
9172
                *(ctxt->space) = 1;
 
9173
            else {
 
9174
                xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
 
9175
                              "Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
 
9176
                              internal_val, NULL);
 
9177
            }
 
9178
        }
 
9179
        if (internal_val) {
 
9180
            xmlFree(internal_val);
 
9181
        }
 
9182
    }
 
9183
 
 
9184
    *value = val;
 
9185
    return (name);
 
9186
}
 
9187
/**
 
9188
 * xmlParseStartTag2:
 
9189
 * @ctxt:  an XML parser context
 
9190
 *
 
9191
 * parse a start of tag either for rule element or
 
9192
 * EmptyElement. In both case we don't parse the tag closing chars.
 
9193
 * This routine is called when running SAX2 parsing
 
9194
 *
 
9195
 * [40] STag ::= '<' Name (S Attribute)* S? '>'
 
9196
 *
 
9197
 * [ WFC: Unique Att Spec ]
 
9198
 * No attribute name may appear more than once in the same start-tag or
 
9199
 * empty-element tag.
 
9200
 *
 
9201
 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
 
9202
 *
 
9203
 * [ WFC: Unique Att Spec ]
 
9204
 * No attribute name may appear more than once in the same start-tag or
 
9205
 * empty-element tag.
 
9206
 *
 
9207
 * With namespace:
 
9208
 *
 
9209
 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
 
9210
 *
 
9211
 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
 
9212
 *
 
9213
 * Returns the element name parsed
 
9214
 */
 
9215
 
 
9216
static const xmlChar *
 
9217
xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
 
9218
                  const xmlChar **URI, int *tlen) {
 
9219
    const xmlChar *localname;
 
9220
    const xmlChar *prefix;
 
9221
    const xmlChar *attname;
 
9222
    const xmlChar *aprefix;
 
9223
    const xmlChar *nsname;
 
9224
    xmlChar *attvalue;
 
9225
    const xmlChar **atts = ctxt->atts;
 
9226
    int maxatts = ctxt->maxatts;
 
9227
    int nratts, nbatts, nbdef;
 
9228
    int i, j, nbNs, attval, oldline, oldcol;
 
9229
    const xmlChar *base;
 
9230
    unsigned long cur;
 
9231
    int nsNr = ctxt->nsNr;
 
9232
 
 
9233
    if (RAW != '<') return(NULL);
 
9234
    NEXT1;
 
9235
 
 
9236
    /*
 
9237
     * NOTE: it is crucial with the SAX2 API to never call SHRINK beyond that
 
9238
     *       point since the attribute values may be stored as pointers to
 
9239
     *       the buffer and calling SHRINK would destroy them !
 
9240
     *       The Shrinking is only possible once the full set of attribute
 
9241
     *       callbacks have been done.
 
9242
     */
 
9243
reparse:
 
9244
    SHRINK;
 
9245
    base = ctxt->input->base;
 
9246
    cur = ctxt->input->cur - ctxt->input->base;
 
9247
    oldline = ctxt->input->line;
 
9248
    oldcol = ctxt->input->col;
 
9249
    nbatts = 0;
 
9250
    nratts = 0;
 
9251
    nbdef = 0;
 
9252
    nbNs = 0;
 
9253
    attval = 0;
 
9254
    /* Forget any namespaces added during an earlier parse of this element. */
 
9255
    ctxt->nsNr = nsNr;
 
9256
 
 
9257
    localname = xmlParseQName(ctxt, &prefix);
 
9258
    if (localname == NULL) {
 
9259
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
9260
                       "StartTag: invalid element name\n");
 
9261
        return(NULL);
 
9262
    }
 
9263
    *tlen = ctxt->input->cur - ctxt->input->base - cur;
 
9264
 
 
9265
    /*
 
9266
     * Now parse the attributes, it ends up with the ending
 
9267
     *
 
9268
     * (S Attribute)* S?
 
9269
     */
 
9270
    SKIP_BLANKS;
 
9271
    GROW;
 
9272
    if (ctxt->input->base != base) goto base_changed;
 
9273
 
 
9274
    while (((RAW != '>') &&
 
9275
           ((RAW != '/') || (NXT(1) != '>')) &&
 
9276
           (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) {
 
9277
        const xmlChar *q = CUR_PTR;
 
9278
        unsigned int cons = ctxt->input->consumed;
 
9279
        int len = -1, alloc = 0;
 
9280
 
 
9281
        attname = xmlParseAttribute2(ctxt, prefix, localname,
 
9282
                                     &aprefix, &attvalue, &len, &alloc);
 
9283
        if (ctxt->input->base != base) {
 
9284
            if ((attvalue != NULL) && (alloc != 0))
 
9285
                xmlFree(attvalue);
 
9286
            attvalue = NULL;
 
9287
            goto base_changed;
 
9288
        }
 
9289
        if ((attname != NULL) && (attvalue != NULL)) {
 
9290
            if (len < 0) len = xmlStrlen(attvalue);
 
9291
            if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
 
9292
                const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
 
9293
                xmlURIPtr uri;
 
9294
 
 
9295
                if (*URL != 0) {
 
9296
                    uri = xmlParseURI((const char *) URL);
 
9297
                    if (uri == NULL) {
 
9298
                        xmlNsErr(ctxt, XML_WAR_NS_URI,
 
9299
                                 "xmlns: '%s' is not a valid URI\n",
 
9300
                                           URL, NULL, NULL);
 
9301
                    } else {
 
9302
                        if (uri->scheme == NULL) {
 
9303
                            xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
 
9304
                                      "xmlns: URI %s is not absolute\n",
 
9305
                                      URL, NULL, NULL);
 
9306
                        }
 
9307
                        xmlFreeURI(uri);
 
9308
                    }
 
9309
                    if (URL == ctxt->str_xml_ns) {
 
9310
                        if (attname != ctxt->str_xml) {
 
9311
                            xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
 
9312
                         "xml namespace URI cannot be the default namespace\n",
 
9313
                                     NULL, NULL, NULL);
 
9314
                        }
 
9315
                        goto skip_default_ns;
 
9316
                    }
 
9317
                    if ((len == 29) &&
 
9318
                        (xmlStrEqual(URL,
 
9319
                                 BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
 
9320
                        xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
 
9321
                             "reuse of the xmlns namespace name is forbidden\n",
 
9322
                                 NULL, NULL, NULL);
 
9323
                        goto skip_default_ns;
 
9324
                    }
 
9325
                }
 
9326
                /*
 
9327
                 * check that it's not a defined namespace
 
9328
                 */
 
9329
                for (j = 1;j <= nbNs;j++)
 
9330
                    if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
 
9331
                        break;
 
9332
                if (j <= nbNs)
 
9333
                    xmlErrAttributeDup(ctxt, NULL, attname);
 
9334
                else
 
9335
                    if (nsPush(ctxt, NULL, URL) > 0) nbNs++;
 
9336
skip_default_ns:
 
9337
                if (alloc != 0) xmlFree(attvalue);
 
9338
                SKIP_BLANKS;
 
9339
                continue;
 
9340
            }
 
9341
            if (aprefix == ctxt->str_xmlns) {
 
9342
                const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
 
9343
                xmlURIPtr uri;
 
9344
 
 
9345
                if (attname == ctxt->str_xml) {
 
9346
                    if (URL != ctxt->str_xml_ns) {
 
9347
                        xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
 
9348
                                 "xml namespace prefix mapped to wrong URI\n",
 
9349
                                 NULL, NULL, NULL);
 
9350
                    }
 
9351
                    /*
 
9352
                     * Do not keep a namespace definition node
 
9353
                     */
 
9354
                    goto skip_ns;
 
9355
                }
 
9356
                if (URL == ctxt->str_xml_ns) {
 
9357
                    if (attname != ctxt->str_xml) {
 
9358
                        xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
 
9359
                                 "xml namespace URI mapped to wrong prefix\n",
 
9360
                                 NULL, NULL, NULL);
 
9361
                    }
 
9362
                    goto skip_ns;
 
9363
                }
 
9364
                if (attname == ctxt->str_xmlns) {
 
9365
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
 
9366
                             "redefinition of the xmlns prefix is forbidden\n",
 
9367
                             NULL, NULL, NULL);
 
9368
                    goto skip_ns;
 
9369
                }
 
9370
                if ((len == 29) &&
 
9371
                    (xmlStrEqual(URL,
 
9372
                                 BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
 
9373
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
 
9374
                             "reuse of the xmlns namespace name is forbidden\n",
 
9375
                             NULL, NULL, NULL);
 
9376
                    goto skip_ns;
 
9377
                }
 
9378
                if ((URL == NULL) || (URL[0] == 0)) {
 
9379
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
 
9380
                             "xmlns:%s: Empty XML namespace is not allowed\n",
 
9381
                                  attname, NULL, NULL);
 
9382
                    goto skip_ns;
 
9383
                } else {
 
9384
                    uri = xmlParseURI((const char *) URL);
 
9385
                    if (uri == NULL) {
 
9386
                        xmlNsErr(ctxt, XML_WAR_NS_URI,
 
9387
                             "xmlns:%s: '%s' is not a valid URI\n",
 
9388
                                           attname, URL, NULL);
 
9389
                    } else {
 
9390
                        if ((ctxt->pedantic) && (uri->scheme == NULL)) {
 
9391
                            xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
 
9392
                                      "xmlns:%s: URI %s is not absolute\n",
 
9393
                                      attname, URL, NULL);
 
9394
                        }
 
9395
                        xmlFreeURI(uri);
 
9396
                    }
 
9397
                }
 
9398
 
 
9399
                /*
 
9400
                 * check that it's not a defined namespace
 
9401
                 */
 
9402
                for (j = 1;j <= nbNs;j++)
 
9403
                    if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
 
9404
                        break;
 
9405
                if (j <= nbNs)
 
9406
                    xmlErrAttributeDup(ctxt, aprefix, attname);
 
9407
                else
 
9408
                    if (nsPush(ctxt, attname, URL) > 0) nbNs++;
 
9409
skip_ns:
 
9410
                if (alloc != 0) xmlFree(attvalue);
 
9411
                SKIP_BLANKS;
 
9412
                if (ctxt->input->base != base) goto base_changed;
 
9413
                continue;
 
9414
            }
 
9415
 
 
9416
            /*
 
9417
             * Add the pair to atts
 
9418
             */
 
9419
            if ((atts == NULL) || (nbatts + 5 > maxatts)) {
 
9420
                if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
 
9421
                    if (attvalue[len] == 0)
 
9422
                        xmlFree(attvalue);
 
9423
                    goto failed;
 
9424
                }
 
9425
                maxatts = ctxt->maxatts;
 
9426
                atts = ctxt->atts;
 
9427
            }
 
9428
            ctxt->attallocs[nratts++] = alloc;
 
9429
            atts[nbatts++] = attname;
 
9430
            atts[nbatts++] = aprefix;
 
9431
            atts[nbatts++] = NULL; /* the URI will be fetched later */
 
9432
            atts[nbatts++] = attvalue;
 
9433
            attvalue += len;
 
9434
            atts[nbatts++] = attvalue;
 
9435
            /*
 
9436
             * tag if some deallocation is needed
 
9437
             */
 
9438
            if (alloc != 0) attval = 1;
 
9439
        } else {
 
9440
            if ((attvalue != NULL) && (attvalue[len] == 0))
 
9441
                xmlFree(attvalue);
 
9442
        }
 
9443
 
 
9444
failed:
 
9445
 
 
9446
        GROW
 
9447
        if (ctxt->instate == XML_PARSER_EOF)
 
9448
            break;
 
9449
        if (ctxt->input->base != base) goto base_changed;
 
9450
        if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
 
9451
            break;
 
9452
        if (!IS_BLANK_CH(RAW)) {
 
9453
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
9454
                           "attributes construct error\n");
 
9455
            break;
 
9456
        }
 
9457
        SKIP_BLANKS;
 
9458
        if ((cons == ctxt->input->consumed) && (q == CUR_PTR) &&
 
9459
            (attname == NULL) && (attvalue == NULL)) {
 
9460
            xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
9461
                 "xmlParseStartTag: problem parsing attributes\n");
 
9462
            break;
 
9463
        }
 
9464
        GROW;
 
9465
        if (ctxt->input->base != base) goto base_changed;
 
9466
    }
 
9467
 
 
9468
    /*
 
9469
     * The attributes defaulting
 
9470
     */
 
9471
    if (ctxt->attsDefault != NULL) {
 
9472
        xmlDefAttrsPtr defaults;
 
9473
 
 
9474
        defaults = xmlHashLookup2(ctxt->attsDefault, localname, prefix);
 
9475
        if (defaults != NULL) {
 
9476
            for (i = 0;i < defaults->nbAttrs;i++) {
 
9477
                attname = defaults->values[5 * i];
 
9478
                aprefix = defaults->values[5 * i + 1];
 
9479
 
 
9480
                /*
 
9481
                 * special work for namespaces defaulted defs
 
9482
                 */
 
9483
                if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
 
9484
                    /*
 
9485
                     * check that it's not a defined namespace
 
9486
                     */
 
9487
                    for (j = 1;j <= nbNs;j++)
 
9488
                        if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
 
9489
                            break;
 
9490
                    if (j <= nbNs) continue;
 
9491
 
 
9492
                    nsname = xmlGetNamespace(ctxt, NULL);
 
9493
                    if (nsname != defaults->values[5 * i + 2]) {
 
9494
                        if (nsPush(ctxt, NULL,
 
9495
                                   defaults->values[5 * i + 2]) > 0)
 
9496
                            nbNs++;
 
9497
                    }
 
9498
                } else if (aprefix == ctxt->str_xmlns) {
 
9499
                    /*
 
9500
                     * check that it's not a defined namespace
 
9501
                     */
 
9502
                    for (j = 1;j <= nbNs;j++)
 
9503
                        if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
 
9504
                            break;
 
9505
                    if (j <= nbNs) continue;
 
9506
 
 
9507
                    nsname = xmlGetNamespace(ctxt, attname);
 
9508
                    if (nsname != defaults->values[2]) {
 
9509
                        if (nsPush(ctxt, attname,
 
9510
                                   defaults->values[5 * i + 2]) > 0)
 
9511
                            nbNs++;
 
9512
                    }
 
9513
                } else {
 
9514
                    /*
 
9515
                     * check that it's not a defined attribute
 
9516
                     */
 
9517
                    for (j = 0;j < nbatts;j+=5) {
 
9518
                        if ((attname == atts[j]) && (aprefix == atts[j+1]))
 
9519
                            break;
 
9520
                    }
 
9521
                    if (j < nbatts) continue;
 
9522
 
 
9523
                    if ((atts == NULL) || (nbatts + 5 > maxatts)) {
 
9524
                        if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
 
9525
                            return(NULL);
 
9526
                        }
 
9527
                        maxatts = ctxt->maxatts;
 
9528
                        atts = ctxt->atts;
 
9529
                    }
 
9530
                    atts[nbatts++] = attname;
 
9531
                    atts[nbatts++] = aprefix;
 
9532
                    if (aprefix == NULL)
 
9533
                        atts[nbatts++] = NULL;
 
9534
                    else
 
9535
                        atts[nbatts++] = xmlGetNamespace(ctxt, aprefix);
 
9536
                    atts[nbatts++] = defaults->values[5 * i + 2];
 
9537
                    atts[nbatts++] = defaults->values[5 * i + 3];
 
9538
                    if ((ctxt->standalone == 1) &&
 
9539
                        (defaults->values[5 * i + 4] != NULL)) {
 
9540
                        xmlValidityError(ctxt, XML_DTD_STANDALONE_DEFAULTED,
 
9541
          "standalone: attribute %s on %s defaulted from external subset\n",
 
9542
                                         attname, localname);
 
9543
                    }
 
9544
                    nbdef++;
 
9545
                }
 
9546
            }
 
9547
        }
 
9548
    }
 
9549
 
 
9550
    /*
 
9551
     * The attributes checkings
 
9552
     */
 
9553
    for (i = 0; i < nbatts;i += 5) {
 
9554
        /*
 
9555
        * The default namespace does not apply to attribute names.
 
9556
        */
 
9557
        if (atts[i + 1] != NULL) {
 
9558
            nsname = xmlGetNamespace(ctxt, atts[i + 1]);
 
9559
            if (nsname == NULL) {
 
9560
                xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
 
9561
                    "Namespace prefix %s for %s on %s is not defined\n",
 
9562
                    atts[i + 1], atts[i], localname);
 
9563
            }
 
9564
            atts[i + 2] = nsname;
 
9565
        } else
 
9566
            nsname = NULL;
 
9567
        /*
 
9568
         * [ WFC: Unique Att Spec ]
 
9569
         * No attribute name may appear more than once in the same
 
9570
         * start-tag or empty-element tag.
 
9571
         * As extended by the Namespace in XML REC.
 
9572
         */
 
9573
        for (j = 0; j < i;j += 5) {
 
9574
            if (atts[i] == atts[j]) {
 
9575
                if (atts[i+1] == atts[j+1]) {
 
9576
                    xmlErrAttributeDup(ctxt, atts[i+1], atts[i]);
 
9577
                    break;
 
9578
                }
 
9579
                if ((nsname != NULL) && (atts[j + 2] == nsname)) {
 
9580
                    xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED,
 
9581
                             "Namespaced Attribute %s in '%s' redefined\n",
 
9582
                             atts[i], nsname, NULL);
 
9583
                    break;
 
9584
                }
 
9585
            }
 
9586
        }
 
9587
    }
 
9588
 
 
9589
    nsname = xmlGetNamespace(ctxt, prefix);
 
9590
    if ((prefix != NULL) && (nsname == NULL)) {
 
9591
        xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
 
9592
                 "Namespace prefix %s on %s is not defined\n",
 
9593
                 prefix, localname, NULL);
 
9594
    }
 
9595
    *pref = prefix;
 
9596
    *URI = nsname;
 
9597
 
 
9598
    /*
 
9599
     * SAX: Start of Element !
 
9600
     */
 
9601
    if ((ctxt->sax != NULL) && (ctxt->sax->startElementNs != NULL) &&
 
9602
        (!ctxt->disableSAX)) {
 
9603
        if (nbNs > 0)
 
9604
            ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
 
9605
                          nsname, nbNs, &ctxt->nsTab[ctxt->nsNr - 2 * nbNs],
 
9606
                          nbatts / 5, nbdef, atts);
 
9607
        else
 
9608
            ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
 
9609
                          nsname, 0, NULL, nbatts / 5, nbdef, atts);
 
9610
    }
 
9611
 
 
9612
    /*
 
9613
     * Free up attribute allocated strings if needed
 
9614
     */
 
9615
    if (attval != 0) {
 
9616
        for (i = 3,j = 0; j < nratts;i += 5,j++)
 
9617
            if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
 
9618
                xmlFree((xmlChar *) atts[i]);
 
9619
    }
 
9620
 
 
9621
    return(localname);
 
9622
 
 
9623
base_changed:
 
9624
    /*
 
9625
     * the attribute strings are valid iif the base didn't changed
 
9626
     */
 
9627
    if (attval != 0) {
 
9628
        for (i = 3,j = 0; j < nratts;i += 5,j++)
 
9629
            if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
 
9630
                xmlFree((xmlChar *) atts[i]);
 
9631
    }
 
9632
    ctxt->input->cur = ctxt->input->base + cur;
 
9633
    ctxt->input->line = oldline;
 
9634
    ctxt->input->col = oldcol;
 
9635
    if (ctxt->wellFormed == 1) {
 
9636
        goto reparse;
 
9637
    }
 
9638
    return(NULL);
 
9639
}
 
9640
 
 
9641
/**
 
9642
 * xmlParseEndTag2:
 
9643
 * @ctxt:  an XML parser context
 
9644
 * @line:  line of the start tag
 
9645
 * @nsNr:  number of namespaces on the start tag
 
9646
 *
 
9647
 * parse an end of tag
 
9648
 *
 
9649
 * [42] ETag ::= '</' Name S? '>'
 
9650
 *
 
9651
 * With namespace
 
9652
 *
 
9653
 * [NS 9] ETag ::= '</' QName S? '>'
 
9654
 */
 
9655
 
 
9656
static void
 
9657
xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlChar *prefix,
 
9658
                const xmlChar *URI, int line, int nsNr, int tlen) {
 
9659
    const xmlChar *name;
 
9660
 
 
9661
    GROW;
 
9662
    if ((RAW != '<') || (NXT(1) != '/')) {
 
9663
        xmlFatalErr(ctxt, XML_ERR_LTSLASH_REQUIRED, NULL);
 
9664
        return;
 
9665
    }
 
9666
    SKIP(2);
 
9667
 
 
9668
    if ((tlen > 0) && (xmlStrncmp(ctxt->input->cur, ctxt->name, tlen) == 0)) {
 
9669
        if (ctxt->input->cur[tlen] == '>') {
 
9670
            ctxt->input->cur += tlen + 1;
 
9671
            goto done;
 
9672
        }
 
9673
        ctxt->input->cur += tlen;
 
9674
        name = (xmlChar*)1;
 
9675
    } else {
 
9676
        if (prefix == NULL)
 
9677
            name = xmlParseNameAndCompare(ctxt, ctxt->name);
 
9678
        else
 
9679
            name = xmlParseQNameAndCompare(ctxt, ctxt->name, prefix);
 
9680
    }
 
9681
 
 
9682
    /*
 
9683
     * We should definitely be at the ending "S? '>'" part
 
9684
     */
 
9685
    GROW;
 
9686
    if (ctxt->instate == XML_PARSER_EOF)
 
9687
        return;
 
9688
    SKIP_BLANKS;
 
9689
    if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
 
9690
        xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
 
9691
    } else
 
9692
        NEXT1;
 
9693
 
 
9694
    /*
 
9695
     * [ WFC: Element Type Match ]
 
9696
     * The Name in an element's end-tag must match the element type in the
 
9697
     * start-tag.
 
9698
     *
 
9699
     */
 
9700
    if (name != (xmlChar*)1) {
 
9701
        if (name == NULL) name = BAD_CAST "unparseable";
 
9702
        if ((line == 0) && (ctxt->node != NULL))
 
9703
            line = ctxt->node->line;
 
9704
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
 
9705
                     "Opening and ending tag mismatch: %s line %d and %s\n",
 
9706
                                ctxt->name, line, name);
 
9707
    }
 
9708
 
 
9709
    /*
 
9710
     * SAX: End of Tag
 
9711
     */
 
9712
done:
 
9713
    if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
 
9714
        (!ctxt->disableSAX))
 
9715
        ctxt->sax->endElementNs(ctxt->userData, ctxt->name, prefix, URI);
 
9716
 
 
9717
    spacePop(ctxt);
 
9718
    if (nsNr != 0)
 
9719
        nsPop(ctxt, nsNr);
 
9720
    return;
 
9721
}
 
9722
 
 
9723
/**
 
9724
 * xmlParseCDSect:
 
9725
 * @ctxt:  an XML parser context
 
9726
 *
 
9727
 * Parse escaped pure raw content.
 
9728
 *
 
9729
 * [18] CDSect ::= CDStart CData CDEnd
 
9730
 *
 
9731
 * [19] CDStart ::= '<![CDATA['
 
9732
 *
 
9733
 * [20] Data ::= (Char* - (Char* ']]>' Char*))
 
9734
 *
 
9735
 * [21] CDEnd ::= ']]>'
 
9736
 */
 
9737
void
 
9738
xmlParseCDSect(xmlParserCtxtPtr ctxt) {
 
9739
    xmlChar *buf = NULL;
 
9740
    int len = 0;
 
9741
    int size = XML_PARSER_BUFFER_SIZE;
 
9742
    int r, rl;
 
9743
    int s, sl;
 
9744
    int cur, l;
 
9745
    int count = 0;
 
9746
 
 
9747
    /* Check 2.6.0 was NXT(0) not RAW */
 
9748
    if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
 
9749
        SKIP(9);
 
9750
    } else
 
9751
        return;
 
9752
 
 
9753
    ctxt->instate = XML_PARSER_CDATA_SECTION;
 
9754
    r = CUR_CHAR(rl);
 
9755
    if (!IS_CHAR(r)) {
 
9756
        xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
 
9757
        ctxt->instate = XML_PARSER_CONTENT;
 
9758
        return;
 
9759
    }
 
9760
    NEXTL(rl);
 
9761
    s = CUR_CHAR(sl);
 
9762
    if (!IS_CHAR(s)) {
 
9763
        xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
 
9764
        ctxt->instate = XML_PARSER_CONTENT;
 
9765
        return;
 
9766
    }
 
9767
    NEXTL(sl);
 
9768
    cur = CUR_CHAR(l);
 
9769
    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
9770
    if (buf == NULL) {
 
9771
        xmlErrMemory(ctxt, NULL);
 
9772
        return;
 
9773
    }
 
9774
    while (IS_CHAR(cur) &&
 
9775
           ((r != ']') || (s != ']') || (cur != '>'))) {
 
9776
        if (len + 5 >= size) {
 
9777
            xmlChar *tmp;
 
9778
 
 
9779
            if ((size > XML_MAX_TEXT_LENGTH) &&
 
9780
                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
9781
                xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED,
 
9782
                             "CData section too big found", NULL);
 
9783
                xmlFree (buf);
 
9784
                return;
 
9785
            }
 
9786
            tmp = (xmlChar *) xmlRealloc(buf, size * 2 * sizeof(xmlChar));
 
9787
            if (tmp == NULL) {
 
9788
                xmlFree(buf);
 
9789
                xmlErrMemory(ctxt, NULL);
 
9790
                return;
 
9791
            }
 
9792
            buf = tmp;
 
9793
            size *= 2;
 
9794
        }
 
9795
        COPY_BUF(rl,buf,len,r);
 
9796
        r = s;
 
9797
        rl = sl;
 
9798
        s = cur;
 
9799
        sl = l;
 
9800
        count++;
 
9801
        if (count > 50) {
 
9802
            GROW;
 
9803
            if (ctxt->instate == XML_PARSER_EOF) {
 
9804
                xmlFree(buf);
 
9805
                return;
 
9806
            }
 
9807
            count = 0;
 
9808
        }
 
9809
        NEXTL(l);
 
9810
        cur = CUR_CHAR(l);
 
9811
    }
 
9812
    buf[len] = 0;
 
9813
    ctxt->instate = XML_PARSER_CONTENT;
 
9814
    if (cur != '>') {
 
9815
        xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED,
 
9816
                             "CData section not finished\n%.50s\n", buf);
 
9817
        xmlFree(buf);
 
9818
        return;
 
9819
    }
 
9820
    NEXTL(l);
 
9821
 
 
9822
    /*
 
9823
     * OK the buffer is to be consumed as cdata.
 
9824
     */
 
9825
    if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
 
9826
        if (ctxt->sax->cdataBlock != NULL)
 
9827
            ctxt->sax->cdataBlock(ctxt->userData, buf, len);
 
9828
        else if (ctxt->sax->characters != NULL)
 
9829
            ctxt->sax->characters(ctxt->userData, buf, len);
 
9830
    }
 
9831
    xmlFree(buf);
 
9832
}
 
9833
 
 
9834
/**
 
9835
 * xmlParseContent:
 
9836
 * @ctxt:  an XML parser context
 
9837
 *
 
9838
 * Parse a content:
 
9839
 *
 
9840
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
 
9841
 */
 
9842
 
 
9843
void
 
9844
xmlParseContent(xmlParserCtxtPtr ctxt) {
 
9845
    GROW;
 
9846
    while ((RAW != 0) &&
 
9847
           ((RAW != '<') || (NXT(1) != '/')) &&
 
9848
           (ctxt->instate != XML_PARSER_EOF)) {
 
9849
        const xmlChar *test = CUR_PTR;
 
9850
        unsigned int cons = ctxt->input->consumed;
 
9851
        const xmlChar *cur = ctxt->input->cur;
 
9852
 
 
9853
        /*
 
9854
         * First case : a Processing Instruction.
 
9855
         */
 
9856
        if ((*cur == '<') && (cur[1] == '?')) {
 
9857
            xmlParsePI(ctxt);
 
9858
        }
 
9859
 
 
9860
        /*
 
9861
         * Second case : a CDSection
 
9862
         */
 
9863
        /* 2.6.0 test was *cur not RAW */
 
9864
        else if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
 
9865
            xmlParseCDSect(ctxt);
 
9866
        }
 
9867
 
 
9868
        /*
 
9869
         * Third case :  a comment
 
9870
         */
 
9871
        else if ((*cur == '<') && (NXT(1) == '!') &&
 
9872
                 (NXT(2) == '-') && (NXT(3) == '-')) {
 
9873
            xmlParseComment(ctxt);
 
9874
            ctxt->instate = XML_PARSER_CONTENT;
 
9875
        }
 
9876
 
 
9877
        /*
 
9878
         * Fourth case :  a sub-element.
 
9879
         */
 
9880
        else if (*cur == '<') {
 
9881
            xmlParseElement(ctxt);
 
9882
        }
 
9883
 
 
9884
        /*
 
9885
         * Fifth case : a reference. If if has not been resolved,
 
9886
         *    parsing returns it's Name, create the node
 
9887
         */
 
9888
 
 
9889
        else if (*cur == '&') {
 
9890
            xmlParseReference(ctxt);
 
9891
        }
 
9892
 
 
9893
        /*
 
9894
         * Last case, text. Note that References are handled directly.
 
9895
         */
 
9896
        else {
 
9897
            xmlParseCharData(ctxt, 0);
 
9898
        }
 
9899
 
 
9900
        GROW;
 
9901
        /*
 
9902
         * Pop-up of finished entities.
 
9903
         */
 
9904
        while ((RAW == 0) && (ctxt->inputNr > 1))
 
9905
            xmlPopInput(ctxt);
 
9906
        SHRINK;
 
9907
 
 
9908
        if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) {
 
9909
            xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
9910
                        "detected an error in element content\n");
 
9911
            ctxt->instate = XML_PARSER_EOF;
 
9912
            break;
 
9913
        }
 
9914
    }
 
9915
}
 
9916
 
 
9917
/**
 
9918
 * xmlParseElement:
 
9919
 * @ctxt:  an XML parser context
 
9920
 *
 
9921
 * parse an XML element, this is highly recursive
 
9922
 *
 
9923
 * [39] element ::= EmptyElemTag | STag content ETag
 
9924
 *
 
9925
 * [ WFC: Element Type Match ]
 
9926
 * The Name in an element's end-tag must match the element type in the
 
9927
 * start-tag.
 
9928
 *
 
9929
 */
 
9930
 
 
9931
void
 
9932
xmlParseElement(xmlParserCtxtPtr ctxt) {
 
9933
    const xmlChar *name;
 
9934
    const xmlChar *prefix = NULL;
 
9935
    const xmlChar *URI = NULL;
 
9936
    xmlParserNodeInfo node_info;
 
9937
    int line, tlen = 0;
 
9938
    xmlNodePtr ret;
 
9939
    int nsNr = ctxt->nsNr;
 
9940
 
 
9941
    if (((unsigned int) ctxt->nameNr > xmlParserMaxDepth) &&
 
9942
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
9943
        xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
 
9944
                 "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
 
9945
                          xmlParserMaxDepth);
 
9946
        ctxt->instate = XML_PARSER_EOF;
 
9947
        return;
 
9948
    }
 
9949
 
 
9950
    /* Capture start position */
 
9951
    if (ctxt->record_info) {
 
9952
        node_info.begin_pos = ctxt->input->consumed +
 
9953
                          (CUR_PTR - ctxt->input->base);
 
9954
        node_info.begin_line = ctxt->input->line;
 
9955
    }
 
9956
 
 
9957
    if (ctxt->spaceNr == 0)
 
9958
        spacePush(ctxt, -1);
 
9959
    else if (*ctxt->space == -2)
 
9960
        spacePush(ctxt, -1);
 
9961
    else
 
9962
        spacePush(ctxt, *ctxt->space);
 
9963
 
 
9964
    line = ctxt->input->line;
 
9965
#ifdef LIBXML_SAX1_ENABLED
 
9966
    if (ctxt->sax2)
 
9967
#endif /* LIBXML_SAX1_ENABLED */
 
9968
        name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
 
9969
#ifdef LIBXML_SAX1_ENABLED
 
9970
    else
 
9971
        name = xmlParseStartTag(ctxt);
 
9972
#endif /* LIBXML_SAX1_ENABLED */
 
9973
    if (ctxt->instate == XML_PARSER_EOF)
 
9974
        return;
 
9975
    if (name == NULL) {
 
9976
        spacePop(ctxt);
 
9977
        return;
 
9978
    }
 
9979
    namePush(ctxt, name);
 
9980
    ret = ctxt->node;
 
9981
 
 
9982
#ifdef LIBXML_VALID_ENABLED
 
9983
    /*
 
9984
     * [ VC: Root Element Type ]
 
9985
     * The Name in the document type declaration must match the element
 
9986
     * type of the root element.
 
9987
     */
 
9988
    if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
 
9989
        ctxt->node && (ctxt->node == ctxt->myDoc->children))
 
9990
        ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
 
9991
#endif /* LIBXML_VALID_ENABLED */
 
9992
 
 
9993
    /*
 
9994
     * Check for an Empty Element.
 
9995
     */
 
9996
    if ((RAW == '/') && (NXT(1) == '>')) {
 
9997
        SKIP(2);
 
9998
        if (ctxt->sax2) {
 
9999
            if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
 
10000
                (!ctxt->disableSAX))
 
10001
                ctxt->sax->endElementNs(ctxt->userData, name, prefix, URI);
 
10002
#ifdef LIBXML_SAX1_ENABLED
 
10003
        } else {
 
10004
            if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
 
10005
                (!ctxt->disableSAX))
 
10006
                ctxt->sax->endElement(ctxt->userData, name);
 
10007
#endif /* LIBXML_SAX1_ENABLED */
 
10008
        }
 
10009
        namePop(ctxt);
 
10010
        spacePop(ctxt);
 
10011
        if (nsNr != ctxt->nsNr)
 
10012
            nsPop(ctxt, ctxt->nsNr - nsNr);
 
10013
        if ( ret != NULL && ctxt->record_info ) {
 
10014
           node_info.end_pos = ctxt->input->consumed +
 
10015
                              (CUR_PTR - ctxt->input->base);
 
10016
           node_info.end_line = ctxt->input->line;
 
10017
           node_info.node = ret;
 
10018
           xmlParserAddNodeInfo(ctxt, &node_info);
 
10019
        }
 
10020
        return;
 
10021
    }
 
10022
    if (RAW == '>') {
 
10023
        NEXT1;
 
10024
    } else {
 
10025
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_GT_REQUIRED,
 
10026
                     "Couldn't find end of Start Tag %s line %d\n",
 
10027
                                name, line, NULL);
 
10028
 
 
10029
        /*
 
10030
         * end of parsing of this node.
 
10031
         */
 
10032
        nodePop(ctxt);
 
10033
        namePop(ctxt);
 
10034
        spacePop(ctxt);
 
10035
        if (nsNr != ctxt->nsNr)
 
10036
            nsPop(ctxt, ctxt->nsNr - nsNr);
 
10037
 
 
10038
        /*
 
10039
         * Capture end position and add node
 
10040
         */
 
10041
        if ( ret != NULL && ctxt->record_info ) {
 
10042
           node_info.end_pos = ctxt->input->consumed +
 
10043
                              (CUR_PTR - ctxt->input->base);
 
10044
           node_info.end_line = ctxt->input->line;
 
10045
           node_info.node = ret;
 
10046
           xmlParserAddNodeInfo(ctxt, &node_info);
 
10047
        }
 
10048
        return;
 
10049
    }
 
10050
 
 
10051
    /*
 
10052
     * Parse the content of the element:
 
10053
     */
 
10054
    xmlParseContent(ctxt);
 
10055
    if (ctxt->instate == XML_PARSER_EOF)
 
10056
        return;
 
10057
    if (!IS_BYTE_CHAR(RAW)) {
 
10058
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
 
10059
         "Premature end of data in tag %s line %d\n",
 
10060
                                name, line, NULL);
 
10061
 
 
10062
        /*
 
10063
         * end of parsing of this node.
 
10064
         */
 
10065
        nodePop(ctxt);
 
10066
        namePop(ctxt);
 
10067
        spacePop(ctxt);
 
10068
        if (nsNr != ctxt->nsNr)
 
10069
            nsPop(ctxt, ctxt->nsNr - nsNr);
 
10070
        return;
 
10071
    }
 
10072
 
 
10073
    /*
 
10074
     * parse the end of tag: '</' should be here.
 
10075
     */
 
10076
    if (ctxt->sax2) {
 
10077
        xmlParseEndTag2(ctxt, prefix, URI, line, ctxt->nsNr - nsNr, tlen);
 
10078
        namePop(ctxt);
 
10079
    }
 
10080
#ifdef LIBXML_SAX1_ENABLED
 
10081
      else
 
10082
        xmlParseEndTag1(ctxt, line);
 
10083
#endif /* LIBXML_SAX1_ENABLED */
 
10084
 
 
10085
    /*
 
10086
     * Capture end position and add node
 
10087
     */
 
10088
    if ( ret != NULL && ctxt->record_info ) {
 
10089
       node_info.end_pos = ctxt->input->consumed +
 
10090
                          (CUR_PTR - ctxt->input->base);
 
10091
       node_info.end_line = ctxt->input->line;
 
10092
       node_info.node = ret;
 
10093
       xmlParserAddNodeInfo(ctxt, &node_info);
 
10094
    }
 
10095
}
 
10096
 
 
10097
/**
 
10098
 * xmlParseVersionNum:
 
10099
 * @ctxt:  an XML parser context
 
10100
 *
 
10101
 * parse the XML version value.
 
10102
 *
 
10103
 * [26] VersionNum ::= '1.' [0-9]+
 
10104
 *
 
10105
 * In practice allow [0-9].[0-9]+ at that level
 
10106
 *
 
10107
 * Returns the string giving the XML version number, or NULL
 
10108
 */
 
10109
xmlChar *
 
10110
xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
 
10111
    xmlChar *buf = NULL;
 
10112
    int len = 0;
 
10113
    int size = 10;
 
10114
    xmlChar cur;
 
10115
 
 
10116
    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
10117
    if (buf == NULL) {
 
10118
        xmlErrMemory(ctxt, NULL);
 
10119
        return(NULL);
 
10120
    }
 
10121
    cur = CUR;
 
10122
    if (!((cur >= '0') && (cur <= '9'))) {
 
10123
        xmlFree(buf);
 
10124
        return(NULL);
 
10125
    }
 
10126
    buf[len++] = cur;
 
10127
    NEXT;
 
10128
    cur=CUR;
 
10129
    if (cur != '.') {
 
10130
        xmlFree(buf);
 
10131
        return(NULL);
 
10132
    }
 
10133
    buf[len++] = cur;
 
10134
    NEXT;
 
10135
    cur=CUR;
 
10136
    while ((cur >= '0') && (cur <= '9')) {
 
10137
        if (len + 1 >= size) {
 
10138
            xmlChar *tmp;
 
10139
 
 
10140
            size *= 2;
 
10141
            tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
 
10142
            if (tmp == NULL) {
 
10143
                xmlFree(buf);
 
10144
                xmlErrMemory(ctxt, NULL);
 
10145
                return(NULL);
 
10146
            }
 
10147
            buf = tmp;
 
10148
        }
 
10149
        buf[len++] = cur;
 
10150
        NEXT;
 
10151
        cur=CUR;
 
10152
    }
 
10153
    buf[len] = 0;
 
10154
    return(buf);
 
10155
}
 
10156
 
 
10157
/**
 
10158
 * xmlParseVersionInfo:
 
10159
 * @ctxt:  an XML parser context
 
10160
 *
 
10161
 * parse the XML version.
 
10162
 *
 
10163
 * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
 
10164
 *
 
10165
 * [25] Eq ::= S? '=' S?
 
10166
 *
 
10167
 * Returns the version string, e.g. "1.0"
 
10168
 */
 
10169
 
 
10170
xmlChar *
 
10171
xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
 
10172
    xmlChar *version = NULL;
 
10173
 
 
10174
    if (CMP7(CUR_PTR, 'v', 'e', 'r', 's', 'i', 'o', 'n')) {
 
10175
        SKIP(7);
 
10176
        SKIP_BLANKS;
 
10177
        if (RAW != '=') {
 
10178
            xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
 
10179
            return(NULL);
 
10180
        }
 
10181
        NEXT;
 
10182
        SKIP_BLANKS;
 
10183
        if (RAW == '"') {
 
10184
            NEXT;
 
10185
            version = xmlParseVersionNum(ctxt);
 
10186
            if (RAW != '"') {
 
10187
                xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
 
10188
            } else
 
10189
                NEXT;
 
10190
        } else if (RAW == '\''){
 
10191
            NEXT;
 
10192
            version = xmlParseVersionNum(ctxt);
 
10193
            if (RAW != '\'') {
 
10194
                xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
 
10195
            } else
 
10196
                NEXT;
 
10197
        } else {
 
10198
            xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
 
10199
        }
 
10200
    }
 
10201
    return(version);
 
10202
}
 
10203
 
 
10204
/**
 
10205
 * xmlParseEncName:
 
10206
 * @ctxt:  an XML parser context
 
10207
 *
 
10208
 * parse the XML encoding name
 
10209
 *
 
10210
 * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
 
10211
 *
 
10212
 * Returns the encoding name value or NULL
 
10213
 */
 
10214
xmlChar *
 
10215
xmlParseEncName(xmlParserCtxtPtr ctxt) {
 
10216
    xmlChar *buf = NULL;
 
10217
    int len = 0;
 
10218
    int size = 10;
 
10219
    xmlChar cur;
 
10220
 
 
10221
    cur = CUR;
 
10222
    if (((cur >= 'a') && (cur <= 'z')) ||
 
10223
        ((cur >= 'A') && (cur <= 'Z'))) {
 
10224
        buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
10225
        if (buf == NULL) {
 
10226
            xmlErrMemory(ctxt, NULL);
 
10227
            return(NULL);
 
10228
        }
 
10229
 
 
10230
        buf[len++] = cur;
 
10231
        NEXT;
 
10232
        cur = CUR;
 
10233
        while (((cur >= 'a') && (cur <= 'z')) ||
 
10234
               ((cur >= 'A') && (cur <= 'Z')) ||
 
10235
               ((cur >= '0') && (cur <= '9')) ||
 
10236
               (cur == '.') || (cur == '_') ||
 
10237
               (cur == '-')) {
 
10238
            if (len + 1 >= size) {
 
10239
                xmlChar *tmp;
 
10240
 
 
10241
                size *= 2;
 
10242
                tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
 
10243
                if (tmp == NULL) {
 
10244
                    xmlErrMemory(ctxt, NULL);
 
10245
                    xmlFree(buf);
 
10246
                    return(NULL);
 
10247
                }
 
10248
                buf = tmp;
 
10249
            }
 
10250
            buf[len++] = cur;
 
10251
            NEXT;
 
10252
            cur = CUR;
 
10253
            if (cur == 0) {
 
10254
                SHRINK;
 
10255
                GROW;
 
10256
                cur = CUR;
 
10257
            }
 
10258
        }
 
10259
        buf[len] = 0;
 
10260
    } else {
 
10261
        xmlFatalErr(ctxt, XML_ERR_ENCODING_NAME, NULL);
 
10262
    }
 
10263
    return(buf);
 
10264
}
 
10265
 
 
10266
/**
 
10267
 * xmlParseEncodingDecl:
 
10268
 * @ctxt:  an XML parser context
 
10269
 *
 
10270
 * parse the XML encoding declaration
 
10271
 *
 
10272
 * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' |  "'" EncName "'")
 
10273
 *
 
10274
 * this setups the conversion filters.
 
10275
 *
 
10276
 * Returns the encoding value or NULL
 
10277
 */
 
10278
 
 
10279
const xmlChar *
 
10280
xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
 
10281
    xmlChar *encoding = NULL;
 
10282
 
 
10283
    SKIP_BLANKS;
 
10284
    if (CMP8(CUR_PTR, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g')) {
 
10285
        SKIP(8);
 
10286
        SKIP_BLANKS;
 
10287
        if (RAW != '=') {
 
10288
            xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
 
10289
            return(NULL);
 
10290
        }
 
10291
        NEXT;
 
10292
        SKIP_BLANKS;
 
10293
        if (RAW == '"') {
 
10294
            NEXT;
 
10295
            encoding = xmlParseEncName(ctxt);
 
10296
            if (RAW != '"') {
 
10297
                xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
 
10298
            } else
 
10299
                NEXT;
 
10300
        } else if (RAW == '\''){
 
10301
            NEXT;
 
10302
            encoding = xmlParseEncName(ctxt);
 
10303
            if (RAW != '\'') {
 
10304
                xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
 
10305
            } else
 
10306
                NEXT;
 
10307
        } else {
 
10308
            xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
 
10309
        }
 
10310
 
 
10311
        /*
 
10312
         * Non standard parsing, allowing the user to ignore encoding
 
10313
         */
 
10314
        if (ctxt->options & XML_PARSE_IGNORE_ENC)
 
10315
            return(encoding);
 
10316
 
 
10317
        /*
 
10318
         * UTF-16 encoding stwich has already taken place at this stage,
 
10319
         * more over the little-endian/big-endian selection is already done
 
10320
         */
 
10321
        if ((encoding != NULL) &&
 
10322
            ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-16")) ||
 
10323
             (!xmlStrcasecmp(encoding, BAD_CAST "UTF16")))) {
 
10324
            /*
 
10325
             * If no encoding was passed to the parser, that we are
 
10326
             * using UTF-16 and no decoder is present i.e. the
 
10327
             * document is apparently UTF-8 compatible, then raise an
 
10328
             * encoding mismatch fatal error
 
10329
             */
 
10330
            if ((ctxt->encoding == NULL) &&
 
10331
                (ctxt->input->buf != NULL) &&
 
10332
                (ctxt->input->buf->encoder == NULL)) {
 
10333
                xmlFatalErrMsg(ctxt, XML_ERR_INVALID_ENCODING,
 
10334
                  "Document labelled UTF-16 but has UTF-8 content\n");
 
10335
            }
 
10336
            if (ctxt->encoding != NULL)
 
10337
                xmlFree((xmlChar *) ctxt->encoding);
 
10338
            ctxt->encoding = encoding;
 
10339
        }
 
10340
        /*
 
10341
         * UTF-8 encoding is handled natively
 
10342
         */
 
10343
        else if ((encoding != NULL) &&
 
10344
            ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-8")) ||
 
10345
             (!xmlStrcasecmp(encoding, BAD_CAST "UTF8")))) {
 
10346
            if (ctxt->encoding != NULL)
 
10347
                xmlFree((xmlChar *) ctxt->encoding);
 
10348
            ctxt->encoding = encoding;
 
10349
        }
 
10350
        else if (encoding != NULL) {
 
10351
            xmlCharEncodingHandlerPtr handler;
 
10352
 
 
10353
            if (ctxt->input->encoding != NULL)
 
10354
                xmlFree((xmlChar *) ctxt->input->encoding);
 
10355
            ctxt->input->encoding = encoding;
 
10356
 
 
10357
            handler = xmlFindCharEncodingHandler((const char *) encoding);
 
10358
            if (handler != NULL) {
 
10359
                xmlSwitchToEncoding(ctxt, handler);
 
10360
            } else {
 
10361
                xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
 
10362
                        "Unsupported encoding %s\n", encoding);
 
10363
                return(NULL);
 
10364
            }
 
10365
        }
 
10366
    }
 
10367
    return(encoding);
 
10368
}
 
10369
 
 
10370
/**
 
10371
 * xmlParseSDDecl:
 
10372
 * @ctxt:  an XML parser context
 
10373
 *
 
10374
 * parse the XML standalone declaration
 
10375
 *
 
10376
 * [32] SDDecl ::= S 'standalone' Eq
 
10377
 *                 (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no')'"'))
 
10378
 *
 
10379
 * [ VC: Standalone Document Declaration ]
 
10380
 * TODO The standalone document declaration must have the value "no"
 
10381
 * if any external markup declarations contain declarations of:
 
10382
 *  - attributes with default values, if elements to which these
 
10383
 *    attributes apply appear in the document without specifications
 
10384
 *    of values for these attributes, or
 
10385
 *  - entities (other than amp, lt, gt, apos, quot), if references
 
10386
 *    to those entities appear in the document, or
 
10387
 *  - attributes with values subject to normalization, where the
 
10388
 *    attribute appears in the document with a value which will change
 
10389
 *    as a result of normalization, or
 
10390
 *  - element types with element content, if white space occurs directly
 
10391
 *    within any instance of those types.
 
10392
 *
 
10393
 * Returns:
 
10394
 *   1 if standalone="yes"
 
10395
 *   0 if standalone="no"
 
10396
 *  -2 if standalone attribute is missing or invalid
 
10397
 *        (A standalone value of -2 means that the XML declaration was found,
 
10398
 *         but no value was specified for the standalone attribute).
 
10399
 */
 
10400
 
 
10401
int
 
10402
xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
 
10403
    int standalone = -2;
 
10404
 
 
10405
    SKIP_BLANKS;
 
10406
    if (CMP10(CUR_PTR, 's', 't', 'a', 'n', 'd', 'a', 'l', 'o', 'n', 'e')) {
 
10407
        SKIP(10);
 
10408
        SKIP_BLANKS;
 
10409
        if (RAW != '=') {
 
10410
            xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
 
10411
            return(standalone);
 
10412
        }
 
10413
        NEXT;
 
10414
        SKIP_BLANKS;
 
10415
        if (RAW == '\''){
 
10416
            NEXT;
 
10417
            if ((RAW == 'n') && (NXT(1) == 'o')) {
 
10418
                standalone = 0;
 
10419
                SKIP(2);
 
10420
            } else if ((RAW == 'y') && (NXT(1) == 'e') &&
 
10421
                       (NXT(2) == 's')) {
 
10422
                standalone = 1;
 
10423
                SKIP(3);
 
10424
            } else {
 
10425
                xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
 
10426
            }
 
10427
            if (RAW != '\'') {
 
10428
                xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
 
10429
            } else
 
10430
                NEXT;
 
10431
        } else if (RAW == '"'){
 
10432
            NEXT;
 
10433
            if ((RAW == 'n') && (NXT(1) == 'o')) {
 
10434
                standalone = 0;
 
10435
                SKIP(2);
 
10436
            } else if ((RAW == 'y') && (NXT(1) == 'e') &&
 
10437
                       (NXT(2) == 's')) {
 
10438
                standalone = 1;
 
10439
                SKIP(3);
 
10440
            } else {
 
10441
                xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
 
10442
            }
 
10443
            if (RAW != '"') {
 
10444
                xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
 
10445
            } else
 
10446
                NEXT;
 
10447
        } else {
 
10448
            xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
 
10449
        }
 
10450
    }
 
10451
    return(standalone);
 
10452
}
 
10453
 
 
10454
/**
 
10455
 * xmlParseXMLDecl:
 
10456
 * @ctxt:  an XML parser context
 
10457
 *
 
10458
 * parse an XML declaration header
 
10459
 *
 
10460
 * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
 
10461
 */
 
10462
 
 
10463
void
 
10464
xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
 
10465
    xmlChar *version;
 
10466
 
 
10467
    /*
 
10468
     * This value for standalone indicates that the document has an
 
10469
     * XML declaration but it does not have a standalone attribute.
 
10470
     * It will be overwritten later if a standalone attribute is found.
 
10471
     */
 
10472
    ctxt->input->standalone = -2;
 
10473
 
 
10474
    /*
 
10475
     * We know that '<?xml' is here.
 
10476
     */
 
10477
    SKIP(5);
 
10478
 
 
10479
    if (!IS_BLANK_CH(RAW)) {
 
10480
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
10481
                       "Blank needed after '<?xml'\n");
 
10482
    }
 
10483
    SKIP_BLANKS;
 
10484
 
 
10485
    /*
 
10486
     * We must have the VersionInfo here.
 
10487
     */
 
10488
    version = xmlParseVersionInfo(ctxt);
 
10489
    if (version == NULL) {
 
10490
        xmlFatalErr(ctxt, XML_ERR_VERSION_MISSING, NULL);
 
10491
    } else {
 
10492
        if (!xmlStrEqual(version, (const xmlChar *) XML_DEFAULT_VERSION)) {
 
10493
            /*
 
10494
             * Changed here for XML-1.0 5th edition
 
10495
             */
 
10496
            if (ctxt->options & XML_PARSE_OLD10) {
 
10497
                xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
 
10498
                                  "Unsupported version '%s'\n",
 
10499
                                  version);
 
10500
            } else {
 
10501
                if ((version[0] == '1') && ((version[1] == '.'))) {
 
10502
                    xmlWarningMsg(ctxt, XML_WAR_UNKNOWN_VERSION,
 
10503
                                  "Unsupported version '%s'\n",
 
10504
                                  version, NULL);
 
10505
                } else {
 
10506
                    xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
 
10507
                                      "Unsupported version '%s'\n",
 
10508
                                      version);
 
10509
                }
 
10510
            }
 
10511
        }
 
10512
        if (ctxt->version != NULL)
 
10513
            xmlFree((void *) ctxt->version);
 
10514
        ctxt->version = version;
 
10515
    }
 
10516
 
 
10517
    /*
 
10518
     * We may have the encoding declaration
 
10519
     */
 
10520
    if (!IS_BLANK_CH(RAW)) {
 
10521
        if ((RAW == '?') && (NXT(1) == '>')) {
 
10522
            SKIP(2);
 
10523
            return;
 
10524
        }
 
10525
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
 
10526
    }
 
10527
    xmlParseEncodingDecl(ctxt);
 
10528
    if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
 
10529
        /*
 
10530
         * The XML REC instructs us to stop parsing right here
 
10531
         */
 
10532
        return;
 
10533
    }
 
10534
 
 
10535
    /*
 
10536
     * We may have the standalone status.
 
10537
     */
 
10538
    if ((ctxt->input->encoding != NULL) && (!IS_BLANK_CH(RAW))) {
 
10539
        if ((RAW == '?') && (NXT(1) == '>')) {
 
10540
            SKIP(2);
 
10541
            return;
 
10542
        }
 
10543
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
 
10544
    }
 
10545
 
 
10546
    /*
 
10547
     * We can grow the input buffer freely at that point
 
10548
     */
 
10549
    GROW;
 
10550
 
 
10551
    SKIP_BLANKS;
 
10552
    ctxt->input->standalone = xmlParseSDDecl(ctxt);
 
10553
 
 
10554
    SKIP_BLANKS;
 
10555
    if ((RAW == '?') && (NXT(1) == '>')) {
 
10556
        SKIP(2);
 
10557
    } else if (RAW == '>') {
 
10558
        /* Deprecated old WD ... */
 
10559
        xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
 
10560
        NEXT;
 
10561
    } else {
 
10562
        xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
 
10563
        MOVETO_ENDTAG(CUR_PTR);
 
10564
        NEXT;
 
10565
    }
 
10566
}
 
10567
 
 
10568
/**
 
10569
 * xmlParseMisc:
 
10570
 * @ctxt:  an XML parser context
 
10571
 *
 
10572
 * parse an XML Misc* optional field.
 
10573
 *
 
10574
 * [27] Misc ::= Comment | PI |  S
 
10575
 */
 
10576
 
 
10577
void
 
10578
xmlParseMisc(xmlParserCtxtPtr ctxt) {
 
10579
    while ((ctxt->instate != XML_PARSER_EOF) &&
 
10580
           (((RAW == '<') && (NXT(1) == '?')) ||
 
10581
            (CMP4(CUR_PTR, '<', '!', '-', '-')) ||
 
10582
            IS_BLANK_CH(CUR))) {
 
10583
        if ((RAW == '<') && (NXT(1) == '?')) {
 
10584
            xmlParsePI(ctxt);
 
10585
        } else if (IS_BLANK_CH(CUR)) {
 
10586
            NEXT;
 
10587
        } else
 
10588
            xmlParseComment(ctxt);
 
10589
    }
 
10590
}
 
10591
 
 
10592
/**
 
10593
 * xmlParseDocument:
 
10594
 * @ctxt:  an XML parser context
 
10595
 *
 
10596
 * parse an XML document (and build a tree if using the standard SAX
 
10597
 * interface).
 
10598
 *
 
10599
 * [1] document ::= prolog element Misc*
 
10600
 *
 
10601
 * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
 
10602
 *
 
10603
 * Returns 0, -1 in case of error. the parser context is augmented
 
10604
 *                as a result of the parsing.
 
10605
 */
 
10606
 
 
10607
int
 
10608
xmlParseDocument(xmlParserCtxtPtr ctxt) {
 
10609
    xmlChar start[4];
 
10610
    xmlCharEncoding enc;
 
10611
 
 
10612
    xmlInitParser();
 
10613
 
 
10614
    if ((ctxt == NULL) || (ctxt->input == NULL))
 
10615
        return(-1);
 
10616
 
 
10617
    GROW;
 
10618
 
 
10619
    /*
 
10620
     * SAX: detecting the level.
 
10621
     */
 
10622
    xmlDetectSAX2(ctxt);
 
10623
 
 
10624
    /*
 
10625
     * SAX: beginning of the document processing.
 
10626
     */
 
10627
    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
 
10628
        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
 
10629
    if (ctxt->instate == XML_PARSER_EOF)
 
10630
        return(-1);
 
10631
 
 
10632
    if ((ctxt->encoding == NULL) &&
 
10633
        ((ctxt->input->end - ctxt->input->cur) >= 4)) {
 
10634
        /*
 
10635
         * Get the 4 first bytes and decode the charset
 
10636
         * if enc != XML_CHAR_ENCODING_NONE
 
10637
         * plug some encoding conversion routines.
 
10638
         */
 
10639
        start[0] = RAW;
 
10640
        start[1] = NXT(1);
 
10641
        start[2] = NXT(2);
 
10642
        start[3] = NXT(3);
 
10643
        enc = xmlDetectCharEncoding(&start[0], 4);
 
10644
        if (enc != XML_CHAR_ENCODING_NONE) {
 
10645
            xmlSwitchEncoding(ctxt, enc);
 
10646
        }
 
10647
    }
 
10648
 
 
10649
 
 
10650
    if (CUR == 0) {
 
10651
        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
 
10652
    }
 
10653
 
 
10654
    /*
 
10655
     * Check for the XMLDecl in the Prolog.
 
10656
     * do not GROW here to avoid the detected encoder to decode more
 
10657
     * than just the first line, unless the amount of data is really
 
10658
     * too small to hold "<?xml version="1.0" encoding="foo"
 
10659
     */
 
10660
    if ((ctxt->input->end - ctxt->input->cur) < 35) {
 
10661
       GROW;
 
10662
    }
 
10663
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
 
10664
 
 
10665
        /*
 
10666
         * Note that we will switch encoding on the fly.
 
10667
         */
 
10668
        xmlParseXMLDecl(ctxt);
 
10669
        if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
 
10670
            /*
 
10671
             * The XML REC instructs us to stop parsing right here
 
10672
             */
 
10673
            return(-1);
 
10674
        }
 
10675
        ctxt->standalone = ctxt->input->standalone;
 
10676
        SKIP_BLANKS;
 
10677
    } else {
 
10678
        ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
 
10679
    }
 
10680
    if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
 
10681
        ctxt->sax->startDocument(ctxt->userData);
 
10682
    if (ctxt->instate == XML_PARSER_EOF)
 
10683
        return(-1);
 
10684
 
 
10685
    /*
 
10686
     * The Misc part of the Prolog
 
10687
     */
 
10688
    GROW;
 
10689
    xmlParseMisc(ctxt);
 
10690
 
 
10691
    /*
 
10692
     * Then possibly doc type declaration(s) and more Misc
 
10693
     * (doctypedecl Misc*)?
 
10694
     */
 
10695
    GROW;
 
10696
    if (CMP9(CUR_PTR, '<', '!', 'D', 'O', 'C', 'T', 'Y', 'P', 'E')) {
 
10697
 
 
10698
        ctxt->inSubset = 1;
 
10699
        xmlParseDocTypeDecl(ctxt);
 
10700
        if (RAW == '[') {
 
10701
            ctxt->instate = XML_PARSER_DTD;
 
10702
            xmlParseInternalSubset(ctxt);
 
10703
            if (ctxt->instate == XML_PARSER_EOF)
 
10704
                return(-1);
 
10705
        }
 
10706
 
 
10707
        /*
 
10708
         * Create and update the external subset.
 
10709
         */
 
10710
        ctxt->inSubset = 2;
 
10711
        if ((ctxt->sax != NULL) && (ctxt->sax->externalSubset != NULL) &&
 
10712
            (!ctxt->disableSAX))
 
10713
            ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
 
10714
                                      ctxt->extSubSystem, ctxt->extSubURI);
 
10715
        if (ctxt->instate == XML_PARSER_EOF)
 
10716
            return(-1);
 
10717
        ctxt->inSubset = 0;
 
10718
 
 
10719
        xmlCleanSpecialAttr(ctxt);
 
10720
 
 
10721
        ctxt->instate = XML_PARSER_PROLOG;
 
10722
        xmlParseMisc(ctxt);
 
10723
    }
 
10724
 
 
10725
    /*
 
10726
     * Time to start parsing the tree itself
 
10727
     */
 
10728
    GROW;
 
10729
    if (RAW != '<') {
 
10730
        xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
 
10731
                       "Start tag expected, '<' not found\n");
 
10732
    } else {
 
10733
        ctxt->instate = XML_PARSER_CONTENT;
 
10734
        xmlParseElement(ctxt);
 
10735
        ctxt->instate = XML_PARSER_EPILOG;
 
10736
 
 
10737
 
 
10738
        /*
 
10739
         * The Misc part at the end
 
10740
         */
 
10741
        xmlParseMisc(ctxt);
 
10742
 
 
10743
        if (RAW != 0) {
 
10744
            xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
 
10745
        }
 
10746
        ctxt->instate = XML_PARSER_EOF;
 
10747
    }
 
10748
 
 
10749
    /*
 
10750
     * SAX: end of the document processing.
 
10751
     */
 
10752
    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 
10753
        ctxt->sax->endDocument(ctxt->userData);
 
10754
 
 
10755
    /*
 
10756
     * Remove locally kept entity definitions if the tree was not built
 
10757
     */
 
10758
    if ((ctxt->myDoc != NULL) &&
 
10759
        (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
 
10760
        xmlFreeDoc(ctxt->myDoc);
 
10761
        ctxt->myDoc = NULL;
 
10762
    }
 
10763
 
 
10764
    if ((ctxt->wellFormed) && (ctxt->myDoc != NULL)) {
 
10765
        ctxt->myDoc->properties |= XML_DOC_WELLFORMED;
 
10766
        if (ctxt->valid)
 
10767
            ctxt->myDoc->properties |= XML_DOC_DTDVALID;
 
10768
        if (ctxt->nsWellFormed)
 
10769
            ctxt->myDoc->properties |= XML_DOC_NSVALID;
 
10770
        if (ctxt->options & XML_PARSE_OLD10)
 
10771
            ctxt->myDoc->properties |= XML_DOC_OLD10;
 
10772
    }
 
10773
    if (! ctxt->wellFormed) {
 
10774
        ctxt->valid = 0;
 
10775
        return(-1);
 
10776
    }
 
10777
    return(0);
 
10778
}
 
10779
 
 
10780
/**
 
10781
 * xmlParseExtParsedEnt:
 
10782
 * @ctxt:  an XML parser context
 
10783
 *
 
10784
 * parse a general parsed entity
 
10785
 * An external general parsed entity is well-formed if it matches the
 
10786
 * production labeled extParsedEnt.
 
10787
 *
 
10788
 * [78] extParsedEnt ::= TextDecl? content
 
10789
 *
 
10790
 * Returns 0, -1 in case of error. the parser context is augmented
 
10791
 *                as a result of the parsing.
 
10792
 */
 
10793
 
 
10794
int
 
10795
xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) {
 
10796
    xmlChar start[4];
 
10797
    xmlCharEncoding enc;
 
10798
 
 
10799
    if ((ctxt == NULL) || (ctxt->input == NULL))
 
10800
        return(-1);
 
10801
 
 
10802
    xmlDefaultSAXHandlerInit();
 
10803
 
 
10804
    xmlDetectSAX2(ctxt);
 
10805
 
 
10806
    GROW;
 
10807
 
 
10808
    /*
 
10809
     * SAX: beginning of the document processing.
 
10810
     */
 
10811
    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
 
10812
        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
 
10813
 
 
10814
    /*
 
10815
     * Get the 4 first bytes and decode the charset
 
10816
     * if enc != XML_CHAR_ENCODING_NONE
 
10817
     * plug some encoding conversion routines.
 
10818
     */
 
10819
    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
 
10820
        start[0] = RAW;
 
10821
        start[1] = NXT(1);
 
10822
        start[2] = NXT(2);
 
10823
        start[3] = NXT(3);
 
10824
        enc = xmlDetectCharEncoding(start, 4);
 
10825
        if (enc != XML_CHAR_ENCODING_NONE) {
 
10826
            xmlSwitchEncoding(ctxt, enc);
 
10827
        }
 
10828
    }
 
10829
 
 
10830
 
 
10831
    if (CUR == 0) {
 
10832
        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
 
10833
    }
 
10834
 
 
10835
    /*
 
10836
     * Check for the XMLDecl in the Prolog.
 
10837
     */
 
10838
    GROW;
 
10839
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
 
10840
 
 
10841
        /*
 
10842
         * Note that we will switch encoding on the fly.
 
10843
         */
 
10844
        xmlParseXMLDecl(ctxt);
 
10845
        if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
 
10846
            /*
 
10847
             * The XML REC instructs us to stop parsing right here
 
10848
             */
 
10849
            return(-1);
 
10850
        }
 
10851
        SKIP_BLANKS;
 
10852
    } else {
 
10853
        ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
 
10854
    }
 
10855
    if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
 
10856
        ctxt->sax->startDocument(ctxt->userData);
 
10857
    if (ctxt->instate == XML_PARSER_EOF)
 
10858
        return(-1);
 
10859
 
 
10860
    /*
 
10861
     * Doing validity checking on chunk doesn't make sense
 
10862
     */
 
10863
    ctxt->instate = XML_PARSER_CONTENT;
 
10864
    ctxt->validate = 0;
 
10865
    ctxt->loadsubset = 0;
 
10866
    ctxt->depth = 0;
 
10867
 
 
10868
    xmlParseContent(ctxt);
 
10869
    if (ctxt->instate == XML_PARSER_EOF)
 
10870
        return(-1);
 
10871
 
 
10872
    if ((RAW == '<') && (NXT(1) == '/')) {
 
10873
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
10874
    } else if (RAW != 0) {
 
10875
        xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
 
10876
    }
 
10877
 
 
10878
    /*
 
10879
     * SAX: end of the document processing.
 
10880
     */
 
10881
    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 
10882
        ctxt->sax->endDocument(ctxt->userData);
 
10883
 
 
10884
    if (! ctxt->wellFormed) return(-1);
 
10885
    return(0);
 
10886
}
 
10887
 
 
10888
#ifdef LIBXML_PUSH_ENABLED
 
10889
/************************************************************************
 
10890
 *                                                                      *
 
10891
 *              Progressive parsing interfaces                          *
 
10892
 *                                                                      *
 
10893
 ************************************************************************/
 
10894
 
 
10895
/**
 
10896
 * xmlParseLookupSequence:
 
10897
 * @ctxt:  an XML parser context
 
10898
 * @first:  the first char to lookup
 
10899
 * @next:  the next char to lookup or zero
 
10900
 * @third:  the next char to lookup or zero
 
10901
 *
 
10902
 * Try to find if a sequence (first, next, third) or  just (first next) or
 
10903
 * (first) is available in the input stream.
 
10904
 * This function has a side effect of (possibly) incrementing ctxt->checkIndex
 
10905
 * to avoid rescanning sequences of bytes, it DOES change the state of the
 
10906
 * parser, do not use liberally.
 
10907
 *
 
10908
 * Returns the index to the current parsing point if the full sequence
 
10909
 *      is available, -1 otherwise.
 
10910
 */
 
10911
static int
 
10912
xmlParseLookupSequence(xmlParserCtxtPtr ctxt, xmlChar first,
 
10913
                       xmlChar next, xmlChar third) {
 
10914
    int base, len;
 
10915
    xmlParserInputPtr in;
 
10916
    const xmlChar *buf;
 
10917
 
 
10918
    in = ctxt->input;
 
10919
    if (in == NULL) return(-1);
 
10920
    base = in->cur - in->base;
 
10921
    if (base < 0) return(-1);
 
10922
    if (ctxt->checkIndex > base)
 
10923
        base = ctxt->checkIndex;
 
10924
    if (in->buf == NULL) {
 
10925
        buf = in->base;
 
10926
        len = in->length;
 
10927
    } else {
 
10928
        buf = xmlBufContent(in->buf->buffer);
 
10929
        len = xmlBufUse(in->buf->buffer);
 
10930
    }
 
10931
    /* take into account the sequence length */
 
10932
    if (third) len -= 2;
 
10933
    else if (next) len --;
 
10934
    for (;base < len;base++) {
 
10935
        if (buf[base] == first) {
 
10936
            if (third != 0) {
 
10937
                if ((buf[base + 1] != next) ||
 
10938
                    (buf[base + 2] != third)) continue;
 
10939
            } else if (next != 0) {
 
10940
                if (buf[base + 1] != next) continue;
 
10941
            }
 
10942
            ctxt->checkIndex = 0;
 
10943
#ifdef DEBUG_PUSH
 
10944
            if (next == 0)
 
10945
                xmlGenericError(xmlGenericErrorContext,
 
10946
                        "PP: lookup '%c' found at %d\n",
 
10947
                        first, base);
 
10948
            else if (third == 0)
 
10949
                xmlGenericError(xmlGenericErrorContext,
 
10950
                        "PP: lookup '%c%c' found at %d\n",
 
10951
                        first, next, base);
 
10952
            else
 
10953
                xmlGenericError(xmlGenericErrorContext,
 
10954
                        "PP: lookup '%c%c%c' found at %d\n",
 
10955
                        first, next, third, base);
 
10956
#endif
 
10957
            return(base - (in->cur - in->base));
 
10958
        }
 
10959
    }
 
10960
    ctxt->checkIndex = base;
 
10961
#ifdef DEBUG_PUSH
 
10962
    if (next == 0)
 
10963
        xmlGenericError(xmlGenericErrorContext,
 
10964
                "PP: lookup '%c' failed\n", first);
 
10965
    else if (third == 0)
 
10966
        xmlGenericError(xmlGenericErrorContext,
 
10967
                "PP: lookup '%c%c' failed\n", first, next);
 
10968
    else
 
10969
        xmlGenericError(xmlGenericErrorContext,
 
10970
                "PP: lookup '%c%c%c' failed\n", first, next, third);
 
10971
#endif
 
10972
    return(-1);
 
10973
}
 
10974
 
 
10975
/**
 
10976
 * xmlParseGetLasts:
 
10977
 * @ctxt:  an XML parser context
 
10978
 * @lastlt:  pointer to store the last '<' from the input
 
10979
 * @lastgt:  pointer to store the last '>' from the input
 
10980
 *
 
10981
 * Lookup the last < and > in the current chunk
 
10982
 */
 
10983
static void
 
10984
xmlParseGetLasts(xmlParserCtxtPtr ctxt, const xmlChar **lastlt,
 
10985
                 const xmlChar **lastgt) {
 
10986
    const xmlChar *tmp;
 
10987
 
 
10988
    if ((ctxt == NULL) || (lastlt == NULL) || (lastgt == NULL)) {
 
10989
        xmlGenericError(xmlGenericErrorContext,
 
10990
                    "Internal error: xmlParseGetLasts\n");
 
10991
        return;
 
10992
    }
 
10993
    if ((ctxt->progressive != 0) && (ctxt->inputNr == 1)) {
 
10994
        tmp = ctxt->input->end;
 
10995
        tmp--;
 
10996
        while ((tmp >= ctxt->input->base) && (*tmp != '<')) tmp--;
 
10997
        if (tmp < ctxt->input->base) {
 
10998
            *lastlt = NULL;
 
10999
            *lastgt = NULL;
 
11000
        } else {
 
11001
            *lastlt = tmp;
 
11002
            tmp++;
 
11003
            while ((tmp < ctxt->input->end) && (*tmp != '>')) {
 
11004
                if (*tmp == '\'') {
 
11005
                    tmp++;
 
11006
                    while ((tmp < ctxt->input->end) && (*tmp != '\'')) tmp++;
 
11007
                    if (tmp < ctxt->input->end) tmp++;
 
11008
                } else if (*tmp == '"') {
 
11009
                    tmp++;
 
11010
                    while ((tmp < ctxt->input->end) && (*tmp != '"')) tmp++;
 
11011
                    if (tmp < ctxt->input->end) tmp++;
 
11012
                } else
 
11013
                    tmp++;
 
11014
            }
 
11015
            if (tmp < ctxt->input->end)
 
11016
                *lastgt = tmp;
 
11017
            else {
 
11018
                tmp = *lastlt;
 
11019
                tmp--;
 
11020
                while ((tmp >= ctxt->input->base) && (*tmp != '>')) tmp--;
 
11021
                if (tmp >= ctxt->input->base)
 
11022
                    *lastgt = tmp;
 
11023
                else
 
11024
                    *lastgt = NULL;
 
11025
            }
 
11026
        }
 
11027
    } else {
 
11028
        *lastlt = NULL;
 
11029
        *lastgt = NULL;
 
11030
    }
 
11031
}
 
11032
/**
 
11033
 * xmlCheckCdataPush:
 
11034
 * @cur: pointer to the bock of characters
 
11035
 * @len: length of the block in bytes
 
11036
 *
 
11037
 * Check that the block of characters is okay as SCdata content [20]
 
11038
 *
 
11039
 * Returns the number of bytes to pass if okay, a negative index where an
 
11040
 *         UTF-8 error occured otherwise
 
11041
 */
 
11042
static int
 
11043
xmlCheckCdataPush(const xmlChar *utf, int len) {
 
11044
    int ix;
 
11045
    unsigned char c;
 
11046
    int codepoint;
 
11047
 
 
11048
    if ((utf == NULL) || (len <= 0))
 
11049
        return(0);
 
11050
 
 
11051
    for (ix = 0; ix < len;) {      /* string is 0-terminated */
 
11052
        c = utf[ix];
 
11053
        if ((c & 0x80) == 0x00) {       /* 1-byte code, starts with 10 */
 
11054
            if (c >= 0x20)
 
11055
                ix++;
 
11056
            else if ((c == 0xA) || (c == 0xD) || (c == 0x9))
 
11057
                ix++;
 
11058
            else
 
11059
                return(-ix);
 
11060
        } else if ((c & 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */
 
11061
            if (ix + 2 > len) return(ix);
 
11062
            if ((utf[ix+1] & 0xc0 ) != 0x80)
 
11063
                return(-ix);
 
11064
            codepoint = (utf[ix] & 0x1f) << 6;
 
11065
            codepoint |= utf[ix+1] & 0x3f;
 
11066
            if (!xmlIsCharQ(codepoint))
 
11067
                return(-ix);
 
11068
            ix += 2;
 
11069
        } else if ((c & 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */
 
11070
            if (ix + 3 > len) return(ix);
 
11071
            if (((utf[ix+1] & 0xc0) != 0x80) ||
 
11072
                ((utf[ix+2] & 0xc0) != 0x80))
 
11073
                    return(-ix);
 
11074
            codepoint = (utf[ix] & 0xf) << 12;
 
11075
            codepoint |= (utf[ix+1] & 0x3f) << 6;
 
11076
            codepoint |= utf[ix+2] & 0x3f;
 
11077
            if (!xmlIsCharQ(codepoint))
 
11078
                return(-ix);
 
11079
            ix += 3;
 
11080
        } else if ((c & 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */
 
11081
            if (ix + 4 > len) return(ix);
 
11082
            if (((utf[ix+1] & 0xc0) != 0x80) ||
 
11083
                ((utf[ix+2] & 0xc0) != 0x80) ||
 
11084
                ((utf[ix+3] & 0xc0) != 0x80))
 
11085
                    return(-ix);
 
11086
            codepoint = (utf[ix] & 0x7) << 18;
 
11087
            codepoint |= (utf[ix+1] & 0x3f) << 12;
 
11088
            codepoint |= (utf[ix+2] & 0x3f) << 6;
 
11089
            codepoint |= utf[ix+3] & 0x3f;
 
11090
            if (!xmlIsCharQ(codepoint))
 
11091
                return(-ix);
 
11092
            ix += 4;
 
11093
        } else                          /* unknown encoding */
 
11094
            return(-ix);
 
11095
      }
 
11096
      return(ix);
 
11097
}
 
11098
 
 
11099
/**
 
11100
 * xmlParseTryOrFinish:
 
11101
 * @ctxt:  an XML parser context
 
11102
 * @terminate:  last chunk indicator
 
11103
 *
 
11104
 * Try to progress on parsing
 
11105
 *
 
11106
 * Returns zero if no parsing was possible
 
11107
 */
 
11108
static int
 
11109
xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
 
11110
    int ret = 0;
 
11111
    int avail, tlen;
 
11112
    xmlChar cur, next;
 
11113
    const xmlChar *lastlt, *lastgt;
 
11114
 
 
11115
    if (ctxt->input == NULL)
 
11116
        return(0);
 
11117
 
 
11118
#ifdef DEBUG_PUSH
 
11119
    switch (ctxt->instate) {
 
11120
        case XML_PARSER_EOF:
 
11121
            xmlGenericError(xmlGenericErrorContext,
 
11122
                    "PP: try EOF\n"); break;
 
11123
        case XML_PARSER_START:
 
11124
            xmlGenericError(xmlGenericErrorContext,
 
11125
                    "PP: try START\n"); break;
 
11126
        case XML_PARSER_MISC:
 
11127
            xmlGenericError(xmlGenericErrorContext,
 
11128
                    "PP: try MISC\n");break;
 
11129
        case XML_PARSER_COMMENT:
 
11130
            xmlGenericError(xmlGenericErrorContext,
 
11131
                    "PP: try COMMENT\n");break;
 
11132
        case XML_PARSER_PROLOG:
 
11133
            xmlGenericError(xmlGenericErrorContext,
 
11134
                    "PP: try PROLOG\n");break;
 
11135
        case XML_PARSER_START_TAG:
 
11136
            xmlGenericError(xmlGenericErrorContext,
 
11137
                    "PP: try START_TAG\n");break;
 
11138
        case XML_PARSER_CONTENT:
 
11139
            xmlGenericError(xmlGenericErrorContext,
 
11140
                    "PP: try CONTENT\n");break;
 
11141
        case XML_PARSER_CDATA_SECTION:
 
11142
            xmlGenericError(xmlGenericErrorContext,
 
11143
                    "PP: try CDATA_SECTION\n");break;
 
11144
        case XML_PARSER_END_TAG:
 
11145
            xmlGenericError(xmlGenericErrorContext,
 
11146
                    "PP: try END_TAG\n");break;
 
11147
        case XML_PARSER_ENTITY_DECL:
 
11148
            xmlGenericError(xmlGenericErrorContext,
 
11149
                    "PP: try ENTITY_DECL\n");break;
 
11150
        case XML_PARSER_ENTITY_VALUE:
 
11151
            xmlGenericError(xmlGenericErrorContext,
 
11152
                    "PP: try ENTITY_VALUE\n");break;
 
11153
        case XML_PARSER_ATTRIBUTE_VALUE:
 
11154
            xmlGenericError(xmlGenericErrorContext,
 
11155
                    "PP: try ATTRIBUTE_VALUE\n");break;
 
11156
        case XML_PARSER_DTD:
 
11157
            xmlGenericError(xmlGenericErrorContext,
 
11158
                    "PP: try DTD\n");break;
 
11159
        case XML_PARSER_EPILOG:
 
11160
            xmlGenericError(xmlGenericErrorContext,
 
11161
                    "PP: try EPILOG\n");break;
 
11162
        case XML_PARSER_PI:
 
11163
            xmlGenericError(xmlGenericErrorContext,
 
11164
                    "PP: try PI\n");break;
 
11165
        case XML_PARSER_IGNORE:
 
11166
            xmlGenericError(xmlGenericErrorContext,
 
11167
                    "PP: try IGNORE\n");break;
 
11168
    }
 
11169
#endif
 
11170
 
 
11171
    if ((ctxt->input != NULL) &&
 
11172
        (ctxt->input->cur - ctxt->input->base > 4096)) {
 
11173
        xmlSHRINK(ctxt);
 
11174
        ctxt->checkIndex = 0;
 
11175
    }
 
11176
    xmlParseGetLasts(ctxt, &lastlt, &lastgt);
 
11177
 
 
11178
    while (ctxt->instate != XML_PARSER_EOF) {
 
11179
        if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
 
11180
            return(0);
 
11181
 
 
11182
 
 
11183
        /*
 
11184
         * Pop-up of finished entities.
 
11185
         */
 
11186
        while ((RAW == 0) && (ctxt->inputNr > 1))
 
11187
            xmlPopInput(ctxt);
 
11188
 
 
11189
        if (ctxt->input == NULL) break;
 
11190
        if (ctxt->input->buf == NULL)
 
11191
            avail = ctxt->input->length -
 
11192
                    (ctxt->input->cur - ctxt->input->base);
 
11193
        else {
 
11194
            /*
 
11195
             * If we are operating on converted input, try to flush
 
11196
             * remainng chars to avoid them stalling in the non-converted
 
11197
             * buffer. But do not do this in document start where
 
11198
             * encoding="..." may not have been read and we work on a
 
11199
             * guessed encoding.
 
11200
             */
 
11201
            if ((ctxt->instate != XML_PARSER_START) &&
 
11202
                (ctxt->input->buf->raw != NULL) &&
 
11203
                (xmlBufIsEmpty(ctxt->input->buf->raw) == 0)) {
 
11204
                size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer,
 
11205
                                                 ctxt->input);
 
11206
                size_t current = ctxt->input->cur - ctxt->input->base;
 
11207
 
 
11208
                xmlParserInputBufferPush(ctxt->input->buf, 0, "");
 
11209
                xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input,
 
11210
                                      base, current);
 
11211
            }
 
11212
            avail = xmlBufUse(ctxt->input->buf->buffer) -
 
11213
                    (ctxt->input->cur - ctxt->input->base);
 
11214
        }
 
11215
        if (avail < 1)
 
11216
            goto done;
 
11217
        switch (ctxt->instate) {
 
11218
            case XML_PARSER_EOF:
 
11219
                /*
 
11220
                 * Document parsing is done !
 
11221
                 */
 
11222
                goto done;
 
11223
            case XML_PARSER_START:
 
11224
                if (ctxt->charset == XML_CHAR_ENCODING_NONE) {
 
11225
                    xmlChar start[4];
 
11226
                    xmlCharEncoding enc;
 
11227
 
 
11228
                    /*
 
11229
                     * Very first chars read from the document flow.
 
11230
                     */
 
11231
                    if (avail < 4)
 
11232
                        goto done;
 
11233
 
 
11234
                    /*
 
11235
                     * Get the 4 first bytes and decode the charset
 
11236
                     * if enc != XML_CHAR_ENCODING_NONE
 
11237
                     * plug some encoding conversion routines,
 
11238
                     * else xmlSwitchEncoding will set to (default)
 
11239
                     * UTF8.
 
11240
                     */
 
11241
                    start[0] = RAW;
 
11242
                    start[1] = NXT(1);
 
11243
                    start[2] = NXT(2);
 
11244
                    start[3] = NXT(3);
 
11245
                    enc = xmlDetectCharEncoding(start, 4);
 
11246
                    xmlSwitchEncoding(ctxt, enc);
 
11247
                    break;
 
11248
                }
 
11249
 
 
11250
                if (avail < 2)
 
11251
                    goto done;
 
11252
                cur = ctxt->input->cur[0];
 
11253
                next = ctxt->input->cur[1];
 
11254
                if (cur == 0) {
 
11255
                    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
 
11256
                        ctxt->sax->setDocumentLocator(ctxt->userData,
 
11257
                                                      &xmlDefaultSAXLocator);
 
11258
                    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
 
11259
                    ctxt->instate = XML_PARSER_EOF;
 
11260
#ifdef DEBUG_PUSH
 
11261
                    xmlGenericError(xmlGenericErrorContext,
 
11262
                            "PP: entering EOF\n");
 
11263
#endif
 
11264
                    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 
11265
                        ctxt->sax->endDocument(ctxt->userData);
 
11266
                    goto done;
 
11267
                }
 
11268
                if ((cur == '<') && (next == '?')) {
 
11269
                    /* PI or XML decl */
 
11270
                    if (avail < 5) return(ret);
 
11271
                    if ((!terminate) &&
 
11272
                        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
 
11273
                        return(ret);
 
11274
                    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
 
11275
                        ctxt->sax->setDocumentLocator(ctxt->userData,
 
11276
                                                      &xmlDefaultSAXLocator);
 
11277
                    if ((ctxt->input->cur[2] == 'x') &&
 
11278
                        (ctxt->input->cur[3] == 'm') &&
 
11279
                        (ctxt->input->cur[4] == 'l') &&
 
11280
                        (IS_BLANK_CH(ctxt->input->cur[5]))) {
 
11281
                        ret += 5;
 
11282
#ifdef DEBUG_PUSH
 
11283
                        xmlGenericError(xmlGenericErrorContext,
 
11284
                                "PP: Parsing XML Decl\n");
 
11285
#endif
 
11286
                        xmlParseXMLDecl(ctxt);
 
11287
                        if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
 
11288
                            /*
 
11289
                             * The XML REC instructs us to stop parsing right
 
11290
                             * here
 
11291
                             */
 
11292
                            ctxt->instate = XML_PARSER_EOF;
 
11293
                            return(0);
 
11294
                        }
 
11295
                        ctxt->standalone = ctxt->input->standalone;
 
11296
                        if ((ctxt->encoding == NULL) &&
 
11297
                            (ctxt->input->encoding != NULL))
 
11298
                            ctxt->encoding = xmlStrdup(ctxt->input->encoding);
 
11299
                        if ((ctxt->sax) && (ctxt->sax->startDocument) &&
 
11300
                            (!ctxt->disableSAX))
 
11301
                            ctxt->sax->startDocument(ctxt->userData);
 
11302
                        ctxt->instate = XML_PARSER_MISC;
 
11303
#ifdef DEBUG_PUSH
 
11304
                        xmlGenericError(xmlGenericErrorContext,
 
11305
                                "PP: entering MISC\n");
 
11306
#endif
 
11307
                    } else {
 
11308
                        ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
 
11309
                        if ((ctxt->sax) && (ctxt->sax->startDocument) &&
 
11310
                            (!ctxt->disableSAX))
 
11311
                            ctxt->sax->startDocument(ctxt->userData);
 
11312
                        ctxt->instate = XML_PARSER_MISC;
 
11313
#ifdef DEBUG_PUSH
 
11314
                        xmlGenericError(xmlGenericErrorContext,
 
11315
                                "PP: entering MISC\n");
 
11316
#endif
 
11317
                    }
 
11318
                } else {
 
11319
                    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
 
11320
                        ctxt->sax->setDocumentLocator(ctxt->userData,
 
11321
                                                      &xmlDefaultSAXLocator);
 
11322
                    ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
 
11323
                    if (ctxt->version == NULL) {
 
11324
                        xmlErrMemory(ctxt, NULL);
 
11325
                        break;
 
11326
                    }
 
11327
                    if ((ctxt->sax) && (ctxt->sax->startDocument) &&
 
11328
                        (!ctxt->disableSAX))
 
11329
                        ctxt->sax->startDocument(ctxt->userData);
 
11330
                    ctxt->instate = XML_PARSER_MISC;
 
11331
#ifdef DEBUG_PUSH
 
11332
                    xmlGenericError(xmlGenericErrorContext,
 
11333
                            "PP: entering MISC\n");
 
11334
#endif
 
11335
                }
 
11336
                break;
 
11337
            case XML_PARSER_START_TAG: {
 
11338
                const xmlChar *name;
 
11339
                const xmlChar *prefix = NULL;
 
11340
                const xmlChar *URI = NULL;
 
11341
                int nsNr = ctxt->nsNr;
 
11342
 
 
11343
                if ((avail < 2) && (ctxt->inputNr == 1))
 
11344
                    goto done;
 
11345
                cur = ctxt->input->cur[0];
 
11346
                if (cur != '<') {
 
11347
                    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
 
11348
                    ctxt->instate = XML_PARSER_EOF;
 
11349
                    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 
11350
                        ctxt->sax->endDocument(ctxt->userData);
 
11351
                    goto done;
 
11352
                }
 
11353
                if (!terminate) {
 
11354
                    if (ctxt->progressive) {
 
11355
                        /* > can be found unescaped in attribute values */
 
11356
                        if ((lastgt == NULL) || (ctxt->input->cur >= lastgt))
 
11357
                            goto done;
 
11358
                    } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) {
 
11359
                        goto done;
 
11360
                    }
 
11361
                }
 
11362
                if (ctxt->spaceNr == 0)
 
11363
                    spacePush(ctxt, -1);
 
11364
                else if (*ctxt->space == -2)
 
11365
                    spacePush(ctxt, -1);
 
11366
                else
 
11367
                    spacePush(ctxt, *ctxt->space);
 
11368
#ifdef LIBXML_SAX1_ENABLED
 
11369
                if (ctxt->sax2)
 
11370
#endif /* LIBXML_SAX1_ENABLED */
 
11371
                    name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
 
11372
#ifdef LIBXML_SAX1_ENABLED
 
11373
                else
 
11374
                    name = xmlParseStartTag(ctxt);
 
11375
#endif /* LIBXML_SAX1_ENABLED */
 
11376
                if (ctxt->instate == XML_PARSER_EOF)
 
11377
                    goto done;
 
11378
                if (name == NULL) {
 
11379
                    spacePop(ctxt);
 
11380
                    ctxt->instate = XML_PARSER_EOF;
 
11381
                    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 
11382
                        ctxt->sax->endDocument(ctxt->userData);
 
11383
                    goto done;
 
11384
                }
 
11385
#ifdef LIBXML_VALID_ENABLED
 
11386
                /*
 
11387
                 * [ VC: Root Element Type ]
 
11388
                 * The Name in the document type declaration must match
 
11389
                 * the element type of the root element.
 
11390
                 */
 
11391
                if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
 
11392
                    ctxt->node && (ctxt->node == ctxt->myDoc->children))
 
11393
                    ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
 
11394
#endif /* LIBXML_VALID_ENABLED */
 
11395
 
 
11396
                /*
 
11397
                 * Check for an Empty Element.
 
11398
                 */
 
11399
                if ((RAW == '/') && (NXT(1) == '>')) {
 
11400
                    SKIP(2);
 
11401
 
 
11402
                    if (ctxt->sax2) {
 
11403
                        if ((ctxt->sax != NULL) &&
 
11404
                            (ctxt->sax->endElementNs != NULL) &&
 
11405
                            (!ctxt->disableSAX))
 
11406
                            ctxt->sax->endElementNs(ctxt->userData, name,
 
11407
                                                    prefix, URI);
 
11408
                        if (ctxt->nsNr - nsNr > 0)
 
11409
                            nsPop(ctxt, ctxt->nsNr - nsNr);
 
11410
#ifdef LIBXML_SAX1_ENABLED
 
11411
                    } else {
 
11412
                        if ((ctxt->sax != NULL) &&
 
11413
                            (ctxt->sax->endElement != NULL) &&
 
11414
                            (!ctxt->disableSAX))
 
11415
                            ctxt->sax->endElement(ctxt->userData, name);
 
11416
#endif /* LIBXML_SAX1_ENABLED */
 
11417
                    }
 
11418
                    if (ctxt->instate == XML_PARSER_EOF)
 
11419
                        goto done;
 
11420
                    spacePop(ctxt);
 
11421
                    if (ctxt->nameNr == 0) {
 
11422
                        ctxt->instate = XML_PARSER_EPILOG;
 
11423
                    } else {
 
11424
                        ctxt->instate = XML_PARSER_CONTENT;
 
11425
                    }
 
11426
                    ctxt->progressive = 1;
 
11427
                    break;
 
11428
                }
 
11429
                if (RAW == '>') {
 
11430
                    NEXT;
 
11431
                } else {
 
11432
                    xmlFatalErrMsgStr(ctxt, XML_ERR_GT_REQUIRED,
 
11433
                                         "Couldn't find end of Start Tag %s\n",
 
11434
                                         name);
 
11435
                    nodePop(ctxt);
 
11436
                    spacePop(ctxt);
 
11437
                }
 
11438
                if (ctxt->sax2)
 
11439
                    nameNsPush(ctxt, name, prefix, URI, ctxt->nsNr - nsNr);
 
11440
#ifdef LIBXML_SAX1_ENABLED
 
11441
                else
 
11442
                    namePush(ctxt, name);
 
11443
#endif /* LIBXML_SAX1_ENABLED */
 
11444
 
 
11445
                ctxt->instate = XML_PARSER_CONTENT;
 
11446
                ctxt->progressive = 1;
 
11447
                break;
 
11448
            }
 
11449
            case XML_PARSER_CONTENT: {
 
11450
                const xmlChar *test;
 
11451
                unsigned int cons;
 
11452
                if ((avail < 2) && (ctxt->inputNr == 1))
 
11453
                    goto done;
 
11454
                cur = ctxt->input->cur[0];
 
11455
                next = ctxt->input->cur[1];
 
11456
 
 
11457
                test = CUR_PTR;
 
11458
                cons = ctxt->input->consumed;
 
11459
                if ((cur == '<') && (next == '/')) {
 
11460
                    ctxt->instate = XML_PARSER_END_TAG;
 
11461
                    break;
 
11462
                } else if ((cur == '<') && (next == '?')) {
 
11463
                    if ((!terminate) &&
 
11464
                        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
 
11465
                        ctxt->progressive = XML_PARSER_PI;
 
11466
                        goto done;
 
11467
                    }
 
11468
                    xmlParsePI(ctxt);
 
11469
                    ctxt->instate = XML_PARSER_CONTENT;
 
11470
                    ctxt->progressive = 1;
 
11471
                } else if ((cur == '<') && (next != '!')) {
 
11472
                    ctxt->instate = XML_PARSER_START_TAG;
 
11473
                    break;
 
11474
                } else if ((cur == '<') && (next == '!') &&
 
11475
                           (ctxt->input->cur[2] == '-') &&
 
11476
                           (ctxt->input->cur[3] == '-')) {
 
11477
                    int term;
 
11478
 
 
11479
                    if (avail < 4)
 
11480
                        goto done;
 
11481
                    ctxt->input->cur += 4;
 
11482
                    term = xmlParseLookupSequence(ctxt, '-', '-', '>');
 
11483
                    ctxt->input->cur -= 4;
 
11484
                    if ((!terminate) && (term < 0)) {
 
11485
                        ctxt->progressive = XML_PARSER_COMMENT;
 
11486
                        goto done;
 
11487
                    }
 
11488
                    xmlParseComment(ctxt);
 
11489
                    ctxt->instate = XML_PARSER_CONTENT;
 
11490
                    ctxt->progressive = 1;
 
11491
                } else if ((cur == '<') && (ctxt->input->cur[1] == '!') &&
 
11492
                    (ctxt->input->cur[2] == '[') &&
 
11493
                    (ctxt->input->cur[3] == 'C') &&
 
11494
                    (ctxt->input->cur[4] == 'D') &&
 
11495
                    (ctxt->input->cur[5] == 'A') &&
 
11496
                    (ctxt->input->cur[6] == 'T') &&
 
11497
                    (ctxt->input->cur[7] == 'A') &&
 
11498
                    (ctxt->input->cur[8] == '[')) {
 
11499
                    SKIP(9);
 
11500
                    ctxt->instate = XML_PARSER_CDATA_SECTION;
 
11501
                    break;
 
11502
                } else if ((cur == '<') && (next == '!') &&
 
11503
                           (avail < 9)) {
 
11504
                    goto done;
 
11505
                } else if (cur == '&') {
 
11506
                    if ((!terminate) &&
 
11507
                        (xmlParseLookupSequence(ctxt, ';', 0, 0) < 0))
 
11508
                        goto done;
 
11509
                    xmlParseReference(ctxt);
 
11510
                } else {
 
11511
                    /* TODO Avoid the extra copy, handle directly !!! */
 
11512
                    /*
 
11513
                     * Goal of the following test is:
 
11514
                     *  - minimize calls to the SAX 'character' callback
 
11515
                     *    when they are mergeable
 
11516
                     *  - handle an problem for isBlank when we only parse
 
11517
                     *    a sequence of blank chars and the next one is
 
11518
                     *    not available to check against '<' presence.
 
11519
                     *  - tries to homogenize the differences in SAX
 
11520
                     *    callbacks between the push and pull versions
 
11521
                     *    of the parser.
 
11522
                     */
 
11523
                    if ((ctxt->inputNr == 1) &&
 
11524
                        (avail < XML_PARSER_BIG_BUFFER_SIZE)) {
 
11525
                        if (!terminate) {
 
11526
                            if (ctxt->progressive) {
 
11527
                                if ((lastlt == NULL) ||
 
11528
                                    (ctxt->input->cur > lastlt))
 
11529
                                    goto done;
 
11530
                            } else if (xmlParseLookupSequence(ctxt,
 
11531
                                                              '<', 0, 0) < 0) {
 
11532
                                goto done;
 
11533
                            }
 
11534
                        }
 
11535
                    }
 
11536
                    ctxt->checkIndex = 0;
 
11537
                    xmlParseCharData(ctxt, 0);
 
11538
                }
 
11539
                /*
 
11540
                 * Pop-up of finished entities.
 
11541
                 */
 
11542
                while ((RAW == 0) && (ctxt->inputNr > 1))
 
11543
                    xmlPopInput(ctxt);
 
11544
                if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) {
 
11545
                    xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
11546
                                "detected an error in element content\n");
 
11547
                    ctxt->instate = XML_PARSER_EOF;
 
11548
                    break;
 
11549
                }
 
11550
                break;
 
11551
            }
 
11552
            case XML_PARSER_END_TAG:
 
11553
                if (avail < 2)
 
11554
                    goto done;
 
11555
                if (!terminate) {
 
11556
                    if (ctxt->progressive) {
 
11557
                        /* > can be found unescaped in attribute values */
 
11558
                        if ((lastgt == NULL) || (ctxt->input->cur >= lastgt))
 
11559
                            goto done;
 
11560
                    } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) {
 
11561
                        goto done;
 
11562
                    }
 
11563
                }
 
11564
                if (ctxt->sax2) {
 
11565
                    xmlParseEndTag2(ctxt,
 
11566
                           (void *) ctxt->pushTab[ctxt->nameNr * 3 - 3],
 
11567
                           (void *) ctxt->pushTab[ctxt->nameNr * 3 - 2], 0,
 
11568
                       (int) (long) ctxt->pushTab[ctxt->nameNr * 3 - 1], 0);
 
11569
                    nameNsPop(ctxt);
 
11570
                }
 
11571
#ifdef LIBXML_SAX1_ENABLED
 
11572
                  else
 
11573
                    xmlParseEndTag1(ctxt, 0);
 
11574
#endif /* LIBXML_SAX1_ENABLED */
 
11575
                if (ctxt->instate == XML_PARSER_EOF) {
 
11576
                    /* Nothing */
 
11577
                } else if (ctxt->nameNr == 0) {
 
11578
                    ctxt->instate = XML_PARSER_EPILOG;
 
11579
                } else {
 
11580
                    ctxt->instate = XML_PARSER_CONTENT;
 
11581
                }
 
11582
                break;
 
11583
            case XML_PARSER_CDATA_SECTION: {
 
11584
                /*
 
11585
                 * The Push mode need to have the SAX callback for
 
11586
                 * cdataBlock merge back contiguous callbacks.
 
11587
                 */
 
11588
                int base;
 
11589
 
 
11590
                base = xmlParseLookupSequence(ctxt, ']', ']', '>');
 
11591
                if (base < 0) {
 
11592
                    if (avail >= XML_PARSER_BIG_BUFFER_SIZE + 2) {
 
11593
                        int tmp;
 
11594
 
 
11595
                        tmp = xmlCheckCdataPush(ctxt->input->cur,
 
11596
                                                XML_PARSER_BIG_BUFFER_SIZE);
 
11597
                        if (tmp < 0) {
 
11598
                            tmp = -tmp;
 
11599
                            ctxt->input->cur += tmp;
 
11600
                            goto encoding_error;
 
11601
                        }
 
11602
                        if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
 
11603
                            if (ctxt->sax->cdataBlock != NULL)
 
11604
                                ctxt->sax->cdataBlock(ctxt->userData,
 
11605
                                                      ctxt->input->cur, tmp);
 
11606
                            else if (ctxt->sax->characters != NULL)
 
11607
                                ctxt->sax->characters(ctxt->userData,
 
11608
                                                      ctxt->input->cur, tmp);
 
11609
                        }
 
11610
                        if (ctxt->instate == XML_PARSER_EOF)
 
11611
                            goto done;
 
11612
                        SKIPL(tmp);
 
11613
                        ctxt->checkIndex = 0;
 
11614
                    }
 
11615
                    goto done;
 
11616
                } else {
 
11617
                    int tmp;
 
11618
 
 
11619
                    tmp = xmlCheckCdataPush(ctxt->input->cur, base);
 
11620
                    if ((tmp < 0) || (tmp != base)) {
 
11621
                        tmp = -tmp;
 
11622
                        ctxt->input->cur += tmp;
 
11623
                        goto encoding_error;
 
11624
                    }
 
11625
                    if ((ctxt->sax != NULL) && (base == 0) &&
 
11626
                        (ctxt->sax->cdataBlock != NULL) &&
 
11627
                        (!ctxt->disableSAX)) {
 
11628
                        /*
 
11629
                         * Special case to provide identical behaviour
 
11630
                         * between pull and push parsers on enpty CDATA
 
11631
                         * sections
 
11632
                         */
 
11633
                         if ((ctxt->input->cur - ctxt->input->base >= 9) &&
 
11634
                             (!strncmp((const char *)&ctxt->input->cur[-9],
 
11635
                                       "<![CDATA[", 9)))
 
11636
                             ctxt->sax->cdataBlock(ctxt->userData,
 
11637
                                                   BAD_CAST "", 0);
 
11638
                    } else if ((ctxt->sax != NULL) && (base > 0) &&
 
11639
                        (!ctxt->disableSAX)) {
 
11640
                        if (ctxt->sax->cdataBlock != NULL)
 
11641
                            ctxt->sax->cdataBlock(ctxt->userData,
 
11642
                                                  ctxt->input->cur, base);
 
11643
                        else if (ctxt->sax->characters != NULL)
 
11644
                            ctxt->sax->characters(ctxt->userData,
 
11645
                                                  ctxt->input->cur, base);
 
11646
                    }
 
11647
                    if (ctxt->instate == XML_PARSER_EOF)
 
11648
                        goto done;
 
11649
                    SKIPL(base + 3);
 
11650
                    ctxt->checkIndex = 0;
 
11651
                    ctxt->instate = XML_PARSER_CONTENT;
 
11652
#ifdef DEBUG_PUSH
 
11653
                    xmlGenericError(xmlGenericErrorContext,
 
11654
                            "PP: entering CONTENT\n");
 
11655
#endif
 
11656
                }
 
11657
                break;
 
11658
            }
 
11659
            case XML_PARSER_MISC:
 
11660
                SKIP_BLANKS;
 
11661
                if (ctxt->input->buf == NULL)
 
11662
                    avail = ctxt->input->length -
 
11663
                            (ctxt->input->cur - ctxt->input->base);
 
11664
                else
 
11665
                    avail = xmlBufUse(ctxt->input->buf->buffer) -
 
11666
                            (ctxt->input->cur - ctxt->input->base);
 
11667
                if (avail < 2)
 
11668
                    goto done;
 
11669
                cur = ctxt->input->cur[0];
 
11670
                next = ctxt->input->cur[1];
 
11671
                if ((cur == '<') && (next == '?')) {
 
11672
                    if ((!terminate) &&
 
11673
                        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
 
11674
                        ctxt->progressive = XML_PARSER_PI;
 
11675
                        goto done;
 
11676
                    }
 
11677
#ifdef DEBUG_PUSH
 
11678
                    xmlGenericError(xmlGenericErrorContext,
 
11679
                            "PP: Parsing PI\n");
 
11680
#endif
 
11681
                    xmlParsePI(ctxt);
 
11682
                    if (ctxt->instate == XML_PARSER_EOF)
 
11683
                        goto done;
 
11684
                    ctxt->instate = XML_PARSER_MISC;
 
11685
                    ctxt->progressive = 1;
 
11686
                    ctxt->checkIndex = 0;
 
11687
                } else if ((cur == '<') && (next == '!') &&
 
11688
                    (ctxt->input->cur[2] == '-') &&
 
11689
                    (ctxt->input->cur[3] == '-')) {
 
11690
                    if ((!terminate) &&
 
11691
                        (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
 
11692
                        ctxt->progressive = XML_PARSER_COMMENT;
 
11693
                        goto done;
 
11694
                    }
 
11695
#ifdef DEBUG_PUSH
 
11696
                    xmlGenericError(xmlGenericErrorContext,
 
11697
                            "PP: Parsing Comment\n");
 
11698
#endif
 
11699
                    xmlParseComment(ctxt);
 
11700
                    if (ctxt->instate == XML_PARSER_EOF)
 
11701
                        goto done;
 
11702
                    ctxt->instate = XML_PARSER_MISC;
 
11703
                    ctxt->progressive = 1;
 
11704
                    ctxt->checkIndex = 0;
 
11705
                } else if ((cur == '<') && (next == '!') &&
 
11706
                    (ctxt->input->cur[2] == 'D') &&
 
11707
                    (ctxt->input->cur[3] == 'O') &&
 
11708
                    (ctxt->input->cur[4] == 'C') &&
 
11709
                    (ctxt->input->cur[5] == 'T') &&
 
11710
                    (ctxt->input->cur[6] == 'Y') &&
 
11711
                    (ctxt->input->cur[7] == 'P') &&
 
11712
                    (ctxt->input->cur[8] == 'E')) {
 
11713
                    if ((!terminate) &&
 
11714
                        (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0)) {
 
11715
                        ctxt->progressive = XML_PARSER_DTD;
 
11716
                        goto done;
 
11717
                    }
 
11718
#ifdef DEBUG_PUSH
 
11719
                    xmlGenericError(xmlGenericErrorContext,
 
11720
                            "PP: Parsing internal subset\n");
 
11721
#endif
 
11722
                    ctxt->inSubset = 1;
 
11723
                    ctxt->progressive = 0;
 
11724
                    ctxt->checkIndex = 0;
 
11725
                    xmlParseDocTypeDecl(ctxt);
 
11726
                    if (ctxt->instate == XML_PARSER_EOF)
 
11727
                        goto done;
 
11728
                    if (RAW == '[') {
 
11729
                        ctxt->instate = XML_PARSER_DTD;
 
11730
#ifdef DEBUG_PUSH
 
11731
                        xmlGenericError(xmlGenericErrorContext,
 
11732
                                "PP: entering DTD\n");
 
11733
#endif
 
11734
                    } else {
 
11735
                        /*
 
11736
                         * Create and update the external subset.
 
11737
                         */
 
11738
                        ctxt->inSubset = 2;
 
11739
                        if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
 
11740
                            (ctxt->sax->externalSubset != NULL))
 
11741
                            ctxt->sax->externalSubset(ctxt->userData,
 
11742
                                    ctxt->intSubName, ctxt->extSubSystem,
 
11743
                                    ctxt->extSubURI);
 
11744
                        ctxt->inSubset = 0;
 
11745
                        xmlCleanSpecialAttr(ctxt);
 
11746
                        ctxt->instate = XML_PARSER_PROLOG;
 
11747
#ifdef DEBUG_PUSH
 
11748
                        xmlGenericError(xmlGenericErrorContext,
 
11749
                                "PP: entering PROLOG\n");
 
11750
#endif
 
11751
                    }
 
11752
                } else if ((cur == '<') && (next == '!') &&
 
11753
                           (avail < 9)) {
 
11754
                    goto done;
 
11755
                } else {
 
11756
                    ctxt->instate = XML_PARSER_START_TAG;
 
11757
                    ctxt->progressive = XML_PARSER_START_TAG;
 
11758
                    xmlParseGetLasts(ctxt, &lastlt, &lastgt);
 
11759
#ifdef DEBUG_PUSH
 
11760
                    xmlGenericError(xmlGenericErrorContext,
 
11761
                            "PP: entering START_TAG\n");
 
11762
#endif
 
11763
                }
 
11764
                break;
 
11765
            case XML_PARSER_PROLOG:
 
11766
                SKIP_BLANKS;
 
11767
                if (ctxt->input->buf == NULL)
 
11768
                    avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
 
11769
                else
 
11770
                    avail = xmlBufUse(ctxt->input->buf->buffer) -
 
11771
                            (ctxt->input->cur - ctxt->input->base);
 
11772
                if (avail < 2)
 
11773
                    goto done;
 
11774
                cur = ctxt->input->cur[0];
 
11775
                next = ctxt->input->cur[1];
 
11776
                if ((cur == '<') && (next == '?')) {
 
11777
                    if ((!terminate) &&
 
11778
                        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
 
11779
                        ctxt->progressive = XML_PARSER_PI;
 
11780
                        goto done;
 
11781
                    }
 
11782
#ifdef DEBUG_PUSH
 
11783
                    xmlGenericError(xmlGenericErrorContext,
 
11784
                            "PP: Parsing PI\n");
 
11785
#endif
 
11786
                    xmlParsePI(ctxt);
 
11787
                    if (ctxt->instate == XML_PARSER_EOF)
 
11788
                        goto done;
 
11789
                    ctxt->instate = XML_PARSER_PROLOG;
 
11790
                    ctxt->progressive = 1;
 
11791
                } else if ((cur == '<') && (next == '!') &&
 
11792
                    (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
 
11793
                    if ((!terminate) &&
 
11794
                        (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
 
11795
                        ctxt->progressive = XML_PARSER_COMMENT;
 
11796
                        goto done;
 
11797
                    }
 
11798
#ifdef DEBUG_PUSH
 
11799
                    xmlGenericError(xmlGenericErrorContext,
 
11800
                            "PP: Parsing Comment\n");
 
11801
#endif
 
11802
                    xmlParseComment(ctxt);
 
11803
                    if (ctxt->instate == XML_PARSER_EOF)
 
11804
                        goto done;
 
11805
                    ctxt->instate = XML_PARSER_PROLOG;
 
11806
                    ctxt->progressive = 1;
 
11807
                } else if ((cur == '<') && (next == '!') &&
 
11808
                           (avail < 4)) {
 
11809
                    goto done;
 
11810
                } else {
 
11811
                    ctxt->instate = XML_PARSER_START_TAG;
 
11812
                    if (ctxt->progressive == 0)
 
11813
                        ctxt->progressive = XML_PARSER_START_TAG;
 
11814
                    xmlParseGetLasts(ctxt, &lastlt, &lastgt);
 
11815
#ifdef DEBUG_PUSH
 
11816
                    xmlGenericError(xmlGenericErrorContext,
 
11817
                            "PP: entering START_TAG\n");
 
11818
#endif
 
11819
                }
 
11820
                break;
 
11821
            case XML_PARSER_EPILOG:
 
11822
                SKIP_BLANKS;
 
11823
                if (ctxt->input->buf == NULL)
 
11824
                    avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
 
11825
                else
 
11826
                    avail = xmlBufUse(ctxt->input->buf->buffer) -
 
11827
                            (ctxt->input->cur - ctxt->input->base);
 
11828
                if (avail < 2)
 
11829
                    goto done;
 
11830
                cur = ctxt->input->cur[0];
 
11831
                next = ctxt->input->cur[1];
 
11832
                if ((cur == '<') && (next == '?')) {
 
11833
                    if ((!terminate) &&
 
11834
                        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
 
11835
                        ctxt->progressive = XML_PARSER_PI;
 
11836
                        goto done;
 
11837
                    }
 
11838
#ifdef DEBUG_PUSH
 
11839
                    xmlGenericError(xmlGenericErrorContext,
 
11840
                            "PP: Parsing PI\n");
 
11841
#endif
 
11842
                    xmlParsePI(ctxt);
 
11843
                    if (ctxt->instate == XML_PARSER_EOF)
 
11844
                        goto done;
 
11845
                    ctxt->instate = XML_PARSER_EPILOG;
 
11846
                    ctxt->progressive = 1;
 
11847
                } else if ((cur == '<') && (next == '!') &&
 
11848
                    (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
 
11849
                    if ((!terminate) &&
 
11850
                        (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
 
11851
                        ctxt->progressive = XML_PARSER_COMMENT;
 
11852
                        goto done;
 
11853
                    }
 
11854
#ifdef DEBUG_PUSH
 
11855
                    xmlGenericError(xmlGenericErrorContext,
 
11856
                            "PP: Parsing Comment\n");
 
11857
#endif
 
11858
                    xmlParseComment(ctxt);
 
11859
                    if (ctxt->instate == XML_PARSER_EOF)
 
11860
                        goto done;
 
11861
                    ctxt->instate = XML_PARSER_EPILOG;
 
11862
                    ctxt->progressive = 1;
 
11863
                } else if ((cur == '<') && (next == '!') &&
 
11864
                           (avail < 4)) {
 
11865
                    goto done;
 
11866
                } else {
 
11867
                    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
 
11868
                    ctxt->instate = XML_PARSER_EOF;
 
11869
#ifdef DEBUG_PUSH
 
11870
                    xmlGenericError(xmlGenericErrorContext,
 
11871
                            "PP: entering EOF\n");
 
11872
#endif
 
11873
                    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 
11874
                        ctxt->sax->endDocument(ctxt->userData);
 
11875
                    goto done;
 
11876
                }
 
11877
                break;
 
11878
            case XML_PARSER_DTD: {
 
11879
                /*
 
11880
                 * Sorry but progressive parsing of the internal subset
 
11881
                 * is not expected to be supported. We first check that
 
11882
                 * the full content of the internal subset is available and
 
11883
                 * the parsing is launched only at that point.
 
11884
                 * Internal subset ends up with "']' S? '>'" in an unescaped
 
11885
                 * section and not in a ']]>' sequence which are conditional
 
11886
                 * sections (whoever argued to keep that crap in XML deserve
 
11887
                 * a place in hell !).
 
11888
                 */
 
11889
                int base, i;
 
11890
                xmlChar *buf;
 
11891
                xmlChar quote = 0;
 
11892
                size_t use;
 
11893
 
 
11894
                base = ctxt->input->cur - ctxt->input->base;
 
11895
                if (base < 0) return(0);
 
11896
                if (ctxt->checkIndex > base)
 
11897
                    base = ctxt->checkIndex;
 
11898
                buf = xmlBufContent(ctxt->input->buf->buffer);
 
11899
                use = xmlBufUse(ctxt->input->buf->buffer);
 
11900
                for (;(unsigned int) base < use; base++) {
 
11901
                    if (quote != 0) {
 
11902
                        if (buf[base] == quote)
 
11903
                            quote = 0;
 
11904
                        continue;
 
11905
                    }
 
11906
                    if ((quote == 0) && (buf[base] == '<')) {
 
11907
                        int found  = 0;
 
11908
                        /* special handling of comments */
 
11909
                        if (((unsigned int) base + 4 < use) &&
 
11910
                            (buf[base + 1] == '!') &&
 
11911
                            (buf[base + 2] == '-') &&
 
11912
                            (buf[base + 3] == '-')) {
 
11913
                            for (;(unsigned int) base + 3 < use; base++) {
 
11914
                                if ((buf[base] == '-') &&
 
11915
                                    (buf[base + 1] == '-') &&
 
11916
                                    (buf[base + 2] == '>')) {
 
11917
                                    found = 1;
 
11918
                                    base += 2;
 
11919
                                    break;
 
11920
                                }
 
11921
                            }
 
11922
                            if (!found) {
 
11923
#if 0
 
11924
                                fprintf(stderr, "unfinished comment\n");
 
11925
#endif
 
11926
                                break; /* for */
 
11927
                            }
 
11928
                            continue;
 
11929
                        }
 
11930
                    }
 
11931
                    if (buf[base] == '"') {
 
11932
                        quote = '"';
 
11933
                        continue;
 
11934
                    }
 
11935
                    if (buf[base] == '\'') {
 
11936
                        quote = '\'';
 
11937
                        continue;
 
11938
                    }
 
11939
                    if (buf[base] == ']') {
 
11940
#if 0
 
11941
                        fprintf(stderr, "%c%c%c%c: ", buf[base],
 
11942
                                buf[base + 1], buf[base + 2], buf[base + 3]);
 
11943
#endif
 
11944
                        if ((unsigned int) base +1 >= use)
 
11945
                            break;
 
11946
                        if (buf[base + 1] == ']') {
 
11947
                            /* conditional crap, skip both ']' ! */
 
11948
                            base++;
 
11949
                            continue;
 
11950
                        }
 
11951
                        for (i = 1; (unsigned int) base + i < use; i++) {
 
11952
                            if (buf[base + i] == '>') {
 
11953
#if 0
 
11954
                                fprintf(stderr, "found\n");
 
11955
#endif
 
11956
                                goto found_end_int_subset;
 
11957
                            }
 
11958
                            if (!IS_BLANK_CH(buf[base + i])) {
 
11959
#if 0
 
11960
                                fprintf(stderr, "not found\n");
 
11961
#endif
 
11962
                                goto not_end_of_int_subset;
 
11963
                            }
 
11964
                        }
 
11965
#if 0
 
11966
                        fprintf(stderr, "end of stream\n");
 
11967
#endif
 
11968
                        break;
 
11969
 
 
11970
                    }
 
11971
not_end_of_int_subset:
 
11972
                    continue; /* for */
 
11973
                }
 
11974
                /*
 
11975
                 * We didn't found the end of the Internal subset
 
11976
                 */
 
11977
                if (quote == 0)
 
11978
                    ctxt->checkIndex = base;
 
11979
                else
 
11980
                    ctxt->checkIndex = 0;
 
11981
#ifdef DEBUG_PUSH
 
11982
                if (next == 0)
 
11983
                    xmlGenericError(xmlGenericErrorContext,
 
11984
                            "PP: lookup of int subset end filed\n");
 
11985
#endif
 
11986
                goto done;
 
11987
 
 
11988
found_end_int_subset:
 
11989
                ctxt->checkIndex = 0;
 
11990
                xmlParseInternalSubset(ctxt);
 
11991
                if (ctxt->instate == XML_PARSER_EOF)
 
11992
                    goto done;
 
11993
                ctxt->inSubset = 2;
 
11994
                if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
 
11995
                    (ctxt->sax->externalSubset != NULL))
 
11996
                    ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
 
11997
                            ctxt->extSubSystem, ctxt->extSubURI);
 
11998
                ctxt->inSubset = 0;
 
11999
                xmlCleanSpecialAttr(ctxt);
 
12000
                if (ctxt->instate == XML_PARSER_EOF)
 
12001
                    goto done;
 
12002
                ctxt->instate = XML_PARSER_PROLOG;
 
12003
                ctxt->checkIndex = 0;
 
12004
#ifdef DEBUG_PUSH
 
12005
                xmlGenericError(xmlGenericErrorContext,
 
12006
                        "PP: entering PROLOG\n");
 
12007
#endif
 
12008
                break;
 
12009
            }
 
12010
            case XML_PARSER_COMMENT:
 
12011
                xmlGenericError(xmlGenericErrorContext,
 
12012
                        "PP: internal error, state == COMMENT\n");
 
12013
                ctxt->instate = XML_PARSER_CONTENT;
 
12014
#ifdef DEBUG_PUSH
 
12015
                xmlGenericError(xmlGenericErrorContext,
 
12016
                        "PP: entering CONTENT\n");
 
12017
#endif
 
12018
                break;
 
12019
            case XML_PARSER_IGNORE:
 
12020
                xmlGenericError(xmlGenericErrorContext,
 
12021
                        "PP: internal error, state == IGNORE");
 
12022
                ctxt->instate = XML_PARSER_DTD;
 
12023
#ifdef DEBUG_PUSH
 
12024
                xmlGenericError(xmlGenericErrorContext,
 
12025
                        "PP: entering DTD\n");
 
12026
#endif
 
12027
                break;
 
12028
            case XML_PARSER_PI:
 
12029
                xmlGenericError(xmlGenericErrorContext,
 
12030
                        "PP: internal error, state == PI\n");
 
12031
                ctxt->instate = XML_PARSER_CONTENT;
 
12032
#ifdef DEBUG_PUSH
 
12033
                xmlGenericError(xmlGenericErrorContext,
 
12034
                        "PP: entering CONTENT\n");
 
12035
#endif
 
12036
                break;
 
12037
            case XML_PARSER_ENTITY_DECL:
 
12038
                xmlGenericError(xmlGenericErrorContext,
 
12039
                        "PP: internal error, state == ENTITY_DECL\n");
 
12040
                ctxt->instate = XML_PARSER_DTD;
 
12041
#ifdef DEBUG_PUSH
 
12042
                xmlGenericError(xmlGenericErrorContext,
 
12043
                        "PP: entering DTD\n");
 
12044
#endif
 
12045
                break;
 
12046
            case XML_PARSER_ENTITY_VALUE:
 
12047
                xmlGenericError(xmlGenericErrorContext,
 
12048
                        "PP: internal error, state == ENTITY_VALUE\n");
 
12049
                ctxt->instate = XML_PARSER_CONTENT;
 
12050
#ifdef DEBUG_PUSH
 
12051
                xmlGenericError(xmlGenericErrorContext,
 
12052
                        "PP: entering DTD\n");
 
12053
#endif
 
12054
                break;
 
12055
            case XML_PARSER_ATTRIBUTE_VALUE:
 
12056
                xmlGenericError(xmlGenericErrorContext,
 
12057
                        "PP: internal error, state == ATTRIBUTE_VALUE\n");
 
12058
                ctxt->instate = XML_PARSER_START_TAG;
 
12059
#ifdef DEBUG_PUSH
 
12060
                xmlGenericError(xmlGenericErrorContext,
 
12061
                        "PP: entering START_TAG\n");
 
12062
#endif
 
12063
                break;
 
12064
            case XML_PARSER_SYSTEM_LITERAL:
 
12065
                xmlGenericError(xmlGenericErrorContext,
 
12066
                        "PP: internal error, state == SYSTEM_LITERAL\n");
 
12067
                ctxt->instate = XML_PARSER_START_TAG;
 
12068
#ifdef DEBUG_PUSH
 
12069
                xmlGenericError(xmlGenericErrorContext,
 
12070
                        "PP: entering START_TAG\n");
 
12071
#endif
 
12072
                break;
 
12073
            case XML_PARSER_PUBLIC_LITERAL:
 
12074
                xmlGenericError(xmlGenericErrorContext,
 
12075
                        "PP: internal error, state == PUBLIC_LITERAL\n");
 
12076
                ctxt->instate = XML_PARSER_START_TAG;
 
12077
#ifdef DEBUG_PUSH
 
12078
                xmlGenericError(xmlGenericErrorContext,
 
12079
                        "PP: entering START_TAG\n");
 
12080
#endif
 
12081
                break;
 
12082
        }
 
12083
    }
 
12084
done:
 
12085
#ifdef DEBUG_PUSH
 
12086
    xmlGenericError(xmlGenericErrorContext, "PP: done %d\n", ret);
 
12087
#endif
 
12088
    return(ret);
 
12089
encoding_error:
 
12090
    {
 
12091
        char buffer[150];
 
12092
 
 
12093
        snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
 
12094
                        ctxt->input->cur[0], ctxt->input->cur[1],
 
12095
                        ctxt->input->cur[2], ctxt->input->cur[3]);
 
12096
        __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
 
12097
                     "Input is not proper UTF-8, indicate encoding !\n%s",
 
12098
                     BAD_CAST buffer, NULL);
 
12099
    }
 
12100
    return(0);
 
12101
}
 
12102
 
 
12103
/**
 
12104
 * xmlParseCheckTransition:
 
12105
 * @ctxt:  an XML parser context
 
12106
 * @chunk:  a char array
 
12107
 * @size:  the size in byte of the chunk
 
12108
 *
 
12109
 * Check depending on the current parser state if the chunk given must be
 
12110
 * processed immediately or one need more data to advance on parsing.
 
12111
 *
 
12112
 * Returns -1 in case of error, 0 if the push is not needed and 1 if needed
 
12113
 */
 
12114
static int
 
12115
xmlParseCheckTransition(xmlParserCtxtPtr ctxt, const char *chunk, int size) {
 
12116
    if ((ctxt == NULL) || (chunk == NULL) || (size < 0))
 
12117
        return(-1);
 
12118
    if (ctxt->instate == XML_PARSER_START_TAG) {
 
12119
        if (memchr(chunk, '>', size) != NULL)
 
12120
            return(1);
 
12121
        return(0);
 
12122
    }
 
12123
    if (ctxt->progressive == XML_PARSER_COMMENT) {
 
12124
        if (memchr(chunk, '>', size) != NULL)
 
12125
            return(1);
 
12126
        return(0);
 
12127
    }
 
12128
    if (ctxt->instate == XML_PARSER_CDATA_SECTION) {
 
12129
        if (memchr(chunk, '>', size) != NULL)
 
12130
            return(1);
 
12131
        return(0);
 
12132
    }
 
12133
    if (ctxt->progressive == XML_PARSER_PI) {
 
12134
        if (memchr(chunk, '>', size) != NULL)
 
12135
            return(1);
 
12136
        return(0);
 
12137
    }
 
12138
    if (ctxt->instate == XML_PARSER_END_TAG) {
 
12139
        if (memchr(chunk, '>', size) != NULL)
 
12140
            return(1);
 
12141
        return(0);
 
12142
    }
 
12143
    if ((ctxt->progressive == XML_PARSER_DTD) ||
 
12144
        (ctxt->instate == XML_PARSER_DTD)) {
 
12145
        if (memchr(chunk, '>', size) != NULL)
 
12146
            return(1);
 
12147
        return(0);
 
12148
    }
 
12149
    return(1);
 
12150
}
 
12151
 
 
12152
/**
 
12153
 * xmlParseChunk:
 
12154
 * @ctxt:  an XML parser context
 
12155
 * @chunk:  an char array
 
12156
 * @size:  the size in byte of the chunk
 
12157
 * @terminate:  last chunk indicator
 
12158
 *
 
12159
 * Parse a Chunk of memory
 
12160
 *
 
12161
 * Returns zero if no error, the xmlParserErrors otherwise.
 
12162
 */
 
12163
int
 
12164
xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
 
12165
              int terminate) {
 
12166
    int end_in_lf = 0;
 
12167
    int remain = 0;
 
12168
    size_t old_avail = 0;
 
12169
    size_t avail = 0;
 
12170
 
 
12171
    if (ctxt == NULL)
 
12172
        return(XML_ERR_INTERNAL_ERROR);
 
12173
    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
 
12174
        return(ctxt->errNo);
 
12175
    if (ctxt->instate == XML_PARSER_EOF)
 
12176
        return(-1);
 
12177
    if (ctxt->instate == XML_PARSER_START)
 
12178
        xmlDetectSAX2(ctxt);
 
12179
    if ((size > 0) && (chunk != NULL) && (!terminate) &&
 
12180
        (chunk[size - 1] == '\r')) {
 
12181
        end_in_lf = 1;
 
12182
        size--;
 
12183
    }
 
12184
 
 
12185
xmldecl_done:
 
12186
 
 
12187
    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
 
12188
        (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF))  {
 
12189
        size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
 
12190
        size_t cur = ctxt->input->cur - ctxt->input->base;
 
12191
        int res;
 
12192
 
 
12193
        old_avail = xmlBufUse(ctxt->input->buf->buffer);
 
12194
        /*
 
12195
         * Specific handling if we autodetected an encoding, we should not
 
12196
         * push more than the first line ... which depend on the encoding
 
12197
         * And only push the rest once the final encoding was detected
 
12198
         */
 
12199
        if ((ctxt->instate == XML_PARSER_START) && (ctxt->input != NULL) &&
 
12200
            (ctxt->input->buf != NULL) && (ctxt->input->buf->encoder != NULL)) {
 
12201
            unsigned int len = 45;
 
12202
 
 
12203
            if ((xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
 
12204
                               BAD_CAST "UTF-16")) ||
 
12205
                (xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
 
12206
                               BAD_CAST "UTF16")))
 
12207
                len = 90;
 
12208
            else if ((xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
 
12209
                                    BAD_CAST "UCS-4")) ||
 
12210
                     (xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
 
12211
                                    BAD_CAST "UCS4")))
 
12212
                len = 180;
 
12213
 
 
12214
            if (ctxt->input->buf->rawconsumed < len)
 
12215
                len -= ctxt->input->buf->rawconsumed;
 
12216
 
 
12217
            /*
 
12218
             * Change size for reading the initial declaration only
 
12219
             * if size is greater than len. Otherwise, memmove in xmlBufferAdd
 
12220
             * will blindly copy extra bytes from memory.
 
12221
             */
 
12222
            if ((unsigned int) size > len) {
 
12223
                remain = size - len;
 
12224
                size = len;
 
12225
            } else {
 
12226
                remain = 0;
 
12227
            }
 
12228
        }
 
12229
        res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
 
12230
        if (res < 0) {
 
12231
            ctxt->errNo = XML_PARSER_EOF;
 
12232
            ctxt->disableSAX = 1;
 
12233
            return (XML_PARSER_EOF);
 
12234
        }
 
12235
        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
 
12236
#ifdef DEBUG_PUSH
 
12237
        xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
 
12238
#endif
 
12239
 
 
12240
    } else if (ctxt->instate != XML_PARSER_EOF) {
 
12241
        if ((ctxt->input != NULL) && ctxt->input->buf != NULL) {
 
12242
            xmlParserInputBufferPtr in = ctxt->input->buf;
 
12243
            if ((in->encoder != NULL) && (in->buffer != NULL) &&
 
12244
                    (in->raw != NULL)) {
 
12245
                int nbchars;
 
12246
                size_t base = xmlBufGetInputBase(in->buffer, ctxt->input);
 
12247
                size_t current = ctxt->input->cur - ctxt->input->base;
 
12248
 
 
12249
                nbchars = xmlCharEncInput(in, terminate);
 
12250
                if (nbchars < 0) {
 
12251
                    /* TODO 2.6.0 */
 
12252
                    xmlGenericError(xmlGenericErrorContext,
 
12253
                                    "xmlParseChunk: encoder error\n");
 
12254
                    return(XML_ERR_INVALID_ENCODING);
 
12255
                }
 
12256
                xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
 
12257
            }
 
12258
        }
 
12259
    }
 
12260
    if (remain != 0) {
 
12261
        xmlParseTryOrFinish(ctxt, 0);
 
12262
    } else {
 
12263
        if ((ctxt->input != NULL) && (ctxt->input->buf != NULL))
 
12264
            avail = xmlBufUse(ctxt->input->buf->buffer);
 
12265
        /*
 
12266
         * Depending on the current state it may not be such
 
12267
         * a good idea to try parsing if there is nothing in the chunk
 
12268
         * which would be worth doing a parser state transition and we
 
12269
         * need to wait for more data
 
12270
         */
 
12271
        if ((terminate) || (avail > XML_MAX_TEXT_LENGTH) ||
 
12272
            (old_avail == 0) || (avail == 0) ||
 
12273
            (xmlParseCheckTransition(ctxt,
 
12274
                       (const char *)&ctxt->input->base[old_avail],
 
12275
                                     avail - old_avail)))
 
12276
            xmlParseTryOrFinish(ctxt, terminate);
 
12277
    }
 
12278
    if (ctxt->instate == XML_PARSER_EOF)
 
12279
        return(ctxt->errNo);
 
12280
 
 
12281
    if ((ctxt->input != NULL) &&
 
12282
         (((ctxt->input->end - ctxt->input->cur) > XML_MAX_LOOKUP_LIMIT) ||
 
12283
         ((ctxt->input->cur - ctxt->input->base) > XML_MAX_LOOKUP_LIMIT)) &&
 
12284
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
12285
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
 
12286
        ctxt->instate = XML_PARSER_EOF;
 
12287
    }
 
12288
    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
 
12289
        return(ctxt->errNo);
 
12290
 
 
12291
    if (remain != 0) {
 
12292
        chunk += size;
 
12293
        size = remain;
 
12294
        remain = 0;
 
12295
        goto xmldecl_done;
 
12296
    }
 
12297
    if ((end_in_lf == 1) && (ctxt->input != NULL) &&
 
12298
        (ctxt->input->buf != NULL)) {
 
12299
        size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer,
 
12300
                                         ctxt->input);
 
12301
        size_t current = ctxt->input->cur - ctxt->input->base;
 
12302
 
 
12303
        xmlParserInputBufferPush(ctxt->input->buf, 1, "\r");
 
12304
 
 
12305
        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input,
 
12306
                              base, current);
 
12307
    }
 
12308
    if (terminate) {
 
12309
        /*
 
12310
         * Check for termination
 
12311
         */
 
12312
        int cur_avail = 0;
 
12313
 
 
12314
        if (ctxt->input != NULL) {
 
12315
            if (ctxt->input->buf == NULL)
 
12316
                cur_avail = ctxt->input->length -
 
12317
                            (ctxt->input->cur - ctxt->input->base);
 
12318
            else
 
12319
                cur_avail = xmlBufUse(ctxt->input->buf->buffer) -
 
12320
                                      (ctxt->input->cur - ctxt->input->base);
 
12321
        }
 
12322
 
 
12323
        if ((ctxt->instate != XML_PARSER_EOF) &&
 
12324
            (ctxt->instate != XML_PARSER_EPILOG)) {
 
12325
            xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
 
12326
        }
 
12327
        if ((ctxt->instate == XML_PARSER_EPILOG) && (cur_avail > 0)) {
 
12328
            xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
 
12329
        }
 
12330
        if (ctxt->instate != XML_PARSER_EOF) {
 
12331
            if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 
12332
                ctxt->sax->endDocument(ctxt->userData);
 
12333
        }
 
12334
        ctxt->instate = XML_PARSER_EOF;
 
12335
    }
 
12336
    if (ctxt->wellFormed == 0)
 
12337
        return((xmlParserErrors) ctxt->errNo);
 
12338
    else
 
12339
        return(0);
 
12340
}
 
12341
 
 
12342
/************************************************************************
 
12343
 *                                                                      *
 
12344
 *              I/O front end functions to the parser                   *
 
12345
 *                                                                      *
 
12346
 ************************************************************************/
 
12347
 
 
12348
/**
 
12349
 * xmlCreatePushParserCtxt:
 
12350
 * @sax:  a SAX handler
 
12351
 * @user_data:  The user data returned on SAX callbacks
 
12352
 * @chunk:  a pointer to an array of chars
 
12353
 * @size:  number of chars in the array
 
12354
 * @filename:  an optional file name or URI
 
12355
 *
 
12356
 * Create a parser context for using the XML parser in push mode.
 
12357
 * If @buffer and @size are non-NULL, the data is used to detect
 
12358
 * the encoding.  The remaining characters will be parsed so they
 
12359
 * don't need to be fed in again through xmlParseChunk.
 
12360
 * To allow content encoding detection, @size should be >= 4
 
12361
 * The value of @filename is used for fetching external entities
 
12362
 * and error/warning reports.
 
12363
 *
 
12364
 * Returns the new parser context or NULL
 
12365
 */
 
12366
 
 
12367
xmlParserCtxtPtr
 
12368
xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
 
12369
                        const char *chunk, int size, const char *filename) {
 
12370
    xmlParserCtxtPtr ctxt;
 
12371
    xmlParserInputPtr inputStream;
 
12372
    xmlParserInputBufferPtr buf;
 
12373
    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
 
12374
 
 
12375
    /*
 
12376
     * plug some encoding conversion routines
 
12377
     */
 
12378
    if ((chunk != NULL) && (size >= 4))
 
12379
        enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
 
12380
 
 
12381
    buf = xmlAllocParserInputBuffer(enc);
 
12382
    if (buf == NULL) return(NULL);
 
12383
 
 
12384
    ctxt = xmlNewParserCtxt();
 
12385
    if (ctxt == NULL) {
 
12386
        xmlErrMemory(NULL, "creating parser: out of memory\n");
 
12387
        xmlFreeParserInputBuffer(buf);
 
12388
        return(NULL);
 
12389
    }
 
12390
    ctxt->dictNames = 1;
 
12391
    ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 * sizeof(xmlChar *));
 
12392
    if (ctxt->pushTab == NULL) {
 
12393
        xmlErrMemory(ctxt, NULL);
 
12394
        xmlFreeParserInputBuffer(buf);
 
12395
        xmlFreeParserCtxt(ctxt);
 
12396
        return(NULL);
 
12397
    }
 
12398
    if (sax != NULL) {
 
12399
#ifdef LIBXML_SAX1_ENABLED
 
12400
        if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
 
12401
#endif /* LIBXML_SAX1_ENABLED */
 
12402
            xmlFree(ctxt->sax);
 
12403
        ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
 
12404
        if (ctxt->sax == NULL) {
 
12405
            xmlErrMemory(ctxt, NULL);
 
12406
            xmlFreeParserInputBuffer(buf);
 
12407
            xmlFreeParserCtxt(ctxt);
 
12408
            return(NULL);
 
12409
        }
 
12410
        memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
 
12411
        if (sax->initialized == XML_SAX2_MAGIC)
 
12412
            memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
 
12413
        else
 
12414
            memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
 
12415
        if (user_data != NULL)
 
12416
            ctxt->userData = user_data;
 
12417
    }
 
12418
    if (filename == NULL) {
 
12419
        ctxt->directory = NULL;
 
12420
    } else {
 
12421
        ctxt->directory = xmlParserGetDirectory(filename);
 
12422
    }
 
12423
 
 
12424
    inputStream = xmlNewInputStream(ctxt);
 
12425
    if (inputStream == NULL) {
 
12426
        xmlFreeParserCtxt(ctxt);
 
12427
        xmlFreeParserInputBuffer(buf);
 
12428
        return(NULL);
 
12429
    }
 
12430
 
 
12431
    if (filename == NULL)
 
12432
        inputStream->filename = NULL;
 
12433
    else {
 
12434
        inputStream->filename = (char *)
 
12435
            xmlCanonicPath((const xmlChar *) filename);
 
12436
        if (inputStream->filename == NULL) {
 
12437
            xmlFreeParserCtxt(ctxt);
 
12438
            xmlFreeParserInputBuffer(buf);
 
12439
            return(NULL);
 
12440
        }
 
12441
    }
 
12442
    inputStream->buf = buf;
 
12443
    xmlBufResetInput(inputStream->buf->buffer, inputStream);
 
12444
    inputPush(ctxt, inputStream);
 
12445
 
 
12446
    /*
 
12447
     * If the caller didn't provide an initial 'chunk' for determining
 
12448
     * the encoding, we set the context to XML_CHAR_ENCODING_NONE so
 
12449
     * that it can be automatically determined later
 
12450
     */
 
12451
    if ((size == 0) || (chunk == NULL)) {
 
12452
        ctxt->charset = XML_CHAR_ENCODING_NONE;
 
12453
    } else if ((ctxt->input != NULL) && (ctxt->input->buf != NULL)) {
 
12454
        size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
 
12455
        size_t cur = ctxt->input->cur - ctxt->input->base;
 
12456
 
 
12457
        xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
 
12458
 
 
12459
        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
 
12460
#ifdef DEBUG_PUSH
 
12461
        xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
 
12462
#endif
 
12463
    }
 
12464
 
 
12465
    if (enc != XML_CHAR_ENCODING_NONE) {
 
12466
        xmlSwitchEncoding(ctxt, enc);
 
12467
    }
 
12468
 
 
12469
    return(ctxt);
 
12470
}
 
12471
#endif /* LIBXML_PUSH_ENABLED */
 
12472
 
 
12473
/**
 
12474
 * xmlStopParser:
 
12475
 * @ctxt:  an XML parser context
 
12476
 *
 
12477
 * Blocks further parser processing
 
12478
 */
 
12479
void
 
12480
xmlStopParser(xmlParserCtxtPtr ctxt) {
 
12481
    if (ctxt == NULL)
 
12482
        return;
 
12483
    ctxt->instate = XML_PARSER_EOF;
 
12484
    ctxt->errNo = XML_ERR_USER_STOP;
 
12485
    ctxt->disableSAX = 1;
 
12486
    if (ctxt->input != NULL) {
 
12487
        ctxt->input->cur = BAD_CAST"";
 
12488
        ctxt->input->base = ctxt->input->cur;
 
12489
    }
 
12490
}
 
12491
 
 
12492
/**
 
12493
 * xmlCreateIOParserCtxt:
 
12494
 * @sax:  a SAX handler
 
12495
 * @user_data:  The user data returned on SAX callbacks
 
12496
 * @ioread:  an I/O read function
 
12497
 * @ioclose:  an I/O close function
 
12498
 * @ioctx:  an I/O handler
 
12499
 * @enc:  the charset encoding if known
 
12500
 *
 
12501
 * Create a parser context for using the XML parser with an existing
 
12502
 * I/O stream
 
12503
 *
 
12504
 * Returns the new parser context or NULL
 
12505
 */
 
12506
xmlParserCtxtPtr
 
12507
xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
 
12508
        xmlInputReadCallback   ioread, xmlInputCloseCallback  ioclose,
 
12509
        void *ioctx, xmlCharEncoding enc) {
 
12510
    xmlParserCtxtPtr ctxt;
 
12511
    xmlParserInputPtr inputStream;
 
12512
    xmlParserInputBufferPtr buf;
 
12513
 
 
12514
    if (ioread == NULL) return(NULL);
 
12515
 
 
12516
    buf = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, enc);
 
12517
    if (buf == NULL) {
 
12518
        if (ioclose != NULL)
 
12519
            ioclose(ioctx);
 
12520
        return (NULL);
 
12521
    }
 
12522
 
 
12523
    ctxt = xmlNewParserCtxt();
 
12524
    if (ctxt == NULL) {
 
12525
        xmlFreeParserInputBuffer(buf);
 
12526
        return(NULL);
 
12527
    }
 
12528
    if (sax != NULL) {
 
12529
#ifdef LIBXML_SAX1_ENABLED
 
12530
        if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
 
12531
#endif /* LIBXML_SAX1_ENABLED */
 
12532
            xmlFree(ctxt->sax);
 
12533
        ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
 
12534
        if (ctxt->sax == NULL) {
 
12535
            xmlErrMemory(ctxt, NULL);
 
12536
            xmlFreeParserCtxt(ctxt);
 
12537
            return(NULL);
 
12538
        }
 
12539
        memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
 
12540
        if (sax->initialized == XML_SAX2_MAGIC)
 
12541
            memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
 
12542
        else
 
12543
            memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
 
12544
        if (user_data != NULL)
 
12545
            ctxt->userData = user_data;
 
12546
    }
 
12547
 
 
12548
    inputStream = xmlNewIOInputStream(ctxt, buf, enc);
 
12549
    if (inputStream == NULL) {
 
12550
        xmlFreeParserCtxt(ctxt);
 
12551
        return(NULL);
 
12552
    }
 
12553
    inputPush(ctxt, inputStream);
 
12554
 
 
12555
    return(ctxt);
 
12556
}
 
12557
 
 
12558
#ifdef LIBXML_VALID_ENABLED
 
12559
/************************************************************************
 
12560
 *                                                                      *
 
12561
 *              Front ends when parsing a DTD                           *
 
12562
 *                                                                      *
 
12563
 ************************************************************************/
 
12564
 
 
12565
/**
 
12566
 * xmlIOParseDTD:
 
12567
 * @sax:  the SAX handler block or NULL
 
12568
 * @input:  an Input Buffer
 
12569
 * @enc:  the charset encoding if known
 
12570
 *
 
12571
 * Load and parse a DTD
 
12572
 *
 
12573
 * Returns the resulting xmlDtdPtr or NULL in case of error.
 
12574
 * @input will be freed by the function in any case.
 
12575
 */
 
12576
 
 
12577
xmlDtdPtr
 
12578
xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
 
12579
              xmlCharEncoding enc) {
 
12580
    xmlDtdPtr ret = NULL;
 
12581
    xmlParserCtxtPtr ctxt;
 
12582
    xmlParserInputPtr pinput = NULL;
 
12583
    xmlChar start[4];
 
12584
 
 
12585
    if (input == NULL)
 
12586
        return(NULL);
 
12587
 
 
12588
    ctxt = xmlNewParserCtxt();
 
12589
    if (ctxt == NULL) {
 
12590
        xmlFreeParserInputBuffer(input);
 
12591
        return(NULL);
 
12592
    }
 
12593
 
 
12594
    /*
 
12595
     * Set-up the SAX context
 
12596
     */
 
12597
    if (sax != NULL) {
 
12598
        if (ctxt->sax != NULL)
 
12599
            xmlFree(ctxt->sax);
 
12600
        ctxt->sax = sax;
 
12601
        ctxt->userData = ctxt;
 
12602
    }
 
12603
    xmlDetectSAX2(ctxt);
 
12604
 
 
12605
    /*
 
12606
     * generate a parser input from the I/O handler
 
12607
     */
 
12608
 
 
12609
    pinput = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
 
12610
    if (pinput == NULL) {
 
12611
        if (sax != NULL) ctxt->sax = NULL;
 
12612
        xmlFreeParserInputBuffer(input);
 
12613
        xmlFreeParserCtxt(ctxt);
 
12614
        return(NULL);
 
12615
    }
 
12616
 
 
12617
    /*
 
12618
     * plug some encoding conversion routines here.
 
12619
     */
 
12620
    if (xmlPushInput(ctxt, pinput) < 0) {
 
12621
        if (sax != NULL) ctxt->sax = NULL;
 
12622
        xmlFreeParserCtxt(ctxt);
 
12623
        return(NULL);
 
12624
    }
 
12625
    if (enc != XML_CHAR_ENCODING_NONE) {
 
12626
        xmlSwitchEncoding(ctxt, enc);
 
12627
    }
 
12628
 
 
12629
    pinput->filename = NULL;
 
12630
    pinput->line = 1;
 
12631
    pinput->col = 1;
 
12632
    pinput->base = ctxt->input->cur;
 
12633
    pinput->cur = ctxt->input->cur;
 
12634
    pinput->free = NULL;
 
12635
 
 
12636
    /*
 
12637
     * let's parse that entity knowing it's an external subset.
 
12638
     */
 
12639
    ctxt->inSubset = 2;
 
12640
    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
 
12641
    if (ctxt->myDoc == NULL) {
 
12642
        xmlErrMemory(ctxt, "New Doc failed");
 
12643
        return(NULL);
 
12644
    }
 
12645
    ctxt->myDoc->properties = XML_DOC_INTERNAL;
 
12646
    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
 
12647
                                       BAD_CAST "none", BAD_CAST "none");
 
12648
 
 
12649
    if ((enc == XML_CHAR_ENCODING_NONE) &&
 
12650
        ((ctxt->input->end - ctxt->input->cur) >= 4)) {
 
12651
        /*
 
12652
         * Get the 4 first bytes and decode the charset
 
12653
         * if enc != XML_CHAR_ENCODING_NONE
 
12654
         * plug some encoding conversion routines.
 
12655
         */
 
12656
        start[0] = RAW;
 
12657
        start[1] = NXT(1);
 
12658
        start[2] = NXT(2);
 
12659
        start[3] = NXT(3);
 
12660
        enc = xmlDetectCharEncoding(start, 4);
 
12661
        if (enc != XML_CHAR_ENCODING_NONE) {
 
12662
            xmlSwitchEncoding(ctxt, enc);
 
12663
        }
 
12664
    }
 
12665
 
 
12666
    xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none");
 
12667
 
 
12668
    if (ctxt->myDoc != NULL) {
 
12669
        if (ctxt->wellFormed) {
 
12670
            ret = ctxt->myDoc->extSubset;
 
12671
            ctxt->myDoc->extSubset = NULL;
 
12672
            if (ret != NULL) {
 
12673
                xmlNodePtr tmp;
 
12674
 
 
12675
                ret->doc = NULL;
 
12676
                tmp = ret->children;
 
12677
                while (tmp != NULL) {
 
12678
                    tmp->doc = NULL;
 
12679
                    tmp = tmp->next;
 
12680
                }
 
12681
            }
 
12682
        } else {
 
12683
            ret = NULL;
 
12684
        }
 
12685
        xmlFreeDoc(ctxt->myDoc);
 
12686
        ctxt->myDoc = NULL;
 
12687
    }
 
12688
    if (sax != NULL) ctxt->sax = NULL;
 
12689
    xmlFreeParserCtxt(ctxt);
 
12690
 
 
12691
    return(ret);
 
12692
}
 
12693
 
 
12694
/**
 
12695
 * xmlSAXParseDTD:
 
12696
 * @sax:  the SAX handler block
 
12697
 * @ExternalID:  a NAME* containing the External ID of the DTD
 
12698
 * @SystemID:  a NAME* containing the URL to the DTD
 
12699
 *
 
12700
 * Load and parse an external subset.
 
12701
 *
 
12702
 * Returns the resulting xmlDtdPtr or NULL in case of error.
 
12703
 */
 
12704
 
 
12705
xmlDtdPtr
 
12706
xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
 
12707
                          const xmlChar *SystemID) {
 
12708
    xmlDtdPtr ret = NULL;
 
12709
    xmlParserCtxtPtr ctxt;
 
12710
    xmlParserInputPtr input = NULL;
 
12711
    xmlCharEncoding enc;
 
12712
    xmlChar* systemIdCanonic;
 
12713
 
 
12714
    if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
 
12715
 
 
12716
    ctxt = xmlNewParserCtxt();
 
12717
    if (ctxt == NULL) {
 
12718
        return(NULL);
 
12719
    }
 
12720
 
 
12721
    /*
 
12722
     * Set-up the SAX context
 
12723
     */
 
12724
    if (sax != NULL) {
 
12725
        if (ctxt->sax != NULL)
 
12726
            xmlFree(ctxt->sax);
 
12727
        ctxt->sax = sax;
 
12728
        ctxt->userData = ctxt;
 
12729
    }
 
12730
 
 
12731
    /*
 
12732
     * Canonicalise the system ID
 
12733
     */
 
12734
    systemIdCanonic = xmlCanonicPath(SystemID);
 
12735
    if ((SystemID != NULL) && (systemIdCanonic == NULL)) {
 
12736
        xmlFreeParserCtxt(ctxt);
 
12737
        return(NULL);
 
12738
    }
 
12739
 
 
12740
    /*
 
12741
     * Ask the Entity resolver to load the damn thing
 
12742
     */
 
12743
 
 
12744
    if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
 
12745
        input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
 
12746
                                         systemIdCanonic);
 
12747
    if (input == NULL) {
 
12748
        if (sax != NULL) ctxt->sax = NULL;
 
12749
        xmlFreeParserCtxt(ctxt);
 
12750
        if (systemIdCanonic != NULL)
 
12751
            xmlFree(systemIdCanonic);
 
12752
        return(NULL);
 
12753
    }
 
12754
 
 
12755
    /*
 
12756
     * plug some encoding conversion routines here.
 
12757
     */
 
12758
    if (xmlPushInput(ctxt, input) < 0) {
 
12759
        if (sax != NULL) ctxt->sax = NULL;
 
12760
        xmlFreeParserCtxt(ctxt);
 
12761
        if (systemIdCanonic != NULL)
 
12762
            xmlFree(systemIdCanonic);
 
12763
        return(NULL);
 
12764
    }
 
12765
    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
 
12766
        enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
 
12767
        xmlSwitchEncoding(ctxt, enc);
 
12768
    }
 
12769
 
 
12770
    if (input->filename == NULL)
 
12771
        input->filename = (char *) systemIdCanonic;
 
12772
    else
 
12773
        xmlFree(systemIdCanonic);
 
12774
    input->line = 1;
 
12775
    input->col = 1;
 
12776
    input->base = ctxt->input->cur;
 
12777
    input->cur = ctxt->input->cur;
 
12778
    input->free = NULL;
 
12779
 
 
12780
    /*
 
12781
     * let's parse that entity knowing it's an external subset.
 
12782
     */
 
12783
    ctxt->inSubset = 2;
 
12784
    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
 
12785
    if (ctxt->myDoc == NULL) {
 
12786
        xmlErrMemory(ctxt, "New Doc failed");
 
12787
        if (sax != NULL) ctxt->sax = NULL;
 
12788
        xmlFreeParserCtxt(ctxt);
 
12789
        return(NULL);
 
12790
    }
 
12791
    ctxt->myDoc->properties = XML_DOC_INTERNAL;
 
12792
    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
 
12793
                                       ExternalID, SystemID);
 
12794
    xmlParseExternalSubset(ctxt, ExternalID, SystemID);
 
12795
 
 
12796
    if (ctxt->myDoc != NULL) {
 
12797
        if (ctxt->wellFormed) {
 
12798
            ret = ctxt->myDoc->extSubset;
 
12799
            ctxt->myDoc->extSubset = NULL;
 
12800
            if (ret != NULL) {
 
12801
                xmlNodePtr tmp;
 
12802
 
 
12803
                ret->doc = NULL;
 
12804
                tmp = ret->children;
 
12805
                while (tmp != NULL) {
 
12806
                    tmp->doc = NULL;
 
12807
                    tmp = tmp->next;
 
12808
                }
 
12809
            }
 
12810
        } else {
 
12811
            ret = NULL;
 
12812
        }
 
12813
        xmlFreeDoc(ctxt->myDoc);
 
12814
        ctxt->myDoc = NULL;
 
12815
    }
 
12816
    if (sax != NULL) ctxt->sax = NULL;
 
12817
    xmlFreeParserCtxt(ctxt);
 
12818
 
 
12819
    return(ret);
 
12820
}
 
12821
 
 
12822
 
 
12823
/**
 
12824
 * xmlParseDTD:
 
12825
 * @ExternalID:  a NAME* containing the External ID of the DTD
 
12826
 * @SystemID:  a NAME* containing the URL to the DTD
 
12827
 *
 
12828
 * Load and parse an external subset.
 
12829
 *
 
12830
 * Returns the resulting xmlDtdPtr or NULL in case of error.
 
12831
 */
 
12832
 
 
12833
xmlDtdPtr
 
12834
xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
 
12835
    return(xmlSAXParseDTD(NULL, ExternalID, SystemID));
 
12836
}
 
12837
#endif /* LIBXML_VALID_ENABLED */
 
12838
 
 
12839
/************************************************************************
 
12840
 *                                                                      *
 
12841
 *              Front ends when parsing an Entity                       *
 
12842
 *                                                                      *
 
12843
 ************************************************************************/
 
12844
 
 
12845
/**
 
12846
 * xmlParseCtxtExternalEntity:
 
12847
 * @ctx:  the existing parsing context
 
12848
 * @URL:  the URL for the entity to load
 
12849
 * @ID:  the System ID for the entity to load
 
12850
 * @lst:  the return value for the set of parsed nodes
 
12851
 *
 
12852
 * Parse an external general entity within an existing parsing context
 
12853
 * An external general parsed entity is well-formed if it matches the
 
12854
 * production labeled extParsedEnt.
 
12855
 *
 
12856
 * [78] extParsedEnt ::= TextDecl? content
 
12857
 *
 
12858
 * Returns 0 if the entity is well formed, -1 in case of args problem and
 
12859
 *    the parser error code otherwise
 
12860
 */
 
12861
 
 
12862
int
 
12863
xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
 
12864
                       const xmlChar *ID, xmlNodePtr *lst) {
 
12865
    xmlParserCtxtPtr ctxt;
 
12866
    xmlDocPtr newDoc;
 
12867
    xmlNodePtr newRoot;
 
12868
    xmlSAXHandlerPtr oldsax = NULL;
 
12869
    int ret = 0;
 
12870
    xmlChar start[4];
 
12871
    xmlCharEncoding enc;
 
12872
 
 
12873
    if (ctx == NULL) return(-1);
 
12874
 
 
12875
    if (((ctx->depth > 40) && ((ctx->options & XML_PARSE_HUGE) == 0)) ||
 
12876
        (ctx->depth > 1024)) {
 
12877
        return(XML_ERR_ENTITY_LOOP);
 
12878
    }
 
12879
 
 
12880
    if (lst != NULL)
 
12881
        *lst = NULL;
 
12882
    if ((URL == NULL) && (ID == NULL))
 
12883
        return(-1);
 
12884
    if (ctx->myDoc == NULL) /* @@ relax but check for dereferences */
 
12885
        return(-1);
 
12886
 
 
12887
    ctxt = xmlCreateEntityParserCtxtInternal(URL, ID, NULL, ctx);
 
12888
    if (ctxt == NULL) {
 
12889
        return(-1);
 
12890
    }
 
12891
 
 
12892
    oldsax = ctxt->sax;
 
12893
    ctxt->sax = ctx->sax;
 
12894
    xmlDetectSAX2(ctxt);
 
12895
    newDoc = xmlNewDoc(BAD_CAST "1.0");
 
12896
    if (newDoc == NULL) {
 
12897
        xmlFreeParserCtxt(ctxt);
 
12898
        return(-1);
 
12899
    }
 
12900
    newDoc->properties = XML_DOC_INTERNAL;
 
12901
    if (ctx->myDoc->dict) {
 
12902
        newDoc->dict = ctx->myDoc->dict;
 
12903
        xmlDictReference(newDoc->dict);
 
12904
    }
 
12905
    if (ctx->myDoc != NULL) {
 
12906
        newDoc->intSubset = ctx->myDoc->intSubset;
 
12907
        newDoc->extSubset = ctx->myDoc->extSubset;
 
12908
    }
 
12909
    if (ctx->myDoc->URL != NULL) {
 
12910
        newDoc->URL = xmlStrdup(ctx->myDoc->URL);
 
12911
    }
 
12912
    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
 
12913
    if (newRoot == NULL) {
 
12914
        ctxt->sax = oldsax;
 
12915
        xmlFreeParserCtxt(ctxt);
 
12916
        newDoc->intSubset = NULL;
 
12917
        newDoc->extSubset = NULL;
 
12918
        xmlFreeDoc(newDoc);
 
12919
        return(-1);
 
12920
    }
 
12921
    xmlAddChild((xmlNodePtr) newDoc, newRoot);
 
12922
    nodePush(ctxt, newDoc->children);
 
12923
    if (ctx->myDoc == NULL) {
 
12924
        ctxt->myDoc = newDoc;
 
12925
    } else {
 
12926
        ctxt->myDoc = ctx->myDoc;
 
12927
        newDoc->children->doc = ctx->myDoc;
 
12928
    }
 
12929
 
 
12930
    /*
 
12931
     * Get the 4 first bytes and decode the charset
 
12932
     * if enc != XML_CHAR_ENCODING_NONE
 
12933
     * plug some encoding conversion routines.
 
12934
     */
 
12935
    GROW
 
12936
    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
 
12937
        start[0] = RAW;
 
12938
        start[1] = NXT(1);
 
12939
        start[2] = NXT(2);
 
12940
        start[3] = NXT(3);
 
12941
        enc = xmlDetectCharEncoding(start, 4);
 
12942
        if (enc != XML_CHAR_ENCODING_NONE) {
 
12943
            xmlSwitchEncoding(ctxt, enc);
 
12944
        }
 
12945
    }
 
12946
 
 
12947
    /*
 
12948
     * Parse a possible text declaration first
 
12949
     */
 
12950
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
 
12951
        xmlParseTextDecl(ctxt);
 
12952
        /*
 
12953
         * An XML-1.0 document can't reference an entity not XML-1.0
 
12954
         */
 
12955
        if ((xmlStrEqual(ctx->version, BAD_CAST "1.0")) &&
 
12956
            (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) {
 
12957
            xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH,
 
12958
                           "Version mismatch between document and entity\n");
 
12959
        }
 
12960
    }
 
12961
 
 
12962
    /*
 
12963
     * If the user provided its own SAX callbacks then reuse the
 
12964
     * useData callback field, otherwise the expected setup in a
 
12965
     * DOM builder is to have userData == ctxt
 
12966
     */
 
12967
    if (ctx->userData == ctx)
 
12968
        ctxt->userData = ctxt;
 
12969
    else
 
12970
        ctxt->userData = ctx->userData;
 
12971
 
 
12972
    /*
 
12973
     * Doing validity checking on chunk doesn't make sense
 
12974
     */
 
12975
    ctxt->instate = XML_PARSER_CONTENT;
 
12976
    ctxt->validate = ctx->validate;
 
12977
    ctxt->valid = ctx->valid;
 
12978
    ctxt->loadsubset = ctx->loadsubset;
 
12979
    ctxt->depth = ctx->depth + 1;
 
12980
    ctxt->replaceEntities = ctx->replaceEntities;
 
12981
    if (ctxt->validate) {
 
12982
        ctxt->vctxt.error = ctx->vctxt.error;
 
12983
        ctxt->vctxt.warning = ctx->vctxt.warning;
 
12984
    } else {
 
12985
        ctxt->vctxt.error = NULL;
 
12986
        ctxt->vctxt.warning = NULL;
 
12987
    }
 
12988
    ctxt->vctxt.nodeTab = NULL;
 
12989
    ctxt->vctxt.nodeNr = 0;
 
12990
    ctxt->vctxt.nodeMax = 0;
 
12991
    ctxt->vctxt.node = NULL;
 
12992
    if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
 
12993
    ctxt->dict = ctx->dict;
 
12994
    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
 
12995
    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
 
12996
    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
 
12997
    ctxt->dictNames = ctx->dictNames;
 
12998
    ctxt->attsDefault = ctx->attsDefault;
 
12999
    ctxt->attsSpecial = ctx->attsSpecial;
 
13000
    ctxt->linenumbers = ctx->linenumbers;
 
13001
 
 
13002
    xmlParseContent(ctxt);
 
13003
 
 
13004
    ctx->validate = ctxt->validate;
 
13005
    ctx->valid = ctxt->valid;
 
13006
    if ((RAW == '<') && (NXT(1) == '/')) {
 
13007
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
13008
    } else if (RAW != 0) {
 
13009
        xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
 
13010
    }
 
13011
    if (ctxt->node != newDoc->children) {
 
13012
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
13013
    }
 
13014
 
 
13015
    if (!ctxt->wellFormed) {
 
13016
        if (ctxt->errNo == 0)
 
13017
            ret = 1;
 
13018
        else
 
13019
            ret = ctxt->errNo;
 
13020
    } else {
 
13021
        if (lst != NULL) {
 
13022
            xmlNodePtr cur;
 
13023
 
 
13024
            /*
 
13025
             * Return the newly created nodeset after unlinking it from
 
13026
             * they pseudo parent.
 
13027
             */
 
13028
            cur = newDoc->children->children;
 
13029
            *lst = cur;
 
13030
            while (cur != NULL) {
 
13031
                cur->parent = NULL;
 
13032
                cur = cur->next;
 
13033
            }
 
13034
            newDoc->children->children = NULL;
 
13035
        }
 
13036
        ret = 0;
 
13037
    }
 
13038
    ctxt->sax = oldsax;
 
13039
    ctxt->dict = NULL;
 
13040
    ctxt->attsDefault = NULL;
 
13041
    ctxt->attsSpecial = NULL;
 
13042
    xmlFreeParserCtxt(ctxt);
 
13043
    newDoc->intSubset = NULL;
 
13044
    newDoc->extSubset = NULL;
 
13045
    xmlFreeDoc(newDoc);
 
13046
 
 
13047
    return(ret);
 
13048
}
 
13049
 
 
13050
/**
 
13051
 * xmlParseExternalEntityPrivate:
 
13052
 * @doc:  the document the chunk pertains to
 
13053
 * @oldctxt:  the previous parser context if available
 
13054
 * @sax:  the SAX handler bloc (possibly NULL)
 
13055
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
 
13056
 * @depth:  Used for loop detection, use 0
 
13057
 * @URL:  the URL for the entity to load
 
13058
 * @ID:  the System ID for the entity to load
 
13059
 * @list:  the return value for the set of parsed nodes
 
13060
 *
 
13061
 * Private version of xmlParseExternalEntity()
 
13062
 *
 
13063
 * Returns 0 if the entity is well formed, -1 in case of args problem and
 
13064
 *    the parser error code otherwise
 
13065
 */
 
13066
 
 
13067
static xmlParserErrors
 
13068
xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
 
13069
                      xmlSAXHandlerPtr sax,
 
13070
                      void *user_data, int depth, const xmlChar *URL,
 
13071
                      const xmlChar *ID, xmlNodePtr *list) {
 
13072
    xmlParserCtxtPtr ctxt;
 
13073
    xmlDocPtr newDoc;
 
13074
    xmlNodePtr newRoot;
 
13075
    xmlSAXHandlerPtr oldsax = NULL;
 
13076
    xmlParserErrors ret = XML_ERR_OK;
 
13077
    xmlChar start[4];
 
13078
    xmlCharEncoding enc;
 
13079
 
 
13080
    if (((depth > 40) &&
 
13081
        ((oldctxt == NULL) || (oldctxt->options & XML_PARSE_HUGE) == 0)) ||
 
13082
        (depth > 1024)) {
 
13083
        return(XML_ERR_ENTITY_LOOP);
 
13084
    }
 
13085
 
 
13086
    if (list != NULL)
 
13087
        *list = NULL;
 
13088
    if ((URL == NULL) && (ID == NULL))
 
13089
        return(XML_ERR_INTERNAL_ERROR);
 
13090
    if (doc == NULL)
 
13091
        return(XML_ERR_INTERNAL_ERROR);
 
13092
 
 
13093
 
 
13094
    ctxt = xmlCreateEntityParserCtxtInternal(URL, ID, NULL, oldctxt);
 
13095
    if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
 
13096
    ctxt->userData = ctxt;
 
13097
    if (oldctxt != NULL) {
 
13098
        ctxt->_private = oldctxt->_private;
 
13099
        ctxt->loadsubset = oldctxt->loadsubset;
 
13100
        ctxt->validate = oldctxt->validate;
 
13101
        ctxt->external = oldctxt->external;
 
13102
        ctxt->record_info = oldctxt->record_info;
 
13103
        ctxt->node_seq.maximum = oldctxt->node_seq.maximum;
 
13104
        ctxt->node_seq.length = oldctxt->node_seq.length;
 
13105
        ctxt->node_seq.buffer = oldctxt->node_seq.buffer;
 
13106
    } else {
 
13107
        /*
 
13108
         * Doing validity checking on chunk without context
 
13109
         * doesn't make sense
 
13110
         */
 
13111
        ctxt->_private = NULL;
 
13112
        ctxt->validate = 0;
 
13113
        ctxt->external = 2;
 
13114
        ctxt->loadsubset = 0;
 
13115
    }
 
13116
    if (sax != NULL) {
 
13117
        oldsax = ctxt->sax;
 
13118
        ctxt->sax = sax;
 
13119
        if (user_data != NULL)
 
13120
            ctxt->userData = user_data;
 
13121
    }
 
13122
    xmlDetectSAX2(ctxt);
 
13123
    newDoc = xmlNewDoc(BAD_CAST "1.0");
 
13124
    if (newDoc == NULL) {
 
13125
        ctxt->node_seq.maximum = 0;
 
13126
        ctxt->node_seq.length = 0;
 
13127
        ctxt->node_seq.buffer = NULL;
 
13128
        xmlFreeParserCtxt(ctxt);
 
13129
        return(XML_ERR_INTERNAL_ERROR);
 
13130
    }
 
13131
    newDoc->properties = XML_DOC_INTERNAL;
 
13132
    newDoc->intSubset = doc->intSubset;
 
13133
    newDoc->extSubset = doc->extSubset;
 
13134
    newDoc->dict = doc->dict;
 
13135
    xmlDictReference(newDoc->dict);
 
13136
 
 
13137
    if (doc->URL != NULL) {
 
13138
        newDoc->URL = xmlStrdup(doc->URL);
 
13139
    }
 
13140
    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
 
13141
    if (newRoot == NULL) {
 
13142
        if (sax != NULL)
 
13143
            ctxt->sax = oldsax;
 
13144
        ctxt->node_seq.maximum = 0;
 
13145
        ctxt->node_seq.length = 0;
 
13146
        ctxt->node_seq.buffer = NULL;
 
13147
        xmlFreeParserCtxt(ctxt);
 
13148
        newDoc->intSubset = NULL;
 
13149
        newDoc->extSubset = NULL;
 
13150
        xmlFreeDoc(newDoc);
 
13151
        return(XML_ERR_INTERNAL_ERROR);
 
13152
    }
 
13153
    xmlAddChild((xmlNodePtr) newDoc, newRoot);
 
13154
    nodePush(ctxt, newDoc->children);
 
13155
    ctxt->myDoc = doc;
 
13156
    newRoot->doc = doc;
 
13157
 
 
13158
    /*
 
13159
     * Get the 4 first bytes and decode the charset
 
13160
     * if enc != XML_CHAR_ENCODING_NONE
 
13161
     * plug some encoding conversion routines.
 
13162
     */
 
13163
    GROW;
 
13164
    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
 
13165
        start[0] = RAW;
 
13166
        start[1] = NXT(1);
 
13167
        start[2] = NXT(2);
 
13168
        start[3] = NXT(3);
 
13169
        enc = xmlDetectCharEncoding(start, 4);
 
13170
        if (enc != XML_CHAR_ENCODING_NONE) {
 
13171
            xmlSwitchEncoding(ctxt, enc);
 
13172
        }
 
13173
    }
 
13174
 
 
13175
    /*
 
13176
     * Parse a possible text declaration first
 
13177
     */
 
13178
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
 
13179
        xmlParseTextDecl(ctxt);
 
13180
    }
 
13181
 
 
13182
    ctxt->instate = XML_PARSER_CONTENT;
 
13183
    ctxt->depth = depth;
 
13184
 
 
13185
    xmlParseContent(ctxt);
 
13186
 
 
13187
    if ((RAW == '<') && (NXT(1) == '/')) {
 
13188
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
13189
    } else if (RAW != 0) {
 
13190
        xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
 
13191
    }
 
13192
    if (ctxt->node != newDoc->children) {
 
13193
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
13194
    }
 
13195
 
 
13196
    if (!ctxt->wellFormed) {
 
13197
        if (ctxt->errNo == 0)
 
13198
            ret = XML_ERR_INTERNAL_ERROR;
 
13199
        else
 
13200
            ret = (xmlParserErrors)ctxt->errNo;
 
13201
    } else {
 
13202
        if (list != NULL) {
 
13203
            xmlNodePtr cur;
 
13204
 
 
13205
            /*
 
13206
             * Return the newly created nodeset after unlinking it from
 
13207
             * they pseudo parent.
 
13208
             */
 
13209
            cur = newDoc->children->children;
 
13210
            *list = cur;
 
13211
            while (cur != NULL) {
 
13212
                cur->parent = NULL;
 
13213
                cur = cur->next;
 
13214
            }
 
13215
            newDoc->children->children = NULL;
 
13216
        }
 
13217
        ret = XML_ERR_OK;
 
13218
    }
 
13219
 
 
13220
    /*
 
13221
     * Record in the parent context the number of entities replacement
 
13222
     * done when parsing that reference.
 
13223
     */
 
13224
    if (oldctxt != NULL)
 
13225
        oldctxt->nbentities += ctxt->nbentities;
 
13226
 
 
13227
    /*
 
13228
     * Also record the size of the entity parsed
 
13229
     */
 
13230
    if (ctxt->input != NULL) {
 
13231
        oldctxt->sizeentities += ctxt->input->consumed;
 
13232
        oldctxt->sizeentities += (ctxt->input->cur - ctxt->input->base);
 
13233
    }
 
13234
    /*
 
13235
     * And record the last error if any
 
13236
     */
 
13237
    if (ctxt->lastError.code != XML_ERR_OK)
 
13238
        xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
 
13239
 
 
13240
    if (sax != NULL)
 
13241
        ctxt->sax = oldsax;
 
13242
    oldctxt->node_seq.maximum = ctxt->node_seq.maximum;
 
13243
    oldctxt->node_seq.length = ctxt->node_seq.length;
 
13244
    oldctxt->node_seq.buffer = ctxt->node_seq.buffer;
 
13245
    ctxt->node_seq.maximum = 0;
 
13246
    ctxt->node_seq.length = 0;
 
13247
    ctxt->node_seq.buffer = NULL;
 
13248
    xmlFreeParserCtxt(ctxt);
 
13249
    newDoc->intSubset = NULL;
 
13250
    newDoc->extSubset = NULL;
 
13251
    xmlFreeDoc(newDoc);
 
13252
 
 
13253
    return(ret);
 
13254
}
 
13255
 
 
13256
#ifdef LIBXML_SAX1_ENABLED
 
13257
/**
 
13258
 * xmlParseExternalEntity:
 
13259
 * @doc:  the document the chunk pertains to
 
13260
 * @sax:  the SAX handler bloc (possibly NULL)
 
13261
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
 
13262
 * @depth:  Used for loop detection, use 0
 
13263
 * @URL:  the URL for the entity to load
 
13264
 * @ID:  the System ID for the entity to load
 
13265
 * @lst:  the return value for the set of parsed nodes
 
13266
 *
 
13267
 * Parse an external general entity
 
13268
 * An external general parsed entity is well-formed if it matches the
 
13269
 * production labeled extParsedEnt.
 
13270
 *
 
13271
 * [78] extParsedEnt ::= TextDecl? content
 
13272
 *
 
13273
 * Returns 0 if the entity is well formed, -1 in case of args problem and
 
13274
 *    the parser error code otherwise
 
13275
 */
 
13276
 
 
13277
int
 
13278
xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data,
 
13279
          int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *lst) {
 
13280
    return(xmlParseExternalEntityPrivate(doc, NULL, sax, user_data, depth, URL,
 
13281
                                       ID, lst));
 
13282
}
 
13283
 
 
13284
/**
 
13285
 * xmlParseBalancedChunkMemory:
 
13286
 * @doc:  the document the chunk pertains to
 
13287
 * @sax:  the SAX handler bloc (possibly NULL)
 
13288
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
 
13289
 * @depth:  Used for loop detection, use 0
 
13290
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
 
13291
 * @lst:  the return value for the set of parsed nodes
 
13292
 *
 
13293
 * Parse a well-balanced chunk of an XML document
 
13294
 * called by the parser
 
13295
 * The allowed sequence for the Well Balanced Chunk is the one defined by
 
13296
 * the content production in the XML grammar:
 
13297
 *
 
13298
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
 
13299
 *
 
13300
 * Returns 0 if the chunk is well balanced, -1 in case of args problem and
 
13301
 *    the parser error code otherwise
 
13302
 */
 
13303
 
 
13304
int
 
13305
xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax,
 
13306
     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst) {
 
13307
    return xmlParseBalancedChunkMemoryRecover( doc, sax, user_data,
 
13308
                                                depth, string, lst, 0 );
 
13309
}
 
13310
#endif /* LIBXML_SAX1_ENABLED */
 
13311
 
 
13312
/**
 
13313
 * xmlParseBalancedChunkMemoryInternal:
 
13314
 * @oldctxt:  the existing parsing context
 
13315
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
 
13316
 * @user_data:  the user data field for the parser context
 
13317
 * @lst:  the return value for the set of parsed nodes
 
13318
 *
 
13319
 *
 
13320
 * Parse a well-balanced chunk of an XML document
 
13321
 * called by the parser
 
13322
 * The allowed sequence for the Well Balanced Chunk is the one defined by
 
13323
 * the content production in the XML grammar:
 
13324
 *
 
13325
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
 
13326
 *
 
13327
 * Returns XML_ERR_OK if the chunk is well balanced, and the parser
 
13328
 * error code otherwise
 
13329
 *
 
13330
 * In case recover is set to 1, the nodelist will not be empty even if
 
13331
 * the parsed chunk is not well balanced.
 
13332
 */
 
13333
static xmlParserErrors
 
13334
xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
 
13335
        const xmlChar *string, void *user_data, xmlNodePtr *lst) {
 
13336
    xmlParserCtxtPtr ctxt;
 
13337
    xmlDocPtr newDoc = NULL;
 
13338
    xmlNodePtr newRoot;
 
13339
    xmlSAXHandlerPtr oldsax = NULL;
 
13340
    xmlNodePtr content = NULL;
 
13341
    xmlNodePtr last = NULL;
 
13342
    int size;
 
13343
    xmlParserErrors ret = XML_ERR_OK;
 
13344
#ifdef SAX2
 
13345
    int i;
 
13346
#endif
 
13347
 
 
13348
    if (((oldctxt->depth > 40) && ((oldctxt->options & XML_PARSE_HUGE) == 0)) ||
 
13349
        (oldctxt->depth >  1024)) {
 
13350
        return(XML_ERR_ENTITY_LOOP);
 
13351
    }
 
13352
 
 
13353
 
 
13354
    if (lst != NULL)
 
13355
        *lst = NULL;
 
13356
    if (string == NULL)
 
13357
        return(XML_ERR_INTERNAL_ERROR);
 
13358
 
 
13359
    size = xmlStrlen(string);
 
13360
 
 
13361
    ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
 
13362
    if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
 
13363
    if (user_data != NULL)
 
13364
        ctxt->userData = user_data;
 
13365
    else
 
13366
        ctxt->userData = ctxt;
 
13367
    if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
 
13368
    ctxt->dict = oldctxt->dict;
 
13369
    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
 
13370
    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
 
13371
    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
 
13372
 
 
13373
#ifdef SAX2
 
13374
    /* propagate namespaces down the entity */
 
13375
    for (i = 0;i < oldctxt->nsNr;i += 2) {
 
13376
        nsPush(ctxt, oldctxt->nsTab[i], oldctxt->nsTab[i+1]);
 
13377
    }
 
13378
#endif
 
13379
 
 
13380
    oldsax = ctxt->sax;
 
13381
    ctxt->sax = oldctxt->sax;
 
13382
    xmlDetectSAX2(ctxt);
 
13383
    ctxt->replaceEntities = oldctxt->replaceEntities;
 
13384
    ctxt->options = oldctxt->options;
 
13385
 
 
13386
    ctxt->_private = oldctxt->_private;
 
13387
    if (oldctxt->myDoc == NULL) {
 
13388
        newDoc = xmlNewDoc(BAD_CAST "1.0");
 
13389
        if (newDoc == NULL) {
 
13390
            ctxt->sax = oldsax;
 
13391
            ctxt->dict = NULL;
 
13392
            xmlFreeParserCtxt(ctxt);
 
13393
            return(XML_ERR_INTERNAL_ERROR);
 
13394
        }
 
13395
        newDoc->properties = XML_DOC_INTERNAL;
 
13396
        newDoc->dict = ctxt->dict;
 
13397
        xmlDictReference(newDoc->dict);
 
13398
        ctxt->myDoc = newDoc;
 
13399
    } else {
 
13400
        ctxt->myDoc = oldctxt->myDoc;
 
13401
        content = ctxt->myDoc->children;
 
13402
        last = ctxt->myDoc->last;
 
13403
    }
 
13404
    newRoot = xmlNewDocNode(ctxt->myDoc, NULL, BAD_CAST "pseudoroot", NULL);
 
13405
    if (newRoot == NULL) {
 
13406
        ctxt->sax = oldsax;
 
13407
        ctxt->dict = NULL;
 
13408
        xmlFreeParserCtxt(ctxt);
 
13409
        if (newDoc != NULL) {
 
13410
            xmlFreeDoc(newDoc);
 
13411
        }
 
13412
        return(XML_ERR_INTERNAL_ERROR);
 
13413
    }
 
13414
    ctxt->myDoc->children = NULL;
 
13415
    ctxt->myDoc->last = NULL;
 
13416
    xmlAddChild((xmlNodePtr) ctxt->myDoc, newRoot);
 
13417
    nodePush(ctxt, ctxt->myDoc->children);
 
13418
    ctxt->instate = XML_PARSER_CONTENT;
 
13419
    ctxt->depth = oldctxt->depth + 1;
 
13420
 
 
13421
    ctxt->validate = 0;
 
13422
    ctxt->loadsubset = oldctxt->loadsubset;
 
13423
    if ((oldctxt->validate) || (oldctxt->replaceEntities != 0)) {
 
13424
        /*
 
13425
         * ID/IDREF registration will be done in xmlValidateElement below
 
13426
         */
 
13427
        ctxt->loadsubset |= XML_SKIP_IDS;
 
13428
    }
 
13429
    ctxt->dictNames = oldctxt->dictNames;
 
13430
    ctxt->attsDefault = oldctxt->attsDefault;
 
13431
    ctxt->attsSpecial = oldctxt->attsSpecial;
 
13432
 
 
13433
    xmlParseContent(ctxt);
 
13434
    if ((RAW == '<') && (NXT(1) == '/')) {
 
13435
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
13436
    } else if (RAW != 0) {
 
13437
        xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
 
13438
    }
 
13439
    if (ctxt->node != ctxt->myDoc->children) {
 
13440
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
13441
    }
 
13442
 
 
13443
    if (!ctxt->wellFormed) {
 
13444
        if (ctxt->errNo == 0)
 
13445
            ret = XML_ERR_INTERNAL_ERROR;
 
13446
        else
 
13447
            ret = (xmlParserErrors)ctxt->errNo;
 
13448
    } else {
 
13449
      ret = XML_ERR_OK;
 
13450
    }
 
13451
 
 
13452
    if ((lst != NULL) && (ret == XML_ERR_OK)) {
 
13453
        xmlNodePtr cur;
 
13454
 
 
13455
        /*
 
13456
         * Return the newly created nodeset after unlinking it from
 
13457
         * they pseudo parent.
 
13458
         */
 
13459
        cur = ctxt->myDoc->children->children;
 
13460
        *lst = cur;
 
13461
        while (cur != NULL) {
 
13462
#ifdef LIBXML_VALID_ENABLED
 
13463
            if ((oldctxt->validate) && (oldctxt->wellFormed) &&
 
13464
                (oldctxt->myDoc) && (oldctxt->myDoc->intSubset) &&
 
13465
                (cur->type == XML_ELEMENT_NODE)) {
 
13466
                oldctxt->valid &= xmlValidateElement(&oldctxt->vctxt,
 
13467
                        oldctxt->myDoc, cur);
 
13468
            }
 
13469
#endif /* LIBXML_VALID_ENABLED */
 
13470
            cur->parent = NULL;
 
13471
            cur = cur->next;
 
13472
        }
 
13473
        ctxt->myDoc->children->children = NULL;
 
13474
    }
 
13475
    if (ctxt->myDoc != NULL) {
 
13476
        xmlFreeNode(ctxt->myDoc->children);
 
13477
        ctxt->myDoc->children = content;
 
13478
        ctxt->myDoc->last = last;
 
13479
    }
 
13480
 
 
13481
    /*
 
13482
     * Record in the parent context the number of entities replacement
 
13483
     * done when parsing that reference.
 
13484
     */
 
13485
    if (oldctxt != NULL)
 
13486
        oldctxt->nbentities += ctxt->nbentities;
 
13487
 
 
13488
    /*
 
13489
     * Also record the last error if any
 
13490
     */
 
13491
    if (ctxt->lastError.code != XML_ERR_OK)
 
13492
        xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
 
13493
 
 
13494
    ctxt->sax = oldsax;
 
13495
    ctxt->dict = NULL;
 
13496
    ctxt->attsDefault = NULL;
 
13497
    ctxt->attsSpecial = NULL;
 
13498
    xmlFreeParserCtxt(ctxt);
 
13499
    if (newDoc != NULL) {
 
13500
        xmlFreeDoc(newDoc);
 
13501
    }
 
13502
 
 
13503
    return(ret);
 
13504
}
 
13505
 
 
13506
/**
 
13507
 * xmlParseInNodeContext:
 
13508
 * @node:  the context node
 
13509
 * @data:  the input string
 
13510
 * @datalen:  the input string length in bytes
 
13511
 * @options:  a combination of xmlParserOption
 
13512
 * @lst:  the return value for the set of parsed nodes
 
13513
 *
 
13514
 * Parse a well-balanced chunk of an XML document
 
13515
 * within the context (DTD, namespaces, etc ...) of the given node.
 
13516
 *
 
13517
 * The allowed sequence for the data is a Well Balanced Chunk defined by
 
13518
 * the content production in the XML grammar:
 
13519
 *
 
13520
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
 
13521
 *
 
13522
 * Returns XML_ERR_OK if the chunk is well balanced, and the parser
 
13523
 * error code otherwise
 
13524
 */
 
13525
xmlParserErrors
 
13526
xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
 
13527
                      int options, xmlNodePtr *lst) {
 
13528
#ifdef SAX2
 
13529
    xmlParserCtxtPtr ctxt;
 
13530
    xmlDocPtr doc = NULL;
 
13531
    xmlNodePtr fake, cur;
 
13532
    int nsnr = 0;
 
13533
 
 
13534
    xmlParserErrors ret = XML_ERR_OK;
 
13535
 
 
13536
    /*
 
13537
     * check all input parameters, grab the document
 
13538
     */
 
13539
    if ((lst == NULL) || (node == NULL) || (data == NULL) || (datalen < 0))
 
13540
        return(XML_ERR_INTERNAL_ERROR);
 
13541
    switch (node->type) {
 
13542
        case XML_ELEMENT_NODE:
 
13543
        case XML_ATTRIBUTE_NODE:
 
13544
        case XML_TEXT_NODE:
 
13545
        case XML_CDATA_SECTION_NODE:
 
13546
        case XML_ENTITY_REF_NODE:
 
13547
        case XML_PI_NODE:
 
13548
        case XML_COMMENT_NODE:
 
13549
        case XML_DOCUMENT_NODE:
 
13550
        case XML_HTML_DOCUMENT_NODE:
 
13551
            break;
 
13552
        default:
 
13553
            return(XML_ERR_INTERNAL_ERROR);
 
13554
 
 
13555
    }
 
13556
    while ((node != NULL) && (node->type != XML_ELEMENT_NODE) &&
 
13557
           (node->type != XML_DOCUMENT_NODE) &&
 
13558
           (node->type != XML_HTML_DOCUMENT_NODE))
 
13559
        node = node->parent;
 
13560
    if (node == NULL)
 
13561
        return(XML_ERR_INTERNAL_ERROR);
 
13562
    if (node->type == XML_ELEMENT_NODE)
 
13563
        doc = node->doc;
 
13564
    else
 
13565
        doc = (xmlDocPtr) node;
 
13566
    if (doc == NULL)
 
13567
        return(XML_ERR_INTERNAL_ERROR);
 
13568
 
 
13569
    /*
 
13570
     * allocate a context and set-up everything not related to the
 
13571
     * node position in the tree
 
13572
     */
 
13573
    if (doc->type == XML_DOCUMENT_NODE)
 
13574
        ctxt = xmlCreateMemoryParserCtxt((char *) data, datalen);
 
13575
#ifdef LIBXML_HTML_ENABLED
 
13576
    else if (doc->type == XML_HTML_DOCUMENT_NODE) {
 
13577
        ctxt = htmlCreateMemoryParserCtxt((char *) data, datalen);
 
13578
        /*
 
13579
         * When parsing in context, it makes no sense to add implied
 
13580
         * elements like html/body/etc...
 
13581
         */
 
13582
        options |= HTML_PARSE_NOIMPLIED;
 
13583
    }
 
13584
#endif
 
13585
    else
 
13586
        return(XML_ERR_INTERNAL_ERROR);
 
13587
 
 
13588
    if (ctxt == NULL)
 
13589
        return(XML_ERR_NO_MEMORY);
 
13590
 
 
13591
    /*
 
13592
     * Use input doc's dict if present, else assure XML_PARSE_NODICT is set.
 
13593
     * We need a dictionary for xmlDetectSAX2, so if there's no doc dict
 
13594
     * we must wait until the last moment to free the original one.
 
13595
     */
 
13596
    if (doc->dict != NULL) {
 
13597
        if (ctxt->dict != NULL)
 
13598
            xmlDictFree(ctxt->dict);
 
13599
        ctxt->dict = doc->dict;
 
13600
    } else
 
13601
        options |= XML_PARSE_NODICT;
 
13602
 
 
13603
    if (doc->encoding != NULL) {
 
13604
        xmlCharEncodingHandlerPtr hdlr;
 
13605
 
 
13606
        if (ctxt->encoding != NULL)
 
13607
            xmlFree((xmlChar *) ctxt->encoding);
 
13608
        ctxt->encoding = xmlStrdup((const xmlChar *) doc->encoding);
 
13609
 
 
13610
        hdlr = xmlFindCharEncodingHandler(doc->encoding);
 
13611
        if (hdlr != NULL) {
 
13612
            xmlSwitchToEncoding(ctxt, hdlr);
 
13613
        } else {
 
13614
            return(XML_ERR_UNSUPPORTED_ENCODING);
 
13615
        }
 
13616
    }
 
13617
 
 
13618
    xmlCtxtUseOptionsInternal(ctxt, options, NULL);
 
13619
    xmlDetectSAX2(ctxt);
 
13620
    ctxt->myDoc = doc;
 
13621
 
 
13622
    fake = xmlNewComment(NULL);
 
13623
    if (fake == NULL) {
 
13624
        xmlFreeParserCtxt(ctxt);
 
13625
        return(XML_ERR_NO_MEMORY);
 
13626
    }
 
13627
    xmlAddChild(node, fake);
 
13628
 
 
13629
    if (node->type == XML_ELEMENT_NODE) {
 
13630
        nodePush(ctxt, node);
 
13631
        /*
 
13632
         * initialize the SAX2 namespaces stack
 
13633
         */
 
13634
        cur = node;
 
13635
        while ((cur != NULL) && (cur->type == XML_ELEMENT_NODE)) {
 
13636
            xmlNsPtr ns = cur->nsDef;
 
13637
            const xmlChar *iprefix, *ihref;
 
13638
 
 
13639
            while (ns != NULL) {
 
13640
                if (ctxt->dict) {
 
13641
                    iprefix = xmlDictLookup(ctxt->dict, ns->prefix, -1);
 
13642
                    ihref = xmlDictLookup(ctxt->dict, ns->href, -1);
 
13643
                } else {
 
13644
                    iprefix = ns->prefix;
 
13645
                    ihref = ns->href;
 
13646
                }
 
13647
 
 
13648
                if (xmlGetNamespace(ctxt, iprefix) == NULL) {
 
13649
                    nsPush(ctxt, iprefix, ihref);
 
13650
                    nsnr++;
 
13651
                }
 
13652
                ns = ns->next;
 
13653
            }
 
13654
            cur = cur->parent;
 
13655
        }
 
13656
        ctxt->instate = XML_PARSER_CONTENT;
 
13657
    }
 
13658
 
 
13659
    if ((ctxt->validate) || (ctxt->replaceEntities != 0)) {
 
13660
        /*
 
13661
         * ID/IDREF registration will be done in xmlValidateElement below
 
13662
         */
 
13663
        ctxt->loadsubset |= XML_SKIP_IDS;
 
13664
    }
 
13665
 
 
13666
#ifdef LIBXML_HTML_ENABLED
 
13667
    if (doc->type == XML_HTML_DOCUMENT_NODE)
 
13668
        __htmlParseContent(ctxt);
 
13669
    else
 
13670
#endif
 
13671
        xmlParseContent(ctxt);
 
13672
 
 
13673
    nsPop(ctxt, nsnr);
 
13674
    if ((RAW == '<') && (NXT(1) == '/')) {
 
13675
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
13676
    } else if (RAW != 0) {
 
13677
        xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
 
13678
    }
 
13679
    if ((ctxt->node != NULL) && (ctxt->node != node)) {
 
13680
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
13681
        ctxt->wellFormed = 0;
 
13682
    }
 
13683
 
 
13684
    if (!ctxt->wellFormed) {
 
13685
        if (ctxt->errNo == 0)
 
13686
            ret = XML_ERR_INTERNAL_ERROR;
 
13687
        else
 
13688
            ret = (xmlParserErrors)ctxt->errNo;
 
13689
    } else {
 
13690
        ret = XML_ERR_OK;
 
13691
    }
 
13692
 
 
13693
    /*
 
13694
     * Return the newly created nodeset after unlinking it from
 
13695
     * the pseudo sibling.
 
13696
     */
 
13697
 
 
13698
    cur = fake->next;
 
13699
    fake->next = NULL;
 
13700
    node->last = fake;
 
13701
 
 
13702
    if (cur != NULL) {
 
13703
        cur->prev = NULL;
 
13704
    }
 
13705
 
 
13706
    *lst = cur;
 
13707
 
 
13708
    while (cur != NULL) {
 
13709
        cur->parent = NULL;
 
13710
        cur = cur->next;
 
13711
    }
 
13712
 
 
13713
    xmlUnlinkNode(fake);
 
13714
    xmlFreeNode(fake);
 
13715
 
 
13716
 
 
13717
    if (ret != XML_ERR_OK) {
 
13718
        xmlFreeNodeList(*lst);
 
13719
        *lst = NULL;
 
13720
    }
 
13721
 
 
13722
    if (doc->dict != NULL)
 
13723
        ctxt->dict = NULL;
 
13724
    xmlFreeParserCtxt(ctxt);
 
13725
 
 
13726
    return(ret);
 
13727
#else /* !SAX2 */
 
13728
    return(XML_ERR_INTERNAL_ERROR);
 
13729
#endif
 
13730
}
 
13731
 
 
13732
#ifdef LIBXML_SAX1_ENABLED
 
13733
/**
 
13734
 * xmlParseBalancedChunkMemoryRecover:
 
13735
 * @doc:  the document the chunk pertains to
 
13736
 * @sax:  the SAX handler bloc (possibly NULL)
 
13737
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
 
13738
 * @depth:  Used for loop detection, use 0
 
13739
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
 
13740
 * @lst:  the return value for the set of parsed nodes
 
13741
 * @recover: return nodes even if the data is broken (use 0)
 
13742
 *
 
13743
 *
 
13744
 * Parse a well-balanced chunk of an XML document
 
13745
 * called by the parser
 
13746
 * The allowed sequence for the Well Balanced Chunk is the one defined by
 
13747
 * the content production in the XML grammar:
 
13748
 *
 
13749
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
 
13750
 *
 
13751
 * Returns 0 if the chunk is well balanced, -1 in case of args problem and
 
13752
 *    the parser error code otherwise
 
13753
 *
 
13754
 * In case recover is set to 1, the nodelist will not be empty even if
 
13755
 * the parsed chunk is not well balanced, assuming the parsing succeeded to
 
13756
 * some extent.
 
13757
 */
 
13758
int
 
13759
xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
 
13760
     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst,
 
13761
     int recover) {
 
13762
    xmlParserCtxtPtr ctxt;
 
13763
    xmlDocPtr newDoc;
 
13764
    xmlSAXHandlerPtr oldsax = NULL;
 
13765
    xmlNodePtr content, newRoot;
 
13766
    int size;
 
13767
    int ret = 0;
 
13768
 
 
13769
    if (depth > 40) {
 
13770
        return(XML_ERR_ENTITY_LOOP);
 
13771
    }
 
13772
 
 
13773
 
 
13774
    if (lst != NULL)
 
13775
        *lst = NULL;
 
13776
    if (string == NULL)
 
13777
        return(-1);
 
13778
 
 
13779
    size = xmlStrlen(string);
 
13780
 
 
13781
    ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
 
13782
    if (ctxt == NULL) return(-1);
 
13783
    ctxt->userData = ctxt;
 
13784
    if (sax != NULL) {
 
13785
        oldsax = ctxt->sax;
 
13786
        ctxt->sax = sax;
 
13787
        if (user_data != NULL)
 
13788
            ctxt->userData = user_data;
 
13789
    }
 
13790
    newDoc = xmlNewDoc(BAD_CAST "1.0");
 
13791
    if (newDoc == NULL) {
 
13792
        xmlFreeParserCtxt(ctxt);
 
13793
        return(-1);
 
13794
    }
 
13795
    newDoc->properties = XML_DOC_INTERNAL;
 
13796
    if ((doc != NULL) && (doc->dict != NULL)) {
 
13797
        xmlDictFree(ctxt->dict);
 
13798
        ctxt->dict = doc->dict;
 
13799
        xmlDictReference(ctxt->dict);
 
13800
        ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
 
13801
        ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
 
13802
        ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
 
13803
        ctxt->dictNames = 1;
 
13804
    } else {
 
13805
        xmlCtxtUseOptionsInternal(ctxt, XML_PARSE_NODICT, NULL);
 
13806
    }
 
13807
    if (doc != NULL) {
 
13808
        newDoc->intSubset = doc->intSubset;
 
13809
        newDoc->extSubset = doc->extSubset;
 
13810
    }
 
13811
    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
 
13812
    if (newRoot == NULL) {
 
13813
        if (sax != NULL)
 
13814
            ctxt->sax = oldsax;
 
13815
        xmlFreeParserCtxt(ctxt);
 
13816
        newDoc->intSubset = NULL;
 
13817
        newDoc->extSubset = NULL;
 
13818
        xmlFreeDoc(newDoc);
 
13819
        return(-1);
 
13820
    }
 
13821
    xmlAddChild((xmlNodePtr) newDoc, newRoot);
 
13822
    nodePush(ctxt, newRoot);
 
13823
    if (doc == NULL) {
 
13824
        ctxt->myDoc = newDoc;
 
13825
    } else {
 
13826
        ctxt->myDoc = newDoc;
 
13827
        newDoc->children->doc = doc;
 
13828
        /* Ensure that doc has XML spec namespace */
 
13829
        xmlSearchNsByHref(doc, (xmlNodePtr)doc, XML_XML_NAMESPACE);
 
13830
        newDoc->oldNs = doc->oldNs;
 
13831
    }
 
13832
    ctxt->instate = XML_PARSER_CONTENT;
 
13833
    ctxt->depth = depth;
 
13834
 
 
13835
    /*
 
13836
     * Doing validity checking on chunk doesn't make sense
 
13837
     */
 
13838
    ctxt->validate = 0;
 
13839
    ctxt->loadsubset = 0;
 
13840
    xmlDetectSAX2(ctxt);
 
13841
 
 
13842
    if ( doc != NULL ){
 
13843
        content = doc->children;
 
13844
        doc->children = NULL;
 
13845
        xmlParseContent(ctxt);
 
13846
        doc->children = content;
 
13847
    }
 
13848
    else {
 
13849
        xmlParseContent(ctxt);
 
13850
    }
 
13851
    if ((RAW == '<') && (NXT(1) == '/')) {
 
13852
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
13853
    } else if (RAW != 0) {
 
13854
        xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
 
13855
    }
 
13856
    if (ctxt->node != newDoc->children) {
 
13857
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
13858
    }
 
13859
 
 
13860
    if (!ctxt->wellFormed) {
 
13861
        if (ctxt->errNo == 0)
 
13862
            ret = 1;
 
13863
        else
 
13864
            ret = ctxt->errNo;
 
13865
    } else {
 
13866
      ret = 0;
 
13867
    }
 
13868
 
 
13869
    if ((lst != NULL) && ((ret == 0) || (recover == 1))) {
 
13870
        xmlNodePtr cur;
 
13871
 
 
13872
        /*
 
13873
         * Return the newly created nodeset after unlinking it from
 
13874
         * they pseudo parent.
 
13875
         */
 
13876
        cur = newDoc->children->children;
 
13877
        *lst = cur;
 
13878
        while (cur != NULL) {
 
13879
            xmlSetTreeDoc(cur, doc);
 
13880
            cur->parent = NULL;
 
13881
            cur = cur->next;
 
13882
        }
 
13883
        newDoc->children->children = NULL;
 
13884
    }
 
13885
 
 
13886
    if (sax != NULL)
 
13887
        ctxt->sax = oldsax;
 
13888
    xmlFreeParserCtxt(ctxt);
 
13889
    newDoc->intSubset = NULL;
 
13890
    newDoc->extSubset = NULL;
 
13891
    newDoc->oldNs = NULL;
 
13892
    xmlFreeDoc(newDoc);
 
13893
 
 
13894
    return(ret);
 
13895
}
 
13896
 
 
13897
/**
 
13898
 * xmlSAXParseEntity:
 
13899
 * @sax:  the SAX handler block
 
13900
 * @filename:  the filename
 
13901
 *
 
13902
 * parse an XML external entity out of context and build a tree.
 
13903
 * It use the given SAX function block to handle the parsing callback.
 
13904
 * If sax is NULL, fallback to the default DOM tree building routines.
 
13905
 *
 
13906
 * [78] extParsedEnt ::= TextDecl? content
 
13907
 *
 
13908
 * This correspond to a "Well Balanced" chunk
 
13909
 *
 
13910
 * Returns the resulting document tree
 
13911
 */
 
13912
 
 
13913
xmlDocPtr
 
13914
xmlSAXParseEntity(xmlSAXHandlerPtr sax, const char *filename) {
 
13915
    xmlDocPtr ret;
 
13916
    xmlParserCtxtPtr ctxt;
 
13917
 
 
13918
    ctxt = xmlCreateFileParserCtxt(filename);
 
13919
    if (ctxt == NULL) {
 
13920
        return(NULL);
 
13921
    }
 
13922
    if (sax != NULL) {
 
13923
        if (ctxt->sax != NULL)
 
13924
            xmlFree(ctxt->sax);
 
13925
        ctxt->sax = sax;
 
13926
        ctxt->userData = NULL;
 
13927
    }
 
13928
 
 
13929
    xmlParseExtParsedEnt(ctxt);
 
13930
 
 
13931
    if (ctxt->wellFormed)
 
13932
        ret = ctxt->myDoc;
 
13933
    else {
 
13934
        ret = NULL;
 
13935
        xmlFreeDoc(ctxt->myDoc);
 
13936
        ctxt->myDoc = NULL;
 
13937
    }
 
13938
    if (sax != NULL)
 
13939
        ctxt->sax = NULL;
 
13940
    xmlFreeParserCtxt(ctxt);
 
13941
 
 
13942
    return(ret);
 
13943
}
 
13944
 
 
13945
/**
 
13946
 * xmlParseEntity:
 
13947
 * @filename:  the filename
 
13948
 *
 
13949
 * parse an XML external entity out of context and build a tree.
 
13950
 *
 
13951
 * [78] extParsedEnt ::= TextDecl? content
 
13952
 *
 
13953
 * This correspond to a "Well Balanced" chunk
 
13954
 *
 
13955
 * Returns the resulting document tree
 
13956
 */
 
13957
 
 
13958
xmlDocPtr
 
13959
xmlParseEntity(const char *filename) {
 
13960
    return(xmlSAXParseEntity(NULL, filename));
 
13961
}
 
13962
#endif /* LIBXML_SAX1_ENABLED */
 
13963
 
 
13964
/**
 
13965
 * xmlCreateEntityParserCtxtInternal:
 
13966
 * @URL:  the entity URL
 
13967
 * @ID:  the entity PUBLIC ID
 
13968
 * @base:  a possible base for the target URI
 
13969
 * @pctx:  parser context used to set options on new context
 
13970
 *
 
13971
 * Create a parser context for an external entity
 
13972
 * Automatic support for ZLIB/Compress compressed document is provided
 
13973
 * by default if found at compile-time.
 
13974
 *
 
13975
 * Returns the new parser context or NULL
 
13976
 */
 
13977
static xmlParserCtxtPtr
 
13978
xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
 
13979
                          const xmlChar *base, xmlParserCtxtPtr pctx) {
 
13980
    xmlParserCtxtPtr ctxt;
 
13981
    xmlParserInputPtr inputStream;
 
13982
    char *directory = NULL;
 
13983
    xmlChar *uri;
 
13984
 
 
13985
    ctxt = xmlNewParserCtxt();
 
13986
    if (ctxt == NULL) {
 
13987
        return(NULL);
 
13988
    }
 
13989
 
 
13990
    if (pctx != NULL) {
 
13991
        ctxt->options = pctx->options;
 
13992
        ctxt->_private = pctx->_private;
 
13993
    }
 
13994
 
 
13995
    uri = xmlBuildURI(URL, base);
 
13996
 
 
13997
    if (uri == NULL) {
 
13998
        inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
 
13999
        if (inputStream == NULL) {
 
14000
            xmlFreeParserCtxt(ctxt);
 
14001
            return(NULL);
 
14002
        }
 
14003
 
 
14004
        inputPush(ctxt, inputStream);
 
14005
 
 
14006
        if ((ctxt->directory == NULL) && (directory == NULL))
 
14007
            directory = xmlParserGetDirectory((char *)URL);
 
14008
        if ((ctxt->directory == NULL) && (directory != NULL))
 
14009
            ctxt->directory = directory;
 
14010
    } else {
 
14011
        inputStream = xmlLoadExternalEntity((char *)uri, (char *)ID, ctxt);
 
14012
        if (inputStream == NULL) {
 
14013
            xmlFree(uri);
 
14014
            xmlFreeParserCtxt(ctxt);
 
14015
            return(NULL);
 
14016
        }
 
14017
 
 
14018
        inputPush(ctxt, inputStream);
 
14019
 
 
14020
        if ((ctxt->directory == NULL) && (directory == NULL))
 
14021
            directory = xmlParserGetDirectory((char *)uri);
 
14022
        if ((ctxt->directory == NULL) && (directory != NULL))
 
14023
            ctxt->directory = directory;
 
14024
        xmlFree(uri);
 
14025
    }
 
14026
    return(ctxt);
 
14027
}
 
14028
 
 
14029
/**
 
14030
 * xmlCreateEntityParserCtxt:
 
14031
 * @URL:  the entity URL
 
14032
 * @ID:  the entity PUBLIC ID
 
14033
 * @base:  a possible base for the target URI
 
14034
 *
 
14035
 * Create a parser context for an external entity
 
14036
 * Automatic support for ZLIB/Compress compressed document is provided
 
14037
 * by default if found at compile-time.
 
14038
 *
 
14039
 * Returns the new parser context or NULL
 
14040
 */
 
14041
xmlParserCtxtPtr
 
14042
xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID,
 
14043
                          const xmlChar *base) {
 
14044
    return xmlCreateEntityParserCtxtInternal(URL, ID, base, NULL);
 
14045
 
 
14046
}
 
14047
 
 
14048
/************************************************************************
 
14049
 *                                                                      *
 
14050
 *              Front ends when parsing from a file                     *
 
14051
 *                                                                      *
 
14052
 ************************************************************************/
 
14053
 
 
14054
/**
 
14055
 * xmlCreateURLParserCtxt:
 
14056
 * @filename:  the filename or URL
 
14057
 * @options:  a combination of xmlParserOption
 
14058
 *
 
14059
 * Create a parser context for a file or URL content.
 
14060
 * Automatic support for ZLIB/Compress compressed document is provided
 
14061
 * by default if found at compile-time and for file accesses
 
14062
 *
 
14063
 * Returns the new parser context or NULL
 
14064
 */
 
14065
xmlParserCtxtPtr
 
14066
xmlCreateURLParserCtxt(const char *filename, int options)
 
14067
{
 
14068
    xmlParserCtxtPtr ctxt;
 
14069
    xmlParserInputPtr inputStream;
 
14070
    char *directory = NULL;
 
14071
 
 
14072
    ctxt = xmlNewParserCtxt();
 
14073
    if (ctxt == NULL) {
 
14074
        xmlErrMemory(NULL, "cannot allocate parser context");
 
14075
        return(NULL);
 
14076
    }
 
14077
 
 
14078
    if (options)
 
14079
        xmlCtxtUseOptionsInternal(ctxt, options, NULL);
 
14080
    ctxt->linenumbers = 1;
 
14081
 
 
14082
    inputStream = xmlLoadExternalEntity(filename, NULL, ctxt);
 
14083
    if (inputStream == NULL) {
 
14084
        xmlFreeParserCtxt(ctxt);
 
14085
        return(NULL);
 
14086
    }
 
14087
 
 
14088
    inputPush(ctxt, inputStream);
 
14089
    if ((ctxt->directory == NULL) && (directory == NULL))
 
14090
        directory = xmlParserGetDirectory(filename);
 
14091
    if ((ctxt->directory == NULL) && (directory != NULL))
 
14092
        ctxt->directory = directory;
 
14093
 
 
14094
    return(ctxt);
 
14095
}
 
14096
 
 
14097
/**
 
14098
 * xmlCreateFileParserCtxt:
 
14099
 * @filename:  the filename
 
14100
 *
 
14101
 * Create a parser context for a file content.
 
14102
 * Automatic support for ZLIB/Compress compressed document is provided
 
14103
 * by default if found at compile-time.
 
14104
 *
 
14105
 * Returns the new parser context or NULL
 
14106
 */
 
14107
xmlParserCtxtPtr
 
14108
xmlCreateFileParserCtxt(const char *filename)
 
14109
{
 
14110
    return(xmlCreateURLParserCtxt(filename, 0));
 
14111
}
 
14112
 
 
14113
#ifdef LIBXML_SAX1_ENABLED
 
14114
/**
 
14115
 * xmlSAXParseFileWithData:
 
14116
 * @sax:  the SAX handler block
 
14117
 * @filename:  the filename
 
14118
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
 
14119
 *             documents
 
14120
 * @data:  the userdata
 
14121
 *
 
14122
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
 
14123
 * compressed document is provided by default if found at compile-time.
 
14124
 * It use the given SAX function block to handle the parsing callback.
 
14125
 * If sax is NULL, fallback to the default DOM tree building routines.
 
14126
 *
 
14127
 * User data (void *) is stored within the parser context in the
 
14128
 * context's _private member, so it is available nearly everywhere in libxml
 
14129
 *
 
14130
 * Returns the resulting document tree
 
14131
 */
 
14132
 
 
14133
xmlDocPtr
 
14134
xmlSAXParseFileWithData(xmlSAXHandlerPtr sax, const char *filename,
 
14135
                        int recovery, void *data) {
 
14136
    xmlDocPtr ret;
 
14137
    xmlParserCtxtPtr ctxt;
 
14138
 
 
14139
    xmlInitParser();
 
14140
 
 
14141
    ctxt = xmlCreateFileParserCtxt(filename);
 
14142
    if (ctxt == NULL) {
 
14143
        return(NULL);
 
14144
    }
 
14145
    if (sax != NULL) {
 
14146
        if (ctxt->sax != NULL)
 
14147
            xmlFree(ctxt->sax);
 
14148
        ctxt->sax = sax;
 
14149
    }
 
14150
    xmlDetectSAX2(ctxt);
 
14151
    if (data!=NULL) {
 
14152
        ctxt->_private = data;
 
14153
    }
 
14154
 
 
14155
    if (ctxt->directory == NULL)
 
14156
        ctxt->directory = xmlParserGetDirectory(filename);
 
14157
 
 
14158
    ctxt->recovery = recovery;
 
14159
 
 
14160
    xmlParseDocument(ctxt);
 
14161
 
 
14162
    if ((ctxt->wellFormed) || recovery) {
 
14163
        ret = ctxt->myDoc;
 
14164
        if (ret != NULL) {
 
14165
            if (ctxt->input->buf->compressed > 0)
 
14166
                ret->compression = 9;
 
14167
            else
 
14168
                ret->compression = ctxt->input->buf->compressed;
 
14169
        }
 
14170
    }
 
14171
    else {
 
14172
       ret = NULL;
 
14173
       xmlFreeDoc(ctxt->myDoc);
 
14174
       ctxt->myDoc = NULL;
 
14175
    }
 
14176
    if (sax != NULL)
 
14177
        ctxt->sax = NULL;
 
14178
    xmlFreeParserCtxt(ctxt);
 
14179
 
 
14180
    return(ret);
 
14181
}
 
14182
 
 
14183
/**
 
14184
 * xmlSAXParseFile:
 
14185
 * @sax:  the SAX handler block
 
14186
 * @filename:  the filename
 
14187
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
 
14188
 *             documents
 
14189
 *
 
14190
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
 
14191
 * compressed document is provided by default if found at compile-time.
 
14192
 * It use the given SAX function block to handle the parsing callback.
 
14193
 * If sax is NULL, fallback to the default DOM tree building routines.
 
14194
 *
 
14195
 * Returns the resulting document tree
 
14196
 */
 
14197
 
 
14198
xmlDocPtr
 
14199
xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
 
14200
                          int recovery) {
 
14201
    return(xmlSAXParseFileWithData(sax,filename,recovery,NULL));
 
14202
}
 
14203
 
 
14204
/**
 
14205
 * xmlRecoverDoc:
 
14206
 * @cur:  a pointer to an array of xmlChar
 
14207
 *
 
14208
 * parse an XML in-memory document and build a tree.
 
14209
 * In the case the document is not Well Formed, a attempt to build a
 
14210
 * tree is tried anyway
 
14211
 *
 
14212
 * Returns the resulting document tree or NULL in case of failure
 
14213
 */
 
14214
 
 
14215
xmlDocPtr
 
14216
xmlRecoverDoc(const xmlChar *cur) {
 
14217
    return(xmlSAXParseDoc(NULL, cur, 1));
 
14218
}
 
14219
 
 
14220
/**
 
14221
 * xmlParseFile:
 
14222
 * @filename:  the filename
 
14223
 *
 
14224
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
 
14225
 * compressed document is provided by default if found at compile-time.
 
14226
 *
 
14227
 * Returns the resulting document tree if the file was wellformed,
 
14228
 * NULL otherwise.
 
14229
 */
 
14230
 
 
14231
xmlDocPtr
 
14232
xmlParseFile(const char *filename) {
 
14233
    return(xmlSAXParseFile(NULL, filename, 0));
 
14234
}
 
14235
 
 
14236
/**
 
14237
 * xmlRecoverFile:
 
14238
 * @filename:  the filename
 
14239
 *
 
14240
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
 
14241
 * compressed document is provided by default if found at compile-time.
 
14242
 * In the case the document is not Well Formed, it attempts to build
 
14243
 * a tree anyway
 
14244
 *
 
14245
 * Returns the resulting document tree or NULL in case of failure
 
14246
 */
 
14247
 
 
14248
xmlDocPtr
 
14249
xmlRecoverFile(const char *filename) {
 
14250
    return(xmlSAXParseFile(NULL, filename, 1));
 
14251
}
 
14252
 
 
14253
 
 
14254
/**
 
14255
 * xmlSetupParserForBuffer:
 
14256
 * @ctxt:  an XML parser context
 
14257
 * @buffer:  a xmlChar * buffer
 
14258
 * @filename:  a file name
 
14259
 *
 
14260
 * Setup the parser context to parse a new buffer; Clears any prior
 
14261
 * contents from the parser context. The buffer parameter must not be
 
14262
 * NULL, but the filename parameter can be
 
14263
 */
 
14264
void
 
14265
xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
 
14266
                             const char* filename)
 
14267
{
 
14268
    xmlParserInputPtr input;
 
14269
 
 
14270
    if ((ctxt == NULL) || (buffer == NULL))
 
14271
        return;
 
14272
 
 
14273
    input = xmlNewInputStream(ctxt);
 
14274
    if (input == NULL) {
 
14275
        xmlErrMemory(NULL, "parsing new buffer: out of memory\n");
 
14276
        xmlClearParserCtxt(ctxt);
 
14277
        return;
 
14278
    }
 
14279
 
 
14280
    xmlClearParserCtxt(ctxt);
 
14281
    if (filename != NULL)
 
14282
        input->filename = (char *) xmlCanonicPath((const xmlChar *)filename);
 
14283
    input->base = buffer;
 
14284
    input->cur = buffer;
 
14285
    input->end = &buffer[xmlStrlen(buffer)];
 
14286
    inputPush(ctxt, input);
 
14287
}
 
14288
 
 
14289
/**
 
14290
 * xmlSAXUserParseFile:
 
14291
 * @sax:  a SAX handler
 
14292
 * @user_data:  The user data returned on SAX callbacks
 
14293
 * @filename:  a file name
 
14294
 *
 
14295
 * parse an XML file and call the given SAX handler routines.
 
14296
 * Automatic support for ZLIB/Compress compressed document is provided
 
14297
 *
 
14298
 * Returns 0 in case of success or a error number otherwise
 
14299
 */
 
14300
int
 
14301
xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
 
14302
                    const char *filename) {
 
14303
    int ret = 0;
 
14304
    xmlParserCtxtPtr ctxt;
 
14305
 
 
14306
    ctxt = xmlCreateFileParserCtxt(filename);
 
14307
    if (ctxt == NULL) return -1;
 
14308
    if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
 
14309
        xmlFree(ctxt->sax);
 
14310
    ctxt->sax = sax;
 
14311
    xmlDetectSAX2(ctxt);
 
14312
 
 
14313
    if (user_data != NULL)
 
14314
        ctxt->userData = user_data;
 
14315
 
 
14316
    xmlParseDocument(ctxt);
 
14317
 
 
14318
    if (ctxt->wellFormed)
 
14319
        ret = 0;
 
14320
    else {
 
14321
        if (ctxt->errNo != 0)
 
14322
            ret = ctxt->errNo;
 
14323
        else
 
14324
            ret = -1;
 
14325
    }
 
14326
    if (sax != NULL)
 
14327
        ctxt->sax = NULL;
 
14328
    if (ctxt->myDoc != NULL) {
 
14329
        xmlFreeDoc(ctxt->myDoc);
 
14330
        ctxt->myDoc = NULL;
 
14331
    }
 
14332
    xmlFreeParserCtxt(ctxt);
 
14333
 
 
14334
    return ret;
 
14335
}
 
14336
#endif /* LIBXML_SAX1_ENABLED */
 
14337
 
 
14338
/************************************************************************
 
14339
 *                                                                      *
 
14340
 *              Front ends when parsing from memory                     *
 
14341
 *                                                                      *
 
14342
 ************************************************************************/
 
14343
 
 
14344
/**
 
14345
 * xmlCreateMemoryParserCtxt:
 
14346
 * @buffer:  a pointer to a char array
 
14347
 * @size:  the size of the array
 
14348
 *
 
14349
 * Create a parser context for an XML in-memory document.
 
14350
 *
 
14351
 * Returns the new parser context or NULL
 
14352
 */
 
14353
xmlParserCtxtPtr
 
14354
xmlCreateMemoryParserCtxt(const char *buffer, int size) {
 
14355
    xmlParserCtxtPtr ctxt;
 
14356
    xmlParserInputPtr input;
 
14357
    xmlParserInputBufferPtr buf;
 
14358
 
 
14359
    if (buffer == NULL)
 
14360
        return(NULL);
 
14361
    if (size <= 0)
 
14362
        return(NULL);
 
14363
 
 
14364
    ctxt = xmlNewParserCtxt();
 
14365
    if (ctxt == NULL)
 
14366
        return(NULL);
 
14367
 
 
14368
    /* TODO: xmlParserInputBufferCreateStatic, requires some serious changes */
 
14369
    buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
 
14370
    if (buf == NULL) {
 
14371
        xmlFreeParserCtxt(ctxt);
 
14372
        return(NULL);
 
14373
    }
 
14374
 
 
14375
    input = xmlNewInputStream(ctxt);
 
14376
    if (input == NULL) {
 
14377
        xmlFreeParserInputBuffer(buf);
 
14378
        xmlFreeParserCtxt(ctxt);
 
14379
        return(NULL);
 
14380
    }
 
14381
 
 
14382
    input->filename = NULL;
 
14383
    input->buf = buf;
 
14384
    xmlBufResetInput(input->buf->buffer, input);
 
14385
 
 
14386
    inputPush(ctxt, input);
 
14387
    return(ctxt);
 
14388
}
 
14389
 
 
14390
#ifdef LIBXML_SAX1_ENABLED
 
14391
/**
 
14392
 * xmlSAXParseMemoryWithData:
 
14393
 * @sax:  the SAX handler block
 
14394
 * @buffer:  an pointer to a char array
 
14395
 * @size:  the size of the array
 
14396
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
 
14397
 *             documents
 
14398
 * @data:  the userdata
 
14399
 *
 
14400
 * parse an XML in-memory block and use the given SAX function block
 
14401
 * to handle the parsing callback. If sax is NULL, fallback to the default
 
14402
 * DOM tree building routines.
 
14403
 *
 
14404
 * User data (void *) is stored within the parser context in the
 
14405
 * context's _private member, so it is available nearly everywhere in libxml
 
14406
 *
 
14407
 * Returns the resulting document tree
 
14408
 */
 
14409
 
 
14410
xmlDocPtr
 
14411
xmlSAXParseMemoryWithData(xmlSAXHandlerPtr sax, const char *buffer,
 
14412
                  int size, int recovery, void *data) {
 
14413
    xmlDocPtr ret;
 
14414
    xmlParserCtxtPtr ctxt;
 
14415
 
 
14416
    xmlInitParser();
 
14417
 
 
14418
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
 
14419
    if (ctxt == NULL) return(NULL);
 
14420
    if (sax != NULL) {
 
14421
        if (ctxt->sax != NULL)
 
14422
            xmlFree(ctxt->sax);
 
14423
        ctxt->sax = sax;
 
14424
    }
 
14425
    xmlDetectSAX2(ctxt);
 
14426
    if (data!=NULL) {
 
14427
        ctxt->_private=data;
 
14428
    }
 
14429
 
 
14430
    ctxt->recovery = recovery;
 
14431
 
 
14432
    xmlParseDocument(ctxt);
 
14433
 
 
14434
    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
 
14435
    else {
 
14436
       ret = NULL;
 
14437
       xmlFreeDoc(ctxt->myDoc);
 
14438
       ctxt->myDoc = NULL;
 
14439
    }
 
14440
    if (sax != NULL)
 
14441
        ctxt->sax = NULL;
 
14442
    xmlFreeParserCtxt(ctxt);
 
14443
 
 
14444
    return(ret);
 
14445
}
 
14446
 
 
14447
/**
 
14448
 * xmlSAXParseMemory:
 
14449
 * @sax:  the SAX handler block
 
14450
 * @buffer:  an pointer to a char array
 
14451
 * @size:  the size of the array
 
14452
 * @recovery:  work in recovery mode, i.e. tries to read not Well Formed
 
14453
 *             documents
 
14454
 *
 
14455
 * parse an XML in-memory block and use the given SAX function block
 
14456
 * to handle the parsing callback. If sax is NULL, fallback to the default
 
14457
 * DOM tree building routines.
 
14458
 *
 
14459
 * Returns the resulting document tree
 
14460
 */
 
14461
xmlDocPtr
 
14462
xmlSAXParseMemory(xmlSAXHandlerPtr sax, const char *buffer,
 
14463
                  int size, int recovery) {
 
14464
    return xmlSAXParseMemoryWithData(sax, buffer, size, recovery, NULL);
 
14465
}
 
14466
 
 
14467
/**
 
14468
 * xmlParseMemory:
 
14469
 * @buffer:  an pointer to a char array
 
14470
 * @size:  the size of the array
 
14471
 *
 
14472
 * parse an XML in-memory block and build a tree.
 
14473
 *
 
14474
 * Returns the resulting document tree
 
14475
 */
 
14476
 
 
14477
xmlDocPtr xmlParseMemory(const char *buffer, int size) {
 
14478
   return(xmlSAXParseMemory(NULL, buffer, size, 0));
 
14479
}
 
14480
 
 
14481
/**
 
14482
 * xmlRecoverMemory:
 
14483
 * @buffer:  an pointer to a char array
 
14484
 * @size:  the size of the array
 
14485
 *
 
14486
 * parse an XML in-memory block and build a tree.
 
14487
 * In the case the document is not Well Formed, an attempt to
 
14488
 * build a tree is tried anyway
 
14489
 *
 
14490
 * Returns the resulting document tree or NULL in case of error
 
14491
 */
 
14492
 
 
14493
xmlDocPtr xmlRecoverMemory(const char *buffer, int size) {
 
14494
   return(xmlSAXParseMemory(NULL, buffer, size, 1));
 
14495
}
 
14496
 
 
14497
/**
 
14498
 * xmlSAXUserParseMemory:
 
14499
 * @sax:  a SAX handler
 
14500
 * @user_data:  The user data returned on SAX callbacks
 
14501
 * @buffer:  an in-memory XML document input
 
14502
 * @size:  the length of the XML document in bytes
 
14503
 *
 
14504
 * A better SAX parsing routine.
 
14505
 * parse an XML in-memory buffer and call the given SAX handler routines.
 
14506
 *
 
14507
 * Returns 0 in case of success or a error number otherwise
 
14508
 */
 
14509
int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
 
14510
                          const char *buffer, int size) {
 
14511
    int ret = 0;
 
14512
    xmlParserCtxtPtr ctxt;
 
14513
 
 
14514
    xmlInitParser();
 
14515
 
 
14516
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
 
14517
    if (ctxt == NULL) return -1;
 
14518
    if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
 
14519
        xmlFree(ctxt->sax);
 
14520
    ctxt->sax = sax;
 
14521
    xmlDetectSAX2(ctxt);
 
14522
 
 
14523
    if (user_data != NULL)
 
14524
        ctxt->userData = user_data;
 
14525
 
 
14526
    xmlParseDocument(ctxt);
 
14527
 
 
14528
    if (ctxt->wellFormed)
 
14529
        ret = 0;
 
14530
    else {
 
14531
        if (ctxt->errNo != 0)
 
14532
            ret = ctxt->errNo;
 
14533
        else
 
14534
            ret = -1;
 
14535
    }
 
14536
    if (sax != NULL)
 
14537
        ctxt->sax = NULL;
 
14538
    if (ctxt->myDoc != NULL) {
 
14539
        xmlFreeDoc(ctxt->myDoc);
 
14540
        ctxt->myDoc = NULL;
 
14541
    }
 
14542
    xmlFreeParserCtxt(ctxt);
 
14543
 
 
14544
    return ret;
 
14545
}
 
14546
#endif /* LIBXML_SAX1_ENABLED */
 
14547
 
 
14548
/**
 
14549
 * xmlCreateDocParserCtxt:
 
14550
 * @cur:  a pointer to an array of xmlChar
 
14551
 *
 
14552
 * Creates a parser context for an XML in-memory document.
 
14553
 *
 
14554
 * Returns the new parser context or NULL
 
14555
 */
 
14556
xmlParserCtxtPtr
 
14557
xmlCreateDocParserCtxt(const xmlChar *cur) {
 
14558
    int len;
 
14559
 
 
14560
    if (cur == NULL)
 
14561
        return(NULL);
 
14562
    len = xmlStrlen(cur);
 
14563
    return(xmlCreateMemoryParserCtxt((const char *)cur, len));
 
14564
}
 
14565
 
 
14566
#ifdef LIBXML_SAX1_ENABLED
 
14567
/**
 
14568
 * xmlSAXParseDoc:
 
14569
 * @sax:  the SAX handler block
 
14570
 * @cur:  a pointer to an array of xmlChar
 
14571
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
 
14572
 *             documents
 
14573
 *
 
14574
 * parse an XML in-memory document and build a tree.
 
14575
 * It use the given SAX function block to handle the parsing callback.
 
14576
 * If sax is NULL, fallback to the default DOM tree building routines.
 
14577
 *
 
14578
 * Returns the resulting document tree
 
14579
 */
 
14580
 
 
14581
xmlDocPtr
 
14582
xmlSAXParseDoc(xmlSAXHandlerPtr sax, const xmlChar *cur, int recovery) {
 
14583
    xmlDocPtr ret;
 
14584
    xmlParserCtxtPtr ctxt;
 
14585
    xmlSAXHandlerPtr oldsax = NULL;
 
14586
 
 
14587
    if (cur == NULL) return(NULL);
 
14588
 
 
14589
 
 
14590
    ctxt = xmlCreateDocParserCtxt(cur);
 
14591
    if (ctxt == NULL) return(NULL);
 
14592
    if (sax != NULL) {
 
14593
        oldsax = ctxt->sax;
 
14594
        ctxt->sax = sax;
 
14595
        ctxt->userData = NULL;
 
14596
    }
 
14597
    xmlDetectSAX2(ctxt);
 
14598
 
 
14599
    xmlParseDocument(ctxt);
 
14600
    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
 
14601
    else {
 
14602
       ret = NULL;
 
14603
       xmlFreeDoc(ctxt->myDoc);
 
14604
       ctxt->myDoc = NULL;
 
14605
    }
 
14606
    if (sax != NULL)
 
14607
        ctxt->sax = oldsax;
 
14608
    xmlFreeParserCtxt(ctxt);
 
14609
 
 
14610
    return(ret);
 
14611
}
 
14612
 
 
14613
/**
 
14614
 * xmlParseDoc:
 
14615
 * @cur:  a pointer to an array of xmlChar
 
14616
 *
 
14617
 * parse an XML in-memory document and build a tree.
 
14618
 *
 
14619
 * Returns the resulting document tree
 
14620
 */
 
14621
 
 
14622
xmlDocPtr
 
14623
xmlParseDoc(const xmlChar *cur) {
 
14624
    return(xmlSAXParseDoc(NULL, cur, 0));
 
14625
}
 
14626
#endif /* LIBXML_SAX1_ENABLED */
 
14627
 
 
14628
#ifdef LIBXML_LEGACY_ENABLED
 
14629
/************************************************************************
 
14630
 *                                                                      *
 
14631
 *      Specific function to keep track of entities references          *
 
14632
 *      and used by the XSLT debugger                                   *
 
14633
 *                                                                      *
 
14634
 ************************************************************************/
 
14635
 
 
14636
static xmlEntityReferenceFunc xmlEntityRefFunc = NULL;
 
14637
 
 
14638
/**
 
14639
 * xmlAddEntityReference:
 
14640
 * @ent : A valid entity
 
14641
 * @firstNode : A valid first node for children of entity
 
14642
 * @lastNode : A valid last node of children entity
 
14643
 *
 
14644
 * Notify of a reference to an entity of type XML_EXTERNAL_GENERAL_PARSED_ENTITY
 
14645
 */
 
14646
static void
 
14647
xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
 
14648
                      xmlNodePtr lastNode)
 
14649
{
 
14650
    if (xmlEntityRefFunc != NULL) {
 
14651
        (*xmlEntityRefFunc) (ent, firstNode, lastNode);
 
14652
    }
 
14653
}
 
14654
 
 
14655
 
 
14656
/**
 
14657
 * xmlSetEntityReferenceFunc:
 
14658
 * @func: A valid function
 
14659
 *
 
14660
 * Set the function to call call back when a xml reference has been made
 
14661
 */
 
14662
void
 
14663
xmlSetEntityReferenceFunc(xmlEntityReferenceFunc func)
 
14664
{
 
14665
    xmlEntityRefFunc = func;
 
14666
}
 
14667
#endif /* LIBXML_LEGACY_ENABLED */
 
14668
 
 
14669
/************************************************************************
 
14670
 *                                                                      *
 
14671
 *                              Miscellaneous                           *
 
14672
 *                                                                      *
 
14673
 ************************************************************************/
 
14674
 
 
14675
#ifdef LIBXML_XPATH_ENABLED
 
14676
#include <libxml/xpath.h>
 
14677
#endif
 
14678
 
 
14679
extern void XMLCDECL xmlGenericErrorDefaultFunc(void *ctx, const char *msg, ...);
 
14680
static int xmlParserInitialized = 0;
 
14681
 
 
14682
/**
 
14683
 * xmlInitParser:
 
14684
 *
 
14685
 * Initialization function for the XML parser.
 
14686
 * This is not reentrant. Call once before processing in case of
 
14687
 * use in multithreaded programs.
 
14688
 */
 
14689
 
 
14690
void
 
14691
xmlInitParser(void) {
 
14692
    if (xmlParserInitialized != 0)
 
14693
        return;
 
14694
 
 
14695
#ifdef LIBXML_THREAD_ENABLED
 
14696
    __xmlGlobalInitMutexLock();
 
14697
    if (xmlParserInitialized == 0) {
 
14698
#endif
 
14699
        xmlInitThreads();
 
14700
        xmlInitGlobals();
 
14701
        if ((xmlGenericError == xmlGenericErrorDefaultFunc) ||
 
14702
            (xmlGenericError == NULL))
 
14703
            initGenericErrorDefaultFunc(NULL);
 
14704
        xmlInitMemory();
 
14705
        xmlInitializeDict();
 
14706
        xmlInitCharEncodingHandlers();
 
14707
        xmlDefaultSAXHandlerInit();
 
14708
        xmlRegisterDefaultInputCallbacks();
 
14709
#ifdef LIBXML_OUTPUT_ENABLED
 
14710
        xmlRegisterDefaultOutputCallbacks();
 
14711
#endif /* LIBXML_OUTPUT_ENABLED */
 
14712
#ifdef LIBXML_HTML_ENABLED
 
14713
        htmlInitAutoClose();
 
14714
        htmlDefaultSAXHandlerInit();
 
14715
#endif
 
14716
#ifdef LIBXML_XPATH_ENABLED
 
14717
        xmlXPathInit();
 
14718
#endif
 
14719
        xmlParserInitialized = 1;
 
14720
#ifdef LIBXML_THREAD_ENABLED
 
14721
    }
 
14722
    __xmlGlobalInitMutexUnlock();
 
14723
#endif
 
14724
}
 
14725
 
 
14726
/**
 
14727
 * xmlCleanupParser:
 
14728
 *
 
14729
 * This function name is somewhat misleading. It does not clean up
 
14730
 * parser state, it cleans up memory allocated by the library itself.
 
14731
 * It is a cleanup function for the XML library. It tries to reclaim all
 
14732
 * related global memory allocated for the library processing.
 
14733
 * It doesn't deallocate any document related memory. One should
 
14734
 * call xmlCleanupParser() only when the process has finished using
 
14735
 * the library and all XML/HTML documents built with it.
 
14736
 * See also xmlInitParser() which has the opposite function of preparing
 
14737
 * the library for operations.
 
14738
 *
 
14739
 * WARNING: if your application is multithreaded or has plugin support
 
14740
 *          calling this may crash the application if another thread or
 
14741
 *          a plugin is still using libxml2. It's sometimes very hard to
 
14742
 *          guess if libxml2 is in use in the application, some libraries
 
14743
 *          or plugins may use it without notice. In case of doubt abstain
 
14744
 *          from calling this function or do it just before calling exit()
 
14745
 *          to avoid leak reports from valgrind !
 
14746
 */
 
14747
 
 
14748
void
 
14749
xmlCleanupParser(void) {
 
14750
    if (!xmlParserInitialized)
 
14751
        return;
 
14752
 
 
14753
    xmlCleanupCharEncodingHandlers();
 
14754
#ifdef LIBXML_CATALOG_ENABLED
 
14755
    xmlCatalogCleanup();
 
14756
#endif
 
14757
    xmlDictCleanup();
 
14758
    xmlCleanupInputCallbacks();
 
14759
#ifdef LIBXML_OUTPUT_ENABLED
 
14760
    xmlCleanupOutputCallbacks();
 
14761
#endif
 
14762
#ifdef LIBXML_SCHEMAS_ENABLED
 
14763
    xmlSchemaCleanupTypes();
 
14764
    xmlRelaxNGCleanupTypes();
 
14765
#endif
 
14766
    xmlResetLastError();
 
14767
    xmlCleanupGlobals();
 
14768
    xmlCleanupThreads(); /* must be last if called not from the main thread */
 
14769
    xmlCleanupMemory();
 
14770
    xmlParserInitialized = 0;
 
14771
}
 
14772
 
 
14773
/************************************************************************
 
14774
 *                                                                      *
 
14775
 *      New set (2.6.0) of simpler and more flexible APIs               *
 
14776
 *                                                                      *
 
14777
 ************************************************************************/
 
14778
 
 
14779
/**
 
14780
 * DICT_FREE:
 
14781
 * @str:  a string
 
14782
 *
 
14783
 * Free a string if it is not owned by the "dict" dictionnary in the
 
14784
 * current scope
 
14785
 */
 
14786
#define DICT_FREE(str)                                          \
 
14787
        if ((str) && ((!dict) ||                                \
 
14788
            (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))  \
 
14789
            xmlFree((char *)(str));
 
14790
 
 
14791
/**
 
14792
 * xmlCtxtReset:
 
14793
 * @ctxt: an XML parser context
 
14794
 *
 
14795
 * Reset a parser context
 
14796
 */
 
14797
void
 
14798
xmlCtxtReset(xmlParserCtxtPtr ctxt)
 
14799
{
 
14800
    xmlParserInputPtr input;
 
14801
    xmlDictPtr dict;
 
14802
 
 
14803
    if (ctxt == NULL)
 
14804
        return;
 
14805
 
 
14806
    dict = ctxt->dict;
 
14807
 
 
14808
    while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
 
14809
        xmlFreeInputStream(input);
 
14810
    }
 
14811
    ctxt->inputNr = 0;
 
14812
    ctxt->input = NULL;
 
14813
 
 
14814
    ctxt->spaceNr = 0;
 
14815
    if (ctxt->spaceTab != NULL) {
 
14816
        ctxt->spaceTab[0] = -1;
 
14817
        ctxt->space = &ctxt->spaceTab[0];
 
14818
    } else {
 
14819
        ctxt->space = NULL;
 
14820
    }
 
14821
 
 
14822
 
 
14823
    ctxt->nodeNr = 0;
 
14824
    ctxt->node = NULL;
 
14825
 
 
14826
    ctxt->nameNr = 0;
 
14827
    ctxt->name = NULL;
 
14828
 
 
14829
    DICT_FREE(ctxt->version);
 
14830
    ctxt->version = NULL;
 
14831
    DICT_FREE(ctxt->encoding);
 
14832
    ctxt->encoding = NULL;
 
14833
    DICT_FREE(ctxt->directory);
 
14834
    ctxt->directory = NULL;
 
14835
    DICT_FREE(ctxt->extSubURI);
 
14836
    ctxt->extSubURI = NULL;
 
14837
    DICT_FREE(ctxt->extSubSystem);
 
14838
    ctxt->extSubSystem = NULL;
 
14839
    if (ctxt->myDoc != NULL)
 
14840
        xmlFreeDoc(ctxt->myDoc);
 
14841
    ctxt->myDoc = NULL;
 
14842
 
 
14843
    ctxt->standalone = -1;
 
14844
    ctxt->hasExternalSubset = 0;
 
14845
    ctxt->hasPErefs = 0;
 
14846
    ctxt->html = 0;
 
14847
    ctxt->external = 0;
 
14848
    ctxt->instate = XML_PARSER_START;
 
14849
    ctxt->token = 0;
 
14850
 
 
14851
    ctxt->wellFormed = 1;
 
14852
    ctxt->nsWellFormed = 1;
 
14853
    ctxt->disableSAX = 0;
 
14854
    ctxt->valid = 1;
 
14855
#if 0
 
14856
    ctxt->vctxt.userData = ctxt;
 
14857
    ctxt->vctxt.error = xmlParserValidityError;
 
14858
    ctxt->vctxt.warning = xmlParserValidityWarning;
 
14859
#endif
 
14860
    ctxt->record_info = 0;
 
14861
    ctxt->nbChars = 0;
 
14862
    ctxt->checkIndex = 0;
 
14863
    ctxt->inSubset = 0;
 
14864
    ctxt->errNo = XML_ERR_OK;
 
14865
    ctxt->depth = 0;
 
14866
    ctxt->charset = XML_CHAR_ENCODING_UTF8;
 
14867
    ctxt->catalogs = NULL;
 
14868
    ctxt->nbentities = 0;
 
14869
    ctxt->sizeentities = 0;
 
14870
    ctxt->sizeentcopy = 0;
 
14871
    xmlInitNodeInfoSeq(&ctxt->node_seq);
 
14872
 
 
14873
    if (ctxt->attsDefault != NULL) {
 
14874
        xmlHashFree(ctxt->attsDefault, (xmlHashDeallocator) xmlFree);
 
14875
        ctxt->attsDefault = NULL;
 
14876
    }
 
14877
    if (ctxt->attsSpecial != NULL) {
 
14878
        xmlHashFree(ctxt->attsSpecial, NULL);
 
14879
        ctxt->attsSpecial = NULL;
 
14880
    }
 
14881
 
 
14882
#ifdef LIBXML_CATALOG_ENABLED
 
14883
    if (ctxt->catalogs != NULL)
 
14884
        xmlCatalogFreeLocal(ctxt->catalogs);
 
14885
#endif
 
14886
    if (ctxt->lastError.code != XML_ERR_OK)
 
14887
        xmlResetError(&ctxt->lastError);
 
14888
}
 
14889
 
 
14890
/**
 
14891
 * xmlCtxtResetPush:
 
14892
 * @ctxt: an XML parser context
 
14893
 * @chunk:  a pointer to an array of chars
 
14894
 * @size:  number of chars in the array
 
14895
 * @filename:  an optional file name or URI
 
14896
 * @encoding:  the document encoding, or NULL
 
14897
 *
 
14898
 * Reset a push parser context
 
14899
 *
 
14900
 * Returns 0 in case of success and 1 in case of error
 
14901
 */
 
14902
int
 
14903
xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk,
 
14904
                 int size, const char *filename, const char *encoding)
 
14905
{
 
14906
    xmlParserInputPtr inputStream;
 
14907
    xmlParserInputBufferPtr buf;
 
14908
    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
 
14909
 
 
14910
    if (ctxt == NULL)
 
14911
        return(1);
 
14912
 
 
14913
    if ((encoding == NULL) && (chunk != NULL) && (size >= 4))
 
14914
        enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
 
14915
 
 
14916
    buf = xmlAllocParserInputBuffer(enc);
 
14917
    if (buf == NULL)
 
14918
        return(1);
 
14919
 
 
14920
    if (ctxt == NULL) {
 
14921
        xmlFreeParserInputBuffer(buf);
 
14922
        return(1);
 
14923
    }
 
14924
 
 
14925
    xmlCtxtReset(ctxt);
 
14926
 
 
14927
    if (ctxt->pushTab == NULL) {
 
14928
        ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 *
 
14929
                                            sizeof(xmlChar *));
 
14930
        if (ctxt->pushTab == NULL) {
 
14931
            xmlErrMemory(ctxt, NULL);
 
14932
            xmlFreeParserInputBuffer(buf);
 
14933
            return(1);
 
14934
        }
 
14935
    }
 
14936
 
 
14937
    if (filename == NULL) {
 
14938
        ctxt->directory = NULL;
 
14939
    } else {
 
14940
        ctxt->directory = xmlParserGetDirectory(filename);
 
14941
    }
 
14942
 
 
14943
    inputStream = xmlNewInputStream(ctxt);
 
14944
    if (inputStream == NULL) {
 
14945
        xmlFreeParserInputBuffer(buf);
 
14946
        return(1);
 
14947
    }
 
14948
 
 
14949
    if (filename == NULL)
 
14950
        inputStream->filename = NULL;
 
14951
    else
 
14952
        inputStream->filename = (char *)
 
14953
            xmlCanonicPath((const xmlChar *) filename);
 
14954
    inputStream->buf = buf;
 
14955
    xmlBufResetInput(buf->buffer, inputStream);
 
14956
 
 
14957
    inputPush(ctxt, inputStream);
 
14958
 
 
14959
    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
 
14960
        (ctxt->input->buf != NULL)) {
 
14961
        size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
 
14962
        size_t cur = ctxt->input->cur - ctxt->input->base;
 
14963
 
 
14964
        xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
 
14965
 
 
14966
        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
 
14967
#ifdef DEBUG_PUSH
 
14968
        xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
 
14969
#endif
 
14970
    }
 
14971
 
 
14972
    if (encoding != NULL) {
 
14973
        xmlCharEncodingHandlerPtr hdlr;
 
14974
 
 
14975
        if (ctxt->encoding != NULL)
 
14976
            xmlFree((xmlChar *) ctxt->encoding);
 
14977
        ctxt->encoding = xmlStrdup((const xmlChar *) encoding);
 
14978
 
 
14979
        hdlr = xmlFindCharEncodingHandler(encoding);
 
14980
        if (hdlr != NULL) {
 
14981
            xmlSwitchToEncoding(ctxt, hdlr);
 
14982
        } else {
 
14983
            xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
 
14984
                              "Unsupported encoding %s\n", BAD_CAST encoding);
 
14985
        }
 
14986
    } else if (enc != XML_CHAR_ENCODING_NONE) {
 
14987
        xmlSwitchEncoding(ctxt, enc);
 
14988
    }
 
14989
 
 
14990
    return(0);
 
14991
}
 
14992
 
 
14993
 
 
14994
/**
 
14995
 * xmlCtxtUseOptionsInternal:
 
14996
 * @ctxt: an XML parser context
 
14997
 * @options:  a combination of xmlParserOption
 
14998
 * @encoding:  the user provided encoding to use
 
14999
 *
 
15000
 * Applies the options to the parser context
 
15001
 *
 
15002
 * Returns 0 in case of success, the set of unknown or unimplemented options
 
15003
 *         in case of error.
 
15004
 */
 
15005
static int
 
15006
xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encoding)
 
15007
{
 
15008
    if (ctxt == NULL)
 
15009
        return(-1);
 
15010
    if (encoding != NULL) {
 
15011
        if (ctxt->encoding != NULL)
 
15012
            xmlFree((xmlChar *) ctxt->encoding);
 
15013
        ctxt->encoding = xmlStrdup((const xmlChar *) encoding);
 
15014
    }
 
15015
    if (options & XML_PARSE_RECOVER) {
 
15016
        ctxt->recovery = 1;
 
15017
        options -= XML_PARSE_RECOVER;
 
15018
        ctxt->options |= XML_PARSE_RECOVER;
 
15019
    } else
 
15020
        ctxt->recovery = 0;
 
15021
    if (options & XML_PARSE_DTDLOAD) {
 
15022
        ctxt->loadsubset = XML_DETECT_IDS;
 
15023
        options -= XML_PARSE_DTDLOAD;
 
15024
        ctxt->options |= XML_PARSE_DTDLOAD;
 
15025
    } else
 
15026
        ctxt->loadsubset = 0;
 
15027
    if (options & XML_PARSE_DTDATTR) {
 
15028
        ctxt->loadsubset |= XML_COMPLETE_ATTRS;
 
15029
        options -= XML_PARSE_DTDATTR;
 
15030
        ctxt->options |= XML_PARSE_DTDATTR;
 
15031
    }
 
15032
    if (options & XML_PARSE_NOENT) {
 
15033
        ctxt->replaceEntities = 1;
 
15034
        /* ctxt->loadsubset |= XML_DETECT_IDS; */
 
15035
        options -= XML_PARSE_NOENT;
 
15036
        ctxt->options |= XML_PARSE_NOENT;
 
15037
    } else
 
15038
        ctxt->replaceEntities = 0;
 
15039
    if (options & XML_PARSE_PEDANTIC) {
 
15040
        ctxt->pedantic = 1;
 
15041
        options -= XML_PARSE_PEDANTIC;
 
15042
        ctxt->options |= XML_PARSE_PEDANTIC;
 
15043
    } else
 
15044
        ctxt->pedantic = 0;
 
15045
    if (options & XML_PARSE_NOBLANKS) {
 
15046
        ctxt->keepBlanks = 0;
 
15047
        ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
 
15048
        options -= XML_PARSE_NOBLANKS;
 
15049
        ctxt->options |= XML_PARSE_NOBLANKS;
 
15050
    } else
 
15051
        ctxt->keepBlanks = 1;
 
15052
    if (options & XML_PARSE_DTDVALID) {
 
15053
        ctxt->validate = 1;
 
15054
        if (options & XML_PARSE_NOWARNING)
 
15055
            ctxt->vctxt.warning = NULL;
 
15056
        if (options & XML_PARSE_NOERROR)
 
15057
            ctxt->vctxt.error = NULL;
 
15058
        options -= XML_PARSE_DTDVALID;
 
15059
        ctxt->options |= XML_PARSE_DTDVALID;
 
15060
    } else
 
15061
        ctxt->validate = 0;
 
15062
    if (options & XML_PARSE_NOWARNING) {
 
15063
        ctxt->sax->warning = NULL;
 
15064
        options -= XML_PARSE_NOWARNING;
 
15065
    }
 
15066
    if (options & XML_PARSE_NOERROR) {
 
15067
        ctxt->sax->error = NULL;
 
15068
        ctxt->sax->fatalError = NULL;
 
15069
        options -= XML_PARSE_NOERROR;
 
15070
    }
 
15071
#ifdef LIBXML_SAX1_ENABLED
 
15072
    if (options & XML_PARSE_SAX1) {
 
15073
        ctxt->sax->startElement = xmlSAX2StartElement;
 
15074
        ctxt->sax->endElement = xmlSAX2EndElement;
 
15075
        ctxt->sax->startElementNs = NULL;
 
15076
        ctxt->sax->endElementNs = NULL;
 
15077
        ctxt->sax->initialized = 1;
 
15078
        options -= XML_PARSE_SAX1;
 
15079
        ctxt->options |= XML_PARSE_SAX1;
 
15080
    }
 
15081
#endif /* LIBXML_SAX1_ENABLED */
 
15082
    if (options & XML_PARSE_NODICT) {
 
15083
        ctxt->dictNames = 0;
 
15084
        options -= XML_PARSE_NODICT;
 
15085
        ctxt->options |= XML_PARSE_NODICT;
 
15086
    } else {
 
15087
        ctxt->dictNames = 1;
 
15088
    }
 
15089
    if (options & XML_PARSE_NOCDATA) {
 
15090
        ctxt->sax->cdataBlock = NULL;
 
15091
        options -= XML_PARSE_NOCDATA;
 
15092
        ctxt->options |= XML_PARSE_NOCDATA;
 
15093
    }
 
15094
    if (options & XML_PARSE_NSCLEAN) {
 
15095
        ctxt->options |= XML_PARSE_NSCLEAN;
 
15096
        options -= XML_PARSE_NSCLEAN;
 
15097
    }
 
15098
    if (options & XML_PARSE_NONET) {
 
15099
        ctxt->options |= XML_PARSE_NONET;
 
15100
        options -= XML_PARSE_NONET;
 
15101
    }
 
15102
    if (options & XML_PARSE_COMPACT) {
 
15103
        ctxt->options |= XML_PARSE_COMPACT;
 
15104
        options -= XML_PARSE_COMPACT;
 
15105
    }
 
15106
    if (options & XML_PARSE_OLD10) {
 
15107
        ctxt->options |= XML_PARSE_OLD10;
 
15108
        options -= XML_PARSE_OLD10;
 
15109
    }
 
15110
    if (options & XML_PARSE_NOBASEFIX) {
 
15111
        ctxt->options |= XML_PARSE_NOBASEFIX;
 
15112
        options -= XML_PARSE_NOBASEFIX;
 
15113
    }
 
15114
    if (options & XML_PARSE_HUGE) {
 
15115
        ctxt->options |= XML_PARSE_HUGE;
 
15116
        options -= XML_PARSE_HUGE;
 
15117
        if (ctxt->dict != NULL)
 
15118
            xmlDictSetLimit(ctxt->dict, 0);
 
15119
    }
 
15120
    if (options & XML_PARSE_OLDSAX) {
 
15121
        ctxt->options |= XML_PARSE_OLDSAX;
 
15122
        options -= XML_PARSE_OLDSAX;
 
15123
    }
 
15124
    if (options & XML_PARSE_IGNORE_ENC) {
 
15125
        ctxt->options |= XML_PARSE_IGNORE_ENC;
 
15126
        options -= XML_PARSE_IGNORE_ENC;
 
15127
    }
 
15128
    if (options & XML_PARSE_BIG_LINES) {
 
15129
        ctxt->options |= XML_PARSE_BIG_LINES;
 
15130
        options -= XML_PARSE_BIG_LINES;
 
15131
    }
 
15132
    ctxt->linenumbers = 1;
 
15133
    return (options);
 
15134
}
 
15135
 
 
15136
/**
 
15137
 * xmlCtxtUseOptions:
 
15138
 * @ctxt: an XML parser context
 
15139
 * @options:  a combination of xmlParserOption
 
15140
 *
 
15141
 * Applies the options to the parser context
 
15142
 *
 
15143
 * Returns 0 in case of success, the set of unknown or unimplemented options
 
15144
 *         in case of error.
 
15145
 */
 
15146
int
 
15147
xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options)
 
15148
{
 
15149
   return(xmlCtxtUseOptionsInternal(ctxt, options, NULL));
 
15150
}
 
15151
 
 
15152
/**
 
15153
 * xmlDoRead:
 
15154
 * @ctxt:  an XML parser context
 
15155
 * @URL:  the base URL to use for the document
 
15156
 * @encoding:  the document encoding, or NULL
 
15157
 * @options:  a combination of xmlParserOption
 
15158
 * @reuse:  keep the context for reuse
 
15159
 *
 
15160
 * Common front-end for the xmlRead functions
 
15161
 *
 
15162
 * Returns the resulting document tree or NULL
 
15163
 */
 
15164
static xmlDocPtr
 
15165
xmlDoRead(xmlParserCtxtPtr ctxt, const char *URL, const char *encoding,
 
15166
          int options, int reuse)
 
15167
{
 
15168
    xmlDocPtr ret;
 
15169
 
 
15170
    xmlCtxtUseOptionsInternal(ctxt, options, encoding);
 
15171
    if (encoding != NULL) {
 
15172
        xmlCharEncodingHandlerPtr hdlr;
 
15173
 
 
15174
        hdlr = xmlFindCharEncodingHandler(encoding);
 
15175
        if (hdlr != NULL)
 
15176
            xmlSwitchToEncoding(ctxt, hdlr);
 
15177
    }
 
15178
    if ((URL != NULL) && (ctxt->input != NULL) &&
 
15179
        (ctxt->input->filename == NULL))
 
15180
        ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL);
 
15181
    xmlParseDocument(ctxt);
 
15182
    if ((ctxt->wellFormed) || ctxt->recovery)
 
15183
        ret = ctxt->myDoc;
 
15184
    else {
 
15185
        ret = NULL;
 
15186
        if (ctxt->myDoc != NULL) {
 
15187
            xmlFreeDoc(ctxt->myDoc);
 
15188
        }
 
15189
    }
 
15190
    ctxt->myDoc = NULL;
 
15191
    if (!reuse) {
 
15192
        xmlFreeParserCtxt(ctxt);
 
15193
    }
 
15194
 
 
15195
    return (ret);
 
15196
}
 
15197
 
 
15198
/**
 
15199
 * xmlReadDoc:
 
15200
 * @cur:  a pointer to a zero terminated string
 
15201
 * @URL:  the base URL to use for the document
 
15202
 * @encoding:  the document encoding, or NULL
 
15203
 * @options:  a combination of xmlParserOption
 
15204
 *
 
15205
 * parse an XML in-memory document and build a tree.
 
15206
 *
 
15207
 * Returns the resulting document tree
 
15208
 */
 
15209
xmlDocPtr
 
15210
xmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int options)
 
15211
{
 
15212
    xmlParserCtxtPtr ctxt;
 
15213
 
 
15214
    if (cur == NULL)
 
15215
        return (NULL);
 
15216
 
 
15217
    ctxt = xmlCreateDocParserCtxt(cur);
 
15218
    if (ctxt == NULL)
 
15219
        return (NULL);
 
15220
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
 
15221
}
 
15222
 
 
15223
/**
 
15224
 * xmlReadFile:
 
15225
 * @filename:  a file or URL
 
15226
 * @encoding:  the document encoding, or NULL
 
15227
 * @options:  a combination of xmlParserOption
 
15228
 *
 
15229
 * parse an XML file from the filesystem or the network.
 
15230
 *
 
15231
 * Returns the resulting document tree
 
15232
 */
 
15233
xmlDocPtr
 
15234
xmlReadFile(const char *filename, const char *encoding, int options)
 
15235
{
 
15236
    xmlParserCtxtPtr ctxt;
 
15237
 
 
15238
    ctxt = xmlCreateURLParserCtxt(filename, options);
 
15239
    if (ctxt == NULL)
 
15240
        return (NULL);
 
15241
    return (xmlDoRead(ctxt, NULL, encoding, options, 0));
 
15242
}
 
15243
 
 
15244
/**
 
15245
 * xmlReadMemory:
 
15246
 * @buffer:  a pointer to a char array
 
15247
 * @size:  the size of the array
 
15248
 * @URL:  the base URL to use for the document
 
15249
 * @encoding:  the document encoding, or NULL
 
15250
 * @options:  a combination of xmlParserOption
 
15251
 *
 
15252
 * parse an XML in-memory document and build a tree.
 
15253
 *
 
15254
 * Returns the resulting document tree
 
15255
 */
 
15256
xmlDocPtr
 
15257
xmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options)
 
15258
{
 
15259
    xmlParserCtxtPtr ctxt;
 
15260
 
 
15261
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
 
15262
    if (ctxt == NULL)
 
15263
        return (NULL);
 
15264
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
 
15265
}
 
15266
 
 
15267
/**
 
15268
 * xmlReadFd:
 
15269
 * @fd:  an open file descriptor
 
15270
 * @URL:  the base URL to use for the document
 
15271
 * @encoding:  the document encoding, or NULL
 
15272
 * @options:  a combination of xmlParserOption
 
15273
 *
 
15274
 * parse an XML from a file descriptor and build a tree.
 
15275
 * NOTE that the file descriptor will not be closed when the
 
15276
 *      reader is closed or reset.
 
15277
 *
 
15278
 * Returns the resulting document tree
 
15279
 */
 
15280
xmlDocPtr
 
15281
xmlReadFd(int fd, const char *URL, const char *encoding, int options)
 
15282
{
 
15283
    xmlParserCtxtPtr ctxt;
 
15284
    xmlParserInputBufferPtr input;
 
15285
    xmlParserInputPtr stream;
 
15286
 
 
15287
    if (fd < 0)
 
15288
        return (NULL);
 
15289
 
 
15290
    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
 
15291
    if (input == NULL)
 
15292
        return (NULL);
 
15293
    input->closecallback = NULL;
 
15294
    ctxt = xmlNewParserCtxt();
 
15295
    if (ctxt == NULL) {
 
15296
        xmlFreeParserInputBuffer(input);
 
15297
        return (NULL);
 
15298
    }
 
15299
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
 
15300
    if (stream == NULL) {
 
15301
        xmlFreeParserInputBuffer(input);
 
15302
        xmlFreeParserCtxt(ctxt);
 
15303
        return (NULL);
 
15304
    }
 
15305
    inputPush(ctxt, stream);
 
15306
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
 
15307
}
 
15308
 
 
15309
/**
 
15310
 * xmlReadIO:
 
15311
 * @ioread:  an I/O read function
 
15312
 * @ioclose:  an I/O close function
 
15313
 * @ioctx:  an I/O handler
 
15314
 * @URL:  the base URL to use for the document
 
15315
 * @encoding:  the document encoding, or NULL
 
15316
 * @options:  a combination of xmlParserOption
 
15317
 *
 
15318
 * parse an XML document from I/O functions and source and build a tree.
 
15319
 *
 
15320
 * Returns the resulting document tree
 
15321
 */
 
15322
xmlDocPtr
 
15323
xmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
 
15324
          void *ioctx, const char *URL, const char *encoding, int options)
 
15325
{
 
15326
    xmlParserCtxtPtr ctxt;
 
15327
    xmlParserInputBufferPtr input;
 
15328
    xmlParserInputPtr stream;
 
15329
 
 
15330
    if (ioread == NULL)
 
15331
        return (NULL);
 
15332
 
 
15333
    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
 
15334
                                         XML_CHAR_ENCODING_NONE);
 
15335
    if (input == NULL) {
 
15336
        if (ioclose != NULL)
 
15337
            ioclose(ioctx);
 
15338
        return (NULL);
 
15339
    }
 
15340
    ctxt = xmlNewParserCtxt();
 
15341
    if (ctxt == NULL) {
 
15342
        xmlFreeParserInputBuffer(input);
 
15343
        return (NULL);
 
15344
    }
 
15345
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
 
15346
    if (stream == NULL) {
 
15347
        xmlFreeParserInputBuffer(input);
 
15348
        xmlFreeParserCtxt(ctxt);
 
15349
        return (NULL);
 
15350
    }
 
15351
    inputPush(ctxt, stream);
 
15352
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
 
15353
}
 
15354
 
 
15355
/**
 
15356
 * xmlCtxtReadDoc:
 
15357
 * @ctxt:  an XML parser context
 
15358
 * @cur:  a pointer to a zero terminated string
 
15359
 * @URL:  the base URL to use for the document
 
15360
 * @encoding:  the document encoding, or NULL
 
15361
 * @options:  a combination of xmlParserOption
 
15362
 *
 
15363
 * parse an XML in-memory document and build a tree.
 
15364
 * This reuses the existing @ctxt parser context
 
15365
 *
 
15366
 * Returns the resulting document tree
 
15367
 */
 
15368
xmlDocPtr
 
15369
xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar * cur,
 
15370
               const char *URL, const char *encoding, int options)
 
15371
{
 
15372
    xmlParserInputPtr stream;
 
15373
 
 
15374
    if (cur == NULL)
 
15375
        return (NULL);
 
15376
    if (ctxt == NULL)
 
15377
        return (NULL);
 
15378
 
 
15379
    xmlCtxtReset(ctxt);
 
15380
 
 
15381
    stream = xmlNewStringInputStream(ctxt, cur);
 
15382
    if (stream == NULL) {
 
15383
        return (NULL);
 
15384
    }
 
15385
    inputPush(ctxt, stream);
 
15386
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
 
15387
}
 
15388
 
 
15389
/**
 
15390
 * xmlCtxtReadFile:
 
15391
 * @ctxt:  an XML parser context
 
15392
 * @filename:  a file or URL
 
15393
 * @encoding:  the document encoding, or NULL
 
15394
 * @options:  a combination of xmlParserOption
 
15395
 *
 
15396
 * parse an XML file from the filesystem or the network.
 
15397
 * This reuses the existing @ctxt parser context
 
15398
 *
 
15399
 * Returns the resulting document tree
 
15400
 */
 
15401
xmlDocPtr
 
15402
xmlCtxtReadFile(xmlParserCtxtPtr ctxt, const char *filename,
 
15403
                const char *encoding, int options)
 
15404
{
 
15405
    xmlParserInputPtr stream;
 
15406
 
 
15407
    if (filename == NULL)
 
15408
        return (NULL);
 
15409
    if (ctxt == NULL)
 
15410
        return (NULL);
 
15411
 
 
15412
    xmlCtxtReset(ctxt);
 
15413
 
 
15414
    stream = xmlLoadExternalEntity(filename, NULL, ctxt);
 
15415
    if (stream == NULL) {
 
15416
        return (NULL);
 
15417
    }
 
15418
    inputPush(ctxt, stream);
 
15419
    return (xmlDoRead(ctxt, NULL, encoding, options, 1));
 
15420
}
 
15421
 
 
15422
/**
 
15423
 * xmlCtxtReadMemory:
 
15424
 * @ctxt:  an XML parser context
 
15425
 * @buffer:  a pointer to a char array
 
15426
 * @size:  the size of the array
 
15427
 * @URL:  the base URL to use for the document
 
15428
 * @encoding:  the document encoding, or NULL
 
15429
 * @options:  a combination of xmlParserOption
 
15430
 *
 
15431
 * parse an XML in-memory document and build a tree.
 
15432
 * This reuses the existing @ctxt parser context
 
15433
 *
 
15434
 * Returns the resulting document tree
 
15435
 */
 
15436
xmlDocPtr
 
15437
xmlCtxtReadMemory(xmlParserCtxtPtr ctxt, const char *buffer, int size,
 
15438
                  const char *URL, const char *encoding, int options)
 
15439
{
 
15440
    xmlParserInputBufferPtr input;
 
15441
    xmlParserInputPtr stream;
 
15442
 
 
15443
    if (ctxt == NULL)
 
15444
        return (NULL);
 
15445
    if (buffer == NULL)
 
15446
        return (NULL);
 
15447
 
 
15448
    xmlCtxtReset(ctxt);
 
15449
 
 
15450
    input = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
 
15451
    if (input == NULL) {
 
15452
        return(NULL);
 
15453
    }
 
15454
 
 
15455
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
 
15456
    if (stream == NULL) {
 
15457
        xmlFreeParserInputBuffer(input);
 
15458
        return(NULL);
 
15459
    }
 
15460
 
 
15461
    inputPush(ctxt, stream);
 
15462
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
 
15463
}
 
15464
 
 
15465
/**
 
15466
 * xmlCtxtReadFd:
 
15467
 * @ctxt:  an XML parser context
 
15468
 * @fd:  an open file descriptor
 
15469
 * @URL:  the base URL to use for the document
 
15470
 * @encoding:  the document encoding, or NULL
 
15471
 * @options:  a combination of xmlParserOption
 
15472
 *
 
15473
 * parse an XML from a file descriptor and build a tree.
 
15474
 * This reuses the existing @ctxt parser context
 
15475
 * NOTE that the file descriptor will not be closed when the
 
15476
 *      reader is closed or reset.
 
15477
 *
 
15478
 * Returns the resulting document tree
 
15479
 */
 
15480
xmlDocPtr
 
15481
xmlCtxtReadFd(xmlParserCtxtPtr ctxt, int fd,
 
15482
              const char *URL, const char *encoding, int options)
 
15483
{
 
15484
    xmlParserInputBufferPtr input;
 
15485
    xmlParserInputPtr stream;
 
15486
 
 
15487
    if (fd < 0)
 
15488
        return (NULL);
 
15489
    if (ctxt == NULL)
 
15490
        return (NULL);
 
15491
 
 
15492
    xmlCtxtReset(ctxt);
 
15493
 
 
15494
 
 
15495
    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
 
15496
    if (input == NULL)
 
15497
        return (NULL);
 
15498
    input->closecallback = NULL;
 
15499
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
 
15500
    if (stream == NULL) {
 
15501
        xmlFreeParserInputBuffer(input);
 
15502
        return (NULL);
 
15503
    }
 
15504
    inputPush(ctxt, stream);
 
15505
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
 
15506
}
 
15507
 
 
15508
/**
 
15509
 * xmlCtxtReadIO:
 
15510
 * @ctxt:  an XML parser context
 
15511
 * @ioread:  an I/O read function
 
15512
 * @ioclose:  an I/O close function
 
15513
 * @ioctx:  an I/O handler
 
15514
 * @URL:  the base URL to use for the document
 
15515
 * @encoding:  the document encoding, or NULL
 
15516
 * @options:  a combination of xmlParserOption
 
15517
 *
 
15518
 * parse an XML document from I/O functions and source and build a tree.
 
15519
 * This reuses the existing @ctxt parser context
 
15520
 *
 
15521
 * Returns the resulting document tree
 
15522
 */
 
15523
xmlDocPtr
 
15524
xmlCtxtReadIO(xmlParserCtxtPtr ctxt, xmlInputReadCallback ioread,
 
15525
              xmlInputCloseCallback ioclose, void *ioctx,
 
15526
              const char *URL,
 
15527
              const char *encoding, int options)
 
15528
{
 
15529
    xmlParserInputBufferPtr input;
 
15530
    xmlParserInputPtr stream;
 
15531
 
 
15532
    if (ioread == NULL)
 
15533
        return (NULL);
 
15534
    if (ctxt == NULL)
 
15535
        return (NULL);
 
15536
 
 
15537
    xmlCtxtReset(ctxt);
 
15538
 
 
15539
    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
 
15540
                                         XML_CHAR_ENCODING_NONE);
 
15541
    if (input == NULL) {
 
15542
        if (ioclose != NULL)
 
15543
            ioclose(ioctx);
 
15544
        return (NULL);
 
15545
    }
 
15546
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
 
15547
    if (stream == NULL) {
 
15548
        xmlFreeParserInputBuffer(input);
 
15549
        return (NULL);
 
15550
    }
 
15551
    inputPush(ctxt, stream);
 
15552
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
 
15553
}
 
15554
 
 
15555
#define bottom_parser
 
15556
#include "elfgcchack.h"