~ubuntu-branches/ubuntu/trusty/libxml2/trusty-updates

« back to all changes in this revision

Viewing changes to .pc/CVE-2014-3660.patch/parser.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2014-10-16 15:30:49 UTC
  • Revision ID: package-import@ubuntu.com-20141016153049-vzdgn4o9sfee23pb
Tags: 2.9.1+dfsg1-3ubuntu4.4
* SECURITY UPDATE: denial of service via entity expansion
  - debian/patches/CVE-2014-3660.patch: added additional tests to
    parser.c.
  - CVE-2014-3660

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
                     * Note: external parameter entities will not be loaded, it
 
2599
                     * is not required for a non-validating parser, unless the
 
2600
                     * option of validating, or substituting entities were
 
2601
                     * given. Doing so is far more secure as the parser will
 
2602
                     * only process data coming from the document entity by
 
2603
                     * default.
 
2604
                     */
 
2605
                    if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
 
2606
                        ((ctxt->options & XML_PARSE_NOENT) == 0) &&
 
2607
                        ((ctxt->options & XML_PARSE_DTDVALID) == 0) &&
 
2608
                        ((ctxt->options & XML_PARSE_DTDLOAD) == 0) &&
 
2609
                        ((ctxt->options & XML_PARSE_DTDATTR) == 0) &&
 
2610
                        (ctxt->replaceEntities == 0) &&
 
2611
                        (ctxt->validate == 0))
 
2612
                        return;
 
2613
 
 
2614
                    /*
 
2615
                     * handle the extra spaces added before and after
 
2616
                     * c.f. http://www.w3.org/TR/REC-xml#as-PE
 
2617
                     * this is done independently.
 
2618
                     */
 
2619
                    input = xmlNewEntityInputStream(ctxt, entity);
 
2620
                    if (xmlPushInput(ctxt, input) < 0)
 
2621
                        return;
 
2622
 
 
2623
                    /*
 
2624
                     * Get the 4 first bytes and decode the charset
 
2625
                     * if enc != XML_CHAR_ENCODING_NONE
 
2626
                     * plug some encoding conversion routines.
 
2627
                     * Note that, since we may have some non-UTF8
 
2628
                     * encoding (like UTF16, bug 135229), the 'length'
 
2629
                     * is not known, but we can calculate based upon
 
2630
                     * the amount of data in the buffer.
 
2631
                     */
 
2632
                    GROW
 
2633
                    if (ctxt->instate == XML_PARSER_EOF)
 
2634
                        return;
 
2635
                    if ((ctxt->input->end - ctxt->input->cur)>=4) {
 
2636
                        start[0] = RAW;
 
2637
                        start[1] = NXT(1);
 
2638
                        start[2] = NXT(2);
 
2639
                        start[3] = NXT(3);
 
2640
                        enc = xmlDetectCharEncoding(start, 4);
 
2641
                        if (enc != XML_CHAR_ENCODING_NONE) {
 
2642
                            xmlSwitchEncoding(ctxt, enc);
 
2643
                        }
 
2644
                    }
 
2645
 
 
2646
                    if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
 
2647
                        (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l' )) &&
 
2648
                        (IS_BLANK_CH(NXT(5)))) {
 
2649
                        xmlParseTextDecl(ctxt);
 
2650
                    }
 
2651
                } else {
 
2652
                    xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
 
2653
                             "PEReference: %s is not a parameter entity\n",
 
2654
                                      name);
 
2655
                }
 
2656
            }
 
2657
        } else {
 
2658
            xmlFatalErr(ctxt, XML_ERR_PEREF_SEMICOL_MISSING, NULL);
 
2659
        }
 
2660
    }
 
2661
}
 
2662
 
 
2663
/*
 
2664
 * Macro used to grow the current buffer.
 
2665
 * buffer##_size is expected to be a size_t
 
2666
 * mem_error: is expected to handle memory allocation failures
 
2667
 */
 
2668
#define growBuffer(buffer, n) {                                         \
 
2669
    xmlChar *tmp;                                                       \
 
2670
    size_t new_size = buffer##_size * 2 + n;                            \
 
2671
    if (new_size < buffer##_size) goto mem_error;                       \
 
2672
    tmp = (xmlChar *) xmlRealloc(buffer, new_size);                     \
 
2673
    if (tmp == NULL) goto mem_error;                                    \
 
2674
    buffer = tmp;                                                       \
 
2675
    buffer##_size = new_size;                                           \
 
2676
}
 
2677
 
 
2678
/**
 
2679
 * xmlStringLenDecodeEntities:
 
2680
 * @ctxt:  the parser context
 
2681
 * @str:  the input string
 
2682
 * @len: the string length
 
2683
 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
 
2684
 * @end:  an end marker xmlChar, 0 if none
 
2685
 * @end2:  an end marker xmlChar, 0 if none
 
2686
 * @end3:  an end marker xmlChar, 0 if none
 
2687
 *
 
2688
 * Takes a entity string content and process to do the adequate substitutions.
 
2689
 *
 
2690
 * [67] Reference ::= EntityRef | CharRef
 
2691
 *
 
2692
 * [69] PEReference ::= '%' Name ';'
 
2693
 *
 
2694
 * Returns A newly allocated string with the substitution done. The caller
 
2695
 *      must deallocate it !
 
2696
 */
 
2697
xmlChar *
 
2698
xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
 
2699
                      int what, xmlChar end, xmlChar  end2, xmlChar end3) {
 
2700
    xmlChar *buffer = NULL;
 
2701
    size_t buffer_size = 0;
 
2702
    size_t nbchars = 0;
 
2703
 
 
2704
    xmlChar *current = NULL;
 
2705
    xmlChar *rep = NULL;
 
2706
    const xmlChar *last;
 
2707
    xmlEntityPtr ent;
 
2708
    int c,l;
 
2709
 
 
2710
    if ((ctxt == NULL) || (str == NULL) || (len < 0))
 
2711
        return(NULL);
 
2712
    last = str + len;
 
2713
 
 
2714
    if (((ctxt->depth > 40) &&
 
2715
         ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
 
2716
        (ctxt->depth > 1024)) {
 
2717
        xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
 
2718
        return(NULL);
 
2719
    }
 
2720
 
 
2721
    /*
 
2722
     * allocate a translation buffer.
 
2723
     */
 
2724
    buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
 
2725
    buffer = (xmlChar *) xmlMallocAtomic(buffer_size);
 
2726
    if (buffer == NULL) goto mem_error;
 
2727
 
 
2728
    /*
 
2729
     * OK loop until we reach one of the ending char or a size limit.
 
2730
     * we are operating on already parsed values.
 
2731
     */
 
2732
    if (str < last)
 
2733
        c = CUR_SCHAR(str, l);
 
2734
    else
 
2735
        c = 0;
 
2736
    while ((c != 0) && (c != end) && /* non input consuming loop */
 
2737
           (c != end2) && (c != end3)) {
 
2738
 
 
2739
        if (c == 0) break;
 
2740
        if ((c == '&') && (str[1] == '#')) {
 
2741
            int val = xmlParseStringCharRef(ctxt, &str);
 
2742
            if (val != 0) {
 
2743
                COPY_BUF(0,buffer,nbchars,val);
 
2744
            }
 
2745
            if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
 
2746
                growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
 
2747
            }
 
2748
        } else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) {
 
2749
            if (xmlParserDebugEntities)
 
2750
                xmlGenericError(xmlGenericErrorContext,
 
2751
                        "String decoding Entity Reference: %.30s\n",
 
2752
                        str);
 
2753
            ent = xmlParseStringEntityRef(ctxt, &str);
 
2754
            if ((ctxt->lastError.code == XML_ERR_ENTITY_LOOP) ||
 
2755
                (ctxt->lastError.code == XML_ERR_INTERNAL_ERROR))
 
2756
                goto int_error;
 
2757
            if (ent != NULL)
 
2758
                ctxt->nbentities += ent->checked / 2;
 
2759
            if ((ent != NULL) &&
 
2760
                (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
 
2761
                if (ent->content != NULL) {
 
2762
                    COPY_BUF(0,buffer,nbchars,ent->content[0]);
 
2763
                    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
 
2764
                        growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
 
2765
                    }
 
2766
                } else {
 
2767
                    xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
 
2768
                            "predefined entity has no content\n");
 
2769
                }
 
2770
            } else if ((ent != NULL) && (ent->content != NULL)) {
 
2771
                ctxt->depth++;
 
2772
                rep = xmlStringDecodeEntities(ctxt, ent->content, what,
 
2773
                                              0, 0, 0);
 
2774
                ctxt->depth--;
 
2775
 
 
2776
                if (rep != NULL) {
 
2777
                    current = rep;
 
2778
                    while (*current != 0) { /* non input consuming loop */
 
2779
                        buffer[nbchars++] = *current++;
 
2780
                        if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
 
2781
                            if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
 
2782
                                goto int_error;
 
2783
                            growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
 
2784
                        }
 
2785
                    }
 
2786
                    xmlFree(rep);
 
2787
                    rep = NULL;
 
2788
                }
 
2789
            } else if (ent != NULL) {
 
2790
                int i = xmlStrlen(ent->name);
 
2791
                const xmlChar *cur = ent->name;
 
2792
 
 
2793
                buffer[nbchars++] = '&';
 
2794
                if (nbchars + i + XML_PARSER_BUFFER_SIZE > buffer_size) {
 
2795
                    growBuffer(buffer, i + XML_PARSER_BUFFER_SIZE);
 
2796
                }
 
2797
                for (;i > 0;i--)
 
2798
                    buffer[nbchars++] = *cur++;
 
2799
                buffer[nbchars++] = ';';
 
2800
            }
 
2801
        } else if (c == '%' && (what & XML_SUBSTITUTE_PEREF)) {
 
2802
            if (xmlParserDebugEntities)
 
2803
                xmlGenericError(xmlGenericErrorContext,
 
2804
                        "String decoding PE Reference: %.30s\n", str);
 
2805
            ent = xmlParseStringPEReference(ctxt, &str);
 
2806
            if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
 
2807
                goto int_error;
 
2808
            if (ent != NULL)
 
2809
                ctxt->nbentities += ent->checked / 2;
 
2810
            if (ent != NULL) {
 
2811
                if (ent->content == NULL) {
 
2812
                    xmlLoadEntityContent(ctxt, ent);
 
2813
                }
 
2814
                ctxt->depth++;
 
2815
                rep = xmlStringDecodeEntities(ctxt, ent->content, what,
 
2816
                                              0, 0, 0);
 
2817
                ctxt->depth--;
 
2818
                if (rep != NULL) {
 
2819
                    current = rep;
 
2820
                    while (*current != 0) { /* non input consuming loop */
 
2821
                        buffer[nbchars++] = *current++;
 
2822
                        if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
 
2823
                            if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
 
2824
                                goto int_error;
 
2825
                            growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
 
2826
                        }
 
2827
                    }
 
2828
                    xmlFree(rep);
 
2829
                    rep = NULL;
 
2830
                }
 
2831
            }
 
2832
        } else {
 
2833
            COPY_BUF(l,buffer,nbchars,c);
 
2834
            str += l;
 
2835
            if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
 
2836
                growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
 
2837
            }
 
2838
        }
 
2839
        if (str < last)
 
2840
            c = CUR_SCHAR(str, l);
 
2841
        else
 
2842
            c = 0;
 
2843
    }
 
2844
    buffer[nbchars] = 0;
 
2845
    return(buffer);
 
2846
 
 
2847
mem_error:
 
2848
    xmlErrMemory(ctxt, NULL);
 
2849
int_error:
 
2850
    if (rep != NULL)
 
2851
        xmlFree(rep);
 
2852
    if (buffer != NULL)
 
2853
        xmlFree(buffer);
 
2854
    return(NULL);
 
2855
}
 
2856
 
 
2857
/**
 
2858
 * xmlStringDecodeEntities:
 
2859
 * @ctxt:  the parser context
 
2860
 * @str:  the input string
 
2861
 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
 
2862
 * @end:  an end marker xmlChar, 0 if none
 
2863
 * @end2:  an end marker xmlChar, 0 if none
 
2864
 * @end3:  an end marker xmlChar, 0 if none
 
2865
 *
 
2866
 * Takes a entity string content and process to do the adequate substitutions.
 
2867
 *
 
2868
 * [67] Reference ::= EntityRef | CharRef
 
2869
 *
 
2870
 * [69] PEReference ::= '%' Name ';'
 
2871
 *
 
2872
 * Returns A newly allocated string with the substitution done. The caller
 
2873
 *      must deallocate it !
 
2874
 */
 
2875
xmlChar *
 
2876
xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what,
 
2877
                        xmlChar end, xmlChar  end2, xmlChar end3) {
 
2878
    if ((ctxt == NULL) || (str == NULL)) return(NULL);
 
2879
    return(xmlStringLenDecodeEntities(ctxt, str, xmlStrlen(str), what,
 
2880
           end, end2, end3));
 
2881
}
 
2882
 
 
2883
/************************************************************************
 
2884
 *                                                                      *
 
2885
 *              Commodity functions, cleanup needed ?                   *
 
2886
 *                                                                      *
 
2887
 ************************************************************************/
 
2888
 
 
2889
/**
 
2890
 * areBlanks:
 
2891
 * @ctxt:  an XML parser context
 
2892
 * @str:  a xmlChar *
 
2893
 * @len:  the size of @str
 
2894
 * @blank_chars: we know the chars are blanks
 
2895
 *
 
2896
 * Is this a sequence of blank chars that one can ignore ?
 
2897
 *
 
2898
 * Returns 1 if ignorable 0 otherwise.
 
2899
 */
 
2900
 
 
2901
static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
 
2902
                     int blank_chars) {
 
2903
    int i, ret;
 
2904
    xmlNodePtr lastChild;
 
2905
 
 
2906
    /*
 
2907
     * Don't spend time trying to differentiate them, the same callback is
 
2908
     * used !
 
2909
     */
 
2910
    if (ctxt->sax->ignorableWhitespace == ctxt->sax->characters)
 
2911
        return(0);
 
2912
 
 
2913
    /*
 
2914
     * Check for xml:space value.
 
2915
     */
 
2916
    if ((ctxt->space == NULL) || (*(ctxt->space) == 1) ||
 
2917
        (*(ctxt->space) == -2))
 
2918
        return(0);
 
2919
 
 
2920
    /*
 
2921
     * Check that the string is made of blanks
 
2922
     */
 
2923
    if (blank_chars == 0) {
 
2924
        for (i = 0;i < len;i++)
 
2925
            if (!(IS_BLANK_CH(str[i]))) return(0);
 
2926
    }
 
2927
 
 
2928
    /*
 
2929
     * Look if the element is mixed content in the DTD if available
 
2930
     */
 
2931
    if (ctxt->node == NULL) return(0);
 
2932
    if (ctxt->myDoc != NULL) {
 
2933
        ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name);
 
2934
        if (ret == 0) return(1);
 
2935
        if (ret == 1) return(0);
 
2936
    }
 
2937
 
 
2938
    /*
 
2939
     * Otherwise, heuristic :-\
 
2940
     */
 
2941
    if ((RAW != '<') && (RAW != 0xD)) return(0);
 
2942
    if ((ctxt->node->children == NULL) &&
 
2943
        (RAW == '<') && (NXT(1) == '/')) return(0);
 
2944
 
 
2945
    lastChild = xmlGetLastChild(ctxt->node);
 
2946
    if (lastChild == NULL) {
 
2947
        if ((ctxt->node->type != XML_ELEMENT_NODE) &&
 
2948
            (ctxt->node->content != NULL)) return(0);
 
2949
    } else if (xmlNodeIsText(lastChild))
 
2950
        return(0);
 
2951
    else if ((ctxt->node->children != NULL) &&
 
2952
             (xmlNodeIsText(ctxt->node->children)))
 
2953
        return(0);
 
2954
    return(1);
 
2955
}
 
2956
 
 
2957
/************************************************************************
 
2958
 *                                                                      *
 
2959
 *              Extra stuff for namespace support                       *
 
2960
 *      Relates to http://www.w3.org/TR/WD-xml-names                    *
 
2961
 *                                                                      *
 
2962
 ************************************************************************/
 
2963
 
 
2964
/**
 
2965
 * xmlSplitQName:
 
2966
 * @ctxt:  an XML parser context
 
2967
 * @name:  an XML parser context
 
2968
 * @prefix:  a xmlChar **
 
2969
 *
 
2970
 * parse an UTF8 encoded XML qualified name string
 
2971
 *
 
2972
 * [NS 5] QName ::= (Prefix ':')? LocalPart
 
2973
 *
 
2974
 * [NS 6] Prefix ::= NCName
 
2975
 *
 
2976
 * [NS 7] LocalPart ::= NCName
 
2977
 *
 
2978
 * Returns the local part, and prefix is updated
 
2979
 *   to get the Prefix if any.
 
2980
 */
 
2981
 
 
2982
xmlChar *
 
2983
xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
 
2984
    xmlChar buf[XML_MAX_NAMELEN + 5];
 
2985
    xmlChar *buffer = NULL;
 
2986
    int len = 0;
 
2987
    int max = XML_MAX_NAMELEN;
 
2988
    xmlChar *ret = NULL;
 
2989
    const xmlChar *cur = name;
 
2990
    int c;
 
2991
 
 
2992
    if (prefix == NULL) return(NULL);
 
2993
    *prefix = NULL;
 
2994
 
 
2995
    if (cur == NULL) return(NULL);
 
2996
 
 
2997
#ifndef XML_XML_NAMESPACE
 
2998
    /* xml: prefix is not really a namespace */
 
2999
    if ((cur[0] == 'x') && (cur[1] == 'm') &&
 
3000
        (cur[2] == 'l') && (cur[3] == ':'))
 
3001
        return(xmlStrdup(name));
 
3002
#endif
 
3003
 
 
3004
    /* nasty but well=formed */
 
3005
    if (cur[0] == ':')
 
3006
        return(xmlStrdup(name));
 
3007
 
 
3008
    c = *cur++;
 
3009
    while ((c != 0) && (c != ':') && (len < max)) { /* tested bigname.xml */
 
3010
        buf[len++] = c;
 
3011
        c = *cur++;
 
3012
    }
 
3013
    if (len >= max) {
 
3014
        /*
 
3015
         * Okay someone managed to make a huge name, so he's ready to pay
 
3016
         * for the processing speed.
 
3017
         */
 
3018
        max = len * 2;
 
3019
 
 
3020
        buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
 
3021
        if (buffer == NULL) {
 
3022
            xmlErrMemory(ctxt, NULL);
 
3023
            return(NULL);
 
3024
        }
 
3025
        memcpy(buffer, buf, len);
 
3026
        while ((c != 0) && (c != ':')) { /* tested bigname.xml */
 
3027
            if (len + 10 > max) {
 
3028
                xmlChar *tmp;
 
3029
 
 
3030
                max *= 2;
 
3031
                tmp = (xmlChar *) xmlRealloc(buffer,
 
3032
                                                max * sizeof(xmlChar));
 
3033
                if (tmp == NULL) {
 
3034
                    xmlFree(buffer);
 
3035
                    xmlErrMemory(ctxt, NULL);
 
3036
                    return(NULL);
 
3037
                }
 
3038
                buffer = tmp;
 
3039
            }
 
3040
            buffer[len++] = c;
 
3041
            c = *cur++;
 
3042
        }
 
3043
        buffer[len] = 0;
 
3044
    }
 
3045
 
 
3046
    if ((c == ':') && (*cur == 0)) {
 
3047
        if (buffer != NULL)
 
3048
            xmlFree(buffer);
 
3049
        *prefix = NULL;
 
3050
        return(xmlStrdup(name));
 
3051
    }
 
3052
 
 
3053
    if (buffer == NULL)
 
3054
        ret = xmlStrndup(buf, len);
 
3055
    else {
 
3056
        ret = buffer;
 
3057
        buffer = NULL;
 
3058
        max = XML_MAX_NAMELEN;
 
3059
    }
 
3060
 
 
3061
 
 
3062
    if (c == ':') {
 
3063
        c = *cur;
 
3064
        *prefix = ret;
 
3065
        if (c == 0) {
 
3066
            return(xmlStrndup(BAD_CAST "", 0));
 
3067
        }
 
3068
        len = 0;
 
3069
 
 
3070
        /*
 
3071
         * Check that the first character is proper to start
 
3072
         * a new name
 
3073
         */
 
3074
        if (!(((c >= 0x61) && (c <= 0x7A)) ||
 
3075
              ((c >= 0x41) && (c <= 0x5A)) ||
 
3076
              (c == '_') || (c == ':'))) {
 
3077
            int l;
 
3078
            int first = CUR_SCHAR(cur, l);
 
3079
 
 
3080
            if (!IS_LETTER(first) && (first != '_')) {
 
3081
                xmlFatalErrMsgStr(ctxt, XML_NS_ERR_QNAME,
 
3082
                            "Name %s is not XML Namespace compliant\n",
 
3083
                                  name);
 
3084
            }
 
3085
        }
 
3086
        cur++;
 
3087
 
 
3088
        while ((c != 0) && (len < max)) { /* tested bigname2.xml */
 
3089
            buf[len++] = c;
 
3090
            c = *cur++;
 
3091
        }
 
3092
        if (len >= max) {
 
3093
            /*
 
3094
             * Okay someone managed to make a huge name, so he's ready to pay
 
3095
             * for the processing speed.
 
3096
             */
 
3097
            max = len * 2;
 
3098
 
 
3099
            buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
 
3100
            if (buffer == NULL) {
 
3101
                xmlErrMemory(ctxt, NULL);
 
3102
                return(NULL);
 
3103
            }
 
3104
            memcpy(buffer, buf, len);
 
3105
            while (c != 0) { /* tested bigname2.xml */
 
3106
                if (len + 10 > max) {
 
3107
                    xmlChar *tmp;
 
3108
 
 
3109
                    max *= 2;
 
3110
                    tmp = (xmlChar *) xmlRealloc(buffer,
 
3111
                                                    max * sizeof(xmlChar));
 
3112
                    if (tmp == NULL) {
 
3113
                        xmlErrMemory(ctxt, NULL);
 
3114
                        xmlFree(buffer);
 
3115
                        return(NULL);
 
3116
                    }
 
3117
                    buffer = tmp;
 
3118
                }
 
3119
                buffer[len++] = c;
 
3120
                c = *cur++;
 
3121
            }
 
3122
            buffer[len] = 0;
 
3123
        }
 
3124
 
 
3125
        if (buffer == NULL)
 
3126
            ret = xmlStrndup(buf, len);
 
3127
        else {
 
3128
            ret = buffer;
 
3129
        }
 
3130
    }
 
3131
 
 
3132
    return(ret);
 
3133
}
 
3134
 
 
3135
/************************************************************************
 
3136
 *                                                                      *
 
3137
 *                      The parser itself                               *
 
3138
 *      Relates to http://www.w3.org/TR/REC-xml                         *
 
3139
 *                                                                      *
 
3140
 ************************************************************************/
 
3141
 
 
3142
/************************************************************************
 
3143
 *                                                                      *
 
3144
 *      Routines to parse Name, NCName and NmToken                      *
 
3145
 *                                                                      *
 
3146
 ************************************************************************/
 
3147
#ifdef DEBUG
 
3148
static unsigned long nbParseName = 0;
 
3149
static unsigned long nbParseNmToken = 0;
 
3150
static unsigned long nbParseNCName = 0;
 
3151
static unsigned long nbParseNCNameComplex = 0;
 
3152
static unsigned long nbParseNameComplex = 0;
 
3153
static unsigned long nbParseStringName = 0;
 
3154
#endif
 
3155
 
 
3156
/*
 
3157
 * The two following functions are related to the change of accepted
 
3158
 * characters for Name and NmToken in the Revision 5 of XML-1.0
 
3159
 * They correspond to the modified production [4] and the new production [4a]
 
3160
 * changes in that revision. Also note that the macros used for the
 
3161
 * productions Letter, Digit, CombiningChar and Extender are not needed
 
3162
 * anymore.
 
3163
 * We still keep compatibility to pre-revision5 parsing semantic if the
 
3164
 * new XML_PARSE_OLD10 option is given to the parser.
 
3165
 */
 
3166
static int
 
3167
xmlIsNameStartChar(xmlParserCtxtPtr ctxt, int c) {
 
3168
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
 
3169
        /*
 
3170
         * Use the new checks of production [4] [4a] amd [5] of the
 
3171
         * Update 5 of XML-1.0
 
3172
         */
 
3173
        if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
 
3174
            (((c >= 'a') && (c <= 'z')) ||
 
3175
             ((c >= 'A') && (c <= 'Z')) ||
 
3176
             (c == '_') || (c == ':') ||
 
3177
             ((c >= 0xC0) && (c <= 0xD6)) ||
 
3178
             ((c >= 0xD8) && (c <= 0xF6)) ||
 
3179
             ((c >= 0xF8) && (c <= 0x2FF)) ||
 
3180
             ((c >= 0x370) && (c <= 0x37D)) ||
 
3181
             ((c >= 0x37F) && (c <= 0x1FFF)) ||
 
3182
             ((c >= 0x200C) && (c <= 0x200D)) ||
 
3183
             ((c >= 0x2070) && (c <= 0x218F)) ||
 
3184
             ((c >= 0x2C00) && (c <= 0x2FEF)) ||
 
3185
             ((c >= 0x3001) && (c <= 0xD7FF)) ||
 
3186
             ((c >= 0xF900) && (c <= 0xFDCF)) ||
 
3187
             ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
 
3188
             ((c >= 0x10000) && (c <= 0xEFFFF))))
 
3189
            return(1);
 
3190
    } else {
 
3191
        if (IS_LETTER(c) || (c == '_') || (c == ':'))
 
3192
            return(1);
 
3193
    }
 
3194
    return(0);
 
3195
}
 
3196
 
 
3197
static int
 
3198
xmlIsNameChar(xmlParserCtxtPtr ctxt, int c) {
 
3199
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
 
3200
        /*
 
3201
         * Use the new checks of production [4] [4a] amd [5] of the
 
3202
         * Update 5 of XML-1.0
 
3203
         */
 
3204
        if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
 
3205
            (((c >= 'a') && (c <= 'z')) ||
 
3206
             ((c >= 'A') && (c <= 'Z')) ||
 
3207
             ((c >= '0') && (c <= '9')) || /* !start */
 
3208
             (c == '_') || (c == ':') ||
 
3209
             (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
 
3210
             ((c >= 0xC0) && (c <= 0xD6)) ||
 
3211
             ((c >= 0xD8) && (c <= 0xF6)) ||
 
3212
             ((c >= 0xF8) && (c <= 0x2FF)) ||
 
3213
             ((c >= 0x300) && (c <= 0x36F)) || /* !start */
 
3214
             ((c >= 0x370) && (c <= 0x37D)) ||
 
3215
             ((c >= 0x37F) && (c <= 0x1FFF)) ||
 
3216
             ((c >= 0x200C) && (c <= 0x200D)) ||
 
3217
             ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
 
3218
             ((c >= 0x2070) && (c <= 0x218F)) ||
 
3219
             ((c >= 0x2C00) && (c <= 0x2FEF)) ||
 
3220
             ((c >= 0x3001) && (c <= 0xD7FF)) ||
 
3221
             ((c >= 0xF900) && (c <= 0xFDCF)) ||
 
3222
             ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
 
3223
             ((c >= 0x10000) && (c <= 0xEFFFF))))
 
3224
             return(1);
 
3225
    } else {
 
3226
        if ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
 
3227
            (c == '.') || (c == '-') ||
 
3228
            (c == '_') || (c == ':') ||
 
3229
            (IS_COMBINING(c)) ||
 
3230
            (IS_EXTENDER(c)))
 
3231
            return(1);
 
3232
    }
 
3233
    return(0);
 
3234
}
 
3235
 
 
3236
static xmlChar * xmlParseAttValueInternal(xmlParserCtxtPtr ctxt,
 
3237
                                          int *len, int *alloc, int normalize);
 
3238
 
 
3239
static const xmlChar *
 
3240
xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
 
3241
    int len = 0, l;
 
3242
    int c;
 
3243
    int count = 0;
 
3244
 
 
3245
#ifdef DEBUG
 
3246
    nbParseNameComplex++;
 
3247
#endif
 
3248
 
 
3249
    /*
 
3250
     * Handler for more complex cases
 
3251
     */
 
3252
    GROW;
 
3253
    if (ctxt->instate == XML_PARSER_EOF)
 
3254
        return(NULL);
 
3255
    c = CUR_CHAR(l);
 
3256
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
 
3257
        /*
 
3258
         * Use the new checks of production [4] [4a] amd [5] of the
 
3259
         * Update 5 of XML-1.0
 
3260
         */
 
3261
        if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
 
3262
            (!(((c >= 'a') && (c <= 'z')) ||
 
3263
               ((c >= 'A') && (c <= 'Z')) ||
 
3264
               (c == '_') || (c == ':') ||
 
3265
               ((c >= 0xC0) && (c <= 0xD6)) ||
 
3266
               ((c >= 0xD8) && (c <= 0xF6)) ||
 
3267
               ((c >= 0xF8) && (c <= 0x2FF)) ||
 
3268
               ((c >= 0x370) && (c <= 0x37D)) ||
 
3269
               ((c >= 0x37F) && (c <= 0x1FFF)) ||
 
3270
               ((c >= 0x200C) && (c <= 0x200D)) ||
 
3271
               ((c >= 0x2070) && (c <= 0x218F)) ||
 
3272
               ((c >= 0x2C00) && (c <= 0x2FEF)) ||
 
3273
               ((c >= 0x3001) && (c <= 0xD7FF)) ||
 
3274
               ((c >= 0xF900) && (c <= 0xFDCF)) ||
 
3275
               ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
 
3276
               ((c >= 0x10000) && (c <= 0xEFFFF))))) {
 
3277
            return(NULL);
 
3278
        }
 
3279
        len += l;
 
3280
        NEXTL(l);
 
3281
        c = CUR_CHAR(l);
 
3282
        while ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
 
3283
               (((c >= 'a') && (c <= 'z')) ||
 
3284
                ((c >= 'A') && (c <= 'Z')) ||
 
3285
                ((c >= '0') && (c <= '9')) || /* !start */
 
3286
                (c == '_') || (c == ':') ||
 
3287
                (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
 
3288
                ((c >= 0xC0) && (c <= 0xD6)) ||
 
3289
                ((c >= 0xD8) && (c <= 0xF6)) ||
 
3290
                ((c >= 0xF8) && (c <= 0x2FF)) ||
 
3291
                ((c >= 0x300) && (c <= 0x36F)) || /* !start */
 
3292
                ((c >= 0x370) && (c <= 0x37D)) ||
 
3293
                ((c >= 0x37F) && (c <= 0x1FFF)) ||
 
3294
                ((c >= 0x200C) && (c <= 0x200D)) ||
 
3295
                ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
 
3296
                ((c >= 0x2070) && (c <= 0x218F)) ||
 
3297
                ((c >= 0x2C00) && (c <= 0x2FEF)) ||
 
3298
                ((c >= 0x3001) && (c <= 0xD7FF)) ||
 
3299
                ((c >= 0xF900) && (c <= 0xFDCF)) ||
 
3300
                ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
 
3301
                ((c >= 0x10000) && (c <= 0xEFFFF))
 
3302
                )) {
 
3303
            if (count++ > XML_PARSER_CHUNK_SIZE) {
 
3304
                count = 0;
 
3305
                GROW;
 
3306
                if (ctxt->instate == XML_PARSER_EOF)
 
3307
                    return(NULL);
 
3308
            }
 
3309
            len += l;
 
3310
            NEXTL(l);
 
3311
            c = CUR_CHAR(l);
 
3312
        }
 
3313
    } else {
 
3314
        if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
 
3315
            (!IS_LETTER(c) && (c != '_') &&
 
3316
             (c != ':'))) {
 
3317
            return(NULL);
 
3318
        }
 
3319
        len += l;
 
3320
        NEXTL(l);
 
3321
        c = CUR_CHAR(l);
 
3322
 
 
3323
        while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
 
3324
               ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
 
3325
                (c == '.') || (c == '-') ||
 
3326
                (c == '_') || (c == ':') ||
 
3327
                (IS_COMBINING(c)) ||
 
3328
                (IS_EXTENDER(c)))) {
 
3329
            if (count++ > XML_PARSER_CHUNK_SIZE) {
 
3330
                count = 0;
 
3331
                GROW;
 
3332
                if (ctxt->instate == XML_PARSER_EOF)
 
3333
                    return(NULL);
 
3334
            }
 
3335
            len += l;
 
3336
            NEXTL(l);
 
3337
            c = CUR_CHAR(l);
 
3338
            if (c == 0) {
 
3339
                count = 0;
 
3340
                GROW;
 
3341
                if (ctxt->instate == XML_PARSER_EOF)
 
3342
                    return(NULL);
 
3343
                c = CUR_CHAR(l);
 
3344
            }
 
3345
        }
 
3346
    }
 
3347
    if ((len > XML_MAX_NAME_LENGTH) &&
 
3348
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
3349
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
 
3350
        return(NULL);
 
3351
    }
 
3352
    if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r'))
 
3353
        return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len));
 
3354
    return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
 
3355
}
 
3356
 
 
3357
/**
 
3358
 * xmlParseName:
 
3359
 * @ctxt:  an XML parser context
 
3360
 *
 
3361
 * parse an XML name.
 
3362
 *
 
3363
 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
 
3364
 *                  CombiningChar | Extender
 
3365
 *
 
3366
 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
 
3367
 *
 
3368
 * [6] Names ::= Name (#x20 Name)*
 
3369
 *
 
3370
 * Returns the Name parsed or NULL
 
3371
 */
 
3372
 
 
3373
const xmlChar *
 
3374
xmlParseName(xmlParserCtxtPtr ctxt) {
 
3375
    const xmlChar *in;
 
3376
    const xmlChar *ret;
 
3377
    int count = 0;
 
3378
 
 
3379
    GROW;
 
3380
 
 
3381
#ifdef DEBUG
 
3382
    nbParseName++;
 
3383
#endif
 
3384
 
 
3385
    /*
 
3386
     * Accelerator for simple ASCII names
 
3387
     */
 
3388
    in = ctxt->input->cur;
 
3389
    if (((*in >= 0x61) && (*in <= 0x7A)) ||
 
3390
        ((*in >= 0x41) && (*in <= 0x5A)) ||
 
3391
        (*in == '_') || (*in == ':')) {
 
3392
        in++;
 
3393
        while (((*in >= 0x61) && (*in <= 0x7A)) ||
 
3394
               ((*in >= 0x41) && (*in <= 0x5A)) ||
 
3395
               ((*in >= 0x30) && (*in <= 0x39)) ||
 
3396
               (*in == '_') || (*in == '-') ||
 
3397
               (*in == ':') || (*in == '.'))
 
3398
            in++;
 
3399
        if ((*in > 0) && (*in < 0x80)) {
 
3400
            count = in - ctxt->input->cur;
 
3401
            if ((count > XML_MAX_NAME_LENGTH) &&
 
3402
                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
3403
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
 
3404
                return(NULL);
 
3405
            }
 
3406
            ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
 
3407
            ctxt->input->cur = in;
 
3408
            ctxt->nbChars += count;
 
3409
            ctxt->input->col += count;
 
3410
            if (ret == NULL)
 
3411
                xmlErrMemory(ctxt, NULL);
 
3412
            return(ret);
 
3413
        }
 
3414
    }
 
3415
    /* accelerator for special cases */
 
3416
    return(xmlParseNameComplex(ctxt));
 
3417
}
 
3418
 
 
3419
static const xmlChar *
 
3420
xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
 
3421
    int len = 0, l;
 
3422
    int c;
 
3423
    int count = 0;
 
3424
    const xmlChar *end; /* needed because CUR_CHAR() can move cur on \r\n */
 
3425
 
 
3426
#ifdef DEBUG
 
3427
    nbParseNCNameComplex++;
 
3428
#endif
 
3429
 
 
3430
    /*
 
3431
     * Handler for more complex cases
 
3432
     */
 
3433
    GROW;
 
3434
    end = ctxt->input->cur;
 
3435
    c = CUR_CHAR(l);
 
3436
    if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
 
3437
        (!xmlIsNameStartChar(ctxt, c) || (c == ':'))) {
 
3438
        return(NULL);
 
3439
    }
 
3440
 
 
3441
    while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
 
3442
           (xmlIsNameChar(ctxt, c) && (c != ':'))) {
 
3443
        if (count++ > XML_PARSER_CHUNK_SIZE) {
 
3444
            if ((len > XML_MAX_NAME_LENGTH) &&
 
3445
                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
3446
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
 
3447
                return(NULL);
 
3448
            }
 
3449
            count = 0;
 
3450
            GROW;
 
3451
            if (ctxt->instate == XML_PARSER_EOF)
 
3452
                return(NULL);
 
3453
        }
 
3454
        len += l;
 
3455
        NEXTL(l);
 
3456
        end = ctxt->input->cur;
 
3457
        c = CUR_CHAR(l);
 
3458
        if (c == 0) {
 
3459
            count = 0;
 
3460
            GROW;
 
3461
            if (ctxt->instate == XML_PARSER_EOF)
 
3462
                return(NULL);
 
3463
            end = ctxt->input->cur;
 
3464
            c = CUR_CHAR(l);
 
3465
        }
 
3466
    }
 
3467
    if ((len > XML_MAX_NAME_LENGTH) &&
 
3468
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
3469
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
 
3470
        return(NULL);
 
3471
    }
 
3472
    return(xmlDictLookup(ctxt->dict, end - len, len));
 
3473
}
 
3474
 
 
3475
/**
 
3476
 * xmlParseNCName:
 
3477
 * @ctxt:  an XML parser context
 
3478
 * @len:  length of the string parsed
 
3479
 *
 
3480
 * parse an XML name.
 
3481
 *
 
3482
 * [4NS] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
 
3483
 *                      CombiningChar | Extender
 
3484
 *
 
3485
 * [5NS] NCName ::= (Letter | '_') (NCNameChar)*
 
3486
 *
 
3487
 * Returns the Name parsed or NULL
 
3488
 */
 
3489
 
 
3490
static const xmlChar *
 
3491
xmlParseNCName(xmlParserCtxtPtr ctxt) {
 
3492
    const xmlChar *in;
 
3493
    const xmlChar *ret;
 
3494
    int count = 0;
 
3495
 
 
3496
#ifdef DEBUG
 
3497
    nbParseNCName++;
 
3498
#endif
 
3499
 
 
3500
    /*
 
3501
     * Accelerator for simple ASCII names
 
3502
     */
 
3503
    in = ctxt->input->cur;
 
3504
    if (((*in >= 0x61) && (*in <= 0x7A)) ||
 
3505
        ((*in >= 0x41) && (*in <= 0x5A)) ||
 
3506
        (*in == '_')) {
 
3507
        in++;
 
3508
        while (((*in >= 0x61) && (*in <= 0x7A)) ||
 
3509
               ((*in >= 0x41) && (*in <= 0x5A)) ||
 
3510
               ((*in >= 0x30) && (*in <= 0x39)) ||
 
3511
               (*in == '_') || (*in == '-') ||
 
3512
               (*in == '.'))
 
3513
            in++;
 
3514
        if ((*in > 0) && (*in < 0x80)) {
 
3515
            count = in - ctxt->input->cur;
 
3516
            if ((count > XML_MAX_NAME_LENGTH) &&
 
3517
                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
3518
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
 
3519
                return(NULL);
 
3520
            }
 
3521
            ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
 
3522
            ctxt->input->cur = in;
 
3523
            ctxt->nbChars += count;
 
3524
            ctxt->input->col += count;
 
3525
            if (ret == NULL) {
 
3526
                xmlErrMemory(ctxt, NULL);
 
3527
            }
 
3528
            return(ret);
 
3529
        }
 
3530
    }
 
3531
    return(xmlParseNCNameComplex(ctxt));
 
3532
}
 
3533
 
 
3534
/**
 
3535
 * xmlParseNameAndCompare:
 
3536
 * @ctxt:  an XML parser context
 
3537
 *
 
3538
 * parse an XML name and compares for match
 
3539
 * (specialized for endtag parsing)
 
3540
 *
 
3541
 * Returns NULL for an illegal name, (xmlChar*) 1 for success
 
3542
 * and the name for mismatch
 
3543
 */
 
3544
 
 
3545
static const xmlChar *
 
3546
xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) {
 
3547
    register const xmlChar *cmp = other;
 
3548
    register const xmlChar *in;
 
3549
    const xmlChar *ret;
 
3550
 
 
3551
    GROW;
 
3552
    if (ctxt->instate == XML_PARSER_EOF)
 
3553
        return(NULL);
 
3554
 
 
3555
    in = ctxt->input->cur;
 
3556
    while (*in != 0 && *in == *cmp) {
 
3557
        ++in;
 
3558
        ++cmp;
 
3559
        ctxt->input->col++;
 
3560
    }
 
3561
    if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
 
3562
        /* success */
 
3563
        ctxt->input->cur = in;
 
3564
        return (const xmlChar*) 1;
 
3565
    }
 
3566
    /* failure (or end of input buffer), check with full function */
 
3567
    ret = xmlParseName (ctxt);
 
3568
    /* strings coming from the dictionnary direct compare possible */
 
3569
    if (ret == other) {
 
3570
        return (const xmlChar*) 1;
 
3571
    }
 
3572
    return ret;
 
3573
}
 
3574
 
 
3575
/**
 
3576
 * xmlParseStringName:
 
3577
 * @ctxt:  an XML parser context
 
3578
 * @str:  a pointer to the string pointer (IN/OUT)
 
3579
 *
 
3580
 * parse an XML name.
 
3581
 *
 
3582
 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
 
3583
 *                  CombiningChar | Extender
 
3584
 *
 
3585
 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
 
3586
 *
 
3587
 * [6] Names ::= Name (#x20 Name)*
 
3588
 *
 
3589
 * Returns the Name parsed or NULL. The @str pointer
 
3590
 * is updated to the current location in the string.
 
3591
 */
 
3592
 
 
3593
static xmlChar *
 
3594
xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
 
3595
    xmlChar buf[XML_MAX_NAMELEN + 5];
 
3596
    const xmlChar *cur = *str;
 
3597
    int len = 0, l;
 
3598
    int c;
 
3599
 
 
3600
#ifdef DEBUG
 
3601
    nbParseStringName++;
 
3602
#endif
 
3603
 
 
3604
    c = CUR_SCHAR(cur, l);
 
3605
    if (!xmlIsNameStartChar(ctxt, c)) {
 
3606
        return(NULL);
 
3607
    }
 
3608
 
 
3609
    COPY_BUF(l,buf,len,c);
 
3610
    cur += l;
 
3611
    c = CUR_SCHAR(cur, l);
 
3612
    while (xmlIsNameChar(ctxt, c)) {
 
3613
        COPY_BUF(l,buf,len,c);
 
3614
        cur += l;
 
3615
        c = CUR_SCHAR(cur, l);
 
3616
        if (len >= XML_MAX_NAMELEN) { /* test bigentname.xml */
 
3617
            /*
 
3618
             * Okay someone managed to make a huge name, so he's ready to pay
 
3619
             * for the processing speed.
 
3620
             */
 
3621
            xmlChar *buffer;
 
3622
            int max = len * 2;
 
3623
 
 
3624
            buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
 
3625
            if (buffer == NULL) {
 
3626
                xmlErrMemory(ctxt, NULL);
 
3627
                return(NULL);
 
3628
            }
 
3629
            memcpy(buffer, buf, len);
 
3630
            while (xmlIsNameChar(ctxt, c)) {
 
3631
                if (len + 10 > max) {
 
3632
                    xmlChar *tmp;
 
3633
 
 
3634
                    if ((len > XML_MAX_NAME_LENGTH) &&
 
3635
                        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
3636
                        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
 
3637
                        xmlFree(buffer);
 
3638
                        return(NULL);
 
3639
                    }
 
3640
                    max *= 2;
 
3641
                    tmp = (xmlChar *) xmlRealloc(buffer,
 
3642
                                                    max * sizeof(xmlChar));
 
3643
                    if (tmp == NULL) {
 
3644
                        xmlErrMemory(ctxt, NULL);
 
3645
                        xmlFree(buffer);
 
3646
                        return(NULL);
 
3647
                    }
 
3648
                    buffer = tmp;
 
3649
                }
 
3650
                COPY_BUF(l,buffer,len,c);
 
3651
                cur += l;
 
3652
                c = CUR_SCHAR(cur, l);
 
3653
            }
 
3654
            buffer[len] = 0;
 
3655
            *str = cur;
 
3656
            return(buffer);
 
3657
        }
 
3658
    }
 
3659
    if ((len > XML_MAX_NAME_LENGTH) &&
 
3660
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
3661
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
 
3662
        return(NULL);
 
3663
    }
 
3664
    *str = cur;
 
3665
    return(xmlStrndup(buf, len));
 
3666
}
 
3667
 
 
3668
/**
 
3669
 * xmlParseNmtoken:
 
3670
 * @ctxt:  an XML parser context
 
3671
 *
 
3672
 * parse an XML Nmtoken.
 
3673
 *
 
3674
 * [7] Nmtoken ::= (NameChar)+
 
3675
 *
 
3676
 * [8] Nmtokens ::= Nmtoken (#x20 Nmtoken)*
 
3677
 *
 
3678
 * Returns the Nmtoken parsed or NULL
 
3679
 */
 
3680
 
 
3681
xmlChar *
 
3682
xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
 
3683
    xmlChar buf[XML_MAX_NAMELEN + 5];
 
3684
    int len = 0, l;
 
3685
    int c;
 
3686
    int count = 0;
 
3687
 
 
3688
#ifdef DEBUG
 
3689
    nbParseNmToken++;
 
3690
#endif
 
3691
 
 
3692
    GROW;
 
3693
    if (ctxt->instate == XML_PARSER_EOF)
 
3694
        return(NULL);
 
3695
    c = CUR_CHAR(l);
 
3696
 
 
3697
    while (xmlIsNameChar(ctxt, c)) {
 
3698
        if (count++ > XML_PARSER_CHUNK_SIZE) {
 
3699
            count = 0;
 
3700
            GROW;
 
3701
        }
 
3702
        COPY_BUF(l,buf,len,c);
 
3703
        NEXTL(l);
 
3704
        c = CUR_CHAR(l);
 
3705
        if (c == 0) {
 
3706
            count = 0;
 
3707
            GROW;
 
3708
            if (ctxt->instate == XML_PARSER_EOF)
 
3709
                return(NULL);
 
3710
            c = CUR_CHAR(l);
 
3711
        }
 
3712
        if (len >= XML_MAX_NAMELEN) {
 
3713
            /*
 
3714
             * Okay someone managed to make a huge token, so he's ready to pay
 
3715
             * for the processing speed.
 
3716
             */
 
3717
            xmlChar *buffer;
 
3718
            int max = len * 2;
 
3719
 
 
3720
            buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
 
3721
            if (buffer == NULL) {
 
3722
                xmlErrMemory(ctxt, NULL);
 
3723
                return(NULL);
 
3724
            }
 
3725
            memcpy(buffer, buf, len);
 
3726
            while (xmlIsNameChar(ctxt, c)) {
 
3727
                if (count++ > XML_PARSER_CHUNK_SIZE) {
 
3728
                    count = 0;
 
3729
                    GROW;
 
3730
                    if (ctxt->instate == XML_PARSER_EOF) {
 
3731
                        xmlFree(buffer);
 
3732
                        return(NULL);
 
3733
                    }
 
3734
                }
 
3735
                if (len + 10 > max) {
 
3736
                    xmlChar *tmp;
 
3737
 
 
3738
                    if ((max > XML_MAX_NAME_LENGTH) &&
 
3739
                        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
3740
                        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
 
3741
                        xmlFree(buffer);
 
3742
                        return(NULL);
 
3743
                    }
 
3744
                    max *= 2;
 
3745
                    tmp = (xmlChar *) xmlRealloc(buffer,
 
3746
                                                    max * sizeof(xmlChar));
 
3747
                    if (tmp == NULL) {
 
3748
                        xmlErrMemory(ctxt, NULL);
 
3749
                        xmlFree(buffer);
 
3750
                        return(NULL);
 
3751
                    }
 
3752
                    buffer = tmp;
 
3753
                }
 
3754
                COPY_BUF(l,buffer,len,c);
 
3755
                NEXTL(l);
 
3756
                c = CUR_CHAR(l);
 
3757
            }
 
3758
            buffer[len] = 0;
 
3759
            return(buffer);
 
3760
        }
 
3761
    }
 
3762
    if (len == 0)
 
3763
        return(NULL);
 
3764
    if ((len > XML_MAX_NAME_LENGTH) &&
 
3765
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
3766
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
 
3767
        return(NULL);
 
3768
    }
 
3769
    return(xmlStrndup(buf, len));
 
3770
}
 
3771
 
 
3772
/**
 
3773
 * xmlParseEntityValue:
 
3774
 * @ctxt:  an XML parser context
 
3775
 * @orig:  if non-NULL store a copy of the original entity value
 
3776
 *
 
3777
 * parse a value for ENTITY declarations
 
3778
 *
 
3779
 * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
 
3780
 *                     "'" ([^%&'] | PEReference | Reference)* "'"
 
3781
 *
 
3782
 * Returns the EntityValue parsed with reference substituted or NULL
 
3783
 */
 
3784
 
 
3785
xmlChar *
 
3786
xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
 
3787
    xmlChar *buf = NULL;
 
3788
    int len = 0;
 
3789
    int size = XML_PARSER_BUFFER_SIZE;
 
3790
    int c, l;
 
3791
    xmlChar stop;
 
3792
    xmlChar *ret = NULL;
 
3793
    const xmlChar *cur = NULL;
 
3794
    xmlParserInputPtr input;
 
3795
 
 
3796
    if (RAW == '"') stop = '"';
 
3797
    else if (RAW == '\'') stop = '\'';
 
3798
    else {
 
3799
        xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_STARTED, NULL);
 
3800
        return(NULL);
 
3801
    }
 
3802
    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
3803
    if (buf == NULL) {
 
3804
        xmlErrMemory(ctxt, NULL);
 
3805
        return(NULL);
 
3806
    }
 
3807
 
 
3808
    /*
 
3809
     * The content of the entity definition is copied in a buffer.
 
3810
     */
 
3811
 
 
3812
    ctxt->instate = XML_PARSER_ENTITY_VALUE;
 
3813
    input = ctxt->input;
 
3814
    GROW;
 
3815
    if (ctxt->instate == XML_PARSER_EOF) {
 
3816
        xmlFree(buf);
 
3817
        return(NULL);
 
3818
    }
 
3819
    NEXT;
 
3820
    c = CUR_CHAR(l);
 
3821
    /*
 
3822
     * NOTE: 4.4.5 Included in Literal
 
3823
     * When a parameter entity reference appears in a literal entity
 
3824
     * value, ... a single or double quote character in the replacement
 
3825
     * text is always treated as a normal data character and will not
 
3826
     * terminate the literal.
 
3827
     * In practice it means we stop the loop only when back at parsing
 
3828
     * the initial entity and the quote is found
 
3829
     */
 
3830
    while (((IS_CHAR(c)) && ((c != stop) || /* checked */
 
3831
            (ctxt->input != input))) && (ctxt->instate != XML_PARSER_EOF)) {
 
3832
        if (len + 5 >= size) {
 
3833
            xmlChar *tmp;
 
3834
 
 
3835
            size *= 2;
 
3836
            tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
 
3837
            if (tmp == NULL) {
 
3838
                xmlErrMemory(ctxt, NULL);
 
3839
                xmlFree(buf);
 
3840
                return(NULL);
 
3841
            }
 
3842
            buf = tmp;
 
3843
        }
 
3844
        COPY_BUF(l,buf,len,c);
 
3845
        NEXTL(l);
 
3846
        /*
 
3847
         * Pop-up of finished entities.
 
3848
         */
 
3849
        while ((RAW == 0) && (ctxt->inputNr > 1)) /* non input consuming */
 
3850
            xmlPopInput(ctxt);
 
3851
 
 
3852
        GROW;
 
3853
        c = CUR_CHAR(l);
 
3854
        if (c == 0) {
 
3855
            GROW;
 
3856
            c = CUR_CHAR(l);
 
3857
        }
 
3858
    }
 
3859
    buf[len] = 0;
 
3860
    if (ctxt->instate == XML_PARSER_EOF) {
 
3861
        xmlFree(buf);
 
3862
        return(NULL);
 
3863
    }
 
3864
 
 
3865
    /*
 
3866
     * Raise problem w.r.t. '&' and '%' being used in non-entities
 
3867
     * reference constructs. Note Charref will be handled in
 
3868
     * xmlStringDecodeEntities()
 
3869
     */
 
3870
    cur = buf;
 
3871
    while (*cur != 0) { /* non input consuming */
 
3872
        if ((*cur == '%') || ((*cur == '&') && (cur[1] != '#'))) {
 
3873
            xmlChar *name;
 
3874
            xmlChar tmp = *cur;
 
3875
 
 
3876
            cur++;
 
3877
            name = xmlParseStringName(ctxt, &cur);
 
3878
            if ((name == NULL) || (*cur != ';')) {
 
3879
                xmlFatalErrMsgInt(ctxt, XML_ERR_ENTITY_CHAR_ERROR,
 
3880
            "EntityValue: '%c' forbidden except for entities references\n",
 
3881
                                  tmp);
 
3882
            }
 
3883
            if ((tmp == '%') && (ctxt->inSubset == 1) &&
 
3884
                (ctxt->inputNr == 1)) {
 
3885
                xmlFatalErr(ctxt, XML_ERR_ENTITY_PE_INTERNAL, NULL);
 
3886
            }
 
3887
            if (name != NULL)
 
3888
                xmlFree(name);
 
3889
            if (*cur == 0)
 
3890
                break;
 
3891
        }
 
3892
        cur++;
 
3893
    }
 
3894
 
 
3895
    /*
 
3896
     * Then PEReference entities are substituted.
 
3897
     */
 
3898
    if (c != stop) {
 
3899
        xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL);
 
3900
        xmlFree(buf);
 
3901
    } else {
 
3902
        NEXT;
 
3903
        /*
 
3904
         * NOTE: 4.4.7 Bypassed
 
3905
         * When a general entity reference appears in the EntityValue in
 
3906
         * an entity declaration, it is bypassed and left as is.
 
3907
         * so XML_SUBSTITUTE_REF is not set here.
 
3908
         */
 
3909
        ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF,
 
3910
                                      0, 0, 0);
 
3911
        if (orig != NULL)
 
3912
            *orig = buf;
 
3913
        else
 
3914
            xmlFree(buf);
 
3915
    }
 
3916
 
 
3917
    return(ret);
 
3918
}
 
3919
 
 
3920
/**
 
3921
 * xmlParseAttValueComplex:
 
3922
 * @ctxt:  an XML parser context
 
3923
 * @len:   the resulting attribute len
 
3924
 * @normalize:  wether to apply the inner normalization
 
3925
 *
 
3926
 * parse a value for an attribute, this is the fallback function
 
3927
 * of xmlParseAttValue() when the attribute parsing requires handling
 
3928
 * of non-ASCII characters, or normalization compaction.
 
3929
 *
 
3930
 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
 
3931
 */
 
3932
static xmlChar *
 
3933
xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
 
3934
    xmlChar limit = 0;
 
3935
    xmlChar *buf = NULL;
 
3936
    xmlChar *rep = NULL;
 
3937
    size_t len = 0;
 
3938
    size_t buf_size = 0;
 
3939
    int c, l, in_space = 0;
 
3940
    xmlChar *current = NULL;
 
3941
    xmlEntityPtr ent;
 
3942
 
 
3943
    if (NXT(0) == '"') {
 
3944
        ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
 
3945
        limit = '"';
 
3946
        NEXT;
 
3947
    } else if (NXT(0) == '\'') {
 
3948
        limit = '\'';
 
3949
        ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
 
3950
        NEXT;
 
3951
    } else {
 
3952
        xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
 
3953
        return(NULL);
 
3954
    }
 
3955
 
 
3956
    /*
 
3957
     * allocate a translation buffer.
 
3958
     */
 
3959
    buf_size = XML_PARSER_BUFFER_SIZE;
 
3960
    buf = (xmlChar *) xmlMallocAtomic(buf_size);
 
3961
    if (buf == NULL) goto mem_error;
 
3962
 
 
3963
    /*
 
3964
     * OK loop until we reach one of the ending char or a size limit.
 
3965
     */
 
3966
    c = CUR_CHAR(l);
 
3967
    while (((NXT(0) != limit) && /* checked */
 
3968
            (IS_CHAR(c)) && (c != '<')) &&
 
3969
            (ctxt->instate != XML_PARSER_EOF)) {
 
3970
        /*
 
3971
         * Impose a reasonable limit on attribute size, unless XML_PARSE_HUGE
 
3972
         * special option is given
 
3973
         */
 
3974
        if ((len > XML_MAX_TEXT_LENGTH) &&
 
3975
            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
3976
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
 
3977
                           "AttValue length too long\n");
 
3978
            goto mem_error;
 
3979
        }
 
3980
        if (c == 0) break;
 
3981
        if (c == '&') {
 
3982
            in_space = 0;
 
3983
            if (NXT(1) == '#') {
 
3984
                int val = xmlParseCharRef(ctxt);
 
3985
 
 
3986
                if (val == '&') {
 
3987
                    if (ctxt->replaceEntities) {
 
3988
                        if (len + 10 > buf_size) {
 
3989
                            growBuffer(buf, 10);
 
3990
                        }
 
3991
                        buf[len++] = '&';
 
3992
                    } else {
 
3993
                        /*
 
3994
                         * The reparsing will be done in xmlStringGetNodeList()
 
3995
                         * called by the attribute() function in SAX.c
 
3996
                         */
 
3997
                        if (len + 10 > buf_size) {
 
3998
                            growBuffer(buf, 10);
 
3999
                        }
 
4000
                        buf[len++] = '&';
 
4001
                        buf[len++] = '#';
 
4002
                        buf[len++] = '3';
 
4003
                        buf[len++] = '8';
 
4004
                        buf[len++] = ';';
 
4005
                    }
 
4006
                } else if (val != 0) {
 
4007
                    if (len + 10 > buf_size) {
 
4008
                        growBuffer(buf, 10);
 
4009
                    }
 
4010
                    len += xmlCopyChar(0, &buf[len], val);
 
4011
                }
 
4012
            } else {
 
4013
                ent = xmlParseEntityRef(ctxt);
 
4014
                ctxt->nbentities++;
 
4015
                if (ent != NULL)
 
4016
                    ctxt->nbentities += ent->owner;
 
4017
                if ((ent != NULL) &&
 
4018
                    (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
 
4019
                    if (len + 10 > buf_size) {
 
4020
                        growBuffer(buf, 10);
 
4021
                    }
 
4022
                    if ((ctxt->replaceEntities == 0) &&
 
4023
                        (ent->content[0] == '&')) {
 
4024
                        buf[len++] = '&';
 
4025
                        buf[len++] = '#';
 
4026
                        buf[len++] = '3';
 
4027
                        buf[len++] = '8';
 
4028
                        buf[len++] = ';';
 
4029
                    } else {
 
4030
                        buf[len++] = ent->content[0];
 
4031
                    }
 
4032
                } else if ((ent != NULL) &&
 
4033
                           (ctxt->replaceEntities != 0)) {
 
4034
                    if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
 
4035
                        rep = xmlStringDecodeEntities(ctxt, ent->content,
 
4036
                                                      XML_SUBSTITUTE_REF,
 
4037
                                                      0, 0, 0);
 
4038
                        if (rep != NULL) {
 
4039
                            current = rep;
 
4040
                            while (*current != 0) { /* non input consuming */
 
4041
                                if ((*current == 0xD) || (*current == 0xA) ||
 
4042
                                    (*current == 0x9)) {
 
4043
                                    buf[len++] = 0x20;
 
4044
                                    current++;
 
4045
                                } else
 
4046
                                    buf[len++] = *current++;
 
4047
                                if (len + 10 > buf_size) {
 
4048
                                    growBuffer(buf, 10);
 
4049
                                }
 
4050
                            }
 
4051
                            xmlFree(rep);
 
4052
                            rep = NULL;
 
4053
                        }
 
4054
                    } else {
 
4055
                        if (len + 10 > buf_size) {
 
4056
                            growBuffer(buf, 10);
 
4057
                        }
 
4058
                        if (ent->content != NULL)
 
4059
                            buf[len++] = ent->content[0];
 
4060
                    }
 
4061
                } else if (ent != NULL) {
 
4062
                    int i = xmlStrlen(ent->name);
 
4063
                    const xmlChar *cur = ent->name;
 
4064
 
 
4065
                    /*
 
4066
                     * This may look absurd but is needed to detect
 
4067
                     * entities problems
 
4068
                     */
 
4069
                    if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
 
4070
                        (ent->content != NULL) && (ent->checked == 0)) {
 
4071
                        unsigned long oldnbent = ctxt->nbentities;
 
4072
 
 
4073
                        rep = xmlStringDecodeEntities(ctxt, ent->content,
 
4074
                                                  XML_SUBSTITUTE_REF, 0, 0, 0);
 
4075
 
 
4076
                        ent->checked = (ctxt->nbentities - oldnbent + 1) * 2;
 
4077
                        if (rep != NULL) {
 
4078
                            if (xmlStrchr(rep, '<'))
 
4079
                                ent->checked |= 1;
 
4080
                            xmlFree(rep);
 
4081
                            rep = NULL;
 
4082
                        }
 
4083
                    }
 
4084
 
 
4085
                    /*
 
4086
                     * Just output the reference
 
4087
                     */
 
4088
                    buf[len++] = '&';
 
4089
                    while (len + i + 10 > buf_size) {
 
4090
                        growBuffer(buf, i + 10);
 
4091
                    }
 
4092
                    for (;i > 0;i--)
 
4093
                        buf[len++] = *cur++;
 
4094
                    buf[len++] = ';';
 
4095
                }
 
4096
            }
 
4097
        } else {
 
4098
            if ((c == 0x20) || (c == 0xD) || (c == 0xA) || (c == 0x9)) {
 
4099
                if ((len != 0) || (!normalize)) {
 
4100
                    if ((!normalize) || (!in_space)) {
 
4101
                        COPY_BUF(l,buf,len,0x20);
 
4102
                        while (len + 10 > buf_size) {
 
4103
                            growBuffer(buf, 10);
 
4104
                        }
 
4105
                    }
 
4106
                    in_space = 1;
 
4107
                }
 
4108
            } else {
 
4109
                in_space = 0;
 
4110
                COPY_BUF(l,buf,len,c);
 
4111
                if (len + 10 > buf_size) {
 
4112
                    growBuffer(buf, 10);
 
4113
                }
 
4114
            }
 
4115
            NEXTL(l);
 
4116
        }
 
4117
        GROW;
 
4118
        c = CUR_CHAR(l);
 
4119
    }
 
4120
    if (ctxt->instate == XML_PARSER_EOF)
 
4121
        goto error;
 
4122
 
 
4123
    if ((in_space) && (normalize)) {
 
4124
        while ((len > 0) && (buf[len - 1] == 0x20)) len--;
 
4125
    }
 
4126
    buf[len] = 0;
 
4127
    if (RAW == '<') {
 
4128
        xmlFatalErr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, NULL);
 
4129
    } else if (RAW != limit) {
 
4130
        if ((c != 0) && (!IS_CHAR(c))) {
 
4131
            xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
 
4132
                           "invalid character in attribute value\n");
 
4133
        } else {
 
4134
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
 
4135
                           "AttValue: ' expected\n");
 
4136
        }
 
4137
    } else
 
4138
        NEXT;
 
4139
 
 
4140
    /*
 
4141
     * There we potentially risk an overflow, don't allow attribute value of
 
4142
     * length more than INT_MAX it is a very reasonnable assumption !
 
4143
     */
 
4144
    if (len >= INT_MAX) {
 
4145
        xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
 
4146
                       "AttValue length too long\n");
 
4147
        goto mem_error;
 
4148
    }
 
4149
 
 
4150
    if (attlen != NULL) *attlen = (int) len;
 
4151
    return(buf);
 
4152
 
 
4153
mem_error:
 
4154
    xmlErrMemory(ctxt, NULL);
 
4155
error:
 
4156
    if (buf != NULL)
 
4157
        xmlFree(buf);
 
4158
    if (rep != NULL)
 
4159
        xmlFree(rep);
 
4160
    return(NULL);
 
4161
}
 
4162
 
 
4163
/**
 
4164
 * xmlParseAttValue:
 
4165
 * @ctxt:  an XML parser context
 
4166
 *
 
4167
 * parse a value for an attribute
 
4168
 * Note: the parser won't do substitution of entities here, this
 
4169
 * will be handled later in xmlStringGetNodeList
 
4170
 *
 
4171
 * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |
 
4172
 *                   "'" ([^<&'] | Reference)* "'"
 
4173
 *
 
4174
 * 3.3.3 Attribute-Value Normalization:
 
4175
 * Before the value of an attribute is passed to the application or
 
4176
 * checked for validity, the XML processor must normalize it as follows:
 
4177
 * - a character reference is processed by appending the referenced
 
4178
 *   character to the attribute value
 
4179
 * - an entity reference is processed by recursively processing the
 
4180
 *   replacement text of the entity
 
4181
 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
 
4182
 *   appending #x20 to the normalized value, except that only a single
 
4183
 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
 
4184
 *   parsed entity or the literal entity value of an internal parsed entity
 
4185
 * - other characters are processed by appending them to the normalized value
 
4186
 * If the declared value is not CDATA, then the XML processor must further
 
4187
 * process the normalized attribute value by discarding any leading and
 
4188
 * trailing space (#x20) characters, and by replacing sequences of space
 
4189
 * (#x20) characters by a single space (#x20) character.
 
4190
 * All attributes for which no declaration has been read should be treated
 
4191
 * by a non-validating parser as if declared CDATA.
 
4192
 *
 
4193
 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
 
4194
 */
 
4195
 
 
4196
 
 
4197
xmlChar *
 
4198
xmlParseAttValue(xmlParserCtxtPtr ctxt) {
 
4199
    if ((ctxt == NULL) || (ctxt->input == NULL)) return(NULL);
 
4200
    return(xmlParseAttValueInternal(ctxt, NULL, NULL, 0));
 
4201
}
 
4202
 
 
4203
/**
 
4204
 * xmlParseSystemLiteral:
 
4205
 * @ctxt:  an XML parser context
 
4206
 *
 
4207
 * parse an XML Literal
 
4208
 *
 
4209
 * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
 
4210
 *
 
4211
 * Returns the SystemLiteral parsed or NULL
 
4212
 */
 
4213
 
 
4214
xmlChar *
 
4215
xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
 
4216
    xmlChar *buf = NULL;
 
4217
    int len = 0;
 
4218
    int size = XML_PARSER_BUFFER_SIZE;
 
4219
    int cur, l;
 
4220
    xmlChar stop;
 
4221
    int state = ctxt->instate;
 
4222
    int count = 0;
 
4223
 
 
4224
    SHRINK;
 
4225
    if (RAW == '"') {
 
4226
        NEXT;
 
4227
        stop = '"';
 
4228
    } else if (RAW == '\'') {
 
4229
        NEXT;
 
4230
        stop = '\'';
 
4231
    } else {
 
4232
        xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
 
4233
        return(NULL);
 
4234
    }
 
4235
 
 
4236
    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
4237
    if (buf == NULL) {
 
4238
        xmlErrMemory(ctxt, NULL);
 
4239
        return(NULL);
 
4240
    }
 
4241
    ctxt->instate = XML_PARSER_SYSTEM_LITERAL;
 
4242
    cur = CUR_CHAR(l);
 
4243
    while ((IS_CHAR(cur)) && (cur != stop)) { /* checked */
 
4244
        if (len + 5 >= size) {
 
4245
            xmlChar *tmp;
 
4246
 
 
4247
            if ((size > XML_MAX_NAME_LENGTH) &&
 
4248
                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
4249
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral");
 
4250
                xmlFree(buf);
 
4251
                ctxt->instate = (xmlParserInputState) state;
 
4252
                return(NULL);
 
4253
            }
 
4254
            size *= 2;
 
4255
            tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
 
4256
            if (tmp == NULL) {
 
4257
                xmlFree(buf);
 
4258
                xmlErrMemory(ctxt, NULL);
 
4259
                ctxt->instate = (xmlParserInputState) state;
 
4260
                return(NULL);
 
4261
            }
 
4262
            buf = tmp;
 
4263
        }
 
4264
        count++;
 
4265
        if (count > 50) {
 
4266
            GROW;
 
4267
            count = 0;
 
4268
            if (ctxt->instate == XML_PARSER_EOF) {
 
4269
                xmlFree(buf);
 
4270
                return(NULL);
 
4271
            }
 
4272
        }
 
4273
        COPY_BUF(l,buf,len,cur);
 
4274
        NEXTL(l);
 
4275
        cur = CUR_CHAR(l);
 
4276
        if (cur == 0) {
 
4277
            GROW;
 
4278
            SHRINK;
 
4279
            cur = CUR_CHAR(l);
 
4280
        }
 
4281
    }
 
4282
    buf[len] = 0;
 
4283
    ctxt->instate = (xmlParserInputState) state;
 
4284
    if (!IS_CHAR(cur)) {
 
4285
        xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
 
4286
    } else {
 
4287
        NEXT;
 
4288
    }
 
4289
    return(buf);
 
4290
}
 
4291
 
 
4292
/**
 
4293
 * xmlParsePubidLiteral:
 
4294
 * @ctxt:  an XML parser context
 
4295
 *
 
4296
 * parse an XML public literal
 
4297
 *
 
4298
 * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
 
4299
 *
 
4300
 * Returns the PubidLiteral parsed or NULL.
 
4301
 */
 
4302
 
 
4303
xmlChar *
 
4304
xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
 
4305
    xmlChar *buf = NULL;
 
4306
    int len = 0;
 
4307
    int size = XML_PARSER_BUFFER_SIZE;
 
4308
    xmlChar cur;
 
4309
    xmlChar stop;
 
4310
    int count = 0;
 
4311
    xmlParserInputState oldstate = ctxt->instate;
 
4312
 
 
4313
    SHRINK;
 
4314
    if (RAW == '"') {
 
4315
        NEXT;
 
4316
        stop = '"';
 
4317
    } else if (RAW == '\'') {
 
4318
        NEXT;
 
4319
        stop = '\'';
 
4320
    } else {
 
4321
        xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
 
4322
        return(NULL);
 
4323
    }
 
4324
    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
4325
    if (buf == NULL) {
 
4326
        xmlErrMemory(ctxt, NULL);
 
4327
        return(NULL);
 
4328
    }
 
4329
    ctxt->instate = XML_PARSER_PUBLIC_LITERAL;
 
4330
    cur = CUR;
 
4331
    while ((IS_PUBIDCHAR_CH(cur)) && (cur != stop)) { /* checked */
 
4332
        if (len + 1 >= size) {
 
4333
            xmlChar *tmp;
 
4334
 
 
4335
            if ((size > XML_MAX_NAME_LENGTH) &&
 
4336
                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
4337
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Public ID");
 
4338
                xmlFree(buf);
 
4339
                return(NULL);
 
4340
            }
 
4341
            size *= 2;
 
4342
            tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
 
4343
            if (tmp == NULL) {
 
4344
                xmlErrMemory(ctxt, NULL);
 
4345
                xmlFree(buf);
 
4346
                return(NULL);
 
4347
            }
 
4348
            buf = tmp;
 
4349
        }
 
4350
        buf[len++] = cur;
 
4351
        count++;
 
4352
        if (count > 50) {
 
4353
            GROW;
 
4354
            count = 0;
 
4355
            if (ctxt->instate == XML_PARSER_EOF) {
 
4356
                xmlFree(buf);
 
4357
                return(NULL);
 
4358
            }
 
4359
        }
 
4360
        NEXT;
 
4361
        cur = CUR;
 
4362
        if (cur == 0) {
 
4363
            GROW;
 
4364
            SHRINK;
 
4365
            cur = CUR;
 
4366
        }
 
4367
    }
 
4368
    buf[len] = 0;
 
4369
    if (cur != stop) {
 
4370
        xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
 
4371
    } else {
 
4372
        NEXT;
 
4373
    }
 
4374
    ctxt->instate = oldstate;
 
4375
    return(buf);
 
4376
}
 
4377
 
 
4378
static void xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata);
 
4379
 
 
4380
/*
 
4381
 * used for the test in the inner loop of the char data testing
 
4382
 */
 
4383
static const unsigned char test_char_data[256] = {
 
4384
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4385
    0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9, CR/LF separated */
 
4386
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4387
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4388
    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x00, 0x27, /* & */
 
4389
    0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
 
4390
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
 
4391
    0x38, 0x39, 0x3A, 0x3B, 0x00, 0x3D, 0x3E, 0x3F, /* < */
 
4392
    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
 
4393
    0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
 
4394
    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
 
4395
    0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x00, 0x5E, 0x5F, /* ] */
 
4396
    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
 
4397
    0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
 
4398
    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
 
4399
    0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
 
4400
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* non-ascii */
 
4401
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4402
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4403
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4404
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4405
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4406
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4407
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4408
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4409
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4410
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4411
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4412
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4413
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4414
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
4415
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 
4416
};
 
4417
 
 
4418
/**
 
4419
 * xmlParseCharData:
 
4420
 * @ctxt:  an XML parser context
 
4421
 * @cdata:  int indicating whether we are within a CDATA section
 
4422
 *
 
4423
 * parse a CharData section.
 
4424
 * if we are within a CDATA section ']]>' marks an end of section.
 
4425
 *
 
4426
 * The right angle bracket (>) may be represented using the string "&gt;",
 
4427
 * and must, for compatibility, be escaped using "&gt;" or a character
 
4428
 * reference when it appears in the string "]]>" in content, when that
 
4429
 * string is not marking the end of a CDATA section.
 
4430
 *
 
4431
 * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
 
4432
 */
 
4433
 
 
4434
void
 
4435
xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) {
 
4436
    const xmlChar *in;
 
4437
    int nbchar = 0;
 
4438
    int line = ctxt->input->line;
 
4439
    int col = ctxt->input->col;
 
4440
    int ccol;
 
4441
 
 
4442
    SHRINK;
 
4443
    GROW;
 
4444
    /*
 
4445
     * Accelerated common case where input don't need to be
 
4446
     * modified before passing it to the handler.
 
4447
     */
 
4448
    if (!cdata) {
 
4449
        in = ctxt->input->cur;
 
4450
        do {
 
4451
get_more_space:
 
4452
            while (*in == 0x20) { in++; ctxt->input->col++; }
 
4453
            if (*in == 0xA) {
 
4454
                do {
 
4455
                    ctxt->input->line++; ctxt->input->col = 1;
 
4456
                    in++;
 
4457
                } while (*in == 0xA);
 
4458
                goto get_more_space;
 
4459
            }
 
4460
            if (*in == '<') {
 
4461
                nbchar = in - ctxt->input->cur;
 
4462
                if (nbchar > 0) {
 
4463
                    const xmlChar *tmp = ctxt->input->cur;
 
4464
                    ctxt->input->cur = in;
 
4465
 
 
4466
                    if ((ctxt->sax != NULL) &&
 
4467
                        (ctxt->sax->ignorableWhitespace !=
 
4468
                         ctxt->sax->characters)) {
 
4469
                        if (areBlanks(ctxt, tmp, nbchar, 1)) {
 
4470
                            if (ctxt->sax->ignorableWhitespace != NULL)
 
4471
                                ctxt->sax->ignorableWhitespace(ctxt->userData,
 
4472
                                                       tmp, nbchar);
 
4473
                        } else {
 
4474
                            if (ctxt->sax->characters != NULL)
 
4475
                                ctxt->sax->characters(ctxt->userData,
 
4476
                                                      tmp, nbchar);
 
4477
                            if (*ctxt->space == -1)
 
4478
                                *ctxt->space = -2;
 
4479
                        }
 
4480
                    } else if ((ctxt->sax != NULL) &&
 
4481
                               (ctxt->sax->characters != NULL)) {
 
4482
                        ctxt->sax->characters(ctxt->userData,
 
4483
                                              tmp, nbchar);
 
4484
                    }
 
4485
                }
 
4486
                return;
 
4487
            }
 
4488
 
 
4489
get_more:
 
4490
            ccol = ctxt->input->col;
 
4491
            while (test_char_data[*in]) {
 
4492
                in++;
 
4493
                ccol++;
 
4494
            }
 
4495
            ctxt->input->col = ccol;
 
4496
            if (*in == 0xA) {
 
4497
                do {
 
4498
                    ctxt->input->line++; ctxt->input->col = 1;
 
4499
                    in++;
 
4500
                } while (*in == 0xA);
 
4501
                goto get_more;
 
4502
            }
 
4503
            if (*in == ']') {
 
4504
                if ((in[1] == ']') && (in[2] == '>')) {
 
4505
                    xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
 
4506
                    ctxt->input->cur = in;
 
4507
                    return;
 
4508
                }
 
4509
                in++;
 
4510
                ctxt->input->col++;
 
4511
                goto get_more;
 
4512
            }
 
4513
            nbchar = in - ctxt->input->cur;
 
4514
            if (nbchar > 0) {
 
4515
                if ((ctxt->sax != NULL) &&
 
4516
                    (ctxt->sax->ignorableWhitespace !=
 
4517
                     ctxt->sax->characters) &&
 
4518
                    (IS_BLANK_CH(*ctxt->input->cur))) {
 
4519
                    const xmlChar *tmp = ctxt->input->cur;
 
4520
                    ctxt->input->cur = in;
 
4521
 
 
4522
                    if (areBlanks(ctxt, tmp, nbchar, 0)) {
 
4523
                        if (ctxt->sax->ignorableWhitespace != NULL)
 
4524
                            ctxt->sax->ignorableWhitespace(ctxt->userData,
 
4525
                                                           tmp, nbchar);
 
4526
                    } else {
 
4527
                        if (ctxt->sax->characters != NULL)
 
4528
                            ctxt->sax->characters(ctxt->userData,
 
4529
                                                  tmp, nbchar);
 
4530
                        if (*ctxt->space == -1)
 
4531
                            *ctxt->space = -2;
 
4532
                    }
 
4533
                    line = ctxt->input->line;
 
4534
                    col = ctxt->input->col;
 
4535
                } else if (ctxt->sax != NULL) {
 
4536
                    if (ctxt->sax->characters != NULL)
 
4537
                        ctxt->sax->characters(ctxt->userData,
 
4538
                                              ctxt->input->cur, nbchar);
 
4539
                    line = ctxt->input->line;
 
4540
                    col = ctxt->input->col;
 
4541
                }
 
4542
                /* something really bad happened in the SAX callback */
 
4543
                if (ctxt->instate != XML_PARSER_CONTENT)
 
4544
                    return;
 
4545
            }
 
4546
            ctxt->input->cur = in;
 
4547
            if (*in == 0xD) {
 
4548
                in++;
 
4549
                if (*in == 0xA) {
 
4550
                    ctxt->input->cur = in;
 
4551
                    in++;
 
4552
                    ctxt->input->line++; ctxt->input->col = 1;
 
4553
                    continue; /* while */
 
4554
                }
 
4555
                in--;
 
4556
            }
 
4557
            if (*in == '<') {
 
4558
                return;
 
4559
            }
 
4560
            if (*in == '&') {
 
4561
                return;
 
4562
            }
 
4563
            SHRINK;
 
4564
            GROW;
 
4565
            if (ctxt->instate == XML_PARSER_EOF)
 
4566
                return;
 
4567
            in = ctxt->input->cur;
 
4568
        } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09));
 
4569
        nbchar = 0;
 
4570
    }
 
4571
    ctxt->input->line = line;
 
4572
    ctxt->input->col = col;
 
4573
    xmlParseCharDataComplex(ctxt, cdata);
 
4574
}
 
4575
 
 
4576
/**
 
4577
 * xmlParseCharDataComplex:
 
4578
 * @ctxt:  an XML parser context
 
4579
 * @cdata:  int indicating whether we are within a CDATA section
 
4580
 *
 
4581
 * parse a CharData section.this is the fallback function
 
4582
 * of xmlParseCharData() when the parsing requires handling
 
4583
 * of non-ASCII characters.
 
4584
 */
 
4585
static void
 
4586
xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) {
 
4587
    xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE + 5];
 
4588
    int nbchar = 0;
 
4589
    int cur, l;
 
4590
    int count = 0;
 
4591
 
 
4592
    SHRINK;
 
4593
    GROW;
 
4594
    cur = CUR_CHAR(l);
 
4595
    while ((cur != '<') && /* checked */
 
4596
           (cur != '&') &&
 
4597
           (IS_CHAR(cur))) /* test also done in xmlCurrentChar() */ {
 
4598
        if ((cur == ']') && (NXT(1) == ']') &&
 
4599
            (NXT(2) == '>')) {
 
4600
            if (cdata) break;
 
4601
            else {
 
4602
                xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
 
4603
            }
 
4604
        }
 
4605
        COPY_BUF(l,buf,nbchar,cur);
 
4606
        if (nbchar >= XML_PARSER_BIG_BUFFER_SIZE) {
 
4607
            buf[nbchar] = 0;
 
4608
 
 
4609
            /*
 
4610
             * OK the segment is to be consumed as chars.
 
4611
             */
 
4612
            if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
 
4613
                if (areBlanks(ctxt, buf, nbchar, 0)) {
 
4614
                    if (ctxt->sax->ignorableWhitespace != NULL)
 
4615
                        ctxt->sax->ignorableWhitespace(ctxt->userData,
 
4616
                                                       buf, nbchar);
 
4617
                } else {
 
4618
                    if (ctxt->sax->characters != NULL)
 
4619
                        ctxt->sax->characters(ctxt->userData, buf, nbchar);
 
4620
                    if ((ctxt->sax->characters !=
 
4621
                         ctxt->sax->ignorableWhitespace) &&
 
4622
                        (*ctxt->space == -1))
 
4623
                        *ctxt->space = -2;
 
4624
                }
 
4625
            }
 
4626
            nbchar = 0;
 
4627
            /* something really bad happened in the SAX callback */
 
4628
            if (ctxt->instate != XML_PARSER_CONTENT)
 
4629
                return;
 
4630
        }
 
4631
        count++;
 
4632
        if (count > 50) {
 
4633
            GROW;
 
4634
            count = 0;
 
4635
            if (ctxt->instate == XML_PARSER_EOF)
 
4636
                return;
 
4637
        }
 
4638
        NEXTL(l);
 
4639
        cur = CUR_CHAR(l);
 
4640
    }
 
4641
    if (nbchar != 0) {
 
4642
        buf[nbchar] = 0;
 
4643
        /*
 
4644
         * OK the segment is to be consumed as chars.
 
4645
         */
 
4646
        if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
 
4647
            if (areBlanks(ctxt, buf, nbchar, 0)) {
 
4648
                if (ctxt->sax->ignorableWhitespace != NULL)
 
4649
                    ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
 
4650
            } else {
 
4651
                if (ctxt->sax->characters != NULL)
 
4652
                    ctxt->sax->characters(ctxt->userData, buf, nbchar);
 
4653
                if ((ctxt->sax->characters != ctxt->sax->ignorableWhitespace) &&
 
4654
                    (*ctxt->space == -1))
 
4655
                    *ctxt->space = -2;
 
4656
            }
 
4657
        }
 
4658
    }
 
4659
    if ((cur != 0) && (!IS_CHAR(cur))) {
 
4660
        /* Generate the error and skip the offending character */
 
4661
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
 
4662
                          "PCDATA invalid Char value %d\n",
 
4663
                          cur);
 
4664
        NEXTL(l);
 
4665
    }
 
4666
}
 
4667
 
 
4668
/**
 
4669
 * xmlParseExternalID:
 
4670
 * @ctxt:  an XML parser context
 
4671
 * @publicID:  a xmlChar** receiving PubidLiteral
 
4672
 * @strict: indicate whether we should restrict parsing to only
 
4673
 *          production [75], see NOTE below
 
4674
 *
 
4675
 * Parse an External ID or a Public ID
 
4676
 *
 
4677
 * NOTE: Productions [75] and [83] interact badly since [75] can generate
 
4678
 *       'PUBLIC' S PubidLiteral S SystemLiteral
 
4679
 *
 
4680
 * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
 
4681
 *                   | 'PUBLIC' S PubidLiteral S SystemLiteral
 
4682
 *
 
4683
 * [83] PublicID ::= 'PUBLIC' S PubidLiteral
 
4684
 *
 
4685
 * Returns the function returns SystemLiteral and in the second
 
4686
 *                case publicID receives PubidLiteral, is strict is off
 
4687
 *                it is possible to return NULL and have publicID set.
 
4688
 */
 
4689
 
 
4690
xmlChar *
 
4691
xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
 
4692
    xmlChar *URI = NULL;
 
4693
 
 
4694
    SHRINK;
 
4695
 
 
4696
    *publicID = NULL;
 
4697
    if (CMP6(CUR_PTR, 'S', 'Y', 'S', 'T', 'E', 'M')) {
 
4698
        SKIP(6);
 
4699
        if (!IS_BLANK_CH(CUR)) {
 
4700
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
4701
                           "Space required after 'SYSTEM'\n");
 
4702
        }
 
4703
        SKIP_BLANKS;
 
4704
        URI = xmlParseSystemLiteral(ctxt);
 
4705
        if (URI == NULL) {
 
4706
            xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
 
4707
        }
 
4708
    } else if (CMP6(CUR_PTR, 'P', 'U', 'B', 'L', 'I', 'C')) {
 
4709
        SKIP(6);
 
4710
        if (!IS_BLANK_CH(CUR)) {
 
4711
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
4712
                    "Space required after 'PUBLIC'\n");
 
4713
        }
 
4714
        SKIP_BLANKS;
 
4715
        *publicID = xmlParsePubidLiteral(ctxt);
 
4716
        if (*publicID == NULL) {
 
4717
            xmlFatalErr(ctxt, XML_ERR_PUBID_REQUIRED, NULL);
 
4718
        }
 
4719
        if (strict) {
 
4720
            /*
 
4721
             * We don't handle [83] so "S SystemLiteral" is required.
 
4722
             */
 
4723
            if (!IS_BLANK_CH(CUR)) {
 
4724
                xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
4725
                        "Space required after the Public Identifier\n");
 
4726
            }
 
4727
        } else {
 
4728
            /*
 
4729
             * We handle [83] so we return immediately, if
 
4730
             * "S SystemLiteral" is not detected. From a purely parsing
 
4731
             * point of view that's a nice mess.
 
4732
             */
 
4733
            const xmlChar *ptr;
 
4734
            GROW;
 
4735
 
 
4736
            ptr = CUR_PTR;
 
4737
            if (!IS_BLANK_CH(*ptr)) return(NULL);
 
4738
 
 
4739
            while (IS_BLANK_CH(*ptr)) ptr++; /* TODO: dangerous, fix ! */
 
4740
            if ((*ptr != '\'') && (*ptr != '"')) return(NULL);
 
4741
        }
 
4742
        SKIP_BLANKS;
 
4743
        URI = xmlParseSystemLiteral(ctxt);
 
4744
        if (URI == NULL) {
 
4745
            xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
 
4746
        }
 
4747
    }
 
4748
    return(URI);
 
4749
}
 
4750
 
 
4751
/**
 
4752
 * xmlParseCommentComplex:
 
4753
 * @ctxt:  an XML parser context
 
4754
 * @buf:  the already parsed part of the buffer
 
4755
 * @len:  number of bytes filles in the buffer
 
4756
 * @size:  allocated size of the buffer
 
4757
 *
 
4758
 * Skip an XML (SGML) comment <!-- .... -->
 
4759
 *  The spec says that "For compatibility, the string "--" (double-hyphen)
 
4760
 *  must not occur within comments. "
 
4761
 * This is the slow routine in case the accelerator for ascii didn't work
 
4762
 *
 
4763
 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
 
4764
 */
 
4765
static void
 
4766
xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
 
4767
                       size_t len, size_t size) {
 
4768
    int q, ql;
 
4769
    int r, rl;
 
4770
    int cur, l;
 
4771
    size_t count = 0;
 
4772
    int inputid;
 
4773
 
 
4774
    inputid = ctxt->input->id;
 
4775
 
 
4776
    if (buf == NULL) {
 
4777
        len = 0;
 
4778
        size = XML_PARSER_BUFFER_SIZE;
 
4779
        buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
4780
        if (buf == NULL) {
 
4781
            xmlErrMemory(ctxt, NULL);
 
4782
            return;
 
4783
        }
 
4784
    }
 
4785
    GROW;       /* Assure there's enough input data */
 
4786
    q = CUR_CHAR(ql);
 
4787
    if (q == 0)
 
4788
        goto not_terminated;
 
4789
    if (!IS_CHAR(q)) {
 
4790
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
 
4791
                          "xmlParseComment: invalid xmlChar value %d\n",
 
4792
                          q);
 
4793
        xmlFree (buf);
 
4794
        return;
 
4795
    }
 
4796
    NEXTL(ql);
 
4797
    r = CUR_CHAR(rl);
 
4798
    if (r == 0)
 
4799
        goto not_terminated;
 
4800
    if (!IS_CHAR(r)) {
 
4801
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
 
4802
                          "xmlParseComment: invalid xmlChar value %d\n",
 
4803
                          q);
 
4804
        xmlFree (buf);
 
4805
        return;
 
4806
    }
 
4807
    NEXTL(rl);
 
4808
    cur = CUR_CHAR(l);
 
4809
    if (cur == 0)
 
4810
        goto not_terminated;
 
4811
    while (IS_CHAR(cur) && /* checked */
 
4812
           ((cur != '>') ||
 
4813
            (r != '-') || (q != '-'))) {
 
4814
        if ((r == '-') && (q == '-')) {
 
4815
            xmlFatalErr(ctxt, XML_ERR_HYPHEN_IN_COMMENT, NULL);
 
4816
        }
 
4817
        if ((len > XML_MAX_TEXT_LENGTH) &&
 
4818
            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
4819
            xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
 
4820
                         "Comment too big found", NULL);
 
4821
            xmlFree (buf);
 
4822
            return;
 
4823
        }
 
4824
        if (len + 5 >= size) {
 
4825
            xmlChar *new_buf;
 
4826
            size_t new_size;
 
4827
 
 
4828
            new_size = size * 2;
 
4829
            new_buf = (xmlChar *) xmlRealloc(buf, new_size);
 
4830
            if (new_buf == NULL) {
 
4831
                xmlFree (buf);
 
4832
                xmlErrMemory(ctxt, NULL);
 
4833
                return;
 
4834
            }
 
4835
            buf = new_buf;
 
4836
            size = new_size;
 
4837
        }
 
4838
        COPY_BUF(ql,buf,len,q);
 
4839
        q = r;
 
4840
        ql = rl;
 
4841
        r = cur;
 
4842
        rl = l;
 
4843
 
 
4844
        count++;
 
4845
        if (count > 50) {
 
4846
            GROW;
 
4847
            count = 0;
 
4848
            if (ctxt->instate == XML_PARSER_EOF) {
 
4849
                xmlFree(buf);
 
4850
                return;
 
4851
            }
 
4852
        }
 
4853
        NEXTL(l);
 
4854
        cur = CUR_CHAR(l);
 
4855
        if (cur == 0) {
 
4856
            SHRINK;
 
4857
            GROW;
 
4858
            cur = CUR_CHAR(l);
 
4859
        }
 
4860
    }
 
4861
    buf[len] = 0;
 
4862
    if (cur == 0) {
 
4863
        xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
 
4864
                             "Comment not terminated \n<!--%.50s\n", buf);
 
4865
    } else if (!IS_CHAR(cur)) {
 
4866
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
 
4867
                          "xmlParseComment: invalid xmlChar value %d\n",
 
4868
                          cur);
 
4869
    } else {
 
4870
        if (inputid != ctxt->input->id) {
 
4871
            xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
4872
                "Comment doesn't start and stop in the same entity\n");
 
4873
        }
 
4874
        NEXT;
 
4875
        if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
 
4876
            (!ctxt->disableSAX))
 
4877
            ctxt->sax->comment(ctxt->userData, buf);
 
4878
    }
 
4879
    xmlFree(buf);
 
4880
    return;
 
4881
not_terminated:
 
4882
    xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
 
4883
                         "Comment not terminated\n", NULL);
 
4884
    xmlFree(buf);
 
4885
    return;
 
4886
}
 
4887
 
 
4888
/**
 
4889
 * xmlParseComment:
 
4890
 * @ctxt:  an XML parser context
 
4891
 *
 
4892
 * Skip an XML (SGML) comment <!-- .... -->
 
4893
 *  The spec says that "For compatibility, the string "--" (double-hyphen)
 
4894
 *  must not occur within comments. "
 
4895
 *
 
4896
 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
 
4897
 */
 
4898
void
 
4899
xmlParseComment(xmlParserCtxtPtr ctxt) {
 
4900
    xmlChar *buf = NULL;
 
4901
    size_t size = XML_PARSER_BUFFER_SIZE;
 
4902
    size_t len = 0;
 
4903
    xmlParserInputState state;
 
4904
    const xmlChar *in;
 
4905
    size_t nbchar = 0;
 
4906
    int ccol;
 
4907
    int inputid;
 
4908
 
 
4909
    /*
 
4910
     * Check that there is a comment right here.
 
4911
     */
 
4912
    if ((RAW != '<') || (NXT(1) != '!') ||
 
4913
        (NXT(2) != '-') || (NXT(3) != '-')) return;
 
4914
    state = ctxt->instate;
 
4915
    ctxt->instate = XML_PARSER_COMMENT;
 
4916
    inputid = ctxt->input->id;
 
4917
    SKIP(4);
 
4918
    SHRINK;
 
4919
    GROW;
 
4920
 
 
4921
    /*
 
4922
     * Accelerated common case where input don't need to be
 
4923
     * modified before passing it to the handler.
 
4924
     */
 
4925
    in = ctxt->input->cur;
 
4926
    do {
 
4927
        if (*in == 0xA) {
 
4928
            do {
 
4929
                ctxt->input->line++; ctxt->input->col = 1;
 
4930
                in++;
 
4931
            } while (*in == 0xA);
 
4932
        }
 
4933
get_more:
 
4934
        ccol = ctxt->input->col;
 
4935
        while (((*in > '-') && (*in <= 0x7F)) ||
 
4936
               ((*in >= 0x20) && (*in < '-')) ||
 
4937
               (*in == 0x09)) {
 
4938
                    in++;
 
4939
                    ccol++;
 
4940
        }
 
4941
        ctxt->input->col = ccol;
 
4942
        if (*in == 0xA) {
 
4943
            do {
 
4944
                ctxt->input->line++; ctxt->input->col = 1;
 
4945
                in++;
 
4946
            } while (*in == 0xA);
 
4947
            goto get_more;
 
4948
        }
 
4949
        nbchar = in - ctxt->input->cur;
 
4950
        /*
 
4951
         * save current set of data
 
4952
         */
 
4953
        if (nbchar > 0) {
 
4954
            if ((ctxt->sax != NULL) &&
 
4955
                (ctxt->sax->comment != NULL)) {
 
4956
                if (buf == NULL) {
 
4957
                    if ((*in == '-') && (in[1] == '-'))
 
4958
                        size = nbchar + 1;
 
4959
                    else
 
4960
                        size = XML_PARSER_BUFFER_SIZE + nbchar;
 
4961
                    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
4962
                    if (buf == NULL) {
 
4963
                        xmlErrMemory(ctxt, NULL);
 
4964
                        ctxt->instate = state;
 
4965
                        return;
 
4966
                    }
 
4967
                    len = 0;
 
4968
                } else if (len + nbchar + 1 >= size) {
 
4969
                    xmlChar *new_buf;
 
4970
                    size  += len + nbchar + XML_PARSER_BUFFER_SIZE;
 
4971
                    new_buf = (xmlChar *) xmlRealloc(buf,
 
4972
                                                     size * sizeof(xmlChar));
 
4973
                    if (new_buf == NULL) {
 
4974
                        xmlFree (buf);
 
4975
                        xmlErrMemory(ctxt, NULL);
 
4976
                        ctxt->instate = state;
 
4977
                        return;
 
4978
                    }
 
4979
                    buf = new_buf;
 
4980
                }
 
4981
                memcpy(&buf[len], ctxt->input->cur, nbchar);
 
4982
                len += nbchar;
 
4983
                buf[len] = 0;
 
4984
            }
 
4985
        }
 
4986
        if ((len > XML_MAX_TEXT_LENGTH) &&
 
4987
            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
4988
            xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
 
4989
                         "Comment too big found", NULL);
 
4990
            xmlFree (buf);
 
4991
            return;
 
4992
        }
 
4993
        ctxt->input->cur = in;
 
4994
        if (*in == 0xA) {
 
4995
            in++;
 
4996
            ctxt->input->line++; ctxt->input->col = 1;
 
4997
        }
 
4998
        if (*in == 0xD) {
 
4999
            in++;
 
5000
            if (*in == 0xA) {
 
5001
                ctxt->input->cur = in;
 
5002
                in++;
 
5003
                ctxt->input->line++; ctxt->input->col = 1;
 
5004
                continue; /* while */
 
5005
            }
 
5006
            in--;
 
5007
        }
 
5008
        SHRINK;
 
5009
        GROW;
 
5010
        if (ctxt->instate == XML_PARSER_EOF) {
 
5011
            xmlFree(buf);
 
5012
            return;
 
5013
        }
 
5014
        in = ctxt->input->cur;
 
5015
        if (*in == '-') {
 
5016
            if (in[1] == '-') {
 
5017
                if (in[2] == '>') {
 
5018
                    if (ctxt->input->id != inputid) {
 
5019
                        xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
5020
                        "comment doesn't start and stop in the same entity\n");
 
5021
                    }
 
5022
                    SKIP(3);
 
5023
                    if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
 
5024
                        (!ctxt->disableSAX)) {
 
5025
                        if (buf != NULL)
 
5026
                            ctxt->sax->comment(ctxt->userData, buf);
 
5027
                        else
 
5028
                            ctxt->sax->comment(ctxt->userData, BAD_CAST "");
 
5029
                    }
 
5030
                    if (buf != NULL)
 
5031
                        xmlFree(buf);
 
5032
                    if (ctxt->instate != XML_PARSER_EOF)
 
5033
                        ctxt->instate = state;
 
5034
                    return;
 
5035
                }
 
5036
                if (buf != NULL) {
 
5037
                    xmlFatalErrMsgStr(ctxt, XML_ERR_HYPHEN_IN_COMMENT,
 
5038
                                      "Double hyphen within comment: "
 
5039
                                      "<!--%.50s\n",
 
5040
                                      buf);
 
5041
                } else
 
5042
                    xmlFatalErrMsgStr(ctxt, XML_ERR_HYPHEN_IN_COMMENT,
 
5043
                                      "Double hyphen within comment\n", NULL);
 
5044
                in++;
 
5045
                ctxt->input->col++;
 
5046
            }
 
5047
            in++;
 
5048
            ctxt->input->col++;
 
5049
            goto get_more;
 
5050
        }
 
5051
    } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09));
 
5052
    xmlParseCommentComplex(ctxt, buf, len, size);
 
5053
    ctxt->instate = state;
 
5054
    return;
 
5055
}
 
5056
 
 
5057
 
 
5058
/**
 
5059
 * xmlParsePITarget:
 
5060
 * @ctxt:  an XML parser context
 
5061
 *
 
5062
 * parse the name of a PI
 
5063
 *
 
5064
 * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
 
5065
 *
 
5066
 * Returns the PITarget name or NULL
 
5067
 */
 
5068
 
 
5069
const xmlChar *
 
5070
xmlParsePITarget(xmlParserCtxtPtr ctxt) {
 
5071
    const xmlChar *name;
 
5072
 
 
5073
    name = xmlParseName(ctxt);
 
5074
    if ((name != NULL) &&
 
5075
        ((name[0] == 'x') || (name[0] == 'X')) &&
 
5076
        ((name[1] == 'm') || (name[1] == 'M')) &&
 
5077
        ((name[2] == 'l') || (name[2] == 'L'))) {
 
5078
        int i;
 
5079
        if ((name[0] == 'x') && (name[1] == 'm') &&
 
5080
            (name[2] == 'l') && (name[3] == 0)) {
 
5081
            xmlFatalErrMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
 
5082
                 "XML declaration allowed only at the start of the document\n");
 
5083
            return(name);
 
5084
        } else if (name[3] == 0) {
 
5085
            xmlFatalErr(ctxt, XML_ERR_RESERVED_XML_NAME, NULL);
 
5086
            return(name);
 
5087
        }
 
5088
        for (i = 0;;i++) {
 
5089
            if (xmlW3CPIs[i] == NULL) break;
 
5090
            if (xmlStrEqual(name, (const xmlChar *)xmlW3CPIs[i]))
 
5091
                return(name);
 
5092
        }
 
5093
        xmlWarningMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
 
5094
                      "xmlParsePITarget: invalid name prefix 'xml'\n",
 
5095
                      NULL, NULL);
 
5096
    }
 
5097
    if ((name != NULL) && (xmlStrchr(name, ':') != NULL)) {
 
5098
        xmlNsErr(ctxt, XML_NS_ERR_COLON,
 
5099
                 "colon are forbidden from PI names '%s'\n", name, NULL, NULL);
 
5100
    }
 
5101
    return(name);
 
5102
}
 
5103
 
 
5104
#ifdef LIBXML_CATALOG_ENABLED
 
5105
/**
 
5106
 * xmlParseCatalogPI:
 
5107
 * @ctxt:  an XML parser context
 
5108
 * @catalog:  the PI value string
 
5109
 *
 
5110
 * parse an XML Catalog Processing Instruction.
 
5111
 *
 
5112
 * <?oasis-xml-catalog catalog="http://example.com/catalog.xml"?>
 
5113
 *
 
5114
 * Occurs only if allowed by the user and if happening in the Misc
 
5115
 * part of the document before any doctype informations
 
5116
 * This will add the given catalog to the parsing context in order
 
5117
 * to be used if there is a resolution need further down in the document
 
5118
 */
 
5119
 
 
5120
static void
 
5121
xmlParseCatalogPI(xmlParserCtxtPtr ctxt, const xmlChar *catalog) {
 
5122
    xmlChar *URL = NULL;
 
5123
    const xmlChar *tmp, *base;
 
5124
    xmlChar marker;
 
5125
 
 
5126
    tmp = catalog;
 
5127
    while (IS_BLANK_CH(*tmp)) tmp++;
 
5128
    if (xmlStrncmp(tmp, BAD_CAST"catalog", 7))
 
5129
        goto error;
 
5130
    tmp += 7;
 
5131
    while (IS_BLANK_CH(*tmp)) tmp++;
 
5132
    if (*tmp != '=') {
 
5133
        return;
 
5134
    }
 
5135
    tmp++;
 
5136
    while (IS_BLANK_CH(*tmp)) tmp++;
 
5137
    marker = *tmp;
 
5138
    if ((marker != '\'') && (marker != '"'))
 
5139
        goto error;
 
5140
    tmp++;
 
5141
    base = tmp;
 
5142
    while ((*tmp != 0) && (*tmp != marker)) tmp++;
 
5143
    if (*tmp == 0)
 
5144
        goto error;
 
5145
    URL = xmlStrndup(base, tmp - base);
 
5146
    tmp++;
 
5147
    while (IS_BLANK_CH(*tmp)) tmp++;
 
5148
    if (*tmp != 0)
 
5149
        goto error;
 
5150
 
 
5151
    if (URL != NULL) {
 
5152
        ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
 
5153
        xmlFree(URL);
 
5154
    }
 
5155
    return;
 
5156
 
 
5157
error:
 
5158
    xmlWarningMsg(ctxt, XML_WAR_CATALOG_PI,
 
5159
                  "Catalog PI syntax error: %s\n",
 
5160
                  catalog, NULL);
 
5161
    if (URL != NULL)
 
5162
        xmlFree(URL);
 
5163
}
 
5164
#endif
 
5165
 
 
5166
/**
 
5167
 * xmlParsePI:
 
5168
 * @ctxt:  an XML parser context
 
5169
 *
 
5170
 * parse an XML Processing Instruction.
 
5171
 *
 
5172
 * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
 
5173
 *
 
5174
 * The processing is transfered to SAX once parsed.
 
5175
 */
 
5176
 
 
5177
void
 
5178
xmlParsePI(xmlParserCtxtPtr ctxt) {
 
5179
    xmlChar *buf = NULL;
 
5180
    size_t len = 0;
 
5181
    size_t size = XML_PARSER_BUFFER_SIZE;
 
5182
    int cur, l;
 
5183
    const xmlChar *target;
 
5184
    xmlParserInputState state;
 
5185
    int count = 0;
 
5186
 
 
5187
    if ((RAW == '<') && (NXT(1) == '?')) {
 
5188
        xmlParserInputPtr input = ctxt->input;
 
5189
        state = ctxt->instate;
 
5190
        ctxt->instate = XML_PARSER_PI;
 
5191
        /*
 
5192
         * this is a Processing Instruction.
 
5193
         */
 
5194
        SKIP(2);
 
5195
        SHRINK;
 
5196
 
 
5197
        /*
 
5198
         * Parse the target name and check for special support like
 
5199
         * namespace.
 
5200
         */
 
5201
        target = xmlParsePITarget(ctxt);
 
5202
        if (target != NULL) {
 
5203
            if ((RAW == '?') && (NXT(1) == '>')) {
 
5204
                if (input != ctxt->input) {
 
5205
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
5206
            "PI declaration doesn't start and stop in the same entity\n");
 
5207
                }
 
5208
                SKIP(2);
 
5209
 
 
5210
                /*
 
5211
                 * SAX: PI detected.
 
5212
                 */
 
5213
                if ((ctxt->sax) && (!ctxt->disableSAX) &&
 
5214
                    (ctxt->sax->processingInstruction != NULL))
 
5215
                    ctxt->sax->processingInstruction(ctxt->userData,
 
5216
                                                     target, NULL);
 
5217
                if (ctxt->instate != XML_PARSER_EOF)
 
5218
                    ctxt->instate = state;
 
5219
                return;
 
5220
            }
 
5221
            buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
5222
            if (buf == NULL) {
 
5223
                xmlErrMemory(ctxt, NULL);
 
5224
                ctxt->instate = state;
 
5225
                return;
 
5226
            }
 
5227
            cur = CUR;
 
5228
            if (!IS_BLANK(cur)) {
 
5229
                xmlFatalErrMsgStr(ctxt, XML_ERR_SPACE_REQUIRED,
 
5230
                          "ParsePI: PI %s space expected\n", target);
 
5231
            }
 
5232
            SKIP_BLANKS;
 
5233
            cur = CUR_CHAR(l);
 
5234
            while (IS_CHAR(cur) && /* checked */
 
5235
                   ((cur != '?') || (NXT(1) != '>'))) {
 
5236
                if (len + 5 >= size) {
 
5237
                    xmlChar *tmp;
 
5238
                    size_t new_size = size * 2;
 
5239
                    tmp = (xmlChar *) xmlRealloc(buf, new_size);
 
5240
                    if (tmp == NULL) {
 
5241
                        xmlErrMemory(ctxt, NULL);
 
5242
                        xmlFree(buf);
 
5243
                        ctxt->instate = state;
 
5244
                        return;
 
5245
                    }
 
5246
                    buf = tmp;
 
5247
                    size = new_size;
 
5248
                }
 
5249
                count++;
 
5250
                if (count > 50) {
 
5251
                    GROW;
 
5252
                    if (ctxt->instate == XML_PARSER_EOF) {
 
5253
                        xmlFree(buf);
 
5254
                        return;
 
5255
                    }
 
5256
                    count = 0;
 
5257
                    if ((len > XML_MAX_TEXT_LENGTH) &&
 
5258
                        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
5259
                        xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
 
5260
                                          "PI %s too big found", target);
 
5261
                        xmlFree(buf);
 
5262
                        ctxt->instate = state;
 
5263
                        return;
 
5264
                    }
 
5265
                }
 
5266
                COPY_BUF(l,buf,len,cur);
 
5267
                NEXTL(l);
 
5268
                cur = CUR_CHAR(l);
 
5269
                if (cur == 0) {
 
5270
                    SHRINK;
 
5271
                    GROW;
 
5272
                    cur = CUR_CHAR(l);
 
5273
                }
 
5274
            }
 
5275
            if ((len > XML_MAX_TEXT_LENGTH) &&
 
5276
                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
5277
                xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
 
5278
                                  "PI %s too big found", target);
 
5279
                xmlFree(buf);
 
5280
                ctxt->instate = state;
 
5281
                return;
 
5282
            }
 
5283
            buf[len] = 0;
 
5284
            if (cur != '?') {
 
5285
                xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
 
5286
                      "ParsePI: PI %s never end ...\n", target);
 
5287
            } else {
 
5288
                if (input != ctxt->input) {
 
5289
                    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5290
            "PI declaration doesn't start and stop in the same entity\n");
 
5291
                }
 
5292
                SKIP(2);
 
5293
 
 
5294
#ifdef LIBXML_CATALOG_ENABLED
 
5295
                if (((state == XML_PARSER_MISC) ||
 
5296
                     (state == XML_PARSER_START)) &&
 
5297
                    (xmlStrEqual(target, XML_CATALOG_PI))) {
 
5298
                    xmlCatalogAllow allow = xmlCatalogGetDefaults();
 
5299
                    if ((allow == XML_CATA_ALLOW_DOCUMENT) ||
 
5300
                        (allow == XML_CATA_ALLOW_ALL))
 
5301
                        xmlParseCatalogPI(ctxt, buf);
 
5302
                }
 
5303
#endif
 
5304
 
 
5305
 
 
5306
                /*
 
5307
                 * SAX: PI detected.
 
5308
                 */
 
5309
                if ((ctxt->sax) && (!ctxt->disableSAX) &&
 
5310
                    (ctxt->sax->processingInstruction != NULL))
 
5311
                    ctxt->sax->processingInstruction(ctxt->userData,
 
5312
                                                     target, buf);
 
5313
            }
 
5314
            xmlFree(buf);
 
5315
        } else {
 
5316
            xmlFatalErr(ctxt, XML_ERR_PI_NOT_STARTED, NULL);
 
5317
        }
 
5318
        if (ctxt->instate != XML_PARSER_EOF)
 
5319
            ctxt->instate = state;
 
5320
    }
 
5321
}
 
5322
 
 
5323
/**
 
5324
 * xmlParseNotationDecl:
 
5325
 * @ctxt:  an XML parser context
 
5326
 *
 
5327
 * parse a notation declaration
 
5328
 *
 
5329
 * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID |  PublicID) S? '>'
 
5330
 *
 
5331
 * Hence there is actually 3 choices:
 
5332
 *     'PUBLIC' S PubidLiteral
 
5333
 *     'PUBLIC' S PubidLiteral S SystemLiteral
 
5334
 * and 'SYSTEM' S SystemLiteral
 
5335
 *
 
5336
 * See the NOTE on xmlParseExternalID().
 
5337
 */
 
5338
 
 
5339
void
 
5340
xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
 
5341
    const xmlChar *name;
 
5342
    xmlChar *Pubid;
 
5343
    xmlChar *Systemid;
 
5344
 
 
5345
    if (CMP10(CUR_PTR, '<', '!', 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
 
5346
        xmlParserInputPtr input = ctxt->input;
 
5347
        SHRINK;
 
5348
        SKIP(10);
 
5349
        if (!IS_BLANK_CH(CUR)) {
 
5350
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5351
                           "Space required after '<!NOTATION'\n");
 
5352
            return;
 
5353
        }
 
5354
        SKIP_BLANKS;
 
5355
 
 
5356
        name = xmlParseName(ctxt);
 
5357
        if (name == NULL) {
 
5358
            xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
 
5359
            return;
 
5360
        }
 
5361
        if (!IS_BLANK_CH(CUR)) {
 
5362
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5363
                     "Space required after the NOTATION name'\n");
 
5364
            return;
 
5365
        }
 
5366
        if (xmlStrchr(name, ':') != NULL) {
 
5367
            xmlNsErr(ctxt, XML_NS_ERR_COLON,
 
5368
                     "colon are forbidden from notation names '%s'\n",
 
5369
                     name, NULL, NULL);
 
5370
        }
 
5371
        SKIP_BLANKS;
 
5372
 
 
5373
        /*
 
5374
         * Parse the IDs.
 
5375
         */
 
5376
        Systemid = xmlParseExternalID(ctxt, &Pubid, 0);
 
5377
        SKIP_BLANKS;
 
5378
 
 
5379
        if (RAW == '>') {
 
5380
            if (input != ctxt->input) {
 
5381
                xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5382
        "Notation declaration doesn't start and stop in the same entity\n");
 
5383
            }
 
5384
            NEXT;
 
5385
            if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
 
5386
                (ctxt->sax->notationDecl != NULL))
 
5387
                ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
 
5388
        } else {
 
5389
            xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
 
5390
        }
 
5391
        if (Systemid != NULL) xmlFree(Systemid);
 
5392
        if (Pubid != NULL) xmlFree(Pubid);
 
5393
    }
 
5394
}
 
5395
 
 
5396
/**
 
5397
 * xmlParseEntityDecl:
 
5398
 * @ctxt:  an XML parser context
 
5399
 *
 
5400
 * parse <!ENTITY declarations
 
5401
 *
 
5402
 * [70] EntityDecl ::= GEDecl | PEDecl
 
5403
 *
 
5404
 * [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
 
5405
 *
 
5406
 * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
 
5407
 *
 
5408
 * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
 
5409
 *
 
5410
 * [74] PEDef ::= EntityValue | ExternalID
 
5411
 *
 
5412
 * [76] NDataDecl ::= S 'NDATA' S Name
 
5413
 *
 
5414
 * [ VC: Notation Declared ]
 
5415
 * The Name must match the declared name of a notation.
 
5416
 */
 
5417
 
 
5418
void
 
5419
xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
 
5420
    const xmlChar *name = NULL;
 
5421
    xmlChar *value = NULL;
 
5422
    xmlChar *URI = NULL, *literal = NULL;
 
5423
    const xmlChar *ndata = NULL;
 
5424
    int isParameter = 0;
 
5425
    xmlChar *orig = NULL;
 
5426
    int skipped;
 
5427
 
 
5428
    /* GROW; done in the caller */
 
5429
    if (CMP8(CUR_PTR, '<', '!', 'E', 'N', 'T', 'I', 'T', 'Y')) {
 
5430
        xmlParserInputPtr input = ctxt->input;
 
5431
        SHRINK;
 
5432
        SKIP(8);
 
5433
        skipped = SKIP_BLANKS;
 
5434
        if (skipped == 0) {
 
5435
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5436
                           "Space required after '<!ENTITY'\n");
 
5437
        }
 
5438
 
 
5439
        if (RAW == '%') {
 
5440
            NEXT;
 
5441
            skipped = SKIP_BLANKS;
 
5442
            if (skipped == 0) {
 
5443
                xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5444
                               "Space required after '%'\n");
 
5445
            }
 
5446
            isParameter = 1;
 
5447
        }
 
5448
 
 
5449
        name = xmlParseName(ctxt);
 
5450
        if (name == NULL) {
 
5451
            xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
5452
                           "xmlParseEntityDecl: no name\n");
 
5453
            return;
 
5454
        }
 
5455
        if (xmlStrchr(name, ':') != NULL) {
 
5456
            xmlNsErr(ctxt, XML_NS_ERR_COLON,
 
5457
                     "colon are forbidden from entities names '%s'\n",
 
5458
                     name, NULL, NULL);
 
5459
        }
 
5460
        skipped = SKIP_BLANKS;
 
5461
        if (skipped == 0) {
 
5462
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5463
                           "Space required after the entity name\n");
 
5464
        }
 
5465
 
 
5466
        ctxt->instate = XML_PARSER_ENTITY_DECL;
 
5467
        /*
 
5468
         * handle the various case of definitions...
 
5469
         */
 
5470
        if (isParameter) {
 
5471
            if ((RAW == '"') || (RAW == '\'')) {
 
5472
                value = xmlParseEntityValue(ctxt, &orig);
 
5473
                if (value) {
 
5474
                    if ((ctxt->sax != NULL) &&
 
5475
                        (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
 
5476
                        ctxt->sax->entityDecl(ctxt->userData, name,
 
5477
                                    XML_INTERNAL_PARAMETER_ENTITY,
 
5478
                                    NULL, NULL, value);
 
5479
                }
 
5480
            } else {
 
5481
                URI = xmlParseExternalID(ctxt, &literal, 1);
 
5482
                if ((URI == NULL) && (literal == NULL)) {
 
5483
                    xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
 
5484
                }
 
5485
                if (URI) {
 
5486
                    xmlURIPtr uri;
 
5487
 
 
5488
                    uri = xmlParseURI((const char *) URI);
 
5489
                    if (uri == NULL) {
 
5490
                        xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
 
5491
                                     "Invalid URI: %s\n", URI);
 
5492
                        /*
 
5493
                         * This really ought to be a well formedness error
 
5494
                         * but the XML Core WG decided otherwise c.f. issue
 
5495
                         * E26 of the XML erratas.
 
5496
                         */
 
5497
                    } else {
 
5498
                        if (uri->fragment != NULL) {
 
5499
                            /*
 
5500
                             * Okay this is foolish to block those but not
 
5501
                             * invalid URIs.
 
5502
                             */
 
5503
                            xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
 
5504
                        } else {
 
5505
                            if ((ctxt->sax != NULL) &&
 
5506
                                (!ctxt->disableSAX) &&
 
5507
                                (ctxt->sax->entityDecl != NULL))
 
5508
                                ctxt->sax->entityDecl(ctxt->userData, name,
 
5509
                                            XML_EXTERNAL_PARAMETER_ENTITY,
 
5510
                                            literal, URI, NULL);
 
5511
                        }
 
5512
                        xmlFreeURI(uri);
 
5513
                    }
 
5514
                }
 
5515
            }
 
5516
        } else {
 
5517
            if ((RAW == '"') || (RAW == '\'')) {
 
5518
                value = xmlParseEntityValue(ctxt, &orig);
 
5519
                if ((ctxt->sax != NULL) &&
 
5520
                    (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
 
5521
                    ctxt->sax->entityDecl(ctxt->userData, name,
 
5522
                                XML_INTERNAL_GENERAL_ENTITY,
 
5523
                                NULL, NULL, value);
 
5524
                /*
 
5525
                 * For expat compatibility in SAX mode.
 
5526
                 */
 
5527
                if ((ctxt->myDoc == NULL) ||
 
5528
                    (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
 
5529
                    if (ctxt->myDoc == NULL) {
 
5530
                        ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
 
5531
                        if (ctxt->myDoc == NULL) {
 
5532
                            xmlErrMemory(ctxt, "New Doc failed");
 
5533
                            return;
 
5534
                        }
 
5535
                        ctxt->myDoc->properties = XML_DOC_INTERNAL;
 
5536
                    }
 
5537
                    if (ctxt->myDoc->intSubset == NULL)
 
5538
                        ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
 
5539
                                            BAD_CAST "fake", NULL, NULL);
 
5540
 
 
5541
                    xmlSAX2EntityDecl(ctxt, name, XML_INTERNAL_GENERAL_ENTITY,
 
5542
                                      NULL, NULL, value);
 
5543
                }
 
5544
            } else {
 
5545
                URI = xmlParseExternalID(ctxt, &literal, 1);
 
5546
                if ((URI == NULL) && (literal == NULL)) {
 
5547
                    xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
 
5548
                }
 
5549
                if (URI) {
 
5550
                    xmlURIPtr uri;
 
5551
 
 
5552
                    uri = xmlParseURI((const char *)URI);
 
5553
                    if (uri == NULL) {
 
5554
                        xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
 
5555
                                     "Invalid URI: %s\n", URI);
 
5556
                        /*
 
5557
                         * This really ought to be a well formedness error
 
5558
                         * but the XML Core WG decided otherwise c.f. issue
 
5559
                         * E26 of the XML erratas.
 
5560
                         */
 
5561
                    } else {
 
5562
                        if (uri->fragment != NULL) {
 
5563
                            /*
 
5564
                             * Okay this is foolish to block those but not
 
5565
                             * invalid URIs.
 
5566
                             */
 
5567
                            xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
 
5568
                        }
 
5569
                        xmlFreeURI(uri);
 
5570
                    }
 
5571
                }
 
5572
                if ((RAW != '>') && (!IS_BLANK_CH(CUR))) {
 
5573
                    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5574
                                   "Space required before 'NDATA'\n");
 
5575
                }
 
5576
                SKIP_BLANKS;
 
5577
                if (CMP5(CUR_PTR, 'N', 'D', 'A', 'T', 'A')) {
 
5578
                    SKIP(5);
 
5579
                    if (!IS_BLANK_CH(CUR)) {
 
5580
                        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5581
                                       "Space required after 'NDATA'\n");
 
5582
                    }
 
5583
                    SKIP_BLANKS;
 
5584
                    ndata = xmlParseName(ctxt);
 
5585
                    if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
 
5586
                        (ctxt->sax->unparsedEntityDecl != NULL))
 
5587
                        ctxt->sax->unparsedEntityDecl(ctxt->userData, name,
 
5588
                                    literal, URI, ndata);
 
5589
                } else {
 
5590
                    if ((ctxt->sax != NULL) &&
 
5591
                        (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
 
5592
                        ctxt->sax->entityDecl(ctxt->userData, name,
 
5593
                                    XML_EXTERNAL_GENERAL_PARSED_ENTITY,
 
5594
                                    literal, URI, NULL);
 
5595
                    /*
 
5596
                     * For expat compatibility in SAX mode.
 
5597
                     * assuming the entity repalcement was asked for
 
5598
                     */
 
5599
                    if ((ctxt->replaceEntities != 0) &&
 
5600
                        ((ctxt->myDoc == NULL) ||
 
5601
                        (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE)))) {
 
5602
                        if (ctxt->myDoc == NULL) {
 
5603
                            ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
 
5604
                            if (ctxt->myDoc == NULL) {
 
5605
                                xmlErrMemory(ctxt, "New Doc failed");
 
5606
                                return;
 
5607
                            }
 
5608
                            ctxt->myDoc->properties = XML_DOC_INTERNAL;
 
5609
                        }
 
5610
 
 
5611
                        if (ctxt->myDoc->intSubset == NULL)
 
5612
                            ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
 
5613
                                                BAD_CAST "fake", NULL, NULL);
 
5614
                        xmlSAX2EntityDecl(ctxt, name,
 
5615
                                          XML_EXTERNAL_GENERAL_PARSED_ENTITY,
 
5616
                                          literal, URI, NULL);
 
5617
                    }
 
5618
                }
 
5619
            }
 
5620
        }
 
5621
        if (ctxt->instate == XML_PARSER_EOF)
 
5622
            return;
 
5623
        SKIP_BLANKS;
 
5624
        if (RAW != '>') {
 
5625
            xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
 
5626
                    "xmlParseEntityDecl: entity %s not terminated\n", name);
 
5627
        } else {
 
5628
            if (input != ctxt->input) {
 
5629
                xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
5630
        "Entity declaration doesn't start and stop in the same entity\n");
 
5631
            }
 
5632
            NEXT;
 
5633
        }
 
5634
        if (orig != NULL) {
 
5635
            /*
 
5636
             * Ugly mechanism to save the raw entity value.
 
5637
             */
 
5638
            xmlEntityPtr cur = NULL;
 
5639
 
 
5640
            if (isParameter) {
 
5641
                if ((ctxt->sax != NULL) &&
 
5642
                    (ctxt->sax->getParameterEntity != NULL))
 
5643
                    cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
 
5644
            } else {
 
5645
                if ((ctxt->sax != NULL) &&
 
5646
                    (ctxt->sax->getEntity != NULL))
 
5647
                    cur = ctxt->sax->getEntity(ctxt->userData, name);
 
5648
                if ((cur == NULL) && (ctxt->userData==ctxt)) {
 
5649
                    cur = xmlSAX2GetEntity(ctxt, name);
 
5650
                }
 
5651
            }
 
5652
            if (cur != NULL) {
 
5653
                if (cur->orig != NULL)
 
5654
                    xmlFree(orig);
 
5655
                else
 
5656
                    cur->orig = orig;
 
5657
            } else
 
5658
                xmlFree(orig);
 
5659
        }
 
5660
        if (value != NULL) xmlFree(value);
 
5661
        if (URI != NULL) xmlFree(URI);
 
5662
        if (literal != NULL) xmlFree(literal);
 
5663
    }
 
5664
}
 
5665
 
 
5666
/**
 
5667
 * xmlParseDefaultDecl:
 
5668
 * @ctxt:  an XML parser context
 
5669
 * @value:  Receive a possible fixed default value for the attribute
 
5670
 *
 
5671
 * Parse an attribute default declaration
 
5672
 *
 
5673
 * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
 
5674
 *
 
5675
 * [ VC: Required Attribute ]
 
5676
 * if the default declaration is the keyword #REQUIRED, then the
 
5677
 * attribute must be specified for all elements of the type in the
 
5678
 * attribute-list declaration.
 
5679
 *
 
5680
 * [ VC: Attribute Default Legal ]
 
5681
 * The declared default value must meet the lexical constraints of
 
5682
 * the declared attribute type c.f. xmlValidateAttributeDecl()
 
5683
 *
 
5684
 * [ VC: Fixed Attribute Default ]
 
5685
 * if an attribute has a default value declared with the #FIXED
 
5686
 * keyword, instances of that attribute must match the default value.
 
5687
 *
 
5688
 * [ WFC: No < in Attribute Values ]
 
5689
 * handled in xmlParseAttValue()
 
5690
 *
 
5691
 * returns: XML_ATTRIBUTE_NONE, XML_ATTRIBUTE_REQUIRED, XML_ATTRIBUTE_IMPLIED
 
5692
 *          or XML_ATTRIBUTE_FIXED.
 
5693
 */
 
5694
 
 
5695
int
 
5696
xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
 
5697
    int val;
 
5698
    xmlChar *ret;
 
5699
 
 
5700
    *value = NULL;
 
5701
    if (CMP9(CUR_PTR, '#', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D')) {
 
5702
        SKIP(9);
 
5703
        return(XML_ATTRIBUTE_REQUIRED);
 
5704
    }
 
5705
    if (CMP8(CUR_PTR, '#', 'I', 'M', 'P', 'L', 'I', 'E', 'D')) {
 
5706
        SKIP(8);
 
5707
        return(XML_ATTRIBUTE_IMPLIED);
 
5708
    }
 
5709
    val = XML_ATTRIBUTE_NONE;
 
5710
    if (CMP6(CUR_PTR, '#', 'F', 'I', 'X', 'E', 'D')) {
 
5711
        SKIP(6);
 
5712
        val = XML_ATTRIBUTE_FIXED;
 
5713
        if (!IS_BLANK_CH(CUR)) {
 
5714
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5715
                           "Space required after '#FIXED'\n");
 
5716
        }
 
5717
        SKIP_BLANKS;
 
5718
    }
 
5719
    ret = xmlParseAttValue(ctxt);
 
5720
    ctxt->instate = XML_PARSER_DTD;
 
5721
    if (ret == NULL) {
 
5722
        xmlFatalErrMsg(ctxt, (xmlParserErrors)ctxt->errNo,
 
5723
                       "Attribute default value declaration error\n");
 
5724
    } else
 
5725
        *value = ret;
 
5726
    return(val);
 
5727
}
 
5728
 
 
5729
/**
 
5730
 * xmlParseNotationType:
 
5731
 * @ctxt:  an XML parser context
 
5732
 *
 
5733
 * parse an Notation attribute type.
 
5734
 *
 
5735
 * Note: the leading 'NOTATION' S part has already being parsed...
 
5736
 *
 
5737
 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
 
5738
 *
 
5739
 * [ VC: Notation Attributes ]
 
5740
 * Values of this type must match one of the notation names included
 
5741
 * in the declaration; all notation names in the declaration must be declared.
 
5742
 *
 
5743
 * Returns: the notation attribute tree built while parsing
 
5744
 */
 
5745
 
 
5746
xmlEnumerationPtr
 
5747
xmlParseNotationType(xmlParserCtxtPtr ctxt) {
 
5748
    const xmlChar *name;
 
5749
    xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
 
5750
 
 
5751
    if (RAW != '(') {
 
5752
        xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
 
5753
        return(NULL);
 
5754
    }
 
5755
    SHRINK;
 
5756
    do {
 
5757
        NEXT;
 
5758
        SKIP_BLANKS;
 
5759
        name = xmlParseName(ctxt);
 
5760
        if (name == NULL) {
 
5761
            xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
5762
                           "Name expected in NOTATION declaration\n");
 
5763
            xmlFreeEnumeration(ret);
 
5764
            return(NULL);
 
5765
        }
 
5766
        tmp = ret;
 
5767
        while (tmp != NULL) {
 
5768
            if (xmlStrEqual(name, tmp->name)) {
 
5769
                xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
 
5770
          "standalone: attribute notation value token %s duplicated\n",
 
5771
                                 name, NULL);
 
5772
                if (!xmlDictOwns(ctxt->dict, name))
 
5773
                    xmlFree((xmlChar *) name);
 
5774
                break;
 
5775
            }
 
5776
            tmp = tmp->next;
 
5777
        }
 
5778
        if (tmp == NULL) {
 
5779
            cur = xmlCreateEnumeration(name);
 
5780
            if (cur == NULL) {
 
5781
                xmlFreeEnumeration(ret);
 
5782
                return(NULL);
 
5783
            }
 
5784
            if (last == NULL) ret = last = cur;
 
5785
            else {
 
5786
                last->next = cur;
 
5787
                last = cur;
 
5788
            }
 
5789
        }
 
5790
        SKIP_BLANKS;
 
5791
    } while (RAW == '|');
 
5792
    if (RAW != ')') {
 
5793
        xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
 
5794
        xmlFreeEnumeration(ret);
 
5795
        return(NULL);
 
5796
    }
 
5797
    NEXT;
 
5798
    return(ret);
 
5799
}
 
5800
 
 
5801
/**
 
5802
 * xmlParseEnumerationType:
 
5803
 * @ctxt:  an XML parser context
 
5804
 *
 
5805
 * parse an Enumeration attribute type.
 
5806
 *
 
5807
 * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
 
5808
 *
 
5809
 * [ VC: Enumeration ]
 
5810
 * Values of this type must match one of the Nmtoken tokens in
 
5811
 * the declaration
 
5812
 *
 
5813
 * Returns: the enumeration attribute tree built while parsing
 
5814
 */
 
5815
 
 
5816
xmlEnumerationPtr
 
5817
xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
 
5818
    xmlChar *name;
 
5819
    xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
 
5820
 
 
5821
    if (RAW != '(') {
 
5822
        xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_STARTED, NULL);
 
5823
        return(NULL);
 
5824
    }
 
5825
    SHRINK;
 
5826
    do {
 
5827
        NEXT;
 
5828
        SKIP_BLANKS;
 
5829
        name = xmlParseNmtoken(ctxt);
 
5830
        if (name == NULL) {
 
5831
            xmlFatalErr(ctxt, XML_ERR_NMTOKEN_REQUIRED, NULL);
 
5832
            return(ret);
 
5833
        }
 
5834
        tmp = ret;
 
5835
        while (tmp != NULL) {
 
5836
            if (xmlStrEqual(name, tmp->name)) {
 
5837
                xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
 
5838
          "standalone: attribute enumeration value token %s duplicated\n",
 
5839
                                 name, NULL);
 
5840
                if (!xmlDictOwns(ctxt->dict, name))
 
5841
                    xmlFree(name);
 
5842
                break;
 
5843
            }
 
5844
            tmp = tmp->next;
 
5845
        }
 
5846
        if (tmp == NULL) {
 
5847
            cur = xmlCreateEnumeration(name);
 
5848
            if (!xmlDictOwns(ctxt->dict, name))
 
5849
                xmlFree(name);
 
5850
            if (cur == NULL) {
 
5851
                xmlFreeEnumeration(ret);
 
5852
                return(NULL);
 
5853
            }
 
5854
            if (last == NULL) ret = last = cur;
 
5855
            else {
 
5856
                last->next = cur;
 
5857
                last = cur;
 
5858
            }
 
5859
        }
 
5860
        SKIP_BLANKS;
 
5861
    } while (RAW == '|');
 
5862
    if (RAW != ')') {
 
5863
        xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_FINISHED, NULL);
 
5864
        return(ret);
 
5865
    }
 
5866
    NEXT;
 
5867
    return(ret);
 
5868
}
 
5869
 
 
5870
/**
 
5871
 * xmlParseEnumeratedType:
 
5872
 * @ctxt:  an XML parser context
 
5873
 * @tree:  the enumeration tree built while parsing
 
5874
 *
 
5875
 * parse an Enumerated attribute type.
 
5876
 *
 
5877
 * [57] EnumeratedType ::= NotationType | Enumeration
 
5878
 *
 
5879
 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
 
5880
 *
 
5881
 *
 
5882
 * Returns: XML_ATTRIBUTE_ENUMERATION or XML_ATTRIBUTE_NOTATION
 
5883
 */
 
5884
 
 
5885
int
 
5886
xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
 
5887
    if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
 
5888
        SKIP(8);
 
5889
        if (!IS_BLANK_CH(CUR)) {
 
5890
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
5891
                           "Space required after 'NOTATION'\n");
 
5892
            return(0);
 
5893
        }
 
5894
        SKIP_BLANKS;
 
5895
        *tree = xmlParseNotationType(ctxt);
 
5896
        if (*tree == NULL) return(0);
 
5897
        return(XML_ATTRIBUTE_NOTATION);
 
5898
    }
 
5899
    *tree = xmlParseEnumerationType(ctxt);
 
5900
    if (*tree == NULL) return(0);
 
5901
    return(XML_ATTRIBUTE_ENUMERATION);
 
5902
}
 
5903
 
 
5904
/**
 
5905
 * xmlParseAttributeType:
 
5906
 * @ctxt:  an XML parser context
 
5907
 * @tree:  the enumeration tree built while parsing
 
5908
 *
 
5909
 * parse the Attribute list def for an element
 
5910
 *
 
5911
 * [54] AttType ::= StringType | TokenizedType | EnumeratedType
 
5912
 *
 
5913
 * [55] StringType ::= 'CDATA'
 
5914
 *
 
5915
 * [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' |
 
5916
 *                        'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
 
5917
 *
 
5918
 * Validity constraints for attribute values syntax are checked in
 
5919
 * xmlValidateAttributeValue()
 
5920
 *
 
5921
 * [ VC: ID ]
 
5922
 * Values of type ID must match the Name production. A name must not
 
5923
 * appear more than once in an XML document as a value of this type;
 
5924
 * i.e., ID values must uniquely identify the elements which bear them.
 
5925
 *
 
5926
 * [ VC: One ID per Element Type ]
 
5927
 * No element type may have more than one ID attribute specified.
 
5928
 *
 
5929
 * [ VC: ID Attribute Default ]
 
5930
 * An ID attribute must have a declared default of #IMPLIED or #REQUIRED.
 
5931
 *
 
5932
 * [ VC: IDREF ]
 
5933
 * Values of type IDREF must match the Name production, and values
 
5934
 * of type IDREFS must match Names; each IDREF Name must match the value
 
5935
 * of an ID attribute on some element in the XML document; i.e. IDREF
 
5936
 * values must match the value of some ID attribute.
 
5937
 *
 
5938
 * [ VC: Entity Name ]
 
5939
 * Values of type ENTITY must match the Name production, values
 
5940
 * of type ENTITIES must match Names; each Entity Name must match the
 
5941
 * name of an unparsed entity declared in the DTD.
 
5942
 *
 
5943
 * [ VC: Name Token ]
 
5944
 * Values of type NMTOKEN must match the Nmtoken production; values
 
5945
 * of type NMTOKENS must match Nmtokens.
 
5946
 *
 
5947
 * Returns the attribute type
 
5948
 */
 
5949
int
 
5950
xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
 
5951
    SHRINK;
 
5952
    if (CMP5(CUR_PTR, 'C', 'D', 'A', 'T', 'A')) {
 
5953
        SKIP(5);
 
5954
        return(XML_ATTRIBUTE_CDATA);
 
5955
     } else if (CMP6(CUR_PTR, 'I', 'D', 'R', 'E', 'F', 'S')) {
 
5956
        SKIP(6);
 
5957
        return(XML_ATTRIBUTE_IDREFS);
 
5958
     } else if (CMP5(CUR_PTR, 'I', 'D', 'R', 'E', 'F')) {
 
5959
        SKIP(5);
 
5960
        return(XML_ATTRIBUTE_IDREF);
 
5961
     } else if ((RAW == 'I') && (NXT(1) == 'D')) {
 
5962
        SKIP(2);
 
5963
        return(XML_ATTRIBUTE_ID);
 
5964
     } else if (CMP6(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'Y')) {
 
5965
        SKIP(6);
 
5966
        return(XML_ATTRIBUTE_ENTITY);
 
5967
     } else if (CMP8(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S')) {
 
5968
        SKIP(8);
 
5969
        return(XML_ATTRIBUTE_ENTITIES);
 
5970
     } else if (CMP8(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S')) {
 
5971
        SKIP(8);
 
5972
        return(XML_ATTRIBUTE_NMTOKENS);
 
5973
     } else if (CMP7(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N')) {
 
5974
        SKIP(7);
 
5975
        return(XML_ATTRIBUTE_NMTOKEN);
 
5976
     }
 
5977
     return(xmlParseEnumeratedType(ctxt, tree));
 
5978
}
 
5979
 
 
5980
/**
 
5981
 * xmlParseAttributeListDecl:
 
5982
 * @ctxt:  an XML parser context
 
5983
 *
 
5984
 * : parse the Attribute list def for an element
 
5985
 *
 
5986
 * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
 
5987
 *
 
5988
 * [53] AttDef ::= S Name S AttType S DefaultDecl
 
5989
 *
 
5990
 */
 
5991
void
 
5992
xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
 
5993
    const xmlChar *elemName;
 
5994
    const xmlChar *attrName;
 
5995
    xmlEnumerationPtr tree;
 
5996
 
 
5997
    if (CMP9(CUR_PTR, '<', '!', 'A', 'T', 'T', 'L', 'I', 'S', 'T')) {
 
5998
        xmlParserInputPtr input = ctxt->input;
 
5999
 
 
6000
        SKIP(9);
 
6001
        if (!IS_BLANK_CH(CUR)) {
 
6002
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
6003
                                 "Space required after '<!ATTLIST'\n");
 
6004
        }
 
6005
        SKIP_BLANKS;
 
6006
        elemName = xmlParseName(ctxt);
 
6007
        if (elemName == NULL) {
 
6008
            xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
6009
                           "ATTLIST: no name for Element\n");
 
6010
            return;
 
6011
        }
 
6012
        SKIP_BLANKS;
 
6013
        GROW;
 
6014
        while ((RAW != '>') && (ctxt->instate != XML_PARSER_EOF)) {
 
6015
            const xmlChar *check = CUR_PTR;
 
6016
            int type;
 
6017
            int def;
 
6018
            xmlChar *defaultValue = NULL;
 
6019
 
 
6020
            GROW;
 
6021
            tree = NULL;
 
6022
            attrName = xmlParseName(ctxt);
 
6023
            if (attrName == NULL) {
 
6024
                xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
6025
                               "ATTLIST: no name for Attribute\n");
 
6026
                break;
 
6027
            }
 
6028
            GROW;
 
6029
            if (!IS_BLANK_CH(CUR)) {
 
6030
                xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
6031
                        "Space required after the attribute name\n");
 
6032
                break;
 
6033
            }
 
6034
            SKIP_BLANKS;
 
6035
 
 
6036
            type = xmlParseAttributeType(ctxt, &tree);
 
6037
            if (type <= 0) {
 
6038
                break;
 
6039
            }
 
6040
 
 
6041
            GROW;
 
6042
            if (!IS_BLANK_CH(CUR)) {
 
6043
                xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
6044
                               "Space required after the attribute type\n");
 
6045
                if (tree != NULL)
 
6046
                    xmlFreeEnumeration(tree);
 
6047
                break;
 
6048
            }
 
6049
            SKIP_BLANKS;
 
6050
 
 
6051
            def = xmlParseDefaultDecl(ctxt, &defaultValue);
 
6052
            if (def <= 0) {
 
6053
                if (defaultValue != NULL)
 
6054
                    xmlFree(defaultValue);
 
6055
                if (tree != NULL)
 
6056
                    xmlFreeEnumeration(tree);
 
6057
                break;
 
6058
            }
 
6059
            if ((type != XML_ATTRIBUTE_CDATA) && (defaultValue != NULL))
 
6060
                xmlAttrNormalizeSpace(defaultValue, defaultValue);
 
6061
 
 
6062
            GROW;
 
6063
            if (RAW != '>') {
 
6064
                if (!IS_BLANK_CH(CUR)) {
 
6065
                    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
6066
                        "Space required after the attribute default value\n");
 
6067
                    if (defaultValue != NULL)
 
6068
                        xmlFree(defaultValue);
 
6069
                    if (tree != NULL)
 
6070
                        xmlFreeEnumeration(tree);
 
6071
                    break;
 
6072
                }
 
6073
                SKIP_BLANKS;
 
6074
            }
 
6075
            if (check == CUR_PTR) {
 
6076
                xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
6077
                            "in xmlParseAttributeListDecl\n");
 
6078
                if (defaultValue != NULL)
 
6079
                    xmlFree(defaultValue);
 
6080
                if (tree != NULL)
 
6081
                    xmlFreeEnumeration(tree);
 
6082
                break;
 
6083
            }
 
6084
            if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
 
6085
                (ctxt->sax->attributeDecl != NULL))
 
6086
                ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
 
6087
                                type, def, defaultValue, tree);
 
6088
            else if (tree != NULL)
 
6089
                xmlFreeEnumeration(tree);
 
6090
 
 
6091
            if ((ctxt->sax2) && (defaultValue != NULL) &&
 
6092
                (def != XML_ATTRIBUTE_IMPLIED) &&
 
6093
                (def != XML_ATTRIBUTE_REQUIRED)) {
 
6094
                xmlAddDefAttrs(ctxt, elemName, attrName, defaultValue);
 
6095
            }
 
6096
            if (ctxt->sax2) {
 
6097
                xmlAddSpecialAttr(ctxt, elemName, attrName, type);
 
6098
            }
 
6099
            if (defaultValue != NULL)
 
6100
                xmlFree(defaultValue);
 
6101
            GROW;
 
6102
        }
 
6103
        if (RAW == '>') {
 
6104
            if (input != ctxt->input) {
 
6105
                xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
6106
    "Attribute list declaration doesn't start and stop in the same entity\n",
 
6107
                                 NULL, NULL);
 
6108
            }
 
6109
            NEXT;
 
6110
        }
 
6111
    }
 
6112
}
 
6113
 
 
6114
/**
 
6115
 * xmlParseElementMixedContentDecl:
 
6116
 * @ctxt:  an XML parser context
 
6117
 * @inputchk:  the input used for the current entity, needed for boundary checks
 
6118
 *
 
6119
 * parse the declaration for a Mixed Element content
 
6120
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
 
6121
 *
 
6122
 * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' |
 
6123
 *                '(' S? '#PCDATA' S? ')'
 
6124
 *
 
6125
 * [ VC: Proper Group/PE Nesting ] applies to [51] too (see [49])
 
6126
 *
 
6127
 * [ VC: No Duplicate Types ]
 
6128
 * The same name must not appear more than once in a single
 
6129
 * mixed-content declaration.
 
6130
 *
 
6131
 * returns: the list of the xmlElementContentPtr describing the element choices
 
6132
 */
 
6133
xmlElementContentPtr
 
6134
xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
 
6135
    xmlElementContentPtr ret = NULL, cur = NULL, n;
 
6136
    const xmlChar *elem = NULL;
 
6137
 
 
6138
    GROW;
 
6139
    if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
 
6140
        SKIP(7);
 
6141
        SKIP_BLANKS;
 
6142
        SHRINK;
 
6143
        if (RAW == ')') {
 
6144
            if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
 
6145
                xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
6146
"Element content declaration doesn't start and stop in the same entity\n",
 
6147
                                 NULL, NULL);
 
6148
            }
 
6149
            NEXT;
 
6150
            ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
 
6151
            if (ret == NULL)
 
6152
                return(NULL);
 
6153
            if (RAW == '*') {
 
6154
                ret->ocur = XML_ELEMENT_CONTENT_MULT;
 
6155
                NEXT;
 
6156
            }
 
6157
            return(ret);
 
6158
        }
 
6159
        if ((RAW == '(') || (RAW == '|')) {
 
6160
            ret = cur = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
 
6161
            if (ret == NULL) return(NULL);
 
6162
        }
 
6163
        while ((RAW == '|') && (ctxt->instate != XML_PARSER_EOF)) {
 
6164
            NEXT;
 
6165
            if (elem == NULL) {
 
6166
                ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
 
6167
                if (ret == NULL) return(NULL);
 
6168
                ret->c1 = cur;
 
6169
                if (cur != NULL)
 
6170
                    cur->parent = ret;
 
6171
                cur = ret;
 
6172
            } else {
 
6173
                n = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
 
6174
                if (n == NULL) return(NULL);
 
6175
                n->c1 = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
 
6176
                if (n->c1 != NULL)
 
6177
                    n->c1->parent = n;
 
6178
                cur->c2 = n;
 
6179
                if (n != NULL)
 
6180
                    n->parent = cur;
 
6181
                cur = n;
 
6182
            }
 
6183
            SKIP_BLANKS;
 
6184
            elem = xmlParseName(ctxt);
 
6185
            if (elem == NULL) {
 
6186
                xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
6187
                        "xmlParseElementMixedContentDecl : Name expected\n");
 
6188
                xmlFreeDocElementContent(ctxt->myDoc, cur);
 
6189
                return(NULL);
 
6190
            }
 
6191
            SKIP_BLANKS;
 
6192
            GROW;
 
6193
        }
 
6194
        if ((RAW == ')') && (NXT(1) == '*')) {
 
6195
            if (elem != NULL) {
 
6196
                cur->c2 = xmlNewDocElementContent(ctxt->myDoc, elem,
 
6197
                                               XML_ELEMENT_CONTENT_ELEMENT);
 
6198
                if (cur->c2 != NULL)
 
6199
                    cur->c2->parent = cur;
 
6200
            }
 
6201
            if (ret != NULL)
 
6202
                ret->ocur = XML_ELEMENT_CONTENT_MULT;
 
6203
            if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
 
6204
                xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
6205
"Element content declaration doesn't start and stop in the same entity\n",
 
6206
                                 NULL, NULL);
 
6207
            }
 
6208
            SKIP(2);
 
6209
        } else {
 
6210
            xmlFreeDocElementContent(ctxt->myDoc, ret);
 
6211
            xmlFatalErr(ctxt, XML_ERR_MIXED_NOT_STARTED, NULL);
 
6212
            return(NULL);
 
6213
        }
 
6214
 
 
6215
    } else {
 
6216
        xmlFatalErr(ctxt, XML_ERR_PCDATA_REQUIRED, NULL);
 
6217
    }
 
6218
    return(ret);
 
6219
}
 
6220
 
 
6221
/**
 
6222
 * xmlParseElementChildrenContentDeclPriv:
 
6223
 * @ctxt:  an XML parser context
 
6224
 * @inputchk:  the input used for the current entity, needed for boundary checks
 
6225
 * @depth: the level of recursion
 
6226
 *
 
6227
 * parse the declaration for a Mixed Element content
 
6228
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
 
6229
 *
 
6230
 *
 
6231
 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
 
6232
 *
 
6233
 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
 
6234
 *
 
6235
 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
 
6236
 *
 
6237
 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
 
6238
 *
 
6239
 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
 
6240
 * TODO Parameter-entity replacement text must be properly nested
 
6241
 *      with parenthesized groups. That is to say, if either of the
 
6242
 *      opening or closing parentheses in a choice, seq, or Mixed
 
6243
 *      construct is contained in the replacement text for a parameter
 
6244
 *      entity, both must be contained in the same replacement text. For
 
6245
 *      interoperability, if a parameter-entity reference appears in a
 
6246
 *      choice, seq, or Mixed construct, its replacement text should not
 
6247
 *      be empty, and neither the first nor last non-blank character of
 
6248
 *      the replacement text should be a connector (| or ,).
 
6249
 *
 
6250
 * Returns the tree of xmlElementContentPtr describing the element
 
6251
 *          hierarchy.
 
6252
 */
 
6253
static xmlElementContentPtr
 
6254
xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
 
6255
                                       int depth) {
 
6256
    xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
 
6257
    const xmlChar *elem;
 
6258
    xmlChar type = 0;
 
6259
 
 
6260
    if (((depth > 128) && ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
 
6261
        (depth >  2048)) {
 
6262
        xmlFatalErrMsgInt(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED,
 
6263
"xmlParseElementChildrenContentDecl : depth %d too deep, use XML_PARSE_HUGE\n",
 
6264
                          depth);
 
6265
        return(NULL);
 
6266
    }
 
6267
    SKIP_BLANKS;
 
6268
    GROW;
 
6269
    if (RAW == '(') {
 
6270
        int inputid = ctxt->input->id;
 
6271
 
 
6272
        /* Recurse on first child */
 
6273
        NEXT;
 
6274
        SKIP_BLANKS;
 
6275
        cur = ret = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
 
6276
                                                           depth + 1);
 
6277
        SKIP_BLANKS;
 
6278
        GROW;
 
6279
    } else {
 
6280
        elem = xmlParseName(ctxt);
 
6281
        if (elem == NULL) {
 
6282
            xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
 
6283
            return(NULL);
 
6284
        }
 
6285
        cur = ret = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
 
6286
        if (cur == NULL) {
 
6287
            xmlErrMemory(ctxt, NULL);
 
6288
            return(NULL);
 
6289
        }
 
6290
        GROW;
 
6291
        if (RAW == '?') {
 
6292
            cur->ocur = XML_ELEMENT_CONTENT_OPT;
 
6293
            NEXT;
 
6294
        } else if (RAW == '*') {
 
6295
            cur->ocur = XML_ELEMENT_CONTENT_MULT;
 
6296
            NEXT;
 
6297
        } else if (RAW == '+') {
 
6298
            cur->ocur = XML_ELEMENT_CONTENT_PLUS;
 
6299
            NEXT;
 
6300
        } else {
 
6301
            cur->ocur = XML_ELEMENT_CONTENT_ONCE;
 
6302
        }
 
6303
        GROW;
 
6304
    }
 
6305
    SKIP_BLANKS;
 
6306
    SHRINK;
 
6307
    while ((RAW != ')') && (ctxt->instate != XML_PARSER_EOF)) {
 
6308
        /*
 
6309
         * Each loop we parse one separator and one element.
 
6310
         */
 
6311
        if (RAW == ',') {
 
6312
            if (type == 0) type = CUR;
 
6313
 
 
6314
            /*
 
6315
             * Detect "Name | Name , Name" error
 
6316
             */
 
6317
            else if (type != CUR) {
 
6318
                xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
 
6319
                    "xmlParseElementChildrenContentDecl : '%c' expected\n",
 
6320
                                  type);
 
6321
                if ((last != NULL) && (last != ret))
 
6322
                    xmlFreeDocElementContent(ctxt->myDoc, last);
 
6323
                if (ret != NULL)
 
6324
                    xmlFreeDocElementContent(ctxt->myDoc, ret);
 
6325
                return(NULL);
 
6326
            }
 
6327
            NEXT;
 
6328
 
 
6329
            op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_SEQ);
 
6330
            if (op == NULL) {
 
6331
                if ((last != NULL) && (last != ret))
 
6332
                    xmlFreeDocElementContent(ctxt->myDoc, last);
 
6333
                xmlFreeDocElementContent(ctxt->myDoc, ret);
 
6334
                return(NULL);
 
6335
            }
 
6336
            if (last == NULL) {
 
6337
                op->c1 = ret;
 
6338
                if (ret != NULL)
 
6339
                    ret->parent = op;
 
6340
                ret = cur = op;
 
6341
            } else {
 
6342
                cur->c2 = op;
 
6343
                if (op != NULL)
 
6344
                    op->parent = cur;
 
6345
                op->c1 = last;
 
6346
                if (last != NULL)
 
6347
                    last->parent = op;
 
6348
                cur =op;
 
6349
                last = NULL;
 
6350
            }
 
6351
        } else if (RAW == '|') {
 
6352
            if (type == 0) type = CUR;
 
6353
 
 
6354
            /*
 
6355
             * Detect "Name , Name | Name" error
 
6356
             */
 
6357
            else if (type != CUR) {
 
6358
                xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
 
6359
                    "xmlParseElementChildrenContentDecl : '%c' expected\n",
 
6360
                                  type);
 
6361
                if ((last != NULL) && (last != ret))
 
6362
                    xmlFreeDocElementContent(ctxt->myDoc, last);
 
6363
                if (ret != NULL)
 
6364
                    xmlFreeDocElementContent(ctxt->myDoc, ret);
 
6365
                return(NULL);
 
6366
            }
 
6367
            NEXT;
 
6368
 
 
6369
            op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
 
6370
            if (op == NULL) {
 
6371
                if ((last != NULL) && (last != ret))
 
6372
                    xmlFreeDocElementContent(ctxt->myDoc, last);
 
6373
                if (ret != NULL)
 
6374
                    xmlFreeDocElementContent(ctxt->myDoc, ret);
 
6375
                return(NULL);
 
6376
            }
 
6377
            if (last == NULL) {
 
6378
                op->c1 = ret;
 
6379
                if (ret != NULL)
 
6380
                    ret->parent = op;
 
6381
                ret = cur = op;
 
6382
            } else {
 
6383
                cur->c2 = op;
 
6384
                if (op != NULL)
 
6385
                    op->parent = cur;
 
6386
                op->c1 = last;
 
6387
                if (last != NULL)
 
6388
                    last->parent = op;
 
6389
                cur =op;
 
6390
                last = NULL;
 
6391
            }
 
6392
        } else {
 
6393
            xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED, NULL);
 
6394
            if ((last != NULL) && (last != ret))
 
6395
                xmlFreeDocElementContent(ctxt->myDoc, last);
 
6396
            if (ret != NULL)
 
6397
                xmlFreeDocElementContent(ctxt->myDoc, ret);
 
6398
            return(NULL);
 
6399
        }
 
6400
        GROW;
 
6401
        SKIP_BLANKS;
 
6402
        GROW;
 
6403
        if (RAW == '(') {
 
6404
            int inputid = ctxt->input->id;
 
6405
            /* Recurse on second child */
 
6406
            NEXT;
 
6407
            SKIP_BLANKS;
 
6408
            last = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
 
6409
                                                          depth + 1);
 
6410
            SKIP_BLANKS;
 
6411
        } else {
 
6412
            elem = xmlParseName(ctxt);
 
6413
            if (elem == NULL) {
 
6414
                xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
 
6415
                if (ret != NULL)
 
6416
                    xmlFreeDocElementContent(ctxt->myDoc, ret);
 
6417
                return(NULL);
 
6418
            }
 
6419
            last = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
 
6420
            if (last == NULL) {
 
6421
                if (ret != NULL)
 
6422
                    xmlFreeDocElementContent(ctxt->myDoc, ret);
 
6423
                return(NULL);
 
6424
            }
 
6425
            if (RAW == '?') {
 
6426
                last->ocur = XML_ELEMENT_CONTENT_OPT;
 
6427
                NEXT;
 
6428
            } else if (RAW == '*') {
 
6429
                last->ocur = XML_ELEMENT_CONTENT_MULT;
 
6430
                NEXT;
 
6431
            } else if (RAW == '+') {
 
6432
                last->ocur = XML_ELEMENT_CONTENT_PLUS;
 
6433
                NEXT;
 
6434
            } else {
 
6435
                last->ocur = XML_ELEMENT_CONTENT_ONCE;
 
6436
            }
 
6437
        }
 
6438
        SKIP_BLANKS;
 
6439
        GROW;
 
6440
    }
 
6441
    if ((cur != NULL) && (last != NULL)) {
 
6442
        cur->c2 = last;
 
6443
        if (last != NULL)
 
6444
            last->parent = cur;
 
6445
    }
 
6446
    if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
 
6447
        xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
6448
"Element content declaration doesn't start and stop in the same entity\n",
 
6449
                         NULL, NULL);
 
6450
    }
 
6451
    NEXT;
 
6452
    if (RAW == '?') {
 
6453
        if (ret != NULL) {
 
6454
            if ((ret->ocur == XML_ELEMENT_CONTENT_PLUS) ||
 
6455
                (ret->ocur == XML_ELEMENT_CONTENT_MULT))
 
6456
                ret->ocur = XML_ELEMENT_CONTENT_MULT;
 
6457
            else
 
6458
                ret->ocur = XML_ELEMENT_CONTENT_OPT;
 
6459
        }
 
6460
        NEXT;
 
6461
    } else if (RAW == '*') {
 
6462
        if (ret != NULL) {
 
6463
            ret->ocur = XML_ELEMENT_CONTENT_MULT;
 
6464
            cur = ret;
 
6465
            /*
 
6466
             * Some normalization:
 
6467
             * (a | b* | c?)* == (a | b | c)*
 
6468
             */
 
6469
            while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
 
6470
                if ((cur->c1 != NULL) &&
 
6471
                    ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
 
6472
                     (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT)))
 
6473
                    cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
 
6474
                if ((cur->c2 != NULL) &&
 
6475
                    ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
 
6476
                     (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT)))
 
6477
                    cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
 
6478
                cur = cur->c2;
 
6479
            }
 
6480
        }
 
6481
        NEXT;
 
6482
    } else if (RAW == '+') {
 
6483
        if (ret != NULL) {
 
6484
            int found = 0;
 
6485
 
 
6486
            if ((ret->ocur == XML_ELEMENT_CONTENT_OPT) ||
 
6487
                (ret->ocur == XML_ELEMENT_CONTENT_MULT))
 
6488
                ret->ocur = XML_ELEMENT_CONTENT_MULT;
 
6489
            else
 
6490
                ret->ocur = XML_ELEMENT_CONTENT_PLUS;
 
6491
            /*
 
6492
             * Some normalization:
 
6493
             * (a | b*)+ == (a | b)*
 
6494
             * (a | b?)+ == (a | b)*
 
6495
             */
 
6496
            while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
 
6497
                if ((cur->c1 != NULL) &&
 
6498
                    ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
 
6499
                     (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT))) {
 
6500
                    cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
 
6501
                    found = 1;
 
6502
                }
 
6503
                if ((cur->c2 != NULL) &&
 
6504
                    ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
 
6505
                     (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT))) {
 
6506
                    cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
 
6507
                    found = 1;
 
6508
                }
 
6509
                cur = cur->c2;
 
6510
            }
 
6511
            if (found)
 
6512
                ret->ocur = XML_ELEMENT_CONTENT_MULT;
 
6513
        }
 
6514
        NEXT;
 
6515
    }
 
6516
    return(ret);
 
6517
}
 
6518
 
 
6519
/**
 
6520
 * xmlParseElementChildrenContentDecl:
 
6521
 * @ctxt:  an XML parser context
 
6522
 * @inputchk:  the input used for the current entity, needed for boundary checks
 
6523
 *
 
6524
 * parse the declaration for a Mixed Element content
 
6525
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
 
6526
 *
 
6527
 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
 
6528
 *
 
6529
 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
 
6530
 *
 
6531
 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
 
6532
 *
 
6533
 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
 
6534
 *
 
6535
 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
 
6536
 * TODO Parameter-entity replacement text must be properly nested
 
6537
 *      with parenthesized groups. That is to say, if either of the
 
6538
 *      opening or closing parentheses in a choice, seq, or Mixed
 
6539
 *      construct is contained in the replacement text for a parameter
 
6540
 *      entity, both must be contained in the same replacement text. For
 
6541
 *      interoperability, if a parameter-entity reference appears in a
 
6542
 *      choice, seq, or Mixed construct, its replacement text should not
 
6543
 *      be empty, and neither the first nor last non-blank character of
 
6544
 *      the replacement text should be a connector (| or ,).
 
6545
 *
 
6546
 * Returns the tree of xmlElementContentPtr describing the element
 
6547
 *          hierarchy.
 
6548
 */
 
6549
xmlElementContentPtr
 
6550
xmlParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
 
6551
    /* stub left for API/ABI compat */
 
6552
    return(xmlParseElementChildrenContentDeclPriv(ctxt, inputchk, 1));
 
6553
}
 
6554
 
 
6555
/**
 
6556
 * xmlParseElementContentDecl:
 
6557
 * @ctxt:  an XML parser context
 
6558
 * @name:  the name of the element being defined.
 
6559
 * @result:  the Element Content pointer will be stored here if any
 
6560
 *
 
6561
 * parse the declaration for an Element content either Mixed or Children,
 
6562
 * the cases EMPTY and ANY are handled directly in xmlParseElementDecl
 
6563
 *
 
6564
 * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
 
6565
 *
 
6566
 * returns: the type of element content XML_ELEMENT_TYPE_xxx
 
6567
 */
 
6568
 
 
6569
int
 
6570
xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, const xmlChar *name,
 
6571
                           xmlElementContentPtr *result) {
 
6572
 
 
6573
    xmlElementContentPtr tree = NULL;
 
6574
    int inputid = ctxt->input->id;
 
6575
    int res;
 
6576
 
 
6577
    *result = NULL;
 
6578
 
 
6579
    if (RAW != '(') {
 
6580
        xmlFatalErrMsgStr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
 
6581
                "xmlParseElementContentDecl : %s '(' expected\n", name);
 
6582
        return(-1);
 
6583
    }
 
6584
    NEXT;
 
6585
    GROW;
 
6586
    if (ctxt->instate == XML_PARSER_EOF)
 
6587
        return(-1);
 
6588
    SKIP_BLANKS;
 
6589
    if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
 
6590
        tree = xmlParseElementMixedContentDecl(ctxt, inputid);
 
6591
        res = XML_ELEMENT_TYPE_MIXED;
 
6592
    } else {
 
6593
        tree = xmlParseElementChildrenContentDeclPriv(ctxt, inputid, 1);
 
6594
        res = XML_ELEMENT_TYPE_ELEMENT;
 
6595
    }
 
6596
    SKIP_BLANKS;
 
6597
    *result = tree;
 
6598
    return(res);
 
6599
}
 
6600
 
 
6601
/**
 
6602
 * xmlParseElementDecl:
 
6603
 * @ctxt:  an XML parser context
 
6604
 *
 
6605
 * parse an Element declaration.
 
6606
 *
 
6607
 * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
 
6608
 *
 
6609
 * [ VC: Unique Element Type Declaration ]
 
6610
 * No element type may be declared more than once
 
6611
 *
 
6612
 * Returns the type of the element, or -1 in case of error
 
6613
 */
 
6614
int
 
6615
xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
 
6616
    const xmlChar *name;
 
6617
    int ret = -1;
 
6618
    xmlElementContentPtr content  = NULL;
 
6619
 
 
6620
    /* GROW; done in the caller */
 
6621
    if (CMP9(CUR_PTR, '<', '!', 'E', 'L', 'E', 'M', 'E', 'N', 'T')) {
 
6622
        xmlParserInputPtr input = ctxt->input;
 
6623
 
 
6624
        SKIP(9);
 
6625
        if (!IS_BLANK_CH(CUR)) {
 
6626
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
6627
                           "Space required after 'ELEMENT'\n");
 
6628
        }
 
6629
        SKIP_BLANKS;
 
6630
        name = xmlParseName(ctxt);
 
6631
        if (name == NULL) {
 
6632
            xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
6633
                           "xmlParseElementDecl: no name for Element\n");
 
6634
            return(-1);
 
6635
        }
 
6636
        while ((RAW == 0) && (ctxt->inputNr > 1))
 
6637
            xmlPopInput(ctxt);
 
6638
        if (!IS_BLANK_CH(CUR)) {
 
6639
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
6640
                           "Space required after the element name\n");
 
6641
        }
 
6642
        SKIP_BLANKS;
 
6643
        if (CMP5(CUR_PTR, 'E', 'M', 'P', 'T', 'Y')) {
 
6644
            SKIP(5);
 
6645
            /*
 
6646
             * Element must always be empty.
 
6647
             */
 
6648
            ret = XML_ELEMENT_TYPE_EMPTY;
 
6649
        } else if ((RAW == 'A') && (NXT(1) == 'N') &&
 
6650
                   (NXT(2) == 'Y')) {
 
6651
            SKIP(3);
 
6652
            /*
 
6653
             * Element is a generic container.
 
6654
             */
 
6655
            ret = XML_ELEMENT_TYPE_ANY;
 
6656
        } else if (RAW == '(') {
 
6657
            ret = xmlParseElementContentDecl(ctxt, name, &content);
 
6658
        } else {
 
6659
            /*
 
6660
             * [ WFC: PEs in Internal Subset ] error handling.
 
6661
             */
 
6662
            if ((RAW == '%') && (ctxt->external == 0) &&
 
6663
                (ctxt->inputNr == 1)) {
 
6664
                xmlFatalErrMsg(ctxt, XML_ERR_PEREF_IN_INT_SUBSET,
 
6665
          "PEReference: forbidden within markup decl in internal subset\n");
 
6666
            } else {
 
6667
                xmlFatalErrMsg(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
 
6668
                      "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
 
6669
            }
 
6670
            return(-1);
 
6671
        }
 
6672
 
 
6673
        SKIP_BLANKS;
 
6674
        /*
 
6675
         * Pop-up of finished entities.
 
6676
         */
 
6677
        while ((RAW == 0) && (ctxt->inputNr > 1))
 
6678
            xmlPopInput(ctxt);
 
6679
        SKIP_BLANKS;
 
6680
 
 
6681
        if (RAW != '>') {
 
6682
            xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
 
6683
            if (content != NULL) {
 
6684
                xmlFreeDocElementContent(ctxt->myDoc, content);
 
6685
            }
 
6686
        } else {
 
6687
            if (input != ctxt->input) {
 
6688
                xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
6689
    "Element declaration doesn't start and stop in the same entity\n");
 
6690
            }
 
6691
 
 
6692
            NEXT;
 
6693
            if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
 
6694
                (ctxt->sax->elementDecl != NULL)) {
 
6695
                if (content != NULL)
 
6696
                    content->parent = NULL;
 
6697
                ctxt->sax->elementDecl(ctxt->userData, name, ret,
 
6698
                                       content);
 
6699
                if ((content != NULL) && (content->parent == NULL)) {
 
6700
                    /*
 
6701
                     * this is a trick: if xmlAddElementDecl is called,
 
6702
                     * instead of copying the full tree it is plugged directly
 
6703
                     * if called from the parser. Avoid duplicating the
 
6704
                     * interfaces or change the API/ABI
 
6705
                     */
 
6706
                    xmlFreeDocElementContent(ctxt->myDoc, content);
 
6707
                }
 
6708
            } else if (content != NULL) {
 
6709
                xmlFreeDocElementContent(ctxt->myDoc, content);
 
6710
            }
 
6711
        }
 
6712
    }
 
6713
    return(ret);
 
6714
}
 
6715
 
 
6716
/**
 
6717
 * xmlParseConditionalSections
 
6718
 * @ctxt:  an XML parser context
 
6719
 *
 
6720
 * [61] conditionalSect ::= includeSect | ignoreSect
 
6721
 * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
 
6722
 * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
 
6723
 * [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
 
6724
 * [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
 
6725
 */
 
6726
 
 
6727
static void
 
6728
xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
 
6729
    int id = ctxt->input->id;
 
6730
 
 
6731
    SKIP(3);
 
6732
    SKIP_BLANKS;
 
6733
    if (CMP7(CUR_PTR, 'I', 'N', 'C', 'L', 'U', 'D', 'E')) {
 
6734
        SKIP(7);
 
6735
        SKIP_BLANKS;
 
6736
        if (RAW != '[') {
 
6737
            xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
 
6738
        } else {
 
6739
            if (ctxt->input->id != id) {
 
6740
                xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
6741
            "All markup of the conditional section is not in the same entity\n",
 
6742
                                     NULL, NULL);
 
6743
            }
 
6744
            NEXT;
 
6745
        }
 
6746
        if (xmlParserDebugEntities) {
 
6747
            if ((ctxt->input != NULL) && (ctxt->input->filename))
 
6748
                xmlGenericError(xmlGenericErrorContext,
 
6749
                        "%s(%d): ", ctxt->input->filename,
 
6750
                        ctxt->input->line);
 
6751
            xmlGenericError(xmlGenericErrorContext,
 
6752
                    "Entering INCLUDE Conditional Section\n");
 
6753
        }
 
6754
 
 
6755
        while (((RAW != 0) && ((RAW != ']') || (NXT(1) != ']') ||
 
6756
                (NXT(2) != '>'))) && (ctxt->instate != XML_PARSER_EOF)) {
 
6757
            const xmlChar *check = CUR_PTR;
 
6758
            unsigned int cons = ctxt->input->consumed;
 
6759
 
 
6760
            if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
 
6761
                xmlParseConditionalSections(ctxt);
 
6762
            } else if (IS_BLANK_CH(CUR)) {
 
6763
                NEXT;
 
6764
            } else if (RAW == '%') {
 
6765
                xmlParsePEReference(ctxt);
 
6766
            } else
 
6767
                xmlParseMarkupDecl(ctxt);
 
6768
 
 
6769
            /*
 
6770
             * Pop-up of finished entities.
 
6771
             */
 
6772
            while ((RAW == 0) && (ctxt->inputNr > 1))
 
6773
                xmlPopInput(ctxt);
 
6774
 
 
6775
            if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
 
6776
                xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
 
6777
                break;
 
6778
            }
 
6779
        }
 
6780
        if (xmlParserDebugEntities) {
 
6781
            if ((ctxt->input != NULL) && (ctxt->input->filename))
 
6782
                xmlGenericError(xmlGenericErrorContext,
 
6783
                        "%s(%d): ", ctxt->input->filename,
 
6784
                        ctxt->input->line);
 
6785
            xmlGenericError(xmlGenericErrorContext,
 
6786
                    "Leaving INCLUDE Conditional Section\n");
 
6787
        }
 
6788
 
 
6789
    } else if (CMP6(CUR_PTR, 'I', 'G', 'N', 'O', 'R', 'E')) {
 
6790
        int state;
 
6791
        xmlParserInputState instate;
 
6792
        int depth = 0;
 
6793
 
 
6794
        SKIP(6);
 
6795
        SKIP_BLANKS;
 
6796
        if (RAW != '[') {
 
6797
            xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
 
6798
        } else {
 
6799
            if (ctxt->input->id != id) {
 
6800
                xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
6801
            "All markup of the conditional section is not in the same entity\n",
 
6802
                                     NULL, NULL);
 
6803
            }
 
6804
            NEXT;
 
6805
        }
 
6806
        if (xmlParserDebugEntities) {
 
6807
            if ((ctxt->input != NULL) && (ctxt->input->filename))
 
6808
                xmlGenericError(xmlGenericErrorContext,
 
6809
                        "%s(%d): ", ctxt->input->filename,
 
6810
                        ctxt->input->line);
 
6811
            xmlGenericError(xmlGenericErrorContext,
 
6812
                    "Entering IGNORE Conditional Section\n");
 
6813
        }
 
6814
 
 
6815
        /*
 
6816
         * Parse up to the end of the conditional section
 
6817
         * But disable SAX event generating DTD building in the meantime
 
6818
         */
 
6819
        state = ctxt->disableSAX;
 
6820
        instate = ctxt->instate;
 
6821
        if (ctxt->recovery == 0) ctxt->disableSAX = 1;
 
6822
        ctxt->instate = XML_PARSER_IGNORE;
 
6823
 
 
6824
        while (((depth >= 0) && (RAW != 0)) &&
 
6825
               (ctxt->instate != XML_PARSER_EOF)) {
 
6826
          if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
 
6827
            depth++;
 
6828
            SKIP(3);
 
6829
            continue;
 
6830
          }
 
6831
          if ((RAW == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
 
6832
            if (--depth >= 0) SKIP(3);
 
6833
            continue;
 
6834
          }
 
6835
          NEXT;
 
6836
          continue;
 
6837
        }
 
6838
 
 
6839
        ctxt->disableSAX = state;
 
6840
        ctxt->instate = instate;
 
6841
 
 
6842
        if (xmlParserDebugEntities) {
 
6843
            if ((ctxt->input != NULL) && (ctxt->input->filename))
 
6844
                xmlGenericError(xmlGenericErrorContext,
 
6845
                        "%s(%d): ", ctxt->input->filename,
 
6846
                        ctxt->input->line);
 
6847
            xmlGenericError(xmlGenericErrorContext,
 
6848
                    "Leaving IGNORE Conditional Section\n");
 
6849
        }
 
6850
 
 
6851
    } else {
 
6852
        xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
 
6853
    }
 
6854
 
 
6855
    if (RAW == 0)
 
6856
        SHRINK;
 
6857
 
 
6858
    if (RAW == 0) {
 
6859
        xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
 
6860
    } else {
 
6861
        if (ctxt->input->id != id) {
 
6862
            xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
 
6863
        "All markup of the conditional section is not in the same entity\n",
 
6864
                                 NULL, NULL);
 
6865
        }
 
6866
        SKIP(3);
 
6867
    }
 
6868
}
 
6869
 
 
6870
/**
 
6871
 * xmlParseMarkupDecl:
 
6872
 * @ctxt:  an XML parser context
 
6873
 *
 
6874
 * parse Markup declarations
 
6875
 *
 
6876
 * [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
 
6877
 *                     NotationDecl | PI | Comment
 
6878
 *
 
6879
 * [ VC: Proper Declaration/PE Nesting ]
 
6880
 * Parameter-entity replacement text must be properly nested with
 
6881
 * markup declarations. That is to say, if either the first character
 
6882
 * or the last character of a markup declaration (markupdecl above) is
 
6883
 * contained in the replacement text for a parameter-entity reference,
 
6884
 * both must be contained in the same replacement text.
 
6885
 *
 
6886
 * [ WFC: PEs in Internal Subset ]
 
6887
 * In the internal DTD subset, parameter-entity references can occur
 
6888
 * only where markup declarations can occur, not within markup declarations.
 
6889
 * (This does not apply to references that occur in external parameter
 
6890
 * entities or to the external subset.)
 
6891
 */
 
6892
void
 
6893
xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
 
6894
    GROW;
 
6895
    if (CUR == '<') {
 
6896
        if (NXT(1) == '!') {
 
6897
            switch (NXT(2)) {
 
6898
                case 'E':
 
6899
                    if (NXT(3) == 'L')
 
6900
                        xmlParseElementDecl(ctxt);
 
6901
                    else if (NXT(3) == 'N')
 
6902
                        xmlParseEntityDecl(ctxt);
 
6903
                    break;
 
6904
                case 'A':
 
6905
                    xmlParseAttributeListDecl(ctxt);
 
6906
                    break;
 
6907
                case 'N':
 
6908
                    xmlParseNotationDecl(ctxt);
 
6909
                    break;
 
6910
                case '-':
 
6911
                    xmlParseComment(ctxt);
 
6912
                    break;
 
6913
                default:
 
6914
                    /* there is an error but it will be detected later */
 
6915
                    break;
 
6916
            }
 
6917
        } else if (NXT(1) == '?') {
 
6918
            xmlParsePI(ctxt);
 
6919
        }
 
6920
    }
 
6921
    /*
 
6922
     * This is only for internal subset. On external entities,
 
6923
     * the replacement is done before parsing stage
 
6924
     */
 
6925
    if ((ctxt->external == 0) && (ctxt->inputNr == 1))
 
6926
        xmlParsePEReference(ctxt);
 
6927
 
 
6928
    /*
 
6929
     * Conditional sections are allowed from entities included
 
6930
     * by PE References in the internal subset.
 
6931
     */
 
6932
    if ((ctxt->external == 0) && (ctxt->inputNr > 1)) {
 
6933
        if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
 
6934
            xmlParseConditionalSections(ctxt);
 
6935
        }
 
6936
    }
 
6937
 
 
6938
    ctxt->instate = XML_PARSER_DTD;
 
6939
}
 
6940
 
 
6941
/**
 
6942
 * xmlParseTextDecl:
 
6943
 * @ctxt:  an XML parser context
 
6944
 *
 
6945
 * parse an XML declaration header for external entities
 
6946
 *
 
6947
 * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
 
6948
 */
 
6949
 
 
6950
void
 
6951
xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
 
6952
    xmlChar *version;
 
6953
    const xmlChar *encoding;
 
6954
 
 
6955
    /*
 
6956
     * We know that '<?xml' is here.
 
6957
     */
 
6958
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
 
6959
        SKIP(5);
 
6960
    } else {
 
6961
        xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_STARTED, NULL);
 
6962
        return;
 
6963
    }
 
6964
 
 
6965
    if (!IS_BLANK_CH(CUR)) {
 
6966
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
6967
                       "Space needed after '<?xml'\n");
 
6968
    }
 
6969
    SKIP_BLANKS;
 
6970
 
 
6971
    /*
 
6972
     * We may have the VersionInfo here.
 
6973
     */
 
6974
    version = xmlParseVersionInfo(ctxt);
 
6975
    if (version == NULL)
 
6976
        version = xmlCharStrdup(XML_DEFAULT_VERSION);
 
6977
    else {
 
6978
        if (!IS_BLANK_CH(CUR)) {
 
6979
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
6980
                           "Space needed here\n");
 
6981
        }
 
6982
    }
 
6983
    ctxt->input->version = version;
 
6984
 
 
6985
    /*
 
6986
     * We must have the encoding declaration
 
6987
     */
 
6988
    encoding = xmlParseEncodingDecl(ctxt);
 
6989
    if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
 
6990
        /*
 
6991
         * The XML REC instructs us to stop parsing right here
 
6992
         */
 
6993
        return;
 
6994
    }
 
6995
    if ((encoding == NULL) && (ctxt->errNo == XML_ERR_OK)) {
 
6996
        xmlFatalErrMsg(ctxt, XML_ERR_MISSING_ENCODING,
 
6997
                       "Missing encoding in text declaration\n");
 
6998
    }
 
6999
 
 
7000
    SKIP_BLANKS;
 
7001
    if ((RAW == '?') && (NXT(1) == '>')) {
 
7002
        SKIP(2);
 
7003
    } else if (RAW == '>') {
 
7004
        /* Deprecated old WD ... */
 
7005
        xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
 
7006
        NEXT;
 
7007
    } else {
 
7008
        xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
 
7009
        MOVETO_ENDTAG(CUR_PTR);
 
7010
        NEXT;
 
7011
    }
 
7012
}
 
7013
 
 
7014
/**
 
7015
 * xmlParseExternalSubset:
 
7016
 * @ctxt:  an XML parser context
 
7017
 * @ExternalID: the external identifier
 
7018
 * @SystemID: the system identifier (or URL)
 
7019
 *
 
7020
 * parse Markup declarations from an external subset
 
7021
 *
 
7022
 * [30] extSubset ::= textDecl? extSubsetDecl
 
7023
 *
 
7024
 * [31] extSubsetDecl ::= (markupdecl | conditionalSect | PEReference | S) *
 
7025
 */
 
7026
void
 
7027
xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
 
7028
                       const xmlChar *SystemID) {
 
7029
    xmlDetectSAX2(ctxt);
 
7030
    GROW;
 
7031
 
 
7032
    if ((ctxt->encoding == NULL) &&
 
7033
        (ctxt->input->end - ctxt->input->cur >= 4)) {
 
7034
        xmlChar start[4];
 
7035
        xmlCharEncoding enc;
 
7036
 
 
7037
        start[0] = RAW;
 
7038
        start[1] = NXT(1);
 
7039
        start[2] = NXT(2);
 
7040
        start[3] = NXT(3);
 
7041
        enc = xmlDetectCharEncoding(start, 4);
 
7042
        if (enc != XML_CHAR_ENCODING_NONE)
 
7043
            xmlSwitchEncoding(ctxt, enc);
 
7044
    }
 
7045
 
 
7046
    if (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) {
 
7047
        xmlParseTextDecl(ctxt);
 
7048
        if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
 
7049
            /*
 
7050
             * The XML REC instructs us to stop parsing right here
 
7051
             */
 
7052
            ctxt->instate = XML_PARSER_EOF;
 
7053
            return;
 
7054
        }
 
7055
    }
 
7056
    if (ctxt->myDoc == NULL) {
 
7057
        ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
 
7058
        if (ctxt->myDoc == NULL) {
 
7059
            xmlErrMemory(ctxt, "New Doc failed");
 
7060
            return;
 
7061
        }
 
7062
        ctxt->myDoc->properties = XML_DOC_INTERNAL;
 
7063
    }
 
7064
    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
 
7065
        xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
 
7066
 
 
7067
    ctxt->instate = XML_PARSER_DTD;
 
7068
    ctxt->external = 1;
 
7069
    while (((RAW == '<') && (NXT(1) == '?')) ||
 
7070
           ((RAW == '<') && (NXT(1) == '!')) ||
 
7071
           (RAW == '%') || IS_BLANK_CH(CUR)) {
 
7072
        const xmlChar *check = CUR_PTR;
 
7073
        unsigned int cons = ctxt->input->consumed;
 
7074
 
 
7075
        GROW;
 
7076
        if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
 
7077
            xmlParseConditionalSections(ctxt);
 
7078
        } else if (IS_BLANK_CH(CUR)) {
 
7079
            NEXT;
 
7080
        } else if (RAW == '%') {
 
7081
            xmlParsePEReference(ctxt);
 
7082
        } else
 
7083
            xmlParseMarkupDecl(ctxt);
 
7084
 
 
7085
        /*
 
7086
         * Pop-up of finished entities.
 
7087
         */
 
7088
        while ((RAW == 0) && (ctxt->inputNr > 1))
 
7089
            xmlPopInput(ctxt);
 
7090
 
 
7091
        if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
 
7092
            xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
 
7093
            break;
 
7094
        }
 
7095
    }
 
7096
 
 
7097
    if (RAW != 0) {
 
7098
        xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
 
7099
    }
 
7100
 
 
7101
}
 
7102
 
 
7103
/**
 
7104
 * xmlParseReference:
 
7105
 * @ctxt:  an XML parser context
 
7106
 *
 
7107
 * parse and handle entity references in content, depending on the SAX
 
7108
 * interface, this may end-up in a call to character() if this is a
 
7109
 * CharRef, a predefined entity, if there is no reference() callback.
 
7110
 * or if the parser was asked to switch to that mode.
 
7111
 *
 
7112
 * [67] Reference ::= EntityRef | CharRef
 
7113
 */
 
7114
void
 
7115
xmlParseReference(xmlParserCtxtPtr ctxt) {
 
7116
    xmlEntityPtr ent;
 
7117
    xmlChar *val;
 
7118
    int was_checked;
 
7119
    xmlNodePtr list = NULL;
 
7120
    xmlParserErrors ret = XML_ERR_OK;
 
7121
 
 
7122
 
 
7123
    if (RAW != '&')
 
7124
        return;
 
7125
 
 
7126
    /*
 
7127
     * Simple case of a CharRef
 
7128
     */
 
7129
    if (NXT(1) == '#') {
 
7130
        int i = 0;
 
7131
        xmlChar out[10];
 
7132
        int hex = NXT(2);
 
7133
        int value = xmlParseCharRef(ctxt);
 
7134
 
 
7135
        if (value == 0)
 
7136
            return;
 
7137
        if (ctxt->charset != XML_CHAR_ENCODING_UTF8) {
 
7138
            /*
 
7139
             * So we are using non-UTF-8 buffers
 
7140
             * Check that the char fit on 8bits, if not
 
7141
             * generate a CharRef.
 
7142
             */
 
7143
            if (value <= 0xFF) {
 
7144
                out[0] = value;
 
7145
                out[1] = 0;
 
7146
                if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
 
7147
                    (!ctxt->disableSAX))
 
7148
                    ctxt->sax->characters(ctxt->userData, out, 1);
 
7149
            } else {
 
7150
                if ((hex == 'x') || (hex == 'X'))
 
7151
                    snprintf((char *)out, sizeof(out), "#x%X", value);
 
7152
                else
 
7153
                    snprintf((char *)out, sizeof(out), "#%d", value);
 
7154
                if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
 
7155
                    (!ctxt->disableSAX))
 
7156
                    ctxt->sax->reference(ctxt->userData, out);
 
7157
            }
 
7158
        } else {
 
7159
            /*
 
7160
             * Just encode the value in UTF-8
 
7161
             */
 
7162
            COPY_BUF(0 ,out, i, value);
 
7163
            out[i] = 0;
 
7164
            if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
 
7165
                (!ctxt->disableSAX))
 
7166
                ctxt->sax->characters(ctxt->userData, out, i);
 
7167
        }
 
7168
        return;
 
7169
    }
 
7170
 
 
7171
    /*
 
7172
     * We are seeing an entity reference
 
7173
     */
 
7174
    ent = xmlParseEntityRef(ctxt);
 
7175
    if (ent == NULL) return;
 
7176
    if (!ctxt->wellFormed)
 
7177
        return;
 
7178
    was_checked = ent->checked;
 
7179
 
 
7180
    /* special case of predefined entities */
 
7181
    if ((ent->name == NULL) ||
 
7182
        (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
 
7183
        val = ent->content;
 
7184
        if (val == NULL) return;
 
7185
        /*
 
7186
         * inline the entity.
 
7187
         */
 
7188
        if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
 
7189
            (!ctxt->disableSAX))
 
7190
            ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
 
7191
        return;
 
7192
    }
 
7193
 
 
7194
    /*
 
7195
     * The first reference to the entity trigger a parsing phase
 
7196
     * where the ent->children is filled with the result from
 
7197
     * the parsing.
 
7198
     * Note: external parsed entities will not be loaded, it is not
 
7199
     * required for a non-validating parser, unless the parsing option
 
7200
     * of validating, or substituting entities were given. Doing so is
 
7201
     * far more secure as the parser will only process data coming from
 
7202
     * the document entity by default.
 
7203
     */
 
7204
    if ((ent->checked == 0) &&
 
7205
        ((ent->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY) ||
 
7206
         (ctxt->options & (XML_PARSE_NOENT | XML_PARSE_DTDVALID)))) {
 
7207
        unsigned long oldnbent = ctxt->nbentities;
 
7208
 
 
7209
        /*
 
7210
         * This is a bit hackish but this seems the best
 
7211
         * way to make sure both SAX and DOM entity support
 
7212
         * behaves okay.
 
7213
         */
 
7214
        void *user_data;
 
7215
        if (ctxt->userData == ctxt)
 
7216
            user_data = NULL;
 
7217
        else
 
7218
            user_data = ctxt->userData;
 
7219
 
 
7220
        /*
 
7221
         * Check that this entity is well formed
 
7222
         * 4.3.2: An internal general parsed entity is well-formed
 
7223
         * if its replacement text matches the production labeled
 
7224
         * content.
 
7225
         */
 
7226
        if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
 
7227
            ctxt->depth++;
 
7228
            ret = xmlParseBalancedChunkMemoryInternal(ctxt, ent->content,
 
7229
                                                      user_data, &list);
 
7230
            ctxt->depth--;
 
7231
 
 
7232
        } else if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
 
7233
            ctxt->depth++;
 
7234
            ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt, ctxt->sax,
 
7235
                                           user_data, ctxt->depth, ent->URI,
 
7236
                                           ent->ExternalID, &list);
 
7237
            ctxt->depth--;
 
7238
        } else {
 
7239
            ret = XML_ERR_ENTITY_PE_INTERNAL;
 
7240
            xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
 
7241
                         "invalid entity type found\n", NULL);
 
7242
        }
 
7243
 
 
7244
        /*
 
7245
         * Store the number of entities needing parsing for this entity
 
7246
         * content and do checkings
 
7247
         */
 
7248
        ent->checked = (ctxt->nbentities - oldnbent + 1) * 2;
 
7249
        if ((ent->content != NULL) && (xmlStrchr(ent->content, '<')))
 
7250
            ent->checked |= 1;
 
7251
        if (ret == XML_ERR_ENTITY_LOOP) {
 
7252
            xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
 
7253
            xmlFreeNodeList(list);
 
7254
            return;
 
7255
        }
 
7256
        if (xmlParserEntityCheck(ctxt, 0, ent, 0)) {
 
7257
            xmlFreeNodeList(list);
 
7258
            return;
 
7259
        }
 
7260
 
 
7261
        if ((ret == XML_ERR_OK) && (list != NULL)) {
 
7262
            if (((ent->etype == XML_INTERNAL_GENERAL_ENTITY) ||
 
7263
             (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY))&&
 
7264
                (ent->children == NULL)) {
 
7265
                ent->children = list;
 
7266
                if (ctxt->replaceEntities) {
 
7267
                    /*
 
7268
                     * Prune it directly in the generated document
 
7269
                     * except for single text nodes.
 
7270
                     */
 
7271
                    if (((list->type == XML_TEXT_NODE) &&
 
7272
                         (list->next == NULL)) ||
 
7273
                        (ctxt->parseMode == XML_PARSE_READER)) {
 
7274
                        list->parent = (xmlNodePtr) ent;
 
7275
                        list = NULL;
 
7276
                        ent->owner = 1;
 
7277
                    } else {
 
7278
                        ent->owner = 0;
 
7279
                        while (list != NULL) {
 
7280
                            list->parent = (xmlNodePtr) ctxt->node;
 
7281
                            list->doc = ctxt->myDoc;
 
7282
                            if (list->next == NULL)
 
7283
                                ent->last = list;
 
7284
                            list = list->next;
 
7285
                        }
 
7286
                        list = ent->children;
 
7287
#ifdef LIBXML_LEGACY_ENABLED
 
7288
                        if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
 
7289
                          xmlAddEntityReference(ent, list, NULL);
 
7290
#endif /* LIBXML_LEGACY_ENABLED */
 
7291
                    }
 
7292
                } else {
 
7293
                    ent->owner = 1;
 
7294
                    while (list != NULL) {
 
7295
                        list->parent = (xmlNodePtr) ent;
 
7296
                        xmlSetTreeDoc(list, ent->doc);
 
7297
                        if (list->next == NULL)
 
7298
                            ent->last = list;
 
7299
                        list = list->next;
 
7300
                    }
 
7301
                }
 
7302
            } else {
 
7303
                xmlFreeNodeList(list);
 
7304
                list = NULL;
 
7305
            }
 
7306
        } else if ((ret != XML_ERR_OK) &&
 
7307
                   (ret != XML_WAR_UNDECLARED_ENTITY)) {
 
7308
            xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
 
7309
                     "Entity '%s' failed to parse\n", ent->name);
 
7310
        } else if (list != NULL) {
 
7311
            xmlFreeNodeList(list);
 
7312
            list = NULL;
 
7313
        }
 
7314
        if (ent->checked == 0)
 
7315
            ent->checked = 2;
 
7316
    } else if (ent->checked != 1) {
 
7317
        ctxt->nbentities += ent->checked / 2;
 
7318
    }
 
7319
 
 
7320
    /*
 
7321
     * Now that the entity content has been gathered
 
7322
     * provide it to the application, this can take different forms based
 
7323
     * on the parsing modes.
 
7324
     */
 
7325
    if (ent->children == NULL) {
 
7326
        /*
 
7327
         * Probably running in SAX mode and the callbacks don't
 
7328
         * build the entity content. So unless we already went
 
7329
         * though parsing for first checking go though the entity
 
7330
         * content to generate callbacks associated to the entity
 
7331
         */
 
7332
        if (was_checked != 0) {
 
7333
            void *user_data;
 
7334
            /*
 
7335
             * This is a bit hackish but this seems the best
 
7336
             * way to make sure both SAX and DOM entity support
 
7337
             * behaves okay.
 
7338
             */
 
7339
            if (ctxt->userData == ctxt)
 
7340
                user_data = NULL;
 
7341
            else
 
7342
                user_data = ctxt->userData;
 
7343
 
 
7344
            if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
 
7345
                ctxt->depth++;
 
7346
                ret = xmlParseBalancedChunkMemoryInternal(ctxt,
 
7347
                                   ent->content, user_data, NULL);
 
7348
                ctxt->depth--;
 
7349
            } else if (ent->etype ==
 
7350
                       XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
 
7351
                ctxt->depth++;
 
7352
                ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt,
 
7353
                           ctxt->sax, user_data, ctxt->depth,
 
7354
                           ent->URI, ent->ExternalID, NULL);
 
7355
                ctxt->depth--;
 
7356
            } else {
 
7357
                ret = XML_ERR_ENTITY_PE_INTERNAL;
 
7358
                xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
 
7359
                             "invalid entity type found\n", NULL);
 
7360
            }
 
7361
            if (ret == XML_ERR_ENTITY_LOOP) {
 
7362
                xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
 
7363
                return;
 
7364
            }
 
7365
        }
 
7366
        if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
 
7367
            (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
 
7368
            /*
 
7369
             * Entity reference callback comes second, it's somewhat
 
7370
             * superfluous but a compatibility to historical behaviour
 
7371
             */
 
7372
            ctxt->sax->reference(ctxt->userData, ent->name);
 
7373
        }
 
7374
        return;
 
7375
    }
 
7376
 
 
7377
    /*
 
7378
     * If we didn't get any children for the entity being built
 
7379
     */
 
7380
    if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
 
7381
        (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
 
7382
        /*
 
7383
         * Create a node.
 
7384
         */
 
7385
        ctxt->sax->reference(ctxt->userData, ent->name);
 
7386
        return;
 
7387
    }
 
7388
 
 
7389
    if ((ctxt->replaceEntities) || (ent->children == NULL))  {
 
7390
        /*
 
7391
         * There is a problem on the handling of _private for entities
 
7392
         * (bug 155816): Should we copy the content of the field from
 
7393
         * the entity (possibly overwriting some value set by the user
 
7394
         * when a copy is created), should we leave it alone, or should
 
7395
         * we try to take care of different situations?  The problem
 
7396
         * is exacerbated by the usage of this field by the xmlReader.
 
7397
         * To fix this bug, we look at _private on the created node
 
7398
         * and, if it's NULL, we copy in whatever was in the entity.
 
7399
         * If it's not NULL we leave it alone.  This is somewhat of a
 
7400
         * hack - maybe we should have further tests to determine
 
7401
         * what to do.
 
7402
         */
 
7403
        if ((ctxt->node != NULL) && (ent->children != NULL)) {
 
7404
            /*
 
7405
             * Seems we are generating the DOM content, do
 
7406
             * a simple tree copy for all references except the first
 
7407
             * In the first occurrence list contains the replacement.
 
7408
             */
 
7409
            if (((list == NULL) && (ent->owner == 0)) ||
 
7410
                (ctxt->parseMode == XML_PARSE_READER)) {
 
7411
                xmlNodePtr nw = NULL, cur, firstChild = NULL;
 
7412
 
 
7413
                /*
 
7414
                 * We are copying here, make sure there is no abuse
 
7415
                 */
 
7416
                ctxt->sizeentcopy += ent->length;
 
7417
                if (xmlParserEntityCheck(ctxt, 0, ent, ctxt->sizeentcopy))
 
7418
                    return;
 
7419
 
 
7420
                /*
 
7421
                 * when operating on a reader, the entities definitions
 
7422
                 * are always owning the entities subtree.
 
7423
                if (ctxt->parseMode == XML_PARSE_READER)
 
7424
                    ent->owner = 1;
 
7425
                 */
 
7426
 
 
7427
                cur = ent->children;
 
7428
                while (cur != NULL) {
 
7429
                    nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
 
7430
                    if (nw != NULL) {
 
7431
                        if (nw->_private == NULL)
 
7432
                            nw->_private = cur->_private;
 
7433
                        if (firstChild == NULL){
 
7434
                            firstChild = nw;
 
7435
                        }
 
7436
                        nw = xmlAddChild(ctxt->node, nw);
 
7437
                    }
 
7438
                    if (cur == ent->last) {
 
7439
                        /*
 
7440
                         * needed to detect some strange empty
 
7441
                         * node cases in the reader tests
 
7442
                         */
 
7443
                        if ((ctxt->parseMode == XML_PARSE_READER) &&
 
7444
                            (nw != NULL) &&
 
7445
                            (nw->type == XML_ELEMENT_NODE) &&
 
7446
                            (nw->children == NULL))
 
7447
                            nw->extra = 1;
 
7448
 
 
7449
                        break;
 
7450
                    }
 
7451
                    cur = cur->next;
 
7452
                }
 
7453
#ifdef LIBXML_LEGACY_ENABLED
 
7454
                if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
 
7455
                  xmlAddEntityReference(ent, firstChild, nw);
 
7456
#endif /* LIBXML_LEGACY_ENABLED */
 
7457
            } else if ((list == NULL) || (ctxt->inputNr > 0)) {
 
7458
                xmlNodePtr nw = NULL, cur, next, last,
 
7459
                           firstChild = NULL;
 
7460
 
 
7461
                /*
 
7462
                 * We are copying here, make sure there is no abuse
 
7463
                 */
 
7464
                ctxt->sizeentcopy += ent->length;
 
7465
                if (xmlParserEntityCheck(ctxt, 0, ent, ctxt->sizeentcopy))
 
7466
                    return;
 
7467
 
 
7468
                /*
 
7469
                 * Copy the entity child list and make it the new
 
7470
                 * entity child list. The goal is to make sure any
 
7471
                 * ID or REF referenced will be the one from the
 
7472
                 * document content and not the entity copy.
 
7473
                 */
 
7474
                cur = ent->children;
 
7475
                ent->children = NULL;
 
7476
                last = ent->last;
 
7477
                ent->last = NULL;
 
7478
                while (cur != NULL) {
 
7479
                    next = cur->next;
 
7480
                    cur->next = NULL;
 
7481
                    cur->parent = NULL;
 
7482
                    nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
 
7483
                    if (nw != NULL) {
 
7484
                        if (nw->_private == NULL)
 
7485
                            nw->_private = cur->_private;
 
7486
                        if (firstChild == NULL){
 
7487
                            firstChild = cur;
 
7488
                        }
 
7489
                        xmlAddChild((xmlNodePtr) ent, nw);
 
7490
                        xmlAddChild(ctxt->node, cur);
 
7491
                    }
 
7492
                    if (cur == last)
 
7493
                        break;
 
7494
                    cur = next;
 
7495
                }
 
7496
                if (ent->owner == 0)
 
7497
                    ent->owner = 1;
 
7498
#ifdef LIBXML_LEGACY_ENABLED
 
7499
                if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
 
7500
                  xmlAddEntityReference(ent, firstChild, nw);
 
7501
#endif /* LIBXML_LEGACY_ENABLED */
 
7502
            } else {
 
7503
                const xmlChar *nbktext;
 
7504
 
 
7505
                /*
 
7506
                 * the name change is to avoid coalescing of the
 
7507
                 * node with a possible previous text one which
 
7508
                 * would make ent->children a dangling pointer
 
7509
                 */
 
7510
                nbktext = xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
 
7511
                                        -1);
 
7512
                if (ent->children->type == XML_TEXT_NODE)
 
7513
                    ent->children->name = nbktext;
 
7514
                if ((ent->last != ent->children) &&
 
7515
                    (ent->last->type == XML_TEXT_NODE))
 
7516
                    ent->last->name = nbktext;
 
7517
                xmlAddChildList(ctxt->node, ent->children);
 
7518
            }
 
7519
 
 
7520
            /*
 
7521
             * This is to avoid a nasty side effect, see
 
7522
             * characters() in SAX.c
 
7523
             */
 
7524
            ctxt->nodemem = 0;
 
7525
            ctxt->nodelen = 0;
 
7526
            return;
 
7527
        }
 
7528
    }
 
7529
}
 
7530
 
 
7531
/**
 
7532
 * xmlParseEntityRef:
 
7533
 * @ctxt:  an XML parser context
 
7534
 *
 
7535
 * parse ENTITY references declarations
 
7536
 *
 
7537
 * [68] EntityRef ::= '&' Name ';'
 
7538
 *
 
7539
 * [ WFC: Entity Declared ]
 
7540
 * In a document without any DTD, a document with only an internal DTD
 
7541
 * subset which contains no parameter entity references, or a document
 
7542
 * with "standalone='yes'", the Name given in the entity reference
 
7543
 * must match that in an entity declaration, except that well-formed
 
7544
 * documents need not declare any of the following entities: amp, lt,
 
7545
 * gt, apos, quot.  The declaration of a parameter entity must precede
 
7546
 * any reference to it.  Similarly, the declaration of a general entity
 
7547
 * must precede any reference to it which appears in a default value in an
 
7548
 * attribute-list declaration. Note that if entities are declared in the
 
7549
 * external subset or in external parameter entities, a non-validating
 
7550
 * processor is not obligated to read and process their declarations;
 
7551
 * for such documents, the rule that an entity must be declared is a
 
7552
 * well-formedness constraint only if standalone='yes'.
 
7553
 *
 
7554
 * [ WFC: Parsed Entity ]
 
7555
 * An entity reference must not contain the name of an unparsed entity
 
7556
 *
 
7557
 * Returns the xmlEntityPtr if found, or NULL otherwise.
 
7558
 */
 
7559
xmlEntityPtr
 
7560
xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
 
7561
    const xmlChar *name;
 
7562
    xmlEntityPtr ent = NULL;
 
7563
 
 
7564
    GROW;
 
7565
    if (ctxt->instate == XML_PARSER_EOF)
 
7566
        return(NULL);
 
7567
 
 
7568
    if (RAW != '&')
 
7569
        return(NULL);
 
7570
    NEXT;
 
7571
    name = xmlParseName(ctxt);
 
7572
    if (name == NULL) {
 
7573
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
7574
                       "xmlParseEntityRef: no name\n");
 
7575
        return(NULL);
 
7576
    }
 
7577
    if (RAW != ';') {
 
7578
        xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
 
7579
        return(NULL);
 
7580
    }
 
7581
    NEXT;
 
7582
 
 
7583
    /*
 
7584
     * Predefined entities override any extra definition
 
7585
     */
 
7586
    if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
 
7587
        ent = xmlGetPredefinedEntity(name);
 
7588
        if (ent != NULL)
 
7589
            return(ent);
 
7590
    }
 
7591
 
 
7592
    /*
 
7593
     * Increase the number of entity references parsed
 
7594
     */
 
7595
    ctxt->nbentities++;
 
7596
 
 
7597
    /*
 
7598
     * Ask first SAX for entity resolution, otherwise try the
 
7599
     * entities which may have stored in the parser context.
 
7600
     */
 
7601
    if (ctxt->sax != NULL) {
 
7602
        if (ctxt->sax->getEntity != NULL)
 
7603
            ent = ctxt->sax->getEntity(ctxt->userData, name);
 
7604
        if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
 
7605
            (ctxt->options & XML_PARSE_OLDSAX))
 
7606
            ent = xmlGetPredefinedEntity(name);
 
7607
        if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
 
7608
            (ctxt->userData==ctxt)) {
 
7609
            ent = xmlSAX2GetEntity(ctxt, name);
 
7610
        }
 
7611
    }
 
7612
    if (ctxt->instate == XML_PARSER_EOF)
 
7613
        return(NULL);
 
7614
    /*
 
7615
     * [ WFC: Entity Declared ]
 
7616
     * In a document without any DTD, a document with only an
 
7617
     * internal DTD subset which contains no parameter entity
 
7618
     * references, or a document with "standalone='yes'", the
 
7619
     * Name given in the entity reference must match that in an
 
7620
     * entity declaration, except that well-formed documents
 
7621
     * need not declare any of the following entities: amp, lt,
 
7622
     * gt, apos, quot.
 
7623
     * The declaration of a parameter entity must precede any
 
7624
     * reference to it.
 
7625
     * Similarly, the declaration of a general entity must
 
7626
     * precede any reference to it which appears in a default
 
7627
     * value in an attribute-list declaration. Note that if
 
7628
     * entities are declared in the external subset or in
 
7629
     * external parameter entities, a non-validating processor
 
7630
     * is not obligated to read and process their declarations;
 
7631
     * for such documents, the rule that an entity must be
 
7632
     * declared is a well-formedness constraint only if
 
7633
     * standalone='yes'.
 
7634
     */
 
7635
    if (ent == NULL) {
 
7636
        if ((ctxt->standalone == 1) ||
 
7637
            ((ctxt->hasExternalSubset == 0) &&
 
7638
             (ctxt->hasPErefs == 0))) {
 
7639
            xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
 
7640
                     "Entity '%s' not defined\n", name);
 
7641
        } else {
 
7642
            xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
 
7643
                     "Entity '%s' not defined\n", name);
 
7644
            if ((ctxt->inSubset == 0) &&
 
7645
                (ctxt->sax != NULL) &&
 
7646
                (ctxt->sax->reference != NULL)) {
 
7647
                ctxt->sax->reference(ctxt->userData, name);
 
7648
            }
 
7649
        }
 
7650
        ctxt->valid = 0;
 
7651
    }
 
7652
 
 
7653
    /*
 
7654
     * [ WFC: Parsed Entity ]
 
7655
     * An entity reference must not contain the name of an
 
7656
     * unparsed entity
 
7657
     */
 
7658
    else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
 
7659
        xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
 
7660
                 "Entity reference to unparsed entity %s\n", name);
 
7661
    }
 
7662
 
 
7663
    /*
 
7664
     * [ WFC: No External Entity References ]
 
7665
     * Attribute values cannot contain direct or indirect
 
7666
     * entity references to external entities.
 
7667
     */
 
7668
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
 
7669
             (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
 
7670
        xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
 
7671
             "Attribute references external entity '%s'\n", name);
 
7672
    }
 
7673
    /*
 
7674
     * [ WFC: No < in Attribute Values ]
 
7675
     * The replacement text of any entity referred to directly or
 
7676
     * indirectly in an attribute value (other than "&lt;") must
 
7677
     * not contain a <.
 
7678
     */
 
7679
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
 
7680
             (ent != NULL) && 
 
7681
             (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
 
7682
        if ((ent->checked & 1) || ((ent->checked == 0) &&
 
7683
             (ent->content != NULL) &&(xmlStrchr(ent->content, '<')))) {
 
7684
            xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
 
7685
        "'<' in entity '%s' is not allowed in attributes values\n", name);
 
7686
        }
 
7687
    }
 
7688
 
 
7689
    /*
 
7690
     * Internal check, no parameter entities here ...
 
7691
     */
 
7692
    else {
 
7693
        switch (ent->etype) {
 
7694
            case XML_INTERNAL_PARAMETER_ENTITY:
 
7695
            case XML_EXTERNAL_PARAMETER_ENTITY:
 
7696
            xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
 
7697
             "Attempt to reference the parameter entity '%s'\n",
 
7698
                              name);
 
7699
            break;
 
7700
            default:
 
7701
            break;
 
7702
        }
 
7703
    }
 
7704
 
 
7705
    /*
 
7706
     * [ WFC: No Recursion ]
 
7707
     * A parsed entity must not contain a recursive reference
 
7708
     * to itself, either directly or indirectly.
 
7709
     * Done somewhere else
 
7710
     */
 
7711
    return(ent);
 
7712
}
 
7713
 
 
7714
/**
 
7715
 * xmlParseStringEntityRef:
 
7716
 * @ctxt:  an XML parser context
 
7717
 * @str:  a pointer to an index in the string
 
7718
 *
 
7719
 * parse ENTITY references declarations, but this version parses it from
 
7720
 * a string value.
 
7721
 *
 
7722
 * [68] EntityRef ::= '&' Name ';'
 
7723
 *
 
7724
 * [ WFC: Entity Declared ]
 
7725
 * In a document without any DTD, a document with only an internal DTD
 
7726
 * subset which contains no parameter entity references, or a document
 
7727
 * with "standalone='yes'", the Name given in the entity reference
 
7728
 * must match that in an entity declaration, except that well-formed
 
7729
 * documents need not declare any of the following entities: amp, lt,
 
7730
 * gt, apos, quot.  The declaration of a parameter entity must precede
 
7731
 * any reference to it.  Similarly, the declaration of a general entity
 
7732
 * must precede any reference to it which appears in a default value in an
 
7733
 * attribute-list declaration. Note that if entities are declared in the
 
7734
 * external subset or in external parameter entities, a non-validating
 
7735
 * processor is not obligated to read and process their declarations;
 
7736
 * for such documents, the rule that an entity must be declared is a
 
7737
 * well-formedness constraint only if standalone='yes'.
 
7738
 *
 
7739
 * [ WFC: Parsed Entity ]
 
7740
 * An entity reference must not contain the name of an unparsed entity
 
7741
 *
 
7742
 * Returns the xmlEntityPtr if found, or NULL otherwise. The str pointer
 
7743
 * is updated to the current location in the string.
 
7744
 */
 
7745
static xmlEntityPtr
 
7746
xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
 
7747
    xmlChar *name;
 
7748
    const xmlChar *ptr;
 
7749
    xmlChar cur;
 
7750
    xmlEntityPtr ent = NULL;
 
7751
 
 
7752
    if ((str == NULL) || (*str == NULL))
 
7753
        return(NULL);
 
7754
    ptr = *str;
 
7755
    cur = *ptr;
 
7756
    if (cur != '&')
 
7757
        return(NULL);
 
7758
 
 
7759
    ptr++;
 
7760
    name = xmlParseStringName(ctxt, &ptr);
 
7761
    if (name == NULL) {
 
7762
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
7763
                       "xmlParseStringEntityRef: no name\n");
 
7764
        *str = ptr;
 
7765
        return(NULL);
 
7766
    }
 
7767
    if (*ptr != ';') {
 
7768
        xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
 
7769
        xmlFree(name);
 
7770
        *str = ptr;
 
7771
        return(NULL);
 
7772
    }
 
7773
    ptr++;
 
7774
 
 
7775
 
 
7776
    /*
 
7777
     * Predefined entites override any extra definition
 
7778
     */
 
7779
    if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
 
7780
        ent = xmlGetPredefinedEntity(name);
 
7781
        if (ent != NULL) {
 
7782
            xmlFree(name);
 
7783
            *str = ptr;
 
7784
            return(ent);
 
7785
        }
 
7786
    }
 
7787
 
 
7788
    /*
 
7789
     * Increate the number of entity references parsed
 
7790
     */
 
7791
    ctxt->nbentities++;
 
7792
 
 
7793
    /*
 
7794
     * Ask first SAX for entity resolution, otherwise try the
 
7795
     * entities which may have stored in the parser context.
 
7796
     */
 
7797
    if (ctxt->sax != NULL) {
 
7798
        if (ctxt->sax->getEntity != NULL)
 
7799
            ent = ctxt->sax->getEntity(ctxt->userData, name);
 
7800
        if ((ent == NULL) && (ctxt->options & XML_PARSE_OLDSAX))
 
7801
            ent = xmlGetPredefinedEntity(name);
 
7802
        if ((ent == NULL) && (ctxt->userData==ctxt)) {
 
7803
            ent = xmlSAX2GetEntity(ctxt, name);
 
7804
        }
 
7805
    }
 
7806
    if (ctxt->instate == XML_PARSER_EOF) {
 
7807
        xmlFree(name);
 
7808
        return(NULL);
 
7809
    }
 
7810
 
 
7811
    /*
 
7812
     * [ WFC: Entity Declared ]
 
7813
     * In a document without any DTD, a document with only an
 
7814
     * internal DTD subset which contains no parameter entity
 
7815
     * references, or a document with "standalone='yes'", the
 
7816
     * Name given in the entity reference must match that in an
 
7817
     * entity declaration, except that well-formed documents
 
7818
     * need not declare any of the following entities: amp, lt,
 
7819
     * gt, apos, quot.
 
7820
     * The declaration of a parameter entity must precede any
 
7821
     * reference to it.
 
7822
     * Similarly, the declaration of a general entity must
 
7823
     * precede any reference to it which appears in a default
 
7824
     * value in an attribute-list declaration. Note that if
 
7825
     * entities are declared in the external subset or in
 
7826
     * external parameter entities, a non-validating processor
 
7827
     * is not obligated to read and process their declarations;
 
7828
     * for such documents, the rule that an entity must be
 
7829
     * declared is a well-formedness constraint only if
 
7830
     * standalone='yes'.
 
7831
     */
 
7832
    if (ent == NULL) {
 
7833
        if ((ctxt->standalone == 1) ||
 
7834
            ((ctxt->hasExternalSubset == 0) &&
 
7835
             (ctxt->hasPErefs == 0))) {
 
7836
            xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
 
7837
                     "Entity '%s' not defined\n", name);
 
7838
        } else {
 
7839
            xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
 
7840
                          "Entity '%s' not defined\n",
 
7841
                          name);
 
7842
        }
 
7843
        /* TODO ? check regressions ctxt->valid = 0; */
 
7844
    }
 
7845
 
 
7846
    /*
 
7847
     * [ WFC: Parsed Entity ]
 
7848
     * An entity reference must not contain the name of an
 
7849
     * unparsed entity
 
7850
     */
 
7851
    else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
 
7852
        xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
 
7853
                 "Entity reference to unparsed entity %s\n", name);
 
7854
    }
 
7855
 
 
7856
    /*
 
7857
     * [ WFC: No External Entity References ]
 
7858
     * Attribute values cannot contain direct or indirect
 
7859
     * entity references to external entities.
 
7860
     */
 
7861
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
 
7862
             (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
 
7863
        xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
 
7864
         "Attribute references external entity '%s'\n", name);
 
7865
    }
 
7866
    /*
 
7867
     * [ WFC: No < in Attribute Values ]
 
7868
     * The replacement text of any entity referred to directly or
 
7869
     * indirectly in an attribute value (other than "&lt;") must
 
7870
     * not contain a <.
 
7871
     */
 
7872
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
 
7873
             (ent != NULL) && (ent->content != NULL) &&
 
7874
             (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
 
7875
             (xmlStrchr(ent->content, '<'))) {
 
7876
        xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
 
7877
     "'<' in entity '%s' is not allowed in attributes values\n",
 
7878
                          name);
 
7879
    }
 
7880
 
 
7881
    /*
 
7882
     * Internal check, no parameter entities here ...
 
7883
     */
 
7884
    else {
 
7885
        switch (ent->etype) {
 
7886
            case XML_INTERNAL_PARAMETER_ENTITY:
 
7887
            case XML_EXTERNAL_PARAMETER_ENTITY:
 
7888
                xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
 
7889
             "Attempt to reference the parameter entity '%s'\n",
 
7890
                                  name);
 
7891
            break;
 
7892
            default:
 
7893
            break;
 
7894
        }
 
7895
    }
 
7896
 
 
7897
    /*
 
7898
     * [ WFC: No Recursion ]
 
7899
     * A parsed entity must not contain a recursive reference
 
7900
     * to itself, either directly or indirectly.
 
7901
     * Done somewhere else
 
7902
     */
 
7903
 
 
7904
    xmlFree(name);
 
7905
    *str = ptr;
 
7906
    return(ent);
 
7907
}
 
7908
 
 
7909
/**
 
7910
 * xmlParsePEReference:
 
7911
 * @ctxt:  an XML parser context
 
7912
 *
 
7913
 * parse PEReference declarations
 
7914
 * The entity content is handled directly by pushing it's content as
 
7915
 * a new input stream.
 
7916
 *
 
7917
 * [69] PEReference ::= '%' Name ';'
 
7918
 *
 
7919
 * [ WFC: No Recursion ]
 
7920
 * A parsed entity must not contain a recursive
 
7921
 * reference to itself, either directly or indirectly.
 
7922
 *
 
7923
 * [ WFC: Entity Declared ]
 
7924
 * In a document without any DTD, a document with only an internal DTD
 
7925
 * subset which contains no parameter entity references, or a document
 
7926
 * with "standalone='yes'", ...  ... The declaration of a parameter
 
7927
 * entity must precede any reference to it...
 
7928
 *
 
7929
 * [ VC: Entity Declared ]
 
7930
 * In a document with an external subset or external parameter entities
 
7931
 * with "standalone='no'", ...  ... The declaration of a parameter entity
 
7932
 * must precede any reference to it...
 
7933
 *
 
7934
 * [ WFC: In DTD ]
 
7935
 * Parameter-entity references may only appear in the DTD.
 
7936
 * NOTE: misleading but this is handled.
 
7937
 */
 
7938
void
 
7939
xmlParsePEReference(xmlParserCtxtPtr ctxt)
 
7940
{
 
7941
    const xmlChar *name;
 
7942
    xmlEntityPtr entity = NULL;
 
7943
    xmlParserInputPtr input;
 
7944
 
 
7945
    if (RAW != '%')
 
7946
        return;
 
7947
    NEXT;
 
7948
    name = xmlParseName(ctxt);
 
7949
    if (name == NULL) {
 
7950
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
7951
                       "xmlParsePEReference: no name\n");
 
7952
        return;
 
7953
    }
 
7954
    if (RAW != ';') {
 
7955
        xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
 
7956
        return;
 
7957
    }
 
7958
 
 
7959
    NEXT;
 
7960
 
 
7961
    /*
 
7962
     * Increate the number of entity references parsed
 
7963
     */
 
7964
    ctxt->nbentities++;
 
7965
 
 
7966
    /*
 
7967
     * Request the entity from SAX
 
7968
     */
 
7969
    if ((ctxt->sax != NULL) &&
 
7970
        (ctxt->sax->getParameterEntity != NULL))
 
7971
        entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
 
7972
    if (ctxt->instate == XML_PARSER_EOF)
 
7973
        return;
 
7974
    if (entity == NULL) {
 
7975
        /*
 
7976
         * [ WFC: Entity Declared ]
 
7977
         * In a document without any DTD, a document with only an
 
7978
         * internal DTD subset which contains no parameter entity
 
7979
         * references, or a document with "standalone='yes'", ...
 
7980
         * ... The declaration of a parameter entity must precede
 
7981
         * any reference to it...
 
7982
         */
 
7983
        if ((ctxt->standalone == 1) ||
 
7984
            ((ctxt->hasExternalSubset == 0) &&
 
7985
             (ctxt->hasPErefs == 0))) {
 
7986
            xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
 
7987
                              "PEReference: %%%s; not found\n",
 
7988
                              name);
 
7989
        } else {
 
7990
            /*
 
7991
             * [ VC: Entity Declared ]
 
7992
             * In a document with an external subset or external
 
7993
             * parameter entities with "standalone='no'", ...
 
7994
             * ... The declaration of a parameter entity must
 
7995
             * precede any reference to it...
 
7996
             */
 
7997
            xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
 
7998
                          "PEReference: %%%s; not found\n",
 
7999
                          name, NULL);
 
8000
            ctxt->valid = 0;
 
8001
        }
 
8002
    } else {
 
8003
        /*
 
8004
         * Internal checking in case the entity quest barfed
 
8005
         */
 
8006
        if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
 
8007
            (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
 
8008
            xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
 
8009
                  "Internal: %%%s; is not a parameter entity\n",
 
8010
                          name, NULL);
 
8011
        } else if (ctxt->input->free != deallocblankswrapper) {
 
8012
            input = xmlNewBlanksWrapperInputStream(ctxt, entity);
 
8013
            if (xmlPushInput(ctxt, input) < 0)
 
8014
                return;
 
8015
        } else {
 
8016
            /*
 
8017
             * TODO !!!
 
8018
             * handle the extra spaces added before and after
 
8019
             * c.f. http://www.w3.org/TR/REC-xml#as-PE
 
8020
             */
 
8021
            input = xmlNewEntityInputStream(ctxt, entity);
 
8022
            if (xmlPushInput(ctxt, input) < 0)
 
8023
                return;
 
8024
            if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
 
8025
                (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) &&
 
8026
                (IS_BLANK_CH(NXT(5)))) {
 
8027
                xmlParseTextDecl(ctxt);
 
8028
                if (ctxt->errNo ==
 
8029
                    XML_ERR_UNSUPPORTED_ENCODING) {
 
8030
                    /*
 
8031
                     * The XML REC instructs us to stop parsing
 
8032
                     * right here
 
8033
                     */
 
8034
                    ctxt->instate = XML_PARSER_EOF;
 
8035
                    return;
 
8036
                }
 
8037
            }
 
8038
        }
 
8039
    }
 
8040
    ctxt->hasPErefs = 1;
 
8041
}
 
8042
 
 
8043
/**
 
8044
 * xmlLoadEntityContent:
 
8045
 * @ctxt:  an XML parser context
 
8046
 * @entity: an unloaded system entity
 
8047
 *
 
8048
 * Load the original content of the given system entity from the
 
8049
 * ExternalID/SystemID given. This is to be used for Included in Literal
 
8050
 * http://www.w3.org/TR/REC-xml/#inliteral processing of entities references
 
8051
 *
 
8052
 * Returns 0 in case of success and -1 in case of failure
 
8053
 */
 
8054
static int
 
8055
xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
 
8056
    xmlParserInputPtr input;
 
8057
    xmlBufferPtr buf;
 
8058
    int l, c;
 
8059
    int count = 0;
 
8060
 
 
8061
    if ((ctxt == NULL) || (entity == NULL) ||
 
8062
        ((entity->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
 
8063
         (entity->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY)) ||
 
8064
        (entity->content != NULL)) {
 
8065
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
8066
                    "xmlLoadEntityContent parameter error");
 
8067
        return(-1);
 
8068
    }
 
8069
 
 
8070
    if (xmlParserDebugEntities)
 
8071
        xmlGenericError(xmlGenericErrorContext,
 
8072
                "Reading %s entity content input\n", entity->name);
 
8073
 
 
8074
    buf = xmlBufferCreate();
 
8075
    if (buf == NULL) {
 
8076
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
8077
                    "xmlLoadEntityContent parameter error");
 
8078
        return(-1);
 
8079
    }
 
8080
 
 
8081
    input = xmlNewEntityInputStream(ctxt, entity);
 
8082
    if (input == NULL) {
 
8083
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
8084
                    "xmlLoadEntityContent input error");
 
8085
        xmlBufferFree(buf);
 
8086
        return(-1);
 
8087
    }
 
8088
 
 
8089
    /*
 
8090
     * Push the entity as the current input, read char by char
 
8091
     * saving to the buffer until the end of the entity or an error
 
8092
     */
 
8093
    if (xmlPushInput(ctxt, input) < 0) {
 
8094
        xmlBufferFree(buf);
 
8095
        return(-1);
 
8096
    }
 
8097
 
 
8098
    GROW;
 
8099
    c = CUR_CHAR(l);
 
8100
    while ((ctxt->input == input) && (ctxt->input->cur < ctxt->input->end) &&
 
8101
           (IS_CHAR(c))) {
 
8102
        xmlBufferAdd(buf, ctxt->input->cur, l);
 
8103
        if (count++ > XML_PARSER_CHUNK_SIZE) {
 
8104
            count = 0;
 
8105
            GROW;
 
8106
            if (ctxt->instate == XML_PARSER_EOF) {
 
8107
                xmlBufferFree(buf);
 
8108
                return(-1);
 
8109
            }
 
8110
        }
 
8111
        NEXTL(l);
 
8112
        c = CUR_CHAR(l);
 
8113
        if (c == 0) {
 
8114
            count = 0;
 
8115
            GROW;
 
8116
            if (ctxt->instate == XML_PARSER_EOF) {
 
8117
                xmlBufferFree(buf);
 
8118
                return(-1);
 
8119
            }
 
8120
            c = CUR_CHAR(l);
 
8121
        }
 
8122
    }
 
8123
 
 
8124
    if ((ctxt->input == input) && (ctxt->input->cur >= ctxt->input->end)) {
 
8125
        xmlPopInput(ctxt);
 
8126
    } else if (!IS_CHAR(c)) {
 
8127
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
 
8128
                          "xmlLoadEntityContent: invalid char value %d\n",
 
8129
                          c);
 
8130
        xmlBufferFree(buf);
 
8131
        return(-1);
 
8132
    }
 
8133
    entity->content = buf->content;
 
8134
    buf->content = NULL;
 
8135
    xmlBufferFree(buf);
 
8136
 
 
8137
    return(0);
 
8138
}
 
8139
 
 
8140
/**
 
8141
 * xmlParseStringPEReference:
 
8142
 * @ctxt:  an XML parser context
 
8143
 * @str:  a pointer to an index in the string
 
8144
 *
 
8145
 * parse PEReference declarations
 
8146
 *
 
8147
 * [69] PEReference ::= '%' Name ';'
 
8148
 *
 
8149
 * [ WFC: No Recursion ]
 
8150
 * A parsed entity must not contain a recursive
 
8151
 * reference to itself, either directly or indirectly.
 
8152
 *
 
8153
 * [ WFC: Entity Declared ]
 
8154
 * In a document without any DTD, a document with only an internal DTD
 
8155
 * subset which contains no parameter entity references, or a document
 
8156
 * with "standalone='yes'", ...  ... The declaration of a parameter
 
8157
 * entity must precede any reference to it...
 
8158
 *
 
8159
 * [ VC: Entity Declared ]
 
8160
 * In a document with an external subset or external parameter entities
 
8161
 * with "standalone='no'", ...  ... The declaration of a parameter entity
 
8162
 * must precede any reference to it...
 
8163
 *
 
8164
 * [ WFC: In DTD ]
 
8165
 * Parameter-entity references may only appear in the DTD.
 
8166
 * NOTE: misleading but this is handled.
 
8167
 *
 
8168
 * Returns the string of the entity content.
 
8169
 *         str is updated to the current value of the index
 
8170
 */
 
8171
static xmlEntityPtr
 
8172
xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
 
8173
    const xmlChar *ptr;
 
8174
    xmlChar cur;
 
8175
    xmlChar *name;
 
8176
    xmlEntityPtr entity = NULL;
 
8177
 
 
8178
    if ((str == NULL) || (*str == NULL)) return(NULL);
 
8179
    ptr = *str;
 
8180
    cur = *ptr;
 
8181
    if (cur != '%')
 
8182
        return(NULL);
 
8183
    ptr++;
 
8184
    name = xmlParseStringName(ctxt, &ptr);
 
8185
    if (name == NULL) {
 
8186
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
8187
                       "xmlParseStringPEReference: no name\n");
 
8188
        *str = ptr;
 
8189
        return(NULL);
 
8190
    }
 
8191
    cur = *ptr;
 
8192
    if (cur != ';') {
 
8193
        xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
 
8194
        xmlFree(name);
 
8195
        *str = ptr;
 
8196
        return(NULL);
 
8197
    }
 
8198
    ptr++;
 
8199
 
 
8200
    /*
 
8201
     * Increate the number of entity references parsed
 
8202
     */
 
8203
    ctxt->nbentities++;
 
8204
 
 
8205
    /*
 
8206
     * Request the entity from SAX
 
8207
     */
 
8208
    if ((ctxt->sax != NULL) &&
 
8209
        (ctxt->sax->getParameterEntity != NULL))
 
8210
        entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
 
8211
    if (ctxt->instate == XML_PARSER_EOF) {
 
8212
        xmlFree(name);
 
8213
        return(NULL);
 
8214
    }
 
8215
    if (entity == NULL) {
 
8216
        /*
 
8217
         * [ WFC: Entity Declared ]
 
8218
         * In a document without any DTD, a document with only an
 
8219
         * internal DTD subset which contains no parameter entity
 
8220
         * references, or a document with "standalone='yes'", ...
 
8221
         * ... The declaration of a parameter entity must precede
 
8222
         * any reference to it...
 
8223
         */
 
8224
        if ((ctxt->standalone == 1) ||
 
8225
            ((ctxt->hasExternalSubset == 0) && (ctxt->hasPErefs == 0))) {
 
8226
            xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
 
8227
                 "PEReference: %%%s; not found\n", name);
 
8228
        } else {
 
8229
            /*
 
8230
             * [ VC: Entity Declared ]
 
8231
             * In a document with an external subset or external
 
8232
             * parameter entities with "standalone='no'", ...
 
8233
             * ... The declaration of a parameter entity must
 
8234
             * precede any reference to it...
 
8235
             */
 
8236
            xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
 
8237
                          "PEReference: %%%s; not found\n",
 
8238
                          name, NULL);
 
8239
            ctxt->valid = 0;
 
8240
        }
 
8241
    } else {
 
8242
        /*
 
8243
         * Internal checking in case the entity quest barfed
 
8244
         */
 
8245
        if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
 
8246
            (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
 
8247
            xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
 
8248
                          "%%%s; is not a parameter entity\n",
 
8249
                          name, NULL);
 
8250
        }
 
8251
    }
 
8252
    ctxt->hasPErefs = 1;
 
8253
    xmlFree(name);
 
8254
    *str = ptr;
 
8255
    return(entity);
 
8256
}
 
8257
 
 
8258
/**
 
8259
 * xmlParseDocTypeDecl:
 
8260
 * @ctxt:  an XML parser context
 
8261
 *
 
8262
 * parse a DOCTYPE declaration
 
8263
 *
 
8264
 * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
 
8265
 *                      ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
 
8266
 *
 
8267
 * [ VC: Root Element Type ]
 
8268
 * The Name in the document type declaration must match the element
 
8269
 * type of the root element.
 
8270
 */
 
8271
 
 
8272
void
 
8273
xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
 
8274
    const xmlChar *name = NULL;
 
8275
    xmlChar *ExternalID = NULL;
 
8276
    xmlChar *URI = NULL;
 
8277
 
 
8278
    /*
 
8279
     * We know that '<!DOCTYPE' has been detected.
 
8280
     */
 
8281
    SKIP(9);
 
8282
 
 
8283
    SKIP_BLANKS;
 
8284
 
 
8285
    /*
 
8286
     * Parse the DOCTYPE name.
 
8287
     */
 
8288
    name = xmlParseName(ctxt);
 
8289
    if (name == NULL) {
 
8290
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
8291
                       "xmlParseDocTypeDecl : no DOCTYPE name !\n");
 
8292
    }
 
8293
    ctxt->intSubName = name;
 
8294
 
 
8295
    SKIP_BLANKS;
 
8296
 
 
8297
    /*
 
8298
     * Check for SystemID and ExternalID
 
8299
     */
 
8300
    URI = xmlParseExternalID(ctxt, &ExternalID, 1);
 
8301
 
 
8302
    if ((URI != NULL) || (ExternalID != NULL)) {
 
8303
        ctxt->hasExternalSubset = 1;
 
8304
    }
 
8305
    ctxt->extSubURI = URI;
 
8306
    ctxt->extSubSystem = ExternalID;
 
8307
 
 
8308
    SKIP_BLANKS;
 
8309
 
 
8310
    /*
 
8311
     * Create and update the internal subset.
 
8312
     */
 
8313
    if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL) &&
 
8314
        (!ctxt->disableSAX))
 
8315
        ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
 
8316
    if (ctxt->instate == XML_PARSER_EOF)
 
8317
        return;
 
8318
 
 
8319
    /*
 
8320
     * Is there any internal subset declarations ?
 
8321
     * they are handled separately in xmlParseInternalSubset()
 
8322
     */
 
8323
    if (RAW == '[')
 
8324
        return;
 
8325
 
 
8326
    /*
 
8327
     * We should be at the end of the DOCTYPE declaration.
 
8328
     */
 
8329
    if (RAW != '>') {
 
8330
        xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
 
8331
    }
 
8332
    NEXT;
 
8333
}
 
8334
 
 
8335
/**
 
8336
 * xmlParseInternalSubset:
 
8337
 * @ctxt:  an XML parser context
 
8338
 *
 
8339
 * parse the internal subset declaration
 
8340
 *
 
8341
 * [28 end] ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
 
8342
 */
 
8343
 
 
8344
static void
 
8345
xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
 
8346
    /*
 
8347
     * Is there any DTD definition ?
 
8348
     */
 
8349
    if (RAW == '[') {
 
8350
        ctxt->instate = XML_PARSER_DTD;
 
8351
        NEXT;
 
8352
        /*
 
8353
         * Parse the succession of Markup declarations and
 
8354
         * PEReferences.
 
8355
         * Subsequence (markupdecl | PEReference | S)*
 
8356
         */
 
8357
        while ((RAW != ']') && (ctxt->instate != XML_PARSER_EOF)) {
 
8358
            const xmlChar *check = CUR_PTR;
 
8359
            unsigned int cons = ctxt->input->consumed;
 
8360
 
 
8361
            SKIP_BLANKS;
 
8362
            xmlParseMarkupDecl(ctxt);
 
8363
            xmlParsePEReference(ctxt);
 
8364
 
 
8365
            /*
 
8366
             * Pop-up of finished entities.
 
8367
             */
 
8368
            while ((RAW == 0) && (ctxt->inputNr > 1))
 
8369
                xmlPopInput(ctxt);
 
8370
 
 
8371
            if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
 
8372
                xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
8373
             "xmlParseInternalSubset: error detected in Markup declaration\n");
 
8374
                break;
 
8375
            }
 
8376
        }
 
8377
        if (RAW == ']') {
 
8378
            NEXT;
 
8379
            SKIP_BLANKS;
 
8380
        }
 
8381
    }
 
8382
 
 
8383
    /*
 
8384
     * We should be at the end of the DOCTYPE declaration.
 
8385
     */
 
8386
    if (RAW != '>') {
 
8387
        xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
 
8388
    }
 
8389
    NEXT;
 
8390
}
 
8391
 
 
8392
#ifdef LIBXML_SAX1_ENABLED
 
8393
/**
 
8394
 * xmlParseAttribute:
 
8395
 * @ctxt:  an XML parser context
 
8396
 * @value:  a xmlChar ** used to store the value of the attribute
 
8397
 *
 
8398
 * parse an attribute
 
8399
 *
 
8400
 * [41] Attribute ::= Name Eq AttValue
 
8401
 *
 
8402
 * [ WFC: No External Entity References ]
 
8403
 * Attribute values cannot contain direct or indirect entity references
 
8404
 * to external entities.
 
8405
 *
 
8406
 * [ WFC: No < in Attribute Values ]
 
8407
 * The replacement text of any entity referred to directly or indirectly in
 
8408
 * an attribute value (other than "&lt;") must not contain a <.
 
8409
 *
 
8410
 * [ VC: Attribute Value Type ]
 
8411
 * The attribute must have been declared; the value must be of the type
 
8412
 * declared for it.
 
8413
 *
 
8414
 * [25] Eq ::= S? '=' S?
 
8415
 *
 
8416
 * With namespace:
 
8417
 *
 
8418
 * [NS 11] Attribute ::= QName Eq AttValue
 
8419
 *
 
8420
 * Also the case QName == xmlns:??? is handled independently as a namespace
 
8421
 * definition.
 
8422
 *
 
8423
 * Returns the attribute name, and the value in *value.
 
8424
 */
 
8425
 
 
8426
const xmlChar *
 
8427
xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
 
8428
    const xmlChar *name;
 
8429
    xmlChar *val;
 
8430
 
 
8431
    *value = NULL;
 
8432
    GROW;
 
8433
    name = xmlParseName(ctxt);
 
8434
    if (name == NULL) {
 
8435
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
8436
                       "error parsing attribute name\n");
 
8437
        return(NULL);
 
8438
    }
 
8439
 
 
8440
    /*
 
8441
     * read the value
 
8442
     */
 
8443
    SKIP_BLANKS;
 
8444
    if (RAW == '=') {
 
8445
        NEXT;
 
8446
        SKIP_BLANKS;
 
8447
        val = xmlParseAttValue(ctxt);
 
8448
        ctxt->instate = XML_PARSER_CONTENT;
 
8449
    } else {
 
8450
        xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
 
8451
               "Specification mandate value for attribute %s\n", name);
 
8452
        return(NULL);
 
8453
    }
 
8454
 
 
8455
    /*
 
8456
     * Check that xml:lang conforms to the specification
 
8457
     * No more registered as an error, just generate a warning now
 
8458
     * since this was deprecated in XML second edition
 
8459
     */
 
8460
    if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "xml:lang"))) {
 
8461
        if (!xmlCheckLanguageID(val)) {
 
8462
            xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
 
8463
                          "Malformed value for xml:lang : %s\n",
 
8464
                          val, NULL);
 
8465
        }
 
8466
    }
 
8467
 
 
8468
    /*
 
8469
     * Check that xml:space conforms to the specification
 
8470
     */
 
8471
    if (xmlStrEqual(name, BAD_CAST "xml:space")) {
 
8472
        if (xmlStrEqual(val, BAD_CAST "default"))
 
8473
            *(ctxt->space) = 0;
 
8474
        else if (xmlStrEqual(val, BAD_CAST "preserve"))
 
8475
            *(ctxt->space) = 1;
 
8476
        else {
 
8477
                xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
 
8478
"Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
 
8479
                                 val, NULL);
 
8480
        }
 
8481
    }
 
8482
 
 
8483
    *value = val;
 
8484
    return(name);
 
8485
}
 
8486
 
 
8487
/**
 
8488
 * xmlParseStartTag:
 
8489
 * @ctxt:  an XML parser context
 
8490
 *
 
8491
 * parse a start of tag either for rule element or
 
8492
 * EmptyElement. In both case we don't parse the tag closing chars.
 
8493
 *
 
8494
 * [40] STag ::= '<' Name (S Attribute)* S? '>'
 
8495
 *
 
8496
 * [ WFC: Unique Att Spec ]
 
8497
 * No attribute name may appear more than once in the same start-tag or
 
8498
 * empty-element tag.
 
8499
 *
 
8500
 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
 
8501
 *
 
8502
 * [ WFC: Unique Att Spec ]
 
8503
 * No attribute name may appear more than once in the same start-tag or
 
8504
 * empty-element tag.
 
8505
 *
 
8506
 * With namespace:
 
8507
 *
 
8508
 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
 
8509
 *
 
8510
 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
 
8511
 *
 
8512
 * Returns the element name parsed
 
8513
 */
 
8514
 
 
8515
const xmlChar *
 
8516
xmlParseStartTag(xmlParserCtxtPtr ctxt) {
 
8517
    const xmlChar *name;
 
8518
    const xmlChar *attname;
 
8519
    xmlChar *attvalue;
 
8520
    const xmlChar **atts = ctxt->atts;
 
8521
    int nbatts = 0;
 
8522
    int maxatts = ctxt->maxatts;
 
8523
    int i;
 
8524
 
 
8525
    if (RAW != '<') return(NULL);
 
8526
    NEXT1;
 
8527
 
 
8528
    name = xmlParseName(ctxt);
 
8529
    if (name == NULL) {
 
8530
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
8531
             "xmlParseStartTag: invalid element name\n");
 
8532
        return(NULL);
 
8533
    }
 
8534
 
 
8535
    /*
 
8536
     * Now parse the attributes, it ends up with the ending
 
8537
     *
 
8538
     * (S Attribute)* S?
 
8539
     */
 
8540
    SKIP_BLANKS;
 
8541
    GROW;
 
8542
 
 
8543
    while (((RAW != '>') &&
 
8544
           ((RAW != '/') || (NXT(1) != '>')) &&
 
8545
           (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) {
 
8546
        const xmlChar *q = CUR_PTR;
 
8547
        unsigned int cons = ctxt->input->consumed;
 
8548
 
 
8549
        attname = xmlParseAttribute(ctxt, &attvalue);
 
8550
        if ((attname != NULL) && (attvalue != NULL)) {
 
8551
            /*
 
8552
             * [ WFC: Unique Att Spec ]
 
8553
             * No attribute name may appear more than once in the same
 
8554
             * start-tag or empty-element tag.
 
8555
             */
 
8556
            for (i = 0; i < nbatts;i += 2) {
 
8557
                if (xmlStrEqual(atts[i], attname)) {
 
8558
                    xmlErrAttributeDup(ctxt, NULL, attname);
 
8559
                    xmlFree(attvalue);
 
8560
                    goto failed;
 
8561
                }
 
8562
            }
 
8563
            /*
 
8564
             * Add the pair to atts
 
8565
             */
 
8566
            if (atts == NULL) {
 
8567
                maxatts = 22; /* allow for 10 attrs by default */
 
8568
                atts = (const xmlChar **)
 
8569
                       xmlMalloc(maxatts * sizeof(xmlChar *));
 
8570
                if (atts == NULL) {
 
8571
                    xmlErrMemory(ctxt, NULL);
 
8572
                    if (attvalue != NULL)
 
8573
                        xmlFree(attvalue);
 
8574
                    goto failed;
 
8575
                }
 
8576
                ctxt->atts = atts;
 
8577
                ctxt->maxatts = maxatts;
 
8578
            } else if (nbatts + 4 > maxatts) {
 
8579
                const xmlChar **n;
 
8580
 
 
8581
                maxatts *= 2;
 
8582
                n = (const xmlChar **) xmlRealloc((void *) atts,
 
8583
                                             maxatts * sizeof(const xmlChar *));
 
8584
                if (n == NULL) {
 
8585
                    xmlErrMemory(ctxt, NULL);
 
8586
                    if (attvalue != NULL)
 
8587
                        xmlFree(attvalue);
 
8588
                    goto failed;
 
8589
                }
 
8590
                atts = n;
 
8591
                ctxt->atts = atts;
 
8592
                ctxt->maxatts = maxatts;
 
8593
            }
 
8594
            atts[nbatts++] = attname;
 
8595
            atts[nbatts++] = attvalue;
 
8596
            atts[nbatts] = NULL;
 
8597
            atts[nbatts + 1] = NULL;
 
8598
        } else {
 
8599
            if (attvalue != NULL)
 
8600
                xmlFree(attvalue);
 
8601
        }
 
8602
 
 
8603
failed:
 
8604
 
 
8605
        GROW
 
8606
        if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
 
8607
            break;
 
8608
        if (!IS_BLANK_CH(RAW)) {
 
8609
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
8610
                           "attributes construct error\n");
 
8611
        }
 
8612
        SKIP_BLANKS;
 
8613
        if ((cons == ctxt->input->consumed) && (q == CUR_PTR) &&
 
8614
            (attname == NULL) && (attvalue == NULL)) {
 
8615
            xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
 
8616
                           "xmlParseStartTag: problem parsing attributes\n");
 
8617
            break;
 
8618
        }
 
8619
        SHRINK;
 
8620
        GROW;
 
8621
    }
 
8622
 
 
8623
    /*
 
8624
     * SAX: Start of Element !
 
8625
     */
 
8626
    if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL) &&
 
8627
        (!ctxt->disableSAX)) {
 
8628
        if (nbatts > 0)
 
8629
            ctxt->sax->startElement(ctxt->userData, name, atts);
 
8630
        else
 
8631
            ctxt->sax->startElement(ctxt->userData, name, NULL);
 
8632
    }
 
8633
 
 
8634
    if (atts != NULL) {
 
8635
        /* Free only the content strings */
 
8636
        for (i = 1;i < nbatts;i+=2)
 
8637
            if (atts[i] != NULL)
 
8638
               xmlFree((xmlChar *) atts[i]);
 
8639
    }
 
8640
    return(name);
 
8641
}
 
8642
 
 
8643
/**
 
8644
 * xmlParseEndTag1:
 
8645
 * @ctxt:  an XML parser context
 
8646
 * @line:  line of the start tag
 
8647
 * @nsNr:  number of namespaces on the start tag
 
8648
 *
 
8649
 * parse an end of tag
 
8650
 *
 
8651
 * [42] ETag ::= '</' Name S? '>'
 
8652
 *
 
8653
 * With namespace
 
8654
 *
 
8655
 * [NS 9] ETag ::= '</' QName S? '>'
 
8656
 */
 
8657
 
 
8658
static void
 
8659
xmlParseEndTag1(xmlParserCtxtPtr ctxt, int line) {
 
8660
    const xmlChar *name;
 
8661
 
 
8662
    GROW;
 
8663
    if ((RAW != '<') || (NXT(1) != '/')) {
 
8664
        xmlFatalErrMsg(ctxt, XML_ERR_LTSLASH_REQUIRED,
 
8665
                       "xmlParseEndTag: '</' not found\n");
 
8666
        return;
 
8667
    }
 
8668
    SKIP(2);
 
8669
 
 
8670
    name = xmlParseNameAndCompare(ctxt,ctxt->name);
 
8671
 
 
8672
    /*
 
8673
     * We should definitely be at the ending "S? '>'" part
 
8674
     */
 
8675
    GROW;
 
8676
    SKIP_BLANKS;
 
8677
    if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
 
8678
        xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
 
8679
    } else
 
8680
        NEXT1;
 
8681
 
 
8682
    /*
 
8683
     * [ WFC: Element Type Match ]
 
8684
     * The Name in an element's end-tag must match the element type in the
 
8685
     * start-tag.
 
8686
     *
 
8687
     */
 
8688
    if (name != (xmlChar*)1) {
 
8689
        if (name == NULL) name = BAD_CAST "unparseable";
 
8690
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
 
8691
                     "Opening and ending tag mismatch: %s line %d and %s\n",
 
8692
                                ctxt->name, line, name);
 
8693
    }
 
8694
 
 
8695
    /*
 
8696
     * SAX: End of Tag
 
8697
     */
 
8698
    if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
 
8699
        (!ctxt->disableSAX))
 
8700
        ctxt->sax->endElement(ctxt->userData, ctxt->name);
 
8701
 
 
8702
    namePop(ctxt);
 
8703
    spacePop(ctxt);
 
8704
    return;
 
8705
}
 
8706
 
 
8707
/**
 
8708
 * xmlParseEndTag:
 
8709
 * @ctxt:  an XML parser context
 
8710
 *
 
8711
 * parse an end of tag
 
8712
 *
 
8713
 * [42] ETag ::= '</' Name S? '>'
 
8714
 *
 
8715
 * With namespace
 
8716
 *
 
8717
 * [NS 9] ETag ::= '</' QName S? '>'
 
8718
 */
 
8719
 
 
8720
void
 
8721
xmlParseEndTag(xmlParserCtxtPtr ctxt) {
 
8722
    xmlParseEndTag1(ctxt, 0);
 
8723
}
 
8724
#endif /* LIBXML_SAX1_ENABLED */
 
8725
 
 
8726
/************************************************************************
 
8727
 *                                                                      *
 
8728
 *                    SAX 2 specific operations                         *
 
8729
 *                                                                      *
 
8730
 ************************************************************************/
 
8731
 
 
8732
/*
 
8733
 * xmlGetNamespace:
 
8734
 * @ctxt:  an XML parser context
 
8735
 * @prefix:  the prefix to lookup
 
8736
 *
 
8737
 * Lookup the namespace name for the @prefix (which ca be NULL)
 
8738
 * The prefix must come from the @ctxt->dict dictionnary
 
8739
 *
 
8740
 * Returns the namespace name or NULL if not bound
 
8741
 */
 
8742
static const xmlChar *
 
8743
xmlGetNamespace(xmlParserCtxtPtr ctxt, const xmlChar *prefix) {
 
8744
    int i;
 
8745
 
 
8746
    if (prefix == ctxt->str_xml) return(ctxt->str_xml_ns);
 
8747
    for (i = ctxt->nsNr - 2;i >= 0;i-=2)
 
8748
        if (ctxt->nsTab[i] == prefix) {
 
8749
            if ((prefix == NULL) && (*ctxt->nsTab[i + 1] == 0))
 
8750
                return(NULL);
 
8751
            return(ctxt->nsTab[i + 1]);
 
8752
        }
 
8753
    return(NULL);
 
8754
}
 
8755
 
 
8756
/**
 
8757
 * xmlParseQName:
 
8758
 * @ctxt:  an XML parser context
 
8759
 * @prefix:  pointer to store the prefix part
 
8760
 *
 
8761
 * parse an XML Namespace QName
 
8762
 *
 
8763
 * [6]  QName  ::= (Prefix ':')? LocalPart
 
8764
 * [7]  Prefix  ::= NCName
 
8765
 * [8]  LocalPart  ::= NCName
 
8766
 *
 
8767
 * Returns the Name parsed or NULL
 
8768
 */
 
8769
 
 
8770
static const xmlChar *
 
8771
xmlParseQName(xmlParserCtxtPtr ctxt, const xmlChar **prefix) {
 
8772
    const xmlChar *l, *p;
 
8773
 
 
8774
    GROW;
 
8775
 
 
8776
    l = xmlParseNCName(ctxt);
 
8777
    if (l == NULL) {
 
8778
        if (CUR == ':') {
 
8779
            l = xmlParseName(ctxt);
 
8780
            if (l != NULL) {
 
8781
                xmlNsErr(ctxt, XML_NS_ERR_QNAME,
 
8782
                         "Failed to parse QName '%s'\n", l, NULL, NULL);
 
8783
                *prefix = NULL;
 
8784
                return(l);
 
8785
            }
 
8786
        }
 
8787
        return(NULL);
 
8788
    }
 
8789
    if (CUR == ':') {
 
8790
        NEXT;
 
8791
        p = l;
 
8792
        l = xmlParseNCName(ctxt);
 
8793
        if (l == NULL) {
 
8794
            xmlChar *tmp;
 
8795
 
 
8796
            xmlNsErr(ctxt, XML_NS_ERR_QNAME,
 
8797
                     "Failed to parse QName '%s:'\n", p, NULL, NULL);
 
8798
            l = xmlParseNmtoken(ctxt);
 
8799
            if (l == NULL)
 
8800
                tmp = xmlBuildQName(BAD_CAST "", p, NULL, 0);
 
8801
            else {
 
8802
                tmp = xmlBuildQName(l, p, NULL, 0);
 
8803
                xmlFree((char *)l);
 
8804
            }
 
8805
            p = xmlDictLookup(ctxt->dict, tmp, -1);
 
8806
            if (tmp != NULL) xmlFree(tmp);
 
8807
            *prefix = NULL;
 
8808
            return(p);
 
8809
        }
 
8810
        if (CUR == ':') {
 
8811
            xmlChar *tmp;
 
8812
 
 
8813
            xmlNsErr(ctxt, XML_NS_ERR_QNAME,
 
8814
                     "Failed to parse QName '%s:%s:'\n", p, l, NULL);
 
8815
            NEXT;
 
8816
            tmp = (xmlChar *) xmlParseName(ctxt);
 
8817
            if (tmp != NULL) {
 
8818
                tmp = xmlBuildQName(tmp, l, NULL, 0);
 
8819
                l = xmlDictLookup(ctxt->dict, tmp, -1);
 
8820
                if (tmp != NULL) xmlFree(tmp);
 
8821
                *prefix = p;
 
8822
                return(l);
 
8823
            }
 
8824
            tmp = xmlBuildQName(BAD_CAST "", l, NULL, 0);
 
8825
            l = xmlDictLookup(ctxt->dict, tmp, -1);
 
8826
            if (tmp != NULL) xmlFree(tmp);
 
8827
            *prefix = p;
 
8828
            return(l);
 
8829
        }
 
8830
        *prefix = p;
 
8831
    } else
 
8832
        *prefix = NULL;
 
8833
    return(l);
 
8834
}
 
8835
 
 
8836
/**
 
8837
 * xmlParseQNameAndCompare:
 
8838
 * @ctxt:  an XML parser context
 
8839
 * @name:  the localname
 
8840
 * @prefix:  the prefix, if any.
 
8841
 *
 
8842
 * parse an XML name and compares for match
 
8843
 * (specialized for endtag parsing)
 
8844
 *
 
8845
 * Returns NULL for an illegal name, (xmlChar*) 1 for success
 
8846
 * and the name for mismatch
 
8847
 */
 
8848
 
 
8849
static const xmlChar *
 
8850
xmlParseQNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *name,
 
8851
                        xmlChar const *prefix) {
 
8852
    const xmlChar *cmp;
 
8853
    const xmlChar *in;
 
8854
    const xmlChar *ret;
 
8855
    const xmlChar *prefix2;
 
8856
 
 
8857
    if (prefix == NULL) return(xmlParseNameAndCompare(ctxt, name));
 
8858
 
 
8859
    GROW;
 
8860
    in = ctxt->input->cur;
 
8861
 
 
8862
    cmp = prefix;
 
8863
    while (*in != 0 && *in == *cmp) {
 
8864
        ++in;
 
8865
        ++cmp;
 
8866
    }
 
8867
    if ((*cmp == 0) && (*in == ':')) {
 
8868
        in++;
 
8869
        cmp = name;
 
8870
        while (*in != 0 && *in == *cmp) {
 
8871
            ++in;
 
8872
            ++cmp;
 
8873
        }
 
8874
        if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
 
8875
            /* success */
 
8876
            ctxt->input->cur = in;
 
8877
            return((const xmlChar*) 1);
 
8878
        }
 
8879
    }
 
8880
    /*
 
8881
     * all strings coms from the dictionary, equality can be done directly
 
8882
     */
 
8883
    ret = xmlParseQName (ctxt, &prefix2);
 
8884
    if ((ret == name) && (prefix == prefix2))
 
8885
        return((const xmlChar*) 1);
 
8886
    return ret;
 
8887
}
 
8888
 
 
8889
/**
 
8890
 * xmlParseAttValueInternal:
 
8891
 * @ctxt:  an XML parser context
 
8892
 * @len:  attribute len result
 
8893
 * @alloc:  whether the attribute was reallocated as a new string
 
8894
 * @normalize:  if 1 then further non-CDATA normalization must be done
 
8895
 *
 
8896
 * parse a value for an attribute.
 
8897
 * NOTE: if no normalization is needed, the routine will return pointers
 
8898
 *       directly from the data buffer.
 
8899
 *
 
8900
 * 3.3.3 Attribute-Value Normalization:
 
8901
 * Before the value of an attribute is passed to the application or
 
8902
 * checked for validity, the XML processor must normalize it as follows:
 
8903
 * - a character reference is processed by appending the referenced
 
8904
 *   character to the attribute value
 
8905
 * - an entity reference is processed by recursively processing the
 
8906
 *   replacement text of the entity
 
8907
 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
 
8908
 *   appending #x20 to the normalized value, except that only a single
 
8909
 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
 
8910
 *   parsed entity or the literal entity value of an internal parsed entity
 
8911
 * - other characters are processed by appending them to the normalized value
 
8912
 * If the declared value is not CDATA, then the XML processor must further
 
8913
 * process the normalized attribute value by discarding any leading and
 
8914
 * trailing space (#x20) characters, and by replacing sequences of space
 
8915
 * (#x20) characters by a single space (#x20) character.
 
8916
 * All attributes for which no declaration has been read should be treated
 
8917
 * by a non-validating parser as if declared CDATA.
 
8918
 *
 
8919
 * Returns the AttValue parsed or NULL. The value has to be freed by the
 
8920
 *     caller if it was copied, this can be detected by val[*len] == 0.
 
8921
 */
 
8922
 
 
8923
static xmlChar *
 
8924
xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
 
8925
                         int normalize)
 
8926
{
 
8927
    xmlChar limit = 0;
 
8928
    const xmlChar *in = NULL, *start, *end, *last;
 
8929
    xmlChar *ret = NULL;
 
8930
 
 
8931
    GROW;
 
8932
    in = (xmlChar *) CUR_PTR;
 
8933
    if (*in != '"' && *in != '\'') {
 
8934
        xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
 
8935
        return (NULL);
 
8936
    }
 
8937
    ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
 
8938
 
 
8939
    /*
 
8940
     * try to handle in this routine the most common case where no
 
8941
     * allocation of a new string is required and where content is
 
8942
     * pure ASCII.
 
8943
     */
 
8944
    limit = *in++;
 
8945
    end = ctxt->input->end;
 
8946
    start = in;
 
8947
    if (in >= end) {
 
8948
        const xmlChar *oldbase = ctxt->input->base;
 
8949
        GROW;
 
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
    }
 
8957
    if (normalize) {
 
8958
        /*
 
8959
         * Skip any leading spaces
 
8960
         */
 
8961
        while ((in < end) && (*in != limit) &&
 
8962
               ((*in == 0x20) || (*in == 0x9) ||
 
8963
                (*in == 0xA) || (*in == 0xD))) {
 
8964
            in++;
 
8965
            start = in;
 
8966
            if (in >= end) {
 
8967
                const xmlChar *oldbase = ctxt->input->base;
 
8968
                GROW;
 
8969
                if (ctxt->instate == XML_PARSER_EOF)
 
8970
                    return(NULL);
 
8971
                if (oldbase != ctxt->input->base) {
 
8972
                    long delta = ctxt->input->base - oldbase;
 
8973
                    start = start + delta;
 
8974
                    in = in + delta;
 
8975
                }
 
8976
                end = ctxt->input->end;
 
8977
                if (((in - start) > XML_MAX_TEXT_LENGTH) &&
 
8978
                    ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
8979
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
 
8980
                                   "AttValue length too long\n");
 
8981
                    return(NULL);
 
8982
                }
 
8983
            }
 
8984
        }
 
8985
        while ((in < end) && (*in != limit) && (*in >= 0x20) &&
 
8986
               (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
 
8987
            if ((*in++ == 0x20) && (*in == 0x20)) break;
 
8988
            if (in >= end) {
 
8989
                const xmlChar *oldbase = ctxt->input->base;
 
8990
                GROW;
 
8991
                if (ctxt->instate == XML_PARSER_EOF)
 
8992
                    return(NULL);
 
8993
                if (oldbase != ctxt->input->base) {
 
8994
                    long delta = ctxt->input->base - oldbase;
 
8995
                    start = start + delta;
 
8996
                    in = in + delta;
 
8997
                }
 
8998
                end = ctxt->input->end;
 
8999
                if (((in - start) > XML_MAX_TEXT_LENGTH) &&
 
9000
                    ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
9001
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
 
9002
                                   "AttValue length too long\n");
 
9003
                    return(NULL);
 
9004
                }
 
9005
            }
 
9006
        }
 
9007
        last = in;
 
9008
        /*
 
9009
         * skip the trailing blanks
 
9010
         */
 
9011
        while ((last[-1] == 0x20) && (last > start)) last--;
 
9012
        while ((in < end) && (*in != limit) &&
 
9013
               ((*in == 0x20) || (*in == 0x9) ||
 
9014
                (*in == 0xA) || (*in == 0xD))) {
 
9015
            in++;
 
9016
            if (in >= end) {
 
9017
                const xmlChar *oldbase = ctxt->input->base;
 
9018
                GROW;
 
9019
                if (ctxt->instate == XML_PARSER_EOF)
 
9020
                    return(NULL);
 
9021
                if (oldbase != ctxt->input->base) {
 
9022
                    long delta = ctxt->input->base - oldbase;
 
9023
                    start = start + delta;
 
9024
                    in = in + delta;
 
9025
                    last = last + delta;
 
9026
                }
 
9027
                end = ctxt->input->end;
 
9028
                if (((in - start) > XML_MAX_TEXT_LENGTH) &&
 
9029
                    ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
9030
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
 
9031
                                   "AttValue length too long\n");
 
9032
                    return(NULL);
 
9033
                }
 
9034
            }
 
9035
        }
 
9036
        if (((in - start) > XML_MAX_TEXT_LENGTH) &&
 
9037
            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
9038
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
 
9039
                           "AttValue length too long\n");
 
9040
            return(NULL);
 
9041
        }
 
9042
        if (*in != limit) goto need_complex;
 
9043
    } else {
 
9044
        while ((in < end) && (*in != limit) && (*in >= 0x20) &&
 
9045
               (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
 
9046
            in++;
 
9047
            if (in >= end) {
 
9048
                const xmlChar *oldbase = ctxt->input->base;
 
9049
                GROW;
 
9050
                if (ctxt->instate == XML_PARSER_EOF)
 
9051
                    return(NULL);
 
9052
                if (oldbase != ctxt->input->base) {
 
9053
                    long delta = ctxt->input->base - oldbase;
 
9054
                    start = start + delta;
 
9055
                    in = in + delta;
 
9056
                }
 
9057
                end = ctxt->input->end;
 
9058
                if (((in - start) > XML_MAX_TEXT_LENGTH) &&
 
9059
                    ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
9060
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
 
9061
                                   "AttValue length too long\n");
 
9062
                    return(NULL);
 
9063
                }
 
9064
            }
 
9065
        }
 
9066
        last = in;
 
9067
        if (((in - start) > XML_MAX_TEXT_LENGTH) &&
 
9068
            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
9069
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
 
9070
                           "AttValue length too long\n");
 
9071
            return(NULL);
 
9072
        }
 
9073
        if (*in != limit) goto need_complex;
 
9074
    }
 
9075
    in++;
 
9076
    if (len != NULL) {
 
9077
        *len = last - start;
 
9078
        ret = (xmlChar *) start;
 
9079
    } else {
 
9080
        if (alloc) *alloc = 1;
 
9081
        ret = xmlStrndup(start, last - start);
 
9082
    }
 
9083
    CUR_PTR = in;
 
9084
    if (alloc) *alloc = 0;
 
9085
    return ret;
 
9086
need_complex:
 
9087
    if (alloc) *alloc = 1;
 
9088
    return xmlParseAttValueComplex(ctxt, len, normalize);
 
9089
}
 
9090
 
 
9091
/**
 
9092
 * xmlParseAttribute2:
 
9093
 * @ctxt:  an XML parser context
 
9094
 * @pref:  the element prefix
 
9095
 * @elem:  the element name
 
9096
 * @prefix:  a xmlChar ** used to store the value of the attribute prefix
 
9097
 * @value:  a xmlChar ** used to store the value of the attribute
 
9098
 * @len:  an int * to save the length of the attribute
 
9099
 * @alloc:  an int * to indicate if the attribute was allocated
 
9100
 *
 
9101
 * parse an attribute in the new SAX2 framework.
 
9102
 *
 
9103
 * Returns the attribute name, and the value in *value, .
 
9104
 */
 
9105
 
 
9106
static const xmlChar *
 
9107
xmlParseAttribute2(xmlParserCtxtPtr ctxt,
 
9108
                   const xmlChar * pref, const xmlChar * elem,
 
9109
                   const xmlChar ** prefix, xmlChar ** value,
 
9110
                   int *len, int *alloc)
 
9111
{
 
9112
    const xmlChar *name;
 
9113
    xmlChar *val, *internal_val = NULL;
 
9114
    int normalize = 0;
 
9115
 
 
9116
    *value = NULL;
 
9117
    GROW;
 
9118
    name = xmlParseQName(ctxt, prefix);
 
9119
    if (name == NULL) {
 
9120
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
9121
                       "error parsing attribute name\n");
 
9122
        return (NULL);
 
9123
    }
 
9124
 
 
9125
    /*
 
9126
     * get the type if needed
 
9127
     */
 
9128
    if (ctxt->attsSpecial != NULL) {
 
9129
        int type;
 
9130
 
 
9131
        type = (int) (long) xmlHashQLookup2(ctxt->attsSpecial,
 
9132
                                            pref, elem, *prefix, name);
 
9133
        if (type != 0)
 
9134
            normalize = 1;
 
9135
    }
 
9136
 
 
9137
    /*
 
9138
     * read the value
 
9139
     */
 
9140
    SKIP_BLANKS;
 
9141
    if (RAW == '=') {
 
9142
        NEXT;
 
9143
        SKIP_BLANKS;
 
9144
        val = xmlParseAttValueInternal(ctxt, len, alloc, normalize);
 
9145
        if (normalize) {
 
9146
            /*
 
9147
             * Sometimes a second normalisation pass for spaces is needed
 
9148
             * but that only happens if charrefs or entities refernces
 
9149
             * have been used in the attribute value, i.e. the attribute
 
9150
             * value have been extracted in an allocated string already.
 
9151
             */
 
9152
            if (*alloc) {
 
9153
                const xmlChar *val2;
 
9154
 
 
9155
                val2 = xmlAttrNormalizeSpace2(ctxt, val, len);
 
9156
                if ((val2 != NULL) && (val2 != val)) {
 
9157
                    xmlFree(val);
 
9158
                    val = (xmlChar *) val2;
 
9159
                }
 
9160
            }
 
9161
        }
 
9162
        ctxt->instate = XML_PARSER_CONTENT;
 
9163
    } else {
 
9164
        xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
 
9165
                          "Specification mandate value for attribute %s\n",
 
9166
                          name);
 
9167
        return (NULL);
 
9168
    }
 
9169
 
 
9170
    if (*prefix == ctxt->str_xml) {
 
9171
        /*
 
9172
         * Check that xml:lang conforms to the specification
 
9173
         * No more registered as an error, just generate a warning now
 
9174
         * since this was deprecated in XML second edition
 
9175
         */
 
9176
        if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "lang"))) {
 
9177
            internal_val = xmlStrndup(val, *len);
 
9178
            if (!xmlCheckLanguageID(internal_val)) {
 
9179
                xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
 
9180
                              "Malformed value for xml:lang : %s\n",
 
9181
                              internal_val, NULL);
 
9182
            }
 
9183
        }
 
9184
 
 
9185
        /*
 
9186
         * Check that xml:space conforms to the specification
 
9187
         */
 
9188
        if (xmlStrEqual(name, BAD_CAST "space")) {
 
9189
            internal_val = xmlStrndup(val, *len);
 
9190
            if (xmlStrEqual(internal_val, BAD_CAST "default"))
 
9191
                *(ctxt->space) = 0;
 
9192
            else if (xmlStrEqual(internal_val, BAD_CAST "preserve"))
 
9193
                *(ctxt->space) = 1;
 
9194
            else {
 
9195
                xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
 
9196
                              "Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
 
9197
                              internal_val, NULL);
 
9198
            }
 
9199
        }
 
9200
        if (internal_val) {
 
9201
            xmlFree(internal_val);
 
9202
        }
 
9203
    }
 
9204
 
 
9205
    *value = val;
 
9206
    return (name);
 
9207
}
 
9208
/**
 
9209
 * xmlParseStartTag2:
 
9210
 * @ctxt:  an XML parser context
 
9211
 *
 
9212
 * parse a start of tag either for rule element or
 
9213
 * EmptyElement. In both case we don't parse the tag closing chars.
 
9214
 * This routine is called when running SAX2 parsing
 
9215
 *
 
9216
 * [40] STag ::= '<' Name (S Attribute)* S? '>'
 
9217
 *
 
9218
 * [ WFC: Unique Att Spec ]
 
9219
 * No attribute name may appear more than once in the same start-tag or
 
9220
 * empty-element tag.
 
9221
 *
 
9222
 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
 
9223
 *
 
9224
 * [ WFC: Unique Att Spec ]
 
9225
 * No attribute name may appear more than once in the same start-tag or
 
9226
 * empty-element tag.
 
9227
 *
 
9228
 * With namespace:
 
9229
 *
 
9230
 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
 
9231
 *
 
9232
 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
 
9233
 *
 
9234
 * Returns the element name parsed
 
9235
 */
 
9236
 
 
9237
static const xmlChar *
 
9238
xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
 
9239
                  const xmlChar **URI, int *tlen) {
 
9240
    const xmlChar *localname;
 
9241
    const xmlChar *prefix;
 
9242
    const xmlChar *attname;
 
9243
    const xmlChar *aprefix;
 
9244
    const xmlChar *nsname;
 
9245
    xmlChar *attvalue;
 
9246
    const xmlChar **atts = ctxt->atts;
 
9247
    int maxatts = ctxt->maxatts;
 
9248
    int nratts, nbatts, nbdef;
 
9249
    int i, j, nbNs, attval, oldline, oldcol;
 
9250
    const xmlChar *base;
 
9251
    unsigned long cur;
 
9252
    int nsNr = ctxt->nsNr;
 
9253
 
 
9254
    if (RAW != '<') return(NULL);
 
9255
    NEXT1;
 
9256
 
 
9257
    /*
 
9258
     * NOTE: it is crucial with the SAX2 API to never call SHRINK beyond that
 
9259
     *       point since the attribute values may be stored as pointers to
 
9260
     *       the buffer and calling SHRINK would destroy them !
 
9261
     *       The Shrinking is only possible once the full set of attribute
 
9262
     *       callbacks have been done.
 
9263
     */
 
9264
reparse:
 
9265
    SHRINK;
 
9266
    base = ctxt->input->base;
 
9267
    cur = ctxt->input->cur - ctxt->input->base;
 
9268
    oldline = ctxt->input->line;
 
9269
    oldcol = ctxt->input->col;
 
9270
    nbatts = 0;
 
9271
    nratts = 0;
 
9272
    nbdef = 0;
 
9273
    nbNs = 0;
 
9274
    attval = 0;
 
9275
    /* Forget any namespaces added during an earlier parse of this element. */
 
9276
    ctxt->nsNr = nsNr;
 
9277
 
 
9278
    localname = xmlParseQName(ctxt, &prefix);
 
9279
    if (localname == NULL) {
 
9280
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 
9281
                       "StartTag: invalid element name\n");
 
9282
        return(NULL);
 
9283
    }
 
9284
    *tlen = ctxt->input->cur - ctxt->input->base - cur;
 
9285
 
 
9286
    /*
 
9287
     * Now parse the attributes, it ends up with the ending
 
9288
     *
 
9289
     * (S Attribute)* S?
 
9290
     */
 
9291
    SKIP_BLANKS;
 
9292
    GROW;
 
9293
    if (ctxt->input->base != base) goto base_changed;
 
9294
 
 
9295
    while (((RAW != '>') &&
 
9296
           ((RAW != '/') || (NXT(1) != '>')) &&
 
9297
           (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) {
 
9298
        const xmlChar *q = CUR_PTR;
 
9299
        unsigned int cons = ctxt->input->consumed;
 
9300
        int len = -1, alloc = 0;
 
9301
 
 
9302
        attname = xmlParseAttribute2(ctxt, prefix, localname,
 
9303
                                     &aprefix, &attvalue, &len, &alloc);
 
9304
        if (ctxt->input->base != base) {
 
9305
            if ((attvalue != NULL) && (alloc != 0))
 
9306
                xmlFree(attvalue);
 
9307
            attvalue = NULL;
 
9308
            goto base_changed;
 
9309
        }
 
9310
        if ((attname != NULL) && (attvalue != NULL)) {
 
9311
            if (len < 0) len = xmlStrlen(attvalue);
 
9312
            if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
 
9313
                const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
 
9314
                xmlURIPtr uri;
 
9315
 
 
9316
                if (*URL != 0) {
 
9317
                    uri = xmlParseURI((const char *) URL);
 
9318
                    if (uri == NULL) {
 
9319
                        xmlNsErr(ctxt, XML_WAR_NS_URI,
 
9320
                                 "xmlns: '%s' is not a valid URI\n",
 
9321
                                           URL, NULL, NULL);
 
9322
                    } else {
 
9323
                        if (uri->scheme == NULL) {
 
9324
                            xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
 
9325
                                      "xmlns: URI %s is not absolute\n",
 
9326
                                      URL, NULL, NULL);
 
9327
                        }
 
9328
                        xmlFreeURI(uri);
 
9329
                    }
 
9330
                    if (URL == ctxt->str_xml_ns) {
 
9331
                        if (attname != ctxt->str_xml) {
 
9332
                            xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
 
9333
                         "xml namespace URI cannot be the default namespace\n",
 
9334
                                     NULL, NULL, NULL);
 
9335
                        }
 
9336
                        goto skip_default_ns;
 
9337
                    }
 
9338
                    if ((len == 29) &&
 
9339
                        (xmlStrEqual(URL,
 
9340
                                 BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
 
9341
                        xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
 
9342
                             "reuse of the xmlns namespace name is forbidden\n",
 
9343
                                 NULL, NULL, NULL);
 
9344
                        goto skip_default_ns;
 
9345
                    }
 
9346
                }
 
9347
                /*
 
9348
                 * check that it's not a defined namespace
 
9349
                 */
 
9350
                for (j = 1;j <= nbNs;j++)
 
9351
                    if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
 
9352
                        break;
 
9353
                if (j <= nbNs)
 
9354
                    xmlErrAttributeDup(ctxt, NULL, attname);
 
9355
                else
 
9356
                    if (nsPush(ctxt, NULL, URL) > 0) nbNs++;
 
9357
skip_default_ns:
 
9358
                if (alloc != 0) xmlFree(attvalue);
 
9359
                SKIP_BLANKS;
 
9360
                continue;
 
9361
            }
 
9362
            if (aprefix == ctxt->str_xmlns) {
 
9363
                const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
 
9364
                xmlURIPtr uri;
 
9365
 
 
9366
                if (attname == ctxt->str_xml) {
 
9367
                    if (URL != ctxt->str_xml_ns) {
 
9368
                        xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
 
9369
                                 "xml namespace prefix mapped to wrong URI\n",
 
9370
                                 NULL, NULL, NULL);
 
9371
                    }
 
9372
                    /*
 
9373
                     * Do not keep a namespace definition node
 
9374
                     */
 
9375
                    goto skip_ns;
 
9376
                }
 
9377
                if (URL == ctxt->str_xml_ns) {
 
9378
                    if (attname != ctxt->str_xml) {
 
9379
                        xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
 
9380
                                 "xml namespace URI mapped to wrong prefix\n",
 
9381
                                 NULL, NULL, NULL);
 
9382
                    }
 
9383
                    goto skip_ns;
 
9384
                }
 
9385
                if (attname == ctxt->str_xmlns) {
 
9386
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
 
9387
                             "redefinition of the xmlns prefix is forbidden\n",
 
9388
                             NULL, NULL, NULL);
 
9389
                    goto skip_ns;
 
9390
                }
 
9391
                if ((len == 29) &&
 
9392
                    (xmlStrEqual(URL,
 
9393
                                 BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
 
9394
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
 
9395
                             "reuse of the xmlns namespace name is forbidden\n",
 
9396
                             NULL, NULL, NULL);
 
9397
                    goto skip_ns;
 
9398
                }
 
9399
                if ((URL == NULL) || (URL[0] == 0)) {
 
9400
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
 
9401
                             "xmlns:%s: Empty XML namespace is not allowed\n",
 
9402
                                  attname, NULL, NULL);
 
9403
                    goto skip_ns;
 
9404
                } else {
 
9405
                    uri = xmlParseURI((const char *) URL);
 
9406
                    if (uri == NULL) {
 
9407
                        xmlNsErr(ctxt, XML_WAR_NS_URI,
 
9408
                             "xmlns:%s: '%s' is not a valid URI\n",
 
9409
                                           attname, URL, NULL);
 
9410
                    } else {
 
9411
                        if ((ctxt->pedantic) && (uri->scheme == NULL)) {
 
9412
                            xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
 
9413
                                      "xmlns:%s: URI %s is not absolute\n",
 
9414
                                      attname, URL, NULL);
 
9415
                        }
 
9416
                        xmlFreeURI(uri);
 
9417
                    }
 
9418
                }
 
9419
 
 
9420
                /*
 
9421
                 * check that it's not a defined namespace
 
9422
                 */
 
9423
                for (j = 1;j <= nbNs;j++)
 
9424
                    if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
 
9425
                        break;
 
9426
                if (j <= nbNs)
 
9427
                    xmlErrAttributeDup(ctxt, aprefix, attname);
 
9428
                else
 
9429
                    if (nsPush(ctxt, attname, URL) > 0) nbNs++;
 
9430
skip_ns:
 
9431
                if (alloc != 0) xmlFree(attvalue);
 
9432
                SKIP_BLANKS;
 
9433
                if (ctxt->input->base != base) goto base_changed;
 
9434
                continue;
 
9435
            }
 
9436
 
 
9437
            /*
 
9438
             * Add the pair to atts
 
9439
             */
 
9440
            if ((atts == NULL) || (nbatts + 5 > maxatts)) {
 
9441
                if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
 
9442
                    if (attvalue[len] == 0)
 
9443
                        xmlFree(attvalue);
 
9444
                    goto failed;
 
9445
                }
 
9446
                maxatts = ctxt->maxatts;
 
9447
                atts = ctxt->atts;
 
9448
            }
 
9449
            ctxt->attallocs[nratts++] = alloc;
 
9450
            atts[nbatts++] = attname;
 
9451
            atts[nbatts++] = aprefix;
 
9452
            atts[nbatts++] = NULL; /* the URI will be fetched later */
 
9453
            atts[nbatts++] = attvalue;
 
9454
            attvalue += len;
 
9455
            atts[nbatts++] = attvalue;
 
9456
            /*
 
9457
             * tag if some deallocation is needed
 
9458
             */
 
9459
            if (alloc != 0) attval = 1;
 
9460
        } else {
 
9461
            if ((attvalue != NULL) && (attvalue[len] == 0))
 
9462
                xmlFree(attvalue);
 
9463
        }
 
9464
 
 
9465
failed:
 
9466
 
 
9467
        GROW
 
9468
        if (ctxt->instate == XML_PARSER_EOF)
 
9469
            break;
 
9470
        if (ctxt->input->base != base) goto base_changed;
 
9471
        if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
 
9472
            break;
 
9473
        if (!IS_BLANK_CH(RAW)) {
 
9474
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
9475
                           "attributes construct error\n");
 
9476
            break;
 
9477
        }
 
9478
        SKIP_BLANKS;
 
9479
        if ((cons == ctxt->input->consumed) && (q == CUR_PTR) &&
 
9480
            (attname == NULL) && (attvalue == NULL)) {
 
9481
            xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
9482
                 "xmlParseStartTag: problem parsing attributes\n");
 
9483
            break;
 
9484
        }
 
9485
        GROW;
 
9486
        if (ctxt->input->base != base) goto base_changed;
 
9487
    }
 
9488
 
 
9489
    /*
 
9490
     * The attributes defaulting
 
9491
     */
 
9492
    if (ctxt->attsDefault != NULL) {
 
9493
        xmlDefAttrsPtr defaults;
 
9494
 
 
9495
        defaults = xmlHashLookup2(ctxt->attsDefault, localname, prefix);
 
9496
        if (defaults != NULL) {
 
9497
            for (i = 0;i < defaults->nbAttrs;i++) {
 
9498
                attname = defaults->values[5 * i];
 
9499
                aprefix = defaults->values[5 * i + 1];
 
9500
 
 
9501
                /*
 
9502
                 * special work for namespaces defaulted defs
 
9503
                 */
 
9504
                if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
 
9505
                    /*
 
9506
                     * check that it's not a defined namespace
 
9507
                     */
 
9508
                    for (j = 1;j <= nbNs;j++)
 
9509
                        if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
 
9510
                            break;
 
9511
                    if (j <= nbNs) continue;
 
9512
 
 
9513
                    nsname = xmlGetNamespace(ctxt, NULL);
 
9514
                    if (nsname != defaults->values[5 * i + 2]) {
 
9515
                        if (nsPush(ctxt, NULL,
 
9516
                                   defaults->values[5 * i + 2]) > 0)
 
9517
                            nbNs++;
 
9518
                    }
 
9519
                } else if (aprefix == ctxt->str_xmlns) {
 
9520
                    /*
 
9521
                     * check that it's not a defined namespace
 
9522
                     */
 
9523
                    for (j = 1;j <= nbNs;j++)
 
9524
                        if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
 
9525
                            break;
 
9526
                    if (j <= nbNs) continue;
 
9527
 
 
9528
                    nsname = xmlGetNamespace(ctxt, attname);
 
9529
                    if (nsname != defaults->values[2]) {
 
9530
                        if (nsPush(ctxt, attname,
 
9531
                                   defaults->values[5 * i + 2]) > 0)
 
9532
                            nbNs++;
 
9533
                    }
 
9534
                } else {
 
9535
                    /*
 
9536
                     * check that it's not a defined attribute
 
9537
                     */
 
9538
                    for (j = 0;j < nbatts;j+=5) {
 
9539
                        if ((attname == atts[j]) && (aprefix == atts[j+1]))
 
9540
                            break;
 
9541
                    }
 
9542
                    if (j < nbatts) continue;
 
9543
 
 
9544
                    if ((atts == NULL) || (nbatts + 5 > maxatts)) {
 
9545
                        if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
 
9546
                            return(NULL);
 
9547
                        }
 
9548
                        maxatts = ctxt->maxatts;
 
9549
                        atts = ctxt->atts;
 
9550
                    }
 
9551
                    atts[nbatts++] = attname;
 
9552
                    atts[nbatts++] = aprefix;
 
9553
                    if (aprefix == NULL)
 
9554
                        atts[nbatts++] = NULL;
 
9555
                    else
 
9556
                        atts[nbatts++] = xmlGetNamespace(ctxt, aprefix);
 
9557
                    atts[nbatts++] = defaults->values[5 * i + 2];
 
9558
                    atts[nbatts++] = defaults->values[5 * i + 3];
 
9559
                    if ((ctxt->standalone == 1) &&
 
9560
                        (defaults->values[5 * i + 4] != NULL)) {
 
9561
                        xmlValidityError(ctxt, XML_DTD_STANDALONE_DEFAULTED,
 
9562
          "standalone: attribute %s on %s defaulted from external subset\n",
 
9563
                                         attname, localname);
 
9564
                    }
 
9565
                    nbdef++;
 
9566
                }
 
9567
            }
 
9568
        }
 
9569
    }
 
9570
 
 
9571
    /*
 
9572
     * The attributes checkings
 
9573
     */
 
9574
    for (i = 0; i < nbatts;i += 5) {
 
9575
        /*
 
9576
        * The default namespace does not apply to attribute names.
 
9577
        */
 
9578
        if (atts[i + 1] != NULL) {
 
9579
            nsname = xmlGetNamespace(ctxt, atts[i + 1]);
 
9580
            if (nsname == NULL) {
 
9581
                xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
 
9582
                    "Namespace prefix %s for %s on %s is not defined\n",
 
9583
                    atts[i + 1], atts[i], localname);
 
9584
            }
 
9585
            atts[i + 2] = nsname;
 
9586
        } else
 
9587
            nsname = NULL;
 
9588
        /*
 
9589
         * [ WFC: Unique Att Spec ]
 
9590
         * No attribute name may appear more than once in the same
 
9591
         * start-tag or empty-element tag.
 
9592
         * As extended by the Namespace in XML REC.
 
9593
         */
 
9594
        for (j = 0; j < i;j += 5) {
 
9595
            if (atts[i] == atts[j]) {
 
9596
                if (atts[i+1] == atts[j+1]) {
 
9597
                    xmlErrAttributeDup(ctxt, atts[i+1], atts[i]);
 
9598
                    break;
 
9599
                }
 
9600
                if ((nsname != NULL) && (atts[j + 2] == nsname)) {
 
9601
                    xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED,
 
9602
                             "Namespaced Attribute %s in '%s' redefined\n",
 
9603
                             atts[i], nsname, NULL);
 
9604
                    break;
 
9605
                }
 
9606
            }
 
9607
        }
 
9608
    }
 
9609
 
 
9610
    nsname = xmlGetNamespace(ctxt, prefix);
 
9611
    if ((prefix != NULL) && (nsname == NULL)) {
 
9612
        xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
 
9613
                 "Namespace prefix %s on %s is not defined\n",
 
9614
                 prefix, localname, NULL);
 
9615
    }
 
9616
    *pref = prefix;
 
9617
    *URI = nsname;
 
9618
 
 
9619
    /*
 
9620
     * SAX: Start of Element !
 
9621
     */
 
9622
    if ((ctxt->sax != NULL) && (ctxt->sax->startElementNs != NULL) &&
 
9623
        (!ctxt->disableSAX)) {
 
9624
        if (nbNs > 0)
 
9625
            ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
 
9626
                          nsname, nbNs, &ctxt->nsTab[ctxt->nsNr - 2 * nbNs],
 
9627
                          nbatts / 5, nbdef, atts);
 
9628
        else
 
9629
            ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
 
9630
                          nsname, 0, NULL, nbatts / 5, nbdef, atts);
 
9631
    }
 
9632
 
 
9633
    /*
 
9634
     * Free up attribute allocated strings if needed
 
9635
     */
 
9636
    if (attval != 0) {
 
9637
        for (i = 3,j = 0; j < nratts;i += 5,j++)
 
9638
            if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
 
9639
                xmlFree((xmlChar *) atts[i]);
 
9640
    }
 
9641
 
 
9642
    return(localname);
 
9643
 
 
9644
base_changed:
 
9645
    /*
 
9646
     * the attribute strings are valid iif the base didn't changed
 
9647
     */
 
9648
    if (attval != 0) {
 
9649
        for (i = 3,j = 0; j < nratts;i += 5,j++)
 
9650
            if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
 
9651
                xmlFree((xmlChar *) atts[i]);
 
9652
    }
 
9653
    ctxt->input->cur = ctxt->input->base + cur;
 
9654
    ctxt->input->line = oldline;
 
9655
    ctxt->input->col = oldcol;
 
9656
    if (ctxt->wellFormed == 1) {
 
9657
        goto reparse;
 
9658
    }
 
9659
    return(NULL);
 
9660
}
 
9661
 
 
9662
/**
 
9663
 * xmlParseEndTag2:
 
9664
 * @ctxt:  an XML parser context
 
9665
 * @line:  line of the start tag
 
9666
 * @nsNr:  number of namespaces on the start tag
 
9667
 *
 
9668
 * parse an end of tag
 
9669
 *
 
9670
 * [42] ETag ::= '</' Name S? '>'
 
9671
 *
 
9672
 * With namespace
 
9673
 *
 
9674
 * [NS 9] ETag ::= '</' QName S? '>'
 
9675
 */
 
9676
 
 
9677
static void
 
9678
xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlChar *prefix,
 
9679
                const xmlChar *URI, int line, int nsNr, int tlen) {
 
9680
    const xmlChar *name;
 
9681
 
 
9682
    GROW;
 
9683
    if ((RAW != '<') || (NXT(1) != '/')) {
 
9684
        xmlFatalErr(ctxt, XML_ERR_LTSLASH_REQUIRED, NULL);
 
9685
        return;
 
9686
    }
 
9687
    SKIP(2);
 
9688
 
 
9689
    if ((tlen > 0) && (xmlStrncmp(ctxt->input->cur, ctxt->name, tlen) == 0)) {
 
9690
        if (ctxt->input->cur[tlen] == '>') {
 
9691
            ctxt->input->cur += tlen + 1;
 
9692
            goto done;
 
9693
        }
 
9694
        ctxt->input->cur += tlen;
 
9695
        name = (xmlChar*)1;
 
9696
    } else {
 
9697
        if (prefix == NULL)
 
9698
            name = xmlParseNameAndCompare(ctxt, ctxt->name);
 
9699
        else
 
9700
            name = xmlParseQNameAndCompare(ctxt, ctxt->name, prefix);
 
9701
    }
 
9702
 
 
9703
    /*
 
9704
     * We should definitely be at the ending "S? '>'" part
 
9705
     */
 
9706
    GROW;
 
9707
    if (ctxt->instate == XML_PARSER_EOF)
 
9708
        return;
 
9709
    SKIP_BLANKS;
 
9710
    if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
 
9711
        xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
 
9712
    } else
 
9713
        NEXT1;
 
9714
 
 
9715
    /*
 
9716
     * [ WFC: Element Type Match ]
 
9717
     * The Name in an element's end-tag must match the element type in the
 
9718
     * start-tag.
 
9719
     *
 
9720
     */
 
9721
    if (name != (xmlChar*)1) {
 
9722
        if (name == NULL) name = BAD_CAST "unparseable";
 
9723
        if ((line == 0) && (ctxt->node != NULL))
 
9724
            line = ctxt->node->line;
 
9725
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
 
9726
                     "Opening and ending tag mismatch: %s line %d and %s\n",
 
9727
                                ctxt->name, line, name);
 
9728
    }
 
9729
 
 
9730
    /*
 
9731
     * SAX: End of Tag
 
9732
     */
 
9733
done:
 
9734
    if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
 
9735
        (!ctxt->disableSAX))
 
9736
        ctxt->sax->endElementNs(ctxt->userData, ctxt->name, prefix, URI);
 
9737
 
 
9738
    spacePop(ctxt);
 
9739
    if (nsNr != 0)
 
9740
        nsPop(ctxt, nsNr);
 
9741
    return;
 
9742
}
 
9743
 
 
9744
/**
 
9745
 * xmlParseCDSect:
 
9746
 * @ctxt:  an XML parser context
 
9747
 *
 
9748
 * Parse escaped pure raw content.
 
9749
 *
 
9750
 * [18] CDSect ::= CDStart CData CDEnd
 
9751
 *
 
9752
 * [19] CDStart ::= '<![CDATA['
 
9753
 *
 
9754
 * [20] Data ::= (Char* - (Char* ']]>' Char*))
 
9755
 *
 
9756
 * [21] CDEnd ::= ']]>'
 
9757
 */
 
9758
void
 
9759
xmlParseCDSect(xmlParserCtxtPtr ctxt) {
 
9760
    xmlChar *buf = NULL;
 
9761
    int len = 0;
 
9762
    int size = XML_PARSER_BUFFER_SIZE;
 
9763
    int r, rl;
 
9764
    int s, sl;
 
9765
    int cur, l;
 
9766
    int count = 0;
 
9767
 
 
9768
    /* Check 2.6.0 was NXT(0) not RAW */
 
9769
    if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
 
9770
        SKIP(9);
 
9771
    } else
 
9772
        return;
 
9773
 
 
9774
    ctxt->instate = XML_PARSER_CDATA_SECTION;
 
9775
    r = CUR_CHAR(rl);
 
9776
    if (!IS_CHAR(r)) {
 
9777
        xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
 
9778
        ctxt->instate = XML_PARSER_CONTENT;
 
9779
        return;
 
9780
    }
 
9781
    NEXTL(rl);
 
9782
    s = CUR_CHAR(sl);
 
9783
    if (!IS_CHAR(s)) {
 
9784
        xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
 
9785
        ctxt->instate = XML_PARSER_CONTENT;
 
9786
        return;
 
9787
    }
 
9788
    NEXTL(sl);
 
9789
    cur = CUR_CHAR(l);
 
9790
    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
9791
    if (buf == NULL) {
 
9792
        xmlErrMemory(ctxt, NULL);
 
9793
        return;
 
9794
    }
 
9795
    while (IS_CHAR(cur) &&
 
9796
           ((r != ']') || (s != ']') || (cur != '>'))) {
 
9797
        if (len + 5 >= size) {
 
9798
            xmlChar *tmp;
 
9799
 
 
9800
            if ((size > XML_MAX_TEXT_LENGTH) &&
 
9801
                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
9802
                xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED,
 
9803
                             "CData section too big found", NULL);
 
9804
                xmlFree (buf);
 
9805
                return;
 
9806
            }
 
9807
            tmp = (xmlChar *) xmlRealloc(buf, size * 2 * sizeof(xmlChar));
 
9808
            if (tmp == NULL) {
 
9809
                xmlFree(buf);
 
9810
                xmlErrMemory(ctxt, NULL);
 
9811
                return;
 
9812
            }
 
9813
            buf = tmp;
 
9814
            size *= 2;
 
9815
        }
 
9816
        COPY_BUF(rl,buf,len,r);
 
9817
        r = s;
 
9818
        rl = sl;
 
9819
        s = cur;
 
9820
        sl = l;
 
9821
        count++;
 
9822
        if (count > 50) {
 
9823
            GROW;
 
9824
            if (ctxt->instate == XML_PARSER_EOF) {
 
9825
                xmlFree(buf);
 
9826
                return;
 
9827
            }
 
9828
            count = 0;
 
9829
        }
 
9830
        NEXTL(l);
 
9831
        cur = CUR_CHAR(l);
 
9832
    }
 
9833
    buf[len] = 0;
 
9834
    ctxt->instate = XML_PARSER_CONTENT;
 
9835
    if (cur != '>') {
 
9836
        xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED,
 
9837
                             "CData section not finished\n%.50s\n", buf);
 
9838
        xmlFree(buf);
 
9839
        return;
 
9840
    }
 
9841
    NEXTL(l);
 
9842
 
 
9843
    /*
 
9844
     * OK the buffer is to be consumed as cdata.
 
9845
     */
 
9846
    if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
 
9847
        if (ctxt->sax->cdataBlock != NULL)
 
9848
            ctxt->sax->cdataBlock(ctxt->userData, buf, len);
 
9849
        else if (ctxt->sax->characters != NULL)
 
9850
            ctxt->sax->characters(ctxt->userData, buf, len);
 
9851
    }
 
9852
    xmlFree(buf);
 
9853
}
 
9854
 
 
9855
/**
 
9856
 * xmlParseContent:
 
9857
 * @ctxt:  an XML parser context
 
9858
 *
 
9859
 * Parse a content:
 
9860
 *
 
9861
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
 
9862
 */
 
9863
 
 
9864
void
 
9865
xmlParseContent(xmlParserCtxtPtr ctxt) {
 
9866
    GROW;
 
9867
    while ((RAW != 0) &&
 
9868
           ((RAW != '<') || (NXT(1) != '/')) &&
 
9869
           (ctxt->instate != XML_PARSER_EOF)) {
 
9870
        const xmlChar *test = CUR_PTR;
 
9871
        unsigned int cons = ctxt->input->consumed;
 
9872
        const xmlChar *cur = ctxt->input->cur;
 
9873
 
 
9874
        /*
 
9875
         * First case : a Processing Instruction.
 
9876
         */
 
9877
        if ((*cur == '<') && (cur[1] == '?')) {
 
9878
            xmlParsePI(ctxt);
 
9879
        }
 
9880
 
 
9881
        /*
 
9882
         * Second case : a CDSection
 
9883
         */
 
9884
        /* 2.6.0 test was *cur not RAW */
 
9885
        else if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
 
9886
            xmlParseCDSect(ctxt);
 
9887
        }
 
9888
 
 
9889
        /*
 
9890
         * Third case :  a comment
 
9891
         */
 
9892
        else if ((*cur == '<') && (NXT(1) == '!') &&
 
9893
                 (NXT(2) == '-') && (NXT(3) == '-')) {
 
9894
            xmlParseComment(ctxt);
 
9895
            ctxt->instate = XML_PARSER_CONTENT;
 
9896
        }
 
9897
 
 
9898
        /*
 
9899
         * Fourth case :  a sub-element.
 
9900
         */
 
9901
        else if (*cur == '<') {
 
9902
            xmlParseElement(ctxt);
 
9903
        }
 
9904
 
 
9905
        /*
 
9906
         * Fifth case : a reference. If if has not been resolved,
 
9907
         *    parsing returns it's Name, create the node
 
9908
         */
 
9909
 
 
9910
        else if (*cur == '&') {
 
9911
            xmlParseReference(ctxt);
 
9912
        }
 
9913
 
 
9914
        /*
 
9915
         * Last case, text. Note that References are handled directly.
 
9916
         */
 
9917
        else {
 
9918
            xmlParseCharData(ctxt, 0);
 
9919
        }
 
9920
 
 
9921
        GROW;
 
9922
        /*
 
9923
         * Pop-up of finished entities.
 
9924
         */
 
9925
        while ((RAW == 0) && (ctxt->inputNr > 1))
 
9926
            xmlPopInput(ctxt);
 
9927
        SHRINK;
 
9928
 
 
9929
        if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) {
 
9930
            xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
9931
                        "detected an error in element content\n");
 
9932
            ctxt->instate = XML_PARSER_EOF;
 
9933
            break;
 
9934
        }
 
9935
    }
 
9936
}
 
9937
 
 
9938
/**
 
9939
 * xmlParseElement:
 
9940
 * @ctxt:  an XML parser context
 
9941
 *
 
9942
 * parse an XML element, this is highly recursive
 
9943
 *
 
9944
 * [39] element ::= EmptyElemTag | STag content ETag
 
9945
 *
 
9946
 * [ WFC: Element Type Match ]
 
9947
 * The Name in an element's end-tag must match the element type in the
 
9948
 * start-tag.
 
9949
 *
 
9950
 */
 
9951
 
 
9952
void
 
9953
xmlParseElement(xmlParserCtxtPtr ctxt) {
 
9954
    const xmlChar *name;
 
9955
    const xmlChar *prefix = NULL;
 
9956
    const xmlChar *URI = NULL;
 
9957
    xmlParserNodeInfo node_info;
 
9958
    int line, tlen = 0;
 
9959
    xmlNodePtr ret;
 
9960
    int nsNr = ctxt->nsNr;
 
9961
 
 
9962
    if (((unsigned int) ctxt->nameNr > xmlParserMaxDepth) &&
 
9963
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
9964
        xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
 
9965
                 "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
 
9966
                          xmlParserMaxDepth);
 
9967
        ctxt->instate = XML_PARSER_EOF;
 
9968
        return;
 
9969
    }
 
9970
 
 
9971
    /* Capture start position */
 
9972
    if (ctxt->record_info) {
 
9973
        node_info.begin_pos = ctxt->input->consumed +
 
9974
                          (CUR_PTR - ctxt->input->base);
 
9975
        node_info.begin_line = ctxt->input->line;
 
9976
    }
 
9977
 
 
9978
    if (ctxt->spaceNr == 0)
 
9979
        spacePush(ctxt, -1);
 
9980
    else if (*ctxt->space == -2)
 
9981
        spacePush(ctxt, -1);
 
9982
    else
 
9983
        spacePush(ctxt, *ctxt->space);
 
9984
 
 
9985
    line = ctxt->input->line;
 
9986
#ifdef LIBXML_SAX1_ENABLED
 
9987
    if (ctxt->sax2)
 
9988
#endif /* LIBXML_SAX1_ENABLED */
 
9989
        name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
 
9990
#ifdef LIBXML_SAX1_ENABLED
 
9991
    else
 
9992
        name = xmlParseStartTag(ctxt);
 
9993
#endif /* LIBXML_SAX1_ENABLED */
 
9994
    if (ctxt->instate == XML_PARSER_EOF)
 
9995
        return;
 
9996
    if (name == NULL) {
 
9997
        spacePop(ctxt);
 
9998
        return;
 
9999
    }
 
10000
    namePush(ctxt, name);
 
10001
    ret = ctxt->node;
 
10002
 
 
10003
#ifdef LIBXML_VALID_ENABLED
 
10004
    /*
 
10005
     * [ VC: Root Element Type ]
 
10006
     * The Name in the document type declaration must match the element
 
10007
     * type of the root element.
 
10008
     */
 
10009
    if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
 
10010
        ctxt->node && (ctxt->node == ctxt->myDoc->children))
 
10011
        ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
 
10012
#endif /* LIBXML_VALID_ENABLED */
 
10013
 
 
10014
    /*
 
10015
     * Check for an Empty Element.
 
10016
     */
 
10017
    if ((RAW == '/') && (NXT(1) == '>')) {
 
10018
        SKIP(2);
 
10019
        if (ctxt->sax2) {
 
10020
            if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
 
10021
                (!ctxt->disableSAX))
 
10022
                ctxt->sax->endElementNs(ctxt->userData, name, prefix, URI);
 
10023
#ifdef LIBXML_SAX1_ENABLED
 
10024
        } else {
 
10025
            if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
 
10026
                (!ctxt->disableSAX))
 
10027
                ctxt->sax->endElement(ctxt->userData, name);
 
10028
#endif /* LIBXML_SAX1_ENABLED */
 
10029
        }
 
10030
        namePop(ctxt);
 
10031
        spacePop(ctxt);
 
10032
        if (nsNr != ctxt->nsNr)
 
10033
            nsPop(ctxt, ctxt->nsNr - nsNr);
 
10034
        if ( ret != NULL && ctxt->record_info ) {
 
10035
           node_info.end_pos = ctxt->input->consumed +
 
10036
                              (CUR_PTR - ctxt->input->base);
 
10037
           node_info.end_line = ctxt->input->line;
 
10038
           node_info.node = ret;
 
10039
           xmlParserAddNodeInfo(ctxt, &node_info);
 
10040
        }
 
10041
        return;
 
10042
    }
 
10043
    if (RAW == '>') {
 
10044
        NEXT1;
 
10045
    } else {
 
10046
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_GT_REQUIRED,
 
10047
                     "Couldn't find end of Start Tag %s line %d\n",
 
10048
                                name, line, NULL);
 
10049
 
 
10050
        /*
 
10051
         * end of parsing of this node.
 
10052
         */
 
10053
        nodePop(ctxt);
 
10054
        namePop(ctxt);
 
10055
        spacePop(ctxt);
 
10056
        if (nsNr != ctxt->nsNr)
 
10057
            nsPop(ctxt, ctxt->nsNr - nsNr);
 
10058
 
 
10059
        /*
 
10060
         * Capture end position and add node
 
10061
         */
 
10062
        if ( ret != NULL && ctxt->record_info ) {
 
10063
           node_info.end_pos = ctxt->input->consumed +
 
10064
                              (CUR_PTR - ctxt->input->base);
 
10065
           node_info.end_line = ctxt->input->line;
 
10066
           node_info.node = ret;
 
10067
           xmlParserAddNodeInfo(ctxt, &node_info);
 
10068
        }
 
10069
        return;
 
10070
    }
 
10071
 
 
10072
    /*
 
10073
     * Parse the content of the element:
 
10074
     */
 
10075
    xmlParseContent(ctxt);
 
10076
    if (ctxt->instate == XML_PARSER_EOF)
 
10077
        return;
 
10078
    if (!IS_BYTE_CHAR(RAW)) {
 
10079
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
 
10080
         "Premature end of data in tag %s line %d\n",
 
10081
                                name, line, NULL);
 
10082
 
 
10083
        /*
 
10084
         * end of parsing of this node.
 
10085
         */
 
10086
        nodePop(ctxt);
 
10087
        namePop(ctxt);
 
10088
        spacePop(ctxt);
 
10089
        if (nsNr != ctxt->nsNr)
 
10090
            nsPop(ctxt, ctxt->nsNr - nsNr);
 
10091
        return;
 
10092
    }
 
10093
 
 
10094
    /*
 
10095
     * parse the end of tag: '</' should be here.
 
10096
     */
 
10097
    if (ctxt->sax2) {
 
10098
        xmlParseEndTag2(ctxt, prefix, URI, line, ctxt->nsNr - nsNr, tlen);
 
10099
        namePop(ctxt);
 
10100
    }
 
10101
#ifdef LIBXML_SAX1_ENABLED
 
10102
      else
 
10103
        xmlParseEndTag1(ctxt, line);
 
10104
#endif /* LIBXML_SAX1_ENABLED */
 
10105
 
 
10106
    /*
 
10107
     * Capture end position and add node
 
10108
     */
 
10109
    if ( ret != NULL && ctxt->record_info ) {
 
10110
       node_info.end_pos = ctxt->input->consumed +
 
10111
                          (CUR_PTR - ctxt->input->base);
 
10112
       node_info.end_line = ctxt->input->line;
 
10113
       node_info.node = ret;
 
10114
       xmlParserAddNodeInfo(ctxt, &node_info);
 
10115
    }
 
10116
}
 
10117
 
 
10118
/**
 
10119
 * xmlParseVersionNum:
 
10120
 * @ctxt:  an XML parser context
 
10121
 *
 
10122
 * parse the XML version value.
 
10123
 *
 
10124
 * [26] VersionNum ::= '1.' [0-9]+
 
10125
 *
 
10126
 * In practice allow [0-9].[0-9]+ at that level
 
10127
 *
 
10128
 * Returns the string giving the XML version number, or NULL
 
10129
 */
 
10130
xmlChar *
 
10131
xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
 
10132
    xmlChar *buf = NULL;
 
10133
    int len = 0;
 
10134
    int size = 10;
 
10135
    xmlChar cur;
 
10136
 
 
10137
    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
10138
    if (buf == NULL) {
 
10139
        xmlErrMemory(ctxt, NULL);
 
10140
        return(NULL);
 
10141
    }
 
10142
    cur = CUR;
 
10143
    if (!((cur >= '0') && (cur <= '9'))) {
 
10144
        xmlFree(buf);
 
10145
        return(NULL);
 
10146
    }
 
10147
    buf[len++] = cur;
 
10148
    NEXT;
 
10149
    cur=CUR;
 
10150
    if (cur != '.') {
 
10151
        xmlFree(buf);
 
10152
        return(NULL);
 
10153
    }
 
10154
    buf[len++] = cur;
 
10155
    NEXT;
 
10156
    cur=CUR;
 
10157
    while ((cur >= '0') && (cur <= '9')) {
 
10158
        if (len + 1 >= size) {
 
10159
            xmlChar *tmp;
 
10160
 
 
10161
            size *= 2;
 
10162
            tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
 
10163
            if (tmp == NULL) {
 
10164
                xmlFree(buf);
 
10165
                xmlErrMemory(ctxt, NULL);
 
10166
                return(NULL);
 
10167
            }
 
10168
            buf = tmp;
 
10169
        }
 
10170
        buf[len++] = cur;
 
10171
        NEXT;
 
10172
        cur=CUR;
 
10173
    }
 
10174
    buf[len] = 0;
 
10175
    return(buf);
 
10176
}
 
10177
 
 
10178
/**
 
10179
 * xmlParseVersionInfo:
 
10180
 * @ctxt:  an XML parser context
 
10181
 *
 
10182
 * parse the XML version.
 
10183
 *
 
10184
 * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
 
10185
 *
 
10186
 * [25] Eq ::= S? '=' S?
 
10187
 *
 
10188
 * Returns the version string, e.g. "1.0"
 
10189
 */
 
10190
 
 
10191
xmlChar *
 
10192
xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
 
10193
    xmlChar *version = NULL;
 
10194
 
 
10195
    if (CMP7(CUR_PTR, 'v', 'e', 'r', 's', 'i', 'o', 'n')) {
 
10196
        SKIP(7);
 
10197
        SKIP_BLANKS;
 
10198
        if (RAW != '=') {
 
10199
            xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
 
10200
            return(NULL);
 
10201
        }
 
10202
        NEXT;
 
10203
        SKIP_BLANKS;
 
10204
        if (RAW == '"') {
 
10205
            NEXT;
 
10206
            version = xmlParseVersionNum(ctxt);
 
10207
            if (RAW != '"') {
 
10208
                xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
 
10209
            } else
 
10210
                NEXT;
 
10211
        } else if (RAW == '\''){
 
10212
            NEXT;
 
10213
            version = xmlParseVersionNum(ctxt);
 
10214
            if (RAW != '\'') {
 
10215
                xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
 
10216
            } else
 
10217
                NEXT;
 
10218
        } else {
 
10219
            xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
 
10220
        }
 
10221
    }
 
10222
    return(version);
 
10223
}
 
10224
 
 
10225
/**
 
10226
 * xmlParseEncName:
 
10227
 * @ctxt:  an XML parser context
 
10228
 *
 
10229
 * parse the XML encoding name
 
10230
 *
 
10231
 * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
 
10232
 *
 
10233
 * Returns the encoding name value or NULL
 
10234
 */
 
10235
xmlChar *
 
10236
xmlParseEncName(xmlParserCtxtPtr ctxt) {
 
10237
    xmlChar *buf = NULL;
 
10238
    int len = 0;
 
10239
    int size = 10;
 
10240
    xmlChar cur;
 
10241
 
 
10242
    cur = CUR;
 
10243
    if (((cur >= 'a') && (cur <= 'z')) ||
 
10244
        ((cur >= 'A') && (cur <= 'Z'))) {
 
10245
        buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 
10246
        if (buf == NULL) {
 
10247
            xmlErrMemory(ctxt, NULL);
 
10248
            return(NULL);
 
10249
        }
 
10250
 
 
10251
        buf[len++] = cur;
 
10252
        NEXT;
 
10253
        cur = CUR;
 
10254
        while (((cur >= 'a') && (cur <= 'z')) ||
 
10255
               ((cur >= 'A') && (cur <= 'Z')) ||
 
10256
               ((cur >= '0') && (cur <= '9')) ||
 
10257
               (cur == '.') || (cur == '_') ||
 
10258
               (cur == '-')) {
 
10259
            if (len + 1 >= size) {
 
10260
                xmlChar *tmp;
 
10261
 
 
10262
                size *= 2;
 
10263
                tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
 
10264
                if (tmp == NULL) {
 
10265
                    xmlErrMemory(ctxt, NULL);
 
10266
                    xmlFree(buf);
 
10267
                    return(NULL);
 
10268
                }
 
10269
                buf = tmp;
 
10270
            }
 
10271
            buf[len++] = cur;
 
10272
            NEXT;
 
10273
            cur = CUR;
 
10274
            if (cur == 0) {
 
10275
                SHRINK;
 
10276
                GROW;
 
10277
                cur = CUR;
 
10278
            }
 
10279
        }
 
10280
        buf[len] = 0;
 
10281
    } else {
 
10282
        xmlFatalErr(ctxt, XML_ERR_ENCODING_NAME, NULL);
 
10283
    }
 
10284
    return(buf);
 
10285
}
 
10286
 
 
10287
/**
 
10288
 * xmlParseEncodingDecl:
 
10289
 * @ctxt:  an XML parser context
 
10290
 *
 
10291
 * parse the XML encoding declaration
 
10292
 *
 
10293
 * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' |  "'" EncName "'")
 
10294
 *
 
10295
 * this setups the conversion filters.
 
10296
 *
 
10297
 * Returns the encoding value or NULL
 
10298
 */
 
10299
 
 
10300
const xmlChar *
 
10301
xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
 
10302
    xmlChar *encoding = NULL;
 
10303
 
 
10304
    SKIP_BLANKS;
 
10305
    if (CMP8(CUR_PTR, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g')) {
 
10306
        SKIP(8);
 
10307
        SKIP_BLANKS;
 
10308
        if (RAW != '=') {
 
10309
            xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
 
10310
            return(NULL);
 
10311
        }
 
10312
        NEXT;
 
10313
        SKIP_BLANKS;
 
10314
        if (RAW == '"') {
 
10315
            NEXT;
 
10316
            encoding = xmlParseEncName(ctxt);
 
10317
            if (RAW != '"') {
 
10318
                xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
 
10319
            } else
 
10320
                NEXT;
 
10321
        } else if (RAW == '\''){
 
10322
            NEXT;
 
10323
            encoding = xmlParseEncName(ctxt);
 
10324
            if (RAW != '\'') {
 
10325
                xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
 
10326
            } else
 
10327
                NEXT;
 
10328
        } else {
 
10329
            xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
 
10330
        }
 
10331
 
 
10332
        /*
 
10333
         * Non standard parsing, allowing the user to ignore encoding
 
10334
         */
 
10335
        if (ctxt->options & XML_PARSE_IGNORE_ENC)
 
10336
            return(encoding);
 
10337
 
 
10338
        /*
 
10339
         * UTF-16 encoding stwich has already taken place at this stage,
 
10340
         * more over the little-endian/big-endian selection is already done
 
10341
         */
 
10342
        if ((encoding != NULL) &&
 
10343
            ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-16")) ||
 
10344
             (!xmlStrcasecmp(encoding, BAD_CAST "UTF16")))) {
 
10345
            /*
 
10346
             * If no encoding was passed to the parser, that we are
 
10347
             * using UTF-16 and no decoder is present i.e. the
 
10348
             * document is apparently UTF-8 compatible, then raise an
 
10349
             * encoding mismatch fatal error
 
10350
             */
 
10351
            if ((ctxt->encoding == NULL) &&
 
10352
                (ctxt->input->buf != NULL) &&
 
10353
                (ctxt->input->buf->encoder == NULL)) {
 
10354
                xmlFatalErrMsg(ctxt, XML_ERR_INVALID_ENCODING,
 
10355
                  "Document labelled UTF-16 but has UTF-8 content\n");
 
10356
            }
 
10357
            if (ctxt->encoding != NULL)
 
10358
                xmlFree((xmlChar *) ctxt->encoding);
 
10359
            ctxt->encoding = encoding;
 
10360
        }
 
10361
        /*
 
10362
         * UTF-8 encoding is handled natively
 
10363
         */
 
10364
        else if ((encoding != NULL) &&
 
10365
            ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-8")) ||
 
10366
             (!xmlStrcasecmp(encoding, BAD_CAST "UTF8")))) {
 
10367
            if (ctxt->encoding != NULL)
 
10368
                xmlFree((xmlChar *) ctxt->encoding);
 
10369
            ctxt->encoding = encoding;
 
10370
        }
 
10371
        else if (encoding != NULL) {
 
10372
            xmlCharEncodingHandlerPtr handler;
 
10373
 
 
10374
            if (ctxt->input->encoding != NULL)
 
10375
                xmlFree((xmlChar *) ctxt->input->encoding);
 
10376
            ctxt->input->encoding = encoding;
 
10377
 
 
10378
            handler = xmlFindCharEncodingHandler((const char *) encoding);
 
10379
            if (handler != NULL) {
 
10380
                xmlSwitchToEncoding(ctxt, handler);
 
10381
            } else {
 
10382
                xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
 
10383
                        "Unsupported encoding %s\n", encoding);
 
10384
                return(NULL);
 
10385
            }
 
10386
        }
 
10387
    }
 
10388
    return(encoding);
 
10389
}
 
10390
 
 
10391
/**
 
10392
 * xmlParseSDDecl:
 
10393
 * @ctxt:  an XML parser context
 
10394
 *
 
10395
 * parse the XML standalone declaration
 
10396
 *
 
10397
 * [32] SDDecl ::= S 'standalone' Eq
 
10398
 *                 (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no')'"'))
 
10399
 *
 
10400
 * [ VC: Standalone Document Declaration ]
 
10401
 * TODO The standalone document declaration must have the value "no"
 
10402
 * if any external markup declarations contain declarations of:
 
10403
 *  - attributes with default values, if elements to which these
 
10404
 *    attributes apply appear in the document without specifications
 
10405
 *    of values for these attributes, or
 
10406
 *  - entities (other than amp, lt, gt, apos, quot), if references
 
10407
 *    to those entities appear in the document, or
 
10408
 *  - attributes with values subject to normalization, where the
 
10409
 *    attribute appears in the document with a value which will change
 
10410
 *    as a result of normalization, or
 
10411
 *  - element types with element content, if white space occurs directly
 
10412
 *    within any instance of those types.
 
10413
 *
 
10414
 * Returns:
 
10415
 *   1 if standalone="yes"
 
10416
 *   0 if standalone="no"
 
10417
 *  -2 if standalone attribute is missing or invalid
 
10418
 *        (A standalone value of -2 means that the XML declaration was found,
 
10419
 *         but no value was specified for the standalone attribute).
 
10420
 */
 
10421
 
 
10422
int
 
10423
xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
 
10424
    int standalone = -2;
 
10425
 
 
10426
    SKIP_BLANKS;
 
10427
    if (CMP10(CUR_PTR, 's', 't', 'a', 'n', 'd', 'a', 'l', 'o', 'n', 'e')) {
 
10428
        SKIP(10);
 
10429
        SKIP_BLANKS;
 
10430
        if (RAW != '=') {
 
10431
            xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
 
10432
            return(standalone);
 
10433
        }
 
10434
        NEXT;
 
10435
        SKIP_BLANKS;
 
10436
        if (RAW == '\''){
 
10437
            NEXT;
 
10438
            if ((RAW == 'n') && (NXT(1) == 'o')) {
 
10439
                standalone = 0;
 
10440
                SKIP(2);
 
10441
            } else if ((RAW == 'y') && (NXT(1) == 'e') &&
 
10442
                       (NXT(2) == 's')) {
 
10443
                standalone = 1;
 
10444
                SKIP(3);
 
10445
            } else {
 
10446
                xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
 
10447
            }
 
10448
            if (RAW != '\'') {
 
10449
                xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
 
10450
            } else
 
10451
                NEXT;
 
10452
        } else if (RAW == '"'){
 
10453
            NEXT;
 
10454
            if ((RAW == 'n') && (NXT(1) == 'o')) {
 
10455
                standalone = 0;
 
10456
                SKIP(2);
 
10457
            } else if ((RAW == 'y') && (NXT(1) == 'e') &&
 
10458
                       (NXT(2) == 's')) {
 
10459
                standalone = 1;
 
10460
                SKIP(3);
 
10461
            } else {
 
10462
                xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
 
10463
            }
 
10464
            if (RAW != '"') {
 
10465
                xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
 
10466
            } else
 
10467
                NEXT;
 
10468
        } else {
 
10469
            xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
 
10470
        }
 
10471
    }
 
10472
    return(standalone);
 
10473
}
 
10474
 
 
10475
/**
 
10476
 * xmlParseXMLDecl:
 
10477
 * @ctxt:  an XML parser context
 
10478
 *
 
10479
 * parse an XML declaration header
 
10480
 *
 
10481
 * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
 
10482
 */
 
10483
 
 
10484
void
 
10485
xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
 
10486
    xmlChar *version;
 
10487
 
 
10488
    /*
 
10489
     * This value for standalone indicates that the document has an
 
10490
     * XML declaration but it does not have a standalone attribute.
 
10491
     * It will be overwritten later if a standalone attribute is found.
 
10492
     */
 
10493
    ctxt->input->standalone = -2;
 
10494
 
 
10495
    /*
 
10496
     * We know that '<?xml' is here.
 
10497
     */
 
10498
    SKIP(5);
 
10499
 
 
10500
    if (!IS_BLANK_CH(RAW)) {
 
10501
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 
10502
                       "Blank needed after '<?xml'\n");
 
10503
    }
 
10504
    SKIP_BLANKS;
 
10505
 
 
10506
    /*
 
10507
     * We must have the VersionInfo here.
 
10508
     */
 
10509
    version = xmlParseVersionInfo(ctxt);
 
10510
    if (version == NULL) {
 
10511
        xmlFatalErr(ctxt, XML_ERR_VERSION_MISSING, NULL);
 
10512
    } else {
 
10513
        if (!xmlStrEqual(version, (const xmlChar *) XML_DEFAULT_VERSION)) {
 
10514
            /*
 
10515
             * Changed here for XML-1.0 5th edition
 
10516
             */
 
10517
            if (ctxt->options & XML_PARSE_OLD10) {
 
10518
                xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
 
10519
                                  "Unsupported version '%s'\n",
 
10520
                                  version);
 
10521
            } else {
 
10522
                if ((version[0] == '1') && ((version[1] == '.'))) {
 
10523
                    xmlWarningMsg(ctxt, XML_WAR_UNKNOWN_VERSION,
 
10524
                                  "Unsupported version '%s'\n",
 
10525
                                  version, NULL);
 
10526
                } else {
 
10527
                    xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
 
10528
                                      "Unsupported version '%s'\n",
 
10529
                                      version);
 
10530
                }
 
10531
            }
 
10532
        }
 
10533
        if (ctxt->version != NULL)
 
10534
            xmlFree((void *) ctxt->version);
 
10535
        ctxt->version = version;
 
10536
    }
 
10537
 
 
10538
    /*
 
10539
     * We may have the encoding declaration
 
10540
     */
 
10541
    if (!IS_BLANK_CH(RAW)) {
 
10542
        if ((RAW == '?') && (NXT(1) == '>')) {
 
10543
            SKIP(2);
 
10544
            return;
 
10545
        }
 
10546
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
 
10547
    }
 
10548
    xmlParseEncodingDecl(ctxt);
 
10549
    if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
 
10550
        /*
 
10551
         * The XML REC instructs us to stop parsing right here
 
10552
         */
 
10553
        return;
 
10554
    }
 
10555
 
 
10556
    /*
 
10557
     * We may have the standalone status.
 
10558
     */
 
10559
    if ((ctxt->input->encoding != NULL) && (!IS_BLANK_CH(RAW))) {
 
10560
        if ((RAW == '?') && (NXT(1) == '>')) {
 
10561
            SKIP(2);
 
10562
            return;
 
10563
        }
 
10564
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
 
10565
    }
 
10566
 
 
10567
    /*
 
10568
     * We can grow the input buffer freely at that point
 
10569
     */
 
10570
    GROW;
 
10571
 
 
10572
    SKIP_BLANKS;
 
10573
    ctxt->input->standalone = xmlParseSDDecl(ctxt);
 
10574
 
 
10575
    SKIP_BLANKS;
 
10576
    if ((RAW == '?') && (NXT(1) == '>')) {
 
10577
        SKIP(2);
 
10578
    } else if (RAW == '>') {
 
10579
        /* Deprecated old WD ... */
 
10580
        xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
 
10581
        NEXT;
 
10582
    } else {
 
10583
        xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
 
10584
        MOVETO_ENDTAG(CUR_PTR);
 
10585
        NEXT;
 
10586
    }
 
10587
}
 
10588
 
 
10589
/**
 
10590
 * xmlParseMisc:
 
10591
 * @ctxt:  an XML parser context
 
10592
 *
 
10593
 * parse an XML Misc* optional field.
 
10594
 *
 
10595
 * [27] Misc ::= Comment | PI |  S
 
10596
 */
 
10597
 
 
10598
void
 
10599
xmlParseMisc(xmlParserCtxtPtr ctxt) {
 
10600
    while ((ctxt->instate != XML_PARSER_EOF) &&
 
10601
           (((RAW == '<') && (NXT(1) == '?')) ||
 
10602
            (CMP4(CUR_PTR, '<', '!', '-', '-')) ||
 
10603
            IS_BLANK_CH(CUR))) {
 
10604
        if ((RAW == '<') && (NXT(1) == '?')) {
 
10605
            xmlParsePI(ctxt);
 
10606
        } else if (IS_BLANK_CH(CUR)) {
 
10607
            NEXT;
 
10608
        } else
 
10609
            xmlParseComment(ctxt);
 
10610
    }
 
10611
}
 
10612
 
 
10613
/**
 
10614
 * xmlParseDocument:
 
10615
 * @ctxt:  an XML parser context
 
10616
 *
 
10617
 * parse an XML document (and build a tree if using the standard SAX
 
10618
 * interface).
 
10619
 *
 
10620
 * [1] document ::= prolog element Misc*
 
10621
 *
 
10622
 * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
 
10623
 *
 
10624
 * Returns 0, -1 in case of error. the parser context is augmented
 
10625
 *                as a result of the parsing.
 
10626
 */
 
10627
 
 
10628
int
 
10629
xmlParseDocument(xmlParserCtxtPtr ctxt) {
 
10630
    xmlChar start[4];
 
10631
    xmlCharEncoding enc;
 
10632
 
 
10633
    xmlInitParser();
 
10634
 
 
10635
    if ((ctxt == NULL) || (ctxt->input == NULL))
 
10636
        return(-1);
 
10637
 
 
10638
    GROW;
 
10639
 
 
10640
    /*
 
10641
     * SAX: detecting the level.
 
10642
     */
 
10643
    xmlDetectSAX2(ctxt);
 
10644
 
 
10645
    /*
 
10646
     * SAX: beginning of the document processing.
 
10647
     */
 
10648
    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
 
10649
        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
 
10650
    if (ctxt->instate == XML_PARSER_EOF)
 
10651
        return(-1);
 
10652
 
 
10653
    if ((ctxt->encoding == NULL) &&
 
10654
        ((ctxt->input->end - ctxt->input->cur) >= 4)) {
 
10655
        /*
 
10656
         * Get the 4 first bytes and decode the charset
 
10657
         * if enc != XML_CHAR_ENCODING_NONE
 
10658
         * plug some encoding conversion routines.
 
10659
         */
 
10660
        start[0] = RAW;
 
10661
        start[1] = NXT(1);
 
10662
        start[2] = NXT(2);
 
10663
        start[3] = NXT(3);
 
10664
        enc = xmlDetectCharEncoding(&start[0], 4);
 
10665
        if (enc != XML_CHAR_ENCODING_NONE) {
 
10666
            xmlSwitchEncoding(ctxt, enc);
 
10667
        }
 
10668
    }
 
10669
 
 
10670
 
 
10671
    if (CUR == 0) {
 
10672
        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
 
10673
    }
 
10674
 
 
10675
    /*
 
10676
     * Check for the XMLDecl in the Prolog.
 
10677
     * do not GROW here to avoid the detected encoder to decode more
 
10678
     * than just the first line, unless the amount of data is really
 
10679
     * too small to hold "<?xml version="1.0" encoding="foo"
 
10680
     */
 
10681
    if ((ctxt->input->end - ctxt->input->cur) < 35) {
 
10682
       GROW;
 
10683
    }
 
10684
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
 
10685
 
 
10686
        /*
 
10687
         * Note that we will switch encoding on the fly.
 
10688
         */
 
10689
        xmlParseXMLDecl(ctxt);
 
10690
        if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
 
10691
            /*
 
10692
             * The XML REC instructs us to stop parsing right here
 
10693
             */
 
10694
            return(-1);
 
10695
        }
 
10696
        ctxt->standalone = ctxt->input->standalone;
 
10697
        SKIP_BLANKS;
 
10698
    } else {
 
10699
        ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
 
10700
    }
 
10701
    if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
 
10702
        ctxt->sax->startDocument(ctxt->userData);
 
10703
    if (ctxt->instate == XML_PARSER_EOF)
 
10704
        return(-1);
 
10705
 
 
10706
    /*
 
10707
     * The Misc part of the Prolog
 
10708
     */
 
10709
    GROW;
 
10710
    xmlParseMisc(ctxt);
 
10711
 
 
10712
    /*
 
10713
     * Then possibly doc type declaration(s) and more Misc
 
10714
     * (doctypedecl Misc*)?
 
10715
     */
 
10716
    GROW;
 
10717
    if (CMP9(CUR_PTR, '<', '!', 'D', 'O', 'C', 'T', 'Y', 'P', 'E')) {
 
10718
 
 
10719
        ctxt->inSubset = 1;
 
10720
        xmlParseDocTypeDecl(ctxt);
 
10721
        if (RAW == '[') {
 
10722
            ctxt->instate = XML_PARSER_DTD;
 
10723
            xmlParseInternalSubset(ctxt);
 
10724
            if (ctxt->instate == XML_PARSER_EOF)
 
10725
                return(-1);
 
10726
        }
 
10727
 
 
10728
        /*
 
10729
         * Create and update the external subset.
 
10730
         */
 
10731
        ctxt->inSubset = 2;
 
10732
        if ((ctxt->sax != NULL) && (ctxt->sax->externalSubset != NULL) &&
 
10733
            (!ctxt->disableSAX))
 
10734
            ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
 
10735
                                      ctxt->extSubSystem, ctxt->extSubURI);
 
10736
        if (ctxt->instate == XML_PARSER_EOF)
 
10737
            return(-1);
 
10738
        ctxt->inSubset = 0;
 
10739
 
 
10740
        xmlCleanSpecialAttr(ctxt);
 
10741
 
 
10742
        ctxt->instate = XML_PARSER_PROLOG;
 
10743
        xmlParseMisc(ctxt);
 
10744
    }
 
10745
 
 
10746
    /*
 
10747
     * Time to start parsing the tree itself
 
10748
     */
 
10749
    GROW;
 
10750
    if (RAW != '<') {
 
10751
        xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
 
10752
                       "Start tag expected, '<' not found\n");
 
10753
    } else {
 
10754
        ctxt->instate = XML_PARSER_CONTENT;
 
10755
        xmlParseElement(ctxt);
 
10756
        ctxt->instate = XML_PARSER_EPILOG;
 
10757
 
 
10758
 
 
10759
        /*
 
10760
         * The Misc part at the end
 
10761
         */
 
10762
        xmlParseMisc(ctxt);
 
10763
 
 
10764
        if (RAW != 0) {
 
10765
            xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
 
10766
        }
 
10767
        ctxt->instate = XML_PARSER_EOF;
 
10768
    }
 
10769
 
 
10770
    /*
 
10771
     * SAX: end of the document processing.
 
10772
     */
 
10773
    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 
10774
        ctxt->sax->endDocument(ctxt->userData);
 
10775
 
 
10776
    /*
 
10777
     * Remove locally kept entity definitions if the tree was not built
 
10778
     */
 
10779
    if ((ctxt->myDoc != NULL) &&
 
10780
        (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
 
10781
        xmlFreeDoc(ctxt->myDoc);
 
10782
        ctxt->myDoc = NULL;
 
10783
    }
 
10784
 
 
10785
    if ((ctxt->wellFormed) && (ctxt->myDoc != NULL)) {
 
10786
        ctxt->myDoc->properties |= XML_DOC_WELLFORMED;
 
10787
        if (ctxt->valid)
 
10788
            ctxt->myDoc->properties |= XML_DOC_DTDVALID;
 
10789
        if (ctxt->nsWellFormed)
 
10790
            ctxt->myDoc->properties |= XML_DOC_NSVALID;
 
10791
        if (ctxt->options & XML_PARSE_OLD10)
 
10792
            ctxt->myDoc->properties |= XML_DOC_OLD10;
 
10793
    }
 
10794
    if (! ctxt->wellFormed) {
 
10795
        ctxt->valid = 0;
 
10796
        return(-1);
 
10797
    }
 
10798
    return(0);
 
10799
}
 
10800
 
 
10801
/**
 
10802
 * xmlParseExtParsedEnt:
 
10803
 * @ctxt:  an XML parser context
 
10804
 *
 
10805
 * parse a general parsed entity
 
10806
 * An external general parsed entity is well-formed if it matches the
 
10807
 * production labeled extParsedEnt.
 
10808
 *
 
10809
 * [78] extParsedEnt ::= TextDecl? content
 
10810
 *
 
10811
 * Returns 0, -1 in case of error. the parser context is augmented
 
10812
 *                as a result of the parsing.
 
10813
 */
 
10814
 
 
10815
int
 
10816
xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) {
 
10817
    xmlChar start[4];
 
10818
    xmlCharEncoding enc;
 
10819
 
 
10820
    if ((ctxt == NULL) || (ctxt->input == NULL))
 
10821
        return(-1);
 
10822
 
 
10823
    xmlDefaultSAXHandlerInit();
 
10824
 
 
10825
    xmlDetectSAX2(ctxt);
 
10826
 
 
10827
    GROW;
 
10828
 
 
10829
    /*
 
10830
     * SAX: beginning of the document processing.
 
10831
     */
 
10832
    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
 
10833
        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
 
10834
 
 
10835
    /*
 
10836
     * Get the 4 first bytes and decode the charset
 
10837
     * if enc != XML_CHAR_ENCODING_NONE
 
10838
     * plug some encoding conversion routines.
 
10839
     */
 
10840
    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
 
10841
        start[0] = RAW;
 
10842
        start[1] = NXT(1);
 
10843
        start[2] = NXT(2);
 
10844
        start[3] = NXT(3);
 
10845
        enc = xmlDetectCharEncoding(start, 4);
 
10846
        if (enc != XML_CHAR_ENCODING_NONE) {
 
10847
            xmlSwitchEncoding(ctxt, enc);
 
10848
        }
 
10849
    }
 
10850
 
 
10851
 
 
10852
    if (CUR == 0) {
 
10853
        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
 
10854
    }
 
10855
 
 
10856
    /*
 
10857
     * Check for the XMLDecl in the Prolog.
 
10858
     */
 
10859
    GROW;
 
10860
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
 
10861
 
 
10862
        /*
 
10863
         * Note that we will switch encoding on the fly.
 
10864
         */
 
10865
        xmlParseXMLDecl(ctxt);
 
10866
        if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
 
10867
            /*
 
10868
             * The XML REC instructs us to stop parsing right here
 
10869
             */
 
10870
            return(-1);
 
10871
        }
 
10872
        SKIP_BLANKS;
 
10873
    } else {
 
10874
        ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
 
10875
    }
 
10876
    if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
 
10877
        ctxt->sax->startDocument(ctxt->userData);
 
10878
    if (ctxt->instate == XML_PARSER_EOF)
 
10879
        return(-1);
 
10880
 
 
10881
    /*
 
10882
     * Doing validity checking on chunk doesn't make sense
 
10883
     */
 
10884
    ctxt->instate = XML_PARSER_CONTENT;
 
10885
    ctxt->validate = 0;
 
10886
    ctxt->loadsubset = 0;
 
10887
    ctxt->depth = 0;
 
10888
 
 
10889
    xmlParseContent(ctxt);
 
10890
    if (ctxt->instate == XML_PARSER_EOF)
 
10891
        return(-1);
 
10892
 
 
10893
    if ((RAW == '<') && (NXT(1) == '/')) {
 
10894
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
10895
    } else if (RAW != 0) {
 
10896
        xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
 
10897
    }
 
10898
 
 
10899
    /*
 
10900
     * SAX: end of the document processing.
 
10901
     */
 
10902
    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 
10903
        ctxt->sax->endDocument(ctxt->userData);
 
10904
 
 
10905
    if (! ctxt->wellFormed) return(-1);
 
10906
    return(0);
 
10907
}
 
10908
 
 
10909
#ifdef LIBXML_PUSH_ENABLED
 
10910
/************************************************************************
 
10911
 *                                                                      *
 
10912
 *              Progressive parsing interfaces                          *
 
10913
 *                                                                      *
 
10914
 ************************************************************************/
 
10915
 
 
10916
/**
 
10917
 * xmlParseLookupSequence:
 
10918
 * @ctxt:  an XML parser context
 
10919
 * @first:  the first char to lookup
 
10920
 * @next:  the next char to lookup or zero
 
10921
 * @third:  the next char to lookup or zero
 
10922
 *
 
10923
 * Try to find if a sequence (first, next, third) or  just (first next) or
 
10924
 * (first) is available in the input stream.
 
10925
 * This function has a side effect of (possibly) incrementing ctxt->checkIndex
 
10926
 * to avoid rescanning sequences of bytes, it DOES change the state of the
 
10927
 * parser, do not use liberally.
 
10928
 *
 
10929
 * Returns the index to the current parsing point if the full sequence
 
10930
 *      is available, -1 otherwise.
 
10931
 */
 
10932
static int
 
10933
xmlParseLookupSequence(xmlParserCtxtPtr ctxt, xmlChar first,
 
10934
                       xmlChar next, xmlChar third) {
 
10935
    int base, len;
 
10936
    xmlParserInputPtr in;
 
10937
    const xmlChar *buf;
 
10938
 
 
10939
    in = ctxt->input;
 
10940
    if (in == NULL) return(-1);
 
10941
    base = in->cur - in->base;
 
10942
    if (base < 0) return(-1);
 
10943
    if (ctxt->checkIndex > base)
 
10944
        base = ctxt->checkIndex;
 
10945
    if (in->buf == NULL) {
 
10946
        buf = in->base;
 
10947
        len = in->length;
 
10948
    } else {
 
10949
        buf = xmlBufContent(in->buf->buffer);
 
10950
        len = xmlBufUse(in->buf->buffer);
 
10951
    }
 
10952
    /* take into account the sequence length */
 
10953
    if (third) len -= 2;
 
10954
    else if (next) len --;
 
10955
    for (;base < len;base++) {
 
10956
        if (buf[base] == first) {
 
10957
            if (third != 0) {
 
10958
                if ((buf[base + 1] != next) ||
 
10959
                    (buf[base + 2] != third)) continue;
 
10960
            } else if (next != 0) {
 
10961
                if (buf[base + 1] != next) continue;
 
10962
            }
 
10963
            ctxt->checkIndex = 0;
 
10964
#ifdef DEBUG_PUSH
 
10965
            if (next == 0)
 
10966
                xmlGenericError(xmlGenericErrorContext,
 
10967
                        "PP: lookup '%c' found at %d\n",
 
10968
                        first, base);
 
10969
            else if (third == 0)
 
10970
                xmlGenericError(xmlGenericErrorContext,
 
10971
                        "PP: lookup '%c%c' found at %d\n",
 
10972
                        first, next, base);
 
10973
            else
 
10974
                xmlGenericError(xmlGenericErrorContext,
 
10975
                        "PP: lookup '%c%c%c' found at %d\n",
 
10976
                        first, next, third, base);
 
10977
#endif
 
10978
            return(base - (in->cur - in->base));
 
10979
        }
 
10980
    }
 
10981
    ctxt->checkIndex = base;
 
10982
#ifdef DEBUG_PUSH
 
10983
    if (next == 0)
 
10984
        xmlGenericError(xmlGenericErrorContext,
 
10985
                "PP: lookup '%c' failed\n", first);
 
10986
    else if (third == 0)
 
10987
        xmlGenericError(xmlGenericErrorContext,
 
10988
                "PP: lookup '%c%c' failed\n", first, next);
 
10989
    else
 
10990
        xmlGenericError(xmlGenericErrorContext,
 
10991
                "PP: lookup '%c%c%c' failed\n", first, next, third);
 
10992
#endif
 
10993
    return(-1);
 
10994
}
 
10995
 
 
10996
/**
 
10997
 * xmlParseGetLasts:
 
10998
 * @ctxt:  an XML parser context
 
10999
 * @lastlt:  pointer to store the last '<' from the input
 
11000
 * @lastgt:  pointer to store the last '>' from the input
 
11001
 *
 
11002
 * Lookup the last < and > in the current chunk
 
11003
 */
 
11004
static void
 
11005
xmlParseGetLasts(xmlParserCtxtPtr ctxt, const xmlChar **lastlt,
 
11006
                 const xmlChar **lastgt) {
 
11007
    const xmlChar *tmp;
 
11008
 
 
11009
    if ((ctxt == NULL) || (lastlt == NULL) || (lastgt == NULL)) {
 
11010
        xmlGenericError(xmlGenericErrorContext,
 
11011
                    "Internal error: xmlParseGetLasts\n");
 
11012
        return;
 
11013
    }
 
11014
    if ((ctxt->progressive != 0) && (ctxt->inputNr == 1)) {
 
11015
        tmp = ctxt->input->end;
 
11016
        tmp--;
 
11017
        while ((tmp >= ctxt->input->base) && (*tmp != '<')) tmp--;
 
11018
        if (tmp < ctxt->input->base) {
 
11019
            *lastlt = NULL;
 
11020
            *lastgt = NULL;
 
11021
        } else {
 
11022
            *lastlt = tmp;
 
11023
            tmp++;
 
11024
            while ((tmp < ctxt->input->end) && (*tmp != '>')) {
 
11025
                if (*tmp == '\'') {
 
11026
                    tmp++;
 
11027
                    while ((tmp < ctxt->input->end) && (*tmp != '\'')) tmp++;
 
11028
                    if (tmp < ctxt->input->end) tmp++;
 
11029
                } else if (*tmp == '"') {
 
11030
                    tmp++;
 
11031
                    while ((tmp < ctxt->input->end) && (*tmp != '"')) tmp++;
 
11032
                    if (tmp < ctxt->input->end) tmp++;
 
11033
                } else
 
11034
                    tmp++;
 
11035
            }
 
11036
            if (tmp < ctxt->input->end)
 
11037
                *lastgt = tmp;
 
11038
            else {
 
11039
                tmp = *lastlt;
 
11040
                tmp--;
 
11041
                while ((tmp >= ctxt->input->base) && (*tmp != '>')) tmp--;
 
11042
                if (tmp >= ctxt->input->base)
 
11043
                    *lastgt = tmp;
 
11044
                else
 
11045
                    *lastgt = NULL;
 
11046
            }
 
11047
        }
 
11048
    } else {
 
11049
        *lastlt = NULL;
 
11050
        *lastgt = NULL;
 
11051
    }
 
11052
}
 
11053
/**
 
11054
 * xmlCheckCdataPush:
 
11055
 * @cur: pointer to the bock of characters
 
11056
 * @len: length of the block in bytes
 
11057
 *
 
11058
 * Check that the block of characters is okay as SCdata content [20]
 
11059
 *
 
11060
 * Returns the number of bytes to pass if okay, a negative index where an
 
11061
 *         UTF-8 error occured otherwise
 
11062
 */
 
11063
static int
 
11064
xmlCheckCdataPush(const xmlChar *utf, int len) {
 
11065
    int ix;
 
11066
    unsigned char c;
 
11067
    int codepoint;
 
11068
 
 
11069
    if ((utf == NULL) || (len <= 0))
 
11070
        return(0);
 
11071
 
 
11072
    for (ix = 0; ix < len;) {      /* string is 0-terminated */
 
11073
        c = utf[ix];
 
11074
        if ((c & 0x80) == 0x00) {       /* 1-byte code, starts with 10 */
 
11075
            if (c >= 0x20)
 
11076
                ix++;
 
11077
            else if ((c == 0xA) || (c == 0xD) || (c == 0x9))
 
11078
                ix++;
 
11079
            else
 
11080
                return(-ix);
 
11081
        } else if ((c & 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */
 
11082
            if (ix + 2 > len) return(ix);
 
11083
            if ((utf[ix+1] & 0xc0 ) != 0x80)
 
11084
                return(-ix);
 
11085
            codepoint = (utf[ix] & 0x1f) << 6;
 
11086
            codepoint |= utf[ix+1] & 0x3f;
 
11087
            if (!xmlIsCharQ(codepoint))
 
11088
                return(-ix);
 
11089
            ix += 2;
 
11090
        } else if ((c & 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */
 
11091
            if (ix + 3 > len) return(ix);
 
11092
            if (((utf[ix+1] & 0xc0) != 0x80) ||
 
11093
                ((utf[ix+2] & 0xc0) != 0x80))
 
11094
                    return(-ix);
 
11095
            codepoint = (utf[ix] & 0xf) << 12;
 
11096
            codepoint |= (utf[ix+1] & 0x3f) << 6;
 
11097
            codepoint |= utf[ix+2] & 0x3f;
 
11098
            if (!xmlIsCharQ(codepoint))
 
11099
                return(-ix);
 
11100
            ix += 3;
 
11101
        } else if ((c & 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */
 
11102
            if (ix + 4 > len) return(ix);
 
11103
            if (((utf[ix+1] & 0xc0) != 0x80) ||
 
11104
                ((utf[ix+2] & 0xc0) != 0x80) ||
 
11105
                ((utf[ix+3] & 0xc0) != 0x80))
 
11106
                    return(-ix);
 
11107
            codepoint = (utf[ix] & 0x7) << 18;
 
11108
            codepoint |= (utf[ix+1] & 0x3f) << 12;
 
11109
            codepoint |= (utf[ix+2] & 0x3f) << 6;
 
11110
            codepoint |= utf[ix+3] & 0x3f;
 
11111
            if (!xmlIsCharQ(codepoint))
 
11112
                return(-ix);
 
11113
            ix += 4;
 
11114
        } else                          /* unknown encoding */
 
11115
            return(-ix);
 
11116
      }
 
11117
      return(ix);
 
11118
}
 
11119
 
 
11120
/**
 
11121
 * xmlParseTryOrFinish:
 
11122
 * @ctxt:  an XML parser context
 
11123
 * @terminate:  last chunk indicator
 
11124
 *
 
11125
 * Try to progress on parsing
 
11126
 *
 
11127
 * Returns zero if no parsing was possible
 
11128
 */
 
11129
static int
 
11130
xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
 
11131
    int ret = 0;
 
11132
    int avail, tlen;
 
11133
    xmlChar cur, next;
 
11134
    const xmlChar *lastlt, *lastgt;
 
11135
 
 
11136
    if (ctxt->input == NULL)
 
11137
        return(0);
 
11138
 
 
11139
#ifdef DEBUG_PUSH
 
11140
    switch (ctxt->instate) {
 
11141
        case XML_PARSER_EOF:
 
11142
            xmlGenericError(xmlGenericErrorContext,
 
11143
                    "PP: try EOF\n"); break;
 
11144
        case XML_PARSER_START:
 
11145
            xmlGenericError(xmlGenericErrorContext,
 
11146
                    "PP: try START\n"); break;
 
11147
        case XML_PARSER_MISC:
 
11148
            xmlGenericError(xmlGenericErrorContext,
 
11149
                    "PP: try MISC\n");break;
 
11150
        case XML_PARSER_COMMENT:
 
11151
            xmlGenericError(xmlGenericErrorContext,
 
11152
                    "PP: try COMMENT\n");break;
 
11153
        case XML_PARSER_PROLOG:
 
11154
            xmlGenericError(xmlGenericErrorContext,
 
11155
                    "PP: try PROLOG\n");break;
 
11156
        case XML_PARSER_START_TAG:
 
11157
            xmlGenericError(xmlGenericErrorContext,
 
11158
                    "PP: try START_TAG\n");break;
 
11159
        case XML_PARSER_CONTENT:
 
11160
            xmlGenericError(xmlGenericErrorContext,
 
11161
                    "PP: try CONTENT\n");break;
 
11162
        case XML_PARSER_CDATA_SECTION:
 
11163
            xmlGenericError(xmlGenericErrorContext,
 
11164
                    "PP: try CDATA_SECTION\n");break;
 
11165
        case XML_PARSER_END_TAG:
 
11166
            xmlGenericError(xmlGenericErrorContext,
 
11167
                    "PP: try END_TAG\n");break;
 
11168
        case XML_PARSER_ENTITY_DECL:
 
11169
            xmlGenericError(xmlGenericErrorContext,
 
11170
                    "PP: try ENTITY_DECL\n");break;
 
11171
        case XML_PARSER_ENTITY_VALUE:
 
11172
            xmlGenericError(xmlGenericErrorContext,
 
11173
                    "PP: try ENTITY_VALUE\n");break;
 
11174
        case XML_PARSER_ATTRIBUTE_VALUE:
 
11175
            xmlGenericError(xmlGenericErrorContext,
 
11176
                    "PP: try ATTRIBUTE_VALUE\n");break;
 
11177
        case XML_PARSER_DTD:
 
11178
            xmlGenericError(xmlGenericErrorContext,
 
11179
                    "PP: try DTD\n");break;
 
11180
        case XML_PARSER_EPILOG:
 
11181
            xmlGenericError(xmlGenericErrorContext,
 
11182
                    "PP: try EPILOG\n");break;
 
11183
        case XML_PARSER_PI:
 
11184
            xmlGenericError(xmlGenericErrorContext,
 
11185
                    "PP: try PI\n");break;
 
11186
        case XML_PARSER_IGNORE:
 
11187
            xmlGenericError(xmlGenericErrorContext,
 
11188
                    "PP: try IGNORE\n");break;
 
11189
    }
 
11190
#endif
 
11191
 
 
11192
    if ((ctxt->input != NULL) &&
 
11193
        (ctxt->input->cur - ctxt->input->base > 4096)) {
 
11194
        xmlSHRINK(ctxt);
 
11195
        ctxt->checkIndex = 0;
 
11196
    }
 
11197
    xmlParseGetLasts(ctxt, &lastlt, &lastgt);
 
11198
 
 
11199
    while (ctxt->instate != XML_PARSER_EOF) {
 
11200
        if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
 
11201
            return(0);
 
11202
 
 
11203
 
 
11204
        /*
 
11205
         * Pop-up of finished entities.
 
11206
         */
 
11207
        while ((RAW == 0) && (ctxt->inputNr > 1))
 
11208
            xmlPopInput(ctxt);
 
11209
 
 
11210
        if (ctxt->input == NULL) break;
 
11211
        if (ctxt->input->buf == NULL)
 
11212
            avail = ctxt->input->length -
 
11213
                    (ctxt->input->cur - ctxt->input->base);
 
11214
        else {
 
11215
            /*
 
11216
             * If we are operating on converted input, try to flush
 
11217
             * remainng chars to avoid them stalling in the non-converted
 
11218
             * buffer. But do not do this in document start where
 
11219
             * encoding="..." may not have been read and we work on a
 
11220
             * guessed encoding.
 
11221
             */
 
11222
            if ((ctxt->instate != XML_PARSER_START) &&
 
11223
                (ctxt->input->buf->raw != NULL) &&
 
11224
                (xmlBufIsEmpty(ctxt->input->buf->raw) == 0)) {
 
11225
                size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer,
 
11226
                                                 ctxt->input);
 
11227
                size_t current = ctxt->input->cur - ctxt->input->base;
 
11228
 
 
11229
                xmlParserInputBufferPush(ctxt->input->buf, 0, "");
 
11230
                xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input,
 
11231
                                      base, current);
 
11232
            }
 
11233
            avail = xmlBufUse(ctxt->input->buf->buffer) -
 
11234
                    (ctxt->input->cur - ctxt->input->base);
 
11235
        }
 
11236
        if (avail < 1)
 
11237
            goto done;
 
11238
        switch (ctxt->instate) {
 
11239
            case XML_PARSER_EOF:
 
11240
                /*
 
11241
                 * Document parsing is done !
 
11242
                 */
 
11243
                goto done;
 
11244
            case XML_PARSER_START:
 
11245
                if (ctxt->charset == XML_CHAR_ENCODING_NONE) {
 
11246
                    xmlChar start[4];
 
11247
                    xmlCharEncoding enc;
 
11248
 
 
11249
                    /*
 
11250
                     * Very first chars read from the document flow.
 
11251
                     */
 
11252
                    if (avail < 4)
 
11253
                        goto done;
 
11254
 
 
11255
                    /*
 
11256
                     * Get the 4 first bytes and decode the charset
 
11257
                     * if enc != XML_CHAR_ENCODING_NONE
 
11258
                     * plug some encoding conversion routines,
 
11259
                     * else xmlSwitchEncoding will set to (default)
 
11260
                     * UTF8.
 
11261
                     */
 
11262
                    start[0] = RAW;
 
11263
                    start[1] = NXT(1);
 
11264
                    start[2] = NXT(2);
 
11265
                    start[3] = NXT(3);
 
11266
                    enc = xmlDetectCharEncoding(start, 4);
 
11267
                    xmlSwitchEncoding(ctxt, enc);
 
11268
                    break;
 
11269
                }
 
11270
 
 
11271
                if (avail < 2)
 
11272
                    goto done;
 
11273
                cur = ctxt->input->cur[0];
 
11274
                next = ctxt->input->cur[1];
 
11275
                if (cur == 0) {
 
11276
                    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
 
11277
                        ctxt->sax->setDocumentLocator(ctxt->userData,
 
11278
                                                      &xmlDefaultSAXLocator);
 
11279
                    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
 
11280
                    ctxt->instate = XML_PARSER_EOF;
 
11281
#ifdef DEBUG_PUSH
 
11282
                    xmlGenericError(xmlGenericErrorContext,
 
11283
                            "PP: entering EOF\n");
 
11284
#endif
 
11285
                    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 
11286
                        ctxt->sax->endDocument(ctxt->userData);
 
11287
                    goto done;
 
11288
                }
 
11289
                if ((cur == '<') && (next == '?')) {
 
11290
                    /* PI or XML decl */
 
11291
                    if (avail < 5) return(ret);
 
11292
                    if ((!terminate) &&
 
11293
                        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
 
11294
                        return(ret);
 
11295
                    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
 
11296
                        ctxt->sax->setDocumentLocator(ctxt->userData,
 
11297
                                                      &xmlDefaultSAXLocator);
 
11298
                    if ((ctxt->input->cur[2] == 'x') &&
 
11299
                        (ctxt->input->cur[3] == 'm') &&
 
11300
                        (ctxt->input->cur[4] == 'l') &&
 
11301
                        (IS_BLANK_CH(ctxt->input->cur[5]))) {
 
11302
                        ret += 5;
 
11303
#ifdef DEBUG_PUSH
 
11304
                        xmlGenericError(xmlGenericErrorContext,
 
11305
                                "PP: Parsing XML Decl\n");
 
11306
#endif
 
11307
                        xmlParseXMLDecl(ctxt);
 
11308
                        if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
 
11309
                            /*
 
11310
                             * The XML REC instructs us to stop parsing right
 
11311
                             * here
 
11312
                             */
 
11313
                            ctxt->instate = XML_PARSER_EOF;
 
11314
                            return(0);
 
11315
                        }
 
11316
                        ctxt->standalone = ctxt->input->standalone;
 
11317
                        if ((ctxt->encoding == NULL) &&
 
11318
                            (ctxt->input->encoding != NULL))
 
11319
                            ctxt->encoding = xmlStrdup(ctxt->input->encoding);
 
11320
                        if ((ctxt->sax) && (ctxt->sax->startDocument) &&
 
11321
                            (!ctxt->disableSAX))
 
11322
                            ctxt->sax->startDocument(ctxt->userData);
 
11323
                        ctxt->instate = XML_PARSER_MISC;
 
11324
#ifdef DEBUG_PUSH
 
11325
                        xmlGenericError(xmlGenericErrorContext,
 
11326
                                "PP: entering MISC\n");
 
11327
#endif
 
11328
                    } else {
 
11329
                        ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
 
11330
                        if ((ctxt->sax) && (ctxt->sax->startDocument) &&
 
11331
                            (!ctxt->disableSAX))
 
11332
                            ctxt->sax->startDocument(ctxt->userData);
 
11333
                        ctxt->instate = XML_PARSER_MISC;
 
11334
#ifdef DEBUG_PUSH
 
11335
                        xmlGenericError(xmlGenericErrorContext,
 
11336
                                "PP: entering MISC\n");
 
11337
#endif
 
11338
                    }
 
11339
                } else {
 
11340
                    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
 
11341
                        ctxt->sax->setDocumentLocator(ctxt->userData,
 
11342
                                                      &xmlDefaultSAXLocator);
 
11343
                    ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
 
11344
                    if (ctxt->version == NULL) {
 
11345
                        xmlErrMemory(ctxt, NULL);
 
11346
                        break;
 
11347
                    }
 
11348
                    if ((ctxt->sax) && (ctxt->sax->startDocument) &&
 
11349
                        (!ctxt->disableSAX))
 
11350
                        ctxt->sax->startDocument(ctxt->userData);
 
11351
                    ctxt->instate = XML_PARSER_MISC;
 
11352
#ifdef DEBUG_PUSH
 
11353
                    xmlGenericError(xmlGenericErrorContext,
 
11354
                            "PP: entering MISC\n");
 
11355
#endif
 
11356
                }
 
11357
                break;
 
11358
            case XML_PARSER_START_TAG: {
 
11359
                const xmlChar *name;
 
11360
                const xmlChar *prefix = NULL;
 
11361
                const xmlChar *URI = NULL;
 
11362
                int nsNr = ctxt->nsNr;
 
11363
 
 
11364
                if ((avail < 2) && (ctxt->inputNr == 1))
 
11365
                    goto done;
 
11366
                cur = ctxt->input->cur[0];
 
11367
                if (cur != '<') {
 
11368
                    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
 
11369
                    ctxt->instate = XML_PARSER_EOF;
 
11370
                    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 
11371
                        ctxt->sax->endDocument(ctxt->userData);
 
11372
                    goto done;
 
11373
                }
 
11374
                if (!terminate) {
 
11375
                    if (ctxt->progressive) {
 
11376
                        /* > can be found unescaped in attribute values */
 
11377
                        if ((lastgt == NULL) || (ctxt->input->cur >= lastgt))
 
11378
                            goto done;
 
11379
                    } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) {
 
11380
                        goto done;
 
11381
                    }
 
11382
                }
 
11383
                if (ctxt->spaceNr == 0)
 
11384
                    spacePush(ctxt, -1);
 
11385
                else if (*ctxt->space == -2)
 
11386
                    spacePush(ctxt, -1);
 
11387
                else
 
11388
                    spacePush(ctxt, *ctxt->space);
 
11389
#ifdef LIBXML_SAX1_ENABLED
 
11390
                if (ctxt->sax2)
 
11391
#endif /* LIBXML_SAX1_ENABLED */
 
11392
                    name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
 
11393
#ifdef LIBXML_SAX1_ENABLED
 
11394
                else
 
11395
                    name = xmlParseStartTag(ctxt);
 
11396
#endif /* LIBXML_SAX1_ENABLED */
 
11397
                if (ctxt->instate == XML_PARSER_EOF)
 
11398
                    goto done;
 
11399
                if (name == NULL) {
 
11400
                    spacePop(ctxt);
 
11401
                    ctxt->instate = XML_PARSER_EOF;
 
11402
                    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 
11403
                        ctxt->sax->endDocument(ctxt->userData);
 
11404
                    goto done;
 
11405
                }
 
11406
#ifdef LIBXML_VALID_ENABLED
 
11407
                /*
 
11408
                 * [ VC: Root Element Type ]
 
11409
                 * The Name in the document type declaration must match
 
11410
                 * the element type of the root element.
 
11411
                 */
 
11412
                if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
 
11413
                    ctxt->node && (ctxt->node == ctxt->myDoc->children))
 
11414
                    ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
 
11415
#endif /* LIBXML_VALID_ENABLED */
 
11416
 
 
11417
                /*
 
11418
                 * Check for an Empty Element.
 
11419
                 */
 
11420
                if ((RAW == '/') && (NXT(1) == '>')) {
 
11421
                    SKIP(2);
 
11422
 
 
11423
                    if (ctxt->sax2) {
 
11424
                        if ((ctxt->sax != NULL) &&
 
11425
                            (ctxt->sax->endElementNs != NULL) &&
 
11426
                            (!ctxt->disableSAX))
 
11427
                            ctxt->sax->endElementNs(ctxt->userData, name,
 
11428
                                                    prefix, URI);
 
11429
                        if (ctxt->nsNr - nsNr > 0)
 
11430
                            nsPop(ctxt, ctxt->nsNr - nsNr);
 
11431
#ifdef LIBXML_SAX1_ENABLED
 
11432
                    } else {
 
11433
                        if ((ctxt->sax != NULL) &&
 
11434
                            (ctxt->sax->endElement != NULL) &&
 
11435
                            (!ctxt->disableSAX))
 
11436
                            ctxt->sax->endElement(ctxt->userData, name);
 
11437
#endif /* LIBXML_SAX1_ENABLED */
 
11438
                    }
 
11439
                    if (ctxt->instate == XML_PARSER_EOF)
 
11440
                        goto done;
 
11441
                    spacePop(ctxt);
 
11442
                    if (ctxt->nameNr == 0) {
 
11443
                        ctxt->instate = XML_PARSER_EPILOG;
 
11444
                    } else {
 
11445
                        ctxt->instate = XML_PARSER_CONTENT;
 
11446
                    }
 
11447
                    ctxt->progressive = 1;
 
11448
                    break;
 
11449
                }
 
11450
                if (RAW == '>') {
 
11451
                    NEXT;
 
11452
                } else {
 
11453
                    xmlFatalErrMsgStr(ctxt, XML_ERR_GT_REQUIRED,
 
11454
                                         "Couldn't find end of Start Tag %s\n",
 
11455
                                         name);
 
11456
                    nodePop(ctxt);
 
11457
                    spacePop(ctxt);
 
11458
                }
 
11459
                if (ctxt->sax2)
 
11460
                    nameNsPush(ctxt, name, prefix, URI, ctxt->nsNr - nsNr);
 
11461
#ifdef LIBXML_SAX1_ENABLED
 
11462
                else
 
11463
                    namePush(ctxt, name);
 
11464
#endif /* LIBXML_SAX1_ENABLED */
 
11465
 
 
11466
                ctxt->instate = XML_PARSER_CONTENT;
 
11467
                ctxt->progressive = 1;
 
11468
                break;
 
11469
            }
 
11470
            case XML_PARSER_CONTENT: {
 
11471
                const xmlChar *test;
 
11472
                unsigned int cons;
 
11473
                if ((avail < 2) && (ctxt->inputNr == 1))
 
11474
                    goto done;
 
11475
                cur = ctxt->input->cur[0];
 
11476
                next = ctxt->input->cur[1];
 
11477
 
 
11478
                test = CUR_PTR;
 
11479
                cons = ctxt->input->consumed;
 
11480
                if ((cur == '<') && (next == '/')) {
 
11481
                    ctxt->instate = XML_PARSER_END_TAG;
 
11482
                    break;
 
11483
                } else if ((cur == '<') && (next == '?')) {
 
11484
                    if ((!terminate) &&
 
11485
                        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
 
11486
                        ctxt->progressive = XML_PARSER_PI;
 
11487
                        goto done;
 
11488
                    }
 
11489
                    xmlParsePI(ctxt);
 
11490
                    ctxt->instate = XML_PARSER_CONTENT;
 
11491
                    ctxt->progressive = 1;
 
11492
                } else if ((cur == '<') && (next != '!')) {
 
11493
                    ctxt->instate = XML_PARSER_START_TAG;
 
11494
                    break;
 
11495
                } else if ((cur == '<') && (next == '!') &&
 
11496
                           (ctxt->input->cur[2] == '-') &&
 
11497
                           (ctxt->input->cur[3] == '-')) {
 
11498
                    int term;
 
11499
 
 
11500
                    if (avail < 4)
 
11501
                        goto done;
 
11502
                    ctxt->input->cur += 4;
 
11503
                    term = xmlParseLookupSequence(ctxt, '-', '-', '>');
 
11504
                    ctxt->input->cur -= 4;
 
11505
                    if ((!terminate) && (term < 0)) {
 
11506
                        ctxt->progressive = XML_PARSER_COMMENT;
 
11507
                        goto done;
 
11508
                    }
 
11509
                    xmlParseComment(ctxt);
 
11510
                    ctxt->instate = XML_PARSER_CONTENT;
 
11511
                    ctxt->progressive = 1;
 
11512
                } else if ((cur == '<') && (ctxt->input->cur[1] == '!') &&
 
11513
                    (ctxt->input->cur[2] == '[') &&
 
11514
                    (ctxt->input->cur[3] == 'C') &&
 
11515
                    (ctxt->input->cur[4] == 'D') &&
 
11516
                    (ctxt->input->cur[5] == 'A') &&
 
11517
                    (ctxt->input->cur[6] == 'T') &&
 
11518
                    (ctxt->input->cur[7] == 'A') &&
 
11519
                    (ctxt->input->cur[8] == '[')) {
 
11520
                    SKIP(9);
 
11521
                    ctxt->instate = XML_PARSER_CDATA_SECTION;
 
11522
                    break;
 
11523
                } else if ((cur == '<') && (next == '!') &&
 
11524
                           (avail < 9)) {
 
11525
                    goto done;
 
11526
                } else if (cur == '&') {
 
11527
                    if ((!terminate) &&
 
11528
                        (xmlParseLookupSequence(ctxt, ';', 0, 0) < 0))
 
11529
                        goto done;
 
11530
                    xmlParseReference(ctxt);
 
11531
                } else {
 
11532
                    /* TODO Avoid the extra copy, handle directly !!! */
 
11533
                    /*
 
11534
                     * Goal of the following test is:
 
11535
                     *  - minimize calls to the SAX 'character' callback
 
11536
                     *    when they are mergeable
 
11537
                     *  - handle an problem for isBlank when we only parse
 
11538
                     *    a sequence of blank chars and the next one is
 
11539
                     *    not available to check against '<' presence.
 
11540
                     *  - tries to homogenize the differences in SAX
 
11541
                     *    callbacks between the push and pull versions
 
11542
                     *    of the parser.
 
11543
                     */
 
11544
                    if ((ctxt->inputNr == 1) &&
 
11545
                        (avail < XML_PARSER_BIG_BUFFER_SIZE)) {
 
11546
                        if (!terminate) {
 
11547
                            if (ctxt->progressive) {
 
11548
                                if ((lastlt == NULL) ||
 
11549
                                    (ctxt->input->cur > lastlt))
 
11550
                                    goto done;
 
11551
                            } else if (xmlParseLookupSequence(ctxt,
 
11552
                                                              '<', 0, 0) < 0) {
 
11553
                                goto done;
 
11554
                            }
 
11555
                        }
 
11556
                    }
 
11557
                    ctxt->checkIndex = 0;
 
11558
                    xmlParseCharData(ctxt, 0);
 
11559
                }
 
11560
                /*
 
11561
                 * Pop-up of finished entities.
 
11562
                 */
 
11563
                while ((RAW == 0) && (ctxt->inputNr > 1))
 
11564
                    xmlPopInput(ctxt);
 
11565
                if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) {
 
11566
                    xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 
11567
                                "detected an error in element content\n");
 
11568
                    ctxt->instate = XML_PARSER_EOF;
 
11569
                    break;
 
11570
                }
 
11571
                break;
 
11572
            }
 
11573
            case XML_PARSER_END_TAG:
 
11574
                if (avail < 2)
 
11575
                    goto done;
 
11576
                if (!terminate) {
 
11577
                    if (ctxt->progressive) {
 
11578
                        /* > can be found unescaped in attribute values */
 
11579
                        if ((lastgt == NULL) || (ctxt->input->cur >= lastgt))
 
11580
                            goto done;
 
11581
                    } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) {
 
11582
                        goto done;
 
11583
                    }
 
11584
                }
 
11585
                if (ctxt->sax2) {
 
11586
                    xmlParseEndTag2(ctxt,
 
11587
                           (void *) ctxt->pushTab[ctxt->nameNr * 3 - 3],
 
11588
                           (void *) ctxt->pushTab[ctxt->nameNr * 3 - 2], 0,
 
11589
                       (int) (long) ctxt->pushTab[ctxt->nameNr * 3 - 1], 0);
 
11590
                    nameNsPop(ctxt);
 
11591
                }
 
11592
#ifdef LIBXML_SAX1_ENABLED
 
11593
                  else
 
11594
                    xmlParseEndTag1(ctxt, 0);
 
11595
#endif /* LIBXML_SAX1_ENABLED */
 
11596
                if (ctxt->instate == XML_PARSER_EOF) {
 
11597
                    /* Nothing */
 
11598
                } else if (ctxt->nameNr == 0) {
 
11599
                    ctxt->instate = XML_PARSER_EPILOG;
 
11600
                } else {
 
11601
                    ctxt->instate = XML_PARSER_CONTENT;
 
11602
                }
 
11603
                break;
 
11604
            case XML_PARSER_CDATA_SECTION: {
 
11605
                /*
 
11606
                 * The Push mode need to have the SAX callback for
 
11607
                 * cdataBlock merge back contiguous callbacks.
 
11608
                 */
 
11609
                int base;
 
11610
 
 
11611
                base = xmlParseLookupSequence(ctxt, ']', ']', '>');
 
11612
                if (base < 0) {
 
11613
                    if (avail >= XML_PARSER_BIG_BUFFER_SIZE + 2) {
 
11614
                        int tmp;
 
11615
 
 
11616
                        tmp = xmlCheckCdataPush(ctxt->input->cur,
 
11617
                                                XML_PARSER_BIG_BUFFER_SIZE);
 
11618
                        if (tmp < 0) {
 
11619
                            tmp = -tmp;
 
11620
                            ctxt->input->cur += tmp;
 
11621
                            goto encoding_error;
 
11622
                        }
 
11623
                        if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
 
11624
                            if (ctxt->sax->cdataBlock != NULL)
 
11625
                                ctxt->sax->cdataBlock(ctxt->userData,
 
11626
                                                      ctxt->input->cur, tmp);
 
11627
                            else if (ctxt->sax->characters != NULL)
 
11628
                                ctxt->sax->characters(ctxt->userData,
 
11629
                                                      ctxt->input->cur, tmp);
 
11630
                        }
 
11631
                        if (ctxt->instate == XML_PARSER_EOF)
 
11632
                            goto done;
 
11633
                        SKIPL(tmp);
 
11634
                        ctxt->checkIndex = 0;
 
11635
                    }
 
11636
                    goto done;
 
11637
                } else {
 
11638
                    int tmp;
 
11639
 
 
11640
                    tmp = xmlCheckCdataPush(ctxt->input->cur, base);
 
11641
                    if ((tmp < 0) || (tmp != base)) {
 
11642
                        tmp = -tmp;
 
11643
                        ctxt->input->cur += tmp;
 
11644
                        goto encoding_error;
 
11645
                    }
 
11646
                    if ((ctxt->sax != NULL) && (base == 0) &&
 
11647
                        (ctxt->sax->cdataBlock != NULL) &&
 
11648
                        (!ctxt->disableSAX)) {
 
11649
                        /*
 
11650
                         * Special case to provide identical behaviour
 
11651
                         * between pull and push parsers on enpty CDATA
 
11652
                         * sections
 
11653
                         */
 
11654
                         if ((ctxt->input->cur - ctxt->input->base >= 9) &&
 
11655
                             (!strncmp((const char *)&ctxt->input->cur[-9],
 
11656
                                       "<![CDATA[", 9)))
 
11657
                             ctxt->sax->cdataBlock(ctxt->userData,
 
11658
                                                   BAD_CAST "", 0);
 
11659
                    } else if ((ctxt->sax != NULL) && (base > 0) &&
 
11660
                        (!ctxt->disableSAX)) {
 
11661
                        if (ctxt->sax->cdataBlock != NULL)
 
11662
                            ctxt->sax->cdataBlock(ctxt->userData,
 
11663
                                                  ctxt->input->cur, base);
 
11664
                        else if (ctxt->sax->characters != NULL)
 
11665
                            ctxt->sax->characters(ctxt->userData,
 
11666
                                                  ctxt->input->cur, base);
 
11667
                    }
 
11668
                    if (ctxt->instate == XML_PARSER_EOF)
 
11669
                        goto done;
 
11670
                    SKIPL(base + 3);
 
11671
                    ctxt->checkIndex = 0;
 
11672
                    ctxt->instate = XML_PARSER_CONTENT;
 
11673
#ifdef DEBUG_PUSH
 
11674
                    xmlGenericError(xmlGenericErrorContext,
 
11675
                            "PP: entering CONTENT\n");
 
11676
#endif
 
11677
                }
 
11678
                break;
 
11679
            }
 
11680
            case XML_PARSER_MISC:
 
11681
                SKIP_BLANKS;
 
11682
                if (ctxt->input->buf == NULL)
 
11683
                    avail = ctxt->input->length -
 
11684
                            (ctxt->input->cur - ctxt->input->base);
 
11685
                else
 
11686
                    avail = xmlBufUse(ctxt->input->buf->buffer) -
 
11687
                            (ctxt->input->cur - ctxt->input->base);
 
11688
                if (avail < 2)
 
11689
                    goto done;
 
11690
                cur = ctxt->input->cur[0];
 
11691
                next = ctxt->input->cur[1];
 
11692
                if ((cur == '<') && (next == '?')) {
 
11693
                    if ((!terminate) &&
 
11694
                        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
 
11695
                        ctxt->progressive = XML_PARSER_PI;
 
11696
                        goto done;
 
11697
                    }
 
11698
#ifdef DEBUG_PUSH
 
11699
                    xmlGenericError(xmlGenericErrorContext,
 
11700
                            "PP: Parsing PI\n");
 
11701
#endif
 
11702
                    xmlParsePI(ctxt);
 
11703
                    if (ctxt->instate == XML_PARSER_EOF)
 
11704
                        goto done;
 
11705
                    ctxt->instate = XML_PARSER_MISC;
 
11706
                    ctxt->progressive = 1;
 
11707
                    ctxt->checkIndex = 0;
 
11708
                } else if ((cur == '<') && (next == '!') &&
 
11709
                    (ctxt->input->cur[2] == '-') &&
 
11710
                    (ctxt->input->cur[3] == '-')) {
 
11711
                    if ((!terminate) &&
 
11712
                        (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
 
11713
                        ctxt->progressive = XML_PARSER_COMMENT;
 
11714
                        goto done;
 
11715
                    }
 
11716
#ifdef DEBUG_PUSH
 
11717
                    xmlGenericError(xmlGenericErrorContext,
 
11718
                            "PP: Parsing Comment\n");
 
11719
#endif
 
11720
                    xmlParseComment(ctxt);
 
11721
                    if (ctxt->instate == XML_PARSER_EOF)
 
11722
                        goto done;
 
11723
                    ctxt->instate = XML_PARSER_MISC;
 
11724
                    ctxt->progressive = 1;
 
11725
                    ctxt->checkIndex = 0;
 
11726
                } else if ((cur == '<') && (next == '!') &&
 
11727
                    (ctxt->input->cur[2] == 'D') &&
 
11728
                    (ctxt->input->cur[3] == 'O') &&
 
11729
                    (ctxt->input->cur[4] == 'C') &&
 
11730
                    (ctxt->input->cur[5] == 'T') &&
 
11731
                    (ctxt->input->cur[6] == 'Y') &&
 
11732
                    (ctxt->input->cur[7] == 'P') &&
 
11733
                    (ctxt->input->cur[8] == 'E')) {
 
11734
                    if ((!terminate) &&
 
11735
                        (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0)) {
 
11736
                        ctxt->progressive = XML_PARSER_DTD;
 
11737
                        goto done;
 
11738
                    }
 
11739
#ifdef DEBUG_PUSH
 
11740
                    xmlGenericError(xmlGenericErrorContext,
 
11741
                            "PP: Parsing internal subset\n");
 
11742
#endif
 
11743
                    ctxt->inSubset = 1;
 
11744
                    ctxt->progressive = 0;
 
11745
                    ctxt->checkIndex = 0;
 
11746
                    xmlParseDocTypeDecl(ctxt);
 
11747
                    if (ctxt->instate == XML_PARSER_EOF)
 
11748
                        goto done;
 
11749
                    if (RAW == '[') {
 
11750
                        ctxt->instate = XML_PARSER_DTD;
 
11751
#ifdef DEBUG_PUSH
 
11752
                        xmlGenericError(xmlGenericErrorContext,
 
11753
                                "PP: entering DTD\n");
 
11754
#endif
 
11755
                    } else {
 
11756
                        /*
 
11757
                         * Create and update the external subset.
 
11758
                         */
 
11759
                        ctxt->inSubset = 2;
 
11760
                        if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
 
11761
                            (ctxt->sax->externalSubset != NULL))
 
11762
                            ctxt->sax->externalSubset(ctxt->userData,
 
11763
                                    ctxt->intSubName, ctxt->extSubSystem,
 
11764
                                    ctxt->extSubURI);
 
11765
                        ctxt->inSubset = 0;
 
11766
                        xmlCleanSpecialAttr(ctxt);
 
11767
                        ctxt->instate = XML_PARSER_PROLOG;
 
11768
#ifdef DEBUG_PUSH
 
11769
                        xmlGenericError(xmlGenericErrorContext,
 
11770
                                "PP: entering PROLOG\n");
 
11771
#endif
 
11772
                    }
 
11773
                } else if ((cur == '<') && (next == '!') &&
 
11774
                           (avail < 9)) {
 
11775
                    goto done;
 
11776
                } else {
 
11777
                    ctxt->instate = XML_PARSER_START_TAG;
 
11778
                    ctxt->progressive = XML_PARSER_START_TAG;
 
11779
                    xmlParseGetLasts(ctxt, &lastlt, &lastgt);
 
11780
#ifdef DEBUG_PUSH
 
11781
                    xmlGenericError(xmlGenericErrorContext,
 
11782
                            "PP: entering START_TAG\n");
 
11783
#endif
 
11784
                }
 
11785
                break;
 
11786
            case XML_PARSER_PROLOG:
 
11787
                SKIP_BLANKS;
 
11788
                if (ctxt->input->buf == NULL)
 
11789
                    avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
 
11790
                else
 
11791
                    avail = xmlBufUse(ctxt->input->buf->buffer) -
 
11792
                            (ctxt->input->cur - ctxt->input->base);
 
11793
                if (avail < 2)
 
11794
                    goto done;
 
11795
                cur = ctxt->input->cur[0];
 
11796
                next = ctxt->input->cur[1];
 
11797
                if ((cur == '<') && (next == '?')) {
 
11798
                    if ((!terminate) &&
 
11799
                        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
 
11800
                        ctxt->progressive = XML_PARSER_PI;
 
11801
                        goto done;
 
11802
                    }
 
11803
#ifdef DEBUG_PUSH
 
11804
                    xmlGenericError(xmlGenericErrorContext,
 
11805
                            "PP: Parsing PI\n");
 
11806
#endif
 
11807
                    xmlParsePI(ctxt);
 
11808
                    if (ctxt->instate == XML_PARSER_EOF)
 
11809
                        goto done;
 
11810
                    ctxt->instate = XML_PARSER_PROLOG;
 
11811
                    ctxt->progressive = 1;
 
11812
                } else if ((cur == '<') && (next == '!') &&
 
11813
                    (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
 
11814
                    if ((!terminate) &&
 
11815
                        (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
 
11816
                        ctxt->progressive = XML_PARSER_COMMENT;
 
11817
                        goto done;
 
11818
                    }
 
11819
#ifdef DEBUG_PUSH
 
11820
                    xmlGenericError(xmlGenericErrorContext,
 
11821
                            "PP: Parsing Comment\n");
 
11822
#endif
 
11823
                    xmlParseComment(ctxt);
 
11824
                    if (ctxt->instate == XML_PARSER_EOF)
 
11825
                        goto done;
 
11826
                    ctxt->instate = XML_PARSER_PROLOG;
 
11827
                    ctxt->progressive = 1;
 
11828
                } else if ((cur == '<') && (next == '!') &&
 
11829
                           (avail < 4)) {
 
11830
                    goto done;
 
11831
                } else {
 
11832
                    ctxt->instate = XML_PARSER_START_TAG;
 
11833
                    if (ctxt->progressive == 0)
 
11834
                        ctxt->progressive = XML_PARSER_START_TAG;
 
11835
                    xmlParseGetLasts(ctxt, &lastlt, &lastgt);
 
11836
#ifdef DEBUG_PUSH
 
11837
                    xmlGenericError(xmlGenericErrorContext,
 
11838
                            "PP: entering START_TAG\n");
 
11839
#endif
 
11840
                }
 
11841
                break;
 
11842
            case XML_PARSER_EPILOG:
 
11843
                SKIP_BLANKS;
 
11844
                if (ctxt->input->buf == NULL)
 
11845
                    avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
 
11846
                else
 
11847
                    avail = xmlBufUse(ctxt->input->buf->buffer) -
 
11848
                            (ctxt->input->cur - ctxt->input->base);
 
11849
                if (avail < 2)
 
11850
                    goto done;
 
11851
                cur = ctxt->input->cur[0];
 
11852
                next = ctxt->input->cur[1];
 
11853
                if ((cur == '<') && (next == '?')) {
 
11854
                    if ((!terminate) &&
 
11855
                        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
 
11856
                        ctxt->progressive = XML_PARSER_PI;
 
11857
                        goto done;
 
11858
                    }
 
11859
#ifdef DEBUG_PUSH
 
11860
                    xmlGenericError(xmlGenericErrorContext,
 
11861
                            "PP: Parsing PI\n");
 
11862
#endif
 
11863
                    xmlParsePI(ctxt);
 
11864
                    if (ctxt->instate == XML_PARSER_EOF)
 
11865
                        goto done;
 
11866
                    ctxt->instate = XML_PARSER_EPILOG;
 
11867
                    ctxt->progressive = 1;
 
11868
                } else if ((cur == '<') && (next == '!') &&
 
11869
                    (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
 
11870
                    if ((!terminate) &&
 
11871
                        (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
 
11872
                        ctxt->progressive = XML_PARSER_COMMENT;
 
11873
                        goto done;
 
11874
                    }
 
11875
#ifdef DEBUG_PUSH
 
11876
                    xmlGenericError(xmlGenericErrorContext,
 
11877
                            "PP: Parsing Comment\n");
 
11878
#endif
 
11879
                    xmlParseComment(ctxt);
 
11880
                    if (ctxt->instate == XML_PARSER_EOF)
 
11881
                        goto done;
 
11882
                    ctxt->instate = XML_PARSER_EPILOG;
 
11883
                    ctxt->progressive = 1;
 
11884
                } else if ((cur == '<') && (next == '!') &&
 
11885
                           (avail < 4)) {
 
11886
                    goto done;
 
11887
                } else {
 
11888
                    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
 
11889
                    ctxt->instate = XML_PARSER_EOF;
 
11890
#ifdef DEBUG_PUSH
 
11891
                    xmlGenericError(xmlGenericErrorContext,
 
11892
                            "PP: entering EOF\n");
 
11893
#endif
 
11894
                    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 
11895
                        ctxt->sax->endDocument(ctxt->userData);
 
11896
                    goto done;
 
11897
                }
 
11898
                break;
 
11899
            case XML_PARSER_DTD: {
 
11900
                /*
 
11901
                 * Sorry but progressive parsing of the internal subset
 
11902
                 * is not expected to be supported. We first check that
 
11903
                 * the full content of the internal subset is available and
 
11904
                 * the parsing is launched only at that point.
 
11905
                 * Internal subset ends up with "']' S? '>'" in an unescaped
 
11906
                 * section and not in a ']]>' sequence which are conditional
 
11907
                 * sections (whoever argued to keep that crap in XML deserve
 
11908
                 * a place in hell !).
 
11909
                 */
 
11910
                int base, i;
 
11911
                xmlChar *buf;
 
11912
                xmlChar quote = 0;
 
11913
                size_t use;
 
11914
 
 
11915
                base = ctxt->input->cur - ctxt->input->base;
 
11916
                if (base < 0) return(0);
 
11917
                if (ctxt->checkIndex > base)
 
11918
                    base = ctxt->checkIndex;
 
11919
                buf = xmlBufContent(ctxt->input->buf->buffer);
 
11920
                use = xmlBufUse(ctxt->input->buf->buffer);
 
11921
                for (;(unsigned int) base < use; base++) {
 
11922
                    if (quote != 0) {
 
11923
                        if (buf[base] == quote)
 
11924
                            quote = 0;
 
11925
                        continue;
 
11926
                    }
 
11927
                    if ((quote == 0) && (buf[base] == '<')) {
 
11928
                        int found  = 0;
 
11929
                        /* special handling of comments */
 
11930
                        if (((unsigned int) base + 4 < use) &&
 
11931
                            (buf[base + 1] == '!') &&
 
11932
                            (buf[base + 2] == '-') &&
 
11933
                            (buf[base + 3] == '-')) {
 
11934
                            for (;(unsigned int) base + 3 < use; base++) {
 
11935
                                if ((buf[base] == '-') &&
 
11936
                                    (buf[base + 1] == '-') &&
 
11937
                                    (buf[base + 2] == '>')) {
 
11938
                                    found = 1;
 
11939
                                    base += 2;
 
11940
                                    break;
 
11941
                                }
 
11942
                            }
 
11943
                            if (!found) {
 
11944
#if 0
 
11945
                                fprintf(stderr, "unfinished comment\n");
 
11946
#endif
 
11947
                                break; /* for */
 
11948
                            }
 
11949
                            continue;
 
11950
                        }
 
11951
                    }
 
11952
                    if (buf[base] == '"') {
 
11953
                        quote = '"';
 
11954
                        continue;
 
11955
                    }
 
11956
                    if (buf[base] == '\'') {
 
11957
                        quote = '\'';
 
11958
                        continue;
 
11959
                    }
 
11960
                    if (buf[base] == ']') {
 
11961
#if 0
 
11962
                        fprintf(stderr, "%c%c%c%c: ", buf[base],
 
11963
                                buf[base + 1], buf[base + 2], buf[base + 3]);
 
11964
#endif
 
11965
                        if ((unsigned int) base +1 >= use)
 
11966
                            break;
 
11967
                        if (buf[base + 1] == ']') {
 
11968
                            /* conditional crap, skip both ']' ! */
 
11969
                            base++;
 
11970
                            continue;
 
11971
                        }
 
11972
                        for (i = 1; (unsigned int) base + i < use; i++) {
 
11973
                            if (buf[base + i] == '>') {
 
11974
#if 0
 
11975
                                fprintf(stderr, "found\n");
 
11976
#endif
 
11977
                                goto found_end_int_subset;
 
11978
                            }
 
11979
                            if (!IS_BLANK_CH(buf[base + i])) {
 
11980
#if 0
 
11981
                                fprintf(stderr, "not found\n");
 
11982
#endif
 
11983
                                goto not_end_of_int_subset;
 
11984
                            }
 
11985
                        }
 
11986
#if 0
 
11987
                        fprintf(stderr, "end of stream\n");
 
11988
#endif
 
11989
                        break;
 
11990
 
 
11991
                    }
 
11992
not_end_of_int_subset:
 
11993
                    continue; /* for */
 
11994
                }
 
11995
                /*
 
11996
                 * We didn't found the end of the Internal subset
 
11997
                 */
 
11998
                if (quote == 0)
 
11999
                    ctxt->checkIndex = base;
 
12000
                else
 
12001
                    ctxt->checkIndex = 0;
 
12002
#ifdef DEBUG_PUSH
 
12003
                if (next == 0)
 
12004
                    xmlGenericError(xmlGenericErrorContext,
 
12005
                            "PP: lookup of int subset end filed\n");
 
12006
#endif
 
12007
                goto done;
 
12008
 
 
12009
found_end_int_subset:
 
12010
                ctxt->checkIndex = 0;
 
12011
                xmlParseInternalSubset(ctxt);
 
12012
                if (ctxt->instate == XML_PARSER_EOF)
 
12013
                    goto done;
 
12014
                ctxt->inSubset = 2;
 
12015
                if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
 
12016
                    (ctxt->sax->externalSubset != NULL))
 
12017
                    ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
 
12018
                            ctxt->extSubSystem, ctxt->extSubURI);
 
12019
                ctxt->inSubset = 0;
 
12020
                xmlCleanSpecialAttr(ctxt);
 
12021
                if (ctxt->instate == XML_PARSER_EOF)
 
12022
                    goto done;
 
12023
                ctxt->instate = XML_PARSER_PROLOG;
 
12024
                ctxt->checkIndex = 0;
 
12025
#ifdef DEBUG_PUSH
 
12026
                xmlGenericError(xmlGenericErrorContext,
 
12027
                        "PP: entering PROLOG\n");
 
12028
#endif
 
12029
                break;
 
12030
            }
 
12031
            case XML_PARSER_COMMENT:
 
12032
                xmlGenericError(xmlGenericErrorContext,
 
12033
                        "PP: internal error, state == COMMENT\n");
 
12034
                ctxt->instate = XML_PARSER_CONTENT;
 
12035
#ifdef DEBUG_PUSH
 
12036
                xmlGenericError(xmlGenericErrorContext,
 
12037
                        "PP: entering CONTENT\n");
 
12038
#endif
 
12039
                break;
 
12040
            case XML_PARSER_IGNORE:
 
12041
                xmlGenericError(xmlGenericErrorContext,
 
12042
                        "PP: internal error, state == IGNORE");
 
12043
                ctxt->instate = XML_PARSER_DTD;
 
12044
#ifdef DEBUG_PUSH
 
12045
                xmlGenericError(xmlGenericErrorContext,
 
12046
                        "PP: entering DTD\n");
 
12047
#endif
 
12048
                break;
 
12049
            case XML_PARSER_PI:
 
12050
                xmlGenericError(xmlGenericErrorContext,
 
12051
                        "PP: internal error, state == PI\n");
 
12052
                ctxt->instate = XML_PARSER_CONTENT;
 
12053
#ifdef DEBUG_PUSH
 
12054
                xmlGenericError(xmlGenericErrorContext,
 
12055
                        "PP: entering CONTENT\n");
 
12056
#endif
 
12057
                break;
 
12058
            case XML_PARSER_ENTITY_DECL:
 
12059
                xmlGenericError(xmlGenericErrorContext,
 
12060
                        "PP: internal error, state == ENTITY_DECL\n");
 
12061
                ctxt->instate = XML_PARSER_DTD;
 
12062
#ifdef DEBUG_PUSH
 
12063
                xmlGenericError(xmlGenericErrorContext,
 
12064
                        "PP: entering DTD\n");
 
12065
#endif
 
12066
                break;
 
12067
            case XML_PARSER_ENTITY_VALUE:
 
12068
                xmlGenericError(xmlGenericErrorContext,
 
12069
                        "PP: internal error, state == ENTITY_VALUE\n");
 
12070
                ctxt->instate = XML_PARSER_CONTENT;
 
12071
#ifdef DEBUG_PUSH
 
12072
                xmlGenericError(xmlGenericErrorContext,
 
12073
                        "PP: entering DTD\n");
 
12074
#endif
 
12075
                break;
 
12076
            case XML_PARSER_ATTRIBUTE_VALUE:
 
12077
                xmlGenericError(xmlGenericErrorContext,
 
12078
                        "PP: internal error, state == ATTRIBUTE_VALUE\n");
 
12079
                ctxt->instate = XML_PARSER_START_TAG;
 
12080
#ifdef DEBUG_PUSH
 
12081
                xmlGenericError(xmlGenericErrorContext,
 
12082
                        "PP: entering START_TAG\n");
 
12083
#endif
 
12084
                break;
 
12085
            case XML_PARSER_SYSTEM_LITERAL:
 
12086
                xmlGenericError(xmlGenericErrorContext,
 
12087
                        "PP: internal error, state == SYSTEM_LITERAL\n");
 
12088
                ctxt->instate = XML_PARSER_START_TAG;
 
12089
#ifdef DEBUG_PUSH
 
12090
                xmlGenericError(xmlGenericErrorContext,
 
12091
                        "PP: entering START_TAG\n");
 
12092
#endif
 
12093
                break;
 
12094
            case XML_PARSER_PUBLIC_LITERAL:
 
12095
                xmlGenericError(xmlGenericErrorContext,
 
12096
                        "PP: internal error, state == PUBLIC_LITERAL\n");
 
12097
                ctxt->instate = XML_PARSER_START_TAG;
 
12098
#ifdef DEBUG_PUSH
 
12099
                xmlGenericError(xmlGenericErrorContext,
 
12100
                        "PP: entering START_TAG\n");
 
12101
#endif
 
12102
                break;
 
12103
        }
 
12104
    }
 
12105
done:
 
12106
#ifdef DEBUG_PUSH
 
12107
    xmlGenericError(xmlGenericErrorContext, "PP: done %d\n", ret);
 
12108
#endif
 
12109
    return(ret);
 
12110
encoding_error:
 
12111
    {
 
12112
        char buffer[150];
 
12113
 
 
12114
        snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
 
12115
                        ctxt->input->cur[0], ctxt->input->cur[1],
 
12116
                        ctxt->input->cur[2], ctxt->input->cur[3]);
 
12117
        __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
 
12118
                     "Input is not proper UTF-8, indicate encoding !\n%s",
 
12119
                     BAD_CAST buffer, NULL);
 
12120
    }
 
12121
    return(0);
 
12122
}
 
12123
 
 
12124
/**
 
12125
 * xmlParseCheckTransition:
 
12126
 * @ctxt:  an XML parser context
 
12127
 * @chunk:  a char array
 
12128
 * @size:  the size in byte of the chunk
 
12129
 *
 
12130
 * Check depending on the current parser state if the chunk given must be
 
12131
 * processed immediately or one need more data to advance on parsing.
 
12132
 *
 
12133
 * Returns -1 in case of error, 0 if the push is not needed and 1 if needed
 
12134
 */
 
12135
static int
 
12136
xmlParseCheckTransition(xmlParserCtxtPtr ctxt, const char *chunk, int size) {
 
12137
    if ((ctxt == NULL) || (chunk == NULL) || (size < 0))
 
12138
        return(-1);
 
12139
    if (ctxt->instate == XML_PARSER_START_TAG) {
 
12140
        if (memchr(chunk, '>', size) != NULL)
 
12141
            return(1);
 
12142
        return(0);
 
12143
    }
 
12144
    if (ctxt->progressive == XML_PARSER_COMMENT) {
 
12145
        if (memchr(chunk, '>', size) != NULL)
 
12146
            return(1);
 
12147
        return(0);
 
12148
    }
 
12149
    if (ctxt->instate == XML_PARSER_CDATA_SECTION) {
 
12150
        if (memchr(chunk, '>', size) != NULL)
 
12151
            return(1);
 
12152
        return(0);
 
12153
    }
 
12154
    if (ctxt->progressive == XML_PARSER_PI) {
 
12155
        if (memchr(chunk, '>', size) != NULL)
 
12156
            return(1);
 
12157
        return(0);
 
12158
    }
 
12159
    if (ctxt->instate == XML_PARSER_END_TAG) {
 
12160
        if (memchr(chunk, '>', size) != NULL)
 
12161
            return(1);
 
12162
        return(0);
 
12163
    }
 
12164
    if ((ctxt->progressive == XML_PARSER_DTD) ||
 
12165
        (ctxt->instate == XML_PARSER_DTD)) {
 
12166
        if (memchr(chunk, '>', size) != NULL)
 
12167
            return(1);
 
12168
        return(0);
 
12169
    }
 
12170
    return(1);
 
12171
}
 
12172
 
 
12173
/**
 
12174
 * xmlParseChunk:
 
12175
 * @ctxt:  an XML parser context
 
12176
 * @chunk:  an char array
 
12177
 * @size:  the size in byte of the chunk
 
12178
 * @terminate:  last chunk indicator
 
12179
 *
 
12180
 * Parse a Chunk of memory
 
12181
 *
 
12182
 * Returns zero if no error, the xmlParserErrors otherwise.
 
12183
 */
 
12184
int
 
12185
xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
 
12186
              int terminate) {
 
12187
    int end_in_lf = 0;
 
12188
    int remain = 0;
 
12189
    size_t old_avail = 0;
 
12190
    size_t avail = 0;
 
12191
 
 
12192
    if (ctxt == NULL)
 
12193
        return(XML_ERR_INTERNAL_ERROR);
 
12194
    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
 
12195
        return(ctxt->errNo);
 
12196
    if (ctxt->instate == XML_PARSER_EOF)
 
12197
        return(-1);
 
12198
    if (ctxt->instate == XML_PARSER_START)
 
12199
        xmlDetectSAX2(ctxt);
 
12200
    if ((size > 0) && (chunk != NULL) && (!terminate) &&
 
12201
        (chunk[size - 1] == '\r')) {
 
12202
        end_in_lf = 1;
 
12203
        size--;
 
12204
    }
 
12205
 
 
12206
xmldecl_done:
 
12207
 
 
12208
    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
 
12209
        (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF))  {
 
12210
        size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
 
12211
        size_t cur = ctxt->input->cur - ctxt->input->base;
 
12212
        int res;
 
12213
 
 
12214
        old_avail = xmlBufUse(ctxt->input->buf->buffer);
 
12215
        /*
 
12216
         * Specific handling if we autodetected an encoding, we should not
 
12217
         * push more than the first line ... which depend on the encoding
 
12218
         * And only push the rest once the final encoding was detected
 
12219
         */
 
12220
        if ((ctxt->instate == XML_PARSER_START) && (ctxt->input != NULL) &&
 
12221
            (ctxt->input->buf != NULL) && (ctxt->input->buf->encoder != NULL)) {
 
12222
            unsigned int len = 45;
 
12223
 
 
12224
            if ((xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
 
12225
                               BAD_CAST "UTF-16")) ||
 
12226
                (xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
 
12227
                               BAD_CAST "UTF16")))
 
12228
                len = 90;
 
12229
            else if ((xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
 
12230
                                    BAD_CAST "UCS-4")) ||
 
12231
                     (xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
 
12232
                                    BAD_CAST "UCS4")))
 
12233
                len = 180;
 
12234
 
 
12235
            if (ctxt->input->buf->rawconsumed < len)
 
12236
                len -= ctxt->input->buf->rawconsumed;
 
12237
 
 
12238
            /*
 
12239
             * Change size for reading the initial declaration only
 
12240
             * if size is greater than len. Otherwise, memmove in xmlBufferAdd
 
12241
             * will blindly copy extra bytes from memory.
 
12242
             */
 
12243
            if ((unsigned int) size > len) {
 
12244
                remain = size - len;
 
12245
                size = len;
 
12246
            } else {
 
12247
                remain = 0;
 
12248
            }
 
12249
        }
 
12250
        res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
 
12251
        if (res < 0) {
 
12252
            ctxt->errNo = XML_PARSER_EOF;
 
12253
            ctxt->disableSAX = 1;
 
12254
            return (XML_PARSER_EOF);
 
12255
        }
 
12256
        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
 
12257
#ifdef DEBUG_PUSH
 
12258
        xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
 
12259
#endif
 
12260
 
 
12261
    } else if (ctxt->instate != XML_PARSER_EOF) {
 
12262
        if ((ctxt->input != NULL) && ctxt->input->buf != NULL) {
 
12263
            xmlParserInputBufferPtr in = ctxt->input->buf;
 
12264
            if ((in->encoder != NULL) && (in->buffer != NULL) &&
 
12265
                    (in->raw != NULL)) {
 
12266
                int nbchars;
 
12267
                size_t base = xmlBufGetInputBase(in->buffer, ctxt->input);
 
12268
                size_t current = ctxt->input->cur - ctxt->input->base;
 
12269
 
 
12270
                nbchars = xmlCharEncInput(in, terminate);
 
12271
                if (nbchars < 0) {
 
12272
                    /* TODO 2.6.0 */
 
12273
                    xmlGenericError(xmlGenericErrorContext,
 
12274
                                    "xmlParseChunk: encoder error\n");
 
12275
                    return(XML_ERR_INVALID_ENCODING);
 
12276
                }
 
12277
                xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
 
12278
            }
 
12279
        }
 
12280
    }
 
12281
    if (remain != 0) {
 
12282
        xmlParseTryOrFinish(ctxt, 0);
 
12283
    } else {
 
12284
        if ((ctxt->input != NULL) && (ctxt->input->buf != NULL))
 
12285
            avail = xmlBufUse(ctxt->input->buf->buffer);
 
12286
        /*
 
12287
         * Depending on the current state it may not be such
 
12288
         * a good idea to try parsing if there is nothing in the chunk
 
12289
         * which would be worth doing a parser state transition and we
 
12290
         * need to wait for more data
 
12291
         */
 
12292
        if ((terminate) || (avail > XML_MAX_TEXT_LENGTH) ||
 
12293
            (old_avail == 0) || (avail == 0) ||
 
12294
            (xmlParseCheckTransition(ctxt,
 
12295
                       (const char *)&ctxt->input->base[old_avail],
 
12296
                                     avail - old_avail)))
 
12297
            xmlParseTryOrFinish(ctxt, terminate);
 
12298
    }
 
12299
    if (ctxt->instate == XML_PARSER_EOF)
 
12300
        return(ctxt->errNo);
 
12301
 
 
12302
    if ((ctxt->input != NULL) &&
 
12303
         (((ctxt->input->end - ctxt->input->cur) > XML_MAX_LOOKUP_LIMIT) ||
 
12304
         ((ctxt->input->cur - ctxt->input->base) > XML_MAX_LOOKUP_LIMIT)) &&
 
12305
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
 
12306
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
 
12307
        ctxt->instate = XML_PARSER_EOF;
 
12308
    }
 
12309
    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
 
12310
        return(ctxt->errNo);
 
12311
 
 
12312
    if (remain != 0) {
 
12313
        chunk += size;
 
12314
        size = remain;
 
12315
        remain = 0;
 
12316
        goto xmldecl_done;
 
12317
    }
 
12318
    if ((end_in_lf == 1) && (ctxt->input != NULL) &&
 
12319
        (ctxt->input->buf != NULL)) {
 
12320
        size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer,
 
12321
                                         ctxt->input);
 
12322
        size_t current = ctxt->input->cur - ctxt->input->base;
 
12323
 
 
12324
        xmlParserInputBufferPush(ctxt->input->buf, 1, "\r");
 
12325
 
 
12326
        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input,
 
12327
                              base, current);
 
12328
    }
 
12329
    if (terminate) {
 
12330
        /*
 
12331
         * Check for termination
 
12332
         */
 
12333
        int cur_avail = 0;
 
12334
 
 
12335
        if (ctxt->input != NULL) {
 
12336
            if (ctxt->input->buf == NULL)
 
12337
                cur_avail = ctxt->input->length -
 
12338
                            (ctxt->input->cur - ctxt->input->base);
 
12339
            else
 
12340
                cur_avail = xmlBufUse(ctxt->input->buf->buffer) -
 
12341
                                      (ctxt->input->cur - ctxt->input->base);
 
12342
        }
 
12343
 
 
12344
        if ((ctxt->instate != XML_PARSER_EOF) &&
 
12345
            (ctxt->instate != XML_PARSER_EPILOG)) {
 
12346
            xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
 
12347
        }
 
12348
        if ((ctxt->instate == XML_PARSER_EPILOG) && (cur_avail > 0)) {
 
12349
            xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
 
12350
        }
 
12351
        if (ctxt->instate != XML_PARSER_EOF) {
 
12352
            if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 
12353
                ctxt->sax->endDocument(ctxt->userData);
 
12354
        }
 
12355
        ctxt->instate = XML_PARSER_EOF;
 
12356
    }
 
12357
    if (ctxt->wellFormed == 0)
 
12358
        return((xmlParserErrors) ctxt->errNo);
 
12359
    else
 
12360
        return(0);
 
12361
}
 
12362
 
 
12363
/************************************************************************
 
12364
 *                                                                      *
 
12365
 *              I/O front end functions to the parser                   *
 
12366
 *                                                                      *
 
12367
 ************************************************************************/
 
12368
 
 
12369
/**
 
12370
 * xmlCreatePushParserCtxt:
 
12371
 * @sax:  a SAX handler
 
12372
 * @user_data:  The user data returned on SAX callbacks
 
12373
 * @chunk:  a pointer to an array of chars
 
12374
 * @size:  number of chars in the array
 
12375
 * @filename:  an optional file name or URI
 
12376
 *
 
12377
 * Create a parser context for using the XML parser in push mode.
 
12378
 * If @buffer and @size are non-NULL, the data is used to detect
 
12379
 * the encoding.  The remaining characters will be parsed so they
 
12380
 * don't need to be fed in again through xmlParseChunk.
 
12381
 * To allow content encoding detection, @size should be >= 4
 
12382
 * The value of @filename is used for fetching external entities
 
12383
 * and error/warning reports.
 
12384
 *
 
12385
 * Returns the new parser context or NULL
 
12386
 */
 
12387
 
 
12388
xmlParserCtxtPtr
 
12389
xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
 
12390
                        const char *chunk, int size, const char *filename) {
 
12391
    xmlParserCtxtPtr ctxt;
 
12392
    xmlParserInputPtr inputStream;
 
12393
    xmlParserInputBufferPtr buf;
 
12394
    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
 
12395
 
 
12396
    /*
 
12397
     * plug some encoding conversion routines
 
12398
     */
 
12399
    if ((chunk != NULL) && (size >= 4))
 
12400
        enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
 
12401
 
 
12402
    buf = xmlAllocParserInputBuffer(enc);
 
12403
    if (buf == NULL) return(NULL);
 
12404
 
 
12405
    ctxt = xmlNewParserCtxt();
 
12406
    if (ctxt == NULL) {
 
12407
        xmlErrMemory(NULL, "creating parser: out of memory\n");
 
12408
        xmlFreeParserInputBuffer(buf);
 
12409
        return(NULL);
 
12410
    }
 
12411
    ctxt->dictNames = 1;
 
12412
    ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 * sizeof(xmlChar *));
 
12413
    if (ctxt->pushTab == NULL) {
 
12414
        xmlErrMemory(ctxt, NULL);
 
12415
        xmlFreeParserInputBuffer(buf);
 
12416
        xmlFreeParserCtxt(ctxt);
 
12417
        return(NULL);
 
12418
    }
 
12419
    if (sax != NULL) {
 
12420
#ifdef LIBXML_SAX1_ENABLED
 
12421
        if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
 
12422
#endif /* LIBXML_SAX1_ENABLED */
 
12423
            xmlFree(ctxt->sax);
 
12424
        ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
 
12425
        if (ctxt->sax == NULL) {
 
12426
            xmlErrMemory(ctxt, NULL);
 
12427
            xmlFreeParserInputBuffer(buf);
 
12428
            xmlFreeParserCtxt(ctxt);
 
12429
            return(NULL);
 
12430
        }
 
12431
        memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
 
12432
        if (sax->initialized == XML_SAX2_MAGIC)
 
12433
            memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
 
12434
        else
 
12435
            memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
 
12436
        if (user_data != NULL)
 
12437
            ctxt->userData = user_data;
 
12438
    }
 
12439
    if (filename == NULL) {
 
12440
        ctxt->directory = NULL;
 
12441
    } else {
 
12442
        ctxt->directory = xmlParserGetDirectory(filename);
 
12443
    }
 
12444
 
 
12445
    inputStream = xmlNewInputStream(ctxt);
 
12446
    if (inputStream == NULL) {
 
12447
        xmlFreeParserCtxt(ctxt);
 
12448
        xmlFreeParserInputBuffer(buf);
 
12449
        return(NULL);
 
12450
    }
 
12451
 
 
12452
    if (filename == NULL)
 
12453
        inputStream->filename = NULL;
 
12454
    else {
 
12455
        inputStream->filename = (char *)
 
12456
            xmlCanonicPath((const xmlChar *) filename);
 
12457
        if (inputStream->filename == NULL) {
 
12458
            xmlFreeParserCtxt(ctxt);
 
12459
            xmlFreeParserInputBuffer(buf);
 
12460
            return(NULL);
 
12461
        }
 
12462
    }
 
12463
    inputStream->buf = buf;
 
12464
    xmlBufResetInput(inputStream->buf->buffer, inputStream);
 
12465
    inputPush(ctxt, inputStream);
 
12466
 
 
12467
    /*
 
12468
     * If the caller didn't provide an initial 'chunk' for determining
 
12469
     * the encoding, we set the context to XML_CHAR_ENCODING_NONE so
 
12470
     * that it can be automatically determined later
 
12471
     */
 
12472
    if ((size == 0) || (chunk == NULL)) {
 
12473
        ctxt->charset = XML_CHAR_ENCODING_NONE;
 
12474
    } else if ((ctxt->input != NULL) && (ctxt->input->buf != NULL)) {
 
12475
        size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
 
12476
        size_t cur = ctxt->input->cur - ctxt->input->base;
 
12477
 
 
12478
        xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
 
12479
 
 
12480
        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
 
12481
#ifdef DEBUG_PUSH
 
12482
        xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
 
12483
#endif
 
12484
    }
 
12485
 
 
12486
    if (enc != XML_CHAR_ENCODING_NONE) {
 
12487
        xmlSwitchEncoding(ctxt, enc);
 
12488
    }
 
12489
 
 
12490
    return(ctxt);
 
12491
}
 
12492
#endif /* LIBXML_PUSH_ENABLED */
 
12493
 
 
12494
/**
 
12495
 * xmlStopParser:
 
12496
 * @ctxt:  an XML parser context
 
12497
 *
 
12498
 * Blocks further parser processing
 
12499
 */
 
12500
void
 
12501
xmlStopParser(xmlParserCtxtPtr ctxt) {
 
12502
    if (ctxt == NULL)
 
12503
        return;
 
12504
    ctxt->instate = XML_PARSER_EOF;
 
12505
    ctxt->errNo = XML_ERR_USER_STOP;
 
12506
    ctxt->disableSAX = 1;
 
12507
    if (ctxt->input != NULL) {
 
12508
        ctxt->input->cur = BAD_CAST"";
 
12509
        ctxt->input->base = ctxt->input->cur;
 
12510
    }
 
12511
}
 
12512
 
 
12513
/**
 
12514
 * xmlCreateIOParserCtxt:
 
12515
 * @sax:  a SAX handler
 
12516
 * @user_data:  The user data returned on SAX callbacks
 
12517
 * @ioread:  an I/O read function
 
12518
 * @ioclose:  an I/O close function
 
12519
 * @ioctx:  an I/O handler
 
12520
 * @enc:  the charset encoding if known
 
12521
 *
 
12522
 * Create a parser context for using the XML parser with an existing
 
12523
 * I/O stream
 
12524
 *
 
12525
 * Returns the new parser context or NULL
 
12526
 */
 
12527
xmlParserCtxtPtr
 
12528
xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
 
12529
        xmlInputReadCallback   ioread, xmlInputCloseCallback  ioclose,
 
12530
        void *ioctx, xmlCharEncoding enc) {
 
12531
    xmlParserCtxtPtr ctxt;
 
12532
    xmlParserInputPtr inputStream;
 
12533
    xmlParserInputBufferPtr buf;
 
12534
 
 
12535
    if (ioread == NULL) return(NULL);
 
12536
 
 
12537
    buf = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, enc);
 
12538
    if (buf == NULL) {
 
12539
        if (ioclose != NULL)
 
12540
            ioclose(ioctx);
 
12541
        return (NULL);
 
12542
    }
 
12543
 
 
12544
    ctxt = xmlNewParserCtxt();
 
12545
    if (ctxt == NULL) {
 
12546
        xmlFreeParserInputBuffer(buf);
 
12547
        return(NULL);
 
12548
    }
 
12549
    if (sax != NULL) {
 
12550
#ifdef LIBXML_SAX1_ENABLED
 
12551
        if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
 
12552
#endif /* LIBXML_SAX1_ENABLED */
 
12553
            xmlFree(ctxt->sax);
 
12554
        ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
 
12555
        if (ctxt->sax == NULL) {
 
12556
            xmlErrMemory(ctxt, NULL);
 
12557
            xmlFreeParserCtxt(ctxt);
 
12558
            return(NULL);
 
12559
        }
 
12560
        memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
 
12561
        if (sax->initialized == XML_SAX2_MAGIC)
 
12562
            memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
 
12563
        else
 
12564
            memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
 
12565
        if (user_data != NULL)
 
12566
            ctxt->userData = user_data;
 
12567
    }
 
12568
 
 
12569
    inputStream = xmlNewIOInputStream(ctxt, buf, enc);
 
12570
    if (inputStream == NULL) {
 
12571
        xmlFreeParserCtxt(ctxt);
 
12572
        return(NULL);
 
12573
    }
 
12574
    inputPush(ctxt, inputStream);
 
12575
 
 
12576
    return(ctxt);
 
12577
}
 
12578
 
 
12579
#ifdef LIBXML_VALID_ENABLED
 
12580
/************************************************************************
 
12581
 *                                                                      *
 
12582
 *              Front ends when parsing a DTD                           *
 
12583
 *                                                                      *
 
12584
 ************************************************************************/
 
12585
 
 
12586
/**
 
12587
 * xmlIOParseDTD:
 
12588
 * @sax:  the SAX handler block or NULL
 
12589
 * @input:  an Input Buffer
 
12590
 * @enc:  the charset encoding if known
 
12591
 *
 
12592
 * Load and parse a DTD
 
12593
 *
 
12594
 * Returns the resulting xmlDtdPtr or NULL in case of error.
 
12595
 * @input will be freed by the function in any case.
 
12596
 */
 
12597
 
 
12598
xmlDtdPtr
 
12599
xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
 
12600
              xmlCharEncoding enc) {
 
12601
    xmlDtdPtr ret = NULL;
 
12602
    xmlParserCtxtPtr ctxt;
 
12603
    xmlParserInputPtr pinput = NULL;
 
12604
    xmlChar start[4];
 
12605
 
 
12606
    if (input == NULL)
 
12607
        return(NULL);
 
12608
 
 
12609
    ctxt = xmlNewParserCtxt();
 
12610
    if (ctxt == NULL) {
 
12611
        xmlFreeParserInputBuffer(input);
 
12612
        return(NULL);
 
12613
    }
 
12614
 
 
12615
    /* We are loading a DTD */
 
12616
    ctxt->options |= XML_PARSE_DTDLOAD;
 
12617
 
 
12618
    /*
 
12619
     * Set-up the SAX context
 
12620
     */
 
12621
    if (sax != NULL) {
 
12622
        if (ctxt->sax != NULL)
 
12623
            xmlFree(ctxt->sax);
 
12624
        ctxt->sax = sax;
 
12625
        ctxt->userData = ctxt;
 
12626
    }
 
12627
    xmlDetectSAX2(ctxt);
 
12628
 
 
12629
    /*
 
12630
     * generate a parser input from the I/O handler
 
12631
     */
 
12632
 
 
12633
    pinput = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
 
12634
    if (pinput == NULL) {
 
12635
        if (sax != NULL) ctxt->sax = NULL;
 
12636
        xmlFreeParserInputBuffer(input);
 
12637
        xmlFreeParserCtxt(ctxt);
 
12638
        return(NULL);
 
12639
    }
 
12640
 
 
12641
    /*
 
12642
     * plug some encoding conversion routines here.
 
12643
     */
 
12644
    if (xmlPushInput(ctxt, pinput) < 0) {
 
12645
        if (sax != NULL) ctxt->sax = NULL;
 
12646
        xmlFreeParserCtxt(ctxt);
 
12647
        return(NULL);
 
12648
    }
 
12649
    if (enc != XML_CHAR_ENCODING_NONE) {
 
12650
        xmlSwitchEncoding(ctxt, enc);
 
12651
    }
 
12652
 
 
12653
    pinput->filename = NULL;
 
12654
    pinput->line = 1;
 
12655
    pinput->col = 1;
 
12656
    pinput->base = ctxt->input->cur;
 
12657
    pinput->cur = ctxt->input->cur;
 
12658
    pinput->free = NULL;
 
12659
 
 
12660
    /*
 
12661
     * let's parse that entity knowing it's an external subset.
 
12662
     */
 
12663
    ctxt->inSubset = 2;
 
12664
    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
 
12665
    if (ctxt->myDoc == NULL) {
 
12666
        xmlErrMemory(ctxt, "New Doc failed");
 
12667
        return(NULL);
 
12668
    }
 
12669
    ctxt->myDoc->properties = XML_DOC_INTERNAL;
 
12670
    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
 
12671
                                       BAD_CAST "none", BAD_CAST "none");
 
12672
 
 
12673
    if ((enc == XML_CHAR_ENCODING_NONE) &&
 
12674
        ((ctxt->input->end - ctxt->input->cur) >= 4)) {
 
12675
        /*
 
12676
         * Get the 4 first bytes and decode the charset
 
12677
         * if enc != XML_CHAR_ENCODING_NONE
 
12678
         * plug some encoding conversion routines.
 
12679
         */
 
12680
        start[0] = RAW;
 
12681
        start[1] = NXT(1);
 
12682
        start[2] = NXT(2);
 
12683
        start[3] = NXT(3);
 
12684
        enc = xmlDetectCharEncoding(start, 4);
 
12685
        if (enc != XML_CHAR_ENCODING_NONE) {
 
12686
            xmlSwitchEncoding(ctxt, enc);
 
12687
        }
 
12688
    }
 
12689
 
 
12690
    xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none");
 
12691
 
 
12692
    if (ctxt->myDoc != NULL) {
 
12693
        if (ctxt->wellFormed) {
 
12694
            ret = ctxt->myDoc->extSubset;
 
12695
            ctxt->myDoc->extSubset = NULL;
 
12696
            if (ret != NULL) {
 
12697
                xmlNodePtr tmp;
 
12698
 
 
12699
                ret->doc = NULL;
 
12700
                tmp = ret->children;
 
12701
                while (tmp != NULL) {
 
12702
                    tmp->doc = NULL;
 
12703
                    tmp = tmp->next;
 
12704
                }
 
12705
            }
 
12706
        } else {
 
12707
            ret = NULL;
 
12708
        }
 
12709
        xmlFreeDoc(ctxt->myDoc);
 
12710
        ctxt->myDoc = NULL;
 
12711
    }
 
12712
    if (sax != NULL) ctxt->sax = NULL;
 
12713
    xmlFreeParserCtxt(ctxt);
 
12714
 
 
12715
    return(ret);
 
12716
}
 
12717
 
 
12718
/**
 
12719
 * xmlSAXParseDTD:
 
12720
 * @sax:  the SAX handler block
 
12721
 * @ExternalID:  a NAME* containing the External ID of the DTD
 
12722
 * @SystemID:  a NAME* containing the URL to the DTD
 
12723
 *
 
12724
 * Load and parse an external subset.
 
12725
 *
 
12726
 * Returns the resulting xmlDtdPtr or NULL in case of error.
 
12727
 */
 
12728
 
 
12729
xmlDtdPtr
 
12730
xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
 
12731
                          const xmlChar *SystemID) {
 
12732
    xmlDtdPtr ret = NULL;
 
12733
    xmlParserCtxtPtr ctxt;
 
12734
    xmlParserInputPtr input = NULL;
 
12735
    xmlCharEncoding enc;
 
12736
    xmlChar* systemIdCanonic;
 
12737
 
 
12738
    if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
 
12739
 
 
12740
    ctxt = xmlNewParserCtxt();
 
12741
    if (ctxt == NULL) {
 
12742
        return(NULL);
 
12743
    }
 
12744
 
 
12745
    /* We are loading a DTD */
 
12746
    ctxt->options |= XML_PARSE_DTDLOAD;
 
12747
 
 
12748
    /*
 
12749
     * Set-up the SAX context
 
12750
     */
 
12751
    if (sax != NULL) {
 
12752
        if (ctxt->sax != NULL)
 
12753
            xmlFree(ctxt->sax);
 
12754
        ctxt->sax = sax;
 
12755
        ctxt->userData = ctxt;
 
12756
    }
 
12757
 
 
12758
    /*
 
12759
     * Canonicalise the system ID
 
12760
     */
 
12761
    systemIdCanonic = xmlCanonicPath(SystemID);
 
12762
    if ((SystemID != NULL) && (systemIdCanonic == NULL)) {
 
12763
        xmlFreeParserCtxt(ctxt);
 
12764
        return(NULL);
 
12765
    }
 
12766
 
 
12767
    /*
 
12768
     * Ask the Entity resolver to load the damn thing
 
12769
     */
 
12770
 
 
12771
    if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
 
12772
        input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
 
12773
                                         systemIdCanonic);
 
12774
    if (input == NULL) {
 
12775
        if (sax != NULL) ctxt->sax = NULL;
 
12776
        xmlFreeParserCtxt(ctxt);
 
12777
        if (systemIdCanonic != NULL)
 
12778
            xmlFree(systemIdCanonic);
 
12779
        return(NULL);
 
12780
    }
 
12781
 
 
12782
    /*
 
12783
     * plug some encoding conversion routines here.
 
12784
     */
 
12785
    if (xmlPushInput(ctxt, input) < 0) {
 
12786
        if (sax != NULL) ctxt->sax = NULL;
 
12787
        xmlFreeParserCtxt(ctxt);
 
12788
        if (systemIdCanonic != NULL)
 
12789
            xmlFree(systemIdCanonic);
 
12790
        return(NULL);
 
12791
    }
 
12792
    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
 
12793
        enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
 
12794
        xmlSwitchEncoding(ctxt, enc);
 
12795
    }
 
12796
 
 
12797
    if (input->filename == NULL)
 
12798
        input->filename = (char *) systemIdCanonic;
 
12799
    else
 
12800
        xmlFree(systemIdCanonic);
 
12801
    input->line = 1;
 
12802
    input->col = 1;
 
12803
    input->base = ctxt->input->cur;
 
12804
    input->cur = ctxt->input->cur;
 
12805
    input->free = NULL;
 
12806
 
 
12807
    /*
 
12808
     * let's parse that entity knowing it's an external subset.
 
12809
     */
 
12810
    ctxt->inSubset = 2;
 
12811
    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
 
12812
    if (ctxt->myDoc == NULL) {
 
12813
        xmlErrMemory(ctxt, "New Doc failed");
 
12814
        if (sax != NULL) ctxt->sax = NULL;
 
12815
        xmlFreeParserCtxt(ctxt);
 
12816
        return(NULL);
 
12817
    }
 
12818
    ctxt->myDoc->properties = XML_DOC_INTERNAL;
 
12819
    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
 
12820
                                       ExternalID, SystemID);
 
12821
    xmlParseExternalSubset(ctxt, ExternalID, SystemID);
 
12822
 
 
12823
    if (ctxt->myDoc != NULL) {
 
12824
        if (ctxt->wellFormed) {
 
12825
            ret = ctxt->myDoc->extSubset;
 
12826
            ctxt->myDoc->extSubset = NULL;
 
12827
            if (ret != NULL) {
 
12828
                xmlNodePtr tmp;
 
12829
 
 
12830
                ret->doc = NULL;
 
12831
                tmp = ret->children;
 
12832
                while (tmp != NULL) {
 
12833
                    tmp->doc = NULL;
 
12834
                    tmp = tmp->next;
 
12835
                }
 
12836
            }
 
12837
        } else {
 
12838
            ret = NULL;
 
12839
        }
 
12840
        xmlFreeDoc(ctxt->myDoc);
 
12841
        ctxt->myDoc = NULL;
 
12842
    }
 
12843
    if (sax != NULL) ctxt->sax = NULL;
 
12844
    xmlFreeParserCtxt(ctxt);
 
12845
 
 
12846
    return(ret);
 
12847
}
 
12848
 
 
12849
 
 
12850
/**
 
12851
 * xmlParseDTD:
 
12852
 * @ExternalID:  a NAME* containing the External ID of the DTD
 
12853
 * @SystemID:  a NAME* containing the URL to the DTD
 
12854
 *
 
12855
 * Load and parse an external subset.
 
12856
 *
 
12857
 * Returns the resulting xmlDtdPtr or NULL in case of error.
 
12858
 */
 
12859
 
 
12860
xmlDtdPtr
 
12861
xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
 
12862
    return(xmlSAXParseDTD(NULL, ExternalID, SystemID));
 
12863
}
 
12864
#endif /* LIBXML_VALID_ENABLED */
 
12865
 
 
12866
/************************************************************************
 
12867
 *                                                                      *
 
12868
 *              Front ends when parsing an Entity                       *
 
12869
 *                                                                      *
 
12870
 ************************************************************************/
 
12871
 
 
12872
/**
 
12873
 * xmlParseCtxtExternalEntity:
 
12874
 * @ctx:  the existing parsing context
 
12875
 * @URL:  the URL for the entity to load
 
12876
 * @ID:  the System ID for the entity to load
 
12877
 * @lst:  the return value for the set of parsed nodes
 
12878
 *
 
12879
 * Parse an external general entity within an existing parsing context
 
12880
 * An external general parsed entity is well-formed if it matches the
 
12881
 * production labeled extParsedEnt.
 
12882
 *
 
12883
 * [78] extParsedEnt ::= TextDecl? content
 
12884
 *
 
12885
 * Returns 0 if the entity is well formed, -1 in case of args problem and
 
12886
 *    the parser error code otherwise
 
12887
 */
 
12888
 
 
12889
int
 
12890
xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
 
12891
                       const xmlChar *ID, xmlNodePtr *lst) {
 
12892
    xmlParserCtxtPtr ctxt;
 
12893
    xmlDocPtr newDoc;
 
12894
    xmlNodePtr newRoot;
 
12895
    xmlSAXHandlerPtr oldsax = NULL;
 
12896
    int ret = 0;
 
12897
    xmlChar start[4];
 
12898
    xmlCharEncoding enc;
 
12899
 
 
12900
    if (ctx == NULL) return(-1);
 
12901
 
 
12902
    if (((ctx->depth > 40) && ((ctx->options & XML_PARSE_HUGE) == 0)) ||
 
12903
        (ctx->depth > 1024)) {
 
12904
        return(XML_ERR_ENTITY_LOOP);
 
12905
    }
 
12906
 
 
12907
    if (lst != NULL)
 
12908
        *lst = NULL;
 
12909
    if ((URL == NULL) && (ID == NULL))
 
12910
        return(-1);
 
12911
    if (ctx->myDoc == NULL) /* @@ relax but check for dereferences */
 
12912
        return(-1);
 
12913
 
 
12914
    ctxt = xmlCreateEntityParserCtxtInternal(URL, ID, NULL, ctx);
 
12915
    if (ctxt == NULL) {
 
12916
        return(-1);
 
12917
    }
 
12918
 
 
12919
    oldsax = ctxt->sax;
 
12920
    ctxt->sax = ctx->sax;
 
12921
    xmlDetectSAX2(ctxt);
 
12922
    newDoc = xmlNewDoc(BAD_CAST "1.0");
 
12923
    if (newDoc == NULL) {
 
12924
        xmlFreeParserCtxt(ctxt);
 
12925
        return(-1);
 
12926
    }
 
12927
    newDoc->properties = XML_DOC_INTERNAL;
 
12928
    if (ctx->myDoc->dict) {
 
12929
        newDoc->dict = ctx->myDoc->dict;
 
12930
        xmlDictReference(newDoc->dict);
 
12931
    }
 
12932
    if (ctx->myDoc != NULL) {
 
12933
        newDoc->intSubset = ctx->myDoc->intSubset;
 
12934
        newDoc->extSubset = ctx->myDoc->extSubset;
 
12935
    }
 
12936
    if (ctx->myDoc->URL != NULL) {
 
12937
        newDoc->URL = xmlStrdup(ctx->myDoc->URL);
 
12938
    }
 
12939
    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
 
12940
    if (newRoot == NULL) {
 
12941
        ctxt->sax = oldsax;
 
12942
        xmlFreeParserCtxt(ctxt);
 
12943
        newDoc->intSubset = NULL;
 
12944
        newDoc->extSubset = NULL;
 
12945
        xmlFreeDoc(newDoc);
 
12946
        return(-1);
 
12947
    }
 
12948
    xmlAddChild((xmlNodePtr) newDoc, newRoot);
 
12949
    nodePush(ctxt, newDoc->children);
 
12950
    if (ctx->myDoc == NULL) {
 
12951
        ctxt->myDoc = newDoc;
 
12952
    } else {
 
12953
        ctxt->myDoc = ctx->myDoc;
 
12954
        newDoc->children->doc = ctx->myDoc;
 
12955
    }
 
12956
 
 
12957
    /*
 
12958
     * Get the 4 first bytes and decode the charset
 
12959
     * if enc != XML_CHAR_ENCODING_NONE
 
12960
     * plug some encoding conversion routines.
 
12961
     */
 
12962
    GROW
 
12963
    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
 
12964
        start[0] = RAW;
 
12965
        start[1] = NXT(1);
 
12966
        start[2] = NXT(2);
 
12967
        start[3] = NXT(3);
 
12968
        enc = xmlDetectCharEncoding(start, 4);
 
12969
        if (enc != XML_CHAR_ENCODING_NONE) {
 
12970
            xmlSwitchEncoding(ctxt, enc);
 
12971
        }
 
12972
    }
 
12973
 
 
12974
    /*
 
12975
     * Parse a possible text declaration first
 
12976
     */
 
12977
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
 
12978
        xmlParseTextDecl(ctxt);
 
12979
        /*
 
12980
         * An XML-1.0 document can't reference an entity not XML-1.0
 
12981
         */
 
12982
        if ((xmlStrEqual(ctx->version, BAD_CAST "1.0")) &&
 
12983
            (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) {
 
12984
            xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH,
 
12985
                           "Version mismatch between document and entity\n");
 
12986
        }
 
12987
    }
 
12988
 
 
12989
    /*
 
12990
     * If the user provided its own SAX callbacks then reuse the
 
12991
     * useData callback field, otherwise the expected setup in a
 
12992
     * DOM builder is to have userData == ctxt
 
12993
     */
 
12994
    if (ctx->userData == ctx)
 
12995
        ctxt->userData = ctxt;
 
12996
    else
 
12997
        ctxt->userData = ctx->userData;
 
12998
 
 
12999
    /*
 
13000
     * Doing validity checking on chunk doesn't make sense
 
13001
     */
 
13002
    ctxt->instate = XML_PARSER_CONTENT;
 
13003
    ctxt->validate = ctx->validate;
 
13004
    ctxt->valid = ctx->valid;
 
13005
    ctxt->loadsubset = ctx->loadsubset;
 
13006
    ctxt->depth = ctx->depth + 1;
 
13007
    ctxt->replaceEntities = ctx->replaceEntities;
 
13008
    if (ctxt->validate) {
 
13009
        ctxt->vctxt.error = ctx->vctxt.error;
 
13010
        ctxt->vctxt.warning = ctx->vctxt.warning;
 
13011
    } else {
 
13012
        ctxt->vctxt.error = NULL;
 
13013
        ctxt->vctxt.warning = NULL;
 
13014
    }
 
13015
    ctxt->vctxt.nodeTab = NULL;
 
13016
    ctxt->vctxt.nodeNr = 0;
 
13017
    ctxt->vctxt.nodeMax = 0;
 
13018
    ctxt->vctxt.node = NULL;
 
13019
    if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
 
13020
    ctxt->dict = ctx->dict;
 
13021
    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
 
13022
    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
 
13023
    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
 
13024
    ctxt->dictNames = ctx->dictNames;
 
13025
    ctxt->attsDefault = ctx->attsDefault;
 
13026
    ctxt->attsSpecial = ctx->attsSpecial;
 
13027
    ctxt->linenumbers = ctx->linenumbers;
 
13028
 
 
13029
    xmlParseContent(ctxt);
 
13030
 
 
13031
    ctx->validate = ctxt->validate;
 
13032
    ctx->valid = ctxt->valid;
 
13033
    if ((RAW == '<') && (NXT(1) == '/')) {
 
13034
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
13035
    } else if (RAW != 0) {
 
13036
        xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
 
13037
    }
 
13038
    if (ctxt->node != newDoc->children) {
 
13039
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
13040
    }
 
13041
 
 
13042
    if (!ctxt->wellFormed) {
 
13043
        if (ctxt->errNo == 0)
 
13044
            ret = 1;
 
13045
        else
 
13046
            ret = ctxt->errNo;
 
13047
    } else {
 
13048
        if (lst != NULL) {
 
13049
            xmlNodePtr cur;
 
13050
 
 
13051
            /*
 
13052
             * Return the newly created nodeset after unlinking it from
 
13053
             * they pseudo parent.
 
13054
             */
 
13055
            cur = newDoc->children->children;
 
13056
            *lst = cur;
 
13057
            while (cur != NULL) {
 
13058
                cur->parent = NULL;
 
13059
                cur = cur->next;
 
13060
            }
 
13061
            newDoc->children->children = NULL;
 
13062
        }
 
13063
        ret = 0;
 
13064
    }
 
13065
    ctxt->sax = oldsax;
 
13066
    ctxt->dict = NULL;
 
13067
    ctxt->attsDefault = NULL;
 
13068
    ctxt->attsSpecial = NULL;
 
13069
    xmlFreeParserCtxt(ctxt);
 
13070
    newDoc->intSubset = NULL;
 
13071
    newDoc->extSubset = NULL;
 
13072
    xmlFreeDoc(newDoc);
 
13073
 
 
13074
    return(ret);
 
13075
}
 
13076
 
 
13077
/**
 
13078
 * xmlParseExternalEntityPrivate:
 
13079
 * @doc:  the document the chunk pertains to
 
13080
 * @oldctxt:  the previous parser context if available
 
13081
 * @sax:  the SAX handler bloc (possibly NULL)
 
13082
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
 
13083
 * @depth:  Used for loop detection, use 0
 
13084
 * @URL:  the URL for the entity to load
 
13085
 * @ID:  the System ID for the entity to load
 
13086
 * @list:  the return value for the set of parsed nodes
 
13087
 *
 
13088
 * Private version of xmlParseExternalEntity()
 
13089
 *
 
13090
 * Returns 0 if the entity is well formed, -1 in case of args problem and
 
13091
 *    the parser error code otherwise
 
13092
 */
 
13093
 
 
13094
static xmlParserErrors
 
13095
xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
 
13096
                      xmlSAXHandlerPtr sax,
 
13097
                      void *user_data, int depth, const xmlChar *URL,
 
13098
                      const xmlChar *ID, xmlNodePtr *list) {
 
13099
    xmlParserCtxtPtr ctxt;
 
13100
    xmlDocPtr newDoc;
 
13101
    xmlNodePtr newRoot;
 
13102
    xmlSAXHandlerPtr oldsax = NULL;
 
13103
    xmlParserErrors ret = XML_ERR_OK;
 
13104
    xmlChar start[4];
 
13105
    xmlCharEncoding enc;
 
13106
 
 
13107
    if (((depth > 40) &&
 
13108
        ((oldctxt == NULL) || (oldctxt->options & XML_PARSE_HUGE) == 0)) ||
 
13109
        (depth > 1024)) {
 
13110
        return(XML_ERR_ENTITY_LOOP);
 
13111
    }
 
13112
 
 
13113
    if (list != NULL)
 
13114
        *list = NULL;
 
13115
    if ((URL == NULL) && (ID == NULL))
 
13116
        return(XML_ERR_INTERNAL_ERROR);
 
13117
    if (doc == NULL)
 
13118
        return(XML_ERR_INTERNAL_ERROR);
 
13119
 
 
13120
 
 
13121
    ctxt = xmlCreateEntityParserCtxtInternal(URL, ID, NULL, oldctxt);
 
13122
    if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
 
13123
    ctxt->userData = ctxt;
 
13124
    if (oldctxt != NULL) {
 
13125
        ctxt->_private = oldctxt->_private;
 
13126
        ctxt->loadsubset = oldctxt->loadsubset;
 
13127
        ctxt->validate = oldctxt->validate;
 
13128
        ctxt->external = oldctxt->external;
 
13129
        ctxt->record_info = oldctxt->record_info;
 
13130
        ctxt->node_seq.maximum = oldctxt->node_seq.maximum;
 
13131
        ctxt->node_seq.length = oldctxt->node_seq.length;
 
13132
        ctxt->node_seq.buffer = oldctxt->node_seq.buffer;
 
13133
    } else {
 
13134
        /*
 
13135
         * Doing validity checking on chunk without context
 
13136
         * doesn't make sense
 
13137
         */
 
13138
        ctxt->_private = NULL;
 
13139
        ctxt->validate = 0;
 
13140
        ctxt->external = 2;
 
13141
        ctxt->loadsubset = 0;
 
13142
    }
 
13143
    if (sax != NULL) {
 
13144
        oldsax = ctxt->sax;
 
13145
        ctxt->sax = sax;
 
13146
        if (user_data != NULL)
 
13147
            ctxt->userData = user_data;
 
13148
    }
 
13149
    xmlDetectSAX2(ctxt);
 
13150
    newDoc = xmlNewDoc(BAD_CAST "1.0");
 
13151
    if (newDoc == NULL) {
 
13152
        ctxt->node_seq.maximum = 0;
 
13153
        ctxt->node_seq.length = 0;
 
13154
        ctxt->node_seq.buffer = NULL;
 
13155
        xmlFreeParserCtxt(ctxt);
 
13156
        return(XML_ERR_INTERNAL_ERROR);
 
13157
    }
 
13158
    newDoc->properties = XML_DOC_INTERNAL;
 
13159
    newDoc->intSubset = doc->intSubset;
 
13160
    newDoc->extSubset = doc->extSubset;
 
13161
    newDoc->dict = doc->dict;
 
13162
    xmlDictReference(newDoc->dict);
 
13163
 
 
13164
    if (doc->URL != NULL) {
 
13165
        newDoc->URL = xmlStrdup(doc->URL);
 
13166
    }
 
13167
    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
 
13168
    if (newRoot == NULL) {
 
13169
        if (sax != NULL)
 
13170
            ctxt->sax = oldsax;
 
13171
        ctxt->node_seq.maximum = 0;
 
13172
        ctxt->node_seq.length = 0;
 
13173
        ctxt->node_seq.buffer = NULL;
 
13174
        xmlFreeParserCtxt(ctxt);
 
13175
        newDoc->intSubset = NULL;
 
13176
        newDoc->extSubset = NULL;
 
13177
        xmlFreeDoc(newDoc);
 
13178
        return(XML_ERR_INTERNAL_ERROR);
 
13179
    }
 
13180
    xmlAddChild((xmlNodePtr) newDoc, newRoot);
 
13181
    nodePush(ctxt, newDoc->children);
 
13182
    ctxt->myDoc = doc;
 
13183
    newRoot->doc = doc;
 
13184
 
 
13185
    /*
 
13186
     * Get the 4 first bytes and decode the charset
 
13187
     * if enc != XML_CHAR_ENCODING_NONE
 
13188
     * plug some encoding conversion routines.
 
13189
     */
 
13190
    GROW;
 
13191
    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
 
13192
        start[0] = RAW;
 
13193
        start[1] = NXT(1);
 
13194
        start[2] = NXT(2);
 
13195
        start[3] = NXT(3);
 
13196
        enc = xmlDetectCharEncoding(start, 4);
 
13197
        if (enc != XML_CHAR_ENCODING_NONE) {
 
13198
            xmlSwitchEncoding(ctxt, enc);
 
13199
        }
 
13200
    }
 
13201
 
 
13202
    /*
 
13203
     * Parse a possible text declaration first
 
13204
     */
 
13205
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
 
13206
        xmlParseTextDecl(ctxt);
 
13207
    }
 
13208
 
 
13209
    ctxt->instate = XML_PARSER_CONTENT;
 
13210
    ctxt->depth = depth;
 
13211
 
 
13212
    xmlParseContent(ctxt);
 
13213
 
 
13214
    if ((RAW == '<') && (NXT(1) == '/')) {
 
13215
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
13216
    } else if (RAW != 0) {
 
13217
        xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
 
13218
    }
 
13219
    if (ctxt->node != newDoc->children) {
 
13220
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
13221
    }
 
13222
 
 
13223
    if (!ctxt->wellFormed) {
 
13224
        if (ctxt->errNo == 0)
 
13225
            ret = XML_ERR_INTERNAL_ERROR;
 
13226
        else
 
13227
            ret = (xmlParserErrors)ctxt->errNo;
 
13228
    } else {
 
13229
        if (list != NULL) {
 
13230
            xmlNodePtr cur;
 
13231
 
 
13232
            /*
 
13233
             * Return the newly created nodeset after unlinking it from
 
13234
             * they pseudo parent.
 
13235
             */
 
13236
            cur = newDoc->children->children;
 
13237
            *list = cur;
 
13238
            while (cur != NULL) {
 
13239
                cur->parent = NULL;
 
13240
                cur = cur->next;
 
13241
            }
 
13242
            newDoc->children->children = NULL;
 
13243
        }
 
13244
        ret = XML_ERR_OK;
 
13245
    }
 
13246
 
 
13247
    /*
 
13248
     * Record in the parent context the number of entities replacement
 
13249
     * done when parsing that reference.
 
13250
     */
 
13251
    if (oldctxt != NULL)
 
13252
        oldctxt->nbentities += ctxt->nbentities;
 
13253
 
 
13254
    /*
 
13255
     * Also record the size of the entity parsed
 
13256
     */
 
13257
    if (ctxt->input != NULL) {
 
13258
        oldctxt->sizeentities += ctxt->input->consumed;
 
13259
        oldctxt->sizeentities += (ctxt->input->cur - ctxt->input->base);
 
13260
    }
 
13261
    /*
 
13262
     * And record the last error if any
 
13263
     */
 
13264
    if (ctxt->lastError.code != XML_ERR_OK)
 
13265
        xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
 
13266
 
 
13267
    if (sax != NULL)
 
13268
        ctxt->sax = oldsax;
 
13269
    oldctxt->node_seq.maximum = ctxt->node_seq.maximum;
 
13270
    oldctxt->node_seq.length = ctxt->node_seq.length;
 
13271
    oldctxt->node_seq.buffer = ctxt->node_seq.buffer;
 
13272
    ctxt->node_seq.maximum = 0;
 
13273
    ctxt->node_seq.length = 0;
 
13274
    ctxt->node_seq.buffer = NULL;
 
13275
    xmlFreeParserCtxt(ctxt);
 
13276
    newDoc->intSubset = NULL;
 
13277
    newDoc->extSubset = NULL;
 
13278
    xmlFreeDoc(newDoc);
 
13279
 
 
13280
    return(ret);
 
13281
}
 
13282
 
 
13283
#ifdef LIBXML_SAX1_ENABLED
 
13284
/**
 
13285
 * xmlParseExternalEntity:
 
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
 * @URL:  the URL for the entity to load
 
13291
 * @ID:  the System ID for the entity to load
 
13292
 * @lst:  the return value for the set of parsed nodes
 
13293
 *
 
13294
 * Parse an external general entity
 
13295
 * An external general parsed entity is well-formed if it matches the
 
13296
 * production labeled extParsedEnt.
 
13297
 *
 
13298
 * [78] extParsedEnt ::= TextDecl? content
 
13299
 *
 
13300
 * Returns 0 if the entity is well formed, -1 in case of args problem and
 
13301
 *    the parser error code otherwise
 
13302
 */
 
13303
 
 
13304
int
 
13305
xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data,
 
13306
          int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *lst) {
 
13307
    return(xmlParseExternalEntityPrivate(doc, NULL, sax, user_data, depth, URL,
 
13308
                                       ID, lst));
 
13309
}
 
13310
 
 
13311
/**
 
13312
 * xmlParseBalancedChunkMemory:
 
13313
 * @doc:  the document the chunk pertains to
 
13314
 * @sax:  the SAX handler bloc (possibly NULL)
 
13315
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
 
13316
 * @depth:  Used for loop detection, use 0
 
13317
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
 
13318
 * @lst:  the return value for the set of parsed nodes
 
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 0 if the chunk is well balanced, -1 in case of args problem and
 
13328
 *    the parser error code otherwise
 
13329
 */
 
13330
 
 
13331
int
 
13332
xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax,
 
13333
     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst) {
 
13334
    return xmlParseBalancedChunkMemoryRecover( doc, sax, user_data,
 
13335
                                                depth, string, lst, 0 );
 
13336
}
 
13337
#endif /* LIBXML_SAX1_ENABLED */
 
13338
 
 
13339
/**
 
13340
 * xmlParseBalancedChunkMemoryInternal:
 
13341
 * @oldctxt:  the existing parsing context
 
13342
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
 
13343
 * @user_data:  the user data field for the parser context
 
13344
 * @lst:  the return value for the set of parsed nodes
 
13345
 *
 
13346
 *
 
13347
 * Parse a well-balanced chunk of an XML document
 
13348
 * called by the parser
 
13349
 * The allowed sequence for the Well Balanced Chunk is the one defined by
 
13350
 * the content production in the XML grammar:
 
13351
 *
 
13352
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
 
13353
 *
 
13354
 * Returns XML_ERR_OK if the chunk is well balanced, and the parser
 
13355
 * error code otherwise
 
13356
 *
 
13357
 * In case recover is set to 1, the nodelist will not be empty even if
 
13358
 * the parsed chunk is not well balanced.
 
13359
 */
 
13360
static xmlParserErrors
 
13361
xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
 
13362
        const xmlChar *string, void *user_data, xmlNodePtr *lst) {
 
13363
    xmlParserCtxtPtr ctxt;
 
13364
    xmlDocPtr newDoc = NULL;
 
13365
    xmlNodePtr newRoot;
 
13366
    xmlSAXHandlerPtr oldsax = NULL;
 
13367
    xmlNodePtr content = NULL;
 
13368
    xmlNodePtr last = NULL;
 
13369
    int size;
 
13370
    xmlParserErrors ret = XML_ERR_OK;
 
13371
#ifdef SAX2
 
13372
    int i;
 
13373
#endif
 
13374
 
 
13375
    if (((oldctxt->depth > 40) && ((oldctxt->options & XML_PARSE_HUGE) == 0)) ||
 
13376
        (oldctxt->depth >  1024)) {
 
13377
        return(XML_ERR_ENTITY_LOOP);
 
13378
    }
 
13379
 
 
13380
 
 
13381
    if (lst != NULL)
 
13382
        *lst = NULL;
 
13383
    if (string == NULL)
 
13384
        return(XML_ERR_INTERNAL_ERROR);
 
13385
 
 
13386
    size = xmlStrlen(string);
 
13387
 
 
13388
    ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
 
13389
    if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
 
13390
    if (user_data != NULL)
 
13391
        ctxt->userData = user_data;
 
13392
    else
 
13393
        ctxt->userData = ctxt;
 
13394
    if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
 
13395
    ctxt->dict = oldctxt->dict;
 
13396
    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
 
13397
    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
 
13398
    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
 
13399
 
 
13400
#ifdef SAX2
 
13401
    /* propagate namespaces down the entity */
 
13402
    for (i = 0;i < oldctxt->nsNr;i += 2) {
 
13403
        nsPush(ctxt, oldctxt->nsTab[i], oldctxt->nsTab[i+1]);
 
13404
    }
 
13405
#endif
 
13406
 
 
13407
    oldsax = ctxt->sax;
 
13408
    ctxt->sax = oldctxt->sax;
 
13409
    xmlDetectSAX2(ctxt);
 
13410
    ctxt->replaceEntities = oldctxt->replaceEntities;
 
13411
    ctxt->options = oldctxt->options;
 
13412
 
 
13413
    ctxt->_private = oldctxt->_private;
 
13414
    if (oldctxt->myDoc == NULL) {
 
13415
        newDoc = xmlNewDoc(BAD_CAST "1.0");
 
13416
        if (newDoc == NULL) {
 
13417
            ctxt->sax = oldsax;
 
13418
            ctxt->dict = NULL;
 
13419
            xmlFreeParserCtxt(ctxt);
 
13420
            return(XML_ERR_INTERNAL_ERROR);
 
13421
        }
 
13422
        newDoc->properties = XML_DOC_INTERNAL;
 
13423
        newDoc->dict = ctxt->dict;
 
13424
        xmlDictReference(newDoc->dict);
 
13425
        ctxt->myDoc = newDoc;
 
13426
    } else {
 
13427
        ctxt->myDoc = oldctxt->myDoc;
 
13428
        content = ctxt->myDoc->children;
 
13429
        last = ctxt->myDoc->last;
 
13430
    }
 
13431
    newRoot = xmlNewDocNode(ctxt->myDoc, NULL, BAD_CAST "pseudoroot", NULL);
 
13432
    if (newRoot == NULL) {
 
13433
        ctxt->sax = oldsax;
 
13434
        ctxt->dict = NULL;
 
13435
        xmlFreeParserCtxt(ctxt);
 
13436
        if (newDoc != NULL) {
 
13437
            xmlFreeDoc(newDoc);
 
13438
        }
 
13439
        return(XML_ERR_INTERNAL_ERROR);
 
13440
    }
 
13441
    ctxt->myDoc->children = NULL;
 
13442
    ctxt->myDoc->last = NULL;
 
13443
    xmlAddChild((xmlNodePtr) ctxt->myDoc, newRoot);
 
13444
    nodePush(ctxt, ctxt->myDoc->children);
 
13445
    ctxt->instate = XML_PARSER_CONTENT;
 
13446
    ctxt->depth = oldctxt->depth + 1;
 
13447
 
 
13448
    ctxt->validate = 0;
 
13449
    ctxt->loadsubset = oldctxt->loadsubset;
 
13450
    if ((oldctxt->validate) || (oldctxt->replaceEntities != 0)) {
 
13451
        /*
 
13452
         * ID/IDREF registration will be done in xmlValidateElement below
 
13453
         */
 
13454
        ctxt->loadsubset |= XML_SKIP_IDS;
 
13455
    }
 
13456
    ctxt->dictNames = oldctxt->dictNames;
 
13457
    ctxt->attsDefault = oldctxt->attsDefault;
 
13458
    ctxt->attsSpecial = oldctxt->attsSpecial;
 
13459
 
 
13460
    xmlParseContent(ctxt);
 
13461
    if ((RAW == '<') && (NXT(1) == '/')) {
 
13462
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
13463
    } else if (RAW != 0) {
 
13464
        xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
 
13465
    }
 
13466
    if (ctxt->node != ctxt->myDoc->children) {
 
13467
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
13468
    }
 
13469
 
 
13470
    if (!ctxt->wellFormed) {
 
13471
        if (ctxt->errNo == 0)
 
13472
            ret = XML_ERR_INTERNAL_ERROR;
 
13473
        else
 
13474
            ret = (xmlParserErrors)ctxt->errNo;
 
13475
    } else {
 
13476
      ret = XML_ERR_OK;
 
13477
    }
 
13478
 
 
13479
    if ((lst != NULL) && (ret == XML_ERR_OK)) {
 
13480
        xmlNodePtr cur;
 
13481
 
 
13482
        /*
 
13483
         * Return the newly created nodeset after unlinking it from
 
13484
         * they pseudo parent.
 
13485
         */
 
13486
        cur = ctxt->myDoc->children->children;
 
13487
        *lst = cur;
 
13488
        while (cur != NULL) {
 
13489
#ifdef LIBXML_VALID_ENABLED
 
13490
            if ((oldctxt->validate) && (oldctxt->wellFormed) &&
 
13491
                (oldctxt->myDoc) && (oldctxt->myDoc->intSubset) &&
 
13492
                (cur->type == XML_ELEMENT_NODE)) {
 
13493
                oldctxt->valid &= xmlValidateElement(&oldctxt->vctxt,
 
13494
                        oldctxt->myDoc, cur);
 
13495
            }
 
13496
#endif /* LIBXML_VALID_ENABLED */
 
13497
            cur->parent = NULL;
 
13498
            cur = cur->next;
 
13499
        }
 
13500
        ctxt->myDoc->children->children = NULL;
 
13501
    }
 
13502
    if (ctxt->myDoc != NULL) {
 
13503
        xmlFreeNode(ctxt->myDoc->children);
 
13504
        ctxt->myDoc->children = content;
 
13505
        ctxt->myDoc->last = last;
 
13506
    }
 
13507
 
 
13508
    /*
 
13509
     * Record in the parent context the number of entities replacement
 
13510
     * done when parsing that reference.
 
13511
     */
 
13512
    if (oldctxt != NULL)
 
13513
        oldctxt->nbentities += ctxt->nbentities;
 
13514
 
 
13515
    /*
 
13516
     * Also record the last error if any
 
13517
     */
 
13518
    if (ctxt->lastError.code != XML_ERR_OK)
 
13519
        xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
 
13520
 
 
13521
    ctxt->sax = oldsax;
 
13522
    ctxt->dict = NULL;
 
13523
    ctxt->attsDefault = NULL;
 
13524
    ctxt->attsSpecial = NULL;
 
13525
    xmlFreeParserCtxt(ctxt);
 
13526
    if (newDoc != NULL) {
 
13527
        xmlFreeDoc(newDoc);
 
13528
    }
 
13529
 
 
13530
    return(ret);
 
13531
}
 
13532
 
 
13533
/**
 
13534
 * xmlParseInNodeContext:
 
13535
 * @node:  the context node
 
13536
 * @data:  the input string
 
13537
 * @datalen:  the input string length in bytes
 
13538
 * @options:  a combination of xmlParserOption
 
13539
 * @lst:  the return value for the set of parsed nodes
 
13540
 *
 
13541
 * Parse a well-balanced chunk of an XML document
 
13542
 * within the context (DTD, namespaces, etc ...) of the given node.
 
13543
 *
 
13544
 * The allowed sequence for the data is a Well Balanced Chunk defined by
 
13545
 * the content production in the XML grammar:
 
13546
 *
 
13547
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
 
13548
 *
 
13549
 * Returns XML_ERR_OK if the chunk is well balanced, and the parser
 
13550
 * error code otherwise
 
13551
 */
 
13552
xmlParserErrors
 
13553
xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
 
13554
                      int options, xmlNodePtr *lst) {
 
13555
#ifdef SAX2
 
13556
    xmlParserCtxtPtr ctxt;
 
13557
    xmlDocPtr doc = NULL;
 
13558
    xmlNodePtr fake, cur;
 
13559
    int nsnr = 0;
 
13560
 
 
13561
    xmlParserErrors ret = XML_ERR_OK;
 
13562
 
 
13563
    /*
 
13564
     * check all input parameters, grab the document
 
13565
     */
 
13566
    if ((lst == NULL) || (node == NULL) || (data == NULL) || (datalen < 0))
 
13567
        return(XML_ERR_INTERNAL_ERROR);
 
13568
    switch (node->type) {
 
13569
        case XML_ELEMENT_NODE:
 
13570
        case XML_ATTRIBUTE_NODE:
 
13571
        case XML_TEXT_NODE:
 
13572
        case XML_CDATA_SECTION_NODE:
 
13573
        case XML_ENTITY_REF_NODE:
 
13574
        case XML_PI_NODE:
 
13575
        case XML_COMMENT_NODE:
 
13576
        case XML_DOCUMENT_NODE:
 
13577
        case XML_HTML_DOCUMENT_NODE:
 
13578
            break;
 
13579
        default:
 
13580
            return(XML_ERR_INTERNAL_ERROR);
 
13581
 
 
13582
    }
 
13583
    while ((node != NULL) && (node->type != XML_ELEMENT_NODE) &&
 
13584
           (node->type != XML_DOCUMENT_NODE) &&
 
13585
           (node->type != XML_HTML_DOCUMENT_NODE))
 
13586
        node = node->parent;
 
13587
    if (node == NULL)
 
13588
        return(XML_ERR_INTERNAL_ERROR);
 
13589
    if (node->type == XML_ELEMENT_NODE)
 
13590
        doc = node->doc;
 
13591
    else
 
13592
        doc = (xmlDocPtr) node;
 
13593
    if (doc == NULL)
 
13594
        return(XML_ERR_INTERNAL_ERROR);
 
13595
 
 
13596
    /*
 
13597
     * allocate a context and set-up everything not related to the
 
13598
     * node position in the tree
 
13599
     */
 
13600
    if (doc->type == XML_DOCUMENT_NODE)
 
13601
        ctxt = xmlCreateMemoryParserCtxt((char *) data, datalen);
 
13602
#ifdef LIBXML_HTML_ENABLED
 
13603
    else if (doc->type == XML_HTML_DOCUMENT_NODE) {
 
13604
        ctxt = htmlCreateMemoryParserCtxt((char *) data, datalen);
 
13605
        /*
 
13606
         * When parsing in context, it makes no sense to add implied
 
13607
         * elements like html/body/etc...
 
13608
         */
 
13609
        options |= HTML_PARSE_NOIMPLIED;
 
13610
    }
 
13611
#endif
 
13612
    else
 
13613
        return(XML_ERR_INTERNAL_ERROR);
 
13614
 
 
13615
    if (ctxt == NULL)
 
13616
        return(XML_ERR_NO_MEMORY);
 
13617
 
 
13618
    /*
 
13619
     * Use input doc's dict if present, else assure XML_PARSE_NODICT is set.
 
13620
     * We need a dictionary for xmlDetectSAX2, so if there's no doc dict
 
13621
     * we must wait until the last moment to free the original one.
 
13622
     */
 
13623
    if (doc->dict != NULL) {
 
13624
        if (ctxt->dict != NULL)
 
13625
            xmlDictFree(ctxt->dict);
 
13626
        ctxt->dict = doc->dict;
 
13627
    } else
 
13628
        options |= XML_PARSE_NODICT;
 
13629
 
 
13630
    if (doc->encoding != NULL) {
 
13631
        xmlCharEncodingHandlerPtr hdlr;
 
13632
 
 
13633
        if (ctxt->encoding != NULL)
 
13634
            xmlFree((xmlChar *) ctxt->encoding);
 
13635
        ctxt->encoding = xmlStrdup((const xmlChar *) doc->encoding);
 
13636
 
 
13637
        hdlr = xmlFindCharEncodingHandler(doc->encoding);
 
13638
        if (hdlr != NULL) {
 
13639
            xmlSwitchToEncoding(ctxt, hdlr);
 
13640
        } else {
 
13641
            return(XML_ERR_UNSUPPORTED_ENCODING);
 
13642
        }
 
13643
    }
 
13644
 
 
13645
    xmlCtxtUseOptionsInternal(ctxt, options, NULL);
 
13646
    xmlDetectSAX2(ctxt);
 
13647
    ctxt->myDoc = doc;
 
13648
 
 
13649
    fake = xmlNewComment(NULL);
 
13650
    if (fake == NULL) {
 
13651
        xmlFreeParserCtxt(ctxt);
 
13652
        return(XML_ERR_NO_MEMORY);
 
13653
    }
 
13654
    xmlAddChild(node, fake);
 
13655
 
 
13656
    if (node->type == XML_ELEMENT_NODE) {
 
13657
        nodePush(ctxt, node);
 
13658
        /*
 
13659
         * initialize the SAX2 namespaces stack
 
13660
         */
 
13661
        cur = node;
 
13662
        while ((cur != NULL) && (cur->type == XML_ELEMENT_NODE)) {
 
13663
            xmlNsPtr ns = cur->nsDef;
 
13664
            const xmlChar *iprefix, *ihref;
 
13665
 
 
13666
            while (ns != NULL) {
 
13667
                if (ctxt->dict) {
 
13668
                    iprefix = xmlDictLookup(ctxt->dict, ns->prefix, -1);
 
13669
                    ihref = xmlDictLookup(ctxt->dict, ns->href, -1);
 
13670
                } else {
 
13671
                    iprefix = ns->prefix;
 
13672
                    ihref = ns->href;
 
13673
                }
 
13674
 
 
13675
                if (xmlGetNamespace(ctxt, iprefix) == NULL) {
 
13676
                    nsPush(ctxt, iprefix, ihref);
 
13677
                    nsnr++;
 
13678
                }
 
13679
                ns = ns->next;
 
13680
            }
 
13681
            cur = cur->parent;
 
13682
        }
 
13683
        ctxt->instate = XML_PARSER_CONTENT;
 
13684
    }
 
13685
 
 
13686
    if ((ctxt->validate) || (ctxt->replaceEntities != 0)) {
 
13687
        /*
 
13688
         * ID/IDREF registration will be done in xmlValidateElement below
 
13689
         */
 
13690
        ctxt->loadsubset |= XML_SKIP_IDS;
 
13691
    }
 
13692
 
 
13693
#ifdef LIBXML_HTML_ENABLED
 
13694
    if (doc->type == XML_HTML_DOCUMENT_NODE)
 
13695
        __htmlParseContent(ctxt);
 
13696
    else
 
13697
#endif
 
13698
        xmlParseContent(ctxt);
 
13699
 
 
13700
    nsPop(ctxt, nsnr);
 
13701
    if ((RAW == '<') && (NXT(1) == '/')) {
 
13702
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
13703
    } else if (RAW != 0) {
 
13704
        xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
 
13705
    }
 
13706
    if ((ctxt->node != NULL) && (ctxt->node != node)) {
 
13707
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
13708
        ctxt->wellFormed = 0;
 
13709
    }
 
13710
 
 
13711
    if (!ctxt->wellFormed) {
 
13712
        if (ctxt->errNo == 0)
 
13713
            ret = XML_ERR_INTERNAL_ERROR;
 
13714
        else
 
13715
            ret = (xmlParserErrors)ctxt->errNo;
 
13716
    } else {
 
13717
        ret = XML_ERR_OK;
 
13718
    }
 
13719
 
 
13720
    /*
 
13721
     * Return the newly created nodeset after unlinking it from
 
13722
     * the pseudo sibling.
 
13723
     */
 
13724
 
 
13725
    cur = fake->next;
 
13726
    fake->next = NULL;
 
13727
    node->last = fake;
 
13728
 
 
13729
    if (cur != NULL) {
 
13730
        cur->prev = NULL;
 
13731
    }
 
13732
 
 
13733
    *lst = cur;
 
13734
 
 
13735
    while (cur != NULL) {
 
13736
        cur->parent = NULL;
 
13737
        cur = cur->next;
 
13738
    }
 
13739
 
 
13740
    xmlUnlinkNode(fake);
 
13741
    xmlFreeNode(fake);
 
13742
 
 
13743
 
 
13744
    if (ret != XML_ERR_OK) {
 
13745
        xmlFreeNodeList(*lst);
 
13746
        *lst = NULL;
 
13747
    }
 
13748
 
 
13749
    if (doc->dict != NULL)
 
13750
        ctxt->dict = NULL;
 
13751
    xmlFreeParserCtxt(ctxt);
 
13752
 
 
13753
    return(ret);
 
13754
#else /* !SAX2 */
 
13755
    return(XML_ERR_INTERNAL_ERROR);
 
13756
#endif
 
13757
}
 
13758
 
 
13759
#ifdef LIBXML_SAX1_ENABLED
 
13760
/**
 
13761
 * xmlParseBalancedChunkMemoryRecover:
 
13762
 * @doc:  the document the chunk pertains to
 
13763
 * @sax:  the SAX handler bloc (possibly NULL)
 
13764
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
 
13765
 * @depth:  Used for loop detection, use 0
 
13766
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
 
13767
 * @lst:  the return value for the set of parsed nodes
 
13768
 * @recover: return nodes even if the data is broken (use 0)
 
13769
 *
 
13770
 *
 
13771
 * Parse a well-balanced chunk of an XML document
 
13772
 * called by the parser
 
13773
 * The allowed sequence for the Well Balanced Chunk is the one defined by
 
13774
 * the content production in the XML grammar:
 
13775
 *
 
13776
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
 
13777
 *
 
13778
 * Returns 0 if the chunk is well balanced, -1 in case of args problem and
 
13779
 *    the parser error code otherwise
 
13780
 *
 
13781
 * In case recover is set to 1, the nodelist will not be empty even if
 
13782
 * the parsed chunk is not well balanced, assuming the parsing succeeded to
 
13783
 * some extent.
 
13784
 */
 
13785
int
 
13786
xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
 
13787
     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst,
 
13788
     int recover) {
 
13789
    xmlParserCtxtPtr ctxt;
 
13790
    xmlDocPtr newDoc;
 
13791
    xmlSAXHandlerPtr oldsax = NULL;
 
13792
    xmlNodePtr content, newRoot;
 
13793
    int size;
 
13794
    int ret = 0;
 
13795
 
 
13796
    if (depth > 40) {
 
13797
        return(XML_ERR_ENTITY_LOOP);
 
13798
    }
 
13799
 
 
13800
 
 
13801
    if (lst != NULL)
 
13802
        *lst = NULL;
 
13803
    if (string == NULL)
 
13804
        return(-1);
 
13805
 
 
13806
    size = xmlStrlen(string);
 
13807
 
 
13808
    ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
 
13809
    if (ctxt == NULL) return(-1);
 
13810
    ctxt->userData = ctxt;
 
13811
    if (sax != NULL) {
 
13812
        oldsax = ctxt->sax;
 
13813
        ctxt->sax = sax;
 
13814
        if (user_data != NULL)
 
13815
            ctxt->userData = user_data;
 
13816
    }
 
13817
    newDoc = xmlNewDoc(BAD_CAST "1.0");
 
13818
    if (newDoc == NULL) {
 
13819
        xmlFreeParserCtxt(ctxt);
 
13820
        return(-1);
 
13821
    }
 
13822
    newDoc->properties = XML_DOC_INTERNAL;
 
13823
    if ((doc != NULL) && (doc->dict != NULL)) {
 
13824
        xmlDictFree(ctxt->dict);
 
13825
        ctxt->dict = doc->dict;
 
13826
        xmlDictReference(ctxt->dict);
 
13827
        ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
 
13828
        ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
 
13829
        ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
 
13830
        ctxt->dictNames = 1;
 
13831
    } else {
 
13832
        xmlCtxtUseOptionsInternal(ctxt, XML_PARSE_NODICT, NULL);
 
13833
    }
 
13834
    if (doc != NULL) {
 
13835
        newDoc->intSubset = doc->intSubset;
 
13836
        newDoc->extSubset = doc->extSubset;
 
13837
    }
 
13838
    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
 
13839
    if (newRoot == NULL) {
 
13840
        if (sax != NULL)
 
13841
            ctxt->sax = oldsax;
 
13842
        xmlFreeParserCtxt(ctxt);
 
13843
        newDoc->intSubset = NULL;
 
13844
        newDoc->extSubset = NULL;
 
13845
        xmlFreeDoc(newDoc);
 
13846
        return(-1);
 
13847
    }
 
13848
    xmlAddChild((xmlNodePtr) newDoc, newRoot);
 
13849
    nodePush(ctxt, newRoot);
 
13850
    if (doc == NULL) {
 
13851
        ctxt->myDoc = newDoc;
 
13852
    } else {
 
13853
        ctxt->myDoc = newDoc;
 
13854
        newDoc->children->doc = doc;
 
13855
        /* Ensure that doc has XML spec namespace */
 
13856
        xmlSearchNsByHref(doc, (xmlNodePtr)doc, XML_XML_NAMESPACE);
 
13857
        newDoc->oldNs = doc->oldNs;
 
13858
    }
 
13859
    ctxt->instate = XML_PARSER_CONTENT;
 
13860
    ctxt->depth = depth;
 
13861
 
 
13862
    /*
 
13863
     * Doing validity checking on chunk doesn't make sense
 
13864
     */
 
13865
    ctxt->validate = 0;
 
13866
    ctxt->loadsubset = 0;
 
13867
    xmlDetectSAX2(ctxt);
 
13868
 
 
13869
    if ( doc != NULL ){
 
13870
        content = doc->children;
 
13871
        doc->children = NULL;
 
13872
        xmlParseContent(ctxt);
 
13873
        doc->children = content;
 
13874
    }
 
13875
    else {
 
13876
        xmlParseContent(ctxt);
 
13877
    }
 
13878
    if ((RAW == '<') && (NXT(1) == '/')) {
 
13879
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
13880
    } else if (RAW != 0) {
 
13881
        xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
 
13882
    }
 
13883
    if (ctxt->node != newDoc->children) {
 
13884
        xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
 
13885
    }
 
13886
 
 
13887
    if (!ctxt->wellFormed) {
 
13888
        if (ctxt->errNo == 0)
 
13889
            ret = 1;
 
13890
        else
 
13891
            ret = ctxt->errNo;
 
13892
    } else {
 
13893
      ret = 0;
 
13894
    }
 
13895
 
 
13896
    if ((lst != NULL) && ((ret == 0) || (recover == 1))) {
 
13897
        xmlNodePtr cur;
 
13898
 
 
13899
        /*
 
13900
         * Return the newly created nodeset after unlinking it from
 
13901
         * they pseudo parent.
 
13902
         */
 
13903
        cur = newDoc->children->children;
 
13904
        *lst = cur;
 
13905
        while (cur != NULL) {
 
13906
            xmlSetTreeDoc(cur, doc);
 
13907
            cur->parent = NULL;
 
13908
            cur = cur->next;
 
13909
        }
 
13910
        newDoc->children->children = NULL;
 
13911
    }
 
13912
 
 
13913
    if (sax != NULL)
 
13914
        ctxt->sax = oldsax;
 
13915
    xmlFreeParserCtxt(ctxt);
 
13916
    newDoc->intSubset = NULL;
 
13917
    newDoc->extSubset = NULL;
 
13918
    newDoc->oldNs = NULL;
 
13919
    xmlFreeDoc(newDoc);
 
13920
 
 
13921
    return(ret);
 
13922
}
 
13923
 
 
13924
/**
 
13925
 * xmlSAXParseEntity:
 
13926
 * @sax:  the SAX handler block
 
13927
 * @filename:  the filename
 
13928
 *
 
13929
 * parse an XML external entity out of context and build a tree.
 
13930
 * It use the given SAX function block to handle the parsing callback.
 
13931
 * If sax is NULL, fallback to the default DOM tree building routines.
 
13932
 *
 
13933
 * [78] extParsedEnt ::= TextDecl? content
 
13934
 *
 
13935
 * This correspond to a "Well Balanced" chunk
 
13936
 *
 
13937
 * Returns the resulting document tree
 
13938
 */
 
13939
 
 
13940
xmlDocPtr
 
13941
xmlSAXParseEntity(xmlSAXHandlerPtr sax, const char *filename) {
 
13942
    xmlDocPtr ret;
 
13943
    xmlParserCtxtPtr ctxt;
 
13944
 
 
13945
    ctxt = xmlCreateFileParserCtxt(filename);
 
13946
    if (ctxt == NULL) {
 
13947
        return(NULL);
 
13948
    }
 
13949
    if (sax != NULL) {
 
13950
        if (ctxt->sax != NULL)
 
13951
            xmlFree(ctxt->sax);
 
13952
        ctxt->sax = sax;
 
13953
        ctxt->userData = NULL;
 
13954
    }
 
13955
 
 
13956
    xmlParseExtParsedEnt(ctxt);
 
13957
 
 
13958
    if (ctxt->wellFormed)
 
13959
        ret = ctxt->myDoc;
 
13960
    else {
 
13961
        ret = NULL;
 
13962
        xmlFreeDoc(ctxt->myDoc);
 
13963
        ctxt->myDoc = NULL;
 
13964
    }
 
13965
    if (sax != NULL)
 
13966
        ctxt->sax = NULL;
 
13967
    xmlFreeParserCtxt(ctxt);
 
13968
 
 
13969
    return(ret);
 
13970
}
 
13971
 
 
13972
/**
 
13973
 * xmlParseEntity:
 
13974
 * @filename:  the filename
 
13975
 *
 
13976
 * parse an XML external entity out of context and build a tree.
 
13977
 *
 
13978
 * [78] extParsedEnt ::= TextDecl? content
 
13979
 *
 
13980
 * This correspond to a "Well Balanced" chunk
 
13981
 *
 
13982
 * Returns the resulting document tree
 
13983
 */
 
13984
 
 
13985
xmlDocPtr
 
13986
xmlParseEntity(const char *filename) {
 
13987
    return(xmlSAXParseEntity(NULL, filename));
 
13988
}
 
13989
#endif /* LIBXML_SAX1_ENABLED */
 
13990
 
 
13991
/**
 
13992
 * xmlCreateEntityParserCtxtInternal:
 
13993
 * @URL:  the entity URL
 
13994
 * @ID:  the entity PUBLIC ID
 
13995
 * @base:  a possible base for the target URI
 
13996
 * @pctx:  parser context used to set options on new context
 
13997
 *
 
13998
 * Create a parser context for an external entity
 
13999
 * Automatic support for ZLIB/Compress compressed document is provided
 
14000
 * by default if found at compile-time.
 
14001
 *
 
14002
 * Returns the new parser context or NULL
 
14003
 */
 
14004
static xmlParserCtxtPtr
 
14005
xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
 
14006
                          const xmlChar *base, xmlParserCtxtPtr pctx) {
 
14007
    xmlParserCtxtPtr ctxt;
 
14008
    xmlParserInputPtr inputStream;
 
14009
    char *directory = NULL;
 
14010
    xmlChar *uri;
 
14011
 
 
14012
    ctxt = xmlNewParserCtxt();
 
14013
    if (ctxt == NULL) {
 
14014
        return(NULL);
 
14015
    }
 
14016
 
 
14017
    if (pctx != NULL) {
 
14018
        ctxt->options = pctx->options;
 
14019
        ctxt->_private = pctx->_private;
 
14020
    }
 
14021
 
 
14022
    uri = xmlBuildURI(URL, base);
 
14023
 
 
14024
    if (uri == NULL) {
 
14025
        inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
 
14026
        if (inputStream == NULL) {
 
14027
            xmlFreeParserCtxt(ctxt);
 
14028
            return(NULL);
 
14029
        }
 
14030
 
 
14031
        inputPush(ctxt, inputStream);
 
14032
 
 
14033
        if ((ctxt->directory == NULL) && (directory == NULL))
 
14034
            directory = xmlParserGetDirectory((char *)URL);
 
14035
        if ((ctxt->directory == NULL) && (directory != NULL))
 
14036
            ctxt->directory = directory;
 
14037
    } else {
 
14038
        inputStream = xmlLoadExternalEntity((char *)uri, (char *)ID, ctxt);
 
14039
        if (inputStream == NULL) {
 
14040
            xmlFree(uri);
 
14041
            xmlFreeParserCtxt(ctxt);
 
14042
            return(NULL);
 
14043
        }
 
14044
 
 
14045
        inputPush(ctxt, inputStream);
 
14046
 
 
14047
        if ((ctxt->directory == NULL) && (directory == NULL))
 
14048
            directory = xmlParserGetDirectory((char *)uri);
 
14049
        if ((ctxt->directory == NULL) && (directory != NULL))
 
14050
            ctxt->directory = directory;
 
14051
        xmlFree(uri);
 
14052
    }
 
14053
    return(ctxt);
 
14054
}
 
14055
 
 
14056
/**
 
14057
 * xmlCreateEntityParserCtxt:
 
14058
 * @URL:  the entity URL
 
14059
 * @ID:  the entity PUBLIC ID
 
14060
 * @base:  a possible base for the target URI
 
14061
 *
 
14062
 * Create a parser context for an external entity
 
14063
 * Automatic support for ZLIB/Compress compressed document is provided
 
14064
 * by default if found at compile-time.
 
14065
 *
 
14066
 * Returns the new parser context or NULL
 
14067
 */
 
14068
xmlParserCtxtPtr
 
14069
xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID,
 
14070
                          const xmlChar *base) {
 
14071
    return xmlCreateEntityParserCtxtInternal(URL, ID, base, NULL);
 
14072
 
 
14073
}
 
14074
 
 
14075
/************************************************************************
 
14076
 *                                                                      *
 
14077
 *              Front ends when parsing from a file                     *
 
14078
 *                                                                      *
 
14079
 ************************************************************************/
 
14080
 
 
14081
/**
 
14082
 * xmlCreateURLParserCtxt:
 
14083
 * @filename:  the filename or URL
 
14084
 * @options:  a combination of xmlParserOption
 
14085
 *
 
14086
 * Create a parser context for a file or URL content.
 
14087
 * Automatic support for ZLIB/Compress compressed document is provided
 
14088
 * by default if found at compile-time and for file accesses
 
14089
 *
 
14090
 * Returns the new parser context or NULL
 
14091
 */
 
14092
xmlParserCtxtPtr
 
14093
xmlCreateURLParserCtxt(const char *filename, int options)
 
14094
{
 
14095
    xmlParserCtxtPtr ctxt;
 
14096
    xmlParserInputPtr inputStream;
 
14097
    char *directory = NULL;
 
14098
 
 
14099
    ctxt = xmlNewParserCtxt();
 
14100
    if (ctxt == NULL) {
 
14101
        xmlErrMemory(NULL, "cannot allocate parser context");
 
14102
        return(NULL);
 
14103
    }
 
14104
 
 
14105
    if (options)
 
14106
        xmlCtxtUseOptionsInternal(ctxt, options, NULL);
 
14107
    ctxt->linenumbers = 1;
 
14108
 
 
14109
    inputStream = xmlLoadExternalEntity(filename, NULL, ctxt);
 
14110
    if (inputStream == NULL) {
 
14111
        xmlFreeParserCtxt(ctxt);
 
14112
        return(NULL);
 
14113
    }
 
14114
 
 
14115
    inputPush(ctxt, inputStream);
 
14116
    if ((ctxt->directory == NULL) && (directory == NULL))
 
14117
        directory = xmlParserGetDirectory(filename);
 
14118
    if ((ctxt->directory == NULL) && (directory != NULL))
 
14119
        ctxt->directory = directory;
 
14120
 
 
14121
    return(ctxt);
 
14122
}
 
14123
 
 
14124
/**
 
14125
 * xmlCreateFileParserCtxt:
 
14126
 * @filename:  the filename
 
14127
 *
 
14128
 * Create a parser context for a file content.
 
14129
 * Automatic support for ZLIB/Compress compressed document is provided
 
14130
 * by default if found at compile-time.
 
14131
 *
 
14132
 * Returns the new parser context or NULL
 
14133
 */
 
14134
xmlParserCtxtPtr
 
14135
xmlCreateFileParserCtxt(const char *filename)
 
14136
{
 
14137
    return(xmlCreateURLParserCtxt(filename, 0));
 
14138
}
 
14139
 
 
14140
#ifdef LIBXML_SAX1_ENABLED
 
14141
/**
 
14142
 * xmlSAXParseFileWithData:
 
14143
 * @sax:  the SAX handler block
 
14144
 * @filename:  the filename
 
14145
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
 
14146
 *             documents
 
14147
 * @data:  the userdata
 
14148
 *
 
14149
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
 
14150
 * compressed document is provided by default if found at compile-time.
 
14151
 * It use the given SAX function block to handle the parsing callback.
 
14152
 * If sax is NULL, fallback to the default DOM tree building routines.
 
14153
 *
 
14154
 * User data (void *) is stored within the parser context in the
 
14155
 * context's _private member, so it is available nearly everywhere in libxml
 
14156
 *
 
14157
 * Returns the resulting document tree
 
14158
 */
 
14159
 
 
14160
xmlDocPtr
 
14161
xmlSAXParseFileWithData(xmlSAXHandlerPtr sax, const char *filename,
 
14162
                        int recovery, void *data) {
 
14163
    xmlDocPtr ret;
 
14164
    xmlParserCtxtPtr ctxt;
 
14165
 
 
14166
    xmlInitParser();
 
14167
 
 
14168
    ctxt = xmlCreateFileParserCtxt(filename);
 
14169
    if (ctxt == NULL) {
 
14170
        return(NULL);
 
14171
    }
 
14172
    if (sax != NULL) {
 
14173
        if (ctxt->sax != NULL)
 
14174
            xmlFree(ctxt->sax);
 
14175
        ctxt->sax = sax;
 
14176
    }
 
14177
    xmlDetectSAX2(ctxt);
 
14178
    if (data!=NULL) {
 
14179
        ctxt->_private = data;
 
14180
    }
 
14181
 
 
14182
    if (ctxt->directory == NULL)
 
14183
        ctxt->directory = xmlParserGetDirectory(filename);
 
14184
 
 
14185
    ctxt->recovery = recovery;
 
14186
 
 
14187
    xmlParseDocument(ctxt);
 
14188
 
 
14189
    if ((ctxt->wellFormed) || recovery) {
 
14190
        ret = ctxt->myDoc;
 
14191
        if (ret != NULL) {
 
14192
            if (ctxt->input->buf->compressed > 0)
 
14193
                ret->compression = 9;
 
14194
            else
 
14195
                ret->compression = ctxt->input->buf->compressed;
 
14196
        }
 
14197
    }
 
14198
    else {
 
14199
       ret = NULL;
 
14200
       xmlFreeDoc(ctxt->myDoc);
 
14201
       ctxt->myDoc = NULL;
 
14202
    }
 
14203
    if (sax != NULL)
 
14204
        ctxt->sax = NULL;
 
14205
    xmlFreeParserCtxt(ctxt);
 
14206
 
 
14207
    return(ret);
 
14208
}
 
14209
 
 
14210
/**
 
14211
 * xmlSAXParseFile:
 
14212
 * @sax:  the SAX handler block
 
14213
 * @filename:  the filename
 
14214
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
 
14215
 *             documents
 
14216
 *
 
14217
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
 
14218
 * compressed document is provided by default if found at compile-time.
 
14219
 * It use the given SAX function block to handle the parsing callback.
 
14220
 * If sax is NULL, fallback to the default DOM tree building routines.
 
14221
 *
 
14222
 * Returns the resulting document tree
 
14223
 */
 
14224
 
 
14225
xmlDocPtr
 
14226
xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
 
14227
                          int recovery) {
 
14228
    return(xmlSAXParseFileWithData(sax,filename,recovery,NULL));
 
14229
}
 
14230
 
 
14231
/**
 
14232
 * xmlRecoverDoc:
 
14233
 * @cur:  a pointer to an array of xmlChar
 
14234
 *
 
14235
 * parse an XML in-memory document and build a tree.
 
14236
 * In the case the document is not Well Formed, a attempt to build a
 
14237
 * tree is tried anyway
 
14238
 *
 
14239
 * Returns the resulting document tree or NULL in case of failure
 
14240
 */
 
14241
 
 
14242
xmlDocPtr
 
14243
xmlRecoverDoc(const xmlChar *cur) {
 
14244
    return(xmlSAXParseDoc(NULL, cur, 1));
 
14245
}
 
14246
 
 
14247
/**
 
14248
 * xmlParseFile:
 
14249
 * @filename:  the filename
 
14250
 *
 
14251
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
 
14252
 * compressed document is provided by default if found at compile-time.
 
14253
 *
 
14254
 * Returns the resulting document tree if the file was wellformed,
 
14255
 * NULL otherwise.
 
14256
 */
 
14257
 
 
14258
xmlDocPtr
 
14259
xmlParseFile(const char *filename) {
 
14260
    return(xmlSAXParseFile(NULL, filename, 0));
 
14261
}
 
14262
 
 
14263
/**
 
14264
 * xmlRecoverFile:
 
14265
 * @filename:  the filename
 
14266
 *
 
14267
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
 
14268
 * compressed document is provided by default if found at compile-time.
 
14269
 * In the case the document is not Well Formed, it attempts to build
 
14270
 * a tree anyway
 
14271
 *
 
14272
 * Returns the resulting document tree or NULL in case of failure
 
14273
 */
 
14274
 
 
14275
xmlDocPtr
 
14276
xmlRecoverFile(const char *filename) {
 
14277
    return(xmlSAXParseFile(NULL, filename, 1));
 
14278
}
 
14279
 
 
14280
 
 
14281
/**
 
14282
 * xmlSetupParserForBuffer:
 
14283
 * @ctxt:  an XML parser context
 
14284
 * @buffer:  a xmlChar * buffer
 
14285
 * @filename:  a file name
 
14286
 *
 
14287
 * Setup the parser context to parse a new buffer; Clears any prior
 
14288
 * contents from the parser context. The buffer parameter must not be
 
14289
 * NULL, but the filename parameter can be
 
14290
 */
 
14291
void
 
14292
xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
 
14293
                             const char* filename)
 
14294
{
 
14295
    xmlParserInputPtr input;
 
14296
 
 
14297
    if ((ctxt == NULL) || (buffer == NULL))
 
14298
        return;
 
14299
 
 
14300
    input = xmlNewInputStream(ctxt);
 
14301
    if (input == NULL) {
 
14302
        xmlErrMemory(NULL, "parsing new buffer: out of memory\n");
 
14303
        xmlClearParserCtxt(ctxt);
 
14304
        return;
 
14305
    }
 
14306
 
 
14307
    xmlClearParserCtxt(ctxt);
 
14308
    if (filename != NULL)
 
14309
        input->filename = (char *) xmlCanonicPath((const xmlChar *)filename);
 
14310
    input->base = buffer;
 
14311
    input->cur = buffer;
 
14312
    input->end = &buffer[xmlStrlen(buffer)];
 
14313
    inputPush(ctxt, input);
 
14314
}
 
14315
 
 
14316
/**
 
14317
 * xmlSAXUserParseFile:
 
14318
 * @sax:  a SAX handler
 
14319
 * @user_data:  The user data returned on SAX callbacks
 
14320
 * @filename:  a file name
 
14321
 *
 
14322
 * parse an XML file and call the given SAX handler routines.
 
14323
 * Automatic support for ZLIB/Compress compressed document is provided
 
14324
 *
 
14325
 * Returns 0 in case of success or a error number otherwise
 
14326
 */
 
14327
int
 
14328
xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
 
14329
                    const char *filename) {
 
14330
    int ret = 0;
 
14331
    xmlParserCtxtPtr ctxt;
 
14332
 
 
14333
    ctxt = xmlCreateFileParserCtxt(filename);
 
14334
    if (ctxt == NULL) return -1;
 
14335
    if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
 
14336
        xmlFree(ctxt->sax);
 
14337
    ctxt->sax = sax;
 
14338
    xmlDetectSAX2(ctxt);
 
14339
 
 
14340
    if (user_data != NULL)
 
14341
        ctxt->userData = user_data;
 
14342
 
 
14343
    xmlParseDocument(ctxt);
 
14344
 
 
14345
    if (ctxt->wellFormed)
 
14346
        ret = 0;
 
14347
    else {
 
14348
        if (ctxt->errNo != 0)
 
14349
            ret = ctxt->errNo;
 
14350
        else
 
14351
            ret = -1;
 
14352
    }
 
14353
    if (sax != NULL)
 
14354
        ctxt->sax = NULL;
 
14355
    if (ctxt->myDoc != NULL) {
 
14356
        xmlFreeDoc(ctxt->myDoc);
 
14357
        ctxt->myDoc = NULL;
 
14358
    }
 
14359
    xmlFreeParserCtxt(ctxt);
 
14360
 
 
14361
    return ret;
 
14362
}
 
14363
#endif /* LIBXML_SAX1_ENABLED */
 
14364
 
 
14365
/************************************************************************
 
14366
 *                                                                      *
 
14367
 *              Front ends when parsing from memory                     *
 
14368
 *                                                                      *
 
14369
 ************************************************************************/
 
14370
 
 
14371
/**
 
14372
 * xmlCreateMemoryParserCtxt:
 
14373
 * @buffer:  a pointer to a char array
 
14374
 * @size:  the size of the array
 
14375
 *
 
14376
 * Create a parser context for an XML in-memory document.
 
14377
 *
 
14378
 * Returns the new parser context or NULL
 
14379
 */
 
14380
xmlParserCtxtPtr
 
14381
xmlCreateMemoryParserCtxt(const char *buffer, int size) {
 
14382
    xmlParserCtxtPtr ctxt;
 
14383
    xmlParserInputPtr input;
 
14384
    xmlParserInputBufferPtr buf;
 
14385
 
 
14386
    if (buffer == NULL)
 
14387
        return(NULL);
 
14388
    if (size <= 0)
 
14389
        return(NULL);
 
14390
 
 
14391
    ctxt = xmlNewParserCtxt();
 
14392
    if (ctxt == NULL)
 
14393
        return(NULL);
 
14394
 
 
14395
    /* TODO: xmlParserInputBufferCreateStatic, requires some serious changes */
 
14396
    buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
 
14397
    if (buf == NULL) {
 
14398
        xmlFreeParserCtxt(ctxt);
 
14399
        return(NULL);
 
14400
    }
 
14401
 
 
14402
    input = xmlNewInputStream(ctxt);
 
14403
    if (input == NULL) {
 
14404
        xmlFreeParserInputBuffer(buf);
 
14405
        xmlFreeParserCtxt(ctxt);
 
14406
        return(NULL);
 
14407
    }
 
14408
 
 
14409
    input->filename = NULL;
 
14410
    input->buf = buf;
 
14411
    xmlBufResetInput(input->buf->buffer, input);
 
14412
 
 
14413
    inputPush(ctxt, input);
 
14414
    return(ctxt);
 
14415
}
 
14416
 
 
14417
#ifdef LIBXML_SAX1_ENABLED
 
14418
/**
 
14419
 * xmlSAXParseMemoryWithData:
 
14420
 * @sax:  the SAX handler block
 
14421
 * @buffer:  an pointer to a char array
 
14422
 * @size:  the size of the array
 
14423
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
 
14424
 *             documents
 
14425
 * @data:  the userdata
 
14426
 *
 
14427
 * parse an XML in-memory block and use the given SAX function block
 
14428
 * to handle the parsing callback. If sax is NULL, fallback to the default
 
14429
 * DOM tree building routines.
 
14430
 *
 
14431
 * User data (void *) is stored within the parser context in the
 
14432
 * context's _private member, so it is available nearly everywhere in libxml
 
14433
 *
 
14434
 * Returns the resulting document tree
 
14435
 */
 
14436
 
 
14437
xmlDocPtr
 
14438
xmlSAXParseMemoryWithData(xmlSAXHandlerPtr sax, const char *buffer,
 
14439
                  int size, int recovery, void *data) {
 
14440
    xmlDocPtr ret;
 
14441
    xmlParserCtxtPtr ctxt;
 
14442
 
 
14443
    xmlInitParser();
 
14444
 
 
14445
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
 
14446
    if (ctxt == NULL) return(NULL);
 
14447
    if (sax != NULL) {
 
14448
        if (ctxt->sax != NULL)
 
14449
            xmlFree(ctxt->sax);
 
14450
        ctxt->sax = sax;
 
14451
    }
 
14452
    xmlDetectSAX2(ctxt);
 
14453
    if (data!=NULL) {
 
14454
        ctxt->_private=data;
 
14455
    }
 
14456
 
 
14457
    ctxt->recovery = recovery;
 
14458
 
 
14459
    xmlParseDocument(ctxt);
 
14460
 
 
14461
    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
 
14462
    else {
 
14463
       ret = NULL;
 
14464
       xmlFreeDoc(ctxt->myDoc);
 
14465
       ctxt->myDoc = NULL;
 
14466
    }
 
14467
    if (sax != NULL)
 
14468
        ctxt->sax = NULL;
 
14469
    xmlFreeParserCtxt(ctxt);
 
14470
 
 
14471
    return(ret);
 
14472
}
 
14473
 
 
14474
/**
 
14475
 * xmlSAXParseMemory:
 
14476
 * @sax:  the SAX handler block
 
14477
 * @buffer:  an pointer to a char array
 
14478
 * @size:  the size of the array
 
14479
 * @recovery:  work in recovery mode, i.e. tries to read not Well Formed
 
14480
 *             documents
 
14481
 *
 
14482
 * parse an XML in-memory block and use the given SAX function block
 
14483
 * to handle the parsing callback. If sax is NULL, fallback to the default
 
14484
 * DOM tree building routines.
 
14485
 *
 
14486
 * Returns the resulting document tree
 
14487
 */
 
14488
xmlDocPtr
 
14489
xmlSAXParseMemory(xmlSAXHandlerPtr sax, const char *buffer,
 
14490
                  int size, int recovery) {
 
14491
    return xmlSAXParseMemoryWithData(sax, buffer, size, recovery, NULL);
 
14492
}
 
14493
 
 
14494
/**
 
14495
 * xmlParseMemory:
 
14496
 * @buffer:  an pointer to a char array
 
14497
 * @size:  the size of the array
 
14498
 *
 
14499
 * parse an XML in-memory block and build a tree.
 
14500
 *
 
14501
 * Returns the resulting document tree
 
14502
 */
 
14503
 
 
14504
xmlDocPtr xmlParseMemory(const char *buffer, int size) {
 
14505
   return(xmlSAXParseMemory(NULL, buffer, size, 0));
 
14506
}
 
14507
 
 
14508
/**
 
14509
 * xmlRecoverMemory:
 
14510
 * @buffer:  an pointer to a char array
 
14511
 * @size:  the size of the array
 
14512
 *
 
14513
 * parse an XML in-memory block and build a tree.
 
14514
 * In the case the document is not Well Formed, an attempt to
 
14515
 * build a tree is tried anyway
 
14516
 *
 
14517
 * Returns the resulting document tree or NULL in case of error
 
14518
 */
 
14519
 
 
14520
xmlDocPtr xmlRecoverMemory(const char *buffer, int size) {
 
14521
   return(xmlSAXParseMemory(NULL, buffer, size, 1));
 
14522
}
 
14523
 
 
14524
/**
 
14525
 * xmlSAXUserParseMemory:
 
14526
 * @sax:  a SAX handler
 
14527
 * @user_data:  The user data returned on SAX callbacks
 
14528
 * @buffer:  an in-memory XML document input
 
14529
 * @size:  the length of the XML document in bytes
 
14530
 *
 
14531
 * A better SAX parsing routine.
 
14532
 * parse an XML in-memory buffer and call the given SAX handler routines.
 
14533
 *
 
14534
 * Returns 0 in case of success or a error number otherwise
 
14535
 */
 
14536
int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
 
14537
                          const char *buffer, int size) {
 
14538
    int ret = 0;
 
14539
    xmlParserCtxtPtr ctxt;
 
14540
 
 
14541
    xmlInitParser();
 
14542
 
 
14543
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
 
14544
    if (ctxt == NULL) return -1;
 
14545
    if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
 
14546
        xmlFree(ctxt->sax);
 
14547
    ctxt->sax = sax;
 
14548
    xmlDetectSAX2(ctxt);
 
14549
 
 
14550
    if (user_data != NULL)
 
14551
        ctxt->userData = user_data;
 
14552
 
 
14553
    xmlParseDocument(ctxt);
 
14554
 
 
14555
    if (ctxt->wellFormed)
 
14556
        ret = 0;
 
14557
    else {
 
14558
        if (ctxt->errNo != 0)
 
14559
            ret = ctxt->errNo;
 
14560
        else
 
14561
            ret = -1;
 
14562
    }
 
14563
    if (sax != NULL)
 
14564
        ctxt->sax = NULL;
 
14565
    if (ctxt->myDoc != NULL) {
 
14566
        xmlFreeDoc(ctxt->myDoc);
 
14567
        ctxt->myDoc = NULL;
 
14568
    }
 
14569
    xmlFreeParserCtxt(ctxt);
 
14570
 
 
14571
    return ret;
 
14572
}
 
14573
#endif /* LIBXML_SAX1_ENABLED */
 
14574
 
 
14575
/**
 
14576
 * xmlCreateDocParserCtxt:
 
14577
 * @cur:  a pointer to an array of xmlChar
 
14578
 *
 
14579
 * Creates a parser context for an XML in-memory document.
 
14580
 *
 
14581
 * Returns the new parser context or NULL
 
14582
 */
 
14583
xmlParserCtxtPtr
 
14584
xmlCreateDocParserCtxt(const xmlChar *cur) {
 
14585
    int len;
 
14586
 
 
14587
    if (cur == NULL)
 
14588
        return(NULL);
 
14589
    len = xmlStrlen(cur);
 
14590
    return(xmlCreateMemoryParserCtxt((const char *)cur, len));
 
14591
}
 
14592
 
 
14593
#ifdef LIBXML_SAX1_ENABLED
 
14594
/**
 
14595
 * xmlSAXParseDoc:
 
14596
 * @sax:  the SAX handler block
 
14597
 * @cur:  a pointer to an array of xmlChar
 
14598
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
 
14599
 *             documents
 
14600
 *
 
14601
 * parse an XML in-memory document and build a tree.
 
14602
 * It use the given SAX function block to handle the parsing callback.
 
14603
 * If sax is NULL, fallback to the default DOM tree building routines.
 
14604
 *
 
14605
 * Returns the resulting document tree
 
14606
 */
 
14607
 
 
14608
xmlDocPtr
 
14609
xmlSAXParseDoc(xmlSAXHandlerPtr sax, const xmlChar *cur, int recovery) {
 
14610
    xmlDocPtr ret;
 
14611
    xmlParserCtxtPtr ctxt;
 
14612
    xmlSAXHandlerPtr oldsax = NULL;
 
14613
 
 
14614
    if (cur == NULL) return(NULL);
 
14615
 
 
14616
 
 
14617
    ctxt = xmlCreateDocParserCtxt(cur);
 
14618
    if (ctxt == NULL) return(NULL);
 
14619
    if (sax != NULL) {
 
14620
        oldsax = ctxt->sax;
 
14621
        ctxt->sax = sax;
 
14622
        ctxt->userData = NULL;
 
14623
    }
 
14624
    xmlDetectSAX2(ctxt);
 
14625
 
 
14626
    xmlParseDocument(ctxt);
 
14627
    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
 
14628
    else {
 
14629
       ret = NULL;
 
14630
       xmlFreeDoc(ctxt->myDoc);
 
14631
       ctxt->myDoc = NULL;
 
14632
    }
 
14633
    if (sax != NULL)
 
14634
        ctxt->sax = oldsax;
 
14635
    xmlFreeParserCtxt(ctxt);
 
14636
 
 
14637
    return(ret);
 
14638
}
 
14639
 
 
14640
/**
 
14641
 * xmlParseDoc:
 
14642
 * @cur:  a pointer to an array of xmlChar
 
14643
 *
 
14644
 * parse an XML in-memory document and build a tree.
 
14645
 *
 
14646
 * Returns the resulting document tree
 
14647
 */
 
14648
 
 
14649
xmlDocPtr
 
14650
xmlParseDoc(const xmlChar *cur) {
 
14651
    return(xmlSAXParseDoc(NULL, cur, 0));
 
14652
}
 
14653
#endif /* LIBXML_SAX1_ENABLED */
 
14654
 
 
14655
#ifdef LIBXML_LEGACY_ENABLED
 
14656
/************************************************************************
 
14657
 *                                                                      *
 
14658
 *      Specific function to keep track of entities references          *
 
14659
 *      and used by the XSLT debugger                                   *
 
14660
 *                                                                      *
 
14661
 ************************************************************************/
 
14662
 
 
14663
static xmlEntityReferenceFunc xmlEntityRefFunc = NULL;
 
14664
 
 
14665
/**
 
14666
 * xmlAddEntityReference:
 
14667
 * @ent : A valid entity
 
14668
 * @firstNode : A valid first node for children of entity
 
14669
 * @lastNode : A valid last node of children entity
 
14670
 *
 
14671
 * Notify of a reference to an entity of type XML_EXTERNAL_GENERAL_PARSED_ENTITY
 
14672
 */
 
14673
static void
 
14674
xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
 
14675
                      xmlNodePtr lastNode)
 
14676
{
 
14677
    if (xmlEntityRefFunc != NULL) {
 
14678
        (*xmlEntityRefFunc) (ent, firstNode, lastNode);
 
14679
    }
 
14680
}
 
14681
 
 
14682
 
 
14683
/**
 
14684
 * xmlSetEntityReferenceFunc:
 
14685
 * @func: A valid function
 
14686
 *
 
14687
 * Set the function to call call back when a xml reference has been made
 
14688
 */
 
14689
void
 
14690
xmlSetEntityReferenceFunc(xmlEntityReferenceFunc func)
 
14691
{
 
14692
    xmlEntityRefFunc = func;
 
14693
}
 
14694
#endif /* LIBXML_LEGACY_ENABLED */
 
14695
 
 
14696
/************************************************************************
 
14697
 *                                                                      *
 
14698
 *                              Miscellaneous                           *
 
14699
 *                                                                      *
 
14700
 ************************************************************************/
 
14701
 
 
14702
#ifdef LIBXML_XPATH_ENABLED
 
14703
#include <libxml/xpath.h>
 
14704
#endif
 
14705
 
 
14706
extern void XMLCDECL xmlGenericErrorDefaultFunc(void *ctx, const char *msg, ...);
 
14707
static int xmlParserInitialized = 0;
 
14708
 
 
14709
/**
 
14710
 * xmlInitParser:
 
14711
 *
 
14712
 * Initialization function for the XML parser.
 
14713
 * This is not reentrant. Call once before processing in case of
 
14714
 * use in multithreaded programs.
 
14715
 */
 
14716
 
 
14717
void
 
14718
xmlInitParser(void) {
 
14719
    if (xmlParserInitialized != 0)
 
14720
        return;
 
14721
 
 
14722
#ifdef LIBXML_THREAD_ENABLED
 
14723
    __xmlGlobalInitMutexLock();
 
14724
    if (xmlParserInitialized == 0) {
 
14725
#endif
 
14726
        xmlInitThreads();
 
14727
        xmlInitGlobals();
 
14728
        if ((xmlGenericError == xmlGenericErrorDefaultFunc) ||
 
14729
            (xmlGenericError == NULL))
 
14730
            initGenericErrorDefaultFunc(NULL);
 
14731
        xmlInitMemory();
 
14732
        xmlInitializeDict();
 
14733
        xmlInitCharEncodingHandlers();
 
14734
        xmlDefaultSAXHandlerInit();
 
14735
        xmlRegisterDefaultInputCallbacks();
 
14736
#ifdef LIBXML_OUTPUT_ENABLED
 
14737
        xmlRegisterDefaultOutputCallbacks();
 
14738
#endif /* LIBXML_OUTPUT_ENABLED */
 
14739
#ifdef LIBXML_HTML_ENABLED
 
14740
        htmlInitAutoClose();
 
14741
        htmlDefaultSAXHandlerInit();
 
14742
#endif
 
14743
#ifdef LIBXML_XPATH_ENABLED
 
14744
        xmlXPathInit();
 
14745
#endif
 
14746
        xmlParserInitialized = 1;
 
14747
#ifdef LIBXML_THREAD_ENABLED
 
14748
    }
 
14749
    __xmlGlobalInitMutexUnlock();
 
14750
#endif
 
14751
}
 
14752
 
 
14753
/**
 
14754
 * xmlCleanupParser:
 
14755
 *
 
14756
 * This function name is somewhat misleading. It does not clean up
 
14757
 * parser state, it cleans up memory allocated by the library itself.
 
14758
 * It is a cleanup function for the XML library. It tries to reclaim all
 
14759
 * related global memory allocated for the library processing.
 
14760
 * It doesn't deallocate any document related memory. One should
 
14761
 * call xmlCleanupParser() only when the process has finished using
 
14762
 * the library and all XML/HTML documents built with it.
 
14763
 * See also xmlInitParser() which has the opposite function of preparing
 
14764
 * the library for operations.
 
14765
 *
 
14766
 * WARNING: if your application is multithreaded or has plugin support
 
14767
 *          calling this may crash the application if another thread or
 
14768
 *          a plugin is still using libxml2. It's sometimes very hard to
 
14769
 *          guess if libxml2 is in use in the application, some libraries
 
14770
 *          or plugins may use it without notice. In case of doubt abstain
 
14771
 *          from calling this function or do it just before calling exit()
 
14772
 *          to avoid leak reports from valgrind !
 
14773
 */
 
14774
 
 
14775
void
 
14776
xmlCleanupParser(void) {
 
14777
    if (!xmlParserInitialized)
 
14778
        return;
 
14779
 
 
14780
    xmlCleanupCharEncodingHandlers();
 
14781
#ifdef LIBXML_CATALOG_ENABLED
 
14782
    xmlCatalogCleanup();
 
14783
#endif
 
14784
    xmlDictCleanup();
 
14785
    xmlCleanupInputCallbacks();
 
14786
#ifdef LIBXML_OUTPUT_ENABLED
 
14787
    xmlCleanupOutputCallbacks();
 
14788
#endif
 
14789
#ifdef LIBXML_SCHEMAS_ENABLED
 
14790
    xmlSchemaCleanupTypes();
 
14791
    xmlRelaxNGCleanupTypes();
 
14792
#endif
 
14793
    xmlResetLastError();
 
14794
    xmlCleanupGlobals();
 
14795
    xmlCleanupThreads(); /* must be last if called not from the main thread */
 
14796
    xmlCleanupMemory();
 
14797
    xmlParserInitialized = 0;
 
14798
}
 
14799
 
 
14800
/************************************************************************
 
14801
 *                                                                      *
 
14802
 *      New set (2.6.0) of simpler and more flexible APIs               *
 
14803
 *                                                                      *
 
14804
 ************************************************************************/
 
14805
 
 
14806
/**
 
14807
 * DICT_FREE:
 
14808
 * @str:  a string
 
14809
 *
 
14810
 * Free a string if it is not owned by the "dict" dictionnary in the
 
14811
 * current scope
 
14812
 */
 
14813
#define DICT_FREE(str)                                          \
 
14814
        if ((str) && ((!dict) ||                                \
 
14815
            (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))  \
 
14816
            xmlFree((char *)(str));
 
14817
 
 
14818
/**
 
14819
 * xmlCtxtReset:
 
14820
 * @ctxt: an XML parser context
 
14821
 *
 
14822
 * Reset a parser context
 
14823
 */
 
14824
void
 
14825
xmlCtxtReset(xmlParserCtxtPtr ctxt)
 
14826
{
 
14827
    xmlParserInputPtr input;
 
14828
    xmlDictPtr dict;
 
14829
 
 
14830
    if (ctxt == NULL)
 
14831
        return;
 
14832
 
 
14833
    dict = ctxt->dict;
 
14834
 
 
14835
    while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
 
14836
        xmlFreeInputStream(input);
 
14837
    }
 
14838
    ctxt->inputNr = 0;
 
14839
    ctxt->input = NULL;
 
14840
 
 
14841
    ctxt->spaceNr = 0;
 
14842
    if (ctxt->spaceTab != NULL) {
 
14843
        ctxt->spaceTab[0] = -1;
 
14844
        ctxt->space = &ctxt->spaceTab[0];
 
14845
    } else {
 
14846
        ctxt->space = NULL;
 
14847
    }
 
14848
 
 
14849
 
 
14850
    ctxt->nodeNr = 0;
 
14851
    ctxt->node = NULL;
 
14852
 
 
14853
    ctxt->nameNr = 0;
 
14854
    ctxt->name = NULL;
 
14855
 
 
14856
    DICT_FREE(ctxt->version);
 
14857
    ctxt->version = NULL;
 
14858
    DICT_FREE(ctxt->encoding);
 
14859
    ctxt->encoding = NULL;
 
14860
    DICT_FREE(ctxt->directory);
 
14861
    ctxt->directory = NULL;
 
14862
    DICT_FREE(ctxt->extSubURI);
 
14863
    ctxt->extSubURI = NULL;
 
14864
    DICT_FREE(ctxt->extSubSystem);
 
14865
    ctxt->extSubSystem = NULL;
 
14866
    if (ctxt->myDoc != NULL)
 
14867
        xmlFreeDoc(ctxt->myDoc);
 
14868
    ctxt->myDoc = NULL;
 
14869
 
 
14870
    ctxt->standalone = -1;
 
14871
    ctxt->hasExternalSubset = 0;
 
14872
    ctxt->hasPErefs = 0;
 
14873
    ctxt->html = 0;
 
14874
    ctxt->external = 0;
 
14875
    ctxt->instate = XML_PARSER_START;
 
14876
    ctxt->token = 0;
 
14877
 
 
14878
    ctxt->wellFormed = 1;
 
14879
    ctxt->nsWellFormed = 1;
 
14880
    ctxt->disableSAX = 0;
 
14881
    ctxt->valid = 1;
 
14882
#if 0
 
14883
    ctxt->vctxt.userData = ctxt;
 
14884
    ctxt->vctxt.error = xmlParserValidityError;
 
14885
    ctxt->vctxt.warning = xmlParserValidityWarning;
 
14886
#endif
 
14887
    ctxt->record_info = 0;
 
14888
    ctxt->nbChars = 0;
 
14889
    ctxt->checkIndex = 0;
 
14890
    ctxt->inSubset = 0;
 
14891
    ctxt->errNo = XML_ERR_OK;
 
14892
    ctxt->depth = 0;
 
14893
    ctxt->charset = XML_CHAR_ENCODING_UTF8;
 
14894
    ctxt->catalogs = NULL;
 
14895
    ctxt->nbentities = 0;
 
14896
    ctxt->sizeentities = 0;
 
14897
    ctxt->sizeentcopy = 0;
 
14898
    xmlInitNodeInfoSeq(&ctxt->node_seq);
 
14899
 
 
14900
    if (ctxt->attsDefault != NULL) {
 
14901
        xmlHashFree(ctxt->attsDefault, (xmlHashDeallocator) xmlFree);
 
14902
        ctxt->attsDefault = NULL;
 
14903
    }
 
14904
    if (ctxt->attsSpecial != NULL) {
 
14905
        xmlHashFree(ctxt->attsSpecial, NULL);
 
14906
        ctxt->attsSpecial = NULL;
 
14907
    }
 
14908
 
 
14909
#ifdef LIBXML_CATALOG_ENABLED
 
14910
    if (ctxt->catalogs != NULL)
 
14911
        xmlCatalogFreeLocal(ctxt->catalogs);
 
14912
#endif
 
14913
    if (ctxt->lastError.code != XML_ERR_OK)
 
14914
        xmlResetError(&ctxt->lastError);
 
14915
}
 
14916
 
 
14917
/**
 
14918
 * xmlCtxtResetPush:
 
14919
 * @ctxt: an XML parser context
 
14920
 * @chunk:  a pointer to an array of chars
 
14921
 * @size:  number of chars in the array
 
14922
 * @filename:  an optional file name or URI
 
14923
 * @encoding:  the document encoding, or NULL
 
14924
 *
 
14925
 * Reset a push parser context
 
14926
 *
 
14927
 * Returns 0 in case of success and 1 in case of error
 
14928
 */
 
14929
int
 
14930
xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk,
 
14931
                 int size, const char *filename, const char *encoding)
 
14932
{
 
14933
    xmlParserInputPtr inputStream;
 
14934
    xmlParserInputBufferPtr buf;
 
14935
    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
 
14936
 
 
14937
    if (ctxt == NULL)
 
14938
        return(1);
 
14939
 
 
14940
    if ((encoding == NULL) && (chunk != NULL) && (size >= 4))
 
14941
        enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
 
14942
 
 
14943
    buf = xmlAllocParserInputBuffer(enc);
 
14944
    if (buf == NULL)
 
14945
        return(1);
 
14946
 
 
14947
    if (ctxt == NULL) {
 
14948
        xmlFreeParserInputBuffer(buf);
 
14949
        return(1);
 
14950
    }
 
14951
 
 
14952
    xmlCtxtReset(ctxt);
 
14953
 
 
14954
    if (ctxt->pushTab == NULL) {
 
14955
        ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 *
 
14956
                                            sizeof(xmlChar *));
 
14957
        if (ctxt->pushTab == NULL) {
 
14958
            xmlErrMemory(ctxt, NULL);
 
14959
            xmlFreeParserInputBuffer(buf);
 
14960
            return(1);
 
14961
        }
 
14962
    }
 
14963
 
 
14964
    if (filename == NULL) {
 
14965
        ctxt->directory = NULL;
 
14966
    } else {
 
14967
        ctxt->directory = xmlParserGetDirectory(filename);
 
14968
    }
 
14969
 
 
14970
    inputStream = xmlNewInputStream(ctxt);
 
14971
    if (inputStream == NULL) {
 
14972
        xmlFreeParserInputBuffer(buf);
 
14973
        return(1);
 
14974
    }
 
14975
 
 
14976
    if (filename == NULL)
 
14977
        inputStream->filename = NULL;
 
14978
    else
 
14979
        inputStream->filename = (char *)
 
14980
            xmlCanonicPath((const xmlChar *) filename);
 
14981
    inputStream->buf = buf;
 
14982
    xmlBufResetInput(buf->buffer, inputStream);
 
14983
 
 
14984
    inputPush(ctxt, inputStream);
 
14985
 
 
14986
    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
 
14987
        (ctxt->input->buf != NULL)) {
 
14988
        size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
 
14989
        size_t cur = ctxt->input->cur - ctxt->input->base;
 
14990
 
 
14991
        xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
 
14992
 
 
14993
        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
 
14994
#ifdef DEBUG_PUSH
 
14995
        xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
 
14996
#endif
 
14997
    }
 
14998
 
 
14999
    if (encoding != NULL) {
 
15000
        xmlCharEncodingHandlerPtr hdlr;
 
15001
 
 
15002
        if (ctxt->encoding != NULL)
 
15003
            xmlFree((xmlChar *) ctxt->encoding);
 
15004
        ctxt->encoding = xmlStrdup((const xmlChar *) encoding);
 
15005
 
 
15006
        hdlr = xmlFindCharEncodingHandler(encoding);
 
15007
        if (hdlr != NULL) {
 
15008
            xmlSwitchToEncoding(ctxt, hdlr);
 
15009
        } else {
 
15010
            xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
 
15011
                              "Unsupported encoding %s\n", BAD_CAST encoding);
 
15012
        }
 
15013
    } else if (enc != XML_CHAR_ENCODING_NONE) {
 
15014
        xmlSwitchEncoding(ctxt, enc);
 
15015
    }
 
15016
 
 
15017
    return(0);
 
15018
}
 
15019
 
 
15020
 
 
15021
/**
 
15022
 * xmlCtxtUseOptionsInternal:
 
15023
 * @ctxt: an XML parser context
 
15024
 * @options:  a combination of xmlParserOption
 
15025
 * @encoding:  the user provided encoding to use
 
15026
 *
 
15027
 * Applies the options to the parser context
 
15028
 *
 
15029
 * Returns 0 in case of success, the set of unknown or unimplemented options
 
15030
 *         in case of error.
 
15031
 */
 
15032
static int
 
15033
xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encoding)
 
15034
{
 
15035
    if (ctxt == NULL)
 
15036
        return(-1);
 
15037
    if (encoding != NULL) {
 
15038
        if (ctxt->encoding != NULL)
 
15039
            xmlFree((xmlChar *) ctxt->encoding);
 
15040
        ctxt->encoding = xmlStrdup((const xmlChar *) encoding);
 
15041
    }
 
15042
    if (options & XML_PARSE_RECOVER) {
 
15043
        ctxt->recovery = 1;
 
15044
        options -= XML_PARSE_RECOVER;
 
15045
        ctxt->options |= XML_PARSE_RECOVER;
 
15046
    } else
 
15047
        ctxt->recovery = 0;
 
15048
    if (options & XML_PARSE_DTDLOAD) {
 
15049
        ctxt->loadsubset = XML_DETECT_IDS;
 
15050
        options -= XML_PARSE_DTDLOAD;
 
15051
        ctxt->options |= XML_PARSE_DTDLOAD;
 
15052
    } else
 
15053
        ctxt->loadsubset = 0;
 
15054
    if (options & XML_PARSE_DTDATTR) {
 
15055
        ctxt->loadsubset |= XML_COMPLETE_ATTRS;
 
15056
        options -= XML_PARSE_DTDATTR;
 
15057
        ctxt->options |= XML_PARSE_DTDATTR;
 
15058
    }
 
15059
    if (options & XML_PARSE_NOENT) {
 
15060
        ctxt->replaceEntities = 1;
 
15061
        /* ctxt->loadsubset |= XML_DETECT_IDS; */
 
15062
        options -= XML_PARSE_NOENT;
 
15063
        ctxt->options |= XML_PARSE_NOENT;
 
15064
    } else
 
15065
        ctxt->replaceEntities = 0;
 
15066
    if (options & XML_PARSE_PEDANTIC) {
 
15067
        ctxt->pedantic = 1;
 
15068
        options -= XML_PARSE_PEDANTIC;
 
15069
        ctxt->options |= XML_PARSE_PEDANTIC;
 
15070
    } else
 
15071
        ctxt->pedantic = 0;
 
15072
    if (options & XML_PARSE_NOBLANKS) {
 
15073
        ctxt->keepBlanks = 0;
 
15074
        ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
 
15075
        options -= XML_PARSE_NOBLANKS;
 
15076
        ctxt->options |= XML_PARSE_NOBLANKS;
 
15077
    } else
 
15078
        ctxt->keepBlanks = 1;
 
15079
    if (options & XML_PARSE_DTDVALID) {
 
15080
        ctxt->validate = 1;
 
15081
        if (options & XML_PARSE_NOWARNING)
 
15082
            ctxt->vctxt.warning = NULL;
 
15083
        if (options & XML_PARSE_NOERROR)
 
15084
            ctxt->vctxt.error = NULL;
 
15085
        options -= XML_PARSE_DTDVALID;
 
15086
        ctxt->options |= XML_PARSE_DTDVALID;
 
15087
    } else
 
15088
        ctxt->validate = 0;
 
15089
    if (options & XML_PARSE_NOWARNING) {
 
15090
        ctxt->sax->warning = NULL;
 
15091
        options -= XML_PARSE_NOWARNING;
 
15092
    }
 
15093
    if (options & XML_PARSE_NOERROR) {
 
15094
        ctxt->sax->error = NULL;
 
15095
        ctxt->sax->fatalError = NULL;
 
15096
        options -= XML_PARSE_NOERROR;
 
15097
    }
 
15098
#ifdef LIBXML_SAX1_ENABLED
 
15099
    if (options & XML_PARSE_SAX1) {
 
15100
        ctxt->sax->startElement = xmlSAX2StartElement;
 
15101
        ctxt->sax->endElement = xmlSAX2EndElement;
 
15102
        ctxt->sax->startElementNs = NULL;
 
15103
        ctxt->sax->endElementNs = NULL;
 
15104
        ctxt->sax->initialized = 1;
 
15105
        options -= XML_PARSE_SAX1;
 
15106
        ctxt->options |= XML_PARSE_SAX1;
 
15107
    }
 
15108
#endif /* LIBXML_SAX1_ENABLED */
 
15109
    if (options & XML_PARSE_NODICT) {
 
15110
        ctxt->dictNames = 0;
 
15111
        options -= XML_PARSE_NODICT;
 
15112
        ctxt->options |= XML_PARSE_NODICT;
 
15113
    } else {
 
15114
        ctxt->dictNames = 1;
 
15115
    }
 
15116
    if (options & XML_PARSE_NOCDATA) {
 
15117
        ctxt->sax->cdataBlock = NULL;
 
15118
        options -= XML_PARSE_NOCDATA;
 
15119
        ctxt->options |= XML_PARSE_NOCDATA;
 
15120
    }
 
15121
    if (options & XML_PARSE_NSCLEAN) {
 
15122
        ctxt->options |= XML_PARSE_NSCLEAN;
 
15123
        options -= XML_PARSE_NSCLEAN;
 
15124
    }
 
15125
    if (options & XML_PARSE_NONET) {
 
15126
        ctxt->options |= XML_PARSE_NONET;
 
15127
        options -= XML_PARSE_NONET;
 
15128
    }
 
15129
    if (options & XML_PARSE_COMPACT) {
 
15130
        ctxt->options |= XML_PARSE_COMPACT;
 
15131
        options -= XML_PARSE_COMPACT;
 
15132
    }
 
15133
    if (options & XML_PARSE_OLD10) {
 
15134
        ctxt->options |= XML_PARSE_OLD10;
 
15135
        options -= XML_PARSE_OLD10;
 
15136
    }
 
15137
    if (options & XML_PARSE_NOBASEFIX) {
 
15138
        ctxt->options |= XML_PARSE_NOBASEFIX;
 
15139
        options -= XML_PARSE_NOBASEFIX;
 
15140
    }
 
15141
    if (options & XML_PARSE_HUGE) {
 
15142
        ctxt->options |= XML_PARSE_HUGE;
 
15143
        options -= XML_PARSE_HUGE;
 
15144
        if (ctxt->dict != NULL)
 
15145
            xmlDictSetLimit(ctxt->dict, 0);
 
15146
    }
 
15147
    if (options & XML_PARSE_OLDSAX) {
 
15148
        ctxt->options |= XML_PARSE_OLDSAX;
 
15149
        options -= XML_PARSE_OLDSAX;
 
15150
    }
 
15151
    if (options & XML_PARSE_IGNORE_ENC) {
 
15152
        ctxt->options |= XML_PARSE_IGNORE_ENC;
 
15153
        options -= XML_PARSE_IGNORE_ENC;
 
15154
    }
 
15155
    if (options & XML_PARSE_BIG_LINES) {
 
15156
        ctxt->options |= XML_PARSE_BIG_LINES;
 
15157
        options -= XML_PARSE_BIG_LINES;
 
15158
    }
 
15159
    ctxt->linenumbers = 1;
 
15160
    return (options);
 
15161
}
 
15162
 
 
15163
/**
 
15164
 * xmlCtxtUseOptions:
 
15165
 * @ctxt: an XML parser context
 
15166
 * @options:  a combination of xmlParserOption
 
15167
 *
 
15168
 * Applies the options to the parser context
 
15169
 *
 
15170
 * Returns 0 in case of success, the set of unknown or unimplemented options
 
15171
 *         in case of error.
 
15172
 */
 
15173
int
 
15174
xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options)
 
15175
{
 
15176
   return(xmlCtxtUseOptionsInternal(ctxt, options, NULL));
 
15177
}
 
15178
 
 
15179
/**
 
15180
 * xmlDoRead:
 
15181
 * @ctxt:  an XML parser context
 
15182
 * @URL:  the base URL to use for the document
 
15183
 * @encoding:  the document encoding, or NULL
 
15184
 * @options:  a combination of xmlParserOption
 
15185
 * @reuse:  keep the context for reuse
 
15186
 *
 
15187
 * Common front-end for the xmlRead functions
 
15188
 *
 
15189
 * Returns the resulting document tree or NULL
 
15190
 */
 
15191
static xmlDocPtr
 
15192
xmlDoRead(xmlParserCtxtPtr ctxt, const char *URL, const char *encoding,
 
15193
          int options, int reuse)
 
15194
{
 
15195
    xmlDocPtr ret;
 
15196
 
 
15197
    xmlCtxtUseOptionsInternal(ctxt, options, encoding);
 
15198
    if (encoding != NULL) {
 
15199
        xmlCharEncodingHandlerPtr hdlr;
 
15200
 
 
15201
        hdlr = xmlFindCharEncodingHandler(encoding);
 
15202
        if (hdlr != NULL)
 
15203
            xmlSwitchToEncoding(ctxt, hdlr);
 
15204
    }
 
15205
    if ((URL != NULL) && (ctxt->input != NULL) &&
 
15206
        (ctxt->input->filename == NULL))
 
15207
        ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL);
 
15208
    xmlParseDocument(ctxt);
 
15209
    if ((ctxt->wellFormed) || ctxt->recovery)
 
15210
        ret = ctxt->myDoc;
 
15211
    else {
 
15212
        ret = NULL;
 
15213
        if (ctxt->myDoc != NULL) {
 
15214
            xmlFreeDoc(ctxt->myDoc);
 
15215
        }
 
15216
    }
 
15217
    ctxt->myDoc = NULL;
 
15218
    if (!reuse) {
 
15219
        xmlFreeParserCtxt(ctxt);
 
15220
    }
 
15221
 
 
15222
    return (ret);
 
15223
}
 
15224
 
 
15225
/**
 
15226
 * xmlReadDoc:
 
15227
 * @cur:  a pointer to a zero terminated string
 
15228
 * @URL:  the base URL to use for the document
 
15229
 * @encoding:  the document encoding, or NULL
 
15230
 * @options:  a combination of xmlParserOption
 
15231
 *
 
15232
 * parse an XML in-memory document and build a tree.
 
15233
 *
 
15234
 * Returns the resulting document tree
 
15235
 */
 
15236
xmlDocPtr
 
15237
xmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int options)
 
15238
{
 
15239
    xmlParserCtxtPtr ctxt;
 
15240
 
 
15241
    if (cur == NULL)
 
15242
        return (NULL);
 
15243
 
 
15244
    ctxt = xmlCreateDocParserCtxt(cur);
 
15245
    if (ctxt == NULL)
 
15246
        return (NULL);
 
15247
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
 
15248
}
 
15249
 
 
15250
/**
 
15251
 * xmlReadFile:
 
15252
 * @filename:  a file or URL
 
15253
 * @encoding:  the document encoding, or NULL
 
15254
 * @options:  a combination of xmlParserOption
 
15255
 *
 
15256
 * parse an XML file from the filesystem or the network.
 
15257
 *
 
15258
 * Returns the resulting document tree
 
15259
 */
 
15260
xmlDocPtr
 
15261
xmlReadFile(const char *filename, const char *encoding, int options)
 
15262
{
 
15263
    xmlParserCtxtPtr ctxt;
 
15264
 
 
15265
    ctxt = xmlCreateURLParserCtxt(filename, options);
 
15266
    if (ctxt == NULL)
 
15267
        return (NULL);
 
15268
    return (xmlDoRead(ctxt, NULL, encoding, options, 0));
 
15269
}
 
15270
 
 
15271
/**
 
15272
 * xmlReadMemory:
 
15273
 * @buffer:  a pointer to a char array
 
15274
 * @size:  the size of the array
 
15275
 * @URL:  the base URL to use for the document
 
15276
 * @encoding:  the document encoding, or NULL
 
15277
 * @options:  a combination of xmlParserOption
 
15278
 *
 
15279
 * parse an XML in-memory document and build a tree.
 
15280
 *
 
15281
 * Returns the resulting document tree
 
15282
 */
 
15283
xmlDocPtr
 
15284
xmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options)
 
15285
{
 
15286
    xmlParserCtxtPtr ctxt;
 
15287
 
 
15288
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
 
15289
    if (ctxt == NULL)
 
15290
        return (NULL);
 
15291
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
 
15292
}
 
15293
 
 
15294
/**
 
15295
 * xmlReadFd:
 
15296
 * @fd:  an open file descriptor
 
15297
 * @URL:  the base URL to use for the document
 
15298
 * @encoding:  the document encoding, or NULL
 
15299
 * @options:  a combination of xmlParserOption
 
15300
 *
 
15301
 * parse an XML from a file descriptor and build a tree.
 
15302
 * NOTE that the file descriptor will not be closed when the
 
15303
 *      reader is closed or reset.
 
15304
 *
 
15305
 * Returns the resulting document tree
 
15306
 */
 
15307
xmlDocPtr
 
15308
xmlReadFd(int fd, const char *URL, const char *encoding, int options)
 
15309
{
 
15310
    xmlParserCtxtPtr ctxt;
 
15311
    xmlParserInputBufferPtr input;
 
15312
    xmlParserInputPtr stream;
 
15313
 
 
15314
    if (fd < 0)
 
15315
        return (NULL);
 
15316
 
 
15317
    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
 
15318
    if (input == NULL)
 
15319
        return (NULL);
 
15320
    input->closecallback = NULL;
 
15321
    ctxt = xmlNewParserCtxt();
 
15322
    if (ctxt == NULL) {
 
15323
        xmlFreeParserInputBuffer(input);
 
15324
        return (NULL);
 
15325
    }
 
15326
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
 
15327
    if (stream == NULL) {
 
15328
        xmlFreeParserInputBuffer(input);
 
15329
        xmlFreeParserCtxt(ctxt);
 
15330
        return (NULL);
 
15331
    }
 
15332
    inputPush(ctxt, stream);
 
15333
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
 
15334
}
 
15335
 
 
15336
/**
 
15337
 * xmlReadIO:
 
15338
 * @ioread:  an I/O read function
 
15339
 * @ioclose:  an I/O close function
 
15340
 * @ioctx:  an I/O handler
 
15341
 * @URL:  the base URL to use for the document
 
15342
 * @encoding:  the document encoding, or NULL
 
15343
 * @options:  a combination of xmlParserOption
 
15344
 *
 
15345
 * parse an XML document from I/O functions and source and build a tree.
 
15346
 *
 
15347
 * Returns the resulting document tree
 
15348
 */
 
15349
xmlDocPtr
 
15350
xmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
 
15351
          void *ioctx, const char *URL, const char *encoding, int options)
 
15352
{
 
15353
    xmlParserCtxtPtr ctxt;
 
15354
    xmlParserInputBufferPtr input;
 
15355
    xmlParserInputPtr stream;
 
15356
 
 
15357
    if (ioread == NULL)
 
15358
        return (NULL);
 
15359
 
 
15360
    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
 
15361
                                         XML_CHAR_ENCODING_NONE);
 
15362
    if (input == NULL) {
 
15363
        if (ioclose != NULL)
 
15364
            ioclose(ioctx);
 
15365
        return (NULL);
 
15366
    }
 
15367
    ctxt = xmlNewParserCtxt();
 
15368
    if (ctxt == NULL) {
 
15369
        xmlFreeParserInputBuffer(input);
 
15370
        return (NULL);
 
15371
    }
 
15372
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
 
15373
    if (stream == NULL) {
 
15374
        xmlFreeParserInputBuffer(input);
 
15375
        xmlFreeParserCtxt(ctxt);
 
15376
        return (NULL);
 
15377
    }
 
15378
    inputPush(ctxt, stream);
 
15379
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
 
15380
}
 
15381
 
 
15382
/**
 
15383
 * xmlCtxtReadDoc:
 
15384
 * @ctxt:  an XML parser context
 
15385
 * @cur:  a pointer to a zero terminated string
 
15386
 * @URL:  the base URL to use for the document
 
15387
 * @encoding:  the document encoding, or NULL
 
15388
 * @options:  a combination of xmlParserOption
 
15389
 *
 
15390
 * parse an XML in-memory document and build a tree.
 
15391
 * This reuses the existing @ctxt parser context
 
15392
 *
 
15393
 * Returns the resulting document tree
 
15394
 */
 
15395
xmlDocPtr
 
15396
xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar * cur,
 
15397
               const char *URL, const char *encoding, int options)
 
15398
{
 
15399
    xmlParserInputPtr stream;
 
15400
 
 
15401
    if (cur == NULL)
 
15402
        return (NULL);
 
15403
    if (ctxt == NULL)
 
15404
        return (NULL);
 
15405
 
 
15406
    xmlCtxtReset(ctxt);
 
15407
 
 
15408
    stream = xmlNewStringInputStream(ctxt, cur);
 
15409
    if (stream == NULL) {
 
15410
        return (NULL);
 
15411
    }
 
15412
    inputPush(ctxt, stream);
 
15413
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
 
15414
}
 
15415
 
 
15416
/**
 
15417
 * xmlCtxtReadFile:
 
15418
 * @ctxt:  an XML parser context
 
15419
 * @filename:  a file or URL
 
15420
 * @encoding:  the document encoding, or NULL
 
15421
 * @options:  a combination of xmlParserOption
 
15422
 *
 
15423
 * parse an XML file from the filesystem or the network.
 
15424
 * This reuses the existing @ctxt parser context
 
15425
 *
 
15426
 * Returns the resulting document tree
 
15427
 */
 
15428
xmlDocPtr
 
15429
xmlCtxtReadFile(xmlParserCtxtPtr ctxt, const char *filename,
 
15430
                const char *encoding, int options)
 
15431
{
 
15432
    xmlParserInputPtr stream;
 
15433
 
 
15434
    if (filename == NULL)
 
15435
        return (NULL);
 
15436
    if (ctxt == NULL)
 
15437
        return (NULL);
 
15438
 
 
15439
    xmlCtxtReset(ctxt);
 
15440
 
 
15441
    stream = xmlLoadExternalEntity(filename, NULL, ctxt);
 
15442
    if (stream == NULL) {
 
15443
        return (NULL);
 
15444
    }
 
15445
    inputPush(ctxt, stream);
 
15446
    return (xmlDoRead(ctxt, NULL, encoding, options, 1));
 
15447
}
 
15448
 
 
15449
/**
 
15450
 * xmlCtxtReadMemory:
 
15451
 * @ctxt:  an XML parser context
 
15452
 * @buffer:  a pointer to a char array
 
15453
 * @size:  the size of the array
 
15454
 * @URL:  the base URL to use for the document
 
15455
 * @encoding:  the document encoding, or NULL
 
15456
 * @options:  a combination of xmlParserOption
 
15457
 *
 
15458
 * parse an XML in-memory document and build a tree.
 
15459
 * This reuses the existing @ctxt parser context
 
15460
 *
 
15461
 * Returns the resulting document tree
 
15462
 */
 
15463
xmlDocPtr
 
15464
xmlCtxtReadMemory(xmlParserCtxtPtr ctxt, const char *buffer, int size,
 
15465
                  const char *URL, const char *encoding, int options)
 
15466
{
 
15467
    xmlParserInputBufferPtr input;
 
15468
    xmlParserInputPtr stream;
 
15469
 
 
15470
    if (ctxt == NULL)
 
15471
        return (NULL);
 
15472
    if (buffer == NULL)
 
15473
        return (NULL);
 
15474
 
 
15475
    xmlCtxtReset(ctxt);
 
15476
 
 
15477
    input = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
 
15478
    if (input == NULL) {
 
15479
        return(NULL);
 
15480
    }
 
15481
 
 
15482
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
 
15483
    if (stream == NULL) {
 
15484
        xmlFreeParserInputBuffer(input);
 
15485
        return(NULL);
 
15486
    }
 
15487
 
 
15488
    inputPush(ctxt, stream);
 
15489
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
 
15490
}
 
15491
 
 
15492
/**
 
15493
 * xmlCtxtReadFd:
 
15494
 * @ctxt:  an XML parser context
 
15495
 * @fd:  an open file descriptor
 
15496
 * @URL:  the base URL to use for the document
 
15497
 * @encoding:  the document encoding, or NULL
 
15498
 * @options:  a combination of xmlParserOption
 
15499
 *
 
15500
 * parse an XML from a file descriptor and build a tree.
 
15501
 * This reuses the existing @ctxt parser context
 
15502
 * NOTE that the file descriptor will not be closed when the
 
15503
 *      reader is closed or reset.
 
15504
 *
 
15505
 * Returns the resulting document tree
 
15506
 */
 
15507
xmlDocPtr
 
15508
xmlCtxtReadFd(xmlParserCtxtPtr ctxt, int fd,
 
15509
              const char *URL, const char *encoding, int options)
 
15510
{
 
15511
    xmlParserInputBufferPtr input;
 
15512
    xmlParserInputPtr stream;
 
15513
 
 
15514
    if (fd < 0)
 
15515
        return (NULL);
 
15516
    if (ctxt == NULL)
 
15517
        return (NULL);
 
15518
 
 
15519
    xmlCtxtReset(ctxt);
 
15520
 
 
15521
 
 
15522
    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
 
15523
    if (input == NULL)
 
15524
        return (NULL);
 
15525
    input->closecallback = NULL;
 
15526
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
 
15527
    if (stream == NULL) {
 
15528
        xmlFreeParserInputBuffer(input);
 
15529
        return (NULL);
 
15530
    }
 
15531
    inputPush(ctxt, stream);
 
15532
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
 
15533
}
 
15534
 
 
15535
/**
 
15536
 * xmlCtxtReadIO:
 
15537
 * @ctxt:  an XML parser context
 
15538
 * @ioread:  an I/O read function
 
15539
 * @ioclose:  an I/O close function
 
15540
 * @ioctx:  an I/O handler
 
15541
 * @URL:  the base URL to use for the document
 
15542
 * @encoding:  the document encoding, or NULL
 
15543
 * @options:  a combination of xmlParserOption
 
15544
 *
 
15545
 * parse an XML document from I/O functions and source and build a tree.
 
15546
 * This reuses the existing @ctxt parser context
 
15547
 *
 
15548
 * Returns the resulting document tree
 
15549
 */
 
15550
xmlDocPtr
 
15551
xmlCtxtReadIO(xmlParserCtxtPtr ctxt, xmlInputReadCallback ioread,
 
15552
              xmlInputCloseCallback ioclose, void *ioctx,
 
15553
              const char *URL,
 
15554
              const char *encoding, int options)
 
15555
{
 
15556
    xmlParserInputBufferPtr input;
 
15557
    xmlParserInputPtr stream;
 
15558
 
 
15559
    if (ioread == NULL)
 
15560
        return (NULL);
 
15561
    if (ctxt == NULL)
 
15562
        return (NULL);
 
15563
 
 
15564
    xmlCtxtReset(ctxt);
 
15565
 
 
15566
    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
 
15567
                                         XML_CHAR_ENCODING_NONE);
 
15568
    if (input == NULL) {
 
15569
        if (ioclose != NULL)
 
15570
            ioclose(ioctx);
 
15571
        return (NULL);
 
15572
    }
 
15573
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
 
15574
    if (stream == NULL) {
 
15575
        xmlFreeParserInputBuffer(input);
 
15576
        return (NULL);
 
15577
    }
 
15578
    inputPush(ctxt, stream);
 
15579
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
 
15580
}
 
15581
 
 
15582
#define bottom_parser
 
15583
#include "elfgcchack.h"