Coverage Report

Created: 2024-02-11 06:23

/src/libprotobuf-mutator/build/examples/libxml2/external.libxml2/src/external.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/parser.h>
55
#include <libxml/xmlmemory.h>
56
#include <libxml/tree.h>
57
#include <libxml/parserInternals.h>
58
#include <libxml/valid.h>
59
#include <libxml/entities.h>
60
#include <libxml/xmlerror.h>
61
#include <libxml/encoding.h>
62
#include <libxml/xmlIO.h>
63
#include <libxml/uri.h>
64
#include <libxml/SAX2.h>
65
#ifdef LIBXML_CATALOG_ENABLED
66
#include <libxml/catalog.h>
67
#endif
68
69
#include "private/buf.h"
70
#include "private/dict.h"
71
#include "private/entities.h"
72
#include "private/error.h"
73
#include "private/html.h"
74
#include "private/io.h"
75
#include "private/parser.h"
76
77
58.4k
#define NS_INDEX_EMPTY  INT_MAX
78
32.6k
#define NS_INDEX_XML    (INT_MAX - 1)
79
16.0k
#define URI_HASH_EMPTY  0xD943A04E
80
2.40k
#define URI_HASH_XML    0xF0451F02
81
82
struct _xmlStartTag {
83
    const xmlChar *prefix;
84
    const xmlChar *URI;
85
    int line;
86
    int nsNr;
87
};
88
89
typedef struct {
90
    void *saxData;
91
    unsigned prefixHashValue;
92
    unsigned uriHashValue;
93
    unsigned elementId;
94
    int oldIndex;
95
} xmlParserNsExtra;
96
97
typedef struct {
98
    unsigned hashValue;
99
    int index;
100
} xmlParserNsBucket;
101
102
struct _xmlParserNsData {
103
    xmlParserNsExtra *extra;
104
105
    unsigned hashSize;
106
    unsigned hashElems;
107
    xmlParserNsBucket *hash;
108
109
    unsigned elementId;
110
    int defaultNsIndex;
111
    int minNsIndex;
112
};
113
114
struct _xmlAttrHashBucket {
115
    int index;
116
};
117
118
static int
119
xmlParseElementStart(xmlParserCtxtPtr ctxt);
120
121
static void
122
xmlParseElementEnd(xmlParserCtxtPtr ctxt);
123
124
static xmlEntityPtr
125
xmlLookupGeneralEntity(xmlParserCtxtPtr ctxt, const xmlChar *name, int inAttr);
126
127
static const xmlChar *
128
xmlParseEntityRefInternal(xmlParserCtxtPtr ctxt);
129
130
/************************************************************************
131
 *                  *
132
 *  Arbitrary limits set in the parser. See XML_PARSE_HUGE    *
133
 *                  *
134
 ************************************************************************/
135
136
#define XML_PARSER_BIG_ENTITY 1000
137
#define XML_PARSER_LOT_ENTITY 5000
138
139
/*
140
 * Constants for protection against abusive entity expansion
141
 * ("billion laughs").
142
 */
143
144
/*
145
 * A certain amount of entity expansion which is always allowed.
146
 */
147
134k
#define XML_PARSER_ALLOWED_EXPANSION 1000000
148
149
/*
150
 * Fixed cost for each entity reference. This crudely models processing time
151
 * as well to protect, for example, against exponential expansion of empty
152
 * or very short entities.
153
 */
154
143k
#define XML_ENT_FIXED_COST 20
155
156
/**
157
 * xmlParserMaxDepth:
158
 *
159
 * arbitrary depth limit for the XML documents that we allow to
160
 * process. This is not a limitation of the parser but a safety
161
 * boundary feature. It can be disabled with the XML_PARSE_HUGE
162
 * parser option.
163
 */
164
const unsigned int xmlParserMaxDepth = 256;
165
166
167
168
51.3k
#define XML_PARSER_BIG_BUFFER_SIZE 300
169
64.8k
#define XML_PARSER_BUFFER_SIZE 100
170
25.9k
#define SAX_COMPAT_MODE BAD_CAST "SAX compatibility mode document"
171
172
/**
173
 * XML_PARSER_CHUNK_SIZE
174
 *
175
 * When calling GROW that's the minimal amount of data
176
 * the parser expected to have received. It is not a hard
177
 * limit but an optimization when reading strings like Names
178
 * It is not strictly needed as long as inputs available characters
179
 * are followed by 0, which should be provided by the I/O level
180
 */
181
#define XML_PARSER_CHUNK_SIZE 100
182
183
/**
184
 * xmlParserVersion:
185
 *
186
 * Constant string describing the internal version of the library
187
 */
188
const char *const
189
xmlParserVersion = LIBXML_VERSION_STRING LIBXML_VERSION_EXTRA;
190
191
/*
192
 * List of XML prefixed PI allowed by W3C specs
193
 */
194
195
static const char* const xmlW3CPIs[] = {
196
    "xml-stylesheet",
197
    "xml-model",
198
    NULL
199
};
200
201
202
/* DEPR void xmlParserHandleReference(xmlParserCtxtPtr ctxt); */
203
static xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt,
204
                                              const xmlChar **str);
205
206
static void
207
xmlCtxtParseEntity(xmlParserCtxtPtr ctxt, xmlEntityPtr ent);
208
209
static int
210
xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity);
211
212
/************************************************************************
213
 *                  *
214
 *    Some factorized error routines        *
215
 *                  *
216
 ************************************************************************/
217
218
static void
219
0
xmlErrMemory(xmlParserCtxtPtr ctxt) {
220
0
    xmlCtxtErrMemory(ctxt);
221
0
}
222
223
/**
224
 * xmlErrAttributeDup:
225
 * @ctxt:  an XML parser context
226
 * @prefix:  the attribute prefix
227
 * @localname:  the attribute localname
228
 *
229
 * Handle a redefinition of attribute error
230
 */
231
static void
232
xmlErrAttributeDup(xmlParserCtxtPtr ctxt, const xmlChar * prefix,
233
                   const xmlChar * localname)
234
5.44k
{
235
5.44k
    if (prefix == NULL)
236
5.13k
        xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, XML_ERR_ATTRIBUTE_REDEFINED,
237
5.13k
                   XML_ERR_FATAL, localname, NULL, NULL, 0,
238
5.13k
                   "Attribute %s redefined\n", localname);
239
309
    else
240
309
        xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, XML_ERR_ATTRIBUTE_REDEFINED,
241
309
                   XML_ERR_FATAL, prefix, localname, NULL, 0,
242
309
                   "Attribute %s:%s redefined\n", prefix, localname);
243
5.44k
}
244
245
/**
246
 * xmlFatalErrMsg:
247
 * @ctxt:  an XML parser context
248
 * @error:  the error number
249
 * @msg:  the error message
250
 *
251
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
252
 */
253
static void LIBXML_ATTR_FORMAT(3,0)
254
xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
255
               const char *msg)
256
304k
{
257
304k
    xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
258
304k
               NULL, NULL, NULL, 0, "%s", msg);
259
304k
}
260
261
/**
262
 * xmlWarningMsg:
263
 * @ctxt:  an XML parser context
264
 * @error:  the error number
265
 * @msg:  the error message
266
 * @str1:  extra data
267
 * @str2:  extra data
268
 *
269
 * Handle a warning.
270
 */
271
void LIBXML_ATTR_FORMAT(3,0)
272
xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
273
              const char *msg, const xmlChar *str1, const xmlChar *str2)
274
4.70k
{
275
4.70k
    xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_WARNING,
276
4.70k
               str1, str2, NULL, 0, msg, str1, str2);
277
4.70k
}
278
279
/**
280
 * xmlValidityError:
281
 * @ctxt:  an XML parser context
282
 * @error:  the error number
283
 * @msg:  the error message
284
 * @str1:  extra data
285
 *
286
 * Handle a validity error.
287
 */
288
static void LIBXML_ATTR_FORMAT(3,0)
289
xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error,
290
              const char *msg, const xmlChar *str1, const xmlChar *str2)
291
1.53k
{
292
1.53k
    ctxt->valid = 0;
293
294
1.53k
    xmlCtxtErr(ctxt, NULL, XML_FROM_DTD, error, XML_ERR_ERROR,
295
1.53k
               str1, str2, NULL, 0, msg, str1, str2);
296
1.53k
}
297
298
/**
299
 * xmlFatalErrMsgInt:
300
 * @ctxt:  an XML parser context
301
 * @error:  the error number
302
 * @msg:  the error message
303
 * @val:  an integer value
304
 *
305
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
306
 */
307
static void LIBXML_ATTR_FORMAT(3,0)
308
xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
309
                  const char *msg, int val)
310
11.4k
{
311
11.4k
    xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
312
11.4k
               NULL, NULL, NULL, val, msg, val);
313
11.4k
}
314
315
/**
316
 * xmlFatalErrMsgStrIntStr:
317
 * @ctxt:  an XML parser context
318
 * @error:  the error number
319
 * @msg:  the error message
320
 * @str1:  an string info
321
 * @val:  an integer value
322
 * @str2:  an string info
323
 *
324
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
325
 */
326
static void LIBXML_ATTR_FORMAT(3,0)
327
xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
328
                  const char *msg, const xmlChar *str1, int val,
329
      const xmlChar *str2)
330
110k
{
331
110k
    xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
332
110k
               str1, str2, NULL, val, msg, str1, val, str2);
333
110k
}
334
335
/**
336
 * xmlFatalErrMsgStr:
337
 * @ctxt:  an XML parser context
338
 * @error:  the error number
339
 * @msg:  the error message
340
 * @val:  a string value
341
 *
342
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
343
 */
344
static void LIBXML_ATTR_FORMAT(3,0)
345
xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
346
                  const char *msg, const xmlChar * val)
347
101k
{
348
101k
    xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
349
101k
               val, NULL, NULL, 0, msg, val);
350
101k
}
351
352
/**
353
 * xmlErrMsgStr:
354
 * @ctxt:  an XML parser context
355
 * @error:  the error number
356
 * @msg:  the error message
357
 * @val:  a string value
358
 *
359
 * Handle a non fatal parser error
360
 */
361
static void LIBXML_ATTR_FORMAT(3,0)
362
xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
363
                  const char *msg, const xmlChar * val)
364
10.6k
{
365
10.6k
    xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_ERROR,
366
10.6k
               val, NULL, NULL, 0, msg, val);
367
10.6k
}
368
369
/**
370
 * xmlNsErr:
371
 * @ctxt:  an XML parser context
372
 * @error:  the error number
373
 * @msg:  the message
374
 * @info1:  extra information string
375
 * @info2:  extra information string
376
 *
377
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
378
 */
379
static void LIBXML_ATTR_FORMAT(3,0)
380
xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
381
         const char *msg,
382
         const xmlChar * info1, const xmlChar * info2,
383
         const xmlChar * info3)
384
48.9k
{
385
48.9k
    ctxt->nsWellFormed = 0;
386
387
48.9k
    xmlCtxtErr(ctxt, NULL, XML_FROM_NAMESPACE, error, XML_ERR_ERROR,
388
48.9k
               info1, info2, info3, 0, msg, info1, info2, info3);
389
48.9k
}
390
391
/**
392
 * xmlNsWarn
393
 * @ctxt:  an XML parser context
394
 * @error:  the error number
395
 * @msg:  the message
396
 * @info1:  extra information string
397
 * @info2:  extra information string
398
 *
399
 * Handle a namespace warning error
400
 */
401
static void LIBXML_ATTR_FORMAT(3,0)
402
xmlNsWarn(xmlParserCtxtPtr ctxt, xmlParserErrors error,
403
         const char *msg,
404
         const xmlChar * info1, const xmlChar * info2,
405
         const xmlChar * info3)
406
998
{
407
998
    xmlCtxtErr(ctxt, NULL, XML_FROM_NAMESPACE, error, XML_ERR_WARNING,
408
998
               info1, info2, info3, 0, msg, info1, info2, info3);
409
998
}
410
411
static void
412
423k
xmlSaturatedAdd(unsigned long *dst, unsigned long val) {
413
423k
    if (val > ULONG_MAX - *dst)
414
0
        *dst = ULONG_MAX;
415
423k
    else
416
423k
        *dst += val;
417
423k
}
418
419
static void
420
137k
xmlSaturatedAddSizeT(unsigned long *dst, unsigned long val) {
421
137k
    if (val > ULONG_MAX - *dst)
422
0
        *dst = ULONG_MAX;
423
137k
    else
424
137k
        *dst += val;
425
137k
}
426
427
/**
428
 * xmlParserEntityCheck:
429
 * @ctxt:  parser context
430
 * @extra:  sum of unexpanded entity sizes
431
 *
432
 * Check for non-linear entity expansion behaviour.
433
 *
434
 * In some cases like xmlExpandEntityInAttValue, this function is called
435
 * for each, possibly nested entity and its unexpanded content length.
436
 *
437
 * In other cases like xmlParseReference, it's only called for each
438
 * top-level entity with its unexpanded content length plus the sum of
439
 * the unexpanded content lengths (plus fixed cost) of all nested
440
 * entities.
441
 *
442
 * Summing the unexpanded lengths also adds the length of the reference.
443
 * This is by design. Taking the length of the entity name into account
444
 * discourages attacks that try to waste CPU time with abusively long
445
 * entity names. See test/recurse/lol6.xml for example. Each call also
446
 * adds some fixed cost XML_ENT_FIXED_COST to discourage attacks with
447
 * short entities.
448
 *
449
 * Returns 1 on error, 0 on success.
450
 */
451
static int
452
xmlParserEntityCheck(xmlParserCtxtPtr ctxt, unsigned long extra)
453
170k
{
454
170k
    unsigned long consumed;
455
170k
    unsigned long *expandedSize;
456
170k
    xmlParserInputPtr input = ctxt->input;
457
170k
    xmlEntityPtr entity = input->entity;
458
459
170k
    if ((entity) && (entity->flags & XML_ENT_CHECKED))
460
36.1k
        return(0);
461
462
    /*
463
     * Compute total consumed bytes so far, including input streams of
464
     * external entities.
465
     */
466
134k
    consumed = input->consumed;
467
134k
    xmlSaturatedAddSizeT(&consumed, input->cur - input->base);
468
134k
    xmlSaturatedAdd(&consumed, ctxt->sizeentities);
469
470
134k
    if (entity)
471
3.59k
        expandedSize = &entity->expandedSize;
472
131k
    else
473
131k
        expandedSize = &ctxt->sizeentcopy;
474
475
    /*
476
     * Add extra cost and some fixed cost.
477
     */
478
134k
    xmlSaturatedAdd(expandedSize, extra);
479
134k
    xmlSaturatedAdd(expandedSize, XML_ENT_FIXED_COST);
480
481
    /*
482
     * It's important to always use saturation arithmetic when tracking
483
     * entity sizes to make the size checks reliable. If "sizeentcopy"
484
     * overflows, we have to abort.
485
     */
486
134k
    if ((*expandedSize > XML_PARSER_ALLOWED_EXPANSION) &&
487
134k
        ((*expandedSize >= ULONG_MAX) ||
488
17
         (*expandedSize / ctxt->maxAmpl > consumed))) {
489
17
        xmlFatalErrMsg(ctxt, XML_ERR_RESOURCE_LIMIT,
490
17
                       "Maximum entity amplification factor exceeded, see "
491
17
                       "xmlCtxtSetMaxAmplification.\n");
492
17
        xmlHaltParser(ctxt);
493
17
        return(1);
494
17
    }
495
496
134k
    return(0);
497
134k
}
498
499
/************************************************************************
500
 *                  *
501
 *    Library wide options          *
502
 *                  *
503
 ************************************************************************/
504
505
/**
506
  * xmlHasFeature:
507
  * @feature: the feature to be examined
508
  *
509
  * Examines if the library has been compiled with a given feature.
510
  *
511
  * Returns a non-zero value if the feature exist, otherwise zero.
512
  * Returns zero (0) if the feature does not exist or an unknown
513
  * unknown feature is requested, non-zero otherwise.
514
  */
515
int
516
xmlHasFeature(xmlFeature feature)
517
0
{
518
0
    switch (feature) {
519
0
  case XML_WITH_THREAD:
520
0
#ifdef LIBXML_THREAD_ENABLED
521
0
      return(1);
522
#else
523
      return(0);
524
#endif
525
0
        case XML_WITH_TREE:
526
0
#ifdef LIBXML_TREE_ENABLED
527
0
            return(1);
528
#else
529
            return(0);
530
#endif
531
0
        case XML_WITH_OUTPUT:
532
0
#ifdef LIBXML_OUTPUT_ENABLED
533
0
            return(1);
534
#else
535
            return(0);
536
#endif
537
0
        case XML_WITH_PUSH:
538
0
#ifdef LIBXML_PUSH_ENABLED
539
0
            return(1);
540
#else
541
            return(0);
542
#endif
543
0
        case XML_WITH_READER:
544
0
#ifdef LIBXML_READER_ENABLED
545
0
            return(1);
546
#else
547
            return(0);
548
#endif
549
0
        case XML_WITH_PATTERN:
550
0
#ifdef LIBXML_PATTERN_ENABLED
551
0
            return(1);
552
#else
553
            return(0);
554
#endif
555
0
        case XML_WITH_WRITER:
556
0
#ifdef LIBXML_WRITER_ENABLED
557
0
            return(1);
558
#else
559
            return(0);
560
#endif
561
0
        case XML_WITH_SAX1:
562
0
#ifdef LIBXML_SAX1_ENABLED
563
0
            return(1);
564
#else
565
            return(0);
566
#endif
567
0
        case XML_WITH_FTP:
568
#ifdef LIBXML_FTP_ENABLED
569
            return(1);
570
#else
571
0
            return(0);
572
0
#endif
573
0
        case XML_WITH_HTTP:
574
0
#ifdef LIBXML_HTTP_ENABLED
575
0
            return(1);
576
#else
577
            return(0);
578
#endif
579
0
        case XML_WITH_VALID:
580
0
#ifdef LIBXML_VALID_ENABLED
581
0
            return(1);
582
#else
583
            return(0);
584
#endif
585
0
        case XML_WITH_HTML:
586
0
#ifdef LIBXML_HTML_ENABLED
587
0
            return(1);
588
#else
589
            return(0);
590
#endif
591
0
        case XML_WITH_LEGACY:
592
#ifdef LIBXML_LEGACY_ENABLED
593
            return(1);
594
#else
595
0
            return(0);
596
0
#endif
597
0
        case XML_WITH_C14N:
598
0
#ifdef LIBXML_C14N_ENABLED
599
0
            return(1);
600
#else
601
            return(0);
602
#endif
603
0
        case XML_WITH_CATALOG:
604
0
#ifdef LIBXML_CATALOG_ENABLED
605
0
            return(1);
606
#else
607
            return(0);
608
#endif
609
0
        case XML_WITH_XPATH:
610
0
#ifdef LIBXML_XPATH_ENABLED
611
0
            return(1);
612
#else
613
            return(0);
614
#endif
615
0
        case XML_WITH_XPTR:
616
0
#ifdef LIBXML_XPTR_ENABLED
617
0
            return(1);
618
#else
619
            return(0);
620
#endif
621
0
        case XML_WITH_XINCLUDE:
622
0
#ifdef LIBXML_XINCLUDE_ENABLED
623
0
            return(1);
624
#else
625
            return(0);
626
#endif
627
0
        case XML_WITH_ICONV:
628
0
#ifdef LIBXML_ICONV_ENABLED
629
0
            return(1);
630
#else
631
            return(0);
632
#endif
633
0
        case XML_WITH_ISO8859X:
634
0
#ifdef LIBXML_ISO8859X_ENABLED
635
0
            return(1);
636
#else
637
            return(0);
638
#endif
639
0
        case XML_WITH_UNICODE:
640
0
#ifdef LIBXML_UNICODE_ENABLED
641
0
            return(1);
642
#else
643
            return(0);
644
#endif
645
0
        case XML_WITH_REGEXP:
646
0
#ifdef LIBXML_REGEXP_ENABLED
647
0
            return(1);
648
#else
649
            return(0);
650
#endif
651
0
        case XML_WITH_AUTOMATA:
652
0
#ifdef LIBXML_AUTOMATA_ENABLED
653
0
            return(1);
654
#else
655
            return(0);
656
#endif
657
0
        case XML_WITH_EXPR:
658
#ifdef LIBXML_EXPR_ENABLED
659
            return(1);
660
#else
661
0
            return(0);
662
0
#endif
663
0
        case XML_WITH_SCHEMAS:
664
0
#ifdef LIBXML_SCHEMAS_ENABLED
665
0
            return(1);
666
#else
667
            return(0);
668
#endif
669
0
        case XML_WITH_SCHEMATRON:
670
0
#ifdef LIBXML_SCHEMATRON_ENABLED
671
0
            return(1);
672
#else
673
            return(0);
674
#endif
675
0
        case XML_WITH_MODULES:
676
0
#ifdef LIBXML_MODULES_ENABLED
677
0
            return(1);
678
#else
679
            return(0);
680
#endif
681
0
        case XML_WITH_DEBUG:
682
0
#ifdef LIBXML_DEBUG_ENABLED
683
0
            return(1);
684
#else
685
            return(0);
686
#endif
687
0
        case XML_WITH_DEBUG_MEM:
688
#ifdef DEBUG_MEMORY_LOCATION
689
            return(1);
690
#else
691
0
            return(0);
692
0
#endif
693
0
        case XML_WITH_ZLIB:
694
0
#ifdef LIBXML_ZLIB_ENABLED
695
0
            return(1);
696
#else
697
            return(0);
698
#endif
699
0
        case XML_WITH_LZMA:
700
0
#ifdef LIBXML_LZMA_ENABLED
701
0
            return(1);
702
#else
703
            return(0);
704
#endif
705
0
        case XML_WITH_ICU:
706
#ifdef LIBXML_ICU_ENABLED
707
            return(1);
708
#else
709
0
            return(0);
710
0
#endif
711
0
        default:
712
0
      break;
713
0
     }
714
0
     return(0);
715
0
}
716
717
/************************************************************************
718
 *                  *
719
 *      Simple string buffer        *
720
 *                  *
721
 ************************************************************************/
722
723
typedef struct {
724
    xmlChar *mem;
725
    unsigned size;
726
    unsigned cap; /* size < cap */
727
    unsigned max; /* size <= max */
728
    xmlParserErrors code;
729
} xmlSBuf;
730
731
static void
732
110k
xmlSBufInit(xmlSBuf *buf, unsigned max) {
733
110k
    buf->mem = NULL;
734
110k
    buf->size = 0;
735
110k
    buf->cap = 0;
736
110k
    buf->max = max;
737
110k
    buf->code = XML_ERR_OK;
738
110k
}
739
740
static int
741
77.2k
xmlSBufGrow(xmlSBuf *buf, unsigned len) {
742
77.2k
    xmlChar *mem;
743
77.2k
    unsigned cap;
744
745
77.2k
    if (len >= UINT_MAX / 2 - buf->size) {
746
0
        buf->code = XML_ERR_RESOURCE_LIMIT;
747
0
        return(-1);
748
0
    }
749
750
77.2k
    cap = (buf->size + len) * 2;
751
77.2k
    if (cap < 240)
752
69.5k
        cap = 240;
753
754
77.2k
    mem = xmlRealloc(buf->mem, cap);
755
77.2k
    if (mem == NULL) {
756
0
        buf->code = XML_ERR_NO_MEMORY;
757
0
        return(-1);
758
0
    }
759
760
77.2k
    buf->mem = mem;
761
77.2k
    buf->cap = cap;
762
763
77.2k
    return(0);
764
77.2k
}
765
766
static void
767
1.27M
xmlSBufAddString(xmlSBuf *buf, const xmlChar *str, unsigned len) {
768
1.27M
    if (buf->max - buf->size < len) {
769
0
        buf->code = XML_ERR_RESOURCE_LIMIT;
770
0
        return;
771
0
    }
772
773
1.27M
    if (buf->cap - buf->size <= len) {
774
74.9k
        if (xmlSBufGrow(buf, len) < 0)
775
0
            return;
776
74.9k
    }
777
778
1.27M
    if (len > 0)
779
1.27M
        memcpy(buf->mem + buf->size, str, len);
780
1.27M
    buf->size += len;
781
1.27M
}
782
783
static void
784
431k
xmlSBufAddCString(xmlSBuf *buf, const char *str, unsigned len) {
785
431k
    xmlSBufAddString(buf, (const xmlChar *) str, len);
786
431k
}
787
788
static void
789
17.9k
xmlSBufAddChar(xmlSBuf *buf, int c) {
790
17.9k
    xmlChar *end;
791
792
17.9k
    if (buf->max - buf->size < 4) {
793
0
        buf->code = XML_ERR_RESOURCE_LIMIT;
794
0
        return;
795
0
    }
796
797
17.9k
    if (buf->cap - buf->size <= 4) {
798
2.36k
        if (xmlSBufGrow(buf, 4) < 0)
799
0
            return;
800
2.36k
    }
801
802
17.9k
    end = buf->mem + buf->size;
803
804
17.9k
    if (c < 0x80) {
805
11.3k
        *end = (xmlChar) c;
806
11.3k
        buf->size += 1;
807
11.3k
    } else {
808
6.60k
        buf->size += xmlCopyCharMultiByte(end, c);
809
6.60k
    }
810
17.9k
}
811
812
static void
813
18.2k
xmlSBufAddReplChar(xmlSBuf *buf) {
814
18.2k
    xmlSBufAddCString(buf, "\xEF\xBF\xBD", 3);
815
18.2k
}
816
817
static void
818
0
xmlSBufReportError(xmlSBuf *buf, xmlParserCtxtPtr ctxt, const char *errMsg) {
819
0
    if (buf->code == XML_ERR_NO_MEMORY)
820
0
        xmlCtxtErrMemory(ctxt);
821
0
    else
822
0
        xmlFatalErr(ctxt, buf->code, errMsg);
823
0
}
824
825
static xmlChar *
826
xmlSBufFinish(xmlSBuf *buf, int *sizeOut, xmlParserCtxtPtr ctxt,
827
78.6k
              const char *errMsg) {
828
78.6k
    if (buf->mem == NULL) {
829
12.5k
        buf->mem = xmlMalloc(1);
830
12.5k
        if (buf->mem == NULL) {
831
0
            buf->code = XML_ERR_NO_MEMORY;
832
12.5k
        } else {
833
12.5k
            buf->mem[0] = 0;
834
12.5k
        }
835
66.0k
    } else {
836
66.0k
        buf->mem[buf->size] = 0;
837
66.0k
    }
838
839
78.6k
    if (buf->code == XML_ERR_OK) {
840
78.6k
        if (sizeOut != NULL)
841
2.19k
            *sizeOut = buf->size;
842
78.6k
        return(buf->mem);
843
78.6k
    }
844
845
0
    xmlSBufReportError(buf, ctxt, errMsg);
846
847
0
    xmlFree(buf->mem);
848
849
0
    if (sizeOut != NULL)
850
0
        *sizeOut = 0;
851
0
    return(NULL);
852
78.6k
}
853
854
static void
855
27.4k
xmlSBufCleanup(xmlSBuf *buf, xmlParserCtxtPtr ctxt, const char *errMsg) {
856
27.4k
    if (buf->code != XML_ERR_OK)
857
0
        xmlSBufReportError(buf, ctxt, errMsg);
858
859
27.4k
    xmlFree(buf->mem);
860
27.4k
}
861
862
static int
863
xmlUTF8MultibyteLen(xmlParserCtxtPtr ctxt, const xmlChar *str,
864
218k
                    const char *errMsg) {
865
218k
    int c = str[0];
866
218k
    int c1 = str[1];
867
868
218k
    if ((c1 & 0xC0) != 0x80)
869
7.13k
        goto encoding_error;
870
871
211k
    if (c < 0xE0) {
872
        /* 2-byte sequence */
873
10.0k
        if (c < 0xC2)
874
3.84k
            goto encoding_error;
875
876
6.23k
        return(2);
877
201k
    } else {
878
201k
        int c2 = str[2];
879
880
201k
        if ((c2 & 0xC0) != 0x80)
881
90
            goto encoding_error;
882
883
201k
        if (c < 0xF0) {
884
            /* 3-byte sequence */
885
199k
            if (c == 0xE0) {
886
                /* overlong */
887
154k
                if (c1 < 0xA0)
888
68
                    goto encoding_error;
889
154k
            } else if (c == 0xED) {
890
                /* surrogate */
891
332
                if (c1 >= 0xA0)
892
67
                    goto encoding_error;
893
44.0k
            } else if (c == 0xEF) {
894
                /* U+FFFE and U+FFFF are invalid Chars */
895
40.0k
                if ((c1 == 0xBF) && (c2 >= 0xBE))
896
249
                    xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR, errMsg);
897
40.0k
            }
898
899
199k
            return(3);
900
199k
        } else {
901
            /* 4-byte sequence */
902
2.13k
            if ((str[3] & 0xC0) != 0x80)
903
79
                goto encoding_error;
904
2.05k
            if (c == 0xF0) {
905
                /* overlong */
906
696
                if (c1 < 0x90)
907
66
                    goto encoding_error;
908
1.36k
            } else if (c >= 0xF4) {
909
                /* greater than 0x10FFFF */
910
530
                if ((c > 0xF4) || (c1 >= 0x90))
911
136
                    goto encoding_error;
912
530
            }
913
914
1.85k
            return(4);
915
2.05k
        }
916
201k
    }
917
918
11.4k
encoding_error:
919
    /* Only report the first error */
920
11.4k
    if ((ctxt->input->flags & XML_INPUT_ENCODING_ERROR) == 0) {
921
708
        xmlCtxtErrIO(ctxt, XML_ERR_INVALID_ENCODING, NULL);
922
708
        ctxt->input->flags |= XML_INPUT_ENCODING_ERROR;
923
708
    }
924
925
11.4k
    return(0);
926
211k
}
927
928
/************************************************************************
929
 *                  *
930
 *    SAX2 defaulted attributes handling      *
931
 *                  *
932
 ************************************************************************/
933
934
/**
935
 * xmlCtxtInitializeLate:
936
 * @ctxt:  an XML parser context
937
 *
938
 * Final initialization of the parser context before starting to parse.
939
 *
940
 * This accounts for users modifying struct members of parser context
941
 * directly.
942
 */
943
static void
944
22.1k
xmlCtxtInitializeLate(xmlParserCtxtPtr ctxt) {
945
22.1k
    xmlSAXHandlerPtr sax;
946
947
    /* Avoid unused variable warning if features are disabled. */
948
22.1k
    (void) sax;
949
950
    /*
951
     * Changing the SAX struct directly is still widespread practice
952
     * in internal and external code.
953
     */
954
22.1k
    if (ctxt == NULL) return;
955
22.1k
    sax = ctxt->sax;
956
22.1k
#ifdef LIBXML_SAX1_ENABLED
957
    /*
958
     * Only enable SAX2 if there SAX2 element handlers, except when there
959
     * are no element handlers at all.
960
     */
961
22.1k
    if (((ctxt->options & XML_PARSE_SAX1) == 0) &&
962
22.1k
        (sax) &&
963
22.1k
        (sax->initialized == XML_SAX2_MAGIC) &&
964
22.1k
        ((sax->startElementNs != NULL) ||
965
18.0k
         (sax->endElementNs != NULL) ||
966
18.0k
         ((sax->startElement == NULL) && (sax->endElement == NULL))))
967
18.0k
        ctxt->sax2 = 1;
968
#else
969
    ctxt->sax2 = 1;
970
#endif /* LIBXML_SAX1_ENABLED */
971
972
    /*
973
     * Some users replace the dictionary directly in the context struct.
974
     * We really need an API function to do that cleanly.
975
     */
976
22.1k
    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
977
22.1k
    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
978
22.1k
    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
979
22.1k
    if ((ctxt->str_xml==NULL) || (ctxt->str_xmlns==NULL) ||
980
22.1k
    (ctxt->str_xml_ns == NULL)) {
981
0
        xmlErrMemory(ctxt);
982
0
    }
983
22.1k
}
984
985
typedef struct {
986
    xmlHashedString prefix;
987
    xmlHashedString name;
988
    xmlHashedString value;
989
    const xmlChar *valueEnd;
990
    int external;
991
    int expandedSize;
992
} xmlDefAttr;
993
994
typedef struct _xmlDefAttrs xmlDefAttrs;
995
typedef xmlDefAttrs *xmlDefAttrsPtr;
996
struct _xmlDefAttrs {
997
    int nbAttrs;  /* number of defaulted attributes on that element */
998
    int maxAttrs;       /* the size of the array */
999
#if __STDC_VERSION__ >= 199901L
1000
    /* Using a C99 flexible array member avoids UBSan errors. */
1001
    xmlDefAttr attrs[]; /* array of localname/prefix/values/external */
1002
#else
1003
    xmlDefAttr attrs[1];
1004
#endif
1005
};
1006
1007
/**
1008
 * xmlAttrNormalizeSpace:
1009
 * @src: the source string
1010
 * @dst: the target string
1011
 *
1012
 * Normalize the space in non CDATA attribute values:
1013
 * If the attribute type is not CDATA, then the XML processor MUST further
1014
 * process the normalized attribute value by discarding any leading and
1015
 * trailing space (#x20) characters, and by replacing sequences of space
1016
 * (#x20) characters by a single space (#x20) character.
1017
 * Note that the size of dst need to be at least src, and if one doesn't need
1018
 * to preserve dst (and it doesn't come from a dictionary or read-only) then
1019
 * passing src as dst is just fine.
1020
 *
1021
 * Returns a pointer to the normalized value (dst) or NULL if no conversion
1022
 *         is needed.
1023
 */
1024
static xmlChar *
1025
xmlAttrNormalizeSpace(const xmlChar *src, xmlChar *dst)
1026
21.8k
{
1027
21.8k
    if ((src == NULL) || (dst == NULL))
1028
0
        return(NULL);
1029
1030
28.6k
    while (*src == 0x20) src++;
1031
142k
    while (*src != 0) {
1032
120k
  if (*src == 0x20) {
1033
22.9k
      while (*src == 0x20) src++;
1034
10.6k
      if (*src != 0)
1035
9.01k
    *dst++ = 0x20;
1036
109k
  } else {
1037
109k
      *dst++ = *src++;
1038
109k
  }
1039
120k
    }
1040
21.8k
    *dst = 0;
1041
21.8k
    if (dst == src)
1042
13.9k
       return(NULL);
1043
7.95k
    return(dst);
1044
21.8k
}
1045
1046
/**
1047
 * xmlAddDefAttrs:
1048
 * @ctxt:  an XML parser context
1049
 * @fullname:  the element fullname
1050
 * @fullattr:  the attribute fullname
1051
 * @value:  the attribute value
1052
 *
1053
 * Add a defaulted attribute for an element
1054
 */
1055
static void
1056
xmlAddDefAttrs(xmlParserCtxtPtr ctxt,
1057
               const xmlChar *fullname,
1058
               const xmlChar *fullattr,
1059
20.8k
               const xmlChar *value) {
1060
20.8k
    xmlDefAttrsPtr defaults;
1061
20.8k
    xmlDefAttr *attr;
1062
20.8k
    int len, expandedSize;
1063
20.8k
    xmlHashedString name;
1064
20.8k
    xmlHashedString prefix;
1065
20.8k
    xmlHashedString hvalue;
1066
20.8k
    const xmlChar *localname;
1067
1068
    /*
1069
     * Allows to detect attribute redefinitions
1070
     */
1071
20.8k
    if (ctxt->attsSpecial != NULL) {
1072
18.2k
        if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL)
1073
14.8k
      return;
1074
18.2k
    }
1075
1076
6.02k
    if (ctxt->attsDefault == NULL) {
1077
2.60k
        ctxt->attsDefault = xmlHashCreateDict(10, ctxt->dict);
1078
2.60k
  if (ctxt->attsDefault == NULL)
1079
0
      goto mem_error;
1080
2.60k
    }
1081
1082
    /*
1083
     * split the element name into prefix:localname , the string found
1084
     * are within the DTD and then not associated to namespace names.
1085
     */
1086
6.02k
    localname = xmlSplitQName3(fullname, &len);
1087
6.02k
    if (localname == NULL) {
1088
5.72k
        name = xmlDictLookupHashed(ctxt->dict, fullname, -1);
1089
5.72k
  prefix.name = NULL;
1090
5.72k
    } else {
1091
304
        name = xmlDictLookupHashed(ctxt->dict, localname, -1);
1092
304
  prefix = xmlDictLookupHashed(ctxt->dict, fullname, len);
1093
304
        if (prefix.name == NULL)
1094
0
            goto mem_error;
1095
304
    }
1096
6.02k
    if (name.name == NULL)
1097
0
        goto mem_error;
1098
1099
    /*
1100
     * make sure there is some storage
1101
     */
1102
6.02k
    defaults = xmlHashLookup2(ctxt->attsDefault, name.name, prefix.name);
1103
6.02k
    if ((defaults == NULL) ||
1104
6.02k
        (defaults->nbAttrs >= defaults->maxAttrs)) {
1105
3.09k
        xmlDefAttrsPtr temp;
1106
3.09k
        int newSize;
1107
1108
3.09k
        newSize = (defaults != NULL) ? 2 * defaults->maxAttrs : 4;
1109
3.09k
        temp = xmlRealloc(defaults,
1110
3.09k
                          sizeof(*defaults) + newSize * sizeof(xmlDefAttr));
1111
3.09k
  if (temp == NULL)
1112
0
      goto mem_error;
1113
3.09k
        if (defaults == NULL)
1114
2.69k
            temp->nbAttrs = 0;
1115
3.09k
  temp->maxAttrs = newSize;
1116
3.09k
        defaults = temp;
1117
3.09k
  if (xmlHashUpdateEntry2(ctxt->attsDefault, name.name, prefix.name,
1118
3.09k
                          defaults, NULL) < 0) {
1119
0
      xmlFree(defaults);
1120
0
      goto mem_error;
1121
0
  }
1122
3.09k
    }
1123
1124
    /*
1125
     * Split the attribute name into prefix:localname , the string found
1126
     * are within the DTD and hen not associated to namespace names.
1127
     */
1128
6.02k
    localname = xmlSplitQName3(fullattr, &len);
1129
6.02k
    if (localname == NULL) {
1130
4.52k
        name = xmlDictLookupHashed(ctxt->dict, fullattr, -1);
1131
4.52k
  prefix.name = NULL;
1132
4.52k
    } else {
1133
1.50k
        name = xmlDictLookupHashed(ctxt->dict, localname, -1);
1134
1.50k
  prefix = xmlDictLookupHashed(ctxt->dict, fullattr, len);
1135
1.50k
        if (prefix.name == NULL)
1136
0
            goto mem_error;
1137
1.50k
    }
1138
6.02k
    if (name.name == NULL)
1139
0
        goto mem_error;
1140
1141
    /* intern the string and precompute the end */
1142
6.02k
    len = strlen((const char *) value);
1143
6.02k
    hvalue = xmlDictLookupHashed(ctxt->dict, value, len);
1144
6.02k
    if (hvalue.name == NULL)
1145
0
        goto mem_error;
1146
1147
6.02k
    expandedSize = strlen((const char *) name.name);
1148
6.02k
    if (prefix.name != NULL)
1149
1.50k
        expandedSize += strlen((const char *) prefix.name);
1150
6.02k
    expandedSize += len;
1151
1152
6.02k
    attr = &defaults->attrs[defaults->nbAttrs++];
1153
6.02k
    attr->name = name;
1154
6.02k
    attr->prefix = prefix;
1155
6.02k
    attr->value = hvalue;
1156
6.02k
    attr->valueEnd = hvalue.name + len;
1157
6.02k
    attr->external = PARSER_EXTERNAL(ctxt);
1158
6.02k
    attr->expandedSize = expandedSize;
1159
1160
6.02k
    return;
1161
1162
0
mem_error:
1163
0
    xmlErrMemory(ctxt);
1164
0
    return;
1165
6.02k
}
1166
1167
/**
1168
 * xmlAddSpecialAttr:
1169
 * @ctxt:  an XML parser context
1170
 * @fullname:  the element fullname
1171
 * @fullattr:  the attribute fullname
1172
 * @type:  the attribute type
1173
 *
1174
 * Register this attribute type
1175
 */
1176
static void
1177
xmlAddSpecialAttr(xmlParserCtxtPtr ctxt,
1178
      const xmlChar *fullname,
1179
      const xmlChar *fullattr,
1180
      int type)
1181
32.4k
{
1182
32.4k
    if (ctxt->attsSpecial == NULL) {
1183
3.11k
        ctxt->attsSpecial = xmlHashCreateDict(10, ctxt->dict);
1184
3.11k
  if (ctxt->attsSpecial == NULL)
1185
0
      goto mem_error;
1186
3.11k
    }
1187
1188
32.4k
    if (xmlHashAdd2(ctxt->attsSpecial, fullname, fullattr,
1189
32.4k
                    (void *) (ptrdiff_t) type) < 0)
1190
0
        goto mem_error;
1191
32.4k
    return;
1192
1193
32.4k
mem_error:
1194
0
    xmlErrMemory(ctxt);
1195
0
    return;
1196
32.4k
}
1197
1198
/**
1199
 * xmlCleanSpecialAttrCallback:
1200
 *
1201
 * Removes CDATA attributes from the special attribute table
1202
 */
1203
static void
1204
xmlCleanSpecialAttrCallback(void *payload, void *data,
1205
                            const xmlChar *fullname, const xmlChar *fullattr,
1206
6.71k
                            const xmlChar *unused ATTRIBUTE_UNUSED) {
1207
6.71k
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) data;
1208
1209
6.71k
    if (((ptrdiff_t) payload) == XML_ATTRIBUTE_CDATA) {
1210
813
        xmlHashRemoveEntry2(ctxt->attsSpecial, fullname, fullattr, NULL);
1211
813
    }
1212
6.71k
}
1213
1214
/**
1215
 * xmlCleanSpecialAttr:
1216
 * @ctxt:  an XML parser context
1217
 *
1218
 * Trim the list of attributes defined to remove all those of type
1219
 * CDATA as they are not special. This call should be done when finishing
1220
 * to parse the DTD and before starting to parse the document root.
1221
 */
1222
static void
1223
xmlCleanSpecialAttr(xmlParserCtxtPtr ctxt)
1224
10.2k
{
1225
10.2k
    if (ctxt->attsSpecial == NULL)
1226
7.11k
        return;
1227
1228
3.11k
    xmlHashScanFull(ctxt->attsSpecial, xmlCleanSpecialAttrCallback, ctxt);
1229
1230
3.11k
    if (xmlHashSize(ctxt->attsSpecial) == 0) {
1231
191
        xmlHashFree(ctxt->attsSpecial, NULL);
1232
191
        ctxt->attsSpecial = NULL;
1233
191
    }
1234
3.11k
    return;
1235
10.2k
}
1236
1237
/**
1238
 * xmlCheckLanguageID:
1239
 * @lang:  pointer to the string value
1240
 *
1241
 * DEPRECATED: Internal function, do not use.
1242
 *
1243
 * Checks that the value conforms to the LanguageID production:
1244
 *
1245
 * NOTE: this is somewhat deprecated, those productions were removed from
1246
 *       the XML Second edition.
1247
 *
1248
 * [33] LanguageID ::= Langcode ('-' Subcode)*
1249
 * [34] Langcode ::= ISO639Code |  IanaCode |  UserCode
1250
 * [35] ISO639Code ::= ([a-z] | [A-Z]) ([a-z] | [A-Z])
1251
 * [36] IanaCode ::= ('i' | 'I') '-' ([a-z] | [A-Z])+
1252
 * [37] UserCode ::= ('x' | 'X') '-' ([a-z] | [A-Z])+
1253
 * [38] Subcode ::= ([a-z] | [A-Z])+
1254
 *
1255
 * The current REC reference the successors of RFC 1766, currently 5646
1256
 *
1257
 * http://www.rfc-editor.org/rfc/rfc5646.txt
1258
 * langtag       = language
1259
 *                 ["-" script]
1260
 *                 ["-" region]
1261
 *                 *("-" variant)
1262
 *                 *("-" extension)
1263
 *                 ["-" privateuse]
1264
 * language      = 2*3ALPHA            ; shortest ISO 639 code
1265
 *                 ["-" extlang]       ; sometimes followed by
1266
 *                                     ; extended language subtags
1267
 *               / 4ALPHA              ; or reserved for future use
1268
 *               / 5*8ALPHA            ; or registered language subtag
1269
 *
1270
 * extlang       = 3ALPHA              ; selected ISO 639 codes
1271
 *                 *2("-" 3ALPHA)      ; permanently reserved
1272
 *
1273
 * script        = 4ALPHA              ; ISO 15924 code
1274
 *
1275
 * region        = 2ALPHA              ; ISO 3166-1 code
1276
 *               / 3DIGIT              ; UN M.49 code
1277
 *
1278
 * variant       = 5*8alphanum         ; registered variants
1279
 *               / (DIGIT 3alphanum)
1280
 *
1281
 * extension     = singleton 1*("-" (2*8alphanum))
1282
 *
1283
 *                                     ; Single alphanumerics
1284
 *                                     ; "x" reserved for private use
1285
 * singleton     = DIGIT               ; 0 - 9
1286
 *               / %x41-57             ; A - W
1287
 *               / %x59-5A             ; Y - Z
1288
 *               / %x61-77             ; a - w
1289
 *               / %x79-7A             ; y - z
1290
 *
1291
 * it sounds right to still allow Irregular i-xxx IANA and user codes too
1292
 * The parser below doesn't try to cope with extension or privateuse
1293
 * that could be added but that's not interoperable anyway
1294
 *
1295
 * Returns 1 if correct 0 otherwise
1296
 **/
1297
int
1298
xmlCheckLanguageID(const xmlChar * lang)
1299
2.21k
{
1300
2.21k
    const xmlChar *cur = lang, *nxt;
1301
1302
2.21k
    if (cur == NULL)
1303
112
        return (0);
1304
2.09k
    if (((cur[0] == 'i') && (cur[1] == '-')) ||
1305
2.09k
        ((cur[0] == 'I') && (cur[1] == '-')) ||
1306
2.09k
        ((cur[0] == 'x') && (cur[1] == '-')) ||
1307
2.09k
        ((cur[0] == 'X') && (cur[1] == '-'))) {
1308
        /*
1309
         * Still allow IANA code and user code which were coming
1310
         * from the previous version of the XML-1.0 specification
1311
         * it's deprecated but we should not fail
1312
         */
1313
244
        cur += 2;
1314
804
        while (((cur[0] >= 'A') && (cur[0] <= 'Z')) ||
1315
804
               ((cur[0] >= 'a') && (cur[0] <= 'z')))
1316
560
            cur++;
1317
244
        return(cur[0] == 0);
1318
244
    }
1319
1.85k
    nxt = cur;
1320
6.59k
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1321
6.59k
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1322
4.74k
           nxt++;
1323
1.85k
    if (nxt - cur >= 4) {
1324
        /*
1325
         * Reserved
1326
         */
1327
151
        if ((nxt - cur > 8) || (nxt[0] != 0))
1328
107
            return(0);
1329
44
        return(1);
1330
151
    }
1331
1.70k
    if (nxt - cur < 2)
1332
119
        return(0);
1333
    /* we got an ISO 639 code */
1334
1.58k
    if (nxt[0] == 0)
1335
90
        return(1);
1336
1.49k
    if (nxt[0] != '-')
1337
73
        return(0);
1338
1339
1.42k
    nxt++;
1340
1.42k
    cur = nxt;
1341
    /* now we can have extlang or script or region or variant */
1342
1.42k
    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1343
258
        goto region_m49;
1344
1345
5.44k
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1346
5.44k
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1347
4.28k
           nxt++;
1348
1.16k
    if (nxt - cur == 4)
1349
302
        goto script;
1350
862
    if (nxt - cur == 2)
1351
202
        goto region;
1352
660
    if ((nxt - cur >= 5) && (nxt - cur <= 8))
1353
110
        goto variant;
1354
550
    if (nxt - cur != 3)
1355
83
        return(0);
1356
    /* we parsed an extlang */
1357
467
    if (nxt[0] == 0)
1358
137
        return(1);
1359
330
    if (nxt[0] != '-')
1360
68
        return(0);
1361
1362
262
    nxt++;
1363
262
    cur = nxt;
1364
    /* now we can have script or region or variant */
1365
262
    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1366
36
        goto region_m49;
1367
1368
1.43k
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1369
1.43k
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1370
1.20k
           nxt++;
1371
226
    if (nxt - cur == 2)
1372
36
        goto region;
1373
190
    if ((nxt - cur >= 5) && (nxt - cur <= 8))
1374
35
        goto variant;
1375
155
    if (nxt - cur != 4)
1376
134
        return(0);
1377
    /* we parsed a script */
1378
323
script:
1379
323
    if (nxt[0] == 0)
1380
43
        return(1);
1381
280
    if (nxt[0] != '-')
1382
53
        return(0);
1383
1384
227
    nxt++;
1385
227
    cur = nxt;
1386
    /* now we can have region or variant */
1387
227
    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1388
36
        goto region_m49;
1389
1390
1.23k
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1391
1.23k
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1392
1.04k
           nxt++;
1393
1394
191
    if ((nxt - cur >= 5) && (nxt - cur <= 8))
1395
38
        goto variant;
1396
153
    if (nxt - cur != 2)
1397
117
        return(0);
1398
    /* we parsed a region */
1399
317
region:
1400
317
    if (nxt[0] == 0)
1401
88
        return(1);
1402
229
    if (nxt[0] != '-')
1403
105
        return(0);
1404
1405
124
    nxt++;
1406
124
    cur = nxt;
1407
    /* now we can just have a variant */
1408
1.20k
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1409
1.20k
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1410
1.08k
           nxt++;
1411
1412
124
    if ((nxt - cur < 5) || (nxt - cur > 8))
1413
82
        return(0);
1414
1415
    /* we parsed a variant */
1416
225
variant:
1417
225
    if (nxt[0] == 0)
1418
115
        return(1);
1419
110
    if (nxt[0] != '-')
1420
69
        return(0);
1421
    /* extensions and private use subtags not checked */
1422
41
    return (1);
1423
1424
330
region_m49:
1425
330
    if (((nxt[1] >= '0') && (nxt[1] <= '9')) &&
1426
330
        ((nxt[2] >= '0') && (nxt[2] <= '9'))) {
1427
43
        nxt += 3;
1428
43
        goto region;
1429
43
    }
1430
287
    return(0);
1431
330
}
1432
1433
/************************************************************************
1434
 *                  *
1435
 *    Parser stacks related functions and macros    *
1436
 *                  *
1437
 ************************************************************************/
1438
1439
static xmlChar *
1440
xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar **str);
1441
1442
/**
1443
 * xmlParserNsCreate:
1444
 *
1445
 * Create a new namespace database.
1446
 *
1447
 * Returns the new obejct.
1448
 */
1449
xmlParserNsData *
1450
22.1k
xmlParserNsCreate(void) {
1451
22.1k
    xmlParserNsData *nsdb = xmlMalloc(sizeof(*nsdb));
1452
1453
22.1k
    if (nsdb == NULL)
1454
0
        return(NULL);
1455
22.1k
    memset(nsdb, 0, sizeof(*nsdb));
1456
22.1k
    nsdb->defaultNsIndex = INT_MAX;
1457
1458
22.1k
    return(nsdb);
1459
22.1k
}
1460
1461
/**
1462
 * xmlParserNsFree:
1463
 * @nsdb: namespace database
1464
 *
1465
 * Free a namespace database.
1466
 */
1467
void
1468
22.1k
xmlParserNsFree(xmlParserNsData *nsdb) {
1469
22.1k
    if (nsdb == NULL)
1470
0
        return;
1471
1472
22.1k
    xmlFree(nsdb->extra);
1473
22.1k
    xmlFree(nsdb->hash);
1474
22.1k
    xmlFree(nsdb);
1475
22.1k
}
1476
1477
/**
1478
 * xmlParserNsReset:
1479
 * @nsdb: namespace database
1480
 *
1481
 * Reset a namespace database.
1482
 */
1483
static void
1484
0
xmlParserNsReset(xmlParserNsData *nsdb) {
1485
0
    if (nsdb == NULL)
1486
0
        return;
1487
1488
0
    nsdb->hashElems = 0;
1489
0
    nsdb->elementId = 0;
1490
0
    nsdb->defaultNsIndex = INT_MAX;
1491
1492
0
    if (nsdb->hash)
1493
0
        memset(nsdb->hash, 0, nsdb->hashSize * sizeof(nsdb->hash[0]));
1494
0
}
1495
1496
/**
1497
 * xmlParserStartElement:
1498
 * @nsdb: namespace database
1499
 *
1500
 * Signal that a new element has started.
1501
 *
1502
 * Returns 0 on success, -1 if the element counter overflowed.
1503
 */
1504
static int
1505
103k
xmlParserNsStartElement(xmlParserNsData *nsdb) {
1506
103k
    if (nsdb->elementId == UINT_MAX)
1507
0
        return(-1);
1508
103k
    nsdb->elementId++;
1509
1510
103k
    return(0);
1511
103k
}
1512
1513
/**
1514
 * xmlParserNsLookup:
1515
 * @ctxt: parser context
1516
 * @prefix: namespace prefix
1517
 * @bucketPtr: optional bucket (return value)
1518
 *
1519
 * Lookup namespace with given prefix. If @bucketPtr is non-NULL, it will
1520
 * be set to the matching bucket, or the first empty bucket if no match
1521
 * was found.
1522
 *
1523
 * Returns the namespace index on success, INT_MAX if no namespace was
1524
 * found.
1525
 */
1526
static int
1527
xmlParserNsLookup(xmlParserCtxtPtr ctxt, const xmlHashedString *prefix,
1528
183k
                  xmlParserNsBucket **bucketPtr) {
1529
183k
    xmlParserNsBucket *bucket;
1530
183k
    unsigned index, hashValue;
1531
1532
183k
    if (prefix->name == NULL)
1533
98.2k
        return(ctxt->nsdb->defaultNsIndex);
1534
1535
85.4k
    if (ctxt->nsdb->hashSize == 0)
1536
8.12k
        return(INT_MAX);
1537
1538
77.3k
    hashValue = prefix->hashValue;
1539
77.3k
    index = hashValue & (ctxt->nsdb->hashSize - 1);
1540
77.3k
    bucket = &ctxt->nsdb->hash[index];
1541
1542
3.69M
    while (bucket->hashValue) {
1543
3.68M
        if ((bucket->hashValue == hashValue) &&
1544
3.68M
            (bucket->index != INT_MAX)) {
1545
60.4k
            if (ctxt->nsTab[bucket->index * 2] == prefix->name) {
1546
60.4k
                if (bucketPtr != NULL)
1547
49.4k
                    *bucketPtr = bucket;
1548
60.4k
                return(bucket->index);
1549
60.4k
            }
1550
60.4k
        }
1551
1552
3.62M
        index++;
1553
3.62M
        bucket++;
1554
3.62M
        if (index == ctxt->nsdb->hashSize) {
1555
13.2k
            index = 0;
1556
13.2k
            bucket = ctxt->nsdb->hash;
1557
13.2k
        }
1558
3.62M
    }
1559
1560
16.8k
    if (bucketPtr != NULL)
1561
11.9k
        *bucketPtr = bucket;
1562
16.8k
    return(INT_MAX);
1563
77.3k
}
1564
1565
/**
1566
 * xmlParserNsLookupUri:
1567
 * @ctxt: parser context
1568
 * @prefix: namespace prefix
1569
 *
1570
 * Lookup namespace URI with given prefix.
1571
 *
1572
 * Returns the namespace URI on success, NULL if no namespace was found.
1573
 */
1574
static const xmlChar *
1575
86.5k
xmlParserNsLookupUri(xmlParserCtxtPtr ctxt, const xmlHashedString *prefix) {
1576
86.5k
    const xmlChar *ret;
1577
86.5k
    int nsIndex;
1578
1579
86.5k
    if (prefix->name == ctxt->str_xml)
1580
631
        return(ctxt->str_xml_ns);
1581
1582
    /*
1583
     * minNsIndex is used when building an entity tree. We must
1584
     * ignore namespaces declared outside the entity.
1585
     */
1586
85.8k
    nsIndex = xmlParserNsLookup(ctxt, prefix, NULL);
1587
85.8k
    if ((nsIndex == INT_MAX) || (nsIndex < ctxt->nsdb->minNsIndex))
1588
63.3k
        return(NULL);
1589
1590
22.4k
    ret = ctxt->nsTab[nsIndex * 2 + 1];
1591
22.4k
    if (ret[0] == 0)
1592
1.43k
        ret = NULL;
1593
22.4k
    return(ret);
1594
85.8k
}
1595
1596
/**
1597
 * xmlParserNsLookupSax:
1598
 * @ctxt: parser context
1599
 * @prefix: namespace prefix
1600
 *
1601
 * Lookup extra data for the given prefix. This returns data stored
1602
 * with xmlParserNsUdpateSax.
1603
 *
1604
 * Returns the data on success, NULL if no namespace was found.
1605
 */
1606
void *
1607
6.57k
xmlParserNsLookupSax(xmlParserCtxtPtr ctxt, const xmlChar *prefix) {
1608
6.57k
    xmlHashedString hprefix;
1609
6.57k
    int nsIndex;
1610
1611
6.57k
    if (prefix == ctxt->str_xml)
1612
4.03k
        return(NULL);
1613
1614
2.53k
    hprefix.name = prefix;
1615
2.53k
    if (prefix != NULL)
1616
724
        hprefix.hashValue = xmlDictComputeHash(ctxt->dict, prefix);
1617
1.81k
    else
1618
1.81k
        hprefix.hashValue = 0;
1619
2.53k
    nsIndex = xmlParserNsLookup(ctxt, &hprefix, NULL);
1620
2.53k
    if ((nsIndex == INT_MAX) || (nsIndex < ctxt->nsdb->minNsIndex))
1621
0
        return(NULL);
1622
1623
2.53k
    return(ctxt->nsdb->extra[nsIndex].saxData);
1624
2.53k
}
1625
1626
/**
1627
 * xmlParserNsUpdateSax:
1628
 * @ctxt: parser context
1629
 * @prefix: namespace prefix
1630
 * @saxData: extra data for SAX handler
1631
 *
1632
 * Sets or updates extra data for the given prefix. This value will be
1633
 * returned by xmlParserNsLookupSax as long as the namespace with the
1634
 * given prefix is in scope.
1635
 *
1636
 * Returns the data on success, NULL if no namespace was found.
1637
 */
1638
int
1639
xmlParserNsUpdateSax(xmlParserCtxtPtr ctxt, const xmlChar *prefix,
1640
22.5k
                     void *saxData) {
1641
22.5k
    xmlHashedString hprefix;
1642
22.5k
    int nsIndex;
1643
1644
22.5k
    if (prefix == ctxt->str_xml)
1645
0
        return(-1);
1646
1647
22.5k
    hprefix.name = prefix;
1648
22.5k
    if (prefix != NULL)
1649
7.30k
        hprefix.hashValue = xmlDictComputeHash(ctxt->dict, prefix);
1650
15.2k
    else
1651
15.2k
        hprefix.hashValue = 0;
1652
22.5k
    nsIndex = xmlParserNsLookup(ctxt, &hprefix, NULL);
1653
22.5k
    if ((nsIndex == INT_MAX) || (nsIndex < ctxt->nsdb->minNsIndex))
1654
0
        return(-1);
1655
1656
22.5k
    ctxt->nsdb->extra[nsIndex].saxData = saxData;
1657
22.5k
    return(0);
1658
22.5k
}
1659
1660
/**
1661
 * xmlParserNsGrow:
1662
 * @ctxt: parser context
1663
 *
1664
 * Grows the namespace tables.
1665
 *
1666
 * Returns 0 on success, -1 if a memory allocation failed.
1667
 */
1668
static int
1669
3.02k
xmlParserNsGrow(xmlParserCtxtPtr ctxt) {
1670
3.02k
    const xmlChar **table;
1671
3.02k
    xmlParserNsExtra *extra;
1672
3.02k
    int newSize;
1673
1674
3.02k
    if (ctxt->nsMax > INT_MAX / 2)
1675
0
        goto error;
1676
3.02k
    newSize = ctxt->nsMax ? ctxt->nsMax * 2 : 16;
1677
1678
3.02k
    table = xmlRealloc(ctxt->nsTab, 2 * newSize * sizeof(table[0]));
1679
3.02k
    if (table == NULL)
1680
0
        goto error;
1681
3.02k
    ctxt->nsTab = table;
1682
1683
3.02k
    extra = xmlRealloc(ctxt->nsdb->extra, newSize * sizeof(extra[0]));
1684
3.02k
    if (extra == NULL)
1685
0
        goto error;
1686
3.02k
    ctxt->nsdb->extra = extra;
1687
1688
3.02k
    ctxt->nsMax = newSize;
1689
3.02k
    return(0);
1690
1691
0
error:
1692
0
    xmlErrMemory(ctxt);
1693
0
    return(-1);
1694
3.02k
}
1695
1696
/**
1697
 * xmlParserNsPush:
1698
 * @ctxt: parser context
1699
 * @prefix: prefix with hash value
1700
 * @uri: uri with hash value
1701
 * @saxData: extra data for SAX handler
1702
 * @defAttr: whether the namespace comes from a default attribute
1703
 *
1704
 * Push a new namespace on the table.
1705
 *
1706
 * Returns 1 if the namespace was pushed, 0 if the namespace was ignored,
1707
 * -1 if a memory allocation failed.
1708
 */
1709
static int
1710
xmlParserNsPush(xmlParserCtxtPtr ctxt, const xmlHashedString *prefix,
1711
51.7k
                const xmlHashedString *uri, void *saxData, int defAttr) {
1712
51.7k
    xmlParserNsBucket *bucket = NULL;
1713
51.7k
    xmlParserNsExtra *extra;
1714
51.7k
    const xmlChar **ns;
1715
51.7k
    unsigned hashValue, nsIndex, oldIndex;
1716
1717
51.7k
    if ((prefix != NULL) && (prefix->name == ctxt->str_xml))
1718
195
        return(0);
1719
1720
51.5k
    if ((ctxt->nsNr >= ctxt->nsMax) && (xmlParserNsGrow(ctxt) < 0)) {
1721
0
        xmlErrMemory(ctxt);
1722
0
        return(-1);
1723
0
    }
1724
1725
    /*
1726
     * Default namespace and 'xml' namespace
1727
     */
1728
51.5k
    if ((prefix == NULL) || (prefix->name == NULL)) {
1729
20.0k
        oldIndex = ctxt->nsdb->defaultNsIndex;
1730
1731
20.0k
        if (oldIndex != INT_MAX) {
1732
7.67k
            extra = &ctxt->nsdb->extra[oldIndex];
1733
1734
7.67k
            if (extra->elementId == ctxt->nsdb->elementId) {
1735
433
                if (defAttr == 0)
1736
264
                    xmlErrAttributeDup(ctxt, NULL, BAD_CAST "xmlns");
1737
433
                return(0);
1738
433
            }
1739
1740
7.24k
            if ((ctxt->options & XML_PARSE_NSCLEAN) &&
1741
7.24k
                (uri->name == ctxt->nsTab[oldIndex * 2 + 1]))
1742
228
                return(0);
1743
7.24k
        }
1744
1745
19.3k
        ctxt->nsdb->defaultNsIndex = ctxt->nsNr;
1746
19.3k
        goto populate_entry;
1747
20.0k
    }
1748
1749
    /*
1750
     * Hash table lookup
1751
     */
1752
31.5k
    oldIndex = xmlParserNsLookup(ctxt, prefix, &bucket);
1753
31.5k
    if (oldIndex != INT_MAX) {
1754
18.5k
        extra = &ctxt->nsdb->extra[oldIndex];
1755
1756
        /*
1757
         * Check for duplicate definitions on the same element.
1758
         */
1759
18.5k
        if (extra->elementId == ctxt->nsdb->elementId) {
1760
127
            if (defAttr == 0)
1761
117
                xmlErrAttributeDup(ctxt, BAD_CAST "xmlns", prefix->name);
1762
127
            return(0);
1763
127
        }
1764
1765
18.4k
        if ((ctxt->options & XML_PARSE_NSCLEAN) &&
1766
18.4k
            (uri->name == ctxt->nsTab[bucket->index * 2 + 1]))
1767
211
            return(0);
1768
1769
18.2k
        bucket->index = ctxt->nsNr;
1770
18.2k
        goto populate_entry;
1771
18.4k
    }
1772
1773
    /*
1774
     * Insert new bucket
1775
     */
1776
1777
12.9k
    hashValue = prefix->hashValue;
1778
1779
    /*
1780
     * Grow hash table, 50% fill factor
1781
     */
1782
12.9k
    if (ctxt->nsdb->hashElems + 1 > ctxt->nsdb->hashSize / 2) {
1783
1.42k
        xmlParserNsBucket *newHash;
1784
1.42k
        unsigned newSize, i, index;
1785
1786
1.42k
        if (ctxt->nsdb->hashSize > UINT_MAX / 2) {
1787
0
            xmlErrMemory(ctxt);
1788
0
            return(-1);
1789
0
        }
1790
1.42k
        newSize = ctxt->nsdb->hashSize ? ctxt->nsdb->hashSize * 2 : 16;
1791
1.42k
        newHash = xmlMalloc(newSize * sizeof(newHash[0]));
1792
1.42k
        if (newHash == NULL) {
1793
0
            xmlErrMemory(ctxt);
1794
0
            return(-1);
1795
0
        }
1796
1.42k
        memset(newHash, 0, newSize * sizeof(newHash[0]));
1797
1798
37.0k
        for (i = 0; i < ctxt->nsdb->hashSize; i++) {
1799
35.6k
            unsigned hv = ctxt->nsdb->hash[i].hashValue;
1800
35.6k
            unsigned newIndex;
1801
1802
35.6k
            if (hv == 0)
1803
17.8k
                continue;
1804
17.8k
            newIndex = hv & (newSize - 1);
1805
1806
1.92M
            while (newHash[newIndex].hashValue != 0) {
1807
1.90M
                newIndex++;
1808
1.90M
                if (newIndex == newSize)
1809
3.71k
                    newIndex = 0;
1810
1.90M
            }
1811
1812
17.8k
            newHash[newIndex] = ctxt->nsdb->hash[i];
1813
17.8k
        }
1814
1815
1.42k
        xmlFree(ctxt->nsdb->hash);
1816
1.42k
        ctxt->nsdb->hash = newHash;
1817
1.42k
        ctxt->nsdb->hashSize = newSize;
1818
1819
        /*
1820
         * Relookup
1821
         */
1822
1.42k
        index = hashValue & (newSize - 1);
1823
1824
10.9k
        while (newHash[index].hashValue != 0) {
1825
9.49k
            index++;
1826
9.49k
            if (index == newSize)
1827
156
                index = 0;
1828
9.49k
        }
1829
1830
1.42k
        bucket = &newHash[index];
1831
1.42k
    }
1832
1833
12.9k
    bucket->hashValue = hashValue;
1834
12.9k
    bucket->index = ctxt->nsNr;
1835
12.9k
    ctxt->nsdb->hashElems++;
1836
12.9k
    oldIndex = INT_MAX;
1837
1838
50.5k
populate_entry:
1839
50.5k
    nsIndex = ctxt->nsNr;
1840
1841
50.5k
    ns = &ctxt->nsTab[nsIndex * 2];
1842
50.5k
    ns[0] = prefix ? prefix->name : NULL;
1843
50.5k
    ns[1] = uri->name;
1844
1845
50.5k
    extra = &ctxt->nsdb->extra[nsIndex];
1846
50.5k
    extra->saxData = saxData;
1847
50.5k
    extra->prefixHashValue = prefix ? prefix->hashValue : 0;
1848
50.5k
    extra->uriHashValue = uri->hashValue;
1849
50.5k
    extra->elementId = ctxt->nsdb->elementId;
1850
50.5k
    extra->oldIndex = oldIndex;
1851
1852
50.5k
    ctxt->nsNr++;
1853
1854
50.5k
    return(1);
1855
12.9k
}
1856
1857
/**
1858
 * xmlParserNsPop:
1859
 * @ctxt: an XML parser context
1860
 * @nr:  the number to pop
1861
 *
1862
 * Pops the top @nr namespaces and restores the hash table.
1863
 *
1864
 * Returns the number of namespaces popped.
1865
 */
1866
static int
1867
xmlParserNsPop(xmlParserCtxtPtr ctxt, int nr)
1868
32.5k
{
1869
32.5k
    int i;
1870
1871
    /* assert(nr <= ctxt->nsNr); */
1872
1873
82.7k
    for (i = ctxt->nsNr - 1; i >= ctxt->nsNr - nr; i--) {
1874
50.1k
        const xmlChar *prefix = ctxt->nsTab[i * 2];
1875
50.1k
        xmlParserNsExtra *extra = &ctxt->nsdb->extra[i];
1876
1877
50.1k
        if (prefix == NULL) {
1878
19.2k
            ctxt->nsdb->defaultNsIndex = extra->oldIndex;
1879
30.9k
        } else {
1880
30.9k
            xmlHashedString hprefix;
1881
30.9k
            xmlParserNsBucket *bucket = NULL;
1882
1883
30.9k
            hprefix.name = prefix;
1884
30.9k
            hprefix.hashValue = extra->prefixHashValue;
1885
30.9k
            xmlParserNsLookup(ctxt, &hprefix, &bucket);
1886
            /* assert(bucket && bucket->hashValue); */
1887
30.9k
            bucket->index = extra->oldIndex;
1888
30.9k
        }
1889
50.1k
    }
1890
1891
32.5k
    ctxt->nsNr -= nr;
1892
32.5k
    return(nr);
1893
32.5k
}
1894
1895
static int
1896
2.43k
xmlCtxtGrowAttrs(xmlParserCtxtPtr ctxt, int nr) {
1897
2.43k
    const xmlChar **atts;
1898
2.43k
    unsigned *attallocs;
1899
2.43k
    int maxatts;
1900
1901
2.43k
    if (nr + 5 > ctxt->maxatts) {
1902
2.43k
  maxatts = ctxt->maxatts == 0 ? 55 : (nr + 5) * 2;
1903
2.43k
  atts = (const xmlChar **) xmlMalloc(
1904
2.43k
             maxatts * sizeof(const xmlChar *));
1905
2.43k
  if (atts == NULL) goto mem_error;
1906
2.43k
  attallocs = xmlRealloc(ctxt->attallocs,
1907
2.43k
                               (maxatts / 5) * sizeof(attallocs[0]));
1908
2.43k
  if (attallocs == NULL) {
1909
0
            xmlFree(atts);
1910
0
            goto mem_error;
1911
0
        }
1912
2.43k
        if (ctxt->maxatts > 0)
1913
145
            memcpy(atts, ctxt->atts, ctxt->maxatts * sizeof(const xmlChar *));
1914
2.43k
        xmlFree(ctxt->atts);
1915
2.43k
  ctxt->atts = atts;
1916
2.43k
  ctxt->attallocs = attallocs;
1917
2.43k
  ctxt->maxatts = maxatts;
1918
2.43k
    }
1919
2.43k
    return(ctxt->maxatts);
1920
0
mem_error:
1921
0
    xmlErrMemory(ctxt);
1922
0
    return(-1);
1923
2.43k
}
1924
1925
/**
1926
 * inputPush:
1927
 * @ctxt:  an XML parser context
1928
 * @value:  the parser input
1929
 *
1930
 * Pushes a new parser input on top of the input stack
1931
 *
1932
 * Returns -1 in case of error, the index in the stack otherwise
1933
 */
1934
int
1935
inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value)
1936
80.3k
{
1937
80.3k
    if ((ctxt == NULL) || (value == NULL))
1938
0
        return(-1);
1939
80.3k
    if (ctxt->inputNr >= ctxt->inputMax) {
1940
0
        size_t newSize = ctxt->inputMax * 2;
1941
0
        xmlParserInputPtr *tmp;
1942
1943
0
        tmp = (xmlParserInputPtr *) xmlRealloc(ctxt->inputTab,
1944
0
                                               newSize * sizeof(*tmp));
1945
0
        if (tmp == NULL) {
1946
0
            xmlErrMemory(ctxt);
1947
0
            return (-1);
1948
0
        }
1949
0
        ctxt->inputTab = tmp;
1950
0
        ctxt->inputMax = newSize;
1951
0
    }
1952
80.3k
    ctxt->inputTab[ctxt->inputNr] = value;
1953
80.3k
    ctxt->input = value;
1954
80.3k
    return (ctxt->inputNr++);
1955
80.3k
}
1956
/**
1957
 * inputPop:
1958
 * @ctxt: an XML parser context
1959
 *
1960
 * Pops the top parser input from the input stack
1961
 *
1962
 * Returns the input just removed
1963
 */
1964
xmlParserInputPtr
1965
inputPop(xmlParserCtxtPtr ctxt)
1966
124k
{
1967
124k
    xmlParserInputPtr ret;
1968
1969
124k
    if (ctxt == NULL)
1970
0
        return(NULL);
1971
124k
    if (ctxt->inputNr <= 0)
1972
44.3k
        return (NULL);
1973
80.3k
    ctxt->inputNr--;
1974
80.3k
    if (ctxt->inputNr > 0)
1975
58.2k
        ctxt->input = ctxt->inputTab[ctxt->inputNr - 1];
1976
22.1k
    else
1977
22.1k
        ctxt->input = NULL;
1978
80.3k
    ret = ctxt->inputTab[ctxt->inputNr];
1979
80.3k
    ctxt->inputTab[ctxt->inputNr] = NULL;
1980
80.3k
    return (ret);
1981
124k
}
1982
/**
1983
 * nodePush:
1984
 * @ctxt:  an XML parser context
1985
 * @value:  the element node
1986
 *
1987
 * DEPRECATED: Internal function, do not use.
1988
 *
1989
 * Pushes a new element node on top of the node stack
1990
 *
1991
 * Returns -1 in case of error, the index in the stack otherwise
1992
 */
1993
int
1994
nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value)
1995
95.0k
{
1996
95.0k
    int maxDepth;
1997
1998
95.0k
    if (ctxt == NULL)
1999
0
        return(0);
2000
2001
95.0k
    maxDepth = (ctxt->options & XML_PARSE_HUGE) ? 2048 : 256;
2002
95.0k
    if (ctxt->nodeNr > maxDepth) {
2003
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_RESOURCE_LIMIT,
2004
0
                "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
2005
0
                ctxt->nodeNr);
2006
0
        xmlHaltParser(ctxt);
2007
0
        return(-1);
2008
0
    }
2009
95.0k
    if (ctxt->nodeNr >= ctxt->nodeMax) {
2010
336
        xmlNodePtr *tmp;
2011
2012
336
  tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
2013
336
                                      ctxt->nodeMax * 2 *
2014
336
                                      sizeof(ctxt->nodeTab[0]));
2015
336
        if (tmp == NULL) {
2016
0
            xmlErrMemory(ctxt);
2017
0
            return (-1);
2018
0
        }
2019
336
        ctxt->nodeTab = tmp;
2020
336
  ctxt->nodeMax *= 2;
2021
336
    }
2022
95.0k
    ctxt->nodeTab[ctxt->nodeNr] = value;
2023
95.0k
    ctxt->node = value;
2024
95.0k
    return (ctxt->nodeNr++);
2025
95.0k
}
2026
2027
/**
2028
 * nodePop:
2029
 * @ctxt: an XML parser context
2030
 *
2031
 * DEPRECATED: Internal function, do not use.
2032
 *
2033
 * Pops the top element node from the node stack
2034
 *
2035
 * Returns the node just removed
2036
 */
2037
xmlNodePtr
2038
nodePop(xmlParserCtxtPtr ctxt)
2039
117k
{
2040
117k
    xmlNodePtr ret;
2041
2042
117k
    if (ctxt == NULL) return(NULL);
2043
117k
    if (ctxt->nodeNr <= 0)
2044
25.3k
        return (NULL);
2045
91.8k
    ctxt->nodeNr--;
2046
91.8k
    if (ctxt->nodeNr > 0)
2047
87.4k
        ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1];
2048
4.37k
    else
2049
4.37k
        ctxt->node = NULL;
2050
91.8k
    ret = ctxt->nodeTab[ctxt->nodeNr];
2051
91.8k
    ctxt->nodeTab[ctxt->nodeNr] = NULL;
2052
91.8k
    return (ret);
2053
117k
}
2054
2055
/**
2056
 * nameNsPush:
2057
 * @ctxt:  an XML parser context
2058
 * @value:  the element name
2059
 * @prefix:  the element prefix
2060
 * @URI:  the element namespace name
2061
 * @line:  the current line number for error messages
2062
 * @nsNr:  the number of namespaces pushed on the namespace table
2063
 *
2064
 * Pushes a new element name/prefix/URL on top of the name stack
2065
 *
2066
 * Returns -1 in case of error, the index in the stack otherwise
2067
 */
2068
static int
2069
nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
2070
           const xmlChar *prefix, const xmlChar *URI, int line, int nsNr)
2071
140k
{
2072
140k
    xmlStartTag *tag;
2073
2074
140k
    if (ctxt->nameNr >= ctxt->nameMax) {
2075
611
        const xmlChar * *tmp;
2076
611
        xmlStartTag *tmp2;
2077
611
        ctxt->nameMax *= 2;
2078
611
        tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
2079
611
                                    ctxt->nameMax *
2080
611
                                    sizeof(ctxt->nameTab[0]));
2081
611
        if (tmp == NULL) {
2082
0
      ctxt->nameMax /= 2;
2083
0
      goto mem_error;
2084
0
        }
2085
611
  ctxt->nameTab = tmp;
2086
611
        tmp2 = (xmlStartTag *) xmlRealloc((void * *)ctxt->pushTab,
2087
611
                                    ctxt->nameMax *
2088
611
                                    sizeof(ctxt->pushTab[0]));
2089
611
        if (tmp2 == NULL) {
2090
0
      ctxt->nameMax /= 2;
2091
0
      goto mem_error;
2092
0
        }
2093
611
  ctxt->pushTab = tmp2;
2094
139k
    } else if (ctxt->pushTab == NULL) {
2095
13.5k
        ctxt->pushTab = (xmlStartTag *) xmlMalloc(ctxt->nameMax *
2096
13.5k
                                            sizeof(ctxt->pushTab[0]));
2097
13.5k
        if (ctxt->pushTab == NULL)
2098
0
            goto mem_error;
2099
13.5k
    }
2100
140k
    ctxt->nameTab[ctxt->nameNr] = value;
2101
140k
    ctxt->name = value;
2102
140k
    tag = &ctxt->pushTab[ctxt->nameNr];
2103
140k
    tag->prefix = prefix;
2104
140k
    tag->URI = URI;
2105
140k
    tag->line = line;
2106
140k
    tag->nsNr = nsNr;
2107
140k
    return (ctxt->nameNr++);
2108
0
mem_error:
2109
0
    xmlErrMemory(ctxt);
2110
0
    return (-1);
2111
140k
}
2112
#ifdef LIBXML_PUSH_ENABLED
2113
/**
2114
 * nameNsPop:
2115
 * @ctxt: an XML parser context
2116
 *
2117
 * Pops the top element/prefix/URI name from the name stack
2118
 *
2119
 * Returns the name just removed
2120
 */
2121
static const xmlChar *
2122
nameNsPop(xmlParserCtxtPtr ctxt)
2123
0
{
2124
0
    const xmlChar *ret;
2125
2126
0
    if (ctxt->nameNr <= 0)
2127
0
        return (NULL);
2128
0
    ctxt->nameNr--;
2129
0
    if (ctxt->nameNr > 0)
2130
0
        ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
2131
0
    else
2132
0
        ctxt->name = NULL;
2133
0
    ret = ctxt->nameTab[ctxt->nameNr];
2134
0
    ctxt->nameTab[ctxt->nameNr] = NULL;
2135
0
    return (ret);
2136
0
}
2137
#endif /* LIBXML_PUSH_ENABLED */
2138
2139
/**
2140
 * namePush:
2141
 * @ctxt:  an XML parser context
2142
 * @value:  the element name
2143
 *
2144
 * DEPRECATED: Internal function, do not use.
2145
 *
2146
 * Pushes a new element name on top of the name stack
2147
 *
2148
 * Returns -1 in case of error, the index in the stack otherwise
2149
 */
2150
int
2151
namePush(xmlParserCtxtPtr ctxt, const xmlChar * value)
2152
0
{
2153
0
    if (ctxt == NULL) return (-1);
2154
2155
0
    if (ctxt->nameNr >= ctxt->nameMax) {
2156
0
        const xmlChar * *tmp;
2157
0
        tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
2158
0
                                    ctxt->nameMax * 2 *
2159
0
                                    sizeof(ctxt->nameTab[0]));
2160
0
        if (tmp == NULL) {
2161
0
      goto mem_error;
2162
0
        }
2163
0
  ctxt->nameTab = tmp;
2164
0
        ctxt->nameMax *= 2;
2165
0
    }
2166
0
    ctxt->nameTab[ctxt->nameNr] = value;
2167
0
    ctxt->name = value;
2168
0
    return (ctxt->nameNr++);
2169
0
mem_error:
2170
0
    xmlErrMemory(ctxt);
2171
0
    return (-1);
2172
0
}
2173
2174
/**
2175
 * namePop:
2176
 * @ctxt: an XML parser context
2177
 *
2178
 * DEPRECATED: Internal function, do not use.
2179
 *
2180
 * Pops the top element name from the name stack
2181
 *
2182
 * Returns the name just removed
2183
 */
2184
const xmlChar *
2185
namePop(xmlParserCtxtPtr ctxt)
2186
135k
{
2187
135k
    const xmlChar *ret;
2188
2189
135k
    if ((ctxt == NULL) || (ctxt->nameNr <= 0))
2190
0
        return (NULL);
2191
135k
    ctxt->nameNr--;
2192
135k
    if (ctxt->nameNr > 0)
2193
126k
        ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
2194
8.80k
    else
2195
8.80k
        ctxt->name = NULL;
2196
135k
    ret = ctxt->nameTab[ctxt->nameNr];
2197
135k
    ctxt->nameTab[ctxt->nameNr] = NULL;
2198
135k
    return (ret);
2199
135k
}
2200
2201
163k
static int spacePush(xmlParserCtxtPtr ctxt, int val) {
2202
163k
    if (ctxt->spaceNr >= ctxt->spaceMax) {
2203
654
        int *tmp;
2204
2205
654
  ctxt->spaceMax *= 2;
2206
654
        tmp = (int *) xmlRealloc(ctxt->spaceTab,
2207
654
                           ctxt->spaceMax * sizeof(ctxt->spaceTab[0]));
2208
654
        if (tmp == NULL) {
2209
0
      xmlErrMemory(ctxt);
2210
0
      ctxt->spaceMax /=2;
2211
0
      return(-1);
2212
0
  }
2213
654
  ctxt->spaceTab = tmp;
2214
654
    }
2215
163k
    ctxt->spaceTab[ctxt->spaceNr] = val;
2216
163k
    ctxt->space = &ctxt->spaceTab[ctxt->spaceNr];
2217
163k
    return(ctxt->spaceNr++);
2218
163k
}
2219
2220
158k
static int spacePop(xmlParserCtxtPtr ctxt) {
2221
158k
    int ret;
2222
158k
    if (ctxt->spaceNr <= 0) return(0);
2223
158k
    ctxt->spaceNr--;
2224
158k
    if (ctxt->spaceNr > 0)
2225
158k
  ctxt->space = &ctxt->spaceTab[ctxt->spaceNr - 1];
2226
0
    else
2227
0
        ctxt->space = &ctxt->spaceTab[0];
2228
158k
    ret = ctxt->spaceTab[ctxt->spaceNr];
2229
158k
    ctxt->spaceTab[ctxt->spaceNr] = -1;
2230
158k
    return(ret);
2231
158k
}
2232
2233
/*
2234
 * Macros for accessing the content. Those should be used only by the parser,
2235
 * and not exported.
2236
 *
2237
 * Dirty macros, i.e. one often need to make assumption on the context to
2238
 * use them
2239
 *
2240
 *   CUR_PTR return the current pointer to the xmlChar to be parsed.
2241
 *           To be used with extreme caution since operations consuming
2242
 *           characters may move the input buffer to a different location !
2243
 *   CUR     returns the current xmlChar value, i.e. a 8 bit value if compiled
2244
 *           This should be used internally by the parser
2245
 *           only to compare to ASCII values otherwise it would break when
2246
 *           running with UTF-8 encoding.
2247
 *   RAW     same as CUR but in the input buffer, bypass any token
2248
 *           extraction that may have been done
2249
 *   NXT(n)  returns the n'th next xmlChar. Same as CUR is should be used only
2250
 *           to compare on ASCII based substring.
2251
 *   SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
2252
 *           strings without newlines within the parser.
2253
 *   NEXT1(l) Skip 1 xmlChar, and must also be used only to skip 1 non-newline ASCII
2254
 *           defined char within the parser.
2255
 * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
2256
 *
2257
 *   NEXT    Skip to the next character, this does the proper decoding
2258
 *           in UTF-8 mode. It also pop-up unfinished entities on the fly.
2259
 *   NEXTL(l) Skip the current unicode character of l xmlChars long.
2260
 *   CUR_CHAR(l) returns the current unicode character (int), set l
2261
 *           to the number of xmlChars used for the encoding [0-5].
2262
 *   CUR_SCHAR  same but operate on a string instead of the context
2263
 *   COPY_BUF  copy the current unicode char to the target buffer, increment
2264
 *            the index
2265
 *   GROW, SHRINK  handling of input buffers
2266
 */
2267
2268
2.50M
#define RAW (*ctxt->input->cur)
2269
3.06M
#define CUR (*ctxt->input->cur)
2270
1.07M
#define NXT(val) ctxt->input->cur[(val)]
2271
3.36M
#define CUR_PTR ctxt->input->cur
2272
381k
#define BASE_PTR ctxt->input->base
2273
2274
#define CMP4( s, c1, c2, c3, c4 ) \
2275
1.53M
  ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char *) s)[ 1 ] == c2 && \
2276
793k
    ((unsigned char *) s)[ 2 ] == c3 && ((unsigned char *) s)[ 3 ] == c4 )
2277
#define CMP5( s, c1, c2, c3, c4, c5 ) \
2278
1.37M
  ( CMP4( s, c1, c2, c3, c4 ) && ((unsigned char *) s)[ 4 ] == c5 )
2279
#define CMP6( s, c1, c2, c3, c4, c5, c6 ) \
2280
1.10M
  ( CMP5( s, c1, c2, c3, c4, c5 ) && ((unsigned char *) s)[ 5 ] == c6 )
2281
#define CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) \
2282
875k
  ( CMP6( s, c1, c2, c3, c4, c5, c6 ) && ((unsigned char *) s)[ 6 ] == c7 )
2283
#define CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) \
2284
702k
  ( CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) && ((unsigned char *) s)[ 7 ] == c8 )
2285
#define CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) \
2286
314k
  ( CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) && \
2287
314k
    ((unsigned char *) s)[ 8 ] == c9 )
2288
#define CMP10( s, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 ) \
2289
10.3k
  ( CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) && \
2290
10.3k
    ((unsigned char *) s)[ 9 ] == c10 )
2291
2292
327k
#define SKIP(val) do {             \
2293
327k
    ctxt->input->cur += (val),ctxt->input->col+=(val);      \
2294
327k
    if (*ctxt->input->cur == 0)           \
2295
327k
        xmlParserGrow(ctxt);           \
2296
327k
  } while (0)
2297
2298
0
#define SKIPL(val) do {             \
2299
0
    int skipl;                \
2300
0
    for(skipl=0; skipl<val; skipl++) {         \
2301
0
  if (*(ctxt->input->cur) == '\n') {       \
2302
0
  ctxt->input->line++; ctxt->input->col = 1;      \
2303
0
  } else ctxt->input->col++;         \
2304
0
  ctxt->input->cur++;           \
2305
0
    }                 \
2306
0
    if (*ctxt->input->cur == 0)           \
2307
0
        xmlParserGrow(ctxt);           \
2308
0
  } while (0)
2309
2310
#define SHRINK \
2311
442k
    if ((!PARSER_PROGRESSIVE(ctxt)) && \
2312
442k
        (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \
2313
442k
  (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \
2314
442k
  xmlParserShrink(ctxt);
2315
2316
#define GROW \
2317
2.45M
    if ((!PARSER_PROGRESSIVE(ctxt)) && \
2318
2.45M
        (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK)) \
2319
2.06M
  xmlParserGrow(ctxt);
2320
2321
460k
#define SKIP_BLANKS xmlSkipBlankChars(ctxt)
2322
2323
562k
#define SKIP_BLANKS_PE xmlSkipBlankCharsPE(ctxt)
2324
2325
765k
#define NEXT xmlNextChar(ctxt)
2326
2327
210k
#define NEXT1 {               \
2328
210k
  ctxt->input->col++;           \
2329
210k
  ctxt->input->cur++;           \
2330
210k
  if (*ctxt->input->cur == 0)         \
2331
210k
      xmlParserGrow(ctxt);           \
2332
210k
    }
2333
2334
2.11M
#define NEXTL(l) do {             \
2335
2.11M
    if (*(ctxt->input->cur) == '\n') {         \
2336
5.17k
  ctxt->input->line++; ctxt->input->col = 1;      \
2337
2.11M
    } else ctxt->input->col++;           \
2338
2.11M
    ctxt->input->cur += l;        \
2339
2.11M
  } while (0)
2340
2341
1.09M
#define CUR_CHAR(l) xmlCurrentChar(ctxt, &l)
2342
880k
#define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l)
2343
2344
#define COPY_BUF(b, i, v)           \
2345
1.07M
    if (v < 0x80) b[i++] = v;           \
2346
1.07M
    else i += xmlCopyCharMultiByte(&b[i],v)
2347
2348
/**
2349
 * xmlSkipBlankChars:
2350
 * @ctxt:  the XML parser context
2351
 *
2352
 * DEPRECATED: Internal function, do not use.
2353
 *
2354
 * Skip whitespace in the input stream.
2355
 *
2356
 * Returns the number of space chars skipped
2357
 */
2358
int
2359
586k
xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
2360
586k
    const xmlChar *cur;
2361
586k
    int res = 0;
2362
2363
    /*
2364
     * It's Okay to use CUR/NEXT here since all the blanks are on
2365
     * the ASCII range.
2366
     */
2367
586k
    cur = ctxt->input->cur;
2368
586k
    while (IS_BLANK_CH(*cur)) {
2369
116k
        if (*cur == '\n') {
2370
5.90k
            ctxt->input->line++; ctxt->input->col = 1;
2371
110k
        } else {
2372
110k
            ctxt->input->col++;
2373
110k
        }
2374
116k
        cur++;
2375
116k
        if (res < INT_MAX)
2376
116k
            res++;
2377
116k
        if (*cur == 0) {
2378
1.64k
            ctxt->input->cur = cur;
2379
1.64k
            xmlParserGrow(ctxt);
2380
1.64k
            cur = ctxt->input->cur;
2381
1.64k
        }
2382
116k
    }
2383
586k
    ctxt->input->cur = cur;
2384
2385
586k
    return(res);
2386
586k
}
2387
2388
static void
2389
57.4k
xmlPopPE(xmlParserCtxtPtr ctxt) {
2390
57.4k
    unsigned long consumed;
2391
57.4k
    xmlEntityPtr ent;
2392
2393
57.4k
    ent = ctxt->input->entity;
2394
2395
57.4k
    ent->flags &= ~XML_ENT_EXPANDING;
2396
2397
57.4k
    if ((ent->flags & XML_ENT_CHECKED) == 0) {
2398
2.31k
        int result;
2399
2400
        /*
2401
         * Read the rest of the stream in case of errors. We want
2402
         * to account for the whole entity size.
2403
         */
2404
2.32k
        do {
2405
2.32k
            ctxt->input->cur = ctxt->input->end;
2406
2.32k
            xmlParserShrink(ctxt);
2407
2.32k
            result = xmlParserGrow(ctxt);
2408
2.32k
        } while (result > 0);
2409
2410
2.31k
        consumed = ctxt->input->consumed;
2411
2.31k
        xmlSaturatedAddSizeT(&consumed,
2412
2.31k
                             ctxt->input->end - ctxt->input->base);
2413
2414
2.31k
        xmlSaturatedAdd(&ent->expandedSize, consumed);
2415
2416
        /*
2417
         * Add to sizeentities when parsing an external entity
2418
         * for the first time.
2419
         */
2420
2.31k
        if (ent->etype == XML_EXTERNAL_PARAMETER_ENTITY) {
2421
0
            xmlSaturatedAdd(&ctxt->sizeentities, consumed);
2422
0
        }
2423
2424
2.31k
        ent->flags |= XML_ENT_CHECKED;
2425
2.31k
    }
2426
2427
57.4k
    xmlPopInput(ctxt);
2428
2429
57.4k
    xmlParserEntityCheck(ctxt, ent->expandedSize);
2430
57.4k
}
2431
2432
/**
2433
 * xmlSkipBlankCharsPE:
2434
 * @ctxt:  the XML parser context
2435
 *
2436
 * Skip whitespace in the input stream, also handling parameter
2437
 * entities.
2438
 *
2439
 * Returns the number of space chars skipped
2440
 */
2441
static int
2442
562k
xmlSkipBlankCharsPE(xmlParserCtxtPtr ctxt) {
2443
562k
    int res = 0;
2444
562k
    int inParam;
2445
562k
    int expandParam;
2446
2447
562k
    inParam = PARSER_IN_PE(ctxt);
2448
562k
    expandParam = PARSER_EXTERNAL(ctxt);
2449
2450
562k
    if (!inParam && !expandParam)
2451
126k
        return(xmlSkipBlankChars(ctxt));
2452
2453
635k
    while (PARSER_STOPPED(ctxt) == 0) {
2454
635k
        if (IS_BLANK_CH(CUR)) { /* CHECKED tstblanks.xml */
2455
142k
            NEXT;
2456
493k
        } else if (CUR == '%') {
2457
56.3k
            if ((expandParam == 0) ||
2458
56.3k
                (IS_BLANK_CH(NXT(1))) || (NXT(1) == 0))
2459
56.3k
                break;
2460
2461
            /*
2462
             * Expand parameter entity. We continue to consume
2463
             * whitespace at the start of the entity and possible
2464
             * even consume the whole entity and pop it. We might
2465
             * even pop multiple PEs in this loop.
2466
             */
2467
0
            xmlParsePEReference(ctxt);
2468
2469
0
            inParam = PARSER_IN_PE(ctxt);
2470
0
            expandParam = PARSER_EXTERNAL(ctxt);
2471
436k
        } else if (CUR == 0) {
2472
57.4k
            if (inParam == 0)
2473
3
                break;
2474
2475
57.4k
            xmlPopPE(ctxt);
2476
2477
57.4k
            inParam = PARSER_IN_PE(ctxt);
2478
57.4k
            expandParam = PARSER_EXTERNAL(ctxt);
2479
379k
        } else {
2480
379k
            break;
2481
379k
        }
2482
2483
        /*
2484
         * Also increase the counter when entering or exiting a PERef.
2485
         * The spec says: "When a parameter-entity reference is recognized
2486
         * in the DTD and included, its replacement text MUST be enlarged
2487
         * by the attachment of one leading and one following space (#x20)
2488
         * character."
2489
         */
2490
199k
        if (res < INT_MAX)
2491
199k
            res++;
2492
199k
    }
2493
2494
435k
    return(res);
2495
562k
}
2496
2497
/************************************************************************
2498
 *                  *
2499
 *    Commodity functions to handle entities      *
2500
 *                  *
2501
 ************************************************************************/
2502
2503
/**
2504
 * xmlPopInput:
2505
 * @ctxt:  an XML parser context
2506
 *
2507
 * xmlPopInput: the current input pointed by ctxt->input came to an end
2508
 *          pop it and return the next char.
2509
 *
2510
 * Returns the current xmlChar in the parser context
2511
 */
2512
xmlChar
2513
57.4k
xmlPopInput(xmlParserCtxtPtr ctxt) {
2514
57.4k
    xmlParserInputPtr input;
2515
2516
57.4k
    if ((ctxt == NULL) || (ctxt->inputNr <= 1)) return(0);
2517
57.4k
    input = inputPop(ctxt);
2518
57.4k
    xmlFreeInputStream(input);
2519
57.4k
    if (*ctxt->input->cur == 0)
2520
323
        xmlParserGrow(ctxt);
2521
57.4k
    return(CUR);
2522
57.4k
}
2523
2524
/**
2525
 * xmlPushInput:
2526
 * @ctxt:  an XML parser context
2527
 * @input:  an XML parser input fragment (entity, XML fragment ...).
2528
 *
2529
 * Push an input stream onto the stack.
2530
 *
2531
 * This makes the parser use an input returned from advanced functions
2532
 * like xmlNewInputURL or xmlNewInputMemory.
2533
 *
2534
 * Returns -1 in case of error or the index in the input stack
2535
 */
2536
int
2537
58.2k
xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
2538
58.2k
    int maxDepth;
2539
58.2k
    int ret;
2540
2541
58.2k
    if ((ctxt == NULL) || (input == NULL))
2542
0
        return(-1);
2543
2544
58.2k
    maxDepth = (ctxt->options & XML_PARSE_HUGE) ? 40 : 20;
2545
58.2k
    if (ctxt->inputNr > maxDepth) {
2546
0
        xmlFatalErrMsg(ctxt, XML_ERR_RESOURCE_LIMIT,
2547
0
                       "Maximum entity nesting depth exceeded");
2548
0
        xmlHaltParser(ctxt);
2549
0
  return(-1);
2550
0
    }
2551
58.2k
    ret = inputPush(ctxt, input);
2552
58.2k
    GROW;
2553
58.2k
    return(ret);
2554
58.2k
}
2555
2556
/**
2557
 * xmlParseCharRef:
2558
 * @ctxt:  an XML parser context
2559
 *
2560
 * DEPRECATED: Internal function, don't use.
2561
 *
2562
 * Parse a numeric character reference. Always consumes '&'.
2563
 *
2564
 * [66] CharRef ::= '&#' [0-9]+ ';' |
2565
 *                  '&#x' [0-9a-fA-F]+ ';'
2566
 *
2567
 * [ WFC: Legal Character ]
2568
 * Characters referred to using character references must match the
2569
 * production for Char.
2570
 *
2571
 * Returns the value parsed (as an int), 0 in case of error
2572
 */
2573
int
2574
13.0k
xmlParseCharRef(xmlParserCtxtPtr ctxt) {
2575
13.0k
    int val = 0;
2576
13.0k
    int count = 0;
2577
2578
    /*
2579
     * Using RAW/CUR/NEXT is okay since we are working on ASCII range here
2580
     */
2581
13.0k
    if ((RAW == '&') && (NXT(1) == '#') &&
2582
13.0k
        (NXT(2) == 'x')) {
2583
6.74k
  SKIP(3);
2584
6.74k
  GROW;
2585
27.3k
  while ((RAW != ';') && (PARSER_STOPPED(ctxt) == 0)) {
2586
21.4k
      if (count++ > 20) {
2587
480
    count = 0;
2588
480
    GROW;
2589
480
      }
2590
21.4k
      if ((RAW >= '0') && (RAW <= '9'))
2591
8.65k
          val = val * 16 + (CUR - '0');
2592
12.8k
      else if ((RAW >= 'a') && (RAW <= 'f') && (count < 20))
2593
3.83k
          val = val * 16 + (CUR - 'a') + 10;
2594
8.97k
      else if ((RAW >= 'A') && (RAW <= 'F') && (count < 20))
2595
8.12k
          val = val * 16 + (CUR - 'A') + 10;
2596
845
      else {
2597
845
    xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
2598
845
    val = 0;
2599
845
    break;
2600
845
      }
2601
20.6k
      if (val > 0x110000)
2602
5.74k
          val = 0x110000;
2603
2604
20.6k
      NEXT;
2605
20.6k
      count++;
2606
20.6k
  }
2607
6.74k
  if (RAW == ';') {
2608
      /* on purpose to avoid reentrancy problems with NEXT and SKIP */
2609
5.89k
      ctxt->input->col++;
2610
5.89k
      ctxt->input->cur++;
2611
5.89k
  }
2612
6.74k
    } else if  ((RAW == '&') && (NXT(1) == '#')) {
2613
6.31k
  SKIP(2);
2614
6.31k
  GROW;
2615
23.2k
  while (RAW != ';') { /* loop blocked by count */
2616
18.2k
      if (count++ > 20) {
2617
345
    count = 0;
2618
345
    GROW;
2619
345
      }
2620
18.2k
      if ((RAW >= '0') && (RAW <= '9'))
2621
16.9k
          val = val * 10 + (CUR - '0');
2622
1.33k
      else {
2623
1.33k
    xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
2624
1.33k
    val = 0;
2625
1.33k
    break;
2626
1.33k
      }
2627
16.9k
      if (val > 0x110000)
2628
3.19k
          val = 0x110000;
2629
2630
16.9k
      NEXT;
2631
16.9k
      count++;
2632
16.9k
  }
2633
6.31k
  if (RAW == ';') {
2634
      /* on purpose to avoid reentrancy problems with NEXT and SKIP */
2635
4.97k
      ctxt->input->col++;
2636
4.97k
      ctxt->input->cur++;
2637
4.97k
  }
2638
6.31k
    } else {
2639
0
        if (RAW == '&')
2640
0
            SKIP(1);
2641
0
        xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
2642
0
    }
2643
2644
    /*
2645
     * [ WFC: Legal Character ]
2646
     * Characters referred to using character references must match the
2647
     * production for Char.
2648
     */
2649
13.0k
    if (val >= 0x110000) {
2650
269
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2651
269
                "xmlParseCharRef: character reference out of bounds\n",
2652
269
          val);
2653
12.7k
    } else if (IS_CHAR(val)) {
2654
10.0k
        return(val);
2655
10.0k
    } else {
2656
2.72k
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2657
2.72k
                          "xmlParseCharRef: invalid xmlChar value %d\n",
2658
2.72k
                    val);
2659
2.72k
    }
2660
2.99k
    return(0);
2661
13.0k
}
2662
2663
/**
2664
 * xmlParseStringCharRef:
2665
 * @ctxt:  an XML parser context
2666
 * @str:  a pointer to an index in the string
2667
 *
2668
 * parse Reference declarations, variant parsing from a string rather
2669
 * than an an input flow.
2670
 *
2671
 * [66] CharRef ::= '&#' [0-9]+ ';' |
2672
 *                  '&#x' [0-9a-fA-F]+ ';'
2673
 *
2674
 * [ WFC: Legal Character ]
2675
 * Characters referred to using character references must match the
2676
 * production for Char.
2677
 *
2678
 * Returns the value parsed (as an int), 0 in case of error, str will be
2679
 *         updated to the current value of the index
2680
 */
2681
static int
2682
16.9k
xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
2683
16.9k
    const xmlChar *ptr;
2684
16.9k
    xmlChar cur;
2685
16.9k
    int val = 0;
2686
2687
16.9k
    if ((str == NULL) || (*str == NULL)) return(0);
2688
16.9k
    ptr = *str;
2689
16.9k
    cur = *ptr;
2690
16.9k
    if ((cur == '&') && (ptr[1] == '#') && (ptr[2] == 'x')) {
2691
5.23k
  ptr += 3;
2692
5.23k
  cur = *ptr;
2693
20.5k
  while (cur != ';') { /* Non input consuming loop */
2694
15.7k
      if ((cur >= '0') && (cur <= '9'))
2695
4.73k
          val = val * 16 + (cur - '0');
2696
11.0k
      else if ((cur >= 'a') && (cur <= 'f'))
2697
4.06k
          val = val * 16 + (cur - 'a') + 10;
2698
6.99k
      else if ((cur >= 'A') && (cur <= 'F'))
2699
6.51k
          val = val * 16 + (cur - 'A') + 10;
2700
484
      else {
2701
484
    xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
2702
484
    val = 0;
2703
484
    break;
2704
484
      }
2705
15.3k
      if (val > 0x110000)
2706
883
          val = 0x110000;
2707
2708
15.3k
      ptr++;
2709
15.3k
      cur = *ptr;
2710
15.3k
  }
2711
5.23k
  if (cur == ';')
2712
4.75k
      ptr++;
2713
11.6k
    } else if  ((cur == '&') && (ptr[1] == '#')){
2714
11.6k
  ptr += 2;
2715
11.6k
  cur = *ptr;
2716
37.4k
  while (cur != ';') { /* Non input consuming loops */
2717
26.7k
      if ((cur >= '0') && (cur <= '9'))
2718
25.7k
          val = val * 10 + (cur - '0');
2719
1.02k
      else {
2720
1.02k
    xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
2721
1.02k
    val = 0;
2722
1.02k
    break;
2723
1.02k
      }
2724
25.7k
      if (val > 0x110000)
2725
545
          val = 0x110000;
2726
2727
25.7k
      ptr++;
2728
25.7k
      cur = *ptr;
2729
25.7k
  }
2730
11.6k
  if (cur == ';')
2731
10.6k
      ptr++;
2732
11.6k
    } else {
2733
0
  xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
2734
0
  return(0);
2735
0
    }
2736
16.9k
    *str = ptr;
2737
2738
    /*
2739
     * [ WFC: Legal Character ]
2740
     * Characters referred to using character references must match the
2741
     * production for Char.
2742
     */
2743
16.9k
    if (val >= 0x110000) {
2744
202
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2745
202
                "xmlParseStringCharRef: character reference out of bounds\n",
2746
202
                val);
2747
16.7k
    } else if (IS_CHAR(val)) {
2748
14.3k
        return(val);
2749
14.3k
    } else {
2750
2.41k
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2751
2.41k
        "xmlParseStringCharRef: invalid xmlChar value %d\n",
2752
2.41k
        val);
2753
2.41k
    }
2754
2.61k
    return(0);
2755
16.9k
}
2756
2757
/**
2758
 * xmlParserHandlePEReference:
2759
 * @ctxt:  the parser context
2760
 *
2761
 * DEPRECATED: Internal function, do not use.
2762
 *
2763
 * [69] PEReference ::= '%' Name ';'
2764
 *
2765
 * [ WFC: No Recursion ]
2766
 * A parsed entity must not contain a recursive
2767
 * reference to itself, either directly or indirectly.
2768
 *
2769
 * [ WFC: Entity Declared ]
2770
 * In a document without any DTD, a document with only an internal DTD
2771
 * subset which contains no parameter entity references, or a document
2772
 * with "standalone='yes'", ...  ... The declaration of a parameter
2773
 * entity must precede any reference to it...
2774
 *
2775
 * [ VC: Entity Declared ]
2776
 * In a document with an external subset or external parameter entities
2777
 * with "standalone='no'", ...  ... The declaration of a parameter entity
2778
 * must precede any reference to it...
2779
 *
2780
 * [ WFC: In DTD ]
2781
 * Parameter-entity references may only appear in the DTD.
2782
 * NOTE: misleading but this is handled.
2783
 *
2784
 * A PEReference may have been detected in the current input stream
2785
 * the handling is done accordingly to
2786
 *      http://www.w3.org/TR/REC-xml#entproc
2787
 * i.e.
2788
 *   - Included in literal in entity values
2789
 *   - Included as Parameter Entity reference within DTDs
2790
 */
2791
void
2792
0
xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
2793
0
    xmlParsePEReference(ctxt);
2794
0
}
2795
2796
/**
2797
 * xmlStringLenDecodeEntities:
2798
 * @ctxt:  the parser context
2799
 * @str:  the input string
2800
 * @len: the string length
2801
 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
2802
 * @end:  an end marker xmlChar, 0 if none
2803
 * @end2:  an end marker xmlChar, 0 if none
2804
 * @end3:  an end marker xmlChar, 0 if none
2805
 *
2806
 * DEPRECATED: Internal function, don't use.
2807
 *
2808
 * Returns A newly allocated string with the substitution done. The caller
2809
 *      must deallocate it !
2810
 */
2811
xmlChar *
2812
xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
2813
                           int what ATTRIBUTE_UNUSED,
2814
0
                           xmlChar end, xmlChar end2, xmlChar end3) {
2815
0
    if ((ctxt == NULL) || (str == NULL) || (len < 0))
2816
0
        return(NULL);
2817
2818
0
    if ((str[len] != 0) ||
2819
0
        (end != 0) || (end2 != 0) || (end3 != 0))
2820
0
        return(NULL);
2821
2822
0
    return(xmlExpandEntitiesInAttValue(ctxt, str, 0));
2823
0
}
2824
2825
/**
2826
 * xmlStringDecodeEntities:
2827
 * @ctxt:  the parser context
2828
 * @str:  the input string
2829
 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
2830
 * @end:  an end marker xmlChar, 0 if none
2831
 * @end2:  an end marker xmlChar, 0 if none
2832
 * @end3:  an end marker xmlChar, 0 if none
2833
 *
2834
 * DEPRECATED: Internal function, don't use.
2835
 *
2836
 * Returns A newly allocated string with the substitution done. The caller
2837
 *      must deallocate it !
2838
 */
2839
xmlChar *
2840
xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
2841
                        int what ATTRIBUTE_UNUSED,
2842
0
            xmlChar end, xmlChar  end2, xmlChar end3) {
2843
0
    if ((ctxt == NULL) || (str == NULL))
2844
0
        return(NULL);
2845
2846
0
    if ((end != 0) || (end2 != 0) || (end3 != 0))
2847
0
        return(NULL);
2848
2849
0
    return(xmlExpandEntitiesInAttValue(ctxt, str, 0));
2850
0
}
2851
2852
/************************************************************************
2853
 *                  *
2854
 *    Commodity functions, cleanup needed ?     *
2855
 *                  *
2856
 ************************************************************************/
2857
2858
/**
2859
 * areBlanks:
2860
 * @ctxt:  an XML parser context
2861
 * @str:  a xmlChar *
2862
 * @len:  the size of @str
2863
 * @blank_chars: we know the chars are blanks
2864
 *
2865
 * Is this a sequence of blank chars that one can ignore ?
2866
 *
2867
 * Returns 1 if ignorable 0 otherwise.
2868
 */
2869
2870
static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
2871
7.09k
                     int blank_chars) {
2872
7.09k
    int i;
2873
7.09k
    xmlNodePtr lastChild;
2874
2875
    /*
2876
     * Don't spend time trying to differentiate them, the same callback is
2877
     * used !
2878
     */
2879
7.09k
    if (ctxt->sax->ignorableWhitespace == ctxt->sax->characters)
2880
1.53k
  return(0);
2881
2882
    /*
2883
     * Check for xml:space value.
2884
     */
2885
5.55k
    if ((ctxt->space == NULL) || (*(ctxt->space) == 1) ||
2886
5.55k
        (*(ctxt->space) == -2))
2887
1.65k
  return(0);
2888
2889
    /*
2890
     * Check that the string is made of blanks
2891
     */
2892
3.90k
    if (blank_chars == 0) {
2893
7.62k
  for (i = 0;i < len;i++)
2894
6.21k
      if (!(IS_BLANK_CH(str[i]))) return(0);
2895
2.22k
    }
2896
2897
    /*
2898
     * Look if the element is mixed content in the DTD if available
2899
     */
2900
3.08k
    if (ctxt->node == NULL) return(0);
2901
3.08k
    if (ctxt->myDoc != NULL) {
2902
3.08k
        xmlElementPtr elemDecl = NULL;
2903
3.08k
        xmlDocPtr doc = ctxt->myDoc;
2904
3.08k
        const xmlChar *prefix = NULL;
2905
2906
3.08k
        if (ctxt->node->ns)
2907
209
            prefix = ctxt->node->ns->prefix;
2908
3.08k
        if (doc->intSubset != NULL)
2909
882
            elemDecl = xmlHashLookup2(doc->intSubset->elements, ctxt->node->name,
2910
882
                                      prefix);
2911
3.08k
        if ((elemDecl == NULL) && (doc->extSubset != NULL))
2912
0
            elemDecl = xmlHashLookup2(doc->extSubset->elements, ctxt->node->name,
2913
0
                                      prefix);
2914
3.08k
        if (elemDecl != NULL) {
2915
483
            if (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT)
2916
194
                return(1);
2917
289
            if ((elemDecl->etype == XML_ELEMENT_TYPE_ANY) ||
2918
289
                (elemDecl->etype == XML_ELEMENT_TYPE_MIXED))
2919
82
                return(0);
2920
289
        }
2921
3.08k
    }
2922
2923
    /*
2924
     * Otherwise, heuristic :-\
2925
     */
2926
2.81k
    if ((RAW != '<') && (RAW != 0xD)) return(0);
2927
2.44k
    if ((ctxt->node->children == NULL) &&
2928
2.44k
  (RAW == '<') && (NXT(1) == '/')) return(0);
2929
2930
2.18k
    lastChild = xmlGetLastChild(ctxt->node);
2931
2.18k
    if (lastChild == NULL) {
2932
1.39k
        if ((ctxt->node->type != XML_ELEMENT_NODE) &&
2933
1.39k
            (ctxt->node->content != NULL)) return(0);
2934
1.39k
    } else if (xmlNodeIsText(lastChild))
2935
228
        return(0);
2936
561
    else if ((ctxt->node->children != NULL) &&
2937
561
             (xmlNodeIsText(ctxt->node->children)))
2938
75
        return(0);
2939
1.88k
    return(1);
2940
2.18k
}
2941
2942
/************************************************************************
2943
 *                  *
2944
 *    Extra stuff for namespace support     *
2945
 *  Relates to http://www.w3.org/TR/WD-xml-names      *
2946
 *                  *
2947
 ************************************************************************/
2948
2949
/**
2950
 * xmlSplitQName:
2951
 * @ctxt:  an XML parser context
2952
 * @name:  an XML parser context
2953
 * @prefixOut:  a xmlChar **
2954
 *
2955
 * parse an UTF8 encoded XML qualified name string
2956
 *
2957
 * [NS 5] QName ::= (Prefix ':')? LocalPart
2958
 *
2959
 * [NS 6] Prefix ::= NCName
2960
 *
2961
 * [NS 7] LocalPart ::= NCName
2962
 *
2963
 * Returns the local part, and prefix is updated
2964
 *   to get the Prefix if any.
2965
 */
2966
2967
xmlChar *
2968
121k
xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefixOut) {
2969
121k
    xmlChar buf[XML_MAX_NAMELEN + 5];
2970
121k
    xmlChar *buffer = NULL;
2971
121k
    int len = 0;
2972
121k
    int max = XML_MAX_NAMELEN;
2973
121k
    xmlChar *ret = NULL;
2974
121k
    xmlChar *prefix;
2975
121k
    const xmlChar *cur = name;
2976
121k
    int c;
2977
2978
121k
    if (prefixOut == NULL) return(NULL);
2979
121k
    *prefixOut = NULL;
2980
2981
121k
    if (cur == NULL) return(NULL);
2982
2983
#ifndef XML_XML_NAMESPACE
2984
    /* xml: prefix is not really a namespace */
2985
    if ((cur[0] == 'x') && (cur[1] == 'm') &&
2986
        (cur[2] == 'l') && (cur[3] == ':'))
2987
  return(xmlStrdup(name));
2988
#endif
2989
2990
    /* nasty but well=formed */
2991
121k
    if (cur[0] == ':')
2992
11.2k
  return(xmlStrdup(name));
2993
2994
109k
    c = *cur++;
2995
465k
    while ((c != 0) && (c != ':') && (len < max)) { /* tested bigname.xml */
2996
355k
  buf[len++] = c;
2997
355k
  c = *cur++;
2998
355k
    }
2999
109k
    if (len >= max) {
3000
  /*
3001
   * Okay someone managed to make a huge name, so he's ready to pay
3002
   * for the processing speed.
3003
   */
3004
748
  max = len * 2;
3005
3006
748
  buffer = (xmlChar *) xmlMallocAtomic(max);
3007
748
  if (buffer == NULL) {
3008
0
      xmlErrMemory(ctxt);
3009
0
      return(NULL);
3010
0
  }
3011
748
  memcpy(buffer, buf, len);
3012
48.8k
  while ((c != 0) && (c != ':')) { /* tested bigname.xml */
3013
48.0k
      if (len + 10 > max) {
3014
340
          xmlChar *tmp;
3015
3016
340
    max *= 2;
3017
340
    tmp = (xmlChar *) xmlRealloc(buffer, max);
3018
340
    if (tmp == NULL) {
3019
0
        xmlFree(buffer);
3020
0
        xmlErrMemory(ctxt);
3021
0
        return(NULL);
3022
0
    }
3023
340
    buffer = tmp;
3024
340
      }
3025
48.0k
      buffer[len++] = c;
3026
48.0k
      c = *cur++;
3027
48.0k
  }
3028
748
  buffer[len] = 0;
3029
748
    }
3030
3031
109k
    if ((c == ':') && (*cur == 0)) {
3032
872
        if (buffer != NULL)
3033
205
      xmlFree(buffer);
3034
872
  return(xmlStrdup(name));
3035
872
    }
3036
3037
109k
    if (buffer == NULL) {
3038
108k
  ret = xmlStrndup(buf, len);
3039
108k
        if (ret == NULL) {
3040
0
      xmlErrMemory(ctxt);
3041
0
      return(NULL);
3042
0
        }
3043
108k
    } else {
3044
543
  ret = buffer;
3045
543
  buffer = NULL;
3046
543
  max = XML_MAX_NAMELEN;
3047
543
    }
3048
3049
3050
109k
    if (c == ':') {
3051
14.1k
  c = *cur;
3052
14.1k
        prefix = ret;
3053
14.1k
  if (c == 0) {
3054
0
      ret = xmlStrndup(BAD_CAST "", 0);
3055
0
            if (ret == NULL) {
3056
0
                xmlFree(prefix);
3057
0
                return(NULL);
3058
0
            }
3059
0
            *prefixOut = prefix;
3060
0
            return(ret);
3061
0
  }
3062
14.1k
  len = 0;
3063
3064
  /*
3065
   * Check that the first character is proper to start
3066
   * a new name
3067
   */
3068
14.1k
  if (!(((c >= 0x61) && (c <= 0x7A)) ||
3069
14.1k
        ((c >= 0x41) && (c <= 0x5A)) ||
3070
14.1k
        (c == '_') || (c == ':'))) {
3071
3.94k
      int l;
3072
3.94k
      int first = CUR_SCHAR(cur, l);
3073
3074
3.94k
      if (!IS_LETTER(first) && (first != '_')) {
3075
2.58k
    xmlFatalErrMsgStr(ctxt, XML_NS_ERR_QNAME,
3076
2.58k
          "Name %s is not XML Namespace compliant\n",
3077
2.58k
          name);
3078
2.58k
      }
3079
3.94k
  }
3080
14.1k
  cur++;
3081
3082
138k
  while ((c != 0) && (len < max)) { /* tested bigname2.xml */
3083
124k
      buf[len++] = c;
3084
124k
      c = *cur++;
3085
124k
  }
3086
14.1k
  if (len >= max) {
3087
      /*
3088
       * Okay someone managed to make a huge name, so he's ready to pay
3089
       * for the processing speed.
3090
       */
3091
782
      max = len * 2;
3092
3093
782
      buffer = (xmlChar *) xmlMallocAtomic(max);
3094
782
      if (buffer == NULL) {
3095
0
          xmlErrMemory(ctxt);
3096
0
                xmlFree(prefix);
3097
0
    return(NULL);
3098
0
      }
3099
782
      memcpy(buffer, buf, len);
3100
45.9k
      while (c != 0) { /* tested bigname2.xml */
3101
45.1k
    if (len + 10 > max) {
3102
373
        xmlChar *tmp;
3103
3104
373
        max *= 2;
3105
373
        tmp = (xmlChar *) xmlRealloc(buffer, max);
3106
373
        if (tmp == NULL) {
3107
0
      xmlErrMemory(ctxt);
3108
0
                        xmlFree(prefix);
3109
0
      xmlFree(buffer);
3110
0
      return(NULL);
3111
0
        }
3112
373
        buffer = tmp;
3113
373
    }
3114
45.1k
    buffer[len++] = c;
3115
45.1k
    c = *cur++;
3116
45.1k
      }
3117
782
      buffer[len] = 0;
3118
782
  }
3119
3120
14.1k
  if (buffer == NULL) {
3121
13.3k
      ret = xmlStrndup(buf, len);
3122
13.3k
            if (ret == NULL) {
3123
0
                xmlFree(prefix);
3124
0
                return(NULL);
3125
0
            }
3126
13.3k
  } else {
3127
782
      ret = buffer;
3128
782
  }
3129
3130
14.1k
        *prefixOut = prefix;
3131
14.1k
    }
3132
3133
109k
    return(ret);
3134
109k
}
3135
3136
/************************************************************************
3137
 *                  *
3138
 *      The parser itself       *
3139
 *  Relates to http://www.w3.org/TR/REC-xml       *
3140
 *                  *
3141
 ************************************************************************/
3142
3143
/************************************************************************
3144
 *                  *
3145
 *  Routines to parse Name, NCName and NmToken      *
3146
 *                  *
3147
 ************************************************************************/
3148
3149
/*
3150
 * The two following functions are related to the change of accepted
3151
 * characters for Name and NmToken in the Revision 5 of XML-1.0
3152
 * They correspond to the modified production [4] and the new production [4a]
3153
 * changes in that revision. Also note that the macros used for the
3154
 * productions Letter, Digit, CombiningChar and Extender are not needed
3155
 * anymore.
3156
 * We still keep compatibility to pre-revision5 parsing semantic if the
3157
 * new XML_PARSE_OLD10 option is given to the parser.
3158
 */
3159
static int
3160
423k
xmlIsNameStartChar(xmlParserCtxtPtr ctxt, int c) {
3161
423k
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3162
        /*
3163
   * Use the new checks of production [4] [4a] amd [5] of the
3164
   * Update 5 of XML-1.0
3165
   */
3166
407k
  if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3167
407k
      (((c >= 'a') && (c <= 'z')) ||
3168
406k
       ((c >= 'A') && (c <= 'Z')) ||
3169
406k
       (c == '_') || (c == ':') ||
3170
406k
       ((c >= 0xC0) && (c <= 0xD6)) ||
3171
406k
       ((c >= 0xD8) && (c <= 0xF6)) ||
3172
406k
       ((c >= 0xF8) && (c <= 0x2FF)) ||
3173
406k
       ((c >= 0x370) && (c <= 0x37D)) ||
3174
406k
       ((c >= 0x37F) && (c <= 0x1FFF)) ||
3175
406k
       ((c >= 0x200C) && (c <= 0x200D)) ||
3176
406k
       ((c >= 0x2070) && (c <= 0x218F)) ||
3177
406k
       ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3178
406k
       ((c >= 0x3001) && (c <= 0xD7FF)) ||
3179
406k
       ((c >= 0xF900) && (c <= 0xFDCF)) ||
3180
406k
       ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3181
406k
       ((c >= 0x10000) && (c <= 0xEFFFF))))
3182
350k
      return(1);
3183
407k
    } else {
3184
16.8k
        if (IS_LETTER(c) || (c == '_') || (c == ':'))
3185
14.0k
      return(1);
3186
16.8k
    }
3187
59.1k
    return(0);
3188
423k
}
3189
3190
static int
3191
808k
xmlIsNameChar(xmlParserCtxtPtr ctxt, int c) {
3192
808k
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3193
        /*
3194
   * Use the new checks of production [4] [4a] amd [5] of the
3195
   * Update 5 of XML-1.0
3196
   */
3197
783k
  if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3198
783k
      (((c >= 'a') && (c <= 'z')) ||
3199
772k
       ((c >= 'A') && (c <= 'Z')) ||
3200
772k
       ((c >= '0') && (c <= '9')) || /* !start */
3201
772k
       (c == '_') || (c == ':') ||
3202
772k
       (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3203
772k
       ((c >= 0xC0) && (c <= 0xD6)) ||
3204
772k
       ((c >= 0xD8) && (c <= 0xF6)) ||
3205
772k
       ((c >= 0xF8) && (c <= 0x2FF)) ||
3206
772k
       ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3207
772k
       ((c >= 0x370) && (c <= 0x37D)) ||
3208
772k
       ((c >= 0x37F) && (c <= 0x1FFF)) ||
3209
772k
       ((c >= 0x200C) && (c <= 0x200D)) ||
3210
772k
       ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3211
772k
       ((c >= 0x2070) && (c <= 0x218F)) ||
3212
772k
       ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3213
772k
       ((c >= 0x3001) && (c <= 0xD7FF)) ||
3214
772k
       ((c >= 0xF900) && (c <= 0xFDCF)) ||
3215
772k
       ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3216
772k
       ((c >= 0x10000) && (c <= 0xEFFFF))))
3217
422k
       return(1);
3218
783k
    } else {
3219
25.8k
        if ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3220
25.8k
            (c == '.') || (c == '-') ||
3221
25.8k
      (c == '_') || (c == ':') ||
3222
25.8k
      (IS_COMBINING(c)) ||
3223
25.8k
      (IS_EXTENDER(c)))
3224
10.7k
      return(1);
3225
25.8k
    }
3226
375k
    return(0);
3227
808k
}
3228
3229
static const xmlChar *
3230
113k
xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
3231
113k
    const xmlChar *ret;
3232
113k
    int len = 0, l;
3233
113k
    int c;
3234
113k
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3235
0
                    XML_MAX_TEXT_LENGTH :
3236
113k
                    XML_MAX_NAME_LENGTH;
3237
3238
    /*
3239
     * Handler for more complex cases
3240
     */
3241
113k
    c = CUR_CHAR(l);
3242
113k
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3243
        /*
3244
   * Use the new checks of production [4] [4a] amd [5] of the
3245
   * Update 5 of XML-1.0
3246
   */
3247
104k
  if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3248
104k
      (!(((c >= 'a') && (c <= 'z')) ||
3249
91.5k
         ((c >= 'A') && (c <= 'Z')) ||
3250
91.5k
         (c == '_') || (c == ':') ||
3251
91.5k
         ((c >= 0xC0) && (c <= 0xD6)) ||
3252
91.5k
         ((c >= 0xD8) && (c <= 0xF6)) ||
3253
91.5k
         ((c >= 0xF8) && (c <= 0x2FF)) ||
3254
91.5k
         ((c >= 0x370) && (c <= 0x37D)) ||
3255
91.5k
         ((c >= 0x37F) && (c <= 0x1FFF)) ||
3256
91.5k
         ((c >= 0x200C) && (c <= 0x200D)) ||
3257
91.5k
         ((c >= 0x2070) && (c <= 0x218F)) ||
3258
91.5k
         ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3259
91.5k
         ((c >= 0x3001) && (c <= 0xD7FF)) ||
3260
91.5k
         ((c >= 0xF900) && (c <= 0xFDCF)) ||
3261
91.5k
         ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3262
95.0k
         ((c >= 0x10000) && (c <= 0xEFFFF))))) {
3263
95.0k
      return(NULL);
3264
95.0k
  }
3265
9.60k
  len += l;
3266
9.60k
  NEXTL(l);
3267
9.60k
  c = CUR_CHAR(l);
3268
172k
  while ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3269
172k
         (((c >= 'a') && (c <= 'z')) ||
3270
169k
          ((c >= 'A') && (c <= 'Z')) ||
3271
169k
          ((c >= '0') && (c <= '9')) || /* !start */
3272
169k
          (c == '_') || (c == ':') ||
3273
169k
          (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3274
169k
          ((c >= 0xC0) && (c <= 0xD6)) ||
3275
169k
          ((c >= 0xD8) && (c <= 0xF6)) ||
3276
169k
          ((c >= 0xF8) && (c <= 0x2FF)) ||
3277
169k
          ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3278
169k
          ((c >= 0x370) && (c <= 0x37D)) ||
3279
169k
          ((c >= 0x37F) && (c <= 0x1FFF)) ||
3280
169k
          ((c >= 0x200C) && (c <= 0x200D)) ||
3281
169k
          ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3282
169k
          ((c >= 0x2070) && (c <= 0x218F)) ||
3283
169k
          ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3284
169k
          ((c >= 0x3001) && (c <= 0xD7FF)) ||
3285
169k
          ((c >= 0xF900) && (c <= 0xFDCF)) ||
3286
169k
          ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3287
169k
          ((c >= 0x10000) && (c <= 0xEFFFF))
3288
169k
    )) {
3289
163k
            if (len <= INT_MAX - l)
3290
163k
          len += l;
3291
163k
      NEXTL(l);
3292
163k
      c = CUR_CHAR(l);
3293
163k
  }
3294
9.60k
    } else {
3295
9.12k
  if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3296
9.12k
      (!IS_LETTER(c) && (c != '_') &&
3297
7.95k
       (c != ':'))) {
3298
5.87k
      return(NULL);
3299
5.87k
  }
3300
3.25k
  len += l;
3301
3.25k
  NEXTL(l);
3302
3.25k
  c = CUR_CHAR(l);
3303
3304
12.9k
  while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
3305
12.9k
         ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3306
12.0k
    (c == '.') || (c == '-') ||
3307
12.0k
    (c == '_') || (c == ':') ||
3308
12.0k
    (IS_COMBINING(c)) ||
3309
12.0k
    (IS_EXTENDER(c)))) {
3310
9.70k
            if (len <= INT_MAX - l)
3311
9.70k
          len += l;
3312
9.70k
      NEXTL(l);
3313
9.70k
      c = CUR_CHAR(l);
3314
9.70k
  }
3315
3.25k
    }
3316
12.8k
    if (len > maxLength) {
3317
0
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
3318
0
        return(NULL);
3319
0
    }
3320
12.8k
    if (ctxt->input->cur - ctxt->input->base < len) {
3321
        /*
3322
         * There were a couple of bugs where PERefs lead to to a change
3323
         * of the buffer. Check the buffer size to avoid passing an invalid
3324
         * pointer to xmlDictLookup.
3325
         */
3326
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
3327
0
                    "unexpected change of input buffer");
3328
0
        return (NULL);
3329
0
    }
3330
12.8k
    if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r'))
3331
194
        ret = xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len);
3332
12.6k
    else
3333
12.6k
        ret = xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len);
3334
12.8k
    if (ret == NULL)
3335
0
        xmlErrMemory(ctxt);
3336
12.8k
    return(ret);
3337
12.8k
}
3338
3339
/**
3340
 * xmlParseName:
3341
 * @ctxt:  an XML parser context
3342
 *
3343
 * DEPRECATED: Internal function, don't use.
3344
 *
3345
 * parse an XML name.
3346
 *
3347
 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3348
 *                  CombiningChar | Extender
3349
 *
3350
 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3351
 *
3352
 * [6] Names ::= Name (#x20 Name)*
3353
 *
3354
 * Returns the Name parsed or NULL
3355
 */
3356
3357
const xmlChar *
3358
457k
xmlParseName(xmlParserCtxtPtr ctxt) {
3359
457k
    const xmlChar *in;
3360
457k
    const xmlChar *ret;
3361
457k
    size_t count = 0;
3362
457k
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3363
0
                       XML_MAX_TEXT_LENGTH :
3364
457k
                       XML_MAX_NAME_LENGTH;
3365
3366
457k
    GROW;
3367
3368
    /*
3369
     * Accelerator for simple ASCII names
3370
     */
3371
457k
    in = ctxt->input->cur;
3372
457k
    if (((*in >= 0x61) && (*in <= 0x7A)) ||
3373
457k
  ((*in >= 0x41) && (*in <= 0x5A)) ||
3374
457k
  (*in == '_') || (*in == ':')) {
3375
349k
  in++;
3376
670k
  while (((*in >= 0x61) && (*in <= 0x7A)) ||
3377
670k
         ((*in >= 0x41) && (*in <= 0x5A)) ||
3378
670k
         ((*in >= 0x30) && (*in <= 0x39)) ||
3379
670k
         (*in == '_') || (*in == '-') ||
3380
670k
         (*in == ':') || (*in == '.'))
3381
321k
      in++;
3382
349k
  if ((*in > 0) && (*in < 0x80)) {
3383
343k
      count = in - ctxt->input->cur;
3384
343k
            if (count > maxLength) {
3385
0
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
3386
0
                return(NULL);
3387
0
            }
3388
343k
      ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
3389
343k
      ctxt->input->cur = in;
3390
343k
      ctxt->input->col += count;
3391
343k
      if (ret == NULL)
3392
0
          xmlErrMemory(ctxt);
3393
343k
      return(ret);
3394
343k
  }
3395
349k
    }
3396
    /* accelerator for special cases */
3397
113k
    return(xmlParseNameComplex(ctxt));
3398
457k
}
3399
3400
static xmlHashedString
3401
98.8k
xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
3402
98.8k
    xmlHashedString ret;
3403
98.8k
    int len = 0, l;
3404
98.8k
    int c;
3405
98.8k
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3406
0
                    XML_MAX_TEXT_LENGTH :
3407
98.8k
                    XML_MAX_NAME_LENGTH;
3408
98.8k
    size_t startPosition = 0;
3409
3410
98.8k
    ret.name = NULL;
3411
98.8k
    ret.hashValue = 0;
3412
3413
    /*
3414
     * Handler for more complex cases
3415
     */
3416
98.8k
    startPosition = CUR_PTR - BASE_PTR;
3417
98.8k
    c = CUR_CHAR(l);
3418
98.8k
    if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3419
98.8k
  (!xmlIsNameStartChar(ctxt, c) || (c == ':'))) {
3420
92.3k
  return(ret);
3421
92.3k
    }
3422
3423
77.3k
    while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
3424
77.3k
     (xmlIsNameChar(ctxt, c) && (c != ':'))) {
3425
70.8k
        if (len <= INT_MAX - l)
3426
70.8k
      len += l;
3427
70.8k
  NEXTL(l);
3428
70.8k
  c = CUR_CHAR(l);
3429
70.8k
    }
3430
6.45k
    if (len > maxLength) {
3431
0
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3432
0
        return(ret);
3433
0
    }
3434
6.45k
    ret = xmlDictLookupHashed(ctxt->dict, (BASE_PTR + startPosition), len);
3435
6.45k
    if (ret.name == NULL)
3436
0
        xmlErrMemory(ctxt);
3437
6.45k
    return(ret);
3438
6.45k
}
3439
3440
/**
3441
 * xmlParseNCName:
3442
 * @ctxt:  an XML parser context
3443
 * @len:  length of the string parsed
3444
 *
3445
 * parse an XML name.
3446
 *
3447
 * [4NS] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
3448
 *                      CombiningChar | Extender
3449
 *
3450
 * [5NS] NCName ::= (Letter | '_') (NCNameChar)*
3451
 *
3452
 * Returns the Name parsed or NULL
3453
 */
3454
3455
static xmlHashedString
3456
189k
xmlParseNCName(xmlParserCtxtPtr ctxt) {
3457
189k
    const xmlChar *in, *e;
3458
189k
    xmlHashedString ret;
3459
189k
    size_t count = 0;
3460
189k
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3461
0
                       XML_MAX_TEXT_LENGTH :
3462
189k
                       XML_MAX_NAME_LENGTH;
3463
3464
189k
    ret.name = NULL;
3465
3466
    /*
3467
     * Accelerator for simple ASCII names
3468
     */
3469
189k
    in = ctxt->input->cur;
3470
189k
    e = ctxt->input->end;
3471
189k
    if ((((*in >= 0x61) && (*in <= 0x7A)) ||
3472
189k
   ((*in >= 0x41) && (*in <= 0x5A)) ||
3473
189k
   (*in == '_')) && (in < e)) {
3474
92.2k
  in++;
3475
163k
  while ((((*in >= 0x61) && (*in <= 0x7A)) ||
3476
163k
          ((*in >= 0x41) && (*in <= 0x5A)) ||
3477
163k
          ((*in >= 0x30) && (*in <= 0x39)) ||
3478
163k
          (*in == '_') || (*in == '-') ||
3479
163k
          (*in == '.')) && (in < e))
3480
71.4k
      in++;
3481
92.2k
  if (in >= e)
3482
33
      goto complex;
3483
92.2k
  if ((*in > 0) && (*in < 0x80)) {
3484
90.9k
      count = in - ctxt->input->cur;
3485
90.9k
            if (count > maxLength) {
3486
0
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3487
0
                return(ret);
3488
0
            }
3489
90.9k
      ret = xmlDictLookupHashed(ctxt->dict, ctxt->input->cur, count);
3490
90.9k
      ctxt->input->cur = in;
3491
90.9k
      ctxt->input->col += count;
3492
90.9k
      if (ret.name == NULL) {
3493
0
          xmlErrMemory(ctxt);
3494
0
      }
3495
90.9k
      return(ret);
3496
90.9k
  }
3497
92.2k
    }
3498
98.8k
complex:
3499
98.8k
    return(xmlParseNCNameComplex(ctxt));
3500
189k
}
3501
3502
/**
3503
 * xmlParseNameAndCompare:
3504
 * @ctxt:  an XML parser context
3505
 *
3506
 * parse an XML name and compares for match
3507
 * (specialized for endtag parsing)
3508
 *
3509
 * Returns NULL for an illegal name, (xmlChar*) 1 for success
3510
 * and the name for mismatch
3511
 */
3512
3513
static const xmlChar *
3514
14.0k
xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) {
3515
14.0k
    register const xmlChar *cmp = other;
3516
14.0k
    register const xmlChar *in;
3517
14.0k
    const xmlChar *ret;
3518
3519
14.0k
    GROW;
3520
3521
14.0k
    in = ctxt->input->cur;
3522
29.5k
    while (*in != 0 && *in == *cmp) {
3523
15.5k
  ++in;
3524
15.5k
  ++cmp;
3525
15.5k
    }
3526
14.0k
    if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
3527
  /* success */
3528
2.39k
  ctxt->input->col += in - ctxt->input->cur;
3529
2.39k
  ctxt->input->cur = in;
3530
2.39k
  return (const xmlChar*) 1;
3531
2.39k
    }
3532
    /* failure (or end of input buffer), check with full function */
3533
11.6k
    ret = xmlParseName (ctxt);
3534
    /* strings coming from the dictionary direct compare possible */
3535
11.6k
    if (ret == other) {
3536
702
  return (const xmlChar*) 1;
3537
702
    }
3538
10.9k
    return ret;
3539
11.6k
}
3540
3541
/**
3542
 * xmlParseStringName:
3543
 * @ctxt:  an XML parser context
3544
 * @str:  a pointer to the string pointer (IN/OUT)
3545
 *
3546
 * parse an XML name.
3547
 *
3548
 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3549
 *                  CombiningChar | Extender
3550
 *
3551
 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3552
 *
3553
 * [6] Names ::= Name (#x20 Name)*
3554
 *
3555
 * Returns the Name parsed or NULL. The @str pointer
3556
 * is updated to the current location in the string.
3557
 */
3558
3559
static xmlChar *
3560
333k
xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
3561
333k
    xmlChar buf[XML_MAX_NAMELEN + 5];
3562
333k
    xmlChar *ret;
3563
333k
    const xmlChar *cur = *str;
3564
333k
    int len = 0, l;
3565
333k
    int c;
3566
333k
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3567
0
                    XML_MAX_TEXT_LENGTH :
3568
333k
                    XML_MAX_NAME_LENGTH;
3569
3570
333k
    c = CUR_SCHAR(cur, l);
3571
333k
    if (!xmlIsNameStartChar(ctxt, c)) {
3572
1.74k
  return(NULL);
3573
1.74k
    }
3574
3575
331k
    COPY_BUF(buf, len, c);
3576
331k
    cur += l;
3577
331k
    c = CUR_SCHAR(cur, l);
3578
520k
    while (xmlIsNameChar(ctxt, c)) {
3579
189k
  COPY_BUF(buf, len, c);
3580
189k
  cur += l;
3581
189k
  c = CUR_SCHAR(cur, l);
3582
189k
  if (len >= XML_MAX_NAMELEN) { /* test bigentname.xml */
3583
      /*
3584
       * Okay someone managed to make a huge name, so he's ready to pay
3585
       * for the processing speed.
3586
       */
3587
427
      xmlChar *buffer;
3588
427
      int max = len * 2;
3589
3590
427
      buffer = (xmlChar *) xmlMallocAtomic(max);
3591
427
      if (buffer == NULL) {
3592
0
          xmlErrMemory(ctxt);
3593
0
    return(NULL);
3594
0
      }
3595
427
      memcpy(buffer, buf, len);
3596
22.3k
      while (xmlIsNameChar(ctxt, c)) {
3597
21.9k
    if (len + 10 > max) {
3598
202
        xmlChar *tmp;
3599
3600
202
        max *= 2;
3601
202
        tmp = (xmlChar *) xmlRealloc(buffer, max);
3602
202
        if (tmp == NULL) {
3603
0
      xmlErrMemory(ctxt);
3604
0
      xmlFree(buffer);
3605
0
      return(NULL);
3606
0
        }
3607
202
        buffer = tmp;
3608
202
    }
3609
21.9k
    COPY_BUF(buffer, len, c);
3610
21.9k
    cur += l;
3611
21.9k
    c = CUR_SCHAR(cur, l);
3612
21.9k
                if (len > maxLength) {
3613
0
                    xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3614
0
                    xmlFree(buffer);
3615
0
                    return(NULL);
3616
0
                }
3617
21.9k
      }
3618
427
      buffer[len] = 0;
3619
427
      *str = cur;
3620
427
      return(buffer);
3621
427
  }
3622
189k
    }
3623
330k
    if (len > maxLength) {
3624
0
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3625
0
        return(NULL);
3626
0
    }
3627
330k
    *str = cur;
3628
330k
    ret = xmlStrndup(buf, len);
3629
330k
    if (ret == NULL)
3630
0
        xmlErrMemory(ctxt);
3631
330k
    return(ret);
3632
330k
}
3633
3634
/**
3635
 * xmlParseNmtoken:
3636
 * @ctxt:  an XML parser context
3637
 *
3638
 * DEPRECATED: Internal function, don't use.
3639
 *
3640
 * parse an XML Nmtoken.
3641
 *
3642
 * [7] Nmtoken ::= (NameChar)+
3643
 *
3644
 * [8] Nmtokens ::= Nmtoken (#x20 Nmtoken)*
3645
 *
3646
 * Returns the Nmtoken parsed or NULL
3647
 */
3648
3649
xmlChar *
3650
39.3k
xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
3651
39.3k
    xmlChar buf[XML_MAX_NAMELEN + 5];
3652
39.3k
    xmlChar *ret;
3653
39.3k
    int len = 0, l;
3654
39.3k
    int c;
3655
39.3k
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3656
0
                    XML_MAX_TEXT_LENGTH :
3657
39.3k
                    XML_MAX_NAME_LENGTH;
3658
3659
39.3k
    c = CUR_CHAR(l);
3660
3661
114k
    while (xmlIsNameChar(ctxt, c)) {
3662
76.2k
  COPY_BUF(buf, len, c);
3663
76.2k
  NEXTL(l);
3664
76.2k
  c = CUR_CHAR(l);
3665
76.2k
  if (len >= XML_MAX_NAMELEN) {
3666
      /*
3667
       * Okay someone managed to make a huge token, so he's ready to pay
3668
       * for the processing speed.
3669
       */
3670
785
      xmlChar *buffer;
3671
785
      int max = len * 2;
3672
3673
785
      buffer = (xmlChar *) xmlMallocAtomic(max);
3674
785
      if (buffer == NULL) {
3675
0
          xmlErrMemory(ctxt);
3676
0
    return(NULL);
3677
0
      }
3678
785
      memcpy(buffer, buf, len);
3679
74.9k
      while (xmlIsNameChar(ctxt, c)) {
3680
74.1k
    if (len + 10 > max) {
3681
908
        xmlChar *tmp;
3682
3683
908
        max *= 2;
3684
908
        tmp = (xmlChar *) xmlRealloc(buffer, max);
3685
908
        if (tmp == NULL) {
3686
0
      xmlErrMemory(ctxt);
3687
0
      xmlFree(buffer);
3688
0
      return(NULL);
3689
0
        }
3690
908
        buffer = tmp;
3691
908
    }
3692
74.1k
    COPY_BUF(buffer, len, c);
3693
74.1k
                if (len > maxLength) {
3694
0
                    xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
3695
0
                    xmlFree(buffer);
3696
0
                    return(NULL);
3697
0
                }
3698
74.1k
    NEXTL(l);
3699
74.1k
    c = CUR_CHAR(l);
3700
74.1k
      }
3701
785
      buffer[len] = 0;
3702
785
      return(buffer);
3703
785
  }
3704
76.2k
    }
3705
38.5k
    if (len == 0)
3706
1.53k
        return(NULL);
3707
36.9k
    if (len > maxLength) {
3708
0
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
3709
0
        return(NULL);
3710
0
    }
3711
36.9k
    ret = xmlStrndup(buf, len);
3712
36.9k
    if (ret == NULL)
3713
0
        xmlErrMemory(ctxt);
3714
36.9k
    return(ret);
3715
36.9k
}
3716
3717
/**
3718
 * xmlExpandPEsInEntityValue:
3719
 * @ctxt:  parser context
3720
 * @buf:  string buffer
3721
 * @str:  entity value
3722
 * @length:  size of entity value
3723
 * @depth:  nesting depth
3724
 *
3725
 * Validate an entity value and expand parameter entities.
3726
 */
3727
static void
3728
xmlExpandPEsInEntityValue(xmlParserCtxtPtr ctxt, xmlSBuf *buf,
3729
13.2k
                          const xmlChar *str, int length, int depth) {
3730
13.2k
    int maxDepth = (ctxt->options & XML_PARSE_HUGE) ? 40 : 20;
3731
13.2k
    const xmlChar *end, *chunk;
3732
13.2k
    int c, l;
3733
3734
13.2k
    if (str == NULL)
3735
0
        return;
3736
3737
13.2k
    depth += 1;
3738
13.2k
    if (depth > maxDepth) {
3739
0
  xmlFatalErrMsg(ctxt, XML_ERR_RESOURCE_LIMIT,
3740
0
                       "Maximum entity nesting depth exceeded");
3741
0
  return;
3742
0
    }
3743
3744
13.2k
    end = str + length;
3745
13.2k
    chunk = str;
3746
3747
318k
    while ((str < end) && (!PARSER_STOPPED(ctxt))) {
3748
311k
        c = *str;
3749
3750
311k
        if (c >= 0x80) {
3751
92.6k
            l = xmlUTF8MultibyteLen(ctxt, str,
3752
92.6k
                    "invalid character in entity value\n");
3753
92.6k
            if (l == 0) {
3754
4.50k
                if (chunk < str)
3755
1.20k
                    xmlSBufAddString(buf, chunk, str - chunk);
3756
4.50k
                xmlSBufAddReplChar(buf);
3757
4.50k
                str += 1;
3758
4.50k
                chunk = str;
3759
88.1k
            } else {
3760
88.1k
                str += l;
3761
88.1k
            }
3762
219k
        } else if (c == '&') {
3763
19.3k
            if (str[1] == '#') {
3764
5.43k
                if (chunk < str)
3765
2.73k
                    xmlSBufAddString(buf, chunk, str - chunk);
3766
3767
5.43k
                c = xmlParseStringCharRef(ctxt, &str);
3768
5.43k
                if (c == 0)
3769
2.61k
                    return;
3770
3771
2.82k
                xmlSBufAddChar(buf, c);
3772
3773
2.82k
                chunk = str;
3774
13.8k
            } else {
3775
13.8k
                xmlChar *name;
3776
3777
                /*
3778
                 * General entity references are checked for
3779
                 * syntactic validity.
3780
                 */
3781
13.8k
                str++;
3782
13.8k
                name = xmlParseStringName(ctxt, &str);
3783
3784
13.8k
                if ((name == NULL) || (*str++ != ';')) {
3785
1.21k
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_CHAR_ERROR,
3786
1.21k
                            "EntityValue: '&' forbidden except for entities "
3787
1.21k
                            "references\n");
3788
1.21k
                    xmlFree(name);
3789
1.21k
                    return;
3790
1.21k
                }
3791
3792
12.6k
                xmlFree(name);
3793
12.6k
            }
3794
199k
        } else if (c == '%') {
3795
2.44k
            xmlEntityPtr ent;
3796
3797
2.44k
            if (chunk < str)
3798
1.61k
                xmlSBufAddString(buf, chunk, str - chunk);
3799
3800
2.44k
            ent = xmlParseStringPEReference(ctxt, &str);
3801
2.44k
            if (ent == NULL)
3802
2.21k
                return;
3803
3804
229
            if (!PARSER_EXTERNAL(ctxt)) {
3805
229
                xmlFatalErr(ctxt, XML_ERR_ENTITY_PE_INTERNAL, NULL);
3806
229
                return;
3807
229
            }
3808
3809
0
            if (ent->content == NULL) {
3810
                /*
3811
                 * Note: external parsed entities will not be loaded,
3812
                 * it is not required for a non-validating parser to
3813
                 * complete external PEReferences coming from the
3814
                 * internal subset
3815
                 */
3816
0
                if (((ctxt->options & XML_PARSE_NO_XXE) == 0) &&
3817
0
                    ((ctxt->replaceEntities) ||
3818
0
                     (ctxt->validate))) {
3819
0
                    xmlLoadEntityContent(ctxt, ent);
3820
0
                } else {
3821
0
                    xmlWarningMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
3822
0
                                  "not validating will not read content for "
3823
0
                                  "PE entity %s\n", ent->name, NULL);
3824
0
                }
3825
0
            }
3826
3827
            /*
3828
             * TODO: Skip if ent->content is still NULL.
3829
             */
3830
3831
0
            if (xmlParserEntityCheck(ctxt, ent->length))
3832
0
                return;
3833
3834
0
            if (ent->flags & XML_ENT_EXPANDING) {
3835
0
                xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
3836
0
                xmlHaltParser(ctxt);
3837
0
                return;
3838
0
            }
3839
3840
0
            ent->flags |= XML_ENT_EXPANDING;
3841
0
            xmlExpandPEsInEntityValue(ctxt, buf, ent->content, ent->length,
3842
0
                                      depth);
3843
0
            ent->flags &= ~XML_ENT_EXPANDING;
3844
3845
0
            chunk = str;
3846
197k
        } else {
3847
            /* Normal ASCII char */
3848
197k
            if (!IS_BYTE_CHAR(c)) {
3849
2.75k
                xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
3850
2.75k
                        "invalid character in entity value\n");
3851
2.75k
                if (chunk < str)
3852
417
                    xmlSBufAddString(buf, chunk, str - chunk);
3853
2.75k
                xmlSBufAddReplChar(buf);
3854
2.75k
                str += 1;
3855
2.75k
                chunk = str;
3856
194k
            } else {
3857
194k
                str += 1;
3858
194k
            }
3859
197k
        }
3860
311k
    }
3861
3862
7.01k
    if (chunk < str)
3863
6.40k
        xmlSBufAddString(buf, chunk, str - chunk);
3864
3865
7.01k
    return;
3866
13.2k
}
3867
3868
/**
3869
 * xmlParseEntityValue:
3870
 * @ctxt:  an XML parser context
3871
 * @orig:  if non-NULL store a copy of the original entity value
3872
 *
3873
 * DEPRECATED: Internal function, don't use.
3874
 *
3875
 * parse a value for ENTITY declarations
3876
 *
3877
 * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
3878
 *                 "'" ([^%&'] | PEReference | Reference)* "'"
3879
 *
3880
 * Returns the EntityValue parsed with reference substituted or NULL
3881
 */
3882
xmlChar *
3883
14.2k
xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
3884
14.2k
    unsigned maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3885
0
                         XML_MAX_HUGE_LENGTH :
3886
14.2k
                         XML_MAX_TEXT_LENGTH;
3887
14.2k
    xmlSBuf buf;
3888
14.2k
    const xmlChar *start;
3889
14.2k
    int quote, length;
3890
3891
14.2k
    xmlSBufInit(&buf, maxLength);
3892
3893
14.2k
    GROW;
3894
3895
14.2k
    quote = CUR;
3896
14.2k
    if ((quote != '"') && (quote != '\'')) {
3897
0
  xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
3898
0
  return(NULL);
3899
0
    }
3900
14.2k
    CUR_PTR++;
3901
3902
14.2k
    length = 0;
3903
3904
    /*
3905
     * Copy raw content of the entity into a buffer
3906
     */
3907
594k
    while (1) {
3908
594k
        int c;
3909
3910
594k
        if (PARSER_STOPPED(ctxt))
3911
0
            goto error;
3912
3913
594k
        if (CUR_PTR >= ctxt->input->end) {
3914
996
            xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL);
3915
996
            goto error;
3916
996
        }
3917
3918
593k
        c = CUR;
3919
3920
593k
        if (c == 0) {
3921
2
            xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
3922
2
                    "invalid character in entity value\n");
3923
2
            goto error;
3924
2
        }
3925
593k
        if (c == quote)
3926
13.2k
            break;
3927
580k
        NEXTL(1);
3928
580k
        length += 1;
3929
3930
        /*
3931
         * TODO: Check growth threshold
3932
         */
3933
580k
        if (ctxt->input->end - CUR_PTR < 10)
3934
28.2k
            GROW;
3935
580k
    }
3936
3937
13.2k
    start = CUR_PTR - length;
3938
3939
13.2k
    if (orig != NULL) {
3940
13.2k
        *orig = xmlStrndup(start, length);
3941
13.2k
        if (*orig == NULL)
3942
0
            xmlErrMemory(ctxt);
3943
13.2k
    }
3944
3945
13.2k
    xmlExpandPEsInEntityValue(ctxt, &buf, start, length, ctxt->inputNr);
3946
3947
13.2k
    NEXTL(1);
3948
3949
13.2k
    return(xmlSBufFinish(&buf, NULL, ctxt, "entity length too long"));
3950
3951
998
error:
3952
998
    xmlSBufCleanup(&buf, ctxt, "entity length too long");
3953
998
    return(NULL);
3954
14.2k
}
3955
3956
/**
3957
 * xmlCheckEntityInAttValue:
3958
 * @ctxt:  parser context
3959
 * @pent:  entity
3960
 * @depth:  nesting depth
3961
 *
3962
 * Check an entity reference in an attribute value for validity
3963
 * without expanding it.
3964
 */
3965
static void
3966
1.14k
xmlCheckEntityInAttValue(xmlParserCtxtPtr ctxt, xmlEntityPtr pent, int depth) {
3967
1.14k
    int maxDepth = (ctxt->options & XML_PARSE_HUGE) ? 40 : 20;
3968
1.14k
    const xmlChar *str;
3969
1.14k
    unsigned long expandedSize = pent->length;
3970
1.14k
    int c, flags;
3971
3972
1.14k
    depth += 1;
3973
1.14k
    if (depth > maxDepth) {
3974
0
  xmlFatalErrMsg(ctxt, XML_ERR_RESOURCE_LIMIT,
3975
0
                       "Maximum entity nesting depth exceeded");
3976
0
  return;
3977
0
    }
3978
3979
1.14k
    if (pent->flags & XML_ENT_EXPANDING) {
3980
15
        xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
3981
15
        xmlHaltParser(ctxt);
3982
15
        return;
3983
15
    }
3984
3985
    /*
3986
     * If we're parsing a default attribute value in DTD content,
3987
     * the entity might reference other entities which weren't
3988
     * defined yet, so the check isn't reliable.
3989
     */
3990
1.12k
    if (ctxt->inSubset == 0)
3991
1.08k
        flags = XML_ENT_CHECKED | XML_ENT_VALIDATED;
3992
40
    else
3993
40
        flags = XML_ENT_VALIDATED;
3994
3995
1.12k
    str = pent->content;
3996
1.12k
    if (str == NULL)
3997
0
        goto done;
3998
3999
    /*
4000
     * Note that entity values are already validated. We only check
4001
     * for illegal less-than signs and compute the expanded size
4002
     * of the entity. No special handling for multi-byte characters
4003
     * is needed.
4004
     */
4005
68.7k
    while (!PARSER_STOPPED(ctxt)) {
4006
68.7k
        c = *str;
4007
4008
68.7k
  if (c != '&') {
4009
58.3k
            if (c == 0)
4010
1.09k
                break;
4011
4012
57.2k
            if (c == '<')
4013
483
                xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
4014
483
                        "'<' in entity '%s' is not allowed in attributes "
4015
483
                        "values\n", pent->name);
4016
4017
57.2k
            str += 1;
4018
57.2k
        } else if (str[1] == '#') {
4019
341
            int val;
4020
4021
341
      val = xmlParseStringCharRef(ctxt, &str);
4022
341
      if (val == 0) {
4023
3
                pent->content[0] = 0;
4024
3
                break;
4025
3
            }
4026
10.1k
  } else {
4027
10.1k
            xmlChar *name;
4028
10.1k
            xmlEntityPtr ent;
4029
4030
10.1k
      name = xmlParseStringEntityRef(ctxt, &str);
4031
10.1k
      if (name == NULL) {
4032
4
                pent->content[0] = 0;
4033
4
                break;
4034
4
            }
4035
4036
10.0k
            ent = xmlLookupGeneralEntity(ctxt, name, /* inAttr */ 1);
4037
10.0k
            xmlFree(name);
4038
4039
10.0k
            if ((ent != NULL) &&
4040
10.0k
                (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
4041
8.53k
                if ((ent->flags & flags) != flags) {
4042
410
                    pent->flags |= XML_ENT_EXPANDING;
4043
410
                    xmlCheckEntityInAttValue(ctxt, ent, depth);
4044
410
                    pent->flags &= ~XML_ENT_EXPANDING;
4045
410
                }
4046
4047
8.53k
                xmlSaturatedAdd(&expandedSize, ent->expandedSize);
4048
8.53k
                xmlSaturatedAdd(&expandedSize, XML_ENT_FIXED_COST);
4049
8.53k
            }
4050
10.0k
        }
4051
68.7k
    }
4052
4053
1.12k
done:
4054
1.12k
    if (ctxt->inSubset == 0)
4055
1.08k
        pent->expandedSize = expandedSize;
4056
4057
1.12k
    pent->flags |= flags;
4058
1.12k
}
4059
4060
/**
4061
 * xmlExpandEntityInAttValue:
4062
 * @ctxt:  parser context
4063
 * @buf:  string buffer
4064
 * @str:  entity or attribute value
4065
 * @pent:  entity for entity value, NULL for attribute values
4066
 * @normalize:  whether to collapse whitespace
4067
 * @inSpace:  whitespace state
4068
 * @depth:  nesting depth
4069
 * @check:  whether to check for amplification
4070
 *
4071
 * Expand general entity references in an entity or attribute value.
4072
 * Perform attribute value normalization.
4073
 */
4074
static void
4075
xmlExpandEntityInAttValue(xmlParserCtxtPtr ctxt, xmlSBuf *buf,
4076
                          const xmlChar *str, xmlEntityPtr pent, int normalize,
4077
262k
                          int *inSpace, int depth, int check) {
4078
262k
    int maxDepth = (ctxt->options & XML_PARSE_HUGE) ? 40 : 20;
4079
262k
    int c, chunkSize;
4080
4081
262k
    if (str == NULL)
4082
0
        return;
4083
4084
262k
    depth += 1;
4085
262k
    if (depth > maxDepth) {
4086
0
  xmlFatalErrMsg(ctxt, XML_ERR_RESOURCE_LIMIT,
4087
0
                       "Maximum entity nesting depth exceeded");
4088
0
  return;
4089
0
    }
4090
4091
262k
    if (pent != NULL) {
4092
229k
        if (pent->flags & XML_ENT_EXPANDING) {
4093
0
            xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
4094
0
            xmlHaltParser(ctxt);
4095
0
            return;
4096
0
        }
4097
4098
229k
        if (check) {
4099
0
            if (xmlParserEntityCheck(ctxt, pent->length))
4100
0
                return;
4101
0
        }
4102
229k
    }
4103
4104
262k
    chunkSize = 0;
4105
4106
    /*
4107
     * Note that entity values are already validated. No special
4108
     * handling for multi-byte characters is needed.
4109
     */
4110
41.3M
    while (!PARSER_STOPPED(ctxt)) {
4111
41.3M
        c = *str;
4112
4113
41.3M
  if (c != '&') {
4114
41.0M
            if (c == 0)
4115
255k
                break;
4116
4117
            /*
4118
             * If this function is called without an entity, it is used to
4119
             * expand entities in an attribute content where less-than was
4120
             * already unscaped and is allowed.
4121
             */
4122
40.7M
            if ((pent != NULL) && (c == '<')) {
4123
6.44k
                xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
4124
6.44k
                        "'<' in entity '%s' is not allowed in attributes "
4125
6.44k
                        "values\n", pent->name);
4126
6.44k
                break;
4127
6.44k
            }
4128
4129
40.7M
            if (c <= 0x20) {
4130
1.77M
                if ((normalize) && (*inSpace)) {
4131
                    /* Skip char */
4132
0
                    if (chunkSize > 0) {
4133
0
                        xmlSBufAddString(buf, str - chunkSize, chunkSize);
4134
0
                        chunkSize = 0;
4135
0
                    }
4136
1.77M
                } else if (c < 0x20) {
4137
299k
                    if (chunkSize > 0) {
4138
296k
                        xmlSBufAddString(buf, str - chunkSize, chunkSize);
4139
296k
                        chunkSize = 0;
4140
296k
                    }
4141
4142
299k
                    xmlSBufAddCString(buf, " ", 1);
4143
1.47M
                } else {
4144
1.47M
                    chunkSize += 1;
4145
1.47M
                }
4146
4147
1.77M
                *inSpace = 1;
4148
38.9M
            } else {
4149
38.9M
                chunkSize += 1;
4150
38.9M
                *inSpace = 0;
4151
38.9M
            }
4152
4153
40.7M
            str += 1;
4154
40.7M
        } else if (str[1] == '#') {
4155
11.1k
            int val;
4156
4157
11.1k
            if (chunkSize > 0) {
4158
7.84k
                xmlSBufAddString(buf, str - chunkSize, chunkSize);
4159
7.84k
                chunkSize = 0;
4160
7.84k
            }
4161
4162
11.1k
      val = xmlParseStringCharRef(ctxt, &str);
4163
11.1k
      if (val == 0) {
4164
0
                if (pent != NULL)
4165
0
                    pent->content[0] = 0;
4166
0
                break;
4167
0
            }
4168
4169
11.1k
            if (val == ' ') {
4170
1.10k
                if ((!normalize) || (!*inSpace))
4171
1.10k
                    xmlSBufAddCString(buf, " ", 1);
4172
1.10k
                *inSpace = 1;
4173
10.0k
            } else {
4174
10.0k
                xmlSBufAddChar(buf, val);
4175
10.0k
                *inSpace = 0;
4176
10.0k
            }
4177
306k
  } else {
4178
306k
            xmlChar *name;
4179
306k
            xmlEntityPtr ent;
4180
4181
306k
            if (chunkSize > 0) {
4182
125k
                xmlSBufAddString(buf, str - chunkSize, chunkSize);
4183
125k
                chunkSize = 0;
4184
125k
            }
4185
4186
306k
      name = xmlParseStringEntityRef(ctxt, &str);
4187
306k
            if (name == NULL) {
4188
0
                if (pent != NULL)
4189
0
                    pent->content[0] = 0;
4190
0
                break;
4191
0
            }
4192
4193
306k
            ent = xmlLookupGeneralEntity(ctxt, name, /* inAttr */ 1);
4194
306k
            xmlFree(name);
4195
4196
306k
      if ((ent != NULL) &&
4197
306k
    (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
4198
33.5k
    if (ent->content == NULL) {
4199
0
        xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
4200
0
          "predefined entity has no content\n");
4201
0
                    break;
4202
0
                }
4203
4204
33.5k
                xmlSBufAddString(buf, ent->content, ent->length);
4205
4206
33.5k
                *inSpace = 0;
4207
273k
      } else if ((ent != NULL) && (ent->content != NULL)) {
4208
229k
                if (pent != NULL)
4209
220k
                    pent->flags |= XML_ENT_EXPANDING;
4210
229k
    xmlExpandEntityInAttValue(ctxt, buf, ent->content, ent,
4211
229k
                                          normalize, inSpace, depth, check);
4212
229k
                if (pent != NULL)
4213
220k
                    pent->flags &= ~XML_ENT_EXPANDING;
4214
229k
      }
4215
306k
        }
4216
41.3M
    }
4217
4218
262k
    if (chunkSize > 0)
4219
259k
        xmlSBufAddString(buf, str - chunkSize, chunkSize);
4220
4221
262k
    return;
4222
262k
}
4223
4224
/**
4225
 * xmlExpandEntitiesInAttValue:
4226
 * @ctxt:  parser context
4227
 * @str:  entity or attribute value
4228
 * @normalize:  whether to collapse whitespace
4229
 *
4230
 * Expand general entity references in an entity or attribute value.
4231
 * Perform attribute value normalization.
4232
 *
4233
 * Returns the expanded attribtue value.
4234
 */
4235
xmlChar *
4236
xmlExpandEntitiesInAttValue(xmlParserCtxtPtr ctxt, const xmlChar *str,
4237
32.5k
                            int normalize) {
4238
32.5k
    unsigned maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4239
0
                         XML_MAX_HUGE_LENGTH :
4240
32.5k
                         XML_MAX_TEXT_LENGTH;
4241
32.5k
    xmlSBuf buf;
4242
32.5k
    int inSpace = 1;
4243
4244
32.5k
    xmlSBufInit(&buf, maxLength);
4245
4246
32.5k
    xmlExpandEntityInAttValue(ctxt, &buf, str, NULL, normalize, &inSpace,
4247
32.5k
                              ctxt->inputNr, /* check */ 0);
4248
4249
32.5k
    if ((normalize) && (inSpace) && (buf.size > 0))
4250
0
        buf.size--;
4251
4252
32.5k
    return(xmlSBufFinish(&buf, NULL, ctxt, "AttValue length too long"));
4253
32.5k
}
4254
4255
/**
4256
 * xmlParseAttValueInternal:
4257
 * @ctxt:  an XML parser context
4258
 * @len:  attribute len result
4259
 * @alloc:  whether the attribute was reallocated as a new string
4260
 * @normalize:  if 1 then further non-CDATA normalization must be done
4261
 *
4262
 * parse a value for an attribute.
4263
 * NOTE: if no normalization is needed, the routine will return pointers
4264
 *       directly from the data buffer.
4265
 *
4266
 * 3.3.3 Attribute-Value Normalization:
4267
 * Before the value of an attribute is passed to the application or
4268
 * checked for validity, the XML processor must normalize it as follows:
4269
 * - a character reference is processed by appending the referenced
4270
 *   character to the attribute value
4271
 * - an entity reference is processed by recursively processing the
4272
 *   replacement text of the entity
4273
 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
4274
 *   appending #x20 to the normalized value, except that only a single
4275
 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
4276
 *   parsed entity or the literal entity value of an internal parsed entity
4277
 * - other characters are processed by appending them to the normalized value
4278
 * If the declared value is not CDATA, then the XML processor must further
4279
 * process the normalized attribute value by discarding any leading and
4280
 * trailing space (#x20) characters, and by replacing sequences of space
4281
 * (#x20) characters by a single space (#x20) character.
4282
 * All attributes for which no declaration has been read should be treated
4283
 * by a non-validating parser as if declared CDATA.
4284
 *
4285
 * Returns the AttValue parsed or NULL. The value has to be freed by the
4286
 *     caller if it was copied, this can be detected by val[*len] == 0.
4287
 */
4288
static xmlChar *
4289
xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *attlen, int *alloc,
4290
63.9k
                         int normalize) {
4291
63.9k
    unsigned maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4292
0
                         XML_MAX_HUGE_LENGTH :
4293
63.9k
                         XML_MAX_TEXT_LENGTH;
4294
63.9k
    xmlSBuf buf;
4295
63.9k
    xmlChar *ret;
4296
63.9k
    int c, l, quote, flags, chunkSize;
4297
63.9k
    int inSpace = 1;
4298
4299
63.9k
    xmlSBufInit(&buf, maxLength);
4300
4301
63.9k
    GROW;
4302
4303
63.9k
    quote = CUR;
4304
63.9k
    if ((quote != '"') && (quote != '\'')) {
4305
4.66k
  xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
4306
4.66k
  return(NULL);
4307
4.66k
    }
4308
59.2k
    CUR_PTR++;
4309
4310
59.2k
    if (ctxt->inSubset == 0)
4311
24.9k
        flags = XML_ENT_CHECKED | XML_ENT_VALIDATED;
4312
34.3k
    else
4313
34.3k
        flags = XML_ENT_VALIDATED;
4314
4315
59.2k
    inSpace = 1;
4316
59.2k
    chunkSize = 0;
4317
4318
807k
    while (1) {
4319
807k
        if (PARSER_STOPPED(ctxt))
4320
15
            goto error;
4321
4322
807k
        if (CUR_PTR >= ctxt->input->end) {
4323
9.79k
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
4324
9.79k
                           "AttValue: ' expected\n");
4325
9.79k
            goto error;
4326
9.79k
        }
4327
4328
        /*
4329
         * TODO: Check growth threshold
4330
         */
4331
797k
        if (ctxt->input->end - CUR_PTR < 10)
4332
99.7k
            GROW;
4333
4334
797k
        c = CUR;
4335
4336
797k
        if (c >= 0x80) {
4337
126k
            l = xmlUTF8MultibyteLen(ctxt, CUR_PTR,
4338
126k
                    "invalid character in attribute value\n");
4339
126k
            if (l == 0) {
4340
6.98k
                if (chunkSize > 0) {
4341
1.13k
                    xmlSBufAddString(&buf, CUR_PTR - chunkSize, chunkSize);
4342
1.13k
                    chunkSize = 0;
4343
1.13k
                }
4344
6.98k
                xmlSBufAddReplChar(&buf);
4345
6.98k
                NEXTL(1);
4346
119k
            } else {
4347
119k
                chunkSize += l;
4348
119k
                NEXTL(l);
4349
119k
            }
4350
4351
126k
            inSpace = 0;
4352
671k
        } else if (c != '&') {
4353
592k
            if (c > 0x20) {
4354
453k
                if (c == quote)
4355
48.1k
                    break;
4356
4357
405k
                if (c == '<')
4358
26.6k
                    xmlFatalErr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, NULL);
4359
4360
405k
                chunkSize += 1;
4361
405k
                inSpace = 0;
4362
405k
            } else if (!IS_BYTE_CHAR(c)) {
4363
3.97k
                xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
4364
3.97k
                        "invalid character in attribute value\n");
4365
3.97k
                if (chunkSize > 0) {
4366
799
                    xmlSBufAddString(&buf, CUR_PTR - chunkSize, chunkSize);
4367
799
                    chunkSize = 0;
4368
799
                }
4369
3.97k
                xmlSBufAddReplChar(&buf);
4370
3.97k
                inSpace = 0;
4371
134k
            } else {
4372
                /* Whitespace */
4373
134k
                if ((normalize) && (inSpace)) {
4374
                    /* Skip char */
4375
1.13k
                    if (chunkSize > 0) {
4376
412
                        xmlSBufAddString(&buf, CUR_PTR - chunkSize, chunkSize);
4377
412
                        chunkSize = 0;
4378
412
                    }
4379
133k
                } else if (c < 0x20) {
4380
                    /* Convert to space */
4381
5.33k
                    if (chunkSize > 0) {
4382
3.21k
                        xmlSBufAddString(&buf, CUR_PTR - chunkSize, chunkSize);
4383
3.21k
                        chunkSize = 0;
4384
3.21k
                    }
4385
4386
5.33k
                    xmlSBufAddCString(&buf, " ", 1);
4387
128k
                } else {
4388
128k
                    chunkSize += 1;
4389
128k
                }
4390
4391
134k
                inSpace = 1;
4392
4393
134k
                if ((c == 0xD) && (NXT(1) == 0xA))
4394
201
                    CUR_PTR++;
4395
134k
            }
4396
4397
544k
            NEXTL(1);
4398
544k
        } else if (NXT(1) == '#') {
4399
8.82k
            int val;
4400
4401
8.82k
            if (chunkSize > 0) {
4402
5.26k
                xmlSBufAddString(&buf, CUR_PTR - chunkSize, chunkSize);
4403
5.26k
                chunkSize = 0;
4404
5.26k
            }
4405
4406
8.82k
            val = xmlParseCharRef(ctxt);
4407
8.82k
            if (val == 0)
4408
1.29k
                goto error;
4409
4410
7.52k
            if ((val == '&') && (!ctxt->replaceEntities)) {
4411
                /*
4412
                 * The reparsing will be done in xmlStringGetNodeList()
4413
                 * called by the attribute() function in SAX.c
4414
                 */
4415
1.29k
                xmlSBufAddCString(&buf, "&#38;", 5);
4416
1.29k
                inSpace = 0;
4417
6.22k
            } else if (val == ' ') {
4418
1.10k
                if ((!normalize) || (!inSpace))
4419
1.03k
                    xmlSBufAddCString(&buf, " ", 1);
4420
1.10k
                inSpace = 1;
4421
5.11k
            } else {
4422
5.11k
                xmlSBufAddChar(&buf, val);
4423
5.11k
                inSpace = 0;
4424
5.11k
            }
4425
70.5k
        } else {
4426
70.5k
            const xmlChar *name;
4427
70.5k
            xmlEntityPtr ent;
4428
4429
70.5k
            if (chunkSize > 0) {
4430
18.0k
                xmlSBufAddString(&buf, CUR_PTR - chunkSize, chunkSize);
4431
18.0k
                chunkSize = 0;
4432
18.0k
            }
4433
4434
70.5k
            name = xmlParseEntityRefInternal(ctxt);
4435
70.5k
            if (name == NULL) {
4436
                /*
4437
                 * Probably a literal '&' which wasn't escaped.
4438
                 * TODO: Handle gracefully in recovery mode.
4439
                 */
4440
5.79k
                continue;
4441
5.79k
            }
4442
4443
64.7k
            ent = xmlLookupGeneralEntity(ctxt, name, /* isAttr */ 1);
4444
64.7k
            if (ent == NULL)
4445
10.3k
                continue;
4446
4447
54.3k
            if (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY) {
4448
3.16k
                if ((ent->content[0] == '&') && (!ctxt->replaceEntities))
4449
1.99k
                    xmlSBufAddCString(&buf, "&#38;", 5);
4450
1.17k
                else
4451
1.17k
                    xmlSBufAddString(&buf, ent->content, ent->length);
4452
3.16k
                inSpace = 0;
4453
51.2k
            } else if (ctxt->replaceEntities) {
4454
0
                xmlExpandEntityInAttValue(ctxt, &buf, ent->content, ent,
4455
0
                                          normalize, &inSpace, ctxt->inputNr,
4456
0
                                          /* check */ 1);
4457
51.2k
            } else {
4458
51.2k
                if ((ent->flags & flags) != flags)
4459
730
                    xmlCheckEntityInAttValue(ctxt, ent, ctxt->inputNr);
4460
4461
51.2k
                if (xmlParserEntityCheck(ctxt, ent->expandedSize)) {
4462
17
                    ent->content[0] = 0;
4463
17
                    goto error;
4464
17
                }
4465
4466
                /*
4467
                 * Just output the reference
4468
                 */
4469
51.2k
                xmlSBufAddCString(&buf, "&", 1);
4470
51.2k
                xmlSBufAddString(&buf, ent->name, xmlStrlen(ent->name));
4471
51.2k
                xmlSBufAddCString(&buf, ";", 1);
4472
4473
51.2k
                inSpace = 0;
4474
51.2k
            }
4475
54.3k
  }
4476
797k
    }
4477
4478
48.1k
    if ((buf.mem == NULL) && (alloc != NULL)) {
4479
15.3k
        ret = (xmlChar *) CUR_PTR - chunkSize;
4480
4481
15.3k
        if (attlen != NULL)
4482
15.3k
            *attlen = chunkSize;
4483
15.3k
        if ((normalize) && (inSpace) && (chunkSize > 0))
4484
90
            *attlen -= 1;
4485
15.3k
        *alloc = 0;
4486
4487
        /* Report potential error */
4488
15.3k
        xmlSBufCleanup(&buf, ctxt, "AttValue length too long");
4489
32.7k
    } else {
4490
32.7k
        if (chunkSize > 0)
4491
23.0k
            xmlSBufAddString(&buf, CUR_PTR - chunkSize, chunkSize);
4492
4493
32.7k
        if ((normalize) && (inSpace) && (buf.size > 0))
4494
100
            buf.size--;
4495
4496
32.7k
        ret = xmlSBufFinish(&buf, attlen, ctxt, "AttValue length too long");
4497
4498
32.7k
        if (ret != NULL) {
4499
32.7k
            if (attlen != NULL)
4500
2.19k
                *attlen = buf.size;
4501
32.7k
            if (alloc != NULL)
4502
2.19k
                *alloc = 1;
4503
32.7k
        }
4504
32.7k
    }
4505
4506
48.1k
    NEXTL(1);
4507
4508
48.1k
    return(ret);
4509
4510
11.1k
error:
4511
11.1k
    xmlSBufCleanup(&buf, ctxt, "AttValue length too long");
4512
11.1k
    return(NULL);
4513
59.2k
}
4514
4515
/**
4516
 * xmlParseAttValue:
4517
 * @ctxt:  an XML parser context
4518
 *
4519
 * DEPRECATED: Internal function, don't use.
4520
 *
4521
 * parse a value for an attribute
4522
 * Note: the parser won't do substitution of entities here, this
4523
 * will be handled later in xmlStringGetNodeList
4524
 *
4525
 * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |
4526
 *                   "'" ([^<&'] | Reference)* "'"
4527
 *
4528
 * 3.3.3 Attribute-Value Normalization:
4529
 * Before the value of an attribute is passed to the application or
4530
 * checked for validity, the XML processor must normalize it as follows:
4531
 * - a character reference is processed by appending the referenced
4532
 *   character to the attribute value
4533
 * - an entity reference is processed by recursively processing the
4534
 *   replacement text of the entity
4535
 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
4536
 *   appending #x20 to the normalized value, except that only a single
4537
 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
4538
 *   parsed entity or the literal entity value of an internal parsed entity
4539
 * - other characters are processed by appending them to the normalized value
4540
 * If the declared value is not CDATA, then the XML processor must further
4541
 * process the normalized attribute value by discarding any leading and
4542
 * trailing space (#x20) characters, and by replacing sequences of space
4543
 * (#x20) characters by a single space (#x20) character.
4544
 * All attributes for which no declaration has been read should be treated
4545
 * by a non-validating parser as if declared CDATA.
4546
 *
4547
 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
4548
 */
4549
4550
4551
xmlChar *
4552
45.0k
xmlParseAttValue(xmlParserCtxtPtr ctxt) {
4553
45.0k
    if ((ctxt == NULL) || (ctxt->input == NULL)) return(NULL);
4554
45.0k
    return(xmlParseAttValueInternal(ctxt, NULL, NULL, 0));
4555
45.0k
}
4556
4557
/**
4558
 * xmlParseSystemLiteral:
4559
 * @ctxt:  an XML parser context
4560
 *
4561
 * DEPRECATED: Internal function, don't use.
4562
 *
4563
 * parse an XML Literal
4564
 *
4565
 * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
4566
 *
4567
 * Returns the SystemLiteral parsed or NULL
4568
 */
4569
4570
xmlChar *
4571
5.14k
xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
4572
5.14k
    xmlChar *buf = NULL;
4573
5.14k
    int len = 0;
4574
5.14k
    int size = XML_PARSER_BUFFER_SIZE;
4575
5.14k
    int cur, l;
4576
5.14k
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4577
0
                    XML_MAX_TEXT_LENGTH :
4578
5.14k
                    XML_MAX_NAME_LENGTH;
4579
5.14k
    xmlChar stop;
4580
4581
5.14k
    if (RAW == '"') {
4582
2.85k
        NEXT;
4583
2.85k
  stop = '"';
4584
2.85k
    } else if (RAW == '\'') {
4585
464
        NEXT;
4586
464
  stop = '\'';
4587
1.82k
    } else {
4588
1.82k
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
4589
1.82k
  return(NULL);
4590
1.82k
    }
4591
4592
3.32k
    buf = (xmlChar *) xmlMallocAtomic(size);
4593
3.32k
    if (buf == NULL) {
4594
0
        xmlErrMemory(ctxt);
4595
0
  return(NULL);
4596
0
    }
4597
3.32k
    cur = CUR_CHAR(l);
4598
43.7k
    while ((IS_CHAR(cur)) && (cur != stop)) { /* checked */
4599
40.4k
  if (len + 5 >= size) {
4600
227
      xmlChar *tmp;
4601
4602
227
      size *= 2;
4603
227
      tmp = (xmlChar *) xmlRealloc(buf, size);
4604
227
      if (tmp == NULL) {
4605
0
          xmlFree(buf);
4606
0
    xmlErrMemory(ctxt);
4607
0
    return(NULL);
4608
0
      }
4609
227
      buf = tmp;
4610
227
  }
4611
40.4k
  COPY_BUF(buf, len, cur);
4612
40.4k
        if (len > maxLength) {
4613
0
            xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral");
4614
0
            xmlFree(buf);
4615
0
            return(NULL);
4616
0
        }
4617
40.4k
  NEXTL(l);
4618
40.4k
  cur = CUR_CHAR(l);
4619
40.4k
    }
4620
3.32k
    buf[len] = 0;
4621
3.32k
    if (!IS_CHAR(cur)) {
4622
957
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
4623
2.36k
    } else {
4624
2.36k
  NEXT;
4625
2.36k
    }
4626
3.32k
    return(buf);
4627
3.32k
}
4628
4629
/**
4630
 * xmlParsePubidLiteral:
4631
 * @ctxt:  an XML parser context
4632
 *
4633
 * DEPRECATED: Internal function, don't use.
4634
 *
4635
 * parse an XML public literal
4636
 *
4637
 * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
4638
 *
4639
 * Returns the PubidLiteral parsed or NULL.
4640
 */
4641
4642
xmlChar *
4643
3.73k
xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
4644
3.73k
    xmlChar *buf = NULL;
4645
3.73k
    int len = 0;
4646
3.73k
    int size = XML_PARSER_BUFFER_SIZE;
4647
3.73k
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4648
0
                    XML_MAX_TEXT_LENGTH :
4649
3.73k
                    XML_MAX_NAME_LENGTH;
4650
3.73k
    xmlChar cur;
4651
3.73k
    xmlChar stop;
4652
4653
3.73k
    if (RAW == '"') {
4654
2.00k
        NEXT;
4655
2.00k
  stop = '"';
4656
2.00k
    } else if (RAW == '\'') {
4657
1.07k
        NEXT;
4658
1.07k
  stop = '\'';
4659
1.07k
    } else {
4660
651
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
4661
651
  return(NULL);
4662
651
    }
4663
3.07k
    buf = (xmlChar *) xmlMallocAtomic(size);
4664
3.07k
    if (buf == NULL) {
4665
0
  xmlErrMemory(ctxt);
4666
0
  return(NULL);
4667
0
    }
4668
3.07k
    cur = CUR;
4669
42.8k
    while ((IS_PUBIDCHAR_CH(cur)) && (cur != stop) &&
4670
42.8k
           (PARSER_STOPPED(ctxt) == 0)) { /* checked */
4671
39.7k
  if (len + 1 >= size) {
4672
194
      xmlChar *tmp;
4673
4674
194
      size *= 2;
4675
194
      tmp = (xmlChar *) xmlRealloc(buf, size);
4676
194
      if (tmp == NULL) {
4677
0
    xmlErrMemory(ctxt);
4678
0
    xmlFree(buf);
4679
0
    return(NULL);
4680
0
      }
4681
194
      buf = tmp;
4682
194
  }
4683
39.7k
  buf[len++] = cur;
4684
39.7k
        if (len > maxLength) {
4685
0
            xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Public ID");
4686
0
            xmlFree(buf);
4687
0
            return(NULL);
4688
0
        }
4689
39.7k
  NEXT;
4690
39.7k
  cur = CUR;
4691
39.7k
    }
4692
3.07k
    buf[len] = 0;
4693
3.07k
    if (cur != stop) {
4694
2.45k
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
4695
2.45k
    } else {
4696
620
  NEXTL(1);
4697
620
    }
4698
3.07k
    return(buf);
4699
3.07k
}
4700
4701
static void xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int partial);
4702
4703
/*
4704
 * used for the test in the inner loop of the char data testing
4705
 */
4706
static const unsigned char test_char_data[256] = {
4707
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4708
    0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9, CR/LF separated */
4709
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4710
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4711
    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x00, 0x27, /* & */
4712
    0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
4713
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
4714
    0x38, 0x39, 0x3A, 0x3B, 0x00, 0x3D, 0x3E, 0x3F, /* < */
4715
    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
4716
    0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
4717
    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
4718
    0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x00, 0x5E, 0x5F, /* ] */
4719
    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
4720
    0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
4721
    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
4722
    0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
4723
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* non-ascii */
4724
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4725
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4726
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4727
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4728
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4729
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4730
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4731
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4732
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4733
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4734
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4735
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4736
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4737
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4738
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4739
};
4740
4741
/**
4742
 * xmlParseCharDataInternal:
4743
 * @ctxt:  an XML parser context
4744
 * @partial:  buffer may contain partial UTF-8 sequences
4745
 *
4746
 * Parse character data. Always makes progress if the first char isn't
4747
 * '<' or '&'.
4748
 *
4749
 * The right angle bracket (>) may be represented using the string "&gt;",
4750
 * and must, for compatibility, be escaped using "&gt;" or a character
4751
 * reference when it appears in the string "]]>" in content, when that
4752
 * string is not marking the end of a CDATA section.
4753
 *
4754
 * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
4755
 */
4756
static void
4757
49.1k
xmlParseCharDataInternal(xmlParserCtxtPtr ctxt, int partial) {
4758
49.1k
    const xmlChar *in;
4759
49.1k
    int nbchar = 0;
4760
49.1k
    int line = ctxt->input->line;
4761
49.1k
    int col = ctxt->input->col;
4762
49.1k
    int ccol;
4763
4764
49.1k
    GROW;
4765
    /*
4766
     * Accelerated common case where input don't need to be
4767
     * modified before passing it to the handler.
4768
     */
4769
49.1k
    in = ctxt->input->cur;
4770
49.6k
    do {
4771
49.9k
get_more_space:
4772
57.2k
        while (*in == 0x20) { in++; ctxt->input->col++; }
4773
49.9k
        if (*in == 0xA) {
4774
848
            do {
4775
848
                ctxt->input->line++; ctxt->input->col = 1;
4776
848
                in++;
4777
848
            } while (*in == 0xA);
4778
285
            goto get_more_space;
4779
285
        }
4780
49.6k
        if (*in == '<') {
4781
3.37k
            nbchar = in - ctxt->input->cur;
4782
3.37k
            if (nbchar > 0) {
4783
3.37k
                const xmlChar *tmp = ctxt->input->cur;
4784
3.37k
                ctxt->input->cur = in;
4785
4786
3.37k
                if ((ctxt->sax != NULL) &&
4787
3.37k
                    (ctxt->disableSAX == 0) &&
4788
3.37k
                    (ctxt->sax->ignorableWhitespace !=
4789
2.75k
                     ctxt->sax->characters)) {
4790
1.98k
                    if (areBlanks(ctxt, tmp, nbchar, 1)) {
4791
1.07k
                        if (ctxt->sax->ignorableWhitespace != NULL)
4792
1.07k
                            ctxt->sax->ignorableWhitespace(ctxt->userData,
4793
1.07k
                                                   tmp, nbchar);
4794
1.07k
                    } else {
4795
909
                        if (ctxt->sax->characters != NULL)
4796
909
                            ctxt->sax->characters(ctxt->userData,
4797
909
                                                  tmp, nbchar);
4798
909
                        if (*ctxt->space == -1)
4799
427
                            *ctxt->space = -2;
4800
909
                    }
4801
1.98k
                } else if ((ctxt->sax != NULL) &&
4802
1.38k
                           (ctxt->disableSAX == 0) &&
4803
1.38k
                           (ctxt->sax->characters != NULL)) {
4804
772
                    ctxt->sax->characters(ctxt->userData,
4805
772
                                          tmp, nbchar);
4806
772
                }
4807
3.37k
            }
4808
3.37k
            return;
4809
3.37k
        }
4810
4811
49.7k
get_more:
4812
49.7k
        ccol = ctxt->input->col;
4813
140k
        while (test_char_data[*in]) {
4814
90.9k
            in++;
4815
90.9k
            ccol++;
4816
90.9k
        }
4817
49.7k
        ctxt->input->col = ccol;
4818
49.7k
        if (*in == 0xA) {
4819
567
            do {
4820
567
                ctxt->input->line++; ctxt->input->col = 1;
4821
567
                in++;
4822
567
            } while (*in == 0xA);
4823
265
            goto get_more;
4824
265
        }
4825
49.4k
        if (*in == ']') {
4826
3.47k
            if ((in[1] == ']') && (in[2] == '>')) {
4827
303
                xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
4828
303
                ctxt->input->cur = in + 1;
4829
303
                return;
4830
303
            }
4831
3.16k
            in++;
4832
3.16k
            ctxt->input->col++;
4833
3.16k
            goto get_more;
4834
3.47k
        }
4835
45.9k
        nbchar = in - ctxt->input->cur;
4836
45.9k
        if (nbchar > 0) {
4837
36.1k
            if ((ctxt->sax != NULL) &&
4838
36.1k
                (ctxt->disableSAX == 0) &&
4839
36.1k
                (ctxt->sax->ignorableWhitespace !=
4840
22.2k
                 ctxt->sax->characters) &&
4841
36.1k
                (IS_BLANK_CH(*ctxt->input->cur))) {
4842
1.72k
                const xmlChar *tmp = ctxt->input->cur;
4843
1.72k
                ctxt->input->cur = in;
4844
4845
1.72k
                if (areBlanks(ctxt, tmp, nbchar, 0)) {
4846
527
                    if (ctxt->sax->ignorableWhitespace != NULL)
4847
527
                        ctxt->sax->ignorableWhitespace(ctxt->userData,
4848
527
                                                       tmp, nbchar);
4849
1.20k
                } else {
4850
1.20k
                    if (ctxt->sax->characters != NULL)
4851
1.20k
                        ctxt->sax->characters(ctxt->userData,
4852
1.20k
                                              tmp, nbchar);
4853
1.20k
                    if (*ctxt->space == -1)
4854
646
                        *ctxt->space = -2;
4855
1.20k
                }
4856
1.72k
                line = ctxt->input->line;
4857
1.72k
                col = ctxt->input->col;
4858
34.4k
            } else if ((ctxt->sax != NULL) &&
4859
34.4k
                       (ctxt->disableSAX == 0)) {
4860
20.4k
                if (ctxt->sax->characters != NULL)
4861
20.4k
                    ctxt->sax->characters(ctxt->userData,
4862
20.4k
                                          ctxt->input->cur, nbchar);
4863
20.4k
                line = ctxt->input->line;
4864
20.4k
                col = ctxt->input->col;
4865
20.4k
            }
4866
36.1k
        }
4867
45.9k
        ctxt->input->cur = in;
4868
45.9k
        if (*in == 0xD) {
4869
1.61k
            in++;
4870
1.61k
            if (*in == 0xA) {
4871
522
                ctxt->input->cur = in;
4872
522
                in++;
4873
522
                ctxt->input->line++; ctxt->input->col = 1;
4874
522
                continue; /* while */
4875
522
            }
4876
1.09k
            in--;
4877
1.09k
        }
4878
45.4k
        if (*in == '<') {
4879
28.8k
            return;
4880
28.8k
        }
4881
16.6k
        if (*in == '&') {
4882
4.64k
            return;
4883
4.64k
        }
4884
11.9k
        SHRINK;
4885
11.9k
        GROW;
4886
11.9k
        in = ctxt->input->cur;
4887
12.5k
    } while (((*in >= 0x20) && (*in <= 0x7F)) ||
4888
12.5k
             (*in == 0x09) || (*in == 0x0a));
4889
11.9k
    ctxt->input->line = line;
4890
11.9k
    ctxt->input->col = col;
4891
11.9k
    xmlParseCharDataComplex(ctxt, partial);
4892
11.9k
}
4893
4894
/**
4895
 * xmlParseCharDataComplex:
4896
 * @ctxt:  an XML parser context
4897
 * @cdata:  int indicating whether we are within a CDATA section
4898
 *
4899
 * Always makes progress if the first char isn't '<' or '&'.
4900
 *
4901
 * parse a CharData section.this is the fallback function
4902
 * of xmlParseCharData() when the parsing requires handling
4903
 * of non-ASCII characters.
4904
 */
4905
static void
4906
11.9k
xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int partial) {
4907
11.9k
    xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE + 5];
4908
11.9k
    int nbchar = 0;
4909
11.9k
    int cur, l;
4910
4911
11.9k
    cur = CUR_CHAR(l);
4912
63.3k
    while ((cur != '<') && /* checked */
4913
63.3k
           (cur != '&') &&
4914
63.3k
     (IS_CHAR(cur))) {
4915
51.3k
  if ((cur == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
4916
246
      xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
4917
246
  }
4918
51.3k
  COPY_BUF(buf, nbchar, cur);
4919
  /* move current position before possible calling of ctxt->sax->characters */
4920
51.3k
  NEXTL(l);
4921
51.3k
  if (nbchar >= XML_PARSER_BIG_BUFFER_SIZE) {
4922
271
      buf[nbchar] = 0;
4923
4924
      /*
4925
       * OK the segment is to be consumed as chars.
4926
       */
4927
271
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
4928
137
    if (areBlanks(ctxt, buf, nbchar, 0)) {
4929
10
        if (ctxt->sax->ignorableWhitespace != NULL)
4930
10
      ctxt->sax->ignorableWhitespace(ctxt->userData,
4931
10
                                     buf, nbchar);
4932
127
    } else {
4933
127
        if (ctxt->sax->characters != NULL)
4934
127
      ctxt->sax->characters(ctxt->userData, buf, nbchar);
4935
127
        if ((ctxt->sax->characters !=
4936
127
             ctxt->sax->ignorableWhitespace) &&
4937
127
      (*ctxt->space == -1))
4938
27
      *ctxt->space = -2;
4939
127
    }
4940
137
      }
4941
271
      nbchar = 0;
4942
271
            SHRINK;
4943
271
  }
4944
51.3k
  cur = CUR_CHAR(l);
4945
51.3k
    }
4946
11.9k
    if (nbchar != 0) {
4947
5.47k
        buf[nbchar] = 0;
4948
  /*
4949
   * OK the segment is to be consumed as chars.
4950
   */
4951
5.47k
  if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
4952
3.24k
      if (areBlanks(ctxt, buf, nbchar, 0)) {
4953
462
    if (ctxt->sax->ignorableWhitespace != NULL)
4954
462
        ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
4955
2.77k
      } else {
4956
2.77k
    if (ctxt->sax->characters != NULL)
4957
2.77k
        ctxt->sax->characters(ctxt->userData, buf, nbchar);
4958
2.77k
    if ((ctxt->sax->characters != ctxt->sax->ignorableWhitespace) &&
4959
2.77k
        (*ctxt->space == -1))
4960
378
        *ctxt->space = -2;
4961
2.77k
      }
4962
3.24k
  }
4963
5.47k
    }
4964
    /*
4965
     * cur == 0 can mean
4966
     *
4967
     * - End of buffer.
4968
     * - An actual 0 character.
4969
     * - An incomplete UTF-8 sequence. This is allowed if partial is set.
4970
     */
4971
11.9k
    if (ctxt->input->cur < ctxt->input->end) {
4972
10.6k
        if ((cur == 0) && (CUR != 0)) {
4973
7
            if (partial == 0) {
4974
7
                xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4975
7
                        "Incomplete UTF-8 sequence starting with %02X\n", CUR);
4976
7
                NEXTL(1);
4977
7
            }
4978
10.6k
        } else if ((cur != '<') && (cur != '&')) {
4979
            /* Generate the error and skip the offending character */
4980
5.39k
            xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4981
5.39k
                              "PCDATA invalid Char value %d\n", cur);
4982
5.39k
            NEXTL(l);
4983
5.39k
        }
4984
10.6k
    }
4985
11.9k
}
4986
4987
/**
4988
 * xmlParseCharData:
4989
 * @ctxt:  an XML parser context
4990
 * @cdata:  unused
4991
 *
4992
 * DEPRECATED: Internal function, don't use.
4993
 */
4994
void
4995
0
xmlParseCharData(xmlParserCtxtPtr ctxt, ATTRIBUTE_UNUSED int cdata) {
4996
0
    xmlParseCharDataInternal(ctxt, 0);
4997
0
}
4998
4999
/**
5000
 * xmlParseExternalID:
5001
 * @ctxt:  an XML parser context
5002
 * @publicID:  a xmlChar** receiving PubidLiteral
5003
 * @strict: indicate whether we should restrict parsing to only
5004
 *          production [75], see NOTE below
5005
 *
5006
 * DEPRECATED: Internal function, don't use.
5007
 *
5008
 * Parse an External ID or a Public ID
5009
 *
5010
 * NOTE: Productions [75] and [83] interact badly since [75] can generate
5011
 *       'PUBLIC' S PubidLiteral S SystemLiteral
5012
 *
5013
 * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
5014
 *                   | 'PUBLIC' S PubidLiteral S SystemLiteral
5015
 *
5016
 * [83] PublicID ::= 'PUBLIC' S PubidLiteral
5017
 *
5018
 * Returns the function returns SystemLiteral and in the second
5019
 *                case publicID receives PubidLiteral, is strict is off
5020
 *                it is possible to return NULL and have publicID set.
5021
 */
5022
5023
xmlChar *
5024
19.5k
xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
5025
19.5k
    xmlChar *URI = NULL;
5026
5027
19.5k
    *publicID = NULL;
5028
19.5k
    if (CMP6(CUR_PTR, 'S', 'Y', 'S', 'T', 'E', 'M')) {
5029
3.31k
        SKIP(6);
5030
3.31k
  if (SKIP_BLANKS == 0) {
5031
2.94k
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5032
2.94k
                     "Space required after 'SYSTEM'\n");
5033
2.94k
  }
5034
3.31k
  URI = xmlParseSystemLiteral(ctxt);
5035
3.31k
  if (URI == NULL) {
5036
531
      xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
5037
531
        }
5038
16.2k
    } else if (CMP6(CUR_PTR, 'P', 'U', 'B', 'L', 'I', 'C')) {
5039
3.73k
        SKIP(6);
5040
3.73k
  if (SKIP_BLANKS == 0) {
5041
2.90k
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5042
2.90k
        "Space required after 'PUBLIC'\n");
5043
2.90k
  }
5044
3.73k
  *publicID = xmlParsePubidLiteral(ctxt);
5045
3.73k
  if (*publicID == NULL) {
5046
651
      xmlFatalErr(ctxt, XML_ERR_PUBID_REQUIRED, NULL);
5047
651
  }
5048
3.73k
  if (strict) {
5049
      /*
5050
       * We don't handle [83] so "S SystemLiteral" is required.
5051
       */
5052
1.35k
      if (SKIP_BLANKS == 0) {
5053
1.15k
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5054
1.15k
      "Space required after the Public Identifier\n");
5055
1.15k
      }
5056
2.38k
  } else {
5057
      /*
5058
       * We handle [83] so we return immediately, if
5059
       * "S SystemLiteral" is not detected. We skip blanks if no
5060
             * system literal was found, but this is harmless since we must
5061
             * be at the end of a NotationDecl.
5062
       */
5063
2.38k
      if (SKIP_BLANKS == 0) return(NULL);
5064
675
      if ((CUR != '\'') && (CUR != '"')) return(NULL);
5065
675
  }
5066
1.83k
  URI = xmlParseSystemLiteral(ctxt);
5067
1.83k
  if (URI == NULL) {
5068
1.29k
      xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
5069
1.29k
        }
5070
1.83k
    }
5071
17.6k
    return(URI);
5072
19.5k
}
5073
5074
/**
5075
 * xmlParseCommentComplex:
5076
 * @ctxt:  an XML parser context
5077
 * @buf:  the already parsed part of the buffer
5078
 * @len:  number of bytes in the buffer
5079
 * @size:  allocated size of the buffer
5080
 *
5081
 * Skip an XML (SGML) comment <!-- .... -->
5082
 *  The spec says that "For compatibility, the string "--" (double-hyphen)
5083
 *  must not occur within comments. "
5084
 * This is the slow routine in case the accelerator for ascii didn't work
5085
 *
5086
 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
5087
 */
5088
static void
5089
xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
5090
12.1k
                       size_t len, size_t size) {
5091
12.1k
    int q, ql;
5092
12.1k
    int r, rl;
5093
12.1k
    int cur, l;
5094
12.1k
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
5095
0
                       XML_MAX_HUGE_LENGTH :
5096
12.1k
                       XML_MAX_TEXT_LENGTH;
5097
5098
12.1k
    if (buf == NULL) {
5099
4.94k
        len = 0;
5100
4.94k
  size = XML_PARSER_BUFFER_SIZE;
5101
4.94k
  buf = (xmlChar *) xmlMallocAtomic(size);
5102
4.94k
  if (buf == NULL) {
5103
0
      xmlErrMemory(ctxt);
5104
0
      return;
5105
0
  }
5106
4.94k
    }
5107
12.1k
    q = CUR_CHAR(ql);
5108
12.1k
    if (q == 0)
5109
7.85k
        goto not_terminated;
5110
4.31k
    if (!IS_CHAR(q)) {
5111
101
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
5112
101
                          "xmlParseComment: invalid xmlChar value %d\n",
5113
101
                    q);
5114
101
  xmlFree (buf);
5115
101
  return;
5116
101
    }
5117
4.20k
    NEXTL(ql);
5118
4.20k
    r = CUR_CHAR(rl);
5119
4.20k
    if (r == 0)
5120
194
        goto not_terminated;
5121
4.01k
    if (!IS_CHAR(r)) {
5122
136
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
5123
136
                          "xmlParseComment: invalid xmlChar value %d\n",
5124
136
                    r);
5125
136
  xmlFree (buf);
5126
136
  return;
5127
136
    }
5128
3.87k
    NEXTL(rl);
5129
3.87k
    cur = CUR_CHAR(l);
5130
3.87k
    if (cur == 0)
5131
202
        goto not_terminated;
5132
48.2k
    while (IS_CHAR(cur) && /* checked */
5133
48.2k
           ((cur != '>') ||
5134
47.0k
      (r != '-') || (q != '-'))) {
5135
44.5k
  if ((r == '-') && (q == '-')) {
5136
505
      xmlFatalErr(ctxt, XML_ERR_HYPHEN_IN_COMMENT, NULL);
5137
505
  }
5138
44.5k
  if (len + 5 >= size) {
5139
541
      xmlChar *new_buf;
5140
541
            size_t new_size;
5141
5142
541
      new_size = size * 2;
5143
541
      new_buf = (xmlChar *) xmlRealloc(buf, new_size);
5144
541
      if (new_buf == NULL) {
5145
0
    xmlFree (buf);
5146
0
    xmlErrMemory(ctxt);
5147
0
    return;
5148
0
      }
5149
541
      buf = new_buf;
5150
541
            size = new_size;
5151
541
  }
5152
44.5k
  COPY_BUF(buf, len, q);
5153
44.5k
        if (len > maxLength) {
5154
0
            xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
5155
0
                         "Comment too big found", NULL);
5156
0
            xmlFree (buf);
5157
0
            return;
5158
0
        }
5159
5160
44.5k
  q = r;
5161
44.5k
  ql = rl;
5162
44.5k
  r = cur;
5163
44.5k
  rl = l;
5164
5165
44.5k
  NEXTL(l);
5166
44.5k
  cur = CUR_CHAR(l);
5167
5168
44.5k
    }
5169
3.67k
    buf[len] = 0;
5170
3.67k
    if (cur == 0) {
5171
1.05k
  xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
5172
1.05k
                       "Comment not terminated \n<!--%.50s\n", buf);
5173
2.62k
    } else if (!IS_CHAR(cur)) {
5174
141
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
5175
141
                          "xmlParseComment: invalid xmlChar value %d\n",
5176
141
                    cur);
5177
2.48k
    } else {
5178
2.48k
        NEXT;
5179
2.48k
  if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
5180
2.48k
      (!ctxt->disableSAX))
5181
2.25k
      ctxt->sax->comment(ctxt->userData, buf);
5182
2.48k
    }
5183
3.67k
    xmlFree(buf);
5184
3.67k
    return;
5185
8.25k
not_terminated:
5186
8.25k
    xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
5187
8.25k
       "Comment not terminated\n", NULL);
5188
8.25k
    xmlFree(buf);
5189
8.25k
    return;
5190
3.67k
}
5191
5192
/**
5193
 * xmlParseComment:
5194
 * @ctxt:  an XML parser context
5195
 *
5196
 * DEPRECATED: Internal function, don't use.
5197
 *
5198
 * Parse an XML (SGML) comment. Always consumes '<!'.
5199
 *
5200
 *  The spec says that "For compatibility, the string "--" (double-hyphen)
5201
 *  must not occur within comments. "
5202
 *
5203
 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
5204
 */
5205
void
5206
15.1k
xmlParseComment(xmlParserCtxtPtr ctxt) {
5207
15.1k
    xmlChar *buf = NULL;
5208
15.1k
    size_t size = XML_PARSER_BUFFER_SIZE;
5209
15.1k
    size_t len = 0;
5210
15.1k
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
5211
0
                       XML_MAX_HUGE_LENGTH :
5212
15.1k
                       XML_MAX_TEXT_LENGTH;
5213
15.1k
    const xmlChar *in;
5214
15.1k
    size_t nbchar = 0;
5215
15.1k
    int ccol;
5216
5217
    /*
5218
     * Check that there is a comment right here.
5219
     */
5220
15.1k
    if ((RAW != '<') || (NXT(1) != '!'))
5221
0
        return;
5222
15.1k
    SKIP(2);
5223
15.1k
    if ((RAW != '-') || (NXT(1) != '-'))
5224
4
        return;
5225
15.1k
    SKIP(2);
5226
15.1k
    GROW;
5227
5228
    /*
5229
     * Accelerated common case where input don't need to be
5230
     * modified before passing it to the handler.
5231
     */
5232
15.1k
    in = ctxt->input->cur;
5233
15.1k
    do {
5234
15.1k
  if (*in == 0xA) {
5235
417
      do {
5236
417
    ctxt->input->line++; ctxt->input->col = 1;
5237
417
    in++;
5238
417
      } while (*in == 0xA);
5239
221
  }
5240
26.3k
get_more:
5241
26.3k
        ccol = ctxt->input->col;
5242
99.8k
  while (((*in > '-') && (*in <= 0x7F)) ||
5243
99.8k
         ((*in >= 0x20) && (*in < '-')) ||
5244
99.8k
         (*in == 0x09)) {
5245
73.4k
        in++;
5246
73.4k
        ccol++;
5247
73.4k
  }
5248
26.3k
  ctxt->input->col = ccol;
5249
26.3k
  if (*in == 0xA) {
5250
412
      do {
5251
412
    ctxt->input->line++; ctxt->input->col = 1;
5252
412
    in++;
5253
412
      } while (*in == 0xA);
5254
218
      goto get_more;
5255
218
  }
5256
26.1k
  nbchar = in - ctxt->input->cur;
5257
  /*
5258
   * save current set of data
5259
   */
5260
26.1k
  if (nbchar > 0) {
5261
15.2k
            if (buf == NULL) {
5262
8.30k
                if ((*in == '-') && (in[1] == '-'))
5263
1.25k
                    size = nbchar + 1;
5264
7.05k
                else
5265
7.05k
                    size = XML_PARSER_BUFFER_SIZE + nbchar;
5266
8.30k
                buf = (xmlChar *) xmlMallocAtomic(size);
5267
8.30k
                if (buf == NULL) {
5268
0
                    xmlErrMemory(ctxt);
5269
0
                    return;
5270
0
                }
5271
8.30k
                len = 0;
5272
8.30k
            } else if (len + nbchar + 1 >= size) {
5273
604
                xmlChar *new_buf;
5274
604
                size  += len + nbchar + XML_PARSER_BUFFER_SIZE;
5275
604
                new_buf = (xmlChar *) xmlRealloc(buf, size);
5276
604
                if (new_buf == NULL) {
5277
0
                    xmlFree (buf);
5278
0
                    xmlErrMemory(ctxt);
5279
0
                    return;
5280
0
                }
5281
604
                buf = new_buf;
5282
604
            }
5283
15.2k
            memcpy(&buf[len], ctxt->input->cur, nbchar);
5284
15.2k
            len += nbchar;
5285
15.2k
            buf[len] = 0;
5286
15.2k
  }
5287
26.1k
        if (len > maxLength) {
5288
0
            xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
5289
0
                         "Comment too big found", NULL);
5290
0
            xmlFree (buf);
5291
0
            return;
5292
0
        }
5293
26.1k
  ctxt->input->cur = in;
5294
26.1k
  if (*in == 0xA) {
5295
0
      in++;
5296
0
      ctxt->input->line++; ctxt->input->col = 1;
5297
0
  }
5298
26.1k
  if (*in == 0xD) {
5299
1.12k
      in++;
5300
1.12k
      if (*in == 0xA) {
5301
200
    ctxt->input->cur = in;
5302
200
    in++;
5303
200
    ctxt->input->line++; ctxt->input->col = 1;
5304
200
    goto get_more;
5305
200
      }
5306
929
      in--;
5307
929
  }
5308
25.9k
  SHRINK;
5309
25.9k
  GROW;
5310
25.9k
  in = ctxt->input->cur;
5311
25.9k
  if (*in == '-') {
5312
13.7k
      if (in[1] == '-') {
5313
8.11k
          if (in[2] == '>') {
5314
2.94k
        SKIP(3);
5315
2.94k
        if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
5316
2.94k
            (!ctxt->disableSAX)) {
5317
2.24k
      if (buf != NULL)
5318
878
          ctxt->sax->comment(ctxt->userData, buf);
5319
1.36k
      else
5320
1.36k
          ctxt->sax->comment(ctxt->userData, BAD_CAST "");
5321
2.24k
        }
5322
2.94k
        if (buf != NULL)
5323
1.08k
            xmlFree(buf);
5324
2.94k
        return;
5325
2.94k
    }
5326
5.16k
    if (buf != NULL) {
5327
1.28k
        xmlFatalErrMsgStr(ctxt, XML_ERR_HYPHEN_IN_COMMENT,
5328
1.28k
                          "Double hyphen within comment: "
5329
1.28k
                                      "<!--%.50s\n",
5330
1.28k
              buf);
5331
1.28k
    } else
5332
3.87k
        xmlFatalErrMsgStr(ctxt, XML_ERR_HYPHEN_IN_COMMENT,
5333
3.87k
                          "Double hyphen within comment\n", NULL);
5334
5.16k
    in++;
5335
5.16k
    ctxt->input->col++;
5336
5.16k
      }
5337
10.8k
      in++;
5338
10.8k
      ctxt->input->col++;
5339
10.8k
      goto get_more;
5340
13.7k
  }
5341
25.9k
    } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09) || (*in == 0x0a));
5342
12.1k
    xmlParseCommentComplex(ctxt, buf, len, size);
5343
12.1k
    return;
5344
15.1k
}
5345
5346
5347
/**
5348
 * xmlParsePITarget:
5349
 * @ctxt:  an XML parser context
5350
 *
5351
 * DEPRECATED: Internal function, don't use.
5352
 *
5353
 * parse the name of a PI
5354
 *
5355
 * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
5356
 *
5357
 * Returns the PITarget name or NULL
5358
 */
5359
5360
const xmlChar *
5361
25.9k
xmlParsePITarget(xmlParserCtxtPtr ctxt) {
5362
25.9k
    const xmlChar *name;
5363
5364
25.9k
    name = xmlParseName(ctxt);
5365
25.9k
    if ((name != NULL) &&
5366
25.9k
        ((name[0] == 'x') || (name[0] == 'X')) &&
5367
25.9k
        ((name[1] == 'm') || (name[1] == 'M')) &&
5368
25.9k
        ((name[2] == 'l') || (name[2] == 'L'))) {
5369
1.30k
  int i;
5370
1.30k
  if ((name[0] == 'x') && (name[1] == 'm') &&
5371
1.30k
      (name[2] == 'l') && (name[3] == 0)) {
5372
200
      xmlFatalErrMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
5373
200
     "XML declaration allowed only at the start of the document\n");
5374
200
      return(name);
5375
1.10k
  } else if (name[3] == 0) {
5376
634
      xmlFatalErr(ctxt, XML_ERR_RESERVED_XML_NAME, NULL);
5377
634
      return(name);
5378
634
  }
5379
1.22k
  for (i = 0;;i++) {
5380
1.22k
      if (xmlW3CPIs[i] == NULL) break;
5381
948
      if (xmlStrEqual(name, (const xmlChar *)xmlW3CPIs[i]))
5382
194
          return(name);
5383
948
  }
5384
280
  xmlWarningMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
5385
280
          "xmlParsePITarget: invalid name prefix 'xml'\n",
5386
280
          NULL, NULL);
5387
280
    }
5388
24.8k
    if ((name != NULL) && (xmlStrchr(name, ':') != NULL)) {
5389
1.24k
  xmlNsErr(ctxt, XML_NS_ERR_COLON,
5390
1.24k
     "colons are forbidden from PI names '%s'\n", name, NULL, NULL);
5391
1.24k
    }
5392
24.8k
    return(name);
5393
25.9k
}
5394
5395
#ifdef LIBXML_CATALOG_ENABLED
5396
/**
5397
 * xmlParseCatalogPI:
5398
 * @ctxt:  an XML parser context
5399
 * @catalog:  the PI value string
5400
 *
5401
 * parse an XML Catalog Processing Instruction.
5402
 *
5403
 * <?oasis-xml-catalog catalog="http://example.com/catalog.xml"?>
5404
 *
5405
 * Occurs only if allowed by the user and if happening in the Misc
5406
 * part of the document before any doctype information
5407
 * This will add the given catalog to the parsing context in order
5408
 * to be used if there is a resolution need further down in the document
5409
 */
5410
5411
static void
5412
597
xmlParseCatalogPI(xmlParserCtxtPtr ctxt, const xmlChar *catalog) {
5413
597
    xmlChar *URL = NULL;
5414
597
    const xmlChar *tmp, *base;
5415
597
    xmlChar marker;
5416
5417
597
    tmp = catalog;
5418
597
    while (IS_BLANK_CH(*tmp)) tmp++;
5419
597
    if (xmlStrncmp(tmp, BAD_CAST"catalog", 7))
5420
132
  goto error;
5421
465
    tmp += 7;
5422
468
    while (IS_BLANK_CH(*tmp)) tmp++;
5423
465
    if (*tmp != '=') {
5424
84
  return;
5425
84
    }
5426
381
    tmp++;
5427
445
    while (IS_BLANK_CH(*tmp)) tmp++;
5428
381
    marker = *tmp;
5429
381
    if ((marker != '\'') && (marker != '"'))
5430
74
  goto error;
5431
307
    tmp++;
5432
307
    base = tmp;
5433
789
    while ((*tmp != 0) && (*tmp != marker)) tmp++;
5434
307
    if (*tmp == 0)
5435
103
  goto error;
5436
204
    URL = xmlStrndup(base, tmp - base);
5437
204
    tmp++;
5438
423
    while (IS_BLANK_CH(*tmp)) tmp++;
5439
204
    if (*tmp != 0)
5440
52
  goto error;
5441
5442
152
    if (URL != NULL) {
5443
        /*
5444
         * Unfortunately, the catalog API doesn't report OOM errors.
5445
         * xmlGetLastError isn't very helpful since we don't know
5446
         * where the last error came from. We'd have to reset it
5447
         * before this call and restore it afterwards.
5448
         */
5449
152
  ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
5450
152
  xmlFree(URL);
5451
152
    }
5452
152
    return;
5453
5454
361
error:
5455
361
    xmlWarningMsg(ctxt, XML_WAR_CATALOG_PI,
5456
361
            "Catalog PI syntax error: %s\n",
5457
361
      catalog, NULL);
5458
361
    if (URL != NULL)
5459
52
  xmlFree(URL);
5460
361
}
5461
#endif
5462
5463
/**
5464
 * xmlParsePI:
5465
 * @ctxt:  an XML parser context
5466
 *
5467
 * DEPRECATED: Internal function, don't use.
5468
 *
5469
 * parse an XML Processing Instruction.
5470
 *
5471
 * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
5472
 *
5473
 * The processing is transferred to SAX once parsed.
5474
 */
5475
5476
void
5477
25.9k
xmlParsePI(xmlParserCtxtPtr ctxt) {
5478
25.9k
    xmlChar *buf = NULL;
5479
25.9k
    size_t len = 0;
5480
25.9k
    size_t size = XML_PARSER_BUFFER_SIZE;
5481
25.9k
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
5482
0
                       XML_MAX_HUGE_LENGTH :
5483
25.9k
                       XML_MAX_TEXT_LENGTH;
5484
25.9k
    int cur, l;
5485
25.9k
    const xmlChar *target;
5486
5487
25.9k
    if ((RAW == '<') && (NXT(1) == '?')) {
5488
  /*
5489
   * this is a Processing Instruction.
5490
   */
5491
25.9k
  SKIP(2);
5492
5493
  /*
5494
   * Parse the target name and check for special support like
5495
   * namespace.
5496
   */
5497
25.9k
        target = xmlParsePITarget(ctxt);
5498
25.9k
  if (target != NULL) {
5499
19.5k
      if ((RAW == '?') && (NXT(1) == '>')) {
5500
5.63k
    SKIP(2);
5501
5502
    /*
5503
     * SAX: PI detected.
5504
     */
5505
5.63k
    if ((ctxt->sax) && (!ctxt->disableSAX) &&
5506
5.63k
        (ctxt->sax->processingInstruction != NULL))
5507
4.85k
        ctxt->sax->processingInstruction(ctxt->userData,
5508
4.85k
                                         target, NULL);
5509
5.63k
    return;
5510
5.63k
      }
5511
13.8k
      buf = (xmlChar *) xmlMallocAtomic(size);
5512
13.8k
      if (buf == NULL) {
5513
0
    xmlErrMemory(ctxt);
5514
0
    return;
5515
0
      }
5516
13.8k
      if (SKIP_BLANKS == 0) {
5517
10.5k
    xmlFatalErrMsgStr(ctxt, XML_ERR_SPACE_REQUIRED,
5518
10.5k
        "ParsePI: PI %s space expected\n", target);
5519
10.5k
      }
5520
13.8k
      cur = CUR_CHAR(l);
5521
240k
      while (IS_CHAR(cur) && /* checked */
5522
240k
       ((cur != '?') || (NXT(1) != '>'))) {
5523
226k
    if (len + 5 >= size) {
5524
1.25k
        xmlChar *tmp;
5525
1.25k
                    size_t new_size = size * 2;
5526
1.25k
        tmp = (xmlChar *) xmlRealloc(buf, new_size);
5527
1.25k
        if (tmp == NULL) {
5528
0
      xmlErrMemory(ctxt);
5529
0
      xmlFree(buf);
5530
0
      return;
5531
0
        }
5532
1.25k
        buf = tmp;
5533
1.25k
                    size = new_size;
5534
1.25k
    }
5535
226k
    COPY_BUF(buf, len, cur);
5536
226k
                if (len > maxLength) {
5537
0
                    xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
5538
0
                                      "PI %s too big found", target);
5539
0
                    xmlFree(buf);
5540
0
                    return;
5541
0
                }
5542
226k
    NEXTL(l);
5543
226k
    cur = CUR_CHAR(l);
5544
226k
      }
5545
13.8k
      buf[len] = 0;
5546
13.8k
      if (cur != '?') {
5547
9.20k
    xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
5548
9.20k
          "ParsePI: PI %s never end ...\n", target);
5549
9.20k
      } else {
5550
4.69k
    SKIP(2);
5551
5552
4.69k
#ifdef LIBXML_CATALOG_ENABLED
5553
4.69k
    if ((ctxt->inSubset == 0) &&
5554
4.69k
        (xmlStrEqual(target, XML_CATALOG_PI))) {
5555
597
        xmlCatalogAllow allow = xmlCatalogGetDefaults();
5556
597
        if ((allow == XML_CATA_ALLOW_DOCUMENT) ||
5557
597
      (allow == XML_CATA_ALLOW_ALL))
5558
597
      xmlParseCatalogPI(ctxt, buf);
5559
597
    }
5560
4.69k
#endif
5561
5562
5563
    /*
5564
     * SAX: PI detected.
5565
     */
5566
4.69k
    if ((ctxt->sax) && (!ctxt->disableSAX) &&
5567
4.69k
        (ctxt->sax->processingInstruction != NULL))
5568
3.30k
        ctxt->sax->processingInstruction(ctxt->userData,
5569
3.30k
                                         target, buf);
5570
4.69k
      }
5571
13.8k
      xmlFree(buf);
5572
13.8k
  } else {
5573
6.37k
      xmlFatalErr(ctxt, XML_ERR_PI_NOT_STARTED, NULL);
5574
6.37k
  }
5575
25.9k
    }
5576
25.9k
}
5577
5578
/**
5579
 * xmlParseNotationDecl:
5580
 * @ctxt:  an XML parser context
5581
 *
5582
 * DEPRECATED: Internal function, don't use.
5583
 *
5584
 * Parse a notation declaration. Always consumes '<!'.
5585
 *
5586
 * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID |  PublicID) S? '>'
5587
 *
5588
 * Hence there is actually 3 choices:
5589
 *     'PUBLIC' S PubidLiteral
5590
 *     'PUBLIC' S PubidLiteral S SystemLiteral
5591
 * and 'SYSTEM' S SystemLiteral
5592
 *
5593
 * See the NOTE on xmlParseExternalID().
5594
 */
5595
5596
void
5597
4.70k
xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
5598
4.70k
    const xmlChar *name;
5599
4.70k
    xmlChar *Pubid;
5600
4.70k
    xmlChar *Systemid;
5601
5602
4.70k
    if ((CUR != '<') || (NXT(1) != '!'))
5603
0
        return;
5604
4.70k
    SKIP(2);
5605
5606
4.70k
    if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
5607
4.68k
  int inputid = ctxt->input->id;
5608
4.68k
  SKIP(8);
5609
4.68k
  if (SKIP_BLANKS_PE == 0) {
5610
209
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5611
209
         "Space required after '<!NOTATION'\n");
5612
209
      return;
5613
209
  }
5614
5615
4.47k
        name = xmlParseName(ctxt);
5616
4.47k
  if (name == NULL) {
5617
220
      xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
5618
220
      return;
5619
220
  }
5620
4.25k
  if (xmlStrchr(name, ':') != NULL) {
5621
247
      xmlNsErr(ctxt, XML_NS_ERR_COLON,
5622
247
         "colons are forbidden from notation names '%s'\n",
5623
247
         name, NULL, NULL);
5624
247
  }
5625
4.25k
  if (SKIP_BLANKS_PE == 0) {
5626
198
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5627
198
         "Space required after the NOTATION name'\n");
5628
198
      return;
5629
198
  }
5630
5631
  /*
5632
   * Parse the IDs.
5633
   */
5634
4.06k
  Systemid = xmlParseExternalID(ctxt, &Pubid, 0);
5635
4.06k
  SKIP_BLANKS_PE;
5636
5637
4.06k
  if (RAW == '>') {
5638
1.48k
      if (inputid != ctxt->input->id) {
5639
140
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5640
140
                         "Notation declaration doesn't start and stop"
5641
140
                               " in the same entity\n");
5642
140
      }
5643
1.48k
      NEXT;
5644
1.48k
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
5645
1.48k
    (ctxt->sax->notationDecl != NULL))
5646
1.40k
    ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
5647
2.57k
  } else {
5648
2.57k
      xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
5649
2.57k
  }
5650
4.06k
  if (Systemid != NULL) xmlFree(Systemid);
5651
4.06k
  if (Pubid != NULL) xmlFree(Pubid);
5652
4.06k
    }
5653
4.70k
}
5654
5655
/**
5656
 * xmlParseEntityDecl:
5657
 * @ctxt:  an XML parser context
5658
 *
5659
 * DEPRECATED: Internal function, don't use.
5660
 *
5661
 * Parse an entity declaration. Always consumes '<!'.
5662
 *
5663
 * [70] EntityDecl ::= GEDecl | PEDecl
5664
 *
5665
 * [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
5666
 *
5667
 * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
5668
 *
5669
 * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
5670
 *
5671
 * [74] PEDef ::= EntityValue | ExternalID
5672
 *
5673
 * [76] NDataDecl ::= S 'NDATA' S Name
5674
 *
5675
 * [ VC: Notation Declared ]
5676
 * The Name must match the declared name of a notation.
5677
 */
5678
5679
void
5680
20.0k
xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
5681
20.0k
    const xmlChar *name = NULL;
5682
20.0k
    xmlChar *value = NULL;
5683
20.0k
    xmlChar *URI = NULL, *literal = NULL;
5684
20.0k
    const xmlChar *ndata = NULL;
5685
20.0k
    int isParameter = 0;
5686
20.0k
    xmlChar *orig = NULL;
5687
5688
20.0k
    if ((CUR != '<') || (NXT(1) != '!'))
5689
0
        return;
5690
20.0k
    SKIP(2);
5691
5692
    /* GROW; done in the caller */
5693
20.0k
    if (CMP6(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'Y')) {
5694
19.9k
  int inputid = ctxt->input->id;
5695
19.9k
  SKIP(6);
5696
19.9k
  if (SKIP_BLANKS_PE == 0) {
5697
17.8k
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5698
17.8k
         "Space required after '<!ENTITY'\n");
5699
17.8k
  }
5700
5701
19.9k
  if (RAW == '%') {
5702
4.60k
      NEXT;
5703
4.60k
      if (SKIP_BLANKS_PE == 0) {
5704
3.65k
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5705
3.65k
             "Space required after '%%'\n");
5706
3.65k
      }
5707
4.60k
      isParameter = 1;
5708
4.60k
  }
5709
5710
19.9k
        name = xmlParseName(ctxt);
5711
19.9k
  if (name == NULL) {
5712
458
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
5713
458
                     "xmlParseEntityDecl: no name\n");
5714
458
            return;
5715
458
  }
5716
19.5k
  if (xmlStrchr(name, ':') != NULL) {
5717
3.86k
      xmlNsErr(ctxt, XML_NS_ERR_COLON,
5718
3.86k
         "colons are forbidden from entities names '%s'\n",
5719
3.86k
         name, NULL, NULL);
5720
3.86k
  }
5721
19.5k
  if (SKIP_BLANKS_PE == 0) {
5722
14.6k
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5723
14.6k
         "Space required after the entity name\n");
5724
14.6k
  }
5725
5726
  /*
5727
   * handle the various case of definitions...
5728
   */
5729
19.5k
  if (isParameter) {
5730
4.28k
      if ((RAW == '"') || (RAW == '\'')) {
5731
2.96k
          value = xmlParseEntityValue(ctxt, &orig);
5732
2.96k
    if (value) {
5733
2.88k
        if ((ctxt->sax != NULL) &&
5734
2.88k
      (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5735
2.63k
      ctxt->sax->entityDecl(ctxt->userData, name,
5736
2.63k
                        XML_INTERNAL_PARAMETER_ENTITY,
5737
2.63k
            NULL, NULL, value);
5738
2.88k
    }
5739
2.96k
      } else {
5740
1.31k
          URI = xmlParseExternalID(ctxt, &literal, 1);
5741
1.31k
    if ((URI == NULL) && (literal == NULL)) {
5742
243
        xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
5743
243
    }
5744
1.31k
    if (URI) {
5745
861
        xmlURIPtr uri;
5746
5747
861
                    if (xmlParseURISafe((const char *) URI, &uri) < 0) {
5748
0
                        xmlErrMemory(ctxt);
5749
861
                    } else if (uri == NULL) {
5750
                        /*
5751
                         * This really ought to be a well formedness error
5752
                         * but the XML Core WG decided otherwise c.f. issue
5753
                         * E26 of the XML erratas.
5754
                         */
5755
244
                        xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
5756
244
                                     "Invalid URI: %s\n", URI);
5757
617
                    } else if (uri->fragment != NULL) {
5758
                        /*
5759
                         * Okay this is foolish to block those but not
5760
                         * invalid URIs.
5761
                         */
5762
194
                        xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
5763
423
                    } else {
5764
423
                        if ((ctxt->sax != NULL) &&
5765
423
                            (!ctxt->disableSAX) &&
5766
423
                            (ctxt->sax->entityDecl != NULL))
5767
384
                            ctxt->sax->entityDecl(ctxt->userData, name,
5768
384
                                        XML_EXTERNAL_PARAMETER_ENTITY,
5769
384
                                        literal, URI, NULL);
5770
423
                    }
5771
861
        xmlFreeURI(uri);
5772
861
    }
5773
1.31k
      }
5774
15.2k
  } else {
5775
15.2k
      if ((RAW == '"') || (RAW == '\'')) {
5776
11.3k
          value = xmlParseEntityValue(ctxt, &orig);
5777
11.3k
    if ((ctxt->sax != NULL) &&
5778
11.3k
        (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5779
10.5k
        ctxt->sax->entityDecl(ctxt->userData, name,
5780
10.5k
        XML_INTERNAL_GENERAL_ENTITY,
5781
10.5k
        NULL, NULL, value);
5782
    /*
5783
     * For expat compatibility in SAX mode.
5784
     */
5785
11.3k
    if ((ctxt->myDoc == NULL) ||
5786
11.3k
        (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
5787
254
        if (ctxt->myDoc == NULL) {
5788
137
      ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
5789
137
      if (ctxt->myDoc == NULL) {
5790
0
          xmlErrMemory(ctxt);
5791
0
          goto done;
5792
0
      }
5793
137
      ctxt->myDoc->properties = XML_DOC_INTERNAL;
5794
137
        }
5795
254
        if (ctxt->myDoc->intSubset == NULL) {
5796
137
      ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
5797
137
              BAD_CAST "fake", NULL, NULL);
5798
137
                        if (ctxt->myDoc->intSubset == NULL) {
5799
0
                            xmlErrMemory(ctxt);
5800
0
                            goto done;
5801
0
                        }
5802
137
                    }
5803
5804
254
        xmlSAX2EntityDecl(ctxt, name, XML_INTERNAL_GENERAL_ENTITY,
5805
254
                    NULL, NULL, value);
5806
254
    }
5807
11.3k
      } else {
5808
3.92k
          URI = xmlParseExternalID(ctxt, &literal, 1);
5809
3.92k
    if ((URI == NULL) && (literal == NULL)) {
5810
2.53k
        xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
5811
2.53k
    }
5812
3.92k
    if (URI) {
5813
992
        xmlURIPtr uri;
5814
5815
992
                    if (xmlParseURISafe((const char *) URI, &uri) < 0) {
5816
0
                        xmlErrMemory(ctxt);
5817
992
                    } else if (uri == NULL) {
5818
                        /*
5819
                         * This really ought to be a well formedness error
5820
                         * but the XML Core WG decided otherwise c.f. issue
5821
                         * E26 of the XML erratas.
5822
                         */
5823
289
                        xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
5824
289
                                     "Invalid URI: %s\n", URI);
5825
703
                    } else if (uri->fragment != NULL) {
5826
                        /*
5827
                         * Okay this is foolish to block those but not
5828
                         * invalid URIs.
5829
                         */
5830
228
                        xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
5831
228
                    }
5832
992
                    xmlFreeURI(uri);
5833
992
    }
5834
3.92k
    if ((RAW != '>') && (SKIP_BLANKS_PE == 0)) {
5835
645
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5836
645
           "Space required before 'NDATA'\n");
5837
645
    }
5838
3.92k
    if (CMP5(CUR_PTR, 'N', 'D', 'A', 'T', 'A')) {
5839
509
        SKIP(5);
5840
509
        if (SKIP_BLANKS_PE == 0) {
5841
307
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5842
307
               "Space required after 'NDATA'\n");
5843
307
        }
5844
509
        ndata = xmlParseName(ctxt);
5845
509
        if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
5846
509
            (ctxt->sax->unparsedEntityDecl != NULL))
5847
439
      ctxt->sax->unparsedEntityDecl(ctxt->userData, name,
5848
439
            literal, URI, ndata);
5849
3.41k
    } else {
5850
3.41k
        if ((ctxt->sax != NULL) &&
5851
3.41k
            (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5852
3.25k
      ctxt->sax->entityDecl(ctxt->userData, name,
5853
3.25k
            XML_EXTERNAL_GENERAL_PARSED_ENTITY,
5854
3.25k
            literal, URI, NULL);
5855
        /*
5856
         * For expat compatibility in SAX mode.
5857
         * assuming the entity replacement was asked for
5858
         */
5859
3.41k
        if ((ctxt->replaceEntities != 0) &&
5860
3.41k
      ((ctxt->myDoc == NULL) ||
5861
0
      (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE)))) {
5862
0
      if (ctxt->myDoc == NULL) {
5863
0
          ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
5864
0
          if (ctxt->myDoc == NULL) {
5865
0
              xmlErrMemory(ctxt);
5866
0
        goto done;
5867
0
          }
5868
0
          ctxt->myDoc->properties = XML_DOC_INTERNAL;
5869
0
      }
5870
5871
0
      if (ctxt->myDoc->intSubset == NULL) {
5872
0
          ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
5873
0
            BAD_CAST "fake", NULL, NULL);
5874
0
                            if (ctxt->myDoc->intSubset == NULL) {
5875
0
                                xmlErrMemory(ctxt);
5876
0
                                goto done;
5877
0
                            }
5878
0
                        }
5879
0
      xmlSAX2EntityDecl(ctxt, name,
5880
0
                  XML_EXTERNAL_GENERAL_PARSED_ENTITY,
5881
0
                  literal, URI, NULL);
5882
0
        }
5883
3.41k
    }
5884
3.92k
      }
5885
15.2k
  }
5886
19.5k
  SKIP_BLANKS_PE;
5887
19.5k
  if (RAW != '>') {
5888
1.26k
      xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
5889
1.26k
              "xmlParseEntityDecl: entity %s not terminated\n", name);
5890
1.26k
      xmlHaltParser(ctxt);
5891
18.2k
  } else {
5892
18.2k
      if (inputid != ctxt->input->id) {
5893
244
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5894
244
                         "Entity declaration doesn't start and stop in"
5895
244
                               " the same entity\n");
5896
244
      }
5897
18.2k
      NEXT;
5898
18.2k
  }
5899
19.5k
  if (orig != NULL) {
5900
      /*
5901
       * Ugly mechanism to save the raw entity value.
5902
       */
5903
13.2k
      xmlEntityPtr cur = NULL;
5904
5905
13.2k
      if (isParameter) {
5906
2.88k
          if ((ctxt->sax != NULL) &&
5907
2.88k
        (ctxt->sax->getParameterEntity != NULL))
5908
2.88k
        cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
5909
10.4k
      } else {
5910
10.4k
          if ((ctxt->sax != NULL) &&
5911
10.4k
        (ctxt->sax->getEntity != NULL))
5912
10.4k
        cur = ctxt->sax->getEntity(ctxt->userData, name);
5913
10.4k
    if ((cur == NULL) && (ctxt->userData==ctxt)) {
5914
496
        cur = xmlSAX2GetEntity(ctxt, name);
5915
496
    }
5916
10.4k
      }
5917
13.2k
            if ((cur != NULL) && (cur->orig == NULL)) {
5918
5.04k
    cur->orig = orig;
5919
5.04k
                orig = NULL;
5920
5.04k
      }
5921
13.2k
  }
5922
5923
19.5k
done:
5924
19.5k
  if (value != NULL) xmlFree(value);
5925
19.5k
  if (URI != NULL) xmlFree(URI);
5926
19.5k
  if (literal != NULL) xmlFree(literal);
5927
19.5k
        if (orig != NULL) xmlFree(orig);
5928
19.5k
    }
5929
20.0k
}
5930
5931
/**
5932
 * xmlParseDefaultDecl:
5933
 * @ctxt:  an XML parser context
5934
 * @value:  Receive a possible fixed default value for the attribute
5935
 *
5936
 * DEPRECATED: Internal function, don't use.
5937
 *
5938
 * Parse an attribute default declaration
5939
 *
5940
 * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
5941
 *
5942
 * [ VC: Required Attribute ]
5943
 * if the default declaration is the keyword #REQUIRED, then the
5944
 * attribute must be specified for all elements of the type in the
5945
 * attribute-list declaration.
5946
 *
5947
 * [ VC: Attribute Default Legal ]
5948
 * The declared default value must meet the lexical constraints of
5949
 * the declared attribute type c.f. xmlValidateAttributeDecl()
5950
 *
5951
 * [ VC: Fixed Attribute Default ]
5952
 * if an attribute has a default value declared with the #FIXED
5953
 * keyword, instances of that attribute must match the default value.
5954
 *
5955
 * [ WFC: No < in Attribute Values ]
5956
 * handled in xmlParseAttValue()
5957
 *
5958
 * returns: XML_ATTRIBUTE_NONE, XML_ATTRIBUTE_REQUIRED, XML_ATTRIBUTE_IMPLIED
5959
 *          or XML_ATTRIBUTE_FIXED.
5960
 */
5961
5962
int
5963
38.6k
xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
5964
38.6k
    int val;
5965
38.6k
    xmlChar *ret;
5966
5967
38.6k
    *value = NULL;
5968
38.6k
    if (CMP9(CUR_PTR, '#', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D')) {
5969
389
  SKIP(9);
5970
389
  return(XML_ATTRIBUTE_REQUIRED);
5971
389
    }
5972
38.2k
    if (CMP8(CUR_PTR, '#', 'I', 'M', 'P', 'L', 'I', 'E', 'D')) {
5973
791
  SKIP(8);
5974
791
  return(XML_ATTRIBUTE_IMPLIED);
5975
791
    }
5976
37.4k
    val = XML_ATTRIBUTE_NONE;
5977
37.4k
    if (CMP6(CUR_PTR, '#', 'F', 'I', 'X', 'E', 'D')) {
5978
417
  SKIP(6);
5979
417
  val = XML_ATTRIBUTE_FIXED;
5980
417
  if (SKIP_BLANKS_PE == 0) {
5981
198
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5982
198
         "Space required after '#FIXED'\n");
5983
198
  }
5984
417
    }
5985
37.4k
    ret = xmlParseAttValue(ctxt);
5986
37.4k
    if (ret == NULL) {
5987
13.3k
  xmlFatalErrMsg(ctxt, (xmlParserErrors)ctxt->errNo,
5988
13.3k
           "Attribute default value declaration error\n");
5989
13.3k
    } else
5990
24.0k
        *value = ret;
5991
37.4k
    return(val);
5992
38.2k
}
5993
5994
/**
5995
 * xmlParseNotationType:
5996
 * @ctxt:  an XML parser context
5997
 *
5998
 * DEPRECATED: Internal function, don't use.
5999
 *
6000
 * parse an Notation attribute type.
6001
 *
6002
 * Note: the leading 'NOTATION' S part has already being parsed...
6003
 *
6004
 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
6005
 *
6006
 * [ VC: Notation Attributes ]
6007
 * Values of this type must match one of the notation names included
6008
 * in the declaration; all notation names in the declaration must be declared.
6009
 *
6010
 * Returns: the notation attribute tree built while parsing
6011
 */
6012
6013
xmlEnumerationPtr
6014
1.12k
xmlParseNotationType(xmlParserCtxtPtr ctxt) {
6015
1.12k
    const xmlChar *name;
6016
1.12k
    xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
6017
6018
1.12k
    if (RAW != '(') {
6019
256
  xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
6020
256
  return(NULL);
6021
256
    }
6022
2.47k
    do {
6023
2.47k
        NEXT;
6024
2.47k
  SKIP_BLANKS_PE;
6025
2.47k
        name = xmlParseName(ctxt);
6026
2.47k
  if (name == NULL) {
6027
260
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6028
260
         "Name expected in NOTATION declaration\n");
6029
260
            xmlFreeEnumeration(ret);
6030
260
      return(NULL);
6031
260
  }
6032
2.21k
  tmp = ret;
6033
4.80k
  while (tmp != NULL) {
6034
3.46k
      if (xmlStrEqual(name, tmp->name)) {
6035
876
    xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
6036
876
    "standalone: attribute notation value token %s duplicated\n",
6037
876
         name, NULL);
6038
876
    if (!xmlDictOwns(ctxt->dict, name))
6039
0
        xmlFree((xmlChar *) name);
6040
876
    break;
6041
876
      }
6042
2.58k
      tmp = tmp->next;
6043
2.58k
  }
6044
2.21k
  if (tmp == NULL) {
6045
1.34k
      cur = xmlCreateEnumeration(name);
6046
1.34k
      if (cur == NULL) {
6047
0
                xmlErrMemory(ctxt);
6048
0
                xmlFreeEnumeration(ret);
6049
0
                return(NULL);
6050
0
            }
6051
1.34k
      if (last == NULL) ret = last = cur;
6052
668
      else {
6053
668
    last->next = cur;
6054
668
    last = cur;
6055
668
      }
6056
1.34k
  }
6057
2.21k
  SKIP_BLANKS_PE;
6058
2.21k
    } while (RAW == '|');
6059
606
    if (RAW != ')') {
6060
325
  xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
6061
325
        xmlFreeEnumeration(ret);
6062
325
  return(NULL);
6063
325
    }
6064
281
    NEXT;
6065
281
    return(ret);
6066
606
}
6067
6068
/**
6069
 * xmlParseEnumerationType:
6070
 * @ctxt:  an XML parser context
6071
 *
6072
 * DEPRECATED: Internal function, don't use.
6073
 *
6074
 * parse an Enumeration attribute type.
6075
 *
6076
 * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
6077
 *
6078
 * [ VC: Enumeration ]
6079
 * Values of this type must match one of the Nmtoken tokens in
6080
 * the declaration
6081
 *
6082
 * Returns: the enumeration attribute tree built while parsing
6083
 */
6084
6085
xmlEnumerationPtr
6086
9.58k
xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
6087
9.58k
    xmlChar *name;
6088
9.58k
    xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
6089
6090
9.58k
    if (RAW != '(') {
6091
799
  xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_STARTED, NULL);
6092
799
  return(NULL);
6093
799
    }
6094
10.5k
    do {
6095
10.5k
        NEXT;
6096
10.5k
  SKIP_BLANKS_PE;
6097
10.5k
        name = xmlParseNmtoken(ctxt);
6098
10.5k
  if (name == NULL) {
6099
270
      xmlFatalErr(ctxt, XML_ERR_NMTOKEN_REQUIRED, NULL);
6100
270
      return(ret);
6101
270
  }
6102
10.2k
  tmp = ret;
6103
14.8k
  while (tmp != NULL) {
6104
5.29k
      if (xmlStrEqual(name, tmp->name)) {
6105
663
    xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
6106
663
    "standalone: attribute enumeration value token %s duplicated\n",
6107
663
         name, NULL);
6108
663
    if (!xmlDictOwns(ctxt->dict, name))
6109
663
        xmlFree(name);
6110
663
    break;
6111
663
      }
6112
4.63k
      tmp = tmp->next;
6113
4.63k
  }
6114
10.2k
  if (tmp == NULL) {
6115
9.59k
      cur = xmlCreateEnumeration(name);
6116
9.59k
      if (!xmlDictOwns(ctxt->dict, name))
6117
9.59k
    xmlFree(name);
6118
9.59k
      if (cur == NULL) {
6119
0
                xmlErrMemory(ctxt);
6120
0
                xmlFreeEnumeration(ret);
6121
0
                return(NULL);
6122
0
            }
6123
9.59k
      if (last == NULL) ret = last = cur;
6124
1.06k
      else {
6125
1.06k
    last->next = cur;
6126
1.06k
    last = cur;
6127
1.06k
      }
6128
9.59k
  }
6129
10.2k
  SKIP_BLANKS_PE;
6130
10.2k
    } while (RAW == '|');
6131
8.51k
    if (RAW != ')') {
6132
1.92k
  xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_FINISHED, NULL);
6133
1.92k
  return(ret);
6134
1.92k
    }
6135
6.58k
    NEXT;
6136
6.58k
    return(ret);
6137
8.51k
}
6138
6139
/**
6140
 * xmlParseEnumeratedType:
6141
 * @ctxt:  an XML parser context
6142
 * @tree:  the enumeration tree built while parsing
6143
 *
6144
 * DEPRECATED: Internal function, don't use.
6145
 *
6146
 * parse an Enumerated attribute type.
6147
 *
6148
 * [57] EnumeratedType ::= NotationType | Enumeration
6149
 *
6150
 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
6151
 *
6152
 *
6153
 * Returns: XML_ATTRIBUTE_ENUMERATION or XML_ATTRIBUTE_NOTATION
6154
 */
6155
6156
int
6157
10.8k
xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
6158
10.8k
    if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
6159
1.31k
  SKIP(8);
6160
1.31k
  if (SKIP_BLANKS_PE == 0) {
6161
195
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6162
195
         "Space required after 'NOTATION'\n");
6163
195
      return(0);
6164
195
  }
6165
1.12k
  *tree = xmlParseNotationType(ctxt);
6166
1.12k
  if (*tree == NULL) return(0);
6167
281
  return(XML_ATTRIBUTE_NOTATION);
6168
1.12k
    }
6169
9.58k
    *tree = xmlParseEnumerationType(ctxt);
6170
9.58k
    if (*tree == NULL) return(0);
6171
8.53k
    return(XML_ATTRIBUTE_ENUMERATION);
6172
9.58k
}
6173
6174
/**
6175
 * xmlParseAttributeType:
6176
 * @ctxt:  an XML parser context
6177
 * @tree:  the enumeration tree built while parsing
6178
 *
6179
 * DEPRECATED: Internal function, don't use.
6180
 *
6181
 * parse the Attribute list def for an element
6182
 *
6183
 * [54] AttType ::= StringType | TokenizedType | EnumeratedType
6184
 *
6185
 * [55] StringType ::= 'CDATA'
6186
 *
6187
 * [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' |
6188
 *                        'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
6189
 *
6190
 * Validity constraints for attribute values syntax are checked in
6191
 * xmlValidateAttributeValue()
6192
 *
6193
 * [ VC: ID ]
6194
 * Values of type ID must match the Name production. A name must not
6195
 * appear more than once in an XML document as a value of this type;
6196
 * i.e., ID values must uniquely identify the elements which bear them.
6197
 *
6198
 * [ VC: One ID per Element Type ]
6199
 * No element type may have more than one ID attribute specified.
6200
 *
6201
 * [ VC: ID Attribute Default ]
6202
 * An ID attribute must have a declared default of #IMPLIED or #REQUIRED.
6203
 *
6204
 * [ VC: IDREF ]
6205
 * Values of type IDREF must match the Name production, and values
6206
 * of type IDREFS must match Names; each IDREF Name must match the value
6207
 * of an ID attribute on some element in the XML document; i.e. IDREF
6208
 * values must match the value of some ID attribute.
6209
 *
6210
 * [ VC: Entity Name ]
6211
 * Values of type ENTITY must match the Name production, values
6212
 * of type ENTITIES must match Names; each Entity Name must match the
6213
 * name of an unparsed entity declared in the DTD.
6214
 *
6215
 * [ VC: Name Token ]
6216
 * Values of type NMTOKEN must match the Nmtoken production; values
6217
 * of type NMTOKENS must match Nmtokens.
6218
 *
6219
 * Returns the attribute type
6220
 */
6221
int
6222
43.0k
xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
6223
43.0k
    if (CMP5(CUR_PTR, 'C', 'D', 'A', 'T', 'A')) {
6224
2.57k
  SKIP(5);
6225
2.57k
  return(XML_ATTRIBUTE_CDATA);
6226
40.4k
     } else if (CMP6(CUR_PTR, 'I', 'D', 'R', 'E', 'F', 'S')) {
6227
3.39k
  SKIP(6);
6228
3.39k
  return(XML_ATTRIBUTE_IDREFS);
6229
37.0k
     } else if (CMP5(CUR_PTR, 'I', 'D', 'R', 'E', 'F')) {
6230
838
  SKIP(5);
6231
838
  return(XML_ATTRIBUTE_IDREF);
6232
36.2k
     } else if ((RAW == 'I') && (NXT(1) == 'D')) {
6233
21.5k
        SKIP(2);
6234
21.5k
  return(XML_ATTRIBUTE_ID);
6235
21.5k
     } else if (CMP6(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'Y')) {
6236
816
  SKIP(6);
6237
816
  return(XML_ATTRIBUTE_ENTITY);
6238
13.8k
     } else if (CMP8(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S')) {
6239
620
  SKIP(8);
6240
620
  return(XML_ATTRIBUTE_ENTITIES);
6241
13.2k
     } else if (CMP8(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S')) {
6242
622
  SKIP(8);
6243
622
  return(XML_ATTRIBUTE_NMTOKENS);
6244
12.6k
     } else if (CMP7(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N')) {
6245
1.75k
  SKIP(7);
6246
1.75k
  return(XML_ATTRIBUTE_NMTOKEN);
6247
1.75k
     }
6248
10.8k
     return(xmlParseEnumeratedType(ctxt, tree));
6249
43.0k
}
6250
6251
/**
6252
 * xmlParseAttributeListDecl:
6253
 * @ctxt:  an XML parser context
6254
 *
6255
 * DEPRECATED: Internal function, don't use.
6256
 *
6257
 * Parse an attribute list declaration for an element. Always consumes '<!'.
6258
 *
6259
 * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
6260
 *
6261
 * [53] AttDef ::= S Name S AttType S DefaultDecl
6262
 *
6263
 */
6264
void
6265
33.2k
xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
6266
33.2k
    const xmlChar *elemName;
6267
33.2k
    const xmlChar *attrName;
6268
33.2k
    xmlEnumerationPtr tree;
6269
6270
33.2k
    if ((CUR != '<') || (NXT(1) != '!'))
6271
0
        return;
6272
33.2k
    SKIP(2);
6273
6274
33.2k
    if (CMP7(CUR_PTR, 'A', 'T', 'T', 'L', 'I', 'S', 'T')) {
6275
33.1k
  int inputid = ctxt->input->id;
6276
6277
33.1k
  SKIP(7);
6278
33.1k
  if (SKIP_BLANKS_PE == 0) {
6279
31.6k
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6280
31.6k
                     "Space required after '<!ATTLIST'\n");
6281
31.6k
  }
6282
33.1k
        elemName = xmlParseName(ctxt);
6283
33.1k
  if (elemName == NULL) {
6284
360
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6285
360
         "ATTLIST: no name for Element\n");
6286
360
      return;
6287
360
  }
6288
32.8k
  SKIP_BLANKS_PE;
6289
32.8k
  GROW;
6290
68.4k
  while ((RAW != '>') && (PARSER_STOPPED(ctxt) == 0)) {
6291
61.7k
      int type;
6292
61.7k
      int def;
6293
61.7k
      xmlChar *defaultValue = NULL;
6294
6295
61.7k
      GROW;
6296
61.7k
            tree = NULL;
6297
61.7k
      attrName = xmlParseName(ctxt);
6298
61.7k
      if (attrName == NULL) {
6299
18.0k
    xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6300
18.0k
             "ATTLIST: no name for Attribute\n");
6301
18.0k
    break;
6302
18.0k
      }
6303
43.6k
      GROW;
6304
43.6k
      if (SKIP_BLANKS_PE == 0) {
6305
646
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6306
646
            "Space required after the attribute name\n");
6307
646
    break;
6308
646
      }
6309
6310
43.0k
      type = xmlParseAttributeType(ctxt, &tree);
6311
43.0k
      if (type <= 0) {
6312
2.08k
          break;
6313
2.08k
      }
6314
6315
40.9k
      GROW;
6316
40.9k
      if (SKIP_BLANKS_PE == 0) {
6317
2.34k
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6318
2.34k
             "Space required after the attribute type\n");
6319
2.34k
          if (tree != NULL)
6320
1.95k
        xmlFreeEnumeration(tree);
6321
2.34k
    break;
6322
2.34k
      }
6323
6324
38.6k
      def = xmlParseDefaultDecl(ctxt, &defaultValue);
6325
38.6k
      if (def <= 0) {
6326
0
                if (defaultValue != NULL)
6327
0
        xmlFree(defaultValue);
6328
0
          if (tree != NULL)
6329
0
        xmlFreeEnumeration(tree);
6330
0
          break;
6331
0
      }
6332
38.6k
      if ((type != XML_ATTRIBUTE_CDATA) && (defaultValue != NULL))
6333
21.8k
          xmlAttrNormalizeSpace(defaultValue, defaultValue);
6334
6335
38.6k
      GROW;
6336
38.6k
            if (RAW != '>') {
6337
32.2k
    if (SKIP_BLANKS_PE == 0) {
6338
3.00k
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6339
3.00k
      "Space required after the attribute default value\n");
6340
3.00k
        if (defaultValue != NULL)
6341
415
      xmlFree(defaultValue);
6342
3.00k
        if (tree != NULL)
6343
254
      xmlFreeEnumeration(tree);
6344
3.00k
        break;
6345
3.00k
    }
6346
32.2k
      }
6347
35.5k
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
6348
35.5k
    (ctxt->sax->attributeDecl != NULL))
6349
33.4k
    ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
6350
33.4k
                          type, def, defaultValue, tree);
6351
2.11k
      else if (tree != NULL)
6352
201
    xmlFreeEnumeration(tree);
6353
6354
35.5k
      if ((ctxt->sax2) && (defaultValue != NULL) &&
6355
35.5k
          (def != XML_ATTRIBUTE_IMPLIED) &&
6356
35.5k
    (def != XML_ATTRIBUTE_REQUIRED)) {
6357
20.8k
    xmlAddDefAttrs(ctxt, elemName, attrName, defaultValue);
6358
20.8k
      }
6359
35.5k
      if (ctxt->sax2) {
6360
32.4k
    xmlAddSpecialAttr(ctxt, elemName, attrName, type);
6361
32.4k
      }
6362
35.5k
      if (defaultValue != NULL)
6363
23.6k
          xmlFree(defaultValue);
6364
35.5k
      GROW;
6365
35.5k
  }
6366
32.8k
  if (RAW == '>') {
6367
7.77k
      if (inputid != ctxt->input->id) {
6368
210
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6369
210
                               "Attribute list declaration doesn't start and"
6370
210
                               " stop in the same entity\n");
6371
210
      }
6372
7.77k
      NEXT;
6373
7.77k
  }
6374
32.8k
    }
6375
33.2k
}
6376
6377
/**
6378
 * xmlParseElementMixedContentDecl:
6379
 * @ctxt:  an XML parser context
6380
 * @inputchk:  the input used for the current entity, needed for boundary checks
6381
 *
6382
 * DEPRECATED: Internal function, don't use.
6383
 *
6384
 * parse the declaration for a Mixed Element content
6385
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6386
 *
6387
 * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' |
6388
 *                '(' S? '#PCDATA' S? ')'
6389
 *
6390
 * [ VC: Proper Group/PE Nesting ] applies to [51] too (see [49])
6391
 *
6392
 * [ VC: No Duplicate Types ]
6393
 * The same name must not appear more than once in a single
6394
 * mixed-content declaration.
6395
 *
6396
 * returns: the list of the xmlElementContentPtr describing the element choices
6397
 */
6398
xmlElementContentPtr
6399
2.32k
xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
6400
2.32k
    xmlElementContentPtr ret = NULL, cur = NULL, n;
6401
2.32k
    const xmlChar *elem = NULL;
6402
6403
2.32k
    GROW;
6404
2.32k
    if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
6405
2.32k
  SKIP(7);
6406
2.32k
  SKIP_BLANKS_PE;
6407
2.32k
  if (RAW == ')') {
6408
470
      if (ctxt->input->id != inputchk) {
6409
67
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6410
67
                               "Element content declaration doesn't start and"
6411
67
                               " stop in the same entity\n");
6412
67
      }
6413
470
      NEXT;
6414
470
      ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
6415
470
      if (ret == NULL)
6416
0
                goto mem_error;
6417
470
      if (RAW == '*') {
6418
202
    ret->ocur = XML_ELEMENT_CONTENT_MULT;
6419
202
    NEXT;
6420
202
      }
6421
470
      return(ret);
6422
470
  }
6423
1.85k
  if ((RAW == '(') || (RAW == '|')) {
6424
995
      ret = cur = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
6425
995
      if (ret == NULL)
6426
0
                goto mem_error;
6427
995
  }
6428
2.65k
  while ((RAW == '|') && (PARSER_STOPPED(ctxt) == 0)) {
6429
1.26k
      NEXT;
6430
1.26k
            n = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6431
1.26k
            if (n == NULL)
6432
0
                goto mem_error;
6433
1.26k
      if (elem == NULL) {
6434
994
    n->c1 = cur;
6435
994
    if (cur != NULL)
6436
994
        cur->parent = n;
6437
994
    ret = cur = n;
6438
994
      } else {
6439
275
          cur->c2 = n;
6440
275
    n->parent = cur;
6441
275
    n->c1 = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6442
275
                if (n->c1 == NULL)
6443
0
                    goto mem_error;
6444
275
    n->c1->parent = n;
6445
275
    cur = n;
6446
275
      }
6447
1.26k
      SKIP_BLANKS_PE;
6448
1.26k
      elem = xmlParseName(ctxt);
6449
1.26k
      if (elem == NULL) {
6450
466
    xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6451
466
      "xmlParseElementMixedContentDecl : Name expected\n");
6452
466
    xmlFreeDocElementContent(ctxt->myDoc, ret);
6453
466
    return(NULL);
6454
466
      }
6455
803
      SKIP_BLANKS_PE;
6456
803
      GROW;
6457
803
  }
6458
1.38k
  if ((RAW == ')') && (NXT(1) == '*')) {
6459
518
      if (elem != NULL) {
6460
518
    cur->c2 = xmlNewDocElementContent(ctxt->myDoc, elem,
6461
518
                                   XML_ELEMENT_CONTENT_ELEMENT);
6462
518
    if (cur->c2 == NULL)
6463
0
                    goto mem_error;
6464
518
    cur->c2->parent = cur;
6465
518
            }
6466
518
            if (ret != NULL)
6467
518
                ret->ocur = XML_ELEMENT_CONTENT_MULT;
6468
518
      if (ctxt->input->id != inputchk) {
6469
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6470
0
                               "Element content declaration doesn't start and"
6471
0
                               " stop in the same entity\n");
6472
0
      }
6473
518
      SKIP(2);
6474
867
  } else {
6475
867
      xmlFreeDocElementContent(ctxt->myDoc, ret);
6476
867
      xmlFatalErr(ctxt, XML_ERR_MIXED_NOT_STARTED, NULL);
6477
867
      return(NULL);
6478
867
  }
6479
6480
1.38k
    } else {
6481
0
  xmlFatalErr(ctxt, XML_ERR_PCDATA_REQUIRED, NULL);
6482
0
    }
6483
518
    return(ret);
6484
6485
0
mem_error:
6486
0
    xmlErrMemory(ctxt);
6487
0
    xmlFreeDocElementContent(ctxt->myDoc, ret);
6488
0
    return(NULL);
6489
2.32k
}
6490
6491
/**
6492
 * xmlParseElementChildrenContentDeclPriv:
6493
 * @ctxt:  an XML parser context
6494
 * @inputchk:  the input used for the current entity, needed for boundary checks
6495
 * @depth: the level of recursion
6496
 *
6497
 * parse the declaration for a Mixed Element content
6498
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6499
 *
6500
 *
6501
 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
6502
 *
6503
 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
6504
 *
6505
 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
6506
 *
6507
 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
6508
 *
6509
 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
6510
 * TODO Parameter-entity replacement text must be properly nested
6511
 *  with parenthesized groups. That is to say, if either of the
6512
 *  opening or closing parentheses in a choice, seq, or Mixed
6513
 *  construct is contained in the replacement text for a parameter
6514
 *  entity, both must be contained in the same replacement text. For
6515
 *  interoperability, if a parameter-entity reference appears in a
6516
 *  choice, seq, or Mixed construct, its replacement text should not
6517
 *  be empty, and neither the first nor last non-blank character of
6518
 *  the replacement text should be a connector (| or ,).
6519
 *
6520
 * Returns the tree of xmlElementContentPtr describing the element
6521
 *          hierarchy.
6522
 */
6523
static xmlElementContentPtr
6524
xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
6525
15.3k
                                       int depth) {
6526
15.3k
    int maxDepth = (ctxt->options & XML_PARSE_HUGE) ? 2048 : 256;
6527
15.3k
    xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
6528
15.3k
    const xmlChar *elem;
6529
15.3k
    xmlChar type = 0;
6530
6531
15.3k
    if (depth > maxDepth) {
6532
1
        xmlFatalErrMsgInt(ctxt, XML_ERR_RESOURCE_LIMIT,
6533
1
                "xmlParseElementChildrenContentDecl : depth %d too deep, "
6534
1
                "use XML_PARSE_HUGE\n", depth);
6535
1
  return(NULL);
6536
1
    }
6537
15.3k
    SKIP_BLANKS_PE;
6538
15.3k
    GROW;
6539
15.3k
    if (RAW == '(') {
6540
5.64k
  int inputid = ctxt->input->id;
6541
6542
        /* Recurse on first child */
6543
5.64k
  NEXT;
6544
5.64k
  SKIP_BLANKS_PE;
6545
5.64k
        cur = ret = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
6546
5.64k
                                                           depth + 1);
6547
5.64k
        if (cur == NULL)
6548
3.25k
            return(NULL);
6549
2.38k
  SKIP_BLANKS_PE;
6550
2.38k
  GROW;
6551
9.66k
    } else {
6552
9.66k
  elem = xmlParseName(ctxt);
6553
9.66k
  if (elem == NULL) {
6554
634
      xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
6555
634
      return(NULL);
6556
634
  }
6557
9.03k
        cur = ret = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6558
9.03k
  if (cur == NULL) {
6559
0
      xmlErrMemory(ctxt);
6560
0
      return(NULL);
6561
0
  }
6562
9.03k
  GROW;
6563
9.03k
  if (RAW == '?') {
6564
1.96k
      cur->ocur = XML_ELEMENT_CONTENT_OPT;
6565
1.96k
      NEXT;
6566
7.06k
  } else if (RAW == '*') {
6567
1.58k
      cur->ocur = XML_ELEMENT_CONTENT_MULT;
6568
1.58k
      NEXT;
6569
5.48k
  } else if (RAW == '+') {
6570
691
      cur->ocur = XML_ELEMENT_CONTENT_PLUS;
6571
691
      NEXT;
6572
4.79k
  } else {
6573
4.79k
      cur->ocur = XML_ELEMENT_CONTENT_ONCE;
6574
4.79k
  }
6575
9.03k
  GROW;
6576
9.03k
    }
6577
11.4k
    SKIP_BLANKS_PE;
6578
20.1k
    while ((RAW != ')') && (PARSER_STOPPED(ctxt) == 0)) {
6579
        /*
6580
   * Each loop we parse one separator and one element.
6581
   */
6582
12.2k
        if (RAW == ',') {
6583
2.74k
      if (type == 0) type = CUR;
6584
6585
      /*
6586
       * Detect "Name | Name , Name" error
6587
       */
6588
1.92k
      else if (type != CUR) {
6589
5
    xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
6590
5
        "xmlParseElementChildrenContentDecl : '%c' expected\n",
6591
5
                      type);
6592
5
    if ((last != NULL) && (last != ret))
6593
5
        xmlFreeDocElementContent(ctxt->myDoc, last);
6594
5
    if (ret != NULL)
6595
5
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6596
5
    return(NULL);
6597
5
      }
6598
2.73k
      NEXT;
6599
6600
2.73k
      op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_SEQ);
6601
2.73k
      if (op == NULL) {
6602
0
                xmlErrMemory(ctxt);
6603
0
    if ((last != NULL) && (last != ret))
6604
0
        xmlFreeDocElementContent(ctxt->myDoc, last);
6605
0
          xmlFreeDocElementContent(ctxt->myDoc, ret);
6606
0
    return(NULL);
6607
0
      }
6608
2.73k
      if (last == NULL) {
6609
816
    op->c1 = ret;
6610
816
    if (ret != NULL)
6611
816
        ret->parent = op;
6612
816
    ret = cur = op;
6613
1.92k
      } else {
6614
1.92k
          cur->c2 = op;
6615
1.92k
    if (op != NULL)
6616
1.92k
        op->parent = cur;
6617
1.92k
    op->c1 = last;
6618
1.92k
    if (last != NULL)
6619
1.92k
        last->parent = op;
6620
1.92k
    cur =op;
6621
1.92k
    last = NULL;
6622
1.92k
      }
6623
9.55k
  } else if (RAW == '|') {
6624
8.19k
      if (type == 0) type = CUR;
6625
6626
      /*
6627
       * Detect "Name , Name | Name" error
6628
       */
6629
2.67k
      else if (type != CUR) {
6630
4
    xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
6631
4
        "xmlParseElementChildrenContentDecl : '%c' expected\n",
6632
4
          type);
6633
4
    if ((last != NULL) && (last != ret))
6634
4
        xmlFreeDocElementContent(ctxt->myDoc, last);
6635
4
    if (ret != NULL)
6636
4
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6637
4
    return(NULL);
6638
4
      }
6639
8.19k
      NEXT;
6640
6641
8.19k
      op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6642
8.19k
      if (op == NULL) {
6643
0
                xmlErrMemory(ctxt);
6644
0
    if ((last != NULL) && (last != ret))
6645
0
        xmlFreeDocElementContent(ctxt->myDoc, last);
6646
0
    if (ret != NULL)
6647
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6648
0
    return(NULL);
6649
0
      }
6650
8.19k
      if (last == NULL) {
6651
5.52k
    op->c1 = ret;
6652
5.52k
    if (ret != NULL)
6653
5.52k
        ret->parent = op;
6654
5.52k
    ret = cur = op;
6655
5.52k
      } else {
6656
2.67k
          cur->c2 = op;
6657
2.67k
    if (op != NULL)
6658
2.67k
        op->parent = cur;
6659
2.67k
    op->c1 = last;
6660
2.67k
    if (last != NULL)
6661
2.67k
        last->parent = op;
6662
2.67k
    cur =op;
6663
2.67k
    last = NULL;
6664
2.67k
      }
6665
8.19k
  } else {
6666
1.35k
      xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED, NULL);
6667
1.35k
      if ((last != NULL) && (last != ret))
6668
759
          xmlFreeDocElementContent(ctxt->myDoc, last);
6669
1.35k
      if (ret != NULL)
6670
1.35k
    xmlFreeDocElementContent(ctxt->myDoc, ret);
6671
1.35k
      return(NULL);
6672
1.35k
  }
6673
10.9k
  GROW;
6674
10.9k
  SKIP_BLANKS_PE;
6675
10.9k
  GROW;
6676
10.9k
  if (RAW == '(') {
6677
3.79k
      int inputid = ctxt->input->id;
6678
      /* Recurse on second child */
6679
3.79k
      NEXT;
6680
3.79k
      SKIP_BLANKS_PE;
6681
3.79k
      last = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
6682
3.79k
                                                          depth + 1);
6683
3.79k
            if (last == NULL) {
6684
1.74k
    if (ret != NULL)
6685
1.74k
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6686
1.74k
    return(NULL);
6687
1.74k
            }
6688
2.05k
      SKIP_BLANKS_PE;
6689
7.13k
  } else {
6690
7.13k
      elem = xmlParseName(ctxt);
6691
7.13k
      if (elem == NULL) {
6692
428
    xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
6693
428
    if (ret != NULL)
6694
428
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6695
428
    return(NULL);
6696
428
      }
6697
6.70k
      last = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6698
6.70k
      if (last == NULL) {
6699
0
                xmlErrMemory(ctxt);
6700
0
    if (ret != NULL)
6701
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6702
0
    return(NULL);
6703
0
      }
6704
6.70k
      if (RAW == '?') {
6705
1.55k
    last->ocur = XML_ELEMENT_CONTENT_OPT;
6706
1.55k
    NEXT;
6707
5.15k
      } else if (RAW == '*') {
6708
671
    last->ocur = XML_ELEMENT_CONTENT_MULT;
6709
671
    NEXT;
6710
4.48k
      } else if (RAW == '+') {
6711
231
    last->ocur = XML_ELEMENT_CONTENT_PLUS;
6712
231
    NEXT;
6713
4.25k
      } else {
6714
4.25k
    last->ocur = XML_ELEMENT_CONTENT_ONCE;
6715
4.25k
      }
6716
6.70k
  }
6717
8.76k
  SKIP_BLANKS_PE;
6718
8.76k
  GROW;
6719
8.76k
    }
6720
7.88k
    if ((cur != NULL) && (last != NULL)) {
6721
3.40k
        cur->c2 = last;
6722
3.40k
  if (last != NULL)
6723
3.40k
      last->parent = cur;
6724
3.40k
    }
6725
7.88k
    if (ctxt->input->id != inputchk) {
6726
66
  xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6727
66
                       "Element content declaration doesn't start and stop in"
6728
66
                       " the same entity\n");
6729
66
    }
6730
7.88k
    NEXT;
6731
7.88k
    if (RAW == '?') {
6732
759
  if (ret != NULL) {
6733
759
      if ((ret->ocur == XML_ELEMENT_CONTENT_PLUS) ||
6734
759
          (ret->ocur == XML_ELEMENT_CONTENT_MULT))
6735
411
          ret->ocur = XML_ELEMENT_CONTENT_MULT;
6736
348
      else
6737
348
          ret->ocur = XML_ELEMENT_CONTENT_OPT;
6738
759
  }
6739
759
  NEXT;
6740
7.12k
    } else if (RAW == '*') {
6741
2.12k
  if (ret != NULL) {
6742
2.12k
      ret->ocur = XML_ELEMENT_CONTENT_MULT;
6743
2.12k
      cur = ret;
6744
      /*
6745
       * Some normalization:
6746
       * (a | b* | c?)* == (a | b | c)*
6747
       */
6748
4.17k
      while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
6749
2.05k
    if ((cur->c1 != NULL) &&
6750
2.05k
              ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
6751
2.05k
         (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT)))
6752
1.17k
        cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
6753
2.05k
    if ((cur->c2 != NULL) &&
6754
2.05k
              ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
6755
2.05k
         (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT)))
6756
920
        cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
6757
2.05k
    cur = cur->c2;
6758
2.05k
      }
6759
2.12k
  }
6760
2.12k
  NEXT;
6761
5.00k
    } else if (RAW == '+') {
6762
2.73k
  if (ret != NULL) {
6763
2.73k
      int found = 0;
6764
6765
2.73k
      if ((ret->ocur == XML_ELEMENT_CONTENT_OPT) ||
6766
2.73k
          (ret->ocur == XML_ELEMENT_CONTENT_MULT))
6767
1.12k
          ret->ocur = XML_ELEMENT_CONTENT_MULT;
6768
1.60k
      else
6769
1.60k
          ret->ocur = XML_ELEMENT_CONTENT_PLUS;
6770
      /*
6771
       * Some normalization:
6772
       * (a | b*)+ == (a | b)*
6773
       * (a | b?)+ == (a | b)*
6774
       */
6775
4.36k
      while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
6776
1.63k
    if ((cur->c1 != NULL) &&
6777
1.63k
              ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
6778
1.63k
         (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT))) {
6779
748
        cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
6780
748
        found = 1;
6781
748
    }
6782
1.63k
    if ((cur->c2 != NULL) &&
6783
1.63k
              ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
6784
1.63k
         (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT))) {
6785
912
        cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
6786
912
        found = 1;
6787
912
    }
6788
1.63k
    cur = cur->c2;
6789
1.63k
      }
6790
2.73k
      if (found)
6791
1.13k
    ret->ocur = XML_ELEMENT_CONTENT_MULT;
6792
2.73k
  }
6793
2.73k
  NEXT;
6794
2.73k
    }
6795
7.88k
    return(ret);
6796
11.4k
}
6797
6798
/**
6799
 * xmlParseElementChildrenContentDecl:
6800
 * @ctxt:  an XML parser context
6801
 * @inputchk:  the input used for the current entity, needed for boundary checks
6802
 *
6803
 * DEPRECATED: Internal function, don't use.
6804
 *
6805
 * parse the declaration for a Mixed Element content
6806
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6807
 *
6808
 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
6809
 *
6810
 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
6811
 *
6812
 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
6813
 *
6814
 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
6815
 *
6816
 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
6817
 * TODO Parameter-entity replacement text must be properly nested
6818
 *  with parenthesized groups. That is to say, if either of the
6819
 *  opening or closing parentheses in a choice, seq, or Mixed
6820
 *  construct is contained in the replacement text for a parameter
6821
 *  entity, both must be contained in the same replacement text. For
6822
 *  interoperability, if a parameter-entity reference appears in a
6823
 *  choice, seq, or Mixed construct, its replacement text should not
6824
 *  be empty, and neither the first nor last non-blank character of
6825
 *  the replacement text should be a connector (| or ,).
6826
 *
6827
 * Returns the tree of xmlElementContentPtr describing the element
6828
 *          hierarchy.
6829
 */
6830
xmlElementContentPtr
6831
0
xmlParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
6832
    /* stub left for API/ABI compat */
6833
0
    return(xmlParseElementChildrenContentDeclPriv(ctxt, inputchk, 1));
6834
0
}
6835
6836
/**
6837
 * xmlParseElementContentDecl:
6838
 * @ctxt:  an XML parser context
6839
 * @name:  the name of the element being defined.
6840
 * @result:  the Element Content pointer will be stored here if any
6841
 *
6842
 * DEPRECATED: Internal function, don't use.
6843
 *
6844
 * parse the declaration for an Element content either Mixed or Children,
6845
 * the cases EMPTY and ANY are handled directly in xmlParseElementDecl
6846
 *
6847
 * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
6848
 *
6849
 * returns: the type of element content XML_ELEMENT_TYPE_xxx
6850
 */
6851
6852
int
6853
xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, const xmlChar *name,
6854
8.19k
                           xmlElementContentPtr *result) {
6855
6856
8.19k
    xmlElementContentPtr tree = NULL;
6857
8.19k
    int inputid = ctxt->input->id;
6858
8.19k
    int res;
6859
6860
8.19k
    *result = NULL;
6861
6862
8.19k
    if (RAW != '(') {
6863
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
6864
0
    "xmlParseElementContentDecl : %s '(' expected\n", name);
6865
0
  return(-1);
6866
0
    }
6867
8.19k
    NEXT;
6868
8.19k
    GROW;
6869
8.19k
    SKIP_BLANKS_PE;
6870
8.19k
    if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
6871
2.32k
        tree = xmlParseElementMixedContentDecl(ctxt, inputid);
6872
2.32k
  res = XML_ELEMENT_TYPE_MIXED;
6873
5.87k
    } else {
6874
5.87k
        tree = xmlParseElementChildrenContentDeclPriv(ctxt, inputid, 1);
6875
5.87k
  res = XML_ELEMENT_TYPE_ELEMENT;
6876
5.87k
    }
6877
8.19k
    SKIP_BLANKS_PE;
6878
8.19k
    *result = tree;
6879
8.19k
    return(res);
6880
8.19k
}
6881
6882
/**
6883
 * xmlParseElementDecl:
6884
 * @ctxt:  an XML parser context
6885
 *
6886
 * DEPRECATED: Internal function, don't use.
6887
 *
6888
 * Parse an element declaration. Always consumes '<!'.
6889
 *
6890
 * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
6891
 *
6892
 * [ VC: Unique Element Type Declaration ]
6893
 * No element type may be declared more than once
6894
 *
6895
 * Returns the type of the element, or -1 in case of error
6896
 */
6897
int
6898
10.2k
xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
6899
10.2k
    const xmlChar *name;
6900
10.2k
    int ret = -1;
6901
10.2k
    xmlElementContentPtr content  = NULL;
6902
6903
10.2k
    if ((CUR != '<') || (NXT(1) != '!'))
6904
0
        return(ret);
6905
10.2k
    SKIP(2);
6906
6907
    /* GROW; done in the caller */
6908
10.2k
    if (CMP7(CUR_PTR, 'E', 'L', 'E', 'M', 'E', 'N', 'T')) {
6909
10.2k
  int inputid = ctxt->input->id;
6910
6911
10.2k
  SKIP(7);
6912
10.2k
  if (SKIP_BLANKS_PE == 0) {
6913
299
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6914
299
               "Space required after 'ELEMENT'\n");
6915
299
      return(-1);
6916
299
  }
6917
9.93k
        name = xmlParseName(ctxt);
6918
9.93k
  if (name == NULL) {
6919
471
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6920
471
         "xmlParseElementDecl: no name for Element\n");
6921
471
      return(-1);
6922
471
  }
6923
9.46k
  if (SKIP_BLANKS_PE == 0) {
6924
8.06k
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6925
8.06k
         "Space required after the element name\n");
6926
8.06k
  }
6927
9.46k
  if (CMP5(CUR_PTR, 'E', 'M', 'P', 'T', 'Y')) {
6928
529
      SKIP(5);
6929
      /*
6930
       * Element must always be empty.
6931
       */
6932
529
      ret = XML_ELEMENT_TYPE_EMPTY;
6933
8.93k
  } else if ((RAW == 'A') && (NXT(1) == 'N') &&
6934
8.93k
             (NXT(2) == 'Y')) {
6935
470
      SKIP(3);
6936
      /*
6937
       * Element is a generic container.
6938
       */
6939
470
      ret = XML_ELEMENT_TYPE_ANY;
6940
8.46k
  } else if (RAW == '(') {
6941
8.19k
      ret = xmlParseElementContentDecl(ctxt, name, &content);
6942
8.19k
  } else {
6943
      /*
6944
       * [ WFC: PEs in Internal Subset ] error handling.
6945
       */
6946
266
            xmlFatalErrMsg(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
6947
266
                  "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
6948
266
      return(-1);
6949
266
  }
6950
6951
9.19k
  SKIP_BLANKS_PE;
6952
6953
9.19k
  if (RAW != '>') {
6954
5.16k
      xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
6955
5.16k
      if (content != NULL) {
6956
2.23k
    xmlFreeDocElementContent(ctxt->myDoc, content);
6957
2.23k
      }
6958
5.16k
  } else {
6959
4.03k
      if (inputid != ctxt->input->id) {
6960
136
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6961
136
                               "Element declaration doesn't start and stop in"
6962
136
                               " the same entity\n");
6963
136
      }
6964
6965
4.03k
      NEXT;
6966
4.03k
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
6967
4.03k
    (ctxt->sax->elementDecl != NULL)) {
6968
3.65k
    if (content != NULL)
6969
2.05k
        content->parent = NULL;
6970
3.65k
          ctxt->sax->elementDecl(ctxt->userData, name, ret,
6971
3.65k
                           content);
6972
3.65k
    if ((content != NULL) && (content->parent == NULL)) {
6973
        /*
6974
         * this is a trick: if xmlAddElementDecl is called,
6975
         * instead of copying the full tree it is plugged directly
6976
         * if called from the parser. Avoid duplicating the
6977
         * interfaces or change the API/ABI
6978
         */
6979
1.75k
        xmlFreeDocElementContent(ctxt->myDoc, content);
6980
1.75k
    }
6981
3.65k
      } else if (content != NULL) {
6982
148
    xmlFreeDocElementContent(ctxt->myDoc, content);
6983
148
      }
6984
4.03k
  }
6985
9.19k
    }
6986
9.22k
    return(ret);
6987
10.2k
}
6988
6989
/**
6990
 * xmlParseConditionalSections
6991
 * @ctxt:  an XML parser context
6992
 *
6993
 * Parse a conditional section. Always consumes '<!['.
6994
 *
6995
 * [61] conditionalSect ::= includeSect | ignoreSect
6996
 * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
6997
 * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
6998
 * [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
6999
 * [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
7000
 */
7001
7002
static void
7003
0
xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
7004
0
    int *inputIds = NULL;
7005
0
    size_t inputIdsSize = 0;
7006
0
    size_t depth = 0;
7007
7008
0
    while (PARSER_STOPPED(ctxt) == 0) {
7009
0
        if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
7010
0
            int id = ctxt->input->id;
7011
7012
0
            SKIP(3);
7013
0
            SKIP_BLANKS_PE;
7014
7015
0
            if (CMP7(CUR_PTR, 'I', 'N', 'C', 'L', 'U', 'D', 'E')) {
7016
0
                SKIP(7);
7017
0
                SKIP_BLANKS_PE;
7018
0
                if (RAW != '[') {
7019
0
                    xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
7020
0
                    xmlHaltParser(ctxt);
7021
0
                    goto error;
7022
0
                }
7023
0
                if (ctxt->input->id != id) {
7024
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
7025
0
                                   "All markup of the conditional section is"
7026
0
                                   " not in the same entity\n");
7027
0
                }
7028
0
                NEXT;
7029
7030
0
                if (inputIdsSize <= depth) {
7031
0
                    int *tmp;
7032
7033
0
                    inputIdsSize = (inputIdsSize == 0 ? 4 : inputIdsSize * 2);
7034
0
                    tmp = (int *) xmlRealloc(inputIds,
7035
0
                            inputIdsSize * sizeof(int));
7036
0
                    if (tmp == NULL) {
7037
0
                        xmlErrMemory(ctxt);
7038
0
                        goto error;
7039
0
                    }
7040
0
                    inputIds = tmp;
7041
0
                }
7042
0
                inputIds[depth] = id;
7043
0
                depth++;
7044
0
            } else if (CMP6(CUR_PTR, 'I', 'G', 'N', 'O', 'R', 'E')) {
7045
0
                size_t ignoreDepth = 0;
7046
7047
0
                SKIP(6);
7048
0
                SKIP_BLANKS_PE;
7049
0
                if (RAW != '[') {
7050
0
                    xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
7051
0
                    xmlHaltParser(ctxt);
7052
0
                    goto error;
7053
0
                }
7054
0
                if (ctxt->input->id != id) {
7055
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
7056
0
                                   "All markup of the conditional section is"
7057
0
                                   " not in the same entity\n");
7058
0
                }
7059
0
                NEXT;
7060
7061
0
                while (PARSER_STOPPED(ctxt) == 0) {
7062
0
                    if (RAW == 0) {
7063
0
                        xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
7064
0
                        goto error;
7065
0
                    }
7066
0
                    if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
7067
0
                        SKIP(3);
7068
0
                        ignoreDepth++;
7069
                        /* Check for integer overflow */
7070
0
                        if (ignoreDepth == 0) {
7071
0
                            xmlErrMemory(ctxt);
7072
0
                            goto error;
7073
0
                        }
7074
0
                    } else if ((RAW == ']') && (NXT(1) == ']') &&
7075
0
                               (NXT(2) == '>')) {
7076
0
                        SKIP(3);
7077
0
                        if (ignoreDepth == 0)
7078
0
                            break;
7079
0
                        ignoreDepth--;
7080
0
                    } else {
7081
0
                        NEXT;
7082
0
                    }
7083
0
                }
7084
7085
0
                if (ctxt->input->id != id) {
7086
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
7087
0
                                   "All markup of the conditional section is"
7088
0
                                   " not in the same entity\n");
7089
0
                }
7090
0
            } else {
7091
0
                xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
7092
0
                xmlHaltParser(ctxt);
7093
0
                goto error;
7094
0
            }
7095
0
        } else if ((depth > 0) &&
7096
0
                   (RAW == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
7097
0
            depth--;
7098
0
            if (ctxt->input->id != inputIds[depth]) {
7099
0
                xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
7100
0
                               "All markup of the conditional section is not"
7101
0
                               " in the same entity\n");
7102
0
            }
7103
0
            SKIP(3);
7104
0
        } else if ((RAW == '<') && ((NXT(1) == '!') || (NXT(1) == '?'))) {
7105
0
            xmlParseMarkupDecl(ctxt);
7106
0
        } else {
7107
0
            xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
7108
0
            xmlHaltParser(ctxt);
7109
0
            goto error;
7110
0
        }
7111
7112
0
        if (depth == 0)
7113
0
            break;
7114
7115
0
        SKIP_BLANKS_PE;
7116
0
        SHRINK;
7117
0
        GROW;
7118
0
    }
7119
7120
0
error:
7121
0
    xmlFree(inputIds);
7122
0
}
7123
7124
/**
7125
 * xmlParseMarkupDecl:
7126
 * @ctxt:  an XML parser context
7127
 *
7128
 * DEPRECATED: Internal function, don't use.
7129
 *
7130
 * Parse markup declarations. Always consumes '<!' or '<?'.
7131
 *
7132
 * [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
7133
 *                     NotationDecl | PI | Comment
7134
 *
7135
 * [ VC: Proper Declaration/PE Nesting ]
7136
 * Parameter-entity replacement text must be properly nested with
7137
 * markup declarations. That is to say, if either the first character
7138
 * or the last character of a markup declaration (markupdecl above) is
7139
 * contained in the replacement text for a parameter-entity reference,
7140
 * both must be contained in the same replacement text.
7141
 *
7142
 * [ WFC: PEs in Internal Subset ]
7143
 * In the internal DTD subset, parameter-entity references can occur
7144
 * only where markup declarations can occur, not within markup declarations.
7145
 * (This does not apply to references that occur in external parameter
7146
 * entities or to the external subset.)
7147
 */
7148
void
7149
103k
xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
7150
103k
    GROW;
7151
103k
    if (CUR == '<') {
7152
103k
        if (NXT(1) == '!') {
7153
81.6k
      switch (NXT(2)) {
7154
30.2k
          case 'E':
7155
30.2k
        if (NXT(3) == 'L')
7156
10.2k
      xmlParseElementDecl(ctxt);
7157
20.0k
        else if (NXT(3) == 'N')
7158
20.0k
      xmlParseEntityDecl(ctxt);
7159
10
                    else
7160
10
                        SKIP(2);
7161
30.2k
        break;
7162
33.2k
          case 'A':
7163
33.2k
        xmlParseAttributeListDecl(ctxt);
7164
33.2k
        break;
7165
4.70k
          case 'N':
7166
4.70k
        xmlParseNotationDecl(ctxt);
7167
4.70k
        break;
7168
12.6k
          case '-':
7169
12.6k
        xmlParseComment(ctxt);
7170
12.6k
        break;
7171
851
    default:
7172
        /* there is an error but it will be detected later */
7173
851
                    SKIP(2);
7174
851
        break;
7175
81.6k
      }
7176
81.6k
  } else if (NXT(1) == '?') {
7177
21.6k
      xmlParsePI(ctxt);
7178
21.6k
  }
7179
103k
    }
7180
103k
}
7181
7182
/**
7183
 * xmlParseTextDecl:
7184
 * @ctxt:  an XML parser context
7185
 *
7186
 * DEPRECATED: Internal function, don't use.
7187
 *
7188
 * parse an XML declaration header for external entities
7189
 *
7190
 * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
7191
 */
7192
7193
void
7194
0
xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
7195
0
    xmlChar *version;
7196
7197
    /*
7198
     * We know that '<?xml' is here.
7199
     */
7200
0
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
7201
0
  SKIP(5);
7202
0
    } else {
7203
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_STARTED, NULL);
7204
0
  return;
7205
0
    }
7206
7207
0
    if (SKIP_BLANKS == 0) {
7208
0
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
7209
0
           "Space needed after '<?xml'\n");
7210
0
    }
7211
7212
    /*
7213
     * We may have the VersionInfo here.
7214
     */
7215
0
    version = xmlParseVersionInfo(ctxt);
7216
0
    if (version == NULL) {
7217
0
  version = xmlCharStrdup(XML_DEFAULT_VERSION);
7218
0
        if (version == NULL) {
7219
0
            xmlErrMemory(ctxt);
7220
0
            return;
7221
0
        }
7222
0
    } else {
7223
0
  if (SKIP_BLANKS == 0) {
7224
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
7225
0
               "Space needed here\n");
7226
0
  }
7227
0
    }
7228
0
    ctxt->input->version = version;
7229
7230
    /*
7231
     * We must have the encoding declaration
7232
     */
7233
0
    xmlParseEncodingDecl(ctxt);
7234
7235
0
    SKIP_BLANKS;
7236
0
    if ((RAW == '?') && (NXT(1) == '>')) {
7237
0
        SKIP(2);
7238
0
    } else if (RAW == '>') {
7239
        /* Deprecated old WD ... */
7240
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
7241
0
  NEXT;
7242
0
    } else {
7243
0
        int c;
7244
7245
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
7246
0
        while ((PARSER_STOPPED(ctxt) == 0) && ((c = CUR) != 0)) {
7247
0
            NEXT;
7248
0
            if (c == '>')
7249
0
                break;
7250
0
        }
7251
0
    }
7252
0
}
7253
7254
/**
7255
 * xmlParseExternalSubset:
7256
 * @ctxt:  an XML parser context
7257
 * @ExternalID: the external identifier
7258
 * @SystemID: the system identifier (or URL)
7259
 *
7260
 * parse Markup declarations from an external subset
7261
 *
7262
 * [30] extSubset ::= textDecl? extSubsetDecl
7263
 *
7264
 * [31] extSubsetDecl ::= (markupdecl | conditionalSect | PEReference | S) *
7265
 */
7266
void
7267
xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
7268
0
                       const xmlChar *SystemID) {
7269
0
    int oldInputNr;
7270
7271
0
    xmlCtxtInitializeLate(ctxt);
7272
7273
0
    xmlDetectEncoding(ctxt);
7274
7275
0
    if (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) {
7276
0
  xmlParseTextDecl(ctxt);
7277
0
    }
7278
0
    if (ctxt->myDoc == NULL) {
7279
0
        ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
7280
0
  if (ctxt->myDoc == NULL) {
7281
0
      xmlErrMemory(ctxt);
7282
0
      return;
7283
0
  }
7284
0
  ctxt->myDoc->properties = XML_DOC_INTERNAL;
7285
0
    }
7286
0
    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL) &&
7287
0
        (xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID) == NULL)) {
7288
0
        xmlErrMemory(ctxt);
7289
0
    }
7290
7291
0
    ctxt->inSubset = 2;
7292
0
    oldInputNr = ctxt->inputNr;
7293
7294
0
    SKIP_BLANKS_PE;
7295
0
    while (((RAW != 0) || (ctxt->inputNr > oldInputNr)) &&
7296
0
           (!PARSER_STOPPED(ctxt))) {
7297
0
  GROW;
7298
0
        if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
7299
0
            xmlParseConditionalSections(ctxt);
7300
0
        } else if ((RAW == '<') && ((NXT(1) == '!') || (NXT(1) == '?'))) {
7301
0
            xmlParseMarkupDecl(ctxt);
7302
0
        } else {
7303
0
            xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
7304
0
            xmlHaltParser(ctxt);
7305
0
            return;
7306
0
        }
7307
0
        SKIP_BLANKS_PE;
7308
0
        SHRINK;
7309
0
    }
7310
7311
0
    while (ctxt->inputNr > oldInputNr)
7312
0
        xmlPopPE(ctxt);
7313
7314
0
    if (RAW != 0) {
7315
0
  xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
7316
0
    }
7317
0
}
7318
7319
/**
7320
 * xmlParseReference:
7321
 * @ctxt:  an XML parser context
7322
 *
7323
 * DEPRECATED: Internal function, don't use.
7324
 *
7325
 * parse and handle entity references in content, depending on the SAX
7326
 * interface, this may end-up in a call to character() if this is a
7327
 * CharRef, a predefined entity, if there is no reference() callback.
7328
 * or if the parser was asked to switch to that mode.
7329
 *
7330
 * Always consumes '&'.
7331
 *
7332
 * [67] Reference ::= EntityRef | CharRef
7333
 */
7334
void
7335
19.5k
xmlParseReference(xmlParserCtxtPtr ctxt) {
7336
19.5k
    xmlEntityPtr ent = NULL;
7337
19.5k
    const xmlChar *name;
7338
19.5k
    xmlChar *val;
7339
7340
19.5k
    if (RAW != '&')
7341
0
        return;
7342
7343
    /*
7344
     * Simple case of a CharRef
7345
     */
7346
19.5k
    if (NXT(1) == '#') {
7347
4.23k
  int i = 0;
7348
4.23k
  xmlChar out[16];
7349
4.23k
  int value = xmlParseCharRef(ctxt);
7350
7351
4.23k
  if (value == 0)
7352
1.69k
      return;
7353
7354
        /*
7355
         * Just encode the value in UTF-8
7356
         */
7357
2.53k
        COPY_BUF(out, i, value);
7358
2.53k
        out[i] = 0;
7359
2.53k
        if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
7360
2.53k
            (!ctxt->disableSAX))
7361
1.74k
            ctxt->sax->characters(ctxt->userData, out, i);
7362
2.53k
  return;
7363
4.23k
    }
7364
7365
    /*
7366
     * We are seeing an entity reference
7367
     */
7368
15.3k
    name = xmlParseEntityRefInternal(ctxt);
7369
15.3k
    if (name != NULL)
7370
10.3k
        ent = xmlLookupGeneralEntity(ctxt, name, /* isAttr */ 0);
7371
15.3k
    if (ent == NULL) return;
7372
8.11k
    if (!ctxt->wellFormed)
7373
6.42k
  return;
7374
7375
    /* special case of predefined entities */
7376
1.69k
    if ((ent->name == NULL) ||
7377
1.69k
        (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
7378
255
  val = ent->content;
7379
255
  if (val == NULL) return;
7380
  /*
7381
   * inline the entity.
7382
   */
7383
255
  if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
7384
255
      (!ctxt->disableSAX))
7385
255
      ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
7386
255
  return;
7387
255
    }
7388
7389
    /*
7390
     * The first reference to the entity trigger a parsing phase
7391
     * where the ent->children is filled with the result from
7392
     * the parsing.
7393
     * Note: external parsed entities will not be loaded, it is not
7394
     * required for a non-validating parser, unless the parsing option
7395
     * of validating, or substituting entities were given. Doing so is
7396
     * far more secure as the parser will only process data coming from
7397
     * the document entity by default.
7398
     *
7399
     * FIXME: This doesn't work correctly since entities can be
7400
     * expanded with different namespace declarations in scope.
7401
     * For example:
7402
     *
7403
     * <!DOCTYPE doc [
7404
     *   <!ENTITY ent "<ns:elem/>">
7405
     * ]>
7406
     * <doc>
7407
     *   <decl1 xmlns:ns="urn:ns1">
7408
     *     &ent;
7409
     *   </decl1>
7410
     *   <decl2 xmlns:ns="urn:ns2">
7411
     *     &ent;
7412
     *   </decl2>
7413
     * </doc>
7414
     *
7415
     * Proposed fix:
7416
     *
7417
     * - Ignore current namespace declarations when parsing the
7418
     *   entity. If a prefix can't be resolved, don't report an error
7419
     *   but mark it as unresolved.
7420
     * - Try to resolve these prefixes when expanding the entity.
7421
     *   This will require a specialized version of xmlStaticCopyNode
7422
     *   which can also make use of the namespace hash table to avoid
7423
     *   quadratic behavior.
7424
     *
7425
     * Alternatively, we could simply reparse the entity on each
7426
     * expansion like we already do with custom SAX callbacks.
7427
     * External entity content should be cached in this case.
7428
     */
7429
1.43k
    if ((ent->etype == XML_INTERNAL_GENERAL_ENTITY) ||
7430
1.43k
        (((ctxt->options & XML_PARSE_NO_XXE) == 0) &&
7431
396
         ((ctxt->replaceEntities) ||
7432
1.04k
          (ctxt->validate)))) {
7433
1.04k
        if ((ent->flags & XML_ENT_PARSED) == 0) {
7434
388
            xmlCtxtParseEntity(ctxt, ent);
7435
652
        } else if (ent->children == NULL) {
7436
            /*
7437
             * Probably running in SAX mode and the callbacks don't
7438
             * build the entity content. Parse the entity again.
7439
             *
7440
             * This will also be triggered in normal tree builder mode
7441
             * if an entity happens to be empty, causing unnecessary
7442
             * reloads. It's hard to come up with a reliable check in
7443
             * which mode we're running.
7444
             */
7445
342
            xmlCtxtParseEntity(ctxt, ent);
7446
342
        }
7447
1.04k
    }
7448
7449
    /*
7450
     * We also check for amplification if entities aren't substituted.
7451
     * They might be expanded later.
7452
     */
7453
1.43k
    if (xmlParserEntityCheck(ctxt, ent->expandedSize))
7454
0
        return;
7455
7456
1.43k
    if ((ctxt->sax == NULL) || (ctxt->disableSAX))
7457
207
        return;
7458
7459
1.22k
    if (ctxt->replaceEntities == 0) {
7460
  /*
7461
   * Create a reference
7462
   */
7463
1.22k
        if (ctxt->sax->reference != NULL)
7464
1.22k
      ctxt->sax->reference(ctxt->userData, ent->name);
7465
1.22k
    } else if ((ent->children != NULL) && (ctxt->node != NULL)) {
7466
0
        xmlNodePtr copy, cur;
7467
7468
        /*
7469
         * Seems we are generating the DOM content, copy the tree
7470
   */
7471
0
        cur = ent->children;
7472
7473
        /*
7474
         * Handle first text node with SAX to coalesce text efficiently
7475
         */
7476
0
        if ((cur->type == XML_TEXT_NODE) ||
7477
0
            (cur->type == XML_CDATA_SECTION_NODE)) {
7478
0
            int len = xmlStrlen(cur->content);
7479
7480
0
            if ((cur->type == XML_TEXT_NODE) ||
7481
0
                (ctxt->sax->cdataBlock == NULL)) {
7482
0
                if (ctxt->sax->characters != NULL)
7483
0
                    ctxt->sax->characters(ctxt, cur->content, len);
7484
0
            } else {
7485
0
                if (ctxt->sax->cdataBlock != NULL)
7486
0
                    ctxt->sax->cdataBlock(ctxt, cur->content, len);
7487
0
            }
7488
7489
0
            cur = cur->next;
7490
0
        }
7491
7492
0
        while (cur != NULL) {
7493
0
            xmlNodePtr last;
7494
7495
            /*
7496
             * Handle last text node with SAX to coalesce text efficiently
7497
             */
7498
0
            if ((cur->next == NULL) &&
7499
0
                ((cur->type == XML_TEXT_NODE) ||
7500
0
                 (cur->type == XML_CDATA_SECTION_NODE))) {
7501
0
                int len = xmlStrlen(cur->content);
7502
7503
0
                if ((cur->type == XML_TEXT_NODE) ||
7504
0
                    (ctxt->sax->cdataBlock == NULL)) {
7505
0
                    if (ctxt->sax->characters != NULL)
7506
0
                        ctxt->sax->characters(ctxt, cur->content, len);
7507
0
                } else {
7508
0
                    if (ctxt->sax->cdataBlock != NULL)
7509
0
                        ctxt->sax->cdataBlock(ctxt, cur->content, len);
7510
0
                }
7511
7512
0
                break;
7513
0
            }
7514
7515
            /*
7516
             * Reset coalesce buffer stats only for non-text nodes.
7517
             */
7518
0
            ctxt->nodemem = 0;
7519
0
            ctxt->nodelen = 0;
7520
7521
0
            copy = xmlDocCopyNode(cur, ctxt->myDoc, 1);
7522
7523
0
            if (copy == NULL) {
7524
0
                xmlErrMemory(ctxt);
7525
0
                break;
7526
0
            }
7527
7528
0
            if (ctxt->parseMode == XML_PARSE_READER) {
7529
                /* Needed for reader */
7530
0
                copy->extra = cur->extra;
7531
                /* Maybe needed for reader */
7532
0
                copy->_private = cur->_private;
7533
0
            }
7534
7535
0
            copy->parent = ctxt->node;
7536
0
            last = ctxt->node->last;
7537
0
            if (last == NULL) {
7538
0
                ctxt->node->children = copy;
7539
0
            } else {
7540
0
                last->next = copy;
7541
0
                copy->prev = last;
7542
0
            }
7543
0
            ctxt->node->last = copy;
7544
7545
0
            cur = cur->next;
7546
0
        }
7547
0
    }
7548
1.22k
}
7549
7550
static xmlEntityPtr
7551
391k
xmlLookupGeneralEntity(xmlParserCtxtPtr ctxt, const xmlChar *name, int inAttr) {
7552
391k
    xmlEntityPtr ent;
7553
7554
    /*
7555
     * Predefined entities override any extra definition
7556
     */
7557
391k
    if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
7558
390k
        ent = xmlGetPredefinedEntity(name);
7559
390k
        if (ent != NULL)
7560
37.4k
            return(ent);
7561
390k
    }
7562
7563
    /*
7564
     * Ask first SAX for entity resolution, otherwise try the
7565
     * entities which may have stored in the parser context.
7566
     */
7567
354k
    if (ctxt->sax != NULL) {
7568
354k
  if (ctxt->sax->getEntity != NULL)
7569
354k
      ent = ctxt->sax->getEntity(ctxt->userData, name);
7570
354k
  if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
7571
354k
      (ctxt->options & XML_PARSE_OLDSAX))
7572
195
      ent = xmlGetPredefinedEntity(name);
7573
354k
  if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
7574
354k
      (ctxt->userData==ctxt)) {
7575
485
      ent = xmlSAX2GetEntity(ctxt, name);
7576
485
  }
7577
354k
    }
7578
    /*
7579
     * [ WFC: Entity Declared ]
7580
     * In a document without any DTD, a document with only an
7581
     * internal DTD subset which contains no parameter entity
7582
     * references, or a document with "standalone='yes'", the
7583
     * Name given in the entity reference must match that in an
7584
     * entity declaration, except that well-formed documents
7585
     * need not declare any of the following entities: amp, lt,
7586
     * gt, apos, quot.
7587
     * The declaration of a parameter entity must precede any
7588
     * reference to it.
7589
     * Similarly, the declaration of a general entity must
7590
     * precede any reference to it which appears in a default
7591
     * value in an attribute-list declaration. Note that if
7592
     * entities are declared in the external subset or in
7593
     * external parameter entities, a non-validating processor
7594
     * is not obligated to read and process their declarations;
7595
     * for such documents, the rule that an entity must be
7596
     * declared is a well-formedness constraint only if
7597
     * standalone='yes'.
7598
     */
7599
354k
    if (ent == NULL) {
7600
56.8k
  if ((ctxt->standalone == 1) ||
7601
56.8k
      ((ctxt->hasExternalSubset == 0) &&
7602
56.4k
       (ctxt->hasPErefs == 0))) {
7603
46.7k
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7604
46.7k
         "Entity '%s' not defined\n", name);
7605
46.7k
  } else {
7606
10.1k
      xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
7607
10.1k
         "Entity '%s' not defined\n", name);
7608
10.1k
      if ((ctxt->inSubset == 0) &&
7609
10.1k
    (ctxt->sax != NULL) &&
7610
10.1k
                (ctxt->disableSAX == 0) &&
7611
10.1k
    (ctxt->sax->reference != NULL)) {
7612
1.05k
    ctxt->sax->reference(ctxt->userData, name);
7613
1.05k
      }
7614
10.1k
  }
7615
56.8k
  ctxt->valid = 0;
7616
56.8k
    }
7617
7618
    /*
7619
     * [ WFC: Parsed Entity ]
7620
     * An entity reference must not contain the name of an
7621
     * unparsed entity
7622
     */
7623
297k
    else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
7624
198
  xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
7625
198
     "Entity reference to unparsed entity %s\n", name);
7626
198
        ent = NULL;
7627
198
    }
7628
7629
    /*
7630
     * [ WFC: No External Entity References ]
7631
     * Attribute values cannot contain direct or indirect
7632
     * entity references to external entities.
7633
     */
7634
297k
    else if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
7635
730
        if (inAttr) {
7636
202
            xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
7637
202
                 "Attribute references external entity '%s'\n", name);
7638
202
            ent = NULL;
7639
202
        }
7640
730
    }
7641
7642
354k
    return(ent);
7643
391k
}
7644
7645
/**
7646
 * xmlParseEntityRefInternal:
7647
 * @ctxt:  an XML parser context
7648
 * @inAttr:  whether we are in an attribute value
7649
 *
7650
 * Parse an entity reference. Always consumes '&'.
7651
 *
7652
 * [68] EntityRef ::= '&' Name ';'
7653
 *
7654
 * Returns the name, or NULL in case of error.
7655
 */
7656
static const xmlChar *
7657
85.8k
xmlParseEntityRefInternal(xmlParserCtxtPtr ctxt) {
7658
85.8k
    const xmlChar *name;
7659
7660
85.8k
    GROW;
7661
7662
85.8k
    if (RAW != '&')
7663
0
        return(NULL);
7664
85.8k
    NEXT;
7665
85.8k
    name = xmlParseName(ctxt);
7666
85.8k
    if (name == NULL) {
7667
8.22k
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7668
8.22k
           "xmlParseEntityRef: no name\n");
7669
8.22k
        return(NULL);
7670
8.22k
    }
7671
77.6k
    if (RAW != ';') {
7672
2.49k
  xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
7673
2.49k
  return(NULL);
7674
2.49k
    }
7675
75.1k
    NEXT;
7676
7677
75.1k
    return(name);
7678
77.6k
}
7679
7680
/**
7681
 * xmlParseEntityRef:
7682
 * @ctxt:  an XML parser context
7683
 *
7684
 * DEPRECATED: Internal function, don't use.
7685
 *
7686
 * Returns the xmlEntityPtr if found, or NULL otherwise.
7687
 */
7688
xmlEntityPtr
7689
0
xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
7690
0
    const xmlChar *name;
7691
7692
0
    if (ctxt == NULL)
7693
0
        return(NULL);
7694
7695
0
    name = xmlParseEntityRefInternal(ctxt);
7696
0
    if (name == NULL)
7697
0
        return(NULL);
7698
7699
0
    return(xmlLookupGeneralEntity(ctxt, name, /* inAttr */ 0));
7700
0
}
7701
7702
/**
7703
 * xmlParseStringEntityRef:
7704
 * @ctxt:  an XML parser context
7705
 * @str:  a pointer to an index in the string
7706
 *
7707
 * parse ENTITY references declarations, but this version parses it from
7708
 * a string value.
7709
 *
7710
 * [68] EntityRef ::= '&' Name ';'
7711
 *
7712
 * [ WFC: Entity Declared ]
7713
 * In a document without any DTD, a document with only an internal DTD
7714
 * subset which contains no parameter entity references, or a document
7715
 * with "standalone='yes'", the Name given in the entity reference
7716
 * must match that in an entity declaration, except that well-formed
7717
 * documents need not declare any of the following entities: amp, lt,
7718
 * gt, apos, quot.  The declaration of a parameter entity must precede
7719
 * any reference to it.  Similarly, the declaration of a general entity
7720
 * must precede any reference to it which appears in a default value in an
7721
 * attribute-list declaration. Note that if entities are declared in the
7722
 * external subset or in external parameter entities, a non-validating
7723
 * processor is not obligated to read and process their declarations;
7724
 * for such documents, the rule that an entity must be declared is a
7725
 * well-formedness constraint only if standalone='yes'.
7726
 *
7727
 * [ WFC: Parsed Entity ]
7728
 * An entity reference must not contain the name of an unparsed entity
7729
 *
7730
 * Returns the xmlEntityPtr if found, or NULL otherwise. The str pointer
7731
 * is updated to the current location in the string.
7732
 */
7733
static xmlChar *
7734
316k
xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
7735
316k
    xmlChar *name;
7736
316k
    const xmlChar *ptr;
7737
316k
    xmlChar cur;
7738
7739
316k
    if ((str == NULL) || (*str == NULL))
7740
0
        return(NULL);
7741
316k
    ptr = *str;
7742
316k
    cur = *ptr;
7743
316k
    if (cur != '&')
7744
0
  return(NULL);
7745
7746
316k
    ptr++;
7747
316k
    name = xmlParseStringName(ctxt, &ptr);
7748
316k
    if (name == NULL) {
7749
1
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7750
1
           "xmlParseStringEntityRef: no name\n");
7751
1
  *str = ptr;
7752
1
  return(NULL);
7753
1
    }
7754
316k
    if (*ptr != ';') {
7755
3
  xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
7756
3
        xmlFree(name);
7757
3
  *str = ptr;
7758
3
  return(NULL);
7759
3
    }
7760
316k
    ptr++;
7761
7762
316k
    *str = ptr;
7763
316k
    return(name);
7764
316k
}
7765
7766
/**
7767
 * xmlParsePEReference:
7768
 * @ctxt:  an XML parser context
7769
 *
7770
 * DEPRECATED: Internal function, don't use.
7771
 *
7772
 * Parse a parameter entity reference. Always consumes '%'.
7773
 *
7774
 * The entity content is handled directly by pushing it's content as
7775
 * a new input stream.
7776
 *
7777
 * [69] PEReference ::= '%' Name ';'
7778
 *
7779
 * [ WFC: No Recursion ]
7780
 * A parsed entity must not contain a recursive
7781
 * reference to itself, either directly or indirectly.
7782
 *
7783
 * [ WFC: Entity Declared ]
7784
 * In a document without any DTD, a document with only an internal DTD
7785
 * subset which contains no parameter entity references, or a document
7786
 * with "standalone='yes'", ...  ... The declaration of a parameter
7787
 * entity must precede any reference to it...
7788
 *
7789
 * [ VC: Entity Declared ]
7790
 * In a document with an external subset or external parameter entities
7791
 * with "standalone='no'", ...  ... The declaration of a parameter entity
7792
 * must precede any reference to it...
7793
 *
7794
 * [ WFC: In DTD ]
7795
 * Parameter-entity references may only appear in the DTD.
7796
 * NOTE: misleading but this is handled.
7797
 */
7798
void
7799
xmlParsePEReference(xmlParserCtxtPtr ctxt)
7800
61.0k
{
7801
61.0k
    const xmlChar *name;
7802
61.0k
    xmlEntityPtr entity = NULL;
7803
61.0k
    xmlParserInputPtr input;
7804
7805
61.0k
    if (RAW != '%')
7806
0
        return;
7807
61.0k
    NEXT;
7808
61.0k
    name = xmlParseName(ctxt);
7809
61.0k
    if (name == NULL) {
7810
779
  xmlFatalErrMsg(ctxt, XML_ERR_PEREF_NO_NAME, "PEReference: no name\n");
7811
779
  return;
7812
779
    }
7813
60.3k
    if (RAW != ';') {
7814
659
  xmlFatalErr(ctxt, XML_ERR_PEREF_SEMICOL_MISSING, NULL);
7815
659
        return;
7816
659
    }
7817
7818
59.6k
    NEXT;
7819
7820
    /*
7821
     * Request the entity from SAX
7822
     */
7823
59.6k
    if ((ctxt->sax != NULL) &&
7824
59.6k
  (ctxt->sax->getParameterEntity != NULL))
7825
59.6k
  entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
7826
59.6k
    if (entity == NULL) {
7827
  /*
7828
   * [ WFC: Entity Declared ]
7829
   * In a document without any DTD, a document with only an
7830
   * internal DTD subset which contains no parameter entity
7831
   * references, or a document with "standalone='yes'", ...
7832
   * ... The declaration of a parameter entity must precede
7833
   * any reference to it...
7834
   */
7835
2.02k
  if ((ctxt->standalone == 1) ||
7836
2.02k
      ((ctxt->hasExternalSubset == 0) &&
7837
1.82k
       (ctxt->hasPErefs == 0))) {
7838
328
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7839
328
            "PEReference: %%%s; not found\n",
7840
328
            name);
7841
1.69k
  } else {
7842
      /*
7843
       * [ VC: Entity Declared ]
7844
       * In a document with an external subset or external
7845
       * parameter entities with "standalone='no'", ...
7846
       * ... The declaration of a parameter entity must
7847
       * precede any reference to it...
7848
       */
7849
1.69k
            if ((ctxt->validate) && (ctxt->vctxt.error != NULL)) {
7850
0
                xmlValidityError(ctxt, XML_WAR_UNDECLARED_ENTITY,
7851
0
                                 "PEReference: %%%s; not found\n",
7852
0
                                 name, NULL);
7853
0
            } else
7854
1.69k
                xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
7855
1.69k
                              "PEReference: %%%s; not found\n",
7856
1.69k
                              name, NULL);
7857
1.69k
            ctxt->valid = 0;
7858
1.69k
  }
7859
57.6k
    } else {
7860
  /*
7861
   * Internal checking in case the entity quest barfed
7862
   */
7863
57.6k
  if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
7864
57.6k
      (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
7865
0
      xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
7866
0
      "Internal: %%%s; is not a parameter entity\n",
7867
0
        name, NULL);
7868
57.6k
  } else {
7869
57.6k
      if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
7870
57.6k
                ((ctxt->options & XML_PARSE_NO_XXE) ||
7871
137
     ((ctxt->loadsubset == 0) &&
7872
71
      (ctxt->replaceEntities == 0) &&
7873
71
      (ctxt->validate == 0))))
7874
137
    return;
7875
7876
57.4k
            if (entity->flags & XML_ENT_EXPANDING) {
7877
2
                xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
7878
2
                xmlHaltParser(ctxt);
7879
2
                return;
7880
2
            }
7881
7882
57.4k
      input = xmlNewEntityInputStream(ctxt, entity);
7883
57.4k
      if (xmlPushInput(ctxt, input) < 0) {
7884
0
                xmlFreeInputStream(input);
7885
0
    return;
7886
0
            }
7887
7888
57.4k
            entity->flags |= XML_ENT_EXPANDING;
7889
7890
57.4k
      if (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) {
7891
0
                xmlDetectEncoding(ctxt);
7892
7893
0
                if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) &&
7894
0
                    (IS_BLANK_CH(NXT(5)))) {
7895
0
                    xmlParseTextDecl(ctxt);
7896
0
                }
7897
0
            }
7898
57.4k
  }
7899
57.6k
    }
7900
59.5k
    ctxt->hasPErefs = 1;
7901
59.5k
}
7902
7903
/**
7904
 * xmlLoadEntityContent:
7905
 * @ctxt:  an XML parser context
7906
 * @entity: an unloaded system entity
7907
 *
7908
 * Load the original content of the given system entity from the
7909
 * ExternalID/SystemID given. This is to be used for Included in Literal
7910
 * http://www.w3.org/TR/REC-xml/#inliteral processing of entities references
7911
 *
7912
 * Returns 0 in case of success and -1 in case of failure
7913
 */
7914
static int
7915
0
xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
7916
0
    xmlParserInputPtr oldinput, input = NULL;
7917
0
    xmlParserInputPtr *oldinputTab;
7918
0
    const xmlChar *oldencoding;
7919
0
    xmlChar *content = NULL;
7920
0
    size_t length, i;
7921
0
    int oldinputNr, oldinputMax;
7922
0
    int ret = -1;
7923
0
    int res;
7924
7925
0
    if ((ctxt == NULL) || (entity == NULL) ||
7926
0
        ((entity->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
7927
0
   (entity->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY)) ||
7928
0
  (entity->content != NULL)) {
7929
0
  xmlFatalErr(ctxt, XML_ERR_ARGUMENT,
7930
0
              "xmlLoadEntityContent parameter error");
7931
0
        return(-1);
7932
0
    }
7933
7934
0
    input = xmlLoadExternalEntity((char *) entity->URI,
7935
0
           (char *) entity->ExternalID, ctxt);
7936
0
    if (input == NULL)
7937
0
        return(-1);
7938
7939
0
    oldinput = ctxt->input;
7940
0
    oldinputNr = ctxt->inputNr;
7941
0
    oldinputMax = ctxt->inputMax;
7942
0
    oldinputTab = ctxt->inputTab;
7943
0
    oldencoding = ctxt->encoding;
7944
7945
0
    ctxt->input = NULL;
7946
0
    ctxt->inputNr = 0;
7947
0
    ctxt->inputMax = 1;
7948
0
    ctxt->encoding = NULL;
7949
0
    ctxt->inputTab = xmlMalloc(sizeof(xmlParserInputPtr));
7950
0
    if (ctxt->inputTab == NULL) {
7951
0
        xmlErrMemory(ctxt);
7952
0
        xmlFreeInputStream(input);
7953
0
        goto error;
7954
0
    }
7955
7956
0
    xmlBufResetInput(input->buf->buffer, input);
7957
7958
0
    inputPush(ctxt, input);
7959
7960
0
    xmlDetectEncoding(ctxt);
7961
7962
    /*
7963
     * Parse a possible text declaration first
7964
     */
7965
0
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
7966
0
  xmlParseTextDecl(ctxt);
7967
        /*
7968
         * An XML-1.0 document can't reference an entity not XML-1.0
7969
         */
7970
0
        if ((xmlStrEqual(ctxt->version, BAD_CAST "1.0")) &&
7971
0
            (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) {
7972
0
            xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH,
7973
0
                           "Version mismatch between document and entity\n");
7974
0
        }
7975
0
    }
7976
7977
0
    length = input->cur - input->base;
7978
0
    xmlBufShrink(input->buf->buffer, length);
7979
0
    xmlSaturatedAdd(&ctxt->sizeentities, length);
7980
7981
0
    while ((res = xmlParserInputBufferGrow(input->buf, 4096)) > 0)
7982
0
        ;
7983
7984
0
    xmlBufResetInput(input->buf->buffer, input);
7985
7986
0
    if (res < 0) {
7987
0
        xmlCtxtErrIO(ctxt, input->buf->error, NULL);
7988
0
        goto error;
7989
0
    }
7990
7991
0
    length = xmlBufUse(input->buf->buffer);
7992
0
    content = xmlBufDetach(input->buf->buffer);
7993
7994
0
    if (length > INT_MAX) {
7995
0
        xmlErrMemory(ctxt);
7996
0
        goto error;
7997
0
    }
7998
7999
0
    for (i = 0; i < length; ) {
8000
0
        int clen = length - i;
8001
0
        int c = xmlGetUTF8Char(content + i, &clen);
8002
8003
0
        if ((c < 0) || (!IS_CHAR(c))) {
8004
0
            xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
8005
0
                              "xmlLoadEntityContent: invalid char value %d\n",
8006
0
                              content[i]);
8007
0
            goto error;
8008
0
        }
8009
0
        i += clen;
8010
0
    }
8011
8012
0
    xmlSaturatedAdd(&ctxt->sizeentities, length);
8013
0
    entity->content = content;
8014
0
    entity->length = length;
8015
0
    content = NULL;
8016
0
    ret = 0;
8017
8018
0
error:
8019
0
    while (ctxt->inputNr > 0)
8020
0
        xmlFreeInputStream(inputPop(ctxt));
8021
0
    xmlFree(ctxt->inputTab);
8022
0
    xmlFree((xmlChar *) ctxt->encoding);
8023
8024
0
    ctxt->input = oldinput;
8025
0
    ctxt->inputNr = oldinputNr;
8026
0
    ctxt->inputMax = oldinputMax;
8027
0
    ctxt->inputTab = oldinputTab;
8028
0
    ctxt->encoding = oldencoding;
8029
8030
0
    xmlFree(content);
8031
8032
0
    return(ret);
8033
0
}
8034
8035
/**
8036
 * xmlParseStringPEReference:
8037
 * @ctxt:  an XML parser context
8038
 * @str:  a pointer to an index in the string
8039
 *
8040
 * parse PEReference declarations
8041
 *
8042
 * [69] PEReference ::= '%' Name ';'
8043
 *
8044
 * [ WFC: No Recursion ]
8045
 * A parsed entity must not contain a recursive
8046
 * reference to itself, either directly or indirectly.
8047
 *
8048
 * [ WFC: Entity Declared ]
8049
 * In a document without any DTD, a document with only an internal DTD
8050
 * subset which contains no parameter entity references, or a document
8051
 * with "standalone='yes'", ...  ... The declaration of a parameter
8052
 * entity must precede any reference to it...
8053
 *
8054
 * [ VC: Entity Declared ]
8055
 * In a document with an external subset or external parameter entities
8056
 * with "standalone='no'", ...  ... The declaration of a parameter entity
8057
 * must precede any reference to it...
8058
 *
8059
 * [ WFC: In DTD ]
8060
 * Parameter-entity references may only appear in the DTD.
8061
 * NOTE: misleading but this is handled.
8062
 *
8063
 * Returns the string of the entity content.
8064
 *         str is updated to the current value of the index
8065
 */
8066
static xmlEntityPtr
8067
2.44k
xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
8068
2.44k
    const xmlChar *ptr;
8069
2.44k
    xmlChar cur;
8070
2.44k
    xmlChar *name;
8071
2.44k
    xmlEntityPtr entity = NULL;
8072
8073
2.44k
    if ((str == NULL) || (*str == NULL)) return(NULL);
8074
2.44k
    ptr = *str;
8075
2.44k
    cur = *ptr;
8076
2.44k
    if (cur != '%')
8077
0
        return(NULL);
8078
2.44k
    ptr++;
8079
2.44k
    name = xmlParseStringName(ctxt, &ptr);
8080
2.44k
    if (name == NULL) {
8081
1.00k
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8082
1.00k
           "xmlParseStringPEReference: no name\n");
8083
1.00k
  *str = ptr;
8084
1.00k
  return(NULL);
8085
1.00k
    }
8086
1.44k
    cur = *ptr;
8087
1.44k
    if (cur != ';') {
8088
459
  xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
8089
459
  xmlFree(name);
8090
459
  *str = ptr;
8091
459
  return(NULL);
8092
459
    }
8093
986
    ptr++;
8094
8095
    /*
8096
     * Request the entity from SAX
8097
     */
8098
986
    if ((ctxt->sax != NULL) &&
8099
986
  (ctxt->sax->getParameterEntity != NULL))
8100
986
  entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
8101
986
    if (entity == NULL) {
8102
  /*
8103
   * [ WFC: Entity Declared ]
8104
   * In a document without any DTD, a document with only an
8105
   * internal DTD subset which contains no parameter entity
8106
   * references, or a document with "standalone='yes'", ...
8107
   * ... The declaration of a parameter entity must precede
8108
   * any reference to it...
8109
   */
8110
757
  if ((ctxt->standalone == 1) ||
8111
757
      ((ctxt->hasExternalSubset == 0) && (ctxt->hasPErefs == 0))) {
8112
203
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
8113
203
     "PEReference: %%%s; not found\n", name);
8114
554
  } else {
8115
      /*
8116
       * [ VC: Entity Declared ]
8117
       * In a document with an external subset or external
8118
       * parameter entities with "standalone='no'", ...
8119
       * ... The declaration of a parameter entity must
8120
       * precede any reference to it...
8121
       */
8122
554
      xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8123
554
        "PEReference: %%%s; not found\n",
8124
554
        name, NULL);
8125
554
      ctxt->valid = 0;
8126
554
  }
8127
757
    } else {
8128
  /*
8129
   * Internal checking in case the entity quest barfed
8130
   */
8131
229
  if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
8132
229
      (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
8133
0
      xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8134
0
        "%%%s; is not a parameter entity\n",
8135
0
        name, NULL);
8136
0
  }
8137
229
    }
8138
986
    ctxt->hasPErefs = 1;
8139
986
    xmlFree(name);
8140
986
    *str = ptr;
8141
986
    return(entity);
8142
1.44k
}
8143
8144
/**
8145
 * xmlParseDocTypeDecl:
8146
 * @ctxt:  an XML parser context
8147
 *
8148
 * DEPRECATED: Internal function, don't use.
8149
 *
8150
 * parse a DOCTYPE declaration
8151
 *
8152
 * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
8153
 *                      ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
8154
 *
8155
 * [ VC: Root Element Type ]
8156
 * The Name in the document type declaration must match the element
8157
 * type of the root element.
8158
 */
8159
8160
void
8161
10.2k
xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
8162
10.2k
    const xmlChar *name = NULL;
8163
10.2k
    xmlChar *ExternalID = NULL;
8164
10.2k
    xmlChar *URI = NULL;
8165
8166
    /*
8167
     * We know that '<!DOCTYPE' has been detected.
8168
     */
8169
10.2k
    SKIP(9);
8170
8171
10.2k
    SKIP_BLANKS;
8172
8173
    /*
8174
     * Parse the DOCTYPE name.
8175
     */
8176
10.2k
    name = xmlParseName(ctxt);
8177
10.2k
    if (name == NULL) {
8178
7.18k
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8179
7.18k
           "xmlParseDocTypeDecl : no DOCTYPE name !\n");
8180
7.18k
    }
8181
10.2k
    ctxt->intSubName = name;
8182
8183
10.2k
    SKIP_BLANKS;
8184
8185
    /*
8186
     * Check for SystemID and ExternalID
8187
     */
8188
10.2k
    URI = xmlParseExternalID(ctxt, &ExternalID, 1);
8189
8190
10.2k
    if ((URI != NULL) || (ExternalID != NULL)) {
8191
778
        ctxt->hasExternalSubset = 1;
8192
778
    }
8193
10.2k
    ctxt->extSubURI = URI;
8194
10.2k
    ctxt->extSubSystem = ExternalID;
8195
8196
10.2k
    SKIP_BLANKS;
8197
8198
    /*
8199
     * Create and update the internal subset.
8200
     */
8201
10.2k
    if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL) &&
8202
10.2k
  (!ctxt->disableSAX))
8203
7.63k
  ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
8204
8205
    /*
8206
     * Is there any internal subset declarations ?
8207
     * they are handled separately in xmlParseInternalSubset()
8208
     */
8209
10.2k
    if (RAW == '[')
8210
8.39k
  return;
8211
8212
    /*
8213
     * We should be at the end of the DOCTYPE declaration.
8214
     */
8215
1.82k
    if (RAW != '>') {
8216
444
  xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
8217
444
    }
8218
1.82k
    NEXT;
8219
1.82k
}
8220
8221
/**
8222
 * xmlParseInternalSubset:
8223
 * @ctxt:  an XML parser context
8224
 *
8225
 * parse the internal subset declaration
8226
 *
8227
 * [28 end] ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
8228
 */
8229
8230
static void
8231
8.59k
xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
8232
    /*
8233
     * Is there any DTD definition ?
8234
     */
8235
8.59k
    if (RAW == '[') {
8236
8.59k
        int oldInputNr = ctxt->inputNr;
8237
8238
8.59k
        NEXT;
8239
  /*
8240
   * Parse the succession of Markup declarations and
8241
   * PEReferences.
8242
   * Subsequence (markupdecl | PEReference | S)*
8243
   */
8244
8.59k
  SKIP_BLANKS;
8245
173k
  while (((RAW != ']') || (ctxt->inputNr > oldInputNr)) &&
8246
173k
               (PARSER_STOPPED(ctxt) == 0)) {
8247
8248
            /*
8249
             * Conditional sections are allowed from external entities included
8250
             * by PE References in the internal subset.
8251
             */
8252
168k
            if ((PARSER_EXTERNAL(ctxt)) &&
8253
168k
                (RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
8254
0
                xmlParseConditionalSections(ctxt);
8255
168k
            } else if ((RAW == '<') && ((NXT(1) == '!') || (NXT(1) == '?'))) {
8256
103k
          xmlParseMarkupDecl(ctxt);
8257
103k
            } else if (RAW == '%') {
8258
61.0k
          xmlParsePEReference(ctxt);
8259
61.0k
            } else {
8260
4.03k
    xmlFatalErr(ctxt, XML_ERR_INT_SUBSET_NOT_FINISHED, NULL);
8261
4.03k
                break;
8262
4.03k
            }
8263
164k
      SKIP_BLANKS_PE;
8264
164k
            SHRINK;
8265
164k
            GROW;
8266
164k
  }
8267
8268
8.65k
        while (ctxt->inputNr > oldInputNr)
8269
61
            xmlPopPE(ctxt);
8270
8271
8.59k
  if (RAW == ']') {
8272
3.40k
      NEXT;
8273
3.40k
      SKIP_BLANKS;
8274
3.40k
  }
8275
8.59k
    }
8276
8277
    /*
8278
     * We should be at the end of the DOCTYPE declaration.
8279
     */
8280
8.59k
    if ((ctxt->wellFormed) && (RAW != '>')) {
8281
220
  xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
8282
220
  return;
8283
220
    }
8284
8.37k
    NEXT;
8285
8.37k
}
8286
8287
#ifdef LIBXML_SAX1_ENABLED
8288
/**
8289
 * xmlParseAttribute:
8290
 * @ctxt:  an XML parser context
8291
 * @value:  a xmlChar ** used to store the value of the attribute
8292
 *
8293
 * DEPRECATED: Internal function, don't use.
8294
 *
8295
 * parse an attribute
8296
 *
8297
 * [41] Attribute ::= Name Eq AttValue
8298
 *
8299
 * [ WFC: No External Entity References ]
8300
 * Attribute values cannot contain direct or indirect entity references
8301
 * to external entities.
8302
 *
8303
 * [ WFC: No < in Attribute Values ]
8304
 * The replacement text of any entity referred to directly or indirectly in
8305
 * an attribute value (other than "&lt;") must not contain a <.
8306
 *
8307
 * [ VC: Attribute Value Type ]
8308
 * The attribute must have been declared; the value must be of the type
8309
 * declared for it.
8310
 *
8311
 * [25] Eq ::= S? '=' S?
8312
 *
8313
 * With namespace:
8314
 *
8315
 * [NS 11] Attribute ::= QName Eq AttValue
8316
 *
8317
 * Also the case QName == xmlns:??? is handled independently as a namespace
8318
 * definition.
8319
 *
8320
 * Returns the attribute name, and the value in *value.
8321
 */
8322
8323
const xmlChar *
8324
52.6k
xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
8325
52.6k
    const xmlChar *name;
8326
52.6k
    xmlChar *val;
8327
8328
52.6k
    *value = NULL;
8329
52.6k
    GROW;
8330
52.6k
    name = xmlParseName(ctxt);
8331
52.6k
    if (name == NULL) {
8332
40.7k
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8333
40.7k
                 "error parsing attribute name\n");
8334
40.7k
        return(NULL);
8335
40.7k
    }
8336
8337
    /*
8338
     * read the value
8339
     */
8340
11.8k
    SKIP_BLANKS;
8341
11.8k
    if (RAW == '=') {
8342
7.67k
        NEXT;
8343
7.67k
  SKIP_BLANKS;
8344
7.67k
  val = xmlParseAttValue(ctxt);
8345
7.67k
    } else {
8346
4.18k
  xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
8347
4.18k
         "Specification mandates value for attribute %s\n", name);
8348
4.18k
  return(name);
8349
4.18k
    }
8350
8351
    /*
8352
     * Check that xml:lang conforms to the specification
8353
     * No more registered as an error, just generate a warning now
8354
     * since this was deprecated in XML second edition
8355
     */
8356
7.67k
    if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "xml:lang"))) {
8357
1.65k
  if (!xmlCheckLanguageID(val)) {
8358
1.26k
      xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
8359
1.26k
              "Malformed value for xml:lang : %s\n",
8360
1.26k
        val, NULL);
8361
1.26k
  }
8362
1.65k
    }
8363
8364
    /*
8365
     * Check that xml:space conforms to the specification
8366
     */
8367
7.67k
    if (xmlStrEqual(name, BAD_CAST "xml:space")) {
8368
167
  if (xmlStrEqual(val, BAD_CAST "default"))
8369
74
      *(ctxt->space) = 0;
8370
93
  else if (xmlStrEqual(val, BAD_CAST "preserve"))
8371
27
      *(ctxt->space) = 1;
8372
66
  else {
8373
66
    xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
8374
66
"Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
8375
66
                                 val, NULL);
8376
66
  }
8377
167
    }
8378
8379
7.67k
    *value = val;
8380
7.67k
    return(name);
8381
11.8k
}
8382
8383
/**
8384
 * xmlParseStartTag:
8385
 * @ctxt:  an XML parser context
8386
 *
8387
 * DEPRECATED: Internal function, don't use.
8388
 *
8389
 * Parse a start tag. Always consumes '<'.
8390
 *
8391
 * [40] STag ::= '<' Name (S Attribute)* S? '>'
8392
 *
8393
 * [ WFC: Unique Att Spec ]
8394
 * No attribute name may appear more than once in the same start-tag or
8395
 * empty-element tag.
8396
 *
8397
 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
8398
 *
8399
 * [ WFC: Unique Att Spec ]
8400
 * No attribute name may appear more than once in the same start-tag or
8401
 * empty-element tag.
8402
 *
8403
 * With namespace:
8404
 *
8405
 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
8406
 *
8407
 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
8408
 *
8409
 * Returns the element name parsed
8410
 */
8411
8412
const xmlChar *
8413
59.5k
xmlParseStartTag(xmlParserCtxtPtr ctxt) {
8414
59.5k
    const xmlChar *name;
8415
59.5k
    const xmlChar *attname;
8416
59.5k
    xmlChar *attvalue;
8417
59.5k
    const xmlChar **atts = ctxt->atts;
8418
59.5k
    int nbatts = 0;
8419
59.5k
    int maxatts = ctxt->maxatts;
8420
59.5k
    int i;
8421
8422
59.5k
    if (RAW != '<') return(NULL);
8423
59.5k
    NEXT1;
8424
8425
59.5k
    name = xmlParseName(ctxt);
8426
59.5k
    if (name == NULL) {
8427
6.72k
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8428
6.72k
       "xmlParseStartTag: invalid element name\n");
8429
6.72k
        return(NULL);
8430
6.72k
    }
8431
8432
    /*
8433
     * Now parse the attributes, it ends up with the ending
8434
     *
8435
     * (S Attribute)* S?
8436
     */
8437
52.8k
    SKIP_BLANKS;
8438
52.8k
    GROW;
8439
8440
62.9k
    while (((RAW != '>') &&
8441
62.9k
     ((RAW != '/') || (NXT(1) != '>')) &&
8442
62.9k
     (IS_BYTE_CHAR(RAW))) && (PARSER_STOPPED(ctxt) == 0)) {
8443
52.6k
  attname = xmlParseAttribute(ctxt, &attvalue);
8444
52.6k
        if (attname == NULL)
8445
40.7k
      break;
8446
11.8k
        if (attvalue != NULL) {
8447
      /*
8448
       * [ WFC: Unique Att Spec ]
8449
       * No attribute name may appear more than once in the same
8450
       * start-tag or empty-element tag.
8451
       */
8452
11.6k
      for (i = 0; i < nbatts;i += 2) {
8453
5.89k
          if (xmlStrEqual(atts[i], attname)) {
8454
761
        xmlErrAttributeDup(ctxt, NULL, attname);
8455
761
        xmlFree(attvalue);
8456
761
        goto failed;
8457
761
    }
8458
5.89k
      }
8459
      /*
8460
       * Add the pair to atts
8461
       */
8462
5.77k
      if (atts == NULL) {
8463
1.43k
          maxatts = 22; /* allow for 10 attrs by default */
8464
1.43k
          atts = (const xmlChar **)
8465
1.43k
           xmlMalloc(maxatts * sizeof(xmlChar *));
8466
1.43k
    if (atts == NULL) {
8467
0
        xmlErrMemory(ctxt);
8468
0
        if (attvalue != NULL)
8469
0
      xmlFree(attvalue);
8470
0
        goto failed;
8471
0
    }
8472
1.43k
    ctxt->atts = atts;
8473
1.43k
    ctxt->maxatts = maxatts;
8474
4.34k
      } else if (nbatts + 4 > maxatts) {
8475
8
          const xmlChar **n;
8476
8477
8
          maxatts *= 2;
8478
8
          n = (const xmlChar **) xmlRealloc((void *) atts,
8479
8
               maxatts * sizeof(const xmlChar *));
8480
8
    if (n == NULL) {
8481
0
        xmlErrMemory(ctxt);
8482
0
        if (attvalue != NULL)
8483
0
      xmlFree(attvalue);
8484
0
        goto failed;
8485
0
    }
8486
8
    atts = n;
8487
8
    ctxt->atts = atts;
8488
8
    ctxt->maxatts = maxatts;
8489
8
      }
8490
5.77k
      atts[nbatts++] = attname;
8491
5.77k
      atts[nbatts++] = attvalue;
8492
5.77k
      atts[nbatts] = NULL;
8493
5.77k
      atts[nbatts + 1] = NULL;
8494
5.77k
  } else {
8495
5.32k
      if (attvalue != NULL)
8496
0
    xmlFree(attvalue);
8497
5.32k
  }
8498
8499
11.8k
failed:
8500
8501
11.8k
  GROW
8502
11.8k
  if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
8503
1.82k
      break;
8504
10.0k
  if (SKIP_BLANKS == 0) {
8505
8.14k
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
8506
8.14k
         "attributes construct error\n");
8507
8.14k
  }
8508
10.0k
  SHRINK;
8509
10.0k
        GROW;
8510
10.0k
    }
8511
8512
    /*
8513
     * SAX: Start of Element !
8514
     */
8515
52.8k
    if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL) &&
8516
52.8k
  (!ctxt->disableSAX)) {
8517
50.5k
  if (nbatts > 0)
8518
4.35k
      ctxt->sax->startElement(ctxt->userData, name, atts);
8519
46.1k
  else
8520
46.1k
      ctxt->sax->startElement(ctxt->userData, name, NULL);
8521
50.5k
    }
8522
8523
52.8k
    if (atts != NULL) {
8524
        /* Free only the content strings */
8525
12.6k
        for (i = 1;i < nbatts;i+=2)
8526
5.77k
      if (atts[i] != NULL)
8527
5.77k
         xmlFree((xmlChar *) atts[i]);
8528
6.83k
    }
8529
52.8k
    return(name);
8530
52.8k
}
8531
8532
/**
8533
 * xmlParseEndTag1:
8534
 * @ctxt:  an XML parser context
8535
 * @line:  line of the start tag
8536
 * @nsNr:  number of namespaces on the start tag
8537
 *
8538
 * Parse an end tag. Always consumes '</'.
8539
 *
8540
 * [42] ETag ::= '</' Name S? '>'
8541
 *
8542
 * With namespace
8543
 *
8544
 * [NS 9] ETag ::= '</' QName S? '>'
8545
 */
8546
8547
static void
8548
5.28k
xmlParseEndTag1(xmlParserCtxtPtr ctxt, int line) {
8549
5.28k
    const xmlChar *name;
8550
8551
5.28k
    GROW;
8552
5.28k
    if ((RAW != '<') || (NXT(1) != '/')) {
8553
3
  xmlFatalErrMsg(ctxt, XML_ERR_LTSLASH_REQUIRED,
8554
3
           "xmlParseEndTag: '</' not found\n");
8555
3
  return;
8556
3
    }
8557
5.27k
    SKIP(2);
8558
8559
5.27k
    name = xmlParseNameAndCompare(ctxt,ctxt->name);
8560
8561
    /*
8562
     * We should definitely be at the ending "S? '>'" part
8563
     */
8564
5.27k
    GROW;
8565
5.27k
    SKIP_BLANKS;
8566
5.27k
    if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
8567
2.43k
  xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
8568
2.43k
    } else
8569
2.84k
  NEXT1;
8570
8571
    /*
8572
     * [ WFC: Element Type Match ]
8573
     * The Name in an element's end-tag must match the element type in the
8574
     * start-tag.
8575
     *
8576
     */
8577
5.27k
    if (name != (xmlChar*)1) {
8578
3.90k
        if (name == NULL) name = BAD_CAST "unparsable";
8579
3.90k
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
8580
3.90k
         "Opening and ending tag mismatch: %s line %d and %s\n",
8581
3.90k
                    ctxt->name, line, name);
8582
3.90k
    }
8583
8584
    /*
8585
     * SAX: End of Tag
8586
     */
8587
5.27k
    if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
8588
5.27k
  (!ctxt->disableSAX))
8589
4.61k
        ctxt->sax->endElement(ctxt->userData, ctxt->name);
8590
8591
5.27k
    namePop(ctxt);
8592
5.27k
    spacePop(ctxt);
8593
5.27k
    return;
8594
5.28k
}
8595
8596
/**
8597
 * xmlParseEndTag:
8598
 * @ctxt:  an XML parser context
8599
 *
8600
 * DEPRECATED: Internal function, don't use.
8601
 *
8602
 * parse an end of tag
8603
 *
8604
 * [42] ETag ::= '</' Name S? '>'
8605
 *
8606
 * With namespace
8607
 *
8608
 * [NS 9] ETag ::= '</' QName S? '>'
8609
 */
8610
8611
void
8612
0
xmlParseEndTag(xmlParserCtxtPtr ctxt) {
8613
0
    xmlParseEndTag1(ctxt, 0);
8614
0
}
8615
#endif /* LIBXML_SAX1_ENABLED */
8616
8617
/************************************************************************
8618
 *                  *
8619
 *          SAX 2 specific operations       *
8620
 *                  *
8621
 ************************************************************************/
8622
8623
/**
8624
 * xmlParseQNameHashed:
8625
 * @ctxt:  an XML parser context
8626
 * @prefix:  pointer to store the prefix part
8627
 *
8628
 * parse an XML Namespace QName
8629
 *
8630
 * [6]  QName  ::= (Prefix ':')? LocalPart
8631
 * [7]  Prefix  ::= NCName
8632
 * [8]  LocalPart  ::= NCName
8633
 *
8634
 * Returns the Name parsed or NULL
8635
 */
8636
8637
static xmlHashedString
8638
173k
xmlParseQNameHashed(xmlParserCtxtPtr ctxt, xmlHashedString *prefix) {
8639
173k
    xmlHashedString l, p;
8640
173k
    int start, isNCName = 0;
8641
8642
173k
    l.name = NULL;
8643
173k
    p.name = NULL;
8644
8645
173k
    GROW;
8646
173k
    start = CUR_PTR - BASE_PTR;
8647
8648
173k
    l = xmlParseNCName(ctxt);
8649
173k
    if (l.name != NULL) {
8650
82.9k
        isNCName = 1;
8651
82.9k
        if (CUR == ':') {
8652
15.9k
            NEXT;
8653
15.9k
            p = l;
8654
15.9k
            l = xmlParseNCName(ctxt);
8655
15.9k
        }
8656
82.9k
    }
8657
173k
    if ((l.name == NULL) || (CUR == ':')) {
8658
92.9k
        xmlChar *tmp;
8659
8660
92.9k
        l.name = NULL;
8661
92.9k
        p.name = NULL;
8662
92.9k
        if ((isNCName == 0) && (CUR != ':'))
8663
64.1k
            return(l);
8664
28.7k
        tmp = xmlParseNmtoken(ctxt);
8665
28.7k
        if (tmp != NULL)
8666
27.5k
            xmlFree(tmp);
8667
28.7k
        l = xmlDictLookupHashed(ctxt->dict, BASE_PTR + start,
8668
28.7k
                                CUR_PTR - (BASE_PTR + start));
8669
28.7k
        if (l.name == NULL) {
8670
0
            xmlErrMemory(ctxt);
8671
0
            return(l);
8672
0
        }
8673
28.7k
        xmlNsErr(ctxt, XML_NS_ERR_QNAME,
8674
28.7k
                 "Failed to parse QName '%s'\n", l.name, NULL, NULL);
8675
28.7k
    }
8676
8677
109k
    *prefix = p;
8678
109k
    return(l);
8679
173k
}
8680
8681
/**
8682
 * xmlParseQName:
8683
 * @ctxt:  an XML parser context
8684
 * @prefix:  pointer to store the prefix part
8685
 *
8686
 * parse an XML Namespace QName
8687
 *
8688
 * [6]  QName  ::= (Prefix ':')? LocalPart
8689
 * [7]  Prefix  ::= NCName
8690
 * [8]  LocalPart  ::= NCName
8691
 *
8692
 * Returns the Name parsed or NULL
8693
 */
8694
8695
static const xmlChar *
8696
1.46k
xmlParseQName(xmlParserCtxtPtr ctxt, const xmlChar **prefix) {
8697
1.46k
    xmlHashedString n, p;
8698
8699
1.46k
    n = xmlParseQNameHashed(ctxt, &p);
8700
1.46k
    if (n.name == NULL)
8701
710
        return(NULL);
8702
752
    *prefix = p.name;
8703
752
    return(n.name);
8704
1.46k
}
8705
8706
/**
8707
 * xmlParseQNameAndCompare:
8708
 * @ctxt:  an XML parser context
8709
 * @name:  the localname
8710
 * @prefix:  the prefix, if any.
8711
 *
8712
 * parse an XML name and compares for match
8713
 * (specialized for endtag parsing)
8714
 *
8715
 * Returns NULL for an illegal name, (xmlChar*) 1 for success
8716
 * and the name for mismatch
8717
 */
8718
8719
static const xmlChar *
8720
xmlParseQNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *name,
8721
1.73k
                        xmlChar const *prefix) {
8722
1.73k
    const xmlChar *cmp;
8723
1.73k
    const xmlChar *in;
8724
1.73k
    const xmlChar *ret;
8725
1.73k
    const xmlChar *prefix2;
8726
8727
1.73k
    if (prefix == NULL) return(xmlParseNameAndCompare(ctxt, name));
8728
8729
1.73k
    GROW;
8730
1.73k
    in = ctxt->input->cur;
8731
8732
1.73k
    cmp = prefix;
8733
3.02k
    while (*in != 0 && *in == *cmp) {
8734
1.28k
  ++in;
8735
1.28k
  ++cmp;
8736
1.28k
    }
8737
1.73k
    if ((*cmp == 0) && (*in == ':')) {
8738
458
        in++;
8739
458
  cmp = name;
8740
1.35k
  while (*in != 0 && *in == *cmp) {
8741
893
      ++in;
8742
893
      ++cmp;
8743
893
  }
8744
458
  if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
8745
      /* success */
8746
274
            ctxt->input->col += in - ctxt->input->cur;
8747
274
      ctxt->input->cur = in;
8748
274
      return((const xmlChar*) 1);
8749
274
  }
8750
458
    }
8751
    /*
8752
     * all strings coms from the dictionary, equality can be done directly
8753
     */
8754
1.46k
    ret = xmlParseQName (ctxt, &prefix2);
8755
1.46k
    if (ret == NULL)
8756
710
        return(NULL);
8757
752
    if ((ret == name) && (prefix == prefix2))
8758
88
  return((const xmlChar*) 1);
8759
664
    return ret;
8760
752
}
8761
8762
/**
8763
 * xmlParseAttribute2:
8764
 * @ctxt:  an XML parser context
8765
 * @pref:  the element prefix
8766
 * @elem:  the element name
8767
 * @prefix:  a xmlChar ** used to store the value of the attribute prefix
8768
 * @value:  a xmlChar ** used to store the value of the attribute
8769
 * @len:  an int * to save the length of the attribute
8770
 * @alloc:  an int * to indicate if the attribute was allocated
8771
 *
8772
 * parse an attribute in the new SAX2 framework.
8773
 *
8774
 * Returns the attribute name, and the value in *value, .
8775
 */
8776
8777
static xmlHashedString
8778
xmlParseAttribute2(xmlParserCtxtPtr ctxt,
8779
                   const xmlChar * pref, const xmlChar * elem,
8780
                   xmlHashedString * hprefix, xmlChar ** value,
8781
                   int *len, int *alloc)
8782
69.1k
{
8783
69.1k
    xmlHashedString hname;
8784
69.1k
    const xmlChar *prefix, *name;
8785
69.1k
    xmlChar *val = NULL, *internal_val = NULL;
8786
69.1k
    int normalize = 0;
8787
8788
69.1k
    *value = NULL;
8789
69.1k
    GROW;
8790
69.1k
    hname = xmlParseQNameHashed(ctxt, hprefix);
8791
69.1k
    if (hname.name == NULL) {
8792
46.7k
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8793
46.7k
                       "error parsing attribute name\n");
8794
46.7k
        return(hname);
8795
46.7k
    }
8796
22.4k
    name = hname.name;
8797
22.4k
    if (hprefix->name != NULL)
8798
8.53k
        prefix = hprefix->name;
8799
13.9k
    else
8800
13.9k
        prefix = NULL;
8801
8802
    /*
8803
     * get the type if needed
8804
     */
8805
22.4k
    if (ctxt->attsSpecial != NULL) {
8806
3.50k
        int type;
8807
8808
3.50k
        type = (int) (ptrdiff_t) xmlHashQLookup2(ctxt->attsSpecial,
8809
3.50k
                                                 pref, elem,
8810
3.50k
                                                 prefix, name);
8811
3.50k
        if (type != 0)
8812
947
            normalize = 1;
8813
3.50k
    }
8814
8815
    /*
8816
     * read the value
8817
     */
8818
22.4k
    SKIP_BLANKS;
8819
22.4k
    if (RAW == '=') {
8820
18.8k
        NEXT;
8821
18.8k
        SKIP_BLANKS;
8822
18.8k
        val = xmlParseAttValueInternal(ctxt, len, alloc, normalize);
8823
18.8k
        if (val == NULL)
8824
1.27k
            goto error;
8825
18.8k
    } else {
8826
3.63k
        xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
8827
3.63k
                          "Specification mandates value for attribute %s\n",
8828
3.63k
                          name);
8829
3.63k
        goto error;
8830
3.63k
    }
8831
8832
17.5k
    if (prefix == ctxt->str_xml) {
8833
        /*
8834
         * Check that xml:lang conforms to the specification
8835
         * No more registered as an error, just generate a warning now
8836
         * since this was deprecated in XML second edition
8837
         */
8838
4.33k
        if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "lang"))) {
8839
557
            internal_val = xmlStrndup(val, *len);
8840
557
            if (internal_val == NULL)
8841
0
                goto mem_error;
8842
557
            if (!xmlCheckLanguageID(internal_val)) {
8843
354
                xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
8844
354
                              "Malformed value for xml:lang : %s\n",
8845
354
                              internal_val, NULL);
8846
354
            }
8847
557
        }
8848
8849
        /*
8850
         * Check that xml:space conforms to the specification
8851
         */
8852
4.33k
        if (xmlStrEqual(name, BAD_CAST "space")) {
8853
123
            internal_val = xmlStrndup(val, *len);
8854
123
            if (internal_val == NULL)
8855
0
                goto mem_error;
8856
123
            if (xmlStrEqual(internal_val, BAD_CAST "default"))
8857
34
                *(ctxt->space) = 0;
8858
89
            else if (xmlStrEqual(internal_val, BAD_CAST "preserve"))
8859
20
                *(ctxt->space) = 1;
8860
69
            else {
8861
69
                xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
8862
69
                              "Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
8863
69
                              internal_val, NULL);
8864
69
            }
8865
123
        }
8866
4.33k
        if (internal_val) {
8867
680
            xmlFree(internal_val);
8868
680
        }
8869
4.33k
    }
8870
8871
17.5k
    *value = val;
8872
17.5k
    return (hname);
8873
8874
0
mem_error:
8875
0
    xmlErrMemory(ctxt);
8876
4.91k
error:
8877
4.91k
    if ((val != NULL) && (*alloc != 0))
8878
0
        xmlFree(val);
8879
4.91k
    return(hname);
8880
0
}
8881
8882
/**
8883
 * xmlAttrHashInsert:
8884
 * @ctxt: parser context
8885
 * @size: size of the hash table
8886
 * @name: attribute name
8887
 * @uri: namespace uri
8888
 * @hashValue: combined hash value of name and uri
8889
 * @aindex: attribute index (this is a multiple of 5)
8890
 *
8891
 * Inserts a new attribute into the hash table.
8892
 *
8893
 * Returns INT_MAX if no existing attribute was found, the attribute
8894
 * index if an attribute was found, -1 if a memory allocation failed.
8895
 */
8896
static int
8897
xmlAttrHashInsert(xmlParserCtxtPtr ctxt, unsigned size, const xmlChar *name,
8898
16.9k
                  const xmlChar *uri, unsigned hashValue, int aindex) {
8899
16.9k
    xmlAttrHashBucket *table = ctxt->attrHash;
8900
16.9k
    xmlAttrHashBucket *bucket;
8901
16.9k
    unsigned hindex;
8902
8903
16.9k
    hindex = hashValue & (size - 1);
8904
16.9k
    bucket = &table[hindex];
8905
8906
44.8k
    while (bucket->index >= 0) {
8907
33.5k
        const xmlChar **atts = &ctxt->atts[bucket->index];
8908
8909
33.5k
        if (name == atts[0]) {
8910
31.1k
            int nsIndex = (int) (ptrdiff_t) atts[2];
8911
8912
31.1k
            if ((nsIndex == NS_INDEX_EMPTY) ? (uri == NULL) :
8913
31.1k
                (nsIndex == NS_INDEX_XML) ? (uri == ctxt->str_xml) :
8914
25.4k
                (uri == ctxt->nsTab[nsIndex * 2 + 1]))
8915
5.78k
                return(bucket->index);
8916
31.1k
        }
8917
8918
27.8k
        hindex++;
8919
27.8k
        bucket++;
8920
27.8k
        if (hindex >= size) {
8921
438
            hindex = 0;
8922
438
            bucket = table;
8923
438
        }
8924
27.8k
    }
8925
8926
11.2k
    bucket->index = aindex;
8927
8928
11.2k
    return(INT_MAX);
8929
16.9k
}
8930
8931
/**
8932
 * xmlParseStartTag2:
8933
 * @ctxt:  an XML parser context
8934
 *
8935
 * Parse a start tag. Always consumes '<'.
8936
 *
8937
 * This routine is called when running SAX2 parsing
8938
 *
8939
 * [40] STag ::= '<' Name (S Attribute)* S? '>'
8940
 *
8941
 * [ WFC: Unique Att Spec ]
8942
 * No attribute name may appear more than once in the same start-tag or
8943
 * empty-element tag.
8944
 *
8945
 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
8946
 *
8947
 * [ WFC: Unique Att Spec ]
8948
 * No attribute name may appear more than once in the same start-tag or
8949
 * empty-element tag.
8950
 *
8951
 * With namespace:
8952
 *
8953
 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
8954
 *
8955
 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
8956
 *
8957
 * Returns the element name parsed
8958
 */
8959
8960
static const xmlChar *
8961
xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
8962
103k
                  const xmlChar **URI, int *nbNsPtr) {
8963
103k
    xmlHashedString hlocalname;
8964
103k
    xmlHashedString hprefix;
8965
103k
    xmlHashedString hattname;
8966
103k
    xmlHashedString haprefix;
8967
103k
    const xmlChar *localname;
8968
103k
    const xmlChar *prefix;
8969
103k
    const xmlChar *attname;
8970
103k
    const xmlChar *aprefix;
8971
103k
    const xmlChar *uri;
8972
103k
    xmlChar *attvalue = NULL;
8973
103k
    const xmlChar **atts = ctxt->atts;
8974
103k
    unsigned attrHashSize = 0;
8975
103k
    int maxatts = ctxt->maxatts;
8976
103k
    int nratts, nbatts, nbdef;
8977
103k
    int i, j, nbNs, nbTotalDef, attval, nsIndex, maxAtts;
8978
103k
    int alloc = 0;
8979
8980
103k
    if (RAW != '<') return(NULL);
8981
103k
    NEXT1;
8982
8983
103k
    nbatts = 0;
8984
103k
    nratts = 0;
8985
103k
    nbdef = 0;
8986
103k
    nbNs = 0;
8987
103k
    nbTotalDef = 0;
8988
103k
    attval = 0;
8989
8990
103k
    if (xmlParserNsStartElement(ctxt->nsdb) < 0) {
8991
0
        xmlErrMemory(ctxt);
8992
0
        return(NULL);
8993
0
    }
8994
8995
103k
    hlocalname = xmlParseQNameHashed(ctxt, &hprefix);
8996
103k
    if (hlocalname.name == NULL) {
8997
16.7k
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8998
16.7k
           "StartTag: invalid element name\n");
8999
16.7k
        return(NULL);
9000
16.7k
    }
9001
86.5k
    localname = hlocalname.name;
9002
86.5k
    prefix = hprefix.name;
9003
9004
    /*
9005
     * Now parse the attributes, it ends up with the ending
9006
     *
9007
     * (S Attribute)* S?
9008
     */
9009
86.5k
    SKIP_BLANKS;
9010
86.5k
    GROW;
9011
9012
    /*
9013
     * The ctxt->atts array will be ultimately passed to the SAX callback
9014
     * containing five xmlChar pointers for each attribute:
9015
     *
9016
     * [0] attribute name
9017
     * [1] attribute prefix
9018
     * [2] namespace URI
9019
     * [3] attribute value
9020
     * [4] end of attribute value
9021
     *
9022
     * To save memory, we reuse this array temporarily and store integers
9023
     * in these pointer variables.
9024
     *
9025
     * [0] attribute name
9026
     * [1] attribute prefix
9027
     * [2] hash value of attribute prefix, and later namespace index
9028
     * [3] for non-allocated values: ptrdiff_t offset into input buffer
9029
     * [4] for non-allocated values: ptrdiff_t offset into input buffer
9030
     *
9031
     * The ctxt->attallocs array contains an additional unsigned int for
9032
     * each attribute, containing the hash value of the attribute name
9033
     * and the alloc flag in bit 31.
9034
     */
9035
9036
95.9k
    while (((RAW != '>') &&
9037
95.9k
     ((RAW != '/') || (NXT(1) != '>')) &&
9038
95.9k
     (IS_BYTE_CHAR(RAW))) && (PARSER_STOPPED(ctxt) == 0)) {
9039
69.1k
  int len = -1;
9040
9041
69.1k
  hattname = xmlParseAttribute2(ctxt, prefix, localname,
9042
69.1k
                                          &haprefix, &attvalue, &len,
9043
69.1k
                                          &alloc);
9044
69.1k
        if (hattname.name == NULL)
9045
46.7k
      break;
9046
22.4k
        if (attvalue == NULL)
9047
4.91k
            goto next_attr;
9048
17.5k
        attname = hattname.name;
9049
17.5k
        aprefix = haprefix.name;
9050
17.5k
  if (len < 0) len = xmlStrlen(attvalue);
9051
9052
17.5k
        if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
9053
2.22k
            xmlHashedString huri;
9054
2.22k
            xmlURIPtr parsedUri;
9055
9056
2.22k
            huri = xmlDictLookupHashed(ctxt->dict, attvalue, len);
9057
2.22k
            uri = huri.name;
9058
2.22k
            if (uri == NULL) {
9059
0
                xmlErrMemory(ctxt);
9060
0
                goto next_attr;
9061
0
            }
9062
2.22k
            if (*uri != 0) {
9063
2.00k
                if (xmlParseURISafe((const char *) uri, &parsedUri) < 0) {
9064
0
                    xmlErrMemory(ctxt);
9065
0
                    goto next_attr;
9066
0
                }
9067
2.00k
                if (parsedUri == NULL) {
9068
816
                    xmlNsErr(ctxt, XML_WAR_NS_URI,
9069
816
                             "xmlns: '%s' is not a valid URI\n",
9070
816
                                       uri, NULL, NULL);
9071
1.19k
                } else {
9072
1.19k
                    if (parsedUri->scheme == NULL) {
9073
930
                        xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
9074
930
                                  "xmlns: URI %s is not absolute\n",
9075
930
                                  uri, NULL, NULL);
9076
930
                    }
9077
1.19k
                    xmlFreeURI(parsedUri);
9078
1.19k
                }
9079
2.00k
                if (uri == ctxt->str_xml_ns) {
9080
34
                    if (attname != ctxt->str_xml) {
9081
34
                        xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9082
34
                     "xml namespace URI cannot be the default namespace\n",
9083
34
                                 NULL, NULL, NULL);
9084
34
                    }
9085
34
                    goto next_attr;
9086
34
                }
9087
1.97k
                if ((len == 29) &&
9088
1.97k
                    (xmlStrEqual(uri,
9089
60
                             BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
9090
18
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9091
18
                         "reuse of the xmlns namespace name is forbidden\n",
9092
18
                             NULL, NULL, NULL);
9093
18
                    goto next_attr;
9094
18
                }
9095
1.97k
            }
9096
9097
2.17k
            if (xmlParserNsPush(ctxt, NULL, &huri, NULL, 0) > 0)
9098
1.91k
                nbNs++;
9099
15.3k
        } else if (aprefix == ctxt->str_xmlns) {
9100
2.21k
            xmlHashedString huri;
9101
2.21k
            xmlURIPtr parsedUri;
9102
9103
2.21k
            huri = xmlDictLookupHashed(ctxt->dict, attvalue, len);
9104
2.21k
            uri = huri.name;
9105
2.21k
            if (uri == NULL) {
9106
0
                xmlErrMemory(ctxt);
9107
0
                goto next_attr;
9108
0
            }
9109
9110
2.21k
            if (attname == ctxt->str_xml) {
9111
102
                if (uri != ctxt->str_xml_ns) {
9112
68
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9113
68
                             "xml namespace prefix mapped to wrong URI\n",
9114
68
                             NULL, NULL, NULL);
9115
68
                }
9116
                /*
9117
                 * Do not keep a namespace definition node
9118
                 */
9119
102
                goto next_attr;
9120
102
            }
9121
2.10k
            if (uri == ctxt->str_xml_ns) {
9122
18
                if (attname != ctxt->str_xml) {
9123
18
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9124
18
                             "xml namespace URI mapped to wrong prefix\n",
9125
18
                             NULL, NULL, NULL);
9126
18
                }
9127
18
                goto next_attr;
9128
18
            }
9129
2.09k
            if (attname == ctxt->str_xmlns) {
9130
66
                xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9131
66
                         "redefinition of the xmlns prefix is forbidden\n",
9132
66
                         NULL, NULL, NULL);
9133
66
                goto next_attr;
9134
66
            }
9135
2.02k
            if ((len == 29) &&
9136
2.02k
                (xmlStrEqual(uri,
9137
70
                             BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
9138
35
                xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9139
35
                         "reuse of the xmlns namespace name is forbidden\n",
9140
35
                         NULL, NULL, NULL);
9141
35
                goto next_attr;
9142
35
            }
9143
1.99k
            if ((uri == NULL) || (uri[0] == 0)) {
9144
70
                xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9145
70
                         "xmlns:%s: Empty XML namespace is not allowed\n",
9146
70
                              attname, NULL, NULL);
9147
70
                goto next_attr;
9148
1.92k
            } else {
9149
1.92k
                if (xmlParseURISafe((const char *) uri, &parsedUri) < 0) {
9150
0
                    xmlErrMemory(ctxt);
9151
0
                    goto next_attr;
9152
0
                }
9153
1.92k
                if (parsedUri == NULL) {
9154
334
                    xmlNsErr(ctxt, XML_WAR_NS_URI,
9155
334
                         "xmlns:%s: '%s' is not a valid URI\n",
9156
334
                                       attname, uri, NULL);
9157
1.58k
                } else {
9158
1.58k
                    if ((ctxt->pedantic) && (parsedUri->scheme == NULL)) {
9159
68
                        xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
9160
68
                                  "xmlns:%s: URI %s is not absolute\n",
9161
68
                                  attname, uri, NULL);
9162
68
                    }
9163
1.58k
                    xmlFreeURI(parsedUri);
9164
1.58k
                }
9165
1.92k
            }
9166
9167
1.92k
            if (xmlParserNsPush(ctxt, &hattname, &huri, NULL, 0) > 0)
9168
1.80k
                nbNs++;
9169
13.1k
        } else {
9170
            /*
9171
             * Populate attributes array, see above for repurposing
9172
             * of xmlChar pointers.
9173
             */
9174
13.1k
            if ((atts == NULL) || (nbatts + 5 > maxatts)) {
9175
2.09k
                if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
9176
0
                    goto next_attr;
9177
0
                }
9178
2.09k
                maxatts = ctxt->maxatts;
9179
2.09k
                atts = ctxt->atts;
9180
2.09k
            }
9181
13.1k
            ctxt->attallocs[nratts++] = (hattname.hashValue & 0x7FFFFFFF) |
9182
13.1k
                                        ((unsigned) alloc << 31);
9183
13.1k
            atts[nbatts++] = attname;
9184
13.1k
            atts[nbatts++] = aprefix;
9185
13.1k
            atts[nbatts++] = (const xmlChar *) (size_t) haprefix.hashValue;
9186
13.1k
            if (alloc) {
9187
1.92k
                atts[nbatts++] = attvalue;
9188
1.92k
                attvalue += len;
9189
1.92k
                atts[nbatts++] = attvalue;
9190
11.1k
            } else {
9191
                /*
9192
                 * attvalue points into the input buffer which can be
9193
                 * reallocated. Store differences to input->base instead.
9194
                 * The pointers will be reconstructed later.
9195
                 */
9196
11.1k
                atts[nbatts++] = (void *) (attvalue - BASE_PTR);
9197
11.1k
                attvalue += len;
9198
11.1k
                atts[nbatts++] = (void *) (attvalue - BASE_PTR);
9199
11.1k
            }
9200
            /*
9201
             * tag if some deallocation is needed
9202
             */
9203
13.1k
            if (alloc != 0) attval = 1;
9204
13.1k
            attvalue = NULL; /* moved into atts */
9205
13.1k
        }
9206
9207
22.4k
next_attr:
9208
22.4k
        if ((attvalue != NULL) && (alloc != 0)) {
9209
267
            xmlFree(attvalue);
9210
267
            attvalue = NULL;
9211
267
        }
9212
9213
22.4k
  GROW
9214
22.4k
  if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
9215
3.58k
      break;
9216
18.8k
  if (SKIP_BLANKS == 0) {
9217
9.47k
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
9218
9.47k
         "attributes construct error\n");
9219
9.47k
      break;
9220
9.47k
  }
9221
9.40k
        GROW;
9222
9.40k
    }
9223
9224
    /*
9225
     * Namespaces from default attributes
9226
     */
9227
86.5k
    if (ctxt->attsDefault != NULL) {
9228
38.1k
        xmlDefAttrsPtr defaults;
9229
9230
38.1k
  defaults = xmlHashLookup2(ctxt->attsDefault, localname, prefix);
9231
38.1k
  if (defaults != NULL) {
9232
94.8k
      for (i = 0; i < defaults->nbAttrs; i++) {
9233
60.7k
                xmlDefAttr *attr = &defaults->attrs[i];
9234
9235
60.7k
          attname = attr->name.name;
9236
60.7k
    aprefix = attr->prefix.name;
9237
9238
60.7k
    if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
9239
17.8k
                    xmlParserEntityCheck(ctxt, attr->expandedSize);
9240
9241
17.8k
                    if (xmlParserNsPush(ctxt, NULL, &attr->value, NULL, 1) > 0)
9242
17.4k
                        nbNs++;
9243
42.8k
    } else if (aprefix == ctxt->str_xmlns) {
9244
29.8k
                    xmlParserEntityCheck(ctxt, attr->expandedSize);
9245
9246
29.8k
                    if (xmlParserNsPush(ctxt, &attr->name, &attr->value,
9247
29.8k
                                      NULL, 1) > 0)
9248
29.3k
                        nbNs++;
9249
29.8k
    } else {
9250
13.0k
                    nbTotalDef += 1;
9251
13.0k
                }
9252
60.7k
      }
9253
34.1k
  }
9254
38.1k
    }
9255
9256
    /*
9257
     * Resolve attribute namespaces
9258
     */
9259
99.6k
    for (i = 0; i < nbatts; i += 5) {
9260
13.1k
        attname = atts[i];
9261
13.1k
        aprefix = atts[i+1];
9262
9263
        /*
9264
  * The default namespace does not apply to attribute names.
9265
  */
9266
13.1k
  if (aprefix == NULL) {
9267
7.34k
            nsIndex = NS_INDEX_EMPTY;
9268
7.34k
        } else if (aprefix == ctxt->str_xml) {
9269
4.33k
            nsIndex = NS_INDEX_XML;
9270
4.33k
        } else {
9271
1.43k
            haprefix.name = aprefix;
9272
1.43k
            haprefix.hashValue = (size_t) atts[i+2];
9273
1.43k
            nsIndex = xmlParserNsLookup(ctxt, &haprefix, NULL);
9274
9275
1.43k
      if ((nsIndex == INT_MAX) || (nsIndex < ctxt->nsdb->minNsIndex)) {
9276
868
                xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
9277
868
        "Namespace prefix %s for %s on %s is not defined\n",
9278
868
        aprefix, attname, localname);
9279
868
                nsIndex = NS_INDEX_EMPTY;
9280
868
            }
9281
1.43k
        }
9282
9283
13.1k
        atts[i+2] = (const xmlChar *) (ptrdiff_t) nsIndex;
9284
13.1k
    }
9285
9286
    /*
9287
     * Maximum number of attributes including default attributes.
9288
     */
9289
86.5k
    maxAtts = nratts + nbTotalDef;
9290
9291
    /*
9292
     * Verify that attribute names are unique.
9293
     */
9294
86.5k
    if (maxAtts > 1) {
9295
4.67k
        attrHashSize = 4;
9296
7.13k
        while (attrHashSize / 2 < (unsigned) maxAtts)
9297
2.46k
            attrHashSize *= 2;
9298
9299
4.67k
        if (attrHashSize > ctxt->attrHashMax) {
9300
739
            xmlAttrHashBucket *tmp;
9301
9302
739
            tmp = xmlRealloc(ctxt->attrHash, attrHashSize * sizeof(tmp[0]));
9303
739
            if (tmp == NULL) {
9304
0
                xmlErrMemory(ctxt);
9305
0
                goto done;
9306
0
            }
9307
9308
739
            ctxt->attrHash = tmp;
9309
739
            ctxt->attrHashMax = attrHashSize;
9310
739
        }
9311
9312
4.67k
        memset(ctxt->attrHash, -1, attrHashSize * sizeof(ctxt->attrHash[0]));
9313
9314
12.9k
        for (i = 0, j = 0; j < nratts; i += 5, j++) {
9315
8.30k
            const xmlChar *nsuri;
9316
8.30k
            unsigned hashValue, nameHashValue, uriHashValue;
9317
8.30k
            int res;
9318
9319
8.30k
            attname = atts[i];
9320
8.30k
            aprefix = atts[i+1];
9321
8.30k
            nsIndex = (ptrdiff_t) atts[i+2];
9322
            /* Hash values always have bit 31 set, see dict.c */
9323
8.30k
            nameHashValue = ctxt->attallocs[j] | 0x80000000;
9324
9325
8.30k
            if (nsIndex == NS_INDEX_EMPTY) {
9326
                /*
9327
                 * Prefix with empty namespace means an undeclared
9328
                 * prefix which was already reported above.
9329
                 */
9330
5.81k
                if (aprefix != NULL)
9331
627
                    continue;
9332
5.19k
                nsuri = NULL;
9333
5.19k
                uriHashValue = URI_HASH_EMPTY;
9334
5.19k
            } else if (nsIndex == NS_INDEX_XML) {
9335
2.00k
                nsuri = ctxt->str_xml_ns;
9336
2.00k
                uriHashValue = URI_HASH_XML;
9337
2.00k
            } else {
9338
482
                nsuri = ctxt->nsTab[nsIndex * 2 + 1];
9339
482
                uriHashValue = ctxt->nsdb->extra[nsIndex].uriHashValue;
9340
482
            }
9341
9342
7.67k
            hashValue = xmlDictCombineHash(nameHashValue, uriHashValue);
9343
7.67k
            res = xmlAttrHashInsert(ctxt, attrHashSize, attname, nsuri,
9344
7.67k
                                    hashValue, i);
9345
7.67k
            if (res < 0)
9346
0
                continue;
9347
9348
            /*
9349
             * [ WFC: Unique Att Spec ]
9350
             * No attribute name may appear more than once in the same
9351
             * start-tag or empty-element tag.
9352
             * As extended by the Namespace in XML REC.
9353
             */
9354
7.67k
            if (res < INT_MAX) {
9355
4.37k
                if (aprefix == atts[res+1]) {
9356
4.30k
                    xmlErrAttributeDup(ctxt, aprefix, attname);
9357
4.30k
                } else {
9358
67
                    xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED,
9359
67
                             "Namespaced Attribute %s in '%s' redefined\n",
9360
67
                             attname, nsuri, NULL);
9361
67
                }
9362
4.37k
            }
9363
7.67k
        }
9364
4.67k
    }
9365
9366
    /*
9367
     * Default attributes
9368
     */
9369
86.5k
    if (ctxt->attsDefault != NULL) {
9370
38.1k
        xmlDefAttrsPtr defaults;
9371
9372
38.1k
  defaults = xmlHashLookup2(ctxt->attsDefault, localname, prefix);
9373
38.1k
  if (defaults != NULL) {
9374
94.8k
      for (i = 0; i < defaults->nbAttrs; i++) {
9375
60.7k
                xmlDefAttr *attr = &defaults->attrs[i];
9376
60.7k
                const xmlChar *nsuri;
9377
60.7k
                unsigned hashValue, uriHashValue;
9378
60.7k
                int res;
9379
9380
60.7k
          attname = attr->name.name;
9381
60.7k
    aprefix = attr->prefix.name;
9382
9383
60.7k
    if ((attname == ctxt->str_xmlns) && (aprefix == NULL))
9384
17.8k
                    continue;
9385
42.8k
    if (aprefix == ctxt->str_xmlns)
9386
29.8k
                    continue;
9387
9388
13.0k
                if (aprefix == NULL) {
9389
3.81k
                    nsIndex = NS_INDEX_EMPTY;
9390
3.81k
                    nsuri = NULL;
9391
3.81k
                    uriHashValue = URI_HASH_EMPTY;
9392
13.0k
                } if (aprefix == ctxt->str_xml) {
9393
399
                    nsIndex = NS_INDEX_XML;
9394
399
                    nsuri = ctxt->str_xml_ns;
9395
399
                    uriHashValue = URI_HASH_XML;
9396
12.6k
                } else if (aprefix != NULL) {
9397
8.84k
                    nsIndex = xmlParserNsLookup(ctxt, &attr->prefix, NULL);
9398
8.84k
                    if ((nsIndex == INT_MAX) ||
9399
8.84k
                        (nsIndex < ctxt->nsdb->minNsIndex)) {
9400
7.05k
                        xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
9401
7.05k
                                 "Namespace prefix %s for %s on %s is not "
9402
7.05k
                                 "defined\n",
9403
7.05k
                                 aprefix, attname, localname);
9404
7.05k
                        nsIndex = NS_INDEX_EMPTY;
9405
7.05k
                        nsuri = NULL;
9406
7.05k
                        uriHashValue = URI_HASH_EMPTY;
9407
7.05k
                    } else {
9408
1.79k
                        nsuri = ctxt->nsTab[nsIndex * 2 + 1];
9409
1.79k
                        uriHashValue = ctxt->nsdb->extra[nsIndex].uriHashValue;
9410
1.79k
                    }
9411
8.84k
                }
9412
9413
                /*
9414
                 * Check whether the attribute exists
9415
                 */
9416
13.0k
                if (maxAtts > 1) {
9417
9.32k
                    hashValue = xmlDictCombineHash(attr->name.hashValue,
9418
9.32k
                                                   uriHashValue);
9419
9.32k
                    res = xmlAttrHashInsert(ctxt, attrHashSize, attname, nsuri,
9420
9.32k
                                            hashValue, nbatts);
9421
9.32k
                    if (res < 0)
9422
0
                        continue;
9423
9.32k
                    if (res < INT_MAX) {
9424
1.40k
                        if (aprefix == atts[res+1])
9425
115
                            continue;
9426
1.29k
                        xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED,
9427
1.29k
                                 "Namespaced Attribute %s in '%s' redefined\n",
9428
1.29k
                                 attname, nsuri, NULL);
9429
1.29k
                    }
9430
9.32k
                }
9431
9432
12.9k
                xmlParserEntityCheck(ctxt, attr->expandedSize);
9433
9434
12.9k
                if ((atts == NULL) || (nbatts + 5 > maxatts)) {
9435
340
                    if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
9436
0
                        localname = NULL;
9437
0
                        goto done;
9438
0
                    }
9439
340
                    maxatts = ctxt->maxatts;
9440
340
                    atts = ctxt->atts;
9441
340
                }
9442
9443
12.9k
                atts[nbatts++] = attname;
9444
12.9k
                atts[nbatts++] = aprefix;
9445
12.9k
                atts[nbatts++] = (const xmlChar *) (ptrdiff_t) nsIndex;
9446
12.9k
                atts[nbatts++] = attr->value.name;
9447
12.9k
                atts[nbatts++] = attr->valueEnd;
9448
12.9k
                if ((ctxt->standalone == 1) && (attr->external != 0)) {
9449
0
                    xmlValidityError(ctxt, XML_DTD_STANDALONE_DEFAULTED,
9450
0
                            "standalone: attribute %s on %s defaulted "
9451
0
                            "from external subset\n",
9452
0
                            attname, localname);
9453
0
                }
9454
12.9k
                nbdef++;
9455
12.9k
      }
9456
34.1k
  }
9457
38.1k
    }
9458
9459
    /*
9460
     * Reconstruct attribute pointers
9461
     */
9462
112k
    for (i = 0, j = 0; i < nbatts; i += 5, j++) {
9463
        /* namespace URI */
9464
26.0k
        nsIndex = (ptrdiff_t) atts[i+2];
9465
26.0k
        if (nsIndex == INT_MAX)
9466
18.9k
            atts[i+2] = NULL;
9467
7.09k
        else if (nsIndex == INT_MAX - 1)
9468
4.73k
            atts[i+2] = ctxt->str_xml_ns;
9469
2.36k
        else
9470
2.36k
            atts[i+2] = ctxt->nsTab[nsIndex * 2 + 1];
9471
9472
26.0k
        if ((j < nratts) && (ctxt->attallocs[j] & 0x80000000) == 0) {
9473
11.1k
            atts[i+3] = BASE_PTR + (ptrdiff_t) atts[i+3];  /* value */
9474
11.1k
            atts[i+4] = BASE_PTR + (ptrdiff_t) atts[i+4];  /* valuend */
9475
11.1k
        }
9476
26.0k
    }
9477
9478
86.5k
    uri = xmlParserNsLookupUri(ctxt, &hprefix);
9479
86.5k
    if ((prefix != NULL) && (uri == NULL)) {
9480
4.09k
  xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
9481
4.09k
           "Namespace prefix %s on %s is not defined\n",
9482
4.09k
     prefix, localname, NULL);
9483
4.09k
    }
9484
86.5k
    *pref = prefix;
9485
86.5k
    *URI = uri;
9486
9487
    /*
9488
     * SAX callback
9489
     */
9490
86.5k
    if ((ctxt->sax != NULL) && (ctxt->sax->startElementNs != NULL) &&
9491
86.5k
  (!ctxt->disableSAX)) {
9492
43.7k
  if (nbNs > 0)
9493
18.2k
      ctxt->sax->startElementNs(ctxt->userData, localname, prefix, uri,
9494
18.2k
                          nbNs, ctxt->nsTab + 2 * (ctxt->nsNr - nbNs),
9495
18.2k
        nbatts / 5, nbdef, atts);
9496
25.5k
  else
9497
25.5k
      ctxt->sax->startElementNs(ctxt->userData, localname, prefix, uri,
9498
25.5k
                          0, NULL, nbatts / 5, nbdef, atts);
9499
43.7k
    }
9500
9501
86.5k
done:
9502
    /*
9503
     * Free allocated attribute values
9504
     */
9505
86.5k
    if (attval != 0) {
9506
4.37k
  for (i = 0, j = 0; j < nratts; i += 5, j++)
9507
2.54k
      if (ctxt->attallocs[j] & 0x80000000)
9508
1.92k
          xmlFree((xmlChar *) atts[i+3]);
9509
1.82k
    }
9510
9511
86.5k
    *nbNsPtr = nbNs;
9512
86.5k
    return(localname);
9513
86.5k
}
9514
9515
/**
9516
 * xmlParseEndTag2:
9517
 * @ctxt:  an XML parser context
9518
 * @line:  line of the start tag
9519
 * @nsNr:  number of namespaces on the start tag
9520
 *
9521
 * Parse an end tag. Always consumes '</'.
9522
 *
9523
 * [42] ETag ::= '</' Name S? '>'
9524
 *
9525
 * With namespace
9526
 *
9527
 * [NS 9] ETag ::= '</' QName S? '>'
9528
 */
9529
9530
static void
9531
10.5k
xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlStartTag *tag) {
9532
10.5k
    const xmlChar *name;
9533
9534
10.5k
    GROW;
9535
10.5k
    if ((RAW != '<') || (NXT(1) != '/')) {
9536
40
  xmlFatalErr(ctxt, XML_ERR_LTSLASH_REQUIRED, NULL);
9537
40
  return;
9538
40
    }
9539
10.4k
    SKIP(2);
9540
9541
10.4k
    if (tag->prefix == NULL)
9542
8.75k
        name = xmlParseNameAndCompare(ctxt, ctxt->name);
9543
1.73k
    else
9544
1.73k
        name = xmlParseQNameAndCompare(ctxt, ctxt->name, tag->prefix);
9545
9546
    /*
9547
     * We should definitely be at the ending "S? '>'" part
9548
     */
9549
10.4k
    GROW;
9550
10.4k
    SKIP_BLANKS;
9551
10.4k
    if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
9552
4.21k
  xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
9553
4.21k
    } else
9554
6.28k
  NEXT1;
9555
9556
    /*
9557
     * [ WFC: Element Type Match ]
9558
     * The Name in an element's end-tag must match the element type in the
9559
     * start-tag.
9560
     *
9561
     */
9562
10.4k
    if (name != (xmlChar*)1) {
9563
8.41k
        if (name == NULL) name = BAD_CAST "unparsable";
9564
8.41k
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
9565
8.41k
         "Opening and ending tag mismatch: %s line %d and %s\n",
9566
8.41k
                    ctxt->name, tag->line, name);
9567
8.41k
    }
9568
9569
    /*
9570
     * SAX: End of Tag
9571
     */
9572
10.4k
    if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
9573
10.4k
  (!ctxt->disableSAX))
9574
2.64k
  ctxt->sax->endElementNs(ctxt->userData, ctxt->name, tag->prefix,
9575
2.64k
                                tag->URI);
9576
9577
10.4k
    spacePop(ctxt);
9578
10.4k
    if (tag->nsNr != 0)
9579
1.47k
  xmlParserNsPop(ctxt, tag->nsNr);
9580
10.4k
}
9581
9582
/**
9583
 * xmlParseCDSect:
9584
 * @ctxt:  an XML parser context
9585
 *
9586
 * DEPRECATED: Internal function, don't use.
9587
 *
9588
 * Parse escaped pure raw content. Always consumes '<!['.
9589
 *
9590
 * [18] CDSect ::= CDStart CData CDEnd
9591
 *
9592
 * [19] CDStart ::= '<![CDATA['
9593
 *
9594
 * [20] Data ::= (Char* - (Char* ']]>' Char*))
9595
 *
9596
 * [21] CDEnd ::= ']]>'
9597
 */
9598
void
9599
2.30k
xmlParseCDSect(xmlParserCtxtPtr ctxt) {
9600
2.30k
    xmlChar *buf = NULL;
9601
2.30k
    int len = 0;
9602
2.30k
    int size = XML_PARSER_BUFFER_SIZE;
9603
2.30k
    int r, rl;
9604
2.30k
    int s, sl;
9605
2.30k
    int cur, l;
9606
2.30k
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
9607
0
                    XML_MAX_HUGE_LENGTH :
9608
2.30k
                    XML_MAX_TEXT_LENGTH;
9609
9610
2.30k
    if ((CUR != '<') || (NXT(1) != '!') || (NXT(2) != '['))
9611
0
        return;
9612
2.30k
    SKIP(3);
9613
9614
2.30k
    if (!CMP6(CUR_PTR, 'C', 'D', 'A', 'T', 'A', '['))
9615
0
        return;
9616
2.30k
    SKIP(6);
9617
9618
2.30k
    r = CUR_CHAR(rl);
9619
2.30k
    if (!IS_CHAR(r)) {
9620
151
  xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
9621
151
        goto out;
9622
151
    }
9623
2.15k
    NEXTL(rl);
9624
2.15k
    s = CUR_CHAR(sl);
9625
2.15k
    if (!IS_CHAR(s)) {
9626
218
  xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
9627
218
        goto out;
9628
218
    }
9629
1.93k
    NEXTL(sl);
9630
1.93k
    cur = CUR_CHAR(l);
9631
1.93k
    buf = (xmlChar *) xmlMallocAtomic(size);
9632
1.93k
    if (buf == NULL) {
9633
0
  xmlErrMemory(ctxt);
9634
0
        goto out;
9635
0
    }
9636
16.6k
    while (IS_CHAR(cur) &&
9637
16.6k
           ((r != ']') || (s != ']') || (cur != '>'))) {
9638
14.6k
  if (len + 5 >= size) {
9639
76
      xmlChar *tmp;
9640
9641
76
      tmp = (xmlChar *) xmlRealloc(buf, size * 2);
9642
76
      if (tmp == NULL) {
9643
0
    xmlErrMemory(ctxt);
9644
0
                goto out;
9645
0
      }
9646
76
      buf = tmp;
9647
76
      size *= 2;
9648
76
  }
9649
14.6k
  COPY_BUF(buf, len, r);
9650
14.6k
        if (len > maxLength) {
9651
0
            xmlFatalErrMsg(ctxt, XML_ERR_CDATA_NOT_FINISHED,
9652
0
                           "CData section too big found\n");
9653
0
            goto out;
9654
0
        }
9655
14.6k
  r = s;
9656
14.6k
  rl = sl;
9657
14.6k
  s = cur;
9658
14.6k
  sl = l;
9659
14.6k
  NEXTL(l);
9660
14.6k
  cur = CUR_CHAR(l);
9661
14.6k
    }
9662
1.93k
    buf[len] = 0;
9663
1.93k
    if (cur != '>') {
9664
520
  xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED,
9665
520
                       "CData section not finished\n%.50s\n", buf);
9666
520
        goto out;
9667
520
    }
9668
1.41k
    NEXTL(l);
9669
9670
    /*
9671
     * OK the buffer is to be consumed as cdata.
9672
     */
9673
1.41k
    if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
9674
1.01k
  if (ctxt->sax->cdataBlock != NULL)
9675
706
      ctxt->sax->cdataBlock(ctxt->userData, buf, len);
9676
310
  else if (ctxt->sax->characters != NULL)
9677
310
      ctxt->sax->characters(ctxt->userData, buf, len);
9678
1.01k
    }
9679
9680
2.30k
out:
9681
2.30k
    xmlFree(buf);
9682
2.30k
}
9683
9684
/**
9685
 * xmlParseContentInternal:
9686
 * @ctxt:  an XML parser context
9687
 *
9688
 * Parse a content sequence. Stops at EOF or '</'. Leaves checking of
9689
 * unexpected EOF to the caller.
9690
 */
9691
9692
static void
9693
9.92k
xmlParseContentInternal(xmlParserCtxtPtr ctxt) {
9694
9.92k
    int oldNameNr = ctxt->nameNr;
9695
9.92k
    int oldSpaceNr = ctxt->spaceNr;
9696
9.92k
    int oldNodeNr = ctxt->nodeNr;
9697
9698
9.92k
    GROW;
9699
239k
    while ((ctxt->input->cur < ctxt->input->end) &&
9700
239k
     (PARSER_STOPPED(ctxt) == 0)) {
9701
234k
  const xmlChar *cur = ctxt->input->cur;
9702
9703
  /*
9704
   * First case : a Processing Instruction.
9705
   */
9706
234k
  if ((*cur == '<') && (cur[1] == '?')) {
9707
1.17k
      xmlParsePI(ctxt);
9708
1.17k
  }
9709
9710
  /*
9711
   * Second case : a CDSection
9712
   */
9713
  /* 2.6.0 test was *cur not RAW */
9714
233k
  else if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
9715
2.30k
      xmlParseCDSect(ctxt);
9716
2.30k
  }
9717
9718
  /*
9719
   * Third case :  a comment
9720
   */
9721
231k
  else if ((*cur == '<') && (NXT(1) == '!') &&
9722
231k
     (NXT(2) == '-') && (NXT(3) == '-')) {
9723
894
      xmlParseComment(ctxt);
9724
894
  }
9725
9726
  /*
9727
   * Fourth case :  a sub-element.
9728
   */
9729
230k
  else if (*cur == '<') {
9730
161k
            if (NXT(1) == '/') {
9731
15.7k
                if (ctxt->nameNr <= oldNameNr)
9732
4.42k
                    break;
9733
11.3k
          xmlParseElementEnd(ctxt);
9734
145k
            } else {
9735
145k
          xmlParseElementStart(ctxt);
9736
145k
            }
9737
161k
  }
9738
9739
  /*
9740
   * Fifth case : a reference. If if has not been resolved,
9741
   *    parsing returns it's Name, create the node
9742
   */
9743
9744
68.6k
  else if (*cur == '&') {
9745
19.5k
      xmlParseReference(ctxt);
9746
19.5k
  }
9747
9748
  /*
9749
   * Last case, text. Note that References are handled directly.
9750
   */
9751
49.1k
  else {
9752
49.1k
      xmlParseCharDataInternal(ctxt, 0);
9753
49.1k
  }
9754
9755
230k
  SHRINK;
9756
230k
  GROW;
9757
230k
    }
9758
9759
9.92k
    if ((ctxt->nameNr > oldNameNr) &&
9760
9.92k
        (ctxt->input->cur >= ctxt->input->end) &&
9761
9.92k
        (ctxt->wellFormed)) {
9762
29
        const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
9763
29
        int line = ctxt->pushTab[ctxt->nameNr - 1].line;
9764
29
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
9765
29
                "Premature end of data in tag %s line %d\n",
9766
29
                name, line, NULL);
9767
29
    }
9768
9769
    /*
9770
     * Clean up in error case
9771
     */
9772
9773
20.2k
    while (ctxt->nodeNr > oldNodeNr)
9774
10.3k
        nodePop(ctxt);
9775
9776
28.1k
    while (ctxt->nameNr > oldNameNr) {
9777
18.2k
        xmlStartTag *tag = &ctxt->pushTab[ctxt->nameNr - 1];
9778
9779
18.2k
        if (tag->nsNr != 0)
9780
6.01k
            xmlParserNsPop(ctxt, tag->nsNr);
9781
9782
18.2k
        namePop(ctxt);
9783
18.2k
    }
9784
9785
28.1k
    while (ctxt->spaceNr > oldSpaceNr)
9786
18.2k
        spacePop(ctxt);
9787
9.92k
}
9788
9789
/**
9790
 * xmlParseContent:
9791
 * @ctxt:  an XML parser context
9792
 *
9793
 * Parse XML element content. This is useful if you're only interested
9794
 * in custom SAX callbacks. If you want a node list, use
9795
 * xmlParseInNodeContext.
9796
 */
9797
void
9798
0
xmlParseContent(xmlParserCtxtPtr ctxt) {
9799
0
    if ((ctxt == NULL) || (ctxt->input == NULL))
9800
0
        return;
9801
9802
0
    xmlCtxtInitializeLate(ctxt);
9803
9804
0
    xmlParseContentInternal(ctxt);
9805
9806
0
    if (ctxt->input->cur < ctxt->input->end)
9807
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
9808
0
}
9809
9810
/**
9811
 * xmlParseElement:
9812
 * @ctxt:  an XML parser context
9813
 *
9814
 * DEPRECATED: Internal function, don't use.
9815
 *
9816
 * parse an XML element
9817
 *
9818
 * [39] element ::= EmptyElemTag | STag content ETag
9819
 *
9820
 * [ WFC: Element Type Match ]
9821
 * The Name in an element's end-tag must match the element type in the
9822
 * start-tag.
9823
 *
9824
 */
9825
9826
void
9827
17.1k
xmlParseElement(xmlParserCtxtPtr ctxt) {
9828
17.1k
    if (xmlParseElementStart(ctxt) != 0)
9829
7.99k
        return;
9830
9831
9.20k
    xmlParseContentInternal(ctxt);
9832
9833
9.20k
    if (ctxt->input->cur >= ctxt->input->end) {
9834
4.75k
        if (ctxt->wellFormed) {
9835
21
            const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
9836
21
            int line = ctxt->pushTab[ctxt->nameNr - 1].line;
9837
21
            xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
9838
21
                    "Premature end of data in tag %s line %d\n",
9839
21
                    name, line, NULL);
9840
21
        }
9841
4.75k
        return;
9842
4.75k
    }
9843
9844
4.44k
    xmlParseElementEnd(ctxt);
9845
4.44k
}
9846
9847
/**
9848
 * xmlParseElementStart:
9849
 * @ctxt:  an XML parser context
9850
 *
9851
 * Parse the start of an XML element. Returns -1 in case of error, 0 if an
9852
 * opening tag was parsed, 1 if an empty element was parsed.
9853
 *
9854
 * Always consumes '<'.
9855
 */
9856
static int
9857
162k
xmlParseElementStart(xmlParserCtxtPtr ctxt) {
9858
162k
    int maxDepth = (ctxt->options & XML_PARSE_HUGE) ? 2048 : 256;
9859
162k
    const xmlChar *name;
9860
162k
    const xmlChar *prefix = NULL;
9861
162k
    const xmlChar *URI = NULL;
9862
162k
    xmlParserNodeInfo node_info;
9863
162k
    int line;
9864
162k
    xmlNodePtr cur;
9865
162k
    int nbNs = 0;
9866
9867
162k
    if (ctxt->nameNr > maxDepth) {
9868
4
        xmlFatalErrMsgInt(ctxt, XML_ERR_RESOURCE_LIMIT,
9869
4
                "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
9870
4
                ctxt->nameNr);
9871
4
  xmlHaltParser(ctxt);
9872
4
  return(-1);
9873
4
    }
9874
9875
    /* Capture start position */
9876
162k
    if (ctxt->record_info) {
9877
0
        node_info.begin_pos = ctxt->input->consumed +
9878
0
                          (CUR_PTR - ctxt->input->base);
9879
0
  node_info.begin_line = ctxt->input->line;
9880
0
    }
9881
9882
162k
    if (ctxt->spaceNr == 0)
9883
0
  spacePush(ctxt, -1);
9884
162k
    else if (*ctxt->space == -2)
9885
5.04k
  spacePush(ctxt, -1);
9886
157k
    else
9887
157k
  spacePush(ctxt, *ctxt->space);
9888
9889
162k
    line = ctxt->input->line;
9890
162k
#ifdef LIBXML_SAX1_ENABLED
9891
162k
    if (ctxt->sax2)
9892
103k
#endif /* LIBXML_SAX1_ENABLED */
9893
103k
        name = xmlParseStartTag2(ctxt, &prefix, &URI, &nbNs);
9894
59.5k
#ifdef LIBXML_SAX1_ENABLED
9895
59.5k
    else
9896
59.5k
  name = xmlParseStartTag(ctxt);
9897
162k
#endif /* LIBXML_SAX1_ENABLED */
9898
162k
    if (name == NULL) {
9899
23.4k
  spacePop(ctxt);
9900
23.4k
        return(-1);
9901
23.4k
    }
9902
139k
    nameNsPush(ctxt, name, prefix, URI, line, nbNs);
9903
139k
    cur = ctxt->node;
9904
9905
139k
#ifdef LIBXML_VALID_ENABLED
9906
    /*
9907
     * [ VC: Root Element Type ]
9908
     * The Name in the document type declaration must match the element
9909
     * type of the root element.
9910
     */
9911
139k
    if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
9912
139k
        ctxt->node && (ctxt->node == ctxt->myDoc->children))
9913
0
        ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
9914
139k
#endif /* LIBXML_VALID_ENABLED */
9915
9916
    /*
9917
     * Check for an Empty Element.
9918
     */
9919
139k
    if ((RAW == '/') && (NXT(1) == '>')) {
9920
2.41k
        SKIP(2);
9921
2.41k
  if (ctxt->sax2) {
9922
1.72k
      if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
9923
1.72k
    (!ctxt->disableSAX))
9924
362
    ctxt->sax->endElementNs(ctxt->userData, name, prefix, URI);
9925
1.72k
#ifdef LIBXML_SAX1_ENABLED
9926
1.72k
  } else {
9927
688
      if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
9928
688
    (!ctxt->disableSAX))
9929
364
    ctxt->sax->endElement(ctxt->userData, name);
9930
688
#endif /* LIBXML_SAX1_ENABLED */
9931
688
  }
9932
2.41k
  namePop(ctxt);
9933
2.41k
  spacePop(ctxt);
9934
2.41k
  if (nbNs > 0)
9935
599
      xmlParserNsPop(ctxt, nbNs);
9936
2.41k
  if (cur != NULL && ctxt->record_info) {
9937
0
            node_info.node = cur;
9938
0
            node_info.end_pos = ctxt->input->consumed +
9939
0
                                (CUR_PTR - ctxt->input->base);
9940
0
            node_info.end_line = ctxt->input->line;
9941
0
            xmlParserAddNodeInfo(ctxt, &node_info);
9942
0
  }
9943
2.41k
  return(1);
9944
2.41k
    }
9945
136k
    if (RAW == '>') {
9946
38.8k
        NEXT1;
9947
38.8k
        if (cur != NULL && ctxt->record_info) {
9948
0
            node_info.node = cur;
9949
0
            node_info.end_pos = 0;
9950
0
            node_info.end_line = 0;
9951
0
            xmlParserAddNodeInfo(ctxt, &node_info);
9952
0
        }
9953
98.1k
    } else {
9954
98.1k
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_GT_REQUIRED,
9955
98.1k
         "Couldn't find end of Start Tag %s line %d\n",
9956
98.1k
                    name, line, NULL);
9957
9958
  /*
9959
   * end of parsing of this node.
9960
   */
9961
98.1k
  nodePop(ctxt);
9962
98.1k
  namePop(ctxt);
9963
98.1k
  spacePop(ctxt);
9964
98.1k
  if (nbNs > 0)
9965
24.5k
      xmlParserNsPop(ctxt, nbNs);
9966
98.1k
  return(-1);
9967
98.1k
    }
9968
9969
38.8k
    return(0);
9970
136k
}
9971
9972
/**
9973
 * xmlParseElementEnd:
9974
 * @ctxt:  an XML parser context
9975
 *
9976
 * Parse the end of an XML element. Always consumes '</'.
9977
 */
9978
static void
9979
15.8k
xmlParseElementEnd(xmlParserCtxtPtr ctxt) {
9980
15.8k
    xmlNodePtr cur = ctxt->node;
9981
9982
15.8k
    if (ctxt->nameNr <= 0) {
9983
0
        if ((RAW == '<') && (NXT(1) == '/'))
9984
0
            SKIP(2);
9985
0
        return;
9986
0
    }
9987
9988
    /*
9989
     * parse the end of tag: '</' should be here.
9990
     */
9991
15.8k
    if (ctxt->sax2) {
9992
10.5k
  xmlParseEndTag2(ctxt, &ctxt->pushTab[ctxt->nameNr - 1]);
9993
10.5k
  namePop(ctxt);
9994
10.5k
    }
9995
5.28k
#ifdef LIBXML_SAX1_ENABLED
9996
5.28k
    else
9997
5.28k
  xmlParseEndTag1(ctxt, 0);
9998
15.8k
#endif /* LIBXML_SAX1_ENABLED */
9999
10000
    /*
10001
     * Capture end position
10002
     */
10003
15.8k
    if (cur != NULL && ctxt->record_info) {
10004
0
        xmlParserNodeInfoPtr node_info;
10005
10006
0
        node_info = (xmlParserNodeInfoPtr) xmlParserFindNodeInfo(ctxt, cur);
10007
0
        if (node_info != NULL) {
10008
0
            node_info->end_pos = ctxt->input->consumed +
10009
0
                                 (CUR_PTR - ctxt->input->base);
10010
0
            node_info->end_line = ctxt->input->line;
10011
0
        }
10012
0
    }
10013
15.8k
}
10014
10015
/**
10016
 * xmlParseVersionNum:
10017
 * @ctxt:  an XML parser context
10018
 *
10019
 * DEPRECATED: Internal function, don't use.
10020
 *
10021
 * parse the XML version value.
10022
 *
10023
 * [26] VersionNum ::= '1.' [0-9]+
10024
 *
10025
 * In practice allow [0-9].[0-9]+ at that level
10026
 *
10027
 * Returns the string giving the XML version number, or NULL
10028
 */
10029
xmlChar *
10030
7.79k
xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
10031
7.79k
    xmlChar *buf = NULL;
10032
7.79k
    int len = 0;
10033
7.79k
    int size = 10;
10034
7.79k
    xmlChar cur;
10035
10036
7.79k
    buf = (xmlChar *) xmlMallocAtomic(size);
10037
7.79k
    if (buf == NULL) {
10038
0
  xmlErrMemory(ctxt);
10039
0
  return(NULL);
10040
0
    }
10041
7.79k
    cur = CUR;
10042
7.79k
    if (!((cur >= '0') && (cur <= '9'))) {
10043
7.65k
  xmlFree(buf);
10044
7.65k
  return(NULL);
10045
7.65k
    }
10046
140
    buf[len++] = cur;
10047
140
    NEXT;
10048
140
    cur=CUR;
10049
140
    if (cur != '.') {
10050
64
  xmlFree(buf);
10051
64
  return(NULL);
10052
64
    }
10053
76
    buf[len++] = cur;
10054
76
    NEXT;
10055
76
    cur=CUR;
10056
6.45k
    while ((cur >= '0') && (cur <= '9')) {
10057
6.38k
  if (len + 1 >= size) {
10058
143
      xmlChar *tmp;
10059
10060
143
      size *= 2;
10061
143
      tmp = (xmlChar *) xmlRealloc(buf, size);
10062
143
      if (tmp == NULL) {
10063
0
          xmlFree(buf);
10064
0
    xmlErrMemory(ctxt);
10065
0
    return(NULL);
10066
0
      }
10067
143
      buf = tmp;
10068
143
  }
10069
6.38k
  buf[len++] = cur;
10070
6.38k
  NEXT;
10071
6.38k
  cur=CUR;
10072
6.38k
    }
10073
76
    buf[len] = 0;
10074
76
    return(buf);
10075
76
}
10076
10077
/**
10078
 * xmlParseVersionInfo:
10079
 * @ctxt:  an XML parser context
10080
 *
10081
 * DEPRECATED: Internal function, don't use.
10082
 *
10083
 * parse the XML version.
10084
 *
10085
 * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
10086
 *
10087
 * [25] Eq ::= S? '=' S?
10088
 *
10089
 * Returns the version string, e.g. "1.0"
10090
 */
10091
10092
xmlChar *
10093
12.7k
xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
10094
12.7k
    xmlChar *version = NULL;
10095
10096
12.7k
    if (CMP7(CUR_PTR, 'v', 'e', 'r', 's', 'i', 'o', 'n')) {
10097
7.80k
  SKIP(7);
10098
7.80k
  SKIP_BLANKS;
10099
7.80k
  if (RAW != '=') {
10100
3
      xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10101
3
      return(NULL);
10102
3
        }
10103
7.79k
  NEXT;
10104
7.79k
  SKIP_BLANKS;
10105
7.79k
  if (RAW == '"') {
10106
7.79k
      NEXT;
10107
7.79k
      version = xmlParseVersionNum(ctxt);
10108
7.79k
      if (RAW != '"') {
10109
7.65k
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10110
7.65k
      } else
10111
146
          NEXT;
10112
7.79k
  } else if (RAW == '\''){
10113
2
      NEXT;
10114
2
      version = xmlParseVersionNum(ctxt);
10115
2
      if (RAW != '\'') {
10116
1
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10117
1
      } else
10118
1
          NEXT;
10119
2
  } else {
10120
1
      xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10121
1
  }
10122
7.79k
    }
10123
12.7k
    return(version);
10124
12.7k
}
10125
10126
/**
10127
 * xmlParseEncName:
10128
 * @ctxt:  an XML parser context
10129
 *
10130
 * DEPRECATED: Internal function, don't use.
10131
 *
10132
 * parse the XML encoding name
10133
 *
10134
 * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
10135
 *
10136
 * Returns the encoding name value or NULL
10137
 */
10138
xmlChar *
10139
4.95k
xmlParseEncName(xmlParserCtxtPtr ctxt) {
10140
4.95k
    xmlChar *buf = NULL;
10141
4.95k
    int len = 0;
10142
4.95k
    int size = 10;
10143
4.95k
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
10144
0
                    XML_MAX_TEXT_LENGTH :
10145
4.95k
                    XML_MAX_NAME_LENGTH;
10146
4.95k
    xmlChar cur;
10147
10148
4.95k
    cur = CUR;
10149
4.95k
    if (((cur >= 'a') && (cur <= 'z')) ||
10150
4.95k
        ((cur >= 'A') && (cur <= 'Z'))) {
10151
3.34k
  buf = (xmlChar *) xmlMallocAtomic(size);
10152
3.34k
  if (buf == NULL) {
10153
0
      xmlErrMemory(ctxt);
10154
0
      return(NULL);
10155
0
  }
10156
10157
3.34k
  buf[len++] = cur;
10158
3.34k
  NEXT;
10159
3.34k
  cur = CUR;
10160
20.7k
  while (((cur >= 'a') && (cur <= 'z')) ||
10161
20.7k
         ((cur >= 'A') && (cur <= 'Z')) ||
10162
20.7k
         ((cur >= '0') && (cur <= '9')) ||
10163
20.7k
         (cur == '.') || (cur == '_') ||
10164
20.7k
         (cur == '-')) {
10165
17.3k
      if (len + 1 >= size) {
10166
361
          xmlChar *tmp;
10167
10168
361
    size *= 2;
10169
361
    tmp = (xmlChar *) xmlRealloc(buf, size);
10170
361
    if (tmp == NULL) {
10171
0
        xmlErrMemory(ctxt);
10172
0
        xmlFree(buf);
10173
0
        return(NULL);
10174
0
    }
10175
361
    buf = tmp;
10176
361
      }
10177
17.3k
      buf[len++] = cur;
10178
17.3k
            if (len > maxLength) {
10179
0
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "EncName");
10180
0
                xmlFree(buf);
10181
0
                return(NULL);
10182
0
            }
10183
17.3k
      NEXT;
10184
17.3k
      cur = CUR;
10185
17.3k
        }
10186
3.34k
  buf[len] = 0;
10187
3.34k
    } else {
10188
1.60k
  xmlFatalErr(ctxt, XML_ERR_ENCODING_NAME, NULL);
10189
1.60k
    }
10190
4.95k
    return(buf);
10191
4.95k
}
10192
10193
/**
10194
 * xmlParseEncodingDecl:
10195
 * @ctxt:  an XML parser context
10196
 *
10197
 * DEPRECATED: Internal function, don't use.
10198
 *
10199
 * parse the XML encoding declaration
10200
 *
10201
 * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' |  "'" EncName "'")
10202
 *
10203
 * this setups the conversion filters.
10204
 *
10205
 * Returns the encoding value or NULL
10206
 */
10207
10208
const xmlChar *
10209
12.5k
xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
10210
12.5k
    xmlChar *encoding = NULL;
10211
10212
12.5k
    SKIP_BLANKS;
10213
12.5k
    if (CMP8(CUR_PTR, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g') == 0)
10214
7.55k
        return(NULL);
10215
10216
5.00k
    SKIP(8);
10217
5.00k
    SKIP_BLANKS;
10218
5.00k
    if (RAW != '=') {
10219
37
        xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10220
37
        return(NULL);
10221
37
    }
10222
4.96k
    NEXT;
10223
4.96k
    SKIP_BLANKS;
10224
4.96k
    if (RAW == '"') {
10225
16
        NEXT;
10226
16
        encoding = xmlParseEncName(ctxt);
10227
16
        if (RAW != '"') {
10228
15
            xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10229
15
            xmlFree((xmlChar *) encoding);
10230
15
            return(NULL);
10231
15
        } else
10232
1
            NEXT;
10233
4.95k
    } else if (RAW == '\''){
10234
4.93k
        NEXT;
10235
4.93k
        encoding = xmlParseEncName(ctxt);
10236
4.93k
        if (RAW != '\'') {
10237
1.67k
            xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10238
1.67k
            xmlFree((xmlChar *) encoding);
10239
1.67k
            return(NULL);
10240
1.67k
        } else
10241
3.25k
            NEXT;
10242
4.93k
    } else {
10243
19
        xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10244
19
    }
10245
10246
3.27k
    if (encoding == NULL)
10247
23
        return(NULL);
10248
10249
3.25k
    xmlSetDeclaredEncoding(ctxt, encoding);
10250
10251
3.25k
    return(ctxt->encoding);
10252
3.27k
}
10253
10254
/**
10255
 * xmlParseSDDecl:
10256
 * @ctxt:  an XML parser context
10257
 *
10258
 * DEPRECATED: Internal function, don't use.
10259
 *
10260
 * parse the XML standalone declaration
10261
 *
10262
 * [32] SDDecl ::= S 'standalone' Eq
10263
 *                 (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no')'"'))
10264
 *
10265
 * [ VC: Standalone Document Declaration ]
10266
 * TODO The standalone document declaration must have the value "no"
10267
 * if any external markup declarations contain declarations of:
10268
 *  - attributes with default values, if elements to which these
10269
 *    attributes apply appear in the document without specifications
10270
 *    of values for these attributes, or
10271
 *  - entities (other than amp, lt, gt, apos, quot), if references
10272
 *    to those entities appear in the document, or
10273
 *  - attributes with values subject to normalization, where the
10274
 *    attribute appears in the document with a value which will change
10275
 *    as a result of normalization, or
10276
 *  - element types with element content, if white space occurs directly
10277
 *    within any instance of those types.
10278
 *
10279
 * Returns:
10280
 *   1 if standalone="yes"
10281
 *   0 if standalone="no"
10282
 *  -2 if standalone attribute is missing or invalid
10283
 *    (A standalone value of -2 means that the XML declaration was found,
10284
 *     but no value was specified for the standalone attribute).
10285
 */
10286
10287
int
10288
10.3k
xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
10289
10.3k
    int standalone = -2;
10290
10291
10.3k
    SKIP_BLANKS;
10292
10.3k
    if (CMP10(CUR_PTR, 's', 't', 'a', 'n', 'd', 'a', 'l', 'o', 'n', 'e')) {
10293
136
  SKIP(10);
10294
136
        SKIP_BLANKS;
10295
136
  if (RAW != '=') {
10296
8
      xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10297
8
      return(standalone);
10298
8
        }
10299
128
  NEXT;
10300
128
  SKIP_BLANKS;
10301
128
        if (RAW == '\''){
10302
74
      NEXT;
10303
74
      if ((RAW == 'n') && (NXT(1) == 'o')) {
10304
2
          standalone = 0;
10305
2
                SKIP(2);
10306
72
      } else if ((RAW == 'y') && (NXT(1) == 'e') &&
10307
72
                 (NXT(2) == 's')) {
10308
49
          standalone = 1;
10309
49
    SKIP(3);
10310
49
            } else {
10311
23
    xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
10312
23
      }
10313
74
      if (RAW != '\'') {
10314
73
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10315
73
      } else
10316
1
          NEXT;
10317
74
  } else if (RAW == '"'){
10318
44
      NEXT;
10319
44
      if ((RAW == 'n') && (NXT(1) == 'o')) {
10320
11
          standalone = 0;
10321
11
    SKIP(2);
10322
33
      } else if ((RAW == 'y') && (NXT(1) == 'e') &&
10323
33
                 (NXT(2) == 's')) {
10324
13
          standalone = 1;
10325
13
                SKIP(3);
10326
20
            } else {
10327
20
    xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
10328
20
      }
10329
44
      if (RAW != '"') {
10330
32
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10331
32
      } else
10332
12
          NEXT;
10333
44
  } else {
10334
10
      xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10335
10
        }
10336
128
    }
10337
10.3k
    return(standalone);
10338
10.3k
}
10339
10340
/**
10341
 * xmlParseXMLDecl:
10342
 * @ctxt:  an XML parser context
10343
 *
10344
 * DEPRECATED: Internal function, don't use.
10345
 *
10346
 * parse an XML declaration header
10347
 *
10348
 * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
10349
 */
10350
10351
void
10352
12.7k
xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
10353
12.7k
    xmlChar *version;
10354
10355
    /*
10356
     * This value for standalone indicates that the document has an
10357
     * XML declaration but it does not have a standalone attribute.
10358
     * It will be overwritten later if a standalone attribute is found.
10359
     */
10360
10361
12.7k
    ctxt->standalone = -2;
10362
10363
    /*
10364
     * We know that '<?xml' is here.
10365
     */
10366
12.7k
    SKIP(5);
10367
10368
12.7k
    if (!IS_BLANK_CH(RAW)) {
10369
0
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
10370
0
                 "Blank needed after '<?xml'\n");
10371
0
    }
10372
12.7k
    SKIP_BLANKS;
10373
10374
    /*
10375
     * We must have the VersionInfo here.
10376
     */
10377
12.7k
    version = xmlParseVersionInfo(ctxt);
10378
12.7k
    if (version == NULL) {
10379
12.6k
  xmlFatalErr(ctxt, XML_ERR_VERSION_MISSING, NULL);
10380
12.6k
    } else {
10381
76
  if (!xmlStrEqual(version, (const xmlChar *) XML_DEFAULT_VERSION)) {
10382
      /*
10383
       * Changed here for XML-1.0 5th edition
10384
       */
10385
64
      if (ctxt->options & XML_PARSE_OLD10) {
10386
1
    xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
10387
1
                "Unsupported version '%s'\n",
10388
1
                version);
10389
63
      } else {
10390
63
          if ((version[0] == '1') && ((version[1] == '.'))) {
10391
54
        xmlWarningMsg(ctxt, XML_WAR_UNKNOWN_VERSION,
10392
54
                      "Unsupported version '%s'\n",
10393
54
          version, NULL);
10394
54
    } else {
10395
9
        xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
10396
9
              "Unsupported version '%s'\n",
10397
9
              version);
10398
9
    }
10399
63
      }
10400
64
  }
10401
76
  if (ctxt->version != NULL)
10402
0
      xmlFree((void *) ctxt->version);
10403
76
  ctxt->version = version;
10404
76
    }
10405
10406
    /*
10407
     * We may have the encoding declaration
10408
     */
10409
12.7k
    if (!IS_BLANK_CH(RAW)) {
10410
12.6k
        if ((RAW == '?') && (NXT(1) == '>')) {
10411
175
      SKIP(2);
10412
175
      return;
10413
175
  }
10414
12.4k
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
10415
12.4k
    }
10416
12.5k
    xmlParseEncodingDecl(ctxt);
10417
10418
    /*
10419
     * We may have the standalone status.
10420
     */
10421
12.5k
    if ((ctxt->encoding != NULL) && (!IS_BLANK_CH(RAW))) {
10422
3.24k
        if ((RAW == '?') && (NXT(1) == '>')) {
10423
2.18k
      SKIP(2);
10424
2.18k
      return;
10425
2.18k
  }
10426
1.05k
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
10427
1.05k
    }
10428
10429
    /*
10430
     * We can grow the input buffer freely at that point
10431
     */
10432
10.3k
    GROW;
10433
10434
10.3k
    SKIP_BLANKS;
10435
10.3k
    ctxt->standalone = xmlParseSDDecl(ctxt);
10436
10437
10.3k
    SKIP_BLANKS;
10438
10.3k
    if ((RAW == '?') && (NXT(1) == '>')) {
10439
51
        SKIP(2);
10440
10.3k
    } else if (RAW == '>') {
10441
        /* Deprecated old WD ... */
10442
8.79k
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
10443
8.79k
  NEXT;
10444
8.79k
    } else {
10445
1.52k
        int c;
10446
10447
1.52k
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
10448
16.5k
        while ((PARSER_STOPPED(ctxt) == 0) &&
10449
16.5k
               ((c = CUR) != 0)) {
10450
16.3k
            NEXT;
10451
16.3k
            if (c == '>')
10452
1.29k
                break;
10453
16.3k
        }
10454
1.52k
    }
10455
10.3k
}
10456
10457
/**
10458
 * xmlParseMisc:
10459
 * @ctxt:  an XML parser context
10460
 *
10461
 * DEPRECATED: Internal function, don't use.
10462
 *
10463
 * parse an XML Misc* optional field.
10464
 *
10465
 * [27] Misc ::= Comment | PI |  S
10466
 */
10467
10468
void
10469
49.6k
xmlParseMisc(xmlParserCtxtPtr ctxt) {
10470
54.2k
    while (PARSER_STOPPED(ctxt) == 0) {
10471
52.8k
        SKIP_BLANKS;
10472
52.8k
        GROW;
10473
52.8k
        if ((RAW == '<') && (NXT(1) == '?')) {
10474
3.06k
      xmlParsePI(ctxt);
10475
49.8k
        } else if (CMP4(CUR_PTR, '<', '!', '-', '-')) {
10476
1.61k
      xmlParseComment(ctxt);
10477
48.1k
        } else {
10478
48.1k
            break;
10479
48.1k
        }
10480
52.8k
    }
10481
49.6k
}
10482
10483
static void
10484
22.1k
xmlFinishDocument(xmlParserCtxtPtr ctxt) {
10485
22.1k
    xmlDocPtr doc;
10486
10487
    /*
10488
     * SAX: end of the document processing.
10489
     */
10490
22.1k
    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
10491
22.1k
        ctxt->sax->endDocument(ctxt->userData);
10492
10493
22.1k
    doc = ctxt->myDoc;
10494
22.1k
    if (doc != NULL) {
10495
14.6k
        if (ctxt->wellFormed) {
10496
47
            doc->properties |= XML_DOC_WELLFORMED;
10497
47
            if (ctxt->valid)
10498
43
                doc->properties |= XML_DOC_DTDVALID;
10499
47
            if (ctxt->nsWellFormed)
10500
41
                doc->properties |= XML_DOC_NSVALID;
10501
47
        }
10502
10503
14.6k
        if (ctxt->options & XML_PARSE_OLD10)
10504
1.10k
            doc->properties |= XML_DOC_OLD10;
10505
10506
        /*
10507
         * Remove locally kept entity definitions if the tree was not built
10508
         */
10509
14.6k
  if (xmlStrEqual(doc->version, SAX_COMPAT_MODE)) {
10510
137
            xmlFreeDoc(doc);
10511
137
            ctxt->myDoc = NULL;
10512
137
        }
10513
14.6k
    }
10514
22.1k
}
10515
10516
/**
10517
 * xmlParseDocument:
10518
 * @ctxt:  an XML parser context
10519
 *
10520
 * Parse an XML document and invoke the SAX handlers. This is useful
10521
 * if you're only interested in custom SAX callbacks. If you want a
10522
 * document tree, use xmlCtxtParseDocument.
10523
 *
10524
 * Returns 0, -1 in case of error.
10525
 */
10526
10527
int
10528
22.1k
xmlParseDocument(xmlParserCtxtPtr ctxt) {
10529
22.1k
    if ((ctxt == NULL) || (ctxt->input == NULL))
10530
0
        return(-1);
10531
10532
22.1k
    GROW;
10533
10534
    /*
10535
     * SAX: detecting the level.
10536
     */
10537
22.1k
    xmlCtxtInitializeLate(ctxt);
10538
10539
    /*
10540
     * Document locator is unused. Only for backward compatibility.
10541
     */
10542
22.1k
    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) {
10543
22.1k
        xmlSAXLocator copy = xmlDefaultSAXLocator;
10544
22.1k
        ctxt->sax->setDocumentLocator(ctxt->userData, &copy);
10545
22.1k
    }
10546
10547
22.1k
    xmlDetectEncoding(ctxt);
10548
10549
22.1k
    if (CUR == 0) {
10550
0
  xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
10551
0
  return(-1);
10552
0
    }
10553
10554
22.1k
    GROW;
10555
22.1k
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
10556
10557
  /*
10558
   * Note that we will switch encoding on the fly.
10559
   */
10560
12.7k
  xmlParseXMLDecl(ctxt);
10561
12.7k
  SKIP_BLANKS;
10562
12.7k
    } else {
10563
9.45k
  ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
10564
9.45k
        if (ctxt->version == NULL) {
10565
0
            xmlErrMemory(ctxt);
10566
0
            return(-1);
10567
0
        }
10568
9.45k
    }
10569
22.1k
    if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
10570
14.5k
        ctxt->sax->startDocument(ctxt->userData);
10571
22.1k
    if ((ctxt->myDoc != NULL) && (ctxt->input != NULL) &&
10572
22.1k
        (ctxt->input->buf != NULL) && (ctxt->input->buf->compressed >= 0)) {
10573
0
  ctxt->myDoc->compression = ctxt->input->buf->compressed;
10574
0
    }
10575
10576
    /*
10577
     * The Misc part of the Prolog
10578
     */
10579
22.1k
    xmlParseMisc(ctxt);
10580
10581
    /*
10582
     * Then possibly doc type declaration(s) and more Misc
10583
     * (doctypedecl Misc*)?
10584
     */
10585
22.1k
    GROW;
10586
22.1k
    if (CMP9(CUR_PTR, '<', '!', 'D', 'O', 'C', 'T', 'Y', 'P', 'E')) {
10587
10588
10.2k
  ctxt->inSubset = 1;
10589
10.2k
  xmlParseDocTypeDecl(ctxt);
10590
10.2k
  if (RAW == '[') {
10591
8.59k
      xmlParseInternalSubset(ctxt);
10592
8.59k
  }
10593
10594
  /*
10595
   * Create and update the external subset.
10596
   */
10597
10.2k
  ctxt->inSubset = 2;
10598
10.2k
  if ((ctxt->sax != NULL) && (ctxt->sax->externalSubset != NULL) &&
10599
10.2k
      (!ctxt->disableSAX))
10600
5.90k
      ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
10601
5.90k
                                ctxt->extSubSystem, ctxt->extSubURI);
10602
10.2k
  ctxt->inSubset = 0;
10603
10604
10.2k
        xmlCleanSpecialAttr(ctxt);
10605
10606
10.2k
  xmlParseMisc(ctxt);
10607
10.2k
    }
10608
10609
    /*
10610
     * Time to start parsing the tree itself
10611
     */
10612
22.1k
    GROW;
10613
22.1k
    if (RAW != '<') {
10614
4.99k
        if (ctxt->wellFormed)
10615
5
            xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
10616
5
                           "Start tag expected, '<' not found\n");
10617
17.1k
    } else {
10618
17.1k
  xmlParseElement(ctxt);
10619
10620
  /*
10621
   * The Misc part at the end
10622
   */
10623
17.1k
  xmlParseMisc(ctxt);
10624
10625
17.1k
        if (ctxt->input->cur < ctxt->input->end) {
10626
7.61k
            if (ctxt->wellFormed)
10627
1
          xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
10628
9.58k
        } else if ((ctxt->input->buf != NULL) &&
10629
9.58k
                   (ctxt->input->buf->encoder != NULL) &&
10630
9.58k
                   (!xmlBufIsEmpty(ctxt->input->buf->raw))) {
10631
134
            xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
10632
134
                           "Truncated multi-byte sequence at EOF\n");
10633
134
        }
10634
17.1k
    }
10635
10636
22.1k
    ctxt->instate = XML_PARSER_EOF;
10637
22.1k
    xmlFinishDocument(ctxt);
10638
10639
22.1k
    if (! ctxt->wellFormed) {
10640
22.1k
  ctxt->valid = 0;
10641
22.1k
  return(-1);
10642
22.1k
    }
10643
10644
47
    return(0);
10645
22.1k
}
10646
10647
/**
10648
 * xmlParseExtParsedEnt:
10649
 * @ctxt:  an XML parser context
10650
 *
10651
 * parse a general parsed entity
10652
 * An external general parsed entity is well-formed if it matches the
10653
 * production labeled extParsedEnt.
10654
 *
10655
 * [78] extParsedEnt ::= TextDecl? content
10656
 *
10657
 * Returns 0, -1 in case of error. the parser context is augmented
10658
 *                as a result of the parsing.
10659
 */
10660
10661
int
10662
0
xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) {
10663
0
    if ((ctxt == NULL) || (ctxt->input == NULL))
10664
0
        return(-1);
10665
10666
0
    xmlCtxtInitializeLate(ctxt);
10667
10668
    /*
10669
     * Document locator is unused. Only for backward compatibility.
10670
     */
10671
0
    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) {
10672
0
        xmlSAXLocator copy = xmlDefaultSAXLocator;
10673
0
        ctxt->sax->setDocumentLocator(ctxt->userData, &copy);
10674
0
    }
10675
10676
0
    xmlDetectEncoding(ctxt);
10677
10678
0
    if (CUR == 0) {
10679
0
  xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
10680
0
    }
10681
10682
    /*
10683
     * Check for the XMLDecl in the Prolog.
10684
     */
10685
0
    GROW;
10686
0
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
10687
10688
  /*
10689
   * Note that we will switch encoding on the fly.
10690
   */
10691
0
  xmlParseXMLDecl(ctxt);
10692
0
  SKIP_BLANKS;
10693
0
    } else {
10694
0
  ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
10695
0
    }
10696
0
    if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
10697
0
        ctxt->sax->startDocument(ctxt->userData);
10698
10699
    /*
10700
     * Doing validity checking on chunk doesn't make sense
10701
     */
10702
0
    ctxt->options &= ~XML_PARSE_DTDVALID;
10703
0
    ctxt->validate = 0;
10704
0
    ctxt->depth = 0;
10705
10706
0
    xmlParseContentInternal(ctxt);
10707
10708
0
    if (ctxt->input->cur < ctxt->input->end)
10709
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
10710
10711
    /*
10712
     * SAX: end of the document processing.
10713
     */
10714
0
    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
10715
0
        ctxt->sax->endDocument(ctxt->userData);
10716
10717
0
    if (! ctxt->wellFormed) return(-1);
10718
0
    return(0);
10719
0
}
10720
10721
#ifdef LIBXML_PUSH_ENABLED
10722
/************************************************************************
10723
 *                  *
10724
 *    Progressive parsing interfaces        *
10725
 *                  *
10726
 ************************************************************************/
10727
10728
/**
10729
 * xmlParseLookupChar:
10730
 * @ctxt:  an XML parser context
10731
 * @c:  character
10732
 *
10733
 * Check whether the input buffer contains a character.
10734
 */
10735
static int
10736
0
xmlParseLookupChar(xmlParserCtxtPtr ctxt, int c) {
10737
0
    const xmlChar *cur;
10738
10739
0
    if (ctxt->checkIndex == 0) {
10740
0
        cur = ctxt->input->cur + 1;
10741
0
    } else {
10742
0
        cur = ctxt->input->cur + ctxt->checkIndex;
10743
0
    }
10744
10745
0
    if (memchr(cur, c, ctxt->input->end - cur) == NULL) {
10746
0
        size_t index = ctxt->input->end - ctxt->input->cur;
10747
10748
0
        if (index > LONG_MAX) {
10749
0
            ctxt->checkIndex = 0;
10750
0
            return(1);
10751
0
        }
10752
0
        ctxt->checkIndex = index;
10753
0
        return(0);
10754
0
    } else {
10755
0
        ctxt->checkIndex = 0;
10756
0
        return(1);
10757
0
    }
10758
0
}
10759
10760
/**
10761
 * xmlParseLookupString:
10762
 * @ctxt:  an XML parser context
10763
 * @startDelta: delta to apply at the start
10764
 * @str:  string
10765
 * @strLen:  length of string
10766
 *
10767
 * Check whether the input buffer contains a string.
10768
 */
10769
static const xmlChar *
10770
xmlParseLookupString(xmlParserCtxtPtr ctxt, size_t startDelta,
10771
0
                     const char *str, size_t strLen) {
10772
0
    const xmlChar *cur, *term;
10773
10774
0
    if (ctxt->checkIndex == 0) {
10775
0
        cur = ctxt->input->cur + startDelta;
10776
0
    } else {
10777
0
        cur = ctxt->input->cur + ctxt->checkIndex;
10778
0
    }
10779
10780
0
    term = BAD_CAST strstr((const char *) cur, str);
10781
0
    if (term == NULL) {
10782
0
        const xmlChar *end = ctxt->input->end;
10783
0
        size_t index;
10784
10785
        /* Rescan (strLen - 1) characters. */
10786
0
        if ((size_t) (end - cur) < strLen)
10787
0
            end = cur;
10788
0
        else
10789
0
            end -= strLen - 1;
10790
0
        index = end - ctxt->input->cur;
10791
0
        if (index > LONG_MAX) {
10792
0
            ctxt->checkIndex = 0;
10793
0
            return(ctxt->input->end - strLen);
10794
0
        }
10795
0
        ctxt->checkIndex = index;
10796
0
    } else {
10797
0
        ctxt->checkIndex = 0;
10798
0
    }
10799
10800
0
    return(term);
10801
0
}
10802
10803
/**
10804
 * xmlParseLookupCharData:
10805
 * @ctxt:  an XML parser context
10806
 *
10807
 * Check whether the input buffer contains terminated char data.
10808
 */
10809
static int
10810
0
xmlParseLookupCharData(xmlParserCtxtPtr ctxt) {
10811
0
    const xmlChar *cur = ctxt->input->cur + ctxt->checkIndex;
10812
0
    const xmlChar *end = ctxt->input->end;
10813
0
    size_t index;
10814
10815
0
    while (cur < end) {
10816
0
        if ((*cur == '<') || (*cur == '&')) {
10817
0
            ctxt->checkIndex = 0;
10818
0
            return(1);
10819
0
        }
10820
0
        cur++;
10821
0
    }
10822
10823
0
    index = cur - ctxt->input->cur;
10824
0
    if (index > LONG_MAX) {
10825
0
        ctxt->checkIndex = 0;
10826
0
        return(1);
10827
0
    }
10828
0
    ctxt->checkIndex = index;
10829
0
    return(0);
10830
0
}
10831
10832
/**
10833
 * xmlParseLookupGt:
10834
 * @ctxt:  an XML parser context
10835
 *
10836
 * Check whether there's enough data in the input buffer to finish parsing
10837
 * a start tag. This has to take quotes into account.
10838
 */
10839
static int
10840
0
xmlParseLookupGt(xmlParserCtxtPtr ctxt) {
10841
0
    const xmlChar *cur;
10842
0
    const xmlChar *end = ctxt->input->end;
10843
0
    int state = ctxt->endCheckState;
10844
0
    size_t index;
10845
10846
0
    if (ctxt->checkIndex == 0)
10847
0
        cur = ctxt->input->cur + 1;
10848
0
    else
10849
0
        cur = ctxt->input->cur + ctxt->checkIndex;
10850
10851
0
    while (cur < end) {
10852
0
        if (state) {
10853
0
            if (*cur == state)
10854
0
                state = 0;
10855
0
        } else if (*cur == '\'' || *cur == '"') {
10856
0
            state = *cur;
10857
0
        } else if (*cur == '>') {
10858
0
            ctxt->checkIndex = 0;
10859
0
            ctxt->endCheckState = 0;
10860
0
            return(1);
10861
0
        }
10862
0
        cur++;
10863
0
    }
10864
10865
0
    index = cur - ctxt->input->cur;
10866
0
    if (index > LONG_MAX) {
10867
0
        ctxt->checkIndex = 0;
10868
0
        ctxt->endCheckState = 0;
10869
0
        return(1);
10870
0
    }
10871
0
    ctxt->checkIndex = index;
10872
0
    ctxt->endCheckState = state;
10873
0
    return(0);
10874
0
}
10875
10876
/**
10877
 * xmlParseLookupInternalSubset:
10878
 * @ctxt:  an XML parser context
10879
 *
10880
 * Check whether there's enough data in the input buffer to finish parsing
10881
 * the internal subset.
10882
 */
10883
static int
10884
0
xmlParseLookupInternalSubset(xmlParserCtxtPtr ctxt) {
10885
    /*
10886
     * Sorry, but progressive parsing of the internal subset is not
10887
     * supported. We first check that the full content of the internal
10888
     * subset is available and parsing is launched only at that point.
10889
     * Internal subset ends with "']' S? '>'" in an unescaped section and
10890
     * not in a ']]>' sequence which are conditional sections.
10891
     */
10892
0
    const xmlChar *cur, *start;
10893
0
    const xmlChar *end = ctxt->input->end;
10894
0
    int state = ctxt->endCheckState;
10895
0
    size_t index;
10896
10897
0
    if (ctxt->checkIndex == 0) {
10898
0
        cur = ctxt->input->cur + 1;
10899
0
    } else {
10900
0
        cur = ctxt->input->cur + ctxt->checkIndex;
10901
0
    }
10902
0
    start = cur;
10903
10904
0
    while (cur < end) {
10905
0
        if (state == '-') {
10906
0
            if ((*cur == '-') &&
10907
0
                (cur[1] == '-') &&
10908
0
                (cur[2] == '>')) {
10909
0
                state = 0;
10910
0
                cur += 3;
10911
0
                start = cur;
10912
0
                continue;
10913
0
            }
10914
0
        }
10915
0
        else if (state == ']') {
10916
0
            if (*cur == '>') {
10917
0
                ctxt->checkIndex = 0;
10918
0
                ctxt->endCheckState = 0;
10919
0
                return(1);
10920
0
            }
10921
0
            if (IS_BLANK_CH(*cur)) {
10922
0
                state = ' ';
10923
0
            } else if (*cur != ']') {
10924
0
                state = 0;
10925
0
                start = cur;
10926
0
                continue;
10927
0
            }
10928
0
        }
10929
0
        else if (state == ' ') {
10930
0
            if (*cur == '>') {
10931
0
                ctxt->checkIndex = 0;
10932
0
                ctxt->endCheckState = 0;
10933
0
                return(1);
10934
0
            }
10935
0
            if (!IS_BLANK_CH(*cur)) {
10936
0
                state = 0;
10937
0
                start = cur;
10938
0
                continue;
10939
0
            }
10940
0
        }
10941
0
        else if (state != 0) {
10942
0
            if (*cur == state) {
10943
0
                state = 0;
10944
0
                start = cur + 1;
10945
0
            }
10946
0
        }
10947
0
        else if (*cur == '<') {
10948
0
            if ((cur[1] == '!') &&
10949
0
                (cur[2] == '-') &&
10950
0
                (cur[3] == '-')) {
10951
0
                state = '-';
10952
0
                cur += 4;
10953
                /* Don't treat <!--> as comment */
10954
0
                start = cur;
10955
0
                continue;
10956
0
            }
10957
0
        }
10958
0
        else if ((*cur == '"') || (*cur == '\'') || (*cur == ']')) {
10959
0
            state = *cur;
10960
0
        }
10961
10962
0
        cur++;
10963
0
    }
10964
10965
    /*
10966
     * Rescan the three last characters to detect "<!--" and "-->"
10967
     * split across chunks.
10968
     */
10969
0
    if ((state == 0) || (state == '-')) {
10970
0
        if (cur - start < 3)
10971
0
            cur = start;
10972
0
        else
10973
0
            cur -= 3;
10974
0
    }
10975
0
    index = cur - ctxt->input->cur;
10976
0
    if (index > LONG_MAX) {
10977
0
        ctxt->checkIndex = 0;
10978
0
        ctxt->endCheckState = 0;
10979
0
        return(1);
10980
0
    }
10981
0
    ctxt->checkIndex = index;
10982
0
    ctxt->endCheckState = state;
10983
0
    return(0);
10984
0
}
10985
10986
/**
10987
 * xmlCheckCdataPush:
10988
 * @cur: pointer to the block of characters
10989
 * @len: length of the block in bytes
10990
 * @complete: 1 if complete CDATA block is passed in, 0 if partial block
10991
 *
10992
 * Check that the block of characters is okay as SCdata content [20]
10993
 *
10994
 * Returns the number of bytes to pass if okay, a negative index where an
10995
 *         UTF-8 error occurred otherwise
10996
 */
10997
static int
10998
0
xmlCheckCdataPush(const xmlChar *utf, int len, int complete) {
10999
0
    int ix;
11000
0
    unsigned char c;
11001
0
    int codepoint;
11002
11003
0
    if ((utf == NULL) || (len <= 0))
11004
0
        return(0);
11005
11006
0
    for (ix = 0; ix < len;) {      /* string is 0-terminated */
11007
0
        c = utf[ix];
11008
0
        if ((c & 0x80) == 0x00) { /* 1-byte code, starts with 10 */
11009
0
      if (c >= 0x20)
11010
0
    ix++;
11011
0
      else if ((c == 0xA) || (c == 0xD) || (c == 0x9))
11012
0
          ix++;
11013
0
      else
11014
0
          return(-ix);
11015
0
  } else if ((c & 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */
11016
0
      if (ix + 2 > len) return(complete ? -ix : ix);
11017
0
      if ((utf[ix+1] & 0xc0 ) != 0x80)
11018
0
          return(-ix);
11019
0
      codepoint = (utf[ix] & 0x1f) << 6;
11020
0
      codepoint |= utf[ix+1] & 0x3f;
11021
0
      if (!xmlIsCharQ(codepoint))
11022
0
          return(-ix);
11023
0
      ix += 2;
11024
0
  } else if ((c & 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */
11025
0
      if (ix + 3 > len) return(complete ? -ix : ix);
11026
0
      if (((utf[ix+1] & 0xc0) != 0x80) ||
11027
0
          ((utf[ix+2] & 0xc0) != 0x80))
11028
0
        return(-ix);
11029
0
      codepoint = (utf[ix] & 0xf) << 12;
11030
0
      codepoint |= (utf[ix+1] & 0x3f) << 6;
11031
0
      codepoint |= utf[ix+2] & 0x3f;
11032
0
      if (!xmlIsCharQ(codepoint))
11033
0
          return(-ix);
11034
0
      ix += 3;
11035
0
  } else if ((c & 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */
11036
0
      if (ix + 4 > len) return(complete ? -ix : ix);
11037
0
      if (((utf[ix+1] & 0xc0) != 0x80) ||
11038
0
          ((utf[ix+2] & 0xc0) != 0x80) ||
11039
0
    ((utf[ix+3] & 0xc0) != 0x80))
11040
0
        return(-ix);
11041
0
      codepoint = (utf[ix] & 0x7) << 18;
11042
0
      codepoint |= (utf[ix+1] & 0x3f) << 12;
11043
0
      codepoint |= (utf[ix+2] & 0x3f) << 6;
11044
0
      codepoint |= utf[ix+3] & 0x3f;
11045
0
      if (!xmlIsCharQ(codepoint))
11046
0
          return(-ix);
11047
0
      ix += 4;
11048
0
  } else       /* unknown encoding */
11049
0
      return(-ix);
11050
0
      }
11051
0
      return(ix);
11052
0
}
11053
11054
/**
11055
 * xmlParseTryOrFinish:
11056
 * @ctxt:  an XML parser context
11057
 * @terminate:  last chunk indicator
11058
 *
11059
 * Try to progress on parsing
11060
 *
11061
 * Returns zero if no parsing was possible
11062
 */
11063
static int
11064
0
xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
11065
0
    int ret = 0;
11066
0
    size_t avail;
11067
0
    xmlChar cur, next;
11068
11069
0
    if (ctxt->input == NULL)
11070
0
        return(0);
11071
11072
0
    if ((ctxt->input != NULL) &&
11073
0
        (ctxt->input->cur - ctxt->input->base > 4096)) {
11074
0
        xmlParserShrink(ctxt);
11075
0
    }
11076
11077
0
    while (ctxt->disableSAX == 0) {
11078
0
        avail = ctxt->input->end - ctxt->input->cur;
11079
0
        if (avail < 1)
11080
0
      goto done;
11081
0
        switch (ctxt->instate) {
11082
0
            case XML_PARSER_EOF:
11083
          /*
11084
     * Document parsing is done !
11085
     */
11086
0
          goto done;
11087
0
            case XML_PARSER_START:
11088
                /*
11089
                 * Very first chars read from the document flow.
11090
                 */
11091
0
                if ((!terminate) && (avail < 4))
11092
0
                    goto done;
11093
11094
                /*
11095
                 * We need more bytes to detect EBCDIC code pages.
11096
                 * See xmlDetectEBCDIC.
11097
                 */
11098
0
                if ((CMP4(CUR_PTR, 0x4C, 0x6F, 0xA7, 0x94)) &&
11099
0
                    (!terminate) && (avail < 200))
11100
0
                    goto done;
11101
11102
0
                xmlDetectEncoding(ctxt);
11103
0
                ctxt->instate = XML_PARSER_XML_DECL;
11104
0
    break;
11105
11106
0
            case XML_PARSER_XML_DECL:
11107
0
    if ((!terminate) && (avail < 2))
11108
0
        goto done;
11109
0
    cur = ctxt->input->cur[0];
11110
0
    next = ctxt->input->cur[1];
11111
0
          if ((cur == '<') && (next == '?')) {
11112
        /* PI or XML decl */
11113
0
        if ((!terminate) &&
11114
0
                        (!xmlParseLookupString(ctxt, 2, "?>", 2)))
11115
0
      goto done;
11116
0
        if ((ctxt->input->cur[2] == 'x') &&
11117
0
      (ctxt->input->cur[3] == 'm') &&
11118
0
      (ctxt->input->cur[4] == 'l') &&
11119
0
      (IS_BLANK_CH(ctxt->input->cur[5]))) {
11120
0
      ret += 5;
11121
0
      xmlParseXMLDecl(ctxt);
11122
0
        } else {
11123
0
      ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11124
0
                        if (ctxt->version == NULL) {
11125
0
                            xmlErrMemory(ctxt);
11126
0
                            break;
11127
0
                        }
11128
0
        }
11129
0
    } else {
11130
0
        ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11131
0
        if (ctxt->version == NULL) {
11132
0
            xmlErrMemory(ctxt);
11133
0
      break;
11134
0
        }
11135
0
    }
11136
0
                if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) {
11137
0
                    xmlSAXLocator copy = xmlDefaultSAXLocator;
11138
0
                    ctxt->sax->setDocumentLocator(ctxt->userData, &copy);
11139
0
                }
11140
0
                if ((ctxt->sax) && (ctxt->sax->startDocument) &&
11141
0
                    (!ctxt->disableSAX))
11142
0
                    ctxt->sax->startDocument(ctxt->userData);
11143
0
                ctxt->instate = XML_PARSER_MISC;
11144
0
    break;
11145
0
            case XML_PARSER_START_TAG: {
11146
0
          const xmlChar *name;
11147
0
    const xmlChar *prefix = NULL;
11148
0
    const xmlChar *URI = NULL;
11149
0
                int line = ctxt->input->line;
11150
0
    int nbNs = 0;
11151
11152
0
    if ((!terminate) && (avail < 2))
11153
0
        goto done;
11154
0
    cur = ctxt->input->cur[0];
11155
0
          if (cur != '<') {
11156
0
        xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
11157
0
                                   "Start tag expected, '<' not found");
11158
0
                    ctxt->instate = XML_PARSER_EOF;
11159
0
                    xmlFinishDocument(ctxt);
11160
0
        goto done;
11161
0
    }
11162
0
    if ((!terminate) && (!xmlParseLookupGt(ctxt)))
11163
0
                    goto done;
11164
0
    if (ctxt->spaceNr == 0)
11165
0
        spacePush(ctxt, -1);
11166
0
    else if (*ctxt->space == -2)
11167
0
        spacePush(ctxt, -1);
11168
0
    else
11169
0
        spacePush(ctxt, *ctxt->space);
11170
0
#ifdef LIBXML_SAX1_ENABLED
11171
0
    if (ctxt->sax2)
11172
0
#endif /* LIBXML_SAX1_ENABLED */
11173
0
        name = xmlParseStartTag2(ctxt, &prefix, &URI, &nbNs);
11174
0
#ifdef LIBXML_SAX1_ENABLED
11175
0
    else
11176
0
        name = xmlParseStartTag(ctxt);
11177
0
#endif /* LIBXML_SAX1_ENABLED */
11178
0
    if (name == NULL) {
11179
0
        spacePop(ctxt);
11180
0
                    ctxt->instate = XML_PARSER_EOF;
11181
0
                    xmlFinishDocument(ctxt);
11182
0
        goto done;
11183
0
    }
11184
0
#ifdef LIBXML_VALID_ENABLED
11185
    /*
11186
     * [ VC: Root Element Type ]
11187
     * The Name in the document type declaration must match
11188
     * the element type of the root element.
11189
     */
11190
0
    if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
11191
0
        ctxt->node && (ctxt->node == ctxt->myDoc->children))
11192
0
        ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
11193
0
#endif /* LIBXML_VALID_ENABLED */
11194
11195
    /*
11196
     * Check for an Empty Element.
11197
     */
11198
0
    if ((RAW == '/') && (NXT(1) == '>')) {
11199
0
        SKIP(2);
11200
11201
0
        if (ctxt->sax2) {
11202
0
      if ((ctxt->sax != NULL) &&
11203
0
          (ctxt->sax->endElementNs != NULL) &&
11204
0
          (!ctxt->disableSAX))
11205
0
          ctxt->sax->endElementNs(ctxt->userData, name,
11206
0
                                  prefix, URI);
11207
0
      if (nbNs > 0)
11208
0
          xmlParserNsPop(ctxt, nbNs);
11209
0
#ifdef LIBXML_SAX1_ENABLED
11210
0
        } else {
11211
0
      if ((ctxt->sax != NULL) &&
11212
0
          (ctxt->sax->endElement != NULL) &&
11213
0
          (!ctxt->disableSAX))
11214
0
          ctxt->sax->endElement(ctxt->userData, name);
11215
0
#endif /* LIBXML_SAX1_ENABLED */
11216
0
        }
11217
0
        spacePop(ctxt);
11218
0
    } else if (RAW == '>') {
11219
0
        NEXT;
11220
0
                    nameNsPush(ctxt, name, prefix, URI, line, nbNs);
11221
0
    } else {
11222
0
        xmlFatalErrMsgStr(ctxt, XML_ERR_GT_REQUIRED,
11223
0
           "Couldn't find end of Start Tag %s\n",
11224
0
           name);
11225
0
        nodePop(ctxt);
11226
0
        spacePop(ctxt);
11227
0
                    if (nbNs > 0)
11228
0
                        xmlParserNsPop(ctxt, nbNs);
11229
0
    }
11230
11231
0
                if (ctxt->nameNr == 0)
11232
0
                    ctxt->instate = XML_PARSER_EPILOG;
11233
0
                else
11234
0
                    ctxt->instate = XML_PARSER_CONTENT;
11235
0
                break;
11236
0
      }
11237
0
            case XML_PARSER_CONTENT: {
11238
0
    cur = ctxt->input->cur[0];
11239
11240
0
    if (cur == '<') {
11241
0
                    if ((!terminate) && (avail < 2))
11242
0
                        goto done;
11243
0
        next = ctxt->input->cur[1];
11244
11245
0
                    if (next == '/') {
11246
0
                        ctxt->instate = XML_PARSER_END_TAG;
11247
0
                        break;
11248
0
                    } else if (next == '?') {
11249
0
                        if ((!terminate) &&
11250
0
                            (!xmlParseLookupString(ctxt, 2, "?>", 2)))
11251
0
                            goto done;
11252
0
                        xmlParsePI(ctxt);
11253
0
                        ctxt->instate = XML_PARSER_CONTENT;
11254
0
                        break;
11255
0
                    } else if (next == '!') {
11256
0
                        if ((!terminate) && (avail < 3))
11257
0
                            goto done;
11258
0
                        next = ctxt->input->cur[2];
11259
11260
0
                        if (next == '-') {
11261
0
                            if ((!terminate) && (avail < 4))
11262
0
                                goto done;
11263
0
                            if (ctxt->input->cur[3] == '-') {
11264
0
                                if ((!terminate) &&
11265
0
                                    (!xmlParseLookupString(ctxt, 4, "-->", 3)))
11266
0
                                    goto done;
11267
0
                                xmlParseComment(ctxt);
11268
0
                                ctxt->instate = XML_PARSER_CONTENT;
11269
0
                                break;
11270
0
                            }
11271
0
                        } else if (next == '[') {
11272
0
                            if ((!terminate) && (avail < 9))
11273
0
                                goto done;
11274
0
                            if ((ctxt->input->cur[2] == '[') &&
11275
0
                                (ctxt->input->cur[3] == 'C') &&
11276
0
                                (ctxt->input->cur[4] == 'D') &&
11277
0
                                (ctxt->input->cur[5] == 'A') &&
11278
0
                                (ctxt->input->cur[6] == 'T') &&
11279
0
                                (ctxt->input->cur[7] == 'A') &&
11280
0
                                (ctxt->input->cur[8] == '[')) {
11281
0
                                SKIP(9);
11282
0
                                ctxt->instate = XML_PARSER_CDATA_SECTION;
11283
0
                                break;
11284
0
                            }
11285
0
                        }
11286
0
                    }
11287
0
    } else if (cur == '&') {
11288
0
        if ((!terminate) && (!xmlParseLookupChar(ctxt, ';')))
11289
0
      goto done;
11290
0
        xmlParseReference(ctxt);
11291
0
                    break;
11292
0
    } else {
11293
        /* TODO Avoid the extra copy, handle directly !!! */
11294
        /*
11295
         * Goal of the following test is:
11296
         *  - minimize calls to the SAX 'character' callback
11297
         *    when they are mergeable
11298
         *  - handle an problem for isBlank when we only parse
11299
         *    a sequence of blank chars and the next one is
11300
         *    not available to check against '<' presence.
11301
         *  - tries to homogenize the differences in SAX
11302
         *    callbacks between the push and pull versions
11303
         *    of the parser.
11304
         */
11305
0
        if (avail < XML_PARSER_BIG_BUFFER_SIZE) {
11306
0
      if ((!terminate) && (!xmlParseLookupCharData(ctxt)))
11307
0
          goto done;
11308
0
                    }
11309
0
                    ctxt->checkIndex = 0;
11310
0
        xmlParseCharDataInternal(ctxt, !terminate);
11311
0
                    break;
11312
0
    }
11313
11314
0
                ctxt->instate = XML_PARSER_START_TAG;
11315
0
    break;
11316
0
      }
11317
0
            case XML_PARSER_END_TAG:
11318
0
    if ((!terminate) && (!xmlParseLookupChar(ctxt, '>')))
11319
0
        goto done;
11320
0
    if (ctxt->sax2) {
11321
0
              xmlParseEndTag2(ctxt, &ctxt->pushTab[ctxt->nameNr - 1]);
11322
0
        nameNsPop(ctxt);
11323
0
    }
11324
0
#ifdef LIBXML_SAX1_ENABLED
11325
0
      else
11326
0
        xmlParseEndTag1(ctxt, 0);
11327
0
#endif /* LIBXML_SAX1_ENABLED */
11328
0
    if (ctxt->nameNr == 0) {
11329
0
        ctxt->instate = XML_PARSER_EPILOG;
11330
0
    } else {
11331
0
        ctxt->instate = XML_PARSER_CONTENT;
11332
0
    }
11333
0
    break;
11334
0
            case XML_PARSER_CDATA_SECTION: {
11335
          /*
11336
     * The Push mode need to have the SAX callback for
11337
     * cdataBlock merge back contiguous callbacks.
11338
     */
11339
0
    const xmlChar *term;
11340
11341
0
                if (terminate) {
11342
                    /*
11343
                     * Don't call xmlParseLookupString. If 'terminate'
11344
                     * is set, checkIndex is invalid.
11345
                     */
11346
0
                    term = BAD_CAST strstr((const char *) ctxt->input->cur,
11347
0
                                           "]]>");
11348
0
                } else {
11349
0
        term = xmlParseLookupString(ctxt, 0, "]]>", 3);
11350
0
                }
11351
11352
0
    if (term == NULL) {
11353
0
        int tmp, size;
11354
11355
0
                    if (terminate) {
11356
                        /* Unfinished CDATA section */
11357
0
                        size = ctxt->input->end - ctxt->input->cur;
11358
0
                    } else {
11359
0
                        if (avail < XML_PARSER_BIG_BUFFER_SIZE + 2)
11360
0
                            goto done;
11361
0
                        ctxt->checkIndex = 0;
11362
                        /* XXX: Why don't we pass the full buffer? */
11363
0
                        size = XML_PARSER_BIG_BUFFER_SIZE;
11364
0
                    }
11365
0
                    tmp = xmlCheckCdataPush(ctxt->input->cur, size, 0);
11366
0
                    if (tmp <= 0) {
11367
0
                        tmp = -tmp;
11368
0
                        ctxt->input->cur += tmp;
11369
0
                        goto encoding_error;
11370
0
                    }
11371
0
                    if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
11372
0
                        if (ctxt->sax->cdataBlock != NULL)
11373
0
                            ctxt->sax->cdataBlock(ctxt->userData,
11374
0
                                                  ctxt->input->cur, tmp);
11375
0
                        else if (ctxt->sax->characters != NULL)
11376
0
                            ctxt->sax->characters(ctxt->userData,
11377
0
                                                  ctxt->input->cur, tmp);
11378
0
                    }
11379
0
                    SKIPL(tmp);
11380
0
    } else {
11381
0
                    int base = term - CUR_PTR;
11382
0
        int tmp;
11383
11384
0
        tmp = xmlCheckCdataPush(ctxt->input->cur, base, 1);
11385
0
        if ((tmp < 0) || (tmp != base)) {
11386
0
      tmp = -tmp;
11387
0
      ctxt->input->cur += tmp;
11388
0
      goto encoding_error;
11389
0
        }
11390
0
        if ((ctxt->sax != NULL) && (base == 0) &&
11391
0
            (ctxt->sax->cdataBlock != NULL) &&
11392
0
            (!ctxt->disableSAX)) {
11393
      /*
11394
       * Special case to provide identical behaviour
11395
       * between pull and push parsers on enpty CDATA
11396
       * sections
11397
       */
11398
0
       if ((ctxt->input->cur - ctxt->input->base >= 9) &&
11399
0
           (!strncmp((const char *)&ctxt->input->cur[-9],
11400
0
                     "<![CDATA[", 9)))
11401
0
           ctxt->sax->cdataBlock(ctxt->userData,
11402
0
                                 BAD_CAST "", 0);
11403
0
        } else if ((ctxt->sax != NULL) && (base > 0) &&
11404
0
      (!ctxt->disableSAX)) {
11405
0
      if (ctxt->sax->cdataBlock != NULL)
11406
0
          ctxt->sax->cdataBlock(ctxt->userData,
11407
0
              ctxt->input->cur, base);
11408
0
      else if (ctxt->sax->characters != NULL)
11409
0
          ctxt->sax->characters(ctxt->userData,
11410
0
              ctxt->input->cur, base);
11411
0
        }
11412
0
        SKIPL(base + 3);
11413
0
        ctxt->instate = XML_PARSER_CONTENT;
11414
0
    }
11415
0
    break;
11416
0
      }
11417
0
            case XML_PARSER_MISC:
11418
0
            case XML_PARSER_PROLOG:
11419
0
            case XML_PARSER_EPILOG:
11420
0
    SKIP_BLANKS;
11421
0
                avail = ctxt->input->end - ctxt->input->cur;
11422
0
    if (avail < 1)
11423
0
        goto done;
11424
0
    if (ctxt->input->cur[0] == '<') {
11425
0
                    if ((!terminate) && (avail < 2))
11426
0
                        goto done;
11427
0
                    next = ctxt->input->cur[1];
11428
0
                    if (next == '?') {
11429
0
                        if ((!terminate) &&
11430
0
                            (!xmlParseLookupString(ctxt, 2, "?>", 2)))
11431
0
                            goto done;
11432
0
                        xmlParsePI(ctxt);
11433
0
                        break;
11434
0
                    } else if (next == '!') {
11435
0
                        if ((!terminate) && (avail < 3))
11436
0
                            goto done;
11437
11438
0
                        if (ctxt->input->cur[2] == '-') {
11439
0
                            if ((!terminate) && (avail < 4))
11440
0
                                goto done;
11441
0
                            if (ctxt->input->cur[3] == '-') {
11442
0
                                if ((!terminate) &&
11443
0
                                    (!xmlParseLookupString(ctxt, 4, "-->", 3)))
11444
0
                                    goto done;
11445
0
                                xmlParseComment(ctxt);
11446
0
                                break;
11447
0
                            }
11448
0
                        } else if (ctxt->instate == XML_PARSER_MISC) {
11449
0
                            if ((!terminate) && (avail < 9))
11450
0
                                goto done;
11451
0
                            if ((ctxt->input->cur[2] == 'D') &&
11452
0
                                (ctxt->input->cur[3] == 'O') &&
11453
0
                                (ctxt->input->cur[4] == 'C') &&
11454
0
                                (ctxt->input->cur[5] == 'T') &&
11455
0
                                (ctxt->input->cur[6] == 'Y') &&
11456
0
                                (ctxt->input->cur[7] == 'P') &&
11457
0
                                (ctxt->input->cur[8] == 'E')) {
11458
0
                                if ((!terminate) && (!xmlParseLookupGt(ctxt)))
11459
0
                                    goto done;
11460
0
                                ctxt->inSubset = 1;
11461
0
                                xmlParseDocTypeDecl(ctxt);
11462
0
                                if (RAW == '[') {
11463
0
                                    ctxt->instate = XML_PARSER_DTD;
11464
0
                                } else {
11465
                                    /*
11466
                                     * Create and update the external subset.
11467
                                     */
11468
0
                                    ctxt->inSubset = 2;
11469
0
                                    if ((ctxt->sax != NULL) &&
11470
0
                                        (!ctxt->disableSAX) &&
11471
0
                                        (ctxt->sax->externalSubset != NULL))
11472
0
                                        ctxt->sax->externalSubset(
11473
0
                                                ctxt->userData,
11474
0
                                                ctxt->intSubName,
11475
0
                                                ctxt->extSubSystem,
11476
0
                                                ctxt->extSubURI);
11477
0
                                    ctxt->inSubset = 0;
11478
0
                                    xmlCleanSpecialAttr(ctxt);
11479
0
                                    ctxt->instate = XML_PARSER_PROLOG;
11480
0
                                }
11481
0
                                break;
11482
0
                            }
11483
0
                        }
11484
0
                    }
11485
0
                }
11486
11487
0
                if (ctxt->instate == XML_PARSER_EPILOG) {
11488
0
                    if (ctxt->errNo == XML_ERR_OK)
11489
0
                        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
11490
0
        ctxt->instate = XML_PARSER_EOF;
11491
0
                    xmlFinishDocument(ctxt);
11492
0
                } else {
11493
0
        ctxt->instate = XML_PARSER_START_TAG;
11494
0
    }
11495
0
    break;
11496
0
            case XML_PARSER_DTD: {
11497
0
                if ((!terminate) && (!xmlParseLookupInternalSubset(ctxt)))
11498
0
                    goto done;
11499
0
    xmlParseInternalSubset(ctxt);
11500
0
    ctxt->inSubset = 2;
11501
0
    if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
11502
0
        (ctxt->sax->externalSubset != NULL))
11503
0
        ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
11504
0
          ctxt->extSubSystem, ctxt->extSubURI);
11505
0
    ctxt->inSubset = 0;
11506
0
    xmlCleanSpecialAttr(ctxt);
11507
0
    ctxt->instate = XML_PARSER_PROLOG;
11508
0
                break;
11509
0
      }
11510
0
            default:
11511
0
                xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
11512
0
      "PP: internal error\n");
11513
0
    ctxt->instate = XML_PARSER_EOF;
11514
0
    break;
11515
0
  }
11516
0
    }
11517
0
done:
11518
0
    return(ret);
11519
0
encoding_error:
11520
    /* Only report the first error */
11521
0
    if ((ctxt->input->flags & XML_INPUT_ENCODING_ERROR) == 0) {
11522
0
        xmlCtxtErrIO(ctxt, XML_ERR_INVALID_ENCODING, NULL);
11523
0
        ctxt->input->flags |= XML_INPUT_ENCODING_ERROR;
11524
0
    }
11525
0
    return(0);
11526
0
}
11527
11528
/**
11529
 * xmlParseChunk:
11530
 * @ctxt:  an XML parser context
11531
 * @chunk:  chunk of memory
11532
 * @size:  size of chunk in bytes
11533
 * @terminate:  last chunk indicator
11534
 *
11535
 * Parse a chunk of memory in push parser mode.
11536
 *
11537
 * Assumes that the parser context was initialized with
11538
 * xmlCreatePushParserCtxt.
11539
 *
11540
 * The last chunk, which will often be empty, must be marked with
11541
 * the @terminate flag. With the default SAX callbacks, the resulting
11542
 * document will be available in ctxt->myDoc. This pointer will not
11543
 * be freed by the library.
11544
 *
11545
 * If the document isn't well-formed, ctxt->myDoc is set to NULL.
11546
 * The push parser doesn't support recovery mode.
11547
 *
11548
 * Returns an xmlParserErrors code (0 on success).
11549
 */
11550
int
11551
xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
11552
0
              int terminate) {
11553
0
    size_t curBase;
11554
0
    size_t maxLength;
11555
0
    int end_in_lf = 0;
11556
11557
0
    if ((ctxt == NULL) || (size < 0))
11558
0
        return(XML_ERR_ARGUMENT);
11559
0
    if (ctxt->disableSAX != 0)
11560
0
        return(ctxt->errNo);
11561
0
    if (ctxt->input == NULL)
11562
0
        return(XML_ERR_INTERNAL_ERROR);
11563
11564
0
    ctxt->input->flags |= XML_INPUT_PROGRESSIVE;
11565
0
    if (ctxt->instate == XML_PARSER_START)
11566
0
        xmlCtxtInitializeLate(ctxt);
11567
0
    if ((size > 0) && (chunk != NULL) && (!terminate) &&
11568
0
        (chunk[size - 1] == '\r')) {
11569
0
  end_in_lf = 1;
11570
0
  size--;
11571
0
    }
11572
11573
0
    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
11574
0
        (ctxt->input->buf != NULL))  {
11575
0
  size_t pos = ctxt->input->cur - ctxt->input->base;
11576
0
  int res;
11577
11578
0
  res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
11579
0
        xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos);
11580
0
  if (res < 0) {
11581
0
            xmlCtxtErrIO(ctxt, ctxt->input->buf->error, NULL);
11582
0
      xmlHaltParser(ctxt);
11583
0
      return(ctxt->errNo);
11584
0
  }
11585
0
    }
11586
11587
0
    xmlParseTryOrFinish(ctxt, terminate);
11588
11589
0
    curBase = ctxt->input->cur - ctxt->input->base;
11590
0
    maxLength = (ctxt->options & XML_PARSE_HUGE) ?
11591
0
                XML_MAX_HUGE_LENGTH :
11592
0
                XML_MAX_LOOKUP_LIMIT;
11593
0
    if (curBase > maxLength) {
11594
0
        xmlFatalErr(ctxt, XML_ERR_RESOURCE_LIMIT,
11595
0
                    "Buffer size limit exceeded, try XML_PARSE_HUGE\n");
11596
0
        xmlHaltParser(ctxt);
11597
0
    }
11598
11599
0
    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
11600
0
        return(ctxt->errNo);
11601
11602
0
    if ((end_in_lf == 1) && (ctxt->input != NULL) &&
11603
0
        (ctxt->input->buf != NULL)) {
11604
0
  size_t pos = ctxt->input->cur - ctxt->input->base;
11605
0
        int res;
11606
11607
0
  res = xmlParserInputBufferPush(ctxt->input->buf, 1, "\r");
11608
0
  xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos);
11609
0
        if (res < 0) {
11610
0
            xmlCtxtErrIO(ctxt, ctxt->input->buf->error, NULL);
11611
0
            xmlHaltParser(ctxt);
11612
0
            return(ctxt->errNo);
11613
0
        }
11614
0
    }
11615
0
    if (terminate) {
11616
  /*
11617
   * Check for termination
11618
   */
11619
0
        if ((ctxt->instate != XML_PARSER_EOF) &&
11620
0
            (ctxt->instate != XML_PARSER_EPILOG)) {
11621
0
            if (ctxt->nameNr > 0) {
11622
0
                const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
11623
0
                int line = ctxt->pushTab[ctxt->nameNr - 1].line;
11624
0
                xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
11625
0
                        "Premature end of data in tag %s line %d\n",
11626
0
                        name, line, NULL);
11627
0
            } else if (ctxt->instate == XML_PARSER_START) {
11628
0
                xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
11629
0
            } else {
11630
0
                xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
11631
0
                               "Start tag expected, '<' not found\n");
11632
0
            }
11633
0
        } else if ((ctxt->input->buf != NULL) &&
11634
0
                   (ctxt->input->buf->encoder != NULL) &&
11635
0
                   (!xmlBufIsEmpty(ctxt->input->buf->raw))) {
11636
0
            xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
11637
0
                           "Truncated multi-byte sequence at EOF\n");
11638
0
        }
11639
0
  if (ctxt->instate != XML_PARSER_EOF) {
11640
0
            ctxt->instate = XML_PARSER_EOF;
11641
0
            xmlFinishDocument(ctxt);
11642
0
  }
11643
0
    }
11644
0
    if (ctxt->wellFormed == 0)
11645
0
  return((xmlParserErrors) ctxt->errNo);
11646
0
    else
11647
0
        return(0);
11648
0
}
11649
11650
/************************************************************************
11651
 *                  *
11652
 *    I/O front end functions to the parser     *
11653
 *                  *
11654
 ************************************************************************/
11655
11656
/**
11657
 * xmlCreatePushParserCtxt:
11658
 * @sax:  a SAX handler (optional)
11659
 * @user_data:  user data for SAX callbacks (optional)
11660
 * @chunk:  initial chunk (optional, deprecated)
11661
 * @size:  size of initial chunk in bytes
11662
 * @filename:  file name or URI (optional)
11663
 *
11664
 * Create a parser context for using the XML parser in push mode.
11665
 * See xmlParseChunk.
11666
 *
11667
 * Passing an initial chunk is useless and deprecated.
11668
 *
11669
 * @filename is used as base URI to fetch external entities and for
11670
 * error reports.
11671
 *
11672
 * Returns the new parser context or NULL in case of error.
11673
 */
11674
11675
xmlParserCtxtPtr
11676
xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
11677
0
                        const char *chunk, int size, const char *filename) {
11678
0
    xmlParserCtxtPtr ctxt;
11679
0
    xmlParserInputPtr input;
11680
11681
0
    ctxt = xmlNewSAXParserCtxt(sax, user_data);
11682
0
    if (ctxt == NULL)
11683
0
  return(NULL);
11684
11685
0
    ctxt->options &= ~XML_PARSE_NODICT;
11686
0
    ctxt->dictNames = 1;
11687
11688
0
    input = xmlNewInputPush(ctxt, filename, chunk, size, NULL);
11689
0
    if (input == NULL) {
11690
0
  xmlFreeParserCtxt(ctxt);
11691
0
  return(NULL);
11692
0
    }
11693
0
    inputPush(ctxt, input);
11694
11695
0
    return(ctxt);
11696
0
}
11697
#endif /* LIBXML_PUSH_ENABLED */
11698
11699
/**
11700
 * xmlStopParser:
11701
 * @ctxt:  an XML parser context
11702
 *
11703
 * Blocks further parser processing
11704
 */
11705
void
11706
0
xmlStopParser(xmlParserCtxtPtr ctxt) {
11707
0
    if (ctxt == NULL)
11708
0
        return;
11709
0
    xmlHaltParser(ctxt);
11710
0
    if (ctxt->errNo != XML_ERR_NO_MEMORY)
11711
0
        ctxt->errNo = XML_ERR_USER_STOP;
11712
0
}
11713
11714
/**
11715
 * xmlCreateIOParserCtxt:
11716
 * @sax:  a SAX handler (optional)
11717
 * @user_data:  user data for SAX callbacks (optional)
11718
 * @ioread:  an I/O read function
11719
 * @ioclose:  an I/O close function (optional)
11720
 * @ioctx:  an I/O handler
11721
 * @enc:  the charset encoding if known (deprecated)
11722
 *
11723
 * DEPRECATED: Use xmlNewParserCtxt and xmlCtxtReadIO.
11724
 *
11725
 * Create a parser context for using the XML parser with an existing
11726
 * I/O stream
11727
 *
11728
 * Returns the new parser context or NULL
11729
 */
11730
xmlParserCtxtPtr
11731
xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
11732
                      xmlInputReadCallback ioread,
11733
                      xmlInputCloseCallback ioclose,
11734
0
                      void *ioctx, xmlCharEncoding enc) {
11735
0
    xmlParserCtxtPtr ctxt;
11736
0
    xmlParserInputPtr input;
11737
0
    const char *encoding;
11738
11739
0
    ctxt = xmlNewSAXParserCtxt(sax, user_data);
11740
0
    if (ctxt == NULL)
11741
0
  return(NULL);
11742
11743
0
    encoding = xmlGetCharEncodingName(enc);
11744
0
    input = xmlNewInputIO(ctxt, NULL, ioread, ioclose, ioctx, encoding, 0);
11745
0
    if (input == NULL) {
11746
0
  xmlFreeParserCtxt(ctxt);
11747
0
        return (NULL);
11748
0
    }
11749
0
    inputPush(ctxt, input);
11750
11751
0
    return(ctxt);
11752
0
}
11753
11754
#ifdef LIBXML_VALID_ENABLED
11755
/************************************************************************
11756
 *                  *
11757
 *    Front ends when parsing a DTD       *
11758
 *                  *
11759
 ************************************************************************/
11760
11761
/**
11762
 * xmlIOParseDTD:
11763
 * @sax:  the SAX handler block or NULL
11764
 * @input:  an Input Buffer
11765
 * @enc:  the charset encoding if known
11766
 *
11767
 * Load and parse a DTD
11768
 *
11769
 * Returns the resulting xmlDtdPtr or NULL in case of error.
11770
 * @input will be freed by the function in any case.
11771
 */
11772
11773
xmlDtdPtr
11774
xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
11775
0
        xmlCharEncoding enc) {
11776
0
    xmlDtdPtr ret = NULL;
11777
0
    xmlParserCtxtPtr ctxt;
11778
0
    xmlParserInputPtr pinput = NULL;
11779
11780
0
    if (input == NULL)
11781
0
  return(NULL);
11782
11783
0
    ctxt = xmlNewSAXParserCtxt(sax, NULL);
11784
0
    if (ctxt == NULL) {
11785
0
        xmlFreeParserInputBuffer(input);
11786
0
  return(NULL);
11787
0
    }
11788
11789
    /*
11790
     * generate a parser input from the I/O handler
11791
     */
11792
11793
0
    pinput = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
11794
0
    if (pinput == NULL) {
11795
0
        xmlFreeParserInputBuffer(input);
11796
0
  xmlFreeParserCtxt(ctxt);
11797
0
  return(NULL);
11798
0
    }
11799
11800
    /*
11801
     * plug some encoding conversion routines here.
11802
     */
11803
0
    if (xmlPushInput(ctxt, pinput) < 0) {
11804
0
  xmlFreeParserCtxt(ctxt);
11805
0
  return(NULL);
11806
0
    }
11807
0
    if (enc != XML_CHAR_ENCODING_NONE) {
11808
0
        xmlSwitchEncoding(ctxt, enc);
11809
0
    }
11810
11811
    /*
11812
     * let's parse that entity knowing it's an external subset.
11813
     */
11814
0
    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
11815
0
    if (ctxt->myDoc == NULL) {
11816
0
  xmlErrMemory(ctxt);
11817
0
  return(NULL);
11818
0
    }
11819
0
    ctxt->myDoc->properties = XML_DOC_INTERNAL;
11820
0
    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
11821
0
                                 BAD_CAST "none", BAD_CAST "none");
11822
11823
0
    xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none");
11824
11825
0
    if (ctxt->myDoc != NULL) {
11826
0
  if (ctxt->wellFormed) {
11827
0
      ret = ctxt->myDoc->extSubset;
11828
0
      ctxt->myDoc->extSubset = NULL;
11829
0
      if (ret != NULL) {
11830
0
    xmlNodePtr tmp;
11831
11832
0
    ret->doc = NULL;
11833
0
    tmp = ret->children;
11834
0
    while (tmp != NULL) {
11835
0
        tmp->doc = NULL;
11836
0
        tmp = tmp->next;
11837
0
    }
11838
0
      }
11839
0
  } else {
11840
0
      ret = NULL;
11841
0
  }
11842
0
        xmlFreeDoc(ctxt->myDoc);
11843
0
        ctxt->myDoc = NULL;
11844
0
    }
11845
0
    xmlFreeParserCtxt(ctxt);
11846
11847
0
    return(ret);
11848
0
}
11849
11850
/**
11851
 * xmlSAXParseDTD:
11852
 * @sax:  the SAX handler block
11853
 * @ExternalID:  a NAME* containing the External ID of the DTD
11854
 * @SystemID:  a NAME* containing the URL to the DTD
11855
 *
11856
 * DEPRECATED: Don't use.
11857
 *
11858
 * Load and parse an external subset.
11859
 *
11860
 * Returns the resulting xmlDtdPtr or NULL in case of error.
11861
 */
11862
11863
xmlDtdPtr
11864
xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
11865
0
                          const xmlChar *SystemID) {
11866
0
    xmlDtdPtr ret = NULL;
11867
0
    xmlParserCtxtPtr ctxt;
11868
0
    xmlParserInputPtr input = NULL;
11869
0
    xmlChar* systemIdCanonic;
11870
11871
0
    if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
11872
11873
0
    ctxt = xmlNewSAXParserCtxt(sax, NULL);
11874
0
    if (ctxt == NULL) {
11875
0
  return(NULL);
11876
0
    }
11877
11878
    /*
11879
     * Canonicalise the system ID
11880
     */
11881
0
    systemIdCanonic = xmlCanonicPath(SystemID);
11882
0
    if ((SystemID != NULL) && (systemIdCanonic == NULL)) {
11883
0
  xmlFreeParserCtxt(ctxt);
11884
0
  return(NULL);
11885
0
    }
11886
11887
    /*
11888
     * Ask the Entity resolver to load the damn thing
11889
     */
11890
11891
0
    if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
11892
0
  input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
11893
0
                                   systemIdCanonic);
11894
0
    if (input == NULL) {
11895
0
  xmlFreeParserCtxt(ctxt);
11896
0
  if (systemIdCanonic != NULL)
11897
0
      xmlFree(systemIdCanonic);
11898
0
  return(NULL);
11899
0
    }
11900
11901
    /*
11902
     * plug some encoding conversion routines here.
11903
     */
11904
0
    if (xmlPushInput(ctxt, input) < 0) {
11905
0
  xmlFreeParserCtxt(ctxt);
11906
0
  if (systemIdCanonic != NULL)
11907
0
      xmlFree(systemIdCanonic);
11908
0
  return(NULL);
11909
0
    }
11910
11911
0
    xmlDetectEncoding(ctxt);
11912
11913
0
    if (input->filename == NULL)
11914
0
  input->filename = (char *) systemIdCanonic;
11915
0
    else
11916
0
  xmlFree(systemIdCanonic);
11917
11918
    /*
11919
     * let's parse that entity knowing it's an external subset.
11920
     */
11921
0
    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
11922
0
    if (ctxt->myDoc == NULL) {
11923
0
  xmlErrMemory(ctxt);
11924
0
  xmlFreeParserCtxt(ctxt);
11925
0
  return(NULL);
11926
0
    }
11927
0
    ctxt->myDoc->properties = XML_DOC_INTERNAL;
11928
0
    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
11929
0
                                 ExternalID, SystemID);
11930
0
    if (ctxt->myDoc->extSubset == NULL) {
11931
0
        xmlFreeDoc(ctxt->myDoc);
11932
0
        xmlFreeParserCtxt(ctxt);
11933
0
        return(NULL);
11934
0
    }
11935
0
    xmlParseExternalSubset(ctxt, ExternalID, SystemID);
11936
11937
0
    if (ctxt->myDoc != NULL) {
11938
0
  if (ctxt->wellFormed) {
11939
0
      ret = ctxt->myDoc->extSubset;
11940
0
      ctxt->myDoc->extSubset = NULL;
11941
0
      if (ret != NULL) {
11942
0
    xmlNodePtr tmp;
11943
11944
0
    ret->doc = NULL;
11945
0
    tmp = ret->children;
11946
0
    while (tmp != NULL) {
11947
0
        tmp->doc = NULL;
11948
0
        tmp = tmp->next;
11949
0
    }
11950
0
      }
11951
0
  } else {
11952
0
      ret = NULL;
11953
0
  }
11954
0
        xmlFreeDoc(ctxt->myDoc);
11955
0
        ctxt->myDoc = NULL;
11956
0
    }
11957
0
    xmlFreeParserCtxt(ctxt);
11958
11959
0
    return(ret);
11960
0
}
11961
11962
11963
/**
11964
 * xmlParseDTD:
11965
 * @ExternalID:  a NAME* containing the External ID of the DTD
11966
 * @SystemID:  a NAME* containing the URL to the DTD
11967
 *
11968
 * Load and parse an external subset.
11969
 *
11970
 * Returns the resulting xmlDtdPtr or NULL in case of error.
11971
 */
11972
11973
xmlDtdPtr
11974
0
xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
11975
0
    return(xmlSAXParseDTD(NULL, ExternalID, SystemID));
11976
0
}
11977
#endif /* LIBXML_VALID_ENABLED */
11978
11979
/************************************************************************
11980
 *                  *
11981
 *    Front ends when parsing an Entity     *
11982
 *                  *
11983
 ************************************************************************/
11984
11985
static xmlNodePtr
11986
xmlCtxtParseContent(xmlParserCtxtPtr ctxt, xmlParserInputPtr input,
11987
716
                    int hasTextDecl, int buildTree) {
11988
716
    xmlNodePtr root = NULL;
11989
716
    xmlNodePtr list = NULL;
11990
716
    xmlChar *rootName = BAD_CAST "#root";
11991
716
    int result;
11992
11993
716
    if (buildTree) {
11994
716
        root = xmlNewDocNode(ctxt->myDoc, NULL, rootName, NULL);
11995
716
        if (root == NULL) {
11996
0
            xmlErrMemory(ctxt);
11997
0
            goto error;
11998
0
        }
11999
716
    }
12000
12001
716
    if (xmlPushInput(ctxt, input) < 0)
12002
0
        goto error;
12003
12004
716
    nameNsPush(ctxt, rootName, NULL, NULL, 0, 0);
12005
716
    spacePush(ctxt, -1);
12006
12007
716
    if (buildTree)
12008
716
        nodePush(ctxt, root);
12009
12010
716
    if (hasTextDecl) {
12011
0
        xmlDetectEncoding(ctxt);
12012
12013
        /*
12014
         * Parse a possible text declaration first
12015
         */
12016
0
        if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) &&
12017
0
            (IS_BLANK_CH(NXT(5)))) {
12018
0
            xmlParseTextDecl(ctxt);
12019
            /*
12020
             * An XML-1.0 document can't reference an entity not XML-1.0
12021
             */
12022
0
            if ((xmlStrEqual(ctxt->version, BAD_CAST "1.0")) &&
12023
0
                (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) {
12024
0
                xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH,
12025
0
                               "Version mismatch between document and "
12026
0
                               "entity\n");
12027
0
            }
12028
0
        }
12029
0
    }
12030
12031
716
    xmlParseContentInternal(ctxt);
12032
12033
716
    if (ctxt->input->cur < ctxt->input->end)
12034
50
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
12035
12036
716
    if ((ctxt->wellFormed) ||
12037
716
        ((ctxt->recovery) && (ctxt->errNo != XML_ERR_NO_MEMORY))) {
12038
535
        if (root != NULL) {
12039
535
            xmlNodePtr cur;
12040
12041
            /*
12042
             * Return the newly created nodeset after unlinking it from
12043
             * its pseudo parent.
12044
             */
12045
535
            cur = root->children;
12046
535
            list = cur;
12047
1.34k
            while (cur != NULL) {
12048
814
                cur->parent = NULL;
12049
814
                cur = cur->next;
12050
814
            }
12051
535
            root->children = NULL;
12052
535
            root->last = NULL;
12053
535
        }
12054
535
    }
12055
12056
    /*
12057
     * Read the rest of the stream in case of errors. We want
12058
     * to account for the whole entity size.
12059
     */
12060
718
    do {
12061
718
        ctxt->input->cur = ctxt->input->end;
12062
718
        xmlParserShrink(ctxt);
12063
718
        result = xmlParserGrow(ctxt);
12064
718
    } while (result > 0);
12065
12066
716
    if (buildTree)
12067
716
        nodePop(ctxt);
12068
12069
716
    namePop(ctxt);
12070
716
    spacePop(ctxt);
12071
12072
    /* xmlPopInput would free the stream */
12073
716
    inputPop(ctxt);
12074
12075
716
error:
12076
716
    xmlFreeNode(root);
12077
12078
716
    return(list);
12079
716
}
12080
12081
static void
12082
730
xmlCtxtParseEntity(xmlParserCtxtPtr ctxt, xmlEntityPtr ent) {
12083
730
    xmlParserInputPtr input;
12084
730
    xmlNodePtr list;
12085
730
    unsigned long consumed;
12086
730
    int isExternal;
12087
730
    int buildTree;
12088
730
    int oldMinNsIndex;
12089
730
    int oldNodelen, oldNodemem;
12090
12091
730
    isExternal = (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY);
12092
730
    buildTree = (ctxt->node != NULL);
12093
12094
    /*
12095
     * Recursion check
12096
     */
12097
730
    if (ent->flags & XML_ENT_EXPANDING) {
12098
14
        xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
12099
14
        xmlHaltParser(ctxt);
12100
14
        goto error;
12101
14
    }
12102
12103
    /*
12104
     * Load entity
12105
     */
12106
716
    input = xmlNewEntityInputStream(ctxt, ent);
12107
716
    if (input == NULL)
12108
0
        goto error;
12109
12110
    /*
12111
     * When building a tree, we need to limit the scope of namespace
12112
     * declarations, so that entities don't reference xmlNs structs
12113
     * from the parent of a reference.
12114
     */
12115
716
    oldMinNsIndex = ctxt->nsdb->minNsIndex;
12116
716
    if (buildTree)
12117
716
        ctxt->nsdb->minNsIndex = ctxt->nsNr;
12118
12119
716
    oldNodelen = ctxt->nodelen;
12120
716
    oldNodemem = ctxt->nodemem;
12121
716
    ctxt->nodelen = 0;
12122
716
    ctxt->nodemem = 0;
12123
12124
    /*
12125
     * Parse content
12126
     *
12127
     * This initiates a recursive call chain:
12128
     *
12129
     * - xmlCtxtParseContent
12130
     * - xmlParseContentInternal
12131
     * - xmlParseReference
12132
     * - xmlCtxtParseEntity
12133
     *
12134
     * The nesting depth is limited by the maximum number of inputs,
12135
     * see xmlPushInput.
12136
     *
12137
     * It's possible to make this non-recursive (minNsIndex must be
12138
     * stored in the input struct) at the expense of code readability.
12139
     */
12140
12141
716
    ent->flags |= XML_ENT_EXPANDING;
12142
12143
716
    list = xmlCtxtParseContent(ctxt, input, isExternal, buildTree);
12144
12145
716
    ent->flags &= ~XML_ENT_EXPANDING;
12146
12147
716
    ctxt->nsdb->minNsIndex = oldMinNsIndex;
12148
716
    ctxt->nodelen = oldNodelen;
12149
716
    ctxt->nodemem = oldNodemem;
12150
12151
    /*
12152
     * Entity size accounting
12153
     */
12154
716
    consumed = input->consumed;
12155
716
    xmlSaturatedAddSizeT(&consumed, input->end - input->base);
12156
12157
716
    if ((ent->flags & XML_ENT_CHECKED) == 0)
12158
360
        xmlSaturatedAdd(&ent->expandedSize, consumed);
12159
12160
716
    if ((ent->flags & XML_ENT_PARSED) == 0) {
12161
360
        if (isExternal)
12162
0
            xmlSaturatedAdd(&ctxt->sizeentities, consumed);
12163
12164
360
        ent->children = list;
12165
12166
1.17k
        while (list != NULL) {
12167
810
            list->parent = (xmlNodePtr) ent;
12168
810
            if (list->next == NULL)
12169
153
                ent->last = list;
12170
810
            list = list->next;
12171
810
        }
12172
360
    } else {
12173
356
        xmlFreeNodeList(list);
12174
356
    }
12175
12176
716
    xmlFreeInputStream(input);
12177
12178
730
error:
12179
730
    ent->flags |= XML_ENT_PARSED | XML_ENT_CHECKED;
12180
730
}
12181
12182
/**
12183
 * xmlParseCtxtExternalEntity:
12184
 * @ctx:  the existing parsing context
12185
 * @URL:  the URL for the entity to load
12186
 * @ID:  the System ID for the entity to load
12187
 * @lst:  the return value for the set of parsed nodes
12188
 *
12189
 * Parse an external general entity within an existing parsing context
12190
 * An external general parsed entity is well-formed if it matches the
12191
 * production labeled extParsedEnt.
12192
 *
12193
 * [78] extParsedEnt ::= TextDecl? content
12194
 *
12195
 * Returns 0 if the entity is well formed, -1 in case of args problem and
12196
 *    the parser error code otherwise
12197
 */
12198
12199
int
12200
xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctxt, const xmlChar *URL,
12201
0
                           const xmlChar *ID, xmlNodePtr *listOut) {
12202
0
    xmlParserInputPtr input;
12203
0
    xmlNodePtr list;
12204
12205
0
    if (listOut != NULL)
12206
0
        *listOut = NULL;
12207
12208
0
    if (ctxt == NULL)
12209
0
        return(XML_ERR_ARGUMENT);
12210
12211
0
    input = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
12212
0
    if (input == NULL)
12213
0
        return(ctxt->errNo);
12214
12215
0
    xmlCtxtInitializeLate(ctxt);
12216
12217
0
    list = xmlCtxtParseContent(ctxt, input, /* hasTextDecl */ 1, 1);
12218
0
    if (*listOut != NULL)
12219
0
        *listOut = list;
12220
0
    else
12221
0
        xmlFreeNodeList(list);
12222
12223
0
    xmlFreeInputStream(input);
12224
0
    return(ctxt->errNo);
12225
0
}
12226
12227
#ifdef LIBXML_SAX1_ENABLED
12228
/**
12229
 * xmlParseExternalEntity:
12230
 * @doc:  the document the chunk pertains to
12231
 * @sax:  the SAX handler block (possibly NULL)
12232
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
12233
 * @depth:  Used for loop detection, use 0
12234
 * @URL:  the URL for the entity to load
12235
 * @ID:  the System ID for the entity to load
12236
 * @lst:  the return value for the set of parsed nodes
12237
 *
12238
 * Parse an external general entity
12239
 * An external general parsed entity is well-formed if it matches the
12240
 * production labeled extParsedEnt.
12241
 *
12242
 * [78] extParsedEnt ::= TextDecl? content
12243
 *
12244
 * Returns 0 if the entity is well formed, -1 in case of args problem and
12245
 *    the parser error code otherwise
12246
 */
12247
12248
int
12249
xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data,
12250
0
    int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *list) {
12251
0
    xmlParserCtxtPtr ctxt;
12252
0
    int ret;
12253
12254
0
    if (list != NULL)
12255
0
        *list = NULL;
12256
12257
0
    if (doc == NULL)
12258
0
        return(XML_ERR_ARGUMENT);
12259
12260
0
    ctxt = xmlNewSAXParserCtxt(sax, user_data);
12261
0
    if (ctxt == NULL)
12262
0
        return(XML_ERR_NO_MEMORY);
12263
12264
0
    ctxt->depth = depth;
12265
0
    ctxt->myDoc = doc;
12266
0
    ret = xmlParseCtxtExternalEntity(ctxt, URL, ID, list);
12267
12268
0
    xmlFreeParserCtxt(ctxt);
12269
0
    return(ret);
12270
0
}
12271
12272
/**
12273
 * xmlParseBalancedChunkMemory:
12274
 * @doc:  the document the chunk pertains to (must not be NULL)
12275
 * @sax:  the SAX handler block (possibly NULL)
12276
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
12277
 * @depth:  Used for loop detection, use 0
12278
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
12279
 * @lst:  the return value for the set of parsed nodes
12280
 *
12281
 * Parse a well-balanced chunk of an XML document
12282
 * called by the parser
12283
 * The allowed sequence for the Well Balanced Chunk is the one defined by
12284
 * the content production in the XML grammar:
12285
 *
12286
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
12287
 *
12288
 * Returns 0 if the chunk is well balanced, -1 in case of args problem and
12289
 *    the parser error code otherwise
12290
 */
12291
12292
int
12293
xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax,
12294
0
     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst) {
12295
0
    return xmlParseBalancedChunkMemoryRecover( doc, sax, user_data,
12296
0
                                                depth, string, lst, 0 );
12297
0
}
12298
#endif /* LIBXML_SAX1_ENABLED */
12299
12300
/**
12301
 * xmlParseInNodeContext:
12302
 * @node:  the context node
12303
 * @data:  the input string
12304
 * @datalen:  the input string length in bytes
12305
 * @options:  a combination of xmlParserOption
12306
 * @lst:  the return value for the set of parsed nodes
12307
 *
12308
 * Parse a well-balanced chunk of an XML document
12309
 * within the context (DTD, namespaces, etc ...) of the given node.
12310
 *
12311
 * The allowed sequence for the data is a Well Balanced Chunk defined by
12312
 * the content production in the XML grammar:
12313
 *
12314
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
12315
 *
12316
 * Returns XML_ERR_OK if the chunk is well balanced, and the parser
12317
 * error code otherwise
12318
 */
12319
xmlParserErrors
12320
xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
12321
0
                      int options, xmlNodePtr *lst) {
12322
0
    xmlParserCtxtPtr ctxt;
12323
0
    xmlDocPtr doc = NULL;
12324
0
    xmlNodePtr fake, cur;
12325
0
    int nsnr = 0;
12326
12327
0
    xmlParserErrors ret = XML_ERR_OK;
12328
12329
    /*
12330
     * check all input parameters, grab the document
12331
     */
12332
0
    if ((lst == NULL) || (node == NULL) || (data == NULL) || (datalen < 0))
12333
0
        return(XML_ERR_ARGUMENT);
12334
0
    switch (node->type) {
12335
0
        case XML_ELEMENT_NODE:
12336
0
        case XML_ATTRIBUTE_NODE:
12337
0
        case XML_TEXT_NODE:
12338
0
        case XML_CDATA_SECTION_NODE:
12339
0
        case XML_ENTITY_REF_NODE:
12340
0
        case XML_PI_NODE:
12341
0
        case XML_COMMENT_NODE:
12342
0
        case XML_DOCUMENT_NODE:
12343
0
        case XML_HTML_DOCUMENT_NODE:
12344
0
      break;
12345
0
  default:
12346
0
      return(XML_ERR_INTERNAL_ERROR);
12347
12348
0
    }
12349
0
    while ((node != NULL) && (node->type != XML_ELEMENT_NODE) &&
12350
0
           (node->type != XML_DOCUMENT_NODE) &&
12351
0
     (node->type != XML_HTML_DOCUMENT_NODE))
12352
0
  node = node->parent;
12353
0
    if (node == NULL)
12354
0
  return(XML_ERR_INTERNAL_ERROR);
12355
0
    if (node->type == XML_ELEMENT_NODE)
12356
0
  doc = node->doc;
12357
0
    else
12358
0
        doc = (xmlDocPtr) node;
12359
0
    if (doc == NULL)
12360
0
  return(XML_ERR_INTERNAL_ERROR);
12361
12362
    /*
12363
     * allocate a context and set-up everything not related to the
12364
     * node position in the tree
12365
     */
12366
0
    if (doc->type == XML_DOCUMENT_NODE)
12367
0
  ctxt = xmlCreateMemoryParserCtxt((char *) data, datalen);
12368
0
#ifdef LIBXML_HTML_ENABLED
12369
0
    else if (doc->type == XML_HTML_DOCUMENT_NODE) {
12370
0
  ctxt = htmlCreateMemoryParserCtxt((char *) data, datalen);
12371
        /*
12372
         * When parsing in context, it makes no sense to add implied
12373
         * elements like html/body/etc...
12374
         */
12375
0
        options |= HTML_PARSE_NOIMPLIED;
12376
0
    }
12377
0
#endif
12378
0
    else
12379
0
        return(XML_ERR_INTERNAL_ERROR);
12380
12381
0
    if (ctxt == NULL)
12382
0
        return(XML_ERR_NO_MEMORY);
12383
12384
    /*
12385
     * Use input doc's dict if present, else assure XML_PARSE_NODICT is set.
12386
     * We need a dictionary for xmlCtxtInitializeLate, so if there's no doc dict
12387
     * we must wait until the last moment to free the original one.
12388
     */
12389
0
    if (doc->dict != NULL) {
12390
0
        if (ctxt->dict != NULL)
12391
0
      xmlDictFree(ctxt->dict);
12392
0
  ctxt->dict = doc->dict;
12393
0
    } else {
12394
0
        options |= XML_PARSE_NODICT;
12395
0
        ctxt->dictNames = 0;
12396
0
    }
12397
12398
0
    if (doc->encoding != NULL)
12399
0
        xmlSwitchEncodingName(ctxt, (const char *) doc->encoding);
12400
12401
0
    xmlCtxtUseOptions(ctxt, options);
12402
0
    xmlCtxtInitializeLate(ctxt);
12403
0
    ctxt->myDoc = doc;
12404
    /* parsing in context, i.e. as within existing content */
12405
0
    ctxt->input_id = 2;
12406
12407
    /*
12408
     * TODO: Use xmlCtxtParseContent
12409
     */
12410
12411
0
    fake = xmlNewDocComment(node->doc, NULL);
12412
0
    if (fake == NULL) {
12413
0
        xmlFreeParserCtxt(ctxt);
12414
0
  return(XML_ERR_NO_MEMORY);
12415
0
    }
12416
0
    xmlAddChild(node, fake);
12417
12418
0
    if (node->type == XML_ELEMENT_NODE)
12419
0
  nodePush(ctxt, node);
12420
12421
0
    if ((ctxt->html == 0) && (node->type == XML_ELEMENT_NODE)) {
12422
  /*
12423
   * initialize the SAX2 namespaces stack
12424
   */
12425
0
  cur = node;
12426
0
  while ((cur != NULL) && (cur->type == XML_ELEMENT_NODE)) {
12427
0
      xmlNsPtr ns = cur->nsDef;
12428
0
            xmlHashedString hprefix, huri;
12429
12430
0
      while (ns != NULL) {
12431
0
                hprefix = xmlDictLookupHashed(ctxt->dict, ns->prefix, -1);
12432
0
                huri = xmlDictLookupHashed(ctxt->dict, ns->href, -1);
12433
0
                if (xmlParserNsPush(ctxt, &hprefix, &huri, ns, 1) > 0)
12434
0
                    nsnr++;
12435
0
    ns = ns->next;
12436
0
      }
12437
0
      cur = cur->parent;
12438
0
  }
12439
0
    }
12440
12441
0
    if ((ctxt->validate) || (ctxt->replaceEntities != 0)) {
12442
  /*
12443
   * ID/IDREF registration will be done in xmlValidateElement below
12444
   */
12445
0
  ctxt->loadsubset |= XML_SKIP_IDS;
12446
0
    }
12447
12448
0
#ifdef LIBXML_HTML_ENABLED
12449
0
    if (doc->type == XML_HTML_DOCUMENT_NODE)
12450
0
        __htmlParseContent(ctxt);
12451
0
    else
12452
0
#endif
12453
0
  xmlParseContentInternal(ctxt);
12454
12455
0
    if (ctxt->input->cur < ctxt->input->end)
12456
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
12457
12458
0
    xmlParserNsPop(ctxt, nsnr);
12459
12460
0
    if ((ctxt->wellFormed) ||
12461
0
        ((ctxt->recovery) && (ctxt->errNo != XML_ERR_NO_MEMORY))) {
12462
0
        ret = XML_ERR_OK;
12463
0
    } else {
12464
0
  ret = (xmlParserErrors) ctxt->errNo;
12465
0
    }
12466
12467
    /*
12468
     * Return the newly created nodeset after unlinking it from
12469
     * the pseudo sibling.
12470
     */
12471
12472
0
    cur = fake->next;
12473
0
    fake->next = NULL;
12474
0
    node->last = fake;
12475
12476
0
    if (cur != NULL) {
12477
0
  cur->prev = NULL;
12478
0
    }
12479
12480
0
    *lst = cur;
12481
12482
0
    while (cur != NULL) {
12483
0
  cur->parent = NULL;
12484
0
  cur = cur->next;
12485
0
    }
12486
12487
0
    xmlUnlinkNode(fake);
12488
0
    xmlFreeNode(fake);
12489
12490
12491
0
    if (ret != XML_ERR_OK) {
12492
0
        xmlFreeNodeList(*lst);
12493
0
  *lst = NULL;
12494
0
    }
12495
12496
0
    if (doc->dict != NULL)
12497
0
        ctxt->dict = NULL;
12498
0
    xmlFreeParserCtxt(ctxt);
12499
12500
0
    return(ret);
12501
0
}
12502
12503
#ifdef LIBXML_SAX1_ENABLED
12504
/**
12505
 * xmlParseBalancedChunkMemoryRecover:
12506
 * @doc:  the document the chunk pertains to (must not be NULL)
12507
 * @sax:  the SAX handler block (possibly NULL)
12508
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
12509
 * @depth:  Used for loop detection, use 0
12510
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
12511
 * @list:  the return value for the set of parsed nodes
12512
 * @recover: return nodes even if the data is broken (use 0)
12513
 *
12514
 * Parse a well-balanced chunk of an XML document
12515
 *
12516
 * The allowed sequence for the Well Balanced Chunk is the one defined by
12517
 * the content production in the XML grammar:
12518
 *
12519
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
12520
 *
12521
 * Returns 0 if the chunk is well balanced, or thehe parser error code
12522
 * otherwise.
12523
 *
12524
 * In case recover is set to 1, the nodelist will not be empty even if
12525
 * the parsed chunk is not well balanced, assuming the parsing succeeded to
12526
 * some extent.
12527
 */
12528
int
12529
xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
12530
     void *user_data, int depth, const xmlChar *string, xmlNodePtr *listOut,
12531
0
     int recover) {
12532
0
    xmlParserCtxtPtr ctxt;
12533
0
    xmlParserInputPtr input;
12534
0
    xmlNodePtr list;
12535
0
    int ret;
12536
12537
0
    if (listOut != NULL)
12538
0
        *listOut = NULL;
12539
12540
0
    if (string == NULL)
12541
0
        return(XML_ERR_ARGUMENT);
12542
12543
0
    ctxt = xmlNewSAXParserCtxt(sax, user_data);
12544
0
    if (ctxt == NULL)
12545
0
        return(XML_ERR_NO_MEMORY);
12546
12547
0
    xmlCtxtInitializeLate(ctxt);
12548
12549
0
    ctxt->depth = depth;
12550
0
    ctxt->myDoc = doc;
12551
0
    if (recover) {
12552
0
        ctxt->options |= XML_PARSE_RECOVER;
12553
0
        ctxt->recovery = 1;
12554
0
    }
12555
12556
0
    input = xmlNewStringInputStream(ctxt, string);
12557
0
    if (input == NULL)
12558
0
        return(ctxt->errNo);
12559
12560
0
    list = xmlCtxtParseContent(ctxt, input, /* hasTextDecl */ 0, 1);
12561
0
    if (listOut != NULL)
12562
0
        *listOut = list;
12563
0
    else
12564
0
        xmlFreeNodeList(list);
12565
12566
0
    ret = ctxt->errNo;
12567
12568
0
    xmlFreeInputStream(input);
12569
0
    xmlFreeParserCtxt(ctxt);
12570
0
    return(ret);
12571
0
}
12572
12573
/**
12574
 * xmlSAXParseEntity:
12575
 * @sax:  the SAX handler block
12576
 * @filename:  the filename
12577
 *
12578
 * DEPRECATED: Don't use.
12579
 *
12580
 * parse an XML external entity out of context and build a tree.
12581
 * It use the given SAX function block to handle the parsing callback.
12582
 * If sax is NULL, fallback to the default DOM tree building routines.
12583
 *
12584
 * [78] extParsedEnt ::= TextDecl? content
12585
 *
12586
 * This correspond to a "Well Balanced" chunk
12587
 *
12588
 * Returns the resulting document tree
12589
 */
12590
12591
xmlDocPtr
12592
0
xmlSAXParseEntity(xmlSAXHandlerPtr sax, const char *filename) {
12593
0
    xmlDocPtr ret;
12594
0
    xmlParserCtxtPtr ctxt;
12595
12596
0
    ctxt = xmlCreateFileParserCtxt(filename);
12597
0
    if (ctxt == NULL) {
12598
0
  return(NULL);
12599
0
    }
12600
0
    if (sax != NULL) {
12601
0
        if (sax->initialized == XML_SAX2_MAGIC) {
12602
0
            *ctxt->sax = *sax;
12603
0
        } else {
12604
0
            memset(ctxt->sax, 0, sizeof(*ctxt->sax));
12605
0
            memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
12606
0
        }
12607
0
        ctxt->userData = NULL;
12608
0
    }
12609
12610
0
    xmlParseExtParsedEnt(ctxt);
12611
12612
0
    if (ctxt->wellFormed) {
12613
0
  ret = ctxt->myDoc;
12614
0
    } else {
12615
0
        ret = NULL;
12616
0
        xmlFreeDoc(ctxt->myDoc);
12617
0
    }
12618
12619
0
    xmlFreeParserCtxt(ctxt);
12620
12621
0
    return(ret);
12622
0
}
12623
12624
/**
12625
 * xmlParseEntity:
12626
 * @filename:  the filename
12627
 *
12628
 * parse an XML external entity out of context and build a tree.
12629
 *
12630
 * [78] extParsedEnt ::= TextDecl? content
12631
 *
12632
 * This correspond to a "Well Balanced" chunk
12633
 *
12634
 * Returns the resulting document tree
12635
 */
12636
12637
xmlDocPtr
12638
0
xmlParseEntity(const char *filename) {
12639
0
    return(xmlSAXParseEntity(NULL, filename));
12640
0
}
12641
#endif /* LIBXML_SAX1_ENABLED */
12642
12643
/**
12644
 * xmlCreateEntityParserCtxt:
12645
 * @URL:  the entity URL
12646
 * @ID:  the entity PUBLIC ID
12647
 * @base:  a possible base for the target URI
12648
 *
12649
 * DEPRECATED: Use xmlNewInputURL.
12650
 *
12651
 * Create a parser context for an external entity
12652
 * Automatic support for ZLIB/Compress compressed document is provided
12653
 * by default if found at compile-time.
12654
 *
12655
 * Returns the new parser context or NULL
12656
 */
12657
xmlParserCtxtPtr
12658
xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID,
12659
0
                    const xmlChar *base) {
12660
0
    xmlParserCtxtPtr ctxt;
12661
0
    xmlParserInputPtr input;
12662
0
    xmlChar *uri = NULL;
12663
12664
0
    ctxt = xmlNewParserCtxt();
12665
0
    if (ctxt == NULL)
12666
0
  return(NULL);
12667
12668
0
    if (base != NULL) {
12669
0
        if (xmlBuildURISafe(URL, base, &uri) < 0)
12670
0
            goto error;
12671
0
        if (uri != NULL)
12672
0
            URL = uri;
12673
0
    }
12674
12675
0
    input = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
12676
0
    if (input == NULL)
12677
0
        goto error;
12678
12679
0
    if (inputPush(ctxt, input) < 0)
12680
0
        goto error;
12681
12682
0
    xmlFree(uri);
12683
0
    return(ctxt);
12684
12685
0
error:
12686
0
    xmlFree(uri);
12687
0
    xmlFreeParserCtxt(ctxt);
12688
0
    return(NULL);
12689
0
}
12690
12691
/************************************************************************
12692
 *                  *
12693
 *    Front ends when parsing from a file     *
12694
 *                  *
12695
 ************************************************************************/
12696
12697
/**
12698
 * xmlCreateURLParserCtxt:
12699
 * @filename:  the filename or URL
12700
 * @options:  a combination of xmlParserOption
12701
 *
12702
 * DEPRECATED: Use xmlNewParserCtxt and xmlCtxtReadFile.
12703
 *
12704
 * Create a parser context for a file or URL content.
12705
 * Automatic support for ZLIB/Compress compressed document is provided
12706
 * by default if found at compile-time and for file accesses
12707
 *
12708
 * Returns the new parser context or NULL
12709
 */
12710
xmlParserCtxtPtr
12711
xmlCreateURLParserCtxt(const char *filename, int options)
12712
0
{
12713
0
    xmlParserCtxtPtr ctxt;
12714
0
    xmlParserInputPtr input;
12715
12716
0
    ctxt = xmlNewParserCtxt();
12717
0
    if (ctxt == NULL)
12718
0
  return(NULL);
12719
12720
0
    xmlCtxtUseOptions(ctxt, options);
12721
0
    ctxt->linenumbers = 1;
12722
12723
0
    input = xmlLoadExternalEntity(filename, NULL, ctxt);
12724
0
    if (input == NULL) {
12725
0
  xmlFreeParserCtxt(ctxt);
12726
0
  return(NULL);
12727
0
    }
12728
0
    inputPush(ctxt, input);
12729
12730
0
    return(ctxt);
12731
0
}
12732
12733
/**
12734
 * xmlCreateFileParserCtxt:
12735
 * @filename:  the filename
12736
 *
12737
 * DEPRECATED: Use xmlNewParserCtxt and xmlCtxtReadFile.
12738
 *
12739
 * Create a parser context for a file content.
12740
 * Automatic support for ZLIB/Compress compressed document is provided
12741
 * by default if found at compile-time.
12742
 *
12743
 * Returns the new parser context or NULL
12744
 */
12745
xmlParserCtxtPtr
12746
xmlCreateFileParserCtxt(const char *filename)
12747
0
{
12748
0
    return(xmlCreateURLParserCtxt(filename, 0));
12749
0
}
12750
12751
#ifdef LIBXML_SAX1_ENABLED
12752
/**
12753
 * xmlSAXParseFileWithData:
12754
 * @sax:  the SAX handler block
12755
 * @filename:  the filename
12756
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
12757
 *             documents
12758
 * @data:  the userdata
12759
 *
12760
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadFile.
12761
 *
12762
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
12763
 * compressed document is provided by default if found at compile-time.
12764
 * It use the given SAX function block to handle the parsing callback.
12765
 * If sax is NULL, fallback to the default DOM tree building routines.
12766
 *
12767
 * User data (void *) is stored within the parser context in the
12768
 * context's _private member, so it is available nearly everywhere in libxml
12769
 *
12770
 * Returns the resulting document tree
12771
 */
12772
12773
xmlDocPtr
12774
xmlSAXParseFileWithData(xmlSAXHandlerPtr sax, const char *filename,
12775
0
                        int recovery, void *data) {
12776
0
    xmlDocPtr ret;
12777
0
    xmlParserCtxtPtr ctxt;
12778
0
    xmlParserInputPtr input;
12779
12780
0
    ctxt = xmlNewSAXParserCtxt(sax, NULL);
12781
0
    if (ctxt == NULL)
12782
0
  return(NULL);
12783
12784
0
    if (data != NULL)
12785
0
  ctxt->_private = data;
12786
12787
0
    if (recovery) {
12788
0
        ctxt->options |= XML_PARSE_RECOVER;
12789
0
        ctxt->recovery = 1;
12790
0
    }
12791
12792
0
    input = xmlNewInputURL(ctxt, filename, NULL, NULL, 0);
12793
12794
0
    ret = xmlCtxtParseDocument(ctxt, input);
12795
12796
0
    xmlFreeParserCtxt(ctxt);
12797
0
    return(ret);
12798
0
}
12799
12800
/**
12801
 * xmlSAXParseFile:
12802
 * @sax:  the SAX handler block
12803
 * @filename:  the filename
12804
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
12805
 *             documents
12806
 *
12807
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadFile.
12808
 *
12809
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
12810
 * compressed document is provided by default if found at compile-time.
12811
 * It use the given SAX function block to handle the parsing callback.
12812
 * If sax is NULL, fallback to the default DOM tree building routines.
12813
 *
12814
 * Returns the resulting document tree
12815
 */
12816
12817
xmlDocPtr
12818
xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
12819
0
                          int recovery) {
12820
0
    return(xmlSAXParseFileWithData(sax,filename,recovery,NULL));
12821
0
}
12822
12823
/**
12824
 * xmlRecoverDoc:
12825
 * @cur:  a pointer to an array of xmlChar
12826
 *
12827
 * DEPRECATED: Use xmlReadDoc with XML_PARSE_RECOVER.
12828
 *
12829
 * parse an XML in-memory document and build a tree.
12830
 * In the case the document is not Well Formed, a attempt to build a
12831
 * tree is tried anyway
12832
 *
12833
 * Returns the resulting document tree or NULL in case of failure
12834
 */
12835
12836
xmlDocPtr
12837
0
xmlRecoverDoc(const xmlChar *cur) {
12838
0
    return(xmlSAXParseDoc(NULL, cur, 1));
12839
0
}
12840
12841
/**
12842
 * xmlParseFile:
12843
 * @filename:  the filename
12844
 *
12845
 * DEPRECATED: Use xmlReadFile.
12846
 *
12847
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
12848
 * compressed document is provided by default if found at compile-time.
12849
 *
12850
 * Returns the resulting document tree if the file was wellformed,
12851
 * NULL otherwise.
12852
 */
12853
12854
xmlDocPtr
12855
0
xmlParseFile(const char *filename) {
12856
0
    return(xmlSAXParseFile(NULL, filename, 0));
12857
0
}
12858
12859
/**
12860
 * xmlRecoverFile:
12861
 * @filename:  the filename
12862
 *
12863
 * DEPRECATED: Use xmlReadFile with XML_PARSE_RECOVER.
12864
 *
12865
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
12866
 * compressed document is provided by default if found at compile-time.
12867
 * In the case the document is not Well Formed, it attempts to build
12868
 * a tree anyway
12869
 *
12870
 * Returns the resulting document tree or NULL in case of failure
12871
 */
12872
12873
xmlDocPtr
12874
0
xmlRecoverFile(const char *filename) {
12875
0
    return(xmlSAXParseFile(NULL, filename, 1));
12876
0
}
12877
12878
12879
/**
12880
 * xmlSetupParserForBuffer:
12881
 * @ctxt:  an XML parser context
12882
 * @buffer:  a xmlChar * buffer
12883
 * @filename:  a file name
12884
 *
12885
 * DEPRECATED: Don't use.
12886
 *
12887
 * Setup the parser context to parse a new buffer; Clears any prior
12888
 * contents from the parser context. The buffer parameter must not be
12889
 * NULL, but the filename parameter can be
12890
 */
12891
void
12892
xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
12893
                             const char* filename)
12894
0
{
12895
0
    xmlParserInputPtr input;
12896
12897
0
    if ((ctxt == NULL) || (buffer == NULL))
12898
0
        return;
12899
12900
0
    xmlClearParserCtxt(ctxt);
12901
12902
0
    input = xmlNewInputString(ctxt, filename, (const char *) buffer, NULL, 0);
12903
0
    if (input == NULL)
12904
0
        return;
12905
0
    inputPush(ctxt, input);
12906
0
}
12907
12908
/**
12909
 * xmlSAXUserParseFile:
12910
 * @sax:  a SAX handler
12911
 * @user_data:  The user data returned on SAX callbacks
12912
 * @filename:  a file name
12913
 *
12914
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadFile.
12915
 *
12916
 * parse an XML file and call the given SAX handler routines.
12917
 * Automatic support for ZLIB/Compress compressed document is provided
12918
 *
12919
 * Returns 0 in case of success or a error number otherwise
12920
 */
12921
int
12922
xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
12923
0
                    const char *filename) {
12924
0
    int ret = 0;
12925
0
    xmlParserCtxtPtr ctxt;
12926
12927
0
    ctxt = xmlCreateFileParserCtxt(filename);
12928
0
    if (ctxt == NULL) return -1;
12929
0
    if (sax != NULL) {
12930
0
        if (sax->initialized == XML_SAX2_MAGIC) {
12931
0
            *ctxt->sax = *sax;
12932
0
        } else {
12933
0
            memset(ctxt->sax, 0, sizeof(*ctxt->sax));
12934
0
            memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
12935
0
        }
12936
0
  ctxt->userData = user_data;
12937
0
    }
12938
12939
0
    xmlParseDocument(ctxt);
12940
12941
0
    if (ctxt->wellFormed)
12942
0
  ret = 0;
12943
0
    else {
12944
0
        if (ctxt->errNo != 0)
12945
0
      ret = ctxt->errNo;
12946
0
  else
12947
0
      ret = -1;
12948
0
    }
12949
0
    if (ctxt->myDoc != NULL) {
12950
0
        xmlFreeDoc(ctxt->myDoc);
12951
0
  ctxt->myDoc = NULL;
12952
0
    }
12953
0
    xmlFreeParserCtxt(ctxt);
12954
12955
0
    return ret;
12956
0
}
12957
#endif /* LIBXML_SAX1_ENABLED */
12958
12959
/************************************************************************
12960
 *                  *
12961
 *    Front ends when parsing from memory     *
12962
 *                  *
12963
 ************************************************************************/
12964
12965
/**
12966
 * xmlCreateMemoryParserCtxt:
12967
 * @buffer:  a pointer to a char array
12968
 * @size:  the size of the array
12969
 *
12970
 * Create a parser context for an XML in-memory document. The input buffer
12971
 * must not contain a terminating null byte.
12972
 *
12973
 * Returns the new parser context or NULL
12974
 */
12975
xmlParserCtxtPtr
12976
0
xmlCreateMemoryParserCtxt(const char *buffer, int size) {
12977
0
    xmlParserCtxtPtr ctxt;
12978
0
    xmlParserInputPtr input;
12979
12980
0
    if (size < 0)
12981
0
  return(NULL);
12982
12983
0
    ctxt = xmlNewParserCtxt();
12984
0
    if (ctxt == NULL)
12985
0
  return(NULL);
12986
12987
0
    input = xmlNewInputMemory(ctxt, NULL, buffer, size, NULL, 0);
12988
0
    if (input == NULL) {
12989
0
  xmlFreeParserCtxt(ctxt);
12990
0
  return(NULL);
12991
0
    }
12992
0
    inputPush(ctxt, input);
12993
12994
0
    return(ctxt);
12995
0
}
12996
12997
#ifdef LIBXML_SAX1_ENABLED
12998
/**
12999
 * xmlSAXParseMemoryWithData:
13000
 * @sax:  the SAX handler block
13001
 * @buffer:  an pointer to a char array
13002
 * @size:  the size of the array
13003
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
13004
 *             documents
13005
 * @data:  the userdata
13006
 *
13007
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadMemory.
13008
 *
13009
 * parse an XML in-memory block and use the given SAX function block
13010
 * to handle the parsing callback. If sax is NULL, fallback to the default
13011
 * DOM tree building routines.
13012
 *
13013
 * User data (void *) is stored within the parser context in the
13014
 * context's _private member, so it is available nearly everywhere in libxml
13015
 *
13016
 * Returns the resulting document tree
13017
 */
13018
13019
xmlDocPtr
13020
xmlSAXParseMemoryWithData(xmlSAXHandlerPtr sax, const char *buffer,
13021
0
                          int size, int recovery, void *data) {
13022
0
    xmlDocPtr ret;
13023
0
    xmlParserCtxtPtr ctxt;
13024
0
    xmlParserInputPtr input;
13025
13026
0
    if (size < 0)
13027
0
        return(NULL);
13028
13029
0
    ctxt = xmlNewSAXParserCtxt(sax, NULL);
13030
0
    if (ctxt == NULL)
13031
0
        return(NULL);
13032
13033
0
    if (data != NULL)
13034
0
  ctxt->_private=data;
13035
13036
0
    if (recovery) {
13037
0
        ctxt->options |= XML_PARSE_RECOVER;
13038
0
        ctxt->recovery = 1;
13039
0
    }
13040
13041
0
    input = xmlNewInputMemory(ctxt, NULL, buffer, size, NULL,
13042
0
                              XML_INPUT_BUF_STATIC);
13043
13044
0
    ret = xmlCtxtParseDocument(ctxt, input);
13045
13046
0
    xmlFreeParserCtxt(ctxt);
13047
0
    return(ret);
13048
0
}
13049
13050
/**
13051
 * xmlSAXParseMemory:
13052
 * @sax:  the SAX handler block
13053
 * @buffer:  an pointer to a char array
13054
 * @size:  the size of the array
13055
 * @recovery:  work in recovery mode, i.e. tries to read not Well Formed
13056
 *             documents
13057
 *
13058
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadMemory.
13059
 *
13060
 * parse an XML in-memory block and use the given SAX function block
13061
 * to handle the parsing callback. If sax is NULL, fallback to the default
13062
 * DOM tree building routines.
13063
 *
13064
 * Returns the resulting document tree
13065
 */
13066
xmlDocPtr
13067
xmlSAXParseMemory(xmlSAXHandlerPtr sax, const char *buffer,
13068
0
            int size, int recovery) {
13069
0
    return xmlSAXParseMemoryWithData(sax, buffer, size, recovery, NULL);
13070
0
}
13071
13072
/**
13073
 * xmlParseMemory:
13074
 * @buffer:  an pointer to a char array
13075
 * @size:  the size of the array
13076
 *
13077
 * DEPRECATED: Use xmlReadMemory.
13078
 *
13079
 * parse an XML in-memory block and build a tree.
13080
 *
13081
 * Returns the resulting document tree
13082
 */
13083
13084
0
xmlDocPtr xmlParseMemory(const char *buffer, int size) {
13085
0
   return(xmlSAXParseMemory(NULL, buffer, size, 0));
13086
0
}
13087
13088
/**
13089
 * xmlRecoverMemory:
13090
 * @buffer:  an pointer to a char array
13091
 * @size:  the size of the array
13092
 *
13093
 * DEPRECATED: Use xmlReadMemory with XML_PARSE_RECOVER.
13094
 *
13095
 * parse an XML in-memory block and build a tree.
13096
 * In the case the document is not Well Formed, an attempt to
13097
 * build a tree is tried anyway
13098
 *
13099
 * Returns the resulting document tree or NULL in case of error
13100
 */
13101
13102
0
xmlDocPtr xmlRecoverMemory(const char *buffer, int size) {
13103
0
   return(xmlSAXParseMemory(NULL, buffer, size, 1));
13104
0
}
13105
13106
/**
13107
 * xmlSAXUserParseMemory:
13108
 * @sax:  a SAX handler
13109
 * @user_data:  The user data returned on SAX callbacks
13110
 * @buffer:  an in-memory XML document input
13111
 * @size:  the length of the XML document in bytes
13112
 *
13113
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadMemory.
13114
 *
13115
 * parse an XML in-memory buffer and call the given SAX handler routines.
13116
 *
13117
 * Returns 0 in case of success or a error number otherwise
13118
 */
13119
int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
13120
0
        const char *buffer, int size) {
13121
0
    int ret = 0;
13122
0
    xmlParserCtxtPtr ctxt;
13123
13124
0
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
13125
0
    if (ctxt == NULL) return -1;
13126
0
    if (sax != NULL) {
13127
0
        if (sax->initialized == XML_SAX2_MAGIC) {
13128
0
            *ctxt->sax = *sax;
13129
0
        } else {
13130
0
            memset(ctxt->sax, 0, sizeof(*ctxt->sax));
13131
0
            memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
13132
0
        }
13133
0
  ctxt->userData = user_data;
13134
0
    }
13135
13136
0
    xmlParseDocument(ctxt);
13137
13138
0
    if (ctxt->wellFormed)
13139
0
  ret = 0;
13140
0
    else {
13141
0
        if (ctxt->errNo != 0)
13142
0
      ret = ctxt->errNo;
13143
0
  else
13144
0
      ret = -1;
13145
0
    }
13146
0
    if (ctxt->myDoc != NULL) {
13147
0
        xmlFreeDoc(ctxt->myDoc);
13148
0
  ctxt->myDoc = NULL;
13149
0
    }
13150
0
    xmlFreeParserCtxt(ctxt);
13151
13152
0
    return ret;
13153
0
}
13154
#endif /* LIBXML_SAX1_ENABLED */
13155
13156
/**
13157
 * xmlCreateDocParserCtxt:
13158
 * @str:  a pointer to an array of xmlChar
13159
 *
13160
 * Creates a parser context for an XML in-memory document.
13161
 *
13162
 * Returns the new parser context or NULL
13163
 */
13164
xmlParserCtxtPtr
13165
0
xmlCreateDocParserCtxt(const xmlChar *str) {
13166
0
    xmlParserCtxtPtr ctxt;
13167
0
    xmlParserInputPtr input;
13168
13169
0
    ctxt = xmlNewParserCtxt();
13170
0
    if (ctxt == NULL)
13171
0
  return(NULL);
13172
13173
0
    input = xmlNewInputString(ctxt, NULL, (const char *) str, NULL, 0);
13174
0
    if (input == NULL) {
13175
0
  xmlFreeParserCtxt(ctxt);
13176
0
  return(NULL);
13177
0
    }
13178
0
    inputPush(ctxt, input);
13179
13180
0
    return(ctxt);
13181
0
}
13182
13183
#ifdef LIBXML_SAX1_ENABLED
13184
/**
13185
 * xmlSAXParseDoc:
13186
 * @sax:  the SAX handler block
13187
 * @cur:  a pointer to an array of xmlChar
13188
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
13189
 *             documents
13190
 *
13191
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadDoc.
13192
 *
13193
 * parse an XML in-memory document and build a tree.
13194
 * It use the given SAX function block to handle the parsing callback.
13195
 * If sax is NULL, fallback to the default DOM tree building routines.
13196
 *
13197
 * Returns the resulting document tree
13198
 */
13199
13200
xmlDocPtr
13201
0
xmlSAXParseDoc(xmlSAXHandlerPtr sax, const xmlChar *cur, int recovery) {
13202
0
    xmlDocPtr ret;
13203
0
    xmlParserCtxtPtr ctxt;
13204
0
    xmlSAXHandlerPtr oldsax = NULL;
13205
13206
0
    if (cur == NULL) return(NULL);
13207
13208
13209
0
    ctxt = xmlCreateDocParserCtxt(cur);
13210
0
    if (ctxt == NULL) return(NULL);
13211
0
    if (sax != NULL) {
13212
0
        oldsax = ctxt->sax;
13213
0
        ctxt->sax = sax;
13214
0
        ctxt->userData = NULL;
13215
0
    }
13216
13217
0
    xmlParseDocument(ctxt);
13218
0
    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
13219
0
    else {
13220
0
       ret = NULL;
13221
0
       xmlFreeDoc(ctxt->myDoc);
13222
0
       ctxt->myDoc = NULL;
13223
0
    }
13224
0
    if (sax != NULL)
13225
0
  ctxt->sax = oldsax;
13226
0
    xmlFreeParserCtxt(ctxt);
13227
13228
0
    return(ret);
13229
0
}
13230
13231
/**
13232
 * xmlParseDoc:
13233
 * @cur:  a pointer to an array of xmlChar
13234
 *
13235
 * DEPRECATED: Use xmlReadDoc.
13236
 *
13237
 * parse an XML in-memory document and build a tree.
13238
 *
13239
 * Returns the resulting document tree
13240
 */
13241
13242
xmlDocPtr
13243
0
xmlParseDoc(const xmlChar *cur) {
13244
0
    return(xmlSAXParseDoc(NULL, cur, 0));
13245
0
}
13246
#endif /* LIBXML_SAX1_ENABLED */
13247
13248
/************************************************************************
13249
 *                  *
13250
 *  New set (2.6.0) of simpler and more flexible APIs   *
13251
 *                  *
13252
 ************************************************************************/
13253
13254
/**
13255
 * DICT_FREE:
13256
 * @str:  a string
13257
 *
13258
 * Free a string if it is not owned by the "dict" dictionary in the
13259
 * current scope
13260
 */
13261
#define DICT_FREE(str)            \
13262
0
  if ((str) && ((!dict) ||       \
13263
0
      (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))  \
13264
0
      xmlFree((char *)(str));
13265
13266
/**
13267
 * xmlCtxtReset:
13268
 * @ctxt: an XML parser context
13269
 *
13270
 * Reset a parser context
13271
 */
13272
void
13273
xmlCtxtReset(xmlParserCtxtPtr ctxt)
13274
0
{
13275
0
    xmlParserInputPtr input;
13276
0
    xmlDictPtr dict;
13277
13278
0
    if (ctxt == NULL)
13279
0
        return;
13280
13281
0
    dict = ctxt->dict;
13282
13283
0
    while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
13284
0
        xmlFreeInputStream(input);
13285
0
    }
13286
0
    ctxt->inputNr = 0;
13287
0
    ctxt->input = NULL;
13288
13289
0
    ctxt->spaceNr = 0;
13290
0
    if (ctxt->spaceTab != NULL) {
13291
0
  ctxt->spaceTab[0] = -1;
13292
0
  ctxt->space = &ctxt->spaceTab[0];
13293
0
    } else {
13294
0
        ctxt->space = NULL;
13295
0
    }
13296
13297
13298
0
    ctxt->nodeNr = 0;
13299
0
    ctxt->node = NULL;
13300
13301
0
    ctxt->nameNr = 0;
13302
0
    ctxt->name = NULL;
13303
13304
0
    ctxt->nsNr = 0;
13305
0
    xmlParserNsReset(ctxt->nsdb);
13306
13307
0
    DICT_FREE(ctxt->version);
13308
0
    ctxt->version = NULL;
13309
0
    DICT_FREE(ctxt->encoding);
13310
0
    ctxt->encoding = NULL;
13311
0
    DICT_FREE(ctxt->extSubURI);
13312
0
    ctxt->extSubURI = NULL;
13313
0
    DICT_FREE(ctxt->extSubSystem);
13314
0
    ctxt->extSubSystem = NULL;
13315
0
    if (ctxt->myDoc != NULL)
13316
0
        xmlFreeDoc(ctxt->myDoc);
13317
0
    ctxt->myDoc = NULL;
13318
13319
0
    ctxt->standalone = -1;
13320
0
    ctxt->hasExternalSubset = 0;
13321
0
    ctxt->hasPErefs = 0;
13322
0
    ctxt->html = 0;
13323
0
    ctxt->instate = XML_PARSER_START;
13324
13325
0
    ctxt->wellFormed = 1;
13326
0
    ctxt->nsWellFormed = 1;
13327
0
    ctxt->disableSAX = 0;
13328
0
    ctxt->valid = 1;
13329
#if 0
13330
    ctxt->vctxt.userData = ctxt;
13331
    ctxt->vctxt.error = xmlParserValidityError;
13332
    ctxt->vctxt.warning = xmlParserValidityWarning;
13333
#endif
13334
0
    ctxt->record_info = 0;
13335
0
    ctxt->checkIndex = 0;
13336
0
    ctxt->endCheckState = 0;
13337
0
    ctxt->inSubset = 0;
13338
0
    ctxt->errNo = XML_ERR_OK;
13339
0
    ctxt->depth = 0;
13340
0
    ctxt->catalogs = NULL;
13341
0
    ctxt->sizeentities = 0;
13342
0
    ctxt->sizeentcopy = 0;
13343
0
    xmlInitNodeInfoSeq(&ctxt->node_seq);
13344
13345
0
    if (ctxt->attsDefault != NULL) {
13346
0
        xmlHashFree(ctxt->attsDefault, xmlHashDefaultDeallocator);
13347
0
        ctxt->attsDefault = NULL;
13348
0
    }
13349
0
    if (ctxt->attsSpecial != NULL) {
13350
0
        xmlHashFree(ctxt->attsSpecial, NULL);
13351
0
        ctxt->attsSpecial = NULL;
13352
0
    }
13353
13354
0
#ifdef LIBXML_CATALOG_ENABLED
13355
0
    if (ctxt->catalogs != NULL)
13356
0
  xmlCatalogFreeLocal(ctxt->catalogs);
13357
0
#endif
13358
0
    ctxt->nbErrors = 0;
13359
0
    ctxt->nbWarnings = 0;
13360
0
    if (ctxt->lastError.code != XML_ERR_OK)
13361
0
        xmlResetError(&ctxt->lastError);
13362
0
}
13363
13364
/**
13365
 * xmlCtxtResetPush:
13366
 * @ctxt: an XML parser context
13367
 * @chunk:  a pointer to an array of chars
13368
 * @size:  number of chars in the array
13369
 * @filename:  an optional file name or URI
13370
 * @encoding:  the document encoding, or NULL
13371
 *
13372
 * Reset a push parser context
13373
 *
13374
 * Returns 0 in case of success and 1 in case of error
13375
 */
13376
int
13377
xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk,
13378
                 int size, const char *filename, const char *encoding)
13379
0
{
13380
0
    xmlParserInputPtr input;
13381
13382
0
    if (ctxt == NULL)
13383
0
        return(1);
13384
13385
0
    xmlCtxtReset(ctxt);
13386
13387
0
    input = xmlNewInputPush(ctxt, filename, chunk, size, encoding);
13388
0
    if (input == NULL)
13389
0
        return(1);
13390
0
    inputPush(ctxt, input);
13391
13392
0
    return(0);
13393
0
}
13394
13395
static int
13396
xmlCtxtSetOptionsInternal(xmlParserCtxtPtr ctxt, int options, int keepMask)
13397
22.1k
{
13398
22.1k
    int allMask;
13399
13400
22.1k
    if (ctxt == NULL)
13401
0
        return(-1);
13402
13403
    /*
13404
     * XInclude options aren't handled by the parser.
13405
     *
13406
     * XML_PARSE_XINCLUDE
13407
     * XML_PARSE_NOXINCNODE
13408
     * XML_PARSE_NOBASEFIX
13409
     */
13410
22.1k
    allMask = XML_PARSE_RECOVER |
13411
22.1k
              XML_PARSE_NOENT |
13412
22.1k
              XML_PARSE_DTDLOAD |
13413
22.1k
              XML_PARSE_DTDATTR |
13414
22.1k
              XML_PARSE_DTDVALID |
13415
22.1k
              XML_PARSE_NOERROR |
13416
22.1k
              XML_PARSE_NOWARNING |
13417
22.1k
              XML_PARSE_PEDANTIC |
13418
22.1k
              XML_PARSE_NOBLANKS |
13419
22.1k
#ifdef LIBXML_SAX1_ENABLED
13420
22.1k
              XML_PARSE_SAX1 |
13421
22.1k
#endif
13422
22.1k
              XML_PARSE_NONET |
13423
22.1k
              XML_PARSE_NODICT |
13424
22.1k
              XML_PARSE_NSCLEAN |
13425
22.1k
              XML_PARSE_NOCDATA |
13426
22.1k
              XML_PARSE_COMPACT |
13427
22.1k
              XML_PARSE_OLD10 |
13428
22.1k
              XML_PARSE_HUGE |
13429
22.1k
              XML_PARSE_OLDSAX |
13430
22.1k
              XML_PARSE_IGNORE_ENC |
13431
22.1k
              XML_PARSE_BIG_LINES |
13432
22.1k
              XML_PARSE_NO_XXE;
13433
13434
22.1k
    ctxt->options = (ctxt->options & keepMask) | (options & allMask);
13435
13436
    /*
13437
     * For some options, struct members are historically the source
13438
     * of truth. The values are initalized from global variables and
13439
     * old code could also modify them directly. Several older API
13440
     * functions that don't take an options argument rely on these
13441
     * deprecated mechanisms.
13442
     *
13443
     * Once public access to struct members and the globals are
13444
     * disabled, we can use the options bitmask as source of
13445
     * truth, making all these struct members obsolete.
13446
     *
13447
     * The XML_DETECT_IDS flags is misnamed. It simply enables
13448
     * loading of the external subset.
13449
     */
13450
22.1k
    ctxt->recovery = (options & XML_PARSE_RECOVER) ? 1 : 0;
13451
22.1k
    ctxt->replaceEntities = (options & XML_PARSE_NOENT) ? 1 : 0;
13452
22.1k
    ctxt->loadsubset = (options & XML_PARSE_DTDLOAD) ? XML_DETECT_IDS : 0;
13453
22.1k
    ctxt->loadsubset |= (options & XML_PARSE_DTDATTR) ? XML_COMPLETE_ATTRS : 0;
13454
22.1k
    ctxt->validate = (options & XML_PARSE_DTDVALID) ? 1 : 0;
13455
22.1k
    ctxt->pedantic = (options & XML_PARSE_PEDANTIC) ? 1 : 0;
13456
22.1k
    ctxt->keepBlanks = (options & XML_PARSE_NOBLANKS) ? 0 : 1;
13457
22.1k
    ctxt->dictNames = (options & XML_PARSE_NODICT) ? 0 : 1;
13458
13459
    /*
13460
     * Changing SAX callbacks is a bad idea. This should be fixed.
13461
     */
13462
22.1k
    if (options & XML_PARSE_NOBLANKS) {
13463
3.63k
        ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
13464
3.63k
    }
13465
22.1k
    if (options & XML_PARSE_NOCDATA) {
13466
477
        ctxt->sax->cdataBlock = NULL;
13467
477
    }
13468
22.1k
    if (options & XML_PARSE_HUGE) {
13469
0
        if (ctxt->dict != NULL)
13470
0
            xmlDictSetLimit(ctxt->dict, 0);
13471
0
    }
13472
13473
22.1k
    ctxt->linenumbers = 1;
13474
13475
22.1k
    return(options & ~allMask);
13476
22.1k
}
13477
13478
/**
13479
 * xmlCtxtSetOptions:
13480
 * @ctxt: an XML parser context
13481
 * @options:  a bitmask of xmlParserOption values
13482
 *
13483
 * Applies the options to the parser context. Unset options are
13484
 * cleared.
13485
 *
13486
 * Available since 2.13.0. With older versions, you can use
13487
 * xmlCtxtUseOptions.
13488
 *
13489
 * XML_PARSE_RECOVER
13490
 *
13491
 * Enable "recovery" mode which allows non-wellformed documents.
13492
 * How this mode behaves exactly is unspecified and may change
13493
 * without further notice. Use of this feature is DISCOURAGED.
13494
 *
13495
 * XML_PARSE_NOENT
13496
 *
13497
 * Despite the confusing name, this option enables substitution
13498
 * of entities. The resulting tree won't contain any entity
13499
 * reference nodes.
13500
 *
13501
 * This option also enables loading of external entities (both
13502
 * general and parameter entities) which is dangerous. If you
13503
 * process untrusted data, it's recommended to set the
13504
 * XML_PARSE_NO_XXE option to disable loading of external
13505
 * entities.
13506
 *
13507
 * XML_PARSE_DTDLOAD
13508
 *
13509
 * Enables loading of an external DTD and the loading and
13510
 * substitution of external parameter entities. Has no effect
13511
 * if XML_PARSE_NO_XXE is set.
13512
 *
13513
 * XML_PARSE_DTDATTR
13514
 *
13515
 * Adds default attributes from the DTD to the result document.
13516
 *
13517
 * Implies XML_PARSE_DTDLOAD, but loading of external content
13518
 * can be disabled with XML_PARSE_NO_XXE.
13519
 *
13520
 * XML_PARSE_DTDVALID
13521
 *
13522
 * This option enables DTD validation which requires to load
13523
 * external DTDs and external entities (both general and
13524
 * parameter entities) unless XML_PARSE_NO_XXE was set.
13525
 *
13526
 * XML_PARSE_NO_XXE
13527
 *
13528
 * Disables loading of external DTDs or entities.
13529
 *
13530
 * XML_PARSE_NOERROR
13531
 *
13532
 * Disable error and warning reports to the error handlers.
13533
 * Errors are still accessible with xmlCtxtGetLastError.
13534
 *
13535
 * XML_PARSE_NOWARNING
13536
 *
13537
 * Disable warning reports.
13538
 *
13539
 * XML_PARSE_PEDANTIC
13540
 *
13541
 * Enable some pedantic warnings.
13542
 *
13543
 * XML_PARSE_NOBLANKS
13544
 *
13545
 * Remove some text nodes containing only whitespace from the
13546
 * result document. Which nodes are removed depends on DTD
13547
 * element declarations or a conservative heuristic. The
13548
 * reindenting feature of the serialization code relies on this
13549
 * option to be set when parsing. Use of this option is
13550
 * DISCOURAGED.
13551
 *
13552
 * XML_PARSE_SAX1
13553
 *
13554
 * Always invoke the deprecated SAX1 startElement and endElement
13555
 * handlers. This option is DEPRECATED.
13556
 *
13557
 * XML_PARSE_NONET
13558
 *
13559
 * Disable network access with the builtin HTTP and FTP clients.
13560
 *
13561
 * XML_PARSE_NODICT
13562
 *
13563
 * Create a document without interned strings, making all
13564
 * strings separate memory allocations.
13565
 *
13566
 * XML_PARSE_NSCLEAN
13567
 *
13568
 * Remove redundant namespace declarations from the result
13569
 * document.
13570
 *
13571
 * XML_PARSE_NOCDATA
13572
 *
13573
 * Output normal text nodes instead of CDATA nodes.
13574
 *
13575
 * XML_PARSE_COMPACT
13576
 *
13577
 * Store small strings directly in the node struct to save
13578
 * memory.
13579
 *
13580
 * XML_PARSE_OLD10
13581
 *
13582
 * Use old Name productions from before XML 1.0 Fifth Edition.
13583
 * This options is DEPRECATED.
13584
 *
13585
 * XML_PARSE_HUGE
13586
 *
13587
 * Relax some internal limits.
13588
 *
13589
 * Maximum size of text nodes, tags, comments, processing instructions,
13590
 * CDATA sections, entity values
13591
 *
13592
 * normal: 10M
13593
 * huge:    1B
13594
 *
13595
 * Maximum size of names, system literals, pubid literals
13596
 *
13597
 * normal: 50K
13598
 * huge:   10M
13599
 *
13600
 * Maximum nesting depth of elements
13601
 *
13602
 * normal:  256
13603
 * huge:   2048
13604
 *
13605
 * Maximum nesting depth of entities
13606
 *
13607
 * normal: 20
13608
 * huge:   40
13609
 *
13610
 * XML_PARSE_OLDSAX
13611
 *
13612
 * Enable an unspecified legacy mode for SAX parsers. This
13613
 * option is DEPRECATED.
13614
 *
13615
 * XML_PARSE_IGNORE_ENC
13616
 *
13617
 * Ignore the encoding in the XML declaration. This option is
13618
 * mostly unneeded these days. The only effect is to enforce
13619
 * UTF-8 decoding of ASCII-like data.
13620
 *
13621
 * XML_PARSE_BIG_LINES
13622
 *
13623
 * Enable reporting of line numbers larger than 65535.
13624
 *
13625
 * Returns 0 in case of success, the set of unknown or unimplemented options
13626
 *         in case of error.
13627
 */
13628
int
13629
xmlCtxtSetOptions(xmlParserCtxtPtr ctxt, int options)
13630
0
{
13631
0
    return(xmlCtxtSetOptionsInternal(ctxt, options, 0));
13632
0
}
13633
13634
/**
13635
 * xmlCtxtUseOptions:
13636
 * @ctxt: an XML parser context
13637
 * @options:  a combination of xmlParserOption
13638
 *
13639
 * DEPRECATED: Use xmlCtxtSetOptions.
13640
 *
13641
 * Applies the options to the parser context. The following options
13642
 * are never cleared and can only be enabled:
13643
 *
13644
 * XML_PARSE_NOERROR
13645
 * XML_PARSE_NOWARNING
13646
 * XML_PARSE_NONET
13647
 * XML_PARSE_NSCLEAN
13648
 * XML_PARSE_NOCDATA
13649
 * XML_PARSE_COMPACT
13650
 * XML_PARSE_OLD10
13651
 * XML_PARSE_HUGE
13652
 * XML_PARSE_OLDSAX
13653
 * XML_PARSE_IGNORE_ENC
13654
 * XML_PARSE_BIG_LINES
13655
 *
13656
 * Returns 0 in case of success, the set of unknown or unimplemented options
13657
 *         in case of error.
13658
 */
13659
int
13660
xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options)
13661
22.1k
{
13662
22.1k
    int keepMask;
13663
13664
    /*
13665
     * For historic reasons, some options can only be enabled.
13666
     */
13667
22.1k
    keepMask = XML_PARSE_NOERROR |
13668
22.1k
               XML_PARSE_NOWARNING |
13669
22.1k
               XML_PARSE_NONET |
13670
22.1k
               XML_PARSE_NSCLEAN |
13671
22.1k
               XML_PARSE_NOCDATA |
13672
22.1k
               XML_PARSE_COMPACT |
13673
22.1k
               XML_PARSE_OLD10 |
13674
22.1k
               XML_PARSE_HUGE |
13675
22.1k
               XML_PARSE_OLDSAX |
13676
22.1k
               XML_PARSE_IGNORE_ENC |
13677
22.1k
               XML_PARSE_BIG_LINES;
13678
13679
22.1k
    return(xmlCtxtSetOptionsInternal(ctxt, options, keepMask));
13680
22.1k
}
13681
13682
/**
13683
 * xmlCtxtSetMaxAmplification:
13684
 * @ctxt: an XML parser context
13685
 * @maxAmpl:  maximum amplification factor
13686
 *
13687
 * To protect against exponential entity expansion ("billion laughs"), the
13688
 * size of serialized output is (roughly) limited to the input size
13689
 * multiplied by this factor. The default value is 5.
13690
 *
13691
 * When working with documents making heavy use of entity expansion, it can
13692
 * be necessary to increase the value. For security reasons, this should only
13693
 * be considered when processing trusted input.
13694
 */
13695
void
13696
xmlCtxtSetMaxAmplification(xmlParserCtxtPtr ctxt, unsigned maxAmpl)
13697
0
{
13698
0
    ctxt->maxAmpl = maxAmpl;
13699
0
}
13700
13701
/**
13702
 * xmlCtxtParseDocument:
13703
 * @ctxt:  an XML parser context
13704
 * @input:  parser input
13705
 *
13706
 * Parse an XML document and return the resulting document tree.
13707
 * Takes ownership of the input object.
13708
 *
13709
 * Returns the resulting document tree or NULL
13710
 */
13711
xmlDocPtr
13712
xmlCtxtParseDocument(xmlParserCtxtPtr ctxt, xmlParserInputPtr input)
13713
22.1k
{
13714
22.1k
    xmlDocPtr ret = NULL;
13715
13716
22.1k
    if ((ctxt == NULL) || (input == NULL))
13717
0
        return(NULL);
13718
13719
    /* assert(ctxt->inputNr == 0); */
13720
22.1k
    while (ctxt->inputNr > 0)
13721
0
        xmlFreeInputStream(inputPop(ctxt));
13722
13723
22.1k
    if (inputPush(ctxt, input) < 0) {
13724
0
        xmlFreeInputStream(input);
13725
0
        return(NULL);
13726
0
    }
13727
13728
22.1k
    xmlParseDocument(ctxt);
13729
13730
22.1k
    if ((ctxt->wellFormed) ||
13731
22.1k
        ((ctxt->recovery) && (ctxt->errNo != XML_ERR_NO_MEMORY))) {
13732
10.7k
        ret = ctxt->myDoc;
13733
11.4k
    } else {
13734
11.4k
        if (ctxt->errNo == XML_ERR_OK)
13735
0
            xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR, "unknown error\n");
13736
13737
11.4k
        ret = NULL;
13738
11.4k
  xmlFreeDoc(ctxt->myDoc);
13739
11.4k
    }
13740
22.1k
    ctxt->myDoc = NULL;
13741
13742
    /* assert(ctxt->inputNr == 1); */
13743
44.3k
    while (ctxt->inputNr > 0)
13744
22.1k
        xmlFreeInputStream(inputPop(ctxt));
13745
13746
22.1k
    return(ret);
13747
22.1k
}
13748
13749
/**
13750
 * xmlReadDoc:
13751
 * @cur:  a pointer to a zero terminated string
13752
 * @URL:  base URL (optional)
13753
 * @encoding:  the document encoding (optional)
13754
 * @options:  a combination of xmlParserOption
13755
 *
13756
 * Convenience function to parse an XML document from a
13757
 * zero-terminated string.
13758
 *
13759
 * See xmlCtxtReadDoc for details.
13760
 *
13761
 * Returns the resulting document tree
13762
 */
13763
xmlDocPtr
13764
xmlReadDoc(const xmlChar *cur, const char *URL, const char *encoding,
13765
           int options)
13766
0
{
13767
0
    xmlParserCtxtPtr ctxt;
13768
0
    xmlParserInputPtr input;
13769
0
    xmlDocPtr doc;
13770
13771
0
    ctxt = xmlNewParserCtxt();
13772
0
    if (ctxt == NULL)
13773
0
        return(NULL);
13774
13775
0
    xmlCtxtUseOptions(ctxt, options);
13776
13777
0
    input = xmlNewInputString(ctxt, URL, (const char *) cur, encoding,
13778
0
                              XML_INPUT_BUF_STATIC);
13779
13780
0
    doc = xmlCtxtParseDocument(ctxt, input);
13781
13782
0
    xmlFreeParserCtxt(ctxt);
13783
0
    return(doc);
13784
0
}
13785
13786
/**
13787
 * xmlReadFile:
13788
 * @filename:  a file or URL
13789
 * @encoding:  the document encoding (optional)
13790
 * @options:  a combination of xmlParserOption
13791
 *
13792
 * Convenience function to parse an XML file from the filesystem,
13793
 * the network or a global user-define resource loader.
13794
 *
13795
 * See xmlCtxtReadFile for details.
13796
 *
13797
 * Returns the resulting document tree
13798
 */
13799
xmlDocPtr
13800
xmlReadFile(const char *filename, const char *encoding, int options)
13801
0
{
13802
0
    xmlParserCtxtPtr ctxt;
13803
0
    xmlParserInputPtr input;
13804
0
    xmlDocPtr doc;
13805
13806
0
    ctxt = xmlNewParserCtxt();
13807
0
    if (ctxt == NULL)
13808
0
        return(NULL);
13809
13810
0
    xmlCtxtUseOptions(ctxt, options);
13811
13812
0
    input = xmlNewInputURL(ctxt, filename, NULL, encoding, 0);
13813
13814
0
    doc = xmlCtxtParseDocument(ctxt, input);
13815
13816
0
    xmlFreeParserCtxt(ctxt);
13817
0
    return(doc);
13818
0
}
13819
13820
/**
13821
 * xmlReadMemory:
13822
 * @buffer:  a pointer to a char array
13823
 * @size:  the size of the array
13824
 * @url:  base URL (optional)
13825
 * @encoding:  the document encoding (optional)
13826
 * @options:  a combination of xmlParserOption
13827
 *
13828
 * Parse an XML in-memory document and build a tree. The input buffer must
13829
 * not contain a terminating null byte.
13830
 *
13831
 * See xmlCtxtReadMemory for details.
13832
 *
13833
 * Returns the resulting document tree
13834
 */
13835
xmlDocPtr
13836
xmlReadMemory(const char *buffer, int size, const char *url,
13837
              const char *encoding, int options)
13838
22.1k
{
13839
22.1k
    xmlParserCtxtPtr ctxt;
13840
22.1k
    xmlParserInputPtr input;
13841
22.1k
    xmlDocPtr doc;
13842
13843
22.1k
    if (size < 0)
13844
0
  return(NULL);
13845
13846
22.1k
    ctxt = xmlNewParserCtxt();
13847
22.1k
    if (ctxt == NULL)
13848
0
        return(NULL);
13849
13850
22.1k
    xmlCtxtUseOptions(ctxt, options);
13851
13852
22.1k
    input = xmlNewInputMemory(ctxt, url, buffer, size, encoding,
13853
22.1k
                              XML_INPUT_BUF_STATIC);
13854
13855
22.1k
    doc = xmlCtxtParseDocument(ctxt, input);
13856
13857
22.1k
    xmlFreeParserCtxt(ctxt);
13858
22.1k
    return(doc);
13859
22.1k
}
13860
13861
/**
13862
 * xmlReadFd:
13863
 * @fd:  an open file descriptor
13864
 * @URL:  base URL (optional)
13865
 * @encoding:  the document encoding (optional)
13866
 * @options:  a combination of xmlParserOption
13867
 *
13868
 * Parse an XML from a file descriptor and build a tree.
13869
 *
13870
 * See xmlCtxtReadFd for details.
13871
 *
13872
 * NOTE that the file descriptor will not be closed when the
13873
 * context is freed or reset.
13874
 *
13875
 * Returns the resulting document tree
13876
 */
13877
xmlDocPtr
13878
xmlReadFd(int fd, const char *URL, const char *encoding, int options)
13879
0
{
13880
0
    xmlParserCtxtPtr ctxt;
13881
0
    xmlParserInputPtr input;
13882
0
    xmlDocPtr doc;
13883
13884
0
    ctxt = xmlNewParserCtxt();
13885
0
    if (ctxt == NULL)
13886
0
        return(NULL);
13887
13888
0
    xmlCtxtUseOptions(ctxt, options);
13889
13890
0
    input = xmlNewInputFd(ctxt, URL, fd, encoding, 0);
13891
0
    input->buf->closecallback = NULL;
13892
13893
0
    doc = xmlCtxtParseDocument(ctxt, input);
13894
13895
0
    xmlFreeParserCtxt(ctxt);
13896
0
    return(doc);
13897
0
}
13898
13899
/**
13900
 * xmlReadIO:
13901
 * @ioread:  an I/O read function
13902
 * @ioclose:  an I/O close function (optional)
13903
 * @ioctx:  an I/O handler
13904
 * @URL:  base URL (optional)
13905
 * @encoding:  the document encoding (optional)
13906
 * @options:  a combination of xmlParserOption
13907
 *
13908
 * Parse an XML document from I/O functions and context and build a tree.
13909
 *
13910
 * See xmlCtxtReadIO for details.
13911
 *
13912
 * Returns the resulting document tree
13913
 */
13914
xmlDocPtr
13915
xmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
13916
          void *ioctx, const char *URL, const char *encoding, int options)
13917
0
{
13918
0
    xmlParserCtxtPtr ctxt;
13919
0
    xmlParserInputPtr input;
13920
0
    xmlDocPtr doc;
13921
13922
0
    ctxt = xmlNewParserCtxt();
13923
0
    if (ctxt == NULL)
13924
0
        return(NULL);
13925
13926
0
    xmlCtxtUseOptions(ctxt, options);
13927
13928
0
    input = xmlNewInputIO(ctxt, URL, ioread, ioclose, ioctx, encoding, 0);
13929
13930
0
    doc = xmlCtxtParseDocument(ctxt, input);
13931
13932
0
    xmlFreeParserCtxt(ctxt);
13933
0
    return(doc);
13934
0
}
13935
13936
/**
13937
 * xmlCtxtReadDoc:
13938
 * @ctxt:  an XML parser context
13939
 * @str:  a pointer to a zero terminated string
13940
 * @URL:  base URL (optional)
13941
 * @encoding:  the document encoding (optional)
13942
 * @options:  a combination of xmlParserOption
13943
 *
13944
 * Parse an XML in-memory document and build a tree.
13945
 *
13946
 * @URL is used as base to resolve external entities and for error
13947
 * reporting.
13948
 *
13949
 * See xmlCtxtUseOptions for details.
13950
 *
13951
 * Returns the resulting document tree
13952
 */
13953
xmlDocPtr
13954
xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar *str,
13955
               const char *URL, const char *encoding, int options)
13956
0
{
13957
0
    xmlParserInputPtr input;
13958
13959
0
    if (ctxt == NULL)
13960
0
        return(NULL);
13961
13962
0
    xmlCtxtReset(ctxt);
13963
0
    xmlCtxtUseOptions(ctxt, options);
13964
13965
0
    input = xmlNewInputString(ctxt, URL, (const char *) str, encoding,
13966
0
                              XML_INPUT_BUF_STATIC);
13967
13968
0
    return(xmlCtxtParseDocument(ctxt, input));
13969
0
}
13970
13971
/**
13972
 * xmlCtxtReadFile:
13973
 * @ctxt:  an XML parser context
13974
 * @filename:  a file or URL
13975
 * @encoding:  the document encoding (optional)
13976
 * @options:  a combination of xmlParserOption
13977
 *
13978
 * Parse an XML file from the filesystem, the network or a user-defined
13979
 * resource loader.
13980
 *
13981
 * See xmlNewInputURL and xmlCtxtUseOptions for details.
13982
 *
13983
 * Returns the resulting document tree
13984
 */
13985
xmlDocPtr
13986
xmlCtxtReadFile(xmlParserCtxtPtr ctxt, const char *filename,
13987
                const char *encoding, int options)
13988
0
{
13989
0
    xmlParserInputPtr input;
13990
13991
0
    if (ctxt == NULL)
13992
0
        return(NULL);
13993
13994
0
    xmlCtxtReset(ctxt);
13995
0
    xmlCtxtUseOptions(ctxt, options);
13996
13997
0
    input = xmlNewInputURL(ctxt, filename, NULL, encoding, 0);
13998
13999
0
    return(xmlCtxtParseDocument(ctxt, input));
14000
0
}
14001
14002
/**
14003
 * xmlCtxtReadMemory:
14004
 * @ctxt:  an XML parser context
14005
 * @buffer:  a pointer to a char array
14006
 * @size:  the size of the array
14007
 * @URL:  base URL (optional)
14008
 * @encoding:  the document encoding (optional)
14009
 * @options:  a combination of xmlParserOption
14010
 *
14011
 * Parse an XML in-memory document and build a tree. The input buffer must
14012
 * not contain a terminating null byte.
14013
 *
14014
 * @URL is used as base to resolve external entities and for error
14015
 * reporting.
14016
 *
14017
 * See xmlCtxtUseOptions for details.
14018
 *
14019
 * Returns the resulting document tree
14020
 */
14021
xmlDocPtr
14022
xmlCtxtReadMemory(xmlParserCtxtPtr ctxt, const char *buffer, int size,
14023
                  const char *URL, const char *encoding, int options)
14024
0
{
14025
0
    xmlParserInputPtr input;
14026
14027
0
    if ((ctxt == NULL) || (size < 0))
14028
0
        return(NULL);
14029
14030
0
    xmlCtxtReset(ctxt);
14031
0
    xmlCtxtUseOptions(ctxt, options);
14032
14033
0
    input = xmlNewInputMemory(ctxt, URL, buffer, size, encoding,
14034
0
                              XML_INPUT_BUF_STATIC);
14035
14036
0
    return(xmlCtxtParseDocument(ctxt, input));
14037
0
}
14038
14039
/**
14040
 * xmlCtxtReadFd:
14041
 * @ctxt:  an XML parser context
14042
 * @fd:  an open file descriptor
14043
 * @URL:  base URL (optional)
14044
 * @encoding:  the document encoding (optional)
14045
 * @options:  a combination of xmlParserOption
14046
 *
14047
 * Parse an XML document from a file descriptor and build a tree.
14048
 *
14049
 * NOTE that the file descriptor will not be closed when the
14050
 * context is freed or reset.
14051
 *
14052
 * @URL is used as base to resolve external entities and for error
14053
 * reporting.
14054
 *
14055
 * See xmlCtxtUseOptions for details.
14056
 *
14057
 * Returns the resulting document tree
14058
 */
14059
xmlDocPtr
14060
xmlCtxtReadFd(xmlParserCtxtPtr ctxt, int fd,
14061
              const char *URL, const char *encoding, int options)
14062
0
{
14063
0
    xmlParserInputPtr input;
14064
14065
0
    if (ctxt == NULL)
14066
0
        return(NULL);
14067
14068
0
    xmlCtxtReset(ctxt);
14069
0
    xmlCtxtUseOptions(ctxt, options);
14070
14071
0
    input = xmlNewInputFd(ctxt, URL, fd, encoding, 0);
14072
0
    input->buf->closecallback = NULL;
14073
14074
0
    return(xmlCtxtParseDocument(ctxt, input));
14075
0
}
14076
14077
/**
14078
 * xmlCtxtReadIO:
14079
 * @ctxt:  an XML parser context
14080
 * @ioread:  an I/O read function
14081
 * @ioclose:  an I/O close function
14082
 * @ioctx:  an I/O handler
14083
 * @URL:  the base URL to use for the document
14084
 * @encoding:  the document encoding, or NULL
14085
 * @options:  a combination of xmlParserOption
14086
 *
14087
 * parse an XML document from I/O functions and source and build a tree.
14088
 * This reuses the existing @ctxt parser context
14089
 *
14090
 * @URL is used as base to resolve external entities and for error
14091
 * reporting.
14092
 *
14093
 * See xmlCtxtUseOptions for details.
14094
 *
14095
 * Returns the resulting document tree
14096
 */
14097
xmlDocPtr
14098
xmlCtxtReadIO(xmlParserCtxtPtr ctxt, xmlInputReadCallback ioread,
14099
              xmlInputCloseCallback ioclose, void *ioctx,
14100
        const char *URL,
14101
              const char *encoding, int options)
14102
0
{
14103
0
    xmlParserInputPtr input;
14104
14105
0
    if (ctxt == NULL)
14106
0
        return(NULL);
14107
14108
0
    xmlCtxtReset(ctxt);
14109
0
    xmlCtxtUseOptions(ctxt, options);
14110
14111
0
    input = xmlNewInputIO(ctxt, URL, ioread, ioclose, ioctx, encoding, 0);
14112
14113
0
    return(xmlCtxtParseDocument(ctxt, input));
14114
0
}
14115