Coverage Report

Created: 2022-11-15 06:34

/src/libxml2/parser.c
Line
Count
Source (jump to first uncovered line)
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
/* To avoid EBCDIC trouble when parsing on zOS */
34
#if defined(__MVS__)
35
#pragma convert("ISO8859-1")
36
#endif
37
38
#define IN_LIBXML
39
#include "libxml.h"
40
41
#if defined(_WIN32)
42
#define XML_DIR_SEP '\\'
43
#else
44
#define XML_DIR_SEP '/'
45
#endif
46
47
#include <stdlib.h>
48
#include <limits.h>
49
#include <string.h>
50
#include <stdarg.h>
51
#include <stddef.h>
52
#include <ctype.h>
53
#include <stdlib.h>
54
#include <libxml/xmlmemory.h>
55
#include <libxml/threads.h>
56
#include <libxml/globals.h>
57
#include <libxml/tree.h>
58
#include <libxml/parser.h>
59
#include <libxml/parserInternals.h>
60
#include <libxml/HTMLparser.h>
61
#include <libxml/valid.h>
62
#include <libxml/entities.h>
63
#include <libxml/xmlerror.h>
64
#include <libxml/encoding.h>
65
#include <libxml/xmlIO.h>
66
#include <libxml/uri.h>
67
#ifdef LIBXML_CATALOG_ENABLED
68
#include <libxml/catalog.h>
69
#endif
70
#ifdef LIBXML_SCHEMAS_ENABLED
71
#include <libxml/xmlschemastypes.h>
72
#include <libxml/relaxng.h>
73
#endif
74
#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
75
#include <libxml/xpath.h>
76
#endif
77
78
#include "private/buf.h"
79
#include "private/enc.h"
80
#include "private/error.h"
81
#include "private/html.h"
82
#include "private/io.h"
83
#include "private/parser.h"
84
#include "private/threads.h"
85
86
struct _xmlStartTag {
87
    const xmlChar *prefix;
88
    const xmlChar *URI;
89
    int line;
90
    int nsNr;
91
};
92
93
static void
94
xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info);
95
96
static xmlParserCtxtPtr
97
xmlCreateEntityParserCtxtInternal(xmlSAXHandlerPtr sax, void *userData,
98
        const xmlChar *URL, const xmlChar *ID, const xmlChar *base,
99
        xmlParserCtxtPtr pctx);
100
101
static void xmlHaltParser(xmlParserCtxtPtr ctxt);
102
103
static int
104
xmlParseElementStart(xmlParserCtxtPtr ctxt);
105
106
static void
107
xmlParseElementEnd(xmlParserCtxtPtr ctxt);
108
109
/************************************************************************
110
 *                  *
111
 *  Arbitrary limits set in the parser. See XML_PARSE_HUGE    *
112
 *                  *
113
 ************************************************************************/
114
115
0
#define XML_MAX_HUGE_LENGTH 1000000000
116
117
17
#define XML_PARSER_BIG_ENTITY 1000
118
#define XML_PARSER_LOT_ENTITY 5000
119
120
/*
121
 * XML_PARSER_NON_LINEAR is the threshold where the ratio of parsed entity
122
 *    replacement over the size in byte of the input indicates that you have
123
 *    and exponential behaviour. A value of 10 correspond to at least 3 entity
124
 *    replacement per byte of input.
125
 */
126
6.98k
#define XML_PARSER_NON_LINEAR 10
127
128
/*
129
 * xmlParserEntityCheck
130
 *
131
 * Function to check non-linear entity expansion behaviour
132
 * This is here to detect and stop exponential linear entity expansion
133
 * This is not a limitation of the parser but a safety
134
 * boundary feature. It can be disabled with the XML_PARSE_HUGE
135
 * parser option.
136
 */
137
static int
138
xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
139
                     xmlEntityPtr ent, size_t replacement)
140
7.81k
{
141
7.81k
    size_t consumed = 0;
142
7.81k
    int i;
143
144
7.81k
    if ((ctxt == NULL) || (ctxt->options & XML_PARSE_HUGE))
145
0
        return (0);
146
7.81k
    if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
147
0
        return (1);
148
149
    /*
150
     * This may look absurd but is needed to detect
151
     * entities problems
152
     */
153
7.81k
    if ((ent != NULL) && (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
154
7.81k
  (ent->content != NULL) && (ent->checked == 0) &&
155
7.81k
  (ctxt->errNo != XML_ERR_ENTITY_LOOP)) {
156
6
  unsigned long oldnbent = ctxt->nbentities, diff;
157
6
  xmlChar *rep;
158
159
6
  ent->checked = 1;
160
161
6
        ++ctxt->depth;
162
6
  rep = xmlStringDecodeEntities(ctxt, ent->content,
163
6
          XML_SUBSTITUTE_REF, 0, 0, 0);
164
6
        --ctxt->depth;
165
6
  if ((rep == NULL) || (ctxt->errNo == XML_ERR_ENTITY_LOOP)) {
166
0
      ent->content[0] = 0;
167
0
  }
168
169
6
        diff = ctxt->nbentities - oldnbent + 1;
170
6
        if (diff > INT_MAX / 2)
171
0
            diff = INT_MAX / 2;
172
6
  ent->checked = diff * 2;
173
6
  if (rep != NULL) {
174
6
      if (xmlStrchr(rep, '<'))
175
6
    ent->checked |= 1;
176
6
      xmlFree(rep);
177
6
      rep = NULL;
178
6
  }
179
6
    }
180
181
    /*
182
     * Prevent entity exponential check, not just replacement while
183
     * parsing the DTD
184
     * The check is potentially costly so do that only once in a thousand
185
     */
186
7.81k
    if ((ctxt->instate == XML_PARSER_DTD) && (ctxt->nbentities > 10000) &&
187
7.81k
        (ctxt->nbentities % 1024 == 0)) {
188
0
  for (i = 0;i < ctxt->inputNr;i++) {
189
0
      consumed += ctxt->inputTab[i]->consumed +
190
0
                 (ctxt->inputTab[i]->cur - ctxt->inputTab[i]->base);
191
0
  }
192
0
  if (ctxt->nbentities > consumed * XML_PARSER_NON_LINEAR) {
193
0
      xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
194
0
      ctxt->instate = XML_PARSER_EOF;
195
0
      return (1);
196
0
  }
197
0
  consumed = 0;
198
0
    }
199
200
201
202
7.81k
    if (replacement != 0) {
203
0
  if (replacement < XML_MAX_TEXT_LENGTH)
204
0
      return(0);
205
206
        /*
207
   * If the volume of entity copy reaches 10 times the
208
   * amount of parsed data and over the large text threshold
209
   * then that's very likely to be an abuse.
210
   */
211
0
        if (ctxt->input != NULL) {
212
0
      consumed = ctxt->input->consumed +
213
0
                 (ctxt->input->cur - ctxt->input->base);
214
0
  }
215
0
        consumed += ctxt->sizeentities;
216
217
0
        if (replacement < XML_PARSER_NON_LINEAR * consumed)
218
0
      return(0);
219
7.81k
    } else if (size != 0) {
220
        /*
221
         * Do the check based on the replacement size of the entity
222
         */
223
17
        if (size < XML_PARSER_BIG_ENTITY)
224
2
      return(0);
225
226
        /*
227
         * A limit on the amount of text data reasonably used
228
         */
229
15
        if (ctxt->input != NULL) {
230
15
            consumed = ctxt->input->consumed +
231
15
                (ctxt->input->cur - ctxt->input->base);
232
15
        }
233
15
        consumed += ctxt->sizeentities;
234
235
15
        if ((size < XML_PARSER_NON_LINEAR * consumed) &&
236
15
      (ctxt->nbentities * 3 < XML_PARSER_NON_LINEAR * consumed))
237
15
            return (0);
238
7.79k
    } else if (ent != NULL) {
239
        /*
240
         * use the number of parsed entities in the replacement
241
         */
242
6.95k
        size = ent->checked / 2;
243
244
        /*
245
         * The amount of data parsed counting entities size only once
246
         */
247
6.95k
        if (ctxt->input != NULL) {
248
6.95k
            consumed = ctxt->input->consumed +
249
6.95k
                (ctxt->input->cur - ctxt->input->base);
250
6.95k
        }
251
6.95k
        consumed += ctxt->sizeentities;
252
253
        /*
254
         * Check the density of entities for the amount of data
255
   * knowing an entity reference will take at least 3 bytes
256
         */
257
6.95k
        if (size * 3 < consumed * XML_PARSER_NON_LINEAR)
258
6.93k
            return (0);
259
6.95k
    } else {
260
        /*
261
         * strange we got no data for checking
262
         */
263
834
  if (((ctxt->lastError.code != XML_ERR_UNDECLARED_ENTITY) &&
264
834
       (ctxt->lastError.code != XML_WAR_UNDECLARED_ENTITY)) ||
265
834
      (ctxt->nbentities <= 10000))
266
834
      return (0);
267
834
    }
268
24
    xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
269
24
    return (1);
270
7.81k
}
271
272
/**
273
 * xmlParserMaxDepth:
274
 *
275
 * arbitrary depth limit for the XML documents that we allow to
276
 * process. This is not a limitation of the parser but a safety
277
 * boundary feature. It can be disabled with the XML_PARSE_HUGE
278
 * parser option.
279
 */
280
unsigned int xmlParserMaxDepth = 256;
281
282
283
284
#define SAX2 1
285
62.3M
#define XML_PARSER_BIG_BUFFER_SIZE 300
286
171M
#define XML_PARSER_BUFFER_SIZE 100
287
2.20k
#define SAX_COMPAT_MODE BAD_CAST "SAX compatibility mode document"
288
289
/**
290
 * XML_PARSER_CHUNK_SIZE
291
 *
292
 * When calling GROW that's the minimal amount of data
293
 * the parser expected to have received. It is not a hard
294
 * limit but an optimization when reading strings like Names
295
 * It is not strictly needed as long as inputs available characters
296
 * are followed by 0, which should be provided by the I/O level
297
 */
298
43.2M
#define XML_PARSER_CHUNK_SIZE 100
299
300
/*
301
 * List of XML prefixed PI allowed by W3C specs
302
 */
303
304
static const char* const xmlW3CPIs[] = {
305
    "xml-stylesheet",
306
    "xml-model",
307
    NULL
308
};
309
310
311
/* DEPR void xmlParserHandleReference(xmlParserCtxtPtr ctxt); */
312
static xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt,
313
                                              const xmlChar **str);
314
315
static xmlParserErrors
316
xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
317
                xmlSAXHandlerPtr sax,
318
          void *user_data, int depth, const xmlChar *URL,
319
          const xmlChar *ID, xmlNodePtr *list);
320
321
static int
322
xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options,
323
                          const char *encoding);
324
#ifdef LIBXML_LEGACY_ENABLED
325
static void
326
xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
327
                      xmlNodePtr lastNode);
328
#endif /* LIBXML_LEGACY_ENABLED */
329
330
static xmlParserErrors
331
xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
332
          const xmlChar *string, void *user_data, xmlNodePtr *lst);
333
334
static int
335
xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity);
336
337
/************************************************************************
338
 *                  *
339
 *    Some factorized error routines        *
340
 *                  *
341
 ************************************************************************/
342
343
/**
344
 * xmlErrAttributeDup:
345
 * @ctxt:  an XML parser context
346
 * @prefix:  the attribute prefix
347
 * @localname:  the attribute localname
348
 *
349
 * Handle a redefinition of attribute error
350
 */
351
static void
352
xmlErrAttributeDup(xmlParserCtxtPtr ctxt, const xmlChar * prefix,
353
                   const xmlChar * localname)
354
710
{
355
710
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
356
710
        (ctxt->instate == XML_PARSER_EOF))
357
0
  return;
358
710
    if (ctxt != NULL)
359
710
  ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
360
361
710
    if (prefix == NULL)
362
584
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
363
584
                        XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
364
584
                        (const char *) localname, NULL, NULL, 0, 0,
365
584
                        "Attribute %s redefined\n", localname);
366
126
    else
367
126
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
368
126
                        XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
369
126
                        (const char *) prefix, (const char *) localname,
370
126
                        NULL, 0, 0, "Attribute %s:%s redefined\n", prefix,
371
126
                        localname);
372
710
    if (ctxt != NULL) {
373
710
  ctxt->wellFormed = 0;
374
710
  if (ctxt->recovery == 0)
375
710
      ctxt->disableSAX = 1;
376
710
    }
377
710
}
378
379
/**
380
 * xmlFatalErr:
381
 * @ctxt:  an XML parser context
382
 * @error:  the error number
383
 * @extra:  extra information string
384
 *
385
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
386
 */
387
static void
388
xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
389
78.1k
{
390
78.1k
    const char *errmsg;
391
392
78.1k
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
393
78.1k
        (ctxt->instate == XML_PARSER_EOF))
394
8
  return;
395
78.1k
    switch (error) {
396
5.17k
        case XML_ERR_INVALID_HEX_CHARREF:
397
5.17k
            errmsg = "CharRef: invalid hexadecimal value";
398
5.17k
            break;
399
119
        case XML_ERR_INVALID_DEC_CHARREF:
400
119
            errmsg = "CharRef: invalid decimal value";
401
119
            break;
402
0
        case XML_ERR_INVALID_CHARREF:
403
0
            errmsg = "CharRef: invalid value";
404
0
            break;
405
43
        case XML_ERR_INTERNAL_ERROR:
406
43
            errmsg = "internal error";
407
43
            break;
408
0
        case XML_ERR_PEREF_AT_EOF:
409
0
            errmsg = "PEReference at end of document";
410
0
            break;
411
0
        case XML_ERR_PEREF_IN_PROLOG:
412
0
            errmsg = "PEReference in prolog";
413
0
            break;
414
0
        case XML_ERR_PEREF_IN_EPILOG:
415
0
            errmsg = "PEReference in epilog";
416
0
            break;
417
0
        case XML_ERR_PEREF_NO_NAME:
418
0
            errmsg = "PEReference: no name";
419
0
            break;
420
938
        case XML_ERR_PEREF_SEMICOL_MISSING:
421
938
            errmsg = "PEReference: expecting ';'";
422
938
            break;
423
27
        case XML_ERR_ENTITY_LOOP:
424
27
            errmsg = "Detected an entity reference loop";
425
27
            break;
426
0
        case XML_ERR_ENTITY_NOT_STARTED:
427
0
            errmsg = "EntityValue: \" or ' expected";
428
0
            break;
429
0
        case XML_ERR_ENTITY_PE_INTERNAL:
430
0
            errmsg = "PEReferences forbidden in internal subset";
431
0
            break;
432
1
        case XML_ERR_ENTITY_NOT_FINISHED:
433
1
            errmsg = "EntityValue: \" or ' expected";
434
1
            break;
435
1.99k
        case XML_ERR_ATTRIBUTE_NOT_STARTED:
436
1.99k
            errmsg = "AttValue: \" or ' expected";
437
1.99k
            break;
438
2.17k
        case XML_ERR_LT_IN_ATTRIBUTE:
439
2.17k
            errmsg = "Unescaped '<' not allowed in attributes values";
440
2.17k
            break;
441
598
        case XML_ERR_LITERAL_NOT_STARTED:
442
598
            errmsg = "SystemLiteral \" or ' expected";
443
598
            break;
444
28.2k
        case XML_ERR_LITERAL_NOT_FINISHED:
445
28.2k
            errmsg = "Unfinished System or Public ID \" or ' expected";
446
28.2k
            break;
447
0
        case XML_ERR_MISPLACED_CDATA_END:
448
0
            errmsg = "Sequence ']]>' not allowed in content";
449
0
            break;
450
598
        case XML_ERR_URI_REQUIRED:
451
598
            errmsg = "SYSTEM or PUBLIC, the URI is missing";
452
598
            break;
453
1
        case XML_ERR_PUBID_REQUIRED:
454
1
            errmsg = "PUBLIC, the Public Identifier is missing";
455
1
            break;
456
835
        case XML_ERR_HYPHEN_IN_COMMENT:
457
835
            errmsg = "Comment must not contain '--' (double-hyphen)";
458
835
            break;
459
568
        case XML_ERR_PI_NOT_STARTED:
460
568
            errmsg = "xmlParsePI : no target name";
461
568
            break;
462
0
        case XML_ERR_RESERVED_XML_NAME:
463
0
            errmsg = "Invalid PI name";
464
0
            break;
465
0
        case XML_ERR_NOTATION_NOT_STARTED:
466
0
            errmsg = "NOTATION: Name expected here";
467
0
            break;
468
23.7k
        case XML_ERR_NOTATION_NOT_FINISHED:
469
23.7k
            errmsg = "'>' required to close NOTATION declaration";
470
23.7k
            break;
471
2
        case XML_ERR_VALUE_REQUIRED:
472
2
            errmsg = "Entity value required";
473
2
            break;
474
0
        case XML_ERR_URI_FRAGMENT:
475
0
            errmsg = "Fragment not allowed";
476
0
            break;
477
971
        case XML_ERR_ATTLIST_NOT_STARTED:
478
971
            errmsg = "'(' required to start ATTLIST enumeration";
479
971
            break;
480
2.45k
        case XML_ERR_NMTOKEN_REQUIRED:
481
2.45k
            errmsg = "NmToken expected in ATTLIST enumeration";
482
2.45k
            break;
483
6.88k
        case XML_ERR_ATTLIST_NOT_FINISHED:
484
6.88k
            errmsg = "')' required to finish ATTLIST enumeration";
485
6.88k
            break;
486
294
        case XML_ERR_MIXED_NOT_STARTED:
487
294
            errmsg = "MixedContentDecl : '|' or ')*' expected";
488
294
            break;
489
0
        case XML_ERR_PCDATA_REQUIRED:
490
0
            errmsg = "MixedContentDecl : '#PCDATA' expected";
491
0
            break;
492
0
        case XML_ERR_ELEMCONTENT_NOT_STARTED:
493
0
            errmsg = "ContentDecl : Name or '(' expected";
494
0
            break;
495
285
        case XML_ERR_ELEMCONTENT_NOT_FINISHED:
496
285
            errmsg = "ContentDecl : ',' '|' or ')' expected";
497
285
            break;
498
0
        case XML_ERR_PEREF_IN_INT_SUBSET:
499
0
            errmsg =
500
0
                "PEReference: forbidden within markup decl in internal subset";
501
0
            break;
502
241
        case XML_ERR_GT_REQUIRED:
503
241
            errmsg = "expected '>'";
504
241
            break;
505
0
        case XML_ERR_CONDSEC_INVALID:
506
0
            errmsg = "XML conditional section '[' expected";
507
0
            break;
508
0
        case XML_ERR_EXT_SUBSET_NOT_FINISHED:
509
0
            errmsg = "Content error in the external subset";
510
0
            break;
511
0
        case XML_ERR_CONDSEC_INVALID_KEYWORD:
512
0
            errmsg =
513
0
                "conditional section INCLUDE or IGNORE keyword expected";
514
0
            break;
515
0
        case XML_ERR_CONDSEC_NOT_FINISHED:
516
0
            errmsg = "XML conditional section not closed";
517
0
            break;
518
0
        case XML_ERR_XMLDECL_NOT_STARTED:
519
0
            errmsg = "Text declaration '<?xml' required";
520
0
            break;
521
27
        case XML_ERR_XMLDECL_NOT_FINISHED:
522
27
            errmsg = "parsing XML declaration: '?>' expected";
523
27
            break;
524
0
        case XML_ERR_EXT_ENTITY_STANDALONE:
525
0
            errmsg = "external parsed entities cannot be standalone";
526
0
            break;
527
610
        case XML_ERR_ENTITYREF_SEMICOL_MISSING:
528
610
            errmsg = "EntityRef: expecting ';'";
529
610
            break;
530
39
        case XML_ERR_DOCTYPE_NOT_FINISHED:
531
39
            errmsg = "DOCTYPE improperly terminated";
532
39
            break;
533
0
        case XML_ERR_LTSLASH_REQUIRED:
534
0
            errmsg = "EndTag: '</' not found";
535
0
            break;
536
0
        case XML_ERR_EQUAL_REQUIRED:
537
0
            errmsg = "expected '='";
538
0
            break;
539
12
        case XML_ERR_STRING_NOT_CLOSED:
540
12
            errmsg = "String not closed expecting \" or '";
541
12
            break;
542
16
        case XML_ERR_STRING_NOT_STARTED:
543
16
            errmsg = "String not started expecting ' or \"";
544
16
            break;
545
1
        case XML_ERR_ENCODING_NAME:
546
1
            errmsg = "Invalid XML encoding name";
547
1
            break;
548
0
        case XML_ERR_STANDALONE_VALUE:
549
0
            errmsg = "standalone accepts only 'yes' or 'no'";
550
0
            break;
551
0
        case XML_ERR_DOCUMENT_EMPTY:
552
0
            errmsg = "Document is empty";
553
0
            break;
554
8
        case XML_ERR_DOCUMENT_END:
555
8
            errmsg = "Extra content at the end of the document";
556
8
            break;
557
97
        case XML_ERR_NOT_WELL_BALANCED:
558
97
            errmsg = "chunk is not well balanced";
559
97
            break;
560
0
        case XML_ERR_EXTRA_CONTENT:
561
0
            errmsg = "extra content at the end of well balanced chunk";
562
0
            break;
563
41
        case XML_ERR_VERSION_MISSING:
564
41
            errmsg = "Malformed declaration expecting version";
565
41
            break;
566
996
        case XML_ERR_NAME_TOO_LONG:
567
996
            errmsg = "Name too long";
568
996
            break;
569
#if 0
570
        case:
571
            errmsg = "";
572
            break;
573
#endif
574
0
        default:
575
0
            errmsg = "Unregistered error message";
576
78.1k
    }
577
78.1k
    if (ctxt != NULL)
578
78.1k
  ctxt->errNo = error;
579
78.1k
    if (info == NULL) {
580
77.0k
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
581
77.0k
                        XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s\n",
582
77.0k
                        errmsg);
583
77.0k
    } else {
584
1.03k
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
585
1.03k
                        XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s: %s\n",
586
1.03k
                        errmsg, info);
587
1.03k
    }
588
78.1k
    if (ctxt != NULL) {
589
78.1k
  ctxt->wellFormed = 0;
590
78.1k
  if (ctxt->recovery == 0)
591
78.1k
      ctxt->disableSAX = 1;
592
78.1k
    }
593
78.1k
}
594
595
/**
596
 * xmlFatalErrMsg:
597
 * @ctxt:  an XML parser context
598
 * @error:  the error number
599
 * @msg:  the error message
600
 *
601
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
602
 */
603
static void LIBXML_ATTR_FORMAT(3,0)
604
xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
605
               const char *msg)
606
73.1k
{
607
73.1k
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
608
73.1k
        (ctxt->instate == XML_PARSER_EOF))
609
1
  return;
610
73.1k
    if (ctxt != NULL)
611
73.1k
  ctxt->errNo = error;
612
73.1k
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
613
73.1k
                    XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
614
73.1k
    if (ctxt != NULL) {
615
73.1k
  ctxt->wellFormed = 0;
616
73.1k
  if (ctxt->recovery == 0)
617
73.1k
      ctxt->disableSAX = 1;
618
73.1k
    }
619
73.1k
}
620
621
/**
622
 * xmlWarningMsg:
623
 * @ctxt:  an XML parser context
624
 * @error:  the error number
625
 * @msg:  the error message
626
 * @str1:  extra data
627
 * @str2:  extra data
628
 *
629
 * Handle a warning.
630
 */
631
static void LIBXML_ATTR_FORMAT(3,0)
632
xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
633
              const char *msg, const xmlChar *str1, const xmlChar *str2)
634
78
{
635
78
    xmlStructuredErrorFunc schannel = NULL;
636
637
78
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
638
78
        (ctxt->instate == XML_PARSER_EOF))
639
0
  return;
640
78
    if ((ctxt != NULL) && (ctxt->sax != NULL) &&
641
78
        (ctxt->sax->initialized == XML_SAX2_MAGIC))
642
78
        schannel = ctxt->sax->serror;
643
78
    if (ctxt != NULL) {
644
78
        __xmlRaiseError(schannel,
645
78
                    (ctxt->sax) ? ctxt->sax->warning : NULL,
646
78
                    ctxt->userData,
647
78
                    ctxt, NULL, XML_FROM_PARSER, error,
648
78
                    XML_ERR_WARNING, NULL, 0,
649
78
        (const char *) str1, (const char *) str2, NULL, 0, 0,
650
78
        msg, (const char *) str1, (const char *) str2);
651
78
    } else {
652
0
        __xmlRaiseError(schannel, NULL, NULL,
653
0
                    ctxt, NULL, XML_FROM_PARSER, error,
654
0
                    XML_ERR_WARNING, NULL, 0,
655
0
        (const char *) str1, (const char *) str2, NULL, 0, 0,
656
0
        msg, (const char *) str1, (const char *) str2);
657
0
    }
658
78
}
659
660
/**
661
 * xmlValidityError:
662
 * @ctxt:  an XML parser context
663
 * @error:  the error number
664
 * @msg:  the error message
665
 * @str1:  extra data
666
 *
667
 * Handle a validity error.
668
 */
669
static void LIBXML_ATTR_FORMAT(3,0)
670
xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error,
671
              const char *msg, const xmlChar *str1, const xmlChar *str2)
672
40.6k
{
673
40.6k
    xmlStructuredErrorFunc schannel = NULL;
674
675
40.6k
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
676
40.6k
        (ctxt->instate == XML_PARSER_EOF))
677
0
  return;
678
40.6k
    if (ctxt != NULL) {
679
40.6k
  ctxt->errNo = error;
680
40.6k
  if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
681
40.6k
      schannel = ctxt->sax->serror;
682
40.6k
    }
683
40.6k
    if (ctxt != NULL) {
684
40.6k
        __xmlRaiseError(schannel,
685
40.6k
                    ctxt->vctxt.error, ctxt->vctxt.userData,
686
40.6k
                    ctxt, NULL, XML_FROM_DTD, error,
687
40.6k
                    XML_ERR_ERROR, NULL, 0, (const char *) str1,
688
40.6k
        (const char *) str2, NULL, 0, 0,
689
40.6k
        msg, (const char *) str1, (const char *) str2);
690
40.6k
  ctxt->valid = 0;
691
40.6k
    } else {
692
0
        __xmlRaiseError(schannel, NULL, NULL,
693
0
                    ctxt, NULL, XML_FROM_DTD, error,
694
0
                    XML_ERR_ERROR, NULL, 0, (const char *) str1,
695
0
        (const char *) str2, NULL, 0, 0,
696
0
        msg, (const char *) str1, (const char *) str2);
697
0
    }
698
40.6k
}
699
700
/**
701
 * xmlFatalErrMsgInt:
702
 * @ctxt:  an XML parser context
703
 * @error:  the error number
704
 * @msg:  the error message
705
 * @val:  an integer value
706
 *
707
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
708
 */
709
static void LIBXML_ATTR_FORMAT(3,0)
710
xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
711
                  const char *msg, int val)
712
13.4k
{
713
13.4k
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
714
13.4k
        (ctxt->instate == XML_PARSER_EOF))
715
0
  return;
716
13.4k
    if (ctxt != NULL)
717
13.4k
  ctxt->errNo = error;
718
13.4k
    __xmlRaiseError(NULL, NULL, NULL,
719
13.4k
                    ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
720
13.4k
                    NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
721
13.4k
    if (ctxt != NULL) {
722
13.4k
  ctxt->wellFormed = 0;
723
13.4k
  if (ctxt->recovery == 0)
724
13.4k
      ctxt->disableSAX = 1;
725
13.4k
    }
726
13.4k
}
727
728
/**
729
 * xmlFatalErrMsgStrIntStr:
730
 * @ctxt:  an XML parser context
731
 * @error:  the error number
732
 * @msg:  the error message
733
 * @str1:  an string info
734
 * @val:  an integer value
735
 * @str2:  an string info
736
 *
737
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
738
 */
739
static void LIBXML_ATTR_FORMAT(3,0)
740
xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
741
                  const char *msg, const xmlChar *str1, int val,
742
      const xmlChar *str2)
743
8.31k
{
744
8.31k
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
745
8.31k
        (ctxt->instate == XML_PARSER_EOF))
746
0
  return;
747
8.31k
    if (ctxt != NULL)
748
8.31k
  ctxt->errNo = error;
749
8.31k
    __xmlRaiseError(NULL, NULL, NULL,
750
8.31k
                    ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
751
8.31k
                    NULL, 0, (const char *) str1, (const char *) str2,
752
8.31k
        NULL, val, 0, msg, str1, val, str2);
753
8.31k
    if (ctxt != NULL) {
754
8.31k
  ctxt->wellFormed = 0;
755
8.31k
  if (ctxt->recovery == 0)
756
8.31k
      ctxt->disableSAX = 1;
757
8.31k
    }
758
8.31k
}
759
760
/**
761
 * xmlFatalErrMsgStr:
762
 * @ctxt:  an XML parser context
763
 * @error:  the error number
764
 * @msg:  the error message
765
 * @val:  a string value
766
 *
767
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
768
 */
769
static void LIBXML_ATTR_FORMAT(3,0)
770
xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
771
                  const char *msg, const xmlChar * val)
772
4.23k
{
773
4.23k
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
774
4.23k
        (ctxt->instate == XML_PARSER_EOF))
775
0
  return;
776
4.23k
    if (ctxt != NULL)
777
4.23k
  ctxt->errNo = error;
778
4.23k
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
779
4.23k
                    XML_FROM_PARSER, error, XML_ERR_FATAL,
780
4.23k
                    NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
781
4.23k
                    val);
782
4.23k
    if (ctxt != NULL) {
783
4.23k
  ctxt->wellFormed = 0;
784
4.23k
  if (ctxt->recovery == 0)
785
4.23k
      ctxt->disableSAX = 1;
786
4.23k
    }
787
4.23k
}
788
789
/**
790
 * xmlErrMsgStr:
791
 * @ctxt:  an XML parser context
792
 * @error:  the error number
793
 * @msg:  the error message
794
 * @val:  a string value
795
 *
796
 * Handle a non fatal parser error
797
 */
798
static void LIBXML_ATTR_FORMAT(3,0)
799
xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
800
                  const char *msg, const xmlChar * val)
801
7
{
802
7
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
803
7
        (ctxt->instate == XML_PARSER_EOF))
804
0
  return;
805
7
    if (ctxt != NULL)
806
7
  ctxt->errNo = error;
807
7
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
808
7
                    XML_FROM_PARSER, error, XML_ERR_ERROR,
809
7
                    NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
810
7
                    val);
811
7
}
812
813
/**
814
 * xmlNsErr:
815
 * @ctxt:  an XML parser context
816
 * @error:  the error number
817
 * @msg:  the message
818
 * @info1:  extra information string
819
 * @info2:  extra information string
820
 *
821
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
822
 */
823
static void LIBXML_ATTR_FORMAT(3,0)
824
xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
825
         const char *msg,
826
         const xmlChar * info1, const xmlChar * info2,
827
         const xmlChar * info3)
828
4.39k
{
829
4.39k
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
830
4.39k
        (ctxt->instate == XML_PARSER_EOF))
831
0
  return;
832
4.39k
    if (ctxt != NULL)
833
4.39k
  ctxt->errNo = error;
834
4.39k
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
835
4.39k
                    XML_ERR_ERROR, NULL, 0, (const char *) info1,
836
4.39k
                    (const char *) info2, (const char *) info3, 0, 0, msg,
837
4.39k
                    info1, info2, info3);
838
4.39k
    if (ctxt != NULL)
839
4.39k
  ctxt->nsWellFormed = 0;
840
4.39k
}
841
842
/**
843
 * xmlNsWarn
844
 * @ctxt:  an XML parser context
845
 * @error:  the error number
846
 * @msg:  the message
847
 * @info1:  extra information string
848
 * @info2:  extra information string
849
 *
850
 * Handle a namespace warning error
851
 */
852
static void LIBXML_ATTR_FORMAT(3,0)
853
xmlNsWarn(xmlParserCtxtPtr ctxt, xmlParserErrors error,
854
         const char *msg,
855
         const xmlChar * info1, const xmlChar * info2,
856
         const xmlChar * info3)
857
506
{
858
506
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
859
506
        (ctxt->instate == XML_PARSER_EOF))
860
0
  return;
861
506
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
862
506
                    XML_ERR_WARNING, NULL, 0, (const char *) info1,
863
506
                    (const char *) info2, (const char *) info3, 0, 0, msg,
864
506
                    info1, info2, info3);
865
506
}
866
867
/************************************************************************
868
 *                  *
869
 *    Library wide options          *
870
 *                  *
871
 ************************************************************************/
872
873
/**
874
  * xmlHasFeature:
875
  * @feature: the feature to be examined
876
  *
877
  * Examines if the library has been compiled with a given feature.
878
  *
879
  * Returns a non-zero value if the feature exist, otherwise zero.
880
  * Returns zero (0) if the feature does not exist or an unknown
881
  * unknown feature is requested, non-zero otherwise.
882
  */
883
int
884
xmlHasFeature(xmlFeature feature)
885
0
{
886
0
    switch (feature) {
887
0
  case XML_WITH_THREAD:
888
0
#ifdef LIBXML_THREAD_ENABLED
889
0
      return(1);
890
#else
891
      return(0);
892
#endif
893
0
        case XML_WITH_TREE:
894
0
#ifdef LIBXML_TREE_ENABLED
895
0
            return(1);
896
#else
897
            return(0);
898
#endif
899
0
        case XML_WITH_OUTPUT:
900
0
#ifdef LIBXML_OUTPUT_ENABLED
901
0
            return(1);
902
#else
903
            return(0);
904
#endif
905
0
        case XML_WITH_PUSH:
906
#ifdef LIBXML_PUSH_ENABLED
907
            return(1);
908
#else
909
0
            return(0);
910
0
#endif
911
0
        case XML_WITH_READER:
912
#ifdef LIBXML_READER_ENABLED
913
            return(1);
914
#else
915
0
            return(0);
916
0
#endif
917
0
        case XML_WITH_PATTERN:
918
0
#ifdef LIBXML_PATTERN_ENABLED
919
0
            return(1);
920
#else
921
            return(0);
922
#endif
923
0
        case XML_WITH_WRITER:
924
#ifdef LIBXML_WRITER_ENABLED
925
            return(1);
926
#else
927
0
            return(0);
928
0
#endif
929
0
        case XML_WITH_SAX1:
930
#ifdef LIBXML_SAX1_ENABLED
931
            return(1);
932
#else
933
0
            return(0);
934
0
#endif
935
0
        case XML_WITH_FTP:
936
#ifdef LIBXML_FTP_ENABLED
937
            return(1);
938
#else
939
0
            return(0);
940
0
#endif
941
0
        case XML_WITH_HTTP:
942
0
#ifdef LIBXML_HTTP_ENABLED
943
0
            return(1);
944
#else
945
            return(0);
946
#endif
947
0
        case XML_WITH_VALID:
948
#ifdef LIBXML_VALID_ENABLED
949
            return(1);
950
#else
951
0
            return(0);
952
0
#endif
953
0
        case XML_WITH_HTML:
954
0
#ifdef LIBXML_HTML_ENABLED
955
0
            return(1);
956
#else
957
            return(0);
958
#endif
959
0
        case XML_WITH_LEGACY:
960
#ifdef LIBXML_LEGACY_ENABLED
961
            return(1);
962
#else
963
0
            return(0);
964
0
#endif
965
0
        case XML_WITH_C14N:
966
#ifdef LIBXML_C14N_ENABLED
967
            return(1);
968
#else
969
0
            return(0);
970
0
#endif
971
0
        case XML_WITH_CATALOG:
972
0
#ifdef LIBXML_CATALOG_ENABLED
973
0
            return(1);
974
#else
975
            return(0);
976
#endif
977
0
        case XML_WITH_XPATH:
978
0
#ifdef LIBXML_XPATH_ENABLED
979
0
            return(1);
980
#else
981
            return(0);
982
#endif
983
0
        case XML_WITH_XPTR:
984
0
#ifdef LIBXML_XPTR_ENABLED
985
0
            return(1);
986
#else
987
            return(0);
988
#endif
989
0
        case XML_WITH_XINCLUDE:
990
0
#ifdef LIBXML_XINCLUDE_ENABLED
991
0
            return(1);
992
#else
993
            return(0);
994
#endif
995
0
        case XML_WITH_ICONV:
996
0
#ifdef LIBXML_ICONV_ENABLED
997
0
            return(1);
998
#else
999
            return(0);
1000
#endif
1001
0
        case XML_WITH_ISO8859X:
1002
0
#ifdef LIBXML_ISO8859X_ENABLED
1003
0
            return(1);
1004
#else
1005
            return(0);
1006
#endif
1007
0
        case XML_WITH_UNICODE:
1008
#ifdef LIBXML_UNICODE_ENABLED
1009
            return(1);
1010
#else
1011
0
            return(0);
1012
0
#endif
1013
0
        case XML_WITH_REGEXP:
1014
#ifdef LIBXML_REGEXP_ENABLED
1015
            return(1);
1016
#else
1017
0
            return(0);
1018
0
#endif
1019
0
        case XML_WITH_AUTOMATA:
1020
#ifdef LIBXML_AUTOMATA_ENABLED
1021
            return(1);
1022
#else
1023
0
            return(0);
1024
0
#endif
1025
0
        case XML_WITH_EXPR:
1026
#ifdef LIBXML_EXPR_ENABLED
1027
            return(1);
1028
#else
1029
0
            return(0);
1030
0
#endif
1031
0
        case XML_WITH_SCHEMAS:
1032
#ifdef LIBXML_SCHEMAS_ENABLED
1033
            return(1);
1034
#else
1035
0
            return(0);
1036
0
#endif
1037
0
        case XML_WITH_SCHEMATRON:
1038
#ifdef LIBXML_SCHEMATRON_ENABLED
1039
            return(1);
1040
#else
1041
0
            return(0);
1042
0
#endif
1043
0
        case XML_WITH_MODULES:
1044
0
#ifdef LIBXML_MODULES_ENABLED
1045
0
            return(1);
1046
#else
1047
            return(0);
1048
#endif
1049
0
        case XML_WITH_DEBUG:
1050
0
#ifdef LIBXML_DEBUG_ENABLED
1051
0
            return(1);
1052
#else
1053
            return(0);
1054
#endif
1055
0
        case XML_WITH_DEBUG_MEM:
1056
#ifdef DEBUG_MEMORY_LOCATION
1057
            return(1);
1058
#else
1059
0
            return(0);
1060
0
#endif
1061
0
        case XML_WITH_DEBUG_RUN:
1062
0
            return(0);
1063
0
        case XML_WITH_ZLIB:
1064
#ifdef LIBXML_ZLIB_ENABLED
1065
            return(1);
1066
#else
1067
0
            return(0);
1068
0
#endif
1069
0
        case XML_WITH_LZMA:
1070
#ifdef LIBXML_LZMA_ENABLED
1071
            return(1);
1072
#else
1073
0
            return(0);
1074
0
#endif
1075
0
        case XML_WITH_ICU:
1076
#ifdef LIBXML_ICU_ENABLED
1077
            return(1);
1078
#else
1079
0
            return(0);
1080
0
#endif
1081
0
        default:
1082
0
      break;
1083
0
     }
1084
0
     return(0);
1085
0
}
1086
1087
/************************************************************************
1088
 *                  *
1089
 *    SAX2 defaulted attributes handling      *
1090
 *                  *
1091
 ************************************************************************/
1092
1093
/**
1094
 * xmlDetectSAX2:
1095
 * @ctxt:  an XML parser context
1096
 *
1097
 * Do the SAX2 detection and specific initialization
1098
 */
1099
static void
1100
325
xmlDetectSAX2(xmlParserCtxtPtr ctxt) {
1101
325
    xmlSAXHandlerPtr sax;
1102
1103
    /* Avoid unused variable warning if features are disabled. */
1104
325
    (void) sax;
1105
1106
325
    if (ctxt == NULL) return;
1107
325
    sax = ctxt->sax;
1108
#ifdef LIBXML_SAX1_ENABLED
1109
    if ((sax) &&  (sax->initialized == XML_SAX2_MAGIC) &&
1110
        ((sax->startElementNs != NULL) ||
1111
         (sax->endElementNs != NULL) ||
1112
         ((sax->startElement == NULL) && (sax->endElement == NULL))))
1113
        ctxt->sax2 = 1;
1114
#else
1115
325
    ctxt->sax2 = 1;
1116
325
#endif /* LIBXML_SAX1_ENABLED */
1117
1118
325
    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
1119
325
    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
1120
325
    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
1121
325
    if ((ctxt->str_xml==NULL) || (ctxt->str_xmlns==NULL) ||
1122
325
    (ctxt->str_xml_ns == NULL)) {
1123
0
        xmlErrMemory(ctxt, NULL);
1124
0
    }
1125
325
}
1126
1127
typedef struct _xmlDefAttrs xmlDefAttrs;
1128
typedef xmlDefAttrs *xmlDefAttrsPtr;
1129
struct _xmlDefAttrs {
1130
    int nbAttrs;  /* number of defaulted attributes on that element */
1131
    int maxAttrs;       /* the size of the array */
1132
#if __STDC_VERSION__ >= 199901L
1133
    /* Using a C99 flexible array member avoids UBSan errors. */
1134
    const xmlChar *values[]; /* array of localname/prefix/values/external */
1135
#else
1136
    const xmlChar *values[5];
1137
#endif
1138
};
1139
1140
/**
1141
 * xmlAttrNormalizeSpace:
1142
 * @src: the source string
1143
 * @dst: the target string
1144
 *
1145
 * Normalize the space in non CDATA attribute values:
1146
 * If the attribute type is not CDATA, then the XML processor MUST further
1147
 * process the normalized attribute value by discarding any leading and
1148
 * trailing space (#x20) characters, and by replacing sequences of space
1149
 * (#x20) characters by a single space (#x20) character.
1150
 * Note that the size of dst need to be at least src, and if one doesn't need
1151
 * to preserve dst (and it doesn't come from a dictionary or read-only) then
1152
 * passing src as dst is just fine.
1153
 *
1154
 * Returns a pointer to the normalized value (dst) or NULL if no conversion
1155
 *         is needed.
1156
 */
1157
static xmlChar *
1158
xmlAttrNormalizeSpace(const xmlChar *src, xmlChar *dst)
1159
598
{
1160
598
    if ((src == NULL) || (dst == NULL))
1161
0
        return(NULL);
1162
1163
610
    while (*src == 0x20) src++;
1164
1.35k
    while (*src != 0) {
1165
757
  if (*src == 0x20) {
1166
0
      while (*src == 0x20) src++;
1167
0
      if (*src != 0)
1168
0
    *dst++ = 0x20;
1169
757
  } else {
1170
757
      *dst++ = *src++;
1171
757
  }
1172
757
    }
1173
598
    *dst = 0;
1174
598
    if (dst == src)
1175
586
       return(NULL);
1176
12
    return(dst);
1177
598
}
1178
1179
/**
1180
 * xmlAttrNormalizeSpace2:
1181
 * @src: the source string
1182
 *
1183
 * Normalize the space in non CDATA attribute values, a slightly more complex
1184
 * front end to avoid allocation problems when running on attribute values
1185
 * coming from the input.
1186
 *
1187
 * Returns a pointer to the normalized value (dst) or NULL if no conversion
1188
 *         is needed.
1189
 */
1190
static const xmlChar *
1191
xmlAttrNormalizeSpace2(xmlParserCtxtPtr ctxt, xmlChar *src, int *len)
1192
0
{
1193
0
    int i;
1194
0
    int remove_head = 0;
1195
0
    int need_realloc = 0;
1196
0
    const xmlChar *cur;
1197
1198
0
    if ((ctxt == NULL) || (src == NULL) || (len == NULL))
1199
0
        return(NULL);
1200
0
    i = *len;
1201
0
    if (i <= 0)
1202
0
        return(NULL);
1203
1204
0
    cur = src;
1205
0
    while (*cur == 0x20) {
1206
0
        cur++;
1207
0
  remove_head++;
1208
0
    }
1209
0
    while (*cur != 0) {
1210
0
  if (*cur == 0x20) {
1211
0
      cur++;
1212
0
      if ((*cur == 0x20) || (*cur == 0)) {
1213
0
          need_realloc = 1;
1214
0
    break;
1215
0
      }
1216
0
  } else
1217
0
      cur++;
1218
0
    }
1219
0
    if (need_realloc) {
1220
0
        xmlChar *ret;
1221
1222
0
  ret = xmlStrndup(src + remove_head, i - remove_head + 1);
1223
0
  if (ret == NULL) {
1224
0
      xmlErrMemory(ctxt, NULL);
1225
0
      return(NULL);
1226
0
  }
1227
0
  xmlAttrNormalizeSpace(ret, ret);
1228
0
  *len = strlen((const char *)ret);
1229
0
        return(ret);
1230
0
    } else if (remove_head) {
1231
0
        *len -= remove_head;
1232
0
        memmove(src, src + remove_head, 1 + *len);
1233
0
  return(src);
1234
0
    }
1235
0
    return(NULL);
1236
0
}
1237
1238
/**
1239
 * xmlAddDefAttrs:
1240
 * @ctxt:  an XML parser context
1241
 * @fullname:  the element fullname
1242
 * @fullattr:  the attribute fullname
1243
 * @value:  the attribute value
1244
 *
1245
 * Add a defaulted attribute for an element
1246
 */
1247
static void
1248
xmlAddDefAttrs(xmlParserCtxtPtr ctxt,
1249
               const xmlChar *fullname,
1250
               const xmlChar *fullattr,
1251
598
               const xmlChar *value) {
1252
598
    xmlDefAttrsPtr defaults;
1253
598
    int len;
1254
598
    const xmlChar *name;
1255
598
    const xmlChar *prefix;
1256
1257
    /*
1258
     * Allows to detect attribute redefinitions
1259
     */
1260
598
    if (ctxt->attsSpecial != NULL) {
1261
585
        if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL)
1262
483
      return;
1263
585
    }
1264
1265
115
    if (ctxt->attsDefault == NULL) {
1266
13
        ctxt->attsDefault = xmlHashCreateDict(10, ctxt->dict);
1267
13
  if (ctxt->attsDefault == NULL)
1268
0
      goto mem_error;
1269
13
    }
1270
1271
    /*
1272
     * split the element name into prefix:localname , the string found
1273
     * are within the DTD and then not associated to namespace names.
1274
     */
1275
115
    name = xmlSplitQName3(fullname, &len);
1276
115
    if (name == NULL) {
1277
115
        name = xmlDictLookup(ctxt->dict, fullname, -1);
1278
115
  prefix = NULL;
1279
115
    } else {
1280
0
        name = xmlDictLookup(ctxt->dict, name, -1);
1281
0
  prefix = xmlDictLookup(ctxt->dict, fullname, len);
1282
0
    }
1283
1284
    /*
1285
     * make sure there is some storage
1286
     */
1287
115
    defaults = xmlHashLookup2(ctxt->attsDefault, name, prefix);
1288
115
    if (defaults == NULL) {
1289
13
        defaults = (xmlDefAttrsPtr) xmlMalloc(sizeof(xmlDefAttrs) +
1290
13
                     (4 * 5) * sizeof(const xmlChar *));
1291
13
  if (defaults == NULL)
1292
0
      goto mem_error;
1293
13
  defaults->nbAttrs = 0;
1294
13
  defaults->maxAttrs = 4;
1295
13
  if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix,
1296
13
                          defaults, NULL) < 0) {
1297
0
      xmlFree(defaults);
1298
0
      goto mem_error;
1299
0
  }
1300
102
    } else if (defaults->nbAttrs >= defaults->maxAttrs) {
1301
12
        xmlDefAttrsPtr temp;
1302
1303
12
        temp = (xmlDefAttrsPtr) xmlRealloc(defaults, sizeof(xmlDefAttrs) +
1304
12
           (2 * defaults->maxAttrs * 5) * sizeof(const xmlChar *));
1305
12
  if (temp == NULL)
1306
0
      goto mem_error;
1307
12
  defaults = temp;
1308
12
  defaults->maxAttrs *= 2;
1309
12
  if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix,
1310
12
                          defaults, NULL) < 0) {
1311
0
      xmlFree(defaults);
1312
0
      goto mem_error;
1313
0
  }
1314
12
    }
1315
1316
    /*
1317
     * Split the element name into prefix:localname , the string found
1318
     * are within the DTD and hen not associated to namespace names.
1319
     */
1320
115
    name = xmlSplitQName3(fullattr, &len);
1321
115
    if (name == NULL) {
1322
13
        name = xmlDictLookup(ctxt->dict, fullattr, -1);
1323
13
  prefix = NULL;
1324
102
    } else {
1325
102
        name = xmlDictLookup(ctxt->dict, name, -1);
1326
102
  prefix = xmlDictLookup(ctxt->dict, fullattr, len);
1327
102
    }
1328
1329
115
    defaults->values[5 * defaults->nbAttrs] = name;
1330
115
    defaults->values[5 * defaults->nbAttrs + 1] = prefix;
1331
    /* intern the string and precompute the end */
1332
115
    len = xmlStrlen(value);
1333
115
    value = xmlDictLookup(ctxt->dict, value, len);
1334
115
    defaults->values[5 * defaults->nbAttrs + 2] = value;
1335
115
    defaults->values[5 * defaults->nbAttrs + 3] = value + len;
1336
115
    if (ctxt->external)
1337
0
        defaults->values[5 * defaults->nbAttrs + 4] = BAD_CAST "external";
1338
115
    else
1339
115
        defaults->values[5 * defaults->nbAttrs + 4] = NULL;
1340
115
    defaults->nbAttrs++;
1341
1342
115
    return;
1343
1344
0
mem_error:
1345
0
    xmlErrMemory(ctxt, NULL);
1346
0
    return;
1347
115
}
1348
1349
/**
1350
 * xmlAddSpecialAttr:
1351
 * @ctxt:  an XML parser context
1352
 * @fullname:  the element fullname
1353
 * @fullattr:  the attribute fullname
1354
 * @type:  the attribute type
1355
 *
1356
 * Register this attribute type
1357
 */
1358
static void
1359
xmlAddSpecialAttr(xmlParserCtxtPtr ctxt,
1360
      const xmlChar *fullname,
1361
      const xmlChar *fullattr,
1362
      int type)
1363
1.08k
{
1364
1.08k
    if (ctxt->attsSpecial == NULL) {
1365
14
        ctxt->attsSpecial = xmlHashCreateDict(10, ctxt->dict);
1366
14
  if (ctxt->attsSpecial == NULL)
1367
0
      goto mem_error;
1368
14
    }
1369
1370
1.08k
    if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL)
1371
968
        return;
1372
1373
116
    xmlHashAddEntry2(ctxt->attsSpecial, fullname, fullattr,
1374
116
                     (void *) (ptrdiff_t) type);
1375
116
    return;
1376
1377
0
mem_error:
1378
0
    xmlErrMemory(ctxt, NULL);
1379
0
    return;
1380
1.08k
}
1381
1382
/**
1383
 * xmlCleanSpecialAttrCallback:
1384
 *
1385
 * Removes CDATA attributes from the special attribute table
1386
 */
1387
static void
1388
xmlCleanSpecialAttrCallback(void *payload, void *data,
1389
                            const xmlChar *fullname, const xmlChar *fullattr,
1390
115
                            const xmlChar *unused ATTRIBUTE_UNUSED) {
1391
115
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) data;
1392
1393
115
    if (((ptrdiff_t) payload) == XML_ATTRIBUTE_CDATA) {
1394
0
        xmlHashRemoveEntry2(ctxt->attsSpecial, fullname, fullattr, NULL);
1395
0
    }
1396
115
}
1397
1398
/**
1399
 * xmlCleanSpecialAttr:
1400
 * @ctxt:  an XML parser context
1401
 *
1402
 * Trim the list of attributes defined to remove all those of type
1403
 * CDATA as they are not special. This call should be done when finishing
1404
 * to parse the DTD and before starting to parse the document root.
1405
 */
1406
static void
1407
xmlCleanSpecialAttr(xmlParserCtxtPtr ctxt)
1408
95
{
1409
95
    if (ctxt->attsSpecial == NULL)
1410
82
        return;
1411
1412
13
    xmlHashScanFull(ctxt->attsSpecial, xmlCleanSpecialAttrCallback, ctxt);
1413
1414
13
    if (xmlHashSize(ctxt->attsSpecial) == 0) {
1415
0
        xmlHashFree(ctxt->attsSpecial, NULL);
1416
0
        ctxt->attsSpecial = NULL;
1417
0
    }
1418
13
    return;
1419
95
}
1420
1421
/**
1422
 * xmlCheckLanguageID:
1423
 * @lang:  pointer to the string value
1424
 *
1425
 * Checks that the value conforms to the LanguageID production:
1426
 *
1427
 * NOTE: this is somewhat deprecated, those productions were removed from
1428
 *       the XML Second edition.
1429
 *
1430
 * [33] LanguageID ::= Langcode ('-' Subcode)*
1431
 * [34] Langcode ::= ISO639Code |  IanaCode |  UserCode
1432
 * [35] ISO639Code ::= ([a-z] | [A-Z]) ([a-z] | [A-Z])
1433
 * [36] IanaCode ::= ('i' | 'I') '-' ([a-z] | [A-Z])+
1434
 * [37] UserCode ::= ('x' | 'X') '-' ([a-z] | [A-Z])+
1435
 * [38] Subcode ::= ([a-z] | [A-Z])+
1436
 *
1437
 * The current REC reference the successors of RFC 1766, currently 5646
1438
 *
1439
 * http://www.rfc-editor.org/rfc/rfc5646.txt
1440
 * langtag       = language
1441
 *                 ["-" script]
1442
 *                 ["-" region]
1443
 *                 *("-" variant)
1444
 *                 *("-" extension)
1445
 *                 ["-" privateuse]
1446
 * language      = 2*3ALPHA            ; shortest ISO 639 code
1447
 *                 ["-" extlang]       ; sometimes followed by
1448
 *                                     ; extended language subtags
1449
 *               / 4ALPHA              ; or reserved for future use
1450
 *               / 5*8ALPHA            ; or registered language subtag
1451
 *
1452
 * extlang       = 3ALPHA              ; selected ISO 639 codes
1453
 *                 *2("-" 3ALPHA)      ; permanently reserved
1454
 *
1455
 * script        = 4ALPHA              ; ISO 15924 code
1456
 *
1457
 * region        = 2ALPHA              ; ISO 3166-1 code
1458
 *               / 3DIGIT              ; UN M.49 code
1459
 *
1460
 * variant       = 5*8alphanum         ; registered variants
1461
 *               / (DIGIT 3alphanum)
1462
 *
1463
 * extension     = singleton 1*("-" (2*8alphanum))
1464
 *
1465
 *                                     ; Single alphanumerics
1466
 *                                     ; "x" reserved for private use
1467
 * singleton     = DIGIT               ; 0 - 9
1468
 *               / %x41-57             ; A - W
1469
 *               / %x59-5A             ; Y - Z
1470
 *               / %x61-77             ; a - w
1471
 *               / %x79-7A             ; y - z
1472
 *
1473
 * it sounds right to still allow Irregular i-xxx IANA and user codes too
1474
 * The parser below doesn't try to cope with extension or privateuse
1475
 * that could be added but that's not interoperable anyway
1476
 *
1477
 * Returns 1 if correct 0 otherwise
1478
 **/
1479
int
1480
xmlCheckLanguageID(const xmlChar * lang)
1481
0
{
1482
0
    const xmlChar *cur = lang, *nxt;
1483
1484
0
    if (cur == NULL)
1485
0
        return (0);
1486
0
    if (((cur[0] == 'i') && (cur[1] == '-')) ||
1487
0
        ((cur[0] == 'I') && (cur[1] == '-')) ||
1488
0
        ((cur[0] == 'x') && (cur[1] == '-')) ||
1489
0
        ((cur[0] == 'X') && (cur[1] == '-'))) {
1490
        /*
1491
         * Still allow IANA code and user code which were coming
1492
         * from the previous version of the XML-1.0 specification
1493
         * it's deprecated but we should not fail
1494
         */
1495
0
        cur += 2;
1496
0
        while (((cur[0] >= 'A') && (cur[0] <= 'Z')) ||
1497
0
               ((cur[0] >= 'a') && (cur[0] <= 'z')))
1498
0
            cur++;
1499
0
        return(cur[0] == 0);
1500
0
    }
1501
0
    nxt = cur;
1502
0
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1503
0
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1504
0
           nxt++;
1505
0
    if (nxt - cur >= 4) {
1506
        /*
1507
         * Reserved
1508
         */
1509
0
        if ((nxt - cur > 8) || (nxt[0] != 0))
1510
0
            return(0);
1511
0
        return(1);
1512
0
    }
1513
0
    if (nxt - cur < 2)
1514
0
        return(0);
1515
    /* we got an ISO 639 code */
1516
0
    if (nxt[0] == 0)
1517
0
        return(1);
1518
0
    if (nxt[0] != '-')
1519
0
        return(0);
1520
1521
0
    nxt++;
1522
0
    cur = nxt;
1523
    /* now we can have extlang or script or region or variant */
1524
0
    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1525
0
        goto region_m49;
1526
1527
0
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1528
0
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1529
0
           nxt++;
1530
0
    if (nxt - cur == 4)
1531
0
        goto script;
1532
0
    if (nxt - cur == 2)
1533
0
        goto region;
1534
0
    if ((nxt - cur >= 5) && (nxt - cur <= 8))
1535
0
        goto variant;
1536
0
    if (nxt - cur != 3)
1537
0
        return(0);
1538
    /* we parsed an extlang */
1539
0
    if (nxt[0] == 0)
1540
0
        return(1);
1541
0
    if (nxt[0] != '-')
1542
0
        return(0);
1543
1544
0
    nxt++;
1545
0
    cur = nxt;
1546
    /* now we can have script or region or variant */
1547
0
    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1548
0
        goto region_m49;
1549
1550
0
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1551
0
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1552
0
           nxt++;
1553
0
    if (nxt - cur == 2)
1554
0
        goto region;
1555
0
    if ((nxt - cur >= 5) && (nxt - cur <= 8))
1556
0
        goto variant;
1557
0
    if (nxt - cur != 4)
1558
0
        return(0);
1559
    /* we parsed a script */
1560
0
script:
1561
0
    if (nxt[0] == 0)
1562
0
        return(1);
1563
0
    if (nxt[0] != '-')
1564
0
        return(0);
1565
1566
0
    nxt++;
1567
0
    cur = nxt;
1568
    /* now we can have region or variant */
1569
0
    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1570
0
        goto region_m49;
1571
1572
0
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1573
0
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1574
0
           nxt++;
1575
1576
0
    if ((nxt - cur >= 5) && (nxt - cur <= 8))
1577
0
        goto variant;
1578
0
    if (nxt - cur != 2)
1579
0
        return(0);
1580
    /* we parsed a region */
1581
0
region:
1582
0
    if (nxt[0] == 0)
1583
0
        return(1);
1584
0
    if (nxt[0] != '-')
1585
0
        return(0);
1586
1587
0
    nxt++;
1588
0
    cur = nxt;
1589
    /* now we can just have a variant */
1590
0
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1591
0
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1592
0
           nxt++;
1593
1594
0
    if ((nxt - cur < 5) || (nxt - cur > 8))
1595
0
        return(0);
1596
1597
    /* we parsed a variant */
1598
0
variant:
1599
0
    if (nxt[0] == 0)
1600
0
        return(1);
1601
0
    if (nxt[0] != '-')
1602
0
        return(0);
1603
    /* extensions and private use subtags not checked */
1604
0
    return (1);
1605
1606
0
region_m49:
1607
0
    if (((nxt[1] >= '0') && (nxt[1] <= '9')) &&
1608
0
        ((nxt[2] >= '0') && (nxt[2] <= '9'))) {
1609
0
        nxt += 3;
1610
0
        goto region;
1611
0
    }
1612
0
    return(0);
1613
0
}
1614
1615
/************************************************************************
1616
 *                  *
1617
 *    Parser stacks related functions and macros    *
1618
 *                  *
1619
 ************************************************************************/
1620
1621
static xmlEntityPtr xmlParseStringEntityRef(xmlParserCtxtPtr ctxt,
1622
                                            const xmlChar ** str);
1623
1624
#ifdef SAX2
1625
/**
1626
 * nsPush:
1627
 * @ctxt:  an XML parser context
1628
 * @prefix:  the namespace prefix or NULL
1629
 * @URL:  the namespace name
1630
 *
1631
 * Pushes a new parser namespace on top of the ns stack
1632
 *
1633
 * Returns -1 in case of error, -2 if the namespace should be discarded
1634
 *     and the index in the stack otherwise.
1635
 */
1636
static int
1637
nsPush(xmlParserCtxtPtr ctxt, const xmlChar *prefix, const xmlChar *URL)
1638
3.78k
{
1639
3.78k
    if (ctxt->options & XML_PARSE_NSCLEAN) {
1640
0
        int i;
1641
0
  for (i = ctxt->nsNr - 2;i >= 0;i -= 2) {
1642
0
      if (ctxt->nsTab[i] == prefix) {
1643
    /* in scope */
1644
0
          if (ctxt->nsTab[i + 1] == URL)
1645
0
        return(-2);
1646
    /* out of scope keep it */
1647
0
    break;
1648
0
      }
1649
0
  }
1650
0
    }
1651
3.78k
    if ((ctxt->nsMax == 0) || (ctxt->nsTab == NULL)) {
1652
215
  ctxt->nsMax = 10;
1653
215
  ctxt->nsNr = 0;
1654
215
  ctxt->nsTab = (const xmlChar **)
1655
215
                xmlMalloc(ctxt->nsMax * sizeof(xmlChar *));
1656
215
  if (ctxt->nsTab == NULL) {
1657
0
      xmlErrMemory(ctxt, NULL);
1658
0
      ctxt->nsMax = 0;
1659
0
            return (-1);
1660
0
  }
1661
3.57k
    } else if (ctxt->nsNr >= ctxt->nsMax) {
1662
8
        const xmlChar ** tmp;
1663
8
        ctxt->nsMax *= 2;
1664
8
        tmp = (const xmlChar **) xmlRealloc((char *) ctxt->nsTab,
1665
8
            ctxt->nsMax * sizeof(ctxt->nsTab[0]));
1666
8
        if (tmp == NULL) {
1667
0
            xmlErrMemory(ctxt, NULL);
1668
0
      ctxt->nsMax /= 2;
1669
0
            return (-1);
1670
0
        }
1671
8
  ctxt->nsTab = tmp;
1672
8
    }
1673
3.78k
    ctxt->nsTab[ctxt->nsNr++] = prefix;
1674
3.78k
    ctxt->nsTab[ctxt->nsNr++] = URL;
1675
3.78k
    return (ctxt->nsNr);
1676
3.78k
}
1677
/**
1678
 * nsPop:
1679
 * @ctxt: an XML parser context
1680
 * @nr:  the number to pop
1681
 *
1682
 * Pops the top @nr parser prefix/namespace from the ns stack
1683
 *
1684
 * Returns the number of namespaces removed
1685
 */
1686
static int
1687
nsPop(xmlParserCtxtPtr ctxt, int nr)
1688
2.97k
{
1689
2.97k
    int i;
1690
1691
2.97k
    if (ctxt->nsTab == NULL) return(0);
1692
2.97k
    if (ctxt->nsNr < nr) {
1693
0
        xmlGenericError(xmlGenericErrorContext, "Pbm popping %d NS\n", nr);
1694
0
        nr = ctxt->nsNr;
1695
0
    }
1696
2.97k
    if (ctxt->nsNr <= 0)
1697
0
        return (0);
1698
1699
10.1k
    for (i = 0;i < nr;i++) {
1700
7.13k
         ctxt->nsNr--;
1701
7.13k
   ctxt->nsTab[ctxt->nsNr] = NULL;
1702
7.13k
    }
1703
2.97k
    return(nr);
1704
2.97k
}
1705
#endif
1706
1707
static int
1708
183
xmlCtxtGrowAttrs(xmlParserCtxtPtr ctxt, int nr) {
1709
183
    const xmlChar **atts;
1710
183
    int *attallocs;
1711
183
    int maxatts;
1712
1713
183
    if (ctxt->atts == NULL) {
1714
183
  maxatts = 55; /* allow for 10 attrs by default */
1715
183
  atts = (const xmlChar **)
1716
183
         xmlMalloc(maxatts * sizeof(xmlChar *));
1717
183
  if (atts == NULL) goto mem_error;
1718
183
  ctxt->atts = atts;
1719
183
  attallocs = (int *) xmlMalloc((maxatts / 5) * sizeof(int));
1720
183
  if (attallocs == NULL) goto mem_error;
1721
183
  ctxt->attallocs = attallocs;
1722
183
  ctxt->maxatts = maxatts;
1723
183
    } else if (nr + 5 > ctxt->maxatts) {
1724
0
  maxatts = (nr + 5) * 2;
1725
0
  atts = (const xmlChar **) xmlRealloc((void *) ctxt->atts,
1726
0
             maxatts * sizeof(const xmlChar *));
1727
0
  if (atts == NULL) goto mem_error;
1728
0
  ctxt->atts = atts;
1729
0
  attallocs = (int *) xmlRealloc((void *) ctxt->attallocs,
1730
0
                               (maxatts / 5) * sizeof(int));
1731
0
  if (attallocs == NULL) goto mem_error;
1732
0
  ctxt->attallocs = attallocs;
1733
0
  ctxt->maxatts = maxatts;
1734
0
    }
1735
183
    return(ctxt->maxatts);
1736
0
mem_error:
1737
0
    xmlErrMemory(ctxt, NULL);
1738
0
    return(-1);
1739
183
}
1740
1741
/**
1742
 * inputPush:
1743
 * @ctxt:  an XML parser context
1744
 * @value:  the parser input
1745
 *
1746
 * Pushes a new parser input on top of the input stack
1747
 *
1748
 * Returns -1 in case of error, the index in the stack otherwise
1749
 */
1750
int
1751
inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value)
1752
7.09k
{
1753
7.09k
    if ((ctxt == NULL) || (value == NULL))
1754
0
        return(-1);
1755
7.09k
    if (ctxt->inputNr >= ctxt->inputMax) {
1756
0
        ctxt->inputMax *= 2;
1757
0
        ctxt->inputTab =
1758
0
            (xmlParserInputPtr *) xmlRealloc(ctxt->inputTab,
1759
0
                                             ctxt->inputMax *
1760
0
                                             sizeof(ctxt->inputTab[0]));
1761
0
        if (ctxt->inputTab == NULL) {
1762
0
            xmlErrMemory(ctxt, NULL);
1763
0
      ctxt->inputMax /= 2;
1764
0
            return (-1);
1765
0
        }
1766
0
    }
1767
7.09k
    ctxt->inputTab[ctxt->inputNr] = value;
1768
7.09k
    ctxt->input = value;
1769
7.09k
    return (ctxt->inputNr++);
1770
7.09k
}
1771
/**
1772
 * inputPop:
1773
 * @ctxt: an XML parser context
1774
 *
1775
 * Pops the top parser input from the input stack
1776
 *
1777
 * Returns the input just removed
1778
 */
1779
xmlParserInputPtr
1780
inputPop(xmlParserCtxtPtr ctxt)
1781
9.42k
{
1782
9.42k
    xmlParserInputPtr ret;
1783
1784
9.42k
    if (ctxt == NULL)
1785
0
        return(NULL);
1786
9.42k
    if (ctxt->inputNr <= 0)
1787
2.32k
        return (NULL);
1788
7.09k
    ctxt->inputNr--;
1789
7.09k
    if (ctxt->inputNr > 0)
1790
6.77k
        ctxt->input = ctxt->inputTab[ctxt->inputNr - 1];
1791
325
    else
1792
325
        ctxt->input = NULL;
1793
7.09k
    ret = ctxt->inputTab[ctxt->inputNr];
1794
7.09k
    ctxt->inputTab[ctxt->inputNr] = NULL;
1795
7.09k
    return (ret);
1796
9.42k
}
1797
/**
1798
 * nodePush:
1799
 * @ctxt:  an XML parser context
1800
 * @value:  the element node
1801
 *
1802
 * Pushes a new element node on top of the node stack
1803
 *
1804
 * Returns -1 in case of error, the index in the stack otherwise
1805
 */
1806
int
1807
nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value)
1808
106k
{
1809
106k
    if (ctxt == NULL) return(0);
1810
106k
    if (ctxt->nodeNr >= ctxt->nodeMax) {
1811
4
        xmlNodePtr *tmp;
1812
1813
4
  tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
1814
4
                                      ctxt->nodeMax * 2 *
1815
4
                                      sizeof(ctxt->nodeTab[0]));
1816
4
        if (tmp == NULL) {
1817
0
            xmlErrMemory(ctxt, NULL);
1818
0
            return (-1);
1819
0
        }
1820
4
        ctxt->nodeTab = tmp;
1821
4
  ctxt->nodeMax *= 2;
1822
4
    }
1823
106k
    if ((((unsigned int) ctxt->nodeNr) > xmlParserMaxDepth) &&
1824
106k
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
1825
0
  xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
1826
0
     "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
1827
0
        xmlParserMaxDepth);
1828
0
  xmlHaltParser(ctxt);
1829
0
  return(-1);
1830
0
    }
1831
106k
    ctxt->nodeTab[ctxt->nodeNr] = value;
1832
106k
    ctxt->node = value;
1833
106k
    return (ctxt->nodeNr++);
1834
106k
}
1835
1836
/**
1837
 * nodePop:
1838
 * @ctxt: an XML parser context
1839
 *
1840
 * Pops the top element node from the node stack
1841
 *
1842
 * Returns the node just removed
1843
 */
1844
xmlNodePtr
1845
nodePop(xmlParserCtxtPtr ctxt)
1846
113k
{
1847
113k
    xmlNodePtr ret;
1848
1849
113k
    if (ctxt == NULL) return(NULL);
1850
113k
    if (ctxt->nodeNr <= 0)
1851
7.64k
        return (NULL);
1852
106k
    ctxt->nodeNr--;
1853
106k
    if (ctxt->nodeNr > 0)
1854
105k
        ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1];
1855
143
    else
1856
143
        ctxt->node = NULL;
1857
106k
    ret = ctxt->nodeTab[ctxt->nodeNr];
1858
106k
    ctxt->nodeTab[ctxt->nodeNr] = NULL;
1859
106k
    return (ret);
1860
113k
}
1861
1862
/**
1863
 * nameNsPush:
1864
 * @ctxt:  an XML parser context
1865
 * @value:  the element name
1866
 * @prefix:  the element prefix
1867
 * @URI:  the element namespace name
1868
 * @line:  the current line number for error messages
1869
 * @nsNr:  the number of namespaces pushed on the namespace table
1870
 *
1871
 * Pushes a new element name/prefix/URL on top of the name stack
1872
 *
1873
 * Returns -1 in case of error, the index in the stack otherwise
1874
 */
1875
static int
1876
nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
1877
           const xmlChar *prefix, const xmlChar *URI, int line, int nsNr)
1878
125k
{
1879
125k
    xmlStartTag *tag;
1880
1881
125k
    if (ctxt->nameNr >= ctxt->nameMax) {
1882
45
        const xmlChar * *tmp;
1883
45
        xmlStartTag *tmp2;
1884
45
        ctxt->nameMax *= 2;
1885
45
        tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
1886
45
                                    ctxt->nameMax *
1887
45
                                    sizeof(ctxt->nameTab[0]));
1888
45
        if (tmp == NULL) {
1889
0
      ctxt->nameMax /= 2;
1890
0
      goto mem_error;
1891
0
        }
1892
45
  ctxt->nameTab = tmp;
1893
45
        tmp2 = (xmlStartTag *) xmlRealloc((void * *)ctxt->pushTab,
1894
45
                                    ctxt->nameMax *
1895
45
                                    sizeof(ctxt->pushTab[0]));
1896
45
        if (tmp2 == NULL) {
1897
0
      ctxt->nameMax /= 2;
1898
0
      goto mem_error;
1899
0
        }
1900
45
  ctxt->pushTab = tmp2;
1901
125k
    } else if (ctxt->pushTab == NULL) {
1902
261
        ctxt->pushTab = (xmlStartTag *) xmlMalloc(ctxt->nameMax *
1903
261
                                            sizeof(ctxt->pushTab[0]));
1904
261
        if (ctxt->pushTab == NULL)
1905
0
            goto mem_error;
1906
261
    }
1907
125k
    ctxt->nameTab[ctxt->nameNr] = value;
1908
125k
    ctxt->name = value;
1909
125k
    tag = &ctxt->pushTab[ctxt->nameNr];
1910
125k
    tag->prefix = prefix;
1911
125k
    tag->URI = URI;
1912
125k
    tag->line = line;
1913
125k
    tag->nsNr = nsNr;
1914
125k
    return (ctxt->nameNr++);
1915
0
mem_error:
1916
0
    xmlErrMemory(ctxt, NULL);
1917
0
    return (-1);
1918
125k
}
1919
#ifdef LIBXML_PUSH_ENABLED
1920
/**
1921
 * nameNsPop:
1922
 * @ctxt: an XML parser context
1923
 *
1924
 * Pops the top element/prefix/URI name from the name stack
1925
 *
1926
 * Returns the name just removed
1927
 */
1928
static const xmlChar *
1929
nameNsPop(xmlParserCtxtPtr ctxt)
1930
{
1931
    const xmlChar *ret;
1932
1933
    if (ctxt->nameNr <= 0)
1934
        return (NULL);
1935
    ctxt->nameNr--;
1936
    if (ctxt->nameNr > 0)
1937
        ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
1938
    else
1939
        ctxt->name = NULL;
1940
    ret = ctxt->nameTab[ctxt->nameNr];
1941
    ctxt->nameTab[ctxt->nameNr] = NULL;
1942
    return (ret);
1943
}
1944
#endif /* LIBXML_PUSH_ENABLED */
1945
1946
/**
1947
 * namePush:
1948
 * @ctxt:  an XML parser context
1949
 * @value:  the element name
1950
 *
1951
 * Pushes a new element name on top of the name stack
1952
 *
1953
 * Returns -1 in case of error, the index in the stack otherwise
1954
 */
1955
int
1956
namePush(xmlParserCtxtPtr ctxt, const xmlChar * value)
1957
0
{
1958
0
    if (ctxt == NULL) return (-1);
1959
1960
0
    if (ctxt->nameNr >= ctxt->nameMax) {
1961
0
        const xmlChar * *tmp;
1962
0
        tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
1963
0
                                    ctxt->nameMax * 2 *
1964
0
                                    sizeof(ctxt->nameTab[0]));
1965
0
        if (tmp == NULL) {
1966
0
      goto mem_error;
1967
0
        }
1968
0
  ctxt->nameTab = tmp;
1969
0
        ctxt->nameMax *= 2;
1970
0
    }
1971
0
    ctxt->nameTab[ctxt->nameNr] = value;
1972
0
    ctxt->name = value;
1973
0
    return (ctxt->nameNr++);
1974
0
mem_error:
1975
0
    xmlErrMemory(ctxt, NULL);
1976
0
    return (-1);
1977
0
}
1978
/**
1979
 * namePop:
1980
 * @ctxt: an XML parser context
1981
 *
1982
 * Pops the top element name from the name stack
1983
 *
1984
 * Returns the name just removed
1985
 */
1986
const xmlChar *
1987
namePop(xmlParserCtxtPtr ctxt)
1988
124k
{
1989
124k
    const xmlChar *ret;
1990
1991
124k
    if ((ctxt == NULL) || (ctxt->nameNr <= 0))
1992
0
        return (NULL);
1993
124k
    ctxt->nameNr--;
1994
124k
    if (ctxt->nameNr > 0)
1995
122k
        ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
1996
2.12k
    else
1997
2.12k
        ctxt->name = NULL;
1998
124k
    ret = ctxt->nameTab[ctxt->nameNr];
1999
124k
    ctxt->nameTab[ctxt->nameNr] = NULL;
2000
124k
    return (ret);
2001
124k
}
2002
2003
132k
static int spacePush(xmlParserCtxtPtr ctxt, int val) {
2004
132k
    if (ctxt->spaceNr >= ctxt->spaceMax) {
2005
47
        int *tmp;
2006
2007
47
  ctxt->spaceMax *= 2;
2008
47
        tmp = (int *) xmlRealloc(ctxt->spaceTab,
2009
47
                           ctxt->spaceMax * sizeof(ctxt->spaceTab[0]));
2010
47
        if (tmp == NULL) {
2011
0
      xmlErrMemory(ctxt, NULL);
2012
0
      ctxt->spaceMax /=2;
2013
0
      return(-1);
2014
0
  }
2015
47
  ctxt->spaceTab = tmp;
2016
47
    }
2017
132k
    ctxt->spaceTab[ctxt->spaceNr] = val;
2018
132k
    ctxt->space = &ctxt->spaceTab[ctxt->spaceNr];
2019
132k
    return(ctxt->spaceNr++);
2020
132k
}
2021
2022
131k
static int spacePop(xmlParserCtxtPtr ctxt) {
2023
131k
    int ret;
2024
131k
    if (ctxt->spaceNr <= 0) return(0);
2025
131k
    ctxt->spaceNr--;
2026
131k
    if (ctxt->spaceNr > 0)
2027
131k
  ctxt->space = &ctxt->spaceTab[ctxt->spaceNr - 1];
2028
0
    else
2029
0
        ctxt->space = &ctxt->spaceTab[0];
2030
131k
    ret = ctxt->spaceTab[ctxt->spaceNr];
2031
131k
    ctxt->spaceTab[ctxt->spaceNr] = -1;
2032
131k
    return(ret);
2033
131k
}
2034
2035
/*
2036
 * Macros for accessing the content. Those should be used only by the parser,
2037
 * and not exported.
2038
 *
2039
 * Dirty macros, i.e. one often need to make assumption on the context to
2040
 * use them
2041
 *
2042
 *   CUR_PTR return the current pointer to the xmlChar to be parsed.
2043
 *           To be used with extreme caution since operations consuming
2044
 *           characters may move the input buffer to a different location !
2045
 *   CUR     returns the current xmlChar value, i.e. a 8 bit value if compiled
2046
 *           This should be used internally by the parser
2047
 *           only to compare to ASCII values otherwise it would break when
2048
 *           running with UTF-8 encoding.
2049
 *   RAW     same as CUR but in the input buffer, bypass any token
2050
 *           extraction that may have been done
2051
 *   NXT(n)  returns the n'th next xmlChar. Same as CUR is should be used only
2052
 *           to compare on ASCII based substring.
2053
 *   SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
2054
 *           strings without newlines within the parser.
2055
 *   NEXT1(l) Skip 1 xmlChar, and must also be used only to skip 1 non-newline ASCII
2056
 *           defined char within the parser.
2057
 * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
2058
 *
2059
 *   NEXT    Skip to the next character, this does the proper decoding
2060
 *           in UTF-8 mode. It also pop-up unfinished entities on the fly.
2061
 *   NEXTL(l) Skip the current unicode character of l xmlChars long.
2062
 *   CUR_CHAR(l) returns the current unicode character (int), set l
2063
 *           to the number of xmlChars used for the encoding [0-5].
2064
 *   CUR_SCHAR  same but operate on a string instead of the context
2065
 *   COPY_BUF  copy the current unicode char to the target buffer, increment
2066
 *            the index
2067
 *   GROW, SHRINK  handling of input buffers
2068
 */
2069
2070
2.34M
#define RAW (*ctxt->input->cur)
2071
4.62M
#define CUR (*ctxt->input->cur)
2072
108M
#define NXT(val) ctxt->input->cur[(val)]
2073
174k
#define CUR_PTR ctxt->input->cur
2074
25.1k
#define BASE_PTR ctxt->input->base
2075
2076
#define CMP4( s, c1, c2, c3, c4 ) \
2077
1.00M
  ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char *) s)[ 1 ] == c2 && \
2078
503k
    ((unsigned char *) s)[ 2 ] == c3 && ((unsigned char *) s)[ 3 ] == c4 )
2079
#define CMP5( s, c1, c2, c3, c4, c5 ) \
2080
976k
  ( CMP4( s, c1, c2, c3, c4 ) && ((unsigned char *) s)[ 4 ] == c5 )
2081
#define CMP6( s, c1, c2, c3, c4, c5, c6 ) \
2082
861k
  ( CMP5( s, c1, c2, c3, c4, c5 ) && ((unsigned char *) s)[ 5 ] == c6 )
2083
#define CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) \
2084
759k
  ( CMP6( s, c1, c2, c3, c4, c5, c6 ) && ((unsigned char *) s)[ 6 ] == c7 )
2085
#define CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) \
2086
701k
  ( CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) && ((unsigned char *) s)[ 7 ] == c8 )
2087
#define CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) \
2088
356k
  ( CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) && \
2089
356k
    ((unsigned char *) s)[ 8 ] == c9 )
2090
#define CMP10( s, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 ) \
2091
27.7k
  ( CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) && \
2092
27.7k
    ((unsigned char *) s)[ 9 ] == c10 )
2093
2094
269k
#define SKIP(val) do {             \
2095
269k
    ctxt->input->cur += (val),ctxt->input->col+=(val);      \
2096
269k
    if (*ctxt->input->cur == 0)           \
2097
269k
        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);     \
2098
269k
  } while (0)
2099
2100
#define SKIPL(val) do {             \
2101
    int skipl;                \
2102
    for(skipl=0; skipl<val; skipl++) {          \
2103
  if (*(ctxt->input->cur) == '\n') {        \
2104
  ctxt->input->line++; ctxt->input->col = 1;      \
2105
  } else ctxt->input->col++;          \
2106
  ctxt->input->cur++;           \
2107
    }                 \
2108
    if (*ctxt->input->cur == 0)           \
2109
        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);     \
2110
  } while (0)
2111
2112
3.84M
#define SHRINK if ((ctxt->progressive == 0) &&       \
2113
3.84M
       (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \
2114
3.84M
       (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \
2115
3.84M
  xmlSHRINK (ctxt);
2116
2117
45.7k
static void xmlSHRINK (xmlParserCtxtPtr ctxt) {
2118
45.7k
    xmlParserInputShrink(ctxt->input);
2119
45.7k
    if (*ctxt->input->cur == 0)
2120
6.80k
        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
2121
45.7k
}
2122
2123
232M
#define GROW if ((ctxt->progressive == 0) &&       \
2124
232M
     (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK))  \
2125
232M
  xmlGROW (ctxt);
2126
2127
274k
static void xmlGROW (xmlParserCtxtPtr ctxt) {
2128
274k
    ptrdiff_t curEnd = ctxt->input->end - ctxt->input->cur;
2129
274k
    ptrdiff_t curBase = ctxt->input->cur - ctxt->input->base;
2130
2131
274k
    if (((curEnd > XML_MAX_LOOKUP_LIMIT) ||
2132
274k
         (curBase > XML_MAX_LOOKUP_LIMIT)) &&
2133
274k
         ((ctxt->input->buf) &&
2134
3
          (ctxt->input->buf->readcallback != xmlInputReadCallbackNop)) &&
2135
274k
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
2136
3
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
2137
3
        xmlHaltParser(ctxt);
2138
3
  return;
2139
3
    }
2140
274k
    xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
2141
274k
    if ((ctxt->input->cur > ctxt->input->end) ||
2142
274k
        (ctxt->input->cur < ctxt->input->base)) {
2143
0
        xmlHaltParser(ctxt);
2144
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "cur index out of bound");
2145
0
  return;
2146
0
    }
2147
274k
    if ((ctxt->input->cur != NULL) && (*ctxt->input->cur == 0))
2148
7.28k
        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
2149
274k
}
2150
2151
791k
#define SKIP_BLANKS xmlSkipBlankChars(ctxt)
2152
2153
3.97M
#define NEXT xmlNextChar(ctxt)
2154
2155
155k
#define NEXT1 {               \
2156
155k
  ctxt->input->col++;           \
2157
155k
  ctxt->input->cur++;           \
2158
155k
  if (*ctxt->input->cur == 0)         \
2159
155k
      xmlParserInputGrow(ctxt->input, INPUT_CHUNK);   \
2160
155k
    }
2161
2162
421M
#define NEXTL(l) do {             \
2163
421M
    if (*(ctxt->input->cur) == '\n') {         \
2164
3.49M
  ctxt->input->line++; ctxt->input->col = 1;      \
2165
418M
    } else ctxt->input->col++;           \
2166
421M
    ctxt->input->cur += l;        \
2167
421M
  } while (0)
2168
2169
422M
#define CUR_CHAR(l) xmlCurrentChar(ctxt, &l)
2170
125M
#define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l)
2171
2172
#define COPY_BUF(l,b,i,v)           \
2173
506M
    if (l == 1) b[i++] = v;           \
2174
506M
    else i += xmlCopyCharMultiByte(&b[i],v)
2175
2176
#define CUR_CONSUMED \
2177
816k
    (ctxt->input->consumed + (ctxt->input->cur - ctxt->input->base))
2178
2179
/**
2180
 * xmlSkipBlankChars:
2181
 * @ctxt:  the XML parser context
2182
 *
2183
 * skip all blanks character found at that point in the input streams.
2184
 * It pops up finished entities in the process if allowable at that point.
2185
 *
2186
 * Returns the number of space chars skipped
2187
 */
2188
2189
int
2190
791k
xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
2191
791k
    int res = 0;
2192
2193
    /*
2194
     * It's Okay to use CUR/NEXT here since all the blanks are on
2195
     * the ASCII range.
2196
     */
2197
791k
    if (((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) ||
2198
791k
        (ctxt->instate == XML_PARSER_START)) {
2199
382k
  const xmlChar *cur;
2200
  /*
2201
   * if we are in the document content, go really fast
2202
   */
2203
382k
  cur = ctxt->input->cur;
2204
382k
  while (IS_BLANK_CH(*cur)) {
2205
158k
      if (*cur == '\n') {
2206
1.21k
    ctxt->input->line++; ctxt->input->col = 1;
2207
157k
      } else {
2208
157k
    ctxt->input->col++;
2209
157k
      }
2210
158k
      cur++;
2211
158k
      if (res < INT_MAX)
2212
158k
    res++;
2213
158k
      if (*cur == 0) {
2214
48
    ctxt->input->cur = cur;
2215
48
    xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
2216
48
    cur = ctxt->input->cur;
2217
48
      }
2218
158k
  }
2219
382k
  ctxt->input->cur = cur;
2220
409k
    } else {
2221
409k
        int expandPE = ((ctxt->external != 0) || (ctxt->inputNr != 1));
2222
2223
634k
  while (ctxt->instate != XML_PARSER_EOF) {
2224
634k
            if (IS_BLANK_CH(CUR)) { /* CHECKED tstblanks.xml */
2225
211k
    NEXT;
2226
422k
      } else if (CUR == '%') {
2227
                /*
2228
                 * Need to handle support of entities branching here
2229
                 */
2230
8.52k
          if ((expandPE == 0) || (IS_BLANK_CH(NXT(1))) || (NXT(1) == 0))
2231
1.75k
                    break;
2232
6.77k
          xmlParsePEReference(ctxt);
2233
414k
            } else if (CUR == 0) {
2234
6.78k
                if (ctxt->inputNr <= 1)
2235
11
                    break;
2236
6.77k
                xmlPopInput(ctxt);
2237
407k
            } else {
2238
407k
                break;
2239
407k
            }
2240
2241
            /*
2242
             * Also increase the counter when entering or exiting a PERef.
2243
             * The spec says: "When a parameter-entity reference is recognized
2244
             * in the DTD and included, its replacement text MUST be enlarged
2245
             * by the attachment of one leading and one following space (#x20)
2246
             * character."
2247
             */
2248
225k
      if (res < INT_MAX)
2249
225k
    res++;
2250
225k
        }
2251
409k
    }
2252
791k
    return(res);
2253
791k
}
2254
2255
/************************************************************************
2256
 *                  *
2257
 *    Commodity functions to handle entities      *
2258
 *                  *
2259
 ************************************************************************/
2260
2261
/**
2262
 * xmlPopInput:
2263
 * @ctxt:  an XML parser context
2264
 *
2265
 * xmlPopInput: the current input pointed by ctxt->input came to an end
2266
 *          pop it and return the next char.
2267
 *
2268
 * Returns the current xmlChar in the parser context
2269
 */
2270
xmlChar
2271
6.77k
xmlPopInput(xmlParserCtxtPtr ctxt) {
2272
6.77k
    if ((ctxt == NULL) || (ctxt->inputNr <= 1)) return(0);
2273
6.77k
    if (xmlParserDebugEntities)
2274
0
  xmlGenericError(xmlGenericErrorContext,
2275
0
    "Popping input %d\n", ctxt->inputNr);
2276
6.77k
    if ((ctxt->inputNr > 1) && (ctxt->inSubset == 0) &&
2277
6.77k
        (ctxt->instate != XML_PARSER_EOF))
2278
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
2279
0
                    "Unfinished entity outside the DTD");
2280
6.77k
    xmlFreeInputStream(inputPop(ctxt));
2281
6.77k
    if (*ctxt->input->cur == 0)
2282
0
        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
2283
6.77k
    return(CUR);
2284
6.77k
}
2285
2286
/**
2287
 * xmlPushInput:
2288
 * @ctxt:  an XML parser context
2289
 * @input:  an XML parser input fragment (entity, XML fragment ...).
2290
 *
2291
 * xmlPushInput: switch to a new input stream which is stacked on top
2292
 *               of the previous one(s).
2293
 * Returns -1 in case of error or the index in the input stack
2294
 */
2295
int
2296
6.77k
xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
2297
6.77k
    int ret;
2298
6.77k
    if (input == NULL) return(-1);
2299
2300
6.77k
    if (xmlParserDebugEntities) {
2301
0
  if ((ctxt->input != NULL) && (ctxt->input->filename))
2302
0
      xmlGenericError(xmlGenericErrorContext,
2303
0
        "%s(%d): ", ctxt->input->filename,
2304
0
        ctxt->input->line);
2305
0
  xmlGenericError(xmlGenericErrorContext,
2306
0
    "Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur);
2307
0
    }
2308
6.77k
    if (((ctxt->inputNr > 40) && ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
2309
6.77k
        (ctxt->inputNr > 1024)) {
2310
0
        xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
2311
0
        while (ctxt->inputNr > 1)
2312
0
            xmlFreeInputStream(inputPop(ctxt));
2313
0
  return(-1);
2314
0
    }
2315
6.77k
    ret = inputPush(ctxt, input);
2316
6.77k
    if (ctxt->instate == XML_PARSER_EOF)
2317
0
        return(-1);
2318
6.77k
    GROW;
2319
6.77k
    return(ret);
2320
6.77k
}
2321
2322
/**
2323
 * xmlParseCharRef:
2324
 * @ctxt:  an XML parser context
2325
 *
2326
 * DEPRECATED: Internal function, don't use.
2327
 *
2328
 * parse Reference declarations
2329
 *
2330
 * [66] CharRef ::= '&#' [0-9]+ ';' |
2331
 *                  '&#x' [0-9a-fA-F]+ ';'
2332
 *
2333
 * [ WFC: Legal Character ]
2334
 * Characters referred to using character references must match the
2335
 * production for Char.
2336
 *
2337
 * Returns the value parsed (as an int), 0 in case of error
2338
 */
2339
int
2340
46.3k
xmlParseCharRef(xmlParserCtxtPtr ctxt) {
2341
46.3k
    int val = 0;
2342
46.3k
    int count = 0;
2343
2344
    /*
2345
     * Using RAW/CUR/NEXT is okay since we are working on ASCII range here
2346
     */
2347
46.3k
    if ((RAW == '&') && (NXT(1) == '#') &&
2348
46.3k
        (NXT(2) == 'x')) {
2349
4.35k
  SKIP(3);
2350
4.35k
  GROW;
2351
69.8k
  while (RAW != ';') { /* loop blocked by count */
2352
68.9k
      if (count++ > 20) {
2353
3.75k
    count = 0;
2354
3.75k
    GROW;
2355
3.75k
                if (ctxt->instate == XML_PARSER_EOF)
2356
0
                    return(0);
2357
3.75k
      }
2358
68.9k
      if ((RAW >= '0') && (RAW <= '9'))
2359
62.9k
          val = val * 16 + (CUR - '0');
2360
5.95k
      else if ((RAW >= 'a') && (RAW <= 'f') && (count < 20))
2361
2.19k
          val = val * 16 + (CUR - 'a') + 10;
2362
3.76k
      else if ((RAW >= 'A') && (RAW <= 'F') && (count < 20))
2363
290
          val = val * 16 + (CUR - 'A') + 10;
2364
3.47k
      else {
2365
3.47k
    xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
2366
3.47k
    val = 0;
2367
3.47k
    break;
2368
3.47k
      }
2369
65.4k
      if (val > 0x110000)
2370
47.9k
          val = 0x110000;
2371
2372
65.4k
      NEXT;
2373
65.4k
      count++;
2374
65.4k
  }
2375
4.35k
  if (RAW == ';') {
2376
      /* on purpose to avoid reentrancy problems with NEXT and SKIP */
2377
876
      ctxt->input->col++;
2378
876
      ctxt->input->cur++;
2379
876
  }
2380
42.0k
    } else if  ((RAW == '&') && (NXT(1) == '#')) {
2381
42.0k
  SKIP(2);
2382
42.0k
  GROW;
2383
132k
  while (RAW != ';') { /* loop blocked by count */
2384
90.3k
      if (count++ > 20) {
2385
0
    count = 0;
2386
0
    GROW;
2387
0
                if (ctxt->instate == XML_PARSER_EOF)
2388
0
                    return(0);
2389
0
      }
2390
90.3k
      if ((RAW >= '0') && (RAW <= '9'))
2391
90.2k
          val = val * 10 + (CUR - '0');
2392
116
      else {
2393
116
    xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
2394
116
    val = 0;
2395
116
    break;
2396
116
      }
2397
90.2k
      if (val > 0x110000)
2398
34
          val = 0x110000;
2399
2400
90.2k
      NEXT;
2401
90.2k
      count++;
2402
90.2k
  }
2403
42.0k
  if (RAW == ';') {
2404
      /* on purpose to avoid reentrancy problems with NEXT and SKIP */
2405
41.9k
      ctxt->input->col++;
2406
41.9k
      ctxt->input->cur++;
2407
41.9k
  }
2408
42.0k
    } else {
2409
0
        xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
2410
0
    }
2411
2412
    /*
2413
     * [ WFC: Legal Character ]
2414
     * Characters referred to using character references must match the
2415
     * production for Char.
2416
     */
2417
46.3k
    if (val >= 0x110000) {
2418
270
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2419
270
                "xmlParseCharRef: character reference out of bounds\n",
2420
270
          val);
2421
46.1k
    } else if (IS_CHAR(val)) {
2422
42.5k
        return(val);
2423
42.5k
    } else {
2424
3.60k
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2425
3.60k
                          "xmlParseCharRef: invalid xmlChar value %d\n",
2426
3.60k
                    val);
2427
3.60k
    }
2428
3.87k
    return(0);
2429
46.3k
}
2430
2431
/**
2432
 * xmlParseStringCharRef:
2433
 * @ctxt:  an XML parser context
2434
 * @str:  a pointer to an index in the string
2435
 *
2436
 * parse Reference declarations, variant parsing from a string rather
2437
 * than an an input flow.
2438
 *
2439
 * [66] CharRef ::= '&#' [0-9]+ ';' |
2440
 *                  '&#x' [0-9a-fA-F]+ ';'
2441
 *
2442
 * [ WFC: Legal Character ]
2443
 * Characters referred to using character references must match the
2444
 * production for Char.
2445
 *
2446
 * Returns the value parsed (as an int), 0 in case of error, str will be
2447
 *         updated to the current value of the index
2448
 */
2449
static int
2450
1.87k
xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
2451
1.87k
    const xmlChar *ptr;
2452
1.87k
    xmlChar cur;
2453
1.87k
    int val = 0;
2454
2455
1.87k
    if ((str == NULL) || (*str == NULL)) return(0);
2456
1.87k
    ptr = *str;
2457
1.87k
    cur = *ptr;
2458
1.87k
    if ((cur == '&') && (ptr[1] == '#') && (ptr[2] == 'x')) {
2459
1.83k
  ptr += 3;
2460
1.83k
  cur = *ptr;
2461
34.2k
  while (cur != ';') { /* Non input consuming loop */
2462
34.0k
      if ((cur >= '0') && (cur <= '9'))
2463
31.3k
          val = val * 16 + (cur - '0');
2464
2.78k
      else if ((cur >= 'a') && (cur <= 'f'))
2465
913
          val = val * 16 + (cur - 'a') + 10;
2466
1.87k
      else if ((cur >= 'A') && (cur <= 'F'))
2467
183
          val = val * 16 + (cur - 'A') + 10;
2468
1.69k
      else {
2469
1.69k
    xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
2470
1.69k
    val = 0;
2471
1.69k
    break;
2472
1.69k
      }
2473
32.4k
      if (val > 0x110000)
2474
24.3k
          val = 0x110000;
2475
2476
32.4k
      ptr++;
2477
32.4k
      cur = *ptr;
2478
32.4k
  }
2479
1.83k
  if (cur == ';')
2480
145
      ptr++;
2481
1.83k
    } else if  ((cur == '&') && (ptr[1] == '#')){
2482
37
  ptr += 2;
2483
37
  cur = *ptr;
2484
105
  while (cur != ';') { /* Non input consuming loops */
2485
71
      if ((cur >= '0') && (cur <= '9'))
2486
68
          val = val * 10 + (cur - '0');
2487
3
      else {
2488
3
    xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
2489
3
    val = 0;
2490
3
    break;
2491
3
      }
2492
68
      if (val > 0x110000)
2493
0
          val = 0x110000;
2494
2495
68
      ptr++;
2496
68
      cur = *ptr;
2497
68
  }
2498
37
  if (cur == ';')
2499
34
      ptr++;
2500
37
    } else {
2501
0
  xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
2502
0
  return(0);
2503
0
    }
2504
1.87k
    *str = ptr;
2505
2506
    /*
2507
     * [ WFC: Legal Character ]
2508
     * Characters referred to using character references must match the
2509
     * production for Char.
2510
     */
2511
1.87k
    if (val >= 0x110000) {
2512
140
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2513
140
                "xmlParseStringCharRef: character reference out of bounds\n",
2514
140
                val);
2515
1.73k
    } else if (IS_CHAR(val)) {
2516
39
        return(val);
2517
1.69k
    } else {
2518
1.69k
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2519
1.69k
        "xmlParseStringCharRef: invalid xmlChar value %d\n",
2520
1.69k
        val);
2521
1.69k
    }
2522
1.83k
    return(0);
2523
1.87k
}
2524
2525
/**
2526
 * xmlParserHandlePEReference:
2527
 * @ctxt:  the parser context
2528
 *
2529
 * [69] PEReference ::= '%' Name ';'
2530
 *
2531
 * [ WFC: No Recursion ]
2532
 * A parsed entity must not contain a recursive
2533
 * reference to itself, either directly or indirectly.
2534
 *
2535
 * [ WFC: Entity Declared ]
2536
 * In a document without any DTD, a document with only an internal DTD
2537
 * subset which contains no parameter entity references, or a document
2538
 * with "standalone='yes'", ...  ... The declaration of a parameter
2539
 * entity must precede any reference to it...
2540
 *
2541
 * [ VC: Entity Declared ]
2542
 * In a document with an external subset or external parameter entities
2543
 * with "standalone='no'", ...  ... The declaration of a parameter entity
2544
 * must precede any reference to it...
2545
 *
2546
 * [ WFC: In DTD ]
2547
 * Parameter-entity references may only appear in the DTD.
2548
 * NOTE: misleading but this is handled.
2549
 *
2550
 * A PEReference may have been detected in the current input stream
2551
 * the handling is done accordingly to
2552
 *      http://www.w3.org/TR/REC-xml#entproc
2553
 * i.e.
2554
 *   - Included in literal in entity values
2555
 *   - Included as Parameter Entity reference within DTDs
2556
 */
2557
void
2558
0
xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
2559
0
    switch(ctxt->instate) {
2560
0
  case XML_PARSER_CDATA_SECTION:
2561
0
      return;
2562
0
        case XML_PARSER_COMMENT:
2563
0
      return;
2564
0
  case XML_PARSER_START_TAG:
2565
0
      return;
2566
0
  case XML_PARSER_END_TAG:
2567
0
      return;
2568
0
        case XML_PARSER_EOF:
2569
0
      xmlFatalErr(ctxt, XML_ERR_PEREF_AT_EOF, NULL);
2570
0
      return;
2571
0
        case XML_PARSER_PROLOG:
2572
0
  case XML_PARSER_START:
2573
0
  case XML_PARSER_MISC:
2574
0
      xmlFatalErr(ctxt, XML_ERR_PEREF_IN_PROLOG, NULL);
2575
0
      return;
2576
0
  case XML_PARSER_ENTITY_DECL:
2577
0
        case XML_PARSER_CONTENT:
2578
0
        case XML_PARSER_ATTRIBUTE_VALUE:
2579
0
        case XML_PARSER_PI:
2580
0
  case XML_PARSER_SYSTEM_LITERAL:
2581
0
  case XML_PARSER_PUBLIC_LITERAL:
2582
      /* we just ignore it there */
2583
0
      return;
2584
0
        case XML_PARSER_EPILOG:
2585
0
      xmlFatalErr(ctxt, XML_ERR_PEREF_IN_EPILOG, NULL);
2586
0
      return;
2587
0
  case XML_PARSER_ENTITY_VALUE:
2588
      /*
2589
       * NOTE: in the case of entity values, we don't do the
2590
       *       substitution here since we need the literal
2591
       *       entity value to be able to save the internal
2592
       *       subset of the document.
2593
       *       This will be handled by xmlStringDecodeEntities
2594
       */
2595
0
      return;
2596
0
        case XML_PARSER_DTD:
2597
      /*
2598
       * [WFC: Well-Formedness Constraint: PEs in Internal Subset]
2599
       * In the internal DTD subset, parameter-entity references
2600
       * can occur only where markup declarations can occur, not
2601
       * within markup declarations.
2602
       * In that case this is handled in xmlParseMarkupDecl
2603
       */
2604
0
      if ((ctxt->external == 0) && (ctxt->inputNr == 1))
2605
0
    return;
2606
0
      if (IS_BLANK_CH(NXT(1)) || NXT(1) == 0)
2607
0
    return;
2608
0
            break;
2609
0
        case XML_PARSER_IGNORE:
2610
0
            return;
2611
0
    }
2612
2613
0
    xmlParsePEReference(ctxt);
2614
0
}
2615
2616
/*
2617
 * Macro used to grow the current buffer.
2618
 * buffer##_size is expected to be a size_t
2619
 * mem_error: is expected to handle memory allocation failures
2620
 */
2621
17.5k
#define growBuffer(buffer, n) {           \
2622
17.5k
    xmlChar *tmp;             \
2623
17.5k
    size_t new_size = buffer##_size * 2 + n;                            \
2624
17.5k
    if (new_size < buffer##_size) goto mem_error;                       \
2625
17.5k
    tmp = (xmlChar *) xmlRealloc(buffer, new_size);                     \
2626
17.5k
    if (tmp == NULL) goto mem_error;         \
2627
17.5k
    buffer = tmp;             \
2628
17.5k
    buffer##_size = new_size;                                           \
2629
17.5k
}
2630
2631
/**
2632
 * xmlStringLenDecodeEntities:
2633
 * @ctxt:  the parser context
2634
 * @str:  the input string
2635
 * @len: the string length
2636
 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
2637
 * @end:  an end marker xmlChar, 0 if none
2638
 * @end2:  an end marker xmlChar, 0 if none
2639
 * @end3:  an end marker xmlChar, 0 if none
2640
 *
2641
 * Takes a entity string content and process to do the adequate substitutions.
2642
 *
2643
 * [67] Reference ::= EntityRef | CharRef
2644
 *
2645
 * [69] PEReference ::= '%' Name ';'
2646
 *
2647
 * Returns A newly allocated string with the substitution done. The caller
2648
 *      must deallocate it !
2649
 */
2650
xmlChar *
2651
xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
2652
1.94k
          int what, xmlChar end, xmlChar  end2, xmlChar end3) {
2653
1.94k
    xmlChar *buffer = NULL;
2654
1.94k
    size_t buffer_size = 0;
2655
1.94k
    size_t nbchars = 0;
2656
2657
1.94k
    xmlChar *current = NULL;
2658
1.94k
    xmlChar *rep = NULL;
2659
1.94k
    const xmlChar *last;
2660
1.94k
    xmlEntityPtr ent;
2661
1.94k
    int c,l;
2662
2663
1.94k
    if ((ctxt == NULL) || (str == NULL) || (len < 0))
2664
0
  return(NULL);
2665
1.94k
    last = str + len;
2666
2667
1.94k
    if (((ctxt->depth > 40) &&
2668
1.94k
         ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
2669
1.94k
  (ctxt->depth > 1024)) {
2670
0
  xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
2671
0
  return(NULL);
2672
0
    }
2673
2674
    /*
2675
     * allocate a translation buffer.
2676
     */
2677
1.94k
    buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
2678
1.94k
    buffer = (xmlChar *) xmlMallocAtomic(buffer_size);
2679
1.94k
    if (buffer == NULL) goto mem_error;
2680
2681
    /*
2682
     * OK loop until we reach one of the ending char or a size limit.
2683
     * we are operating on already parsed values.
2684
     */
2685
1.94k
    if (str < last)
2686
1.94k
  c = CUR_SCHAR(str, l);
2687
4
    else
2688
4
        c = 0;
2689
123M
    while ((c != 0) && (c != end) && /* non input consuming loop */
2690
123M
           (c != end2) && (c != end3) &&
2691
123M
           (ctxt->instate != XML_PARSER_EOF)) {
2692
2693
123M
  if (c == 0) break;
2694
123M
        if ((c == '&') && (str[1] == '#')) {
2695
1.87k
      int val = xmlParseStringCharRef(ctxt, &str);
2696
1.87k
      if (val == 0)
2697
1.83k
                goto int_error;
2698
39
      COPY_BUF(0,buffer,nbchars,val);
2699
39
      if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2700
0
          growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2701
0
      }
2702
123M
  } else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) {
2703
587
      if (xmlParserDebugEntities)
2704
0
    xmlGenericError(xmlGenericErrorContext,
2705
0
      "String decoding Entity Reference: %.30s\n",
2706
0
      str);
2707
587
      ent = xmlParseStringEntityRef(ctxt, &str);
2708
587
      xmlParserEntityCheck(ctxt, 0, ent, 0);
2709
587
      if (ent != NULL)
2710
16
          ctxt->nbentities += ent->checked / 2;
2711
587
      if ((ent != NULL) &&
2712
587
    (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
2713
0
    if (ent->content != NULL) {
2714
0
        COPY_BUF(0,buffer,nbchars,ent->content[0]);
2715
0
        if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2716
0
      growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2717
0
        }
2718
0
    } else {
2719
0
        xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
2720
0
          "predefined entity has no content\n");
2721
0
                    goto int_error;
2722
0
    }
2723
587
      } else if ((ent != NULL) && (ent->content != NULL)) {
2724
16
    ctxt->depth++;
2725
16
    rep = xmlStringDecodeEntities(ctxt, ent->content, what,
2726
16
                            0, 0, 0);
2727
16
    ctxt->depth--;
2728
16
    if (rep == NULL) {
2729
0
                    ent->content[0] = 0;
2730
0
                    goto int_error;
2731
0
                }
2732
2733
16
                current = rep;
2734
48.2M
                while (*current != 0) { /* non input consuming loop */
2735
48.2M
                    buffer[nbchars++] = *current++;
2736
48.2M
                    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2737
17
                        if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
2738
0
                            goto int_error;
2739
51
                        growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2740
51
                    }
2741
48.2M
                }
2742
16
                xmlFree(rep);
2743
16
                rep = NULL;
2744
571
      } else if (ent != NULL) {
2745
0
    int i = xmlStrlen(ent->name);
2746
0
    const xmlChar *cur = ent->name;
2747
2748
0
    buffer[nbchars++] = '&';
2749
0
    if (nbchars + i + XML_PARSER_BUFFER_SIZE > buffer_size) {
2750
0
        growBuffer(buffer, i + XML_PARSER_BUFFER_SIZE);
2751
0
    }
2752
0
    for (;i > 0;i--)
2753
0
        buffer[nbchars++] = *cur++;
2754
0
    buffer[nbchars++] = ';';
2755
0
      }
2756
123M
  } else if (c == '%' && (what & XML_SUBSTITUTE_PEREF)) {
2757
0
      if (xmlParserDebugEntities)
2758
0
    xmlGenericError(xmlGenericErrorContext,
2759
0
      "String decoding PE Reference: %.30s\n", str);
2760
0
      ent = xmlParseStringPEReference(ctxt, &str);
2761
0
      xmlParserEntityCheck(ctxt, 0, ent, 0);
2762
0
      if (ent != NULL)
2763
0
          ctxt->nbentities += ent->checked / 2;
2764
0
      if (ent != NULL) {
2765
0
                if (ent->content == NULL) {
2766
        /*
2767
         * Note: external parsed entities will not be loaded,
2768
         * it is not required for a non-validating parser to
2769
         * complete external PEReferences coming from the
2770
         * internal subset
2771
         */
2772
0
        if (((ctxt->options & XML_PARSE_NOENT) != 0) ||
2773
0
      ((ctxt->options & XML_PARSE_DTDVALID) != 0) ||
2774
0
      (ctxt->validate != 0)) {
2775
0
      xmlLoadEntityContent(ctxt, ent);
2776
0
        } else {
2777
0
      xmlWarningMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
2778
0
      "not validating will not read content for PE entity %s\n",
2779
0
                          ent->name, NULL);
2780
0
        }
2781
0
    }
2782
0
    ctxt->depth++;
2783
0
    rep = xmlStringDecodeEntities(ctxt, ent->content, what,
2784
0
                            0, 0, 0);
2785
0
    ctxt->depth--;
2786
0
    if (rep == NULL) {
2787
0
                    if (ent->content != NULL)
2788
0
                        ent->content[0] = 0;
2789
0
                    goto int_error;
2790
0
                }
2791
0
                current = rep;
2792
0
                while (*current != 0) { /* non input consuming loop */
2793
0
                    buffer[nbchars++] = *current++;
2794
0
                    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2795
0
                        if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
2796
0
                            goto int_error;
2797
0
                        growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2798
0
                    }
2799
0
                }
2800
0
                xmlFree(rep);
2801
0
                rep = NULL;
2802
0
      }
2803
123M
  } else {
2804
123M
      COPY_BUF(l,buffer,nbchars,c);
2805
123M
      str += l;
2806
123M
      if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2807
1.80k
          growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2808
1.80k
      }
2809
123M
  }
2810
123M
  if (str < last)
2811
123M
      c = CUR_SCHAR(str, l);
2812
106
  else
2813
106
      c = 0;
2814
123M
    }
2815
110
    buffer[nbchars] = 0;
2816
110
    return(buffer);
2817
2818
0
mem_error:
2819
0
    xmlErrMemory(ctxt, NULL);
2820
1.83k
int_error:
2821
1.83k
    if (rep != NULL)
2822
0
        xmlFree(rep);
2823
1.83k
    if (buffer != NULL)
2824
1.83k
        xmlFree(buffer);
2825
1.83k
    return(NULL);
2826
0
}
2827
2828
/**
2829
 * xmlStringDecodeEntities:
2830
 * @ctxt:  the parser context
2831
 * @str:  the input string
2832
 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
2833
 * @end:  an end marker xmlChar, 0 if none
2834
 * @end2:  an end marker xmlChar, 0 if none
2835
 * @end3:  an end marker xmlChar, 0 if none
2836
 *
2837
 * Takes a entity string content and process to do the adequate substitutions.
2838
 *
2839
 * [67] Reference ::= EntityRef | CharRef
2840
 *
2841
 * [69] PEReference ::= '%' Name ';'
2842
 *
2843
 * Returns A newly allocated string with the substitution done. The caller
2844
 *      must deallocate it !
2845
 */
2846
xmlChar *
2847
xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what,
2848
1.94k
            xmlChar end, xmlChar  end2, xmlChar end3) {
2849
1.94k
    if ((ctxt == NULL) || (str == NULL)) return(NULL);
2850
1.94k
    return(xmlStringLenDecodeEntities(ctxt, str, xmlStrlen(str), what,
2851
1.94k
           end, end2, end3));
2852
1.94k
}
2853
2854
/************************************************************************
2855
 *                  *
2856
 *    Commodity functions, cleanup needed ?     *
2857
 *                  *
2858
 ************************************************************************/
2859
2860
/**
2861
 * areBlanks:
2862
 * @ctxt:  an XML parser context
2863
 * @str:  a xmlChar *
2864
 * @len:  the size of @str
2865
 * @blank_chars: we know the chars are blanks
2866
 *
2867
 * Is this a sequence of blank chars that one can ignore ?
2868
 *
2869
 * Returns 1 if ignorable 0 otherwise.
2870
 */
2871
2872
static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
2873
206k
                     int blank_chars) {
2874
206k
    int i, ret;
2875
206k
    xmlNodePtr lastChild;
2876
2877
    /*
2878
     * Don't spend time trying to differentiate them, the same callback is
2879
     * used !
2880
     */
2881
206k
    if (ctxt->sax->ignorableWhitespace == ctxt->sax->characters)
2882
206k
  return(0);
2883
2884
    /*
2885
     * Check for xml:space value.
2886
     */
2887
0
    if ((ctxt->space == NULL) || (*(ctxt->space) == 1) ||
2888
0
        (*(ctxt->space) == -2))
2889
0
  return(0);
2890
2891
    /*
2892
     * Check that the string is made of blanks
2893
     */
2894
0
    if (blank_chars == 0) {
2895
0
  for (i = 0;i < len;i++)
2896
0
      if (!(IS_BLANK_CH(str[i]))) return(0);
2897
0
    }
2898
2899
    /*
2900
     * Look if the element is mixed content in the DTD if available
2901
     */
2902
0
    if (ctxt->node == NULL) return(0);
2903
0
    if (ctxt->myDoc != NULL) {
2904
0
  ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name);
2905
0
        if (ret == 0) return(1);
2906
0
        if (ret == 1) return(0);
2907
0
    }
2908
2909
    /*
2910
     * Otherwise, heuristic :-\
2911
     */
2912
0
    if ((RAW != '<') && (RAW != 0xD)) return(0);
2913
0
    if ((ctxt->node->children == NULL) &&
2914
0
  (RAW == '<') && (NXT(1) == '/')) return(0);
2915
2916
0
    lastChild = xmlGetLastChild(ctxt->node);
2917
0
    if (lastChild == NULL) {
2918
0
        if ((ctxt->node->type != XML_ELEMENT_NODE) &&
2919
0
            (ctxt->node->content != NULL)) return(0);
2920
0
    } else if (xmlNodeIsText(lastChild))
2921
0
        return(0);
2922
0
    else if ((ctxt->node->children != NULL) &&
2923
0
             (xmlNodeIsText(ctxt->node->children)))
2924
0
        return(0);
2925
0
    return(1);
2926
0
}
2927
2928
/************************************************************************
2929
 *                  *
2930
 *    Extra stuff for namespace support     *
2931
 *  Relates to http://www.w3.org/TR/WD-xml-names      *
2932
 *                  *
2933
 ************************************************************************/
2934
2935
/**
2936
 * xmlSplitQName:
2937
 * @ctxt:  an XML parser context
2938
 * @name:  an XML parser context
2939
 * @prefix:  a xmlChar **
2940
 *
2941
 * parse an UTF8 encoded XML qualified name string
2942
 *
2943
 * [NS 5] QName ::= (Prefix ':')? LocalPart
2944
 *
2945
 * [NS 6] Prefix ::= NCName
2946
 *
2947
 * [NS 7] LocalPart ::= NCName
2948
 *
2949
 * Returns the local part, and prefix is updated
2950
 *   to get the Prefix if any.
2951
 */
2952
2953
xmlChar *
2954
588
xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
2955
588
    xmlChar buf[XML_MAX_NAMELEN + 5];
2956
588
    xmlChar *buffer = NULL;
2957
588
    int len = 0;
2958
588
    int max = XML_MAX_NAMELEN;
2959
588
    xmlChar *ret = NULL;
2960
588
    const xmlChar *cur = name;
2961
588
    int c;
2962
2963
588
    if (prefix == NULL) return(NULL);
2964
588
    *prefix = NULL;
2965
2966
588
    if (cur == NULL) return(NULL);
2967
2968
#ifndef XML_XML_NAMESPACE
2969
    /* xml: prefix is not really a namespace */
2970
    if ((cur[0] == 'x') && (cur[1] == 'm') &&
2971
        (cur[2] == 'l') && (cur[3] == ':'))
2972
  return(xmlStrdup(name));
2973
#endif
2974
2975
    /* nasty but well=formed */
2976
588
    if (cur[0] == ':')
2977
0
  return(xmlStrdup(name));
2978
2979
588
    c = *cur++;
2980
11.3k
    while ((c != 0) && (c != ':') && (len < max)) { /* tested bigname.xml */
2981
10.7k
  buf[len++] = c;
2982
10.7k
  c = *cur++;
2983
10.7k
    }
2984
588
    if (len >= max) {
2985
  /*
2986
   * Okay someone managed to make a huge name, so he's ready to pay
2987
   * for the processing speed.
2988
   */
2989
0
  max = len * 2;
2990
2991
0
  buffer = (xmlChar *) xmlMallocAtomic(max);
2992
0
  if (buffer == NULL) {
2993
0
      xmlErrMemory(ctxt, NULL);
2994
0
      return(NULL);
2995
0
  }
2996
0
  memcpy(buffer, buf, len);
2997
0
  while ((c != 0) && (c != ':')) { /* tested bigname.xml */
2998
0
      if (len + 10 > max) {
2999
0
          xmlChar *tmp;
3000
3001
0
    max *= 2;
3002
0
    tmp = (xmlChar *) xmlRealloc(buffer, max);
3003
0
    if (tmp == NULL) {
3004
0
        xmlFree(buffer);
3005
0
        xmlErrMemory(ctxt, NULL);
3006
0
        return(NULL);
3007
0
    }
3008
0
    buffer = tmp;
3009
0
      }
3010
0
      buffer[len++] = c;
3011
0
      c = *cur++;
3012
0
  }
3013
0
  buffer[len] = 0;
3014
0
    }
3015
3016
588
    if ((c == ':') && (*cur == 0)) {
3017
0
        if (buffer != NULL)
3018
0
      xmlFree(buffer);
3019
0
  *prefix = NULL;
3020
0
  return(xmlStrdup(name));
3021
0
    }
3022
3023
588
    if (buffer == NULL)
3024
588
  ret = xmlStrndup(buf, len);
3025
0
    else {
3026
0
  ret = buffer;
3027
0
  buffer = NULL;
3028
0
  max = XML_MAX_NAMELEN;
3029
0
    }
3030
3031
3032
588
    if (c == ':') {
3033
585
  c = *cur;
3034
585
        *prefix = ret;
3035
585
  if (c == 0) {
3036
0
      return(xmlStrndup(BAD_CAST "", 0));
3037
0
  }
3038
585
  len = 0;
3039
3040
  /*
3041
   * Check that the first character is proper to start
3042
   * a new name
3043
   */
3044
585
  if (!(((c >= 0x61) && (c <= 0x7A)) ||
3045
585
        ((c >= 0x41) && (c <= 0x5A)) ||
3046
585
        (c == '_') || (c == ':'))) {
3047
81
      int l;
3048
81
      int first = CUR_SCHAR(cur, l);
3049
3050
81
      if (!IS_LETTER(first) && (first != '_')) {
3051
0
    xmlFatalErrMsgStr(ctxt, XML_NS_ERR_QNAME,
3052
0
          "Name %s is not XML Namespace compliant\n",
3053
0
          name);
3054
0
      }
3055
81
  }
3056
585
  cur++;
3057
3058
36.2k
  while ((c != 0) && (len < max)) { /* tested bigname2.xml */
3059
35.6k
      buf[len++] = c;
3060
35.6k
      c = *cur++;
3061
35.6k
  }
3062
585
  if (len >= max) {
3063
      /*
3064
       * Okay someone managed to make a huge name, so he's ready to pay
3065
       * for the processing speed.
3066
       */
3067
258
      max = len * 2;
3068
3069
258
      buffer = (xmlChar *) xmlMallocAtomic(max);
3070
258
      if (buffer == NULL) {
3071
0
          xmlErrMemory(ctxt, NULL);
3072
0
    return(NULL);
3073
0
      }
3074
258
      memcpy(buffer, buf, len);
3075
3.63k
      while (c != 0) { /* tested bigname2.xml */
3076
3.37k
    if (len + 10 > max) {
3077
3
        xmlChar *tmp;
3078
3079
3
        max *= 2;
3080
3
        tmp = (xmlChar *) xmlRealloc(buffer, max);
3081
3
        if (tmp == NULL) {
3082
0
      xmlErrMemory(ctxt, NULL);
3083
0
      xmlFree(buffer);
3084
0
      return(NULL);
3085
0
        }
3086
3
        buffer = tmp;
3087
3
    }
3088
3.37k
    buffer[len++] = c;
3089
3.37k
    c = *cur++;
3090
3.37k
      }
3091
258
      buffer[len] = 0;
3092
258
  }
3093
3094
585
  if (buffer == NULL)
3095
327
      ret = xmlStrndup(buf, len);
3096
258
  else {
3097
258
      ret = buffer;
3098
258
  }
3099
585
    }
3100
3101
588
    return(ret);
3102
588
}
3103
3104
/************************************************************************
3105
 *                  *
3106
 *      The parser itself       *
3107
 *  Relates to http://www.w3.org/TR/REC-xml       *
3108
 *                  *
3109
 ************************************************************************/
3110
3111
/************************************************************************
3112
 *                  *
3113
 *  Routines to parse Name, NCName and NmToken      *
3114
 *                  *
3115
 ************************************************************************/
3116
#ifdef DEBUG
3117
static unsigned long nbParseName = 0;
3118
static unsigned long nbParseNmToken = 0;
3119
static unsigned long nbParseNCName = 0;
3120
static unsigned long nbParseNCNameComplex = 0;
3121
static unsigned long nbParseNameComplex = 0;
3122
static unsigned long nbParseStringName = 0;
3123
#endif
3124
3125
/*
3126
 * The two following functions are related to the change of accepted
3127
 * characters for Name and NmToken in the Revision 5 of XML-1.0
3128
 * They correspond to the modified production [4] and the new production [4a]
3129
 * changes in that revision. Also note that the macros used for the
3130
 * productions Letter, Digit, CombiningChar and Extender are not needed
3131
 * anymore.
3132
 * We still keep compatibility to pre-revision5 parsing semantic if the
3133
 * new XML_PARSE_OLD10 option is given to the parser.
3134
 */
3135
static int
3136
18.4k
xmlIsNameStartChar(xmlParserCtxtPtr ctxt, int c) {
3137
18.4k
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3138
        /*
3139
   * Use the new checks of production [4] [4a] amd [5] of the
3140
   * Update 5 of XML-1.0
3141
   */
3142
18.4k
  if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3143
18.4k
      (((c >= 'a') && (c <= 'z')) ||
3144
18.2k
       ((c >= 'A') && (c <= 'Z')) ||
3145
18.2k
       (c == '_') || (c == ':') ||
3146
18.2k
       ((c >= 0xC0) && (c <= 0xD6)) ||
3147
18.2k
       ((c >= 0xD8) && (c <= 0xF6)) ||
3148
18.2k
       ((c >= 0xF8) && (c <= 0x2FF)) ||
3149
18.2k
       ((c >= 0x370) && (c <= 0x37D)) ||
3150
18.2k
       ((c >= 0x37F) && (c <= 0x1FFF)) ||
3151
18.2k
       ((c >= 0x200C) && (c <= 0x200D)) ||
3152
18.2k
       ((c >= 0x2070) && (c <= 0x218F)) ||
3153
18.2k
       ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3154
18.2k
       ((c >= 0x3001) && (c <= 0xD7FF)) ||
3155
18.2k
       ((c >= 0xF900) && (c <= 0xFDCF)) ||
3156
18.2k
       ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3157
18.2k
       ((c >= 0x10000) && (c <= 0xEFFFF))))
3158
7.66k
      return(1);
3159
18.4k
    } else {
3160
0
        if (IS_LETTER(c) || (c == '_') || (c == ':'))
3161
0
      return(1);
3162
0
    }
3163
10.8k
    return(0);
3164
18.4k
}
3165
3166
static int
3167
28.4M
xmlIsNameChar(xmlParserCtxtPtr ctxt, int c) {
3168
28.4M
    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
28.4M
  if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3174
28.4M
      (((c >= 'a') && (c <= 'z')) ||
3175
28.4M
       ((c >= 'A') && (c <= 'Z')) ||
3176
28.4M
       ((c >= '0') && (c <= '9')) || /* !start */
3177
28.4M
       (c == '_') || (c == ':') ||
3178
28.4M
       (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3179
28.4M
       ((c >= 0xC0) && (c <= 0xD6)) ||
3180
28.4M
       ((c >= 0xD8) && (c <= 0xF6)) ||
3181
28.4M
       ((c >= 0xF8) && (c <= 0x2FF)) ||
3182
28.4M
       ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3183
28.4M
       ((c >= 0x370) && (c <= 0x37D)) ||
3184
28.4M
       ((c >= 0x37F) && (c <= 0x1FFF)) ||
3185
28.4M
       ((c >= 0x200C) && (c <= 0x200D)) ||
3186
28.4M
       ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3187
28.4M
       ((c >= 0x2070) && (c <= 0x218F)) ||
3188
28.4M
       ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3189
28.4M
       ((c >= 0x3001) && (c <= 0xD7FF)) ||
3190
28.4M
       ((c >= 0xF900) && (c <= 0xFDCF)) ||
3191
28.4M
       ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3192
28.4M
       ((c >= 0x10000) && (c <= 0xEFFFF))))
3193
28.3M
       return(1);
3194
28.4M
    } else {
3195
0
        if ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3196
0
            (c == '.') || (c == '-') ||
3197
0
      (c == '_') || (c == ':') ||
3198
0
      (IS_COMBINING(c)) ||
3199
0
      (IS_EXTENDER(c)))
3200
0
      return(1);
3201
0
    }
3202
76.0k
    return(0);
3203
28.4M
}
3204
3205
static xmlChar * xmlParseAttValueInternal(xmlParserCtxtPtr ctxt,
3206
                                          int *len, int *alloc, int normalize);
3207
3208
static const xmlChar *
3209
14.7k
xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
3210
14.7k
    int len = 0, l;
3211
14.7k
    int c;
3212
14.7k
    int count = 0;
3213
14.7k
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3214
0
                    XML_MAX_TEXT_LENGTH :
3215
14.7k
                    XML_MAX_NAME_LENGTH;
3216
3217
#ifdef DEBUG
3218
    nbParseNameComplex++;
3219
#endif
3220
3221
    /*
3222
     * Handler for more complex cases
3223
     */
3224
14.7k
    GROW;
3225
14.7k
    if (ctxt->instate == XML_PARSER_EOF)
3226
0
        return(NULL);
3227
14.7k
    c = CUR_CHAR(l);
3228
14.7k
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3229
        /*
3230
   * Use the new checks of production [4] [4a] amd [5] of the
3231
   * Update 5 of XML-1.0
3232
   */
3233
14.7k
  if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3234
14.7k
      (!(((c >= 'a') && (c <= 'z')) ||
3235
12.4k
         ((c >= 'A') && (c <= 'Z')) ||
3236
12.4k
         (c == '_') || (c == ':') ||
3237
12.4k
         ((c >= 0xC0) && (c <= 0xD6)) ||
3238
12.4k
         ((c >= 0xD8) && (c <= 0xF6)) ||
3239
12.4k
         ((c >= 0xF8) && (c <= 0x2FF)) ||
3240
12.4k
         ((c >= 0x370) && (c <= 0x37D)) ||
3241
12.4k
         ((c >= 0x37F) && (c <= 0x1FFF)) ||
3242
12.4k
         ((c >= 0x200C) && (c <= 0x200D)) ||
3243
12.4k
         ((c >= 0x2070) && (c <= 0x218F)) ||
3244
12.4k
         ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3245
12.4k
         ((c >= 0x3001) && (c <= 0xD7FF)) ||
3246
12.4k
         ((c >= 0xF900) && (c <= 0xFDCF)) ||
3247
12.4k
         ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3248
12.4k
         ((c >= 0x10000) && (c <= 0xEFFFF))))) {
3249
6.30k
      return(NULL);
3250
6.30k
  }
3251
8.40k
  len += l;
3252
8.40k
  NEXTL(l);
3253
8.40k
  c = CUR_CHAR(l);
3254
17.1M
  while ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3255
17.1M
         (((c >= 'a') && (c <= 'z')) ||
3256
17.1M
          ((c >= 'A') && (c <= 'Z')) ||
3257
17.1M
          ((c >= '0') && (c <= '9')) || /* !start */
3258
17.1M
          (c == '_') || (c == ':') ||
3259
17.1M
          (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3260
17.1M
          ((c >= 0xC0) && (c <= 0xD6)) ||
3261
17.1M
          ((c >= 0xD8) && (c <= 0xF6)) ||
3262
17.1M
          ((c >= 0xF8) && (c <= 0x2FF)) ||
3263
17.1M
          ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3264
17.1M
          ((c >= 0x370) && (c <= 0x37D)) ||
3265
17.1M
          ((c >= 0x37F) && (c <= 0x1FFF)) ||
3266
17.1M
          ((c >= 0x200C) && (c <= 0x200D)) ||
3267
17.1M
          ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3268
17.1M
          ((c >= 0x2070) && (c <= 0x218F)) ||
3269
17.1M
          ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3270
17.1M
          ((c >= 0x3001) && (c <= 0xD7FF)) ||
3271
17.1M
          ((c >= 0xF900) && (c <= 0xFDCF)) ||
3272
17.1M
          ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3273
17.1M
          ((c >= 0x10000) && (c <= 0xEFFFF))
3274
17.1M
    )) {
3275
17.1M
      if (count++ > XML_PARSER_CHUNK_SIZE) {
3276
165k
    count = 0;
3277
165k
    GROW;
3278
165k
                if (ctxt->instate == XML_PARSER_EOF)
3279
0
                    return(NULL);
3280
165k
      }
3281
17.1M
            if (len <= INT_MAX - l)
3282
17.1M
          len += l;
3283
17.1M
      NEXTL(l);
3284
17.1M
      c = CUR_CHAR(l);
3285
17.1M
  }
3286
8.40k
    } else {
3287
0
  if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3288
0
      (!IS_LETTER(c) && (c != '_') &&
3289
0
       (c != ':'))) {
3290
0
      return(NULL);
3291
0
  }
3292
0
  len += l;
3293
0
  NEXTL(l);
3294
0
  c = CUR_CHAR(l);
3295
3296
0
  while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
3297
0
         ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3298
0
    (c == '.') || (c == '-') ||
3299
0
    (c == '_') || (c == ':') ||
3300
0
    (IS_COMBINING(c)) ||
3301
0
    (IS_EXTENDER(c)))) {
3302
0
      if (count++ > XML_PARSER_CHUNK_SIZE) {
3303
0
    count = 0;
3304
0
    GROW;
3305
0
                if (ctxt->instate == XML_PARSER_EOF)
3306
0
                    return(NULL);
3307
0
      }
3308
0
            if (len <= INT_MAX - l)
3309
0
          len += l;
3310
0
      NEXTL(l);
3311
0
      c = CUR_CHAR(l);
3312
0
  }
3313
0
    }
3314
8.40k
    if (len > maxLength) {
3315
384
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
3316
384
        return(NULL);
3317
384
    }
3318
8.02k
    if (ctxt->input->cur - ctxt->input->base < len) {
3319
        /*
3320
         * There were a couple of bugs where PERefs lead to to a change
3321
         * of the buffer. Check the buffer size to avoid passing an invalid
3322
         * pointer to xmlDictLookup.
3323
         */
3324
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
3325
0
                    "unexpected change of input buffer");
3326
0
        return (NULL);
3327
0
    }
3328
8.02k
    if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r'))
3329
0
        return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len));
3330
8.02k
    return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
3331
8.02k
}
3332
3333
/**
3334
 * xmlParseName:
3335
 * @ctxt:  an XML parser context
3336
 *
3337
 * DEPRECATED: Internal function, don't use.
3338
 *
3339
 * parse an XML name.
3340
 *
3341
 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3342
 *                  CombiningChar | Extender
3343
 *
3344
 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3345
 *
3346
 * [6] Names ::= Name (#x20 Name)*
3347
 *
3348
 * Returns the Name parsed or NULL
3349
 */
3350
3351
const xmlChar *
3352
97.7k
xmlParseName(xmlParserCtxtPtr ctxt) {
3353
97.7k
    const xmlChar *in;
3354
97.7k
    const xmlChar *ret;
3355
97.7k
    size_t count = 0;
3356
97.7k
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3357
0
                       XML_MAX_TEXT_LENGTH :
3358
97.7k
                       XML_MAX_NAME_LENGTH;
3359
3360
97.7k
    GROW;
3361
3362
#ifdef DEBUG
3363
    nbParseName++;
3364
#endif
3365
3366
    /*
3367
     * Accelerator for simple ASCII names
3368
     */
3369
97.7k
    in = ctxt->input->cur;
3370
97.7k
    if (((*in >= 0x61) && (*in <= 0x7A)) ||
3371
97.7k
  ((*in >= 0x41) && (*in <= 0x5A)) ||
3372
97.7k
  (*in == '_') || (*in == ':')) {
3373
84.1k
  in++;
3374
181k
  while (((*in >= 0x61) && (*in <= 0x7A)) ||
3375
181k
         ((*in >= 0x41) && (*in <= 0x5A)) ||
3376
181k
         ((*in >= 0x30) && (*in <= 0x39)) ||
3377
181k
         (*in == '_') || (*in == '-') ||
3378
181k
         (*in == ':') || (*in == '.'))
3379
97.6k
      in++;
3380
84.1k
  if ((*in > 0) && (*in < 0x80)) {
3381
83.0k
      count = in - ctxt->input->cur;
3382
83.0k
            if (count > maxLength) {
3383
0
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
3384
0
                return(NULL);
3385
0
            }
3386
83.0k
      ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
3387
83.0k
      ctxt->input->cur = in;
3388
83.0k
      ctxt->input->col += count;
3389
83.0k
      if (ret == NULL)
3390
0
          xmlErrMemory(ctxt, NULL);
3391
83.0k
      return(ret);
3392
83.0k
  }
3393
84.1k
    }
3394
    /* accelerator for special cases */
3395
14.7k
    return(xmlParseNameComplex(ctxt));
3396
97.7k
}
3397
3398
static const xmlChar *
3399
18.8k
xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
3400
18.8k
    int len = 0, l;
3401
18.8k
    int c;
3402
18.8k
    int count = 0;
3403
18.8k
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3404
0
                    XML_MAX_TEXT_LENGTH :
3405
18.8k
                    XML_MAX_NAME_LENGTH;
3406
18.8k
    size_t startPosition = 0;
3407
3408
#ifdef DEBUG
3409
    nbParseNCNameComplex++;
3410
#endif
3411
3412
    /*
3413
     * Handler for more complex cases
3414
     */
3415
18.8k
    GROW;
3416
18.8k
    startPosition = CUR_PTR - BASE_PTR;
3417
18.8k
    c = CUR_CHAR(l);
3418
18.8k
    if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3419
18.8k
  (!xmlIsNameStartChar(ctxt, c) || (c == ':'))) {
3420
12.0k
  return(NULL);
3421
12.0k
    }
3422
3423
23.7M
    while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
3424
23.7M
     (xmlIsNameChar(ctxt, c) && (c != ':'))) {
3425
23.7M
  if (count++ > XML_PARSER_CHUNK_SIZE) {
3426
231k
      count = 0;
3427
231k
      GROW;
3428
231k
            if (ctxt->instate == XML_PARSER_EOF)
3429
1
                return(NULL);
3430
231k
  }
3431
23.7M
        if (len <= INT_MAX - l)
3432
23.7M
      len += l;
3433
23.7M
  NEXTL(l);
3434
23.7M
  c = CUR_CHAR(l);
3435
23.7M
  if (c == 0) {
3436
40
      count = 0;
3437
      /*
3438
       * when shrinking to extend the buffer we really need to preserve
3439
       * the part of the name we already parsed. Hence rolling back
3440
       * by current length.
3441
       */
3442
40
      ctxt->input->cur -= l;
3443
40
      GROW;
3444
40
            if (ctxt->instate == XML_PARSER_EOF)
3445
0
                return(NULL);
3446
40
      ctxt->input->cur += l;
3447
40
      c = CUR_CHAR(l);
3448
40
  }
3449
23.7M
    }
3450
6.77k
    if (len > maxLength) {
3451
508
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3452
508
        return(NULL);
3453
508
    }
3454
6.26k
    return(xmlDictLookup(ctxt->dict, (BASE_PTR + startPosition), len));
3455
6.77k
}
3456
3457
/**
3458
 * xmlParseNCName:
3459
 * @ctxt:  an XML parser context
3460
 * @len:  length of the string parsed
3461
 *
3462
 * parse an XML name.
3463
 *
3464
 * [4NS] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
3465
 *                      CombiningChar | Extender
3466
 *
3467
 * [5NS] NCName ::= (Letter | '_') (NCNameChar)*
3468
 *
3469
 * Returns the Name parsed or NULL
3470
 */
3471
3472
static const xmlChar *
3473
289k
xmlParseNCName(xmlParserCtxtPtr ctxt) {
3474
289k
    const xmlChar *in, *e;
3475
289k
    const xmlChar *ret;
3476
289k
    size_t count = 0;
3477
289k
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3478
0
                       XML_MAX_TEXT_LENGTH :
3479
289k
                       XML_MAX_NAME_LENGTH;
3480
3481
#ifdef DEBUG
3482
    nbParseNCName++;
3483
#endif
3484
3485
    /*
3486
     * Accelerator for simple ASCII names
3487
     */
3488
289k
    in = ctxt->input->cur;
3489
289k
    e = ctxt->input->end;
3490
289k
    if ((((*in >= 0x61) && (*in <= 0x7A)) ||
3491
289k
   ((*in >= 0x41) && (*in <= 0x5A)) ||
3492
289k
   (*in == '_')) && (in < e)) {
3493
273k
  in++;
3494
3.47M
  while ((((*in >= 0x61) && (*in <= 0x7A)) ||
3495
3.47M
          ((*in >= 0x41) && (*in <= 0x5A)) ||
3496
3.47M
          ((*in >= 0x30) && (*in <= 0x39)) ||
3497
3.47M
          (*in == '_') || (*in == '-') ||
3498
3.47M
          (*in == '.')) && (in < e))
3499
3.20M
      in++;
3500
273k
  if (in >= e)
3501
3
      goto complex;
3502
273k
  if ((*in > 0) && (*in < 0x80)) {
3503
270k
      count = in - ctxt->input->cur;
3504
270k
            if (count > maxLength) {
3505
16
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3506
16
                return(NULL);
3507
16
            }
3508
270k
      ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
3509
270k
      ctxt->input->cur = in;
3510
270k
      ctxt->input->col += count;
3511
270k
      if (ret == NULL) {
3512
0
          xmlErrMemory(ctxt, NULL);
3513
0
      }
3514
270k
      return(ret);
3515
270k
  }
3516
273k
    }
3517
18.8k
complex:
3518
18.8k
    return(xmlParseNCNameComplex(ctxt));
3519
289k
}
3520
3521
/**
3522
 * xmlParseNameAndCompare:
3523
 * @ctxt:  an XML parser context
3524
 *
3525
 * parse an XML name and compares for match
3526
 * (specialized for endtag parsing)
3527
 *
3528
 * Returns NULL for an illegal name, (xmlChar*) 1 for success
3529
 * and the name for mismatch
3530
 */
3531
3532
static const xmlChar *
3533
4.74k
xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) {
3534
4.74k
    register const xmlChar *cmp = other;
3535
4.74k
    register const xmlChar *in;
3536
4.74k
    const xmlChar *ret;
3537
3538
4.74k
    GROW;
3539
4.74k
    if (ctxt->instate == XML_PARSER_EOF)
3540
0
        return(NULL);
3541
3542
4.74k
    in = ctxt->input->cur;
3543
11.4k
    while (*in != 0 && *in == *cmp) {
3544
6.74k
  ++in;
3545
6.74k
  ++cmp;
3546
6.74k
    }
3547
4.74k
    if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
3548
  /* success */
3549
4.49k
  ctxt->input->col += in - ctxt->input->cur;
3550
4.49k
  ctxt->input->cur = in;
3551
4.49k
  return (const xmlChar*) 1;
3552
4.49k
    }
3553
    /* failure (or end of input buffer), check with full function */
3554
245
    ret = xmlParseName (ctxt);
3555
    /* strings coming from the dictionary direct compare possible */
3556
245
    if (ret == other) {
3557
0
  return (const xmlChar*) 1;
3558
0
    }
3559
245
    return ret;
3560
245
}
3561
3562
/**
3563
 * xmlParseStringName:
3564
 * @ctxt:  an XML parser context
3565
 * @str:  a pointer to the string pointer (IN/OUT)
3566
 *
3567
 * parse an XML name.
3568
 *
3569
 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3570
 *                  CombiningChar | Extender
3571
 *
3572
 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3573
 *
3574
 * [6] Names ::= Name (#x20 Name)*
3575
 *
3576
 * Returns the Name parsed or NULL. The @str pointer
3577
 * is updated to the current location in the string.
3578
 */
3579
3580
static xmlChar *
3581
864
xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
3582
864
    xmlChar buf[XML_MAX_NAMELEN + 5];
3583
864
    const xmlChar *cur = *str;
3584
864
    int len = 0, l;
3585
864
    int c;
3586
864
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3587
0
                    XML_MAX_TEXT_LENGTH :
3588
864
                    XML_MAX_NAME_LENGTH;
3589
3590
#ifdef DEBUG
3591
    nbParseStringName++;
3592
#endif
3593
3594
864
    c = CUR_SCHAR(cur, l);
3595
864
    if (!xmlIsNameStartChar(ctxt, c)) {
3596
171
  return(NULL);
3597
171
    }
3598
3599
693
    COPY_BUF(l,buf,len,c);
3600
693
    cur += l;
3601
693
    c = CUR_SCHAR(cur, l);
3602
17.1k
    while (xmlIsNameChar(ctxt, c)) {
3603
16.9k
  COPY_BUF(l,buf,len,c);
3604
16.9k
  cur += l;
3605
16.9k
  c = CUR_SCHAR(cur, l);
3606
16.9k
  if (len >= XML_MAX_NAMELEN) { /* test bigentname.xml */
3607
      /*
3608
       * Okay someone managed to make a huge name, so he's ready to pay
3609
       * for the processing speed.
3610
       */
3611
510
      xmlChar *buffer;
3612
510
      int max = len * 2;
3613
3614
510
      buffer = (xmlChar *) xmlMallocAtomic(max);
3615
510
      if (buffer == NULL) {
3616
0
          xmlErrMemory(ctxt, NULL);
3617
0
    return(NULL);
3618
0
      }
3619
510
      memcpy(buffer, buf, len);
3620
2.23M
      while (xmlIsNameChar(ctxt, c)) {
3621
2.23M
    if (len + 10 > max) {
3622
3.16k
        xmlChar *tmp;
3623
3624
3.16k
        max *= 2;
3625
3.16k
        tmp = (xmlChar *) xmlRealloc(buffer, max);
3626
3.16k
        if (tmp == NULL) {
3627
0
      xmlErrMemory(ctxt, NULL);
3628
0
      xmlFree(buffer);
3629
0
      return(NULL);
3630
0
        }
3631
3.16k
        buffer = tmp;
3632
3.16k
    }
3633
2.23M
    COPY_BUF(l,buffer,len,c);
3634
2.23M
    cur += l;
3635
2.23M
    c = CUR_SCHAR(cur, l);
3636
2.23M
                if (len > maxLength) {
3637
34
                    xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3638
34
                    xmlFree(buffer);
3639
34
                    return(NULL);
3640
34
                }
3641
2.23M
      }
3642
476
      buffer[len] = 0;
3643
476
      *str = cur;
3644
476
      return(buffer);
3645
510
  }
3646
16.9k
    }
3647
183
    if (len > maxLength) {
3648
0
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3649
0
        return(NULL);
3650
0
    }
3651
183
    *str = cur;
3652
183
    return(xmlStrndup(buf, len));
3653
183
}
3654
3655
/**
3656
 * xmlParseNmtoken:
3657
 * @ctxt:  an XML parser context
3658
 *
3659
 * DEPRECATED: Internal function, don't use.
3660
 *
3661
 * parse an XML Nmtoken.
3662
 *
3663
 * [7] Nmtoken ::= (NameChar)+
3664
 *
3665
 * [8] Nmtokens ::= Nmtoken (#x20 Nmtoken)*
3666
 *
3667
 * Returns the Nmtoken parsed or NULL
3668
 */
3669
3670
xmlChar *
3671
72.0k
xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
3672
72.0k
    xmlChar buf[XML_MAX_NAMELEN + 5];
3673
72.0k
    int len = 0, l;
3674
72.0k
    int c;
3675
72.0k
    int count = 0;
3676
72.0k
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3677
0
                    XML_MAX_TEXT_LENGTH :
3678
72.0k
                    XML_MAX_NAME_LENGTH;
3679
3680
#ifdef DEBUG
3681
    nbParseNmToken++;
3682
#endif
3683
3684
72.0k
    GROW;
3685
72.0k
    if (ctxt->instate == XML_PARSER_EOF)
3686
0
        return(NULL);
3687
72.0k
    c = CUR_CHAR(l);
3688
3689
160k
    while (xmlIsNameChar(ctxt, c)) {
3690
88.8k
  if (count++ > XML_PARSER_CHUNK_SIZE) {
3691
0
      count = 0;
3692
0
      GROW;
3693
0
  }
3694
88.8k
  COPY_BUF(l,buf,len,c);
3695
88.8k
  NEXTL(l);
3696
88.8k
  c = CUR_CHAR(l);
3697
88.8k
  if (c == 0) {
3698
0
      count = 0;
3699
0
      GROW;
3700
0
      if (ctxt->instate == XML_PARSER_EOF)
3701
0
    return(NULL);
3702
0
            c = CUR_CHAR(l);
3703
0
  }
3704
88.8k
  if (len >= XML_MAX_NAMELEN) {
3705
      /*
3706
       * Okay someone managed to make a huge token, so he's ready to pay
3707
       * for the processing speed.
3708
       */
3709
254
      xmlChar *buffer;
3710
254
      int max = len * 2;
3711
3712
254
      buffer = (xmlChar *) xmlMallocAtomic(max);
3713
254
      if (buffer == NULL) {
3714
0
          xmlErrMemory(ctxt, NULL);
3715
0
    return(NULL);
3716
0
      }
3717
254
      memcpy(buffer, buf, len);
3718
2.33M
      while (xmlIsNameChar(ctxt, c)) {
3719
2.33M
    if (count++ > XML_PARSER_CHUNK_SIZE) {
3720
22.8k
        count = 0;
3721
22.8k
        GROW;
3722
22.8k
                    if (ctxt->instate == XML_PARSER_EOF) {
3723
0
                        xmlFree(buffer);
3724
0
                        return(NULL);
3725
0
                    }
3726
22.8k
    }
3727
2.33M
    if (len + 10 > max) {
3728
1.65k
        xmlChar *tmp;
3729
3730
1.65k
        max *= 2;
3731
1.65k
        tmp = (xmlChar *) xmlRealloc(buffer, max);
3732
1.65k
        if (tmp == NULL) {
3733
0
      xmlErrMemory(ctxt, NULL);
3734
0
      xmlFree(buffer);
3735
0
      return(NULL);
3736
0
        }
3737
1.65k
        buffer = tmp;
3738
1.65k
    }
3739
2.33M
    COPY_BUF(l,buffer,len,c);
3740
2.33M
    NEXTL(l);
3741
2.33M
    c = CUR_CHAR(l);
3742
2.33M
                if (len > maxLength) {
3743
53
                    xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
3744
53
                    xmlFree(buffer);
3745
53
                    return(NULL);
3746
53
                }
3747
2.33M
      }
3748
201
      buffer[len] = 0;
3749
201
      return(buffer);
3750
254
  }
3751
88.8k
    }
3752
71.7k
    if (len == 0)
3753
2.49k
        return(NULL);
3754
69.2k
    if (len > maxLength) {
3755
0
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
3756
0
        return(NULL);
3757
0
    }
3758
69.2k
    return(xmlStrndup(buf, len));
3759
69.2k
}
3760
3761
/**
3762
 * xmlParseEntityValue:
3763
 * @ctxt:  an XML parser context
3764
 * @orig:  if non-NULL store a copy of the original entity value
3765
 *
3766
 * DEPRECATED: Internal function, don't use.
3767
 *
3768
 * parse a value for ENTITY declarations
3769
 *
3770
 * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
3771
 *                 "'" ([^%&'] | PEReference | Reference)* "'"
3772
 *
3773
 * Returns the EntityValue parsed with reference substituted or NULL
3774
 */
3775
3776
xmlChar *
3777
2.06k
xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
3778
2.06k
    xmlChar *buf = NULL;
3779
2.06k
    int len = 0;
3780
2.06k
    int size = XML_PARSER_BUFFER_SIZE;
3781
2.06k
    int c, l;
3782
2.06k
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3783
0
                    XML_MAX_HUGE_LENGTH :
3784
2.06k
                    XML_MAX_TEXT_LENGTH;
3785
2.06k
    xmlChar stop;
3786
2.06k
    xmlChar *ret = NULL;
3787
2.06k
    const xmlChar *cur = NULL;
3788
2.06k
    xmlParserInputPtr input;
3789
3790
2.06k
    if (RAW == '"') stop = '"';
3791
2.06k
    else if (RAW == '\'') stop = '\'';
3792
0
    else {
3793
0
  xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_STARTED, NULL);
3794
0
  return(NULL);
3795
0
    }
3796
2.06k
    buf = (xmlChar *) xmlMallocAtomic(size);
3797
2.06k
    if (buf == NULL) {
3798
0
  xmlErrMemory(ctxt, NULL);
3799
0
  return(NULL);
3800
0
    }
3801
3802
    /*
3803
     * The content of the entity definition is copied in a buffer.
3804
     */
3805
3806
2.06k
    ctxt->instate = XML_PARSER_ENTITY_VALUE;
3807
2.06k
    input = ctxt->input;
3808
2.06k
    GROW;
3809
2.06k
    if (ctxt->instate == XML_PARSER_EOF)
3810
0
        goto error;
3811
2.06k
    NEXT;
3812
2.06k
    c = CUR_CHAR(l);
3813
    /*
3814
     * NOTE: 4.4.5 Included in Literal
3815
     * When a parameter entity reference appears in a literal entity
3816
     * value, ... a single or double quote character in the replacement
3817
     * text is always treated as a normal data character and will not
3818
     * terminate the literal.
3819
     * In practice it means we stop the loop only when back at parsing
3820
     * the initial entity and the quote is found
3821
     */
3822
120M
    while (((IS_CHAR(c)) && ((c != stop) || /* checked */
3823
120M
      (ctxt->input != input))) && (ctxt->instate != XML_PARSER_EOF)) {
3824
120M
  if (len + 5 >= size) {
3825
2.57k
      xmlChar *tmp;
3826
3827
2.57k
      size *= 2;
3828
2.57k
      tmp = (xmlChar *) xmlRealloc(buf, size);
3829
2.57k
      if (tmp == NULL) {
3830
0
    xmlErrMemory(ctxt, NULL);
3831
0
                goto error;
3832
0
      }
3833
2.57k
      buf = tmp;
3834
2.57k
  }
3835
120M
  COPY_BUF(l,buf,len,c);
3836
120M
  NEXTL(l);
3837
3838
120M
  GROW;
3839
120M
  c = CUR_CHAR(l);
3840
120M
  if (c == 0) {
3841
1
      GROW;
3842
1
      c = CUR_CHAR(l);
3843
1
  }
3844
3845
120M
        if (len > maxLength) {
3846
4
            xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
3847
4
                           "entity value too long\n");
3848
4
            goto error;
3849
4
        }
3850
120M
    }
3851
2.05k
    buf[len] = 0;
3852
2.05k
    if (ctxt->instate == XML_PARSER_EOF)
3853
0
        goto error;
3854
2.05k
    if (c != stop) {
3855
1
        xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL);
3856
1
        goto error;
3857
1
    }
3858
2.05k
    NEXT;
3859
3860
    /*
3861
     * Raise problem w.r.t. '&' and '%' being used in non-entities
3862
     * reference constructs. Note Charref will be handled in
3863
     * xmlStringDecodeEntities()
3864
     */
3865
2.05k
    cur = buf;
3866
317M
    while (*cur != 0) { /* non input consuming */
3867
317M
  if ((*cur == '%') || ((*cur == '&') && (cur[1] != '#'))) {
3868
277
      xmlChar *name;
3869
277
      xmlChar tmp = *cur;
3870
277
            int nameOk = 0;
3871
3872
277
      cur++;
3873
277
      name = xmlParseStringName(ctxt, &cur);
3874
277
            if (name != NULL) {
3875
140
                nameOk = 1;
3876
140
                xmlFree(name);
3877
140
            }
3878
277
            if ((nameOk == 0) || (*cur != ';')) {
3879
139
    xmlFatalErrMsgInt(ctxt, XML_ERR_ENTITY_CHAR_ERROR,
3880
139
      "EntityValue: '%c' forbidden except for entities references\n",
3881
139
                            tmp);
3882
139
                goto error;
3883
139
      }
3884
138
      if ((tmp == '%') && (ctxt->inSubset == 1) &&
3885
138
    (ctxt->inputNr == 1)) {
3886
0
    xmlFatalErr(ctxt, XML_ERR_ENTITY_PE_INTERNAL, NULL);
3887
0
                goto error;
3888
0
      }
3889
138
      if (*cur == 0)
3890
0
          break;
3891
138
  }
3892
317M
  cur++;
3893
317M
    }
3894
3895
    /*
3896
     * Then PEReference entities are substituted.
3897
     *
3898
     * NOTE: 4.4.7 Bypassed
3899
     * When a general entity reference appears in the EntityValue in
3900
     * an entity declaration, it is bypassed and left as is.
3901
     * so XML_SUBSTITUTE_REF is not set here.
3902
     */
3903
1.91k
    ++ctxt->depth;
3904
1.91k
    ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF,
3905
1.91k
                                  0, 0, 0);
3906
1.91k
    --ctxt->depth;
3907
1.91k
    if (orig != NULL) {
3908
1.91k
        *orig = buf;
3909
1.91k
        buf = NULL;
3910
1.91k
    }
3911
3912
2.06k
error:
3913
2.06k
    if (buf != NULL)
3914
144
        xmlFree(buf);
3915
2.06k
    return(ret);
3916
1.91k
}
3917
3918
/**
3919
 * xmlParseAttValueComplex:
3920
 * @ctxt:  an XML parser context
3921
 * @len:   the resulting attribute len
3922
 * @normalize:  whether to apply the inner normalization
3923
 *
3924
 * parse a value for an attribute, this is the fallback function
3925
 * of xmlParseAttValue() when the attribute parsing requires handling
3926
 * of non-ASCII characters, or normalization compaction.
3927
 *
3928
 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
3929
 */
3930
static xmlChar *
3931
29.9k
xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
3932
29.9k
    xmlChar limit = 0;
3933
29.9k
    xmlChar *buf = NULL;
3934
29.9k
    xmlChar *rep = NULL;
3935
29.9k
    size_t len = 0;
3936
29.9k
    size_t buf_size = 0;
3937
29.9k
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3938
0
                       XML_MAX_HUGE_LENGTH :
3939
29.9k
                       XML_MAX_TEXT_LENGTH;
3940
29.9k
    int c, l, in_space = 0;
3941
29.9k
    xmlChar *current = NULL;
3942
29.9k
    xmlEntityPtr ent;
3943
3944
29.9k
    if (NXT(0) == '"') {
3945
29.8k
  ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
3946
29.8k
  limit = '"';
3947
29.8k
        NEXT;
3948
29.8k
    } else if (NXT(0) == '\'') {
3949
92
  limit = '\'';
3950
92
  ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
3951
92
        NEXT;
3952
92
    } else {
3953
0
  xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
3954
0
  return(NULL);
3955
0
    }
3956
3957
    /*
3958
     * allocate a translation buffer.
3959
     */
3960
29.9k
    buf_size = XML_PARSER_BUFFER_SIZE;
3961
29.9k
    buf = (xmlChar *) xmlMallocAtomic(buf_size);
3962
29.9k
    if (buf == NULL) goto mem_error;
3963
3964
    /*
3965
     * OK loop until we reach one of the ending char or a size limit.
3966
     */
3967
29.9k
    c = CUR_CHAR(l);
3968
107M
    while (((NXT(0) != limit) && /* checked */
3969
107M
            (IS_CHAR(c)) && (c != '<')) &&
3970
107M
            (ctxt->instate != XML_PARSER_EOF)) {
3971
107M
  if (c == '&') {
3972
28.2k
      in_space = 0;
3973
28.2k
      if (NXT(1) == '#') {
3974
24.2k
    int val = xmlParseCharRef(ctxt);
3975
3976
24.2k
    if (val == '&') {
3977
33
        if (ctxt->replaceEntities) {
3978
0
      if (len + 10 > buf_size) {
3979
0
          growBuffer(buf, 10);
3980
0
      }
3981
0
      buf[len++] = '&';
3982
33
        } else {
3983
      /*
3984
       * The reparsing will be done in xmlStringGetNodeList()
3985
       * called by the attribute() function in SAX.c
3986
       */
3987
33
      if (len + 10 > buf_size) {
3988
0
          growBuffer(buf, 10);
3989
0
      }
3990
33
      buf[len++] = '&';
3991
33
      buf[len++] = '#';
3992
33
      buf[len++] = '3';
3993
33
      buf[len++] = '8';
3994
33
      buf[len++] = ';';
3995
33
        }
3996
24.2k
    } else if (val != 0) {
3997
24.1k
        if (len + 10 > buf_size) {
3998
0
      growBuffer(buf, 10);
3999
0
        }
4000
24.1k
        len += xmlCopyChar(0, &buf[len], val);
4001
24.1k
    }
4002
24.2k
      } else {
4003
3.92k
    ent = xmlParseEntityRef(ctxt);
4004
3.92k
    ctxt->nbentities++;
4005
3.92k
    if (ent != NULL)
4006
3.83k
        ctxt->nbentities += ent->owner;
4007
3.92k
    if ((ent != NULL) &&
4008
3.92k
        (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
4009
0
        if (len + 10 > buf_size) {
4010
0
      growBuffer(buf, 10);
4011
0
        }
4012
0
        if ((ctxt->replaceEntities == 0) &&
4013
0
            (ent->content[0] == '&')) {
4014
0
      buf[len++] = '&';
4015
0
      buf[len++] = '#';
4016
0
      buf[len++] = '3';
4017
0
      buf[len++] = '8';
4018
0
      buf[len++] = ';';
4019
0
        } else {
4020
0
      buf[len++] = ent->content[0];
4021
0
        }
4022
3.92k
    } else if ((ent != NULL) &&
4023
3.92k
               (ctxt->replaceEntities != 0)) {
4024
0
        if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
4025
0
      ++ctxt->depth;
4026
0
      rep = xmlStringDecodeEntities(ctxt, ent->content,
4027
0
                  XML_SUBSTITUTE_REF,
4028
0
                  0, 0, 0);
4029
0
      --ctxt->depth;
4030
0
      if (rep != NULL) {
4031
0
          current = rep;
4032
0
          while (*current != 0) { /* non input consuming */
4033
0
                                if ((*current == 0xD) || (*current == 0xA) ||
4034
0
                                    (*current == 0x9)) {
4035
0
                                    buf[len++] = 0x20;
4036
0
                                    current++;
4037
0
                                } else
4038
0
                                    buf[len++] = *current++;
4039
0
        if (len + 10 > buf_size) {
4040
0
            growBuffer(buf, 10);
4041
0
        }
4042
0
          }
4043
0
          xmlFree(rep);
4044
0
          rep = NULL;
4045
0
      }
4046
0
        } else {
4047
0
      if (len + 10 > buf_size) {
4048
0
          growBuffer(buf, 10);
4049
0
      }
4050
0
      if (ent->content != NULL)
4051
0
          buf[len++] = ent->content[0];
4052
0
        }
4053
3.92k
    } else if (ent != NULL) {
4054
3.83k
        int i = xmlStrlen(ent->name);
4055
3.83k
        const xmlChar *cur = ent->name;
4056
4057
        /*
4058
         * This may look absurd but is needed to detect
4059
         * entities problems
4060
         */
4061
3.83k
        if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
4062
3.83k
      (ent->content != NULL) && (ent->checked == 0)) {
4063
7
      unsigned long oldnbent = ctxt->nbentities, diff;
4064
4065
7
      ++ctxt->depth;
4066
7
      rep = xmlStringDecodeEntities(ctxt, ent->content,
4067
7
              XML_SUBSTITUTE_REF, 0, 0, 0);
4068
7
      --ctxt->depth;
4069
4070
7
                        diff = ctxt->nbentities - oldnbent + 1;
4071
7
                        if (diff > INT_MAX / 2)
4072
0
                            diff = INT_MAX / 2;
4073
7
                        ent->checked = diff * 2;
4074
7
      if (rep != NULL) {
4075
7
          if (xmlStrchr(rep, '<'))
4076
1
              ent->checked |= 1;
4077
7
          xmlFree(rep);
4078
7
          rep = NULL;
4079
7
      } else {
4080
0
                            ent->content[0] = 0;
4081
0
                        }
4082
7
        }
4083
4084
        /*
4085
         * Just output the reference
4086
         */
4087
3.83k
        buf[len++] = '&';
4088
3.88k
        while (len + i + 10 > buf_size) {
4089
94
      growBuffer(buf, i + 10);
4090
94
        }
4091
7.67k
        for (;i > 0;i--)
4092
3.83k
      buf[len++] = *cur++;
4093
3.83k
        buf[len++] = ';';
4094
3.83k
    }
4095
3.92k
      }
4096
107M
  } else {
4097
107M
      if ((c == 0x20) || (c == 0xD) || (c == 0xA) || (c == 0x9)) {
4098
3.14M
          if ((len != 0) || (!normalize)) {
4099
3.14M
        if ((!normalize) || (!in_space)) {
4100
3.14M
      COPY_BUF(l,buf,len,0x20);
4101
3.14M
      while (len + 10 > buf_size) {
4102
4.39k
          growBuffer(buf, 10);
4103
4.39k
      }
4104
3.14M
        }
4105
3.14M
        in_space = 1;
4106
3.14M
    }
4107
104M
      } else {
4108
104M
          in_space = 0;
4109
104M
    COPY_BUF(l,buf,len,c);
4110
104M
    if (len + 10 > buf_size) {
4111
28.7k
        growBuffer(buf, 10);
4112
28.7k
    }
4113
104M
      }
4114
107M
      NEXTL(l);
4115
107M
  }
4116
107M
  GROW;
4117
107M
  c = CUR_CHAR(l);
4118
107M
        if (len > maxLength) {
4119
3
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
4120
3
                           "AttValue length too long\n");
4121
3
            goto mem_error;
4122
3
        }
4123
107M
    }
4124
29.9k
    if (ctxt->instate == XML_PARSER_EOF)
4125
2
        goto error;
4126
4127
29.9k
    if ((in_space) && (normalize)) {
4128
0
        while ((len > 0) && (buf[len - 1] == 0x20)) len--;
4129
0
    }
4130
29.9k
    buf[len] = 0;
4131
29.9k
    if (RAW == '<') {
4132
2.17k
  xmlFatalErr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, NULL);
4133
27.7k
    } else if (RAW != limit) {
4134
47
  if ((c != 0) && (!IS_CHAR(c))) {
4135
46
      xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
4136
46
         "invalid character in attribute value\n");
4137
46
  } else {
4138
1
      xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
4139
1
         "AttValue: ' expected\n");
4140
1
        }
4141
47
    } else
4142
27.6k
  NEXT;
4143
4144
29.9k
    if (attlen != NULL) *attlen = len;
4145
29.9k
    return(buf);
4146
4147
3
mem_error:
4148
3
    xmlErrMemory(ctxt, NULL);
4149
5
error:
4150
5
    if (buf != NULL)
4151
5
        xmlFree(buf);
4152
5
    if (rep != NULL)
4153
0
        xmlFree(rep);
4154
5
    return(NULL);
4155
3
}
4156
4157
/**
4158
 * xmlParseAttValue:
4159
 * @ctxt:  an XML parser context
4160
 *
4161
 * DEPRECATED: Internal function, don't use.
4162
 *
4163
 * parse a value for an attribute
4164
 * Note: the parser won't do substitution of entities here, this
4165
 * will be handled later in xmlStringGetNodeList
4166
 *
4167
 * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |
4168
 *                   "'" ([^<&'] | Reference)* "'"
4169
 *
4170
 * 3.3.3 Attribute-Value Normalization:
4171
 * Before the value of an attribute is passed to the application or
4172
 * checked for validity, the XML processor must normalize it as follows:
4173
 * - a character reference is processed by appending the referenced
4174
 *   character to the attribute value
4175
 * - an entity reference is processed by recursively processing the
4176
 *   replacement text of the entity
4177
 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
4178
 *   appending #x20 to the normalized value, except that only a single
4179
 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
4180
 *   parsed entity or the literal entity value of an internal parsed entity
4181
 * - other characters are processed by appending them to the normalized value
4182
 * If the declared value is not CDATA, then the XML processor must further
4183
 * process the normalized attribute value by discarding any leading and
4184
 * trailing space (#x20) characters, and by replacing sequences of space
4185
 * (#x20) characters by a single space (#x20) character.
4186
 * All attributes for which no declaration has been read should be treated
4187
 * by a non-validating parser as if declared CDATA.
4188
 *
4189
 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
4190
 */
4191
4192
4193
xmlChar *
4194
2.49k
xmlParseAttValue(xmlParserCtxtPtr ctxt) {
4195
2.49k
    if ((ctxt == NULL) || (ctxt->input == NULL)) return(NULL);
4196
2.49k
    return(xmlParseAttValueInternal(ctxt, NULL, NULL, 0));
4197
2.49k
}
4198
4199
/**
4200
 * xmlParseSystemLiteral:
4201
 * @ctxt:  an XML parser context
4202
 *
4203
 * DEPRECATED: Internal function, don't use.
4204
 *
4205
 * parse an XML Literal
4206
 *
4207
 * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
4208
 *
4209
 * Returns the SystemLiteral parsed or NULL
4210
 */
4211
4212
xmlChar *
4213
3.54k
xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
4214
3.54k
    xmlChar *buf = NULL;
4215
3.54k
    int len = 0;
4216
3.54k
    int size = XML_PARSER_BUFFER_SIZE;
4217
3.54k
    int cur, l;
4218
3.54k
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4219
0
                    XML_MAX_TEXT_LENGTH :
4220
3.54k
                    XML_MAX_NAME_LENGTH;
4221
3.54k
    xmlChar stop;
4222
3.54k
    int state = ctxt->instate;
4223
3.54k
    int count = 0;
4224
4225
3.54k
    SHRINK;
4226
3.54k
    if (RAW == '"') {
4227
691
        NEXT;
4228
691
  stop = '"';
4229
2.85k
    } else if (RAW == '\'') {
4230
2.25k
        NEXT;
4231
2.25k
  stop = '\'';
4232
2.25k
    } else {
4233
598
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
4234
598
  return(NULL);
4235
598
    }
4236
4237
2.95k
    buf = (xmlChar *) xmlMallocAtomic(size);
4238
2.95k
    if (buf == NULL) {
4239
0
        xmlErrMemory(ctxt, NULL);
4240
0
  return(NULL);
4241
0
    }
4242
2.95k
    ctxt->instate = XML_PARSER_SYSTEM_LITERAL;
4243
2.95k
    cur = CUR_CHAR(l);
4244
451k
    while ((IS_CHAR(cur)) && (cur != stop)) { /* checked */
4245
448k
  if (len + 5 >= size) {
4246
2.55k
      xmlChar *tmp;
4247
4248
2.55k
      size *= 2;
4249
2.55k
      tmp = (xmlChar *) xmlRealloc(buf, size);
4250
2.55k
      if (tmp == NULL) {
4251
0
          xmlFree(buf);
4252
0
    xmlErrMemory(ctxt, NULL);
4253
0
    ctxt->instate = (xmlParserInputState) state;
4254
0
    return(NULL);
4255
0
      }
4256
2.55k
      buf = tmp;
4257
2.55k
  }
4258
448k
  count++;
4259
448k
  if (count > 50) {
4260
7.77k
      SHRINK;
4261
7.77k
      GROW;
4262
7.77k
      count = 0;
4263
7.77k
            if (ctxt->instate == XML_PARSER_EOF) {
4264
0
          xmlFree(buf);
4265
0
    return(NULL);
4266
0
            }
4267
7.77k
  }
4268
448k
  COPY_BUF(l,buf,len,cur);
4269
448k
  NEXTL(l);
4270
448k
  cur = CUR_CHAR(l);
4271
448k
  if (cur == 0) {
4272
2
      GROW;
4273
2
      SHRINK;
4274
2
      cur = CUR_CHAR(l);
4275
2
  }
4276
448k
        if (len > maxLength) {
4277
0
            xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral");
4278
0
            xmlFree(buf);
4279
0
            ctxt->instate = (xmlParserInputState) state;
4280
0
            return(NULL);
4281
0
        }
4282
448k
    }
4283
2.95k
    buf[len] = 0;
4284
2.95k
    ctxt->instate = (xmlParserInputState) state;
4285
2.95k
    if (!IS_CHAR(cur)) {
4286
2
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
4287
2.94k
    } else {
4288
2.94k
  NEXT;
4289
2.94k
    }
4290
2.95k
    return(buf);
4291
2.95k
}
4292
4293
/**
4294
 * xmlParsePubidLiteral:
4295
 * @ctxt:  an XML parser context
4296
 *
4297
 * DEPRECATED: Internal function, don't use.
4298
 *
4299
 * parse an XML public literal
4300
 *
4301
 * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
4302
 *
4303
 * Returns the PubidLiteral parsed or NULL.
4304
 */
4305
4306
xmlChar *
4307
28.9k
xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
4308
28.9k
    xmlChar *buf = NULL;
4309
28.9k
    int len = 0;
4310
28.9k
    int size = XML_PARSER_BUFFER_SIZE;
4311
28.9k
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4312
0
                    XML_MAX_TEXT_LENGTH :
4313
28.9k
                    XML_MAX_NAME_LENGTH;
4314
28.9k
    xmlChar cur;
4315
28.9k
    xmlChar stop;
4316
28.9k
    int count = 0;
4317
28.9k
    xmlParserInputState oldstate = ctxt->instate;
4318
4319
28.9k
    SHRINK;
4320
28.9k
    if (RAW == '"') {
4321
28.3k
        NEXT;
4322
28.3k
  stop = '"';
4323
28.3k
    } else if (RAW == '\'') {
4324
599
        NEXT;
4325
599
  stop = '\'';
4326
599
    } else {
4327
0
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
4328
0
  return(NULL);
4329
0
    }
4330
28.9k
    buf = (xmlChar *) xmlMallocAtomic(size);
4331
28.9k
    if (buf == NULL) {
4332
0
  xmlErrMemory(ctxt, NULL);
4333
0
  return(NULL);
4334
0
    }
4335
28.9k
    ctxt->instate = XML_PARSER_PUBLIC_LITERAL;
4336
28.9k
    cur = CUR;
4337
3.26M
    while ((IS_PUBIDCHAR_CH(cur)) && (cur != stop)) { /* checked */
4338
3.24M
  if (len + 1 >= size) {
4339
13.5k
      xmlChar *tmp;
4340
4341
13.5k
      size *= 2;
4342
13.5k
      tmp = (xmlChar *) xmlRealloc(buf, size);
4343
13.5k
      if (tmp == NULL) {
4344
0
    xmlErrMemory(ctxt, NULL);
4345
0
    xmlFree(buf);
4346
0
    return(NULL);
4347
0
      }
4348
13.5k
      buf = tmp;
4349
13.5k
  }
4350
3.24M
  buf[len++] = cur;
4351
3.24M
  count++;
4352
3.24M
  if (count > 50) {
4353
55.7k
      SHRINK;
4354
55.7k
      GROW;
4355
55.7k
      count = 0;
4356
55.7k
            if (ctxt->instate == XML_PARSER_EOF) {
4357
0
    xmlFree(buf);
4358
0
    return(NULL);
4359
0
            }
4360
55.7k
  }
4361
3.24M
  NEXT;
4362
3.24M
  cur = CUR;
4363
3.24M
  if (cur == 0) {
4364
6.77k
      GROW;
4365
6.77k
      SHRINK;
4366
6.77k
      cur = CUR;
4367
6.77k
  }
4368
3.24M
        if (len > maxLength) {
4369
1
            xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Public ID");
4370
1
            xmlFree(buf);
4371
1
            return(NULL);
4372
1
        }
4373
3.24M
    }
4374
28.9k
    buf[len] = 0;
4375
28.9k
    if (cur != stop) {
4376
28.2k
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
4377
28.2k
    } else {
4378
691
  NEXT;
4379
691
    }
4380
28.9k
    ctxt->instate = oldstate;
4381
28.9k
    return(buf);
4382
28.9k
}
4383
4384
static void xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata);
4385
4386
/*
4387
 * used for the test in the inner loop of the char data testing
4388
 */
4389
static const unsigned char test_char_data[256] = {
4390
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4391
    0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9, CR/LF separated */
4392
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4393
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4394
    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x00, 0x27, /* & */
4395
    0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
4396
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
4397
    0x38, 0x39, 0x3A, 0x3B, 0x00, 0x3D, 0x3E, 0x3F, /* < */
4398
    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
4399
    0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
4400
    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
4401
    0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x00, 0x5E, 0x5F, /* ] */
4402
    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
4403
    0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
4404
    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
4405
    0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
4406
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* non-ascii */
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
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4417
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4418
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4419
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4420
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4421
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4422
};
4423
4424
/**
4425
 * xmlParseCharData:
4426
 * @ctxt:  an XML parser context
4427
 * @cdata:  int indicating whether we are within a CDATA section
4428
 *
4429
 * DEPRECATED: Internal function, don't use.
4430
 *
4431
 * parse a CharData section.
4432
 * if we are within a CDATA section ']]>' marks an end of section.
4433
 *
4434
 * The right angle bracket (>) may be represented using the string "&gt;",
4435
 * and must, for compatibility, be escaped using "&gt;" or a character
4436
 * reference when it appears in the string "]]>" in content, when that
4437
 * string is not marking the end of a CDATA section.
4438
 *
4439
 * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
4440
 */
4441
4442
void
4443
114k
xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) {
4444
114k
    const xmlChar *in;
4445
114k
    int nbchar = 0;
4446
114k
    int line = ctxt->input->line;
4447
114k
    int col = ctxt->input->col;
4448
114k
    int ccol;
4449
4450
114k
    SHRINK;
4451
114k
    GROW;
4452
    /*
4453
     * Accelerated common case where input don't need to be
4454
     * modified before passing it to the handler.
4455
     */
4456
114k
    if (!cdata) {
4457
114k
  in = ctxt->input->cur;
4458
115k
  do {
4459
141k
get_more_space:
4460
155k
      while (*in == 0x20) { in++; ctxt->input->col++; }
4461
141k
      if (*in == 0xA) {
4462
152k
    do {
4463
152k
        ctxt->input->line++; ctxt->input->col = 1;
4464
152k
        in++;
4465
152k
    } while (*in == 0xA);
4466
26.5k
    goto get_more_space;
4467
26.5k
      }
4468
115k
      if (*in == '<') {
4469
17.6k
    nbchar = in - ctxt->input->cur;
4470
17.6k
    if (nbchar > 0) {
4471
17.2k
        const xmlChar *tmp = ctxt->input->cur;
4472
17.2k
        ctxt->input->cur = in;
4473
4474
17.2k
        if ((ctxt->sax != NULL) &&
4475
17.2k
            (ctxt->sax->ignorableWhitespace !=
4476
17.2k
             ctxt->sax->characters)) {
4477
0
      if (areBlanks(ctxt, tmp, nbchar, 1)) {
4478
0
          if (ctxt->sax->ignorableWhitespace != NULL)
4479
0
        ctxt->sax->ignorableWhitespace(ctxt->userData,
4480
0
                   tmp, nbchar);
4481
0
      } else {
4482
0
          if (ctxt->sax->characters != NULL)
4483
0
        ctxt->sax->characters(ctxt->userData,
4484
0
                  tmp, nbchar);
4485
0
          if (*ctxt->space == -1)
4486
0
              *ctxt->space = -2;
4487
0
      }
4488
17.2k
        } else if ((ctxt->sax != NULL) &&
4489
17.2k
                   (ctxt->sax->characters != NULL)) {
4490
17.2k
      ctxt->sax->characters(ctxt->userData,
4491
17.2k
                tmp, nbchar);
4492
17.2k
        }
4493
17.2k
    }
4494
17.6k
    return;
4495
17.6k
      }
4496
4497
111k
get_more:
4498
111k
            ccol = ctxt->input->col;
4499
2.54M
      while (test_char_data[*in]) {
4500
2.42M
    in++;
4501
2.42M
    ccol++;
4502
2.42M
      }
4503
111k
      ctxt->input->col = ccol;
4504
111k
      if (*in == 0xA) {
4505
117k
    do {
4506
117k
        ctxt->input->line++; ctxt->input->col = 1;
4507
117k
        in++;
4508
117k
    } while (*in == 0xA);
4509
11.7k
    goto get_more;
4510
11.7k
      }
4511
100k
      if (*in == ']') {
4512
2.56k
    if ((in[1] == ']') && (in[2] == '>')) {
4513
0
        xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
4514
0
        ctxt->input->cur = in + 1;
4515
0
        return;
4516
0
    }
4517
2.56k
    in++;
4518
2.56k
    ctxt->input->col++;
4519
2.56k
    goto get_more;
4520
2.56k
      }
4521
97.6k
      nbchar = in - ctxt->input->cur;
4522
97.6k
      if (nbchar > 0) {
4523
82.6k
    if ((ctxt->sax != NULL) &&
4524
82.6k
        (ctxt->sax->ignorableWhitespace !=
4525
82.6k
         ctxt->sax->characters) &&
4526
82.6k
        (IS_BLANK_CH(*ctxt->input->cur))) {
4527
0
        const xmlChar *tmp = ctxt->input->cur;
4528
0
        ctxt->input->cur = in;
4529
4530
0
        if (areBlanks(ctxt, tmp, nbchar, 0)) {
4531
0
            if (ctxt->sax->ignorableWhitespace != NULL)
4532
0
          ctxt->sax->ignorableWhitespace(ctxt->userData,
4533
0
                 tmp, nbchar);
4534
0
        } else {
4535
0
            if (ctxt->sax->characters != NULL)
4536
0
          ctxt->sax->characters(ctxt->userData,
4537
0
              tmp, nbchar);
4538
0
      if (*ctxt->space == -1)
4539
0
          *ctxt->space = -2;
4540
0
        }
4541
0
                    line = ctxt->input->line;
4542
0
                    col = ctxt->input->col;
4543
82.6k
    } else if (ctxt->sax != NULL) {
4544
82.6k
        if (ctxt->sax->characters != NULL)
4545
82.6k
      ctxt->sax->characters(ctxt->userData,
4546
82.6k
                ctxt->input->cur, nbchar);
4547
82.6k
                    line = ctxt->input->line;
4548
82.6k
                    col = ctxt->input->col;
4549
82.6k
    }
4550
                /* something really bad happened in the SAX callback */
4551
82.6k
                if (ctxt->instate != XML_PARSER_CONTENT)
4552
2
                    return;
4553
82.6k
      }
4554
97.6k
      ctxt->input->cur = in;
4555
97.6k
      if (*in == 0xD) {
4556
3.58k
    in++;
4557
3.58k
    if (*in == 0xA) {
4558
1
        ctxt->input->cur = in;
4559
1
        in++;
4560
1
        ctxt->input->line++; ctxt->input->col = 1;
4561
1
        continue; /* while */
4562
1
    }
4563
3.58k
    in--;
4564
3.58k
      }
4565
97.6k
      if (*in == '<') {
4566
24.0k
    return;
4567
24.0k
      }
4568
73.5k
      if (*in == '&') {
4569
16.1k
    return;
4570
16.1k
      }
4571
57.3k
      SHRINK;
4572
57.3k
      GROW;
4573
57.3k
            if (ctxt->instate == XML_PARSER_EOF)
4574
0
    return;
4575
57.3k
      in = ctxt->input->cur;
4576
57.3k
  } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09) || (*in == 0x0a));
4577
56.9k
  nbchar = 0;
4578
56.9k
    }
4579
56.9k
    ctxt->input->line = line;
4580
56.9k
    ctxt->input->col = col;
4581
56.9k
    xmlParseCharDataComplex(ctxt, cdata);
4582
56.9k
}
4583
4584
/**
4585
 * xmlParseCharDataComplex:
4586
 * @ctxt:  an XML parser context
4587
 * @cdata:  int indicating whether we are within a CDATA section
4588
 *
4589
 * parse a CharData section.this is the fallback function
4590
 * of xmlParseCharData() when the parsing requires handling
4591
 * of non-ASCII characters.
4592
 */
4593
static void
4594
56.9k
xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) {
4595
56.9k
    xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE + 5];
4596
56.9k
    int nbchar = 0;
4597
56.9k
    int cur, l;
4598
56.9k
    int count = 0;
4599
4600
56.9k
    SHRINK;
4601
56.9k
    GROW;
4602
56.9k
    cur = CUR_CHAR(l);
4603
62.4M
    while ((cur != '<') && /* checked */
4604
62.4M
           (cur != '&') &&
4605
62.4M
     (IS_CHAR(cur))) /* test also done in xmlCurrentChar() */ {
4606
62.3M
  if ((cur == ']') && (NXT(1) == ']') &&
4607
62.3M
      (NXT(2) == '>')) {
4608
0
      if (cdata) break;
4609
0
      else {
4610
0
    xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
4611
0
      }
4612
0
  }
4613
62.3M
  COPY_BUF(l,buf,nbchar,cur);
4614
  /* move current position before possible calling of ctxt->sax->characters */
4615
62.3M
  NEXTL(l);
4616
62.3M
  cur = CUR_CHAR(l);
4617
62.3M
  if (nbchar >= XML_PARSER_BIG_BUFFER_SIZE) {
4618
549k
      buf[nbchar] = 0;
4619
4620
      /*
4621
       * OK the segment is to be consumed as chars.
4622
       */
4623
549k
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
4624
176k
    if (areBlanks(ctxt, buf, nbchar, 0)) {
4625
0
        if (ctxt->sax->ignorableWhitespace != NULL)
4626
0
      ctxt->sax->ignorableWhitespace(ctxt->userData,
4627
0
                                     buf, nbchar);
4628
176k
    } else {
4629
176k
        if (ctxt->sax->characters != NULL)
4630
176k
      ctxt->sax->characters(ctxt->userData, buf, nbchar);
4631
176k
        if ((ctxt->sax->characters !=
4632
176k
             ctxt->sax->ignorableWhitespace) &&
4633
176k
      (*ctxt->space == -1))
4634
0
      *ctxt->space = -2;
4635
176k
    }
4636
176k
      }
4637
549k
      nbchar = 0;
4638
            /* something really bad happened in the SAX callback */
4639
549k
            if (ctxt->instate != XML_PARSER_CONTENT)
4640
3.36k
                return;
4641
549k
  }
4642
62.3M
  count++;
4643
62.3M
  if (count > 50) {
4644
1.20M
      SHRINK;
4645
1.20M
      GROW;
4646
1.20M
      count = 0;
4647
1.20M
            if (ctxt->instate == XML_PARSER_EOF)
4648
0
    return;
4649
1.20M
  }
4650
62.3M
    }
4651
53.6k
    if (nbchar != 0) {
4652
46.4k
        buf[nbchar] = 0;
4653
  /*
4654
   * OK the segment is to be consumed as chars.
4655
   */
4656
46.4k
  if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
4657
29.3k
      if (areBlanks(ctxt, buf, nbchar, 0)) {
4658
0
    if (ctxt->sax->ignorableWhitespace != NULL)
4659
0
        ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
4660
29.3k
      } else {
4661
29.3k
    if (ctxt->sax->characters != NULL)
4662
29.3k
        ctxt->sax->characters(ctxt->userData, buf, nbchar);
4663
29.3k
    if ((ctxt->sax->characters != ctxt->sax->ignorableWhitespace) &&
4664
29.3k
        (*ctxt->space == -1))
4665
0
        *ctxt->space = -2;
4666
29.3k
      }
4667
29.3k
  }
4668
46.4k
    }
4669
53.6k
    if ((cur != 0) && (!IS_CHAR(cur))) {
4670
  /* Generate the error and skip the offending character */
4671
7.47k
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4672
7.47k
                          "PCDATA invalid Char value %d\n",
4673
7.47k
                    cur);
4674
7.47k
  NEXTL(l);
4675
7.47k
    }
4676
53.6k
}
4677
4678
/**
4679
 * xmlParseExternalID:
4680
 * @ctxt:  an XML parser context
4681
 * @publicID:  a xmlChar** receiving PubidLiteral
4682
 * @strict: indicate whether we should restrict parsing to only
4683
 *          production [75], see NOTE below
4684
 *
4685
 * DEPRECATED: Internal function, don't use.
4686
 *
4687
 * Parse an External ID or a Public ID
4688
 *
4689
 * NOTE: Productions [75] and [83] interact badly since [75] can generate
4690
 *       'PUBLIC' S PubidLiteral S SystemLiteral
4691
 *
4692
 * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
4693
 *                   | 'PUBLIC' S PubidLiteral S SystemLiteral
4694
 *
4695
 * [83] PublicID ::= 'PUBLIC' S PubidLiteral
4696
 *
4697
 * Returns the function returns SystemLiteral and in the second
4698
 *                case publicID receives PubidLiteral, is strict is off
4699
 *                it is possible to return NULL and have publicID set.
4700
 */
4701
4702
xmlChar *
4703
29.0k
xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
4704
29.0k
    xmlChar *URI = NULL;
4705
4706
29.0k
    SHRINK;
4707
4708
29.0k
    *publicID = NULL;
4709
29.0k
    if (CMP6(CUR_PTR, 'S', 'Y', 'S', 'T', 'E', 'M')) {
4710
1
        SKIP(6);
4711
1
  if (SKIP_BLANKS == 0) {
4712
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4713
0
                     "Space required after 'SYSTEM'\n");
4714
0
  }
4715
1
  URI = xmlParseSystemLiteral(ctxt);
4716
1
  if (URI == NULL) {
4717
0
      xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
4718
0
        }
4719
29.0k
    } else if (CMP6(CUR_PTR, 'P', 'U', 'B', 'L', 'I', 'C')) {
4720
28.9k
        SKIP(6);
4721
28.9k
  if (SKIP_BLANKS == 0) {
4722
28.2k
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4723
28.2k
        "Space required after 'PUBLIC'\n");
4724
28.2k
  }
4725
28.9k
  *publicID = xmlParsePubidLiteral(ctxt);
4726
28.9k
  if (*publicID == NULL) {
4727
1
      xmlFatalErr(ctxt, XML_ERR_PUBID_REQUIRED, NULL);
4728
1
  }
4729
28.9k
  if (strict) {
4730
      /*
4731
       * We don't handle [83] so "S SystemLiteral" is required.
4732
       */
4733
1.28k
      if (SKIP_BLANKS == 0) {
4734
598
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4735
598
      "Space required after the Public Identifier\n");
4736
598
      }
4737
27.6k
  } else {
4738
      /*
4739
       * We handle [83] so we return immediately, if
4740
       * "S SystemLiteral" is not detected. We skip blanks if no
4741
             * system literal was found, but this is harmless since we must
4742
             * be at the end of a NotationDecl.
4743
       */
4744
27.6k
      if (SKIP_BLANKS == 0) return(NULL);
4745
6.77k
      if ((CUR != '\'') && (CUR != '"')) return(NULL);
4746
6.77k
  }
4747
3.54k
  URI = xmlParseSystemLiteral(ctxt);
4748
3.54k
  if (URI == NULL) {
4749
598
      xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
4750
598
        }
4751
3.54k
    }
4752
3.65k
    return(URI);
4753
29.0k
}
4754
4755
/**
4756
 * xmlParseCommentComplex:
4757
 * @ctxt:  an XML parser context
4758
 * @buf:  the already parsed part of the buffer
4759
 * @len:  number of bytes in the buffer
4760
 * @size:  allocated size of the buffer
4761
 *
4762
 * Skip an XML (SGML) comment <!-- .... -->
4763
 *  The spec says that "For compatibility, the string "--" (double-hyphen)
4764
 *  must not occur within comments. "
4765
 * This is the slow routine in case the accelerator for ascii didn't work
4766
 *
4767
 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
4768
 */
4769
static void
4770
xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
4771
612
                       size_t len, size_t size) {
4772
612
    int q, ql;
4773
612
    int r, rl;
4774
612
    int cur, l;
4775
612
    size_t count = 0;
4776
612
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4777
0
                       XML_MAX_HUGE_LENGTH :
4778
612
                       XML_MAX_TEXT_LENGTH;
4779
612
    int inputid;
4780
4781
612
    inputid = ctxt->input->id;
4782
4783
612
    if (buf == NULL) {
4784
1
        len = 0;
4785
1
  size = XML_PARSER_BUFFER_SIZE;
4786
1
  buf = (xmlChar *) xmlMallocAtomic(size);
4787
1
  if (buf == NULL) {
4788
0
      xmlErrMemory(ctxt, NULL);
4789
0
      return;
4790
0
  }
4791
1
    }
4792
612
    GROW; /* Assure there's enough input data */
4793
612
    q = CUR_CHAR(ql);
4794
612
    if (q == 0)
4795
1
        goto not_terminated;
4796
611
    if (!IS_CHAR(q)) {
4797
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4798
0
                          "xmlParseComment: invalid xmlChar value %d\n",
4799
0
                    q);
4800
0
  xmlFree (buf);
4801
0
  return;
4802
0
    }
4803
611
    NEXTL(ql);
4804
611
    r = CUR_CHAR(rl);
4805
611
    if (r == 0)
4806
0
        goto not_terminated;
4807
611
    if (!IS_CHAR(r)) {
4808
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4809
0
                          "xmlParseComment: invalid xmlChar value %d\n",
4810
0
                    r);
4811
0
  xmlFree (buf);
4812
0
  return;
4813
0
    }
4814
611
    NEXTL(rl);
4815
611
    cur = CUR_CHAR(l);
4816
611
    if (cur == 0)
4817
0
        goto not_terminated;
4818
4.71M
    while (IS_CHAR(cur) && /* checked */
4819
4.71M
           ((cur != '>') ||
4820
4.71M
      (r != '-') || (q != '-'))) {
4821
4.71M
  if ((r == '-') && (q == '-')) {
4822
835
      xmlFatalErr(ctxt, XML_ERR_HYPHEN_IN_COMMENT, NULL);
4823
835
  }
4824
4.71M
  if (len + 5 >= size) {
4825
1.00k
      xmlChar *new_buf;
4826
1.00k
            size_t new_size;
4827
4828
1.00k
      new_size = size * 2;
4829
1.00k
      new_buf = (xmlChar *) xmlRealloc(buf, new_size);
4830
1.00k
      if (new_buf == NULL) {
4831
0
    xmlFree (buf);
4832
0
    xmlErrMemory(ctxt, NULL);
4833
0
    return;
4834
0
      }
4835
1.00k
      buf = new_buf;
4836
1.00k
            size = new_size;
4837
1.00k
  }
4838
4.71M
  COPY_BUF(ql,buf,len,q);
4839
4.71M
  q = r;
4840
4.71M
  ql = rl;
4841
4.71M
  r = cur;
4842
4.71M
  rl = l;
4843
4844
4.71M
  count++;
4845
4.71M
  if (count > 50) {
4846
92.1k
      SHRINK;
4847
92.1k
      GROW;
4848
92.1k
      count = 0;
4849
92.1k
            if (ctxt->instate == XML_PARSER_EOF) {
4850
0
    xmlFree(buf);
4851
0
    return;
4852
0
            }
4853
92.1k
  }
4854
4.71M
  NEXTL(l);
4855
4.71M
  cur = CUR_CHAR(l);
4856
4.71M
  if (cur == 0) {
4857
41.4k
      SHRINK;
4858
41.4k
      GROW;
4859
41.4k
      cur = CUR_CHAR(l);
4860
41.4k
  }
4861
4862
4.71M
        if (len > maxLength) {
4863
1
            xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4864
1
                         "Comment too big found", NULL);
4865
1
            xmlFree (buf);
4866
1
            return;
4867
1
        }
4868
4.71M
    }
4869
610
    buf[len] = 0;
4870
610
    if (cur == 0) {
4871
5
  xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4872
5
                       "Comment not terminated \n<!--%.50s\n", buf);
4873
605
    } else if (!IS_CHAR(cur)) {
4874
156
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4875
156
                          "xmlParseComment: invalid xmlChar value %d\n",
4876
156
                    cur);
4877
449
    } else {
4878
449
  if (inputid != ctxt->input->id) {
4879
0
      xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
4880
0
               "Comment doesn't start and stop in the same"
4881
0
                           " entity\n");
4882
0
  }
4883
449
        NEXT;
4884
449
  if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
4885
449
      (!ctxt->disableSAX))
4886
0
      ctxt->sax->comment(ctxt->userData, buf);
4887
449
    }
4888
610
    xmlFree(buf);
4889
610
    return;
4890
1
not_terminated:
4891
1
    xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4892
1
       "Comment not terminated\n", NULL);
4893
1
    xmlFree(buf);
4894
1
    return;
4895
611
}
4896
4897
/**
4898
 * xmlParseComment:
4899
 * @ctxt:  an XML parser context
4900
 *
4901
 * DEPRECATED: Internal function, don't use.
4902
 *
4903
 * Skip an XML (SGML) comment <!-- .... -->
4904
 *  The spec says that "For compatibility, the string "--" (double-hyphen)
4905
 *  must not occur within comments. "
4906
 *
4907
 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
4908
 */
4909
void
4910
616
xmlParseComment(xmlParserCtxtPtr ctxt) {
4911
616
    xmlChar *buf = NULL;
4912
616
    size_t size = XML_PARSER_BUFFER_SIZE;
4913
616
    size_t len = 0;
4914
616
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4915
0
                       XML_MAX_HUGE_LENGTH :
4916
616
                       XML_MAX_TEXT_LENGTH;
4917
616
    xmlParserInputState state;
4918
616
    const xmlChar *in;
4919
616
    size_t nbchar = 0;
4920
616
    int ccol;
4921
616
    int inputid;
4922
4923
    /*
4924
     * Check that there is a comment right here.
4925
     */
4926
616
    if ((RAW != '<') || (NXT(1) != '!') ||
4927
616
        (NXT(2) != '-') || (NXT(3) != '-')) return;
4928
616
    state = ctxt->instate;
4929
616
    ctxt->instate = XML_PARSER_COMMENT;
4930
616
    inputid = ctxt->input->id;
4931
616
    SKIP(4);
4932
616
    SHRINK;
4933
616
    GROW;
4934
4935
    /*
4936
     * Accelerated common case where input don't need to be
4937
     * modified before passing it to the handler.
4938
     */
4939
616
    in = ctxt->input->cur;
4940
2.68k
    do {
4941
2.68k
  if (*in == 0xA) {
4942
150
      do {
4943
150
    ctxt->input->line++; ctxt->input->col = 1;
4944
150
    in++;
4945
150
      } while (*in == 0xA);
4946
75
  }
4947
3.31k
get_more:
4948
3.31k
        ccol = ctxt->input->col;
4949
392k
  while (((*in > '-') && (*in <= 0x7F)) ||
4950
392k
         ((*in >= 0x20) && (*in < '-')) ||
4951
392k
         (*in == 0x09)) {
4952
389k
        in++;
4953
389k
        ccol++;
4954
389k
  }
4955
3.31k
  ctxt->input->col = ccol;
4956
3.31k
  if (*in == 0xA) {
4957
214
      do {
4958
214
    ctxt->input->line++; ctxt->input->col = 1;
4959
214
    in++;
4960
214
      } while (*in == 0xA);
4961
214
      goto get_more;
4962
214
  }
4963
3.09k
  nbchar = in - ctxt->input->cur;
4964
  /*
4965
   * save current set of data
4966
   */
4967
3.09k
  if (nbchar > 0) {
4968
2.95k
      if ((ctxt->sax != NULL) &&
4969
2.95k
    (ctxt->sax->comment != NULL)) {
4970
2.95k
    if (buf == NULL) {
4971
615
        if ((*in == '-') && (in[1] == '-'))
4972
210
            size = nbchar + 1;
4973
405
        else
4974
405
            size = XML_PARSER_BUFFER_SIZE + nbchar;
4975
615
        buf = (xmlChar *) xmlMallocAtomic(size);
4976
615
        if (buf == NULL) {
4977
0
            xmlErrMemory(ctxt, NULL);
4978
0
      ctxt->instate = state;
4979
0
      return;
4980
0
        }
4981
615
        len = 0;
4982
2.33k
    } else if (len + nbchar + 1 >= size) {
4983
651
        xmlChar *new_buf;
4984
651
        size  += len + nbchar + XML_PARSER_BUFFER_SIZE;
4985
651
        new_buf = (xmlChar *) xmlRealloc(buf, size);
4986
651
        if (new_buf == NULL) {
4987
0
            xmlFree (buf);
4988
0
      xmlErrMemory(ctxt, NULL);
4989
0
      ctxt->instate = state;
4990
0
      return;
4991
0
        }
4992
651
        buf = new_buf;
4993
651
    }
4994
2.95k
    memcpy(&buf[len], ctxt->input->cur, nbchar);
4995
2.95k
    len += nbchar;
4996
2.95k
    buf[len] = 0;
4997
2.95k
      }
4998
2.95k
  }
4999
3.09k
        if (len > maxLength) {
5000
0
            xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
5001
0
                         "Comment too big found", NULL);
5002
0
            xmlFree (buf);
5003
0
            return;
5004
0
        }
5005
3.09k
  ctxt->input->cur = in;
5006
3.09k
  if (*in == 0xA) {
5007
0
      in++;
5008
0
      ctxt->input->line++; ctxt->input->col = 1;
5009
0
  }
5010
3.09k
  if (*in == 0xD) {
5011
0
      in++;
5012
0
      if (*in == 0xA) {
5013
0
    ctxt->input->cur = in;
5014
0
    in++;
5015
0
    ctxt->input->line++; ctxt->input->col = 1;
5016
0
    goto get_more;
5017
0
      }
5018
0
      in--;
5019
0
  }
5020
3.09k
  SHRINK;
5021
3.09k
  GROW;
5022
3.09k
        if (ctxt->instate == XML_PARSER_EOF) {
5023
0
            xmlFree(buf);
5024
0
            return;
5025
0
        }
5026
3.09k
  in = ctxt->input->cur;
5027
3.09k
  if (*in == '-') {
5028
420
      if (in[1] == '-') {
5029
390
          if (in[2] == '>') {
5030
4
        if (ctxt->input->id != inputid) {
5031
0
      xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5032
0
                     "comment doesn't start and stop in the"
5033
0
                                       " same entity\n");
5034
0
        }
5035
4
        SKIP(3);
5036
4
        if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
5037
4
            (!ctxt->disableSAX)) {
5038
4
      if (buf != NULL)
5039
4
          ctxt->sax->comment(ctxt->userData, buf);
5040
0
      else
5041
0
          ctxt->sax->comment(ctxt->userData, BAD_CAST "");
5042
4
        }
5043
4
        if (buf != NULL)
5044
4
            xmlFree(buf);
5045
4
        if (ctxt->instate != XML_PARSER_EOF)
5046
4
      ctxt->instate = state;
5047
4
        return;
5048
4
    }
5049
386
    if (buf != NULL) {
5050
243
        xmlFatalErrMsgStr(ctxt, XML_ERR_HYPHEN_IN_COMMENT,
5051
243
                          "Double hyphen within comment: "
5052
243
                                      "<!--%.50s\n",
5053
243
              buf);
5054
243
    } else
5055
143
        xmlFatalErrMsgStr(ctxt, XML_ERR_HYPHEN_IN_COMMENT,
5056
143
                          "Double hyphen within comment\n", NULL);
5057
386
                if (ctxt->instate == XML_PARSER_EOF) {
5058
0
                    xmlFree(buf);
5059
0
                    return;
5060
0
                }
5061
386
    in++;
5062
386
    ctxt->input->col++;
5063
386
      }
5064
416
      in++;
5065
416
      ctxt->input->col++;
5066
416
      goto get_more;
5067
420
  }
5068
3.09k
    } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09) || (*in == 0x0a));
5069
612
    xmlParseCommentComplex(ctxt, buf, len, size);
5070
612
    ctxt->instate = state;
5071
612
    return;
5072
616
}
5073
5074
5075
/**
5076
 * xmlParsePITarget:
5077
 * @ctxt:  an XML parser context
5078
 *
5079
 * DEPRECATED: Internal function, don't use.
5080
 *
5081
 * parse the name of a PI
5082
 *
5083
 * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
5084
 *
5085
 * Returns the PITarget name or NULL
5086
 */
5087
5088
const xmlChar *
5089
13.1k
xmlParsePITarget(xmlParserCtxtPtr ctxt) {
5090
13.1k
    const xmlChar *name;
5091
5092
13.1k
    name = xmlParseName(ctxt);
5093
13.1k
    if ((name != NULL) &&
5094
13.1k
        ((name[0] == 'x') || (name[0] == 'X')) &&
5095
13.1k
        ((name[1] == 'm') || (name[1] == 'M')) &&
5096
13.1k
        ((name[2] == 'l') || (name[2] == 'L'))) {
5097
351
  int i;
5098
351
  if ((name[0] == 'x') && (name[1] == 'm') &&
5099
351
      (name[2] == 'l') && (name[3] == 0)) {
5100
350
      xmlFatalErrMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
5101
350
     "XML declaration allowed only at the start of the document\n");
5102
350
      return(name);
5103
350
  } else if (name[3] == 0) {
5104
0
      xmlFatalErr(ctxt, XML_ERR_RESERVED_XML_NAME, NULL);
5105
0
      return(name);
5106
0
  }
5107
3
  for (i = 0;;i++) {
5108
3
      if (xmlW3CPIs[i] == NULL) break;
5109
2
      if (xmlStrEqual(name, (const xmlChar *)xmlW3CPIs[i]))
5110
0
          return(name);
5111
2
  }
5112
1
  xmlWarningMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
5113
1
          "xmlParsePITarget: invalid name prefix 'xml'\n",
5114
1
          NULL, NULL);
5115
1
    }
5116
12.8k
    if ((name != NULL) && (xmlStrchr(name, ':') != NULL)) {
5117
10
  xmlNsErr(ctxt, XML_NS_ERR_COLON,
5118
10
     "colons are forbidden from PI names '%s'\n", name, NULL, NULL);
5119
10
    }
5120
12.8k
    return(name);
5121
13.1k
}
5122
5123
#ifdef LIBXML_CATALOG_ENABLED
5124
/**
5125
 * xmlParseCatalogPI:
5126
 * @ctxt:  an XML parser context
5127
 * @catalog:  the PI value string
5128
 *
5129
 * parse an XML Catalog Processing Instruction.
5130
 *
5131
 * <?oasis-xml-catalog catalog="http://example.com/catalog.xml"?>
5132
 *
5133
 * Occurs only if allowed by the user and if happening in the Misc
5134
 * part of the document before any doctype information
5135
 * This will add the given catalog to the parsing context in order
5136
 * to be used if there is a resolution need further down in the document
5137
 */
5138
5139
static void
5140
36
xmlParseCatalogPI(xmlParserCtxtPtr ctxt, const xmlChar *catalog) {
5141
36
    xmlChar *URL = NULL;
5142
36
    const xmlChar *tmp, *base;
5143
36
    xmlChar marker;
5144
5145
36
    tmp = catalog;
5146
36
    while (IS_BLANK_CH(*tmp)) tmp++;
5147
36
    if (xmlStrncmp(tmp, BAD_CAST"catalog", 7))
5148
5
  goto error;
5149
31
    tmp += 7;
5150
58
    while (IS_BLANK_CH(*tmp)) tmp++;
5151
31
    if (*tmp != '=') {
5152
31
  return;
5153
31
    }
5154
0
    tmp++;
5155
0
    while (IS_BLANK_CH(*tmp)) tmp++;
5156
0
    marker = *tmp;
5157
0
    if ((marker != '\'') && (marker != '"'))
5158
0
  goto error;
5159
0
    tmp++;
5160
0
    base = tmp;
5161
0
    while ((*tmp != 0) && (*tmp != marker)) tmp++;
5162
0
    if (*tmp == 0)
5163
0
  goto error;
5164
0
    URL = xmlStrndup(base, tmp - base);
5165
0
    tmp++;
5166
0
    while (IS_BLANK_CH(*tmp)) tmp++;
5167
0
    if (*tmp != 0)
5168
0
  goto error;
5169
5170
0
    if (URL != NULL) {
5171
0
  ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
5172
0
  xmlFree(URL);
5173
0
    }
5174
0
    return;
5175
5176
5
error:
5177
5
    xmlWarningMsg(ctxt, XML_WAR_CATALOG_PI,
5178
5
            "Catalog PI syntax error: %s\n",
5179
5
      catalog, NULL);
5180
5
    if (URL != NULL)
5181
0
  xmlFree(URL);
5182
5
}
5183
#endif
5184
5185
/**
5186
 * xmlParsePI:
5187
 * @ctxt:  an XML parser context
5188
 *
5189
 * DEPRECATED: Internal function, don't use.
5190
 *
5191
 * parse an XML Processing Instruction.
5192
 *
5193
 * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
5194
 *
5195
 * The processing is transferred to SAX once parsed.
5196
 */
5197
5198
void
5199
13.1k
xmlParsePI(xmlParserCtxtPtr ctxt) {
5200
13.1k
    xmlChar *buf = NULL;
5201
13.1k
    size_t len = 0;
5202
13.1k
    size_t size = XML_PARSER_BUFFER_SIZE;
5203
13.1k
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
5204
0
                       XML_MAX_HUGE_LENGTH :
5205
13.1k
                       XML_MAX_TEXT_LENGTH;
5206
13.1k
    int cur, l;
5207
13.1k
    const xmlChar *target;
5208
13.1k
    xmlParserInputState state;
5209
13.1k
    int count = 0;
5210
5211
13.1k
    if ((RAW == '<') && (NXT(1) == '?')) {
5212
13.1k
  int inputid = ctxt->input->id;
5213
13.1k
  state = ctxt->instate;
5214
13.1k
        ctxt->instate = XML_PARSER_PI;
5215
  /*
5216
   * this is a Processing Instruction.
5217
   */
5218
13.1k
  SKIP(2);
5219
13.1k
  SHRINK;
5220
5221
  /*
5222
   * Parse the target name and check for special support like
5223
   * namespace.
5224
   */
5225
13.1k
        target = xmlParsePITarget(ctxt);
5226
13.1k
  if (target != NULL) {
5227
12.6k
      if ((RAW == '?') && (NXT(1) == '>')) {
5228
8.26k
    if (inputid != ctxt->input->id) {
5229
0
        xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5230
0
                             "PI declaration doesn't start and stop in"
5231
0
                                   " the same entity\n");
5232
0
    }
5233
8.26k
    SKIP(2);
5234
5235
    /*
5236
     * SAX: PI detected.
5237
     */
5238
8.26k
    if ((ctxt->sax) && (!ctxt->disableSAX) &&
5239
8.26k
        (ctxt->sax->processingInstruction != NULL))
5240
292
        ctxt->sax->processingInstruction(ctxt->userData,
5241
292
                                         target, NULL);
5242
8.26k
    if (ctxt->instate != XML_PARSER_EOF)
5243
8.26k
        ctxt->instate = state;
5244
8.26k
    return;
5245
8.26k
      }
5246
4.33k
      buf = (xmlChar *) xmlMallocAtomic(size);
5247
4.33k
      if (buf == NULL) {
5248
0
    xmlErrMemory(ctxt, NULL);
5249
0
    ctxt->instate = state;
5250
0
    return;
5251
0
      }
5252
4.33k
      if (SKIP_BLANKS == 0) {
5253
3.07k
    xmlFatalErrMsgStr(ctxt, XML_ERR_SPACE_REQUIRED,
5254
3.07k
        "ParsePI: PI %s space expected\n", target);
5255
3.07k
      }
5256
4.33k
      cur = CUR_CHAR(l);
5257
6.53M
      while (IS_CHAR(cur) && /* checked */
5258
6.53M
       ((cur != '?') || (NXT(1) != '>'))) {
5259
6.52M
    if (len + 5 >= size) {
5260
3.48k
        xmlChar *tmp;
5261
3.48k
                    size_t new_size = size * 2;
5262
3.48k
        tmp = (xmlChar *) xmlRealloc(buf, new_size);
5263
3.48k
        if (tmp == NULL) {
5264
0
      xmlErrMemory(ctxt, NULL);
5265
0
      xmlFree(buf);
5266
0
      ctxt->instate = state;
5267
0
      return;
5268
0
        }
5269
3.48k
        buf = tmp;
5270
3.48k
                    size = new_size;
5271
3.48k
    }
5272
6.52M
    count++;
5273
6.52M
    if (count > 50) {
5274
126k
        SHRINK;
5275
126k
        GROW;
5276
126k
                    if (ctxt->instate == XML_PARSER_EOF) {
5277
0
                        xmlFree(buf);
5278
0
                        return;
5279
0
                    }
5280
126k
        count = 0;
5281
126k
    }
5282
6.52M
    COPY_BUF(l,buf,len,cur);
5283
6.52M
    NEXTL(l);
5284
6.52M
    cur = CUR_CHAR(l);
5285
6.52M
    if (cur == 0) {
5286
10.2k
        SHRINK;
5287
10.2k
        GROW;
5288
10.2k
        cur = CUR_CHAR(l);
5289
10.2k
    }
5290
6.52M
                if (len > maxLength) {
5291
0
                    xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
5292
0
                                      "PI %s too big found", target);
5293
0
                    xmlFree(buf);
5294
0
                    ctxt->instate = state;
5295
0
                    return;
5296
0
                }
5297
6.52M
      }
5298
4.33k
      buf[len] = 0;
5299
4.33k
      if (cur != '?') {
5300
64
    xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
5301
64
          "ParsePI: PI %s never end ...\n", target);
5302
4.27k
      } else {
5303
4.27k
    if (inputid != ctxt->input->id) {
5304
0
        xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5305
0
                             "PI declaration doesn't start and stop in"
5306
0
                                   " the same entity\n");
5307
0
    }
5308
4.27k
    SKIP(2);
5309
5310
4.27k
#ifdef LIBXML_CATALOG_ENABLED
5311
4.27k
    if (((state == XML_PARSER_MISC) ||
5312
4.27k
               (state == XML_PARSER_START)) &&
5313
4.27k
        (xmlStrEqual(target, XML_CATALOG_PI))) {
5314
36
        xmlCatalogAllow allow = xmlCatalogGetDefaults();
5315
36
        if ((allow == XML_CATA_ALLOW_DOCUMENT) ||
5316
36
      (allow == XML_CATA_ALLOW_ALL))
5317
36
      xmlParseCatalogPI(ctxt, buf);
5318
36
    }
5319
4.27k
#endif
5320
5321
5322
    /*
5323
     * SAX: PI detected.
5324
     */
5325
4.27k
    if ((ctxt->sax) && (!ctxt->disableSAX) &&
5326
4.27k
        (ctxt->sax->processingInstruction != NULL))
5327
38
        ctxt->sax->processingInstruction(ctxt->userData,
5328
38
                                         target, buf);
5329
4.27k
      }
5330
4.33k
      xmlFree(buf);
5331
4.33k
  } else {
5332
568
      xmlFatalErr(ctxt, XML_ERR_PI_NOT_STARTED, NULL);
5333
568
  }
5334
4.90k
  if (ctxt->instate != XML_PARSER_EOF)
5335
4.90k
      ctxt->instate = state;
5336
4.90k
    }
5337
13.1k
}
5338
5339
/**
5340
 * xmlParseNotationDecl:
5341
 * @ctxt:  an XML parser context
5342
 *
5343
 * DEPRECATED: Internal function, don't use.
5344
 *
5345
 * parse a notation declaration
5346
 *
5347
 * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID |  PublicID) S? '>'
5348
 *
5349
 * Hence there is actually 3 choices:
5350
 *     'PUBLIC' S PubidLiteral
5351
 *     'PUBLIC' S PubidLiteral S SystemLiteral
5352
 * and 'SYSTEM' S SystemLiteral
5353
 *
5354
 * See the NOTE on xmlParseExternalID().
5355
 */
5356
5357
void
5358
27.6k
xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
5359
27.6k
    const xmlChar *name;
5360
27.6k
    xmlChar *Pubid;
5361
27.6k
    xmlChar *Systemid;
5362
5363
27.6k
    if (CMP10(CUR_PTR, '<', '!', 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
5364
27.6k
  int inputid = ctxt->input->id;
5365
27.6k
  SHRINK;
5366
27.6k
  SKIP(10);
5367
27.6k
  if (SKIP_BLANKS == 0) {
5368
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5369
0
         "Space required after '<!NOTATION'\n");
5370
0
      return;
5371
0
  }
5372
5373
27.6k
        name = xmlParseName(ctxt);
5374
27.6k
  if (name == NULL) {
5375
0
      xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
5376
0
      return;
5377
0
  }
5378
27.6k
  if (xmlStrchr(name, ':') != NULL) {
5379
0
      xmlNsErr(ctxt, XML_NS_ERR_COLON,
5380
0
         "colons are forbidden from notation names '%s'\n",
5381
0
         name, NULL, NULL);
5382
0
  }
5383
27.6k
  if (SKIP_BLANKS == 0) {
5384
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5385
0
         "Space required after the NOTATION name'\n");
5386
0
      return;
5387
0
  }
5388
5389
  /*
5390
   * Parse the IDs.
5391
   */
5392
27.6k
  Systemid = xmlParseExternalID(ctxt, &Pubid, 0);
5393
27.6k
  SKIP_BLANKS;
5394
5395
27.6k
  if (RAW == '>') {
5396
3.91k
      if (inputid != ctxt->input->id) {
5397
3.91k
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5398
3.91k
                         "Notation declaration doesn't start and stop"
5399
3.91k
                               " in the same entity\n");
5400
3.91k
      }
5401
3.91k
      NEXT;
5402
3.91k
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
5403
3.91k
    (ctxt->sax->notationDecl != NULL))
5404
0
    ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
5405
23.7k
  } else {
5406
23.7k
      xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
5407
23.7k
  }
5408
27.6k
  if (Systemid != NULL) xmlFree(Systemid);
5409
27.6k
  if (Pubid != NULL) xmlFree(Pubid);
5410
27.6k
    }
5411
27.6k
}
5412
5413
/**
5414
 * xmlParseEntityDecl:
5415
 * @ctxt:  an XML parser context
5416
 *
5417
 * DEPRECATED: Internal function, don't use.
5418
 *
5419
 * parse <!ENTITY declarations
5420
 *
5421
 * [70] EntityDecl ::= GEDecl | PEDecl
5422
 *
5423
 * [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
5424
 *
5425
 * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
5426
 *
5427
 * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
5428
 *
5429
 * [74] PEDef ::= EntityValue | ExternalID
5430
 *
5431
 * [76] NDataDecl ::= S 'NDATA' S Name
5432
 *
5433
 * [ VC: Notation Declared ]
5434
 * The Name must match the declared name of a notation.
5435
 */
5436
5437
void
5438
3.34k
xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
5439
3.34k
    const xmlChar *name = NULL;
5440
3.34k
    xmlChar *value = NULL;
5441
3.34k
    xmlChar *URI = NULL, *literal = NULL;
5442
3.34k
    const xmlChar *ndata = NULL;
5443
3.34k
    int isParameter = 0;
5444
3.34k
    xmlChar *orig = NULL;
5445
5446
    /* GROW; done in the caller */
5447
3.34k
    if (CMP8(CUR_PTR, '<', '!', 'E', 'N', 'T', 'I', 'T', 'Y')) {
5448
3.34k
  int inputid = ctxt->input->id;
5449
3.34k
  SHRINK;
5450
3.34k
  SKIP(8);
5451
3.34k
  if (SKIP_BLANKS == 0) {
5452
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5453
0
         "Space required after '<!ENTITY'\n");
5454
0
  }
5455
5456
3.34k
  if (RAW == '%') {
5457
695
      NEXT;
5458
695
      if (SKIP_BLANKS == 0) {
5459
0
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5460
0
             "Space required after '%%'\n");
5461
0
      }
5462
695
      isParameter = 1;
5463
695
  }
5464
5465
3.34k
        name = xmlParseName(ctxt);
5466
3.34k
  if (name == NULL) {
5467
0
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
5468
0
                     "xmlParseEntityDecl: no name\n");
5469
0
            return;
5470
0
  }
5471
3.34k
  if (xmlStrchr(name, ':') != NULL) {
5472
3
      xmlNsErr(ctxt, XML_NS_ERR_COLON,
5473
3
         "colons are forbidden from entities names '%s'\n",
5474
3
         name, NULL, NULL);
5475
3
  }
5476
3.34k
  if (SKIP_BLANKS == 0) {
5477
1
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5478
1
         "Space required after the entity name\n");
5479
1
  }
5480
5481
3.34k
  ctxt->instate = XML_PARSER_ENTITY_DECL;
5482
  /*
5483
   * handle the various case of definitions...
5484
   */
5485
3.34k
  if (isParameter) {
5486
695
      if ((RAW == '"') || (RAW == '\'')) {
5487
5
          value = xmlParseEntityValue(ctxt, &orig);
5488
5
    if (value) {
5489
5
        if ((ctxt->sax != NULL) &&
5490
5
      (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5491
5
      ctxt->sax->entityDecl(ctxt->userData, name,
5492
5
                        XML_INTERNAL_PARAMETER_ENTITY,
5493
5
            NULL, NULL, value);
5494
5
    }
5495
690
      } else {
5496
690
          URI = xmlParseExternalID(ctxt, &literal, 1);
5497
690
    if ((URI == NULL) && (literal == NULL)) {
5498
0
        xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
5499
0
    }
5500
690
    if (URI) {
5501
690
        xmlURIPtr uri;
5502
5503
690
        uri = xmlParseURI((const char *) URI);
5504
690
        if (uri == NULL) {
5505
7
            xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
5506
7
             "Invalid URI: %s\n", URI);
5507
      /*
5508
       * This really ought to be a well formedness error
5509
       * but the XML Core WG decided otherwise c.f. issue
5510
       * E26 of the XML erratas.
5511
       */
5512
683
        } else {
5513
683
      if (uri->fragment != NULL) {
5514
          /*
5515
           * Okay this is foolish to block those but not
5516
           * invalid URIs.
5517
           */
5518
0
          xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
5519
683
      } else {
5520
683
          if ((ctxt->sax != NULL) &&
5521
683
        (!ctxt->disableSAX) &&
5522
683
        (ctxt->sax->entityDecl != NULL))
5523
0
        ctxt->sax->entityDecl(ctxt->userData, name,
5524
0
              XML_EXTERNAL_PARAMETER_ENTITY,
5525
0
              literal, URI, NULL);
5526
683
      }
5527
683
      xmlFreeURI(uri);
5528
683
        }
5529
690
    }
5530
690
      }
5531
2.65k
  } else {
5532
2.65k
      if ((RAW == '"') || (RAW == '\'')) {
5533
2.05k
          value = xmlParseEntityValue(ctxt, &orig);
5534
2.05k
    if ((ctxt->sax != NULL) &&
5535
2.05k
        (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5536
68
        ctxt->sax->entityDecl(ctxt->userData, name,
5537
68
        XML_INTERNAL_GENERAL_ENTITY,
5538
68
        NULL, NULL, value);
5539
    /*
5540
     * For expat compatibility in SAX mode.
5541
     */
5542
2.05k
    if ((ctxt->myDoc == NULL) ||
5543
2.05k
        (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
5544
5
        if (ctxt->myDoc == NULL) {
5545
3
      ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
5546
3
      if (ctxt->myDoc == NULL) {
5547
0
          xmlErrMemory(ctxt, "New Doc failed");
5548
0
          return;
5549
0
      }
5550
3
      ctxt->myDoc->properties = XML_DOC_INTERNAL;
5551
3
        }
5552
5
        if (ctxt->myDoc->intSubset == NULL)
5553
3
      ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
5554
3
              BAD_CAST "fake", NULL, NULL);
5555
5556
5
        xmlSAX2EntityDecl(ctxt, name, XML_INTERNAL_GENERAL_ENTITY,
5557
5
                    NULL, NULL, value);
5558
5
    }
5559
2.05k
      } else {
5560
599
          URI = xmlParseExternalID(ctxt, &literal, 1);
5561
599
    if ((URI == NULL) && (literal == NULL)) {
5562
2
        xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
5563
2
    }
5564
599
    if (URI) {
5565
0
        xmlURIPtr uri;
5566
5567
0
        uri = xmlParseURI((const char *)URI);
5568
0
        if (uri == NULL) {
5569
0
            xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
5570
0
             "Invalid URI: %s\n", URI);
5571
      /*
5572
       * This really ought to be a well formedness error
5573
       * but the XML Core WG decided otherwise c.f. issue
5574
       * E26 of the XML erratas.
5575
       */
5576
0
        } else {
5577
0
      if (uri->fragment != NULL) {
5578
          /*
5579
           * Okay this is foolish to block those but not
5580
           * invalid URIs.
5581
           */
5582
0
          xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
5583
0
      }
5584
0
      xmlFreeURI(uri);
5585
0
        }
5586
0
    }
5587
599
    if ((RAW != '>') && (SKIP_BLANKS == 0)) {
5588
2
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5589
2
           "Space required before 'NDATA'\n");
5590
2
    }
5591
599
    if (CMP5(CUR_PTR, 'N', 'D', 'A', 'T', 'A')) {
5592
0
        SKIP(5);
5593
0
        if (SKIP_BLANKS == 0) {
5594
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5595
0
               "Space required after 'NDATA'\n");
5596
0
        }
5597
0
        ndata = xmlParseName(ctxt);
5598
0
        if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
5599
0
            (ctxt->sax->unparsedEntityDecl != NULL))
5600
0
      ctxt->sax->unparsedEntityDecl(ctxt->userData, name,
5601
0
            literal, URI, ndata);
5602
599
    } else {
5603
599
        if ((ctxt->sax != NULL) &&
5604
599
            (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5605
0
      ctxt->sax->entityDecl(ctxt->userData, name,
5606
0
            XML_EXTERNAL_GENERAL_PARSED_ENTITY,
5607
0
            literal, URI, NULL);
5608
        /*
5609
         * For expat compatibility in SAX mode.
5610
         * assuming the entity replacement was asked for
5611
         */
5612
599
        if ((ctxt->replaceEntities != 0) &&
5613
599
      ((ctxt->myDoc == NULL) ||
5614
0
      (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE)))) {
5615
0
      if (ctxt->myDoc == NULL) {
5616
0
          ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
5617
0
          if (ctxt->myDoc == NULL) {
5618
0
              xmlErrMemory(ctxt, "New Doc failed");
5619
0
        return;
5620
0
          }
5621
0
          ctxt->myDoc->properties = XML_DOC_INTERNAL;
5622
0
      }
5623
5624
0
      if (ctxt->myDoc->intSubset == NULL)
5625
0
          ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
5626
0
            BAD_CAST "fake", NULL, NULL);
5627
0
      xmlSAX2EntityDecl(ctxt, name,
5628
0
                  XML_EXTERNAL_GENERAL_PARSED_ENTITY,
5629
0
                  literal, URI, NULL);
5630
0
        }
5631
599
    }
5632
599
      }
5633
2.65k
  }
5634
3.34k
  if (ctxt->instate == XML_PARSER_EOF)
5635
0
      goto done;
5636
3.34k
  SKIP_BLANKS;
5637
3.34k
  if (RAW != '>') {
5638
8
      xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
5639
8
              "xmlParseEntityDecl: entity %s not terminated\n", name);
5640
8
      xmlHaltParser(ctxt);
5641
3.34k
  } else {
5642
3.34k
      if (inputid != ctxt->input->id) {
5643
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5644
0
                         "Entity declaration doesn't start and stop in"
5645
0
                               " the same entity\n");
5646
0
      }
5647
3.34k
      NEXT;
5648
3.34k
  }
5649
3.34k
  if (orig != NULL) {
5650
      /*
5651
       * Ugly mechanism to save the raw entity value.
5652
       */
5653
1.91k
      xmlEntityPtr cur = NULL;
5654
5655
1.91k
      if (isParameter) {
5656
5
          if ((ctxt->sax != NULL) &&
5657
5
        (ctxt->sax->getParameterEntity != NULL))
5658
5
        cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
5659
1.91k
      } else {
5660
1.91k
          if ((ctxt->sax != NULL) &&
5661
1.91k
        (ctxt->sax->getEntity != NULL))
5662
1.91k
        cur = ctxt->sax->getEntity(ctxt->userData, name);
5663
1.91k
    if ((cur == NULL) && (ctxt->userData==ctxt)) {
5664
1.84k
        cur = xmlSAX2GetEntity(ctxt, name);
5665
1.84k
    }
5666
1.91k
      }
5667
1.91k
            if ((cur != NULL) && (cur->orig == NULL)) {
5668
70
    cur->orig = orig;
5669
70
                orig = NULL;
5670
70
      }
5671
1.91k
  }
5672
5673
3.34k
done:
5674
3.34k
  if (value != NULL) xmlFree(value);
5675
3.34k
  if (URI != NULL) xmlFree(URI);
5676
3.34k
  if (literal != NULL) xmlFree(literal);
5677
3.34k
        if (orig != NULL) xmlFree(orig);
5678
3.34k
    }
5679
3.34k
}
5680
5681
/**
5682
 * xmlParseDefaultDecl:
5683
 * @ctxt:  an XML parser context
5684
 * @value:  Receive a possible fixed default value for the attribute
5685
 *
5686
 * DEPRECATED: Internal function, don't use.
5687
 *
5688
 * Parse an attribute default declaration
5689
 *
5690
 * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
5691
 *
5692
 * [ VC: Required Attribute ]
5693
 * if the default declaration is the keyword #REQUIRED, then the
5694
 * attribute must be specified for all elements of the type in the
5695
 * attribute-list declaration.
5696
 *
5697
 * [ VC: Attribute Default Legal ]
5698
 * The declared default value must meet the lexical constraints of
5699
 * the declared attribute type c.f. xmlValidateAttributeDecl()
5700
 *
5701
 * [ VC: Fixed Attribute Default ]
5702
 * if an attribute has a default value declared with the #FIXED
5703
 * keyword, instances of that attribute must match the default value.
5704
 *
5705
 * [ WFC: No < in Attribute Values ]
5706
 * handled in xmlParseAttValue()
5707
 *
5708
 * returns: XML_ATTRIBUTE_NONE, XML_ATTRIBUTE_REQUIRED, XML_ATTRIBUTE_IMPLIED
5709
 *          or XML_ATTRIBUTE_FIXED.
5710
 */
5711
5712
int
5713
2.98k
xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
5714
2.98k
    int val;
5715
2.98k
    xmlChar *ret;
5716
5717
2.98k
    *value = NULL;
5718
2.98k
    if (CMP9(CUR_PTR, '#', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D')) {
5719
486
  SKIP(9);
5720
486
  return(XML_ATTRIBUTE_REQUIRED);
5721
486
    }
5722
2.49k
    if (CMP8(CUR_PTR, '#', 'I', 'M', 'P', 'L', 'I', 'E', 'D')) {
5723
0
  SKIP(8);
5724
0
  return(XML_ATTRIBUTE_IMPLIED);
5725
0
    }
5726
2.49k
    val = XML_ATTRIBUTE_NONE;
5727
2.49k
    if (CMP6(CUR_PTR, '#', 'F', 'I', 'X', 'E', 'D')) {
5728
0
  SKIP(6);
5729
0
  val = XML_ATTRIBUTE_FIXED;
5730
0
  if (SKIP_BLANKS == 0) {
5731
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5732
0
         "Space required after '#FIXED'\n");
5733
0
  }
5734
0
    }
5735
2.49k
    ret = xmlParseAttValue(ctxt);
5736
2.49k
    ctxt->instate = XML_PARSER_DTD;
5737
2.49k
    if (ret == NULL) {
5738
1.90k
  xmlFatalErrMsg(ctxt, (xmlParserErrors)ctxt->errNo,
5739
1.90k
           "Attribute default value declaration error\n");
5740
1.90k
    } else
5741
598
        *value = ret;
5742
2.49k
    return(val);
5743
2.49k
}
5744
5745
/**
5746
 * xmlParseNotationType:
5747
 * @ctxt:  an XML parser context
5748
 *
5749
 * DEPRECATED: Internal function, don't use.
5750
 *
5751
 * parse an Notation attribute type.
5752
 *
5753
 * Note: the leading 'NOTATION' S part has already being parsed...
5754
 *
5755
 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
5756
 *
5757
 * [ VC: Notation Attributes ]
5758
 * Values of this type must match one of the notation names included
5759
 * in the declaration; all notation names in the declaration must be declared.
5760
 *
5761
 * Returns: the notation attribute tree built while parsing
5762
 */
5763
5764
xmlEnumerationPtr
5765
673
xmlParseNotationType(xmlParserCtxtPtr ctxt) {
5766
673
    const xmlChar *name;
5767
673
    xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
5768
5769
673
    if (RAW != '(') {
5770
0
  xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
5771
0
  return(NULL);
5772
0
    }
5773
673
    SHRINK;
5774
673
    do {
5775
673
        NEXT;
5776
673
  SKIP_BLANKS;
5777
673
        name = xmlParseName(ctxt);
5778
673
  if (name == NULL) {
5779
0
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
5780
0
         "Name expected in NOTATION declaration\n");
5781
0
            xmlFreeEnumeration(ret);
5782
0
      return(NULL);
5783
0
  }
5784
673
  tmp = ret;
5785
673
  while (tmp != NULL) {
5786
0
      if (xmlStrEqual(name, tmp->name)) {
5787
0
    xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
5788
0
    "standalone: attribute notation value token %s duplicated\n",
5789
0
         name, NULL);
5790
0
    if (!xmlDictOwns(ctxt->dict, name))
5791
0
        xmlFree((xmlChar *) name);
5792
0
    break;
5793
0
      }
5794
0
      tmp = tmp->next;
5795
0
  }
5796
673
  if (tmp == NULL) {
5797
673
      cur = xmlCreateEnumeration(name);
5798
673
      if (cur == NULL) {
5799
0
                xmlFreeEnumeration(ret);
5800
0
                return(NULL);
5801
0
            }
5802
673
      if (last == NULL) ret = last = cur;
5803
0
      else {
5804
0
    last->next = cur;
5805
0
    last = cur;
5806
0
      }
5807
673
  }
5808
673
  SKIP_BLANKS;
5809
673
    } while (RAW == '|');
5810
673
    if (RAW != ')') {
5811
0
  xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
5812
0
        xmlFreeEnumeration(ret);
5813
0
  return(NULL);
5814
0
    }
5815
673
    NEXT;
5816
673
    return(ret);
5817
673
}
5818
5819
/**
5820
 * xmlParseEnumerationType:
5821
 * @ctxt:  an XML parser context
5822
 *
5823
 * DEPRECATED: Internal function, don't use.
5824
 *
5825
 * parse an Enumeration attribute type.
5826
 *
5827
 * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
5828
 *
5829
 * [ VC: Enumeration ]
5830
 * Values of this type must match one of the Nmtoken tokens in
5831
 * the declaration
5832
 *
5833
 * Returns: the enumeration attribute tree built while parsing
5834
 */
5835
5836
xmlEnumerationPtr
5837
11.7k
xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
5838
11.7k
    xmlChar *name;
5839
11.7k
    xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
5840
5841
11.7k
    if (RAW != '(') {
5842
971
  xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_STARTED, NULL);
5843
971
  return(NULL);
5844
971
    }
5845
10.7k
    SHRINK;
5846
71.6k
    do {
5847
71.6k
        NEXT;
5848
71.6k
  SKIP_BLANKS;
5849
71.6k
        name = xmlParseNmtoken(ctxt);
5850
71.6k
  if (name == NULL) {
5851
2.45k
      xmlFatalErr(ctxt, XML_ERR_NMTOKEN_REQUIRED, NULL);
5852
2.45k
      return(ret);
5853
2.45k
  }
5854
69.2k
  tmp = ret;
5855
109k
  while (tmp != NULL) {
5856
81.2k
      if (xmlStrEqual(name, tmp->name)) {
5857
40.6k
    xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
5858
40.6k
    "standalone: attribute enumeration value token %s duplicated\n",
5859
40.6k
         name, NULL);
5860
40.6k
    if (!xmlDictOwns(ctxt->dict, name))
5861
40.6k
        xmlFree(name);
5862
40.6k
    break;
5863
40.6k
      }
5864
40.6k
      tmp = tmp->next;
5865
40.6k
  }
5866
69.2k
  if (tmp == NULL) {
5867
28.5k
      cur = xmlCreateEnumeration(name);
5868
28.5k
      if (!xmlDictOwns(ctxt->dict, name))
5869
28.5k
    xmlFree(name);
5870
28.5k
      if (cur == NULL) {
5871
0
                xmlFreeEnumeration(ret);
5872
0
                return(NULL);
5873
0
            }
5874
28.5k
      if (last == NULL) ret = last = cur;
5875
20.3k
      else {
5876
20.3k
    last->next = cur;
5877
20.3k
    last = cur;
5878
20.3k
      }
5879
28.5k
  }
5880
69.2k
  SKIP_BLANKS;
5881
69.2k
    } while (RAW == '|');
5882
8.27k
    if (RAW != ')') {
5883
6.88k
  xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_FINISHED, NULL);
5884
6.88k
  return(ret);
5885
6.88k
    }
5886
1.39k
    NEXT;
5887
1.39k
    return(ret);
5888
8.27k
}
5889
5890
/**
5891
 * xmlParseEnumeratedType:
5892
 * @ctxt:  an XML parser context
5893
 * @tree:  the enumeration tree built while parsing
5894
 *
5895
 * DEPRECATED: Internal function, don't use.
5896
 *
5897
 * parse an Enumerated attribute type.
5898
 *
5899
 * [57] EnumeratedType ::= NotationType | Enumeration
5900
 *
5901
 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
5902
 *
5903
 *
5904
 * Returns: XML_ATTRIBUTE_ENUMERATION or XML_ATTRIBUTE_NOTATION
5905
 */
5906
5907
int
5908
12.3k
xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
5909
12.3k
    if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
5910
673
  SKIP(8);
5911
673
  if (SKIP_BLANKS == 0) {
5912
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5913
0
         "Space required after 'NOTATION'\n");
5914
0
      return(0);
5915
0
  }
5916
673
  *tree = xmlParseNotationType(ctxt);
5917
673
  if (*tree == NULL) return(0);
5918
673
  return(XML_ATTRIBUTE_NOTATION);
5919
673
    }
5920
11.7k
    *tree = xmlParseEnumerationType(ctxt);
5921
11.7k
    if (*tree == NULL) return(0);
5922
8.27k
    return(XML_ATTRIBUTE_ENUMERATION);
5923
11.7k
}
5924
5925
/**
5926
 * xmlParseAttributeType:
5927
 * @ctxt:  an XML parser context
5928
 * @tree:  the enumeration tree built while parsing
5929
 *
5930
 * DEPRECATED: Internal function, don't use.
5931
 *
5932
 * parse the Attribute list def for an element
5933
 *
5934
 * [54] AttType ::= StringType | TokenizedType | EnumeratedType
5935
 *
5936
 * [55] StringType ::= 'CDATA'
5937
 *
5938
 * [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' |
5939
 *                        'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
5940
 *
5941
 * Validity constraints for attribute values syntax are checked in
5942
 * xmlValidateAttributeValue()
5943
 *
5944
 * [ VC: ID ]
5945
 * Values of type ID must match the Name production. A name must not
5946
 * appear more than once in an XML document as a value of this type;
5947
 * i.e., ID values must uniquely identify the elements which bear them.
5948
 *
5949
 * [ VC: One ID per Element Type ]
5950
 * No element type may have more than one ID attribute specified.
5951
 *
5952
 * [ VC: ID Attribute Default ]
5953
 * An ID attribute must have a declared default of #IMPLIED or #REQUIRED.
5954
 *
5955
 * [ VC: IDREF ]
5956
 * Values of type IDREF must match the Name production, and values
5957
 * of type IDREFS must match Names; each IDREF Name must match the value
5958
 * of an ID attribute on some element in the XML document; i.e. IDREF
5959
 * values must match the value of some ID attribute.
5960
 *
5961
 * [ VC: Entity Name ]
5962
 * Values of type ENTITY must match the Name production, values
5963
 * of type ENTITIES must match Names; each Entity Name must match the
5964
 * name of an unparsed entity declared in the DTD.
5965
 *
5966
 * [ VC: Name Token ]
5967
 * Values of type NMTOKEN must match the Nmtoken production; values
5968
 * of type NMTOKENS must match Nmtokens.
5969
 *
5970
 * Returns the attribute type
5971
 */
5972
int
5973
13.3k
xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
5974
13.3k
    SHRINK;
5975
13.3k
    if (CMP5(CUR_PTR, 'C', 'D', 'A', 'T', 'A')) {
5976
0
  SKIP(5);
5977
0
  return(XML_ATTRIBUTE_CDATA);
5978
13.3k
     } else if (CMP6(CUR_PTR, 'I', 'D', 'R', 'E', 'F', 'S')) {
5979
0
  SKIP(6);
5980
0
  return(XML_ATTRIBUTE_IDREFS);
5981
13.3k
     } else if (CMP5(CUR_PTR, 'I', 'D', 'R', 'E', 'F')) {
5982
0
  SKIP(5);
5983
0
  return(XML_ATTRIBUTE_IDREF);
5984
13.3k
     } else if ((RAW == 'I') && (NXT(1) == 'D')) {
5985
922
        SKIP(2);
5986
922
  return(XML_ATTRIBUTE_ID);
5987
12.3k
     } else if (CMP6(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'Y')) {
5988
0
  SKIP(6);
5989
0
  return(XML_ATTRIBUTE_ENTITY);
5990
12.3k
     } else if (CMP8(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S')) {
5991
0
  SKIP(8);
5992
0
  return(XML_ATTRIBUTE_ENTITIES);
5993
12.3k
     } else if (CMP8(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S')) {
5994
0
  SKIP(8);
5995
0
  return(XML_ATTRIBUTE_NMTOKENS);
5996
12.3k
     } else if (CMP7(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N')) {
5997
0
  SKIP(7);
5998
0
  return(XML_ATTRIBUTE_NMTOKEN);
5999
0
     }
6000
12.3k
     return(xmlParseEnumeratedType(ctxt, tree));
6001
13.3k
}
6002
6003
/**
6004
 * xmlParseAttributeListDecl:
6005
 * @ctxt:  an XML parser context
6006
 *
6007
 * DEPRECATED: Internal function, don't use.
6008
 *
6009
 * : parse the Attribute list def for an element
6010
 *
6011
 * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
6012
 *
6013
 * [53] AttDef ::= S Name S AttType S DefaultDecl
6014
 *
6015
 */
6016
void
6017
14.4k
xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
6018
14.4k
    const xmlChar *elemName;
6019
14.4k
    const xmlChar *attrName;
6020
14.4k
    xmlEnumerationPtr tree;
6021
6022
14.4k
    if (CMP9(CUR_PTR, '<', '!', 'A', 'T', 'T', 'L', 'I', 'S', 'T')) {
6023
14.4k
  int inputid = ctxt->input->id;
6024
6025
14.4k
  SKIP(9);
6026
14.4k
  if (SKIP_BLANKS == 0) {
6027
2.46k
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6028
2.46k
                     "Space required after '<!ATTLIST'\n");
6029
2.46k
  }
6030
14.4k
        elemName = xmlParseName(ctxt);
6031
14.4k
  if (elemName == NULL) {
6032
0
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6033
0
         "ATTLIST: no name for Element\n");
6034
0
      return;
6035
0
  }
6036
14.4k
  SKIP_BLANKS;
6037
14.4k
  GROW;
6038
15.5k
  while ((RAW != '>') && (ctxt->instate != XML_PARSER_EOF)) {
6039
15.3k
      int type;
6040
15.3k
      int def;
6041
15.3k
      xmlChar *defaultValue = NULL;
6042
6043
15.3k
      GROW;
6044
15.3k
            tree = NULL;
6045
15.3k
      attrName = xmlParseName(ctxt);
6046
15.3k
      if (attrName == NULL) {
6047
1.23k
    xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6048
1.23k
             "ATTLIST: no name for Attribute\n");
6049
1.23k
    break;
6050
1.23k
      }
6051
14.1k
      GROW;
6052
14.1k
      if (SKIP_BLANKS == 0) {
6053
827
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6054
827
            "Space required after the attribute name\n");
6055
827
    break;
6056
827
      }
6057
6058
13.3k
      type = xmlParseAttributeType(ctxt, &tree);
6059
13.3k
      if (type <= 0) {
6060
3.43k
          break;
6061
3.43k
      }
6062
6063
9.87k
      GROW;
6064
9.87k
      if (SKIP_BLANKS == 0) {
6065
6.88k
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6066
6.88k
             "Space required after the attribute type\n");
6067
6.88k
          if (tree != NULL)
6068
6.88k
        xmlFreeEnumeration(tree);
6069
6.88k
    break;
6070
6.88k
      }
6071
6072
2.98k
      def = xmlParseDefaultDecl(ctxt, &defaultValue);
6073
2.98k
      if (def <= 0) {
6074
0
                if (defaultValue != NULL)
6075
0
        xmlFree(defaultValue);
6076
0
          if (tree != NULL)
6077
0
        xmlFreeEnumeration(tree);
6078
0
          break;
6079
0
      }
6080
2.98k
      if ((type != XML_ATTRIBUTE_CDATA) && (defaultValue != NULL))
6081
598
          xmlAttrNormalizeSpace(defaultValue, defaultValue);
6082
6083
2.98k
      GROW;
6084
2.98k
            if (RAW != '>') {
6085
2.82k
    if (SKIP_BLANKS == 0) {
6086
1.90k
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6087
1.90k
      "Space required after the attribute default value\n");
6088
1.90k
        if (defaultValue != NULL)
6089
0
      xmlFree(defaultValue);
6090
1.90k
        if (tree != NULL)
6091
1.90k
      xmlFreeEnumeration(tree);
6092
1.90k
        break;
6093
1.90k
    }
6094
2.82k
      }
6095
1.08k
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
6096
1.08k
    (ctxt->sax->attributeDecl != NULL))
6097
588
    ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
6098
588
                          type, def, defaultValue, tree);
6099
496
      else if (tree != NULL)
6100
162
    xmlFreeEnumeration(tree);
6101
6102
1.08k
      if ((ctxt->sax2) && (defaultValue != NULL) &&
6103
1.08k
          (def != XML_ATTRIBUTE_IMPLIED) &&
6104
1.08k
    (def != XML_ATTRIBUTE_REQUIRED)) {
6105
598
    xmlAddDefAttrs(ctxt, elemName, attrName, defaultValue);
6106
598
      }
6107
1.08k
      if (ctxt->sax2) {
6108
1.08k
    xmlAddSpecialAttr(ctxt, elemName, attrName, type);
6109
1.08k
      }
6110
1.08k
      if (defaultValue != NULL)
6111
598
          xmlFree(defaultValue);
6112
1.08k
      GROW;
6113
1.08k
  }
6114
14.4k
  if (RAW == '>') {
6115
162
      if (inputid != ctxt->input->id) {
6116
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6117
0
                               "Attribute list declaration doesn't start and"
6118
0
                               " stop in the same entity\n");
6119
0
      }
6120
162
      NEXT;
6121
162
  }
6122
14.4k
    }
6123
14.4k
}
6124
6125
/**
6126
 * xmlParseElementMixedContentDecl:
6127
 * @ctxt:  an XML parser context
6128
 * @inputchk:  the input used for the current entity, needed for boundary checks
6129
 *
6130
 * DEPRECATED: Internal function, don't use.
6131
 *
6132
 * parse the declaration for a Mixed Element content
6133
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6134
 *
6135
 * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' |
6136
 *                '(' S? '#PCDATA' S? ')'
6137
 *
6138
 * [ VC: Proper Group/PE Nesting ] applies to [51] too (see [49])
6139
 *
6140
 * [ VC: No Duplicate Types ]
6141
 * The same name must not appear more than once in a single
6142
 * mixed-content declaration.
6143
 *
6144
 * returns: the list of the xmlElementContentPtr describing the element choices
6145
 */
6146
xmlElementContentPtr
6147
1.10k
xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
6148
1.10k
    xmlElementContentPtr ret = NULL, cur = NULL, n;
6149
1.10k
    const xmlChar *elem = NULL;
6150
6151
1.10k
    GROW;
6152
1.10k
    if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
6153
1.10k
  SKIP(7);
6154
1.10k
  SKIP_BLANKS;
6155
1.10k
  SHRINK;
6156
1.10k
  if (RAW == ')') {
6157
342
      if (ctxt->input->id != inputchk) {
6158
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6159
0
                               "Element content declaration doesn't start and"
6160
0
                               " stop in the same entity\n");
6161
0
      }
6162
342
      NEXT;
6163
342
      ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
6164
342
      if (ret == NULL)
6165
0
          return(NULL);
6166
342
      if (RAW == '*') {
6167
20
    ret->ocur = XML_ELEMENT_CONTENT_MULT;
6168
20
    NEXT;
6169
20
      }
6170
342
      return(ret);
6171
342
  }
6172
765
  if ((RAW == '(') || (RAW == '|')) {
6173
745
      ret = cur = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
6174
745
      if (ret == NULL) return(NULL);
6175
745
  }
6176
2.59k
  while ((RAW == '|') && (ctxt->instate != XML_PARSER_EOF)) {
6177
1.84k
      NEXT;
6178
1.84k
      if (elem == NULL) {
6179
745
          ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6180
745
    if (ret == NULL) {
6181
0
        xmlFreeDocElementContent(ctxt->myDoc, cur);
6182
0
                    return(NULL);
6183
0
                }
6184
745
    ret->c1 = cur;
6185
745
    if (cur != NULL)
6186
745
        cur->parent = ret;
6187
745
    cur = ret;
6188
1.09k
      } else {
6189
1.09k
          n = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6190
1.09k
    if (n == NULL) {
6191
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6192
0
                    return(NULL);
6193
0
                }
6194
1.09k
    n->c1 = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6195
1.09k
    if (n->c1 != NULL)
6196
1.09k
        n->c1->parent = n;
6197
1.09k
          cur->c2 = n;
6198
1.09k
    if (n != NULL)
6199
1.09k
        n->parent = cur;
6200
1.09k
    cur = n;
6201
1.09k
      }
6202
1.84k
      SKIP_BLANKS;
6203
1.84k
      elem = xmlParseName(ctxt);
6204
1.84k
      if (elem == NULL) {
6205
12
    xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6206
12
      "xmlParseElementMixedContentDecl : Name expected\n");
6207
12
    xmlFreeDocElementContent(ctxt->myDoc, ret);
6208
12
    return(NULL);
6209
12
      }
6210
1.83k
      SKIP_BLANKS;
6211
1.83k
      GROW;
6212
1.83k
  }
6213
753
  if ((RAW == ')') && (NXT(1) == '*')) {
6214
459
      if (elem != NULL) {
6215
459
    cur->c2 = xmlNewDocElementContent(ctxt->myDoc, elem,
6216
459
                                   XML_ELEMENT_CONTENT_ELEMENT);
6217
459
    if (cur->c2 != NULL)
6218
459
        cur->c2->parent = cur;
6219
459
            }
6220
459
            if (ret != NULL)
6221
459
                ret->ocur = XML_ELEMENT_CONTENT_MULT;
6222
459
      if (ctxt->input->id != inputchk) {
6223
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6224
0
                               "Element content declaration doesn't start and"
6225
0
                               " stop in the same entity\n");
6226
0
      }
6227
459
      SKIP(2);
6228
459
  } else {
6229
294
      xmlFreeDocElementContent(ctxt->myDoc, ret);
6230
294
      xmlFatalErr(ctxt, XML_ERR_MIXED_NOT_STARTED, NULL);
6231
294
      return(NULL);
6232
294
  }
6233
6234
753
    } else {
6235
0
  xmlFatalErr(ctxt, XML_ERR_PCDATA_REQUIRED, NULL);
6236
0
    }
6237
459
    return(ret);
6238
1.10k
}
6239
6240
/**
6241
 * xmlParseElementChildrenContentDeclPriv:
6242
 * @ctxt:  an XML parser context
6243
 * @inputchk:  the input used for the current entity, needed for boundary checks
6244
 * @depth: the level of recursion
6245
 *
6246
 * parse the declaration for a Mixed Element content
6247
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6248
 *
6249
 *
6250
 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
6251
 *
6252
 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
6253
 *
6254
 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
6255
 *
6256
 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
6257
 *
6258
 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
6259
 * TODO Parameter-entity replacement text must be properly nested
6260
 *  with parenthesized groups. That is to say, if either of the
6261
 *  opening or closing parentheses in a choice, seq, or Mixed
6262
 *  construct is contained in the replacement text for a parameter
6263
 *  entity, both must be contained in the same replacement text. For
6264
 *  interoperability, if a parameter-entity reference appears in a
6265
 *  choice, seq, or Mixed construct, its replacement text should not
6266
 *  be empty, and neither the first nor last non-blank character of
6267
 *  the replacement text should be a connector (| or ,).
6268
 *
6269
 * Returns the tree of xmlElementContentPtr describing the element
6270
 *          hierarchy.
6271
 */
6272
static xmlElementContentPtr
6273
xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
6274
562
                                       int depth) {
6275
562
    xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
6276
562
    const xmlChar *elem;
6277
562
    xmlChar type = 0;
6278
6279
562
    if (((depth > 128) && ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
6280
562
        (depth >  2048)) {
6281
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED,
6282
0
"xmlParseElementChildrenContentDecl : depth %d too deep, use XML_PARSE_HUGE\n",
6283
0
                          depth);
6284
0
  return(NULL);
6285
0
    }
6286
562
    SKIP_BLANKS;
6287
562
    GROW;
6288
562
    if (RAW == '(') {
6289
0
  int inputid = ctxt->input->id;
6290
6291
        /* Recurse on first child */
6292
0
  NEXT;
6293
0
  SKIP_BLANKS;
6294
0
        cur = ret = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
6295
0
                                                           depth + 1);
6296
0
        if (cur == NULL)
6297
0
            return(NULL);
6298
0
  SKIP_BLANKS;
6299
0
  GROW;
6300
562
    } else {
6301
562
  elem = xmlParseName(ctxt);
6302
562
  if (elem == NULL) {
6303
0
      xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
6304
0
      return(NULL);
6305
0
  }
6306
562
        cur = ret = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6307
562
  if (cur == NULL) {
6308
0
      xmlErrMemory(ctxt, NULL);
6309
0
      return(NULL);
6310
0
  }
6311
562
  GROW;
6312
562
  if (RAW == '?') {
6313
0
      cur->ocur = XML_ELEMENT_CONTENT_OPT;
6314
0
      NEXT;
6315
562
  } else if (RAW == '*') {
6316
9
      cur->ocur = XML_ELEMENT_CONTENT_MULT;
6317
9
      NEXT;
6318
553
  } else if (RAW == '+') {
6319
0
      cur->ocur = XML_ELEMENT_CONTENT_PLUS;
6320
0
      NEXT;
6321
553
  } else {
6322
553
      cur->ocur = XML_ELEMENT_CONTENT_ONCE;
6323
553
  }
6324
562
  GROW;
6325
562
    }
6326
562
    SKIP_BLANKS;
6327
562
    SHRINK;
6328
1.67k
    while ((RAW != ')') && (ctxt->instate != XML_PARSER_EOF)) {
6329
        /*
6330
   * Each loop we parse one separator and one element.
6331
   */
6332
1.42k
        if (RAW == ',') {
6333
18
      if (type == 0) type = CUR;
6334
6335
      /*
6336
       * Detect "Name | Name , Name" error
6337
       */
6338
0
      else if (type != CUR) {
6339
0
    xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
6340
0
        "xmlParseElementChildrenContentDecl : '%c' expected\n",
6341
0
                      type);
6342
0
    if ((last != NULL) && (last != ret))
6343
0
        xmlFreeDocElementContent(ctxt->myDoc, last);
6344
0
    if (ret != NULL)
6345
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6346
0
    return(NULL);
6347
0
      }
6348
18
      NEXT;
6349
6350
18
      op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_SEQ);
6351
18
      if (op == NULL) {
6352
0
    if ((last != NULL) && (last != ret))
6353
0
        xmlFreeDocElementContent(ctxt->myDoc, last);
6354
0
          xmlFreeDocElementContent(ctxt->myDoc, ret);
6355
0
    return(NULL);
6356
0
      }
6357
18
      if (last == NULL) {
6358
18
    op->c1 = ret;
6359
18
    if (ret != NULL)
6360
18
        ret->parent = op;
6361
18
    ret = cur = op;
6362
18
      } else {
6363
0
          cur->c2 = op;
6364
0
    if (op != NULL)
6365
0
        op->parent = cur;
6366
0
    op->c1 = last;
6367
0
    if (last != NULL)
6368
0
        last->parent = op;
6369
0
    cur =op;
6370
0
    last = NULL;
6371
0
      }
6372
1.40k
  } else if (RAW == '|') {
6373
1.11k
      if (type == 0) type = CUR;
6374
6375
      /*
6376
       * Detect "Name , Name | Name" error
6377
       */
6378
573
      else if (type != CUR) {
6379
0
    xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
6380
0
        "xmlParseElementChildrenContentDecl : '%c' expected\n",
6381
0
          type);
6382
0
    if ((last != NULL) && (last != ret))
6383
0
        xmlFreeDocElementContent(ctxt->myDoc, last);
6384
0
    if (ret != NULL)
6385
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6386
0
    return(NULL);
6387
0
      }
6388
1.11k
      NEXT;
6389
6390
1.11k
      op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6391
1.11k
      if (op == NULL) {
6392
0
    if ((last != NULL) && (last != ret))
6393
0
        xmlFreeDocElementContent(ctxt->myDoc, last);
6394
0
    if (ret != NULL)
6395
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6396
0
    return(NULL);
6397
0
      }
6398
1.11k
      if (last == NULL) {
6399
544
    op->c1 = ret;
6400
544
    if (ret != NULL)
6401
544
        ret->parent = op;
6402
544
    ret = cur = op;
6403
573
      } else {
6404
573
          cur->c2 = op;
6405
573
    if (op != NULL)
6406
573
        op->parent = cur;
6407
573
    op->c1 = last;
6408
573
    if (last != NULL)
6409
573
        last->parent = op;
6410
573
    cur =op;
6411
573
    last = NULL;
6412
573
      }
6413
1.11k
  } else {
6414
285
      xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED, NULL);
6415
285
      if ((last != NULL) && (last != ret))
6416
285
          xmlFreeDocElementContent(ctxt->myDoc, last);
6417
285
      if (ret != NULL)
6418
285
    xmlFreeDocElementContent(ctxt->myDoc, ret);
6419
285
      return(NULL);
6420
285
  }
6421
1.13k
  GROW;
6422
1.13k
  SKIP_BLANKS;
6423
1.13k
  GROW;
6424
1.13k
  if (RAW == '(') {
6425
18
      int inputid = ctxt->input->id;
6426
      /* Recurse on second child */
6427
18
      NEXT;
6428
18
      SKIP_BLANKS;
6429
18
      last = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
6430
18
                                                          depth + 1);
6431
18
            if (last == NULL) {
6432
18
    if (ret != NULL)
6433
18
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6434
18
    return(NULL);
6435
18
            }
6436
0
      SKIP_BLANKS;
6437
1.11k
  } else {
6438
1.11k
      elem = xmlParseName(ctxt);
6439
1.11k
      if (elem == NULL) {
6440
0
    xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
6441
0
    if (ret != NULL)
6442
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6443
0
    return(NULL);
6444
0
      }
6445
1.11k
      last = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6446
1.11k
      if (last == NULL) {
6447
0
    if (ret != NULL)
6448
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6449
0
    return(NULL);
6450
0
      }
6451
1.11k
      if (RAW == '?') {
6452
0
    last->ocur = XML_ELEMENT_CONTENT_OPT;
6453
0
    NEXT;
6454
1.11k
      } else if (RAW == '*') {
6455
0
    last->ocur = XML_ELEMENT_CONTENT_MULT;
6456
0
    NEXT;
6457
1.11k
      } else if (RAW == '+') {
6458
0
    last->ocur = XML_ELEMENT_CONTENT_PLUS;
6459
0
    NEXT;
6460
1.11k
      } else {
6461
1.11k
    last->ocur = XML_ELEMENT_CONTENT_ONCE;
6462
1.11k
      }
6463
1.11k
  }
6464
1.11k
  SKIP_BLANKS;
6465
1.11k
  GROW;
6466
1.11k
    }
6467
259
    if ((cur != NULL) && (last != NULL)) {
6468
259
        cur->c2 = last;
6469
259
  if (last != NULL)
6470
259
      last->parent = cur;
6471
259
    }
6472
259
    if (ctxt->input->id != inputchk) {
6473
0
  xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6474
0
                       "Element content declaration doesn't start and stop in"
6475
0
                       " the same entity\n");
6476
0
    }
6477
259
    NEXT;
6478
259
    if (RAW == '?') {
6479
0
  if (ret != NULL) {
6480
0
      if ((ret->ocur == XML_ELEMENT_CONTENT_PLUS) ||
6481
0
          (ret->ocur == XML_ELEMENT_CONTENT_MULT))
6482
0
          ret->ocur = XML_ELEMENT_CONTENT_MULT;
6483
0
      else
6484
0
          ret->ocur = XML_ELEMENT_CONTENT_OPT;
6485
0
  }
6486
0
  NEXT;
6487
259
    } else if (RAW == '*') {
6488
0
  if (ret != NULL) {
6489
0
      ret->ocur = XML_ELEMENT_CONTENT_MULT;
6490
0
      cur = ret;
6491
      /*
6492
       * Some normalization:
6493
       * (a | b* | c?)* == (a | b | c)*
6494
       */
6495
0
      while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
6496
0
    if ((cur->c1 != NULL) &&
6497
0
              ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
6498
0
         (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT)))
6499
0
        cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
6500
0
    if ((cur->c2 != NULL) &&
6501
0
              ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
6502
0
         (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT)))
6503
0
        cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
6504
0
    cur = cur->c2;
6505
0
      }
6506
0
  }
6507
0
  NEXT;
6508
259
    } else if (RAW == '+') {
6509
0
  if (ret != NULL) {
6510
0
      int found = 0;
6511
6512
0
      if ((ret->ocur == XML_ELEMENT_CONTENT_OPT) ||
6513
0
          (ret->ocur == XML_ELEMENT_CONTENT_MULT))
6514
0
          ret->ocur = XML_ELEMENT_CONTENT_MULT;
6515
0
      else
6516
0
          ret->ocur = XML_ELEMENT_CONTENT_PLUS;
6517
      /*
6518
       * Some normalization:
6519
       * (a | b*)+ == (a | b)*
6520
       * (a | b?)+ == (a | b)*
6521
       */
6522
0
      while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
6523
0
    if ((cur->c1 != NULL) &&
6524
0
              ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
6525
0
         (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT))) {
6526
0
        cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
6527
0
        found = 1;
6528
0
    }
6529
0
    if ((cur->c2 != NULL) &&
6530
0
              ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
6531
0
         (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT))) {
6532
0
        cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
6533
0
        found = 1;
6534
0
    }
6535
0
    cur = cur->c2;
6536
0
      }
6537
0
      if (found)
6538
0
    ret->ocur = XML_ELEMENT_CONTENT_MULT;
6539
0
  }
6540
0
  NEXT;
6541
0
    }
6542
259
    return(ret);
6543
562
}
6544
6545
/**
6546
 * xmlParseElementChildrenContentDecl:
6547
 * @ctxt:  an XML parser context
6548
 * @inputchk:  the input used for the current entity, needed for boundary checks
6549
 *
6550
 * DEPRECATED: Internal function, don't use.
6551
 *
6552
 * parse the declaration for a Mixed Element content
6553
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6554
 *
6555
 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
6556
 *
6557
 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
6558
 *
6559
 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
6560
 *
6561
 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
6562
 *
6563
 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
6564
 * TODO Parameter-entity replacement text must be properly nested
6565
 *  with parenthesized groups. That is to say, if either of the
6566
 *  opening or closing parentheses in a choice, seq, or Mixed
6567
 *  construct is contained in the replacement text for a parameter
6568
 *  entity, both must be contained in the same replacement text. For
6569
 *  interoperability, if a parameter-entity reference appears in a
6570
 *  choice, seq, or Mixed construct, its replacement text should not
6571
 *  be empty, and neither the first nor last non-blank character of
6572
 *  the replacement text should be a connector (| or ,).
6573
 *
6574
 * Returns the tree of xmlElementContentPtr describing the element
6575
 *          hierarchy.
6576
 */
6577
xmlElementContentPtr
6578
0
xmlParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
6579
    /* stub left for API/ABI compat */
6580
0
    return(xmlParseElementChildrenContentDeclPriv(ctxt, inputchk, 1));
6581
0
}
6582
6583
/**
6584
 * xmlParseElementContentDecl:
6585
 * @ctxt:  an XML parser context
6586
 * @name:  the name of the element being defined.
6587
 * @result:  the Element Content pointer will be stored here if any
6588
 *
6589
 * DEPRECATED: Internal function, don't use.
6590
 *
6591
 * parse the declaration for an Element content either Mixed or Children,
6592
 * the cases EMPTY and ANY are handled directly in xmlParseElementDecl
6593
 *
6594
 * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
6595
 *
6596
 * returns: the type of element content XML_ELEMENT_TYPE_xxx
6597
 */
6598
6599
int
6600
xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, const xmlChar *name,
6601
1.65k
                           xmlElementContentPtr *result) {
6602
6603
1.65k
    xmlElementContentPtr tree = NULL;
6604
1.65k
    int inputid = ctxt->input->id;
6605
1.65k
    int res;
6606
6607
1.65k
    *result = NULL;
6608
6609
1.65k
    if (RAW != '(') {
6610
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
6611
0
    "xmlParseElementContentDecl : %s '(' expected\n", name);
6612
0
  return(-1);
6613
0
    }
6614
1.65k
    NEXT;
6615
1.65k
    GROW;
6616
1.65k
    if (ctxt->instate == XML_PARSER_EOF)
6617
0
        return(-1);
6618
1.65k
    SKIP_BLANKS;
6619
1.65k
    if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
6620
1.10k
        tree = xmlParseElementMixedContentDecl(ctxt, inputid);
6621
1.10k
  res = XML_ELEMENT_TYPE_MIXED;
6622
1.10k
    } else {
6623
544
        tree = xmlParseElementChildrenContentDeclPriv(ctxt, inputid, 1);
6624
544
  res = XML_ELEMENT_TYPE_ELEMENT;
6625
544
    }
6626
1.65k
    SKIP_BLANKS;
6627
1.65k
    *result = tree;
6628
1.65k
    return(res);
6629
1.65k
}
6630
6631
/**
6632
 * xmlParseElementDecl:
6633
 * @ctxt:  an XML parser context
6634
 *
6635
 * DEPRECATED: Internal function, don't use.
6636
 *
6637
 * parse an Element declaration.
6638
 *
6639
 * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
6640
 *
6641
 * [ VC: Unique Element Type Declaration ]
6642
 * No element type may be declared more than once
6643
 *
6644
 * Returns the type of the element, or -1 in case of error
6645
 */
6646
int
6647
1.65k
xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
6648
1.65k
    const xmlChar *name;
6649
1.65k
    int ret = -1;
6650
1.65k
    xmlElementContentPtr content  = NULL;
6651
6652
    /* GROW; done in the caller */
6653
1.65k
    if (CMP9(CUR_PTR, '<', '!', 'E', 'L', 'E', 'M', 'E', 'N', 'T')) {
6654
1.65k
  int inputid = ctxt->input->id;
6655
6656
1.65k
  SKIP(9);
6657
1.65k
  if (SKIP_BLANKS == 0) {
6658
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6659
0
               "Space required after 'ELEMENT'\n");
6660
0
      return(-1);
6661
0
  }
6662
1.65k
        name = xmlParseName(ctxt);
6663
1.65k
  if (name == NULL) {
6664
0
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6665
0
         "xmlParseElementDecl: no name for Element\n");
6666
0
      return(-1);
6667
0
  }
6668
1.65k
  if (SKIP_BLANKS == 0) {
6669
13
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6670
13
         "Space required after the element name\n");
6671
13
  }
6672
1.65k
  if (CMP5(CUR_PTR, 'E', 'M', 'P', 'T', 'Y')) {
6673
0
      SKIP(5);
6674
      /*
6675
       * Element must always be empty.
6676
       */
6677
0
      ret = XML_ELEMENT_TYPE_EMPTY;
6678
1.65k
  } else if ((RAW == 'A') && (NXT(1) == 'N') &&
6679
1.65k
             (NXT(2) == 'Y')) {
6680
0
      SKIP(3);
6681
      /*
6682
       * Element is a generic container.
6683
       */
6684
0
      ret = XML_ELEMENT_TYPE_ANY;
6685
1.65k
  } else if (RAW == '(') {
6686
1.65k
      ret = xmlParseElementContentDecl(ctxt, name, &content);
6687
1.65k
  } else {
6688
      /*
6689
       * [ WFC: PEs in Internal Subset ] error handling.
6690
       */
6691
7
      if ((RAW == '%') && (ctxt->external == 0) &&
6692
7
          (ctxt->inputNr == 1)) {
6693
0
    xmlFatalErrMsg(ctxt, XML_ERR_PEREF_IN_INT_SUBSET,
6694
0
    "PEReference: forbidden within markup decl in internal subset\n");
6695
7
      } else {
6696
7
    xmlFatalErrMsg(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
6697
7
          "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
6698
7
            }
6699
7
      return(-1);
6700
7
  }
6701
6702
1.65k
  SKIP_BLANKS;
6703
6704
1.65k
  if (RAW != '>') {
6705
106
      xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
6706
106
      if (content != NULL) {
6707
0
    xmlFreeDocElementContent(ctxt->myDoc, content);
6708
0
      }
6709
1.54k
  } else {
6710
1.54k
      if (inputid != ctxt->input->id) {
6711
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6712
0
                               "Element declaration doesn't start and stop in"
6713
0
                               " the same entity\n");
6714
0
      }
6715
6716
1.54k
      NEXT;
6717
1.54k
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
6718
1.54k
    (ctxt->sax->elementDecl != NULL)) {
6719
0
    if (content != NULL)
6720
0
        content->parent = NULL;
6721
0
          ctxt->sax->elementDecl(ctxt->userData, name, ret,
6722
0
                           content);
6723
0
    if ((content != NULL) && (content->parent == NULL)) {
6724
        /*
6725
         * this is a trick: if xmlAddElementDecl is called,
6726
         * instead of copying the full tree it is plugged directly
6727
         * if called from the parser. Avoid duplicating the
6728
         * interfaces or change the API/ABI
6729
         */
6730
0
        xmlFreeDocElementContent(ctxt->myDoc, content);
6731
0
    }
6732
1.54k
      } else if (content != NULL) {
6733
1.06k
    xmlFreeDocElementContent(ctxt->myDoc, content);
6734
1.06k
      }
6735
1.54k
  }
6736
1.65k
    }
6737
1.65k
    return(ret);
6738
1.65k
}
6739
6740
/**
6741
 * xmlParseConditionalSections
6742
 * @ctxt:  an XML parser context
6743
 *
6744
 * [61] conditionalSect ::= includeSect | ignoreSect
6745
 * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
6746
 * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
6747
 * [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
6748
 * [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
6749
 */
6750
6751
static void
6752
0
xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
6753
0
    int *inputIds = NULL;
6754
0
    size_t inputIdsSize = 0;
6755
0
    size_t depth = 0;
6756
6757
0
    while (ctxt->instate != XML_PARSER_EOF) {
6758
0
        if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
6759
0
            int id = ctxt->input->id;
6760
6761
0
            SKIP(3);
6762
0
            SKIP_BLANKS;
6763
6764
0
            if (CMP7(CUR_PTR, 'I', 'N', 'C', 'L', 'U', 'D', 'E')) {
6765
0
                SKIP(7);
6766
0
                SKIP_BLANKS;
6767
0
                if (RAW != '[') {
6768
0
                    xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
6769
0
                    xmlHaltParser(ctxt);
6770
0
                    goto error;
6771
0
                }
6772
0
                if (ctxt->input->id != id) {
6773
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6774
0
                                   "All markup of the conditional section is"
6775
0
                                   " not in the same entity\n");
6776
0
                }
6777
0
                NEXT;
6778
6779
0
                if (inputIdsSize <= depth) {
6780
0
                    int *tmp;
6781
6782
0
                    inputIdsSize = (inputIdsSize == 0 ? 4 : inputIdsSize * 2);
6783
0
                    tmp = (int *) xmlRealloc(inputIds,
6784
0
                            inputIdsSize * sizeof(int));
6785
0
                    if (tmp == NULL) {
6786
0
                        xmlErrMemory(ctxt, NULL);
6787
0
                        goto error;
6788
0
                    }
6789
0
                    inputIds = tmp;
6790
0
                }
6791
0
                inputIds[depth] = id;
6792
0
                depth++;
6793
0
            } else if (CMP6(CUR_PTR, 'I', 'G', 'N', 'O', 'R', 'E')) {
6794
0
                int state;
6795
0
                xmlParserInputState instate;
6796
0
                size_t ignoreDepth = 0;
6797
6798
0
                SKIP(6);
6799
0
                SKIP_BLANKS;
6800
0
                if (RAW != '[') {
6801
0
                    xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
6802
0
                    xmlHaltParser(ctxt);
6803
0
                    goto error;
6804
0
                }
6805
0
                if (ctxt->input->id != id) {
6806
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6807
0
                                   "All markup of the conditional section is"
6808
0
                                   " not in the same entity\n");
6809
0
                }
6810
0
                NEXT;
6811
6812
                /*
6813
                 * Parse up to the end of the conditional section but disable
6814
                 * SAX event generating DTD building in the meantime
6815
                 */
6816
0
                state = ctxt->disableSAX;
6817
0
                instate = ctxt->instate;
6818
0
                if (ctxt->recovery == 0) ctxt->disableSAX = 1;
6819
0
                ctxt->instate = XML_PARSER_IGNORE;
6820
6821
0
                while (RAW != 0) {
6822
0
                    if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
6823
0
                        SKIP(3);
6824
0
                        ignoreDepth++;
6825
                        /* Check for integer overflow */
6826
0
                        if (ignoreDepth == 0) {
6827
0
                            xmlErrMemory(ctxt, NULL);
6828
0
                            goto error;
6829
0
                        }
6830
0
                    } else if ((RAW == ']') && (NXT(1) == ']') &&
6831
0
                               (NXT(2) == '>')) {
6832
0
                        if (ignoreDepth == 0)
6833
0
                            break;
6834
0
                        SKIP(3);
6835
0
                        ignoreDepth--;
6836
0
                    } else {
6837
0
                        NEXT;
6838
0
                    }
6839
0
                }
6840
6841
0
                ctxt->disableSAX = state;
6842
0
                ctxt->instate = instate;
6843
6844
0
    if (RAW == 0) {
6845
0
        xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
6846
0
                    goto error;
6847
0
    }
6848
0
                if (ctxt->input->id != id) {
6849
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6850
0
                                   "All markup of the conditional section is"
6851
0
                                   " not in the same entity\n");
6852
0
                }
6853
0
                SKIP(3);
6854
0
            } else {
6855
0
                xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
6856
0
                xmlHaltParser(ctxt);
6857
0
                goto error;
6858
0
            }
6859
0
        } else if ((depth > 0) &&
6860
0
                   (RAW == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
6861
0
            depth--;
6862
0
            if (ctxt->input->id != inputIds[depth]) {
6863
0
                xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6864
0
                               "All markup of the conditional section is not"
6865
0
                               " in the same entity\n");
6866
0
            }
6867
0
            SKIP(3);
6868
0
        } else {
6869
0
            int id = ctxt->input->id;
6870
0
            unsigned long cons = CUR_CONSUMED;
6871
6872
0
            xmlParseMarkupDecl(ctxt);
6873
6874
0
            if ((id == ctxt->input->id) && (cons == CUR_CONSUMED)) {
6875
0
                xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
6876
0
                xmlHaltParser(ctxt);
6877
0
                goto error;
6878
0
            }
6879
0
        }
6880
6881
0
        if (depth == 0)
6882
0
            break;
6883
6884
0
        SKIP_BLANKS;
6885
0
        GROW;
6886
0
    }
6887
6888
0
error:
6889
0
    xmlFree(inputIds);
6890
0
}
6891
6892
/**
6893
 * xmlParseMarkupDecl:
6894
 * @ctxt:  an XML parser context
6895
 *
6896
 * DEPRECATED: Internal function, don't use.
6897
 *
6898
 * parse Markup declarations
6899
 *
6900
 * [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
6901
 *                     NotationDecl | PI | Comment
6902
 *
6903
 * [ VC: Proper Declaration/PE Nesting ]
6904
 * Parameter-entity replacement text must be properly nested with
6905
 * markup declarations. That is to say, if either the first character
6906
 * or the last character of a markup declaration (markupdecl above) is
6907
 * contained in the replacement text for a parameter-entity reference,
6908
 * both must be contained in the same replacement text.
6909
 *
6910
 * [ WFC: PEs in Internal Subset ]
6911
 * In the internal DTD subset, parameter-entity references can occur
6912
 * only where markup declarations can occur, not within markup declarations.
6913
 * (This does not apply to references that occur in external parameter
6914
 * entities or to the external subset.)
6915
 */
6916
void
6917
48.1k
xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
6918
48.1k
    GROW;
6919
48.1k
    if (CUR == '<') {
6920
48.0k
        if (NXT(1) == '!') {
6921
47.2k
      switch (NXT(2)) {
6922
5.00k
          case 'E':
6923
5.00k
        if (NXT(3) == 'L')
6924
1.65k
      xmlParseElementDecl(ctxt);
6925
3.35k
        else if (NXT(3) == 'N')
6926
3.34k
      xmlParseEntityDecl(ctxt);
6927
5.00k
        break;
6928
14.4k
          case 'A':
6929
14.4k
        xmlParseAttributeListDecl(ctxt);
6930
14.4k
        break;
6931
27.6k
          case 'N':
6932
27.6k
        xmlParseNotationDecl(ctxt);
6933
27.6k
        break;
6934
75
          case '-':
6935
75
        xmlParseComment(ctxt);
6936
75
        break;
6937
0
    default:
6938
        /* there is an error but it will be detected later */
6939
0
        break;
6940
47.2k
      }
6941
47.2k
  } else if (NXT(1) == '?') {
6942
856
      xmlParsePI(ctxt);
6943
856
  }
6944
48.0k
    }
6945
6946
    /*
6947
     * detect requirement to exit there and act accordingly
6948
     * and avoid having instate overridden later on
6949
     */
6950
48.1k
    if (ctxt->instate == XML_PARSER_EOF)
6951
8
        return;
6952
6953
48.1k
    ctxt->instate = XML_PARSER_DTD;
6954
48.1k
}
6955
6956
/**
6957
 * xmlParseTextDecl:
6958
 * @ctxt:  an XML parser context
6959
 *
6960
 * DEPRECATED: Internal function, don't use.
6961
 *
6962
 * parse an XML declaration header for external entities
6963
 *
6964
 * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
6965
 */
6966
6967
void
6968
0
xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
6969
0
    xmlChar *version;
6970
0
    const xmlChar *encoding;
6971
0
    int oldstate;
6972
6973
    /*
6974
     * We know that '<?xml' is here.
6975
     */
6976
0
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
6977
0
  SKIP(5);
6978
0
    } else {
6979
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_STARTED, NULL);
6980
0
  return;
6981
0
    }
6982
6983
    /* Avoid expansion of parameter entities when skipping blanks. */
6984
0
    oldstate = ctxt->instate;
6985
0
    ctxt->instate = XML_PARSER_START;
6986
6987
0
    if (SKIP_BLANKS == 0) {
6988
0
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6989
0
           "Space needed after '<?xml'\n");
6990
0
    }
6991
6992
    /*
6993
     * We may have the VersionInfo here.
6994
     */
6995
0
    version = xmlParseVersionInfo(ctxt);
6996
0
    if (version == NULL)
6997
0
  version = xmlCharStrdup(XML_DEFAULT_VERSION);
6998
0
    else {
6999
0
  if (SKIP_BLANKS == 0) {
7000
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
7001
0
               "Space needed here\n");
7002
0
  }
7003
0
    }
7004
0
    ctxt->input->version = version;
7005
7006
    /*
7007
     * We must have the encoding declaration
7008
     */
7009
0
    encoding = xmlParseEncodingDecl(ctxt);
7010
0
    if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
7011
  /*
7012
   * The XML REC instructs us to stop parsing right here
7013
   */
7014
0
        ctxt->instate = oldstate;
7015
0
        return;
7016
0
    }
7017
0
    if ((encoding == NULL) && (ctxt->errNo == XML_ERR_OK)) {
7018
0
  xmlFatalErrMsg(ctxt, XML_ERR_MISSING_ENCODING,
7019
0
           "Missing encoding in text declaration\n");
7020
0
    }
7021
7022
0
    SKIP_BLANKS;
7023
0
    if ((RAW == '?') && (NXT(1) == '>')) {
7024
0
        SKIP(2);
7025
0
    } else if (RAW == '>') {
7026
        /* Deprecated old WD ... */
7027
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
7028
0
  NEXT;
7029
0
    } else {
7030
0
        int c;
7031
7032
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
7033
0
        while ((c = CUR) != 0) {
7034
0
            NEXT;
7035
0
            if (c == '>')
7036
0
                break;
7037
0
        }
7038
0
    }
7039
7040
0
    ctxt->instate = oldstate;
7041
0
}
7042
7043
/**
7044
 * xmlParseExternalSubset:
7045
 * @ctxt:  an XML parser context
7046
 * @ExternalID: the external identifier
7047
 * @SystemID: the system identifier (or URL)
7048
 *
7049
 * parse Markup declarations from an external subset
7050
 *
7051
 * [30] extSubset ::= textDecl? extSubsetDecl
7052
 *
7053
 * [31] extSubsetDecl ::= (markupdecl | conditionalSect | PEReference | S) *
7054
 */
7055
void
7056
xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
7057
0
                       const xmlChar *SystemID) {
7058
0
    xmlDetectSAX2(ctxt);
7059
0
    GROW;
7060
7061
0
    if ((ctxt->encoding == NULL) &&
7062
0
        (ctxt->input->end - ctxt->input->cur >= 4)) {
7063
0
        xmlChar start[4];
7064
0
  xmlCharEncoding enc;
7065
7066
0
  start[0] = RAW;
7067
0
  start[1] = NXT(1);
7068
0
  start[2] = NXT(2);
7069
0
  start[3] = NXT(3);
7070
0
  enc = xmlDetectCharEncoding(start, 4);
7071
0
  if (enc != XML_CHAR_ENCODING_NONE)
7072
0
      xmlSwitchEncoding(ctxt, enc);
7073
0
    }
7074
7075
0
    if (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) {
7076
0
  xmlParseTextDecl(ctxt);
7077
0
  if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
7078
      /*
7079
       * The XML REC instructs us to stop parsing right here
7080
       */
7081
0
      xmlHaltParser(ctxt);
7082
0
      return;
7083
0
  }
7084
0
    }
7085
0
    if (ctxt->myDoc == NULL) {
7086
0
        ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
7087
0
  if (ctxt->myDoc == NULL) {
7088
0
      xmlErrMemory(ctxt, "New Doc failed");
7089
0
      return;
7090
0
  }
7091
0
  ctxt->myDoc->properties = XML_DOC_INTERNAL;
7092
0
    }
7093
0
    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
7094
0
        xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
7095
7096
0
    ctxt->instate = XML_PARSER_DTD;
7097
0
    ctxt->external = 1;
7098
0
    SKIP_BLANKS;
7099
0
    while (((RAW == '<') && (NXT(1) == '?')) ||
7100
0
           ((RAW == '<') && (NXT(1) == '!')) ||
7101
0
     (RAW == '%')) {
7102
0
  int id = ctxt->input->id;
7103
0
  unsigned long cons = CUR_CONSUMED;
7104
7105
0
  GROW;
7106
0
        if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
7107
0
      xmlParseConditionalSections(ctxt);
7108
0
  } else
7109
0
      xmlParseMarkupDecl(ctxt);
7110
0
        SKIP_BLANKS;
7111
7112
0
  if ((id == ctxt->input->id) && (cons == CUR_CONSUMED)) {
7113
0
      xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
7114
0
      break;
7115
0
  }
7116
0
    }
7117
7118
0
    if (RAW != 0) {
7119
0
  xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
7120
0
    }
7121
7122
0
}
7123
7124
/**
7125
 * xmlParseReference:
7126
 * @ctxt:  an XML parser context
7127
 *
7128
 * DEPRECATED: Internal function, don't use.
7129
 *
7130
 * parse and handle entity references in content, depending on the SAX
7131
 * interface, this may end-up in a call to character() if this is a
7132
 * CharRef, a predefined entity, if there is no reference() callback.
7133
 * or if the parser was asked to switch to that mode.
7134
 *
7135
 * [67] Reference ::= EntityRef | CharRef
7136
 */
7137
void
7138
22.7k
xmlParseReference(xmlParserCtxtPtr ctxt) {
7139
22.7k
    xmlEntityPtr ent;
7140
22.7k
    xmlChar *val;
7141
22.7k
    int was_checked;
7142
22.7k
    xmlNodePtr list = NULL;
7143
22.7k
    xmlParserErrors ret = XML_ERR_OK;
7144
7145
7146
22.7k
    if (RAW != '&')
7147
0
        return;
7148
7149
    /*
7150
     * Simple case of a CharRef
7151
     */
7152
22.7k
    if (NXT(1) == '#') {
7153
22.1k
  int i = 0;
7154
22.1k
  xmlChar out[16];
7155
22.1k
  int hex = NXT(2);
7156
22.1k
  int value = xmlParseCharRef(ctxt);
7157
7158
22.1k
  if (value == 0)
7159
3.79k
      return;
7160
18.3k
  if (ctxt->charset != XML_CHAR_ENCODING_UTF8) {
7161
      /*
7162
       * So we are using non-UTF-8 buffers
7163
       * Check that the char fit on 8bits, if not
7164
       * generate a CharRef.
7165
       */
7166
33
      if (value <= 0xFF) {
7167
33
    out[0] = value;
7168
33
    out[1] = 0;
7169
33
    if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
7170
33
        (!ctxt->disableSAX))
7171
0
        ctxt->sax->characters(ctxt->userData, out, 1);
7172
33
      } else {
7173
0
    if ((hex == 'x') || (hex == 'X'))
7174
0
        snprintf((char *)out, sizeof(out), "#x%X", value);
7175
0
    else
7176
0
        snprintf((char *)out, sizeof(out), "#%d", value);
7177
0
    if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
7178
0
        (!ctxt->disableSAX))
7179
0
        ctxt->sax->reference(ctxt->userData, out);
7180
0
      }
7181
18.2k
  } else {
7182
      /*
7183
       * Just encode the value in UTF-8
7184
       */
7185
18.2k
      COPY_BUF(0 ,out, i, value);
7186
18.2k
      out[i] = 0;
7187
18.2k
      if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
7188
18.2k
    (!ctxt->disableSAX))
7189
18.2k
    ctxt->sax->characters(ctxt->userData, out, i);
7190
18.2k
  }
7191
18.3k
  return;
7192
22.1k
    }
7193
7194
    /*
7195
     * We are seeing an entity reference
7196
     */
7197
663
    ent = xmlParseEntityRef(ctxt);
7198
663
    if (ent == NULL) return;
7199
286
    if (!ctxt->wellFormed)
7200
37
  return;
7201
249
    was_checked = ent->checked;
7202
7203
    /* special case of predefined entities */
7204
249
    if ((ent->name == NULL) ||
7205
249
        (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
7206
120
  val = ent->content;
7207
120
  if (val == NULL) return;
7208
  /*
7209
   * inline the entity.
7210
   */
7211
120
  if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
7212
120
      (!ctxt->disableSAX))
7213
120
      ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
7214
120
  return;
7215
120
    }
7216
7217
    /*
7218
     * The first reference to the entity trigger a parsing phase
7219
     * where the ent->children is filled with the result from
7220
     * the parsing.
7221
     * Note: external parsed entities will not be loaded, it is not
7222
     * required for a non-validating parser, unless the parsing option
7223
     * of validating, or substituting entities were given. Doing so is
7224
     * far more secure as the parser will only process data coming from
7225
     * the document entity by default.
7226
     */
7227
129
    if (((ent->checked == 0) ||
7228
129
         ((ent->children == NULL) && (ctxt->options & XML_PARSE_NOENT))) &&
7229
129
        ((ent->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY) ||
7230
97
         (ctxt->options & (XML_PARSE_NOENT | XML_PARSE_DTDVALID)))) {
7231
97
  unsigned long oldnbent = ctxt->nbentities, diff;
7232
7233
  /*
7234
   * This is a bit hackish but this seems the best
7235
   * way to make sure both SAX and DOM entity support
7236
   * behaves okay.
7237
   */
7238
97
  void *user_data;
7239
97
  if (ctxt->userData == ctxt)
7240
97
      user_data = NULL;
7241
0
  else
7242
0
      user_data = ctxt->userData;
7243
7244
  /*
7245
   * Check that this entity is well formed
7246
   * 4.3.2: An internal general parsed entity is well-formed
7247
   * if its replacement text matches the production labeled
7248
   * content.
7249
   */
7250
97
  if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
7251
97
      ctxt->depth++;
7252
97
      ret = xmlParseBalancedChunkMemoryInternal(ctxt, ent->content,
7253
97
                                                user_data, &list);
7254
97
      ctxt->depth--;
7255
7256
97
  } else if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
7257
0
      ctxt->depth++;
7258
0
      ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt, ctxt->sax,
7259
0
                                     user_data, ctxt->depth, ent->URI,
7260
0
             ent->ExternalID, &list);
7261
0
      ctxt->depth--;
7262
0
  } else {
7263
0
      ret = XML_ERR_ENTITY_PE_INTERNAL;
7264
0
      xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
7265
0
       "invalid entity type found\n", NULL);
7266
0
  }
7267
7268
  /*
7269
   * Store the number of entities needing parsing for this entity
7270
   * content and do checkings
7271
   */
7272
97
        diff = ctxt->nbentities - oldnbent + 1;
7273
97
        if (diff > INT_MAX / 2)
7274
0
            diff = INT_MAX / 2;
7275
97
        ent->checked = diff * 2;
7276
97
  if ((ent->content != NULL) && (xmlStrchr(ent->content, '<')))
7277
43
      ent->checked |= 1;
7278
97
  if (ret == XML_ERR_ENTITY_LOOP) {
7279
0
      xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
7280
0
            xmlHaltParser(ctxt);
7281
0
      xmlFreeNodeList(list);
7282
0
      return;
7283
0
  }
7284
97
  if (xmlParserEntityCheck(ctxt, 0, ent, 0)) {
7285
24
      xmlFreeNodeList(list);
7286
24
      return;
7287
24
  }
7288
7289
73
  if ((ret == XML_ERR_OK) && (list != NULL)) {
7290
0
      if (((ent->etype == XML_INTERNAL_GENERAL_ENTITY) ||
7291
0
       (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY))&&
7292
0
    (ent->children == NULL)) {
7293
0
    ent->children = list;
7294
                /*
7295
                 * Prune it directly in the generated document
7296
                 * except for single text nodes.
7297
                 */
7298
0
                if ((ctxt->replaceEntities == 0) ||
7299
0
                    (ctxt->parseMode == XML_PARSE_READER) ||
7300
0
                    ((list->type == XML_TEXT_NODE) &&
7301
0
                     (list->next == NULL))) {
7302
0
                    ent->owner = 1;
7303
0
                    while (list != NULL) {
7304
0
                        list->parent = (xmlNodePtr) ent;
7305
0
                        if (list->doc != ent->doc)
7306
0
                            xmlSetTreeDoc(list, ent->doc);
7307
0
                        if (list->next == NULL)
7308
0
                            ent->last = list;
7309
0
                        list = list->next;
7310
0
                    }
7311
0
                    list = NULL;
7312
0
                } else {
7313
0
                    ent->owner = 0;
7314
0
                    while (list != NULL) {
7315
0
                        list->parent = (xmlNodePtr) ctxt->node;
7316
0
                        list->doc = ctxt->myDoc;
7317
0
                        if (list->next == NULL)
7318
0
                            ent->last = list;
7319
0
                        list = list->next;
7320
0
                    }
7321
0
                    list = ent->children;
7322
#ifdef LIBXML_LEGACY_ENABLED
7323
                    if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7324
                        xmlAddEntityReference(ent, list, NULL);
7325
#endif /* LIBXML_LEGACY_ENABLED */
7326
0
                }
7327
0
      } else {
7328
0
    xmlFreeNodeList(list);
7329
0
    list = NULL;
7330
0
      }
7331
73
  } else if ((ret != XML_ERR_OK) &&
7332
73
       (ret != XML_WAR_UNDECLARED_ENTITY)) {
7333
73
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7334
73
         "Entity '%s' failed to parse\n", ent->name);
7335
73
            if (ent->content != NULL)
7336
73
                ent->content[0] = 0;
7337
73
      xmlParserEntityCheck(ctxt, 0, ent, 0);
7338
73
  } else if (list != NULL) {
7339
0
      xmlFreeNodeList(list);
7340
0
      list = NULL;
7341
0
  }
7342
73
  if (ent->checked == 0)
7343
0
      ent->checked = 2;
7344
7345
        /* Prevent entity from being parsed and expanded twice (Bug 760367). */
7346
73
        was_checked = 0;
7347
73
    } else if (ent->checked != 1) {
7348
32
  ctxt->nbentities += ent->checked / 2;
7349
32
    }
7350
7351
    /*
7352
     * Now that the entity content has been gathered
7353
     * provide it to the application, this can take different forms based
7354
     * on the parsing modes.
7355
     */
7356
105
    if (ent->children == NULL) {
7357
  /*
7358
   * Probably running in SAX mode and the callbacks don't
7359
   * build the entity content. So unless we already went
7360
   * though parsing for first checking go though the entity
7361
   * content to generate callbacks associated to the entity
7362
   */
7363
105
  if (was_checked != 0) {
7364
32
      void *user_data;
7365
      /*
7366
       * This is a bit hackish but this seems the best
7367
       * way to make sure both SAX and DOM entity support
7368
       * behaves okay.
7369
       */
7370
32
      if (ctxt->userData == ctxt)
7371
32
    user_data = NULL;
7372
0
      else
7373
0
    user_data = ctxt->userData;
7374
7375
32
      if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
7376
32
    ctxt->depth++;
7377
32
    ret = xmlParseBalancedChunkMemoryInternal(ctxt,
7378
32
           ent->content, user_data, NULL);
7379
32
    ctxt->depth--;
7380
32
      } else if (ent->etype ==
7381
0
           XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
7382
0
    ctxt->depth++;
7383
0
    ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt,
7384
0
         ctxt->sax, user_data, ctxt->depth,
7385
0
         ent->URI, ent->ExternalID, NULL);
7386
0
    ctxt->depth--;
7387
0
      } else {
7388
0
    ret = XML_ERR_ENTITY_PE_INTERNAL;
7389
0
    xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
7390
0
           "invalid entity type found\n", NULL);
7391
0
      }
7392
32
      if (ret == XML_ERR_ENTITY_LOOP) {
7393
3
    xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
7394
3
    return;
7395
3
      }
7396
32
  }
7397
102
  if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
7398
102
      (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
7399
      /*
7400
       * Entity reference callback comes second, it's somewhat
7401
       * superfluous but a compatibility to historical behaviour
7402
       */
7403
29
      ctxt->sax->reference(ctxt->userData, ent->name);
7404
29
  }
7405
102
  return;
7406
105
    }
7407
7408
    /*
7409
     * If we didn't get any children for the entity being built
7410
     */
7411
0
    if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
7412
0
  (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
7413
  /*
7414
   * Create a node.
7415
   */
7416
0
  ctxt->sax->reference(ctxt->userData, ent->name);
7417
0
  return;
7418
0
    }
7419
7420
0
    if ((ctxt->replaceEntities) || (ent->children == NULL))  {
7421
  /*
7422
   * There is a problem on the handling of _private for entities
7423
   * (bug 155816): Should we copy the content of the field from
7424
   * the entity (possibly overwriting some value set by the user
7425
   * when a copy is created), should we leave it alone, or should
7426
   * we try to take care of different situations?  The problem
7427
   * is exacerbated by the usage of this field by the xmlReader.
7428
   * To fix this bug, we look at _private on the created node
7429
   * and, if it's NULL, we copy in whatever was in the entity.
7430
   * If it's not NULL we leave it alone.  This is somewhat of a
7431
   * hack - maybe we should have further tests to determine
7432
   * what to do.
7433
   */
7434
0
  if ((ctxt->node != NULL) && (ent->children != NULL)) {
7435
      /*
7436
       * Seems we are generating the DOM content, do
7437
       * a simple tree copy for all references except the first
7438
       * In the first occurrence list contains the replacement.
7439
       */
7440
0
      if (((list == NULL) && (ent->owner == 0)) ||
7441
0
    (ctxt->parseMode == XML_PARSE_READER)) {
7442
0
    xmlNodePtr nw = NULL, cur, firstChild = NULL;
7443
7444
    /*
7445
     * We are copying here, make sure there is no abuse
7446
     */
7447
0
    ctxt->sizeentcopy += ent->length + 5;
7448
0
    if (xmlParserEntityCheck(ctxt, 0, ent, ctxt->sizeentcopy))
7449
0
        return;
7450
7451
    /*
7452
     * when operating on a reader, the entities definitions
7453
     * are always owning the entities subtree.
7454
    if (ctxt->parseMode == XML_PARSE_READER)
7455
        ent->owner = 1;
7456
     */
7457
7458
0
    cur = ent->children;
7459
0
    while (cur != NULL) {
7460
0
        nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
7461
0
        if (nw != NULL) {
7462
0
      if (nw->_private == NULL)
7463
0
          nw->_private = cur->_private;
7464
0
      if (firstChild == NULL){
7465
0
          firstChild = nw;
7466
0
      }
7467
0
      nw = xmlAddChild(ctxt->node, nw);
7468
0
        }
7469
0
        if (cur == ent->last) {
7470
      /*
7471
       * needed to detect some strange empty
7472
       * node cases in the reader tests
7473
       */
7474
0
      if ((ctxt->parseMode == XML_PARSE_READER) &&
7475
0
          (nw != NULL) &&
7476
0
          (nw->type == XML_ELEMENT_NODE) &&
7477
0
          (nw->children == NULL))
7478
0
          nw->extra = 1;
7479
7480
0
      break;
7481
0
        }
7482
0
        cur = cur->next;
7483
0
    }
7484
#ifdef LIBXML_LEGACY_ENABLED
7485
    if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7486
      xmlAddEntityReference(ent, firstChild, nw);
7487
#endif /* LIBXML_LEGACY_ENABLED */
7488
0
      } else if ((list == NULL) || (ctxt->inputNr > 0)) {
7489
0
    xmlNodePtr nw = NULL, cur, next, last,
7490
0
         firstChild = NULL;
7491
7492
    /*
7493
     * We are copying here, make sure there is no abuse
7494
     */
7495
0
    ctxt->sizeentcopy += ent->length + 5;
7496
0
    if (xmlParserEntityCheck(ctxt, 0, ent, ctxt->sizeentcopy))
7497
0
        return;
7498
7499
    /*
7500
     * Copy the entity child list and make it the new
7501
     * entity child list. The goal is to make sure any
7502
     * ID or REF referenced will be the one from the
7503
     * document content and not the entity copy.
7504
     */
7505
0
    cur = ent->children;
7506
0
    ent->children = NULL;
7507
0
    last = ent->last;
7508
0
    ent->last = NULL;
7509
0
    while (cur != NULL) {
7510
0
        next = cur->next;
7511
0
        cur->next = NULL;
7512
0
        cur->parent = NULL;
7513
0
        nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
7514
0
        if (nw != NULL) {
7515
0
      if (nw->_private == NULL)
7516
0
          nw->_private = cur->_private;
7517
0
      if (firstChild == NULL){
7518
0
          firstChild = cur;
7519
0
      }
7520
0
      xmlAddChild((xmlNodePtr) ent, nw);
7521
0
        }
7522
0
        xmlAddChild(ctxt->node, cur);
7523
0
        if (cur == last)
7524
0
      break;
7525
0
        cur = next;
7526
0
    }
7527
0
    if (ent->owner == 0)
7528
0
        ent->owner = 1;
7529
#ifdef LIBXML_LEGACY_ENABLED
7530
    if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7531
      xmlAddEntityReference(ent, firstChild, nw);
7532
#endif /* LIBXML_LEGACY_ENABLED */
7533
0
      } else {
7534
0
    const xmlChar *nbktext;
7535
7536
    /*
7537
     * the name change is to avoid coalescing of the
7538
     * node with a possible previous text one which
7539
     * would make ent->children a dangling pointer
7540
     */
7541
0
    nbktext = xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
7542
0
          -1);
7543
0
    if (ent->children->type == XML_TEXT_NODE)
7544
0
        ent->children->name = nbktext;
7545
0
    if ((ent->last != ent->children) &&
7546
0
        (ent->last->type == XML_TEXT_NODE))
7547
0
        ent->last->name = nbktext;
7548
0
    xmlAddChildList(ctxt->node, ent->children);
7549
0
      }
7550
7551
      /*
7552
       * This is to avoid a nasty side effect, see
7553
       * characters() in SAX.c
7554
       */
7555
0
      ctxt->nodemem = 0;
7556
0
      ctxt->nodelen = 0;
7557
0
      return;
7558
0
  }
7559
0
    }
7560
0
}
7561
7562
/**
7563
 * xmlParseEntityRef:
7564
 * @ctxt:  an XML parser context
7565
 *
7566
 * DEPRECATED: Internal function, don't use.
7567
 *
7568
 * parse ENTITY references declarations
7569
 *
7570
 * [68] EntityRef ::= '&' Name ';'
7571
 *
7572
 * [ WFC: Entity Declared ]
7573
 * In a document without any DTD, a document with only an internal DTD
7574
 * subset which contains no parameter entity references, or a document
7575
 * with "standalone='yes'", the Name given in the entity reference
7576
 * must match that in an entity declaration, except that well-formed
7577
 * documents need not declare any of the following entities: amp, lt,
7578
 * gt, apos, quot.  The declaration of a parameter entity must precede
7579
 * any reference to it.  Similarly, the declaration of a general entity
7580
 * must precede any reference to it which appears in a default value in an
7581
 * attribute-list declaration. Note that if entities are declared in the
7582
 * external subset or in external parameter entities, a non-validating
7583
 * processor is not obligated to read and process their declarations;
7584
 * for such documents, the rule that an entity must be declared is a
7585
 * well-formedness constraint only if standalone='yes'.
7586
 *
7587
 * [ WFC: Parsed Entity ]
7588
 * An entity reference must not contain the name of an unparsed entity
7589
 *
7590
 * Returns the xmlEntityPtr if found, or NULL otherwise.
7591
 */
7592
xmlEntityPtr
7593
4.58k
xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
7594
4.58k
    const xmlChar *name;
7595
4.58k
    xmlEntityPtr ent = NULL;
7596
7597
4.58k
    GROW;
7598
4.58k
    if (ctxt->instate == XML_PARSER_EOF)
7599
0
        return(NULL);
7600
7601
4.58k
    if (RAW != '&')
7602
0
        return(NULL);
7603
4.58k
    NEXT;
7604
4.58k
    name = xmlParseName(ctxt);
7605
4.58k
    if (name == NULL) {
7606
94
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7607
94
           "xmlParseEntityRef: no name\n");
7608
94
        return(NULL);
7609
94
    }
7610
4.49k
    if (RAW != ';') {
7611
117
  xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
7612
117
  return(NULL);
7613
117
    }
7614
4.37k
    NEXT;
7615
7616
    /*
7617
     * Predefined entities override any extra definition
7618
     */
7619
4.37k
    if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
7620
4.37k
        ent = xmlGetPredefinedEntity(name);
7621
4.37k
        if (ent != NULL)
7622
144
            return(ent);
7623
4.37k
    }
7624
7625
    /*
7626
     * Increase the number of entity references parsed
7627
     */
7628
4.23k
    ctxt->nbentities++;
7629
7630
    /*
7631
     * Ask first SAX for entity resolution, otherwise try the
7632
     * entities which may have stored in the parser context.
7633
     */
7634
4.23k
    if (ctxt->sax != NULL) {
7635
4.23k
  if (ctxt->sax->getEntity != NULL)
7636
4.23k
      ent = ctxt->sax->getEntity(ctxt->userData, name);
7637
4.23k
  if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
7638
4.23k
      (ctxt->options & XML_PARSE_OLDSAX))
7639
0
      ent = xmlGetPredefinedEntity(name);
7640
4.23k
  if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
7641
4.23k
      (ctxt->userData==ctxt)) {
7642
0
      ent = xmlSAX2GetEntity(ctxt, name);
7643
0
  }
7644
4.23k
    }
7645
4.23k
    if (ctxt->instate == XML_PARSER_EOF)
7646
0
  return(NULL);
7647
    /*
7648
     * [ WFC: Entity Declared ]
7649
     * In a document without any DTD, a document with only an
7650
     * internal DTD subset which contains no parameter entity
7651
     * references, or a document with "standalone='yes'", the
7652
     * Name given in the entity reference must match that in an
7653
     * entity declaration, except that well-formed documents
7654
     * need not declare any of the following entities: amp, lt,
7655
     * gt, apos, quot.
7656
     * The declaration of a parameter entity must precede any
7657
     * reference to it.
7658
     * Similarly, the declaration of a general entity must
7659
     * precede any reference to it which appears in a default
7660
     * value in an attribute-list declaration. Note that if
7661
     * entities are declared in the external subset or in
7662
     * external parameter entities, a non-validating processor
7663
     * is not obligated to read and process their declarations;
7664
     * for such documents, the rule that an entity must be
7665
     * declared is a well-formedness constraint only if
7666
     * standalone='yes'.
7667
     */
7668
4.23k
    if (ent == NULL) {
7669
253
  if ((ctxt->standalone == 1) ||
7670
253
      ((ctxt->hasExternalSubset == 0) &&
7671
253
       (ctxt->hasPErefs == 0))) {
7672
253
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7673
253
         "Entity '%s' not defined\n", name);
7674
253
  } else {
7675
0
      xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
7676
0
         "Entity '%s' not defined\n", name);
7677
0
      if ((ctxt->inSubset == 0) &&
7678
0
    (ctxt->sax != NULL) &&
7679
0
    (ctxt->sax->reference != NULL)) {
7680
0
    ctxt->sax->reference(ctxt->userData, name);
7681
0
      }
7682
0
  }
7683
253
  xmlParserEntityCheck(ctxt, 0, ent, 0);
7684
253
  ctxt->valid = 0;
7685
253
    }
7686
7687
    /*
7688
     * [ WFC: Parsed Entity ]
7689
     * An entity reference must not contain the name of an
7690
     * unparsed entity
7691
     */
7692
3.97k
    else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
7693
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
7694
0
     "Entity reference to unparsed entity %s\n", name);
7695
0
    }
7696
7697
    /*
7698
     * [ WFC: No External Entity References ]
7699
     * Attribute values cannot contain direct or indirect
7700
     * entity references to external entities.
7701
     */
7702
3.97k
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7703
3.97k
       (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
7704
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
7705
0
       "Attribute references external entity '%s'\n", name);
7706
0
    }
7707
    /*
7708
     * [ WFC: No < in Attribute Values ]
7709
     * The replacement text of any entity referred to directly or
7710
     * indirectly in an attribute value (other than "&lt;") must
7711
     * not contain a <.
7712
     */
7713
3.97k
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7714
3.97k
       (ent != NULL) && 
7715
3.97k
       (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
7716
3.83k
  if (((ent->checked & 1) || (ent->checked == 0)) &&
7717
3.83k
       (ent->content != NULL) && (xmlStrchr(ent->content, '<'))) {
7718
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
7719
0
  "'<' in entity '%s' is not allowed in attributes values\n", name);
7720
0
        }
7721
3.83k
    }
7722
7723
    /*
7724
     * Internal check, no parameter entities here ...
7725
     */
7726
142
    else {
7727
142
  switch (ent->etype) {
7728
0
      case XML_INTERNAL_PARAMETER_ENTITY:
7729
0
      case XML_EXTERNAL_PARAMETER_ENTITY:
7730
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
7731
0
       "Attempt to reference the parameter entity '%s'\n",
7732
0
            name);
7733
0
      break;
7734
142
      default:
7735
142
      break;
7736
142
  }
7737
142
    }
7738
7739
    /*
7740
     * [ WFC: No Recursion ]
7741
     * A parsed entity must not contain a recursive reference
7742
     * to itself, either directly or indirectly.
7743
     * Done somewhere else
7744
     */
7745
4.23k
    return(ent);
7746
4.23k
}
7747
7748
/**
7749
 * xmlParseStringEntityRef:
7750
 * @ctxt:  an XML parser context
7751
 * @str:  a pointer to an index in the string
7752
 *
7753
 * parse ENTITY references declarations, but this version parses it from
7754
 * a string value.
7755
 *
7756
 * [68] EntityRef ::= '&' Name ';'
7757
 *
7758
 * [ WFC: Entity Declared ]
7759
 * In a document without any DTD, a document with only an internal DTD
7760
 * subset which contains no parameter entity references, or a document
7761
 * with "standalone='yes'", the Name given in the entity reference
7762
 * must match that in an entity declaration, except that well-formed
7763
 * documents need not declare any of the following entities: amp, lt,
7764
 * gt, apos, quot.  The declaration of a parameter entity must precede
7765
 * any reference to it.  Similarly, the declaration of a general entity
7766
 * must precede any reference to it which appears in a default value in an
7767
 * attribute-list declaration. Note that if entities are declared in the
7768
 * external subset or in external parameter entities, a non-validating
7769
 * processor is not obligated to read and process their declarations;
7770
 * for such documents, the rule that an entity must be declared is a
7771
 * well-formedness constraint only if standalone='yes'.
7772
 *
7773
 * [ WFC: Parsed Entity ]
7774
 * An entity reference must not contain the name of an unparsed entity
7775
 *
7776
 * Returns the xmlEntityPtr if found, or NULL otherwise. The str pointer
7777
 * is updated to the current location in the string.
7778
 */
7779
static xmlEntityPtr
7780
587
xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
7781
587
    xmlChar *name;
7782
587
    const xmlChar *ptr;
7783
587
    xmlChar cur;
7784
587
    xmlEntityPtr ent = NULL;
7785
7786
587
    if ((str == NULL) || (*str == NULL))
7787
0
        return(NULL);
7788
587
    ptr = *str;
7789
587
    cur = *ptr;
7790
587
    if (cur != '&')
7791
0
  return(NULL);
7792
7793
587
    ptr++;
7794
587
    name = xmlParseStringName(ctxt, &ptr);
7795
587
    if (name == NULL) {
7796
68
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7797
68
           "xmlParseStringEntityRef: no name\n");
7798
68
  *str = ptr;
7799
68
  return(NULL);
7800
68
    }
7801
519
    if (*ptr != ';') {
7802
493
  xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
7803
493
        xmlFree(name);
7804
493
  *str = ptr;
7805
493
  return(NULL);
7806
493
    }
7807
26
    ptr++;
7808
7809
7810
    /*
7811
     * Predefined entities override any extra definition
7812
     */
7813
26
    if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
7814
26
        ent = xmlGetPredefinedEntity(name);
7815
26
        if (ent != NULL) {
7816
0
            xmlFree(name);
7817
0
            *str = ptr;
7818
0
            return(ent);
7819
0
        }
7820
26
    }
7821
7822
    /*
7823
     * Increase the number of entity references parsed
7824
     */
7825
26
    ctxt->nbentities++;
7826
7827
    /*
7828
     * Ask first SAX for entity resolution, otherwise try the
7829
     * entities which may have stored in the parser context.
7830
     */
7831
26
    if (ctxt->sax != NULL) {
7832
26
  if (ctxt->sax->getEntity != NULL)
7833
26
      ent = ctxt->sax->getEntity(ctxt->userData, name);
7834
26
  if ((ent == NULL) && (ctxt->options & XML_PARSE_OLDSAX))
7835
0
      ent = xmlGetPredefinedEntity(name);
7836
26
  if ((ent == NULL) && (ctxt->userData==ctxt)) {
7837
10
      ent = xmlSAX2GetEntity(ctxt, name);
7838
10
  }
7839
26
    }
7840
26
    if (ctxt->instate == XML_PARSER_EOF) {
7841
0
  xmlFree(name);
7842
0
  return(NULL);
7843
0
    }
7844
7845
    /*
7846
     * [ WFC: Entity Declared ]
7847
     * In a document without any DTD, a document with only an
7848
     * internal DTD subset which contains no parameter entity
7849
     * references, or a document with "standalone='yes'", the
7850
     * Name given in the entity reference must match that in an
7851
     * entity declaration, except that well-formed documents
7852
     * need not declare any of the following entities: amp, lt,
7853
     * gt, apos, quot.
7854
     * The declaration of a parameter entity must precede any
7855
     * reference to it.
7856
     * Similarly, the declaration of a general entity must
7857
     * precede any reference to it which appears in a default
7858
     * value in an attribute-list declaration. Note that if
7859
     * entities are declared in the external subset or in
7860
     * external parameter entities, a non-validating processor
7861
     * is not obligated to read and process their declarations;
7862
     * for such documents, the rule that an entity must be
7863
     * declared is a well-formedness constraint only if
7864
     * standalone='yes'.
7865
     */
7866
26
    if (ent == NULL) {
7867
10
  if ((ctxt->standalone == 1) ||
7868
10
      ((ctxt->hasExternalSubset == 0) &&
7869
10
       (ctxt->hasPErefs == 0))) {
7870
10
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7871
10
         "Entity '%s' not defined\n", name);
7872
10
  } else {
7873
0
      xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
7874
0
        "Entity '%s' not defined\n",
7875
0
        name);
7876
0
  }
7877
10
  xmlParserEntityCheck(ctxt, 0, ent, 0);
7878
  /* TODO ? check regressions ctxt->valid = 0; */
7879
10
    }
7880
7881
    /*
7882
     * [ WFC: Parsed Entity ]
7883
     * An entity reference must not contain the name of an
7884
     * unparsed entity
7885
     */
7886
16
    else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
7887
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
7888
0
     "Entity reference to unparsed entity %s\n", name);
7889
0
    }
7890
7891
    /*
7892
     * [ WFC: No External Entity References ]
7893
     * Attribute values cannot contain direct or indirect
7894
     * entity references to external entities.
7895
     */
7896
16
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7897
16
       (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
7898
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
7899
0
   "Attribute references external entity '%s'\n", name);
7900
0
    }
7901
    /*
7902
     * [ WFC: No < in Attribute Values ]
7903
     * The replacement text of any entity referred to directly or
7904
     * indirectly in an attribute value (other than "&lt;") must
7905
     * not contain a <.
7906
     */
7907
16
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7908
16
       (ent != NULL) && (ent->content != NULL) &&
7909
16
       (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
7910
16
       (xmlStrchr(ent->content, '<'))) {
7911
16
  xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
7912
16
     "'<' in entity '%s' is not allowed in attributes values\n",
7913
16
        name);
7914
16
    }
7915
7916
    /*
7917
     * Internal check, no parameter entities here ...
7918
     */
7919
0
    else {
7920
0
  switch (ent->etype) {
7921
0
      case XML_INTERNAL_PARAMETER_ENTITY:
7922
0
      case XML_EXTERNAL_PARAMETER_ENTITY:
7923
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
7924
0
       "Attempt to reference the parameter entity '%s'\n",
7925
0
          name);
7926
0
      break;
7927
0
      default:
7928
0
      break;
7929
0
  }
7930
0
    }
7931
7932
    /*
7933
     * [ WFC: No Recursion ]
7934
     * A parsed entity must not contain a recursive reference
7935
     * to itself, either directly or indirectly.
7936
     * Done somewhere else
7937
     */
7938
7939
26
    xmlFree(name);
7940
26
    *str = ptr;
7941
26
    return(ent);
7942
26
}
7943
7944
/**
7945
 * xmlParsePEReference:
7946
 * @ctxt:  an XML parser context
7947
 *
7948
 * DEPRECATED: Internal function, don't use.
7949
 *
7950
 * parse PEReference declarations
7951
 * The entity content is handled directly by pushing it's content as
7952
 * a new input stream.
7953
 *
7954
 * [69] PEReference ::= '%' Name ';'
7955
 *
7956
 * [ WFC: No Recursion ]
7957
 * A parsed entity must not contain a recursive
7958
 * reference to itself, either directly or indirectly.
7959
 *
7960
 * [ WFC: Entity Declared ]
7961
 * In a document without any DTD, a document with only an internal DTD
7962
 * subset which contains no parameter entity references, or a document
7963
 * with "standalone='yes'", ...  ... The declaration of a parameter
7964
 * entity must precede any reference to it...
7965
 *
7966
 * [ VC: Entity Declared ]
7967
 * In a document with an external subset or external parameter entities
7968
 * with "standalone='no'", ...  ... The declaration of a parameter entity
7969
 * must precede any reference to it...
7970
 *
7971
 * [ WFC: In DTD ]
7972
 * Parameter-entity references may only appear in the DTD.
7973
 * NOTE: misleading but this is handled.
7974
 */
7975
void
7976
xmlParsePEReference(xmlParserCtxtPtr ctxt)
7977
54.8k
{
7978
54.8k
    const xmlChar *name;
7979
54.8k
    xmlEntityPtr entity = NULL;
7980
54.8k
    xmlParserInputPtr input;
7981
7982
54.8k
    if (RAW != '%')
7983
42.6k
        return;
7984
12.2k
    NEXT;
7985
12.2k
    name = xmlParseName(ctxt);
7986
12.2k
    if (name == NULL) {
7987
4.51k
  xmlFatalErrMsg(ctxt, XML_ERR_PEREF_NO_NAME, "PEReference: no name\n");
7988
4.51k
  return;
7989
4.51k
    }
7990
7.71k
    if (xmlParserDebugEntities)
7991
0
  xmlGenericError(xmlGenericErrorContext,
7992
0
    "PEReference: %s\n", name);
7993
7.71k
    if (RAW != ';') {
7994
938
  xmlFatalErr(ctxt, XML_ERR_PEREF_SEMICOL_MISSING, NULL);
7995
938
        return;
7996
938
    }
7997
7998
6.77k
    NEXT;
7999
8000
    /*
8001
     * Increase the number of entity references parsed
8002
     */
8003
6.77k
    ctxt->nbentities++;
8004
8005
    /*
8006
     * Request the entity from SAX
8007
     */
8008
6.77k
    if ((ctxt->sax != NULL) &&
8009
6.77k
  (ctxt->sax->getParameterEntity != NULL))
8010
6.77k
  entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
8011
6.77k
    if (ctxt->instate == XML_PARSER_EOF)
8012
0
  return;
8013
6.77k
    if (entity == NULL) {
8014
  /*
8015
   * [ WFC: Entity Declared ]
8016
   * In a document without any DTD, a document with only an
8017
   * internal DTD subset which contains no parameter entity
8018
   * references, or a document with "standalone='yes'", ...
8019
   * ... The declaration of a parameter entity must precede
8020
   * any reference to it...
8021
   */
8022
0
  if ((ctxt->standalone == 1) ||
8023
0
      ((ctxt->hasExternalSubset == 0) &&
8024
0
       (ctxt->hasPErefs == 0))) {
8025
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
8026
0
            "PEReference: %%%s; not found\n",
8027
0
            name);
8028
0
  } else {
8029
      /*
8030
       * [ VC: Entity Declared ]
8031
       * In a document with an external subset or external
8032
       * parameter entities with "standalone='no'", ...
8033
       * ... The declaration of a parameter entity must
8034
       * precede any reference to it...
8035
       */
8036
0
            if ((ctxt->validate) && (ctxt->vctxt.error != NULL)) {
8037
0
                xmlValidityError(ctxt, XML_WAR_UNDECLARED_ENTITY,
8038
0
                                 "PEReference: %%%s; not found\n",
8039
0
                                 name, NULL);
8040
0
            } else
8041
0
                xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8042
0
                              "PEReference: %%%s; not found\n",
8043
0
                              name, NULL);
8044
0
            ctxt->valid = 0;
8045
0
  }
8046
0
  xmlParserEntityCheck(ctxt, 0, NULL, 0);
8047
6.77k
    } else {
8048
  /*
8049
   * Internal checking in case the entity quest barfed
8050
   */
8051
6.77k
  if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
8052
6.77k
      (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
8053
0
      xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8054
0
      "Internal: %%%s; is not a parameter entity\n",
8055
0
        name, NULL);
8056
6.77k
  } else {
8057
6.77k
            xmlChar start[4];
8058
6.77k
            xmlCharEncoding enc;
8059
8060
6.77k
      if (xmlParserEntityCheck(ctxt, 0, entity, 0))
8061
0
          return;
8062
8063
6.77k
      if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
8064
6.77k
          ((ctxt->options & XML_PARSE_NOENT) == 0) &&
8065
6.77k
    ((ctxt->options & XML_PARSE_DTDVALID) == 0) &&
8066
6.77k
    ((ctxt->options & XML_PARSE_DTDLOAD) == 0) &&
8067
6.77k
    ((ctxt->options & XML_PARSE_DTDATTR) == 0) &&
8068
6.77k
    (ctxt->replaceEntities == 0) &&
8069
6.77k
    (ctxt->validate == 0))
8070
0
    return;
8071
8072
6.77k
      input = xmlNewEntityInputStream(ctxt, entity);
8073
6.77k
      if (xmlPushInput(ctxt, input) < 0) {
8074
0
                xmlFreeInputStream(input);
8075
0
    return;
8076
0
            }
8077
8078
6.77k
      if (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) {
8079
                /*
8080
                 * Get the 4 first bytes and decode the charset
8081
                 * if enc != XML_CHAR_ENCODING_NONE
8082
                 * plug some encoding conversion routines.
8083
                 * Note that, since we may have some non-UTF8
8084
                 * encoding (like UTF16, bug 135229), the 'length'
8085
                 * is not known, but we can calculate based upon
8086
                 * the amount of data in the buffer.
8087
                 */
8088
0
                GROW
8089
0
                if (ctxt->instate == XML_PARSER_EOF)
8090
0
                    return;
8091
0
                if ((ctxt->input->end - ctxt->input->cur)>=4) {
8092
0
                    start[0] = RAW;
8093
0
                    start[1] = NXT(1);
8094
0
                    start[2] = NXT(2);
8095
0
                    start[3] = NXT(3);
8096
0
                    enc = xmlDetectCharEncoding(start, 4);
8097
0
                    if (enc != XML_CHAR_ENCODING_NONE) {
8098
0
                        xmlSwitchEncoding(ctxt, enc);
8099
0
                    }
8100
0
                }
8101
8102
0
                if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) &&
8103
0
                    (IS_BLANK_CH(NXT(5)))) {
8104
0
                    xmlParseTextDecl(ctxt);
8105
0
                }
8106
0
            }
8107
6.77k
  }
8108
6.77k
    }
8109
6.77k
    ctxt->hasPErefs = 1;
8110
6.77k
}
8111
8112
/**
8113
 * xmlLoadEntityContent:
8114
 * @ctxt:  an XML parser context
8115
 * @entity: an unloaded system entity
8116
 *
8117
 * Load the original content of the given system entity from the
8118
 * ExternalID/SystemID given. This is to be used for Included in Literal
8119
 * http://www.w3.org/TR/REC-xml/#inliteral processing of entities references
8120
 *
8121
 * Returns 0 in case of success and -1 in case of failure
8122
 */
8123
static int
8124
0
xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
8125
0
    xmlParserInputPtr input;
8126
0
    xmlBufferPtr buf;
8127
0
    int l, c;
8128
0
    int count = 0;
8129
8130
0
    if ((ctxt == NULL) || (entity == NULL) ||
8131
0
        ((entity->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
8132
0
   (entity->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY)) ||
8133
0
  (entity->content != NULL)) {
8134
0
  xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8135
0
              "xmlLoadEntityContent parameter error");
8136
0
        return(-1);
8137
0
    }
8138
8139
0
    if (xmlParserDebugEntities)
8140
0
  xmlGenericError(xmlGenericErrorContext,
8141
0
    "Reading %s entity content input\n", entity->name);
8142
8143
0
    buf = xmlBufferCreate();
8144
0
    if (buf == NULL) {
8145
0
  xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8146
0
              "xmlLoadEntityContent parameter error");
8147
0
        return(-1);
8148
0
    }
8149
0
    xmlBufferSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);
8150
8151
0
    input = xmlNewEntityInputStream(ctxt, entity);
8152
0
    if (input == NULL) {
8153
0
  xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8154
0
              "xmlLoadEntityContent input error");
8155
0
  xmlBufferFree(buf);
8156
0
        return(-1);
8157
0
    }
8158
8159
    /*
8160
     * Push the entity as the current input, read char by char
8161
     * saving to the buffer until the end of the entity or an error
8162
     */
8163
0
    if (xmlPushInput(ctxt, input) < 0) {
8164
0
        xmlBufferFree(buf);
8165
0
  xmlFreeInputStream(input);
8166
0
  return(-1);
8167
0
    }
8168
8169
0
    GROW;
8170
0
    c = CUR_CHAR(l);
8171
0
    while ((ctxt->input == input) && (ctxt->input->cur < ctxt->input->end) &&
8172
0
           (IS_CHAR(c))) {
8173
0
        xmlBufferAdd(buf, ctxt->input->cur, l);
8174
0
  if (count++ > XML_PARSER_CHUNK_SIZE) {
8175
0
      count = 0;
8176
0
      GROW;
8177
0
            if (ctxt->instate == XML_PARSER_EOF) {
8178
0
                xmlBufferFree(buf);
8179
0
                return(-1);
8180
0
            }
8181
0
  }
8182
0
  NEXTL(l);
8183
0
  c = CUR_CHAR(l);
8184
0
  if (c == 0) {
8185
0
      count = 0;
8186
0
      GROW;
8187
0
            if (ctxt->instate == XML_PARSER_EOF) {
8188
0
                xmlBufferFree(buf);
8189
0
                return(-1);
8190
0
            }
8191
0
      c = CUR_CHAR(l);
8192
0
  }
8193
0
    }
8194
8195
0
    if ((ctxt->input == input) && (ctxt->input->cur >= ctxt->input->end)) {
8196
0
        xmlPopInput(ctxt);
8197
0
    } else if (!IS_CHAR(c)) {
8198
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
8199
0
                          "xmlLoadEntityContent: invalid char value %d\n",
8200
0
                    c);
8201
0
  xmlBufferFree(buf);
8202
0
  return(-1);
8203
0
    }
8204
0
    entity->content = buf->content;
8205
0
    buf->content = NULL;
8206
0
    xmlBufferFree(buf);
8207
8208
0
    return(0);
8209
0
}
8210
8211
/**
8212
 * xmlParseStringPEReference:
8213
 * @ctxt:  an XML parser context
8214
 * @str:  a pointer to an index in the string
8215
 *
8216
 * parse PEReference declarations
8217
 *
8218
 * [69] PEReference ::= '%' Name ';'
8219
 *
8220
 * [ WFC: No Recursion ]
8221
 * A parsed entity must not contain a recursive
8222
 * reference to itself, either directly or indirectly.
8223
 *
8224
 * [ WFC: Entity Declared ]
8225
 * In a document without any DTD, a document with only an internal DTD
8226
 * subset which contains no parameter entity references, or a document
8227
 * with "standalone='yes'", ...  ... The declaration of a parameter
8228
 * entity must precede any reference to it...
8229
 *
8230
 * [ VC: Entity Declared ]
8231
 * In a document with an external subset or external parameter entities
8232
 * with "standalone='no'", ...  ... The declaration of a parameter entity
8233
 * must precede any reference to it...
8234
 *
8235
 * [ WFC: In DTD ]
8236
 * Parameter-entity references may only appear in the DTD.
8237
 * NOTE: misleading but this is handled.
8238
 *
8239
 * Returns the string of the entity content.
8240
 *         str is updated to the current value of the index
8241
 */
8242
static xmlEntityPtr
8243
0
xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
8244
0
    const xmlChar *ptr;
8245
0
    xmlChar cur;
8246
0
    xmlChar *name;
8247
0
    xmlEntityPtr entity = NULL;
8248
8249
0
    if ((str == NULL) || (*str == NULL)) return(NULL);
8250
0
    ptr = *str;
8251
0
    cur = *ptr;
8252
0
    if (cur != '%')
8253
0
        return(NULL);
8254
0
    ptr++;
8255
0
    name = xmlParseStringName(ctxt, &ptr);
8256
0
    if (name == NULL) {
8257
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8258
0
           "xmlParseStringPEReference: no name\n");
8259
0
  *str = ptr;
8260
0
  return(NULL);
8261
0
    }
8262
0
    cur = *ptr;
8263
0
    if (cur != ';') {
8264
0
  xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
8265
0
  xmlFree(name);
8266
0
  *str = ptr;
8267
0
  return(NULL);
8268
0
    }
8269
0
    ptr++;
8270
8271
    /*
8272
     * Increase the number of entity references parsed
8273
     */
8274
0
    ctxt->nbentities++;
8275
8276
    /*
8277
     * Request the entity from SAX
8278
     */
8279
0
    if ((ctxt->sax != NULL) &&
8280
0
  (ctxt->sax->getParameterEntity != NULL))
8281
0
  entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
8282
0
    if (ctxt->instate == XML_PARSER_EOF) {
8283
0
  xmlFree(name);
8284
0
  *str = ptr;
8285
0
  return(NULL);
8286
0
    }
8287
0
    if (entity == NULL) {
8288
  /*
8289
   * [ WFC: Entity Declared ]
8290
   * In a document without any DTD, a document with only an
8291
   * internal DTD subset which contains no parameter entity
8292
   * references, or a document with "standalone='yes'", ...
8293
   * ... The declaration of a parameter entity must precede
8294
   * any reference to it...
8295
   */
8296
0
  if ((ctxt->standalone == 1) ||
8297
0
      ((ctxt->hasExternalSubset == 0) && (ctxt->hasPErefs == 0))) {
8298
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
8299
0
     "PEReference: %%%s; not found\n", name);
8300
0
  } else {
8301
      /*
8302
       * [ VC: Entity Declared ]
8303
       * In a document with an external subset or external
8304
       * parameter entities with "standalone='no'", ...
8305
       * ... The declaration of a parameter entity must
8306
       * precede any reference to it...
8307
       */
8308
0
      xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8309
0
        "PEReference: %%%s; not found\n",
8310
0
        name, NULL);
8311
0
      ctxt->valid = 0;
8312
0
  }
8313
0
  xmlParserEntityCheck(ctxt, 0, NULL, 0);
8314
0
    } else {
8315
  /*
8316
   * Internal checking in case the entity quest barfed
8317
   */
8318
0
  if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
8319
0
      (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
8320
0
      xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8321
0
        "%%%s; is not a parameter entity\n",
8322
0
        name, NULL);
8323
0
  }
8324
0
    }
8325
0
    ctxt->hasPErefs = 1;
8326
0
    xmlFree(name);
8327
0
    *str = ptr;
8328
0
    return(entity);
8329
0
}
8330
8331
/**
8332
 * xmlParseDocTypeDecl:
8333
 * @ctxt:  an XML parser context
8334
 *
8335
 * DEPRECATED: Internal function, don't use.
8336
 *
8337
 * parse a DOCTYPE declaration
8338
 *
8339
 * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
8340
 *                      ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
8341
 *
8342
 * [ VC: Root Element Type ]
8343
 * The Name in the document type declaration must match the element
8344
 * type of the root element.
8345
 */
8346
8347
void
8348
103
xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
8349
103
    const xmlChar *name = NULL;
8350
103
    xmlChar *ExternalID = NULL;
8351
103
    xmlChar *URI = NULL;
8352
8353
    /*
8354
     * We know that '<!DOCTYPE' has been detected.
8355
     */
8356
103
    SKIP(9);
8357
8358
103
    SKIP_BLANKS;
8359
8360
    /*
8361
     * Parse the DOCTYPE name.
8362
     */
8363
103
    name = xmlParseName(ctxt);
8364
103
    if (name == NULL) {
8365
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8366
0
           "xmlParseDocTypeDecl : no DOCTYPE name !\n");
8367
0
    }
8368
103
    ctxt->intSubName = name;
8369
8370
103
    SKIP_BLANKS;
8371
8372
    /*
8373
     * Check for SystemID and ExternalID
8374
     */
8375
103
    URI = xmlParseExternalID(ctxt, &ExternalID, 1);
8376
8377
103
    if ((URI != NULL) || (ExternalID != NULL)) {
8378
2
        ctxt->hasExternalSubset = 1;
8379
2
    }
8380
103
    ctxt->extSubURI = URI;
8381
103
    ctxt->extSubSystem = ExternalID;
8382
8383
103
    SKIP_BLANKS;
8384
8385
    /*
8386
     * Create and update the internal subset.
8387
     */
8388
103
    if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL) &&
8389
103
  (!ctxt->disableSAX))
8390
80
  ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
8391
103
    if (ctxt->instate == XML_PARSER_EOF)
8392
0
  return;
8393
8394
    /*
8395
     * Is there any internal subset declarations ?
8396
     * they are handled separately in xmlParseInternalSubset()
8397
     */
8398
103
    if (RAW == '[')
8399
102
  return;
8400
8401
    /*
8402
     * We should be at the end of the DOCTYPE declaration.
8403
     */
8404
1
    if (RAW != '>') {
8405
1
  xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
8406
1
    }
8407
1
    NEXT;
8408
1
}
8409
8410
/**
8411
 * xmlParseInternalSubset:
8412
 * @ctxt:  an XML parser context
8413
 *
8414
 * parse the internal subset declaration
8415
 *
8416
 * [28 end] ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
8417
 */
8418
8419
static void
8420
102
xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
8421
    /*
8422
     * Is there any DTD definition ?
8423
     */
8424
102
    if (RAW == '[') {
8425
102
        int baseInputNr = ctxt->inputNr;
8426
102
        ctxt->instate = XML_PARSER_DTD;
8427
102
        NEXT;
8428
  /*
8429
   * Parse the succession of Markup declarations and
8430
   * PEReferences.
8431
   * Subsequence (markupdecl | PEReference | S)*
8432
   */
8433
48.1k
  while (((RAW != ']') || (ctxt->inputNr > baseInputNr)) &&
8434
48.1k
               (ctxt->instate != XML_PARSER_EOF)) {
8435
48.1k
      int id = ctxt->input->id;
8436
48.1k
      unsigned long cons = CUR_CONSUMED;
8437
8438
48.1k
      SKIP_BLANKS;
8439
48.1k
      xmlParseMarkupDecl(ctxt);
8440
48.1k
      xmlParsePEReference(ctxt);
8441
8442
            /*
8443
             * Conditional sections are allowed from external entities included
8444
             * by PE References in the internal subset.
8445
             */
8446
48.1k
            if ((ctxt->inputNr > 1) && (ctxt->input->filename != NULL) &&
8447
48.1k
                (RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
8448
0
                xmlParseConditionalSections(ctxt);
8449
0
            }
8450
8451
48.1k
      if ((id == ctxt->input->id) && (cons == CUR_CONSUMED)) {
8452
38
    xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8453
38
       "xmlParseInternalSubset: error detected in Markup declaration\n");
8454
38
                if (ctxt->inputNr > baseInputNr)
8455
0
                    xmlPopInput(ctxt);
8456
38
                else
8457
38
        break;
8458
38
      }
8459
48.1k
  }
8460
102
  if (RAW == ']') {
8461
56
      NEXT;
8462
56
      SKIP_BLANKS;
8463
56
  }
8464
102
    }
8465
8466
    /*
8467
     * We should be at the end of the DOCTYPE declaration.
8468
     */
8469
102
    if (RAW != '>') {
8470
46
  xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
8471
46
  return;
8472
46
    }
8473
56
    NEXT;
8474
56
}
8475
8476
#ifdef LIBXML_SAX1_ENABLED
8477
/**
8478
 * xmlParseAttribute:
8479
 * @ctxt:  an XML parser context
8480
 * @value:  a xmlChar ** used to store the value of the attribute
8481
 *
8482
 * DEPRECATED: Internal function, don't use.
8483
 *
8484
 * parse an attribute
8485
 *
8486
 * [41] Attribute ::= Name Eq AttValue
8487
 *
8488
 * [ WFC: No External Entity References ]
8489
 * Attribute values cannot contain direct or indirect entity references
8490
 * to external entities.
8491
 *
8492
 * [ WFC: No < in Attribute Values ]
8493
 * The replacement text of any entity referred to directly or indirectly in
8494
 * an attribute value (other than "&lt;") must not contain a <.
8495
 *
8496
 * [ VC: Attribute Value Type ]
8497
 * The attribute must have been declared; the value must be of the type
8498
 * declared for it.
8499
 *
8500
 * [25] Eq ::= S? '=' S?
8501
 *
8502
 * With namespace:
8503
 *
8504
 * [NS 11] Attribute ::= QName Eq AttValue
8505
 *
8506
 * Also the case QName == xmlns:??? is handled independently as a namespace
8507
 * definition.
8508
 *
8509
 * Returns the attribute name, and the value in *value.
8510
 */
8511
8512
const xmlChar *
8513
xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
8514
    const xmlChar *name;
8515
    xmlChar *val;
8516
8517
    *value = NULL;
8518
    GROW;
8519
    name = xmlParseName(ctxt);
8520
    if (name == NULL) {
8521
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8522
                 "error parsing attribute name\n");
8523
        return(NULL);
8524
    }
8525
8526
    /*
8527
     * read the value
8528
     */
8529
    SKIP_BLANKS;
8530
    if (RAW == '=') {
8531
        NEXT;
8532
  SKIP_BLANKS;
8533
  val = xmlParseAttValue(ctxt);
8534
  ctxt->instate = XML_PARSER_CONTENT;
8535
    } else {
8536
  xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
8537
         "Specification mandates value for attribute %s\n", name);
8538
  return(NULL);
8539
    }
8540
8541
    /*
8542
     * Check that xml:lang conforms to the specification
8543
     * No more registered as an error, just generate a warning now
8544
     * since this was deprecated in XML second edition
8545
     */
8546
    if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "xml:lang"))) {
8547
  if (!xmlCheckLanguageID(val)) {
8548
      xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
8549
              "Malformed value for xml:lang : %s\n",
8550
        val, NULL);
8551
  }
8552
    }
8553
8554
    /*
8555
     * Check that xml:space conforms to the specification
8556
     */
8557
    if (xmlStrEqual(name, BAD_CAST "xml:space")) {
8558
  if (xmlStrEqual(val, BAD_CAST "default"))
8559
      *(ctxt->space) = 0;
8560
  else if (xmlStrEqual(val, BAD_CAST "preserve"))
8561
      *(ctxt->space) = 1;
8562
  else {
8563
    xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
8564
"Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
8565
                                 val, NULL);
8566
  }
8567
    }
8568
8569
    *value = val;
8570
    return(name);
8571
}
8572
8573
/**
8574
 * xmlParseStartTag:
8575
 * @ctxt:  an XML parser context
8576
 *
8577
 * DEPRECATED: Internal function, don't use.
8578
 *
8579
 * parse a start of tag either for rule element or
8580
 * EmptyElement. In both case we don't parse the tag closing chars.
8581
 *
8582
 * [40] STag ::= '<' Name (S Attribute)* S? '>'
8583
 *
8584
 * [ WFC: Unique Att Spec ]
8585
 * No attribute name may appear more than once in the same start-tag or
8586
 * empty-element tag.
8587
 *
8588
 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
8589
 *
8590
 * [ WFC: Unique Att Spec ]
8591
 * No attribute name may appear more than once in the same start-tag or
8592
 * empty-element tag.
8593
 *
8594
 * With namespace:
8595
 *
8596
 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
8597
 *
8598
 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
8599
 *
8600
 * Returns the element name parsed
8601
 */
8602
8603
const xmlChar *
8604
xmlParseStartTag(xmlParserCtxtPtr ctxt) {
8605
    const xmlChar *name;
8606
    const xmlChar *attname;
8607
    xmlChar *attvalue;
8608
    const xmlChar **atts = ctxt->atts;
8609
    int nbatts = 0;
8610
    int maxatts = ctxt->maxatts;
8611
    int i;
8612
8613
    if (RAW != '<') return(NULL);
8614
    NEXT1;
8615
8616
    name = xmlParseName(ctxt);
8617
    if (name == NULL) {
8618
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8619
       "xmlParseStartTag: invalid element name\n");
8620
        return(NULL);
8621
    }
8622
8623
    /*
8624
     * Now parse the attributes, it ends up with the ending
8625
     *
8626
     * (S Attribute)* S?
8627
     */
8628
    SKIP_BLANKS;
8629
    GROW;
8630
8631
    while (((RAW != '>') &&
8632
     ((RAW != '/') || (NXT(1) != '>')) &&
8633
     (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) {
8634
        int id = ctxt->input->id;
8635
  unsigned long cons = CUR_CONSUMED;
8636
8637
  attname = xmlParseAttribute(ctxt, &attvalue);
8638
        if ((attname != NULL) && (attvalue != NULL)) {
8639
      /*
8640
       * [ WFC: Unique Att Spec ]
8641
       * No attribute name may appear more than once in the same
8642
       * start-tag or empty-element tag.
8643
       */
8644
      for (i = 0; i < nbatts;i += 2) {
8645
          if (xmlStrEqual(atts[i], attname)) {
8646
        xmlErrAttributeDup(ctxt, NULL, attname);
8647
        xmlFree(attvalue);
8648
        goto failed;
8649
    }
8650
      }
8651
      /*
8652
       * Add the pair to atts
8653
       */
8654
      if (atts == NULL) {
8655
          maxatts = 22; /* allow for 10 attrs by default */
8656
          atts = (const xmlChar **)
8657
           xmlMalloc(maxatts * sizeof(xmlChar *));
8658
    if (atts == NULL) {
8659
        xmlErrMemory(ctxt, NULL);
8660
        if (attvalue != NULL)
8661
      xmlFree(attvalue);
8662
        goto failed;
8663
    }
8664
    ctxt->atts = atts;
8665
    ctxt->maxatts = maxatts;
8666
      } else if (nbatts + 4 > maxatts) {
8667
          const xmlChar **n;
8668
8669
          maxatts *= 2;
8670
          n = (const xmlChar **) xmlRealloc((void *) atts,
8671
               maxatts * sizeof(const xmlChar *));
8672
    if (n == NULL) {
8673
        xmlErrMemory(ctxt, NULL);
8674
        if (attvalue != NULL)
8675
      xmlFree(attvalue);
8676
        goto failed;
8677
    }
8678
    atts = n;
8679
    ctxt->atts = atts;
8680
    ctxt->maxatts = maxatts;
8681
      }
8682
      atts[nbatts++] = attname;
8683
      atts[nbatts++] = attvalue;
8684
      atts[nbatts] = NULL;
8685
      atts[nbatts + 1] = NULL;
8686
  } else {
8687
      if (attvalue != NULL)
8688
    xmlFree(attvalue);
8689
  }
8690
8691
failed:
8692
8693
  GROW
8694
  if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
8695
      break;
8696
  if (SKIP_BLANKS == 0) {
8697
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
8698
         "attributes construct error\n");
8699
  }
8700
        if ((cons == CUR_CONSUMED) && (id == ctxt->input->id) &&
8701
            (attname == NULL) && (attvalue == NULL)) {
8702
      xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
8703
         "xmlParseStartTag: problem parsing attributes\n");
8704
      break;
8705
  }
8706
  SHRINK;
8707
        GROW;
8708
    }
8709
8710
    /*
8711
     * SAX: Start of Element !
8712
     */
8713
    if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL) &&
8714
  (!ctxt->disableSAX)) {
8715
  if (nbatts > 0)
8716
      ctxt->sax->startElement(ctxt->userData, name, atts);
8717
  else
8718
      ctxt->sax->startElement(ctxt->userData, name, NULL);
8719
    }
8720
8721
    if (atts != NULL) {
8722
        /* Free only the content strings */
8723
        for (i = 1;i < nbatts;i+=2)
8724
      if (atts[i] != NULL)
8725
         xmlFree((xmlChar *) atts[i]);
8726
    }
8727
    return(name);
8728
}
8729
8730
/**
8731
 * xmlParseEndTag1:
8732
 * @ctxt:  an XML parser context
8733
 * @line:  line of the start tag
8734
 * @nsNr:  number of namespaces on the start tag
8735
 *
8736
 * parse an end of tag
8737
 *
8738
 * [42] ETag ::= '</' Name S? '>'
8739
 *
8740
 * With namespace
8741
 *
8742
 * [NS 9] ETag ::= '</' QName S? '>'
8743
 */
8744
8745
static void
8746
xmlParseEndTag1(xmlParserCtxtPtr ctxt, int line) {
8747
    const xmlChar *name;
8748
8749
    GROW;
8750
    if ((RAW != '<') || (NXT(1) != '/')) {
8751
  xmlFatalErrMsg(ctxt, XML_ERR_LTSLASH_REQUIRED,
8752
           "xmlParseEndTag: '</' not found\n");
8753
  return;
8754
    }
8755
    SKIP(2);
8756
8757
    name = xmlParseNameAndCompare(ctxt,ctxt->name);
8758
8759
    /*
8760
     * We should definitely be at the ending "S? '>'" part
8761
     */
8762
    GROW;
8763
    SKIP_BLANKS;
8764
    if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
8765
  xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
8766
    } else
8767
  NEXT1;
8768
8769
    /*
8770
     * [ WFC: Element Type Match ]
8771
     * The Name in an element's end-tag must match the element type in the
8772
     * start-tag.
8773
     *
8774
     */
8775
    if (name != (xmlChar*)1) {
8776
        if (name == NULL) name = BAD_CAST "unparsable";
8777
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
8778
         "Opening and ending tag mismatch: %s line %d and %s\n",
8779
                    ctxt->name, line, name);
8780
    }
8781
8782
    /*
8783
     * SAX: End of Tag
8784
     */
8785
    if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
8786
  (!ctxt->disableSAX))
8787
        ctxt->sax->endElement(ctxt->userData, ctxt->name);
8788
8789
    namePop(ctxt);
8790
    spacePop(ctxt);
8791
    return;
8792
}
8793
8794
/**
8795
 * xmlParseEndTag:
8796
 * @ctxt:  an XML parser context
8797
 *
8798
 * DEPRECATED: Internal function, don't use.
8799
 *
8800
 * parse an end of tag
8801
 *
8802
 * [42] ETag ::= '</' Name S? '>'
8803
 *
8804
 * With namespace
8805
 *
8806
 * [NS 9] ETag ::= '</' QName S? '>'
8807
 */
8808
8809
void
8810
xmlParseEndTag(xmlParserCtxtPtr ctxt) {
8811
    xmlParseEndTag1(ctxt, 0);
8812
}
8813
#endif /* LIBXML_SAX1_ENABLED */
8814
8815
/************************************************************************
8816
 *                  *
8817
 *          SAX 2 specific operations       *
8818
 *                  *
8819
 ************************************************************************/
8820
8821
/*
8822
 * xmlGetNamespace:
8823
 * @ctxt:  an XML parser context
8824
 * @prefix:  the prefix to lookup
8825
 *
8826
 * Lookup the namespace name for the @prefix (which ca be NULL)
8827
 * The prefix must come from the @ctxt->dict dictionary
8828
 *
8829
 * Returns the namespace name or NULL if not bound
8830
 */
8831
static const xmlChar *
8832
127k
xmlGetNamespace(xmlParserCtxtPtr ctxt, const xmlChar *prefix) {
8833
127k
    int i;
8834
8835
127k
    if (prefix == ctxt->str_xml) return(ctxt->str_xml_ns);
8836
238k
    for (i = ctxt->nsNr - 2;i >= 0;i-=2)
8837
168k
        if (ctxt->nsTab[i] == prefix) {
8838
56.5k
      if ((prefix == NULL) && (*ctxt->nsTab[i + 1] == 0))
8839
130
          return(NULL);
8840
56.4k
      return(ctxt->nsTab[i + 1]);
8841
56.5k
  }
8842
70.0k
    return(NULL);
8843
126k
}
8844
8845
/**
8846
 * xmlParseQName:
8847
 * @ctxt:  an XML parser context
8848
 * @prefix:  pointer to store the prefix part
8849
 *
8850
 * parse an XML Namespace QName
8851
 *
8852
 * [6]  QName  ::= (Prefix ':')? LocalPart
8853
 * [7]  Prefix  ::= NCName
8854
 * [8]  LocalPart  ::= NCName
8855
 *
8856
 * Returns the Name parsed or NULL
8857
 */
8858
8859
static const xmlChar *
8860
229k
xmlParseQName(xmlParserCtxtPtr ctxt, const xmlChar **prefix) {
8861
229k
    const xmlChar *l, *p;
8862
8863
229k
    GROW;
8864
8865
229k
    l = xmlParseNCName(ctxt);
8866
229k
    if (l == NULL) {
8867
12.2k
        if (CUR == ':') {
8868
335
      l = xmlParseName(ctxt);
8869
335
      if (l != NULL) {
8870
72
          xmlNsErr(ctxt, XML_NS_ERR_QNAME,
8871
72
             "Failed to parse QName '%s'\n", l, NULL, NULL);
8872
72
    *prefix = NULL;
8873
72
    return(l);
8874
72
      }
8875
335
  }
8876
12.1k
        return(NULL);
8877
12.2k
    }
8878
217k
    if (CUR == ':') {
8879
59.7k
        NEXT;
8880
59.7k
  p = l;
8881
59.7k
  l = xmlParseNCName(ctxt);
8882
59.7k
  if (l == NULL) {
8883
373
      xmlChar *tmp;
8884
8885
373
            if (ctxt->instate == XML_PARSER_EOF)
8886
0
                return(NULL);
8887
373
            xmlNsErr(ctxt, XML_NS_ERR_QNAME,
8888
373
               "Failed to parse QName '%s:'\n", p, NULL, NULL);
8889
373
      l = xmlParseNmtoken(ctxt);
8890
373
      if (l == NULL) {
8891
90
                if (ctxt->instate == XML_PARSER_EOF)
8892
0
                    return(NULL);
8893
90
    tmp = xmlBuildQName(BAD_CAST "", p, NULL, 0);
8894
283
            } else {
8895
283
    tmp = xmlBuildQName(l, p, NULL, 0);
8896
283
    xmlFree((char *)l);
8897
283
      }
8898
373
      p = xmlDictLookup(ctxt->dict, tmp, -1);
8899
373
      if (tmp != NULL) xmlFree(tmp);
8900
373
      *prefix = NULL;
8901
373
      return(p);
8902
373
  }
8903
59.4k
  if (CUR == ':') {
8904
432
      xmlChar *tmp;
8905
8906
432
            xmlNsErr(ctxt, XML_NS_ERR_QNAME,
8907
432
               "Failed to parse QName '%s:%s:'\n", p, l, NULL);
8908
432
      NEXT;
8909
432
      tmp = (xmlChar *) xmlParseName(ctxt);
8910
432
      if (tmp != NULL) {
8911
429
          tmp = xmlBuildQName(tmp, l, NULL, 0);
8912
429
    l = xmlDictLookup(ctxt->dict, tmp, -1);
8913
429
    if (tmp != NULL) xmlFree(tmp);
8914
429
    *prefix = p;
8915
429
    return(l);
8916
429
      }
8917
3
            if (ctxt->instate == XML_PARSER_EOF)
8918
0
                return(NULL);
8919
3
      tmp = xmlBuildQName(BAD_CAST "", l, NULL, 0);
8920
3
      l = xmlDictLookup(ctxt->dict, tmp, -1);
8921
3
      if (tmp != NULL) xmlFree(tmp);
8922
3
      *prefix = p;
8923
3
      return(l);
8924
3
  }
8925
58.9k
  *prefix = p;
8926
58.9k
    } else
8927
157k
        *prefix = NULL;
8928
216k
    return(l);
8929
217k
}
8930
8931
/**
8932
 * xmlParseQNameAndCompare:
8933
 * @ctxt:  an XML parser context
8934
 * @name:  the localname
8935
 * @prefix:  the prefix, if any.
8936
 *
8937
 * parse an XML name and compares for match
8938
 * (specialized for endtag parsing)
8939
 *
8940
 * Returns NULL for an illegal name, (xmlChar*) 1 for success
8941
 * and the name for mismatch
8942
 */
8943
8944
static const xmlChar *
8945
xmlParseQNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *name,
8946
6.37k
                        xmlChar const *prefix) {
8947
6.37k
    const xmlChar *cmp;
8948
6.37k
    const xmlChar *in;
8949
6.37k
    const xmlChar *ret;
8950
6.37k
    const xmlChar *prefix2;
8951
8952
6.37k
    if (prefix == NULL) return(xmlParseNameAndCompare(ctxt, name));
8953
8954
6.37k
    GROW;
8955
6.37k
    in = ctxt->input->cur;
8956
8957
6.37k
    cmp = prefix;
8958
12.7k
    while (*in != 0 && *in == *cmp) {
8959
6.35k
  ++in;
8960
6.35k
  ++cmp;
8961
6.35k
    }
8962
6.37k
    if ((*cmp == 0) && (*in == ':')) {
8963
6.35k
        in++;
8964
6.35k
  cmp = name;
8965
53.4k
  while (*in != 0 && *in == *cmp) {
8966
47.0k
      ++in;
8967
47.0k
      ++cmp;
8968
47.0k
  }
8969
6.35k
  if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
8970
      /* success */
8971
6.30k
            ctxt->input->col += in - ctxt->input->cur;
8972
6.30k
      ctxt->input->cur = in;
8973
6.30k
      return((const xmlChar*) 1);
8974
6.30k
  }
8975
6.35k
    }
8976
    /*
8977
     * all strings coms from the dictionary, equality can be done directly
8978
     */
8979
74
    ret = xmlParseQName (ctxt, &prefix2);
8980
74
    if ((ret == name) && (prefix == prefix2))
8981
0
  return((const xmlChar*) 1);
8982
74
    return ret;
8983
74
}
8984
8985
/**
8986
 * xmlParseAttValueInternal:
8987
 * @ctxt:  an XML parser context
8988
 * @len:  attribute len result
8989
 * @alloc:  whether the attribute was reallocated as a new string
8990
 * @normalize:  if 1 then further non-CDATA normalization must be done
8991
 *
8992
 * parse a value for an attribute.
8993
 * NOTE: if no normalization is needed, the routine will return pointers
8994
 *       directly from the data buffer.
8995
 *
8996
 * 3.3.3 Attribute-Value Normalization:
8997
 * Before the value of an attribute is passed to the application or
8998
 * checked for validity, the XML processor must normalize it as follows:
8999
 * - a character reference is processed by appending the referenced
9000
 *   character to the attribute value
9001
 * - an entity reference is processed by recursively processing the
9002
 *   replacement text of the entity
9003
 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
9004
 *   appending #x20 to the normalized value, except that only a single
9005
 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
9006
 *   parsed entity or the literal entity value of an internal parsed entity
9007
 * - other characters are processed by appending them to the normalized value
9008
 * If the declared value is not CDATA, then the XML processor must further
9009
 * process the normalized attribute value by discarding any leading and
9010
 * trailing space (#x20) characters, and by replacing sequences of space
9011
 * (#x20) characters by a single space (#x20) character.
9012
 * All attributes for which no declaration has been read should be treated
9013
 * by a non-validating parser as if declared CDATA.
9014
 *
9015
 * Returns the AttValue parsed or NULL. The value has to be freed by the
9016
 *     caller if it was copied, this can be detected by val[*len] == 0.
9017
 */
9018
9019
#define GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end) \
9020
203
    const xmlChar *oldbase = ctxt->input->base;\
9021
203
    GROW;\
9022
203
    if (ctxt->instate == XML_PARSER_EOF)\
9023
203
        return(NULL);\
9024
203
    if (oldbase != ctxt->input->base) {\
9025
0
        ptrdiff_t delta = ctxt->input->base - oldbase;\
9026
0
        start = start + delta;\
9027
0
        in = in + delta;\
9028
0
    }\
9029
203
    end = ctxt->input->end;
9030
9031
static xmlChar *
9032
xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
9033
                         int normalize)
9034
93.7k
{
9035
93.7k
    xmlChar limit = 0;
9036
93.7k
    const xmlChar *in = NULL, *start, *end, *last;
9037
93.7k
    xmlChar *ret = NULL;
9038
93.7k
    int line, col;
9039
93.7k
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
9040
0
                    XML_MAX_HUGE_LENGTH :
9041
93.7k
                    XML_MAX_TEXT_LENGTH;
9042
9043
93.7k
    GROW;
9044
93.7k
    in = (xmlChar *) CUR_PTR;
9045
93.7k
    line = ctxt->input->line;
9046
93.7k
    col = ctxt->input->col;
9047
93.7k
    if (*in != '"' && *in != '\'') {
9048
1.99k
        xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
9049
1.99k
        return (NULL);
9050
1.99k
    }
9051
91.7k
    ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
9052
9053
    /*
9054
     * try to handle in this routine the most common case where no
9055
     * allocation of a new string is required and where content is
9056
     * pure ASCII.
9057
     */
9058
91.7k
    limit = *in++;
9059
91.7k
    col++;
9060
91.7k
    end = ctxt->input->end;
9061
91.7k
    start = in;
9062
91.7k
    if (in >= end) {
9063
0
        GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
9064
0
    }
9065
91.7k
    if (normalize) {
9066
        /*
9067
   * Skip any leading spaces
9068
   */
9069
0
  while ((in < end) && (*in != limit) &&
9070
0
         ((*in == 0x20) || (*in == 0x9) ||
9071
0
          (*in == 0xA) || (*in == 0xD))) {
9072
0
      if (*in == 0xA) {
9073
0
          line++; col = 1;
9074
0
      } else {
9075
0
          col++;
9076
0
      }
9077
0
      in++;
9078
0
      start = in;
9079
0
      if (in >= end) {
9080
0
                GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
9081
0
                if ((in - start) > maxLength) {
9082
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9083
0
                                   "AttValue length too long\n");
9084
0
                    return(NULL);
9085
0
                }
9086
0
      }
9087
0
  }
9088
0
  while ((in < end) && (*in != limit) && (*in >= 0x20) &&
9089
0
         (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
9090
0
      col++;
9091
0
      if ((*in++ == 0x20) && (*in == 0x20)) break;
9092
0
      if (in >= end) {
9093
0
                GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
9094
0
                if ((in - start) > maxLength) {
9095
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9096
0
                                   "AttValue length too long\n");
9097
0
                    return(NULL);
9098
0
                }
9099
0
      }
9100
0
  }
9101
0
  last = in;
9102
  /*
9103
   * skip the trailing blanks
9104
   */
9105
0
  while ((last[-1] == 0x20) && (last > start)) last--;
9106
0
  while ((in < end) && (*in != limit) &&
9107
0
         ((*in == 0x20) || (*in == 0x9) ||
9108
0
          (*in == 0xA) || (*in == 0xD))) {
9109
0
      if (*in == 0xA) {
9110
0
          line++, col = 1;
9111
0
      } else {
9112
0
          col++;
9113
0
      }
9114
0
      in++;
9115
0
      if (in >= end) {
9116
0
    const xmlChar *oldbase = ctxt->input->base;
9117
0
    GROW;
9118
0
                if (ctxt->instate == XML_PARSER_EOF)
9119
0
                    return(NULL);
9120
0
    if (oldbase != ctxt->input->base) {
9121
0
        ptrdiff_t delta = ctxt->input->base - oldbase;
9122
0
        start = start + delta;
9123
0
        in = in + delta;
9124
0
        last = last + delta;
9125
0
    }
9126
0
    end = ctxt->input->end;
9127
0
                if ((in - start) > maxLength) {
9128
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9129
0
                                   "AttValue length too long\n");
9130
0
                    return(NULL);
9131
0
                }
9132
0
      }
9133
0
  }
9134
0
        if ((in - start) > maxLength) {
9135
0
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9136
0
                           "AttValue length too long\n");
9137
0
            return(NULL);
9138
0
        }
9139
0
  if (*in != limit) goto need_complex;
9140
91.7k
    } else {
9141
1.78M
  while ((in < end) && (*in != limit) && (*in >= 0x20) &&
9142
1.78M
         (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
9143
1.69M
      in++;
9144
1.69M
      col++;
9145
1.69M
      if (in >= end) {
9146
203
                GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
9147
203
                if ((in - start) > maxLength) {
9148
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9149
0
                                   "AttValue length too long\n");
9150
0
                    return(NULL);
9151
0
                }
9152
203
      }
9153
1.69M
  }
9154
91.7k
  last = in;
9155
91.7k
        if ((in - start) > maxLength) {
9156
0
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9157
0
                           "AttValue length too long\n");
9158
0
            return(NULL);
9159
0
        }
9160
91.7k
  if (*in != limit) goto need_complex;
9161
91.7k
    }
9162
61.8k
    in++;
9163
61.8k
    col++;
9164
61.8k
    if (len != NULL) {
9165
61.2k
        if (alloc) *alloc = 0;
9166
61.2k
        *len = last - start;
9167
61.2k
        ret = (xmlChar *) start;
9168
61.2k
    } else {
9169
598
        if (alloc) *alloc = 1;
9170
598
        ret = xmlStrndup(start, last - start);
9171
598
    }
9172
61.8k
    CUR_PTR = in;
9173
61.8k
    ctxt->input->line = line;
9174
61.8k
    ctxt->input->col = col;
9175
61.8k
    return ret;
9176
29.9k
need_complex:
9177
29.9k
    if (alloc) *alloc = 1;
9178
29.9k
    return xmlParseAttValueComplex(ctxt, len, normalize);
9179
91.7k
}
9180
9181
/**
9182
 * xmlParseAttribute2:
9183
 * @ctxt:  an XML parser context
9184
 * @pref:  the element prefix
9185
 * @elem:  the element name
9186
 * @prefix:  a xmlChar ** used to store the value of the attribute prefix
9187
 * @value:  a xmlChar ** used to store the value of the attribute
9188
 * @len:  an int * to save the length of the attribute
9189
 * @alloc:  an int * to indicate if the attribute was allocated
9190
 *
9191
 * parse an attribute in the new SAX2 framework.
9192
 *
9193
 * Returns the attribute name, and the value in *value, .
9194
 */
9195
9196
static const xmlChar *
9197
xmlParseAttribute2(xmlParserCtxtPtr ctxt,
9198
                   const xmlChar * pref, const xmlChar * elem,
9199
                   const xmlChar ** prefix, xmlChar ** value,
9200
                   int *len, int *alloc)
9201
96.5k
{
9202
96.5k
    const xmlChar *name;
9203
96.5k
    xmlChar *val, *internal_val = NULL;
9204
96.5k
    int normalize = 0;
9205
9206
96.5k
    *value = NULL;
9207
96.5k
    GROW;
9208
96.5k
    name = xmlParseQName(ctxt, prefix);
9209
96.5k
    if (name == NULL) {
9210
4.93k
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
9211
4.93k
                       "error parsing attribute name\n");
9212
4.93k
        return (NULL);
9213
4.93k
    }
9214
9215
    /*
9216
     * get the type if needed
9217
     */
9218
91.6k
    if (ctxt->attsSpecial != NULL) {
9219
69
        int type;
9220
9221
69
        type = (int) (ptrdiff_t) xmlHashQLookup2(ctxt->attsSpecial,
9222
69
                                                 pref, elem, *prefix, name);
9223
69
        if (type != 0)
9224
0
            normalize = 1;
9225
69
    }
9226
9227
    /*
9228
     * read the value
9229
     */
9230
91.6k
    SKIP_BLANKS;
9231
91.6k
    if (RAW == '=') {
9232
91.2k
        NEXT;
9233
91.2k
        SKIP_BLANKS;
9234
91.2k
        val = xmlParseAttValueInternal(ctxt, len, alloc, normalize);
9235
91.2k
  if (normalize) {
9236
      /*
9237
       * Sometimes a second normalisation pass for spaces is needed
9238
       * but that only happens if charrefs or entities references
9239
       * have been used in the attribute value, i.e. the attribute
9240
       * value have been extracted in an allocated string already.
9241
       */
9242
0
      if (*alloc) {
9243
0
          const xmlChar *val2;
9244
9245
0
          val2 = xmlAttrNormalizeSpace2(ctxt, val, len);
9246
0
    if ((val2 != NULL) && (val2 != val)) {
9247
0
        xmlFree(val);
9248
0
        val = (xmlChar *) val2;
9249
0
    }
9250
0
      }
9251
0
  }
9252
91.2k
        ctxt->instate = XML_PARSER_CONTENT;
9253
91.2k
    } else {
9254
325
        xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
9255
325
                          "Specification mandates value for attribute %s\n",
9256
325
                          name);
9257
325
        return (NULL);
9258
325
    }
9259
9260
91.2k
    if (*prefix == ctxt->str_xml) {
9261
        /*
9262
         * Check that xml:lang conforms to the specification
9263
         * No more registered as an error, just generate a warning now
9264
         * since this was deprecated in XML second edition
9265
         */
9266
907
        if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "lang"))) {
9267
0
            internal_val = xmlStrndup(val, *len);
9268
0
            if (!xmlCheckLanguageID(internal_val)) {
9269
0
                xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
9270
0
                              "Malformed value for xml:lang : %s\n",
9271
0
                              internal_val, NULL);
9272
0
            }
9273
0
        }
9274
9275
        /*
9276
         * Check that xml:space conforms to the specification
9277
         */
9278
907
        if (xmlStrEqual(name, BAD_CAST "space")) {
9279
0
            internal_val = xmlStrndup(val, *len);
9280
0
            if (xmlStrEqual(internal_val, BAD_CAST "default"))
9281
0
                *(ctxt->space) = 0;
9282
0
            else if (xmlStrEqual(internal_val, BAD_CAST "preserve"))
9283
0
                *(ctxt->space) = 1;
9284
0
            else {
9285
0
                xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
9286
0
                              "Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
9287
0
                              internal_val, NULL);
9288
0
            }
9289
0
        }
9290
907
        if (internal_val) {
9291
0
            xmlFree(internal_val);
9292
0
        }
9293
907
    }
9294
9295
91.2k
    *value = val;
9296
91.2k
    return (name);
9297
91.6k
}
9298
/**
9299
 * xmlParseStartTag2:
9300
 * @ctxt:  an XML parser context
9301
 *
9302
 * parse a start of tag either for rule element or
9303
 * EmptyElement. In both case we don't parse the tag closing chars.
9304
 * This routine is called when running SAX2 parsing
9305
 *
9306
 * [40] STag ::= '<' Name (S Attribute)* S? '>'
9307
 *
9308
 * [ WFC: Unique Att Spec ]
9309
 * No attribute name may appear more than once in the same start-tag or
9310
 * empty-element tag.
9311
 *
9312
 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
9313
 *
9314
 * [ WFC: Unique Att Spec ]
9315
 * No attribute name may appear more than once in the same start-tag or
9316
 * empty-element tag.
9317
 *
9318
 * With namespace:
9319
 *
9320
 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
9321
 *
9322
 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
9323
 *
9324
 * Returns the element name parsed
9325
 */
9326
9327
static const xmlChar *
9328
xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
9329
132k
                  const xmlChar **URI, int *tlen) {
9330
132k
    const xmlChar *localname;
9331
132k
    const xmlChar *prefix;
9332
132k
    const xmlChar *attname;
9333
132k
    const xmlChar *aprefix;
9334
132k
    const xmlChar *nsname;
9335
132k
    xmlChar *attvalue;
9336
132k
    const xmlChar **atts = ctxt->atts;
9337
132k
    int maxatts = ctxt->maxatts;
9338
132k
    int nratts, nbatts, nbdef, inputid;
9339
132k
    int i, j, nbNs, attval;
9340
132k
    unsigned long cur;
9341
132k
    int nsNr = ctxt->nsNr;
9342
9343
132k
    if (RAW != '<') return(NULL);
9344
132k
    NEXT1;
9345
9346
    /*
9347
     * NOTE: it is crucial with the SAX2 API to never call SHRINK beyond that
9348
     *       point since the attribute values may be stored as pointers to
9349
     *       the buffer and calling SHRINK would destroy them !
9350
     *       The Shrinking is only possible once the full set of attribute
9351
     *       callbacks have been done.
9352
     */
9353
132k
    SHRINK;
9354
132k
    cur = ctxt->input->cur - ctxt->input->base;
9355
132k
    inputid = ctxt->input->id;
9356
132k
    nbatts = 0;
9357
132k
    nratts = 0;
9358
132k
    nbdef = 0;
9359
132k
    nbNs = 0;
9360
132k
    attval = 0;
9361
    /* Forget any namespaces added during an earlier parse of this element. */
9362
132k
    ctxt->nsNr = nsNr;
9363
9364
132k
    localname = xmlParseQName(ctxt, &prefix);
9365
132k
    if (localname == NULL) {
9366
7.23k
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
9367
7.23k
           "StartTag: invalid element name\n");
9368
7.23k
        return(NULL);
9369
7.23k
    }
9370
125k
    *tlen = ctxt->input->cur - ctxt->input->base - cur;
9371
9372
    /*
9373
     * Now parse the attributes, it ends up with the ending
9374
     *
9375
     * (S Attribute)* S?
9376
     */
9377
125k
    SKIP_BLANKS;
9378
125k
    GROW;
9379
9380
168k
    while (((RAW != '>') &&
9381
168k
     ((RAW != '/') || (NXT(1) != '>')) &&
9382
168k
     (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) {
9383
96.5k
  int id = ctxt->input->id;
9384
96.5k
  unsigned long cons = CUR_CONSUMED;
9385
96.5k
  int len = -1, alloc = 0;
9386
9387
96.5k
  attname = xmlParseAttribute2(ctxt, prefix, localname,
9388
96.5k
                               &aprefix, &attvalue, &len, &alloc);
9389
96.5k
        if ((attname == NULL) || (attvalue == NULL))
9390
5.35k
            goto next_attr;
9391
91.1k
  if (len < 0) len = xmlStrlen(attvalue);
9392
9393
91.1k
        if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
9394
1.53k
            const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
9395
1.53k
            xmlURIPtr uri;
9396
9397
1.53k
            if (URL == NULL) {
9398
0
                xmlErrMemory(ctxt, "dictionary allocation failure");
9399
0
                if ((attvalue != NULL) && (alloc != 0))
9400
0
                    xmlFree(attvalue);
9401
0
                localname = NULL;
9402
0
                goto done;
9403
0
            }
9404
1.53k
            if (*URL != 0) {
9405
1.46k
                uri = xmlParseURI((const char *) URL);
9406
1.46k
                if (uri == NULL) {
9407
800
                    xmlNsErr(ctxt, XML_WAR_NS_URI,
9408
800
                             "xmlns: '%s' is not a valid URI\n",
9409
800
                                       URL, NULL, NULL);
9410
800
                } else {
9411
665
                    if (uri->scheme == NULL) {
9412
506
                        xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
9413
506
                                  "xmlns: URI %s is not absolute\n",
9414
506
                                  URL, NULL, NULL);
9415
506
                    }
9416
665
                    xmlFreeURI(uri);
9417
665
                }
9418
1.46k
                if (URL == ctxt->str_xml_ns) {
9419
0
                    if (attname != ctxt->str_xml) {
9420
0
                        xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9421
0
                     "xml namespace URI cannot be the default namespace\n",
9422
0
                                 NULL, NULL, NULL);
9423
0
                    }
9424
0
                    goto next_attr;
9425
0
                }
9426
1.46k
                if ((len == 29) &&
9427
1.46k
                    (xmlStrEqual(URL,
9428
0
                             BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
9429
0
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9430
0
                         "reuse of the xmlns namespace name is forbidden\n",
9431
0
                             NULL, NULL, NULL);
9432
0
                    goto next_attr;
9433
0
                }
9434
1.46k
            }
9435
            /*
9436
             * check that it's not a defined namespace
9437
             */
9438
1.61k
            for (j = 1;j <= nbNs;j++)
9439
667
                if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
9440
584
                    break;
9441
1.53k
            if (j <= nbNs)
9442
584
                xmlErrAttributeDup(ctxt, NULL, attname);
9443
946
            else
9444
946
                if (nsPush(ctxt, NULL, URL) > 0) nbNs++;
9445
9446
89.6k
        } else if (aprefix == ctxt->str_xmlns) {
9447
2.75k
            const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
9448
2.75k
            xmlURIPtr uri;
9449
9450
2.75k
            if (attname == ctxt->str_xml) {
9451
0
                if (URL != ctxt->str_xml_ns) {
9452
0
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9453
0
                             "xml namespace prefix mapped to wrong URI\n",
9454
0
                             NULL, NULL, NULL);
9455
0
                }
9456
                /*
9457
                 * Do not keep a namespace definition node
9458
                 */
9459
0
                goto next_attr;
9460
0
            }
9461
2.75k
            if (URL == ctxt->str_xml_ns) {
9462
0
                if (attname != ctxt->str_xml) {
9463
0
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9464
0
                             "xml namespace URI mapped to wrong prefix\n",
9465
0
                             NULL, NULL, NULL);
9466
0
                }
9467
0
                goto next_attr;
9468
0
            }
9469
2.75k
            if (attname == ctxt->str_xmlns) {
9470
0
                xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9471
0
                         "redefinition of the xmlns prefix is forbidden\n",
9472
0
                         NULL, NULL, NULL);
9473
0
                goto next_attr;
9474
0
            }
9475
2.75k
            if ((len == 29) &&
9476
2.75k
                (xmlStrEqual(URL,
9477
0
                             BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
9478
0
                xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9479
0
                         "reuse of the xmlns namespace name is forbidden\n",
9480
0
                         NULL, NULL, NULL);
9481
0
                goto next_attr;
9482
0
            }
9483
2.75k
            if ((URL == NULL) || (URL[0] == 0)) {
9484
0
                xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9485
0
                         "xmlns:%s: Empty XML namespace is not allowed\n",
9486
0
                              attname, NULL, NULL);
9487
0
                goto next_attr;
9488
2.75k
            } else {
9489
2.75k
                uri = xmlParseURI((const char *) URL);
9490
2.75k
                if (uri == NULL) {
9491
649
                    xmlNsErr(ctxt, XML_WAR_NS_URI,
9492
649
                         "xmlns:%s: '%s' is not a valid URI\n",
9493
649
                                       attname, URL, NULL);
9494
2.10k
                } else {
9495
2.10k
                    if ((ctxt->pedantic) && (uri->scheme == NULL)) {
9496
0
                        xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
9497
0
                                  "xmlns:%s: URI %s is not absolute\n",
9498
0
                                  attname, URL, NULL);
9499
0
                    }
9500
2.10k
                    xmlFreeURI(uri);
9501
2.10k
                }
9502
2.75k
            }
9503
9504
            /*
9505
             * check that it's not a defined namespace
9506
             */
9507
3.30k
            for (j = 1;j <= nbNs;j++)
9508
547
                if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
9509
0
                    break;
9510
2.75k
            if (j <= nbNs)
9511
0
                xmlErrAttributeDup(ctxt, aprefix, attname);
9512
2.75k
            else
9513
2.75k
                if (nsPush(ctxt, attname, URL) > 0) nbNs++;
9514
9515
86.9k
        } else {
9516
            /*
9517
             * Add the pair to atts
9518
             */
9519
86.9k
            if ((atts == NULL) || (nbatts + 5 > maxatts)) {
9520
183
                if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
9521
0
                    goto next_attr;
9522
0
                }
9523
183
                maxatts = ctxt->maxatts;
9524
183
                atts = ctxt->atts;
9525
183
            }
9526
86.9k
            ctxt->attallocs[nratts++] = alloc;
9527
86.9k
            atts[nbatts++] = attname;
9528
86.9k
            atts[nbatts++] = aprefix;
9529
            /*
9530
             * The namespace URI field is used temporarily to point at the
9531
             * base of the current input buffer for non-alloced attributes.
9532
             * When the input buffer is reallocated, all the pointers become
9533
             * invalid, but they can be reconstructed later.
9534
             */
9535
86.9k
            if (alloc)
9536
27.2k
                atts[nbatts++] = NULL;
9537
59.6k
            else
9538
59.6k
                atts[nbatts++] = ctxt->input->base;
9539
86.9k
            atts[nbatts++] = attvalue;
9540
86.9k
            attvalue += len;
9541
86.9k
            atts[nbatts++] = attvalue;
9542
            /*
9543
             * tag if some deallocation is needed
9544
             */
9545
86.9k
            if (alloc != 0) attval = 1;
9546
86.9k
            attvalue = NULL; /* moved into atts */
9547
86.9k
        }
9548
9549
96.5k
next_attr:
9550
96.5k
        if ((attvalue != NULL) && (alloc != 0)) {
9551
2.67k
            xmlFree(attvalue);
9552
2.67k
            attvalue = NULL;
9553
2.67k
        }
9554
9555
96.5k
  GROW
9556
96.5k
        if (ctxt->instate == XML_PARSER_EOF)
9557
0
            break;
9558
96.5k
  if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
9559
45.7k
      break;
9560
50.7k
  if (SKIP_BLANKS == 0) {
9561
7.80k
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
9562
7.80k
         "attributes construct error\n");
9563
7.80k
      break;
9564
7.80k
  }
9565
42.9k
        if ((cons == CUR_CONSUMED) && (id == ctxt->input->id) &&
9566
42.9k
            (attname == NULL) && (attvalue == NULL)) {
9567
0
      xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
9568
0
           "xmlParseStartTag: problem parsing attributes\n");
9569
0
      break;
9570
0
  }
9571
42.9k
        GROW;
9572
42.9k
    }
9573
9574
125k
    if (ctxt->input->id != inputid) {
9575
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
9576
0
                    "Unexpected change of input\n");
9577
0
        localname = NULL;
9578
0
        goto done;
9579
0
    }
9580
9581
    /* Reconstruct attribute value pointers. */
9582
212k
    for (i = 0, j = 0; j < nratts; i += 5, j++) {
9583
86.9k
        if (atts[i+2] != NULL) {
9584
            /*
9585
             * Arithmetic on dangling pointers is technically undefined
9586
             * behavior, but well...
9587
             */
9588
59.6k
            ptrdiff_t offset = ctxt->input->base - atts[i+2];
9589
59.6k
            atts[i+2]  = NULL;    /* Reset repurposed namespace URI */
9590
59.6k
            atts[i+3] += offset;  /* value */
9591
59.6k
            atts[i+4] += offset;  /* valuend */
9592
59.6k
        }
9593
86.9k
    }
9594
9595
    /*
9596
     * The attributes defaulting
9597
     */
9598
125k
    if (ctxt->attsDefault != NULL) {
9599
79
        xmlDefAttrsPtr defaults;
9600
9601
79
  defaults = xmlHashLookup2(ctxt->attsDefault, localname, prefix);
9602
79
  if (defaults != NULL) {
9603
0
      for (i = 0;i < defaults->nbAttrs;i++) {
9604
0
          attname = defaults->values[5 * i];
9605
0
    aprefix = defaults->values[5 * i + 1];
9606
9607
                /*
9608
     * special work for namespaces defaulted defs
9609
     */
9610
0
    if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
9611
        /*
9612
         * check that it's not a defined namespace
9613
         */
9614
0
        for (j = 1;j <= nbNs;j++)
9615
0
            if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
9616
0
          break;
9617
0
              if (j <= nbNs) continue;
9618
9619
0
        nsname = xmlGetNamespace(ctxt, NULL);
9620
0
        if (nsname != defaults->values[5 * i + 2]) {
9621
0
      if (nsPush(ctxt, NULL,
9622
0
                 defaults->values[5 * i + 2]) > 0)
9623
0
          nbNs++;
9624
0
        }
9625
0
    } else if (aprefix == ctxt->str_xmlns) {
9626
        /*
9627
         * check that it's not a defined namespace
9628
         */
9629
0
        for (j = 1;j <= nbNs;j++)
9630
0
            if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
9631
0
          break;
9632
0
              if (j <= nbNs) continue;
9633
9634
0
        nsname = xmlGetNamespace(ctxt, attname);
9635
0
        if (nsname != defaults->values[2]) {
9636
0
      if (nsPush(ctxt, attname,
9637
0
                 defaults->values[5 * i + 2]) > 0)
9638
0
          nbNs++;
9639
0
        }
9640
0
    } else {
9641
        /*
9642
         * check that it's not a defined attribute
9643
         */
9644
0
        for (j = 0;j < nbatts;j+=5) {
9645
0
      if ((attname == atts[j]) && (aprefix == atts[j+1]))
9646
0
          break;
9647
0
        }
9648
0
        if (j < nbatts) continue;
9649
9650
0
        if ((atts == NULL) || (nbatts + 5 > maxatts)) {
9651
0
      if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
9652
0
                            localname = NULL;
9653
0
                            goto done;
9654
0
      }
9655
0
      maxatts = ctxt->maxatts;
9656
0
      atts = ctxt->atts;
9657
0
        }
9658
0
        atts[nbatts++] = attname;
9659
0
        atts[nbatts++] = aprefix;
9660
0
        if (aprefix == NULL)
9661
0
      atts[nbatts++] = NULL;
9662
0
        else
9663
0
            atts[nbatts++] = xmlGetNamespace(ctxt, aprefix);
9664
0
        atts[nbatts++] = defaults->values[5 * i + 2];
9665
0
        atts[nbatts++] = defaults->values[5 * i + 3];
9666
0
        if ((ctxt->standalone == 1) &&
9667
0
            (defaults->values[5 * i + 4] != NULL)) {
9668
0
      xmlValidityError(ctxt, XML_DTD_STANDALONE_DEFAULTED,
9669
0
    "standalone: attribute %s on %s defaulted from external subset\n",
9670
0
                                   attname, localname);
9671
0
        }
9672
0
        nbdef++;
9673
0
    }
9674
0
      }
9675
0
  }
9676
79
    }
9677
9678
    /*
9679
     * The attributes checkings
9680
     */
9681
212k
    for (i = 0; i < nbatts;i += 5) {
9682
        /*
9683
  * The default namespace does not apply to attribute names.
9684
  */
9685
86.9k
  if (atts[i + 1] != NULL) {
9686
2.05k
      nsname = xmlGetNamespace(ctxt, atts[i + 1]);
9687
2.05k
      if (nsname == NULL) {
9688
603
    xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
9689
603
        "Namespace prefix %s for %s on %s is not defined\n",
9690
603
        atts[i + 1], atts[i], localname);
9691
603
      }
9692
2.05k
      atts[i + 2] = nsname;
9693
2.05k
  } else
9694
84.8k
      nsname = NULL;
9695
  /*
9696
   * [ WFC: Unique Att Spec ]
9697
   * No attribute name may appear more than once in the same
9698
   * start-tag or empty-element tag.
9699
   * As extended by the Namespace in XML REC.
9700
   */
9701
149k
        for (j = 0; j < i;j += 5) {
9702
62.5k
      if (atts[i] == atts[j]) {
9703
711
          if (atts[i+1] == atts[j+1]) {
9704
126
        xmlErrAttributeDup(ctxt, atts[i+1], atts[i]);
9705
126
        break;
9706
126
    }
9707
585
    if ((nsname != NULL) && (atts[j + 2] == nsname)) {
9708
0
        xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED,
9709
0
           "Namespaced Attribute %s in '%s' redefined\n",
9710
0
           atts[i], nsname, NULL);
9711
0
        break;
9712
0
    }
9713
585
      }
9714
62.5k
  }
9715
86.9k
    }
9716
9717
125k
    nsname = xmlGetNamespace(ctxt, prefix);
9718
125k
    if ((prefix != NULL) && (nsname == NULL)) {
9719
1.45k
  xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
9720
1.45k
           "Namespace prefix %s on %s is not defined\n",
9721
1.45k
     prefix, localname, NULL);
9722
1.45k
    }
9723
125k
    *pref = prefix;
9724
125k
    *URI = nsname;
9725
9726
    /*
9727
     * SAX: Start of Element !
9728
     */
9729
125k
    if ((ctxt->sax != NULL) && (ctxt->sax->startElementNs != NULL) &&
9730
125k
  (!ctxt->disableSAX)) {
9731
106k
  if (nbNs > 0)
9732
588
      ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
9733
588
        nsname, nbNs, &ctxt->nsTab[ctxt->nsNr - 2 * nbNs],
9734
588
        nbatts / 5, nbdef, atts);
9735
105k
  else
9736
105k
      ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
9737
105k
                    nsname, 0, NULL, nbatts / 5, nbdef, atts);
9738
106k
    }
9739
9740
125k
done:
9741
    /*
9742
     * Free up attribute allocated strings if needed
9743
     */
9744
125k
    if (attval != 0) {
9745
62.4k
  for (i = 3,j = 0; j < nratts;i += 5,j++)
9746
40.6k
      if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
9747
27.2k
          xmlFree((xmlChar *) atts[i]);
9748
21.7k
    }
9749
9750
125k
    return(localname);
9751
125k
}
9752
9753
/**
9754
 * xmlParseEndTag2:
9755
 * @ctxt:  an XML parser context
9756
 * @line:  line of the start tag
9757
 * @nsNr:  number of namespaces on the start tag
9758
 *
9759
 * parse an end of tag
9760
 *
9761
 * [42] ETag ::= '</' Name S? '>'
9762
 *
9763
 * With namespace
9764
 *
9765
 * [NS 9] ETag ::= '</' QName S? '>'
9766
 */
9767
9768
static void
9769
11.1k
xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlStartTag *tag) {
9770
11.1k
    const xmlChar *name;
9771
9772
11.1k
    GROW;
9773
11.1k
    if ((RAW != '<') || (NXT(1) != '/')) {
9774
0
  xmlFatalErr(ctxt, XML_ERR_LTSLASH_REQUIRED, NULL);
9775
0
  return;
9776
0
    }
9777
11.1k
    SKIP(2);
9778
9779
11.1k
    if (tag->prefix == NULL)
9780
4.74k
        name = xmlParseNameAndCompare(ctxt, ctxt->name);
9781
6.37k
    else
9782
6.37k
        name = xmlParseQNameAndCompare(ctxt, ctxt->name, tag->prefix);
9783
9784
    /*
9785
     * We should definitely be at the ending "S? '>'" part
9786
     */
9787
11.1k
    GROW;
9788
11.1k
    if (ctxt->instate == XML_PARSER_EOF)
9789
0
        return;
9790
11.1k
    SKIP_BLANKS;
9791
11.1k
    if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
9792
135
  xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
9793
135
    } else
9794
10.9k
  NEXT1;
9795
9796
    /*
9797
     * [ WFC: Element Type Match ]
9798
     * The Name in an element's end-tag must match the element type in the
9799
     * start-tag.
9800
     *
9801
     */
9802
11.1k
    if (name != (xmlChar*)1) {
9803
319
        if (name == NULL) name = BAD_CAST "unparsable";
9804
319
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
9805
319
         "Opening and ending tag mismatch: %s line %d and %s\n",
9806
319
                    ctxt->name, tag->line, name);
9807
319
    }
9808
9809
    /*
9810
     * SAX: End of Tag
9811
     */
9812
11.1k
    if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
9813
11.1k
  (!ctxt->disableSAX))
9814
5.85k
  ctxt->sax->endElementNs(ctxt->userData, ctxt->name, tag->prefix,
9815
5.85k
                                tag->URI);
9816
9817
11.1k
    spacePop(ctxt);
9818
11.1k
    if (tag->nsNr != 0)
9819
680
  nsPop(ctxt, tag->nsNr);
9820
11.1k
}
9821
9822
/**
9823
 * xmlParseCDSect:
9824
 * @ctxt:  an XML parser context
9825
 *
9826
 * DEPRECATED: Internal function, don't use.
9827
 *
9828
 * Parse escaped pure raw content.
9829
 *
9830
 * [18] CDSect ::= CDStart CData CDEnd
9831
 *
9832
 * [19] CDStart ::= '<![CDATA['
9833
 *
9834
 * [20] Data ::= (Char* - (Char* ']]>' Char*))
9835
 *
9836
 * [21] CDEnd ::= ']]>'
9837
 */
9838
void
9839
69
xmlParseCDSect(xmlParserCtxtPtr ctxt) {
9840
69
    xmlChar *buf = NULL;
9841
69
    int len = 0;
9842
69
    int size = XML_PARSER_BUFFER_SIZE;
9843
69
    int r, rl;
9844
69
    int s, sl;
9845
69
    int cur, l;
9846
69
    int count = 0;
9847
69
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
9848
0
                    XML_MAX_HUGE_LENGTH :
9849
69
                    XML_MAX_TEXT_LENGTH;
9850
9851
    /* Check 2.6.0 was NXT(0) not RAW */
9852
69
    if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
9853
69
  SKIP(9);
9854
69
    } else
9855
0
        return;
9856
9857
69
    ctxt->instate = XML_PARSER_CDATA_SECTION;
9858
69
    r = CUR_CHAR(rl);
9859
69
    if (!IS_CHAR(r)) {
9860
0
  xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
9861
0
  ctxt->instate = XML_PARSER_CONTENT;
9862
0
        return;
9863
0
    }
9864
69
    NEXTL(rl);
9865
69
    s = CUR_CHAR(sl);
9866
69
    if (!IS_CHAR(s)) {
9867
0
  xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
9868
0
  ctxt->instate = XML_PARSER_CONTENT;
9869
0
        return;
9870
0
    }
9871
69
    NEXTL(sl);
9872
69
    cur = CUR_CHAR(l);
9873
69
    buf = (xmlChar *) xmlMallocAtomic(size);
9874
69
    if (buf == NULL) {
9875
0
  xmlErrMemory(ctxt, NULL);
9876
0
  return;
9877
0
    }
9878
76.7M
    while (IS_CHAR(cur) &&
9879
76.7M
           ((r != ']') || (s != ']') || (cur != '>'))) {
9880
76.7M
  if (len + 5 >= size) {
9881
479
      xmlChar *tmp;
9882
9883
479
      tmp = (xmlChar *) xmlRealloc(buf, size * 2);
9884
479
      if (tmp == NULL) {
9885
0
          xmlFree(buf);
9886
0
    xmlErrMemory(ctxt, NULL);
9887
0
    return;
9888
0
      }
9889
479
      buf = tmp;
9890
479
      size *= 2;
9891
479
  }
9892
76.7M
  COPY_BUF(rl,buf,len,r);
9893
76.7M
  r = s;
9894
76.7M
  rl = sl;
9895
76.7M
  s = cur;
9896
76.7M
  sl = l;
9897
76.7M
  count++;
9898
76.7M
  if (count > 50) {
9899
1.50M
      SHRINK;
9900
1.50M
      GROW;
9901
1.50M
            if (ctxt->instate == XML_PARSER_EOF) {
9902
0
    xmlFree(buf);
9903
0
    return;
9904
0
            }
9905
1.50M
      count = 0;
9906
1.50M
  }
9907
76.7M
  NEXTL(l);
9908
76.7M
  cur = CUR_CHAR(l);
9909
76.7M
        if (len > maxLength) {
9910
10
            xmlFatalErrMsg(ctxt, XML_ERR_CDATA_NOT_FINISHED,
9911
10
                           "CData section too big found\n");
9912
10
            xmlFree(buf);
9913
10
            return;
9914
10
        }
9915
76.7M
    }
9916
59
    buf[len] = 0;
9917
59
    ctxt->instate = XML_PARSER_CONTENT;
9918
59
    if (cur != '>') {
9919
19
  xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED,
9920
19
                       "CData section not finished\n%.50s\n", buf);
9921
19
  xmlFree(buf);
9922
19
        return;
9923
19
    }
9924
40
    NEXTL(l);
9925
9926
    /*
9927
     * OK the buffer is to be consumed as cdata.
9928
     */
9929
40
    if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
9930
2
  if (ctxt->sax->cdataBlock != NULL)
9931
2
      ctxt->sax->cdataBlock(ctxt->userData, buf, len);
9932
0
  else if (ctxt->sax->characters != NULL)
9933
0
      ctxt->sax->characters(ctxt->userData, buf, len);
9934
2
    }
9935
40
    xmlFree(buf);
9936
40
}
9937
9938
/**
9939
 * xmlParseContentInternal:
9940
 * @ctxt:  an XML parser context
9941
 *
9942
 * Parse a content sequence. Stops at EOF or '</'. Leaves checking of
9943
 * unexpected EOF to the caller.
9944
 */
9945
9946
static void
9947
287
xmlParseContentInternal(xmlParserCtxtPtr ctxt) {
9948
287
    int nameNr = ctxt->nameNr;
9949
9950
287
    GROW;
9951
294k
    while ((RAW != 0) &&
9952
294k
     (ctxt->instate != XML_PARSER_EOF)) {
9953
294k
        int id = ctxt->input->id;
9954
294k
  unsigned long cons = CUR_CONSUMED;
9955
294k
  const xmlChar *cur = ctxt->input->cur;
9956
9957
  /*
9958
   * First case : a Processing Instruction.
9959
   */
9960
294k
  if ((*cur == '<') && (cur[1] == '?')) {
9961
12.2k
      xmlParsePI(ctxt);
9962
12.2k
  }
9963
9964
  /*
9965
   * Second case : a CDSection
9966
   */
9967
  /* 2.6.0 test was *cur not RAW */
9968
281k
  else if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
9969
69
      xmlParseCDSect(ctxt);
9970
69
  }
9971
9972
  /*
9973
   * Third case :  a comment
9974
   */
9975
281k
  else if ((*cur == '<') && (NXT(1) == '!') &&
9976
281k
     (NXT(2) == '-') && (NXT(3) == '-')) {
9977
539
      xmlParseComment(ctxt);
9978
539
      ctxt->instate = XML_PARSER_CONTENT;
9979
539
  }
9980
9981
  /*
9982
   * Fourth case :  a sub-element.
9983
   */
9984
281k
  else if (*cur == '<') {
9985
143k
            if (NXT(1) == '/') {
9986
11.1k
                if (ctxt->nameNr <= nameNr)
9987
87
                    break;
9988
11.0k
          xmlParseElementEnd(ctxt);
9989
132k
            } else {
9990
132k
          xmlParseElementStart(ctxt);
9991
132k
            }
9992
143k
  }
9993
9994
  /*
9995
   * Fifth case : a reference. If if has not been resolved,
9996
   *    parsing returns it's Name, create the node
9997
   */
9998
9999
137k
  else if (*cur == '&') {
10000
22.7k
      xmlParseReference(ctxt);
10001
22.7k
  }
10002
10003
  /*
10004
   * Last case, text. Note that References are handled directly.
10005
   */
10006
114k
  else {
10007
114k
      xmlParseCharData(ctxt, 0);
10008
114k
  }
10009
10010
294k
  GROW;
10011
294k
  SHRINK;
10012
10013
294k
  if ((cons == CUR_CONSUMED) && (id == ctxt->input->id)) {
10014
2
      xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
10015
2
                  "detected an error in element content\n");
10016
2
      xmlHaltParser(ctxt);
10017
2
            break;
10018
2
  }
10019
294k
    }
10020
287
}
10021
10022
/**
10023
 * xmlParseContent:
10024
 * @ctxt:  an XML parser context
10025
 *
10026
 * Parse a content sequence. Stops at EOF or '</'.
10027
 *
10028
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
10029
 */
10030
10031
void
10032
124
xmlParseContent(xmlParserCtxtPtr ctxt) {
10033
124
    int nameNr = ctxt->nameNr;
10034
10035
124
    xmlParseContentInternal(ctxt);
10036
10037
124
    if ((ctxt->instate != XML_PARSER_EOF) && (ctxt->nameNr > nameNr)) {
10038
60
        const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
10039
60
        int line = ctxt->pushTab[ctxt->nameNr - 1].line;
10040
60
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
10041
60
                "Premature end of data in tag %s line %d\n",
10042
60
    name, line, NULL);
10043
60
    }
10044
124
}
10045
10046
/**
10047
 * xmlParseElement:
10048
 * @ctxt:  an XML parser context
10049
 *
10050
 * DEPRECATED: Internal function, don't use.
10051
 *
10052
 * parse an XML element
10053
 *
10054
 * [39] element ::= EmptyElemTag | STag content ETag
10055
 *
10056
 * [ WFC: Element Type Match ]
10057
 * The Name in an element's end-tag must match the element type in the
10058
 * start-tag.
10059
 *
10060
 */
10061
10062
void
10063
169
xmlParseElement(xmlParserCtxtPtr ctxt) {
10064
169
    if (xmlParseElementStart(ctxt) != 0)
10065
6
        return;
10066
10067
163
    xmlParseContentInternal(ctxt);
10068
163
    if (ctxt->instate == XML_PARSER_EOF)
10069
5
  return;
10070
10071
158
    if (CUR == 0) {
10072
91
        const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
10073
91
        int line = ctxt->pushTab[ctxt->nameNr - 1].line;
10074
91
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
10075
91
                "Premature end of data in tag %s line %d\n",
10076
91
    name, line, NULL);
10077
91
        return;
10078
91
    }
10079
10080
67
    xmlParseElementEnd(ctxt);
10081
67
}
10082
10083
/**
10084
 * xmlParseElementStart:
10085
 * @ctxt:  an XML parser context
10086
 *
10087
 * Parse the start of an XML element. Returns -1 in case of error, 0 if an
10088
 * opening tag was parsed, 1 if an empty element was parsed.
10089
 */
10090
static int
10091
132k
xmlParseElementStart(xmlParserCtxtPtr ctxt) {
10092
132k
    const xmlChar *name;
10093
132k
    const xmlChar *prefix = NULL;
10094
132k
    const xmlChar *URI = NULL;
10095
132k
    xmlParserNodeInfo node_info;
10096
132k
    int line, tlen = 0;
10097
132k
    xmlNodePtr ret;
10098
132k
    int nsNr = ctxt->nsNr;
10099
10100
132k
    if (((unsigned int) ctxt->nameNr > xmlParserMaxDepth) &&
10101
132k
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
10102
1
  xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
10103
1
     "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
10104
1
        xmlParserMaxDepth);
10105
1
  xmlHaltParser(ctxt);
10106
1
  return(-1);
10107
1
    }
10108
10109
    /* Capture start position */
10110
132k
    if (ctxt->record_info) {
10111
0
        node_info.begin_pos = ctxt->input->consumed +
10112
0
                          (CUR_PTR - ctxt->input->base);
10113
0
  node_info.begin_line = ctxt->input->line;
10114
0
    }
10115
10116
132k
    if (ctxt->spaceNr == 0)
10117
0
  spacePush(ctxt, -1);
10118
132k
    else if (*ctxt->space == -2)
10119
0
  spacePush(ctxt, -1);
10120
132k
    else
10121
132k
  spacePush(ctxt, *ctxt->space);
10122
10123
132k
    line = ctxt->input->line;
10124
#ifdef LIBXML_SAX1_ENABLED
10125
    if (ctxt->sax2)
10126
#endif /* LIBXML_SAX1_ENABLED */
10127
132k
        name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
10128
#ifdef LIBXML_SAX1_ENABLED
10129
    else
10130
  name = xmlParseStartTag(ctxt);
10131
#endif /* LIBXML_SAX1_ENABLED */
10132
132k
    if (ctxt->instate == XML_PARSER_EOF)
10133
1
  return(-1);
10134
132k
    if (name == NULL) {
10135
7.23k
  spacePop(ctxt);
10136
7.23k
        return(-1);
10137
7.23k
    }
10138
125k
    nameNsPush(ctxt, name, prefix, URI, line, ctxt->nsNr - nsNr);
10139
125k
    ret = ctxt->node;
10140
10141
#ifdef LIBXML_VALID_ENABLED
10142
    /*
10143
     * [ VC: Root Element Type ]
10144
     * The Name in the document type declaration must match the element
10145
     * type of the root element.
10146
     */
10147
    if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
10148
        ctxt->node && (ctxt->node == ctxt->myDoc->children))
10149
        ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
10150
#endif /* LIBXML_VALID_ENABLED */
10151
10152
    /*
10153
     * Check for an Empty Element.
10154
     */
10155
125k
    if ((RAW == '/') && (NXT(1) == '>')) {
10156
105k
        SKIP(2);
10157
105k
  if (ctxt->sax2) {
10158
105k
      if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
10159
105k
    (!ctxt->disableSAX))
10160
100k
    ctxt->sax->endElementNs(ctxt->userData, name, prefix, URI);
10161
#ifdef LIBXML_SAX1_ENABLED
10162
  } else {
10163
      if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
10164
    (!ctxt->disableSAX))
10165
    ctxt->sax->endElement(ctxt->userData, name);
10166
#endif /* LIBXML_SAX1_ENABLED */
10167
105k
  }
10168
105k
  namePop(ctxt);
10169
105k
  spacePop(ctxt);
10170
105k
  if (nsNr != ctxt->nsNr)
10171
3
      nsPop(ctxt, ctxt->nsNr - nsNr);
10172
105k
  if ( ret != NULL && ctxt->record_info ) {
10173
0
     node_info.end_pos = ctxt->input->consumed +
10174
0
            (CUR_PTR - ctxt->input->base);
10175
0
     node_info.end_line = ctxt->input->line;
10176
0
     node_info.node = ret;
10177
0
     xmlParserAddNodeInfo(ctxt, &node_info);
10178
0
  }
10179
105k
  return(1);
10180
105k
    }
10181
20.1k
    if (RAW == '>') {
10182
12.2k
        NEXT1;
10183
12.2k
    } else {
10184
7.84k
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_GT_REQUIRED,
10185
7.84k
         "Couldn't find end of Start Tag %s line %d\n",
10186
7.84k
                    name, line, NULL);
10187
10188
  /*
10189
   * end of parsing of this node.
10190
   */
10191
7.84k
  nodePop(ctxt);
10192
7.84k
  namePop(ctxt);
10193
7.84k
  spacePop(ctxt);
10194
7.84k
  if (nsNr != ctxt->nsNr)
10195
2.29k
      nsPop(ctxt, ctxt->nsNr - nsNr);
10196
10197
  /*
10198
   * Capture end position and add node
10199
   */
10200
7.84k
  if ( ret != NULL && ctxt->record_info ) {
10201
0
     node_info.end_pos = ctxt->input->consumed +
10202
0
            (CUR_PTR - ctxt->input->base);
10203
0
     node_info.end_line = ctxt->input->line;
10204
0
     node_info.node = ret;
10205
0
     xmlParserAddNodeInfo(ctxt, &node_info);
10206
0
  }
10207
7.84k
  return(-1);
10208
7.84k
    }
10209
10210
12.2k
    return(0);
10211
20.1k
}
10212
10213
/**
10214
 * xmlParseElementEnd:
10215
 * @ctxt:  an XML parser context
10216
 *
10217
 * Parse the end of an XML element.
10218
 */
10219
static void
10220
11.1k
xmlParseElementEnd(xmlParserCtxtPtr ctxt) {
10221
11.1k
    xmlParserNodeInfo node_info;
10222
11.1k
    xmlNodePtr ret = ctxt->node;
10223
10224
11.1k
    if (ctxt->nameNr <= 0)
10225
0
        return;
10226
10227
    /*
10228
     * parse the end of tag: '</' should be here.
10229
     */
10230
11.1k
    if (ctxt->sax2) {
10231
11.1k
  xmlParseEndTag2(ctxt, &ctxt->pushTab[ctxt->nameNr - 1]);
10232
11.1k
  namePop(ctxt);
10233
11.1k
    }
10234
#ifdef LIBXML_SAX1_ENABLED
10235
    else
10236
  xmlParseEndTag1(ctxt, 0);
10237
#endif /* LIBXML_SAX1_ENABLED */
10238
10239
    /*
10240
     * Capture end position and add node
10241
     */
10242
11.1k
    if ( ret != NULL && ctxt->record_info ) {
10243
0
       node_info.end_pos = ctxt->input->consumed +
10244
0
                          (CUR_PTR - ctxt->input->base);
10245
0
       node_info.end_line = ctxt->input->line;
10246
0
       node_info.node = ret;
10247
0
       xmlParserAddNodeInfo(ctxt, &node_info);
10248
0
    }
10249
11.1k
}
10250
10251
/**
10252
 * xmlParseVersionNum:
10253
 * @ctxt:  an XML parser context
10254
 *
10255
 * DEPRECATED: Internal function, don't use.
10256
 *
10257
 * parse the XML version value.
10258
 *
10259
 * [26] VersionNum ::= '1.' [0-9]+
10260
 *
10261
 * In practice allow [0-9].[0-9]+ at that level
10262
 *
10263
 * Returns the string giving the XML version number, or NULL
10264
 */
10265
xmlChar *
10266
146
xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
10267
146
    xmlChar *buf = NULL;
10268
146
    int len = 0;
10269
146
    int size = 10;
10270
146
    xmlChar cur;
10271
10272
146
    buf = (xmlChar *) xmlMallocAtomic(size);
10273
146
    if (buf == NULL) {
10274
0
  xmlErrMemory(ctxt, NULL);
10275
0
  return(NULL);
10276
0
    }
10277
146
    cur = CUR;
10278
146
    if (!((cur >= '0') && (cur <= '9'))) {
10279
10
  xmlFree(buf);
10280
10
  return(NULL);
10281
10
    }
10282
136
    buf[len++] = cur;
10283
136
    NEXT;
10284
136
    cur=CUR;
10285
136
    if (cur != '.') {
10286
0
  xmlFree(buf);
10287
0
  return(NULL);
10288
0
    }
10289
136
    buf[len++] = cur;
10290
136
    NEXT;
10291
136
    cur=CUR;
10292
216
    while ((cur >= '0') && (cur <= '9')) {
10293
80
  if (len + 1 >= size) {
10294
0
      xmlChar *tmp;
10295
10296
0
      size *= 2;
10297
0
      tmp = (xmlChar *) xmlRealloc(buf, size);
10298
0
      if (tmp == NULL) {
10299
0
          xmlFree(buf);
10300
0
    xmlErrMemory(ctxt, NULL);
10301
0
    return(NULL);
10302
0
      }
10303
0
      buf = tmp;
10304
0
  }
10305
80
  buf[len++] = cur;
10306
80
  NEXT;
10307
80
  cur=CUR;
10308
80
    }
10309
136
    buf[len] = 0;
10310
136
    return(buf);
10311
136
}
10312
10313
/**
10314
 * xmlParseVersionInfo:
10315
 * @ctxt:  an XML parser context
10316
 *
10317
 * DEPRECATED: Internal function, don't use.
10318
 *
10319
 * parse the XML version.
10320
 *
10321
 * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
10322
 *
10323
 * [25] Eq ::= S? '=' S?
10324
 *
10325
 * Returns the version string, e.g. "1.0"
10326
 */
10327
10328
xmlChar *
10329
177
xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
10330
177
    xmlChar *version = NULL;
10331
10332
177
    if (CMP7(CUR_PTR, 'v', 'e', 'r', 's', 'i', 'o', 'n')) {
10333
162
  SKIP(7);
10334
162
  SKIP_BLANKS;
10335
162
  if (RAW != '=') {
10336
0
      xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10337
0
      return(NULL);
10338
0
        }
10339
162
  NEXT;
10340
162
  SKIP_BLANKS;
10341
162
  if (RAW == '"') {
10342
146
      NEXT;
10343
146
      version = xmlParseVersionNum(ctxt);
10344
146
      if (RAW != '"') {
10345
10
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10346
10
      } else
10347
136
          NEXT;
10348
146
  } else if (RAW == '\''){
10349
0
      NEXT;
10350
0
      version = xmlParseVersionNum(ctxt);
10351
0
      if (RAW != '\'') {
10352
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10353
0
      } else
10354
0
          NEXT;
10355
16
  } else {
10356
16
      xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10357
16
  }
10358
162
    }
10359
177
    return(version);
10360
177
}
10361
10362
/**
10363
 * xmlParseEncName:
10364
 * @ctxt:  an XML parser context
10365
 *
10366
 * DEPRECATED: Internal function, don't use.
10367
 *
10368
 * parse the XML encoding name
10369
 *
10370
 * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
10371
 *
10372
 * Returns the encoding name value or NULL
10373
 */
10374
xmlChar *
10375
177
xmlParseEncName(xmlParserCtxtPtr ctxt) {
10376
177
    xmlChar *buf = NULL;
10377
177
    int len = 0;
10378
177
    int size = 10;
10379
177
    xmlChar cur;
10380
10381
177
    cur = CUR;
10382
177
    if (((cur >= 'a') && (cur <= 'z')) ||
10383
177
        ((cur >= 'A') && (cur <= 'Z'))) {
10384
176
  buf = (xmlChar *) xmlMallocAtomic(size);
10385
176
  if (buf == NULL) {
10386
0
      xmlErrMemory(ctxt, NULL);
10387
0
      return(NULL);
10388
0
  }
10389
10390
176
  buf[len++] = cur;
10391
176
  NEXT;
10392
176
  cur = CUR;
10393
937
  while (((cur >= 'a') && (cur <= 'z')) ||
10394
937
         ((cur >= 'A') && (cur <= 'Z')) ||
10395
937
         ((cur >= '0') && (cur <= '9')) ||
10396
937
         (cur == '.') || (cur == '_') ||
10397
937
         (cur == '-')) {
10398
761
      if (len + 1 >= size) {
10399
12
          xmlChar *tmp;
10400
10401
12
    size *= 2;
10402
12
    tmp = (xmlChar *) xmlRealloc(buf, size);
10403
12
    if (tmp == NULL) {
10404
0
        xmlErrMemory(ctxt, NULL);
10405
0
        xmlFree(buf);
10406
0
        return(NULL);
10407
0
    }
10408
12
    buf = tmp;
10409
12
      }
10410
761
      buf[len++] = cur;
10411
761
      NEXT;
10412
761
      cur = CUR;
10413
761
      if (cur == 0) {
10414
1
          SHRINK;
10415
1
    GROW;
10416
1
    cur = CUR;
10417
1
      }
10418
761
        }
10419
176
  buf[len] = 0;
10420
176
    } else {
10421
1
  xmlFatalErr(ctxt, XML_ERR_ENCODING_NAME, NULL);
10422
1
    }
10423
177
    return(buf);
10424
177
}
10425
10426
/**
10427
 * xmlParseEncodingDecl:
10428
 * @ctxt:  an XML parser context
10429
 *
10430
 * DEPRECATED: Internal function, don't use.
10431
 *
10432
 * parse the XML encoding declaration
10433
 *
10434
 * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' |  "'" EncName "'")
10435
 *
10436
 * this setups the conversion filters.
10437
 *
10438
 * Returns the encoding value or NULL
10439
 */
10440
10441
const xmlChar *
10442
177
xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
10443
177
    xmlChar *encoding = NULL;
10444
10445
177
    SKIP_BLANKS;
10446
177
    if (CMP8(CUR_PTR, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g')) {
10447
177
  SKIP(8);
10448
177
  SKIP_BLANKS;
10449
177
  if (RAW != '=') {
10450
0
      xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10451
0
      return(NULL);
10452
0
        }
10453
177
  NEXT;
10454
177
  SKIP_BLANKS;
10455
177
  if (RAW == '"') {
10456
177
      NEXT;
10457
177
      encoding = xmlParseEncName(ctxt);
10458
177
      if (RAW != '"') {
10459
2
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10460
2
    xmlFree((xmlChar *) encoding);
10461
2
    return(NULL);
10462
2
      } else
10463
175
          NEXT;
10464
177
  } else if (RAW == '\''){
10465
0
      NEXT;
10466
0
      encoding = xmlParseEncName(ctxt);
10467
0
      if (RAW != '\'') {
10468
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10469
0
    xmlFree((xmlChar *) encoding);
10470
0
    return(NULL);
10471
0
      } else
10472
0
          NEXT;
10473
0
  } else {
10474
0
      xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10475
0
  }
10476
10477
        /*
10478
         * Non standard parsing, allowing the user to ignore encoding
10479
         */
10480
175
        if (ctxt->options & XML_PARSE_IGNORE_ENC) {
10481
0
      xmlFree((xmlChar *) encoding);
10482
0
            return(NULL);
10483
0
  }
10484
10485
  /*
10486
   * UTF-16 encoding switch has already taken place at this stage,
10487
   * more over the little-endian/big-endian selection is already done
10488
   */
10489
175
        if ((encoding != NULL) &&
10490
175
      ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-16")) ||
10491
175
       (!xmlStrcasecmp(encoding, BAD_CAST "UTF16")))) {
10492
      /*
10493
       * If no encoding was passed to the parser, that we are
10494
       * using UTF-16 and no decoder is present i.e. the
10495
       * document is apparently UTF-8 compatible, then raise an
10496
       * encoding mismatch fatal error
10497
       */
10498
0
      if ((ctxt->encoding == NULL) &&
10499
0
          (ctxt->input->buf != NULL) &&
10500
0
          (ctxt->input->buf->encoder == NULL)) {
10501
0
    xmlFatalErrMsg(ctxt, XML_ERR_INVALID_ENCODING,
10502
0
      "Document labelled UTF-16 but has UTF-8 content\n");
10503
0
      }
10504
0
      if (ctxt->encoding != NULL)
10505
0
    xmlFree((xmlChar *) ctxt->encoding);
10506
0
      ctxt->encoding = encoding;
10507
0
  }
10508
  /*
10509
   * UTF-8 encoding is handled natively
10510
   */
10511
175
        else if ((encoding != NULL) &&
10512
175
      ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-8")) ||
10513
175
       (!xmlStrcasecmp(encoding, BAD_CAST "UTF8")))) {
10514
0
      if (ctxt->encoding != NULL)
10515
0
    xmlFree((xmlChar *) ctxt->encoding);
10516
0
      ctxt->encoding = encoding;
10517
0
  }
10518
175
  else if (encoding != NULL) {
10519
175
      xmlCharEncodingHandlerPtr handler;
10520
10521
175
      if (ctxt->input->encoding != NULL)
10522
0
    xmlFree((xmlChar *) ctxt->input->encoding);
10523
175
      ctxt->input->encoding = encoding;
10524
10525
175
            handler = xmlFindCharEncodingHandler((const char *) encoding);
10526
175
      if (handler != NULL) {
10527
175
    if (xmlSwitchToEncoding(ctxt, handler) < 0) {
10528
        /* failed to convert */
10529
0
        ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
10530
0
        return(NULL);
10531
0
    }
10532
175
      } else {
10533
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
10534
0
      "Unsupported encoding %s\n", encoding);
10535
0
    return(NULL);
10536
0
      }
10537
175
  }
10538
175
    }
10539
175
    return(encoding);
10540
177
}
10541
10542
/**
10543
 * xmlParseSDDecl:
10544
 * @ctxt:  an XML parser context
10545
 *
10546
 * DEPRECATED: Internal function, don't use.
10547
 *
10548
 * parse the XML standalone declaration
10549
 *
10550
 * [32] SDDecl ::= S 'standalone' Eq
10551
 *                 (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no')'"'))
10552
 *
10553
 * [ VC: Standalone Document Declaration ]
10554
 * TODO The standalone document declaration must have the value "no"
10555
 * if any external markup declarations contain declarations of:
10556
 *  - attributes with default values, if elements to which these
10557
 *    attributes apply appear in the document without specifications
10558
 *    of values for these attributes, or
10559
 *  - entities (other than amp, lt, gt, apos, quot), if references
10560
 *    to those entities appear in the document, or
10561
 *  - attributes with values subject to normalization, where the
10562
 *    attribute appears in the document with a value which will change
10563
 *    as a result of normalization, or
10564
 *  - element types with element content, if white space occurs directly
10565
 *    within any instance of those types.
10566
 *
10567
 * Returns:
10568
 *   1 if standalone="yes"
10569
 *   0 if standalone="no"
10570
 *  -2 if standalone attribute is missing or invalid
10571
 *    (A standalone value of -2 means that the XML declaration was found,
10572
 *     but no value was specified for the standalone attribute).
10573
 */
10574
10575
int
10576
27
xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
10577
27
    int standalone = -2;
10578
10579
27
    SKIP_BLANKS;
10580
27
    if (CMP10(CUR_PTR, 's', 't', 'a', 'n', 'd', 'a', 'l', 'o', 'n', 'e')) {
10581
0
  SKIP(10);
10582
0
        SKIP_BLANKS;
10583
0
  if (RAW != '=') {
10584
0
      xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10585
0
      return(standalone);
10586
0
        }
10587
0
  NEXT;
10588
0
  SKIP_BLANKS;
10589
0
        if (RAW == '\''){
10590
0
      NEXT;
10591
0
      if ((RAW == 'n') && (NXT(1) == 'o')) {
10592
0
          standalone = 0;
10593
0
                SKIP(2);
10594
0
      } else if ((RAW == 'y') && (NXT(1) == 'e') &&
10595
0
                 (NXT(2) == 's')) {
10596
0
          standalone = 1;
10597
0
    SKIP(3);
10598
0
            } else {
10599
0
    xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
10600
0
      }
10601
0
      if (RAW != '\'') {
10602
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10603
0
      } else
10604
0
          NEXT;
10605
0
  } else if (RAW == '"'){
10606
0
      NEXT;
10607
0
      if ((RAW == 'n') && (NXT(1) == 'o')) {
10608
0
          standalone = 0;
10609
0
    SKIP(2);
10610
0
      } else if ((RAW == 'y') && (NXT(1) == 'e') &&
10611
0
                 (NXT(2) == 's')) {
10612
0
          standalone = 1;
10613
0
                SKIP(3);
10614
0
            } else {
10615
0
    xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
10616
0
      }
10617
0
      if (RAW != '"') {
10618
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10619
0
      } else
10620
0
          NEXT;
10621
0
  } else {
10622
0
      xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10623
0
        }
10624
0
    }
10625
27
    return(standalone);
10626
27
}
10627
10628
/**
10629
 * xmlParseXMLDecl:
10630
 * @ctxt:  an XML parser context
10631
 *
10632
 * DEPRECATED: Internal function, don't use.
10633
 *
10634
 * parse an XML declaration header
10635
 *
10636
 * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
10637
 */
10638
10639
void
10640
177
xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
10641
177
    xmlChar *version;
10642
10643
    /*
10644
     * This value for standalone indicates that the document has an
10645
     * XML declaration but it does not have a standalone attribute.
10646
     * It will be overwritten later if a standalone attribute is found.
10647
     */
10648
177
    ctxt->input->standalone = -2;
10649
10650
    /*
10651
     * We know that '<?xml' is here.
10652
     */
10653
177
    SKIP(5);
10654
10655
177
    if (!IS_BLANK_CH(RAW)) {
10656
0
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
10657
0
                 "Blank needed after '<?xml'\n");
10658
0
    }
10659
177
    SKIP_BLANKS;
10660
10661
    /*
10662
     * We must have the VersionInfo here.
10663
     */
10664
177
    version = xmlParseVersionInfo(ctxt);
10665
177
    if (version == NULL) {
10666
41
  xmlFatalErr(ctxt, XML_ERR_VERSION_MISSING, NULL);
10667
136
    } else {
10668
136
  if (!xmlStrEqual(version, (const xmlChar *) XML_DEFAULT_VERSION)) {
10669
      /*
10670
       * Changed here for XML-1.0 5th edition
10671
       */
10672
74
      if (ctxt->options & XML_PARSE_OLD10) {
10673
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
10674
0
                "Unsupported version '%s'\n",
10675
0
                version);
10676
74
      } else {
10677
74
          if ((version[0] == '1') && ((version[1] == '.'))) {
10678
72
        xmlWarningMsg(ctxt, XML_WAR_UNKNOWN_VERSION,
10679
72
                      "Unsupported version '%s'\n",
10680
72
          version, NULL);
10681
72
    } else {
10682
2
        xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
10683
2
              "Unsupported version '%s'\n",
10684
2
              version);
10685
2
    }
10686
74
      }
10687
74
  }
10688
136
  if (ctxt->version != NULL)
10689
0
      xmlFree((void *) ctxt->version);
10690
136
  ctxt->version = version;
10691
136
    }
10692
10693
    /*
10694
     * We may have the encoding declaration
10695
     */
10696
177
    if (!IS_BLANK_CH(RAW)) {
10697
31
        if ((RAW == '?') && (NXT(1) == '>')) {
10698
0
      SKIP(2);
10699
0
      return;
10700
0
  }
10701
31
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
10702
31
    }
10703
177
    xmlParseEncodingDecl(ctxt);
10704
177
    if ((ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) ||
10705
177
         (ctxt->instate == XML_PARSER_EOF)) {
10706
  /*
10707
   * The XML REC instructs us to stop parsing right here
10708
   */
10709
0
        return;
10710
0
    }
10711
10712
    /*
10713
     * We may have the standalone status.
10714
     */
10715
177
    if ((ctxt->input->encoding != NULL) && (!IS_BLANK_CH(RAW))) {
10716
175
        if ((RAW == '?') && (NXT(1) == '>')) {
10717
150
      SKIP(2);
10718
150
      return;
10719
150
  }
10720
25
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
10721
25
    }
10722
10723
    /*
10724
     * We can grow the input buffer freely at that point
10725
     */
10726
27
    GROW;
10727
10728
27
    SKIP_BLANKS;
10729
27
    ctxt->input->standalone = xmlParseSDDecl(ctxt);
10730
10731
27
    SKIP_BLANKS;
10732
27
    if ((RAW == '?') && (NXT(1) == '>')) {
10733
0
        SKIP(2);
10734
27
    } else if (RAW == '>') {
10735
        /* Deprecated old WD ... */
10736
9
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
10737
9
  NEXT;
10738
18
    } else {
10739
18
        int c;
10740
10741
18
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
10742
399
        while ((c = CUR) != 0) {
10743
398
            NEXT;
10744
398
            if (c == '>')
10745
17
                break;
10746
398
        }
10747
18
    }
10748
27
}
10749
10750
/**
10751
 * xmlParseMisc:
10752
 * @ctxt:  an XML parser context
10753
 *
10754
 * DEPRECATED: Internal function, don't use.
10755
 *
10756
 * parse an XML Misc* optional field.
10757
 *
10758
 * [27] Misc ::= Comment | PI |  S
10759
 */
10760
10761
void
10762
465
xmlParseMisc(xmlParserCtxtPtr ctxt) {
10763
518
    while (ctxt->instate != XML_PARSER_EOF) {
10764
518
        SKIP_BLANKS;
10765
518
        GROW;
10766
518
        if ((RAW == '<') && (NXT(1) == '?')) {
10767
51
      xmlParsePI(ctxt);
10768
467
        } else if (CMP4(CUR_PTR, '<', '!', '-', '-')) {
10769
2
      xmlParseComment(ctxt);
10770
465
        } else {
10771
465
            break;
10772
465
        }
10773
518
    }
10774
465
}
10775
10776
/**
10777
 * xmlParseDocument:
10778
 * @ctxt:  an XML parser context
10779
 *
10780
 * parse an XML document (and build a tree if using the standard SAX
10781
 * interface).
10782
 *
10783
 * [1] document ::= prolog element Misc*
10784
 *
10785
 * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
10786
 *
10787
 * Returns 0, -1 in case of error. the parser context is augmented
10788
 *                as a result of the parsing.
10789
 */
10790
10791
int
10792
201
xmlParseDocument(xmlParserCtxtPtr ctxt) {
10793
201
    xmlChar start[4];
10794
201
    xmlCharEncoding enc;
10795
10796
201
    xmlInitParser();
10797
10798
201
    if ((ctxt == NULL) || (ctxt->input == NULL))
10799
0
        return(-1);
10800
10801
201
    GROW;
10802
10803
    /*
10804
     * SAX: detecting the level.
10805
     */
10806
201
    xmlDetectSAX2(ctxt);
10807
10808
    /*
10809
     * SAX: beginning of the document processing.
10810
     */
10811
201
    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
10812
201
        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
10813
201
    if (ctxt->instate == XML_PARSER_EOF)
10814
0
  return(-1);
10815
10816
201
    if ((ctxt->encoding == NULL) &&
10817
201
        ((ctxt->input->end - ctxt->input->cur) >= 4)) {
10818
  /*
10819
   * Get the 4 first bytes and decode the charset
10820
   * if enc != XML_CHAR_ENCODING_NONE
10821
   * plug some encoding conversion routines.
10822
   */
10823
201
  start[0] = RAW;
10824
201
  start[1] = NXT(1);
10825
201
  start[2] = NXT(2);
10826
201
  start[3] = NXT(3);
10827
201
  enc = xmlDetectCharEncoding(&start[0], 4);
10828
201
  if (enc != XML_CHAR_ENCODING_NONE) {
10829
186
      xmlSwitchEncoding(ctxt, enc);
10830
186
  }
10831
201
    }
10832
10833
10834
201
    if (CUR == 0) {
10835
0
  xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
10836
0
  return(-1);
10837
0
    }
10838
10839
    /*
10840
     * Check for the XMLDecl in the Prolog.
10841
     * do not GROW here to avoid the detected encoder to decode more
10842
     * than just the first line, unless the amount of data is really
10843
     * too small to hold "<?xml version="1.0" encoding="foo"
10844
     */
10845
201
    if ((ctxt->input->end - ctxt->input->cur) < 35) {
10846
0
       GROW;
10847
0
    }
10848
201
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
10849
10850
  /*
10851
   * Note that we will switch encoding on the fly.
10852
   */
10853
177
  xmlParseXMLDecl(ctxt);
10854
177
  if ((ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) ||
10855
177
      (ctxt->instate == XML_PARSER_EOF)) {
10856
      /*
10857
       * The XML REC instructs us to stop parsing right here
10858
       */
10859
0
      return(-1);
10860
0
  }
10861
177
  ctxt->standalone = ctxt->input->standalone;
10862
177
  SKIP_BLANKS;
10863
177
    } else {
10864
24
  ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
10865
24
    }
10866
201
    if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
10867
156
        ctxt->sax->startDocument(ctxt->userData);
10868
201
    if (ctxt->instate == XML_PARSER_EOF)
10869
0
  return(-1);
10870
201
    if ((ctxt->myDoc != NULL) && (ctxt->input != NULL) &&
10871
201
        (ctxt->input->buf != NULL) && (ctxt->input->buf->compressed >= 0)) {
10872
0
  ctxt->myDoc->compression = ctxt->input->buf->compressed;
10873
0
    }
10874
10875
    /*
10876
     * The Misc part of the Prolog
10877
     */
10878
201
    xmlParseMisc(ctxt);
10879
10880
    /*
10881
     * Then possibly doc type declaration(s) and more Misc
10882
     * (doctypedecl Misc*)?
10883
     */
10884
201
    GROW;
10885
201
    if (CMP9(CUR_PTR, '<', '!', 'D', 'O', 'C', 'T', 'Y', 'P', 'E')) {
10886
10887
103
  ctxt->inSubset = 1;
10888
103
  xmlParseDocTypeDecl(ctxt);
10889
103
  if (RAW == '[') {
10890
102
      ctxt->instate = XML_PARSER_DTD;
10891
102
      xmlParseInternalSubset(ctxt);
10892
102
      if (ctxt->instate == XML_PARSER_EOF)
10893
8
    return(-1);
10894
102
  }
10895
10896
  /*
10897
   * Create and update the external subset.
10898
   */
10899
95
  ctxt->inSubset = 2;
10900
95
  if ((ctxt->sax != NULL) && (ctxt->sax->externalSubset != NULL) &&
10901
95
      (!ctxt->disableSAX))
10902
55
      ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
10903
55
                                ctxt->extSubSystem, ctxt->extSubURI);
10904
95
  if (ctxt->instate == XML_PARSER_EOF)
10905
0
      return(-1);
10906
95
  ctxt->inSubset = 0;
10907
10908
95
        xmlCleanSpecialAttr(ctxt);
10909
10910
95
  ctxt->instate = XML_PARSER_PROLOG;
10911
95
  xmlParseMisc(ctxt);
10912
95
    }
10913
10914
    /*
10915
     * Time to start parsing the tree itself
10916
     */
10917
193
    GROW;
10918
193
    if (RAW != '<') {
10919
24
  xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
10920
24
           "Start tag expected, '<' not found\n");
10921
169
    } else {
10922
169
  ctxt->instate = XML_PARSER_CONTENT;
10923
169
  xmlParseElement(ctxt);
10924
169
  ctxt->instate = XML_PARSER_EPILOG;
10925
10926
10927
  /*
10928
   * The Misc part at the end
10929
   */
10930
169
  xmlParseMisc(ctxt);
10931
10932
169
  if (RAW != 0) {
10933
8
      xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
10934
8
  }
10935
169
  ctxt->instate = XML_PARSER_EOF;
10936
169
    }
10937
10938
    /*
10939
     * SAX: end of the document processing.
10940
     */
10941
193
    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
10942
193
        ctxt->sax->endDocument(ctxt->userData);
10943
10944
    /*
10945
     * Remove locally kept entity definitions if the tree was not built
10946
     */
10947
193
    if ((ctxt->myDoc != NULL) &&
10948
193
  (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
10949
1
  xmlFreeDoc(ctxt->myDoc);
10950
1
  ctxt->myDoc = NULL;
10951
1
    }
10952
10953
193
    if ((ctxt->wellFormed) && (ctxt->myDoc != NULL)) {
10954
64
        ctxt->myDoc->properties |= XML_DOC_WELLFORMED;
10955
64
  if (ctxt->valid)
10956
64
      ctxt->myDoc->properties |= XML_DOC_DTDVALID;
10957
64
  if (ctxt->nsWellFormed)
10958
55
      ctxt->myDoc->properties |= XML_DOC_NSVALID;
10959
64
  if (ctxt->options & XML_PARSE_OLD10)
10960
0
      ctxt->myDoc->properties |= XML_DOC_OLD10;
10961
64
    }
10962
193
    if (! ctxt->wellFormed) {
10963
129
  ctxt->valid = 0;
10964
129
  return(-1);
10965
129
    }
10966
64
    return(0);
10967
193
}
10968
10969
/**
10970
 * xmlParseExtParsedEnt:
10971
 * @ctxt:  an XML parser context
10972
 *
10973
 * parse a general parsed entity
10974
 * An external general parsed entity is well-formed if it matches the
10975
 * production labeled extParsedEnt.
10976
 *
10977
 * [78] extParsedEnt ::= TextDecl? content
10978
 *
10979
 * Returns 0, -1 in case of error. the parser context is augmented
10980
 *                as a result of the parsing.
10981
 */
10982
10983
int
10984
0
xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) {
10985
0
    xmlChar start[4];
10986
0
    xmlCharEncoding enc;
10987
10988
0
    if ((ctxt == NULL) || (ctxt->input == NULL))
10989
0
        return(-1);
10990
10991
0
    xmlDetectSAX2(ctxt);
10992
10993
0
    GROW;
10994
10995
    /*
10996
     * SAX: beginning of the document processing.
10997
     */
10998
0
    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
10999
0
        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
11000
11001
    /*
11002
     * Get the 4 first bytes and decode the charset
11003
     * if enc != XML_CHAR_ENCODING_NONE
11004
     * plug some encoding conversion routines.
11005
     */
11006
0
    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
11007
0
  start[0] = RAW;
11008
0
  start[1] = NXT(1);
11009
0
  start[2] = NXT(2);
11010
0
  start[3] = NXT(3);
11011
0
  enc = xmlDetectCharEncoding(start, 4);
11012
0
  if (enc != XML_CHAR_ENCODING_NONE) {
11013
0
      xmlSwitchEncoding(ctxt, enc);
11014
0
  }
11015
0
    }
11016
11017
11018
0
    if (CUR == 0) {
11019
0
  xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
11020
0
    }
11021
11022
    /*
11023
     * Check for the XMLDecl in the Prolog.
11024
     */
11025
0
    GROW;
11026
0
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
11027
11028
  /*
11029
   * Note that we will switch encoding on the fly.
11030
   */
11031
0
  xmlParseXMLDecl(ctxt);
11032
0
  if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
11033
      /*
11034
       * The XML REC instructs us to stop parsing right here
11035
       */
11036
0
      return(-1);
11037
0
  }
11038
0
  SKIP_BLANKS;
11039
0
    } else {
11040
0
  ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11041
0
    }
11042
0
    if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
11043
0
        ctxt->sax->startDocument(ctxt->userData);
11044
0
    if (ctxt->instate == XML_PARSER_EOF)
11045
0
  return(-1);
11046
11047
    /*
11048
     * Doing validity checking on chunk doesn't make sense
11049
     */
11050
0
    ctxt->instate = XML_PARSER_CONTENT;
11051
0
    ctxt->validate = 0;
11052
0
    ctxt->loadsubset = 0;
11053
0
    ctxt->depth = 0;
11054
11055
0
    xmlParseContent(ctxt);
11056
0
    if (ctxt->instate == XML_PARSER_EOF)
11057
0
  return(-1);
11058
11059
0
    if ((RAW == '<') && (NXT(1) == '/')) {
11060
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
11061
0
    } else if (RAW != 0) {
11062
0
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
11063
0
    }
11064
11065
    /*
11066
     * SAX: end of the document processing.
11067
     */
11068
0
    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11069
0
        ctxt->sax->endDocument(ctxt->userData);
11070
11071
0
    if (! ctxt->wellFormed) return(-1);
11072
0
    return(0);
11073
0
}
11074
11075
#ifdef LIBXML_PUSH_ENABLED
11076
/************************************************************************
11077
 *                  *
11078
 *    Progressive parsing interfaces        *
11079
 *                  *
11080
 ************************************************************************/
11081
11082
/**
11083
 * xmlParseLookupSequence:
11084
 * @ctxt:  an XML parser context
11085
 * @first:  the first char to lookup
11086
 * @next:  the next char to lookup or zero
11087
 * @third:  the next char to lookup or zero
11088
 *
11089
 * Try to find if a sequence (first, next, third) or  just (first next) or
11090
 * (first) is available in the input stream.
11091
 * This function has a side effect of (possibly) incrementing ctxt->checkIndex
11092
 * to avoid rescanning sequences of bytes, it DOES change the state of the
11093
 * parser, do not use liberally.
11094
 *
11095
 * Returns the index to the current parsing point if the full sequence
11096
 *      is available, -1 otherwise.
11097
 */
11098
static int
11099
xmlParseLookupSequence(xmlParserCtxtPtr ctxt, xmlChar first,
11100
                       xmlChar next, xmlChar third) {
11101
    int base, len;
11102
    xmlParserInputPtr in;
11103
    const xmlChar *buf;
11104
11105
    in = ctxt->input;
11106
    if (in == NULL) return(-1);
11107
    base = in->cur - in->base;
11108
    if (base < 0) return(-1);
11109
    if (ctxt->checkIndex > base)
11110
        base = ctxt->checkIndex;
11111
    if (in->buf == NULL) {
11112
  buf = in->base;
11113
  len = in->length;
11114
    } else {
11115
  buf = xmlBufContent(in->buf->buffer);
11116
  len = xmlBufUse(in->buf->buffer);
11117
    }
11118
    /* take into account the sequence length */
11119
    if (third) len -= 2;
11120
    else if (next) len --;
11121
    for (;base < len;base++) {
11122
        if (buf[base] == first) {
11123
      if (third != 0) {
11124
    if ((buf[base + 1] != next) ||
11125
        (buf[base + 2] != third)) continue;
11126
      } else if (next != 0) {
11127
    if (buf[base + 1] != next) continue;
11128
      }
11129
      ctxt->checkIndex = 0;
11130
#ifdef DEBUG_PUSH
11131
      if (next == 0)
11132
    xmlGenericError(xmlGenericErrorContext,
11133
      "PP: lookup '%c' found at %d\n",
11134
      first, base);
11135
      else if (third == 0)
11136
    xmlGenericError(xmlGenericErrorContext,
11137
      "PP: lookup '%c%c' found at %d\n",
11138
      first, next, base);
11139
      else
11140
    xmlGenericError(xmlGenericErrorContext,
11141
      "PP: lookup '%c%c%c' found at %d\n",
11142
      first, next, third, base);
11143
#endif
11144
      return(base - (in->cur - in->base));
11145
  }
11146
    }
11147
    ctxt->checkIndex = base;
11148
#ifdef DEBUG_PUSH
11149
    if (next == 0)
11150
  xmlGenericError(xmlGenericErrorContext,
11151
    "PP: lookup '%c' failed\n", first);
11152
    else if (third == 0)
11153
  xmlGenericError(xmlGenericErrorContext,
11154
    "PP: lookup '%c%c' failed\n", first, next);
11155
    else
11156
  xmlGenericError(xmlGenericErrorContext,
11157
    "PP: lookup '%c%c%c' failed\n", first, next, third);
11158
#endif
11159
    return(-1);
11160
}
11161
11162
/**
11163
 * xmlParseGetLasts:
11164
 * @ctxt:  an XML parser context
11165
 * @lastlt:  pointer to store the last '<' from the input
11166
 * @lastgt:  pointer to store the last '>' from the input
11167
 *
11168
 * Lookup the last < and > in the current chunk
11169
 */
11170
static void
11171
xmlParseGetLasts(xmlParserCtxtPtr ctxt, const xmlChar **lastlt,
11172
                 const xmlChar **lastgt) {
11173
    const xmlChar *tmp;
11174
11175
    if ((ctxt == NULL) || (lastlt == NULL) || (lastgt == NULL)) {
11176
  xmlGenericError(xmlGenericErrorContext,
11177
        "Internal error: xmlParseGetLasts\n");
11178
  return;
11179
    }
11180
    if ((ctxt->progressive != 0) && (ctxt->inputNr == 1)) {
11181
        tmp = ctxt->input->end;
11182
  tmp--;
11183
  while ((tmp >= ctxt->input->base) && (*tmp != '<')) tmp--;
11184
  if (tmp < ctxt->input->base) {
11185
      *lastlt = NULL;
11186
      *lastgt = NULL;
11187
  } else {
11188
      *lastlt = tmp;
11189
      tmp++;
11190
      while ((tmp < ctxt->input->end) && (*tmp != '>')) {
11191
          if (*tmp == '\'') {
11192
        tmp++;
11193
        while ((tmp < ctxt->input->end) && (*tmp != '\'')) tmp++;
11194
        if (tmp < ctxt->input->end) tmp++;
11195
    } else if (*tmp == '"') {
11196
        tmp++;
11197
        while ((tmp < ctxt->input->end) && (*tmp != '"')) tmp++;
11198
        if (tmp < ctxt->input->end) tmp++;
11199
    } else
11200
        tmp++;
11201
      }
11202
      if (tmp < ctxt->input->end)
11203
          *lastgt = tmp;
11204
      else {
11205
          tmp = *lastlt;
11206
    tmp--;
11207
    while ((tmp >= ctxt->input->base) && (*tmp != '>')) tmp--;
11208
    if (tmp >= ctxt->input->base)
11209
        *lastgt = tmp;
11210
    else
11211
        *lastgt = NULL;
11212
      }
11213
  }
11214
    } else {
11215
        *lastlt = NULL;
11216
  *lastgt = NULL;
11217
    }
11218
}
11219
/**
11220
 * xmlCheckCdataPush:
11221
 * @cur: pointer to the block of characters
11222
 * @len: length of the block in bytes
11223
 * @complete: 1 if complete CDATA block is passed in, 0 if partial block
11224
 *
11225
 * Check that the block of characters is okay as SCdata content [20]
11226
 *
11227
 * Returns the number of bytes to pass if okay, a negative index where an
11228
 *         UTF-8 error occurred otherwise
11229
 */
11230
static int
11231
xmlCheckCdataPush(const xmlChar *utf, int len, int complete) {
11232
    int ix;
11233
    unsigned char c;
11234
    int codepoint;
11235
11236
    if ((utf == NULL) || (len <= 0))
11237
        return(0);
11238
11239
    for (ix = 0; ix < len;) {      /* string is 0-terminated */
11240
        c = utf[ix];
11241
        if ((c & 0x80) == 0x00) { /* 1-byte code, starts with 10 */
11242
      if (c >= 0x20)
11243
    ix++;
11244
      else if ((c == 0xA) || (c == 0xD) || (c == 0x9))
11245
          ix++;
11246
      else
11247
          return(-ix);
11248
  } else if ((c & 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */
11249
      if (ix + 2 > len) return(complete ? -ix : ix);
11250
      if ((utf[ix+1] & 0xc0 ) != 0x80)
11251
          return(-ix);
11252
      codepoint = (utf[ix] & 0x1f) << 6;
11253
      codepoint |= utf[ix+1] & 0x3f;
11254
      if (!xmlIsCharQ(codepoint))
11255
          return(-ix);
11256
      ix += 2;
11257
  } else if ((c & 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */
11258
      if (ix + 3 > len) return(complete ? -ix : ix);
11259
      if (((utf[ix+1] & 0xc0) != 0x80) ||
11260
          ((utf[ix+2] & 0xc0) != 0x80))
11261
        return(-ix);
11262
      codepoint = (utf[ix] & 0xf) << 12;
11263
      codepoint |= (utf[ix+1] & 0x3f) << 6;
11264
      codepoint |= utf[ix+2] & 0x3f;
11265
      if (!xmlIsCharQ(codepoint))
11266
          return(-ix);
11267
      ix += 3;
11268
  } else if ((c & 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */
11269
      if (ix + 4 > len) return(complete ? -ix : ix);
11270
      if (((utf[ix+1] & 0xc0) != 0x80) ||
11271
          ((utf[ix+2] & 0xc0) != 0x80) ||
11272
    ((utf[ix+3] & 0xc0) != 0x80))
11273
        return(-ix);
11274
      codepoint = (utf[ix] & 0x7) << 18;
11275
      codepoint |= (utf[ix+1] & 0x3f) << 12;
11276
      codepoint |= (utf[ix+2] & 0x3f) << 6;
11277
      codepoint |= utf[ix+3] & 0x3f;
11278
      if (!xmlIsCharQ(codepoint))
11279
          return(-ix);
11280
      ix += 4;
11281
  } else        /* unknown encoding */
11282
      return(-ix);
11283
      }
11284
      return(ix);
11285
}
11286
11287
/**
11288
 * xmlParseTryOrFinish:
11289
 * @ctxt:  an XML parser context
11290
 * @terminate:  last chunk indicator
11291
 *
11292
 * Try to progress on parsing
11293
 *
11294
 * Returns zero if no parsing was possible
11295
 */
11296
static int
11297
xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
11298
    int ret = 0;
11299
    int avail, tlen;
11300
    xmlChar cur, next;
11301
    const xmlChar *lastlt, *lastgt;
11302
11303
    if (ctxt->input == NULL)
11304
        return(0);
11305
11306
#ifdef DEBUG_PUSH
11307
    switch (ctxt->instate) {
11308
  case XML_PARSER_EOF:
11309
      xmlGenericError(xmlGenericErrorContext,
11310
        "PP: try EOF\n"); break;
11311
  case XML_PARSER_START:
11312
      xmlGenericError(xmlGenericErrorContext,
11313
        "PP: try START\n"); break;
11314
  case XML_PARSER_MISC:
11315
      xmlGenericError(xmlGenericErrorContext,
11316
        "PP: try MISC\n");break;
11317
  case XML_PARSER_COMMENT:
11318
      xmlGenericError(xmlGenericErrorContext,
11319
        "PP: try COMMENT\n");break;
11320
  case XML_PARSER_PROLOG:
11321
      xmlGenericError(xmlGenericErrorContext,
11322
        "PP: try PROLOG\n");break;
11323
  case XML_PARSER_START_TAG:
11324
      xmlGenericError(xmlGenericErrorContext,
11325
        "PP: try START_TAG\n");break;
11326
  case XML_PARSER_CONTENT:
11327
      xmlGenericError(xmlGenericErrorContext,
11328
        "PP: try CONTENT\n");break;
11329
  case XML_PARSER_CDATA_SECTION:
11330
      xmlGenericError(xmlGenericErrorContext,
11331
        "PP: try CDATA_SECTION\n");break;
11332
  case XML_PARSER_END_TAG:
11333
      xmlGenericError(xmlGenericErrorContext,
11334
        "PP: try END_TAG\n");break;
11335
  case XML_PARSER_ENTITY_DECL:
11336
      xmlGenericError(xmlGenericErrorContext,
11337
        "PP: try ENTITY_DECL\n");break;
11338
  case XML_PARSER_ENTITY_VALUE:
11339
      xmlGenericError(xmlGenericErrorContext,
11340
        "PP: try ENTITY_VALUE\n");break;
11341
  case XML_PARSER_ATTRIBUTE_VALUE:
11342
      xmlGenericError(xmlGenericErrorContext,
11343
        "PP: try ATTRIBUTE_VALUE\n");break;
11344
  case XML_PARSER_DTD:
11345
      xmlGenericError(xmlGenericErrorContext,
11346
        "PP: try DTD\n");break;
11347
  case XML_PARSER_EPILOG:
11348
      xmlGenericError(xmlGenericErrorContext,
11349
        "PP: try EPILOG\n");break;
11350
  case XML_PARSER_PI:
11351
      xmlGenericError(xmlGenericErrorContext,
11352
        "PP: try PI\n");break;
11353
        case XML_PARSER_IGNORE:
11354
            xmlGenericError(xmlGenericErrorContext,
11355
        "PP: try IGNORE\n");break;
11356
    }
11357
#endif
11358
11359
    if ((ctxt->input != NULL) &&
11360
        (ctxt->input->cur - ctxt->input->base > 4096)) {
11361
  xmlSHRINK(ctxt);
11362
  ctxt->checkIndex = 0;
11363
    }
11364
    xmlParseGetLasts(ctxt, &lastlt, &lastgt);
11365
11366
    while (ctxt->instate != XML_PARSER_EOF) {
11367
  if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
11368
      return(0);
11369
11370
  if (ctxt->input == NULL) break;
11371
  if (ctxt->input->buf == NULL)
11372
      avail = ctxt->input->length -
11373
              (ctxt->input->cur - ctxt->input->base);
11374
  else {
11375
      /*
11376
       * If we are operating on converted input, try to flush
11377
       * remaining chars to avoid them stalling in the non-converted
11378
       * buffer. But do not do this in document start where
11379
       * encoding="..." may not have been read and we work on a
11380
       * guessed encoding.
11381
       */
11382
      if ((ctxt->instate != XML_PARSER_START) &&
11383
          (ctxt->input->buf->raw != NULL) &&
11384
    (xmlBufIsEmpty(ctxt->input->buf->raw) == 0)) {
11385
                size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer,
11386
                                                 ctxt->input);
11387
    size_t current = ctxt->input->cur - ctxt->input->base;
11388
11389
    xmlParserInputBufferPush(ctxt->input->buf, 0, "");
11390
                xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input,
11391
                                      base, current);
11392
      }
11393
      avail = xmlBufUse(ctxt->input->buf->buffer) -
11394
        (ctxt->input->cur - ctxt->input->base);
11395
  }
11396
        if (avail < 1)
11397
      goto done;
11398
        switch (ctxt->instate) {
11399
            case XML_PARSER_EOF:
11400
          /*
11401
     * Document parsing is done !
11402
     */
11403
          goto done;
11404
            case XML_PARSER_START:
11405
    if (ctxt->charset == XML_CHAR_ENCODING_NONE) {
11406
        xmlChar start[4];
11407
        xmlCharEncoding enc;
11408
11409
        /*
11410
         * Very first chars read from the document flow.
11411
         */
11412
        if (avail < 4)
11413
      goto done;
11414
11415
        /*
11416
         * Get the 4 first bytes and decode the charset
11417
         * if enc != XML_CHAR_ENCODING_NONE
11418
         * plug some encoding conversion routines,
11419
         * else xmlSwitchEncoding will set to (default)
11420
         * UTF8.
11421
         */
11422
        start[0] = RAW;
11423
        start[1] = NXT(1);
11424
        start[2] = NXT(2);
11425
        start[3] = NXT(3);
11426
        enc = xmlDetectCharEncoding(start, 4);
11427
        xmlSwitchEncoding(ctxt, enc);
11428
        break;
11429
    }
11430
11431
    if (avail < 2)
11432
        goto done;
11433
    cur = ctxt->input->cur[0];
11434
    next = ctxt->input->cur[1];
11435
    if (cur == 0) {
11436
        if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
11437
      ctxt->sax->setDocumentLocator(ctxt->userData,
11438
                  &xmlDefaultSAXLocator);
11439
        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
11440
        xmlHaltParser(ctxt);
11441
#ifdef DEBUG_PUSH
11442
        xmlGenericError(xmlGenericErrorContext,
11443
          "PP: entering EOF\n");
11444
#endif
11445
        if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11446
      ctxt->sax->endDocument(ctxt->userData);
11447
        goto done;
11448
    }
11449
          if ((cur == '<') && (next == '?')) {
11450
        /* PI or XML decl */
11451
        if (avail < 5) return(ret);
11452
        if ((!terminate) &&
11453
            (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
11454
      return(ret);
11455
        if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
11456
      ctxt->sax->setDocumentLocator(ctxt->userData,
11457
                  &xmlDefaultSAXLocator);
11458
        if ((ctxt->input->cur[2] == 'x') &&
11459
      (ctxt->input->cur[3] == 'm') &&
11460
      (ctxt->input->cur[4] == 'l') &&
11461
      (IS_BLANK_CH(ctxt->input->cur[5]))) {
11462
      ret += 5;
11463
#ifdef DEBUG_PUSH
11464
      xmlGenericError(xmlGenericErrorContext,
11465
        "PP: Parsing XML Decl\n");
11466
#endif
11467
      xmlParseXMLDecl(ctxt);
11468
      if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
11469
          /*
11470
           * The XML REC instructs us to stop parsing right
11471
           * here
11472
           */
11473
          xmlHaltParser(ctxt);
11474
          return(0);
11475
      }
11476
      ctxt->standalone = ctxt->input->standalone;
11477
      if ((ctxt->encoding == NULL) &&
11478
          (ctxt->input->encoding != NULL))
11479
          ctxt->encoding = xmlStrdup(ctxt->input->encoding);
11480
      if ((ctxt->sax) && (ctxt->sax->startDocument) &&
11481
          (!ctxt->disableSAX))
11482
          ctxt->sax->startDocument(ctxt->userData);
11483
      ctxt->instate = XML_PARSER_MISC;
11484
#ifdef DEBUG_PUSH
11485
      xmlGenericError(xmlGenericErrorContext,
11486
        "PP: entering MISC\n");
11487
#endif
11488
        } else {
11489
      ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11490
      if ((ctxt->sax) && (ctxt->sax->startDocument) &&
11491
          (!ctxt->disableSAX))
11492
          ctxt->sax->startDocument(ctxt->userData);
11493
      ctxt->instate = XML_PARSER_MISC;
11494
#ifdef DEBUG_PUSH
11495
      xmlGenericError(xmlGenericErrorContext,
11496
        "PP: entering MISC\n");
11497
#endif
11498
        }
11499
    } else {
11500
        if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
11501
      ctxt->sax->setDocumentLocator(ctxt->userData,
11502
                  &xmlDefaultSAXLocator);
11503
        ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11504
        if (ctxt->version == NULL) {
11505
            xmlErrMemory(ctxt, NULL);
11506
      break;
11507
        }
11508
        if ((ctxt->sax) && (ctxt->sax->startDocument) &&
11509
            (!ctxt->disableSAX))
11510
      ctxt->sax->startDocument(ctxt->userData);
11511
        ctxt->instate = XML_PARSER_MISC;
11512
#ifdef DEBUG_PUSH
11513
        xmlGenericError(xmlGenericErrorContext,
11514
          "PP: entering MISC\n");
11515
#endif
11516
    }
11517
    break;
11518
            case XML_PARSER_START_TAG: {
11519
          const xmlChar *name;
11520
    const xmlChar *prefix = NULL;
11521
    const xmlChar *URI = NULL;
11522
                int line = ctxt->input->line;
11523
    int nsNr = ctxt->nsNr;
11524
11525
    if ((avail < 2) && (ctxt->inputNr == 1))
11526
        goto done;
11527
    cur = ctxt->input->cur[0];
11528
          if (cur != '<') {
11529
        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
11530
        xmlHaltParser(ctxt);
11531
        if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11532
      ctxt->sax->endDocument(ctxt->userData);
11533
        goto done;
11534
    }
11535
    if (!terminate) {
11536
        if (ctxt->progressive) {
11537
            /* > can be found unescaped in attribute values */
11538
            if ((lastgt == NULL) || (ctxt->input->cur >= lastgt))
11539
          goto done;
11540
        } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) {
11541
      goto done;
11542
        }
11543
    }
11544
    if (ctxt->spaceNr == 0)
11545
        spacePush(ctxt, -1);
11546
    else if (*ctxt->space == -2)
11547
        spacePush(ctxt, -1);
11548
    else
11549
        spacePush(ctxt, *ctxt->space);
11550
#ifdef LIBXML_SAX1_ENABLED
11551
    if (ctxt->sax2)
11552
#endif /* LIBXML_SAX1_ENABLED */
11553
        name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
11554
#ifdef LIBXML_SAX1_ENABLED
11555
    else
11556
        name = xmlParseStartTag(ctxt);
11557
#endif /* LIBXML_SAX1_ENABLED */
11558
    if (ctxt->instate == XML_PARSER_EOF)
11559
        goto done;
11560
    if (name == NULL) {
11561
        spacePop(ctxt);
11562
        xmlHaltParser(ctxt);
11563
        if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11564
      ctxt->sax->endDocument(ctxt->userData);
11565
        goto done;
11566
    }
11567
#ifdef LIBXML_VALID_ENABLED
11568
    /*
11569
     * [ VC: Root Element Type ]
11570
     * The Name in the document type declaration must match
11571
     * the element type of the root element.
11572
     */
11573
    if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
11574
        ctxt->node && (ctxt->node == ctxt->myDoc->children))
11575
        ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
11576
#endif /* LIBXML_VALID_ENABLED */
11577
11578
    /*
11579
     * Check for an Empty Element.
11580
     */
11581
    if ((RAW == '/') && (NXT(1) == '>')) {
11582
        SKIP(2);
11583
11584
        if (ctxt->sax2) {
11585
      if ((ctxt->sax != NULL) &&
11586
          (ctxt->sax->endElementNs != NULL) &&
11587
          (!ctxt->disableSAX))
11588
          ctxt->sax->endElementNs(ctxt->userData, name,
11589
                                  prefix, URI);
11590
      if (ctxt->nsNr - nsNr > 0)
11591
          nsPop(ctxt, ctxt->nsNr - nsNr);
11592
#ifdef LIBXML_SAX1_ENABLED
11593
        } else {
11594
      if ((ctxt->sax != NULL) &&
11595
          (ctxt->sax->endElement != NULL) &&
11596
          (!ctxt->disableSAX))
11597
          ctxt->sax->endElement(ctxt->userData, name);
11598
#endif /* LIBXML_SAX1_ENABLED */
11599
        }
11600
        if (ctxt->instate == XML_PARSER_EOF)
11601
      goto done;
11602
        spacePop(ctxt);
11603
        if (ctxt->nameNr == 0) {
11604
      ctxt->instate = XML_PARSER_EPILOG;
11605
        } else {
11606
      ctxt->instate = XML_PARSER_CONTENT;
11607
        }
11608
                    ctxt->progressive = 1;
11609
        break;
11610
    }
11611
    if (RAW == '>') {
11612
        NEXT;
11613
    } else {
11614
        xmlFatalErrMsgStr(ctxt, XML_ERR_GT_REQUIRED,
11615
           "Couldn't find end of Start Tag %s\n",
11616
           name);
11617
        nodePop(ctxt);
11618
        spacePop(ctxt);
11619
    }
11620
                nameNsPush(ctxt, name, prefix, URI, line, ctxt->nsNr - nsNr);
11621
11622
    ctxt->instate = XML_PARSER_CONTENT;
11623
                ctxt->progressive = 1;
11624
                break;
11625
      }
11626
            case XML_PARSER_CONTENT: {
11627
    int id;
11628
    unsigned long cons;
11629
    if ((avail < 2) && (ctxt->inputNr == 1))
11630
        goto done;
11631
    cur = ctxt->input->cur[0];
11632
    next = ctxt->input->cur[1];
11633
11634
    id = ctxt->input->id;
11635
          cons = CUR_CONSUMED;
11636
    if ((cur == '<') && (next == '/')) {
11637
        ctxt->instate = XML_PARSER_END_TAG;
11638
        break;
11639
          } else if ((cur == '<') && (next == '?')) {
11640
        if ((!terminate) &&
11641
            (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
11642
                        ctxt->progressive = XML_PARSER_PI;
11643
      goto done;
11644
                    }
11645
        xmlParsePI(ctxt);
11646
        ctxt->instate = XML_PARSER_CONTENT;
11647
                    ctxt->progressive = 1;
11648
    } else if ((cur == '<') && (next != '!')) {
11649
        ctxt->instate = XML_PARSER_START_TAG;
11650
        break;
11651
    } else if ((cur == '<') && (next == '!') &&
11652
               (ctxt->input->cur[2] == '-') &&
11653
         (ctxt->input->cur[3] == '-')) {
11654
        int term;
11655
11656
              if (avail < 4)
11657
            goto done;
11658
        ctxt->input->cur += 4;
11659
        term = xmlParseLookupSequence(ctxt, '-', '-', '>');
11660
        ctxt->input->cur -= 4;
11661
        if ((!terminate) && (term < 0)) {
11662
                        ctxt->progressive = XML_PARSER_COMMENT;
11663
      goto done;
11664
                    }
11665
        xmlParseComment(ctxt);
11666
        ctxt->instate = XML_PARSER_CONTENT;
11667
                    ctxt->progressive = 1;
11668
    } else if ((cur == '<') && (ctxt->input->cur[1] == '!') &&
11669
        (ctxt->input->cur[2] == '[') &&
11670
        (ctxt->input->cur[3] == 'C') &&
11671
        (ctxt->input->cur[4] == 'D') &&
11672
        (ctxt->input->cur[5] == 'A') &&
11673
        (ctxt->input->cur[6] == 'T') &&
11674
        (ctxt->input->cur[7] == 'A') &&
11675
        (ctxt->input->cur[8] == '[')) {
11676
        SKIP(9);
11677
        ctxt->instate = XML_PARSER_CDATA_SECTION;
11678
        break;
11679
    } else if ((cur == '<') && (next == '!') &&
11680
               (avail < 9)) {
11681
        goto done;
11682
    } else if (cur == '&') {
11683
        if ((!terminate) &&
11684
            (xmlParseLookupSequence(ctxt, ';', 0, 0) < 0))
11685
      goto done;
11686
        xmlParseReference(ctxt);
11687
    } else {
11688
        /* TODO Avoid the extra copy, handle directly !!! */
11689
        /*
11690
         * Goal of the following test is:
11691
         *  - minimize calls to the SAX 'character' callback
11692
         *    when they are mergeable
11693
         *  - handle an problem for isBlank when we only parse
11694
         *    a sequence of blank chars and the next one is
11695
         *    not available to check against '<' presence.
11696
         *  - tries to homogenize the differences in SAX
11697
         *    callbacks between the push and pull versions
11698
         *    of the parser.
11699
         */
11700
        if ((ctxt->inputNr == 1) &&
11701
            (avail < XML_PARSER_BIG_BUFFER_SIZE)) {
11702
      if (!terminate) {
11703
          if (ctxt->progressive) {
11704
        if ((lastlt == NULL) ||
11705
            (ctxt->input->cur > lastlt))
11706
            goto done;
11707
          } else if (xmlParseLookupSequence(ctxt,
11708
                                            '<', 0, 0) < 0) {
11709
        goto done;
11710
          }
11711
      }
11712
                    }
11713
        ctxt->checkIndex = 0;
11714
        xmlParseCharData(ctxt, 0);
11715
    }
11716
    if ((cons == CUR_CONSUMED) && (id == ctxt->input->id)) {
11717
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
11718
                    "detected an error in element content\n");
11719
        xmlHaltParser(ctxt);
11720
        break;
11721
    }
11722
    break;
11723
      }
11724
            case XML_PARSER_END_TAG:
11725
    if (avail < 2)
11726
        goto done;
11727
    if (!terminate) {
11728
        if (ctxt->progressive) {
11729
            /* > can be found unescaped in attribute values */
11730
            if ((lastgt == NULL) || (ctxt->input->cur >= lastgt))
11731
          goto done;
11732
        } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) {
11733
      goto done;
11734
        }
11735
    }
11736
    if (ctxt->sax2) {
11737
              xmlParseEndTag2(ctxt, &ctxt->pushTab[ctxt->nameNr - 1]);
11738
        nameNsPop(ctxt);
11739
    }
11740
#ifdef LIBXML_SAX1_ENABLED
11741
      else
11742
        xmlParseEndTag1(ctxt, 0);
11743
#endif /* LIBXML_SAX1_ENABLED */
11744
    if (ctxt->instate == XML_PARSER_EOF) {
11745
        /* Nothing */
11746
    } else if (ctxt->nameNr == 0) {
11747
        ctxt->instate = XML_PARSER_EPILOG;
11748
    } else {
11749
        ctxt->instate = XML_PARSER_CONTENT;
11750
    }
11751
    break;
11752
            case XML_PARSER_CDATA_SECTION: {
11753
          /*
11754
     * The Push mode need to have the SAX callback for
11755
     * cdataBlock merge back contiguous callbacks.
11756
     */
11757
    int base;
11758
11759
    base = xmlParseLookupSequence(ctxt, ']', ']', '>');
11760
    if (base < 0) {
11761
        if (avail >= XML_PARSER_BIG_BUFFER_SIZE + 2) {
11762
            int tmp;
11763
11764
      tmp = xmlCheckCdataPush(ctxt->input->cur,
11765
                              XML_PARSER_BIG_BUFFER_SIZE, 0);
11766
      if (tmp < 0) {
11767
          tmp = -tmp;
11768
          ctxt->input->cur += tmp;
11769
          goto encoding_error;
11770
      }
11771
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
11772
          if (ctxt->sax->cdataBlock != NULL)
11773
        ctxt->sax->cdataBlock(ctxt->userData,
11774
                              ctxt->input->cur, tmp);
11775
          else if (ctxt->sax->characters != NULL)
11776
        ctxt->sax->characters(ctxt->userData,
11777
                              ctxt->input->cur, tmp);
11778
      }
11779
      if (ctxt->instate == XML_PARSER_EOF)
11780
          goto done;
11781
      SKIPL(tmp);
11782
      ctxt->checkIndex = 0;
11783
        }
11784
        goto done;
11785
    } else {
11786
        int tmp;
11787
11788
        tmp = xmlCheckCdataPush(ctxt->input->cur, base, 1);
11789
        if ((tmp < 0) || (tmp != base)) {
11790
      tmp = -tmp;
11791
      ctxt->input->cur += tmp;
11792
      goto encoding_error;
11793
        }
11794
        if ((ctxt->sax != NULL) && (base == 0) &&
11795
            (ctxt->sax->cdataBlock != NULL) &&
11796
            (!ctxt->disableSAX)) {
11797
      /*
11798
       * Special case to provide identical behaviour
11799
       * between pull and push parsers on enpty CDATA
11800
       * sections
11801
       */
11802
       if ((ctxt->input->cur - ctxt->input->base >= 9) &&
11803
           (!strncmp((const char *)&ctxt->input->cur[-9],
11804
                     "<![CDATA[", 9)))
11805
           ctxt->sax->cdataBlock(ctxt->userData,
11806
                                 BAD_CAST "", 0);
11807
        } else if ((ctxt->sax != NULL) && (base > 0) &&
11808
      (!ctxt->disableSAX)) {
11809
      if (ctxt->sax->cdataBlock != NULL)
11810
          ctxt->sax->cdataBlock(ctxt->userData,
11811
              ctxt->input->cur, base);
11812
      else if (ctxt->sax->characters != NULL)
11813
          ctxt->sax->characters(ctxt->userData,
11814
              ctxt->input->cur, base);
11815
        }
11816
        if (ctxt->instate == XML_PARSER_EOF)
11817
      goto done;
11818
        SKIPL(base + 3);
11819
        ctxt->checkIndex = 0;
11820
        ctxt->instate = XML_PARSER_CONTENT;
11821
#ifdef DEBUG_PUSH
11822
        xmlGenericError(xmlGenericErrorContext,
11823
          "PP: entering CONTENT\n");
11824
#endif
11825
    }
11826
    break;
11827
      }
11828
            case XML_PARSER_MISC:
11829
    SKIP_BLANKS;
11830
    if (ctxt->input->buf == NULL)
11831
        avail = ctxt->input->length -
11832
                (ctxt->input->cur - ctxt->input->base);
11833
    else
11834
        avail = xmlBufUse(ctxt->input->buf->buffer) -
11835
                (ctxt->input->cur - ctxt->input->base);
11836
    if (avail < 2)
11837
        goto done;
11838
    cur = ctxt->input->cur[0];
11839
    next = ctxt->input->cur[1];
11840
          if ((cur == '<') && (next == '?')) {
11841
        if ((!terminate) &&
11842
            (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
11843
                        ctxt->progressive = XML_PARSER_PI;
11844
      goto done;
11845
                    }
11846
#ifdef DEBUG_PUSH
11847
        xmlGenericError(xmlGenericErrorContext,
11848
          "PP: Parsing PI\n");
11849
#endif
11850
        xmlParsePI(ctxt);
11851
        if (ctxt->instate == XML_PARSER_EOF)
11852
      goto done;
11853
        ctxt->instate = XML_PARSER_MISC;
11854
                    ctxt->progressive = 1;
11855
        ctxt->checkIndex = 0;
11856
    } else if ((cur == '<') && (next == '!') &&
11857
        (ctxt->input->cur[2] == '-') &&
11858
        (ctxt->input->cur[3] == '-')) {
11859
        if ((!terminate) &&
11860
            (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
11861
                        ctxt->progressive = XML_PARSER_COMMENT;
11862
      goto done;
11863
                    }
11864
#ifdef DEBUG_PUSH
11865
        xmlGenericError(xmlGenericErrorContext,
11866
          "PP: Parsing Comment\n");
11867
#endif
11868
        xmlParseComment(ctxt);
11869
        if (ctxt->instate == XML_PARSER_EOF)
11870
      goto done;
11871
        ctxt->instate = XML_PARSER_MISC;
11872
                    ctxt->progressive = 1;
11873
        ctxt->checkIndex = 0;
11874
    } else if ((cur == '<') && (next == '!') &&
11875
        (ctxt->input->cur[2] == 'D') &&
11876
        (ctxt->input->cur[3] == 'O') &&
11877
        (ctxt->input->cur[4] == 'C') &&
11878
        (ctxt->input->cur[5] == 'T') &&
11879
        (ctxt->input->cur[6] == 'Y') &&
11880
        (ctxt->input->cur[7] == 'P') &&
11881
        (ctxt->input->cur[8] == 'E')) {
11882
        if ((!terminate) &&
11883
            (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0)) {
11884
                        ctxt->progressive = XML_PARSER_DTD;
11885
      goto done;
11886
                    }
11887
#ifdef DEBUG_PUSH
11888
        xmlGenericError(xmlGenericErrorContext,
11889
          "PP: Parsing internal subset\n");
11890
#endif
11891
        ctxt->inSubset = 1;
11892
                    ctxt->progressive = 0;
11893
        ctxt->checkIndex = 0;
11894
        xmlParseDocTypeDecl(ctxt);
11895
        if (ctxt->instate == XML_PARSER_EOF)
11896
      goto done;
11897
        if (RAW == '[') {
11898
      ctxt->instate = XML_PARSER_DTD;
11899
#ifdef DEBUG_PUSH
11900
      xmlGenericError(xmlGenericErrorContext,
11901
        "PP: entering DTD\n");
11902
#endif
11903
        } else {
11904
      /*
11905
       * Create and update the external subset.
11906
       */
11907
      ctxt->inSubset = 2;
11908
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
11909
          (ctxt->sax->externalSubset != NULL))
11910
          ctxt->sax->externalSubset(ctxt->userData,
11911
            ctxt->intSubName, ctxt->extSubSystem,
11912
            ctxt->extSubURI);
11913
      ctxt->inSubset = 0;
11914
      xmlCleanSpecialAttr(ctxt);
11915
      ctxt->instate = XML_PARSER_PROLOG;
11916
#ifdef DEBUG_PUSH
11917
      xmlGenericError(xmlGenericErrorContext,
11918
        "PP: entering PROLOG\n");
11919
#endif
11920
        }
11921
    } else if ((cur == '<') && (next == '!') &&
11922
               (avail < 9)) {
11923
        goto done;
11924
    } else {
11925
        ctxt->instate = XML_PARSER_START_TAG;
11926
        ctxt->progressive = XML_PARSER_START_TAG;
11927
        xmlParseGetLasts(ctxt, &lastlt, &lastgt);
11928
#ifdef DEBUG_PUSH
11929
        xmlGenericError(xmlGenericErrorContext,
11930
          "PP: entering START_TAG\n");
11931
#endif
11932
    }
11933
    break;
11934
            case XML_PARSER_PROLOG:
11935
    SKIP_BLANKS;
11936
    if (ctxt->input->buf == NULL)
11937
        avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
11938
    else
11939
        avail = xmlBufUse(ctxt->input->buf->buffer) -
11940
                            (ctxt->input->cur - ctxt->input->base);
11941
    if (avail < 2)
11942
        goto done;
11943
    cur = ctxt->input->cur[0];
11944
    next = ctxt->input->cur[1];
11945
          if ((cur == '<') && (next == '?')) {
11946
        if ((!terminate) &&
11947
            (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
11948
                        ctxt->progressive = XML_PARSER_PI;
11949
      goto done;
11950
                    }
11951
#ifdef DEBUG_PUSH
11952
        xmlGenericError(xmlGenericErrorContext,
11953
          "PP: Parsing PI\n");
11954
#endif
11955
        xmlParsePI(ctxt);
11956
        if (ctxt->instate == XML_PARSER_EOF)
11957
      goto done;
11958
        ctxt->instate = XML_PARSER_PROLOG;
11959
                    ctxt->progressive = 1;
11960
    } else if ((cur == '<') && (next == '!') &&
11961
        (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
11962
        if ((!terminate) &&
11963
            (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
11964
                        ctxt->progressive = XML_PARSER_COMMENT;
11965
      goto done;
11966
                    }
11967
#ifdef DEBUG_PUSH
11968
        xmlGenericError(xmlGenericErrorContext,
11969
          "PP: Parsing Comment\n");
11970
#endif
11971
        xmlParseComment(ctxt);
11972
        if (ctxt->instate == XML_PARSER_EOF)
11973
      goto done;
11974
        ctxt->instate = XML_PARSER_PROLOG;
11975
                    ctxt->progressive = 1;
11976
    } else if ((cur == '<') && (next == '!') &&
11977
               (avail < 4)) {
11978
        goto done;
11979
    } else {
11980
        ctxt->instate = XML_PARSER_START_TAG;
11981
        if (ctxt->progressive == 0)
11982
      ctxt->progressive = XML_PARSER_START_TAG;
11983
        xmlParseGetLasts(ctxt, &lastlt, &lastgt);
11984
#ifdef DEBUG_PUSH
11985
        xmlGenericError(xmlGenericErrorContext,
11986
          "PP: entering START_TAG\n");
11987
#endif
11988
    }
11989
    break;
11990
            case XML_PARSER_EPILOG:
11991
    SKIP_BLANKS;
11992
    if (ctxt->input->buf == NULL)
11993
        avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
11994
    else
11995
        avail = xmlBufUse(ctxt->input->buf->buffer) -
11996
                            (ctxt->input->cur - ctxt->input->base);
11997
    if (avail < 2)
11998
        goto done;
11999
    cur = ctxt->input->cur[0];
12000
    next = ctxt->input->cur[1];
12001
          if ((cur == '<') && (next == '?')) {
12002
        if ((!terminate) &&
12003
            (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
12004
                        ctxt->progressive = XML_PARSER_PI;
12005
      goto done;
12006
                    }
12007
#ifdef DEBUG_PUSH
12008
        xmlGenericError(xmlGenericErrorContext,
12009
          "PP: Parsing PI\n");
12010
#endif
12011
        xmlParsePI(ctxt);
12012
        if (ctxt->instate == XML_PARSER_EOF)
12013
      goto done;
12014
        ctxt->instate = XML_PARSER_EPILOG;
12015
                    ctxt->progressive = 1;
12016
    } else if ((cur == '<') && (next == '!') &&
12017
        (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
12018
        if ((!terminate) &&
12019
            (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
12020
                        ctxt->progressive = XML_PARSER_COMMENT;
12021
      goto done;
12022
                    }
12023
#ifdef DEBUG_PUSH
12024
        xmlGenericError(xmlGenericErrorContext,
12025
          "PP: Parsing Comment\n");
12026
#endif
12027
        xmlParseComment(ctxt);
12028
        if (ctxt->instate == XML_PARSER_EOF)
12029
      goto done;
12030
        ctxt->instate = XML_PARSER_EPILOG;
12031
                    ctxt->progressive = 1;
12032
    } else if ((cur == '<') && (next == '!') &&
12033
               (avail < 4)) {
12034
        goto done;
12035
    } else {
12036
        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
12037
        xmlHaltParser(ctxt);
12038
#ifdef DEBUG_PUSH
12039
        xmlGenericError(xmlGenericErrorContext,
12040
          "PP: entering EOF\n");
12041
#endif
12042
        if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
12043
      ctxt->sax->endDocument(ctxt->userData);
12044
        goto done;
12045
    }
12046
    break;
12047
            case XML_PARSER_DTD: {
12048
          /*
12049
     * Sorry but progressive parsing of the internal subset
12050
     * is not expected to be supported. We first check that
12051
     * the full content of the internal subset is available and
12052
     * the parsing is launched only at that point.
12053
     * Internal subset ends up with "']' S? '>'" in an unescaped
12054
     * section and not in a ']]>' sequence which are conditional
12055
     * sections (whoever argued to keep that crap in XML deserve
12056
     * a place in hell !).
12057
     */
12058
    int base, i;
12059
    xmlChar *buf;
12060
          xmlChar quote = 0;
12061
                size_t use;
12062
12063
    base = ctxt->input->cur - ctxt->input->base;
12064
    if (base < 0) return(0);
12065
    if (ctxt->checkIndex > base)
12066
        base = ctxt->checkIndex;
12067
    buf = xmlBufContent(ctxt->input->buf->buffer);
12068
                use = xmlBufUse(ctxt->input->buf->buffer);
12069
    for (;(unsigned int) base < use; base++) {
12070
        if (quote != 0) {
12071
            if (buf[base] == quote)
12072
          quote = 0;
12073
      continue;
12074
        }
12075
        if ((quote == 0) && (buf[base] == '<')) {
12076
            int found  = 0;
12077
      /* special handling of comments */
12078
            if (((unsigned int) base + 4 < use) &&
12079
          (buf[base + 1] == '!') &&
12080
          (buf[base + 2] == '-') &&
12081
          (buf[base + 3] == '-')) {
12082
          for (;(unsigned int) base + 3 < use; base++) {
12083
        if ((buf[base] == '-') &&
12084
            (buf[base + 1] == '-') &&
12085
            (buf[base + 2] == '>')) {
12086
            found = 1;
12087
            base += 2;
12088
            break;
12089
        }
12090
                }
12091
          if (!found) {
12092
#if 0
12093
              fprintf(stderr, "unfinished comment\n");
12094
#endif
12095
              break; /* for */
12096
                }
12097
                continue;
12098
      }
12099
        }
12100
        if (buf[base] == '"') {
12101
            quote = '"';
12102
      continue;
12103
        }
12104
        if (buf[base] == '\'') {
12105
            quote = '\'';
12106
      continue;
12107
        }
12108
        if (buf[base] == ']') {
12109
#if 0
12110
            fprintf(stderr, "%c%c%c%c: ", buf[base],
12111
              buf[base + 1], buf[base + 2], buf[base + 3]);
12112
#endif
12113
            if ((unsigned int) base +1 >= use)
12114
          break;
12115
      if (buf[base + 1] == ']') {
12116
          /* conditional crap, skip both ']' ! */
12117
          base++;
12118
          continue;
12119
      }
12120
            for (i = 1; (unsigned int) base + i < use; i++) {
12121
          if (buf[base + i] == '>') {
12122
#if 0
12123
              fprintf(stderr, "found\n");
12124
#endif
12125
              goto found_end_int_subset;
12126
          }
12127
          if (!IS_BLANK_CH(buf[base + i])) {
12128
#if 0
12129
              fprintf(stderr, "not found\n");
12130
#endif
12131
              goto not_end_of_int_subset;
12132
          }
12133
      }
12134
#if 0
12135
      fprintf(stderr, "end of stream\n");
12136
#endif
12137
            break;
12138
12139
        }
12140
not_end_of_int_subset:
12141
                    continue; /* for */
12142
    }
12143
    /*
12144
     * We didn't found the end of the Internal subset
12145
     */
12146
                if (quote == 0)
12147
                    ctxt->checkIndex = base;
12148
                else
12149
                    ctxt->checkIndex = 0;
12150
#ifdef DEBUG_PUSH
12151
    if (next == 0)
12152
        xmlGenericError(xmlGenericErrorContext,
12153
          "PP: lookup of int subset end filed\n");
12154
#endif
12155
          goto done;
12156
12157
found_end_int_subset:
12158
                ctxt->checkIndex = 0;
12159
    xmlParseInternalSubset(ctxt);
12160
    if (ctxt->instate == XML_PARSER_EOF)
12161
        goto done;
12162
    ctxt->inSubset = 2;
12163
    if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
12164
        (ctxt->sax->externalSubset != NULL))
12165
        ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
12166
          ctxt->extSubSystem, ctxt->extSubURI);
12167
    ctxt->inSubset = 0;
12168
    xmlCleanSpecialAttr(ctxt);
12169
    if (ctxt->instate == XML_PARSER_EOF)
12170
        goto done;
12171
    ctxt->instate = XML_PARSER_PROLOG;
12172
    ctxt->checkIndex = 0;
12173
#ifdef DEBUG_PUSH
12174
    xmlGenericError(xmlGenericErrorContext,
12175
      "PP: entering PROLOG\n");
12176
#endif
12177
                break;
12178
      }
12179
            case XML_PARSER_COMMENT:
12180
    xmlGenericError(xmlGenericErrorContext,
12181
      "PP: internal error, state == COMMENT\n");
12182
    ctxt->instate = XML_PARSER_CONTENT;
12183
#ifdef DEBUG_PUSH
12184
    xmlGenericError(xmlGenericErrorContext,
12185
      "PP: entering CONTENT\n");
12186
#endif
12187
    break;
12188
            case XML_PARSER_IGNORE:
12189
    xmlGenericError(xmlGenericErrorContext,
12190
      "PP: internal error, state == IGNORE");
12191
          ctxt->instate = XML_PARSER_DTD;
12192
#ifdef DEBUG_PUSH
12193
    xmlGenericError(xmlGenericErrorContext,
12194
      "PP: entering DTD\n");
12195
#endif
12196
          break;
12197
            case XML_PARSER_PI:
12198
    xmlGenericError(xmlGenericErrorContext,
12199
      "PP: internal error, state == PI\n");
12200
    ctxt->instate = XML_PARSER_CONTENT;
12201
#ifdef DEBUG_PUSH
12202
    xmlGenericError(xmlGenericErrorContext,
12203
      "PP: entering CONTENT\n");
12204
#endif
12205
    break;
12206
            case XML_PARSER_ENTITY_DECL:
12207
    xmlGenericError(xmlGenericErrorContext,
12208
      "PP: internal error, state == ENTITY_DECL\n");
12209
    ctxt->instate = XML_PARSER_DTD;
12210
#ifdef DEBUG_PUSH
12211
    xmlGenericError(xmlGenericErrorContext,
12212
      "PP: entering DTD\n");
12213
#endif
12214
    break;
12215
            case XML_PARSER_ENTITY_VALUE:
12216
    xmlGenericError(xmlGenericErrorContext,
12217
      "PP: internal error, state == ENTITY_VALUE\n");
12218
    ctxt->instate = XML_PARSER_CONTENT;
12219
#ifdef DEBUG_PUSH
12220
    xmlGenericError(xmlGenericErrorContext,
12221
      "PP: entering DTD\n");
12222
#endif
12223
    break;
12224
            case XML_PARSER_ATTRIBUTE_VALUE:
12225
    xmlGenericError(xmlGenericErrorContext,
12226
      "PP: internal error, state == ATTRIBUTE_VALUE\n");
12227
    ctxt->instate = XML_PARSER_START_TAG;
12228
#ifdef DEBUG_PUSH
12229
    xmlGenericError(xmlGenericErrorContext,
12230
      "PP: entering START_TAG\n");
12231
#endif
12232
    break;
12233
            case XML_PARSER_SYSTEM_LITERAL:
12234
    xmlGenericError(xmlGenericErrorContext,
12235
      "PP: internal error, state == SYSTEM_LITERAL\n");
12236
    ctxt->instate = XML_PARSER_START_TAG;
12237
#ifdef DEBUG_PUSH
12238
    xmlGenericError(xmlGenericErrorContext,
12239
      "PP: entering START_TAG\n");
12240
#endif
12241
    break;
12242
            case XML_PARSER_PUBLIC_LITERAL:
12243
    xmlGenericError(xmlGenericErrorContext,
12244
      "PP: internal error, state == PUBLIC_LITERAL\n");
12245
    ctxt->instate = XML_PARSER_START_TAG;
12246
#ifdef DEBUG_PUSH
12247
    xmlGenericError(xmlGenericErrorContext,
12248
      "PP: entering START_TAG\n");
12249
#endif
12250
    break;
12251
  }
12252
    }
12253
done:
12254
#ifdef DEBUG_PUSH
12255
    xmlGenericError(xmlGenericErrorContext, "PP: done %d\n", ret);
12256
#endif
12257
    return(ret);
12258
encoding_error:
12259
    {
12260
        char buffer[150];
12261
12262
  snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
12263
      ctxt->input->cur[0], ctxt->input->cur[1],
12264
      ctxt->input->cur[2], ctxt->input->cur[3]);
12265
  __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
12266
         "Input is not proper UTF-8, indicate encoding !\n%s",
12267
         BAD_CAST buffer, NULL);
12268
    }
12269
    return(0);
12270
}
12271
12272
/**
12273
 * xmlParseCheckTransition:
12274
 * @ctxt:  an XML parser context
12275
 * @chunk:  a char array
12276
 * @size:  the size in byte of the chunk
12277
 *
12278
 * Check depending on the current parser state if the chunk given must be
12279
 * processed immediately or one need more data to advance on parsing.
12280
 *
12281
 * Returns -1 in case of error, 0 if the push is not needed and 1 if needed
12282
 */
12283
static int
12284
xmlParseCheckTransition(xmlParserCtxtPtr ctxt, const char *chunk, int size) {
12285
    if ((ctxt == NULL) || (chunk == NULL) || (size < 0))
12286
        return(-1);
12287
    if (ctxt->instate == XML_PARSER_START_TAG) {
12288
        if (memchr(chunk, '>', size) != NULL)
12289
            return(1);
12290
        return(0);
12291
    }
12292
    if (ctxt->progressive == XML_PARSER_COMMENT) {
12293
        if (memchr(chunk, '>', size) != NULL)
12294
            return(1);
12295
        return(0);
12296
    }
12297
    if (ctxt->instate == XML_PARSER_CDATA_SECTION) {
12298
        if (memchr(chunk, '>', size) != NULL)
12299
            return(1);
12300
        return(0);
12301
    }
12302
    if (ctxt->progressive == XML_PARSER_PI) {
12303
        if (memchr(chunk, '>', size) != NULL)
12304
            return(1);
12305
        return(0);
12306
    }
12307
    if (ctxt->instate == XML_PARSER_END_TAG) {
12308
        if (memchr(chunk, '>', size) != NULL)
12309
            return(1);
12310
        return(0);
12311
    }
12312
    if ((ctxt->progressive == XML_PARSER_DTD) ||
12313
        (ctxt->instate == XML_PARSER_DTD)) {
12314
        if (memchr(chunk, '>', size) != NULL)
12315
            return(1);
12316
        return(0);
12317
    }
12318
    return(1);
12319
}
12320
12321
/**
12322
 * xmlParseChunk:
12323
 * @ctxt:  an XML parser context
12324
 * @chunk:  an char array
12325
 * @size:  the size in byte of the chunk
12326
 * @terminate:  last chunk indicator
12327
 *
12328
 * Parse a Chunk of memory
12329
 *
12330
 * Returns zero if no error, the xmlParserErrors otherwise.
12331
 */
12332
int
12333
xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
12334
              int terminate) {
12335
    int end_in_lf = 0;
12336
    int remain = 0;
12337
    size_t old_avail = 0;
12338
    size_t avail = 0;
12339
12340
    if (ctxt == NULL)
12341
        return(XML_ERR_INTERNAL_ERROR);
12342
    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
12343
        return(ctxt->errNo);
12344
    if (ctxt->instate == XML_PARSER_EOF)
12345
        return(-1);
12346
    if (ctxt->instate == XML_PARSER_START)
12347
        xmlDetectSAX2(ctxt);
12348
    if ((size > 0) && (chunk != NULL) && (!terminate) &&
12349
        (chunk[size - 1] == '\r')) {
12350
  end_in_lf = 1;
12351
  size--;
12352
    }
12353
12354
xmldecl_done:
12355
12356
    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
12357
        (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF))  {
12358
  size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
12359
  size_t cur = ctxt->input->cur - ctxt->input->base;
12360
  int res;
12361
12362
        old_avail = xmlBufUse(ctxt->input->buf->buffer);
12363
        /*
12364
         * Specific handling if we autodetected an encoding, we should not
12365
         * push more than the first line ... which depend on the encoding
12366
         * And only push the rest once the final encoding was detected
12367
         */
12368
        if ((ctxt->instate == XML_PARSER_START) && (ctxt->input != NULL) &&
12369
            (ctxt->input->buf != NULL) && (ctxt->input->buf->encoder != NULL)) {
12370
            unsigned int len = 45;
12371
12372
            if ((xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
12373
                               BAD_CAST "UTF-16")) ||
12374
                (xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
12375
                               BAD_CAST "UTF16")))
12376
                len = 90;
12377
            else if ((xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
12378
                                    BAD_CAST "UCS-4")) ||
12379
                     (xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
12380
                                    BAD_CAST "UCS4")))
12381
                len = 180;
12382
12383
            if (ctxt->input->buf->rawconsumed < len)
12384
                len -= ctxt->input->buf->rawconsumed;
12385
12386
            /*
12387
             * Change size for reading the initial declaration only
12388
             * if size is greater than len. Otherwise, memmove in xmlBufferAdd
12389
             * will blindly copy extra bytes from memory.
12390
             */
12391
            if ((unsigned int) size > len) {
12392
                remain = size - len;
12393
                size = len;
12394
            } else {
12395
                remain = 0;
12396
            }
12397
        }
12398
  res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
12399
        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
12400
  if (res < 0) {
12401
      ctxt->errNo = XML_PARSER_EOF;
12402
      xmlHaltParser(ctxt);
12403
      return (XML_PARSER_EOF);
12404
  }
12405
#ifdef DEBUG_PUSH
12406
  xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
12407
#endif
12408
12409
    } else if (ctxt->instate != XML_PARSER_EOF) {
12410
  if ((ctxt->input != NULL) && ctxt->input->buf != NULL) {
12411
      xmlParserInputBufferPtr in = ctxt->input->buf;
12412
      if ((in->encoder != NULL) && (in->buffer != NULL) &&
12413
        (in->raw != NULL)) {
12414
    int nbchars;
12415
    size_t base = xmlBufGetInputBase(in->buffer, ctxt->input);
12416
    size_t current = ctxt->input->cur - ctxt->input->base;
12417
12418
    nbchars = xmlCharEncInput(in, terminate);
12419
    xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
12420
    if (nbchars < 0) {
12421
        /* TODO 2.6.0 */
12422
        xmlGenericError(xmlGenericErrorContext,
12423
            "xmlParseChunk: encoder error\n");
12424
                    xmlHaltParser(ctxt);
12425
        return(XML_ERR_INVALID_ENCODING);
12426
    }
12427
      }
12428
  }
12429
    }
12430
    if (remain != 0) {
12431
        xmlParseTryOrFinish(ctxt, 0);
12432
    } else {
12433
        if ((ctxt->input != NULL) && (ctxt->input->buf != NULL))
12434
            avail = xmlBufUse(ctxt->input->buf->buffer);
12435
        /*
12436
         * Depending on the current state it may not be such
12437
         * a good idea to try parsing if there is nothing in the chunk
12438
         * which would be worth doing a parser state transition and we
12439
         * need to wait for more data
12440
         */
12441
        if ((terminate) || (avail > XML_MAX_TEXT_LENGTH) ||
12442
            (old_avail == 0) || (avail == 0) ||
12443
            (xmlParseCheckTransition(ctxt,
12444
                       (const char *)&ctxt->input->base[old_avail],
12445
                                     avail - old_avail)))
12446
            xmlParseTryOrFinish(ctxt, terminate);
12447
    }
12448
    if (ctxt->instate == XML_PARSER_EOF)
12449
        return(ctxt->errNo);
12450
12451
    if ((ctxt->input != NULL) &&
12452
         (((ctxt->input->end - ctxt->input->cur) > XML_MAX_LOOKUP_LIMIT) ||
12453
         ((ctxt->input->cur - ctxt->input->base) > XML_MAX_LOOKUP_LIMIT)) &&
12454
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
12455
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
12456
        xmlHaltParser(ctxt);
12457
    }
12458
    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
12459
        return(ctxt->errNo);
12460
12461
    if (remain != 0) {
12462
        chunk += size;
12463
        size = remain;
12464
        remain = 0;
12465
        goto xmldecl_done;
12466
    }
12467
    if ((end_in_lf == 1) && (ctxt->input != NULL) &&
12468
        (ctxt->input->buf != NULL)) {
12469
  size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer,
12470
           ctxt->input);
12471
  size_t current = ctxt->input->cur - ctxt->input->base;
12472
12473
  xmlParserInputBufferPush(ctxt->input->buf, 1, "\r");
12474
12475
  xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input,
12476
            base, current);
12477
    }
12478
    if (terminate) {
12479
  /*
12480
   * Check for termination
12481
   */
12482
  int cur_avail = 0;
12483
12484
  if (ctxt->input != NULL) {
12485
      if (ctxt->input->buf == NULL)
12486
    cur_avail = ctxt->input->length -
12487
          (ctxt->input->cur - ctxt->input->base);
12488
      else
12489
    cur_avail = xmlBufUse(ctxt->input->buf->buffer) -
12490
                    (ctxt->input->cur - ctxt->input->base);
12491
  }
12492
12493
  if ((ctxt->instate != XML_PARSER_EOF) &&
12494
      (ctxt->instate != XML_PARSER_EPILOG)) {
12495
      xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
12496
  }
12497
  if ((ctxt->instate == XML_PARSER_EPILOG) && (cur_avail > 0)) {
12498
      xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
12499
  }
12500
  if (ctxt->instate != XML_PARSER_EOF) {
12501
      if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
12502
    ctxt->sax->endDocument(ctxt->userData);
12503
  }
12504
  ctxt->instate = XML_PARSER_EOF;
12505
    }
12506
    if (ctxt->wellFormed == 0)
12507
  return((xmlParserErrors) ctxt->errNo);
12508
    else
12509
        return(0);
12510
}
12511
12512
/************************************************************************
12513
 *                  *
12514
 *    I/O front end functions to the parser     *
12515
 *                  *
12516
 ************************************************************************/
12517
12518
/**
12519
 * xmlCreatePushParserCtxt:
12520
 * @sax:  a SAX handler
12521
 * @user_data:  The user data returned on SAX callbacks
12522
 * @chunk:  a pointer to an array of chars
12523
 * @size:  number of chars in the array
12524
 * @filename:  an optional file name or URI
12525
 *
12526
 * Create a parser context for using the XML parser in push mode.
12527
 * If @buffer and @size are non-NULL, the data is used to detect
12528
 * the encoding.  The remaining characters will be parsed so they
12529
 * don't need to be fed in again through xmlParseChunk.
12530
 * To allow content encoding detection, @size should be >= 4
12531
 * The value of @filename is used for fetching external entities
12532
 * and error/warning reports.
12533
 *
12534
 * Returns the new parser context or NULL
12535
 */
12536
12537
xmlParserCtxtPtr
12538
xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
12539
                        const char *chunk, int size, const char *filename) {
12540
    xmlParserCtxtPtr ctxt;
12541
    xmlParserInputPtr inputStream;
12542
    xmlParserInputBufferPtr buf;
12543
    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
12544
12545
    /*
12546
     * plug some encoding conversion routines
12547
     */
12548
    if ((chunk != NULL) && (size >= 4))
12549
  enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
12550
12551
    buf = xmlAllocParserInputBuffer(enc);
12552
    if (buf == NULL) return(NULL);
12553
12554
    ctxt = xmlNewSAXParserCtxt(sax, user_data);
12555
    if (ctxt == NULL) {
12556
        xmlErrMemory(NULL, "creating parser: out of memory\n");
12557
  xmlFreeParserInputBuffer(buf);
12558
  return(NULL);
12559
    }
12560
    ctxt->dictNames = 1;
12561
    if (filename == NULL) {
12562
  ctxt->directory = NULL;
12563
    } else {
12564
        ctxt->directory = xmlParserGetDirectory(filename);
12565
    }
12566
12567
    inputStream = xmlNewInputStream(ctxt);
12568
    if (inputStream == NULL) {
12569
  xmlFreeParserCtxt(ctxt);
12570
  xmlFreeParserInputBuffer(buf);
12571
  return(NULL);
12572
    }
12573
12574
    if (filename == NULL)
12575
  inputStream->filename = NULL;
12576
    else {
12577
  inputStream->filename = (char *)
12578
      xmlCanonicPath((const xmlChar *) filename);
12579
  if (inputStream->filename == NULL) {
12580
            xmlFreeInputStream(inputStream);
12581
      xmlFreeParserCtxt(ctxt);
12582
      xmlFreeParserInputBuffer(buf);
12583
      return(NULL);
12584
  }
12585
    }
12586
    inputStream->buf = buf;
12587
    xmlBufResetInput(inputStream->buf->buffer, inputStream);
12588
    inputPush(ctxt, inputStream);
12589
12590
    /*
12591
     * If the caller didn't provide an initial 'chunk' for determining
12592
     * the encoding, we set the context to XML_CHAR_ENCODING_NONE so
12593
     * that it can be automatically determined later
12594
     */
12595
    if ((size == 0) || (chunk == NULL)) {
12596
  ctxt->charset = XML_CHAR_ENCODING_NONE;
12597
    } else if ((ctxt->input != NULL) && (ctxt->input->buf != NULL)) {
12598
  size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
12599
  size_t cur = ctxt->input->cur - ctxt->input->base;
12600
12601
  xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
12602
12603
        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
12604
#ifdef DEBUG_PUSH
12605
  xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
12606
#endif
12607
    }
12608
12609
    if (enc != XML_CHAR_ENCODING_NONE) {
12610
        xmlSwitchEncoding(ctxt, enc);
12611
    }
12612
12613
    return(ctxt);
12614
}
12615
#endif /* LIBXML_PUSH_ENABLED */
12616
12617
/**
12618
 * xmlHaltParser:
12619
 * @ctxt:  an XML parser context
12620
 *
12621
 * Blocks further parser processing don't override error
12622
 * for internal use
12623
 */
12624
static void
12625
14
xmlHaltParser(xmlParserCtxtPtr ctxt) {
12626
14
    if (ctxt == NULL)
12627
0
        return;
12628
14
    ctxt->instate = XML_PARSER_EOF;
12629
14
    ctxt->disableSAX = 1;
12630
14
    while (ctxt->inputNr > 1)
12631
0
        xmlFreeInputStream(inputPop(ctxt));
12632
14
    if (ctxt->input != NULL) {
12633
        /*
12634
   * in case there was a specific allocation deallocate before
12635
   * overriding base
12636
   */
12637
14
        if (ctxt->input->free != NULL) {
12638
0
      ctxt->input->free((xmlChar *) ctxt->input->base);
12639
0
      ctxt->input->free = NULL;
12640
0
  }
12641
14
        if (ctxt->input->buf != NULL) {
12642
14
            xmlFreeParserInputBuffer(ctxt->input->buf);
12643
14
            ctxt->input->buf = NULL;
12644
14
        }
12645
14
  ctxt->input->cur = BAD_CAST"";
12646
14
        ctxt->input->length = 0;
12647
14
  ctxt->input->base = ctxt->input->cur;
12648
14
        ctxt->input->end = ctxt->input->cur;
12649
14
    }
12650
14
}
12651
12652
/**
12653
 * xmlStopParser:
12654
 * @ctxt:  an XML parser context
12655
 *
12656
 * Blocks further parser processing
12657
 */
12658
void
12659
1.77M
xmlStopParser(xmlParserCtxtPtr ctxt) {
12660
1.77M
    if (ctxt == NULL)
12661
1.77M
        return;
12662
0
    xmlHaltParser(ctxt);
12663
0
    ctxt->errNo = XML_ERR_USER_STOP;
12664
0
}
12665
12666
/**
12667
 * xmlCreateIOParserCtxt:
12668
 * @sax:  a SAX handler
12669
 * @user_data:  The user data returned on SAX callbacks
12670
 * @ioread:  an I/O read function
12671
 * @ioclose:  an I/O close function
12672
 * @ioctx:  an I/O handler
12673
 * @enc:  the charset encoding if known
12674
 *
12675
 * Create a parser context for using the XML parser with an existing
12676
 * I/O stream
12677
 *
12678
 * Returns the new parser context or NULL
12679
 */
12680
xmlParserCtxtPtr
12681
xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
12682
  xmlInputReadCallback   ioread, xmlInputCloseCallback  ioclose,
12683
0
  void *ioctx, xmlCharEncoding enc) {
12684
0
    xmlParserCtxtPtr ctxt;
12685
0
    xmlParserInputPtr inputStream;
12686
0
    xmlParserInputBufferPtr buf;
12687
12688
0
    if (ioread == NULL) return(NULL);
12689
12690
0
    buf = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, enc);
12691
0
    if (buf == NULL) {
12692
0
        if (ioclose != NULL)
12693
0
            ioclose(ioctx);
12694
0
        return (NULL);
12695
0
    }
12696
12697
0
    ctxt = xmlNewSAXParserCtxt(sax, user_data);
12698
0
    if (ctxt == NULL) {
12699
0
  xmlFreeParserInputBuffer(buf);
12700
0
  return(NULL);
12701
0
    }
12702
12703
0
    inputStream = xmlNewIOInputStream(ctxt, buf, enc);
12704
0
    if (inputStream == NULL) {
12705
0
  xmlFreeParserCtxt(ctxt);
12706
0
  return(NULL);
12707
0
    }
12708
0
    inputPush(ctxt, inputStream);
12709
12710
0
    return(ctxt);
12711
0
}
12712
12713
#ifdef LIBXML_VALID_ENABLED
12714
/************************************************************************
12715
 *                  *
12716
 *    Front ends when parsing a DTD       *
12717
 *                  *
12718
 ************************************************************************/
12719
12720
/**
12721
 * xmlIOParseDTD:
12722
 * @sax:  the SAX handler block or NULL
12723
 * @input:  an Input Buffer
12724
 * @enc:  the charset encoding if known
12725
 *
12726
 * Load and parse a DTD
12727
 *
12728
 * Returns the resulting xmlDtdPtr or NULL in case of error.
12729
 * @input will be freed by the function in any case.
12730
 */
12731
12732
xmlDtdPtr
12733
xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
12734
        xmlCharEncoding enc) {
12735
    xmlDtdPtr ret = NULL;
12736
    xmlParserCtxtPtr ctxt;
12737
    xmlParserInputPtr pinput = NULL;
12738
    xmlChar start[4];
12739
12740
    if (input == NULL)
12741
  return(NULL);
12742
12743
    ctxt = xmlNewSAXParserCtxt(sax, NULL);
12744
    if (ctxt == NULL) {
12745
        xmlFreeParserInputBuffer(input);
12746
  return(NULL);
12747
    }
12748
12749
    /* We are loading a DTD */
12750
    ctxt->options |= XML_PARSE_DTDLOAD;
12751
12752
    xmlDetectSAX2(ctxt);
12753
12754
    /*
12755
     * generate a parser input from the I/O handler
12756
     */
12757
12758
    pinput = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
12759
    if (pinput == NULL) {
12760
        xmlFreeParserInputBuffer(input);
12761
  xmlFreeParserCtxt(ctxt);
12762
  return(NULL);
12763
    }
12764
12765
    /*
12766
     * plug some encoding conversion routines here.
12767
     */
12768
    if (xmlPushInput(ctxt, pinput) < 0) {
12769
  xmlFreeParserCtxt(ctxt);
12770
  return(NULL);
12771
    }
12772
    if (enc != XML_CHAR_ENCODING_NONE) {
12773
        xmlSwitchEncoding(ctxt, enc);
12774
    }
12775
12776
    pinput->filename = NULL;
12777
    pinput->line = 1;
12778
    pinput->col = 1;
12779
    pinput->base = ctxt->input->cur;
12780
    pinput->cur = ctxt->input->cur;
12781
    pinput->free = NULL;
12782
12783
    /*
12784
     * let's parse that entity knowing it's an external subset.
12785
     */
12786
    ctxt->inSubset = 2;
12787
    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
12788
    if (ctxt->myDoc == NULL) {
12789
  xmlErrMemory(ctxt, "New Doc failed");
12790
  return(NULL);
12791
    }
12792
    ctxt->myDoc->properties = XML_DOC_INTERNAL;
12793
    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
12794
                                 BAD_CAST "none", BAD_CAST "none");
12795
12796
    if ((enc == XML_CHAR_ENCODING_NONE) &&
12797
        ((ctxt->input->end - ctxt->input->cur) >= 4)) {
12798
  /*
12799
   * Get the 4 first bytes and decode the charset
12800
   * if enc != XML_CHAR_ENCODING_NONE
12801
   * plug some encoding conversion routines.
12802
   */
12803
  start[0] = RAW;
12804
  start[1] = NXT(1);
12805
  start[2] = NXT(2);
12806
  start[3] = NXT(3);
12807
  enc = xmlDetectCharEncoding(start, 4);
12808
  if (enc != XML_CHAR_ENCODING_NONE) {
12809
      xmlSwitchEncoding(ctxt, enc);
12810
  }
12811
    }
12812
12813
    xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none");
12814
12815
    if (ctxt->myDoc != NULL) {
12816
  if (ctxt->wellFormed) {
12817
      ret = ctxt->myDoc->extSubset;
12818
      ctxt->myDoc->extSubset = NULL;
12819
      if (ret != NULL) {
12820
    xmlNodePtr tmp;
12821
12822
    ret->doc = NULL;
12823
    tmp = ret->children;
12824
    while (tmp != NULL) {
12825
        tmp->doc = NULL;
12826
        tmp = tmp->next;
12827
    }
12828
      }
12829
  } else {
12830
      ret = NULL;
12831
  }
12832
        xmlFreeDoc(ctxt->myDoc);
12833
        ctxt->myDoc = NULL;
12834
    }
12835
    xmlFreeParserCtxt(ctxt);
12836
12837
    return(ret);
12838
}
12839
12840
/**
12841
 * xmlSAXParseDTD:
12842
 * @sax:  the SAX handler block
12843
 * @ExternalID:  a NAME* containing the External ID of the DTD
12844
 * @SystemID:  a NAME* containing the URL to the DTD
12845
 *
12846
 * DEPRECATED: Don't use.
12847
 *
12848
 * Load and parse an external subset.
12849
 *
12850
 * Returns the resulting xmlDtdPtr or NULL in case of error.
12851
 */
12852
12853
xmlDtdPtr
12854
xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
12855
                          const xmlChar *SystemID) {
12856
    xmlDtdPtr ret = NULL;
12857
    xmlParserCtxtPtr ctxt;
12858
    xmlParserInputPtr input = NULL;
12859
    xmlCharEncoding enc;
12860
    xmlChar* systemIdCanonic;
12861
12862
    if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
12863
12864
    ctxt = xmlNewSAXParserCtxt(sax, NULL);
12865
    if (ctxt == NULL) {
12866
  return(NULL);
12867
    }
12868
12869
    /* We are loading a DTD */
12870
    ctxt->options |= XML_PARSE_DTDLOAD;
12871
12872
    /*
12873
     * Canonicalise the system ID
12874
     */
12875
    systemIdCanonic = xmlCanonicPath(SystemID);
12876
    if ((SystemID != NULL) && (systemIdCanonic == NULL)) {
12877
  xmlFreeParserCtxt(ctxt);
12878
  return(NULL);
12879
    }
12880
12881
    /*
12882
     * Ask the Entity resolver to load the damn thing
12883
     */
12884
12885
    if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
12886
  input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
12887
                                   systemIdCanonic);
12888
    if (input == NULL) {
12889
  xmlFreeParserCtxt(ctxt);
12890
  if (systemIdCanonic != NULL)
12891
      xmlFree(systemIdCanonic);
12892
  return(NULL);
12893
    }
12894
12895
    /*
12896
     * plug some encoding conversion routines here.
12897
     */
12898
    if (xmlPushInput(ctxt, input) < 0) {
12899
  xmlFreeParserCtxt(ctxt);
12900
  if (systemIdCanonic != NULL)
12901
      xmlFree(systemIdCanonic);
12902
  return(NULL);
12903
    }
12904
    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
12905
  enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
12906
  xmlSwitchEncoding(ctxt, enc);
12907
    }
12908
12909
    if (input->filename == NULL)
12910
  input->filename = (char *) systemIdCanonic;
12911
    else
12912
  xmlFree(systemIdCanonic);
12913
    input->line = 1;
12914
    input->col = 1;
12915
    input->base = ctxt->input->cur;
12916
    input->cur = ctxt->input->cur;
12917
    input->free = NULL;
12918
12919
    /*
12920
     * let's parse that entity knowing it's an external subset.
12921
     */
12922
    ctxt->inSubset = 2;
12923
    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
12924
    if (ctxt->myDoc == NULL) {
12925
  xmlErrMemory(ctxt, "New Doc failed");
12926
  xmlFreeParserCtxt(ctxt);
12927
  return(NULL);
12928
    }
12929
    ctxt->myDoc->properties = XML_DOC_INTERNAL;
12930
    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
12931
                                 ExternalID, SystemID);
12932
    xmlParseExternalSubset(ctxt, ExternalID, SystemID);
12933
12934
    if (ctxt->myDoc != NULL) {
12935
  if (ctxt->wellFormed) {
12936
      ret = ctxt->myDoc->extSubset;
12937
      ctxt->myDoc->extSubset = NULL;
12938
      if (ret != NULL) {
12939
    xmlNodePtr tmp;
12940
12941
    ret->doc = NULL;
12942
    tmp = ret->children;
12943
    while (tmp != NULL) {
12944
        tmp->doc = NULL;
12945
        tmp = tmp->next;
12946
    }
12947
      }
12948
  } else {
12949
      ret = NULL;
12950
  }
12951
        xmlFreeDoc(ctxt->myDoc);
12952
        ctxt->myDoc = NULL;
12953
    }
12954
    xmlFreeParserCtxt(ctxt);
12955
12956
    return(ret);
12957
}
12958
12959
12960
/**
12961
 * xmlParseDTD:
12962
 * @ExternalID:  a NAME* containing the External ID of the DTD
12963
 * @SystemID:  a NAME* containing the URL to the DTD
12964
 *
12965
 * Load and parse an external subset.
12966
 *
12967
 * Returns the resulting xmlDtdPtr or NULL in case of error.
12968
 */
12969
12970
xmlDtdPtr
12971
xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
12972
    return(xmlSAXParseDTD(NULL, ExternalID, SystemID));
12973
}
12974
#endif /* LIBXML_VALID_ENABLED */
12975
12976
/************************************************************************
12977
 *                  *
12978
 *    Front ends when parsing an Entity     *
12979
 *                  *
12980
 ************************************************************************/
12981
12982
/**
12983
 * xmlParseCtxtExternalEntity:
12984
 * @ctx:  the existing parsing context
12985
 * @URL:  the URL for the entity to load
12986
 * @ID:  the System ID for the entity to load
12987
 * @lst:  the return value for the set of parsed nodes
12988
 *
12989
 * Parse an external general entity within an existing parsing context
12990
 * An external general parsed entity is well-formed if it matches the
12991
 * production labeled extParsedEnt.
12992
 *
12993
 * [78] extParsedEnt ::= TextDecl? content
12994
 *
12995
 * Returns 0 if the entity is well formed, -1 in case of args problem and
12996
 *    the parser error code otherwise
12997
 */
12998
12999
int
13000
xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
13001
0
                 const xmlChar *ID, xmlNodePtr *lst) {
13002
0
    void *userData;
13003
13004
0
    if (ctx == NULL) return(-1);
13005
    /*
13006
     * If the user provided their own SAX callbacks, then reuse the
13007
     * userData callback field, otherwise the expected setup in a
13008
     * DOM builder is to have userData == ctxt
13009
     */
13010
0
    if (ctx->userData == ctx)
13011
0
        userData = NULL;
13012
0
    else
13013
0
        userData = ctx->userData;
13014
0
    return xmlParseExternalEntityPrivate(ctx->myDoc, ctx, ctx->sax,
13015
0
                                         userData, ctx->depth + 1,
13016
0
                                         URL, ID, lst);
13017
0
}
13018
13019
/**
13020
 * xmlParseExternalEntityPrivate:
13021
 * @doc:  the document the chunk pertains to
13022
 * @oldctxt:  the previous parser context if available
13023
 * @sax:  the SAX handler block (possibly NULL)
13024
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
13025
 * @depth:  Used for loop detection, use 0
13026
 * @URL:  the URL for the entity to load
13027
 * @ID:  the System ID for the entity to load
13028
 * @list:  the return value for the set of parsed nodes
13029
 *
13030
 * Private version of xmlParseExternalEntity()
13031
 *
13032
 * Returns 0 if the entity is well formed, -1 in case of args problem and
13033
 *    the parser error code otherwise
13034
 */
13035
13036
static xmlParserErrors
13037
xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
13038
                xmlSAXHandlerPtr sax,
13039
          void *user_data, int depth, const xmlChar *URL,
13040
0
          const xmlChar *ID, xmlNodePtr *list) {
13041
0
    xmlParserCtxtPtr ctxt;
13042
0
    xmlDocPtr newDoc;
13043
0
    xmlNodePtr newRoot;
13044
0
    xmlParserErrors ret = XML_ERR_OK;
13045
0
    xmlChar start[4];
13046
0
    xmlCharEncoding enc;
13047
13048
0
    if (((depth > 40) &&
13049
0
  ((oldctxt == NULL) || (oldctxt->options & XML_PARSE_HUGE) == 0)) ||
13050
0
  (depth > 1024)) {
13051
0
  return(XML_ERR_ENTITY_LOOP);
13052
0
    }
13053
13054
0
    if (list != NULL)
13055
0
        *list = NULL;
13056
0
    if ((URL == NULL) && (ID == NULL))
13057
0
  return(XML_ERR_INTERNAL_ERROR);
13058
0
    if (doc == NULL)
13059
0
  return(XML_ERR_INTERNAL_ERROR);
13060
13061
0
    ctxt = xmlCreateEntityParserCtxtInternal(sax, user_data, URL, ID, NULL,
13062
0
                                             oldctxt);
13063
0
    if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
13064
0
    xmlDetectSAX2(ctxt);
13065
13066
0
    newDoc = xmlNewDoc(BAD_CAST "1.0");
13067
0
    if (newDoc == NULL) {
13068
0
  xmlFreeParserCtxt(ctxt);
13069
0
  return(XML_ERR_INTERNAL_ERROR);
13070
0
    }
13071
0
    newDoc->properties = XML_DOC_INTERNAL;
13072
0
    if (doc) {
13073
0
        newDoc->intSubset = doc->intSubset;
13074
0
        newDoc->extSubset = doc->extSubset;
13075
0
        if (doc->dict) {
13076
0
            newDoc->dict = doc->dict;
13077
0
            xmlDictReference(newDoc->dict);
13078
0
        }
13079
0
        if (doc->URL != NULL) {
13080
0
            newDoc->URL = xmlStrdup(doc->URL);
13081
0
        }
13082
0
    }
13083
0
    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
13084
0
    if (newRoot == NULL) {
13085
0
  if (sax != NULL)
13086
0
  xmlFreeParserCtxt(ctxt);
13087
0
  newDoc->intSubset = NULL;
13088
0
  newDoc->extSubset = NULL;
13089
0
        xmlFreeDoc(newDoc);
13090
0
  return(XML_ERR_INTERNAL_ERROR);
13091
0
    }
13092
0
    xmlAddChild((xmlNodePtr) newDoc, newRoot);
13093
0
    nodePush(ctxt, newDoc->children);
13094
0
    if (doc == NULL) {
13095
0
        ctxt->myDoc = newDoc;
13096
0
    } else {
13097
0
        ctxt->myDoc = doc;
13098
0
        newRoot->doc = doc;
13099
0
    }
13100
13101
    /*
13102
     * Get the 4 first bytes and decode the charset
13103
     * if enc != XML_CHAR_ENCODING_NONE
13104
     * plug some encoding conversion routines.
13105
     */
13106
0
    GROW;
13107
0
    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
13108
0
  start[0] = RAW;
13109
0
  start[1] = NXT(1);
13110
0
  start[2] = NXT(2);
13111
0
  start[3] = NXT(3);
13112
0
  enc = xmlDetectCharEncoding(start, 4);
13113
0
  if (enc != XML_CHAR_ENCODING_NONE) {
13114
0
      xmlSwitchEncoding(ctxt, enc);
13115
0
  }
13116
0
    }
13117
13118
    /*
13119
     * Parse a possible text declaration first
13120
     */
13121
0
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
13122
0
  xmlParseTextDecl(ctxt);
13123
        /*
13124
         * An XML-1.0 document can't reference an entity not XML-1.0
13125
         */
13126
0
        if ((xmlStrEqual(oldctxt->version, BAD_CAST "1.0")) &&
13127
0
            (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) {
13128
0
            xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH,
13129
0
                           "Version mismatch between document and entity\n");
13130
0
        }
13131
0
    }
13132
13133
0
    ctxt->instate = XML_PARSER_CONTENT;
13134
0
    ctxt->depth = depth;
13135
0
    if (oldctxt != NULL) {
13136
0
  ctxt->_private = oldctxt->_private;
13137
0
  ctxt->loadsubset = oldctxt->loadsubset;
13138
0
  ctxt->validate = oldctxt->validate;
13139
0
  ctxt->valid = oldctxt->valid;
13140
0
  ctxt->replaceEntities = oldctxt->replaceEntities;
13141
0
        if (oldctxt->validate) {
13142
0
            ctxt->vctxt.error = oldctxt->vctxt.error;
13143
0
            ctxt->vctxt.warning = oldctxt->vctxt.warning;
13144
0
            ctxt->vctxt.userData = oldctxt->vctxt.userData;
13145
0
        }
13146
0
  ctxt->external = oldctxt->external;
13147
0
        if (ctxt->dict) xmlDictFree(ctxt->dict);
13148
0
        ctxt->dict = oldctxt->dict;
13149
0
        ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
13150
0
        ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
13151
0
        ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
13152
0
        ctxt->dictNames = oldctxt->dictNames;
13153
0
        ctxt->attsDefault = oldctxt->attsDefault;
13154
0
        ctxt->attsSpecial = oldctxt->attsSpecial;
13155
0
        ctxt->linenumbers = oldctxt->linenumbers;
13156
0
  ctxt->record_info = oldctxt->record_info;
13157
0
  ctxt->node_seq.maximum = oldctxt->node_seq.maximum;
13158
0
  ctxt->node_seq.length = oldctxt->node_seq.length;
13159
0
  ctxt->node_seq.buffer = oldctxt->node_seq.buffer;
13160
0
    } else {
13161
  /*
13162
   * Doing validity checking on chunk without context
13163
   * doesn't make sense
13164
   */
13165
0
  ctxt->_private = NULL;
13166
0
  ctxt->validate = 0;
13167
0
  ctxt->external = 2;
13168
0
  ctxt->loadsubset = 0;
13169
0
    }
13170
13171
0
    xmlParseContent(ctxt);
13172
13173
0
    if ((RAW == '<') && (NXT(1) == '/')) {
13174
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13175
0
    } else if (RAW != 0) {
13176
0
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13177
0
    }
13178
0
    if (ctxt->node != newDoc->children) {
13179
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13180
0
    }
13181
13182
0
    if (!ctxt->wellFormed) {
13183
0
        if (ctxt->errNo == 0)
13184
0
      ret = XML_ERR_INTERNAL_ERROR;
13185
0
  else
13186
0
      ret = (xmlParserErrors)ctxt->errNo;
13187
0
    } else {
13188
0
  if (list != NULL) {
13189
0
      xmlNodePtr cur;
13190
13191
      /*
13192
       * Return the newly created nodeset after unlinking it from
13193
       * they pseudo parent.
13194
       */
13195
0
      cur = newDoc->children->children;
13196
0
      *list = cur;
13197
0
      while (cur != NULL) {
13198
0
    cur->parent = NULL;
13199
0
    cur = cur->next;
13200
0
      }
13201
0
            newDoc->children->children = NULL;
13202
0
  }
13203
0
  ret = XML_ERR_OK;
13204
0
    }
13205
13206
    /*
13207
     * Record in the parent context the number of entities replacement
13208
     * done when parsing that reference.
13209
     */
13210
0
    if (oldctxt != NULL)
13211
0
        oldctxt->nbentities += ctxt->nbentities;
13212
13213
    /*
13214
     * Also record the size of the entity parsed
13215
     */
13216
0
    if (ctxt->input != NULL && oldctxt != NULL) {
13217
0
  oldctxt->sizeentities += ctxt->input->consumed;
13218
0
  oldctxt->sizeentities += (ctxt->input->cur - ctxt->input->base);
13219
0
    }
13220
    /*
13221
     * And record the last error if any
13222
     */
13223
0
    if ((oldctxt != NULL) && (ctxt->lastError.code != XML_ERR_OK))
13224
0
        xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
13225
13226
0
    if (oldctxt != NULL) {
13227
0
        ctxt->dict = NULL;
13228
0
        ctxt->attsDefault = NULL;
13229
0
        ctxt->attsSpecial = NULL;
13230
0
        oldctxt->validate = ctxt->validate;
13231
0
        oldctxt->valid = ctxt->valid;
13232
0
        oldctxt->node_seq.maximum = ctxt->node_seq.maximum;
13233
0
        oldctxt->node_seq.length = ctxt->node_seq.length;
13234
0
        oldctxt->node_seq.buffer = ctxt->node_seq.buffer;
13235
0
    }
13236
0
    ctxt->node_seq.maximum = 0;
13237
0
    ctxt->node_seq.length = 0;
13238
0
    ctxt->node_seq.buffer = NULL;
13239
0
    xmlFreeParserCtxt(ctxt);
13240
0
    newDoc->intSubset = NULL;
13241
0
    newDoc->extSubset = NULL;
13242
0
    xmlFreeDoc(newDoc);
13243
13244
0
    return(ret);
13245
0
}
13246
13247
#ifdef LIBXML_SAX1_ENABLED
13248
/**
13249
 * xmlParseExternalEntity:
13250
 * @doc:  the document the chunk pertains to
13251
 * @sax:  the SAX handler block (possibly NULL)
13252
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
13253
 * @depth:  Used for loop detection, use 0
13254
 * @URL:  the URL for the entity to load
13255
 * @ID:  the System ID for the entity to load
13256
 * @lst:  the return value for the set of parsed nodes
13257
 *
13258
 * Parse an external general entity
13259
 * An external general parsed entity is well-formed if it matches the
13260
 * production labeled extParsedEnt.
13261
 *
13262
 * [78] extParsedEnt ::= TextDecl? content
13263
 *
13264
 * Returns 0 if the entity is well formed, -1 in case of args problem and
13265
 *    the parser error code otherwise
13266
 */
13267
13268
int
13269
xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data,
13270
    int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *lst) {
13271
    return(xmlParseExternalEntityPrivate(doc, NULL, sax, user_data, depth, URL,
13272
                           ID, lst));
13273
}
13274
13275
/**
13276
 * xmlParseBalancedChunkMemory:
13277
 * @doc:  the document the chunk pertains to (must not be NULL)
13278
 * @sax:  the SAX handler block (possibly NULL)
13279
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
13280
 * @depth:  Used for loop detection, use 0
13281
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
13282
 * @lst:  the return value for the set of parsed nodes
13283
 *
13284
 * Parse a well-balanced chunk of an XML document
13285
 * called by the parser
13286
 * The allowed sequence for the Well Balanced Chunk is the one defined by
13287
 * the content production in the XML grammar:
13288
 *
13289
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13290
 *
13291
 * Returns 0 if the chunk is well balanced, -1 in case of args problem and
13292
 *    the parser error code otherwise
13293
 */
13294
13295
int
13296
xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax,
13297
     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst) {
13298
    return xmlParseBalancedChunkMemoryRecover( doc, sax, user_data,
13299
                                                depth, string, lst, 0 );
13300
}
13301
#endif /* LIBXML_SAX1_ENABLED */
13302
13303
/**
13304
 * xmlParseBalancedChunkMemoryInternal:
13305
 * @oldctxt:  the existing parsing context
13306
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
13307
 * @user_data:  the user data field for the parser context
13308
 * @lst:  the return value for the set of parsed nodes
13309
 *
13310
 *
13311
 * Parse a well-balanced chunk of an XML document
13312
 * called by the parser
13313
 * The allowed sequence for the Well Balanced Chunk is the one defined by
13314
 * the content production in the XML grammar:
13315
 *
13316
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13317
 *
13318
 * Returns XML_ERR_OK if the chunk is well balanced, and the parser
13319
 * error code otherwise
13320
 *
13321
 * In case recover is set to 1, the nodelist will not be empty even if
13322
 * the parsed chunk is not well balanced.
13323
 */
13324
static xmlParserErrors
13325
xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
13326
129
  const xmlChar *string, void *user_data, xmlNodePtr *lst) {
13327
129
    xmlParserCtxtPtr ctxt;
13328
129
    xmlDocPtr newDoc = NULL;
13329
129
    xmlNodePtr newRoot;
13330
129
    xmlSAXHandlerPtr oldsax = NULL;
13331
129
    xmlNodePtr content = NULL;
13332
129
    xmlNodePtr last = NULL;
13333
129
    int size;
13334
129
    xmlParserErrors ret = XML_ERR_OK;
13335
129
#ifdef SAX2
13336
129
    int i;
13337
129
#endif
13338
13339
129
    if (((oldctxt->depth > 40) && ((oldctxt->options & XML_PARSE_HUGE) == 0)) ||
13340
129
        (oldctxt->depth >  1024)) {
13341
3
  return(XML_ERR_ENTITY_LOOP);
13342
3
    }
13343
13344
13345
126
    if (lst != NULL)
13346
97
        *lst = NULL;
13347
126
    if (string == NULL)
13348
0
        return(XML_ERR_INTERNAL_ERROR);
13349
13350
126
    size = xmlStrlen(string);
13351
13352
126
    ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
13353
126
    if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
13354
124
    if (user_data != NULL)
13355
0
  ctxt->userData = user_data;
13356
124
    else
13357
124
  ctxt->userData = ctxt;
13358
124
    if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
13359
124
    ctxt->dict = oldctxt->dict;
13360
124
    ctxt->input_id = oldctxt->input_id + 1;
13361
124
    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
13362
124
    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
13363
124
    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
13364
13365
124
#ifdef SAX2
13366
    /* propagate namespaces down the entity */
13367
211
    for (i = 0;i < oldctxt->nsNr;i += 2) {
13368
87
        nsPush(ctxt, oldctxt->nsTab[i], oldctxt->nsTab[i+1]);
13369
87
    }
13370
124
#endif
13371
13372
124
    oldsax = ctxt->sax;
13373
124
    ctxt->sax = oldctxt->sax;
13374
124
    xmlDetectSAX2(ctxt);
13375
124
    ctxt->replaceEntities = oldctxt->replaceEntities;
13376
124
    ctxt->options = oldctxt->options;
13377
13378
124
    ctxt->_private = oldctxt->_private;
13379
124
    if (oldctxt->myDoc == NULL) {
13380
0
  newDoc = xmlNewDoc(BAD_CAST "1.0");
13381
0
  if (newDoc == NULL) {
13382
0
      ctxt->sax = oldsax;
13383
0
      ctxt->dict = NULL;
13384
0
      xmlFreeParserCtxt(ctxt);
13385
0
      return(XML_ERR_INTERNAL_ERROR);
13386
0
  }
13387
0
  newDoc->properties = XML_DOC_INTERNAL;
13388
0
  newDoc->dict = ctxt->dict;
13389
0
  xmlDictReference(newDoc->dict);
13390
0
  ctxt->myDoc = newDoc;
13391
124
    } else {
13392
124
  ctxt->myDoc = oldctxt->myDoc;
13393
124
        content = ctxt->myDoc->children;
13394
124
  last = ctxt->myDoc->last;
13395
124
    }
13396
124
    newRoot = xmlNewDocNode(ctxt->myDoc, NULL, BAD_CAST "pseudoroot", NULL);
13397
124
    if (newRoot == NULL) {
13398
0
  ctxt->sax = oldsax;
13399
0
  ctxt->dict = NULL;
13400
0
  xmlFreeParserCtxt(ctxt);
13401
0
  if (newDoc != NULL) {
13402
0
      xmlFreeDoc(newDoc);
13403
0
  }
13404
0
  return(XML_ERR_INTERNAL_ERROR);
13405
0
    }
13406
124
    ctxt->myDoc->children = NULL;
13407
124
    ctxt->myDoc->last = NULL;
13408
124
    xmlAddChild((xmlNodePtr) ctxt->myDoc, newRoot);
13409
124
    nodePush(ctxt, ctxt->myDoc->children);
13410
124
    ctxt->instate = XML_PARSER_CONTENT;
13411
124
    ctxt->depth = oldctxt->depth + 1;
13412
13413
124
    ctxt->validate = 0;
13414
124
    ctxt->loadsubset = oldctxt->loadsubset;
13415
124
    if ((oldctxt->validate) || (oldctxt->replaceEntities != 0)) {
13416
  /*
13417
   * ID/IDREF registration will be done in xmlValidateElement below
13418
   */
13419
0
  ctxt->loadsubset |= XML_SKIP_IDS;
13420
0
    }
13421
124
    ctxt->dictNames = oldctxt->dictNames;
13422
124
    ctxt->attsDefault = oldctxt->attsDefault;
13423
124
    ctxt->attsSpecial = oldctxt->attsSpecial;
13424
13425
124
    xmlParseContent(ctxt);
13426
124
    if ((RAW == '<') && (NXT(1) == '/')) {
13427
20
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13428
104
    } else if (RAW != 0) {
13429
0
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13430
0
    }
13431
124
    if (ctxt->node != ctxt->myDoc->children) {
13432
77
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13433
77
    }
13434
13435
124
    if (!ctxt->wellFormed) {
13436
97
        if (ctxt->errNo == 0)
13437
0
      ret = XML_ERR_INTERNAL_ERROR;
13438
97
  else
13439
97
      ret = (xmlParserErrors)ctxt->errNo;
13440
97
    } else {
13441
27
      ret = XML_ERR_OK;
13442
27
    }
13443
13444
124
    if ((lst != NULL) && (ret == XML_ERR_OK)) {
13445
0
  xmlNodePtr cur;
13446
13447
  /*
13448
   * Return the newly created nodeset after unlinking it from
13449
   * they pseudo parent.
13450
   */
13451
0
  cur = ctxt->myDoc->children->children;
13452
0
  *lst = cur;
13453
0
  while (cur != NULL) {
13454
#ifdef LIBXML_VALID_ENABLED
13455
      if ((oldctxt->validate) && (oldctxt->wellFormed) &&
13456
    (oldctxt->myDoc) && (oldctxt->myDoc->intSubset) &&
13457
    (cur->type == XML_ELEMENT_NODE)) {
13458
    oldctxt->valid &= xmlValidateElement(&oldctxt->vctxt,
13459
      oldctxt->myDoc, cur);
13460
      }
13461
#endif /* LIBXML_VALID_ENABLED */
13462
0
      cur->parent = NULL;
13463
0
      cur = cur->next;
13464
0
  }
13465
0
  ctxt->myDoc->children->children = NULL;
13466
0
    }
13467
124
    if (ctxt->myDoc != NULL) {
13468
124
  xmlFreeNode(ctxt->myDoc->children);
13469
124
        ctxt->myDoc->children = content;
13470
124
        ctxt->myDoc->last = last;
13471
124
    }
13472
13473
    /*
13474
     * Record in the parent context the number of entities replacement
13475
     * done when parsing that reference.
13476
     */
13477
124
    if (oldctxt != NULL)
13478
124
        oldctxt->nbentities += ctxt->nbentities;
13479
13480
    /*
13481
     * Also record the last error if any
13482
     */
13483
124
    if (ctxt->lastError.code != XML_ERR_OK)
13484
97
        xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
13485
13486
124
    ctxt->sax = oldsax;
13487
124
    ctxt->dict = NULL;
13488
124
    ctxt->attsDefault = NULL;
13489
124
    ctxt->attsSpecial = NULL;
13490
124
    xmlFreeParserCtxt(ctxt);
13491
124
    if (newDoc != NULL) {
13492
0
  xmlFreeDoc(newDoc);
13493
0
    }
13494
13495
124
    return(ret);
13496
124
}
13497
13498
/**
13499
 * xmlParseInNodeContext:
13500
 * @node:  the context node
13501
 * @data:  the input string
13502
 * @datalen:  the input string length in bytes
13503
 * @options:  a combination of xmlParserOption
13504
 * @lst:  the return value for the set of parsed nodes
13505
 *
13506
 * Parse a well-balanced chunk of an XML document
13507
 * within the context (DTD, namespaces, etc ...) of the given node.
13508
 *
13509
 * The allowed sequence for the data is a Well Balanced Chunk defined by
13510
 * the content production in the XML grammar:
13511
 *
13512
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13513
 *
13514
 * Returns XML_ERR_OK if the chunk is well balanced, and the parser
13515
 * error code otherwise
13516
 */
13517
xmlParserErrors
13518
xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
13519
0
                      int options, xmlNodePtr *lst) {
13520
0
#ifdef SAX2
13521
0
    xmlParserCtxtPtr ctxt;
13522
0
    xmlDocPtr doc = NULL;
13523
0
    xmlNodePtr fake, cur;
13524
0
    int nsnr = 0;
13525
13526
0
    xmlParserErrors ret = XML_ERR_OK;
13527
13528
    /*
13529
     * check all input parameters, grab the document
13530
     */
13531
0
    if ((lst == NULL) || (node == NULL) || (data == NULL) || (datalen < 0))
13532
0
        return(XML_ERR_INTERNAL_ERROR);
13533
0
    switch (node->type) {
13534
0
        case XML_ELEMENT_NODE:
13535
0
        case XML_ATTRIBUTE_NODE:
13536
0
        case XML_TEXT_NODE:
13537
0
        case XML_CDATA_SECTION_NODE:
13538
0
        case XML_ENTITY_REF_NODE:
13539
0
        case XML_PI_NODE:
13540
0
        case XML_COMMENT_NODE:
13541
0
        case XML_DOCUMENT_NODE:
13542
0
        case XML_HTML_DOCUMENT_NODE:
13543
0
      break;
13544
0
  default:
13545
0
      return(XML_ERR_INTERNAL_ERROR);
13546
13547
0
    }
13548
0
    while ((node != NULL) && (node->type != XML_ELEMENT_NODE) &&
13549
0
           (node->type != XML_DOCUMENT_NODE) &&
13550
0
     (node->type != XML_HTML_DOCUMENT_NODE))
13551
0
  node = node->parent;
13552
0
    if (node == NULL)
13553
0
  return(XML_ERR_INTERNAL_ERROR);
13554
0
    if (node->type == XML_ELEMENT_NODE)
13555
0
  doc = node->doc;
13556
0
    else
13557
0
        doc = (xmlDocPtr) node;
13558
0
    if (doc == NULL)
13559
0
  return(XML_ERR_INTERNAL_ERROR);
13560
13561
    /*
13562
     * allocate a context and set-up everything not related to the
13563
     * node position in the tree
13564
     */
13565
0
    if (doc->type == XML_DOCUMENT_NODE)
13566
0
  ctxt = xmlCreateMemoryParserCtxt((char *) data, datalen);
13567
0
#ifdef LIBXML_HTML_ENABLED
13568
0
    else if (doc->type == XML_HTML_DOCUMENT_NODE) {
13569
0
  ctxt = htmlCreateMemoryParserCtxt((char *) data, datalen);
13570
        /*
13571
         * When parsing in context, it makes no sense to add implied
13572
         * elements like html/body/etc...
13573
         */
13574
0
        options |= HTML_PARSE_NOIMPLIED;
13575
0
    }
13576
0
#endif
13577
0
    else
13578
0
        return(XML_ERR_INTERNAL_ERROR);
13579
13580
0
    if (ctxt == NULL)
13581
0
        return(XML_ERR_NO_MEMORY);
13582
13583
    /*
13584
     * Use input doc's dict if present, else assure XML_PARSE_NODICT is set.
13585
     * We need a dictionary for xmlDetectSAX2, so if there's no doc dict
13586
     * we must wait until the last moment to free the original one.
13587
     */
13588
0
    if (doc->dict != NULL) {
13589
0
        if (ctxt->dict != NULL)
13590
0
      xmlDictFree(ctxt->dict);
13591
0
  ctxt->dict = doc->dict;
13592
0
    } else
13593
0
        options |= XML_PARSE_NODICT;
13594
13595
0
    if (doc->encoding != NULL) {
13596
0
        xmlCharEncodingHandlerPtr hdlr;
13597
13598
0
        if (ctxt->encoding != NULL)
13599
0
      xmlFree((xmlChar *) ctxt->encoding);
13600
0
        ctxt->encoding = xmlStrdup((const xmlChar *) doc->encoding);
13601
13602
0
        hdlr = xmlFindCharEncodingHandler((const char *) doc->encoding);
13603
0
        if (hdlr != NULL) {
13604
0
            xmlSwitchToEncoding(ctxt, hdlr);
13605
0
  } else {
13606
0
            return(XML_ERR_UNSUPPORTED_ENCODING);
13607
0
        }
13608
0
    }
13609
13610
0
    xmlCtxtUseOptionsInternal(ctxt, options, NULL);
13611
0
    xmlDetectSAX2(ctxt);
13612
0
    ctxt->myDoc = doc;
13613
    /* parsing in context, i.e. as within existing content */
13614
0
    ctxt->input_id = 2;
13615
0
    ctxt->instate = XML_PARSER_CONTENT;
13616
13617
0
    fake = xmlNewDocComment(node->doc, NULL);
13618
0
    if (fake == NULL) {
13619
0
        xmlFreeParserCtxt(ctxt);
13620
0
  return(XML_ERR_NO_MEMORY);
13621
0
    }
13622
0
    xmlAddChild(node, fake);
13623
13624
0
    if (node->type == XML_ELEMENT_NODE) {
13625
0
  nodePush(ctxt, node);
13626
  /*
13627
   * initialize the SAX2 namespaces stack
13628
   */
13629
0
  cur = node;
13630
0
  while ((cur != NULL) && (cur->type == XML_ELEMENT_NODE)) {
13631
0
      xmlNsPtr ns = cur->nsDef;
13632
0
      const xmlChar *iprefix, *ihref;
13633
13634
0
      while (ns != NULL) {
13635
0
    if (ctxt->dict) {
13636
0
        iprefix = xmlDictLookup(ctxt->dict, ns->prefix, -1);
13637
0
        ihref = xmlDictLookup(ctxt->dict, ns->href, -1);
13638
0
    } else {
13639
0
        iprefix = ns->prefix;
13640
0
        ihref = ns->href;
13641
0
    }
13642
13643
0
          if (xmlGetNamespace(ctxt, iprefix) == NULL) {
13644
0
        nsPush(ctxt, iprefix, ihref);
13645
0
        nsnr++;
13646
0
    }
13647
0
    ns = ns->next;
13648
0
      }
13649
0
      cur = cur->parent;
13650
0
  }
13651
0
    }
13652
13653
0
    if ((ctxt->validate) || (ctxt->replaceEntities != 0)) {
13654
  /*
13655
   * ID/IDREF registration will be done in xmlValidateElement below
13656
   */
13657
0
  ctxt->loadsubset |= XML_SKIP_IDS;
13658
0
    }
13659
13660
0
#ifdef LIBXML_HTML_ENABLED
13661
0
    if (doc->type == XML_HTML_DOCUMENT_NODE)
13662
0
        __htmlParseContent(ctxt);
13663
0
    else
13664
0
#endif
13665
0
  xmlParseContent(ctxt);
13666
13667
0
    nsPop(ctxt, nsnr);
13668
0
    if ((RAW == '<') && (NXT(1) == '/')) {
13669
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13670
0
    } else if (RAW != 0) {
13671
0
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13672
0
    }
13673
0
    if ((ctxt->node != NULL) && (ctxt->node != node)) {
13674
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13675
0
  ctxt->wellFormed = 0;
13676
0
    }
13677
13678
0
    if (!ctxt->wellFormed) {
13679
0
        if (ctxt->errNo == 0)
13680
0
      ret = XML_ERR_INTERNAL_ERROR;
13681
0
  else
13682
0
      ret = (xmlParserErrors)ctxt->errNo;
13683
0
    } else {
13684
0
        ret = XML_ERR_OK;
13685
0
    }
13686
13687
    /*
13688
     * Return the newly created nodeset after unlinking it from
13689
     * the pseudo sibling.
13690
     */
13691
13692
0
    cur = fake->next;
13693
0
    fake->next = NULL;
13694
0
    node->last = fake;
13695
13696
0
    if (cur != NULL) {
13697
0
  cur->prev = NULL;
13698
0
    }
13699
13700
0
    *lst = cur;
13701
13702
0
    while (cur != NULL) {
13703
0
  cur->parent = NULL;
13704
0
  cur = cur->next;
13705
0
    }
13706
13707
0
    xmlUnlinkNode(fake);
13708
0
    xmlFreeNode(fake);
13709
13710
13711
0
    if (ret != XML_ERR_OK) {
13712
0
        xmlFreeNodeList(*lst);
13713
0
  *lst = NULL;
13714
0
    }
13715
13716
0
    if (doc->dict != NULL)
13717
0
        ctxt->dict = NULL;
13718
0
    xmlFreeParserCtxt(ctxt);
13719
13720
0
    return(ret);
13721
#else /* !SAX2 */
13722
    return(XML_ERR_INTERNAL_ERROR);
13723
#endif
13724
0
}
13725
13726
#ifdef LIBXML_SAX1_ENABLED
13727
/**
13728
 * xmlParseBalancedChunkMemoryRecover:
13729
 * @doc:  the document the chunk pertains to (must not be NULL)
13730
 * @sax:  the SAX handler block (possibly NULL)
13731
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
13732
 * @depth:  Used for loop detection, use 0
13733
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
13734
 * @lst:  the return value for the set of parsed nodes
13735
 * @recover: return nodes even if the data is broken (use 0)
13736
 *
13737
 *
13738
 * Parse a well-balanced chunk of an XML document
13739
 * called by the parser
13740
 * The allowed sequence for the Well Balanced Chunk is the one defined by
13741
 * the content production in the XML grammar:
13742
 *
13743
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13744
 *
13745
 * Returns 0 if the chunk is well balanced, -1 in case of args problem and
13746
 *    the parser error code otherwise
13747
 *
13748
 * In case recover is set to 1, the nodelist will not be empty even if
13749
 * the parsed chunk is not well balanced, assuming the parsing succeeded to
13750
 * some extent.
13751
 */
13752
int
13753
xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
13754
     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst,
13755
     int recover) {
13756
    xmlParserCtxtPtr ctxt;
13757
    xmlDocPtr newDoc;
13758
    xmlSAXHandlerPtr oldsax = NULL;
13759
    xmlNodePtr content, newRoot;
13760
    int size;
13761
    int ret = 0;
13762
13763
    if (depth > 40) {
13764
  return(XML_ERR_ENTITY_LOOP);
13765
    }
13766
13767
13768
    if (lst != NULL)
13769
        *lst = NULL;
13770
    if (string == NULL)
13771
        return(-1);
13772
13773
    size = xmlStrlen(string);
13774
13775
    ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
13776
    if (ctxt == NULL) return(-1);
13777
    ctxt->userData = ctxt;
13778
    if (sax != NULL) {
13779
  oldsax = ctxt->sax;
13780
        ctxt->sax = sax;
13781
  if (user_data != NULL)
13782
      ctxt->userData = user_data;
13783
    }
13784
    newDoc = xmlNewDoc(BAD_CAST "1.0");
13785
    if (newDoc == NULL) {
13786
  xmlFreeParserCtxt(ctxt);
13787
  return(-1);
13788
    }
13789
    newDoc->properties = XML_DOC_INTERNAL;
13790
    if ((doc != NULL) && (doc->dict != NULL)) {
13791
        xmlDictFree(ctxt->dict);
13792
  ctxt->dict = doc->dict;
13793
  xmlDictReference(ctxt->dict);
13794
  ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
13795
  ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
13796
  ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
13797
  ctxt->dictNames = 1;
13798
    } else {
13799
  xmlCtxtUseOptionsInternal(ctxt, XML_PARSE_NODICT, NULL);
13800
    }
13801
    /* doc == NULL is only supported for historic reasons */
13802
    if (doc != NULL) {
13803
  newDoc->intSubset = doc->intSubset;
13804
  newDoc->extSubset = doc->extSubset;
13805
    }
13806
    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
13807
    if (newRoot == NULL) {
13808
  if (sax != NULL)
13809
      ctxt->sax = oldsax;
13810
  xmlFreeParserCtxt(ctxt);
13811
  newDoc->intSubset = NULL;
13812
  newDoc->extSubset = NULL;
13813
        xmlFreeDoc(newDoc);
13814
  return(-1);
13815
    }
13816
    xmlAddChild((xmlNodePtr) newDoc, newRoot);
13817
    nodePush(ctxt, newRoot);
13818
    /* doc == NULL is only supported for historic reasons */
13819
    if (doc == NULL) {
13820
  ctxt->myDoc = newDoc;
13821
    } else {
13822
  ctxt->myDoc = newDoc;
13823
  newDoc->children->doc = doc;
13824
  /* Ensure that doc has XML spec namespace */
13825
  xmlSearchNsByHref(doc, (xmlNodePtr)doc, XML_XML_NAMESPACE);
13826
  newDoc->oldNs = doc->oldNs;
13827
    }
13828
    ctxt->instate = XML_PARSER_CONTENT;
13829
    ctxt->input_id = 2;
13830
    ctxt->depth = depth;
13831
13832
    /*
13833
     * Doing validity checking on chunk doesn't make sense
13834
     */
13835
    ctxt->validate = 0;
13836
    ctxt->loadsubset = 0;
13837
    xmlDetectSAX2(ctxt);
13838
13839
    if ( doc != NULL ){
13840
        content = doc->children;
13841
        doc->children = NULL;
13842
        xmlParseContent(ctxt);
13843
        doc->children = content;
13844
    }
13845
    else {
13846
        xmlParseContent(ctxt);
13847
    }
13848
    if ((RAW == '<') && (NXT(1) == '/')) {
13849
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13850
    } else if (RAW != 0) {
13851
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13852
    }
13853
    if (ctxt->node != newDoc->children) {
13854
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13855
    }
13856
13857
    if (!ctxt->wellFormed) {
13858
        if (ctxt->errNo == 0)
13859
      ret = 1;
13860
  else
13861
      ret = ctxt->errNo;
13862
    } else {
13863
      ret = 0;
13864
    }
13865
13866
    if ((lst != NULL) && ((ret == 0) || (recover == 1))) {
13867
  xmlNodePtr cur;
13868
13869
  /*
13870
   * Return the newly created nodeset after unlinking it from
13871
   * they pseudo parent.
13872
   */
13873
  cur = newDoc->children->children;
13874
  *lst = cur;
13875
  while (cur != NULL) {
13876
      xmlSetTreeDoc(cur, doc);
13877
      cur->parent = NULL;
13878
      cur = cur->next;
13879
  }
13880
  newDoc->children->children = NULL;
13881
    }
13882
13883
    if (sax != NULL)
13884
  ctxt->sax = oldsax;
13885
    xmlFreeParserCtxt(ctxt);
13886
    newDoc->intSubset = NULL;
13887
    newDoc->extSubset = NULL;
13888
    /* This leaks the namespace list if doc == NULL */
13889
    newDoc->oldNs = NULL;
13890
    xmlFreeDoc(newDoc);
13891
13892
    return(ret);
13893
}
13894
13895
/**
13896
 * xmlSAXParseEntity:
13897
 * @sax:  the SAX handler block
13898
 * @filename:  the filename
13899
 *
13900
 * DEPRECATED: Don't use.
13901
 *
13902
 * parse an XML external entity out of context and build a tree.
13903
 * It use the given SAX function block to handle the parsing callback.
13904
 * If sax is NULL, fallback to the default DOM tree building routines.
13905
 *
13906
 * [78] extParsedEnt ::= TextDecl? content
13907
 *
13908
 * This correspond to a "Well Balanced" chunk
13909
 *
13910
 * Returns the resulting document tree
13911
 */
13912
13913
xmlDocPtr
13914
xmlSAXParseEntity(xmlSAXHandlerPtr sax, const char *filename) {
13915
    xmlDocPtr ret;
13916
    xmlParserCtxtPtr ctxt;
13917
13918
    ctxt = xmlCreateFileParserCtxt(filename);
13919
    if (ctxt == NULL) {
13920
  return(NULL);
13921
    }
13922
    if (sax != NULL) {
13923
  if (ctxt->sax != NULL)
13924
      xmlFree(ctxt->sax);
13925
        ctxt->sax = sax;
13926
        ctxt->userData = NULL;
13927
    }
13928
13929
    xmlParseExtParsedEnt(ctxt);
13930
13931
    if (ctxt->wellFormed)
13932
  ret = ctxt->myDoc;
13933
    else {
13934
        ret = NULL;
13935
        xmlFreeDoc(ctxt->myDoc);
13936
        ctxt->myDoc = NULL;
13937
    }
13938
    if (sax != NULL)
13939
        ctxt->sax = NULL;
13940
    xmlFreeParserCtxt(ctxt);
13941
13942
    return(ret);
13943
}
13944
13945
/**
13946
 * xmlParseEntity:
13947
 * @filename:  the filename
13948
 *
13949
 * parse an XML external entity out of context and build a tree.
13950
 *
13951
 * [78] extParsedEnt ::= TextDecl? content
13952
 *
13953
 * This correspond to a "Well Balanced" chunk
13954
 *
13955
 * Returns the resulting document tree
13956
 */
13957
13958
xmlDocPtr
13959
xmlParseEntity(const char *filename) {
13960
    return(xmlSAXParseEntity(NULL, filename));
13961
}
13962
#endif /* LIBXML_SAX1_ENABLED */
13963
13964
/**
13965
 * xmlCreateEntityParserCtxtInternal:
13966
 * @URL:  the entity URL
13967
 * @ID:  the entity PUBLIC ID
13968
 * @base:  a possible base for the target URI
13969
 * @pctx:  parser context used to set options on new context
13970
 *
13971
 * Create a parser context for an external entity
13972
 * Automatic support for ZLIB/Compress compressed document is provided
13973
 * by default if found at compile-time.
13974
 *
13975
 * Returns the new parser context or NULL
13976
 */
13977
static xmlParserCtxtPtr
13978
xmlCreateEntityParserCtxtInternal(xmlSAXHandlerPtr sax, void *userData,
13979
        const xmlChar *URL, const xmlChar *ID, const xmlChar *base,
13980
0
        xmlParserCtxtPtr pctx) {
13981
0
    xmlParserCtxtPtr ctxt;
13982
0
    xmlParserInputPtr inputStream;
13983
0
    char *directory = NULL;
13984
0
    xmlChar *uri;
13985
13986
0
    ctxt = xmlNewSAXParserCtxt(sax, userData);
13987
0
    if (ctxt == NULL) {
13988
0
  return(NULL);
13989
0
    }
13990
13991
0
    if (pctx != NULL) {
13992
0
        ctxt->options = pctx->options;
13993
0
        ctxt->_private = pctx->_private;
13994
  /*
13995
   * this is a subparser of pctx, so the input_id should be
13996
   * incremented to distinguish from main entity
13997
   */
13998
0
  ctxt->input_id = pctx->input_id + 1;
13999
0
    }
14000
14001
    /* Don't read from stdin. */
14002
0
    if (xmlStrcmp(URL, BAD_CAST "-") == 0)
14003
0
        URL = BAD_CAST "./-";
14004
14005
0
    uri = xmlBuildURI(URL, base);
14006
14007
0
    if (uri == NULL) {
14008
0
  inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
14009
0
  if (inputStream == NULL) {
14010
0
      xmlFreeParserCtxt(ctxt);
14011
0
      return(NULL);
14012
0
  }
14013
14014
0
  inputPush(ctxt, inputStream);
14015
14016
0
  if ((ctxt->directory == NULL) && (directory == NULL))
14017
0
      directory = xmlParserGetDirectory((char *)URL);
14018
0
  if ((ctxt->directory == NULL) && (directory != NULL))
14019
0
      ctxt->directory = directory;
14020
0
    } else {
14021
0
  inputStream = xmlLoadExternalEntity((char *)uri, (char *)ID, ctxt);
14022
0
  if (inputStream == NULL) {
14023
0
      xmlFree(uri);
14024
0
      xmlFreeParserCtxt(ctxt);
14025
0
      return(NULL);
14026
0
  }
14027
14028
0
  inputPush(ctxt, inputStream);
14029
14030
0
  if ((ctxt->directory == NULL) && (directory == NULL))
14031
0
      directory = xmlParserGetDirectory((char *)uri);
14032
0
  if ((ctxt->directory == NULL) && (directory != NULL))
14033
0
      ctxt->directory = directory;
14034
0
  xmlFree(uri);
14035
0
    }
14036
0
    return(ctxt);
14037
0
}
14038
14039
/**
14040
 * xmlCreateEntityParserCtxt:
14041
 * @URL:  the entity URL
14042
 * @ID:  the entity PUBLIC ID
14043
 * @base:  a possible base for the target URI
14044
 *
14045
 * Create a parser context for an external entity
14046
 * Automatic support for ZLIB/Compress compressed document is provided
14047
 * by default if found at compile-time.
14048
 *
14049
 * Returns the new parser context or NULL
14050
 */
14051
xmlParserCtxtPtr
14052
xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID,
14053
0
                    const xmlChar *base) {
14054
0
    return xmlCreateEntityParserCtxtInternal(NULL, NULL, URL, ID, base, NULL);
14055
14056
0
}
14057
14058
/************************************************************************
14059
 *                  *
14060
 *    Front ends when parsing from a file     *
14061
 *                  *
14062
 ************************************************************************/
14063
14064
/**
14065
 * xmlCreateURLParserCtxt:
14066
 * @filename:  the filename or URL
14067
 * @options:  a combination of xmlParserOption
14068
 *
14069
 * Create a parser context for a file or URL content.
14070
 * Automatic support for ZLIB/Compress compressed document is provided
14071
 * by default if found at compile-time and for file accesses
14072
 *
14073
 * Returns the new parser context or NULL
14074
 */
14075
xmlParserCtxtPtr
14076
xmlCreateURLParserCtxt(const char *filename, int options)
14077
2
{
14078
2
    xmlParserCtxtPtr ctxt;
14079
2
    xmlParserInputPtr inputStream;
14080
2
    char *directory = NULL;
14081
14082
2
    ctxt = xmlNewParserCtxt();
14083
2
    if (ctxt == NULL) {
14084
0
  xmlErrMemory(NULL, "cannot allocate parser context");
14085
0
  return(NULL);
14086
0
    }
14087
14088
2
    if (options)
14089
0
  xmlCtxtUseOptionsInternal(ctxt, options, NULL);
14090
2
    ctxt->linenumbers = 1;
14091
14092
2
    inputStream = xmlLoadExternalEntity(filename, NULL, ctxt);
14093
2
    if (inputStream == NULL) {
14094
0
  xmlFreeParserCtxt(ctxt);
14095
0
  return(NULL);
14096
0
    }
14097
14098
2
    inputPush(ctxt, inputStream);
14099
2
    if ((ctxt->directory == NULL) && (directory == NULL))
14100
0
        directory = xmlParserGetDirectory(filename);
14101
2
    if ((ctxt->directory == NULL) && (directory != NULL))
14102
0
        ctxt->directory = directory;
14103
14104
2
    return(ctxt);
14105
2
}
14106
14107
/**
14108
 * xmlCreateFileParserCtxt:
14109
 * @filename:  the filename
14110
 *
14111
 * Create a parser context for a file content.
14112
 * Automatic support for ZLIB/Compress compressed document is provided
14113
 * by default if found at compile-time.
14114
 *
14115
 * Returns the new parser context or NULL
14116
 */
14117
xmlParserCtxtPtr
14118
xmlCreateFileParserCtxt(const char *filename)
14119
0
{
14120
0
    return(xmlCreateURLParserCtxt(filename, 0));
14121
0
}
14122
14123
#ifdef LIBXML_SAX1_ENABLED
14124
/**
14125
 * xmlSAXParseFileWithData:
14126
 * @sax:  the SAX handler block
14127
 * @filename:  the filename
14128
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14129
 *             documents
14130
 * @data:  the userdata
14131
 *
14132
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadFile.
14133
 *
14134
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
14135
 * compressed document is provided by default if found at compile-time.
14136
 * It use the given SAX function block to handle the parsing callback.
14137
 * If sax is NULL, fallback to the default DOM tree building routines.
14138
 *
14139
 * User data (void *) is stored within the parser context in the
14140
 * context's _private member, so it is available nearly everywhere in libxml
14141
 *
14142
 * Returns the resulting document tree
14143
 */
14144
14145
xmlDocPtr
14146
xmlSAXParseFileWithData(xmlSAXHandlerPtr sax, const char *filename,
14147
                        int recovery, void *data) {
14148
    xmlDocPtr ret;
14149
    xmlParserCtxtPtr ctxt;
14150
14151
    xmlInitParser();
14152
14153
    ctxt = xmlCreateFileParserCtxt(filename);
14154
    if (ctxt == NULL) {
14155
  return(NULL);
14156
    }
14157
    if (sax != NULL) {
14158
  if (ctxt->sax != NULL)
14159
      xmlFree(ctxt->sax);
14160
        ctxt->sax = sax;
14161
    }
14162
    xmlDetectSAX2(ctxt);
14163
    if (data!=NULL) {
14164
  ctxt->_private = data;
14165
    }
14166
14167
    if (ctxt->directory == NULL)
14168
        ctxt->directory = xmlParserGetDirectory(filename);
14169
14170
    ctxt->recovery = recovery;
14171
14172
    xmlParseDocument(ctxt);
14173
14174
    if ((ctxt->wellFormed) || recovery) {
14175
        ret = ctxt->myDoc;
14176
  if ((ret != NULL) && (ctxt->input->buf != NULL)) {
14177
      if (ctxt->input->buf->compressed > 0)
14178
    ret->compression = 9;
14179
      else
14180
    ret->compression = ctxt->input->buf->compressed;
14181
  }
14182
    }
14183
    else {
14184
       ret = NULL;
14185
       xmlFreeDoc(ctxt->myDoc);
14186
       ctxt->myDoc = NULL;
14187
    }
14188
    if (sax != NULL)
14189
        ctxt->sax = NULL;
14190
    xmlFreeParserCtxt(ctxt);
14191
14192
    return(ret);
14193
}
14194
14195
/**
14196
 * xmlSAXParseFile:
14197
 * @sax:  the SAX handler block
14198
 * @filename:  the filename
14199
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14200
 *             documents
14201
 *
14202
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadFile.
14203
 *
14204
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
14205
 * compressed document is provided by default if found at compile-time.
14206
 * It use the given SAX function block to handle the parsing callback.
14207
 * If sax is NULL, fallback to the default DOM tree building routines.
14208
 *
14209
 * Returns the resulting document tree
14210
 */
14211
14212
xmlDocPtr
14213
xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
14214
                          int recovery) {
14215
    return(xmlSAXParseFileWithData(sax,filename,recovery,NULL));
14216
}
14217
14218
/**
14219
 * xmlRecoverDoc:
14220
 * @cur:  a pointer to an array of xmlChar
14221
 *
14222
 * DEPRECATED: Use xmlReadDoc with XML_PARSE_RECOVER.
14223
 *
14224
 * parse an XML in-memory document and build a tree.
14225
 * In the case the document is not Well Formed, a attempt to build a
14226
 * tree is tried anyway
14227
 *
14228
 * Returns the resulting document tree or NULL in case of failure
14229
 */
14230
14231
xmlDocPtr
14232
xmlRecoverDoc(const xmlChar *cur) {
14233
    return(xmlSAXParseDoc(NULL, cur, 1));
14234
}
14235
14236
/**
14237
 * xmlParseFile:
14238
 * @filename:  the filename
14239
 *
14240
 * DEPRECATED: Use xmlReadFile.
14241
 *
14242
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
14243
 * compressed document is provided by default if found at compile-time.
14244
 *
14245
 * Returns the resulting document tree if the file was wellformed,
14246
 * NULL otherwise.
14247
 */
14248
14249
xmlDocPtr
14250
xmlParseFile(const char *filename) {
14251
    return(xmlSAXParseFile(NULL, filename, 0));
14252
}
14253
14254
/**
14255
 * xmlRecoverFile:
14256
 * @filename:  the filename
14257
 *
14258
 * DEPRECATED: Use xmlReadFile with XML_PARSE_RECOVER.
14259
 *
14260
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
14261
 * compressed document is provided by default if found at compile-time.
14262
 * In the case the document is not Well Formed, it attempts to build
14263
 * a tree anyway
14264
 *
14265
 * Returns the resulting document tree or NULL in case of failure
14266
 */
14267
14268
xmlDocPtr
14269
xmlRecoverFile(const char *filename) {
14270
    return(xmlSAXParseFile(NULL, filename, 1));
14271
}
14272
14273
14274
/**
14275
 * xmlSetupParserForBuffer:
14276
 * @ctxt:  an XML parser context
14277
 * @buffer:  a xmlChar * buffer
14278
 * @filename:  a file name
14279
 *
14280
 * DEPRECATED: Don't use.
14281
 *
14282
 * Setup the parser context to parse a new buffer; Clears any prior
14283
 * contents from the parser context. The buffer parameter must not be
14284
 * NULL, but the filename parameter can be
14285
 */
14286
void
14287
xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
14288
                             const char* filename)
14289
{
14290
    xmlParserInputPtr input;
14291
14292
    if ((ctxt == NULL) || (buffer == NULL))
14293
        return;
14294
14295
    input = xmlNewInputStream(ctxt);
14296
    if (input == NULL) {
14297
        xmlErrMemory(NULL, "parsing new buffer: out of memory\n");
14298
        xmlClearParserCtxt(ctxt);
14299
        return;
14300
    }
14301
14302
    xmlClearParserCtxt(ctxt);
14303
    if (filename != NULL)
14304
        input->filename = (char *) xmlCanonicPath((const xmlChar *)filename);
14305
    input->base = buffer;
14306
    input->cur = buffer;
14307
    input->end = &buffer[xmlStrlen(buffer)];
14308
    inputPush(ctxt, input);
14309
}
14310
14311
/**
14312
 * xmlSAXUserParseFile:
14313
 * @sax:  a SAX handler
14314
 * @user_data:  The user data returned on SAX callbacks
14315
 * @filename:  a file name
14316
 *
14317
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadFile.
14318
 *
14319
 * parse an XML file and call the given SAX handler routines.
14320
 * Automatic support for ZLIB/Compress compressed document is provided
14321
 *
14322
 * Returns 0 in case of success or a error number otherwise
14323
 */
14324
int
14325
xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
14326
                    const char *filename) {
14327
    int ret = 0;
14328
    xmlParserCtxtPtr ctxt;
14329
14330
    ctxt = xmlCreateFileParserCtxt(filename);
14331
    if (ctxt == NULL) return -1;
14332
    if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
14333
  xmlFree(ctxt->sax);
14334
    ctxt->sax = sax;
14335
    xmlDetectSAX2(ctxt);
14336
14337
    if (user_data != NULL)
14338
  ctxt->userData = user_data;
14339
14340
    xmlParseDocument(ctxt);
14341
14342
    if (ctxt->wellFormed)
14343
  ret = 0;
14344
    else {
14345
        if (ctxt->errNo != 0)
14346
      ret = ctxt->errNo;
14347
  else
14348
      ret = -1;
14349
    }
14350
    if (sax != NULL)
14351
  ctxt->sax = NULL;
14352
    if (ctxt->myDoc != NULL) {
14353
        xmlFreeDoc(ctxt->myDoc);
14354
  ctxt->myDoc = NULL;
14355
    }
14356
    xmlFreeParserCtxt(ctxt);
14357
14358
    return ret;
14359
}
14360
#endif /* LIBXML_SAX1_ENABLED */
14361
14362
/************************************************************************
14363
 *                  *
14364
 *    Front ends when parsing from memory     *
14365
 *                  *
14366
 ************************************************************************/
14367
14368
/**
14369
 * xmlCreateMemoryParserCtxt:
14370
 * @buffer:  a pointer to a char array
14371
 * @size:  the size of the array
14372
 *
14373
 * Create a parser context for an XML in-memory document.
14374
 *
14375
 * Returns the new parser context or NULL
14376
 */
14377
xmlParserCtxtPtr
14378
325
xmlCreateMemoryParserCtxt(const char *buffer, int size) {
14379
325
    xmlParserCtxtPtr ctxt;
14380
325
    xmlParserInputPtr input;
14381
325
    xmlParserInputBufferPtr buf;
14382
14383
325
    if (buffer == NULL)
14384
0
  return(NULL);
14385
325
    if (size <= 0)
14386
2
  return(NULL);
14387
14388
323
    ctxt = xmlNewParserCtxt();
14389
323
    if (ctxt == NULL)
14390
0
  return(NULL);
14391
14392
    /* TODO: xmlParserInputBufferCreateStatic, requires some serious changes */
14393
323
    buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
14394
323
    if (buf == NULL) {
14395
0
  xmlFreeParserCtxt(ctxt);
14396
0
  return(NULL);
14397
0
    }
14398
14399
323
    input = xmlNewInputStream(ctxt);
14400
323
    if (input == NULL) {
14401
0
  xmlFreeParserInputBuffer(buf);
14402
0
  xmlFreeParserCtxt(ctxt);
14403
0
  return(NULL);
14404
0
    }
14405
14406
323
    input->filename = NULL;
14407
323
    input->buf = buf;
14408
323
    xmlBufResetInput(input->buf->buffer, input);
14409
14410
323
    inputPush(ctxt, input);
14411
323
    return(ctxt);
14412
323
}
14413
14414
#ifdef LIBXML_SAX1_ENABLED
14415
/**
14416
 * xmlSAXParseMemoryWithData:
14417
 * @sax:  the SAX handler block
14418
 * @buffer:  an pointer to a char array
14419
 * @size:  the size of the array
14420
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14421
 *             documents
14422
 * @data:  the userdata
14423
 *
14424
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadMemory.
14425
 *
14426
 * parse an XML in-memory block and use the given SAX function block
14427
 * to handle the parsing callback. If sax is NULL, fallback to the default
14428
 * DOM tree building routines.
14429
 *
14430
 * User data (void *) is stored within the parser context in the
14431
 * context's _private member, so it is available nearly everywhere in libxml
14432
 *
14433
 * Returns the resulting document tree
14434
 */
14435
14436
xmlDocPtr
14437
xmlSAXParseMemoryWithData(xmlSAXHandlerPtr sax, const char *buffer,
14438
            int size, int recovery, void *data) {
14439
    xmlDocPtr ret;
14440
    xmlParserCtxtPtr ctxt;
14441
14442
    xmlInitParser();
14443
14444
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
14445
    if (ctxt == NULL) return(NULL);
14446
    if (sax != NULL) {
14447
  if (ctxt->sax != NULL)
14448
      xmlFree(ctxt->sax);
14449
        ctxt->sax = sax;
14450
    }
14451
    xmlDetectSAX2(ctxt);
14452
    if (data!=NULL) {
14453
  ctxt->_private=data;
14454
    }
14455
14456
    ctxt->recovery = recovery;
14457
14458
    xmlParseDocument(ctxt);
14459
14460
    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
14461
    else {
14462
       ret = NULL;
14463
       xmlFreeDoc(ctxt->myDoc);
14464
       ctxt->myDoc = NULL;
14465
    }
14466
    if (sax != NULL)
14467
  ctxt->sax = NULL;
14468
    xmlFreeParserCtxt(ctxt);
14469
14470
    return(ret);
14471
}
14472
14473
/**
14474
 * xmlSAXParseMemory:
14475
 * @sax:  the SAX handler block
14476
 * @buffer:  an pointer to a char array
14477
 * @size:  the size of the array
14478
 * @recovery:  work in recovery mode, i.e. tries to read not Well Formed
14479
 *             documents
14480
 *
14481
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadMemory.
14482
 *
14483
 * parse an XML in-memory block and use the given SAX function block
14484
 * to handle the parsing callback. If sax is NULL, fallback to the default
14485
 * DOM tree building routines.
14486
 *
14487
 * Returns the resulting document tree
14488
 */
14489
xmlDocPtr
14490
xmlSAXParseMemory(xmlSAXHandlerPtr sax, const char *buffer,
14491
            int size, int recovery) {
14492
    return xmlSAXParseMemoryWithData(sax, buffer, size, recovery, NULL);
14493
}
14494
14495
/**
14496
 * xmlParseMemory:
14497
 * @buffer:  an pointer to a char array
14498
 * @size:  the size of the array
14499
 *
14500
 * DEPRECATED: Use xmlReadMemory.
14501
 *
14502
 * parse an XML in-memory block and build a tree.
14503
 *
14504
 * Returns the resulting document tree
14505
 */
14506
14507
xmlDocPtr xmlParseMemory(const char *buffer, int size) {
14508
   return(xmlSAXParseMemory(NULL, buffer, size, 0));
14509
}
14510
14511
/**
14512
 * xmlRecoverMemory:
14513
 * @buffer:  an pointer to a char array
14514
 * @size:  the size of the array
14515
 *
14516
 * DEPRECATED: Use xmlReadMemory with XML_PARSE_RECOVER.
14517
 *
14518
 * parse an XML in-memory block and build a tree.
14519
 * In the case the document is not Well Formed, an attempt to
14520
 * build a tree is tried anyway
14521
 *
14522
 * Returns the resulting document tree or NULL in case of error
14523
 */
14524
14525
xmlDocPtr xmlRecoverMemory(const char *buffer, int size) {
14526
   return(xmlSAXParseMemory(NULL, buffer, size, 1));
14527
}
14528
14529
/**
14530
 * xmlSAXUserParseMemory:
14531
 * @sax:  a SAX handler
14532
 * @user_data:  The user data returned on SAX callbacks
14533
 * @buffer:  an in-memory XML document input
14534
 * @size:  the length of the XML document in bytes
14535
 *
14536
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadMemory.
14537
 *
14538
 * parse an XML in-memory buffer and call the given SAX handler routines.
14539
 *
14540
 * Returns 0 in case of success or a error number otherwise
14541
 */
14542
int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
14543
        const char *buffer, int size) {
14544
    int ret = 0;
14545
    xmlParserCtxtPtr ctxt;
14546
14547
    xmlInitParser();
14548
14549
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
14550
    if (ctxt == NULL) return -1;
14551
    if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
14552
        xmlFree(ctxt->sax);
14553
    ctxt->sax = sax;
14554
    xmlDetectSAX2(ctxt);
14555
14556
    if (user_data != NULL)
14557
  ctxt->userData = user_data;
14558
14559
    xmlParseDocument(ctxt);
14560
14561
    if (ctxt->wellFormed)
14562
  ret = 0;
14563
    else {
14564
        if (ctxt->errNo != 0)
14565
      ret = ctxt->errNo;
14566
  else
14567
      ret = -1;
14568
    }
14569
    if (sax != NULL)
14570
        ctxt->sax = NULL;
14571
    if (ctxt->myDoc != NULL) {
14572
        xmlFreeDoc(ctxt->myDoc);
14573
  ctxt->myDoc = NULL;
14574
    }
14575
    xmlFreeParserCtxt(ctxt);
14576
14577
    return ret;
14578
}
14579
#endif /* LIBXML_SAX1_ENABLED */
14580
14581
/**
14582
 * xmlCreateDocParserCtxt:
14583
 * @cur:  a pointer to an array of xmlChar
14584
 *
14585
 * Creates a parser context for an XML in-memory document.
14586
 *
14587
 * Returns the new parser context or NULL
14588
 */
14589
xmlParserCtxtPtr
14590
0
xmlCreateDocParserCtxt(const xmlChar *cur) {
14591
0
    int len;
14592
14593
0
    if (cur == NULL)
14594
0
  return(NULL);
14595
0
    len = xmlStrlen(cur);
14596
0
    return(xmlCreateMemoryParserCtxt((const char *)cur, len));
14597
0
}
14598
14599
#ifdef LIBXML_SAX1_ENABLED
14600
/**
14601
 * xmlSAXParseDoc:
14602
 * @sax:  the SAX handler block
14603
 * @cur:  a pointer to an array of xmlChar
14604
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14605
 *             documents
14606
 *
14607
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadDoc.
14608
 *
14609
 * parse an XML in-memory document and build a tree.
14610
 * It use the given SAX function block to handle the parsing callback.
14611
 * If sax is NULL, fallback to the default DOM tree building routines.
14612
 *
14613
 * Returns the resulting document tree
14614
 */
14615
14616
xmlDocPtr
14617
xmlSAXParseDoc(xmlSAXHandlerPtr sax, const xmlChar *cur, int recovery) {
14618
    xmlDocPtr ret;
14619
    xmlParserCtxtPtr ctxt;
14620
    xmlSAXHandlerPtr oldsax = NULL;
14621
14622
    if (cur == NULL) return(NULL);
14623
14624
14625
    ctxt = xmlCreateDocParserCtxt(cur);
14626
    if (ctxt == NULL) return(NULL);
14627
    if (sax != NULL) {
14628
        oldsax = ctxt->sax;
14629
        ctxt->sax = sax;
14630
        ctxt->userData = NULL;
14631
    }
14632
    xmlDetectSAX2(ctxt);
14633
14634
    xmlParseDocument(ctxt);
14635
    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
14636
    else {
14637
       ret = NULL;
14638
       xmlFreeDoc(ctxt->myDoc);
14639
       ctxt->myDoc = NULL;
14640
    }
14641
    if (sax != NULL)
14642
  ctxt->sax = oldsax;
14643
    xmlFreeParserCtxt(ctxt);
14644
14645
    return(ret);
14646
}
14647
14648
/**
14649
 * xmlParseDoc:
14650
 * @cur:  a pointer to an array of xmlChar
14651
 *
14652
 * DEPRECATED: Use xmlReadDoc.
14653
 *
14654
 * parse an XML in-memory document and build a tree.
14655
 *
14656
 * Returns the resulting document tree
14657
 */
14658
14659
xmlDocPtr
14660
xmlParseDoc(const xmlChar *cur) {
14661
    return(xmlSAXParseDoc(NULL, cur, 0));
14662
}
14663
#endif /* LIBXML_SAX1_ENABLED */
14664
14665
#ifdef LIBXML_LEGACY_ENABLED
14666
/************************************************************************
14667
 *                  *
14668
 *  Specific function to keep track of entities references    *
14669
 *  and used by the XSLT debugger         *
14670
 *                  *
14671
 ************************************************************************/
14672
14673
static xmlEntityReferenceFunc xmlEntityRefFunc = NULL;
14674
14675
/**
14676
 * xmlAddEntityReference:
14677
 * @ent : A valid entity
14678
 * @firstNode : A valid first node for children of entity
14679
 * @lastNode : A valid last node of children entity
14680
 *
14681
 * Notify of a reference to an entity of type XML_EXTERNAL_GENERAL_PARSED_ENTITY
14682
 */
14683
static void
14684
xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
14685
                      xmlNodePtr lastNode)
14686
{
14687
    if (xmlEntityRefFunc != NULL) {
14688
        (*xmlEntityRefFunc) (ent, firstNode, lastNode);
14689
    }
14690
}
14691
14692
14693
/**
14694
 * xmlSetEntityReferenceFunc:
14695
 * @func: A valid function
14696
 *
14697
 * Set the function to call call back when a xml reference has been made
14698
 */
14699
void
14700
xmlSetEntityReferenceFunc(xmlEntityReferenceFunc func)
14701
{
14702
    xmlEntityRefFunc = func;
14703
}
14704
#endif /* LIBXML_LEGACY_ENABLED */
14705
14706
/************************************************************************
14707
 *                  *
14708
 *        Miscellaneous       *
14709
 *                  *
14710
 ************************************************************************/
14711
14712
static int xmlParserInitialized = 0;
14713
14714
/**
14715
 * xmlInitParser:
14716
 *
14717
 * Initialization function for the XML parser.
14718
 * This is not reentrant. Call once before processing in case of
14719
 * use in multithreaded programs.
14720
 */
14721
14722
void
14723
67.9k
xmlInitParser(void) {
14724
67.9k
    if (xmlParserInitialized != 0)
14725
67.9k
  return;
14726
14727
#if defined(_WIN32) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
14728
    if (xmlFree == free)
14729
        atexit(xmlCleanupParser);
14730
#endif
14731
14732
2
#ifdef LIBXML_THREAD_ENABLED
14733
2
    __xmlGlobalInitMutexLock();
14734
2
    if (xmlParserInitialized == 0) {
14735
2
#endif
14736
2
  xmlInitThreads();
14737
2
  xmlInitGlobals();
14738
2
  xmlInitMemory();
14739
2
        xmlInitializeDict();
14740
2
  xmlInitCharEncodingHandlers();
14741
2
  xmlDefaultSAXHandlerInit();
14742
2
  xmlRegisterDefaultInputCallbacks();
14743
2
#ifdef LIBXML_OUTPUT_ENABLED
14744
2
  xmlRegisterDefaultOutputCallbacks();
14745
2
#endif /* LIBXML_OUTPUT_ENABLED */
14746
2
#ifdef LIBXML_HTML_ENABLED
14747
2
  htmlInitAutoClose();
14748
2
  htmlDefaultSAXHandlerInit();
14749
2
#endif
14750
2
#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
14751
2
  xmlXPathInit();
14752
2
#endif
14753
2
  xmlParserInitialized = 1;
14754
2
#ifdef LIBXML_THREAD_ENABLED
14755
2
    }
14756
2
    __xmlGlobalInitMutexUnlock();
14757
2
#endif
14758
2
}
14759
14760
/**
14761
 * xmlCleanupParser:
14762
 *
14763
 * This function name is somewhat misleading. It does not clean up
14764
 * parser state, it cleans up memory allocated by the library itself.
14765
 * It is a cleanup function for the XML library. It tries to reclaim all
14766
 * related global memory allocated for the library processing.
14767
 * It doesn't deallocate any document related memory. One should
14768
 * call xmlCleanupParser() only when the process has finished using
14769
 * the library and all XML/HTML documents built with it.
14770
 * See also xmlInitParser() which has the opposite function of preparing
14771
 * the library for operations.
14772
 *
14773
 * WARNING: if your application is multithreaded or has plugin support
14774
 *          calling this may crash the application if another thread or
14775
 *          a plugin is still using libxml2. It's sometimes very hard to
14776
 *          guess if libxml2 is in use in the application, some libraries
14777
 *          or plugins may use it without notice. In case of doubt abstain
14778
 *          from calling this function or do it just before calling exit()
14779
 *          to avoid leak reports from valgrind !
14780
 */
14781
14782
void
14783
0
xmlCleanupParser(void) {
14784
0
    if (!xmlParserInitialized)
14785
0
  return;
14786
14787
0
    xmlCleanupCharEncodingHandlers();
14788
0
#ifdef LIBXML_CATALOG_ENABLED
14789
0
    xmlCatalogCleanup();
14790
0
#endif
14791
0
    xmlDictCleanup();
14792
0
    xmlCleanupInputCallbacks();
14793
0
#ifdef LIBXML_OUTPUT_ENABLED
14794
0
    xmlCleanupOutputCallbacks();
14795
0
#endif
14796
#ifdef LIBXML_SCHEMAS_ENABLED
14797
    xmlSchemaCleanupTypes();
14798
    xmlRelaxNGCleanupTypes();
14799
#endif
14800
0
    xmlCleanupGlobals();
14801
0
    xmlCleanupThreads(); /* must be last if called not from the main thread */
14802
0
    xmlCleanupMemory();
14803
0
    xmlParserInitialized = 0;
14804
0
}
14805
14806
#if defined(HAVE_ATTRIBUTE_DESTRUCTOR) && !defined(LIBXML_STATIC) && \
14807
    !defined(_WIN32)
14808
static void
14809
ATTRIBUTE_DESTRUCTOR
14810
xmlDestructor(void) {
14811
    /*
14812
     * Calling custom deallocation functions in a destructor can cause
14813
     * problems, for example with Nokogiri.
14814
     */
14815
    if (xmlFree == free)
14816
        xmlCleanupParser();
14817
}
14818
#endif
14819
14820
/************************************************************************
14821
 *                  *
14822
 *  New set (2.6.0) of simpler and more flexible APIs   *
14823
 *                  *
14824
 ************************************************************************/
14825
14826
/**
14827
 * DICT_FREE:
14828
 * @str:  a string
14829
 *
14830
 * Free a string if it is not owned by the "dict" dictionary in the
14831
 * current scope
14832
 */
14833
#define DICT_FREE(str)            \
14834
0
  if ((str) && ((!dict) ||       \
14835
0
      (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))  \
14836
0
      xmlFree((char *)(str));
14837
14838
/**
14839
 * xmlCtxtReset:
14840
 * @ctxt: an XML parser context
14841
 *
14842
 * Reset a parser context
14843
 */
14844
void
14845
xmlCtxtReset(xmlParserCtxtPtr ctxt)
14846
0
{
14847
0
    xmlParserInputPtr input;
14848
0
    xmlDictPtr dict;
14849
14850
0
    if (ctxt == NULL)
14851
0
        return;
14852
14853
0
    dict = ctxt->dict;
14854
14855
0
    while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
14856
0
        xmlFreeInputStream(input);
14857
0
    }
14858
0
    ctxt->inputNr = 0;
14859
0
    ctxt->input = NULL;
14860
14861
0
    ctxt->spaceNr = 0;
14862
0
    if (ctxt->spaceTab != NULL) {
14863
0
  ctxt->spaceTab[0] = -1;
14864
0
  ctxt->space = &ctxt->spaceTab[0];
14865
0
    } else {
14866
0
        ctxt->space = NULL;
14867
0
    }
14868
14869
14870
0
    ctxt->nodeNr = 0;
14871
0
    ctxt->node = NULL;
14872
14873
0
    ctxt->nameNr = 0;
14874
0
    ctxt->name = NULL;
14875
14876
0
    ctxt->nsNr = 0;
14877
14878
0
    DICT_FREE(ctxt->version);
14879
0
    ctxt->version = NULL;
14880
0
    DICT_FREE(ctxt->encoding);
14881
0
    ctxt->encoding = NULL;
14882
0
    DICT_FREE(ctxt->directory);
14883
0
    ctxt->directory = NULL;
14884
0
    DICT_FREE(ctxt->extSubURI);
14885
0
    ctxt->extSubURI = NULL;
14886
0
    DICT_FREE(ctxt->extSubSystem);
14887
0
    ctxt->extSubSystem = NULL;
14888
0
    if (ctxt->myDoc != NULL)
14889
0
        xmlFreeDoc(ctxt->myDoc);
14890
0
    ctxt->myDoc = NULL;
14891
14892
0
    ctxt->standalone = -1;
14893
0
    ctxt->hasExternalSubset = 0;
14894
0
    ctxt->hasPErefs = 0;
14895
0
    ctxt->html = 0;
14896
0
    ctxt->external = 0;
14897
0
    ctxt->instate = XML_PARSER_START;
14898
0
    ctxt->token = 0;
14899
14900
0
    ctxt->wellFormed = 1;
14901
0
    ctxt->nsWellFormed = 1;
14902
0
    ctxt->disableSAX = 0;
14903
0
    ctxt->valid = 1;
14904
#if 0
14905
    ctxt->vctxt.userData = ctxt;
14906
    ctxt->vctxt.error = xmlParserValidityError;
14907
    ctxt->vctxt.warning = xmlParserValidityWarning;
14908
#endif
14909
0
    ctxt->record_info = 0;
14910
0
    ctxt->checkIndex = 0;
14911
0
    ctxt->inSubset = 0;
14912
0
    ctxt->errNo = XML_ERR_OK;
14913
0
    ctxt->depth = 0;
14914
0
    ctxt->charset = XML_CHAR_ENCODING_UTF8;
14915
0
    ctxt->catalogs = NULL;
14916
0
    ctxt->nbentities = 0;
14917
0
    ctxt->sizeentities = 0;
14918
0
    ctxt->sizeentcopy = 0;
14919
0
    xmlInitNodeInfoSeq(&ctxt->node_seq);
14920
14921
0
    if (ctxt->attsDefault != NULL) {
14922
0
        xmlHashFree(ctxt->attsDefault, xmlHashDefaultDeallocator);
14923
0
        ctxt->attsDefault = NULL;
14924
0
    }
14925
0
    if (ctxt->attsSpecial != NULL) {
14926
0
        xmlHashFree(ctxt->attsSpecial, NULL);
14927
0
        ctxt->attsSpecial = NULL;
14928
0
    }
14929
14930
0
#ifdef LIBXML_CATALOG_ENABLED
14931
0
    if (ctxt->catalogs != NULL)
14932
0
  xmlCatalogFreeLocal(ctxt->catalogs);
14933
0
#endif
14934
0
    if (ctxt->lastError.code != XML_ERR_OK)
14935
0
        xmlResetError(&ctxt->lastError);
14936
0
}
14937
14938
/**
14939
 * xmlCtxtResetPush:
14940
 * @ctxt: an XML parser context
14941
 * @chunk:  a pointer to an array of chars
14942
 * @size:  number of chars in the array
14943
 * @filename:  an optional file name or URI
14944
 * @encoding:  the document encoding, or NULL
14945
 *
14946
 * Reset a push parser context
14947
 *
14948
 * Returns 0 in case of success and 1 in case of error
14949
 */
14950
int
14951
xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk,
14952
                 int size, const char *filename, const char *encoding)
14953
0
{
14954
0
    xmlParserInputPtr inputStream;
14955
0
    xmlParserInputBufferPtr buf;
14956
0
    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
14957
14958
0
    if (ctxt == NULL)
14959
0
        return(1);
14960
14961
0
    if ((encoding == NULL) && (chunk != NULL) && (size >= 4))
14962
0
        enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
14963
14964
0
    buf = xmlAllocParserInputBuffer(enc);
14965
0
    if (buf == NULL)
14966
0
        return(1);
14967
14968
0
    if (ctxt == NULL) {
14969
0
        xmlFreeParserInputBuffer(buf);
14970
0
        return(1);
14971
0
    }
14972
14973
0
    xmlCtxtReset(ctxt);
14974
14975
0
    if (filename == NULL) {
14976
0
        ctxt->directory = NULL;
14977
0
    } else {
14978
0
        ctxt->directory = xmlParserGetDirectory(filename);
14979
0
    }
14980
14981
0
    inputStream = xmlNewInputStream(ctxt);
14982
0
    if (inputStream == NULL) {
14983
0
        xmlFreeParserInputBuffer(buf);
14984
0
        return(1);
14985
0
    }
14986
14987
0
    if (filename == NULL)
14988
0
        inputStream->filename = NULL;
14989
0
    else
14990
0
        inputStream->filename = (char *)
14991
0
            xmlCanonicPath((const xmlChar *) filename);
14992
0
    inputStream->buf = buf;
14993
0
    xmlBufResetInput(buf->buffer, inputStream);
14994
14995
0
    inputPush(ctxt, inputStream);
14996
14997
0
    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
14998
0
        (ctxt->input->buf != NULL)) {
14999
0
  size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
15000
0
        size_t cur = ctxt->input->cur - ctxt->input->base;
15001
15002
0
        xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
15003
15004
0
        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
15005
#ifdef DEBUG_PUSH
15006
        xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
15007
#endif
15008
0
    }
15009
15010
0
    if (encoding != NULL) {
15011
0
        xmlCharEncodingHandlerPtr hdlr;
15012
15013
0
        if (ctxt->encoding != NULL)
15014
0
      xmlFree((xmlChar *) ctxt->encoding);
15015
0
        ctxt->encoding = xmlStrdup((const xmlChar *) encoding);
15016
15017
0
        hdlr = xmlFindCharEncodingHandler(encoding);
15018
0
        if (hdlr != NULL) {
15019
0
            xmlSwitchToEncoding(ctxt, hdlr);
15020
0
  } else {
15021
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
15022
0
            "Unsupported encoding %s\n", BAD_CAST encoding);
15023
0
        }
15024
0
    } else if (enc != XML_CHAR_ENCODING_NONE) {
15025
0
        xmlSwitchEncoding(ctxt, enc);
15026
0
    }
15027
15028
0
    return(0);
15029
0
}
15030
15031
15032
/**
15033
 * xmlCtxtUseOptionsInternal:
15034
 * @ctxt: an XML parser context
15035
 * @options:  a combination of xmlParserOption
15036
 * @encoding:  the user provided encoding to use
15037
 *
15038
 * Applies the options to the parser context
15039
 *
15040
 * Returns 0 in case of success, the set of unknown or unimplemented options
15041
 *         in case of error.
15042
 */
15043
static int
15044
xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encoding)
15045
1.03k
{
15046
1.03k
    if (ctxt == NULL)
15047
0
        return(-1);
15048
1.03k
    if (encoding != NULL) {
15049
0
        if (ctxt->encoding != NULL)
15050
0
      xmlFree((xmlChar *) ctxt->encoding);
15051
0
        ctxt->encoding = xmlStrdup((const xmlChar *) encoding);
15052
0
    }
15053
1.03k
    if (options & XML_PARSE_RECOVER) {
15054
0
        ctxt->recovery = 1;
15055
0
        options -= XML_PARSE_RECOVER;
15056
0
  ctxt->options |= XML_PARSE_RECOVER;
15057
0
    } else
15058
1.03k
        ctxt->recovery = 0;
15059
1.03k
    if (options & XML_PARSE_DTDLOAD) {
15060
836
        ctxt->loadsubset = XML_DETECT_IDS;
15061
836
        options -= XML_PARSE_DTDLOAD;
15062
836
  ctxt->options |= XML_PARSE_DTDLOAD;
15063
836
    } else
15064
201
        ctxt->loadsubset = 0;
15065
1.03k
    if (options & XML_PARSE_DTDATTR) {
15066
836
        ctxt->loadsubset |= XML_COMPLETE_ATTRS;
15067
836
        options -= XML_PARSE_DTDATTR;
15068
836
  ctxt->options |= XML_PARSE_DTDATTR;
15069
836
    }
15070
1.03k
    if (options & XML_PARSE_NOENT) {
15071
836
        ctxt->replaceEntities = 1;
15072
        /* ctxt->loadsubset |= XML_DETECT_IDS; */
15073
836
        options -= XML_PARSE_NOENT;
15074
836
  ctxt->options |= XML_PARSE_NOENT;
15075
836
    } else
15076
201
        ctxt->replaceEntities = 0;
15077
1.03k
    if (options & XML_PARSE_PEDANTIC) {
15078
0
        ctxt->pedantic = 1;
15079
0
        options -= XML_PARSE_PEDANTIC;
15080
0
  ctxt->options |= XML_PARSE_PEDANTIC;
15081
0
    } else
15082
1.03k
        ctxt->pedantic = 0;
15083
1.03k
    if (options & XML_PARSE_NOBLANKS) {
15084
0
        ctxt->keepBlanks = 0;
15085
0
        ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
15086
0
        options -= XML_PARSE_NOBLANKS;
15087
0
  ctxt->options |= XML_PARSE_NOBLANKS;
15088
0
    } else
15089
1.03k
        ctxt->keepBlanks = 1;
15090
1.03k
    if (options & XML_PARSE_DTDVALID) {
15091
0
        ctxt->validate = 1;
15092
0
        if (options & XML_PARSE_NOWARNING)
15093
0
            ctxt->vctxt.warning = NULL;
15094
0
        if (options & XML_PARSE_NOERROR)
15095
0
            ctxt->vctxt.error = NULL;
15096
0
        options -= XML_PARSE_DTDVALID;
15097
0
  ctxt->options |= XML_PARSE_DTDVALID;
15098
0
    } else
15099
1.03k
        ctxt->validate = 0;
15100
1.03k
    if (options & XML_PARSE_NOWARNING) {
15101
0
        ctxt->sax->warning = NULL;
15102
0
        options -= XML_PARSE_NOWARNING;
15103
0
    }
15104
1.03k
    if (options & XML_PARSE_NOERROR) {
15105
0
        ctxt->sax->error = NULL;
15106
0
        ctxt->sax->fatalError = NULL;
15107
0
        options -= XML_PARSE_NOERROR;
15108
0
    }
15109
#ifdef LIBXML_SAX1_ENABLED
15110
    if (options & XML_PARSE_SAX1) {
15111
        ctxt->sax->startElement = xmlSAX2StartElement;
15112
        ctxt->sax->endElement = xmlSAX2EndElement;
15113
        ctxt->sax->startElementNs = NULL;
15114
        ctxt->sax->endElementNs = NULL;
15115
        ctxt->sax->initialized = 1;
15116
        options -= XML_PARSE_SAX1;
15117
  ctxt->options |= XML_PARSE_SAX1;
15118
    }
15119
#endif /* LIBXML_SAX1_ENABLED */
15120
1.03k
    if (options & XML_PARSE_NODICT) {
15121
0
        ctxt->dictNames = 0;
15122
0
        options -= XML_PARSE_NODICT;
15123
0
  ctxt->options |= XML_PARSE_NODICT;
15124
1.03k
    } else {
15125
1.03k
        ctxt->dictNames = 1;
15126
1.03k
    }
15127
1.03k
    if (options & XML_PARSE_NOCDATA) {
15128
836
        ctxt->sax->cdataBlock = NULL;
15129
836
        options -= XML_PARSE_NOCDATA;
15130
836
  ctxt->options |= XML_PARSE_NOCDATA;
15131
836
    }
15132
1.03k
    if (options & XML_PARSE_NSCLEAN) {
15133
0
  ctxt->options |= XML_PARSE_NSCLEAN;
15134
0
        options -= XML_PARSE_NSCLEAN;
15135
0
    }
15136
1.03k
    if (options & XML_PARSE_NONET) {
15137
0
  ctxt->options |= XML_PARSE_NONET;
15138
0
        options -= XML_PARSE_NONET;
15139
0
    }
15140
1.03k
    if (options & XML_PARSE_COMPACT) {
15141
0
  ctxt->options |= XML_PARSE_COMPACT;
15142
0
        options -= XML_PARSE_COMPACT;
15143
0
    }
15144
1.03k
    if (options & XML_PARSE_OLD10) {
15145
0
  ctxt->options |= XML_PARSE_OLD10;
15146
0
        options -= XML_PARSE_OLD10;
15147
0
    }
15148
1.03k
    if (options & XML_PARSE_NOBASEFIX) {
15149
0
  ctxt->options |= XML_PARSE_NOBASEFIX;
15150
0
        options -= XML_PARSE_NOBASEFIX;
15151
0
    }
15152
1.03k
    if (options & XML_PARSE_HUGE) {
15153
0
  ctxt->options |= XML_PARSE_HUGE;
15154
0
        options -= XML_PARSE_HUGE;
15155
0
        if (ctxt->dict != NULL)
15156
0
            xmlDictSetLimit(ctxt->dict, 0);
15157
0
    }
15158
1.03k
    if (options & XML_PARSE_OLDSAX) {
15159
0
  ctxt->options |= XML_PARSE_OLDSAX;
15160
0
        options -= XML_PARSE_OLDSAX;
15161
0
    }
15162
1.03k
    if (options & XML_PARSE_IGNORE_ENC) {
15163
0
  ctxt->options |= XML_PARSE_IGNORE_ENC;
15164
0
        options -= XML_PARSE_IGNORE_ENC;
15165
0
    }
15166
1.03k
    if (options & XML_PARSE_BIG_LINES) {
15167
0
  ctxt->options |= XML_PARSE_BIG_LINES;
15168
0
        options -= XML_PARSE_BIG_LINES;
15169
0
    }
15170
1.03k
    ctxt->linenumbers = 1;
15171
1.03k
    return (options);
15172
1.03k
}
15173
15174
/**
15175
 * xmlCtxtUseOptions:
15176
 * @ctxt: an XML parser context
15177
 * @options:  a combination of xmlParserOption
15178
 *
15179
 * Applies the options to the parser context
15180
 *
15181
 * Returns 0 in case of success, the set of unknown or unimplemented options
15182
 *         in case of error.
15183
 */
15184
int
15185
xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options)
15186
836
{
15187
836
   return(xmlCtxtUseOptionsInternal(ctxt, options, NULL));
15188
836
}
15189
15190
/**
15191
 * xmlDoRead:
15192
 * @ctxt:  an XML parser context
15193
 * @URL:  the base URL to use for the document
15194
 * @encoding:  the document encoding, or NULL
15195
 * @options:  a combination of xmlParserOption
15196
 * @reuse:  keep the context for reuse
15197
 *
15198
 * Common front-end for the xmlRead functions
15199
 *
15200
 * Returns the resulting document tree or NULL
15201
 */
15202
static xmlDocPtr
15203
xmlDoRead(xmlParserCtxtPtr ctxt, const char *URL, const char *encoding,
15204
          int options, int reuse)
15205
201
{
15206
201
    xmlDocPtr ret;
15207
15208
201
    xmlCtxtUseOptionsInternal(ctxt, options, encoding);
15209
201
    if (encoding != NULL) {
15210
0
        xmlCharEncodingHandlerPtr hdlr;
15211
15212
0
  hdlr = xmlFindCharEncodingHandler(encoding);
15213
0
  if (hdlr != NULL)
15214
0
      xmlSwitchToEncoding(ctxt, hdlr);
15215
0
    }
15216
201
    if ((URL != NULL) && (ctxt->input != NULL) &&
15217
201
        (ctxt->input->filename == NULL))
15218
0
        ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL);
15219
201
    xmlParseDocument(ctxt);
15220
201
    if ((ctxt->wellFormed) || ctxt->recovery)
15221
64
        ret = ctxt->myDoc;
15222
137
    else {
15223
137
        ret = NULL;
15224
137
  if (ctxt->myDoc != NULL) {
15225
94
      xmlFreeDoc(ctxt->myDoc);
15226
94
  }
15227
137
    }
15228
201
    ctxt->myDoc = NULL;
15229
201
    if (!reuse) {
15230
201
  xmlFreeParserCtxt(ctxt);
15231
201
    }
15232
15233
201
    return (ret);
15234
201
}
15235
15236
/**
15237
 * xmlReadDoc:
15238
 * @cur:  a pointer to a zero terminated string
15239
 * @URL:  the base URL to use for the document
15240
 * @encoding:  the document encoding, or NULL
15241
 * @options:  a combination of xmlParserOption
15242
 *
15243
 * parse an XML in-memory document and build a tree.
15244
 *
15245
 * Returns the resulting document tree
15246
 */
15247
xmlDocPtr
15248
xmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int options)
15249
0
{
15250
0
    xmlParserCtxtPtr ctxt;
15251
15252
0
    if (cur == NULL)
15253
0
        return (NULL);
15254
0
    xmlInitParser();
15255
15256
0
    ctxt = xmlCreateDocParserCtxt(cur);
15257
0
    if (ctxt == NULL)
15258
0
        return (NULL);
15259
0
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
15260
0
}
15261
15262
/**
15263
 * xmlReadFile:
15264
 * @filename:  a file or URL
15265
 * @encoding:  the document encoding, or NULL
15266
 * @options:  a combination of xmlParserOption
15267
 *
15268
 * parse an XML file from the filesystem or the network.
15269
 *
15270
 * Returns the resulting document tree
15271
 */
15272
xmlDocPtr
15273
xmlReadFile(const char *filename, const char *encoding, int options)
15274
2
{
15275
2
    xmlParserCtxtPtr ctxt;
15276
15277
2
    xmlInitParser();
15278
2
    ctxt = xmlCreateURLParserCtxt(filename, options);
15279
2
    if (ctxt == NULL)
15280
0
        return (NULL);
15281
2
    return (xmlDoRead(ctxt, NULL, encoding, options, 0));
15282
2
}
15283
15284
/**
15285
 * xmlReadMemory:
15286
 * @buffer:  a pointer to a char array
15287
 * @size:  the size of the array
15288
 * @URL:  the base URL to use for the document
15289
 * @encoding:  the document encoding, or NULL
15290
 * @options:  a combination of xmlParserOption
15291
 *
15292
 * parse an XML in-memory document and build a tree.
15293
 *
15294
 * Returns the resulting document tree
15295
 */
15296
xmlDocPtr
15297
xmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options)
15298
199
{
15299
199
    xmlParserCtxtPtr ctxt;
15300
15301
199
    xmlInitParser();
15302
199
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
15303
199
    if (ctxt == NULL)
15304
0
        return (NULL);
15305
199
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
15306
199
}
15307
15308
/**
15309
 * xmlReadFd:
15310
 * @fd:  an open file descriptor
15311
 * @URL:  the base URL to use for the document
15312
 * @encoding:  the document encoding, or NULL
15313
 * @options:  a combination of xmlParserOption
15314
 *
15315
 * parse an XML from a file descriptor and build a tree.
15316
 * NOTE that the file descriptor will not be closed when the
15317
 *      reader is closed or reset.
15318
 *
15319
 * Returns the resulting document tree
15320
 */
15321
xmlDocPtr
15322
xmlReadFd(int fd, const char *URL, const char *encoding, int options)
15323
0
{
15324
0
    xmlParserCtxtPtr ctxt;
15325
0
    xmlParserInputBufferPtr input;
15326
0
    xmlParserInputPtr stream;
15327
15328
0
    if (fd < 0)
15329
0
        return (NULL);
15330
0
    xmlInitParser();
15331
15332
0
    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
15333
0
    if (input == NULL)
15334
0
        return (NULL);
15335
0
    input->closecallback = NULL;
15336
0
    ctxt = xmlNewParserCtxt();
15337
0
    if (ctxt == NULL) {
15338
0
        xmlFreeParserInputBuffer(input);
15339
0
        return (NULL);
15340
0
    }
15341
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15342
0
    if (stream == NULL) {
15343
0
        xmlFreeParserInputBuffer(input);
15344
0
  xmlFreeParserCtxt(ctxt);
15345
0
        return (NULL);
15346
0
    }
15347
0
    inputPush(ctxt, stream);
15348
0
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
15349
0
}
15350
15351
/**
15352
 * xmlReadIO:
15353
 * @ioread:  an I/O read function
15354
 * @ioclose:  an I/O close function
15355
 * @ioctx:  an I/O handler
15356
 * @URL:  the base URL to use for the document
15357
 * @encoding:  the document encoding, or NULL
15358
 * @options:  a combination of xmlParserOption
15359
 *
15360
 * parse an XML document from I/O functions and source and build a tree.
15361
 *
15362
 * Returns the resulting document tree
15363
 */
15364
xmlDocPtr
15365
xmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
15366
          void *ioctx, const char *URL, const char *encoding, int options)
15367
0
{
15368
0
    xmlParserCtxtPtr ctxt;
15369
0
    xmlParserInputBufferPtr input;
15370
0
    xmlParserInputPtr stream;
15371
15372
0
    if (ioread == NULL)
15373
0
        return (NULL);
15374
0
    xmlInitParser();
15375
15376
0
    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
15377
0
                                         XML_CHAR_ENCODING_NONE);
15378
0
    if (input == NULL) {
15379
0
        if (ioclose != NULL)
15380
0
            ioclose(ioctx);
15381
0
        return (NULL);
15382
0
    }
15383
0
    ctxt = xmlNewParserCtxt();
15384
0
    if (ctxt == NULL) {
15385
0
        xmlFreeParserInputBuffer(input);
15386
0
        return (NULL);
15387
0
    }
15388
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15389
0
    if (stream == NULL) {
15390
0
        xmlFreeParserInputBuffer(input);
15391
0
  xmlFreeParserCtxt(ctxt);
15392
0
        return (NULL);
15393
0
    }
15394
0
    inputPush(ctxt, stream);
15395
0
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
15396
0
}
15397
15398
/**
15399
 * xmlCtxtReadDoc:
15400
 * @ctxt:  an XML parser context
15401
 * @cur:  a pointer to a zero terminated string
15402
 * @URL:  the base URL to use for the document
15403
 * @encoding:  the document encoding, or NULL
15404
 * @options:  a combination of xmlParserOption
15405
 *
15406
 * parse an XML in-memory document and build a tree.
15407
 * This reuses the existing @ctxt parser context
15408
 *
15409
 * Returns the resulting document tree
15410
 */
15411
xmlDocPtr
15412
xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar * cur,
15413
               const char *URL, const char *encoding, int options)
15414
0
{
15415
0
    if (cur == NULL)
15416
0
        return (NULL);
15417
0
    return (xmlCtxtReadMemory(ctxt, (const char *) cur, xmlStrlen(cur), URL,
15418
0
                              encoding, options));
15419
0
}
15420
15421
/**
15422
 * xmlCtxtReadFile:
15423
 * @ctxt:  an XML parser context
15424
 * @filename:  a file or URL
15425
 * @encoding:  the document encoding, or NULL
15426
 * @options:  a combination of xmlParserOption
15427
 *
15428
 * parse an XML file from the filesystem or the network.
15429
 * This reuses the existing @ctxt parser context
15430
 *
15431
 * Returns the resulting document tree
15432
 */
15433
xmlDocPtr
15434
xmlCtxtReadFile(xmlParserCtxtPtr ctxt, const char *filename,
15435
                const char *encoding, int options)
15436
0
{
15437
0
    xmlParserInputPtr stream;
15438
15439
0
    if (filename == NULL)
15440
0
        return (NULL);
15441
0
    if (ctxt == NULL)
15442
0
        return (NULL);
15443
0
    xmlInitParser();
15444
15445
0
    xmlCtxtReset(ctxt);
15446
15447
0
    stream = xmlLoadExternalEntity(filename, NULL, ctxt);
15448
0
    if (stream == NULL) {
15449
0
        return (NULL);
15450
0
    }
15451
0
    inputPush(ctxt, stream);
15452
0
    return (xmlDoRead(ctxt, NULL, encoding, options, 1));
15453
0
}
15454
15455
/**
15456
 * xmlCtxtReadMemory:
15457
 * @ctxt:  an XML parser context
15458
 * @buffer:  a pointer to a char array
15459
 * @size:  the size of the array
15460
 * @URL:  the base URL to use for the document
15461
 * @encoding:  the document encoding, or NULL
15462
 * @options:  a combination of xmlParserOption
15463
 *
15464
 * parse an XML in-memory document and build a tree.
15465
 * This reuses the existing @ctxt parser context
15466
 *
15467
 * Returns the resulting document tree
15468
 */
15469
xmlDocPtr
15470
xmlCtxtReadMemory(xmlParserCtxtPtr ctxt, const char *buffer, int size,
15471
                  const char *URL, const char *encoding, int options)
15472
0
{
15473
0
    xmlParserInputBufferPtr input;
15474
0
    xmlParserInputPtr stream;
15475
15476
0
    if (ctxt == NULL)
15477
0
        return (NULL);
15478
0
    if (buffer == NULL)
15479
0
        return (NULL);
15480
0
    xmlInitParser();
15481
15482
0
    xmlCtxtReset(ctxt);
15483
15484
0
    input = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
15485
0
    if (input == NULL) {
15486
0
  return(NULL);
15487
0
    }
15488
15489
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15490
0
    if (stream == NULL) {
15491
0
  xmlFreeParserInputBuffer(input);
15492
0
  return(NULL);
15493
0
    }
15494
15495
0
    inputPush(ctxt, stream);
15496
0
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15497
0
}
15498
15499
/**
15500
 * xmlCtxtReadFd:
15501
 * @ctxt:  an XML parser context
15502
 * @fd:  an open file descriptor
15503
 * @URL:  the base URL to use for the document
15504
 * @encoding:  the document encoding, or NULL
15505
 * @options:  a combination of xmlParserOption
15506
 *
15507
 * parse an XML from a file descriptor and build a tree.
15508
 * This reuses the existing @ctxt parser context
15509
 * NOTE that the file descriptor will not be closed when the
15510
 *      reader is closed or reset.
15511
 *
15512
 * Returns the resulting document tree
15513
 */
15514
xmlDocPtr
15515
xmlCtxtReadFd(xmlParserCtxtPtr ctxt, int fd,
15516
              const char *URL, const char *encoding, int options)
15517
0
{
15518
0
    xmlParserInputBufferPtr input;
15519
0
    xmlParserInputPtr stream;
15520
15521
0
    if (fd < 0)
15522
0
        return (NULL);
15523
0
    if (ctxt == NULL)
15524
0
        return (NULL);
15525
0
    xmlInitParser();
15526
15527
0
    xmlCtxtReset(ctxt);
15528
15529
15530
0
    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
15531
0
    if (input == NULL)
15532
0
        return (NULL);
15533
0
    input->closecallback = NULL;
15534
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15535
0
    if (stream == NULL) {
15536
0
        xmlFreeParserInputBuffer(input);
15537
0
        return (NULL);
15538
0
    }
15539
0
    inputPush(ctxt, stream);
15540
0
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15541
0
}
15542
15543
/**
15544
 * xmlCtxtReadIO:
15545
 * @ctxt:  an XML parser context
15546
 * @ioread:  an I/O read function
15547
 * @ioclose:  an I/O close function
15548
 * @ioctx:  an I/O handler
15549
 * @URL:  the base URL to use for the document
15550
 * @encoding:  the document encoding, or NULL
15551
 * @options:  a combination of xmlParserOption
15552
 *
15553
 * parse an XML document from I/O functions and source and build a tree.
15554
 * This reuses the existing @ctxt parser context
15555
 *
15556
 * Returns the resulting document tree
15557
 */
15558
xmlDocPtr
15559
xmlCtxtReadIO(xmlParserCtxtPtr ctxt, xmlInputReadCallback ioread,
15560
              xmlInputCloseCallback ioclose, void *ioctx,
15561
        const char *URL,
15562
              const char *encoding, int options)
15563
0
{
15564
0
    xmlParserInputBufferPtr input;
15565
0
    xmlParserInputPtr stream;
15566
15567
0
    if (ioread == NULL)
15568
0
        return (NULL);
15569
0
    if (ctxt == NULL)
15570
0
        return (NULL);
15571
0
    xmlInitParser();
15572
15573
0
    xmlCtxtReset(ctxt);
15574
15575
0
    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
15576
0
                                         XML_CHAR_ENCODING_NONE);
15577
0
    if (input == NULL) {
15578
0
        if (ioclose != NULL)
15579
0
            ioclose(ioctx);
15580
0
        return (NULL);
15581
0
    }
15582
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15583
0
    if (stream == NULL) {
15584
0
        xmlFreeParserInputBuffer(input);
15585
0
        return (NULL);
15586
0
    }
15587
0
    inputPush(ctxt, stream);
15588
0
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15589
0
}
15590