Coverage Report

Created: 2023-03-02 15:27

/src/libxml2/parser.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * parser.c : an XML 1.0 parser, namespaces and validity support are mostly
3
 *            implemented on top of the SAX interfaces
4
 *
5
 * References:
6
 *   The XML specification:
7
 *     http://www.w3.org/TR/REC-xml
8
 *   Original 1.0 version:
9
 *     http://www.w3.org/TR/1998/REC-xml-19980210
10
 *   XML second edition working draft
11
 *     http://www.w3.org/TR/2000/WD-xml-2e-20000814
12
 *
13
 * Okay this is a big file, the parser core is around 7000 lines, then it
14
 * is followed by the progressive parser top routines, then the various
15
 * high level APIs to call the parser and a few miscellaneous functions.
16
 * A number of helper functions and deprecated ones have been moved to
17
 * parserInternals.c to reduce this file size.
18
 * As much as possible the functions are associated with their relative
19
 * production in the XML specification. A few productions defining the
20
 * different ranges of character are actually implanted either in
21
 * parserInternals.h or parserInternals.c
22
 * The DOM tree build is realized from the default SAX callbacks in
23
 * the module SAX.c.
24
 * The routines doing the validation checks are in valid.c and called either
25
 * from the SAX callbacks or as standalone functions using a preparsed
26
 * document.
27
 *
28
 * See Copyright for the status of this software.
29
 *
30
 * daniel@veillard.com
31
 */
32
33
/* To avoid EBCDIC trouble when parsing on zOS */
34
#if defined(__MVS__)
35
#pragma convert("ISO8859-1")
36
#endif
37
38
#define IN_LIBXML
39
#include "libxml.h"
40
41
#if defined(_WIN32)
42
#define XML_DIR_SEP '\\'
43
#else
44
#define XML_DIR_SEP '/'
45
#endif
46
47
#include <stdlib.h>
48
#include <limits.h>
49
#include <string.h>
50
#include <stdarg.h>
51
#include <stddef.h>
52
#include <ctype.h>
53
#include <stdlib.h>
54
#include <libxml/xmlmemory.h>
55
#include <libxml/threads.h>
56
#include <libxml/globals.h>
57
#include <libxml/tree.h>
58
#include <libxml/parser.h>
59
#include <libxml/parserInternals.h>
60
#include <libxml/HTMLparser.h>
61
#include <libxml/valid.h>
62
#include <libxml/entities.h>
63
#include <libxml/xmlerror.h>
64
#include <libxml/encoding.h>
65
#include <libxml/xmlIO.h>
66
#include <libxml/uri.h>
67
#ifdef LIBXML_CATALOG_ENABLED
68
#include <libxml/catalog.h>
69
#endif
70
#ifdef LIBXML_SCHEMAS_ENABLED
71
#include <libxml/xmlschemastypes.h>
72
#include <libxml/relaxng.h>
73
#endif
74
#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
75
#include <libxml/xpath.h>
76
#endif
77
78
#include "private/buf.h"
79
#include "private/dict.h"
80
#include "private/enc.h"
81
#include "private/entities.h"
82
#include "private/error.h"
83
#include "private/globals.h"
84
#include "private/html.h"
85
#include "private/io.h"
86
#include "private/memory.h"
87
#include "private/parser.h"
88
#include "private/threads.h"
89
#include "private/xpath.h"
90
91
struct _xmlStartTag {
92
    const xmlChar *prefix;
93
    const xmlChar *URI;
94
    int line;
95
    int nsNr;
96
};
97
98
static xmlParserCtxtPtr
99
xmlCreateEntityParserCtxtInternal(xmlSAXHandlerPtr sax, void *userData,
100
        const xmlChar *URL, const xmlChar *ID, const xmlChar *base,
101
        xmlParserCtxtPtr pctx);
102
103
static void xmlHaltParser(xmlParserCtxtPtr ctxt);
104
105
static int
106
xmlParseElementStart(xmlParserCtxtPtr ctxt);
107
108
static void
109
xmlParseElementEnd(xmlParserCtxtPtr ctxt);
110
111
/************************************************************************
112
 *                  *
113
 *  Arbitrary limits set in the parser. See XML_PARSE_HUGE    *
114
 *                  *
115
 ************************************************************************/
116
117
0
#define XML_MAX_HUGE_LENGTH 1000000000
118
119
#define XML_PARSER_BIG_ENTITY 1000
120
#define XML_PARSER_LOT_ENTITY 5000
121
122
/*
123
 * XML_PARSER_NON_LINEAR is the threshold where the ratio of parsed entity
124
 *    replacement over the size in byte of the input indicates that you have
125
 *    and exponential behaviour. A value of 10 correspond to at least 3 entity
126
 *    replacement per byte of input.
127
 */
128
0
#define XML_PARSER_NON_LINEAR 10
129
130
0
#define XML_ENT_FIXED_COST 50
131
132
/**
133
 * xmlParserMaxDepth:
134
 *
135
 * arbitrary depth limit for the XML documents that we allow to
136
 * process. This is not a limitation of the parser but a safety
137
 * boundary feature. It can be disabled with the XML_PARSE_HUGE
138
 * parser option.
139
 */
140
unsigned int xmlParserMaxDepth = 256;
141
142
143
144
#define SAX2 1
145
22.1k
#define XML_PARSER_BIG_BUFFER_SIZE 300
146
22.1k
#define XML_PARSER_BUFFER_SIZE 100
147
3.69k
#define SAX_COMPAT_MODE BAD_CAST "SAX compatibility mode document"
148
149
/**
150
 * XML_PARSER_CHUNK_SIZE
151
 *
152
 * When calling GROW that's the minimal amount of data
153
 * the parser expected to have received. It is not a hard
154
 * limit but an optimization when reading strings like Names
155
 * It is not strictly needed as long as inputs available characters
156
 * are followed by 0, which should be provided by the I/O level
157
 */
158
0
#define XML_PARSER_CHUNK_SIZE 100
159
160
/*
161
 * List of XML prefixed PI allowed by W3C specs
162
 */
163
164
static const char* const xmlW3CPIs[] = {
165
    "xml-stylesheet",
166
    "xml-model",
167
    NULL
168
};
169
170
171
/* DEPR void xmlParserHandleReference(xmlParserCtxtPtr ctxt); */
172
static xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt,
173
                                              const xmlChar **str);
174
175
static xmlParserErrors
176
xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
177
                xmlSAXHandlerPtr sax,
178
          void *user_data, int depth, const xmlChar *URL,
179
          const xmlChar *ID, xmlNodePtr *list);
180
181
static int
182
xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options,
183
                          const char *encoding);
184
#ifdef LIBXML_LEGACY_ENABLED
185
static void
186
xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
187
                      xmlNodePtr lastNode);
188
#endif /* LIBXML_LEGACY_ENABLED */
189
190
static xmlParserErrors
191
xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
192
          const xmlChar *string, void *user_data, xmlNodePtr *lst);
193
194
static int
195
xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity);
196
197
/************************************************************************
198
 *                  *
199
 *    Some factorized error routines        *
200
 *                  *
201
 ************************************************************************/
202
203
/**
204
 * xmlErrAttributeDup:
205
 * @ctxt:  an XML parser context
206
 * @prefix:  the attribute prefix
207
 * @localname:  the attribute localname
208
 *
209
 * Handle a redefinition of attribute error
210
 */
211
static void
212
xmlErrAttributeDup(xmlParserCtxtPtr ctxt, const xmlChar * prefix,
213
                   const xmlChar * localname)
214
0
{
215
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
216
0
        (ctxt->instate == XML_PARSER_EOF))
217
0
  return;
218
0
    if (ctxt != NULL)
219
0
  ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
220
221
0
    if (prefix == NULL)
222
0
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
223
0
                        XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
224
0
                        (const char *) localname, NULL, NULL, 0, 0,
225
0
                        "Attribute %s redefined\n", localname);
226
0
    else
227
0
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
228
0
                        XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
229
0
                        (const char *) prefix, (const char *) localname,
230
0
                        NULL, 0, 0, "Attribute %s:%s redefined\n", prefix,
231
0
                        localname);
232
0
    if (ctxt != NULL) {
233
0
  ctxt->wellFormed = 0;
234
0
  if (ctxt->recovery == 0)
235
0
      ctxt->disableSAX = 1;
236
0
    }
237
0
}
238
239
/**
240
 * xmlFatalErr:
241
 * @ctxt:  an XML parser context
242
 * @error:  the error number
243
 * @extra:  extra information string
244
 *
245
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
246
 */
247
static void
248
xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
249
0
{
250
0
    const char *errmsg;
251
252
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
253
0
        (ctxt->instate == XML_PARSER_EOF))
254
0
  return;
255
0
    switch (error) {
256
0
        case XML_ERR_INVALID_HEX_CHARREF:
257
0
            errmsg = "CharRef: invalid hexadecimal value";
258
0
            break;
259
0
        case XML_ERR_INVALID_DEC_CHARREF:
260
0
            errmsg = "CharRef: invalid decimal value";
261
0
            break;
262
0
        case XML_ERR_INVALID_CHARREF:
263
0
            errmsg = "CharRef: invalid value";
264
0
            break;
265
0
        case XML_ERR_INTERNAL_ERROR:
266
0
            errmsg = "internal error";
267
0
            break;
268
0
        case XML_ERR_PEREF_AT_EOF:
269
0
            errmsg = "PEReference at end of document";
270
0
            break;
271
0
        case XML_ERR_PEREF_IN_PROLOG:
272
0
            errmsg = "PEReference in prolog";
273
0
            break;
274
0
        case XML_ERR_PEREF_IN_EPILOG:
275
0
            errmsg = "PEReference in epilog";
276
0
            break;
277
0
        case XML_ERR_PEREF_NO_NAME:
278
0
            errmsg = "PEReference: no name";
279
0
            break;
280
0
        case XML_ERR_PEREF_SEMICOL_MISSING:
281
0
            errmsg = "PEReference: expecting ';'";
282
0
            break;
283
0
        case XML_ERR_ENTITY_LOOP:
284
0
            errmsg = "Detected an entity reference loop";
285
0
            break;
286
0
        case XML_ERR_ENTITY_NOT_STARTED:
287
0
            errmsg = "EntityValue: \" or ' expected";
288
0
            break;
289
0
        case XML_ERR_ENTITY_PE_INTERNAL:
290
0
            errmsg = "PEReferences forbidden in internal subset";
291
0
            break;
292
0
        case XML_ERR_ENTITY_NOT_FINISHED:
293
0
            errmsg = "EntityValue: \" or ' expected";
294
0
            break;
295
0
        case XML_ERR_ATTRIBUTE_NOT_STARTED:
296
0
            errmsg = "AttValue: \" or ' expected";
297
0
            break;
298
0
        case XML_ERR_LT_IN_ATTRIBUTE:
299
0
            errmsg = "Unescaped '<' not allowed in attributes values";
300
0
            break;
301
0
        case XML_ERR_LITERAL_NOT_STARTED:
302
0
            errmsg = "SystemLiteral \" or ' expected";
303
0
            break;
304
0
        case XML_ERR_LITERAL_NOT_FINISHED:
305
0
            errmsg = "Unfinished System or Public ID \" or ' expected";
306
0
            break;
307
0
        case XML_ERR_MISPLACED_CDATA_END:
308
0
            errmsg = "Sequence ']]>' not allowed in content";
309
0
            break;
310
0
        case XML_ERR_URI_REQUIRED:
311
0
            errmsg = "SYSTEM or PUBLIC, the URI is missing";
312
0
            break;
313
0
        case XML_ERR_PUBID_REQUIRED:
314
0
            errmsg = "PUBLIC, the Public Identifier is missing";
315
0
            break;
316
0
        case XML_ERR_HYPHEN_IN_COMMENT:
317
0
            errmsg = "Comment must not contain '--' (double-hyphen)";
318
0
            break;
319
0
        case XML_ERR_PI_NOT_STARTED:
320
0
            errmsg = "xmlParsePI : no target name";
321
0
            break;
322
0
        case XML_ERR_RESERVED_XML_NAME:
323
0
            errmsg = "Invalid PI name";
324
0
            break;
325
0
        case XML_ERR_NOTATION_NOT_STARTED:
326
0
            errmsg = "NOTATION: Name expected here";
327
0
            break;
328
0
        case XML_ERR_NOTATION_NOT_FINISHED:
329
0
            errmsg = "'>' required to close NOTATION declaration";
330
0
            break;
331
0
        case XML_ERR_VALUE_REQUIRED:
332
0
            errmsg = "Entity value required";
333
0
            break;
334
0
        case XML_ERR_URI_FRAGMENT:
335
0
            errmsg = "Fragment not allowed";
336
0
            break;
337
0
        case XML_ERR_ATTLIST_NOT_STARTED:
338
0
            errmsg = "'(' required to start ATTLIST enumeration";
339
0
            break;
340
0
        case XML_ERR_NMTOKEN_REQUIRED:
341
0
            errmsg = "NmToken expected in ATTLIST enumeration";
342
0
            break;
343
0
        case XML_ERR_ATTLIST_NOT_FINISHED:
344
0
            errmsg = "')' required to finish ATTLIST enumeration";
345
0
            break;
346
0
        case XML_ERR_MIXED_NOT_STARTED:
347
0
            errmsg = "MixedContentDecl : '|' or ')*' expected";
348
0
            break;
349
0
        case XML_ERR_PCDATA_REQUIRED:
350
0
            errmsg = "MixedContentDecl : '#PCDATA' expected";
351
0
            break;
352
0
        case XML_ERR_ELEMCONTENT_NOT_STARTED:
353
0
            errmsg = "ContentDecl : Name or '(' expected";
354
0
            break;
355
0
        case XML_ERR_ELEMCONTENT_NOT_FINISHED:
356
0
            errmsg = "ContentDecl : ',' '|' or ')' expected";
357
0
            break;
358
0
        case XML_ERR_PEREF_IN_INT_SUBSET:
359
0
            errmsg =
360
0
                "PEReference: forbidden within markup decl in internal subset";
361
0
            break;
362
0
        case XML_ERR_GT_REQUIRED:
363
0
            errmsg = "expected '>'";
364
0
            break;
365
0
        case XML_ERR_CONDSEC_INVALID:
366
0
            errmsg = "XML conditional section '[' expected";
367
0
            break;
368
0
        case XML_ERR_EXT_SUBSET_NOT_FINISHED:
369
0
            errmsg = "Content error in the external subset";
370
0
            break;
371
0
        case XML_ERR_CONDSEC_INVALID_KEYWORD:
372
0
            errmsg =
373
0
                "conditional section INCLUDE or IGNORE keyword expected";
374
0
            break;
375
0
        case XML_ERR_CONDSEC_NOT_FINISHED:
376
0
            errmsg = "XML conditional section not closed";
377
0
            break;
378
0
        case XML_ERR_XMLDECL_NOT_STARTED:
379
0
            errmsg = "Text declaration '<?xml' required";
380
0
            break;
381
0
        case XML_ERR_XMLDECL_NOT_FINISHED:
382
0
            errmsg = "parsing XML declaration: '?>' expected";
383
0
            break;
384
0
        case XML_ERR_EXT_ENTITY_STANDALONE:
385
0
            errmsg = "external parsed entities cannot be standalone";
386
0
            break;
387
0
        case XML_ERR_ENTITYREF_SEMICOL_MISSING:
388
0
            errmsg = "EntityRef: expecting ';'";
389
0
            break;
390
0
        case XML_ERR_DOCTYPE_NOT_FINISHED:
391
0
            errmsg = "DOCTYPE improperly terminated";
392
0
            break;
393
0
        case XML_ERR_LTSLASH_REQUIRED:
394
0
            errmsg = "EndTag: '</' not found";
395
0
            break;
396
0
        case XML_ERR_EQUAL_REQUIRED:
397
0
            errmsg = "expected '='";
398
0
            break;
399
0
        case XML_ERR_STRING_NOT_CLOSED:
400
0
            errmsg = "String not closed expecting \" or '";
401
0
            break;
402
0
        case XML_ERR_STRING_NOT_STARTED:
403
0
            errmsg = "String not started expecting ' or \"";
404
0
            break;
405
0
        case XML_ERR_ENCODING_NAME:
406
0
            errmsg = "Invalid XML encoding name";
407
0
            break;
408
0
        case XML_ERR_STANDALONE_VALUE:
409
0
            errmsg = "standalone accepts only 'yes' or 'no'";
410
0
            break;
411
0
        case XML_ERR_DOCUMENT_EMPTY:
412
0
            errmsg = "Document is empty";
413
0
            break;
414
0
        case XML_ERR_DOCUMENT_END:
415
0
            errmsg = "Extra content at the end of the document";
416
0
            break;
417
0
        case XML_ERR_NOT_WELL_BALANCED:
418
0
            errmsg = "chunk is not well balanced";
419
0
            break;
420
0
        case XML_ERR_EXTRA_CONTENT:
421
0
            errmsg = "extra content at the end of well balanced chunk";
422
0
            break;
423
0
        case XML_ERR_VERSION_MISSING:
424
0
            errmsg = "Malformed declaration expecting version";
425
0
            break;
426
0
        case XML_ERR_NAME_TOO_LONG:
427
0
            errmsg = "Name too long";
428
0
            break;
429
#if 0
430
        case:
431
            errmsg = "";
432
            break;
433
#endif
434
0
        default:
435
0
            errmsg = "Unregistered error message";
436
0
    }
437
0
    if (ctxt != NULL)
438
0
  ctxt->errNo = error;
439
0
    if (info == NULL) {
440
0
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
441
0
                        XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s\n",
442
0
                        errmsg);
443
0
    } else {
444
0
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
445
0
                        XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s: %s\n",
446
0
                        errmsg, info);
447
0
    }
448
0
    if (ctxt != NULL) {
449
0
  ctxt->wellFormed = 0;
450
0
  if (ctxt->recovery == 0)
451
0
      ctxt->disableSAX = 1;
452
0
    }
453
0
}
454
455
/**
456
 * xmlFatalErrMsg:
457
 * @ctxt:  an XML parser context
458
 * @error:  the error number
459
 * @msg:  the error message
460
 *
461
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
462
 */
463
static void LIBXML_ATTR_FORMAT(3,0)
464
xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
465
               const char *msg)
466
0
{
467
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
468
0
        (ctxt->instate == XML_PARSER_EOF))
469
0
  return;
470
0
    if (ctxt != NULL)
471
0
  ctxt->errNo = error;
472
0
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
473
0
                    XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
474
0
    if (ctxt != NULL) {
475
0
  ctxt->wellFormed = 0;
476
0
  if (ctxt->recovery == 0)
477
0
      ctxt->disableSAX = 1;
478
0
    }
479
0
}
480
481
/**
482
 * xmlWarningMsg:
483
 * @ctxt:  an XML parser context
484
 * @error:  the error number
485
 * @msg:  the error message
486
 * @str1:  extra data
487
 * @str2:  extra data
488
 *
489
 * Handle a warning.
490
 */
491
static void LIBXML_ATTR_FORMAT(3,0)
492
xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
493
              const char *msg, const xmlChar *str1, const xmlChar *str2)
494
0
{
495
0
    xmlStructuredErrorFunc schannel = NULL;
496
497
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
498
0
        (ctxt->instate == XML_PARSER_EOF))
499
0
  return;
500
0
    if ((ctxt != NULL) && (ctxt->sax != NULL) &&
501
0
        (ctxt->sax->initialized == XML_SAX2_MAGIC))
502
0
        schannel = ctxt->sax->serror;
503
0
    if (ctxt != NULL) {
504
0
        __xmlRaiseError(schannel,
505
0
                    (ctxt->sax) ? ctxt->sax->warning : NULL,
506
0
                    ctxt->userData,
507
0
                    ctxt, NULL, XML_FROM_PARSER, error,
508
0
                    XML_ERR_WARNING, NULL, 0,
509
0
        (const char *) str1, (const char *) str2, NULL, 0, 0,
510
0
        msg, (const char *) str1, (const char *) str2);
511
0
    } else {
512
0
        __xmlRaiseError(schannel, NULL, NULL,
513
0
                    ctxt, NULL, XML_FROM_PARSER, error,
514
0
                    XML_ERR_WARNING, NULL, 0,
515
0
        (const char *) str1, (const char *) str2, NULL, 0, 0,
516
0
        msg, (const char *) str1, (const char *) str2);
517
0
    }
518
0
}
519
520
/**
521
 * xmlValidityError:
522
 * @ctxt:  an XML parser context
523
 * @error:  the error number
524
 * @msg:  the error message
525
 * @str1:  extra data
526
 *
527
 * Handle a validity error.
528
 */
529
static void LIBXML_ATTR_FORMAT(3,0)
530
xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error,
531
              const char *msg, const xmlChar *str1, const xmlChar *str2)
532
0
{
533
0
    xmlStructuredErrorFunc schannel = NULL;
534
535
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
536
0
        (ctxt->instate == XML_PARSER_EOF))
537
0
  return;
538
0
    if (ctxt != NULL) {
539
0
  ctxt->errNo = error;
540
0
  if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
541
0
      schannel = ctxt->sax->serror;
542
0
    }
543
0
    if (ctxt != NULL) {
544
0
        __xmlRaiseError(schannel,
545
0
                    ctxt->vctxt.error, ctxt->vctxt.userData,
546
0
                    ctxt, NULL, XML_FROM_DTD, error,
547
0
                    XML_ERR_ERROR, NULL, 0, (const char *) str1,
548
0
        (const char *) str2, NULL, 0, 0,
549
0
        msg, (const char *) str1, (const char *) str2);
550
0
  ctxt->valid = 0;
551
0
    } else {
552
0
        __xmlRaiseError(schannel, NULL, NULL,
553
0
                    ctxt, NULL, XML_FROM_DTD, error,
554
0
                    XML_ERR_ERROR, NULL, 0, (const char *) str1,
555
0
        (const char *) str2, NULL, 0, 0,
556
0
        msg, (const char *) str1, (const char *) str2);
557
0
    }
558
0
}
559
560
/**
561
 * xmlFatalErrMsgInt:
562
 * @ctxt:  an XML parser context
563
 * @error:  the error number
564
 * @msg:  the error message
565
 * @val:  an integer value
566
 *
567
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
568
 */
569
static void LIBXML_ATTR_FORMAT(3,0)
570
xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
571
                  const char *msg, int val)
572
0
{
573
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
574
0
        (ctxt->instate == XML_PARSER_EOF))
575
0
  return;
576
0
    if (ctxt != NULL)
577
0
  ctxt->errNo = error;
578
0
    __xmlRaiseError(NULL, NULL, NULL,
579
0
                    ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
580
0
                    NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
581
0
    if (ctxt != NULL) {
582
0
  ctxt->wellFormed = 0;
583
0
  if (ctxt->recovery == 0)
584
0
      ctxt->disableSAX = 1;
585
0
    }
586
0
}
587
588
/**
589
 * xmlFatalErrMsgStrIntStr:
590
 * @ctxt:  an XML parser context
591
 * @error:  the error number
592
 * @msg:  the error message
593
 * @str1:  an string info
594
 * @val:  an integer value
595
 * @str2:  an string info
596
 *
597
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
598
 */
599
static void LIBXML_ATTR_FORMAT(3,0)
600
xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
601
                  const char *msg, const xmlChar *str1, int val,
602
      const xmlChar *str2)
603
0
{
604
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
605
0
        (ctxt->instate == XML_PARSER_EOF))
606
0
  return;
607
0
    if (ctxt != NULL)
608
0
  ctxt->errNo = error;
609
0
    __xmlRaiseError(NULL, NULL, NULL,
610
0
                    ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
611
0
                    NULL, 0, (const char *) str1, (const char *) str2,
612
0
        NULL, val, 0, msg, str1, val, str2);
613
0
    if (ctxt != NULL) {
614
0
  ctxt->wellFormed = 0;
615
0
  if (ctxt->recovery == 0)
616
0
      ctxt->disableSAX = 1;
617
0
    }
618
0
}
619
620
/**
621
 * xmlFatalErrMsgStr:
622
 * @ctxt:  an XML parser context
623
 * @error:  the error number
624
 * @msg:  the error message
625
 * @val:  a string value
626
 *
627
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
628
 */
629
static void LIBXML_ATTR_FORMAT(3,0)
630
xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
631
                  const char *msg, const xmlChar * val)
632
0
{
633
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
634
0
        (ctxt->instate == XML_PARSER_EOF))
635
0
  return;
636
0
    if (ctxt != NULL)
637
0
  ctxt->errNo = error;
638
0
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
639
0
                    XML_FROM_PARSER, error, XML_ERR_FATAL,
640
0
                    NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
641
0
                    val);
642
0
    if (ctxt != NULL) {
643
0
  ctxt->wellFormed = 0;
644
0
  if (ctxt->recovery == 0)
645
0
      ctxt->disableSAX = 1;
646
0
    }
647
0
}
648
649
/**
650
 * xmlErrMsgStr:
651
 * @ctxt:  an XML parser context
652
 * @error:  the error number
653
 * @msg:  the error message
654
 * @val:  a string value
655
 *
656
 * Handle a non fatal parser error
657
 */
658
static void LIBXML_ATTR_FORMAT(3,0)
659
xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
660
                  const char *msg, const xmlChar * val)
661
0
{
662
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
663
0
        (ctxt->instate == XML_PARSER_EOF))
664
0
  return;
665
0
    if (ctxt != NULL)
666
0
  ctxt->errNo = error;
667
0
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
668
0
                    XML_FROM_PARSER, error, XML_ERR_ERROR,
669
0
                    NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
670
0
                    val);
671
0
}
672
673
/**
674
 * xmlNsErr:
675
 * @ctxt:  an XML parser context
676
 * @error:  the error number
677
 * @msg:  the message
678
 * @info1:  extra information string
679
 * @info2:  extra information string
680
 *
681
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
682
 */
683
static void LIBXML_ATTR_FORMAT(3,0)
684
xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
685
         const char *msg,
686
         const xmlChar * info1, const xmlChar * info2,
687
         const xmlChar * info3)
688
0
{
689
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
690
0
        (ctxt->instate == XML_PARSER_EOF))
691
0
  return;
692
0
    if (ctxt != NULL)
693
0
  ctxt->errNo = error;
694
0
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
695
0
                    XML_ERR_ERROR, NULL, 0, (const char *) info1,
696
0
                    (const char *) info2, (const char *) info3, 0, 0, msg,
697
0
                    info1, info2, info3);
698
0
    if (ctxt != NULL)
699
0
  ctxt->nsWellFormed = 0;
700
0
}
701
702
/**
703
 * xmlNsWarn
704
 * @ctxt:  an XML parser context
705
 * @error:  the error number
706
 * @msg:  the message
707
 * @info1:  extra information string
708
 * @info2:  extra information string
709
 *
710
 * Handle a namespace warning error
711
 */
712
static void LIBXML_ATTR_FORMAT(3,0)
713
xmlNsWarn(xmlParserCtxtPtr ctxt, xmlParserErrors error,
714
         const char *msg,
715
         const xmlChar * info1, const xmlChar * info2,
716
         const xmlChar * info3)
717
0
{
718
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
719
0
        (ctxt->instate == XML_PARSER_EOF))
720
0
  return;
721
0
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
722
0
                    XML_ERR_WARNING, NULL, 0, (const char *) info1,
723
0
                    (const char *) info2, (const char *) info3, 0, 0, msg,
724
0
                    info1, info2, info3);
725
0
}
726
727
static void
728
0
xmlSaturatedAdd(unsigned long *dst, unsigned long val) {
729
0
    if (val > ULONG_MAX - *dst)
730
0
        *dst = ULONG_MAX;
731
0
    else
732
0
        *dst += val;
733
0
}
734
735
static void
736
0
xmlSaturatedAddSizeT(unsigned long *dst, unsigned long val) {
737
0
    if (val > ULONG_MAX - *dst)
738
0
        *dst = ULONG_MAX;
739
0
    else
740
0
        *dst += val;
741
0
}
742
743
/**
744
 * xmlParserEntityCheck:
745
 * @ctxt:  parser context
746
 * @extra:  sum of unexpanded entity sizes
747
 *
748
 * Check for non-linear entity expansion behaviour.
749
 *
750
 * In some cases like xmlStringDecodeEntities, this function is called
751
 * for each, possibly nested entity and its unexpanded content length.
752
 *
753
 * In other cases like xmlParseReference, it's only called for each
754
 * top-level entity with its unexpanded content length plus the sum of
755
 * the unexpanded content lengths (plus fixed cost) of all nested
756
 * entities.
757
 *
758
 * Summing the unexpanded lengths also adds the length of the reference.
759
 * This is by design. Taking the length of the entity name into account
760
 * discourages attacks that try to waste CPU time with abusively long
761
 * entity names. See test/recurse/lol6.xml for example. Each call also
762
 * adds some fixed cost XML_ENT_FIXED_COST to discourage attacks with
763
 * short entities.
764
 *
765
 * Returns 1 on error, 0 on success.
766
 */
767
static int
768
xmlParserEntityCheck(xmlParserCtxtPtr ctxt, unsigned long extra)
769
0
{
770
0
    unsigned long consumed;
771
0
    xmlParserInputPtr input = ctxt->input;
772
0
    xmlEntityPtr entity = input->entity;
773
774
    /*
775
     * Compute total consumed bytes so far, including input streams of
776
     * external entities.
777
     */
778
0
    consumed = input->parentConsumed;
779
0
    if ((entity == NULL) ||
780
0
        ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
781
0
         ((entity->flags & XML_ENT_PARSED) == 0))) {
782
0
        xmlSaturatedAdd(&consumed, input->consumed);
783
0
        xmlSaturatedAddSizeT(&consumed, input->cur - input->base);
784
0
    }
785
0
    xmlSaturatedAdd(&consumed, ctxt->sizeentities);
786
787
    /*
788
     * Add extra cost and some fixed cost.
789
     */
790
0
    xmlSaturatedAdd(&ctxt->sizeentcopy, extra);
791
0
    xmlSaturatedAdd(&ctxt->sizeentcopy, XML_ENT_FIXED_COST);
792
793
    /*
794
     * It's important to always use saturation arithmetic when tracking
795
     * entity sizes to make the size checks reliable. If "sizeentcopy"
796
     * overflows, we have to abort.
797
     */
798
0
    if ((ctxt->sizeentcopy > XML_MAX_TEXT_LENGTH) &&
799
0
        ((ctxt->sizeentcopy >= ULONG_MAX) ||
800
0
         (ctxt->sizeentcopy / XML_PARSER_NON_LINEAR > consumed))) {
801
0
        xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_LOOP,
802
0
                       "Maximum entity amplification factor exceeded");
803
0
        xmlHaltParser(ctxt);
804
0
        return(1);
805
0
    }
806
807
0
    return(0);
808
0
}
809
810
/************************************************************************
811
 *                  *
812
 *    Library wide options          *
813
 *                  *
814
 ************************************************************************/
815
816
/**
817
  * xmlHasFeature:
818
  * @feature: the feature to be examined
819
  *
820
  * Examines if the library has been compiled with a given feature.
821
  *
822
  * Returns a non-zero value if the feature exist, otherwise zero.
823
  * Returns zero (0) if the feature does not exist or an unknown
824
  * unknown feature is requested, non-zero otherwise.
825
  */
826
int
827
xmlHasFeature(xmlFeature feature)
828
0
{
829
0
    switch (feature) {
830
0
  case XML_WITH_THREAD:
831
0
#ifdef LIBXML_THREAD_ENABLED
832
0
      return(1);
833
#else
834
      return(0);
835
#endif
836
0
        case XML_WITH_TREE:
837
0
#ifdef LIBXML_TREE_ENABLED
838
0
            return(1);
839
#else
840
            return(0);
841
#endif
842
0
        case XML_WITH_OUTPUT:
843
0
#ifdef LIBXML_OUTPUT_ENABLED
844
0
            return(1);
845
#else
846
            return(0);
847
#endif
848
0
        case XML_WITH_PUSH:
849
#ifdef LIBXML_PUSH_ENABLED
850
            return(1);
851
#else
852
0
            return(0);
853
0
#endif
854
0
        case XML_WITH_READER:
855
#ifdef LIBXML_READER_ENABLED
856
            return(1);
857
#else
858
0
            return(0);
859
0
#endif
860
0
        case XML_WITH_PATTERN:
861
0
#ifdef LIBXML_PATTERN_ENABLED
862
0
            return(1);
863
#else
864
            return(0);
865
#endif
866
0
        case XML_WITH_WRITER:
867
#ifdef LIBXML_WRITER_ENABLED
868
            return(1);
869
#else
870
0
            return(0);
871
0
#endif
872
0
        case XML_WITH_SAX1:
873
#ifdef LIBXML_SAX1_ENABLED
874
            return(1);
875
#else
876
0
            return(0);
877
0
#endif
878
0
        case XML_WITH_FTP:
879
#ifdef LIBXML_FTP_ENABLED
880
            return(1);
881
#else
882
0
            return(0);
883
0
#endif
884
0
        case XML_WITH_HTTP:
885
0
#ifdef LIBXML_HTTP_ENABLED
886
0
            return(1);
887
#else
888
            return(0);
889
#endif
890
0
        case XML_WITH_VALID:
891
#ifdef LIBXML_VALID_ENABLED
892
            return(1);
893
#else
894
0
            return(0);
895
0
#endif
896
0
        case XML_WITH_HTML:
897
0
#ifdef LIBXML_HTML_ENABLED
898
0
            return(1);
899
#else
900
            return(0);
901
#endif
902
0
        case XML_WITH_LEGACY:
903
#ifdef LIBXML_LEGACY_ENABLED
904
            return(1);
905
#else
906
0
            return(0);
907
0
#endif
908
0
        case XML_WITH_C14N:
909
#ifdef LIBXML_C14N_ENABLED
910
            return(1);
911
#else
912
0
            return(0);
913
0
#endif
914
0
        case XML_WITH_CATALOG:
915
0
#ifdef LIBXML_CATALOG_ENABLED
916
0
            return(1);
917
#else
918
            return(0);
919
#endif
920
0
        case XML_WITH_XPATH:
921
0
#ifdef LIBXML_XPATH_ENABLED
922
0
            return(1);
923
#else
924
            return(0);
925
#endif
926
0
        case XML_WITH_XPTR:
927
0
#ifdef LIBXML_XPTR_ENABLED
928
0
            return(1);
929
#else
930
            return(0);
931
#endif
932
0
        case XML_WITH_XINCLUDE:
933
0
#ifdef LIBXML_XINCLUDE_ENABLED
934
0
            return(1);
935
#else
936
            return(0);
937
#endif
938
0
        case XML_WITH_ICONV:
939
0
#ifdef LIBXML_ICONV_ENABLED
940
0
            return(1);
941
#else
942
            return(0);
943
#endif
944
0
        case XML_WITH_ISO8859X:
945
0
#ifdef LIBXML_ISO8859X_ENABLED
946
0
            return(1);
947
#else
948
            return(0);
949
#endif
950
0
        case XML_WITH_UNICODE:
951
#ifdef LIBXML_UNICODE_ENABLED
952
            return(1);
953
#else
954
0
            return(0);
955
0
#endif
956
0
        case XML_WITH_REGEXP:
957
#ifdef LIBXML_REGEXP_ENABLED
958
            return(1);
959
#else
960
0
            return(0);
961
0
#endif
962
0
        case XML_WITH_AUTOMATA:
963
#ifdef LIBXML_AUTOMATA_ENABLED
964
            return(1);
965
#else
966
0
            return(0);
967
0
#endif
968
0
        case XML_WITH_EXPR:
969
#ifdef LIBXML_EXPR_ENABLED
970
            return(1);
971
#else
972
0
            return(0);
973
0
#endif
974
0
        case XML_WITH_SCHEMAS:
975
#ifdef LIBXML_SCHEMAS_ENABLED
976
            return(1);
977
#else
978
0
            return(0);
979
0
#endif
980
0
        case XML_WITH_SCHEMATRON:
981
#ifdef LIBXML_SCHEMATRON_ENABLED
982
            return(1);
983
#else
984
0
            return(0);
985
0
#endif
986
0
        case XML_WITH_MODULES:
987
0
#ifdef LIBXML_MODULES_ENABLED
988
0
            return(1);
989
#else
990
            return(0);
991
#endif
992
0
        case XML_WITH_DEBUG:
993
0
#ifdef LIBXML_DEBUG_ENABLED
994
0
            return(1);
995
#else
996
            return(0);
997
#endif
998
0
        case XML_WITH_DEBUG_MEM:
999
#ifdef DEBUG_MEMORY_LOCATION
1000
            return(1);
1001
#else
1002
0
            return(0);
1003
0
#endif
1004
0
        case XML_WITH_DEBUG_RUN:
1005
0
            return(0);
1006
0
        case XML_WITH_ZLIB:
1007
#ifdef LIBXML_ZLIB_ENABLED
1008
            return(1);
1009
#else
1010
0
            return(0);
1011
0
#endif
1012
0
        case XML_WITH_LZMA:
1013
#ifdef LIBXML_LZMA_ENABLED
1014
            return(1);
1015
#else
1016
0
            return(0);
1017
0
#endif
1018
0
        case XML_WITH_ICU:
1019
#ifdef LIBXML_ICU_ENABLED
1020
            return(1);
1021
#else
1022
0
            return(0);
1023
0
#endif
1024
0
        default:
1025
0
      break;
1026
0
     }
1027
0
     return(0);
1028
0
}
1029
1030
/************************************************************************
1031
 *                  *
1032
 *    SAX2 defaulted attributes handling      *
1033
 *                  *
1034
 ************************************************************************/
1035
1036
/**
1037
 * xmlDetectSAX2:
1038
 * @ctxt:  an XML parser context
1039
 *
1040
 * Do the SAX2 detection and specific initialization
1041
 */
1042
static void
1043
3.69k
xmlDetectSAX2(xmlParserCtxtPtr ctxt) {
1044
3.69k
    xmlSAXHandlerPtr sax;
1045
1046
    /* Avoid unused variable warning if features are disabled. */
1047
3.69k
    (void) sax;
1048
1049
3.69k
    if (ctxt == NULL) return;
1050
3.69k
    sax = ctxt->sax;
1051
#ifdef LIBXML_SAX1_ENABLED
1052
    if ((sax) &&  (sax->initialized == XML_SAX2_MAGIC) &&
1053
        ((sax->startElementNs != NULL) ||
1054
         (sax->endElementNs != NULL) ||
1055
         ((sax->startElement == NULL) && (sax->endElement == NULL))))
1056
        ctxt->sax2 = 1;
1057
#else
1058
3.69k
    ctxt->sax2 = 1;
1059
3.69k
#endif /* LIBXML_SAX1_ENABLED */
1060
1061
3.69k
    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
1062
3.69k
    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
1063
3.69k
    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
1064
3.69k
    if ((ctxt->str_xml==NULL) || (ctxt->str_xmlns==NULL) ||
1065
3.69k
    (ctxt->str_xml_ns == NULL)) {
1066
0
        xmlErrMemory(ctxt, NULL);
1067
0
    }
1068
3.69k
}
1069
1070
typedef struct _xmlDefAttrs xmlDefAttrs;
1071
typedef xmlDefAttrs *xmlDefAttrsPtr;
1072
struct _xmlDefAttrs {
1073
    int nbAttrs;  /* number of defaulted attributes on that element */
1074
    int maxAttrs;       /* the size of the array */
1075
#if __STDC_VERSION__ >= 199901L
1076
    /* Using a C99 flexible array member avoids UBSan errors. */
1077
    const xmlChar *values[]; /* array of localname/prefix/values/external */
1078
#else
1079
    const xmlChar *values[5];
1080
#endif
1081
};
1082
1083
/**
1084
 * xmlAttrNormalizeSpace:
1085
 * @src: the source string
1086
 * @dst: the target string
1087
 *
1088
 * Normalize the space in non CDATA attribute values:
1089
 * If the attribute type is not CDATA, then the XML processor MUST further
1090
 * process the normalized attribute value by discarding any leading and
1091
 * trailing space (#x20) characters, and by replacing sequences of space
1092
 * (#x20) characters by a single space (#x20) character.
1093
 * Note that the size of dst need to be at least src, and if one doesn't need
1094
 * to preserve dst (and it doesn't come from a dictionary or read-only) then
1095
 * passing src as dst is just fine.
1096
 *
1097
 * Returns a pointer to the normalized value (dst) or NULL if no conversion
1098
 *         is needed.
1099
 */
1100
static xmlChar *
1101
xmlAttrNormalizeSpace(const xmlChar *src, xmlChar *dst)
1102
0
{
1103
0
    if ((src == NULL) || (dst == NULL))
1104
0
        return(NULL);
1105
1106
0
    while (*src == 0x20) src++;
1107
0
    while (*src != 0) {
1108
0
  if (*src == 0x20) {
1109
0
      while (*src == 0x20) src++;
1110
0
      if (*src != 0)
1111
0
    *dst++ = 0x20;
1112
0
  } else {
1113
0
      *dst++ = *src++;
1114
0
  }
1115
0
    }
1116
0
    *dst = 0;
1117
0
    if (dst == src)
1118
0
       return(NULL);
1119
0
    return(dst);
1120
0
}
1121
1122
/**
1123
 * xmlAttrNormalizeSpace2:
1124
 * @src: the source string
1125
 *
1126
 * Normalize the space in non CDATA attribute values, a slightly more complex
1127
 * front end to avoid allocation problems when running on attribute values
1128
 * coming from the input.
1129
 *
1130
 * Returns a pointer to the normalized value (dst) or NULL if no conversion
1131
 *         is needed.
1132
 */
1133
static const xmlChar *
1134
xmlAttrNormalizeSpace2(xmlParserCtxtPtr ctxt, xmlChar *src, int *len)
1135
0
{
1136
0
    int i;
1137
0
    int remove_head = 0;
1138
0
    int need_realloc = 0;
1139
0
    const xmlChar *cur;
1140
1141
0
    if ((ctxt == NULL) || (src == NULL) || (len == NULL))
1142
0
        return(NULL);
1143
0
    i = *len;
1144
0
    if (i <= 0)
1145
0
        return(NULL);
1146
1147
0
    cur = src;
1148
0
    while (*cur == 0x20) {
1149
0
        cur++;
1150
0
  remove_head++;
1151
0
    }
1152
0
    while (*cur != 0) {
1153
0
  if (*cur == 0x20) {
1154
0
      cur++;
1155
0
      if ((*cur == 0x20) || (*cur == 0)) {
1156
0
          need_realloc = 1;
1157
0
    break;
1158
0
      }
1159
0
  } else
1160
0
      cur++;
1161
0
    }
1162
0
    if (need_realloc) {
1163
0
        xmlChar *ret;
1164
1165
0
  ret = xmlStrndup(src + remove_head, i - remove_head + 1);
1166
0
  if (ret == NULL) {
1167
0
      xmlErrMemory(ctxt, NULL);
1168
0
      return(NULL);
1169
0
  }
1170
0
  xmlAttrNormalizeSpace(ret, ret);
1171
0
  *len = strlen((const char *)ret);
1172
0
        return(ret);
1173
0
    } else if (remove_head) {
1174
0
        *len -= remove_head;
1175
0
        memmove(src, src + remove_head, 1 + *len);
1176
0
  return(src);
1177
0
    }
1178
0
    return(NULL);
1179
0
}
1180
1181
/**
1182
 * xmlAddDefAttrs:
1183
 * @ctxt:  an XML parser context
1184
 * @fullname:  the element fullname
1185
 * @fullattr:  the attribute fullname
1186
 * @value:  the attribute value
1187
 *
1188
 * Add a defaulted attribute for an element
1189
 */
1190
static void
1191
xmlAddDefAttrs(xmlParserCtxtPtr ctxt,
1192
               const xmlChar *fullname,
1193
               const xmlChar *fullattr,
1194
0
               const xmlChar *value) {
1195
0
    xmlDefAttrsPtr defaults;
1196
0
    int len;
1197
0
    const xmlChar *name;
1198
0
    const xmlChar *prefix;
1199
1200
    /*
1201
     * Allows to detect attribute redefinitions
1202
     */
1203
0
    if (ctxt->attsSpecial != NULL) {
1204
0
        if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL)
1205
0
      return;
1206
0
    }
1207
1208
0
    if (ctxt->attsDefault == NULL) {
1209
0
        ctxt->attsDefault = xmlHashCreateDict(10, ctxt->dict);
1210
0
  if (ctxt->attsDefault == NULL)
1211
0
      goto mem_error;
1212
0
    }
1213
1214
    /*
1215
     * split the element name into prefix:localname , the string found
1216
     * are within the DTD and then not associated to namespace names.
1217
     */
1218
0
    name = xmlSplitQName3(fullname, &len);
1219
0
    if (name == NULL) {
1220
0
        name = xmlDictLookup(ctxt->dict, fullname, -1);
1221
0
  prefix = NULL;
1222
0
    } else {
1223
0
        name = xmlDictLookup(ctxt->dict, name, -1);
1224
0
  prefix = xmlDictLookup(ctxt->dict, fullname, len);
1225
0
    }
1226
1227
    /*
1228
     * make sure there is some storage
1229
     */
1230
0
    defaults = xmlHashLookup2(ctxt->attsDefault, name, prefix);
1231
0
    if (defaults == NULL) {
1232
0
        defaults = (xmlDefAttrsPtr) xmlMalloc(sizeof(xmlDefAttrs) +
1233
0
                     (4 * 5) * sizeof(const xmlChar *));
1234
0
  if (defaults == NULL)
1235
0
      goto mem_error;
1236
0
  defaults->nbAttrs = 0;
1237
0
  defaults->maxAttrs = 4;
1238
0
  if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix,
1239
0
                          defaults, NULL) < 0) {
1240
0
      xmlFree(defaults);
1241
0
      goto mem_error;
1242
0
  }
1243
0
    } else if (defaults->nbAttrs >= defaults->maxAttrs) {
1244
0
        xmlDefAttrsPtr temp;
1245
1246
0
        temp = (xmlDefAttrsPtr) xmlRealloc(defaults, sizeof(xmlDefAttrs) +
1247
0
           (2 * defaults->maxAttrs * 5) * sizeof(const xmlChar *));
1248
0
  if (temp == NULL)
1249
0
      goto mem_error;
1250
0
  defaults = temp;
1251
0
  defaults->maxAttrs *= 2;
1252
0
  if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix,
1253
0
                          defaults, NULL) < 0) {
1254
0
      xmlFree(defaults);
1255
0
      goto mem_error;
1256
0
  }
1257
0
    }
1258
1259
    /*
1260
     * Split the element name into prefix:localname , the string found
1261
     * are within the DTD and hen not associated to namespace names.
1262
     */
1263
0
    name = xmlSplitQName3(fullattr, &len);
1264
0
    if (name == NULL) {
1265
0
        name = xmlDictLookup(ctxt->dict, fullattr, -1);
1266
0
  prefix = NULL;
1267
0
    } else {
1268
0
        name = xmlDictLookup(ctxt->dict, name, -1);
1269
0
  prefix = xmlDictLookup(ctxt->dict, fullattr, len);
1270
0
    }
1271
1272
0
    defaults->values[5 * defaults->nbAttrs] = name;
1273
0
    defaults->values[5 * defaults->nbAttrs + 1] = prefix;
1274
    /* intern the string and precompute the end */
1275
0
    len = xmlStrlen(value);
1276
0
    value = xmlDictLookup(ctxt->dict, value, len);
1277
0
    if (value == NULL)
1278
0
        goto mem_error;
1279
0
    defaults->values[5 * defaults->nbAttrs + 2] = value;
1280
0
    defaults->values[5 * defaults->nbAttrs + 3] = value + len;
1281
0
    if (ctxt->external)
1282
0
        defaults->values[5 * defaults->nbAttrs + 4] = BAD_CAST "external";
1283
0
    else
1284
0
        defaults->values[5 * defaults->nbAttrs + 4] = NULL;
1285
0
    defaults->nbAttrs++;
1286
1287
0
    return;
1288
1289
0
mem_error:
1290
0
    xmlErrMemory(ctxt, NULL);
1291
0
    return;
1292
0
}
1293
1294
/**
1295
 * xmlAddSpecialAttr:
1296
 * @ctxt:  an XML parser context
1297
 * @fullname:  the element fullname
1298
 * @fullattr:  the attribute fullname
1299
 * @type:  the attribute type
1300
 *
1301
 * Register this attribute type
1302
 */
1303
static void
1304
xmlAddSpecialAttr(xmlParserCtxtPtr ctxt,
1305
      const xmlChar *fullname,
1306
      const xmlChar *fullattr,
1307
      int type)
1308
0
{
1309
0
    if (ctxt->attsSpecial == NULL) {
1310
0
        ctxt->attsSpecial = xmlHashCreateDict(10, ctxt->dict);
1311
0
  if (ctxt->attsSpecial == NULL)
1312
0
      goto mem_error;
1313
0
    }
1314
1315
0
    if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL)
1316
0
        return;
1317
1318
0
    xmlHashAddEntry2(ctxt->attsSpecial, fullname, fullattr,
1319
0
                     (void *) (ptrdiff_t) type);
1320
0
    return;
1321
1322
0
mem_error:
1323
0
    xmlErrMemory(ctxt, NULL);
1324
0
    return;
1325
0
}
1326
1327
/**
1328
 * xmlCleanSpecialAttrCallback:
1329
 *
1330
 * Removes CDATA attributes from the special attribute table
1331
 */
1332
static void
1333
xmlCleanSpecialAttrCallback(void *payload, void *data,
1334
                            const xmlChar *fullname, const xmlChar *fullattr,
1335
0
                            const xmlChar *unused ATTRIBUTE_UNUSED) {
1336
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) data;
1337
1338
0
    if (((ptrdiff_t) payload) == XML_ATTRIBUTE_CDATA) {
1339
0
        xmlHashRemoveEntry2(ctxt->attsSpecial, fullname, fullattr, NULL);
1340
0
    }
1341
0
}
1342
1343
/**
1344
 * xmlCleanSpecialAttr:
1345
 * @ctxt:  an XML parser context
1346
 *
1347
 * Trim the list of attributes defined to remove all those of type
1348
 * CDATA as they are not special. This call should be done when finishing
1349
 * to parse the DTD and before starting to parse the document root.
1350
 */
1351
static void
1352
xmlCleanSpecialAttr(xmlParserCtxtPtr ctxt)
1353
0
{
1354
0
    if (ctxt->attsSpecial == NULL)
1355
0
        return;
1356
1357
0
    xmlHashScanFull(ctxt->attsSpecial, xmlCleanSpecialAttrCallback, ctxt);
1358
1359
0
    if (xmlHashSize(ctxt->attsSpecial) == 0) {
1360
0
        xmlHashFree(ctxt->attsSpecial, NULL);
1361
0
        ctxt->attsSpecial = NULL;
1362
0
    }
1363
0
    return;
1364
0
}
1365
1366
/**
1367
 * xmlCheckLanguageID:
1368
 * @lang:  pointer to the string value
1369
 *
1370
 * Checks that the value conforms to the LanguageID production:
1371
 *
1372
 * NOTE: this is somewhat deprecated, those productions were removed from
1373
 *       the XML Second edition.
1374
 *
1375
 * [33] LanguageID ::= Langcode ('-' Subcode)*
1376
 * [34] Langcode ::= ISO639Code |  IanaCode |  UserCode
1377
 * [35] ISO639Code ::= ([a-z] | [A-Z]) ([a-z] | [A-Z])
1378
 * [36] IanaCode ::= ('i' | 'I') '-' ([a-z] | [A-Z])+
1379
 * [37] UserCode ::= ('x' | 'X') '-' ([a-z] | [A-Z])+
1380
 * [38] Subcode ::= ([a-z] | [A-Z])+
1381
 *
1382
 * The current REC reference the successors of RFC 1766, currently 5646
1383
 *
1384
 * http://www.rfc-editor.org/rfc/rfc5646.txt
1385
 * langtag       = language
1386
 *                 ["-" script]
1387
 *                 ["-" region]
1388
 *                 *("-" variant)
1389
 *                 *("-" extension)
1390
 *                 ["-" privateuse]
1391
 * language      = 2*3ALPHA            ; shortest ISO 639 code
1392
 *                 ["-" extlang]       ; sometimes followed by
1393
 *                                     ; extended language subtags
1394
 *               / 4ALPHA              ; or reserved for future use
1395
 *               / 5*8ALPHA            ; or registered language subtag
1396
 *
1397
 * extlang       = 3ALPHA              ; selected ISO 639 codes
1398
 *                 *2("-" 3ALPHA)      ; permanently reserved
1399
 *
1400
 * script        = 4ALPHA              ; ISO 15924 code
1401
 *
1402
 * region        = 2ALPHA              ; ISO 3166-1 code
1403
 *               / 3DIGIT              ; UN M.49 code
1404
 *
1405
 * variant       = 5*8alphanum         ; registered variants
1406
 *               / (DIGIT 3alphanum)
1407
 *
1408
 * extension     = singleton 1*("-" (2*8alphanum))
1409
 *
1410
 *                                     ; Single alphanumerics
1411
 *                                     ; "x" reserved for private use
1412
 * singleton     = DIGIT               ; 0 - 9
1413
 *               / %x41-57             ; A - W
1414
 *               / %x59-5A             ; Y - Z
1415
 *               / %x61-77             ; a - w
1416
 *               / %x79-7A             ; y - z
1417
 *
1418
 * it sounds right to still allow Irregular i-xxx IANA and user codes too
1419
 * The parser below doesn't try to cope with extension or privateuse
1420
 * that could be added but that's not interoperable anyway
1421
 *
1422
 * Returns 1 if correct 0 otherwise
1423
 **/
1424
int
1425
xmlCheckLanguageID(const xmlChar * lang)
1426
0
{
1427
0
    const xmlChar *cur = lang, *nxt;
1428
1429
0
    if (cur == NULL)
1430
0
        return (0);
1431
0
    if (((cur[0] == 'i') && (cur[1] == '-')) ||
1432
0
        ((cur[0] == 'I') && (cur[1] == '-')) ||
1433
0
        ((cur[0] == 'x') && (cur[1] == '-')) ||
1434
0
        ((cur[0] == 'X') && (cur[1] == '-'))) {
1435
        /*
1436
         * Still allow IANA code and user code which were coming
1437
         * from the previous version of the XML-1.0 specification
1438
         * it's deprecated but we should not fail
1439
         */
1440
0
        cur += 2;
1441
0
        while (((cur[0] >= 'A') && (cur[0] <= 'Z')) ||
1442
0
               ((cur[0] >= 'a') && (cur[0] <= 'z')))
1443
0
            cur++;
1444
0
        return(cur[0] == 0);
1445
0
    }
1446
0
    nxt = cur;
1447
0
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1448
0
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1449
0
           nxt++;
1450
0
    if (nxt - cur >= 4) {
1451
        /*
1452
         * Reserved
1453
         */
1454
0
        if ((nxt - cur > 8) || (nxt[0] != 0))
1455
0
            return(0);
1456
0
        return(1);
1457
0
    }
1458
0
    if (nxt - cur < 2)
1459
0
        return(0);
1460
    /* we got an ISO 639 code */
1461
0
    if (nxt[0] == 0)
1462
0
        return(1);
1463
0
    if (nxt[0] != '-')
1464
0
        return(0);
1465
1466
0
    nxt++;
1467
0
    cur = nxt;
1468
    /* now we can have extlang or script or region or variant */
1469
0
    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1470
0
        goto region_m49;
1471
1472
0
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1473
0
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1474
0
           nxt++;
1475
0
    if (nxt - cur == 4)
1476
0
        goto script;
1477
0
    if (nxt - cur == 2)
1478
0
        goto region;
1479
0
    if ((nxt - cur >= 5) && (nxt - cur <= 8))
1480
0
        goto variant;
1481
0
    if (nxt - cur != 3)
1482
0
        return(0);
1483
    /* we parsed an extlang */
1484
0
    if (nxt[0] == 0)
1485
0
        return(1);
1486
0
    if (nxt[0] != '-')
1487
0
        return(0);
1488
1489
0
    nxt++;
1490
0
    cur = nxt;
1491
    /* now we can have script or region or variant */
1492
0
    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1493
0
        goto region_m49;
1494
1495
0
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1496
0
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1497
0
           nxt++;
1498
0
    if (nxt - cur == 2)
1499
0
        goto region;
1500
0
    if ((nxt - cur >= 5) && (nxt - cur <= 8))
1501
0
        goto variant;
1502
0
    if (nxt - cur != 4)
1503
0
        return(0);
1504
    /* we parsed a script */
1505
0
script:
1506
0
    if (nxt[0] == 0)
1507
0
        return(1);
1508
0
    if (nxt[0] != '-')
1509
0
        return(0);
1510
1511
0
    nxt++;
1512
0
    cur = nxt;
1513
    /* now we can have region or variant */
1514
0
    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1515
0
        goto region_m49;
1516
1517
0
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1518
0
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1519
0
           nxt++;
1520
1521
0
    if ((nxt - cur >= 5) && (nxt - cur <= 8))
1522
0
        goto variant;
1523
0
    if (nxt - cur != 2)
1524
0
        return(0);
1525
    /* we parsed a region */
1526
0
region:
1527
0
    if (nxt[0] == 0)
1528
0
        return(1);
1529
0
    if (nxt[0] != '-')
1530
0
        return(0);
1531
1532
0
    nxt++;
1533
0
    cur = nxt;
1534
    /* now we can just have a variant */
1535
0
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1536
0
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1537
0
           nxt++;
1538
1539
0
    if ((nxt - cur < 5) || (nxt - cur > 8))
1540
0
        return(0);
1541
1542
    /* we parsed a variant */
1543
0
variant:
1544
0
    if (nxt[0] == 0)
1545
0
        return(1);
1546
0
    if (nxt[0] != '-')
1547
0
        return(0);
1548
    /* extensions and private use subtags not checked */
1549
0
    return (1);
1550
1551
0
region_m49:
1552
0
    if (((nxt[1] >= '0') && (nxt[1] <= '9')) &&
1553
0
        ((nxt[2] >= '0') && (nxt[2] <= '9'))) {
1554
0
        nxt += 3;
1555
0
        goto region;
1556
0
    }
1557
0
    return(0);
1558
0
}
1559
1560
/************************************************************************
1561
 *                  *
1562
 *    Parser stacks related functions and macros    *
1563
 *                  *
1564
 ************************************************************************/
1565
1566
static xmlEntityPtr xmlParseStringEntityRef(xmlParserCtxtPtr ctxt,
1567
                                            const xmlChar ** str);
1568
1569
#ifdef SAX2
1570
/**
1571
 * nsPush:
1572
 * @ctxt:  an XML parser context
1573
 * @prefix:  the namespace prefix or NULL
1574
 * @URL:  the namespace name
1575
 *
1576
 * Pushes a new parser namespace on top of the ns stack
1577
 *
1578
 * Returns -1 in case of error, -2 if the namespace should be discarded
1579
 *     and the index in the stack otherwise.
1580
 */
1581
static int
1582
nsPush(xmlParserCtxtPtr ctxt, const xmlChar *prefix, const xmlChar *URL)
1583
11.0k
{
1584
11.0k
    if (ctxt->options & XML_PARSE_NSCLEAN) {
1585
0
        int i;
1586
0
  for (i = ctxt->nsNr - 2;i >= 0;i -= 2) {
1587
0
      if (ctxt->nsTab[i] == prefix) {
1588
    /* in scope */
1589
0
          if (ctxt->nsTab[i + 1] == URL)
1590
0
        return(-2);
1591
    /* out of scope keep it */
1592
0
    break;
1593
0
      }
1594
0
  }
1595
0
    }
1596
11.0k
    if ((ctxt->nsMax == 0) || (ctxt->nsTab == NULL)) {
1597
3.69k
  ctxt->nsMax = 10;
1598
3.69k
  ctxt->nsNr = 0;
1599
3.69k
  ctxt->nsTab = (const xmlChar **)
1600
3.69k
                xmlMalloc(ctxt->nsMax * sizeof(xmlChar *));
1601
3.69k
  if (ctxt->nsTab == NULL) {
1602
0
      xmlErrMemory(ctxt, NULL);
1603
0
      ctxt->nsMax = 0;
1604
0
            return (-1);
1605
0
  }
1606
7.38k
    } else if (ctxt->nsNr >= ctxt->nsMax) {
1607
0
        const xmlChar ** tmp;
1608
0
        ctxt->nsMax *= 2;
1609
0
        tmp = (const xmlChar **) xmlRealloc((char *) ctxt->nsTab,
1610
0
            ctxt->nsMax * sizeof(ctxt->nsTab[0]));
1611
0
        if (tmp == NULL) {
1612
0
            xmlErrMemory(ctxt, NULL);
1613
0
      ctxt->nsMax /= 2;
1614
0
            return (-1);
1615
0
        }
1616
0
  ctxt->nsTab = tmp;
1617
0
    }
1618
11.0k
    ctxt->nsTab[ctxt->nsNr++] = prefix;
1619
11.0k
    ctxt->nsTab[ctxt->nsNr++] = URL;
1620
11.0k
    return (ctxt->nsNr);
1621
11.0k
}
1622
/**
1623
 * nsPop:
1624
 * @ctxt: an XML parser context
1625
 * @nr:  the number to pop
1626
 *
1627
 * Pops the top @nr parser prefix/namespace from the ns stack
1628
 *
1629
 * Returns the number of namespaces removed
1630
 */
1631
static int
1632
nsPop(xmlParserCtxtPtr ctxt, int nr)
1633
11.0k
{
1634
11.0k
    int i;
1635
1636
11.0k
    if (ctxt->nsTab == NULL) return(0);
1637
11.0k
    if (ctxt->nsNr < nr) {
1638
0
        xmlGenericError(xmlGenericErrorContext, "Pbm popping %d NS\n", nr);
1639
0
        nr = ctxt->nsNr;
1640
0
    }
1641
11.0k
    if (ctxt->nsNr <= 0)
1642
0
        return (0);
1643
1644
33.2k
    for (i = 0;i < nr;i++) {
1645
22.1k
         ctxt->nsNr--;
1646
22.1k
   ctxt->nsTab[ctxt->nsNr] = NULL;
1647
22.1k
    }
1648
11.0k
    return(nr);
1649
11.0k
}
1650
#endif
1651
1652
static int
1653
3.69k
xmlCtxtGrowAttrs(xmlParserCtxtPtr ctxt, int nr) {
1654
3.69k
    const xmlChar **atts;
1655
3.69k
    int *attallocs;
1656
3.69k
    int maxatts;
1657
1658
3.69k
    if (nr + 5 > ctxt->maxatts) {
1659
3.69k
  maxatts = ctxt->maxatts == 0 ? 55 : (nr + 5) * 2;
1660
3.69k
  atts = (const xmlChar **) xmlMalloc(
1661
3.69k
             maxatts * sizeof(const xmlChar *));
1662
3.69k
  if (atts == NULL) goto mem_error;
1663
3.69k
  attallocs = (int *) xmlRealloc((void *) ctxt->attallocs,
1664
3.69k
                               (maxatts / 5) * sizeof(int));
1665
3.69k
  if (attallocs == NULL) {
1666
0
            xmlFree(atts);
1667
0
            goto mem_error;
1668
0
        }
1669
3.69k
        if (ctxt->maxatts > 0)
1670
0
            memcpy(atts, ctxt->atts, ctxt->maxatts * sizeof(const xmlChar *));
1671
3.69k
        xmlFree(ctxt->atts);
1672
3.69k
  ctxt->atts = atts;
1673
3.69k
  ctxt->attallocs = attallocs;
1674
3.69k
  ctxt->maxatts = maxatts;
1675
3.69k
    }
1676
3.69k
    return(ctxt->maxatts);
1677
0
mem_error:
1678
0
    xmlErrMemory(ctxt, NULL);
1679
0
    return(-1);
1680
3.69k
}
1681
1682
/**
1683
 * inputPush:
1684
 * @ctxt:  an XML parser context
1685
 * @value:  the parser input
1686
 *
1687
 * Pushes a new parser input on top of the input stack
1688
 *
1689
 * Returns -1 in case of error, the index in the stack otherwise
1690
 */
1691
int
1692
inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value)
1693
3.69k
{
1694
3.69k
    if ((ctxt == NULL) || (value == NULL))
1695
0
        return(-1);
1696
3.69k
    if (ctxt->inputNr >= ctxt->inputMax) {
1697
0
        size_t newSize = ctxt->inputMax * 2;
1698
0
        xmlParserInputPtr *tmp;
1699
1700
0
        tmp = (xmlParserInputPtr *) xmlRealloc(ctxt->inputTab,
1701
0
                                               newSize * sizeof(*tmp));
1702
0
        if (tmp == NULL) {
1703
0
            xmlErrMemory(ctxt, NULL);
1704
0
            return (-1);
1705
0
        }
1706
0
        ctxt->inputTab = tmp;
1707
0
        ctxt->inputMax = newSize;
1708
0
    }
1709
3.69k
    ctxt->inputTab[ctxt->inputNr] = value;
1710
3.69k
    ctxt->input = value;
1711
3.69k
    return (ctxt->inputNr++);
1712
3.69k
}
1713
/**
1714
 * inputPop:
1715
 * @ctxt: an XML parser context
1716
 *
1717
 * Pops the top parser input from the input stack
1718
 *
1719
 * Returns the input just removed
1720
 */
1721
xmlParserInputPtr
1722
inputPop(xmlParserCtxtPtr ctxt)
1723
11.0k
{
1724
11.0k
    xmlParserInputPtr ret;
1725
1726
11.0k
    if (ctxt == NULL)
1727
0
        return(NULL);
1728
11.0k
    if (ctxt->inputNr <= 0)
1729
7.38k
        return (NULL);
1730
3.69k
    ctxt->inputNr--;
1731
3.69k
    if (ctxt->inputNr > 0)
1732
0
        ctxt->input = ctxt->inputTab[ctxt->inputNr - 1];
1733
3.69k
    else
1734
3.69k
        ctxt->input = NULL;
1735
3.69k
    ret = ctxt->inputTab[ctxt->inputNr];
1736
3.69k
    ctxt->inputTab[ctxt->inputNr] = NULL;
1737
3.69k
    return (ret);
1738
11.0k
}
1739
/**
1740
 * nodePush:
1741
 * @ctxt:  an XML parser context
1742
 * @value:  the element node
1743
 *
1744
 * Pushes a new element node on top of the node stack
1745
 *
1746
 * Returns -1 in case of error, the index in the stack otherwise
1747
 */
1748
int
1749
nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value)
1750
44.3k
{
1751
44.3k
    if (ctxt == NULL) return(0);
1752
44.3k
    if (ctxt->nodeNr >= ctxt->nodeMax) {
1753
0
        xmlNodePtr *tmp;
1754
1755
0
  tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
1756
0
                                      ctxt->nodeMax * 2 *
1757
0
                                      sizeof(ctxt->nodeTab[0]));
1758
0
        if (tmp == NULL) {
1759
0
            xmlErrMemory(ctxt, NULL);
1760
0
            return (-1);
1761
0
        }
1762
0
        ctxt->nodeTab = tmp;
1763
0
  ctxt->nodeMax *= 2;
1764
0
    }
1765
44.3k
    if ((((unsigned int) ctxt->nodeNr) > xmlParserMaxDepth) &&
1766
44.3k
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
1767
0
  xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
1768
0
     "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
1769
0
        xmlParserMaxDepth);
1770
0
  xmlHaltParser(ctxt);
1771
0
  return(-1);
1772
0
    }
1773
44.3k
    ctxt->nodeTab[ctxt->nodeNr] = value;
1774
44.3k
    ctxt->node = value;
1775
44.3k
    return (ctxt->nodeNr++);
1776
44.3k
}
1777
1778
/**
1779
 * nodePop:
1780
 * @ctxt: an XML parser context
1781
 *
1782
 * Pops the top element node from the node stack
1783
 *
1784
 * Returns the node just removed
1785
 */
1786
xmlNodePtr
1787
nodePop(xmlParserCtxtPtr ctxt)
1788
44.3k
{
1789
44.3k
    xmlNodePtr ret;
1790
1791
44.3k
    if (ctxt == NULL) return(NULL);
1792
44.3k
    if (ctxt->nodeNr <= 0)
1793
0
        return (NULL);
1794
44.3k
    ctxt->nodeNr--;
1795
44.3k
    if (ctxt->nodeNr > 0)
1796
40.6k
        ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1];
1797
3.69k
    else
1798
3.69k
        ctxt->node = NULL;
1799
44.3k
    ret = ctxt->nodeTab[ctxt->nodeNr];
1800
44.3k
    ctxt->nodeTab[ctxt->nodeNr] = NULL;
1801
44.3k
    return (ret);
1802
44.3k
}
1803
1804
/**
1805
 * nameNsPush:
1806
 * @ctxt:  an XML parser context
1807
 * @value:  the element name
1808
 * @prefix:  the element prefix
1809
 * @URI:  the element namespace name
1810
 * @line:  the current line number for error messages
1811
 * @nsNr:  the number of namespaces pushed on the namespace table
1812
 *
1813
 * Pushes a new element name/prefix/URL on top of the name stack
1814
 *
1815
 * Returns -1 in case of error, the index in the stack otherwise
1816
 */
1817
static int
1818
nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
1819
           const xmlChar *prefix, const xmlChar *URI, int line, int nsNr)
1820
44.3k
{
1821
44.3k
    xmlStartTag *tag;
1822
1823
44.3k
    if (ctxt->nameNr >= ctxt->nameMax) {
1824
0
        const xmlChar * *tmp;
1825
0
        xmlStartTag *tmp2;
1826
0
        ctxt->nameMax *= 2;
1827
0
        tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
1828
0
                                    ctxt->nameMax *
1829
0
                                    sizeof(ctxt->nameTab[0]));
1830
0
        if (tmp == NULL) {
1831
0
      ctxt->nameMax /= 2;
1832
0
      goto mem_error;
1833
0
        }
1834
0
  ctxt->nameTab = tmp;
1835
0
        tmp2 = (xmlStartTag *) xmlRealloc((void * *)ctxt->pushTab,
1836
0
                                    ctxt->nameMax *
1837
0
                                    sizeof(ctxt->pushTab[0]));
1838
0
        if (tmp2 == NULL) {
1839
0
      ctxt->nameMax /= 2;
1840
0
      goto mem_error;
1841
0
        }
1842
0
  ctxt->pushTab = tmp2;
1843
44.3k
    } else if (ctxt->pushTab == NULL) {
1844
3.69k
        ctxt->pushTab = (xmlStartTag *) xmlMalloc(ctxt->nameMax *
1845
3.69k
                                            sizeof(ctxt->pushTab[0]));
1846
3.69k
        if (ctxt->pushTab == NULL)
1847
0
            goto mem_error;
1848
3.69k
    }
1849
44.3k
    ctxt->nameTab[ctxt->nameNr] = value;
1850
44.3k
    ctxt->name = value;
1851
44.3k
    tag = &ctxt->pushTab[ctxt->nameNr];
1852
44.3k
    tag->prefix = prefix;
1853
44.3k
    tag->URI = URI;
1854
44.3k
    tag->line = line;
1855
44.3k
    tag->nsNr = nsNr;
1856
44.3k
    return (ctxt->nameNr++);
1857
0
mem_error:
1858
0
    xmlErrMemory(ctxt, NULL);
1859
0
    return (-1);
1860
44.3k
}
1861
#ifdef LIBXML_PUSH_ENABLED
1862
/**
1863
 * nameNsPop:
1864
 * @ctxt: an XML parser context
1865
 *
1866
 * Pops the top element/prefix/URI name from the name stack
1867
 *
1868
 * Returns the name just removed
1869
 */
1870
static const xmlChar *
1871
nameNsPop(xmlParserCtxtPtr ctxt)
1872
{
1873
    const xmlChar *ret;
1874
1875
    if (ctxt->nameNr <= 0)
1876
        return (NULL);
1877
    ctxt->nameNr--;
1878
    if (ctxt->nameNr > 0)
1879
        ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
1880
    else
1881
        ctxt->name = NULL;
1882
    ret = ctxt->nameTab[ctxt->nameNr];
1883
    ctxt->nameTab[ctxt->nameNr] = NULL;
1884
    return (ret);
1885
}
1886
#endif /* LIBXML_PUSH_ENABLED */
1887
1888
/**
1889
 * namePush:
1890
 * @ctxt:  an XML parser context
1891
 * @value:  the element name
1892
 *
1893
 * Pushes a new element name on top of the name stack
1894
 *
1895
 * Returns -1 in case of error, the index in the stack otherwise
1896
 */
1897
int
1898
namePush(xmlParserCtxtPtr ctxt, const xmlChar * value)
1899
0
{
1900
0
    if (ctxt == NULL) return (-1);
1901
1902
0
    if (ctxt->nameNr >= ctxt->nameMax) {
1903
0
        const xmlChar * *tmp;
1904
0
        tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
1905
0
                                    ctxt->nameMax * 2 *
1906
0
                                    sizeof(ctxt->nameTab[0]));
1907
0
        if (tmp == NULL) {
1908
0
      goto mem_error;
1909
0
        }
1910
0
  ctxt->nameTab = tmp;
1911
0
        ctxt->nameMax *= 2;
1912
0
    }
1913
0
    ctxt->nameTab[ctxt->nameNr] = value;
1914
0
    ctxt->name = value;
1915
0
    return (ctxt->nameNr++);
1916
0
mem_error:
1917
0
    xmlErrMemory(ctxt, NULL);
1918
0
    return (-1);
1919
0
}
1920
/**
1921
 * namePop:
1922
 * @ctxt: an XML parser context
1923
 *
1924
 * Pops the top element name from the name stack
1925
 *
1926
 * Returns the name just removed
1927
 */
1928
const xmlChar *
1929
namePop(xmlParserCtxtPtr ctxt)
1930
44.3k
{
1931
44.3k
    const xmlChar *ret;
1932
1933
44.3k
    if ((ctxt == NULL) || (ctxt->nameNr <= 0))
1934
0
        return (NULL);
1935
44.3k
    ctxt->nameNr--;
1936
44.3k
    if (ctxt->nameNr > 0)
1937
40.6k
        ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
1938
3.69k
    else
1939
3.69k
        ctxt->name = NULL;
1940
44.3k
    ret = ctxt->nameTab[ctxt->nameNr];
1941
44.3k
    ctxt->nameTab[ctxt->nameNr] = NULL;
1942
44.3k
    return (ret);
1943
44.3k
}
1944
1945
44.3k
static int spacePush(xmlParserCtxtPtr ctxt, int val) {
1946
44.3k
    if (ctxt->spaceNr >= ctxt->spaceMax) {
1947
0
        int *tmp;
1948
1949
0
  ctxt->spaceMax *= 2;
1950
0
        tmp = (int *) xmlRealloc(ctxt->spaceTab,
1951
0
                           ctxt->spaceMax * sizeof(ctxt->spaceTab[0]));
1952
0
        if (tmp == NULL) {
1953
0
      xmlErrMemory(ctxt, NULL);
1954
0
      ctxt->spaceMax /=2;
1955
0
      return(-1);
1956
0
  }
1957
0
  ctxt->spaceTab = tmp;
1958
0
    }
1959
44.3k
    ctxt->spaceTab[ctxt->spaceNr] = val;
1960
44.3k
    ctxt->space = &ctxt->spaceTab[ctxt->spaceNr];
1961
44.3k
    return(ctxt->spaceNr++);
1962
44.3k
}
1963
1964
44.3k
static int spacePop(xmlParserCtxtPtr ctxt) {
1965
44.3k
    int ret;
1966
44.3k
    if (ctxt->spaceNr <= 0) return(0);
1967
44.3k
    ctxt->spaceNr--;
1968
44.3k
    if (ctxt->spaceNr > 0)
1969
44.3k
  ctxt->space = &ctxt->spaceTab[ctxt->spaceNr - 1];
1970
0
    else
1971
0
        ctxt->space = &ctxt->spaceTab[0];
1972
44.3k
    ret = ctxt->spaceTab[ctxt->spaceNr];
1973
44.3k
    ctxt->spaceTab[ctxt->spaceNr] = -1;
1974
44.3k
    return(ret);
1975
44.3k
}
1976
1977
/*
1978
 * Macros for accessing the content. Those should be used only by the parser,
1979
 * and not exported.
1980
 *
1981
 * Dirty macros, i.e. one often need to make assumption on the context to
1982
 * use them
1983
 *
1984
 *   CUR_PTR return the current pointer to the xmlChar to be parsed.
1985
 *           To be used with extreme caution since operations consuming
1986
 *           characters may move the input buffer to a different location !
1987
 *   CUR     returns the current xmlChar value, i.e. a 8 bit value if compiled
1988
 *           This should be used internally by the parser
1989
 *           only to compare to ASCII values otherwise it would break when
1990
 *           running with UTF-8 encoding.
1991
 *   RAW     same as CUR but in the input buffer, bypass any token
1992
 *           extraction that may have been done
1993
 *   NXT(n)  returns the n'th next xmlChar. Same as CUR is should be used only
1994
 *           to compare on ASCII based substring.
1995
 *   SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
1996
 *           strings without newlines within the parser.
1997
 *   NEXT1(l) Skip 1 xmlChar, and must also be used only to skip 1 non-newline ASCII
1998
 *           defined char within the parser.
1999
 * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
2000
 *
2001
 *   NEXT    Skip to the next character, this does the proper decoding
2002
 *           in UTF-8 mode. It also pop-up unfinished entities on the fly.
2003
 *   NEXTL(l) Skip the current unicode character of l xmlChars long.
2004
 *   CUR_CHAR(l) returns the current unicode character (int), set l
2005
 *           to the number of xmlChars used for the encoding [0-5].
2006
 *   CUR_SCHAR  same but operate on a string instead of the context
2007
 *   COPY_BUF  copy the current unicode char to the target buffer, increment
2008
 *            the index
2009
 *   GROW, SHRINK  handling of input buffers
2010
 */
2011
2012
708k
#define RAW (*ctxt->input->cur)
2013
155k
#define CUR (*ctxt->input->cur)
2014
313k
#define NXT(val) ctxt->input->cur[(val)]
2015
84.9k
#define CUR_PTR ctxt->input->cur
2016
0
#define BASE_PTR ctxt->input->base
2017
2018
#define CMP4( s, c1, c2, c3, c4 ) \
2019
369k
  ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char *) s)[ 1 ] == c2 && \
2020
188k
    ((unsigned char *) s)[ 2 ] == c3 && ((unsigned char *) s)[ 3 ] == c4 )
2021
#define CMP5( s, c1, c2, c3, c4, c5 ) \
2022
358k
  ( CMP4( s, c1, c2, c3, c4 ) && ((unsigned char *) s)[ 4 ] == c5 )
2023
#define CMP6( s, c1, c2, c3, c4, c5, c6 ) \
2024
350k
  ( CMP5( s, c1, c2, c3, c4, c5 ) && ((unsigned char *) s)[ 5 ] == c6 )
2025
#define CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) \
2026
347k
  ( CMP6( s, c1, c2, c3, c4, c5, c6 ) && ((unsigned char *) s)[ 6 ] == c7 )
2027
#define CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) \
2028
347k
  ( CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) && ((unsigned char *) s)[ 7 ] == c8 )
2029
#define CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) \
2030
173k
  ( CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) && \
2031
173k
    ((unsigned char *) s)[ 8 ] == c9 )
2032
#define CMP10( s, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 ) \
2033
0
  ( CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) && \
2034
0
    ((unsigned char *) s)[ 9 ] == c10 )
2035
2036
92.3k
#define SKIP(val) do {             \
2037
92.3k
    ctxt->input->cur += (val),ctxt->input->col+=(val);      \
2038
92.3k
    if (*ctxt->input->cur == 0)           \
2039
92.3k
        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);     \
2040
92.3k
  } while (0)
2041
2042
#define SKIPL(val) do {             \
2043
    int skipl;                \
2044
    for(skipl=0; skipl<val; skipl++) {          \
2045
  if (*(ctxt->input->cur) == '\n') {        \
2046
  ctxt->input->line++; ctxt->input->col = 1;      \
2047
  } else ctxt->input->col++;          \
2048
  ctxt->input->cur++;           \
2049
    }                 \
2050
    if (*ctxt->input->cur == 0)           \
2051
        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);     \
2052
  } while (0)
2053
2054
332k
#define SHRINK if ((ctxt->progressive == 0) &&       \
2055
332k
       (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \
2056
332k
       (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \
2057
332k
  xmlSHRINK (ctxt);
2058
2059
0
static void xmlSHRINK (xmlParserCtxtPtr ctxt) {
2060
    /* Don't shrink memory buffers. */
2061
0
    if ((ctxt->input->buf) &&
2062
0
        ((ctxt->input->buf->encoder) || (ctxt->input->buf->readcallback)))
2063
0
        xmlParserInputShrink(ctxt->input);
2064
0
    if (*ctxt->input->cur == 0)
2065
0
        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
2066
0
}
2067
2068
705k
#define GROW if ((ctxt->progressive == 0) &&       \
2069
705k
     (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK))  \
2070
705k
  xmlGROW (ctxt);
2071
2072
409k
static void xmlGROW (xmlParserCtxtPtr ctxt) {
2073
409k
    ptrdiff_t curEnd = ctxt->input->end - ctxt->input->cur;
2074
409k
    ptrdiff_t curBase = ctxt->input->cur - ctxt->input->base;
2075
2076
409k
    if (((curEnd > XML_MAX_LOOKUP_LIMIT) ||
2077
409k
         (curBase > XML_MAX_LOOKUP_LIMIT)) &&
2078
409k
         ((ctxt->input->buf) &&
2079
0
          (ctxt->input->buf->readcallback != NULL)) &&
2080
409k
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
2081
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
2082
0
        xmlHaltParser(ctxt);
2083
0
  return;
2084
0
    }
2085
409k
    xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
2086
409k
    if ((ctxt->input->cur > ctxt->input->end) ||
2087
409k
        (ctxt->input->cur < ctxt->input->base)) {
2088
0
        xmlHaltParser(ctxt);
2089
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "cur index out of bound");
2090
0
  return;
2091
0
    }
2092
409k
    if ((ctxt->input->cur != NULL) && (*ctxt->input->cur == 0))
2093
3.69k
        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
2094
409k
}
2095
2096
195k
#define SKIP_BLANKS xmlSkipBlankChars(ctxt)
2097
2098
107k
#define NEXT xmlNextChar(ctxt)
2099
2100
110k
#define NEXT1 {               \
2101
110k
  ctxt->input->col++;           \
2102
110k
  ctxt->input->cur++;           \
2103
110k
  if (*ctxt->input->cur == 0)         \
2104
110k
      xmlParserInputGrow(ctxt->input, INPUT_CHUNK);   \
2105
110k
    }
2106
2107
110k
#define NEXTL(l) do {             \
2108
110k
    if (*(ctxt->input->cur) == '\n') {         \
2109
0
  ctxt->input->line++; ctxt->input->col = 1;      \
2110
110k
    } else ctxt->input->col++;           \
2111
110k
    ctxt->input->cur += l;        \
2112
110k
  } while (0)
2113
2114
129k
#define CUR_CHAR(l) xmlCurrentChar(ctxt, &l)
2115
0
#define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l)
2116
2117
#define COPY_BUF(l,b,i,v)           \
2118
103k
    if (l == 1) b[i++] = v;           \
2119
103k
    else i += xmlCopyCharMultiByte(&b[i],v)
2120
2121
/**
2122
 * xmlSkipBlankChars:
2123
 * @ctxt:  the XML parser context
2124
 *
2125
 * skip all blanks character found at that point in the input streams.
2126
 * It pops up finished entities in the process if allowable at that point.
2127
 *
2128
 * Returns the number of space chars skipped
2129
 */
2130
2131
int
2132
195k
xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
2133
195k
    int res = 0;
2134
2135
    /*
2136
     * It's Okay to use CUR/NEXT here since all the blanks are on
2137
     * the ASCII range.
2138
     */
2139
195k
    if (((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) ||
2140
195k
        (ctxt->instate == XML_PARSER_START)) {
2141
195k
  const xmlChar *cur;
2142
  /*
2143
   * if we are in the document content, go really fast
2144
   */
2145
195k
  cur = ctxt->input->cur;
2146
195k
  while (IS_BLANK_CH(*cur)) {
2147
59.0k
      if (*cur == '\n') {
2148
7.38k
    ctxt->input->line++; ctxt->input->col = 1;
2149
51.6k
      } else {
2150
51.6k
    ctxt->input->col++;
2151
51.6k
      }
2152
59.0k
      cur++;
2153
59.0k
      if (res < INT_MAX)
2154
59.0k
    res++;
2155
59.0k
      if (*cur == 0) {
2156
3.69k
    ctxt->input->cur = cur;
2157
3.69k
    xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
2158
3.69k
    cur = ctxt->input->cur;
2159
3.69k
      }
2160
59.0k
  }
2161
195k
  ctxt->input->cur = cur;
2162
195k
    } else {
2163
0
        int expandPE = ((ctxt->external != 0) || (ctxt->inputNr != 1));
2164
2165
0
  while (ctxt->instate != XML_PARSER_EOF) {
2166
0
            if (IS_BLANK_CH(CUR)) { /* CHECKED tstblanks.xml */
2167
0
    NEXT;
2168
0
      } else if (CUR == '%') {
2169
                /*
2170
                 * Need to handle support of entities branching here
2171
                 */
2172
0
          if ((expandPE == 0) || (IS_BLANK_CH(NXT(1))) || (NXT(1) == 0))
2173
0
                    break;
2174
0
          xmlParsePEReference(ctxt);
2175
0
            } else if (CUR == 0) {
2176
0
                unsigned long consumed;
2177
0
                xmlEntityPtr ent;
2178
2179
0
                if (ctxt->inputNr <= 1)
2180
0
                    break;
2181
2182
0
                consumed = ctxt->input->consumed;
2183
0
                xmlSaturatedAddSizeT(&consumed,
2184
0
                                     ctxt->input->cur - ctxt->input->base);
2185
2186
                /*
2187
                 * Add to sizeentities when parsing an external entity
2188
                 * for the first time.
2189
                 */
2190
0
                ent = ctxt->input->entity;
2191
0
                if ((ent->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
2192
0
                    ((ent->flags & XML_ENT_PARSED) == 0)) {
2193
0
                    ent->flags |= XML_ENT_PARSED;
2194
2195
0
                    xmlSaturatedAdd(&ctxt->sizeentities, consumed);
2196
0
                }
2197
2198
0
                xmlParserEntityCheck(ctxt, consumed);
2199
2200
0
                xmlPopInput(ctxt);
2201
0
            } else {
2202
0
                break;
2203
0
            }
2204
2205
            /*
2206
             * Also increase the counter when entering or exiting a PERef.
2207
             * The spec says: "When a parameter-entity reference is recognized
2208
             * in the DTD and included, its replacement text MUST be enlarged
2209
             * by the attachment of one leading and one following space (#x20)
2210
             * character."
2211
             */
2212
0
      if (res < INT_MAX)
2213
0
    res++;
2214
0
        }
2215
0
    }
2216
195k
    return(res);
2217
195k
}
2218
2219
/************************************************************************
2220
 *                  *
2221
 *    Commodity functions to handle entities      *
2222
 *                  *
2223
 ************************************************************************/
2224
2225
/**
2226
 * xmlPopInput:
2227
 * @ctxt:  an XML parser context
2228
 *
2229
 * xmlPopInput: the current input pointed by ctxt->input came to an end
2230
 *          pop it and return the next char.
2231
 *
2232
 * Returns the current xmlChar in the parser context
2233
 */
2234
xmlChar
2235
0
xmlPopInput(xmlParserCtxtPtr ctxt) {
2236
0
    xmlParserInputPtr input;
2237
2238
0
    if ((ctxt == NULL) || (ctxt->inputNr <= 1)) return(0);
2239
0
    if (xmlParserDebugEntities)
2240
0
  xmlGenericError(xmlGenericErrorContext,
2241
0
    "Popping input %d\n", ctxt->inputNr);
2242
0
    if ((ctxt->inputNr > 1) && (ctxt->inSubset == 0) &&
2243
0
        (ctxt->instate != XML_PARSER_EOF))
2244
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
2245
0
                    "Unfinished entity outside the DTD");
2246
0
    input = inputPop(ctxt);
2247
0
    if (input->entity != NULL)
2248
0
        input->entity->flags &= ~XML_ENT_EXPANDING;
2249
0
    xmlFreeInputStream(input);
2250
0
    if (*ctxt->input->cur == 0)
2251
0
        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
2252
0
    return(CUR);
2253
0
}
2254
2255
/**
2256
 * xmlPushInput:
2257
 * @ctxt:  an XML parser context
2258
 * @input:  an XML parser input fragment (entity, XML fragment ...).
2259
 *
2260
 * xmlPushInput: switch to a new input stream which is stacked on top
2261
 *               of the previous one(s).
2262
 * Returns -1 in case of error or the index in the input stack
2263
 */
2264
int
2265
0
xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
2266
0
    int ret;
2267
0
    if (input == NULL) return(-1);
2268
2269
0
    if (xmlParserDebugEntities) {
2270
0
  if ((ctxt->input != NULL) && (ctxt->input->filename))
2271
0
      xmlGenericError(xmlGenericErrorContext,
2272
0
        "%s(%d): ", ctxt->input->filename,
2273
0
        ctxt->input->line);
2274
0
  xmlGenericError(xmlGenericErrorContext,
2275
0
    "Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur);
2276
0
    }
2277
0
    if (((ctxt->inputNr > 40) && ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
2278
0
        (ctxt->inputNr > 100)) {
2279
0
        xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
2280
0
        while (ctxt->inputNr > 1)
2281
0
            xmlFreeInputStream(inputPop(ctxt));
2282
0
  return(-1);
2283
0
    }
2284
0
    ret = inputPush(ctxt, input);
2285
0
    if (ctxt->instate == XML_PARSER_EOF)
2286
0
        return(-1);
2287
0
    GROW;
2288
0
    return(ret);
2289
0
}
2290
2291
/**
2292
 * xmlParseCharRef:
2293
 * @ctxt:  an XML parser context
2294
 *
2295
 * DEPRECATED: Internal function, don't use.
2296
 *
2297
 * Parse a numeric character reference. Always consumes '&'.
2298
 *
2299
 * [66] CharRef ::= '&#' [0-9]+ ';' |
2300
 *                  '&#x' [0-9a-fA-F]+ ';'
2301
 *
2302
 * [ WFC: Legal Character ]
2303
 * Characters referred to using character references must match the
2304
 * production for Char.
2305
 *
2306
 * Returns the value parsed (as an int), 0 in case of error
2307
 */
2308
int
2309
3.69k
xmlParseCharRef(xmlParserCtxtPtr ctxt) {
2310
3.69k
    int val = 0;
2311
3.69k
    int count = 0;
2312
2313
    /*
2314
     * Using RAW/CUR/NEXT is okay since we are working on ASCII range here
2315
     */
2316
3.69k
    if ((RAW == '&') && (NXT(1) == '#') &&
2317
3.69k
        (NXT(2) == 'x')) {
2318
3.69k
  SKIP(3);
2319
3.69k
  GROW;
2320
22.1k
  while (RAW != ';') { /* loop blocked by count */
2321
18.4k
      if (count++ > 20) {
2322
0
    count = 0;
2323
0
    GROW;
2324
0
                if (ctxt->instate == XML_PARSER_EOF)
2325
0
                    return(0);
2326
0
      }
2327
18.4k
      if ((RAW >= '0') && (RAW <= '9'))
2328
14.7k
          val = val * 16 + (CUR - '0');
2329
3.69k
      else if ((RAW >= 'a') && (RAW <= 'f') && (count < 20))
2330
3.69k
          val = val * 16 + (CUR - 'a') + 10;
2331
0
      else if ((RAW >= 'A') && (RAW <= 'F') && (count < 20))
2332
0
          val = val * 16 + (CUR - 'A') + 10;
2333
0
      else {
2334
0
    xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
2335
0
    val = 0;
2336
0
    break;
2337
0
      }
2338
18.4k
      if (val > 0x110000)
2339
0
          val = 0x110000;
2340
2341
18.4k
      NEXT;
2342
18.4k
      count++;
2343
18.4k
  }
2344
3.69k
  if (RAW == ';') {
2345
      /* on purpose to avoid reentrancy problems with NEXT and SKIP */
2346
3.69k
      ctxt->input->col++;
2347
3.69k
      ctxt->input->cur++;
2348
3.69k
  }
2349
3.69k
    } else if  ((RAW == '&') && (NXT(1) == '#')) {
2350
0
  SKIP(2);
2351
0
  GROW;
2352
0
  while (RAW != ';') { /* loop blocked by count */
2353
0
      if (count++ > 20) {
2354
0
    count = 0;
2355
0
    GROW;
2356
0
                if (ctxt->instate == XML_PARSER_EOF)
2357
0
                    return(0);
2358
0
      }
2359
0
      if ((RAW >= '0') && (RAW <= '9'))
2360
0
          val = val * 10 + (CUR - '0');
2361
0
      else {
2362
0
    xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
2363
0
    val = 0;
2364
0
    break;
2365
0
      }
2366
0
      if (val > 0x110000)
2367
0
          val = 0x110000;
2368
2369
0
      NEXT;
2370
0
      count++;
2371
0
  }
2372
0
  if (RAW == ';') {
2373
      /* on purpose to avoid reentrancy problems with NEXT and SKIP */
2374
0
      ctxt->input->col++;
2375
0
      ctxt->input->cur++;
2376
0
  }
2377
0
    } else {
2378
0
        if (RAW == '&')
2379
0
            SKIP(1);
2380
0
        xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
2381
0
    }
2382
2383
    /*
2384
     * [ WFC: Legal Character ]
2385
     * Characters referred to using character references must match the
2386
     * production for Char.
2387
     */
2388
3.69k
    if (val >= 0x110000) {
2389
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2390
0
                "xmlParseCharRef: character reference out of bounds\n",
2391
0
          val);
2392
3.69k
    } else if (IS_CHAR(val)) {
2393
3.69k
        return(val);
2394
3.69k
    } else {
2395
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2396
0
                          "xmlParseCharRef: invalid xmlChar value %d\n",
2397
0
                    val);
2398
0
    }
2399
0
    return(0);
2400
3.69k
}
2401
2402
/**
2403
 * xmlParseStringCharRef:
2404
 * @ctxt:  an XML parser context
2405
 * @str:  a pointer to an index in the string
2406
 *
2407
 * parse Reference declarations, variant parsing from a string rather
2408
 * than an an input flow.
2409
 *
2410
 * [66] CharRef ::= '&#' [0-9]+ ';' |
2411
 *                  '&#x' [0-9a-fA-F]+ ';'
2412
 *
2413
 * [ WFC: Legal Character ]
2414
 * Characters referred to using character references must match the
2415
 * production for Char.
2416
 *
2417
 * Returns the value parsed (as an int), 0 in case of error, str will be
2418
 *         updated to the current value of the index
2419
 */
2420
static int
2421
0
xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
2422
0
    const xmlChar *ptr;
2423
0
    xmlChar cur;
2424
0
    int val = 0;
2425
2426
0
    if ((str == NULL) || (*str == NULL)) return(0);
2427
0
    ptr = *str;
2428
0
    cur = *ptr;
2429
0
    if ((cur == '&') && (ptr[1] == '#') && (ptr[2] == 'x')) {
2430
0
  ptr += 3;
2431
0
  cur = *ptr;
2432
0
  while (cur != ';') { /* Non input consuming loop */
2433
0
      if ((cur >= '0') && (cur <= '9'))
2434
0
          val = val * 16 + (cur - '0');
2435
0
      else if ((cur >= 'a') && (cur <= 'f'))
2436
0
          val = val * 16 + (cur - 'a') + 10;
2437
0
      else if ((cur >= 'A') && (cur <= 'F'))
2438
0
          val = val * 16 + (cur - 'A') + 10;
2439
0
      else {
2440
0
    xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
2441
0
    val = 0;
2442
0
    break;
2443
0
      }
2444
0
      if (val > 0x110000)
2445
0
          val = 0x110000;
2446
2447
0
      ptr++;
2448
0
      cur = *ptr;
2449
0
  }
2450
0
  if (cur == ';')
2451
0
      ptr++;
2452
0
    } else if  ((cur == '&') && (ptr[1] == '#')){
2453
0
  ptr += 2;
2454
0
  cur = *ptr;
2455
0
  while (cur != ';') { /* Non input consuming loops */
2456
0
      if ((cur >= '0') && (cur <= '9'))
2457
0
          val = val * 10 + (cur - '0');
2458
0
      else {
2459
0
    xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
2460
0
    val = 0;
2461
0
    break;
2462
0
      }
2463
0
      if (val > 0x110000)
2464
0
          val = 0x110000;
2465
2466
0
      ptr++;
2467
0
      cur = *ptr;
2468
0
  }
2469
0
  if (cur == ';')
2470
0
      ptr++;
2471
0
    } else {
2472
0
  xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
2473
0
  return(0);
2474
0
    }
2475
0
    *str = ptr;
2476
2477
    /*
2478
     * [ WFC: Legal Character ]
2479
     * Characters referred to using character references must match the
2480
     * production for Char.
2481
     */
2482
0
    if (val >= 0x110000) {
2483
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2484
0
                "xmlParseStringCharRef: character reference out of bounds\n",
2485
0
                val);
2486
0
    } else if (IS_CHAR(val)) {
2487
0
        return(val);
2488
0
    } else {
2489
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2490
0
        "xmlParseStringCharRef: invalid xmlChar value %d\n",
2491
0
        val);
2492
0
    }
2493
0
    return(0);
2494
0
}
2495
2496
/**
2497
 * xmlParserHandlePEReference:
2498
 * @ctxt:  the parser context
2499
 *
2500
 * [69] PEReference ::= '%' Name ';'
2501
 *
2502
 * [ WFC: No Recursion ]
2503
 * A parsed entity must not contain a recursive
2504
 * reference to itself, either directly or indirectly.
2505
 *
2506
 * [ WFC: Entity Declared ]
2507
 * In a document without any DTD, a document with only an internal DTD
2508
 * subset which contains no parameter entity references, or a document
2509
 * with "standalone='yes'", ...  ... The declaration of a parameter
2510
 * entity must precede any reference to it...
2511
 *
2512
 * [ VC: Entity Declared ]
2513
 * In a document with an external subset or external parameter entities
2514
 * with "standalone='no'", ...  ... The declaration of a parameter entity
2515
 * must precede any reference to it...
2516
 *
2517
 * [ WFC: In DTD ]
2518
 * Parameter-entity references may only appear in the DTD.
2519
 * NOTE: misleading but this is handled.
2520
 *
2521
 * A PEReference may have been detected in the current input stream
2522
 * the handling is done accordingly to
2523
 *      http://www.w3.org/TR/REC-xml#entproc
2524
 * i.e.
2525
 *   - Included in literal in entity values
2526
 *   - Included as Parameter Entity reference within DTDs
2527
 */
2528
void
2529
0
xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
2530
0
    switch(ctxt->instate) {
2531
0
  case XML_PARSER_CDATA_SECTION:
2532
0
      return;
2533
0
        case XML_PARSER_COMMENT:
2534
0
      return;
2535
0
  case XML_PARSER_START_TAG:
2536
0
      return;
2537
0
  case XML_PARSER_END_TAG:
2538
0
      return;
2539
0
        case XML_PARSER_EOF:
2540
0
      xmlFatalErr(ctxt, XML_ERR_PEREF_AT_EOF, NULL);
2541
0
      return;
2542
0
        case XML_PARSER_PROLOG:
2543
0
  case XML_PARSER_START:
2544
0
  case XML_PARSER_MISC:
2545
0
      xmlFatalErr(ctxt, XML_ERR_PEREF_IN_PROLOG, NULL);
2546
0
      return;
2547
0
  case XML_PARSER_ENTITY_DECL:
2548
0
        case XML_PARSER_CONTENT:
2549
0
        case XML_PARSER_ATTRIBUTE_VALUE:
2550
0
        case XML_PARSER_PI:
2551
0
  case XML_PARSER_SYSTEM_LITERAL:
2552
0
  case XML_PARSER_PUBLIC_LITERAL:
2553
      /* we just ignore it there */
2554
0
      return;
2555
0
        case XML_PARSER_EPILOG:
2556
0
      xmlFatalErr(ctxt, XML_ERR_PEREF_IN_EPILOG, NULL);
2557
0
      return;
2558
0
  case XML_PARSER_ENTITY_VALUE:
2559
      /*
2560
       * NOTE: in the case of entity values, we don't do the
2561
       *       substitution here since we need the literal
2562
       *       entity value to be able to save the internal
2563
       *       subset of the document.
2564
       *       This will be handled by xmlStringDecodeEntities
2565
       */
2566
0
      return;
2567
0
        case XML_PARSER_DTD:
2568
      /*
2569
       * [WFC: Well-Formedness Constraint: PEs in Internal Subset]
2570
       * In the internal DTD subset, parameter-entity references
2571
       * can occur only where markup declarations can occur, not
2572
       * within markup declarations.
2573
       * In that case this is handled in xmlParseMarkupDecl
2574
       */
2575
0
      if ((ctxt->external == 0) && (ctxt->inputNr == 1))
2576
0
    return;
2577
0
      if (IS_BLANK_CH(NXT(1)) || NXT(1) == 0)
2578
0
    return;
2579
0
            break;
2580
0
        case XML_PARSER_IGNORE:
2581
0
            return;
2582
0
    }
2583
2584
0
    xmlParsePEReference(ctxt);
2585
0
}
2586
2587
/*
2588
 * Macro used to grow the current buffer.
2589
 * buffer##_size is expected to be a size_t
2590
 * mem_error: is expected to handle memory allocation failures
2591
 */
2592
0
#define growBuffer(buffer, n) {           \
2593
0
    xmlChar *tmp;             \
2594
0
    size_t new_size = buffer##_size * 2 + n;                            \
2595
0
    if (new_size < buffer##_size) goto mem_error;                       \
2596
0
    tmp = (xmlChar *) xmlRealloc(buffer, new_size);                     \
2597
0
    if (tmp == NULL) goto mem_error;         \
2598
0
    buffer = tmp;             \
2599
0
    buffer##_size = new_size;                                           \
2600
0
}
2601
2602
/**
2603
 * xmlStringDecodeEntitiesInt:
2604
 * @ctxt:  the parser context
2605
 * @str:  the input string
2606
 * @len: the string length
2607
 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
2608
 * @end:  an end marker xmlChar, 0 if none
2609
 * @end2:  an end marker xmlChar, 0 if none
2610
 * @end3:  an end marker xmlChar, 0 if none
2611
 * @check:  whether to perform entity checks
2612
 */
2613
static xmlChar *
2614
xmlStringDecodeEntitiesInt(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
2615
               int what, xmlChar end, xmlChar  end2, xmlChar end3,
2616
0
                           int check) {
2617
0
    xmlChar *buffer = NULL;
2618
0
    size_t buffer_size = 0;
2619
0
    size_t nbchars = 0;
2620
2621
0
    xmlChar *current = NULL;
2622
0
    xmlChar *rep = NULL;
2623
0
    const xmlChar *last;
2624
0
    xmlEntityPtr ent;
2625
0
    int c,l;
2626
2627
0
    if (str == NULL)
2628
0
        return(NULL);
2629
0
    last = str + len;
2630
2631
0
    if (((ctxt->depth > 40) &&
2632
0
         ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
2633
0
  (ctxt->depth > 100)) {
2634
0
  xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_LOOP,
2635
0
                       "Maximum entity nesting depth exceeded");
2636
0
  return(NULL);
2637
0
    }
2638
2639
    /*
2640
     * allocate a translation buffer.
2641
     */
2642
0
    buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
2643
0
    buffer = (xmlChar *) xmlMallocAtomic(buffer_size);
2644
0
    if (buffer == NULL) goto mem_error;
2645
2646
    /*
2647
     * OK loop until we reach one of the ending char or a size limit.
2648
     * we are operating on already parsed values.
2649
     */
2650
0
    if (str < last)
2651
0
  c = CUR_SCHAR(str, l);
2652
0
    else
2653
0
        c = 0;
2654
0
    while ((c != 0) && (c != end) && /* non input consuming loop */
2655
0
           (c != end2) && (c != end3) &&
2656
0
           (ctxt->instate != XML_PARSER_EOF)) {
2657
2658
0
  if (c == 0) break;
2659
0
        if ((c == '&') && (str[1] == '#')) {
2660
0
      int val = xmlParseStringCharRef(ctxt, &str);
2661
0
      if (val == 0)
2662
0
                goto int_error;
2663
0
      COPY_BUF(0,buffer,nbchars,val);
2664
0
      if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2665
0
          growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2666
0
      }
2667
0
  } else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) {
2668
0
      if (xmlParserDebugEntities)
2669
0
    xmlGenericError(xmlGenericErrorContext,
2670
0
      "String decoding Entity Reference: %.30s\n",
2671
0
      str);
2672
0
      ent = xmlParseStringEntityRef(ctxt, &str);
2673
0
      if ((ent != NULL) &&
2674
0
    (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
2675
0
    if (ent->content != NULL) {
2676
0
        COPY_BUF(0,buffer,nbchars,ent->content[0]);
2677
0
        if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2678
0
      growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2679
0
        }
2680
0
    } else {
2681
0
        xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
2682
0
          "predefined entity has no content\n");
2683
0
                    goto int_error;
2684
0
    }
2685
0
      } else if ((ent != NULL) && (ent->content != NULL)) {
2686
0
          if ((check) && (xmlParserEntityCheck(ctxt, ent->length)))
2687
0
                    goto int_error;
2688
2689
0
                if (ent->flags & XML_ENT_EXPANDING) {
2690
0
              xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
2691
0
                    xmlHaltParser(ctxt);
2692
0
                    ent->content[0] = 0;
2693
0
                    goto int_error;
2694
0
                }
2695
2696
0
                ent->flags |= XML_ENT_EXPANDING;
2697
0
    ctxt->depth++;
2698
0
    rep = xmlStringDecodeEntitiesInt(ctxt, ent->content,
2699
0
                        ent->length, what, 0, 0, 0, check);
2700
0
    ctxt->depth--;
2701
0
                ent->flags &= ~XML_ENT_EXPANDING;
2702
2703
0
    if (rep == NULL) {
2704
0
                    ent->content[0] = 0;
2705
0
                    goto int_error;
2706
0
                }
2707
2708
0
                current = rep;
2709
0
                while (*current != 0) { /* non input consuming loop */
2710
0
                    buffer[nbchars++] = *current++;
2711
0
                    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2712
0
                        growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2713
0
                    }
2714
0
                }
2715
0
                xmlFree(rep);
2716
0
                rep = NULL;
2717
0
      } else if (ent != NULL) {
2718
0
    int i = xmlStrlen(ent->name);
2719
0
    const xmlChar *cur = ent->name;
2720
2721
0
    buffer[nbchars++] = '&';
2722
0
    if (nbchars + i + XML_PARSER_BUFFER_SIZE > buffer_size) {
2723
0
        growBuffer(buffer, i + XML_PARSER_BUFFER_SIZE);
2724
0
    }
2725
0
    for (;i > 0;i--)
2726
0
        buffer[nbchars++] = *cur++;
2727
0
    buffer[nbchars++] = ';';
2728
0
      }
2729
0
  } else if (c == '%' && (what & XML_SUBSTITUTE_PEREF)) {
2730
0
      if (xmlParserDebugEntities)
2731
0
    xmlGenericError(xmlGenericErrorContext,
2732
0
      "String decoding PE Reference: %.30s\n", str);
2733
0
      ent = xmlParseStringPEReference(ctxt, &str);
2734
0
      if (ent != NULL) {
2735
0
                if (ent->content == NULL) {
2736
        /*
2737
         * Note: external parsed entities will not be loaded,
2738
         * it is not required for a non-validating parser to
2739
         * complete external PEReferences coming from the
2740
         * internal subset
2741
         */
2742
0
        if (((ctxt->options & XML_PARSE_NOENT) != 0) ||
2743
0
      ((ctxt->options & XML_PARSE_DTDVALID) != 0) ||
2744
0
      (ctxt->validate != 0)) {
2745
0
      xmlLoadEntityContent(ctxt, ent);
2746
0
        } else {
2747
0
      xmlWarningMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
2748
0
      "not validating will not read content for PE entity %s\n",
2749
0
                          ent->name, NULL);
2750
0
        }
2751
0
    }
2752
2753
0
          if ((check) && (xmlParserEntityCheck(ctxt, ent->length)))
2754
0
                    goto int_error;
2755
2756
0
                if (ent->flags & XML_ENT_EXPANDING) {
2757
0
              xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
2758
0
                    xmlHaltParser(ctxt);
2759
0
                    if (ent->content != NULL)
2760
0
                        ent->content[0] = 0;
2761
0
                    goto int_error;
2762
0
                }
2763
2764
0
                ent->flags |= XML_ENT_EXPANDING;
2765
0
    ctxt->depth++;
2766
0
    rep = xmlStringDecodeEntitiesInt(ctxt, ent->content,
2767
0
                        ent->length, what, 0, 0, 0, check);
2768
0
    ctxt->depth--;
2769
0
                ent->flags &= ~XML_ENT_EXPANDING;
2770
2771
0
    if (rep == NULL) {
2772
0
                    if (ent->content != NULL)
2773
0
                        ent->content[0] = 0;
2774
0
                    goto int_error;
2775
0
                }
2776
0
                current = rep;
2777
0
                while (*current != 0) { /* non input consuming loop */
2778
0
                    buffer[nbchars++] = *current++;
2779
0
                    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2780
0
                        growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2781
0
                    }
2782
0
                }
2783
0
                xmlFree(rep);
2784
0
                rep = NULL;
2785
0
      }
2786
0
  } else {
2787
0
      COPY_BUF(l,buffer,nbchars,c);
2788
0
      str += l;
2789
0
      if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2790
0
          growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2791
0
      }
2792
0
  }
2793
0
  if (str < last)
2794
0
      c = CUR_SCHAR(str, l);
2795
0
  else
2796
0
      c = 0;
2797
0
    }
2798
0
    buffer[nbchars] = 0;
2799
0
    return(buffer);
2800
2801
0
mem_error:
2802
0
    xmlErrMemory(ctxt, NULL);
2803
0
int_error:
2804
0
    if (rep != NULL)
2805
0
        xmlFree(rep);
2806
0
    if (buffer != NULL)
2807
0
        xmlFree(buffer);
2808
0
    return(NULL);
2809
0
}
2810
2811
/**
2812
 * xmlStringLenDecodeEntities:
2813
 * @ctxt:  the parser context
2814
 * @str:  the input string
2815
 * @len: the string length
2816
 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
2817
 * @end:  an end marker xmlChar, 0 if none
2818
 * @end2:  an end marker xmlChar, 0 if none
2819
 * @end3:  an end marker xmlChar, 0 if none
2820
 *
2821
 * DEPRECATED: Internal function, don't use.
2822
 *
2823
 * Takes a entity string content and process to do the adequate substitutions.
2824
 *
2825
 * [67] Reference ::= EntityRef | CharRef
2826
 *
2827
 * [69] PEReference ::= '%' Name ';'
2828
 *
2829
 * Returns A newly allocated string with the substitution done. The caller
2830
 *      must deallocate it !
2831
 */
2832
xmlChar *
2833
xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
2834
                           int what, xmlChar end, xmlChar  end2,
2835
0
                           xmlChar end3) {
2836
0
    if ((ctxt == NULL) || (str == NULL) || (len < 0))
2837
0
        return(NULL);
2838
0
    return(xmlStringDecodeEntitiesInt(ctxt, str, len, what,
2839
0
                                      end, end2, end3, 0));
2840
0
}
2841
2842
/**
2843
 * xmlStringDecodeEntities:
2844
 * @ctxt:  the parser context
2845
 * @str:  the input string
2846
 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
2847
 * @end:  an end marker xmlChar, 0 if none
2848
 * @end2:  an end marker xmlChar, 0 if none
2849
 * @end3:  an end marker xmlChar, 0 if none
2850
 *
2851
 * DEPRECATED: Internal function, don't use.
2852
 *
2853
 * Takes a entity string content and process to do the adequate substitutions.
2854
 *
2855
 * [67] Reference ::= EntityRef | CharRef
2856
 *
2857
 * [69] PEReference ::= '%' Name ';'
2858
 *
2859
 * Returns A newly allocated string with the substitution done. The caller
2860
 *      must deallocate it !
2861
 */
2862
xmlChar *
2863
xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what,
2864
0
            xmlChar end, xmlChar  end2, xmlChar end3) {
2865
0
    if ((ctxt == NULL) || (str == NULL)) return(NULL);
2866
0
    return(xmlStringDecodeEntitiesInt(ctxt, str, xmlStrlen(str), what,
2867
0
                                      end, end2, end3, 0));
2868
0
}
2869
2870
/************************************************************************
2871
 *                  *
2872
 *    Commodity functions, cleanup needed ?     *
2873
 *                  *
2874
 ************************************************************************/
2875
2876
/**
2877
 * areBlanks:
2878
 * @ctxt:  an XML parser context
2879
 * @str:  a xmlChar *
2880
 * @len:  the size of @str
2881
 * @blank_chars: we know the chars are blanks
2882
 *
2883
 * Is this a sequence of blank chars that one can ignore ?
2884
 *
2885
 * Returns 1 if ignorable 0 otherwise.
2886
 */
2887
2888
static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
2889
7.38k
                     int blank_chars) {
2890
7.38k
    int i, ret;
2891
7.38k
    xmlNodePtr lastChild;
2892
2893
    /*
2894
     * Don't spend time trying to differentiate them, the same callback is
2895
     * used !
2896
     */
2897
7.38k
    if (ctxt->sax->ignorableWhitespace == ctxt->sax->characters)
2898
7.38k
  return(0);
2899
2900
    /*
2901
     * Check for xml:space value.
2902
     */
2903
0
    if ((ctxt->space == NULL) || (*(ctxt->space) == 1) ||
2904
0
        (*(ctxt->space) == -2))
2905
0
  return(0);
2906
2907
    /*
2908
     * Check that the string is made of blanks
2909
     */
2910
0
    if (blank_chars == 0) {
2911
0
  for (i = 0;i < len;i++)
2912
0
      if (!(IS_BLANK_CH(str[i]))) return(0);
2913
0
    }
2914
2915
    /*
2916
     * Look if the element is mixed content in the DTD if available
2917
     */
2918
0
    if (ctxt->node == NULL) return(0);
2919
0
    if (ctxt->myDoc != NULL) {
2920
0
  ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name);
2921
0
        if (ret == 0) return(1);
2922
0
        if (ret == 1) return(0);
2923
0
    }
2924
2925
    /*
2926
     * Otherwise, heuristic :-\
2927
     */
2928
0
    if ((RAW != '<') && (RAW != 0xD)) return(0);
2929
0
    if ((ctxt->node->children == NULL) &&
2930
0
  (RAW == '<') && (NXT(1) == '/')) return(0);
2931
2932
0
    lastChild = xmlGetLastChild(ctxt->node);
2933
0
    if (lastChild == NULL) {
2934
0
        if ((ctxt->node->type != XML_ELEMENT_NODE) &&
2935
0
            (ctxt->node->content != NULL)) return(0);
2936
0
    } else if (xmlNodeIsText(lastChild))
2937
0
        return(0);
2938
0
    else if ((ctxt->node->children != NULL) &&
2939
0
             (xmlNodeIsText(ctxt->node->children)))
2940
0
        return(0);
2941
0
    return(1);
2942
0
}
2943
2944
/************************************************************************
2945
 *                  *
2946
 *    Extra stuff for namespace support     *
2947
 *  Relates to http://www.w3.org/TR/WD-xml-names      *
2948
 *                  *
2949
 ************************************************************************/
2950
2951
/**
2952
 * xmlSplitQName:
2953
 * @ctxt:  an XML parser context
2954
 * @name:  an XML parser context
2955
 * @prefix:  a xmlChar **
2956
 *
2957
 * parse an UTF8 encoded XML qualified name string
2958
 *
2959
 * [NS 5] QName ::= (Prefix ':')? LocalPart
2960
 *
2961
 * [NS 6] Prefix ::= NCName
2962
 *
2963
 * [NS 7] LocalPart ::= NCName
2964
 *
2965
 * Returns the local part, and prefix is updated
2966
 *   to get the Prefix if any.
2967
 */
2968
2969
xmlChar *
2970
0
xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
2971
0
    xmlChar buf[XML_MAX_NAMELEN + 5];
2972
0
    xmlChar *buffer = NULL;
2973
0
    int len = 0;
2974
0
    int max = XML_MAX_NAMELEN;
2975
0
    xmlChar *ret = NULL;
2976
0
    const xmlChar *cur = name;
2977
0
    int c;
2978
2979
0
    if (prefix == NULL) return(NULL);
2980
0
    *prefix = NULL;
2981
2982
0
    if (cur == NULL) return(NULL);
2983
2984
#ifndef XML_XML_NAMESPACE
2985
    /* xml: prefix is not really a namespace */
2986
    if ((cur[0] == 'x') && (cur[1] == 'm') &&
2987
        (cur[2] == 'l') && (cur[3] == ':'))
2988
  return(xmlStrdup(name));
2989
#endif
2990
2991
    /* nasty but well=formed */
2992
0
    if (cur[0] == ':')
2993
0
  return(xmlStrdup(name));
2994
2995
0
    c = *cur++;
2996
0
    while ((c != 0) && (c != ':') && (len < max)) { /* tested bigname.xml */
2997
0
  buf[len++] = c;
2998
0
  c = *cur++;
2999
0
    }
3000
0
    if (len >= max) {
3001
  /*
3002
   * Okay someone managed to make a huge name, so he's ready to pay
3003
   * for the processing speed.
3004
   */
3005
0
  max = len * 2;
3006
3007
0
  buffer = (xmlChar *) xmlMallocAtomic(max);
3008
0
  if (buffer == NULL) {
3009
0
      xmlErrMemory(ctxt, NULL);
3010
0
      return(NULL);
3011
0
  }
3012
0
  memcpy(buffer, buf, len);
3013
0
  while ((c != 0) && (c != ':')) { /* tested bigname.xml */
3014
0
      if (len + 10 > max) {
3015
0
          xmlChar *tmp;
3016
3017
0
    max *= 2;
3018
0
    tmp = (xmlChar *) xmlRealloc(buffer, max);
3019
0
    if (tmp == NULL) {
3020
0
        xmlFree(buffer);
3021
0
        xmlErrMemory(ctxt, NULL);
3022
0
        return(NULL);
3023
0
    }
3024
0
    buffer = tmp;
3025
0
      }
3026
0
      buffer[len++] = c;
3027
0
      c = *cur++;
3028
0
  }
3029
0
  buffer[len] = 0;
3030
0
    }
3031
3032
0
    if ((c == ':') && (*cur == 0)) {
3033
0
        if (buffer != NULL)
3034
0
      xmlFree(buffer);
3035
0
  *prefix = NULL;
3036
0
  return(xmlStrdup(name));
3037
0
    }
3038
3039
0
    if (buffer == NULL)
3040
0
  ret = xmlStrndup(buf, len);
3041
0
    else {
3042
0
  ret = buffer;
3043
0
  buffer = NULL;
3044
0
  max = XML_MAX_NAMELEN;
3045
0
    }
3046
3047
3048
0
    if (c == ':') {
3049
0
  c = *cur;
3050
0
        *prefix = ret;
3051
0
  if (c == 0) {
3052
0
      return(xmlStrndup(BAD_CAST "", 0));
3053
0
  }
3054
0
  len = 0;
3055
3056
  /*
3057
   * Check that the first character is proper to start
3058
   * a new name
3059
   */
3060
0
  if (!(((c >= 0x61) && (c <= 0x7A)) ||
3061
0
        ((c >= 0x41) && (c <= 0x5A)) ||
3062
0
        (c == '_') || (c == ':'))) {
3063
0
      int l;
3064
0
      int first = CUR_SCHAR(cur, l);
3065
3066
0
      if (!IS_LETTER(first) && (first != '_')) {
3067
0
    xmlFatalErrMsgStr(ctxt, XML_NS_ERR_QNAME,
3068
0
          "Name %s is not XML Namespace compliant\n",
3069
0
          name);
3070
0
      }
3071
0
  }
3072
0
  cur++;
3073
3074
0
  while ((c != 0) && (len < max)) { /* tested bigname2.xml */
3075
0
      buf[len++] = c;
3076
0
      c = *cur++;
3077
0
  }
3078
0
  if (len >= max) {
3079
      /*
3080
       * Okay someone managed to make a huge name, so he's ready to pay
3081
       * for the processing speed.
3082
       */
3083
0
      max = len * 2;
3084
3085
0
      buffer = (xmlChar *) xmlMallocAtomic(max);
3086
0
      if (buffer == NULL) {
3087
0
          xmlErrMemory(ctxt, NULL);
3088
0
    return(NULL);
3089
0
      }
3090
0
      memcpy(buffer, buf, len);
3091
0
      while (c != 0) { /* tested bigname2.xml */
3092
0
    if (len + 10 > max) {
3093
0
        xmlChar *tmp;
3094
3095
0
        max *= 2;
3096
0
        tmp = (xmlChar *) xmlRealloc(buffer, max);
3097
0
        if (tmp == NULL) {
3098
0
      xmlErrMemory(ctxt, NULL);
3099
0
      xmlFree(buffer);
3100
0
      return(NULL);
3101
0
        }
3102
0
        buffer = tmp;
3103
0
    }
3104
0
    buffer[len++] = c;
3105
0
    c = *cur++;
3106
0
      }
3107
0
      buffer[len] = 0;
3108
0
  }
3109
3110
0
  if (buffer == NULL)
3111
0
      ret = xmlStrndup(buf, len);
3112
0
  else {
3113
0
      ret = buffer;
3114
0
  }
3115
0
    }
3116
3117
0
    return(ret);
3118
0
}
3119
3120
/************************************************************************
3121
 *                  *
3122
 *      The parser itself       *
3123
 *  Relates to http://www.w3.org/TR/REC-xml       *
3124
 *                  *
3125
 ************************************************************************/
3126
3127
/************************************************************************
3128
 *                  *
3129
 *  Routines to parse Name, NCName and NmToken      *
3130
 *                  *
3131
 ************************************************************************/
3132
#ifdef DEBUG
3133
static unsigned long nbParseName = 0;
3134
static unsigned long nbParseNmToken = 0;
3135
static unsigned long nbParseNCName = 0;
3136
static unsigned long nbParseNCNameComplex = 0;
3137
static unsigned long nbParseNameComplex = 0;
3138
static unsigned long nbParseStringName = 0;
3139
#endif
3140
3141
/*
3142
 * The two following functions are related to the change of accepted
3143
 * characters for Name and NmToken in the Revision 5 of XML-1.0
3144
 * They correspond to the modified production [4] and the new production [4a]
3145
 * changes in that revision. Also note that the macros used for the
3146
 * productions Letter, Digit, CombiningChar and Extender are not needed
3147
 * anymore.
3148
 * We still keep compatibility to pre-revision5 parsing semantic if the
3149
 * new XML_PARSE_OLD10 option is given to the parser.
3150
 */
3151
static int
3152
0
xmlIsNameStartChar(xmlParserCtxtPtr ctxt, int c) {
3153
0
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3154
        /*
3155
   * Use the new checks of production [4] [4a] amd [5] of the
3156
   * Update 5 of XML-1.0
3157
   */
3158
0
  if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3159
0
      (((c >= 'a') && (c <= 'z')) ||
3160
0
       ((c >= 'A') && (c <= 'Z')) ||
3161
0
       (c == '_') || (c == ':') ||
3162
0
       ((c >= 0xC0) && (c <= 0xD6)) ||
3163
0
       ((c >= 0xD8) && (c <= 0xF6)) ||
3164
0
       ((c >= 0xF8) && (c <= 0x2FF)) ||
3165
0
       ((c >= 0x370) && (c <= 0x37D)) ||
3166
0
       ((c >= 0x37F) && (c <= 0x1FFF)) ||
3167
0
       ((c >= 0x200C) && (c <= 0x200D)) ||
3168
0
       ((c >= 0x2070) && (c <= 0x218F)) ||
3169
0
       ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3170
0
       ((c >= 0x3001) && (c <= 0xD7FF)) ||
3171
0
       ((c >= 0xF900) && (c <= 0xFDCF)) ||
3172
0
       ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3173
0
       ((c >= 0x10000) && (c <= 0xEFFFF))))
3174
0
      return(1);
3175
0
    } else {
3176
0
        if (IS_LETTER(c) || (c == '_') || (c == ':'))
3177
0
      return(1);
3178
0
    }
3179
0
    return(0);
3180
0
}
3181
3182
static int
3183
0
xmlIsNameChar(xmlParserCtxtPtr ctxt, int c) {
3184
0
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3185
        /*
3186
   * Use the new checks of production [4] [4a] amd [5] of the
3187
   * Update 5 of XML-1.0
3188
   */
3189
0
  if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3190
0
      (((c >= 'a') && (c <= 'z')) ||
3191
0
       ((c >= 'A') && (c <= 'Z')) ||
3192
0
       ((c >= '0') && (c <= '9')) || /* !start */
3193
0
       (c == '_') || (c == ':') ||
3194
0
       (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3195
0
       ((c >= 0xC0) && (c <= 0xD6)) ||
3196
0
       ((c >= 0xD8) && (c <= 0xF6)) ||
3197
0
       ((c >= 0xF8) && (c <= 0x2FF)) ||
3198
0
       ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3199
0
       ((c >= 0x370) && (c <= 0x37D)) ||
3200
0
       ((c >= 0x37F) && (c <= 0x1FFF)) ||
3201
0
       ((c >= 0x200C) && (c <= 0x200D)) ||
3202
0
       ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3203
0
       ((c >= 0x2070) && (c <= 0x218F)) ||
3204
0
       ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3205
0
       ((c >= 0x3001) && (c <= 0xD7FF)) ||
3206
0
       ((c >= 0xF900) && (c <= 0xFDCF)) ||
3207
0
       ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3208
0
       ((c >= 0x10000) && (c <= 0xEFFFF))))
3209
0
       return(1);
3210
0
    } else {
3211
0
        if ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3212
0
            (c == '.') || (c == '-') ||
3213
0
      (c == '_') || (c == ':') ||
3214
0
      (IS_COMBINING(c)) ||
3215
0
      (IS_EXTENDER(c)))
3216
0
      return(1);
3217
0
    }
3218
0
    return(0);
3219
0
}
3220
3221
static xmlChar * xmlParseAttValueInternal(xmlParserCtxtPtr ctxt,
3222
                                          int *len, int *alloc, int normalize);
3223
3224
static const xmlChar *
3225
0
xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
3226
0
    int len = 0, l;
3227
0
    int c;
3228
0
    int count = 0;
3229
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3230
0
                    XML_MAX_TEXT_LENGTH :
3231
0
                    XML_MAX_NAME_LENGTH;
3232
3233
#ifdef DEBUG
3234
    nbParseNameComplex++;
3235
#endif
3236
3237
    /*
3238
     * Handler for more complex cases
3239
     */
3240
0
    GROW;
3241
0
    if (ctxt->instate == XML_PARSER_EOF)
3242
0
        return(NULL);
3243
0
    c = CUR_CHAR(l);
3244
0
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3245
        /*
3246
   * Use the new checks of production [4] [4a] amd [5] of the
3247
   * Update 5 of XML-1.0
3248
   */
3249
0
  if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3250
0
      (!(((c >= 'a') && (c <= 'z')) ||
3251
0
         ((c >= 'A') && (c <= 'Z')) ||
3252
0
         (c == '_') || (c == ':') ||
3253
0
         ((c >= 0xC0) && (c <= 0xD6)) ||
3254
0
         ((c >= 0xD8) && (c <= 0xF6)) ||
3255
0
         ((c >= 0xF8) && (c <= 0x2FF)) ||
3256
0
         ((c >= 0x370) && (c <= 0x37D)) ||
3257
0
         ((c >= 0x37F) && (c <= 0x1FFF)) ||
3258
0
         ((c >= 0x200C) && (c <= 0x200D)) ||
3259
0
         ((c >= 0x2070) && (c <= 0x218F)) ||
3260
0
         ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3261
0
         ((c >= 0x3001) && (c <= 0xD7FF)) ||
3262
0
         ((c >= 0xF900) && (c <= 0xFDCF)) ||
3263
0
         ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3264
0
         ((c >= 0x10000) && (c <= 0xEFFFF))))) {
3265
0
      return(NULL);
3266
0
  }
3267
0
  len += l;
3268
0
  NEXTL(l);
3269
0
  c = CUR_CHAR(l);
3270
0
  while ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3271
0
         (((c >= 'a') && (c <= 'z')) ||
3272
0
          ((c >= 'A') && (c <= 'Z')) ||
3273
0
          ((c >= '0') && (c <= '9')) || /* !start */
3274
0
          (c == '_') || (c == ':') ||
3275
0
          (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3276
0
          ((c >= 0xC0) && (c <= 0xD6)) ||
3277
0
          ((c >= 0xD8) && (c <= 0xF6)) ||
3278
0
          ((c >= 0xF8) && (c <= 0x2FF)) ||
3279
0
          ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3280
0
          ((c >= 0x370) && (c <= 0x37D)) ||
3281
0
          ((c >= 0x37F) && (c <= 0x1FFF)) ||
3282
0
          ((c >= 0x200C) && (c <= 0x200D)) ||
3283
0
          ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3284
0
          ((c >= 0x2070) && (c <= 0x218F)) ||
3285
0
          ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3286
0
          ((c >= 0x3001) && (c <= 0xD7FF)) ||
3287
0
          ((c >= 0xF900) && (c <= 0xFDCF)) ||
3288
0
          ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3289
0
          ((c >= 0x10000) && (c <= 0xEFFFF))
3290
0
    )) {
3291
0
      if (count++ > XML_PARSER_CHUNK_SIZE) {
3292
0
    count = 0;
3293
0
    GROW;
3294
0
                if (ctxt->instate == XML_PARSER_EOF)
3295
0
                    return(NULL);
3296
0
      }
3297
0
            if (len <= INT_MAX - l)
3298
0
          len += l;
3299
0
      NEXTL(l);
3300
0
      c = CUR_CHAR(l);
3301
0
  }
3302
0
    } else {
3303
0
  if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3304
0
      (!IS_LETTER(c) && (c != '_') &&
3305
0
       (c != ':'))) {
3306
0
      return(NULL);
3307
0
  }
3308
0
  len += l;
3309
0
  NEXTL(l);
3310
0
  c = CUR_CHAR(l);
3311
3312
0
  while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
3313
0
         ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3314
0
    (c == '.') || (c == '-') ||
3315
0
    (c == '_') || (c == ':') ||
3316
0
    (IS_COMBINING(c)) ||
3317
0
    (IS_EXTENDER(c)))) {
3318
0
      if (count++ > XML_PARSER_CHUNK_SIZE) {
3319
0
    count = 0;
3320
0
    GROW;
3321
0
                if (ctxt->instate == XML_PARSER_EOF)
3322
0
                    return(NULL);
3323
0
      }
3324
0
            if (len <= INT_MAX - l)
3325
0
          len += l;
3326
0
      NEXTL(l);
3327
0
      c = CUR_CHAR(l);
3328
0
  }
3329
0
    }
3330
0
    if (len > maxLength) {
3331
0
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
3332
0
        return(NULL);
3333
0
    }
3334
0
    if (ctxt->input->cur - ctxt->input->base < len) {
3335
        /*
3336
         * There were a couple of bugs where PERefs lead to to a change
3337
         * of the buffer. Check the buffer size to avoid passing an invalid
3338
         * pointer to xmlDictLookup.
3339
         */
3340
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
3341
0
                    "unexpected change of input buffer");
3342
0
        return (NULL);
3343
0
    }
3344
0
    if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r'))
3345
0
        return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len));
3346
0
    return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
3347
0
}
3348
3349
/**
3350
 * xmlParseName:
3351
 * @ctxt:  an XML parser context
3352
 *
3353
 * DEPRECATED: Internal function, don't use.
3354
 *
3355
 * parse an XML name.
3356
 *
3357
 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3358
 *                  CombiningChar | Extender
3359
 *
3360
 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3361
 *
3362
 * [6] Names ::= Name (#x20 Name)*
3363
 *
3364
 * Returns the Name parsed or NULL
3365
 */
3366
3367
const xmlChar *
3368
7.38k
xmlParseName(xmlParserCtxtPtr ctxt) {
3369
7.38k
    const xmlChar *in;
3370
7.38k
    const xmlChar *ret;
3371
7.38k
    size_t count = 0;
3372
7.38k
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3373
0
                       XML_MAX_TEXT_LENGTH :
3374
7.38k
                       XML_MAX_NAME_LENGTH;
3375
3376
7.38k
    GROW;
3377
3378
#ifdef DEBUG
3379
    nbParseName++;
3380
#endif
3381
3382
    /*
3383
     * Accelerator for simple ASCII names
3384
     */
3385
7.38k
    in = ctxt->input->cur;
3386
7.38k
    if (((*in >= 0x61) && (*in <= 0x7A)) ||
3387
7.38k
  ((*in >= 0x41) && (*in <= 0x5A)) ||
3388
7.38k
  (*in == '_') || (*in == ':')) {
3389
7.38k
  in++;
3390
14.7k
  while (((*in >= 0x61) && (*in <= 0x7A)) ||
3391
14.7k
         ((*in >= 0x41) && (*in <= 0x5A)) ||
3392
14.7k
         ((*in >= 0x30) && (*in <= 0x39)) ||
3393
14.7k
         (*in == '_') || (*in == '-') ||
3394
14.7k
         (*in == ':') || (*in == '.'))
3395
7.38k
      in++;
3396
7.38k
  if ((*in > 0) && (*in < 0x80)) {
3397
7.38k
      count = in - ctxt->input->cur;
3398
7.38k
            if (count > maxLength) {
3399
0
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
3400
0
                return(NULL);
3401
0
            }
3402
7.38k
      ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
3403
7.38k
      ctxt->input->cur = in;
3404
7.38k
      ctxt->input->col += count;
3405
7.38k
      if (ret == NULL)
3406
0
          xmlErrMemory(ctxt, NULL);
3407
7.38k
      return(ret);
3408
7.38k
  }
3409
7.38k
    }
3410
    /* accelerator for special cases */
3411
0
    return(xmlParseNameComplex(ctxt));
3412
7.38k
}
3413
3414
static const xmlChar *
3415
0
xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
3416
0
    int len = 0, l;
3417
0
    int c;
3418
0
    int count = 0;
3419
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3420
0
                    XML_MAX_TEXT_LENGTH :
3421
0
                    XML_MAX_NAME_LENGTH;
3422
0
    size_t startPosition = 0;
3423
3424
#ifdef DEBUG
3425
    nbParseNCNameComplex++;
3426
#endif
3427
3428
    /*
3429
     * Handler for more complex cases
3430
     */
3431
0
    GROW;
3432
0
    startPosition = CUR_PTR - BASE_PTR;
3433
0
    c = CUR_CHAR(l);
3434
0
    if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3435
0
  (!xmlIsNameStartChar(ctxt, c) || (c == ':'))) {
3436
0
  return(NULL);
3437
0
    }
3438
3439
0
    while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
3440
0
     (xmlIsNameChar(ctxt, c) && (c != ':'))) {
3441
0
  if (count++ > XML_PARSER_CHUNK_SIZE) {
3442
0
      count = 0;
3443
0
      GROW;
3444
0
            if (ctxt->instate == XML_PARSER_EOF)
3445
0
                return(NULL);
3446
0
  }
3447
0
        if (len <= INT_MAX - l)
3448
0
      len += l;
3449
0
  NEXTL(l);
3450
0
  c = CUR_CHAR(l);
3451
0
  if (c == 0) {
3452
0
      count = 0;
3453
      /*
3454
       * when shrinking to extend the buffer we really need to preserve
3455
       * the part of the name we already parsed. Hence rolling back
3456
       * by current length.
3457
       */
3458
0
      ctxt->input->cur -= l;
3459
0
      GROW;
3460
0
            if (ctxt->instate == XML_PARSER_EOF)
3461
0
                return(NULL);
3462
0
      ctxt->input->cur += l;
3463
0
      c = CUR_CHAR(l);
3464
0
  }
3465
0
    }
3466
0
    if (len > maxLength) {
3467
0
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3468
0
        return(NULL);
3469
0
    }
3470
0
    return(xmlDictLookup(ctxt->dict, (BASE_PTR + startPosition), len));
3471
0
}
3472
3473
/**
3474
 * xmlParseNCName:
3475
 * @ctxt:  an XML parser context
3476
 * @len:  length of the string parsed
3477
 *
3478
 * parse an XML name.
3479
 *
3480
 * [4NS] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
3481
 *                      CombiningChar | Extender
3482
 *
3483
 * [5NS] NCName ::= (Letter | '_') (NCNameChar)*
3484
 *
3485
 * Returns the Name parsed or NULL
3486
 */
3487
3488
static const xmlChar *
3489
125k
xmlParseNCName(xmlParserCtxtPtr ctxt) {
3490
125k
    const xmlChar *in, *e;
3491
125k
    const xmlChar *ret;
3492
125k
    size_t count = 0;
3493
125k
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3494
0
                       XML_MAX_TEXT_LENGTH :
3495
125k
                       XML_MAX_NAME_LENGTH;
3496
3497
#ifdef DEBUG
3498
    nbParseNCName++;
3499
#endif
3500
3501
    /*
3502
     * Accelerator for simple ASCII names
3503
     */
3504
125k
    in = ctxt->input->cur;
3505
125k
    e = ctxt->input->end;
3506
125k
    if ((((*in >= 0x61) && (*in <= 0x7A)) ||
3507
125k
   ((*in >= 0x41) && (*in <= 0x5A)) ||
3508
125k
   (*in == '_')) && (in < e)) {
3509
125k
  in++;
3510
173k
  while ((((*in >= 0x61) && (*in <= 0x7A)) ||
3511
173k
          ((*in >= 0x41) && (*in <= 0x5A)) ||
3512
173k
          ((*in >= 0x30) && (*in <= 0x39)) ||
3513
173k
          (*in == '_') || (*in == '-') ||
3514
173k
          (*in == '.')) && (in < e))
3515
47.9k
      in++;
3516
125k
  if (in >= e)
3517
0
      goto complex;
3518
125k
  if ((*in > 0) && (*in < 0x80)) {
3519
125k
      count = in - ctxt->input->cur;
3520
125k
            if (count > maxLength) {
3521
0
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3522
0
                return(NULL);
3523
0
            }
3524
125k
      ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
3525
125k
      ctxt->input->cur = in;
3526
125k
      ctxt->input->col += count;
3527
125k
      if (ret == NULL) {
3528
0
          xmlErrMemory(ctxt, NULL);
3529
0
      }
3530
125k
      return(ret);
3531
125k
  }
3532
125k
    }
3533
0
complex:
3534
0
    return(xmlParseNCNameComplex(ctxt));
3535
125k
}
3536
3537
/**
3538
 * xmlParseNameAndCompare:
3539
 * @ctxt:  an XML parser context
3540
 *
3541
 * parse an XML name and compares for match
3542
 * (specialized for endtag parsing)
3543
 *
3544
 * Returns NULL for an illegal name, (xmlChar*) 1 for success
3545
 * and the name for mismatch
3546
 */
3547
3548
static const xmlChar *
3549
14.7k
xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) {
3550
14.7k
    register const xmlChar *cmp = other;
3551
14.7k
    register const xmlChar *in;
3552
14.7k
    const xmlChar *ret;
3553
3554
14.7k
    GROW;
3555
14.7k
    if (ctxt->instate == XML_PARSER_EOF)
3556
0
        return(NULL);
3557
3558
14.7k
    in = ctxt->input->cur;
3559
29.5k
    while (*in != 0 && *in == *cmp) {
3560
14.7k
  ++in;
3561
14.7k
  ++cmp;
3562
14.7k
    }
3563
14.7k
    if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
3564
  /* success */
3565
14.7k
  ctxt->input->col += in - ctxt->input->cur;
3566
14.7k
  ctxt->input->cur = in;
3567
14.7k
  return (const xmlChar*) 1;
3568
14.7k
    }
3569
    /* failure (or end of input buffer), check with full function */
3570
0
    ret = xmlParseName (ctxt);
3571
    /* strings coming from the dictionary direct compare possible */
3572
0
    if (ret == other) {
3573
0
  return (const xmlChar*) 1;
3574
0
    }
3575
0
    return ret;
3576
0
}
3577
3578
/**
3579
 * xmlParseStringName:
3580
 * @ctxt:  an XML parser context
3581
 * @str:  a pointer to the string pointer (IN/OUT)
3582
 *
3583
 * parse an XML name.
3584
 *
3585
 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3586
 *                  CombiningChar | Extender
3587
 *
3588
 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3589
 *
3590
 * [6] Names ::= Name (#x20 Name)*
3591
 *
3592
 * Returns the Name parsed or NULL. The @str pointer
3593
 * is updated to the current location in the string.
3594
 */
3595
3596
static xmlChar *
3597
0
xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
3598
0
    xmlChar buf[XML_MAX_NAMELEN + 5];
3599
0
    const xmlChar *cur = *str;
3600
0
    int len = 0, l;
3601
0
    int c;
3602
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3603
0
                    XML_MAX_TEXT_LENGTH :
3604
0
                    XML_MAX_NAME_LENGTH;
3605
3606
#ifdef DEBUG
3607
    nbParseStringName++;
3608
#endif
3609
3610
0
    c = CUR_SCHAR(cur, l);
3611
0
    if (!xmlIsNameStartChar(ctxt, c)) {
3612
0
  return(NULL);
3613
0
    }
3614
3615
0
    COPY_BUF(l,buf,len,c);
3616
0
    cur += l;
3617
0
    c = CUR_SCHAR(cur, l);
3618
0
    while (xmlIsNameChar(ctxt, c)) {
3619
0
  COPY_BUF(l,buf,len,c);
3620
0
  cur += l;
3621
0
  c = CUR_SCHAR(cur, l);
3622
0
  if (len >= XML_MAX_NAMELEN) { /* test bigentname.xml */
3623
      /*
3624
       * Okay someone managed to make a huge name, so he's ready to pay
3625
       * for the processing speed.
3626
       */
3627
0
      xmlChar *buffer;
3628
0
      int max = len * 2;
3629
3630
0
      buffer = (xmlChar *) xmlMallocAtomic(max);
3631
0
      if (buffer == NULL) {
3632
0
          xmlErrMemory(ctxt, NULL);
3633
0
    return(NULL);
3634
0
      }
3635
0
      memcpy(buffer, buf, len);
3636
0
      while (xmlIsNameChar(ctxt, c)) {
3637
0
    if (len + 10 > max) {
3638
0
        xmlChar *tmp;
3639
3640
0
        max *= 2;
3641
0
        tmp = (xmlChar *) xmlRealloc(buffer, max);
3642
0
        if (tmp == NULL) {
3643
0
      xmlErrMemory(ctxt, NULL);
3644
0
      xmlFree(buffer);
3645
0
      return(NULL);
3646
0
        }
3647
0
        buffer = tmp;
3648
0
    }
3649
0
    COPY_BUF(l,buffer,len,c);
3650
0
    cur += l;
3651
0
    c = CUR_SCHAR(cur, l);
3652
0
                if (len > maxLength) {
3653
0
                    xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3654
0
                    xmlFree(buffer);
3655
0
                    return(NULL);
3656
0
                }
3657
0
      }
3658
0
      buffer[len] = 0;
3659
0
      *str = cur;
3660
0
      return(buffer);
3661
0
  }
3662
0
    }
3663
0
    if (len > maxLength) {
3664
0
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3665
0
        return(NULL);
3666
0
    }
3667
0
    *str = cur;
3668
0
    return(xmlStrndup(buf, len));
3669
0
}
3670
3671
/**
3672
 * xmlParseNmtoken:
3673
 * @ctxt:  an XML parser context
3674
 *
3675
 * DEPRECATED: Internal function, don't use.
3676
 *
3677
 * parse an XML Nmtoken.
3678
 *
3679
 * [7] Nmtoken ::= (NameChar)+
3680
 *
3681
 * [8] Nmtokens ::= Nmtoken (#x20 Nmtoken)*
3682
 *
3683
 * Returns the Nmtoken parsed or NULL
3684
 */
3685
3686
xmlChar *
3687
0
xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
3688
0
    xmlChar buf[XML_MAX_NAMELEN + 5];
3689
0
    int len = 0, l;
3690
0
    int c;
3691
0
    int count = 0;
3692
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3693
0
                    XML_MAX_TEXT_LENGTH :
3694
0
                    XML_MAX_NAME_LENGTH;
3695
3696
#ifdef DEBUG
3697
    nbParseNmToken++;
3698
#endif
3699
3700
0
    GROW;
3701
0
    if (ctxt->instate == XML_PARSER_EOF)
3702
0
        return(NULL);
3703
0
    c = CUR_CHAR(l);
3704
3705
0
    while (xmlIsNameChar(ctxt, c)) {
3706
0
  if (count++ > XML_PARSER_CHUNK_SIZE) {
3707
0
      count = 0;
3708
0
      GROW;
3709
0
  }
3710
0
  COPY_BUF(l,buf,len,c);
3711
0
  NEXTL(l);
3712
0
  c = CUR_CHAR(l);
3713
0
  if (c == 0) {
3714
0
      count = 0;
3715
0
      GROW;
3716
0
      if (ctxt->instate == XML_PARSER_EOF)
3717
0
    return(NULL);
3718
0
            c = CUR_CHAR(l);
3719
0
  }
3720
0
  if (len >= XML_MAX_NAMELEN) {
3721
      /*
3722
       * Okay someone managed to make a huge token, so he's ready to pay
3723
       * for the processing speed.
3724
       */
3725
0
      xmlChar *buffer;
3726
0
      int max = len * 2;
3727
3728
0
      buffer = (xmlChar *) xmlMallocAtomic(max);
3729
0
      if (buffer == NULL) {
3730
0
          xmlErrMemory(ctxt, NULL);
3731
0
    return(NULL);
3732
0
      }
3733
0
      memcpy(buffer, buf, len);
3734
0
      while (xmlIsNameChar(ctxt, c)) {
3735
0
    if (count++ > XML_PARSER_CHUNK_SIZE) {
3736
0
        count = 0;
3737
0
        GROW;
3738
0
                    if (ctxt->instate == XML_PARSER_EOF) {
3739
0
                        xmlFree(buffer);
3740
0
                        return(NULL);
3741
0
                    }
3742
0
    }
3743
0
    if (len + 10 > max) {
3744
0
        xmlChar *tmp;
3745
3746
0
        max *= 2;
3747
0
        tmp = (xmlChar *) xmlRealloc(buffer, max);
3748
0
        if (tmp == NULL) {
3749
0
      xmlErrMemory(ctxt, NULL);
3750
0
      xmlFree(buffer);
3751
0
      return(NULL);
3752
0
        }
3753
0
        buffer = tmp;
3754
0
    }
3755
0
    COPY_BUF(l,buffer,len,c);
3756
0
    NEXTL(l);
3757
0
    c = CUR_CHAR(l);
3758
0
                if (len > maxLength) {
3759
0
                    xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
3760
0
                    xmlFree(buffer);
3761
0
                    return(NULL);
3762
0
                }
3763
0
      }
3764
0
      buffer[len] = 0;
3765
0
      return(buffer);
3766
0
  }
3767
0
    }
3768
0
    if (len == 0)
3769
0
        return(NULL);
3770
0
    if (len > maxLength) {
3771
0
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
3772
0
        return(NULL);
3773
0
    }
3774
0
    return(xmlStrndup(buf, len));
3775
0
}
3776
3777
/**
3778
 * xmlParseEntityValue:
3779
 * @ctxt:  an XML parser context
3780
 * @orig:  if non-NULL store a copy of the original entity value
3781
 *
3782
 * DEPRECATED: Internal function, don't use.
3783
 *
3784
 * parse a value for ENTITY declarations
3785
 *
3786
 * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
3787
 *                 "'" ([^%&'] | PEReference | Reference)* "'"
3788
 *
3789
 * Returns the EntityValue parsed with reference substituted or NULL
3790
 */
3791
3792
xmlChar *
3793
0
xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
3794
0
    xmlChar *buf = NULL;
3795
0
    int len = 0;
3796
0
    int size = XML_PARSER_BUFFER_SIZE;
3797
0
    int c, l;
3798
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3799
0
                    XML_MAX_HUGE_LENGTH :
3800
0
                    XML_MAX_TEXT_LENGTH;
3801
0
    xmlChar stop;
3802
0
    xmlChar *ret = NULL;
3803
0
    const xmlChar *cur = NULL;
3804
0
    xmlParserInputPtr input;
3805
3806
0
    if (RAW == '"') stop = '"';
3807
0
    else if (RAW == '\'') stop = '\'';
3808
0
    else {
3809
0
  xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_STARTED, NULL);
3810
0
  return(NULL);
3811
0
    }
3812
0
    buf = (xmlChar *) xmlMallocAtomic(size);
3813
0
    if (buf == NULL) {
3814
0
  xmlErrMemory(ctxt, NULL);
3815
0
  return(NULL);
3816
0
    }
3817
3818
    /*
3819
     * The content of the entity definition is copied in a buffer.
3820
     */
3821
3822
0
    ctxt->instate = XML_PARSER_ENTITY_VALUE;
3823
0
    input = ctxt->input;
3824
0
    GROW;
3825
0
    if (ctxt->instate == XML_PARSER_EOF)
3826
0
        goto error;
3827
0
    NEXT;
3828
0
    c = CUR_CHAR(l);
3829
    /*
3830
     * NOTE: 4.4.5 Included in Literal
3831
     * When a parameter entity reference appears in a literal entity
3832
     * value, ... a single or double quote character in the replacement
3833
     * text is always treated as a normal data character and will not
3834
     * terminate the literal.
3835
     * In practice it means we stop the loop only when back at parsing
3836
     * the initial entity and the quote is found
3837
     */
3838
0
    while (((IS_CHAR(c)) && ((c != stop) || /* checked */
3839
0
      (ctxt->input != input))) && (ctxt->instate != XML_PARSER_EOF)) {
3840
0
  if (len + 5 >= size) {
3841
0
      xmlChar *tmp;
3842
3843
0
      size *= 2;
3844
0
      tmp = (xmlChar *) xmlRealloc(buf, size);
3845
0
      if (tmp == NULL) {
3846
0
    xmlErrMemory(ctxt, NULL);
3847
0
                goto error;
3848
0
      }
3849
0
      buf = tmp;
3850
0
  }
3851
0
  COPY_BUF(l,buf,len,c);
3852
0
  NEXTL(l);
3853
3854
0
  GROW;
3855
0
  c = CUR_CHAR(l);
3856
0
  if (c == 0) {
3857
0
      GROW;
3858
0
      c = CUR_CHAR(l);
3859
0
  }
3860
3861
0
        if (len > maxLength) {
3862
0
            xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
3863
0
                           "entity value too long\n");
3864
0
            goto error;
3865
0
        }
3866
0
    }
3867
0
    buf[len] = 0;
3868
0
    if (ctxt->instate == XML_PARSER_EOF)
3869
0
        goto error;
3870
0
    if (c != stop) {
3871
0
        xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL);
3872
0
        goto error;
3873
0
    }
3874
0
    NEXT;
3875
3876
    /*
3877
     * Raise problem w.r.t. '&' and '%' being used in non-entities
3878
     * reference constructs. Note Charref will be handled in
3879
     * xmlStringDecodeEntities()
3880
     */
3881
0
    cur = buf;
3882
0
    while (*cur != 0) { /* non input consuming */
3883
0
  if ((*cur == '%') || ((*cur == '&') && (cur[1] != '#'))) {
3884
0
      xmlChar *name;
3885
0
      xmlChar tmp = *cur;
3886
0
            int nameOk = 0;
3887
3888
0
      cur++;
3889
0
      name = xmlParseStringName(ctxt, &cur);
3890
0
            if (name != NULL) {
3891
0
                nameOk = 1;
3892
0
                xmlFree(name);
3893
0
            }
3894
0
            if ((nameOk == 0) || (*cur != ';')) {
3895
0
    xmlFatalErrMsgInt(ctxt, XML_ERR_ENTITY_CHAR_ERROR,
3896
0
      "EntityValue: '%c' forbidden except for entities references\n",
3897
0
                            tmp);
3898
0
                goto error;
3899
0
      }
3900
0
      if ((tmp == '%') && (ctxt->inSubset == 1) &&
3901
0
    (ctxt->inputNr == 1)) {
3902
0
    xmlFatalErr(ctxt, XML_ERR_ENTITY_PE_INTERNAL, NULL);
3903
0
                goto error;
3904
0
      }
3905
0
      if (*cur == 0)
3906
0
          break;
3907
0
  }
3908
0
  cur++;
3909
0
    }
3910
3911
    /*
3912
     * Then PEReference entities are substituted.
3913
     *
3914
     * NOTE: 4.4.7 Bypassed
3915
     * When a general entity reference appears in the EntityValue in
3916
     * an entity declaration, it is bypassed and left as is.
3917
     * so XML_SUBSTITUTE_REF is not set here.
3918
     */
3919
0
    ++ctxt->depth;
3920
0
    ret = xmlStringDecodeEntitiesInt(ctxt, buf, len, XML_SUBSTITUTE_PEREF,
3921
0
                                     0, 0, 0, /* check */ 1);
3922
0
    --ctxt->depth;
3923
3924
0
    if (orig != NULL) {
3925
0
        *orig = buf;
3926
0
        buf = NULL;
3927
0
    }
3928
3929
0
error:
3930
0
    if (buf != NULL)
3931
0
        xmlFree(buf);
3932
0
    return(ret);
3933
0
}
3934
3935
/**
3936
 * xmlParseAttValueComplex:
3937
 * @ctxt:  an XML parser context
3938
 * @len:   the resulting attribute len
3939
 * @normalize:  whether to apply the inner normalization
3940
 *
3941
 * parse a value for an attribute, this is the fallback function
3942
 * of xmlParseAttValue() when the attribute parsing requires handling
3943
 * of non-ASCII characters, or normalization compaction.
3944
 *
3945
 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
3946
 */
3947
static xmlChar *
3948
3.69k
xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
3949
3.69k
    xmlChar limit = 0;
3950
3.69k
    xmlChar *buf = NULL;
3951
3.69k
    xmlChar *rep = NULL;
3952
3.69k
    size_t len = 0;
3953
3.69k
    size_t buf_size = 0;
3954
3.69k
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3955
0
                       XML_MAX_HUGE_LENGTH :
3956
3.69k
                       XML_MAX_TEXT_LENGTH;
3957
3.69k
    int c, l, in_space = 0;
3958
3.69k
    xmlChar *current = NULL;
3959
3.69k
    xmlEntityPtr ent;
3960
3961
3.69k
    if (NXT(0) == '"') {
3962
3.69k
  ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
3963
3.69k
  limit = '"';
3964
3.69k
        NEXT;
3965
3.69k
    } else if (NXT(0) == '\'') {
3966
0
  limit = '\'';
3967
0
  ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
3968
0
        NEXT;
3969
0
    } else {
3970
0
  xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
3971
0
  return(NULL);
3972
0
    }
3973
3974
    /*
3975
     * allocate a translation buffer.
3976
     */
3977
3.69k
    buf_size = XML_PARSER_BUFFER_SIZE;
3978
3.69k
    buf = (xmlChar *) xmlMallocAtomic(buf_size);
3979
3.69k
    if (buf == NULL) goto mem_error;
3980
3981
    /*
3982
     * OK loop until we reach one of the ending char or a size limit.
3983
     */
3984
3.69k
    c = CUR_CHAR(l);
3985
14.7k
    while (((NXT(0) != limit) && /* checked */
3986
14.7k
            (IS_CHAR(c)) && (c != '<')) &&
3987
14.7k
            (ctxt->instate != XML_PARSER_EOF)) {
3988
11.0k
  if (c == '&') {
3989
0
      in_space = 0;
3990
0
      if (NXT(1) == '#') {
3991
0
    int val = xmlParseCharRef(ctxt);
3992
3993
0
    if (val == '&') {
3994
0
        if (ctxt->replaceEntities) {
3995
0
      if (len + 10 > buf_size) {
3996
0
          growBuffer(buf, 10);
3997
0
      }
3998
0
      buf[len++] = '&';
3999
0
        } else {
4000
      /*
4001
       * The reparsing will be done in xmlStringGetNodeList()
4002
       * called by the attribute() function in SAX.c
4003
       */
4004
0
      if (len + 10 > buf_size) {
4005
0
          growBuffer(buf, 10);
4006
0
      }
4007
0
      buf[len++] = '&';
4008
0
      buf[len++] = '#';
4009
0
      buf[len++] = '3';
4010
0
      buf[len++] = '8';
4011
0
      buf[len++] = ';';
4012
0
        }
4013
0
    } else if (val != 0) {
4014
0
        if (len + 10 > buf_size) {
4015
0
      growBuffer(buf, 10);
4016
0
        }
4017
0
        len += xmlCopyChar(0, &buf[len], val);
4018
0
    }
4019
0
      } else {
4020
0
    ent = xmlParseEntityRef(ctxt);
4021
0
    if ((ent != NULL) &&
4022
0
        (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
4023
0
        if (len + 10 > buf_size) {
4024
0
      growBuffer(buf, 10);
4025
0
        }
4026
0
        if ((ctxt->replaceEntities == 0) &&
4027
0
            (ent->content[0] == '&')) {
4028
0
      buf[len++] = '&';
4029
0
      buf[len++] = '#';
4030
0
      buf[len++] = '3';
4031
0
      buf[len++] = '8';
4032
0
      buf[len++] = ';';
4033
0
        } else {
4034
0
      buf[len++] = ent->content[0];
4035
0
        }
4036
0
    } else if ((ent != NULL) &&
4037
0
               (ctxt->replaceEntities != 0)) {
4038
0
        if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
4039
0
                        if (xmlParserEntityCheck(ctxt, ent->length))
4040
0
                            goto error;
4041
4042
0
      ++ctxt->depth;
4043
0
      rep = xmlStringDecodeEntitiesInt(ctxt, ent->content,
4044
0
                                ent->length, XML_SUBSTITUTE_REF, 0, 0, 0,
4045
0
                                /* check */ 1);
4046
0
      --ctxt->depth;
4047
0
      if (rep != NULL) {
4048
0
          current = rep;
4049
0
          while (*current != 0) { /* non input consuming */
4050
0
                                if ((*current == 0xD) || (*current == 0xA) ||
4051
0
                                    (*current == 0x9)) {
4052
0
                                    buf[len++] = 0x20;
4053
0
                                    current++;
4054
0
                                } else
4055
0
                                    buf[len++] = *current++;
4056
0
        if (len + 10 > buf_size) {
4057
0
            growBuffer(buf, 10);
4058
0
        }
4059
0
          }
4060
0
          xmlFree(rep);
4061
0
          rep = NULL;
4062
0
      }
4063
0
        } else {
4064
0
      if (len + 10 > buf_size) {
4065
0
          growBuffer(buf, 10);
4066
0
      }
4067
0
      if (ent->content != NULL)
4068
0
          buf[len++] = ent->content[0];
4069
0
        }
4070
0
    } else if (ent != NULL) {
4071
0
        int i = xmlStrlen(ent->name);
4072
0
        const xmlChar *cur = ent->name;
4073
4074
        /*
4075
                     * We also check for recursion and amplification
4076
                     * when entities are not substituted. They're
4077
                     * often expanded later.
4078
         */
4079
0
        if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
4080
0
      (ent->content != NULL)) {
4081
0
                        if ((ent->flags & XML_ENT_CHECKED) == 0) {
4082
0
                            unsigned long oldCopy = ctxt->sizeentcopy;
4083
4084
0
                            ctxt->sizeentcopy = ent->length;
4085
4086
0
                            ++ctxt->depth;
4087
0
                            rep = xmlStringDecodeEntitiesInt(ctxt,
4088
0
                                    ent->content, ent->length,
4089
0
                                    XML_SUBSTITUTE_REF, 0, 0, 0,
4090
0
                                    /* check */ 1);
4091
0
                            --ctxt->depth;
4092
4093
                            /*
4094
                             * If we're parsing DTD content, the entity
4095
                             * might reference other entities which
4096
                             * weren't defined yet, so the check isn't
4097
                             * reliable.
4098
                             */
4099
0
                            if (ctxt->inSubset == 0) {
4100
0
                                ent->flags |= XML_ENT_CHECKED;
4101
0
                                ent->expandedSize = ctxt->sizeentcopy;
4102
0
                            }
4103
4104
0
                            if (rep != NULL) {
4105
0
                                xmlFree(rep);
4106
0
                                rep = NULL;
4107
0
                            } else {
4108
0
                                ent->content[0] = 0;
4109
0
                            }
4110
4111
0
                            if (xmlParserEntityCheck(ctxt, oldCopy))
4112
0
                                goto error;
4113
0
                        } else {
4114
0
                            if (xmlParserEntityCheck(ctxt, ent->expandedSize))
4115
0
                                goto error;
4116
0
                        }
4117
0
        }
4118
4119
        /*
4120
         * Just output the reference
4121
         */
4122
0
        buf[len++] = '&';
4123
0
        while (len + i + 10 > buf_size) {
4124
0
      growBuffer(buf, i + 10);
4125
0
        }
4126
0
        for (;i > 0;i--)
4127
0
      buf[len++] = *cur++;
4128
0
        buf[len++] = ';';
4129
0
    }
4130
0
      }
4131
11.0k
  } else {
4132
11.0k
      if ((c == 0x20) || (c == 0xD) || (c == 0xA) || (c == 0x9)) {
4133
0
          if ((len != 0) || (!normalize)) {
4134
0
        if ((!normalize) || (!in_space)) {
4135
0
      COPY_BUF(l,buf,len,0x20);
4136
0
      while (len + 10 > buf_size) {
4137
0
          growBuffer(buf, 10);
4138
0
      }
4139
0
        }
4140
0
        in_space = 1;
4141
0
    }
4142
11.0k
      } else {
4143
11.0k
          in_space = 0;
4144
11.0k
    COPY_BUF(l,buf,len,c);
4145
11.0k
    if (len + 10 > buf_size) {
4146
0
        growBuffer(buf, 10);
4147
0
    }
4148
11.0k
      }
4149
11.0k
      NEXTL(l);
4150
11.0k
  }
4151
11.0k
  GROW;
4152
11.0k
  c = CUR_CHAR(l);
4153
11.0k
        if (len > maxLength) {
4154
0
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
4155
0
                           "AttValue length too long\n");
4156
0
            goto mem_error;
4157
0
        }
4158
11.0k
    }
4159
3.69k
    if (ctxt->instate == XML_PARSER_EOF)
4160
0
        goto error;
4161
4162
3.69k
    if ((in_space) && (normalize)) {
4163
0
        while ((len > 0) && (buf[len - 1] == 0x20)) len--;
4164
0
    }
4165
3.69k
    buf[len] = 0;
4166
3.69k
    if (RAW == '<') {
4167
0
  xmlFatalErr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, NULL);
4168
3.69k
    } else if (RAW != limit) {
4169
0
  if ((c != 0) && (!IS_CHAR(c))) {
4170
0
      xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
4171
0
         "invalid character in attribute value\n");
4172
0
  } else {
4173
0
      xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
4174
0
         "AttValue: ' expected\n");
4175
0
        }
4176
0
    } else
4177
3.69k
  NEXT;
4178
4179
3.69k
    if (attlen != NULL) *attlen = len;
4180
3.69k
    return(buf);
4181
4182
0
mem_error:
4183
0
    xmlErrMemory(ctxt, NULL);
4184
0
error:
4185
0
    if (buf != NULL)
4186
0
        xmlFree(buf);
4187
0
    if (rep != NULL)
4188
0
        xmlFree(rep);
4189
0
    return(NULL);
4190
0
}
4191
4192
/**
4193
 * xmlParseAttValue:
4194
 * @ctxt:  an XML parser context
4195
 *
4196
 * DEPRECATED: Internal function, don't use.
4197
 *
4198
 * parse a value for an attribute
4199
 * Note: the parser won't do substitution of entities here, this
4200
 * will be handled later in xmlStringGetNodeList
4201
 *
4202
 * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |
4203
 *                   "'" ([^<&'] | Reference)* "'"
4204
 *
4205
 * 3.3.3 Attribute-Value Normalization:
4206
 * Before the value of an attribute is passed to the application or
4207
 * checked for validity, the XML processor must normalize it as follows:
4208
 * - a character reference is processed by appending the referenced
4209
 *   character to the attribute value
4210
 * - an entity reference is processed by recursively processing the
4211
 *   replacement text of the entity
4212
 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
4213
 *   appending #x20 to the normalized value, except that only a single
4214
 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
4215
 *   parsed entity or the literal entity value of an internal parsed entity
4216
 * - other characters are processed by appending them to the normalized value
4217
 * If the declared value is not CDATA, then the XML processor must further
4218
 * process the normalized attribute value by discarding any leading and
4219
 * trailing space (#x20) characters, and by replacing sequences of space
4220
 * (#x20) characters by a single space (#x20) character.
4221
 * All attributes for which no declaration has been read should be treated
4222
 * by a non-validating parser as if declared CDATA.
4223
 *
4224
 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
4225
 */
4226
4227
4228
xmlChar *
4229
0
xmlParseAttValue(xmlParserCtxtPtr ctxt) {
4230
0
    if ((ctxt == NULL) || (ctxt->input == NULL)) return(NULL);
4231
0
    return(xmlParseAttValueInternal(ctxt, NULL, NULL, 0));
4232
0
}
4233
4234
/**
4235
 * xmlParseSystemLiteral:
4236
 * @ctxt:  an XML parser context
4237
 *
4238
 * DEPRECATED: Internal function, don't use.
4239
 *
4240
 * parse an XML Literal
4241
 *
4242
 * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
4243
 *
4244
 * Returns the SystemLiteral parsed or NULL
4245
 */
4246
4247
xmlChar *
4248
0
xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
4249
0
    xmlChar *buf = NULL;
4250
0
    int len = 0;
4251
0
    int size = XML_PARSER_BUFFER_SIZE;
4252
0
    int cur, l;
4253
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4254
0
                    XML_MAX_TEXT_LENGTH :
4255
0
                    XML_MAX_NAME_LENGTH;
4256
0
    xmlChar stop;
4257
0
    int state = ctxt->instate;
4258
0
    int count = 0;
4259
4260
0
    SHRINK;
4261
0
    if (RAW == '"') {
4262
0
        NEXT;
4263
0
  stop = '"';
4264
0
    } else if (RAW == '\'') {
4265
0
        NEXT;
4266
0
  stop = '\'';
4267
0
    } else {
4268
0
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
4269
0
  return(NULL);
4270
0
    }
4271
4272
0
    buf = (xmlChar *) xmlMallocAtomic(size);
4273
0
    if (buf == NULL) {
4274
0
        xmlErrMemory(ctxt, NULL);
4275
0
  return(NULL);
4276
0
    }
4277
0
    ctxt->instate = XML_PARSER_SYSTEM_LITERAL;
4278
0
    cur = CUR_CHAR(l);
4279
0
    while ((IS_CHAR(cur)) && (cur != stop)) { /* checked */
4280
0
  if (len + 5 >= size) {
4281
0
      xmlChar *tmp;
4282
4283
0
      size *= 2;
4284
0
      tmp = (xmlChar *) xmlRealloc(buf, size);
4285
0
      if (tmp == NULL) {
4286
0
          xmlFree(buf);
4287
0
    xmlErrMemory(ctxt, NULL);
4288
0
    ctxt->instate = (xmlParserInputState) state;
4289
0
    return(NULL);
4290
0
      }
4291
0
      buf = tmp;
4292
0
  }
4293
0
  count++;
4294
0
  if (count > 50) {
4295
0
      SHRINK;
4296
0
      GROW;
4297
0
      count = 0;
4298
0
            if (ctxt->instate == XML_PARSER_EOF) {
4299
0
          xmlFree(buf);
4300
0
    return(NULL);
4301
0
            }
4302
0
  }
4303
0
  COPY_BUF(l,buf,len,cur);
4304
0
  NEXTL(l);
4305
0
  cur = CUR_CHAR(l);
4306
0
  if (cur == 0) {
4307
0
      GROW;
4308
0
      SHRINK;
4309
0
      cur = CUR_CHAR(l);
4310
0
  }
4311
0
        if (len > maxLength) {
4312
0
            xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral");
4313
0
            xmlFree(buf);
4314
0
            ctxt->instate = (xmlParserInputState) state;
4315
0
            return(NULL);
4316
0
        }
4317
0
    }
4318
0
    buf[len] = 0;
4319
0
    ctxt->instate = (xmlParserInputState) state;
4320
0
    if (!IS_CHAR(cur)) {
4321
0
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
4322
0
    } else {
4323
0
  NEXT;
4324
0
    }
4325
0
    return(buf);
4326
0
}
4327
4328
/**
4329
 * xmlParsePubidLiteral:
4330
 * @ctxt:  an XML parser context
4331
 *
4332
 * DEPRECATED: Internal function, don't use.
4333
 *
4334
 * parse an XML public literal
4335
 *
4336
 * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
4337
 *
4338
 * Returns the PubidLiteral parsed or NULL.
4339
 */
4340
4341
xmlChar *
4342
0
xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
4343
0
    xmlChar *buf = NULL;
4344
0
    int len = 0;
4345
0
    int size = XML_PARSER_BUFFER_SIZE;
4346
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4347
0
                    XML_MAX_TEXT_LENGTH :
4348
0
                    XML_MAX_NAME_LENGTH;
4349
0
    xmlChar cur;
4350
0
    xmlChar stop;
4351
0
    int count = 0;
4352
0
    xmlParserInputState oldstate = ctxt->instate;
4353
4354
0
    SHRINK;
4355
0
    if (RAW == '"') {
4356
0
        NEXT;
4357
0
  stop = '"';
4358
0
    } else if (RAW == '\'') {
4359
0
        NEXT;
4360
0
  stop = '\'';
4361
0
    } else {
4362
0
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
4363
0
  return(NULL);
4364
0
    }
4365
0
    buf = (xmlChar *) xmlMallocAtomic(size);
4366
0
    if (buf == NULL) {
4367
0
  xmlErrMemory(ctxt, NULL);
4368
0
  return(NULL);
4369
0
    }
4370
0
    ctxt->instate = XML_PARSER_PUBLIC_LITERAL;
4371
0
    cur = CUR;
4372
0
    while ((IS_PUBIDCHAR_CH(cur)) && (cur != stop)) { /* checked */
4373
0
  if (len + 1 >= size) {
4374
0
      xmlChar *tmp;
4375
4376
0
      size *= 2;
4377
0
      tmp = (xmlChar *) xmlRealloc(buf, size);
4378
0
      if (tmp == NULL) {
4379
0
    xmlErrMemory(ctxt, NULL);
4380
0
    xmlFree(buf);
4381
0
    return(NULL);
4382
0
      }
4383
0
      buf = tmp;
4384
0
  }
4385
0
  buf[len++] = cur;
4386
0
  count++;
4387
0
  if (count > 50) {
4388
0
      SHRINK;
4389
0
      GROW;
4390
0
      count = 0;
4391
0
            if (ctxt->instate == XML_PARSER_EOF) {
4392
0
    xmlFree(buf);
4393
0
    return(NULL);
4394
0
            }
4395
0
  }
4396
0
  NEXT;
4397
0
  cur = CUR;
4398
0
  if (cur == 0) {
4399
0
      GROW;
4400
0
      SHRINK;
4401
0
      cur = CUR;
4402
0
  }
4403
0
        if (len > maxLength) {
4404
0
            xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Public ID");
4405
0
            xmlFree(buf);
4406
0
            return(NULL);
4407
0
        }
4408
0
    }
4409
0
    buf[len] = 0;
4410
0
    if (cur != stop) {
4411
0
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
4412
0
    } else {
4413
0
  NEXT;
4414
0
    }
4415
0
    ctxt->instate = oldstate;
4416
0
    return(buf);
4417
0
}
4418
4419
static void xmlParseCharDataComplex(xmlParserCtxtPtr ctxt);
4420
4421
/*
4422
 * used for the test in the inner loop of the char data testing
4423
 */
4424
static const unsigned char test_char_data[256] = {
4425
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4426
    0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9, CR/LF separated */
4427
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4428
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4429
    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x00, 0x27, /* & */
4430
    0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
4431
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
4432
    0x38, 0x39, 0x3A, 0x3B, 0x00, 0x3D, 0x3E, 0x3F, /* < */
4433
    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
4434
    0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
4435
    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
4436
    0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x00, 0x5E, 0x5F, /* ] */
4437
    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
4438
    0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
4439
    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
4440
    0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
4441
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* non-ascii */
4442
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4443
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4444
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4445
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4446
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4447
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4448
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4449
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4450
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4451
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4452
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4453
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4454
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4455
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4456
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4457
};
4458
4459
/**
4460
 * xmlParseCharData:
4461
 * @ctxt:  an XML parser context
4462
 * @cdata:  unused
4463
 *
4464
 * DEPRECATED: Internal function, don't use.
4465
 *
4466
 * Parse character data. Always makes progress if the first char isn't
4467
 * '<' or '&'.
4468
 *
4469
 * if we are within a CDATA section ']]>' marks an end of section.
4470
 *
4471
 * The right angle bracket (>) may be represented using the string "&gt;",
4472
 * and must, for compatibility, be escaped using "&gt;" or a character
4473
 * reference when it appears in the string "]]>" in content, when that
4474
 * string is not marking the end of a CDATA section.
4475
 *
4476
 * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
4477
 */
4478
4479
void
4480
81.2k
xmlParseCharData(xmlParserCtxtPtr ctxt, ATTRIBUTE_UNUSED int cdata) {
4481
81.2k
    const xmlChar *in;
4482
81.2k
    int nbchar = 0;
4483
81.2k
    int line = ctxt->input->line;
4484
81.2k
    int col = ctxt->input->col;
4485
81.2k
    int ccol;
4486
4487
81.2k
    SHRINK;
4488
81.2k
    GROW;
4489
    /*
4490
     * Accelerated common case where input don't need to be
4491
     * modified before passing it to the handler.
4492
     */
4493
81.2k
    in = ctxt->input->cur;
4494
81.2k
    do {
4495
143k
get_more_space:
4496
498k
        while (*in == 0x20) { in++; ctxt->input->col++; }
4497
143k
        if (*in == 0xA) {
4498
62.7k
            do {
4499
62.7k
                ctxt->input->line++; ctxt->input->col = 1;
4500
62.7k
                in++;
4501
62.7k
            } while (*in == 0xA);
4502
62.7k
            goto get_more_space;
4503
62.7k
        }
4504
81.2k
        if (*in == '<') {
4505
62.7k
            nbchar = in - ctxt->input->cur;
4506
62.7k
            if (nbchar > 0) {
4507
62.7k
                const xmlChar *tmp = ctxt->input->cur;
4508
62.7k
                ctxt->input->cur = in;
4509
4510
62.7k
                if ((ctxt->sax != NULL) &&
4511
62.7k
                    (ctxt->sax->ignorableWhitespace !=
4512
62.7k
                     ctxt->sax->characters)) {
4513
0
                    if (areBlanks(ctxt, tmp, nbchar, 1)) {
4514
0
                        if (ctxt->sax->ignorableWhitespace != NULL)
4515
0
                            ctxt->sax->ignorableWhitespace(ctxt->userData,
4516
0
                                                   tmp, nbchar);
4517
0
                    } else {
4518
0
                        if (ctxt->sax->characters != NULL)
4519
0
                            ctxt->sax->characters(ctxt->userData,
4520
0
                                                  tmp, nbchar);
4521
0
                        if (*ctxt->space == -1)
4522
0
                            *ctxt->space = -2;
4523
0
                    }
4524
62.7k
                } else if ((ctxt->sax != NULL) &&
4525
62.7k
                           (ctxt->sax->characters != NULL)) {
4526
62.7k
                    ctxt->sax->characters(ctxt->userData,
4527
62.7k
                                          tmp, nbchar);
4528
62.7k
                }
4529
62.7k
            }
4530
62.7k
            return;
4531
62.7k
        }
4532
4533
18.4k
get_more:
4534
18.4k
        ccol = ctxt->input->col;
4535
66.4k
        while (test_char_data[*in]) {
4536
47.9k
            in++;
4537
47.9k
            ccol++;
4538
47.9k
        }
4539
18.4k
        ctxt->input->col = ccol;
4540
18.4k
        if (*in == 0xA) {
4541
0
            do {
4542
0
                ctxt->input->line++; ctxt->input->col = 1;
4543
0
                in++;
4544
0
            } while (*in == 0xA);
4545
0
            goto get_more;
4546
0
        }
4547
18.4k
        if (*in == ']') {
4548
0
            if ((in[1] == ']') && (in[2] == '>')) {
4549
0
                xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
4550
0
                ctxt->input->cur = in + 1;
4551
0
                return;
4552
0
            }
4553
0
            in++;
4554
0
            ctxt->input->col++;
4555
0
            goto get_more;
4556
0
        }
4557
18.4k
        nbchar = in - ctxt->input->cur;
4558
18.4k
        if (nbchar > 0) {
4559
11.0k
            if ((ctxt->sax != NULL) &&
4560
11.0k
                (ctxt->sax->ignorableWhitespace !=
4561
11.0k
                 ctxt->sax->characters) &&
4562
11.0k
                (IS_BLANK_CH(*ctxt->input->cur))) {
4563
0
                const xmlChar *tmp = ctxt->input->cur;
4564
0
                ctxt->input->cur = in;
4565
4566
0
                if (areBlanks(ctxt, tmp, nbchar, 0)) {
4567
0
                    if (ctxt->sax->ignorableWhitespace != NULL)
4568
0
                        ctxt->sax->ignorableWhitespace(ctxt->userData,
4569
0
                                                       tmp, nbchar);
4570
0
                } else {
4571
0
                    if (ctxt->sax->characters != NULL)
4572
0
                        ctxt->sax->characters(ctxt->userData,
4573
0
                                              tmp, nbchar);
4574
0
                    if (*ctxt->space == -1)
4575
0
                        *ctxt->space = -2;
4576
0
                }
4577
0
                line = ctxt->input->line;
4578
0
                col = ctxt->input->col;
4579
11.0k
            } else if (ctxt->sax != NULL) {
4580
11.0k
                if (ctxt->sax->characters != NULL)
4581
11.0k
                    ctxt->sax->characters(ctxt->userData,
4582
11.0k
                                          ctxt->input->cur, nbchar);
4583
11.0k
                line = ctxt->input->line;
4584
11.0k
                col = ctxt->input->col;
4585
11.0k
            }
4586
11.0k
        }
4587
18.4k
        ctxt->input->cur = in;
4588
18.4k
        if (*in == 0xD) {
4589
0
            in++;
4590
0
            if (*in == 0xA) {
4591
0
                ctxt->input->cur = in;
4592
0
                in++;
4593
0
                ctxt->input->line++; ctxt->input->col = 1;
4594
0
                continue; /* while */
4595
0
            }
4596
0
            in--;
4597
0
        }
4598
18.4k
        if (*in == '<') {
4599
11.0k
            return;
4600
11.0k
        }
4601
7.38k
        if (*in == '&') {
4602
0
            return;
4603
0
        }
4604
7.38k
        SHRINK;
4605
7.38k
        GROW;
4606
7.38k
        if (ctxt->instate == XML_PARSER_EOF)
4607
0
            return;
4608
7.38k
        in = ctxt->input->cur;
4609
7.38k
    } while (((*in >= 0x20) && (*in <= 0x7F)) ||
4610
7.38k
             (*in == 0x09) || (*in == 0x0a));
4611
7.38k
    ctxt->input->line = line;
4612
7.38k
    ctxt->input->col = col;
4613
7.38k
    xmlParseCharDataComplex(ctxt);
4614
7.38k
}
4615
4616
/**
4617
 * xmlParseCharDataComplex:
4618
 * @ctxt:  an XML parser context
4619
 * @cdata:  int indicating whether we are within a CDATA section
4620
 *
4621
 * Always makes progress if the first char isn't '<' or '&'.
4622
 *
4623
 * parse a CharData section.this is the fallback function
4624
 * of xmlParseCharData() when the parsing requires handling
4625
 * of non-ASCII characters.
4626
 */
4627
static void
4628
7.38k
xmlParseCharDataComplex(xmlParserCtxtPtr ctxt) {
4629
7.38k
    xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE + 5];
4630
7.38k
    int nbchar = 0;
4631
7.38k
    int cur, l;
4632
7.38k
    int count = 0;
4633
4634
7.38k
    SHRINK;
4635
7.38k
    GROW;
4636
7.38k
    cur = CUR_CHAR(l);
4637
29.5k
    while ((cur != '<') && /* checked */
4638
29.5k
           (cur != '&') &&
4639
29.5k
     (IS_CHAR(cur))) /* test also done in xmlCurrentChar() */ {
4640
22.1k
  if ((cur == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
4641
0
      xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
4642
0
  }
4643
22.1k
  COPY_BUF(l,buf,nbchar,cur);
4644
  /* move current position before possible calling of ctxt->sax->characters */
4645
22.1k
  NEXTL(l);
4646
22.1k
  cur = CUR_CHAR(l);
4647
22.1k
  if (nbchar >= XML_PARSER_BIG_BUFFER_SIZE) {
4648
0
      buf[nbchar] = 0;
4649
4650
      /*
4651
       * OK the segment is to be consumed as chars.
4652
       */
4653
0
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
4654
0
    if (areBlanks(ctxt, buf, nbchar, 0)) {
4655
0
        if (ctxt->sax->ignorableWhitespace != NULL)
4656
0
      ctxt->sax->ignorableWhitespace(ctxt->userData,
4657
0
                                     buf, nbchar);
4658
0
    } else {
4659
0
        if (ctxt->sax->characters != NULL)
4660
0
      ctxt->sax->characters(ctxt->userData, buf, nbchar);
4661
0
        if ((ctxt->sax->characters !=
4662
0
             ctxt->sax->ignorableWhitespace) &&
4663
0
      (*ctxt->space == -1))
4664
0
      *ctxt->space = -2;
4665
0
    }
4666
0
      }
4667
0
      nbchar = 0;
4668
            /* something really bad happened in the SAX callback */
4669
0
            if (ctxt->instate != XML_PARSER_CONTENT)
4670
0
                return;
4671
0
  }
4672
22.1k
  count++;
4673
22.1k
  if (count > 50) {
4674
0
      SHRINK;
4675
0
      GROW;
4676
0
      count = 0;
4677
0
            if (ctxt->instate == XML_PARSER_EOF)
4678
0
    return;
4679
0
  }
4680
22.1k
    }
4681
7.38k
    if (nbchar != 0) {
4682
7.38k
        buf[nbchar] = 0;
4683
  /*
4684
   * OK the segment is to be consumed as chars.
4685
   */
4686
7.38k
  if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
4687
7.38k
      if (areBlanks(ctxt, buf, nbchar, 0)) {
4688
0
    if (ctxt->sax->ignorableWhitespace != NULL)
4689
0
        ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
4690
7.38k
      } else {
4691
7.38k
    if (ctxt->sax->characters != NULL)
4692
7.38k
        ctxt->sax->characters(ctxt->userData, buf, nbchar);
4693
7.38k
    if ((ctxt->sax->characters != ctxt->sax->ignorableWhitespace) &&
4694
7.38k
        (*ctxt->space == -1))
4695
0
        *ctxt->space = -2;
4696
7.38k
      }
4697
7.38k
  }
4698
7.38k
    }
4699
7.38k
    if ((ctxt->input->cur < ctxt->input->end) && (!IS_CHAR(cur))) {
4700
  /* Generate the error and skip the offending character */
4701
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4702
0
                          "PCDATA invalid Char value %d\n",
4703
0
                    cur ? cur : CUR);
4704
0
  NEXT;
4705
0
    }
4706
7.38k
}
4707
4708
/**
4709
 * xmlParseExternalID:
4710
 * @ctxt:  an XML parser context
4711
 * @publicID:  a xmlChar** receiving PubidLiteral
4712
 * @strict: indicate whether we should restrict parsing to only
4713
 *          production [75], see NOTE below
4714
 *
4715
 * DEPRECATED: Internal function, don't use.
4716
 *
4717
 * Parse an External ID or a Public ID
4718
 *
4719
 * NOTE: Productions [75] and [83] interact badly since [75] can generate
4720
 *       'PUBLIC' S PubidLiteral S SystemLiteral
4721
 *
4722
 * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
4723
 *                   | 'PUBLIC' S PubidLiteral S SystemLiteral
4724
 *
4725
 * [83] PublicID ::= 'PUBLIC' S PubidLiteral
4726
 *
4727
 * Returns the function returns SystemLiteral and in the second
4728
 *                case publicID receives PubidLiteral, is strict is off
4729
 *                it is possible to return NULL and have publicID set.
4730
 */
4731
4732
xmlChar *
4733
0
xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
4734
0
    xmlChar *URI = NULL;
4735
4736
0
    SHRINK;
4737
4738
0
    *publicID = NULL;
4739
0
    if (CMP6(CUR_PTR, 'S', 'Y', 'S', 'T', 'E', 'M')) {
4740
0
        SKIP(6);
4741
0
  if (SKIP_BLANKS == 0) {
4742
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4743
0
                     "Space required after 'SYSTEM'\n");
4744
0
  }
4745
0
  URI = xmlParseSystemLiteral(ctxt);
4746
0
  if (URI == NULL) {
4747
0
      xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
4748
0
        }
4749
0
    } else if (CMP6(CUR_PTR, 'P', 'U', 'B', 'L', 'I', 'C')) {
4750
0
        SKIP(6);
4751
0
  if (SKIP_BLANKS == 0) {
4752
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4753
0
        "Space required after 'PUBLIC'\n");
4754
0
  }
4755
0
  *publicID = xmlParsePubidLiteral(ctxt);
4756
0
  if (*publicID == NULL) {
4757
0
      xmlFatalErr(ctxt, XML_ERR_PUBID_REQUIRED, NULL);
4758
0
  }
4759
0
  if (strict) {
4760
      /*
4761
       * We don't handle [83] so "S SystemLiteral" is required.
4762
       */
4763
0
      if (SKIP_BLANKS == 0) {
4764
0
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4765
0
      "Space required after the Public Identifier\n");
4766
0
      }
4767
0
  } else {
4768
      /*
4769
       * We handle [83] so we return immediately, if
4770
       * "S SystemLiteral" is not detected. We skip blanks if no
4771
             * system literal was found, but this is harmless since we must
4772
             * be at the end of a NotationDecl.
4773
       */
4774
0
      if (SKIP_BLANKS == 0) return(NULL);
4775
0
      if ((CUR != '\'') && (CUR != '"')) return(NULL);
4776
0
  }
4777
0
  URI = xmlParseSystemLiteral(ctxt);
4778
0
  if (URI == NULL) {
4779
0
      xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
4780
0
        }
4781
0
    }
4782
0
    return(URI);
4783
0
}
4784
4785
/**
4786
 * xmlParseCommentComplex:
4787
 * @ctxt:  an XML parser context
4788
 * @buf:  the already parsed part of the buffer
4789
 * @len:  number of bytes in the buffer
4790
 * @size:  allocated size of the buffer
4791
 *
4792
 * Skip an XML (SGML) comment <!-- .... -->
4793
 *  The spec says that "For compatibility, the string "--" (double-hyphen)
4794
 *  must not occur within comments. "
4795
 * This is the slow routine in case the accelerator for ascii didn't work
4796
 *
4797
 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
4798
 */
4799
static void
4800
xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
4801
0
                       size_t len, size_t size) {
4802
0
    int q, ql;
4803
0
    int r, rl;
4804
0
    int cur, l;
4805
0
    size_t count = 0;
4806
0
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4807
0
                       XML_MAX_HUGE_LENGTH :
4808
0
                       XML_MAX_TEXT_LENGTH;
4809
0
    int inputid;
4810
4811
0
    inputid = ctxt->input->id;
4812
4813
0
    if (buf == NULL) {
4814
0
        len = 0;
4815
0
  size = XML_PARSER_BUFFER_SIZE;
4816
0
  buf = (xmlChar *) xmlMallocAtomic(size);
4817
0
  if (buf == NULL) {
4818
0
      xmlErrMemory(ctxt, NULL);
4819
0
      return;
4820
0
  }
4821
0
    }
4822
0
    GROW; /* Assure there's enough input data */
4823
0
    q = CUR_CHAR(ql);
4824
0
    if (q == 0)
4825
0
        goto not_terminated;
4826
0
    if (!IS_CHAR(q)) {
4827
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4828
0
                          "xmlParseComment: invalid xmlChar value %d\n",
4829
0
                    q);
4830
0
  xmlFree (buf);
4831
0
  return;
4832
0
    }
4833
0
    NEXTL(ql);
4834
0
    r = CUR_CHAR(rl);
4835
0
    if (r == 0)
4836
0
        goto not_terminated;
4837
0
    if (!IS_CHAR(r)) {
4838
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4839
0
                          "xmlParseComment: invalid xmlChar value %d\n",
4840
0
                    r);
4841
0
  xmlFree (buf);
4842
0
  return;
4843
0
    }
4844
0
    NEXTL(rl);
4845
0
    cur = CUR_CHAR(l);
4846
0
    if (cur == 0)
4847
0
        goto not_terminated;
4848
0
    while (IS_CHAR(cur) && /* checked */
4849
0
           ((cur != '>') ||
4850
0
      (r != '-') || (q != '-'))) {
4851
0
  if ((r == '-') && (q == '-')) {
4852
0
      xmlFatalErr(ctxt, XML_ERR_HYPHEN_IN_COMMENT, NULL);
4853
0
  }
4854
0
  if (len + 5 >= size) {
4855
0
      xmlChar *new_buf;
4856
0
            size_t new_size;
4857
4858
0
      new_size = size * 2;
4859
0
      new_buf = (xmlChar *) xmlRealloc(buf, new_size);
4860
0
      if (new_buf == NULL) {
4861
0
    xmlFree (buf);
4862
0
    xmlErrMemory(ctxt, NULL);
4863
0
    return;
4864
0
      }
4865
0
      buf = new_buf;
4866
0
            size = new_size;
4867
0
  }
4868
0
  COPY_BUF(ql,buf,len,q);
4869
0
  q = r;
4870
0
  ql = rl;
4871
0
  r = cur;
4872
0
  rl = l;
4873
4874
0
  count++;
4875
0
  if (count > 50) {
4876
0
      SHRINK;
4877
0
      GROW;
4878
0
      count = 0;
4879
0
            if (ctxt->instate == XML_PARSER_EOF) {
4880
0
    xmlFree(buf);
4881
0
    return;
4882
0
            }
4883
0
  }
4884
0
  NEXTL(l);
4885
0
  cur = CUR_CHAR(l);
4886
0
  if (cur == 0) {
4887
0
      SHRINK;
4888
0
      GROW;
4889
0
      cur = CUR_CHAR(l);
4890
0
  }
4891
4892
0
        if (len > maxLength) {
4893
0
            xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4894
0
                         "Comment too big found", NULL);
4895
0
            xmlFree (buf);
4896
0
            return;
4897
0
        }
4898
0
    }
4899
0
    buf[len] = 0;
4900
0
    if (cur == 0) {
4901
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4902
0
                       "Comment not terminated \n<!--%.50s\n", buf);
4903
0
    } else if (!IS_CHAR(cur)) {
4904
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4905
0
                          "xmlParseComment: invalid xmlChar value %d\n",
4906
0
                    cur);
4907
0
    } else {
4908
0
  if (inputid != ctxt->input->id) {
4909
0
      xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
4910
0
               "Comment doesn't start and stop in the same"
4911
0
                           " entity\n");
4912
0
  }
4913
0
        NEXT;
4914
0
  if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
4915
0
      (!ctxt->disableSAX))
4916
0
      ctxt->sax->comment(ctxt->userData, buf);
4917
0
    }
4918
0
    xmlFree(buf);
4919
0
    return;
4920
0
not_terminated:
4921
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4922
0
       "Comment not terminated\n", NULL);
4923
0
    xmlFree(buf);
4924
0
    return;
4925
0
}
4926
4927
/**
4928
 * xmlParseComment:
4929
 * @ctxt:  an XML parser context
4930
 *
4931
 * DEPRECATED: Internal function, don't use.
4932
 *
4933
 * Parse an XML (SGML) comment. Always consumes '<!'.
4934
 *
4935
 *  The spec says that "For compatibility, the string "--" (double-hyphen)
4936
 *  must not occur within comments. "
4937
 *
4938
 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
4939
 */
4940
void
4941
7.38k
xmlParseComment(xmlParserCtxtPtr ctxt) {
4942
7.38k
    xmlChar *buf = NULL;
4943
7.38k
    size_t size = XML_PARSER_BUFFER_SIZE;
4944
7.38k
    size_t len = 0;
4945
7.38k
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4946
0
                       XML_MAX_HUGE_LENGTH :
4947
7.38k
                       XML_MAX_TEXT_LENGTH;
4948
7.38k
    xmlParserInputState state;
4949
7.38k
    const xmlChar *in;
4950
7.38k
    size_t nbchar = 0;
4951
7.38k
    int ccol;
4952
7.38k
    int inputid;
4953
4954
    /*
4955
     * Check that there is a comment right here.
4956
     */
4957
7.38k
    if ((RAW != '<') || (NXT(1) != '!'))
4958
0
        return;
4959
7.38k
    SKIP(2);
4960
7.38k
    if ((RAW != '-') || (NXT(1) != '-'))
4961
0
        return;
4962
7.38k
    state = ctxt->instate;
4963
7.38k
    ctxt->instate = XML_PARSER_COMMENT;
4964
7.38k
    inputid = ctxt->input->id;
4965
7.38k
    SKIP(2);
4966
7.38k
    SHRINK;
4967
7.38k
    GROW;
4968
4969
    /*
4970
     * Accelerated common case where input don't need to be
4971
     * modified before passing it to the handler.
4972
     */
4973
7.38k
    in = ctxt->input->cur;
4974
7.38k
    do {
4975
7.38k
  if (*in == 0xA) {
4976
0
      do {
4977
0
    ctxt->input->line++; ctxt->input->col = 1;
4978
0
    in++;
4979
0
      } while (*in == 0xA);
4980
0
  }
4981
7.38k
get_more:
4982
7.38k
        ccol = ctxt->input->col;
4983
73.8k
  while (((*in > '-') && (*in <= 0x7F)) ||
4984
73.8k
         ((*in >= 0x20) && (*in < '-')) ||
4985
73.8k
         (*in == 0x09)) {
4986
66.4k
        in++;
4987
66.4k
        ccol++;
4988
66.4k
  }
4989
7.38k
  ctxt->input->col = ccol;
4990
7.38k
  if (*in == 0xA) {
4991
0
      do {
4992
0
    ctxt->input->line++; ctxt->input->col = 1;
4993
0
    in++;
4994
0
      } while (*in == 0xA);
4995
0
      goto get_more;
4996
0
  }
4997
7.38k
  nbchar = in - ctxt->input->cur;
4998
  /*
4999
   * save current set of data
5000
   */
5001
7.38k
  if (nbchar > 0) {
5002
7.38k
      if ((ctxt->sax != NULL) &&
5003
7.38k
    (ctxt->sax->comment != NULL)) {
5004
7.38k
    if (buf == NULL) {
5005
7.38k
        if ((*in == '-') && (in[1] == '-'))
5006
7.38k
            size = nbchar + 1;
5007
0
        else
5008
0
            size = XML_PARSER_BUFFER_SIZE + nbchar;
5009
7.38k
        buf = (xmlChar *) xmlMallocAtomic(size);
5010
7.38k
        if (buf == NULL) {
5011
0
            xmlErrMemory(ctxt, NULL);
5012
0
      ctxt->instate = state;
5013
0
      return;
5014
0
        }
5015
7.38k
        len = 0;
5016
7.38k
    } else if (len + nbchar + 1 >= size) {
5017
0
        xmlChar *new_buf;
5018
0
        size  += len + nbchar + XML_PARSER_BUFFER_SIZE;
5019
0
        new_buf = (xmlChar *) xmlRealloc(buf, size);
5020
0
        if (new_buf == NULL) {
5021
0
            xmlFree (buf);
5022
0
      xmlErrMemory(ctxt, NULL);
5023
0
      ctxt->instate = state;
5024
0
      return;
5025
0
        }
5026
0
        buf = new_buf;
5027
0
    }
5028
7.38k
    memcpy(&buf[len], ctxt->input->cur, nbchar);
5029
7.38k
    len += nbchar;
5030
7.38k
    buf[len] = 0;
5031
7.38k
      }
5032
7.38k
  }
5033
7.38k
        if (len > maxLength) {
5034
0
            xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
5035
0
                         "Comment too big found", NULL);
5036
0
            xmlFree (buf);
5037
0
            return;
5038
0
        }
5039
7.38k
  ctxt->input->cur = in;
5040
7.38k
  if (*in == 0xA) {
5041
0
      in++;
5042
0
      ctxt->input->line++; ctxt->input->col = 1;
5043
0
  }
5044
7.38k
  if (*in == 0xD) {
5045
0
      in++;
5046
0
      if (*in == 0xA) {
5047
0
    ctxt->input->cur = in;
5048
0
    in++;
5049
0
    ctxt->input->line++; ctxt->input->col = 1;
5050
0
    goto get_more;
5051
0
      }
5052
0
      in--;
5053
0
  }
5054
7.38k
  SHRINK;
5055
7.38k
  GROW;
5056
7.38k
        if (ctxt->instate == XML_PARSER_EOF) {
5057
0
            xmlFree(buf);
5058
0
            return;
5059
0
        }
5060
7.38k
  in = ctxt->input->cur;
5061
7.38k
  if (*in == '-') {
5062
7.38k
      if (in[1] == '-') {
5063
7.38k
          if (in[2] == '>') {
5064
7.38k
        if (ctxt->input->id != inputid) {
5065
0
      xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5066
0
                     "comment doesn't start and stop in the"
5067
0
                                       " same entity\n");
5068
0
        }
5069
7.38k
        SKIP(3);
5070
7.38k
        if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
5071
7.38k
            (!ctxt->disableSAX)) {
5072
7.38k
      if (buf != NULL)
5073
7.38k
          ctxt->sax->comment(ctxt->userData, buf);
5074
0
      else
5075
0
          ctxt->sax->comment(ctxt->userData, BAD_CAST "");
5076
7.38k
        }
5077
7.38k
        if (buf != NULL)
5078
7.38k
            xmlFree(buf);
5079
7.38k
        if (ctxt->instate != XML_PARSER_EOF)
5080
7.38k
      ctxt->instate = state;
5081
7.38k
        return;
5082
7.38k
    }
5083
0
    if (buf != NULL) {
5084
0
        xmlFatalErrMsgStr(ctxt, XML_ERR_HYPHEN_IN_COMMENT,
5085
0
                          "Double hyphen within comment: "
5086
0
                                      "<!--%.50s\n",
5087
0
              buf);
5088
0
    } else
5089
0
        xmlFatalErrMsgStr(ctxt, XML_ERR_HYPHEN_IN_COMMENT,
5090
0
                          "Double hyphen within comment\n", NULL);
5091
0
                if (ctxt->instate == XML_PARSER_EOF) {
5092
0
                    xmlFree(buf);
5093
0
                    return;
5094
0
                }
5095
0
    in++;
5096
0
    ctxt->input->col++;
5097
0
      }
5098
0
      in++;
5099
0
      ctxt->input->col++;
5100
0
      goto get_more;
5101
7.38k
  }
5102
7.38k
    } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09) || (*in == 0x0a));
5103
0
    xmlParseCommentComplex(ctxt, buf, len, size);
5104
0
    ctxt->instate = state;
5105
0
    return;
5106
7.38k
}
5107
5108
5109
/**
5110
 * xmlParsePITarget:
5111
 * @ctxt:  an XML parser context
5112
 *
5113
 * DEPRECATED: Internal function, don't use.
5114
 *
5115
 * parse the name of a PI
5116
 *
5117
 * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
5118
 *
5119
 * Returns the PITarget name or NULL
5120
 */
5121
5122
const xmlChar *
5123
7.38k
xmlParsePITarget(xmlParserCtxtPtr ctxt) {
5124
7.38k
    const xmlChar *name;
5125
5126
7.38k
    name = xmlParseName(ctxt);
5127
7.38k
    if ((name != NULL) &&
5128
7.38k
        ((name[0] == 'x') || (name[0] == 'X')) &&
5129
7.38k
        ((name[1] == 'm') || (name[1] == 'M')) &&
5130
7.38k
        ((name[2] == 'l') || (name[2] == 'L'))) {
5131
0
  int i;
5132
0
  if ((name[0] == 'x') && (name[1] == 'm') &&
5133
0
      (name[2] == 'l') && (name[3] == 0)) {
5134
0
      xmlFatalErrMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
5135
0
     "XML declaration allowed only at the start of the document\n");
5136
0
      return(name);
5137
0
  } else if (name[3] == 0) {
5138
0
      xmlFatalErr(ctxt, XML_ERR_RESERVED_XML_NAME, NULL);
5139
0
      return(name);
5140
0
  }
5141
0
  for (i = 0;;i++) {
5142
0
      if (xmlW3CPIs[i] == NULL) break;
5143
0
      if (xmlStrEqual(name, (const xmlChar *)xmlW3CPIs[i]))
5144
0
          return(name);
5145
0
  }
5146
0
  xmlWarningMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
5147
0
          "xmlParsePITarget: invalid name prefix 'xml'\n",
5148
0
          NULL, NULL);
5149
0
    }
5150
7.38k
    if ((name != NULL) && (xmlStrchr(name, ':') != NULL)) {
5151
0
  xmlNsErr(ctxt, XML_NS_ERR_COLON,
5152
0
     "colons are forbidden from PI names '%s'\n", name, NULL, NULL);
5153
0
    }
5154
7.38k
    return(name);
5155
7.38k
}
5156
5157
#ifdef LIBXML_CATALOG_ENABLED
5158
/**
5159
 * xmlParseCatalogPI:
5160
 * @ctxt:  an XML parser context
5161
 * @catalog:  the PI value string
5162
 *
5163
 * parse an XML Catalog Processing Instruction.
5164
 *
5165
 * <?oasis-xml-catalog catalog="http://example.com/catalog.xml"?>
5166
 *
5167
 * Occurs only if allowed by the user and if happening in the Misc
5168
 * part of the document before any doctype information
5169
 * This will add the given catalog to the parsing context in order
5170
 * to be used if there is a resolution need further down in the document
5171
 */
5172
5173
static void
5174
0
xmlParseCatalogPI(xmlParserCtxtPtr ctxt, const xmlChar *catalog) {
5175
0
    xmlChar *URL = NULL;
5176
0
    const xmlChar *tmp, *base;
5177
0
    xmlChar marker;
5178
5179
0
    tmp = catalog;
5180
0
    while (IS_BLANK_CH(*tmp)) tmp++;
5181
0
    if (xmlStrncmp(tmp, BAD_CAST"catalog", 7))
5182
0
  goto error;
5183
0
    tmp += 7;
5184
0
    while (IS_BLANK_CH(*tmp)) tmp++;
5185
0
    if (*tmp != '=') {
5186
0
  return;
5187
0
    }
5188
0
    tmp++;
5189
0
    while (IS_BLANK_CH(*tmp)) tmp++;
5190
0
    marker = *tmp;
5191
0
    if ((marker != '\'') && (marker != '"'))
5192
0
  goto error;
5193
0
    tmp++;
5194
0
    base = tmp;
5195
0
    while ((*tmp != 0) && (*tmp != marker)) tmp++;
5196
0
    if (*tmp == 0)
5197
0
  goto error;
5198
0
    URL = xmlStrndup(base, tmp - base);
5199
0
    tmp++;
5200
0
    while (IS_BLANK_CH(*tmp)) tmp++;
5201
0
    if (*tmp != 0)
5202
0
  goto error;
5203
5204
0
    if (URL != NULL) {
5205
0
  ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
5206
0
  xmlFree(URL);
5207
0
    }
5208
0
    return;
5209
5210
0
error:
5211
0
    xmlWarningMsg(ctxt, XML_WAR_CATALOG_PI,
5212
0
            "Catalog PI syntax error: %s\n",
5213
0
      catalog, NULL);
5214
0
    if (URL != NULL)
5215
0
  xmlFree(URL);
5216
0
}
5217
#endif
5218
5219
/**
5220
 * xmlParsePI:
5221
 * @ctxt:  an XML parser context
5222
 *
5223
 * DEPRECATED: Internal function, don't use.
5224
 *
5225
 * parse an XML Processing Instruction.
5226
 *
5227
 * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
5228
 *
5229
 * The processing is transferred to SAX once parsed.
5230
 */
5231
5232
void
5233
7.38k
xmlParsePI(xmlParserCtxtPtr ctxt) {
5234
7.38k
    xmlChar *buf = NULL;
5235
7.38k
    size_t len = 0;
5236
7.38k
    size_t size = XML_PARSER_BUFFER_SIZE;
5237
7.38k
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
5238
0
                       XML_MAX_HUGE_LENGTH :
5239
7.38k
                       XML_MAX_TEXT_LENGTH;
5240
7.38k
    int cur, l;
5241
7.38k
    const xmlChar *target;
5242
7.38k
    xmlParserInputState state;
5243
7.38k
    int count = 0;
5244
5245
7.38k
    if ((RAW == '<') && (NXT(1) == '?')) {
5246
7.38k
  int inputid = ctxt->input->id;
5247
7.38k
  state = ctxt->instate;
5248
7.38k
        ctxt->instate = XML_PARSER_PI;
5249
  /*
5250
   * this is a Processing Instruction.
5251
   */
5252
7.38k
  SKIP(2);
5253
7.38k
  SHRINK;
5254
5255
  /*
5256
   * Parse the target name and check for special support like
5257
   * namespace.
5258
   */
5259
7.38k
        target = xmlParsePITarget(ctxt);
5260
7.38k
  if (target != NULL) {
5261
7.38k
      if ((RAW == '?') && (NXT(1) == '>')) {
5262
0
    if (inputid != ctxt->input->id) {
5263
0
        xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5264
0
                             "PI declaration doesn't start and stop in"
5265
0
                                   " the same entity\n");
5266
0
    }
5267
0
    SKIP(2);
5268
5269
    /*
5270
     * SAX: PI detected.
5271
     */
5272
0
    if ((ctxt->sax) && (!ctxt->disableSAX) &&
5273
0
        (ctxt->sax->processingInstruction != NULL))
5274
0
        ctxt->sax->processingInstruction(ctxt->userData,
5275
0
                                         target, NULL);
5276
0
    if (ctxt->instate != XML_PARSER_EOF)
5277
0
        ctxt->instate = state;
5278
0
    return;
5279
0
      }
5280
7.38k
      buf = (xmlChar *) xmlMallocAtomic(size);
5281
7.38k
      if (buf == NULL) {
5282
0
    xmlErrMemory(ctxt, NULL);
5283
0
    ctxt->instate = state;
5284
0
    return;
5285
0
      }
5286
7.38k
      if (SKIP_BLANKS == 0) {
5287
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_SPACE_REQUIRED,
5288
0
        "ParsePI: PI %s space expected\n", target);
5289
0
      }
5290
7.38k
      cur = CUR_CHAR(l);
5291
59.0k
      while (IS_CHAR(cur) && /* checked */
5292
59.0k
       ((cur != '?') || (NXT(1) != '>'))) {
5293
51.6k
    if (len + 5 >= size) {
5294
0
        xmlChar *tmp;
5295
0
                    size_t new_size = size * 2;
5296
0
        tmp = (xmlChar *) xmlRealloc(buf, new_size);
5297
0
        if (tmp == NULL) {
5298
0
      xmlErrMemory(ctxt, NULL);
5299
0
      xmlFree(buf);
5300
0
      ctxt->instate = state;
5301
0
      return;
5302
0
        }
5303
0
        buf = tmp;
5304
0
                    size = new_size;
5305
0
    }
5306
51.6k
    count++;
5307
51.6k
    if (count > 50) {
5308
0
        SHRINK;
5309
0
        GROW;
5310
0
                    if (ctxt->instate == XML_PARSER_EOF) {
5311
0
                        xmlFree(buf);
5312
0
                        return;
5313
0
                    }
5314
0
        count = 0;
5315
0
    }
5316
51.6k
    COPY_BUF(l,buf,len,cur);
5317
51.6k
    NEXTL(l);
5318
51.6k
    cur = CUR_CHAR(l);
5319
51.6k
    if (cur == 0) {
5320
0
        SHRINK;
5321
0
        GROW;
5322
0
        cur = CUR_CHAR(l);
5323
0
    }
5324
51.6k
                if (len > maxLength) {
5325
0
                    xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
5326
0
                                      "PI %s too big found", target);
5327
0
                    xmlFree(buf);
5328
0
                    ctxt->instate = state;
5329
0
                    return;
5330
0
                }
5331
51.6k
      }
5332
7.38k
      buf[len] = 0;
5333
7.38k
      if (cur != '?') {
5334
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
5335
0
          "ParsePI: PI %s never end ...\n", target);
5336
7.38k
      } else {
5337
7.38k
    if (inputid != ctxt->input->id) {
5338
0
        xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5339
0
                             "PI declaration doesn't start and stop in"
5340
0
                                   " the same entity\n");
5341
0
    }
5342
7.38k
    SKIP(2);
5343
5344
7.38k
#ifdef LIBXML_CATALOG_ENABLED
5345
7.38k
    if (((state == XML_PARSER_MISC) ||
5346
7.38k
               (state == XML_PARSER_START)) &&
5347
7.38k
        (xmlStrEqual(target, XML_CATALOG_PI))) {
5348
0
        xmlCatalogAllow allow = xmlCatalogGetDefaults();
5349
0
        if ((allow == XML_CATA_ALLOW_DOCUMENT) ||
5350
0
      (allow == XML_CATA_ALLOW_ALL))
5351
0
      xmlParseCatalogPI(ctxt, buf);
5352
0
    }
5353
7.38k
#endif
5354
5355
5356
    /*
5357
     * SAX: PI detected.
5358
     */
5359
7.38k
    if ((ctxt->sax) && (!ctxt->disableSAX) &&
5360
7.38k
        (ctxt->sax->processingInstruction != NULL))
5361
7.38k
        ctxt->sax->processingInstruction(ctxt->userData,
5362
7.38k
                                         target, buf);
5363
7.38k
      }
5364
7.38k
      xmlFree(buf);
5365
7.38k
  } else {
5366
0
      xmlFatalErr(ctxt, XML_ERR_PI_NOT_STARTED, NULL);
5367
0
  }
5368
7.38k
  if (ctxt->instate != XML_PARSER_EOF)
5369
7.38k
      ctxt->instate = state;
5370
7.38k
    }
5371
7.38k
}
5372
5373
/**
5374
 * xmlParseNotationDecl:
5375
 * @ctxt:  an XML parser context
5376
 *
5377
 * DEPRECATED: Internal function, don't use.
5378
 *
5379
 * Parse a notation declaration. Always consumes '<!'.
5380
 *
5381
 * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID |  PublicID) S? '>'
5382
 *
5383
 * Hence there is actually 3 choices:
5384
 *     'PUBLIC' S PubidLiteral
5385
 *     'PUBLIC' S PubidLiteral S SystemLiteral
5386
 * and 'SYSTEM' S SystemLiteral
5387
 *
5388
 * See the NOTE on xmlParseExternalID().
5389
 */
5390
5391
void
5392
0
xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
5393
0
    const xmlChar *name;
5394
0
    xmlChar *Pubid;
5395
0
    xmlChar *Systemid;
5396
5397
0
    if ((CUR != '<') || (NXT(1) != '!'))
5398
0
        return;
5399
0
    SKIP(2);
5400
5401
0
    if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
5402
0
  int inputid = ctxt->input->id;
5403
0
  SHRINK;
5404
0
  SKIP(8);
5405
0
  if (SKIP_BLANKS == 0) {
5406
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5407
0
         "Space required after '<!NOTATION'\n");
5408
0
      return;
5409
0
  }
5410
5411
0
        name = xmlParseName(ctxt);
5412
0
  if (name == NULL) {
5413
0
      xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
5414
0
      return;
5415
0
  }
5416
0
  if (xmlStrchr(name, ':') != NULL) {
5417
0
      xmlNsErr(ctxt, XML_NS_ERR_COLON,
5418
0
         "colons are forbidden from notation names '%s'\n",
5419
0
         name, NULL, NULL);
5420
0
  }
5421
0
  if (SKIP_BLANKS == 0) {
5422
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5423
0
         "Space required after the NOTATION name'\n");
5424
0
      return;
5425
0
  }
5426
5427
  /*
5428
   * Parse the IDs.
5429
   */
5430
0
  Systemid = xmlParseExternalID(ctxt, &Pubid, 0);
5431
0
  SKIP_BLANKS;
5432
5433
0
  if (RAW == '>') {
5434
0
      if (inputid != ctxt->input->id) {
5435
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5436
0
                         "Notation declaration doesn't start and stop"
5437
0
                               " in the same entity\n");
5438
0
      }
5439
0
      NEXT;
5440
0
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
5441
0
    (ctxt->sax->notationDecl != NULL))
5442
0
    ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
5443
0
  } else {
5444
0
      xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
5445
0
  }
5446
0
  if (Systemid != NULL) xmlFree(Systemid);
5447
0
  if (Pubid != NULL) xmlFree(Pubid);
5448
0
    }
5449
0
}
5450
5451
/**
5452
 * xmlParseEntityDecl:
5453
 * @ctxt:  an XML parser context
5454
 *
5455
 * DEPRECATED: Internal function, don't use.
5456
 *
5457
 * Parse an entity declaration. Always consumes '<!'.
5458
 *
5459
 * [70] EntityDecl ::= GEDecl | PEDecl
5460
 *
5461
 * [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
5462
 *
5463
 * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
5464
 *
5465
 * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
5466
 *
5467
 * [74] PEDef ::= EntityValue | ExternalID
5468
 *
5469
 * [76] NDataDecl ::= S 'NDATA' S Name
5470
 *
5471
 * [ VC: Notation Declared ]
5472
 * The Name must match the declared name of a notation.
5473
 */
5474
5475
void
5476
0
xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
5477
0
    const xmlChar *name = NULL;
5478
0
    xmlChar *value = NULL;
5479
0
    xmlChar *URI = NULL, *literal = NULL;
5480
0
    const xmlChar *ndata = NULL;
5481
0
    int isParameter = 0;
5482
0
    xmlChar *orig = NULL;
5483
5484
0
    if ((CUR != '<') || (NXT(1) != '!'))
5485
0
        return;
5486
0
    SKIP(2);
5487
5488
    /* GROW; done in the caller */
5489
0
    if (CMP6(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'Y')) {
5490
0
  int inputid = ctxt->input->id;
5491
0
  SHRINK;
5492
0
  SKIP(6);
5493
0
  if (SKIP_BLANKS == 0) {
5494
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5495
0
         "Space required after '<!ENTITY'\n");
5496
0
  }
5497
5498
0
  if (RAW == '%') {
5499
0
      NEXT;
5500
0
      if (SKIP_BLANKS == 0) {
5501
0
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5502
0
             "Space required after '%%'\n");
5503
0
      }
5504
0
      isParameter = 1;
5505
0
  }
5506
5507
0
        name = xmlParseName(ctxt);
5508
0
  if (name == NULL) {
5509
0
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
5510
0
                     "xmlParseEntityDecl: no name\n");
5511
0
            return;
5512
0
  }
5513
0
  if (xmlStrchr(name, ':') != NULL) {
5514
0
      xmlNsErr(ctxt, XML_NS_ERR_COLON,
5515
0
         "colons are forbidden from entities names '%s'\n",
5516
0
         name, NULL, NULL);
5517
0
  }
5518
0
  if (SKIP_BLANKS == 0) {
5519
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5520
0
         "Space required after the entity name\n");
5521
0
  }
5522
5523
0
  ctxt->instate = XML_PARSER_ENTITY_DECL;
5524
  /*
5525
   * handle the various case of definitions...
5526
   */
5527
0
  if (isParameter) {
5528
0
      if ((RAW == '"') || (RAW == '\'')) {
5529
0
          value = xmlParseEntityValue(ctxt, &orig);
5530
0
    if (value) {
5531
0
        if ((ctxt->sax != NULL) &&
5532
0
      (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5533
0
      ctxt->sax->entityDecl(ctxt->userData, name,
5534
0
                        XML_INTERNAL_PARAMETER_ENTITY,
5535
0
            NULL, NULL, value);
5536
0
    }
5537
0
      } else {
5538
0
          URI = xmlParseExternalID(ctxt, &literal, 1);
5539
0
    if ((URI == NULL) && (literal == NULL)) {
5540
0
        xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
5541
0
    }
5542
0
    if (URI) {
5543
0
        xmlURIPtr uri;
5544
5545
0
        uri = xmlParseURI((const char *) URI);
5546
0
        if (uri == NULL) {
5547
0
            xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
5548
0
             "Invalid URI: %s\n", URI);
5549
      /*
5550
       * This really ought to be a well formedness error
5551
       * but the XML Core WG decided otherwise c.f. issue
5552
       * E26 of the XML erratas.
5553
       */
5554
0
        } else {
5555
0
      if (uri->fragment != NULL) {
5556
          /*
5557
           * Okay this is foolish to block those but not
5558
           * invalid URIs.
5559
           */
5560
0
          xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
5561
0
      } else {
5562
0
          if ((ctxt->sax != NULL) &&
5563
0
        (!ctxt->disableSAX) &&
5564
0
        (ctxt->sax->entityDecl != NULL))
5565
0
        ctxt->sax->entityDecl(ctxt->userData, name,
5566
0
              XML_EXTERNAL_PARAMETER_ENTITY,
5567
0
              literal, URI, NULL);
5568
0
      }
5569
0
      xmlFreeURI(uri);
5570
0
        }
5571
0
    }
5572
0
      }
5573
0
  } else {
5574
0
      if ((RAW == '"') || (RAW == '\'')) {
5575
0
          value = xmlParseEntityValue(ctxt, &orig);
5576
0
    if ((ctxt->sax != NULL) &&
5577
0
        (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5578
0
        ctxt->sax->entityDecl(ctxt->userData, name,
5579
0
        XML_INTERNAL_GENERAL_ENTITY,
5580
0
        NULL, NULL, value);
5581
    /*
5582
     * For expat compatibility in SAX mode.
5583
     */
5584
0
    if ((ctxt->myDoc == NULL) ||
5585
0
        (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
5586
0
        if (ctxt->myDoc == NULL) {
5587
0
      ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
5588
0
      if (ctxt->myDoc == NULL) {
5589
0
          xmlErrMemory(ctxt, "New Doc failed");
5590
0
          return;
5591
0
      }
5592
0
      ctxt->myDoc->properties = XML_DOC_INTERNAL;
5593
0
        }
5594
0
        if (ctxt->myDoc->intSubset == NULL)
5595
0
      ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
5596
0
              BAD_CAST "fake", NULL, NULL);
5597
5598
0
        xmlSAX2EntityDecl(ctxt, name, XML_INTERNAL_GENERAL_ENTITY,
5599
0
                    NULL, NULL, value);
5600
0
    }
5601
0
      } else {
5602
0
          URI = xmlParseExternalID(ctxt, &literal, 1);
5603
0
    if ((URI == NULL) && (literal == NULL)) {
5604
0
        xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
5605
0
    }
5606
0
    if (URI) {
5607
0
        xmlURIPtr uri;
5608
5609
0
        uri = xmlParseURI((const char *)URI);
5610
0
        if (uri == NULL) {
5611
0
            xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
5612
0
             "Invalid URI: %s\n", URI);
5613
      /*
5614
       * This really ought to be a well formedness error
5615
       * but the XML Core WG decided otherwise c.f. issue
5616
       * E26 of the XML erratas.
5617
       */
5618
0
        } else {
5619
0
      if (uri->fragment != NULL) {
5620
          /*
5621
           * Okay this is foolish to block those but not
5622
           * invalid URIs.
5623
           */
5624
0
          xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
5625
0
      }
5626
0
      xmlFreeURI(uri);
5627
0
        }
5628
0
    }
5629
0
    if ((RAW != '>') && (SKIP_BLANKS == 0)) {
5630
0
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5631
0
           "Space required before 'NDATA'\n");
5632
0
    }
5633
0
    if (CMP5(CUR_PTR, 'N', 'D', 'A', 'T', 'A')) {
5634
0
        SKIP(5);
5635
0
        if (SKIP_BLANKS == 0) {
5636
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5637
0
               "Space required after 'NDATA'\n");
5638
0
        }
5639
0
        ndata = xmlParseName(ctxt);
5640
0
        if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
5641
0
            (ctxt->sax->unparsedEntityDecl != NULL))
5642
0
      ctxt->sax->unparsedEntityDecl(ctxt->userData, name,
5643
0
            literal, URI, ndata);
5644
0
    } else {
5645
0
        if ((ctxt->sax != NULL) &&
5646
0
            (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5647
0
      ctxt->sax->entityDecl(ctxt->userData, name,
5648
0
            XML_EXTERNAL_GENERAL_PARSED_ENTITY,
5649
0
            literal, URI, NULL);
5650
        /*
5651
         * For expat compatibility in SAX mode.
5652
         * assuming the entity replacement was asked for
5653
         */
5654
0
        if ((ctxt->replaceEntities != 0) &&
5655
0
      ((ctxt->myDoc == NULL) ||
5656
0
      (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE)))) {
5657
0
      if (ctxt->myDoc == NULL) {
5658
0
          ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
5659
0
          if (ctxt->myDoc == NULL) {
5660
0
              xmlErrMemory(ctxt, "New Doc failed");
5661
0
        return;
5662
0
          }
5663
0
          ctxt->myDoc->properties = XML_DOC_INTERNAL;
5664
0
      }
5665
5666
0
      if (ctxt->myDoc->intSubset == NULL)
5667
0
          ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
5668
0
            BAD_CAST "fake", NULL, NULL);
5669
0
      xmlSAX2EntityDecl(ctxt, name,
5670
0
                  XML_EXTERNAL_GENERAL_PARSED_ENTITY,
5671
0
                  literal, URI, NULL);
5672
0
        }
5673
0
    }
5674
0
      }
5675
0
  }
5676
0
  if (ctxt->instate == XML_PARSER_EOF)
5677
0
      goto done;
5678
0
  SKIP_BLANKS;
5679
0
  if (RAW != '>') {
5680
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
5681
0
              "xmlParseEntityDecl: entity %s not terminated\n", name);
5682
0
      xmlHaltParser(ctxt);
5683
0
  } else {
5684
0
      if (inputid != ctxt->input->id) {
5685
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5686
0
                         "Entity declaration doesn't start and stop in"
5687
0
                               " the same entity\n");
5688
0
      }
5689
0
      NEXT;
5690
0
  }
5691
0
  if (orig != NULL) {
5692
      /*
5693
       * Ugly mechanism to save the raw entity value.
5694
       */
5695
0
      xmlEntityPtr cur = NULL;
5696
5697
0
      if (isParameter) {
5698
0
          if ((ctxt->sax != NULL) &&
5699
0
        (ctxt->sax->getParameterEntity != NULL))
5700
0
        cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
5701
0
      } else {
5702
0
          if ((ctxt->sax != NULL) &&
5703
0
        (ctxt->sax->getEntity != NULL))
5704
0
        cur = ctxt->sax->getEntity(ctxt->userData, name);
5705
0
    if ((cur == NULL) && (ctxt->userData==ctxt)) {
5706
0
        cur = xmlSAX2GetEntity(ctxt, name);
5707
0
    }
5708
0
      }
5709
0
            if ((cur != NULL) && (cur->orig == NULL)) {
5710
0
    cur->orig = orig;
5711
0
                orig = NULL;
5712
0
      }
5713
0
  }
5714
5715
0
done:
5716
0
  if (value != NULL) xmlFree(value);
5717
0
  if (URI != NULL) xmlFree(URI);
5718
0
  if (literal != NULL) xmlFree(literal);
5719
0
        if (orig != NULL) xmlFree(orig);
5720
0
    }
5721
0
}
5722
5723
/**
5724
 * xmlParseDefaultDecl:
5725
 * @ctxt:  an XML parser context
5726
 * @value:  Receive a possible fixed default value for the attribute
5727
 *
5728
 * DEPRECATED: Internal function, don't use.
5729
 *
5730
 * Parse an attribute default declaration
5731
 *
5732
 * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
5733
 *
5734
 * [ VC: Required Attribute ]
5735
 * if the default declaration is the keyword #REQUIRED, then the
5736
 * attribute must be specified for all elements of the type in the
5737
 * attribute-list declaration.
5738
 *
5739
 * [ VC: Attribute Default Legal ]
5740
 * The declared default value must meet the lexical constraints of
5741
 * the declared attribute type c.f. xmlValidateAttributeDecl()
5742
 *
5743
 * [ VC: Fixed Attribute Default ]
5744
 * if an attribute has a default value declared with the #FIXED
5745
 * keyword, instances of that attribute must match the default value.
5746
 *
5747
 * [ WFC: No < in Attribute Values ]
5748
 * handled in xmlParseAttValue()
5749
 *
5750
 * returns: XML_ATTRIBUTE_NONE, XML_ATTRIBUTE_REQUIRED, XML_ATTRIBUTE_IMPLIED
5751
 *          or XML_ATTRIBUTE_FIXED.
5752
 */
5753
5754
int
5755
0
xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
5756
0
    int val;
5757
0
    xmlChar *ret;
5758
5759
0
    *value = NULL;
5760
0
    if (CMP9(CUR_PTR, '#', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D')) {
5761
0
  SKIP(9);
5762
0
  return(XML_ATTRIBUTE_REQUIRED);
5763
0
    }
5764
0
    if (CMP8(CUR_PTR, '#', 'I', 'M', 'P', 'L', 'I', 'E', 'D')) {
5765
0
  SKIP(8);
5766
0
  return(XML_ATTRIBUTE_IMPLIED);
5767
0
    }
5768
0
    val = XML_ATTRIBUTE_NONE;
5769
0
    if (CMP6(CUR_PTR, '#', 'F', 'I', 'X', 'E', 'D')) {
5770
0
  SKIP(6);
5771
0
  val = XML_ATTRIBUTE_FIXED;
5772
0
  if (SKIP_BLANKS == 0) {
5773
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5774
0
         "Space required after '#FIXED'\n");
5775
0
  }
5776
0
    }
5777
0
    ret = xmlParseAttValue(ctxt);
5778
0
    ctxt->instate = XML_PARSER_DTD;
5779
0
    if (ret == NULL) {
5780
0
  xmlFatalErrMsg(ctxt, (xmlParserErrors)ctxt->errNo,
5781
0
           "Attribute default value declaration error\n");
5782
0
    } else
5783
0
        *value = ret;
5784
0
    return(val);
5785
0
}
5786
5787
/**
5788
 * xmlParseNotationType:
5789
 * @ctxt:  an XML parser context
5790
 *
5791
 * DEPRECATED: Internal function, don't use.
5792
 *
5793
 * parse an Notation attribute type.
5794
 *
5795
 * Note: the leading 'NOTATION' S part has already being parsed...
5796
 *
5797
 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
5798
 *
5799
 * [ VC: Notation Attributes ]
5800
 * Values of this type must match one of the notation names included
5801
 * in the declaration; all notation names in the declaration must be declared.
5802
 *
5803
 * Returns: the notation attribute tree built while parsing
5804
 */
5805
5806
xmlEnumerationPtr
5807
0
xmlParseNotationType(xmlParserCtxtPtr ctxt) {
5808
0
    const xmlChar *name;
5809
0
    xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
5810
5811
0
    if (RAW != '(') {
5812
0
  xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
5813
0
  return(NULL);
5814
0
    }
5815
0
    SHRINK;
5816
0
    do {
5817
0
        NEXT;
5818
0
  SKIP_BLANKS;
5819
0
        name = xmlParseName(ctxt);
5820
0
  if (name == NULL) {
5821
0
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
5822
0
         "Name expected in NOTATION declaration\n");
5823
0
            xmlFreeEnumeration(ret);
5824
0
      return(NULL);
5825
0
  }
5826
0
  tmp = ret;
5827
0
  while (tmp != NULL) {
5828
0
      if (xmlStrEqual(name, tmp->name)) {
5829
0
    xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
5830
0
    "standalone: attribute notation value token %s duplicated\n",
5831
0
         name, NULL);
5832
0
    if (!xmlDictOwns(ctxt->dict, name))
5833
0
        xmlFree((xmlChar *) name);
5834
0
    break;
5835
0
      }
5836
0
      tmp = tmp->next;
5837
0
  }
5838
0
  if (tmp == NULL) {
5839
0
      cur = xmlCreateEnumeration(name);
5840
0
      if (cur == NULL) {
5841
0
                xmlFreeEnumeration(ret);
5842
0
                return(NULL);
5843
0
            }
5844
0
      if (last == NULL) ret = last = cur;
5845
0
      else {
5846
0
    last->next = cur;
5847
0
    last = cur;
5848
0
      }
5849
0
  }
5850
0
  SKIP_BLANKS;
5851
0
    } while (RAW == '|');
5852
0
    if (RAW != ')') {
5853
0
  xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
5854
0
        xmlFreeEnumeration(ret);
5855
0
  return(NULL);
5856
0
    }
5857
0
    NEXT;
5858
0
    return(ret);
5859
0
}
5860
5861
/**
5862
 * xmlParseEnumerationType:
5863
 * @ctxt:  an XML parser context
5864
 *
5865
 * DEPRECATED: Internal function, don't use.
5866
 *
5867
 * parse an Enumeration attribute type.
5868
 *
5869
 * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
5870
 *
5871
 * [ VC: Enumeration ]
5872
 * Values of this type must match one of the Nmtoken tokens in
5873
 * the declaration
5874
 *
5875
 * Returns: the enumeration attribute tree built while parsing
5876
 */
5877
5878
xmlEnumerationPtr
5879
0
xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
5880
0
    xmlChar *name;
5881
0
    xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
5882
5883
0
    if (RAW != '(') {
5884
0
  xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_STARTED, NULL);
5885
0
  return(NULL);
5886
0
    }
5887
0
    SHRINK;
5888
0
    do {
5889
0
        NEXT;
5890
0
  SKIP_BLANKS;
5891
0
        name = xmlParseNmtoken(ctxt);
5892
0
  if (name == NULL) {
5893
0
      xmlFatalErr(ctxt, XML_ERR_NMTOKEN_REQUIRED, NULL);
5894
0
      return(ret);
5895
0
  }
5896
0
  tmp = ret;
5897
0
  while (tmp != NULL) {
5898
0
      if (xmlStrEqual(name, tmp->name)) {
5899
0
    xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
5900
0
    "standalone: attribute enumeration value token %s duplicated\n",
5901
0
         name, NULL);
5902
0
    if (!xmlDictOwns(ctxt->dict, name))
5903
0
        xmlFree(name);
5904
0
    break;
5905
0
      }
5906
0
      tmp = tmp->next;
5907
0
  }
5908
0
  if (tmp == NULL) {
5909
0
      cur = xmlCreateEnumeration(name);
5910
0
      if (!xmlDictOwns(ctxt->dict, name))
5911
0
    xmlFree(name);
5912
0
      if (cur == NULL) {
5913
0
                xmlFreeEnumeration(ret);
5914
0
                return(NULL);
5915
0
            }
5916
0
      if (last == NULL) ret = last = cur;
5917
0
      else {
5918
0
    last->next = cur;
5919
0
    last = cur;
5920
0
      }
5921
0
  }
5922
0
  SKIP_BLANKS;
5923
0
    } while (RAW == '|');
5924
0
    if (RAW != ')') {
5925
0
  xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_FINISHED, NULL);
5926
0
  return(ret);
5927
0
    }
5928
0
    NEXT;
5929
0
    return(ret);
5930
0
}
5931
5932
/**
5933
 * xmlParseEnumeratedType:
5934
 * @ctxt:  an XML parser context
5935
 * @tree:  the enumeration tree built while parsing
5936
 *
5937
 * DEPRECATED: Internal function, don't use.
5938
 *
5939
 * parse an Enumerated attribute type.
5940
 *
5941
 * [57] EnumeratedType ::= NotationType | Enumeration
5942
 *
5943
 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
5944
 *
5945
 *
5946
 * Returns: XML_ATTRIBUTE_ENUMERATION or XML_ATTRIBUTE_NOTATION
5947
 */
5948
5949
int
5950
0
xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
5951
0
    if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
5952
0
  SKIP(8);
5953
0
  if (SKIP_BLANKS == 0) {
5954
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5955
0
         "Space required after 'NOTATION'\n");
5956
0
      return(0);
5957
0
  }
5958
0
  *tree = xmlParseNotationType(ctxt);
5959
0
  if (*tree == NULL) return(0);
5960
0
  return(XML_ATTRIBUTE_NOTATION);
5961
0
    }
5962
0
    *tree = xmlParseEnumerationType(ctxt);
5963
0
    if (*tree == NULL) return(0);
5964
0
    return(XML_ATTRIBUTE_ENUMERATION);
5965
0
}
5966
5967
/**
5968
 * xmlParseAttributeType:
5969
 * @ctxt:  an XML parser context
5970
 * @tree:  the enumeration tree built while parsing
5971
 *
5972
 * DEPRECATED: Internal function, don't use.
5973
 *
5974
 * parse the Attribute list def for an element
5975
 *
5976
 * [54] AttType ::= StringType | TokenizedType | EnumeratedType
5977
 *
5978
 * [55] StringType ::= 'CDATA'
5979
 *
5980
 * [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' |
5981
 *                        'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
5982
 *
5983
 * Validity constraints for attribute values syntax are checked in
5984
 * xmlValidateAttributeValue()
5985
 *
5986
 * [ VC: ID ]
5987
 * Values of type ID must match the Name production. A name must not
5988
 * appear more than once in an XML document as a value of this type;
5989
 * i.e., ID values must uniquely identify the elements which bear them.
5990
 *
5991
 * [ VC: One ID per Element Type ]
5992
 * No element type may have more than one ID attribute specified.
5993
 *
5994
 * [ VC: ID Attribute Default ]
5995
 * An ID attribute must have a declared default of #IMPLIED or #REQUIRED.
5996
 *
5997
 * [ VC: IDREF ]
5998
 * Values of type IDREF must match the Name production, and values
5999
 * of type IDREFS must match Names; each IDREF Name must match the value
6000
 * of an ID attribute on some element in the XML document; i.e. IDREF
6001
 * values must match the value of some ID attribute.
6002
 *
6003
 * [ VC: Entity Name ]
6004
 * Values of type ENTITY must match the Name production, values
6005
 * of type ENTITIES must match Names; each Entity Name must match the
6006
 * name of an unparsed entity declared in the DTD.
6007
 *
6008
 * [ VC: Name Token ]
6009
 * Values of type NMTOKEN must match the Nmtoken production; values
6010
 * of type NMTOKENS must match Nmtokens.
6011
 *
6012
 * Returns the attribute type
6013
 */
6014
int
6015
0
xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
6016
0
    SHRINK;
6017
0
    if (CMP5(CUR_PTR, 'C', 'D', 'A', 'T', 'A')) {
6018
0
  SKIP(5);
6019
0
  return(XML_ATTRIBUTE_CDATA);
6020
0
     } else if (CMP6(CUR_PTR, 'I', 'D', 'R', 'E', 'F', 'S')) {
6021
0
  SKIP(6);
6022
0
  return(XML_ATTRIBUTE_IDREFS);
6023
0
     } else if (CMP5(CUR_PTR, 'I', 'D', 'R', 'E', 'F')) {
6024
0
  SKIP(5);
6025
0
  return(XML_ATTRIBUTE_IDREF);
6026
0
     } else if ((RAW == 'I') && (NXT(1) == 'D')) {
6027
0
        SKIP(2);
6028
0
  return(XML_ATTRIBUTE_ID);
6029
0
     } else if (CMP6(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'Y')) {
6030
0
  SKIP(6);
6031
0
  return(XML_ATTRIBUTE_ENTITY);
6032
0
     } else if (CMP8(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S')) {
6033
0
  SKIP(8);
6034
0
  return(XML_ATTRIBUTE_ENTITIES);
6035
0
     } else if (CMP8(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S')) {
6036
0
  SKIP(8);
6037
0
  return(XML_ATTRIBUTE_NMTOKENS);
6038
0
     } else if (CMP7(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N')) {
6039
0
  SKIP(7);
6040
0
  return(XML_ATTRIBUTE_NMTOKEN);
6041
0
     }
6042
0
     return(xmlParseEnumeratedType(ctxt, tree));
6043
0
}
6044
6045
/**
6046
 * xmlParseAttributeListDecl:
6047
 * @ctxt:  an XML parser context
6048
 *
6049
 * DEPRECATED: Internal function, don't use.
6050
 *
6051
 * Parse an attribute list declaration for an element. Always consumes '<!'.
6052
 *
6053
 * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
6054
 *
6055
 * [53] AttDef ::= S Name S AttType S DefaultDecl
6056
 *
6057
 */
6058
void
6059
0
xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
6060
0
    const xmlChar *elemName;
6061
0
    const xmlChar *attrName;
6062
0
    xmlEnumerationPtr tree;
6063
6064
0
    if ((CUR != '<') || (NXT(1) != '!'))
6065
0
        return;
6066
0
    SKIP(2);
6067
6068
0
    if (CMP7(CUR_PTR, 'A', 'T', 'T', 'L', 'I', 'S', 'T')) {
6069
0
  int inputid = ctxt->input->id;
6070
6071
0
  SKIP(7);
6072
0
  if (SKIP_BLANKS == 0) {
6073
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6074
0
                     "Space required after '<!ATTLIST'\n");
6075
0
  }
6076
0
        elemName = xmlParseName(ctxt);
6077
0
  if (elemName == NULL) {
6078
0
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6079
0
         "ATTLIST: no name for Element\n");
6080
0
      return;
6081
0
  }
6082
0
  SKIP_BLANKS;
6083
0
  GROW;
6084
0
  while ((RAW != '>') && (ctxt->instate != XML_PARSER_EOF)) {
6085
0
      int type;
6086
0
      int def;
6087
0
      xmlChar *defaultValue = NULL;
6088
6089
0
      GROW;
6090
0
            tree = NULL;
6091
0
      attrName = xmlParseName(ctxt);
6092
0
      if (attrName == NULL) {
6093
0
    xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6094
0
             "ATTLIST: no name for Attribute\n");
6095
0
    break;
6096
0
      }
6097
0
      GROW;
6098
0
      if (SKIP_BLANKS == 0) {
6099
0
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6100
0
            "Space required after the attribute name\n");
6101
0
    break;
6102
0
      }
6103
6104
0
      type = xmlParseAttributeType(ctxt, &tree);
6105
0
      if (type <= 0) {
6106
0
          break;
6107
0
      }
6108
6109
0
      GROW;
6110
0
      if (SKIP_BLANKS == 0) {
6111
0
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6112
0
             "Space required after the attribute type\n");
6113
0
          if (tree != NULL)
6114
0
        xmlFreeEnumeration(tree);
6115
0
    break;
6116
0
      }
6117
6118
0
      def = xmlParseDefaultDecl(ctxt, &defaultValue);
6119
0
      if (def <= 0) {
6120
0
                if (defaultValue != NULL)
6121
0
        xmlFree(defaultValue);
6122
0
          if (tree != NULL)
6123
0
        xmlFreeEnumeration(tree);
6124
0
          break;
6125
0
      }
6126
0
      if ((type != XML_ATTRIBUTE_CDATA) && (defaultValue != NULL))
6127
0
          xmlAttrNormalizeSpace(defaultValue, defaultValue);
6128
6129
0
      GROW;
6130
0
            if (RAW != '>') {
6131
0
    if (SKIP_BLANKS == 0) {
6132
0
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6133
0
      "Space required after the attribute default value\n");
6134
0
        if (defaultValue != NULL)
6135
0
      xmlFree(defaultValue);
6136
0
        if (tree != NULL)
6137
0
      xmlFreeEnumeration(tree);
6138
0
        break;
6139
0
    }
6140
0
      }
6141
0
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
6142
0
    (ctxt->sax->attributeDecl != NULL))
6143
0
    ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
6144
0
                          type, def, defaultValue, tree);
6145
0
      else if (tree != NULL)
6146
0
    xmlFreeEnumeration(tree);
6147
6148
0
      if ((ctxt->sax2) && (defaultValue != NULL) &&
6149
0
          (def != XML_ATTRIBUTE_IMPLIED) &&
6150
0
    (def != XML_ATTRIBUTE_REQUIRED)) {
6151
0
    xmlAddDefAttrs(ctxt, elemName, attrName, defaultValue);
6152
0
      }
6153
0
      if (ctxt->sax2) {
6154
0
    xmlAddSpecialAttr(ctxt, elemName, attrName, type);
6155
0
      }
6156
0
      if (defaultValue != NULL)
6157
0
          xmlFree(defaultValue);
6158
0
      GROW;
6159
0
  }
6160
0
  if (RAW == '>') {
6161
0
      if (inputid != ctxt->input->id) {
6162
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6163
0
                               "Attribute list declaration doesn't start and"
6164
0
                               " stop in the same entity\n");
6165
0
      }
6166
0
      NEXT;
6167
0
  }
6168
0
    }
6169
0
}
6170
6171
/**
6172
 * xmlParseElementMixedContentDecl:
6173
 * @ctxt:  an XML parser context
6174
 * @inputchk:  the input used for the current entity, needed for boundary checks
6175
 *
6176
 * DEPRECATED: Internal function, don't use.
6177
 *
6178
 * parse the declaration for a Mixed Element content
6179
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6180
 *
6181
 * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' |
6182
 *                '(' S? '#PCDATA' S? ')'
6183
 *
6184
 * [ VC: Proper Group/PE Nesting ] applies to [51] too (see [49])
6185
 *
6186
 * [ VC: No Duplicate Types ]
6187
 * The same name must not appear more than once in a single
6188
 * mixed-content declaration.
6189
 *
6190
 * returns: the list of the xmlElementContentPtr describing the element choices
6191
 */
6192
xmlElementContentPtr
6193
0
xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
6194
0
    xmlElementContentPtr ret = NULL, cur = NULL, n;
6195
0
    const xmlChar *elem = NULL;
6196
6197
0
    GROW;
6198
0
    if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
6199
0
  SKIP(7);
6200
0
  SKIP_BLANKS;
6201
0
  SHRINK;
6202
0
  if (RAW == ')') {
6203
0
      if (ctxt->input->id != inputchk) {
6204
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6205
0
                               "Element content declaration doesn't start and"
6206
0
                               " stop in the same entity\n");
6207
0
      }
6208
0
      NEXT;
6209
0
      ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
6210
0
      if (ret == NULL)
6211
0
          return(NULL);
6212
0
      if (RAW == '*') {
6213
0
    ret->ocur = XML_ELEMENT_CONTENT_MULT;
6214
0
    NEXT;
6215
0
      }
6216
0
      return(ret);
6217
0
  }
6218
0
  if ((RAW == '(') || (RAW == '|')) {
6219
0
      ret = cur = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
6220
0
      if (ret == NULL) return(NULL);
6221
0
  }
6222
0
  while ((RAW == '|') && (ctxt->instate != XML_PARSER_EOF)) {
6223
0
      NEXT;
6224
0
      if (elem == NULL) {
6225
0
          ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6226
0
    if (ret == NULL) {
6227
0
        xmlFreeDocElementContent(ctxt->myDoc, cur);
6228
0
                    return(NULL);
6229
0
                }
6230
0
    ret->c1 = cur;
6231
0
    if (cur != NULL)
6232
0
        cur->parent = ret;
6233
0
    cur = ret;
6234
0
      } else {
6235
0
          n = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6236
0
    if (n == NULL) {
6237
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6238
0
                    return(NULL);
6239
0
                }
6240
0
    n->c1 = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6241
0
    if (n->c1 != NULL)
6242
0
        n->c1->parent = n;
6243
0
          cur->c2 = n;
6244
0
    if (n != NULL)
6245
0
        n->parent = cur;
6246
0
    cur = n;
6247
0
      }
6248
0
      SKIP_BLANKS;
6249
0
      elem = xmlParseName(ctxt);
6250
0
      if (elem == NULL) {
6251
0
    xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6252
0
      "xmlParseElementMixedContentDecl : Name expected\n");
6253
0
    xmlFreeDocElementContent(ctxt->myDoc, ret);
6254
0
    return(NULL);
6255
0
      }
6256
0
      SKIP_BLANKS;
6257
0
      GROW;
6258
0
  }
6259
0
  if ((RAW == ')') && (NXT(1) == '*')) {
6260
0
      if (elem != NULL) {
6261
0
    cur->c2 = xmlNewDocElementContent(ctxt->myDoc, elem,
6262
0
                                   XML_ELEMENT_CONTENT_ELEMENT);
6263
0
    if (cur->c2 != NULL)
6264
0
        cur->c2->parent = cur;
6265
0
            }
6266
0
            if (ret != NULL)
6267
0
                ret->ocur = XML_ELEMENT_CONTENT_MULT;
6268
0
      if (ctxt->input->id != inputchk) {
6269
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6270
0
                               "Element content declaration doesn't start and"
6271
0
                               " stop in the same entity\n");
6272
0
      }
6273
0
      SKIP(2);
6274
0
  } else {
6275
0
      xmlFreeDocElementContent(ctxt->myDoc, ret);
6276
0
      xmlFatalErr(ctxt, XML_ERR_MIXED_NOT_STARTED, NULL);
6277
0
      return(NULL);
6278
0
  }
6279
6280
0
    } else {
6281
0
  xmlFatalErr(ctxt, XML_ERR_PCDATA_REQUIRED, NULL);
6282
0
    }
6283
0
    return(ret);
6284
0
}
6285
6286
/**
6287
 * xmlParseElementChildrenContentDeclPriv:
6288
 * @ctxt:  an XML parser context
6289
 * @inputchk:  the input used for the current entity, needed for boundary checks
6290
 * @depth: the level of recursion
6291
 *
6292
 * parse the declaration for a Mixed Element content
6293
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6294
 *
6295
 *
6296
 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
6297
 *
6298
 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
6299
 *
6300
 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
6301
 *
6302
 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
6303
 *
6304
 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
6305
 * TODO Parameter-entity replacement text must be properly nested
6306
 *  with parenthesized groups. That is to say, if either of the
6307
 *  opening or closing parentheses in a choice, seq, or Mixed
6308
 *  construct is contained in the replacement text for a parameter
6309
 *  entity, both must be contained in the same replacement text. For
6310
 *  interoperability, if a parameter-entity reference appears in a
6311
 *  choice, seq, or Mixed construct, its replacement text should not
6312
 *  be empty, and neither the first nor last non-blank character of
6313
 *  the replacement text should be a connector (| or ,).
6314
 *
6315
 * Returns the tree of xmlElementContentPtr describing the element
6316
 *          hierarchy.
6317
 */
6318
static xmlElementContentPtr
6319
xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
6320
0
                                       int depth) {
6321
0
    xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
6322
0
    const xmlChar *elem;
6323
0
    xmlChar type = 0;
6324
6325
0
    if (((depth > 128) && ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
6326
0
        (depth >  2048)) {
6327
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED,
6328
0
"xmlParseElementChildrenContentDecl : depth %d too deep, use XML_PARSE_HUGE\n",
6329
0
                          depth);
6330
0
  return(NULL);
6331
0
    }
6332
0
    SKIP_BLANKS;
6333
0
    GROW;
6334
0
    if (RAW == '(') {
6335
0
  int inputid = ctxt->input->id;
6336
6337
        /* Recurse on first child */
6338
0
  NEXT;
6339
0
  SKIP_BLANKS;
6340
0
        cur = ret = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
6341
0
                                                           depth + 1);
6342
0
        if (cur == NULL)
6343
0
            return(NULL);
6344
0
  SKIP_BLANKS;
6345
0
  GROW;
6346
0
    } else {
6347
0
  elem = xmlParseName(ctxt);
6348
0
  if (elem == NULL) {
6349
0
      xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
6350
0
      return(NULL);
6351
0
  }
6352
0
        cur = ret = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6353
0
  if (cur == NULL) {
6354
0
      xmlErrMemory(ctxt, NULL);
6355
0
      return(NULL);
6356
0
  }
6357
0
  GROW;
6358
0
  if (RAW == '?') {
6359
0
      cur->ocur = XML_ELEMENT_CONTENT_OPT;
6360
0
      NEXT;
6361
0
  } else if (RAW == '*') {
6362
0
      cur->ocur = XML_ELEMENT_CONTENT_MULT;
6363
0
      NEXT;
6364
0
  } else if (RAW == '+') {
6365
0
      cur->ocur = XML_ELEMENT_CONTENT_PLUS;
6366
0
      NEXT;
6367
0
  } else {
6368
0
      cur->ocur = XML_ELEMENT_CONTENT_ONCE;
6369
0
  }
6370
0
  GROW;
6371
0
    }
6372
0
    SKIP_BLANKS;
6373
0
    SHRINK;
6374
0
    while ((RAW != ')') && (ctxt->instate != XML_PARSER_EOF)) {
6375
        /*
6376
   * Each loop we parse one separator and one element.
6377
   */
6378
0
        if (RAW == ',') {
6379
0
      if (type == 0) type = CUR;
6380
6381
      /*
6382
       * Detect "Name | Name , Name" error
6383
       */
6384
0
      else if (type != CUR) {
6385
0
    xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
6386
0
        "xmlParseElementChildrenContentDecl : '%c' expected\n",
6387
0
                      type);
6388
0
    if ((last != NULL) && (last != ret))
6389
0
        xmlFreeDocElementContent(ctxt->myDoc, last);
6390
0
    if (ret != NULL)
6391
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6392
0
    return(NULL);
6393
0
      }
6394
0
      NEXT;
6395
6396
0
      op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_SEQ);
6397
0
      if (op == NULL) {
6398
0
    if ((last != NULL) && (last != ret))
6399
0
        xmlFreeDocElementContent(ctxt->myDoc, last);
6400
0
          xmlFreeDocElementContent(ctxt->myDoc, ret);
6401
0
    return(NULL);
6402
0
      }
6403
0
      if (last == NULL) {
6404
0
    op->c1 = ret;
6405
0
    if (ret != NULL)
6406
0
        ret->parent = op;
6407
0
    ret = cur = op;
6408
0
      } else {
6409
0
          cur->c2 = op;
6410
0
    if (op != NULL)
6411
0
        op->parent = cur;
6412
0
    op->c1 = last;
6413
0
    if (last != NULL)
6414
0
        last->parent = op;
6415
0
    cur =op;
6416
0
    last = NULL;
6417
0
      }
6418
0
  } else if (RAW == '|') {
6419
0
      if (type == 0) type = CUR;
6420
6421
      /*
6422
       * Detect "Name , Name | Name" error
6423
       */
6424
0
      else if (type != CUR) {
6425
0
    xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
6426
0
        "xmlParseElementChildrenContentDecl : '%c' expected\n",
6427
0
          type);
6428
0
    if ((last != NULL) && (last != ret))
6429
0
        xmlFreeDocElementContent(ctxt->myDoc, last);
6430
0
    if (ret != NULL)
6431
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6432
0
    return(NULL);
6433
0
      }
6434
0
      NEXT;
6435
6436
0
      op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6437
0
      if (op == NULL) {
6438
0
    if ((last != NULL) && (last != ret))
6439
0
        xmlFreeDocElementContent(ctxt->myDoc, last);
6440
0
    if (ret != NULL)
6441
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6442
0
    return(NULL);
6443
0
      }
6444
0
      if (last == NULL) {
6445
0
    op->c1 = ret;
6446
0
    if (ret != NULL)
6447
0
        ret->parent = op;
6448
0
    ret = cur = op;
6449
0
      } else {
6450
0
          cur->c2 = op;
6451
0
    if (op != NULL)
6452
0
        op->parent = cur;
6453
0
    op->c1 = last;
6454
0
    if (last != NULL)
6455
0
        last->parent = op;
6456
0
    cur =op;
6457
0
    last = NULL;
6458
0
      }
6459
0
  } else {
6460
0
      xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED, NULL);
6461
0
      if ((last != NULL) && (last != ret))
6462
0
          xmlFreeDocElementContent(ctxt->myDoc, last);
6463
0
      if (ret != NULL)
6464
0
    xmlFreeDocElementContent(ctxt->myDoc, ret);
6465
0
      return(NULL);
6466
0
  }
6467
0
  GROW;
6468
0
  SKIP_BLANKS;
6469
0
  GROW;
6470
0
  if (RAW == '(') {
6471
0
      int inputid = ctxt->input->id;
6472
      /* Recurse on second child */
6473
0
      NEXT;
6474
0
      SKIP_BLANKS;
6475
0
      last = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
6476
0
                                                          depth + 1);
6477
0
            if (last == NULL) {
6478
0
    if (ret != NULL)
6479
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6480
0
    return(NULL);
6481
0
            }
6482
0
      SKIP_BLANKS;
6483
0
  } else {
6484
0
      elem = xmlParseName(ctxt);
6485
0
      if (elem == NULL) {
6486
0
    xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
6487
0
    if (ret != NULL)
6488
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6489
0
    return(NULL);
6490
0
      }
6491
0
      last = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6492
0
      if (last == NULL) {
6493
0
    if (ret != NULL)
6494
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6495
0
    return(NULL);
6496
0
      }
6497
0
      if (RAW == '?') {
6498
0
    last->ocur = XML_ELEMENT_CONTENT_OPT;
6499
0
    NEXT;
6500
0
      } else if (RAW == '*') {
6501
0
    last->ocur = XML_ELEMENT_CONTENT_MULT;
6502
0
    NEXT;
6503
0
      } else if (RAW == '+') {
6504
0
    last->ocur = XML_ELEMENT_CONTENT_PLUS;
6505
0
    NEXT;
6506
0
      } else {
6507
0
    last->ocur = XML_ELEMENT_CONTENT_ONCE;
6508
0
      }
6509
0
  }
6510
0
  SKIP_BLANKS;
6511
0
  GROW;
6512
0
    }
6513
0
    if ((cur != NULL) && (last != NULL)) {
6514
0
        cur->c2 = last;
6515
0
  if (last != NULL)
6516
0
      last->parent = cur;
6517
0
    }
6518
0
    if (ctxt->input->id != inputchk) {
6519
0
  xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6520
0
                       "Element content declaration doesn't start and stop in"
6521
0
                       " the same entity\n");
6522
0
    }
6523
0
    NEXT;
6524
0
    if (RAW == '?') {
6525
0
  if (ret != NULL) {
6526
0
      if ((ret->ocur == XML_ELEMENT_CONTENT_PLUS) ||
6527
0
          (ret->ocur == XML_ELEMENT_CONTENT_MULT))
6528
0
          ret->ocur = XML_ELEMENT_CONTENT_MULT;
6529
0
      else
6530
0
          ret->ocur = XML_ELEMENT_CONTENT_OPT;
6531
0
  }
6532
0
  NEXT;
6533
0
    } else if (RAW == '*') {
6534
0
  if (ret != NULL) {
6535
0
      ret->ocur = XML_ELEMENT_CONTENT_MULT;
6536
0
      cur = ret;
6537
      /*
6538
       * Some normalization:
6539
       * (a | b* | c?)* == (a | b | c)*
6540
       */
6541
0
      while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
6542
0
    if ((cur->c1 != NULL) &&
6543
0
              ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
6544
0
         (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT)))
6545
0
        cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
6546
0
    if ((cur->c2 != NULL) &&
6547
0
              ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
6548
0
         (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT)))
6549
0
        cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
6550
0
    cur = cur->c2;
6551
0
      }
6552
0
  }
6553
0
  NEXT;
6554
0
    } else if (RAW == '+') {
6555
0
  if (ret != NULL) {
6556
0
      int found = 0;
6557
6558
0
      if ((ret->ocur == XML_ELEMENT_CONTENT_OPT) ||
6559
0
          (ret->ocur == XML_ELEMENT_CONTENT_MULT))
6560
0
          ret->ocur = XML_ELEMENT_CONTENT_MULT;
6561
0
      else
6562
0
          ret->ocur = XML_ELEMENT_CONTENT_PLUS;
6563
      /*
6564
       * Some normalization:
6565
       * (a | b*)+ == (a | b)*
6566
       * (a | b?)+ == (a | b)*
6567
       */
6568
0
      while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
6569
0
    if ((cur->c1 != NULL) &&
6570
0
              ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
6571
0
         (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT))) {
6572
0
        cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
6573
0
        found = 1;
6574
0
    }
6575
0
    if ((cur->c2 != NULL) &&
6576
0
              ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
6577
0
         (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT))) {
6578
0
        cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
6579
0
        found = 1;
6580
0
    }
6581
0
    cur = cur->c2;
6582
0
      }
6583
0
      if (found)
6584
0
    ret->ocur = XML_ELEMENT_CONTENT_MULT;
6585
0
  }
6586
0
  NEXT;
6587
0
    }
6588
0
    return(ret);
6589
0
}
6590
6591
/**
6592
 * xmlParseElementChildrenContentDecl:
6593
 * @ctxt:  an XML parser context
6594
 * @inputchk:  the input used for the current entity, needed for boundary checks
6595
 *
6596
 * DEPRECATED: Internal function, don't use.
6597
 *
6598
 * parse the declaration for a Mixed Element content
6599
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6600
 *
6601
 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
6602
 *
6603
 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
6604
 *
6605
 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
6606
 *
6607
 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
6608
 *
6609
 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
6610
 * TODO Parameter-entity replacement text must be properly nested
6611
 *  with parenthesized groups. That is to say, if either of the
6612
 *  opening or closing parentheses in a choice, seq, or Mixed
6613
 *  construct is contained in the replacement text for a parameter
6614
 *  entity, both must be contained in the same replacement text. For
6615
 *  interoperability, if a parameter-entity reference appears in a
6616
 *  choice, seq, or Mixed construct, its replacement text should not
6617
 *  be empty, and neither the first nor last non-blank character of
6618
 *  the replacement text should be a connector (| or ,).
6619
 *
6620
 * Returns the tree of xmlElementContentPtr describing the element
6621
 *          hierarchy.
6622
 */
6623
xmlElementContentPtr
6624
0
xmlParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
6625
    /* stub left for API/ABI compat */
6626
0
    return(xmlParseElementChildrenContentDeclPriv(ctxt, inputchk, 1));
6627
0
}
6628
6629
/**
6630
 * xmlParseElementContentDecl:
6631
 * @ctxt:  an XML parser context
6632
 * @name:  the name of the element being defined.
6633
 * @result:  the Element Content pointer will be stored here if any
6634
 *
6635
 * DEPRECATED: Internal function, don't use.
6636
 *
6637
 * parse the declaration for an Element content either Mixed or Children,
6638
 * the cases EMPTY and ANY are handled directly in xmlParseElementDecl
6639
 *
6640
 * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
6641
 *
6642
 * returns: the type of element content XML_ELEMENT_TYPE_xxx
6643
 */
6644
6645
int
6646
xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, const xmlChar *name,
6647
0
                           xmlElementContentPtr *result) {
6648
6649
0
    xmlElementContentPtr tree = NULL;
6650
0
    int inputid = ctxt->input->id;
6651
0
    int res;
6652
6653
0
    *result = NULL;
6654
6655
0
    if (RAW != '(') {
6656
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
6657
0
    "xmlParseElementContentDecl : %s '(' expected\n", name);
6658
0
  return(-1);
6659
0
    }
6660
0
    NEXT;
6661
0
    GROW;
6662
0
    if (ctxt->instate == XML_PARSER_EOF)
6663
0
        return(-1);
6664
0
    SKIP_BLANKS;
6665
0
    if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
6666
0
        tree = xmlParseElementMixedContentDecl(ctxt, inputid);
6667
0
  res = XML_ELEMENT_TYPE_MIXED;
6668
0
    } else {
6669
0
        tree = xmlParseElementChildrenContentDeclPriv(ctxt, inputid, 1);
6670
0
  res = XML_ELEMENT_TYPE_ELEMENT;
6671
0
    }
6672
0
    SKIP_BLANKS;
6673
0
    *result = tree;
6674
0
    return(res);
6675
0
}
6676
6677
/**
6678
 * xmlParseElementDecl:
6679
 * @ctxt:  an XML parser context
6680
 *
6681
 * DEPRECATED: Internal function, don't use.
6682
 *
6683
 * Parse an element declaration. Always consumes '<!'.
6684
 *
6685
 * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
6686
 *
6687
 * [ VC: Unique Element Type Declaration ]
6688
 * No element type may be declared more than once
6689
 *
6690
 * Returns the type of the element, or -1 in case of error
6691
 */
6692
int
6693
0
xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
6694
0
    const xmlChar *name;
6695
0
    int ret = -1;
6696
0
    xmlElementContentPtr content  = NULL;
6697
6698
0
    if ((CUR != '<') || (NXT(1) != '!'))
6699
0
        return(ret);
6700
0
    SKIP(2);
6701
6702
    /* GROW; done in the caller */
6703
0
    if (CMP7(CUR_PTR, 'E', 'L', 'E', 'M', 'E', 'N', 'T')) {
6704
0
  int inputid = ctxt->input->id;
6705
6706
0
  SKIP(7);
6707
0
  if (SKIP_BLANKS == 0) {
6708
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6709
0
               "Space required after 'ELEMENT'\n");
6710
0
      return(-1);
6711
0
  }
6712
0
        name = xmlParseName(ctxt);
6713
0
  if (name == NULL) {
6714
0
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6715
0
         "xmlParseElementDecl: no name for Element\n");
6716
0
      return(-1);
6717
0
  }
6718
0
  if (SKIP_BLANKS == 0) {
6719
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6720
0
         "Space required after the element name\n");
6721
0
  }
6722
0
  if (CMP5(CUR_PTR, 'E', 'M', 'P', 'T', 'Y')) {
6723
0
      SKIP(5);
6724
      /*
6725
       * Element must always be empty.
6726
       */
6727
0
      ret = XML_ELEMENT_TYPE_EMPTY;
6728
0
  } else if ((RAW == 'A') && (NXT(1) == 'N') &&
6729
0
             (NXT(2) == 'Y')) {
6730
0
      SKIP(3);
6731
      /*
6732
       * Element is a generic container.
6733
       */
6734
0
      ret = XML_ELEMENT_TYPE_ANY;
6735
0
  } else if (RAW == '(') {
6736
0
      ret = xmlParseElementContentDecl(ctxt, name, &content);
6737
0
  } else {
6738
      /*
6739
       * [ WFC: PEs in Internal Subset ] error handling.
6740
       */
6741
0
      if ((RAW == '%') && (ctxt->external == 0) &&
6742
0
          (ctxt->inputNr == 1)) {
6743
0
    xmlFatalErrMsg(ctxt, XML_ERR_PEREF_IN_INT_SUBSET,
6744
0
    "PEReference: forbidden within markup decl in internal subset\n");
6745
0
      } else {
6746
0
    xmlFatalErrMsg(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
6747
0
          "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
6748
0
            }
6749
0
      return(-1);
6750
0
  }
6751
6752
0
  SKIP_BLANKS;
6753
6754
0
  if (RAW != '>') {
6755
0
      xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
6756
0
      if (content != NULL) {
6757
0
    xmlFreeDocElementContent(ctxt->myDoc, content);
6758
0
      }
6759
0
  } else {
6760
0
      if (inputid != ctxt->input->id) {
6761
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6762
0
                               "Element declaration doesn't start and stop in"
6763
0
                               " the same entity\n");
6764
0
      }
6765
6766
0
      NEXT;
6767
0
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
6768
0
    (ctxt->sax->elementDecl != NULL)) {
6769
0
    if (content != NULL)
6770
0
        content->parent = NULL;
6771
0
          ctxt->sax->elementDecl(ctxt->userData, name, ret,
6772
0
                           content);
6773
0
    if ((content != NULL) && (content->parent == NULL)) {
6774
        /*
6775
         * this is a trick: if xmlAddElementDecl is called,
6776
         * instead of copying the full tree it is plugged directly
6777
         * if called from the parser. Avoid duplicating the
6778
         * interfaces or change the API/ABI
6779
         */
6780
0
        xmlFreeDocElementContent(ctxt->myDoc, content);
6781
0
    }
6782
0
      } else if (content != NULL) {
6783
0
    xmlFreeDocElementContent(ctxt->myDoc, content);
6784
0
      }
6785
0
  }
6786
0
    }
6787
0
    return(ret);
6788
0
}
6789
6790
/**
6791
 * xmlParseConditionalSections
6792
 * @ctxt:  an XML parser context
6793
 *
6794
 * Parse a conditional section. Always consumes '<!['.
6795
 *
6796
 * [61] conditionalSect ::= includeSect | ignoreSect
6797
 * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
6798
 * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
6799
 * [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
6800
 * [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
6801
 */
6802
6803
static void
6804
0
xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
6805
0
    int *inputIds = NULL;
6806
0
    size_t inputIdsSize = 0;
6807
0
    size_t depth = 0;
6808
6809
0
    while (ctxt->instate != XML_PARSER_EOF) {
6810
0
        if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
6811
0
            int id = ctxt->input->id;
6812
6813
0
            SKIP(3);
6814
0
            SKIP_BLANKS;
6815
6816
0
            if (CMP7(CUR_PTR, 'I', 'N', 'C', 'L', 'U', 'D', 'E')) {
6817
0
                SKIP(7);
6818
0
                SKIP_BLANKS;
6819
0
                if (RAW != '[') {
6820
0
                    xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
6821
0
                    xmlHaltParser(ctxt);
6822
0
                    goto error;
6823
0
                }
6824
0
                if (ctxt->input->id != id) {
6825
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6826
0
                                   "All markup of the conditional section is"
6827
0
                                   " not in the same entity\n");
6828
0
                }
6829
0
                NEXT;
6830
6831
0
                if (inputIdsSize <= depth) {
6832
0
                    int *tmp;
6833
6834
0
                    inputIdsSize = (inputIdsSize == 0 ? 4 : inputIdsSize * 2);
6835
0
                    tmp = (int *) xmlRealloc(inputIds,
6836
0
                            inputIdsSize * sizeof(int));
6837
0
                    if (tmp == NULL) {
6838
0
                        xmlErrMemory(ctxt, NULL);
6839
0
                        goto error;
6840
0
                    }
6841
0
                    inputIds = tmp;
6842
0
                }
6843
0
                inputIds[depth] = id;
6844
0
                depth++;
6845
0
            } else if (CMP6(CUR_PTR, 'I', 'G', 'N', 'O', 'R', 'E')) {
6846
0
                size_t ignoreDepth = 0;
6847
6848
0
                SKIP(6);
6849
0
                SKIP_BLANKS;
6850
0
                if (RAW != '[') {
6851
0
                    xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
6852
0
                    xmlHaltParser(ctxt);
6853
0
                    goto error;
6854
0
                }
6855
0
                if (ctxt->input->id != id) {
6856
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6857
0
                                   "All markup of the conditional section is"
6858
0
                                   " not in the same entity\n");
6859
0
                }
6860
0
                NEXT;
6861
6862
0
                while (RAW != 0) {
6863
0
                    if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
6864
0
                        SKIP(3);
6865
0
                        ignoreDepth++;
6866
                        /* Check for integer overflow */
6867
0
                        if (ignoreDepth == 0) {
6868
0
                            xmlErrMemory(ctxt, NULL);
6869
0
                            goto error;
6870
0
                        }
6871
0
                    } else if ((RAW == ']') && (NXT(1) == ']') &&
6872
0
                               (NXT(2) == '>')) {
6873
0
                        if (ignoreDepth == 0)
6874
0
                            break;
6875
0
                        SKIP(3);
6876
0
                        ignoreDepth--;
6877
0
                    } else {
6878
0
                        NEXT;
6879
0
                    }
6880
0
                }
6881
6882
0
    if (RAW == 0) {
6883
0
        xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
6884
0
                    goto error;
6885
0
    }
6886
0
                if (ctxt->input->id != id) {
6887
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6888
0
                                   "All markup of the conditional section is"
6889
0
                                   " not in the same entity\n");
6890
0
                }
6891
0
                SKIP(3);
6892
0
            } else {
6893
0
                xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
6894
0
                xmlHaltParser(ctxt);
6895
0
                goto error;
6896
0
            }
6897
0
        } else if ((depth > 0) &&
6898
0
                   (RAW == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
6899
0
            depth--;
6900
0
            if (ctxt->input->id != inputIds[depth]) {
6901
0
                xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6902
0
                               "All markup of the conditional section is not"
6903
0
                               " in the same entity\n");
6904
0
            }
6905
0
            SKIP(3);
6906
0
        } else if ((RAW == '<') && ((NXT(1) == '!') || (NXT(1) == '?'))) {
6907
0
            xmlParseMarkupDecl(ctxt);
6908
0
        } else {
6909
0
            xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
6910
0
            xmlHaltParser(ctxt);
6911
0
            goto error;
6912
0
        }
6913
6914
0
        if (depth == 0)
6915
0
            break;
6916
6917
0
        SKIP_BLANKS;
6918
0
        GROW;
6919
0
    }
6920
6921
0
error:
6922
0
    xmlFree(inputIds);
6923
0
}
6924
6925
/**
6926
 * xmlParseMarkupDecl:
6927
 * @ctxt:  an XML parser context
6928
 *
6929
 * DEPRECATED: Internal function, don't use.
6930
 *
6931
 * Parse markup declarations. Always consumes '<!' or '<?'.
6932
 *
6933
 * [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
6934
 *                     NotationDecl | PI | Comment
6935
 *
6936
 * [ VC: Proper Declaration/PE Nesting ]
6937
 * Parameter-entity replacement text must be properly nested with
6938
 * markup declarations. That is to say, if either the first character
6939
 * or the last character of a markup declaration (markupdecl above) is
6940
 * contained in the replacement text for a parameter-entity reference,
6941
 * both must be contained in the same replacement text.
6942
 *
6943
 * [ WFC: PEs in Internal Subset ]
6944
 * In the internal DTD subset, parameter-entity references can occur
6945
 * only where markup declarations can occur, not within markup declarations.
6946
 * (This does not apply to references that occur in external parameter
6947
 * entities or to the external subset.)
6948
 */
6949
void
6950
0
xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
6951
0
    GROW;
6952
0
    if (CUR == '<') {
6953
0
        if (NXT(1) == '!') {
6954
0
      switch (NXT(2)) {
6955
0
          case 'E':
6956
0
        if (NXT(3) == 'L')
6957
0
      xmlParseElementDecl(ctxt);
6958
0
        else if (NXT(3) == 'N')
6959
0
      xmlParseEntityDecl(ctxt);
6960
0
                    else
6961
0
                        SKIP(2);
6962
0
        break;
6963
0
          case 'A':
6964
0
        xmlParseAttributeListDecl(ctxt);
6965
0
        break;
6966
0
          case 'N':
6967
0
        xmlParseNotationDecl(ctxt);
6968
0
        break;
6969
0
          case '-':
6970
0
        xmlParseComment(ctxt);
6971
0
        break;
6972
0
    default:
6973
        /* there is an error but it will be detected later */
6974
0
                    SKIP(2);
6975
0
        break;
6976
0
      }
6977
0
  } else if (NXT(1) == '?') {
6978
0
      xmlParsePI(ctxt);
6979
0
  }
6980
0
    }
6981
6982
    /*
6983
     * detect requirement to exit there and act accordingly
6984
     * and avoid having instate overridden later on
6985
     */
6986
0
    if (ctxt->instate == XML_PARSER_EOF)
6987
0
        return;
6988
6989
0
    ctxt->instate = XML_PARSER_DTD;
6990
0
}
6991
6992
/**
6993
 * xmlParseTextDecl:
6994
 * @ctxt:  an XML parser context
6995
 *
6996
 * DEPRECATED: Internal function, don't use.
6997
 *
6998
 * parse an XML declaration header for external entities
6999
 *
7000
 * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
7001
 */
7002
7003
void
7004
0
xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
7005
0
    xmlChar *version;
7006
0
    const xmlChar *encoding;
7007
0
    int oldstate;
7008
7009
    /*
7010
     * We know that '<?xml' is here.
7011
     */
7012
0
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
7013
0
  SKIP(5);
7014
0
    } else {
7015
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_STARTED, NULL);
7016
0
  return;
7017
0
    }
7018
7019
    /* Avoid expansion of parameter entities when skipping blanks. */
7020
0
    oldstate = ctxt->instate;
7021
0
    ctxt->instate = XML_PARSER_START;
7022
7023
0
    if (SKIP_BLANKS == 0) {
7024
0
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
7025
0
           "Space needed after '<?xml'\n");
7026
0
    }
7027
7028
    /*
7029
     * We may have the VersionInfo here.
7030
     */
7031
0
    version = xmlParseVersionInfo(ctxt);
7032
0
    if (version == NULL)
7033
0
  version = xmlCharStrdup(XML_DEFAULT_VERSION);
7034
0
    else {
7035
0
  if (SKIP_BLANKS == 0) {
7036
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
7037
0
               "Space needed here\n");
7038
0
  }
7039
0
    }
7040
0
    ctxt->input->version = version;
7041
7042
    /*
7043
     * We must have the encoding declaration
7044
     */
7045
0
    encoding = xmlParseEncodingDecl(ctxt);
7046
0
    if (ctxt->instate == XML_PARSER_EOF)
7047
0
        return;
7048
0
    if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
7049
  /*
7050
   * The XML REC instructs us to stop parsing right here
7051
   */
7052
0
        ctxt->instate = oldstate;
7053
0
        return;
7054
0
    }
7055
0
    if ((encoding == NULL) && (ctxt->errNo == XML_ERR_OK)) {
7056
0
  xmlFatalErrMsg(ctxt, XML_ERR_MISSING_ENCODING,
7057
0
           "Missing encoding in text declaration\n");
7058
0
    }
7059
7060
0
    SKIP_BLANKS;
7061
0
    if ((RAW == '?') && (NXT(1) == '>')) {
7062
0
        SKIP(2);
7063
0
    } else if (RAW == '>') {
7064
        /* Deprecated old WD ... */
7065
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
7066
0
  NEXT;
7067
0
    } else {
7068
0
        int c;
7069
7070
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
7071
0
        while ((c = CUR) != 0) {
7072
0
            NEXT;
7073
0
            if (c == '>')
7074
0
                break;
7075
0
        }
7076
0
    }
7077
7078
0
    ctxt->instate = oldstate;
7079
0
}
7080
7081
/**
7082
 * xmlParseExternalSubset:
7083
 * @ctxt:  an XML parser context
7084
 * @ExternalID: the external identifier
7085
 * @SystemID: the system identifier (or URL)
7086
 *
7087
 * parse Markup declarations from an external subset
7088
 *
7089
 * [30] extSubset ::= textDecl? extSubsetDecl
7090
 *
7091
 * [31] extSubsetDecl ::= (markupdecl | conditionalSect | PEReference | S) *
7092
 */
7093
void
7094
xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
7095
0
                       const xmlChar *SystemID) {
7096
0
    xmlDetectSAX2(ctxt);
7097
0
    GROW;
7098
7099
0
    if ((ctxt->encoding == NULL) &&
7100
0
        (ctxt->input->end - ctxt->input->cur >= 4)) {
7101
0
        xmlChar start[4];
7102
0
  xmlCharEncoding enc;
7103
7104
0
  start[0] = RAW;
7105
0
  start[1] = NXT(1);
7106
0
  start[2] = NXT(2);
7107
0
  start[3] = NXT(3);
7108
0
  enc = xmlDetectCharEncoding(start, 4);
7109
0
  if (enc != XML_CHAR_ENCODING_NONE)
7110
0
      xmlSwitchEncoding(ctxt, enc);
7111
0
    }
7112
7113
0
    if (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) {
7114
0
  xmlParseTextDecl(ctxt);
7115
0
  if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
7116
      /*
7117
       * The XML REC instructs us to stop parsing right here
7118
       */
7119
0
      xmlHaltParser(ctxt);
7120
0
      return;
7121
0
  }
7122
0
    }
7123
0
    if (ctxt->myDoc == NULL) {
7124
0
        ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
7125
0
  if (ctxt->myDoc == NULL) {
7126
0
      xmlErrMemory(ctxt, "New Doc failed");
7127
0
      return;
7128
0
  }
7129
0
  ctxt->myDoc->properties = XML_DOC_INTERNAL;
7130
0
    }
7131
0
    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
7132
0
        xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
7133
7134
0
    ctxt->instate = XML_PARSER_DTD;
7135
0
    ctxt->external = 1;
7136
0
    SKIP_BLANKS;
7137
0
    while ((ctxt->instate != XML_PARSER_EOF) && (RAW != 0)) {
7138
0
  GROW;
7139
0
        if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
7140
0
            xmlParseConditionalSections(ctxt);
7141
0
        } else if ((RAW == '<') && ((NXT(1) == '!') || (NXT(1) == '?'))) {
7142
0
            xmlParseMarkupDecl(ctxt);
7143
0
        } else {
7144
0
            xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
7145
0
            xmlHaltParser(ctxt);
7146
0
            return;
7147
0
        }
7148
0
        SKIP_BLANKS;
7149
0
    }
7150
7151
0
    if (RAW != 0) {
7152
0
  xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
7153
0
    }
7154
7155
0
}
7156
7157
/**
7158
 * xmlParseReference:
7159
 * @ctxt:  an XML parser context
7160
 *
7161
 * DEPRECATED: Internal function, don't use.
7162
 *
7163
 * parse and handle entity references in content, depending on the SAX
7164
 * interface, this may end-up in a call to character() if this is a
7165
 * CharRef, a predefined entity, if there is no reference() callback.
7166
 * or if the parser was asked to switch to that mode.
7167
 *
7168
 * Always consumes '&'.
7169
 *
7170
 * [67] Reference ::= EntityRef | CharRef
7171
 */
7172
void
7173
3.69k
xmlParseReference(xmlParserCtxtPtr ctxt) {
7174
3.69k
    xmlEntityPtr ent;
7175
3.69k
    xmlChar *val;
7176
3.69k
    int was_checked;
7177
3.69k
    xmlNodePtr list = NULL;
7178
3.69k
    xmlParserErrors ret = XML_ERR_OK;
7179
7180
7181
3.69k
    if (RAW != '&')
7182
0
        return;
7183
7184
    /*
7185
     * Simple case of a CharRef
7186
     */
7187
3.69k
    if (NXT(1) == '#') {
7188
3.69k
  int i = 0;
7189
3.69k
  xmlChar out[16];
7190
3.69k
  int hex = NXT(2);
7191
3.69k
  int value = xmlParseCharRef(ctxt);
7192
7193
3.69k
  if (value == 0)
7194
0
      return;
7195
3.69k
  if (ctxt->charset != XML_CHAR_ENCODING_UTF8) {
7196
      /*
7197
       * So we are using non-UTF-8 buffers
7198
       * Check that the char fit on 8bits, if not
7199
       * generate a CharRef.
7200
       */
7201
0
      if (value <= 0xFF) {
7202
0
    out[0] = value;
7203
0
    out[1] = 0;
7204
0
    if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
7205
0
        (!ctxt->disableSAX))
7206
0
        ctxt->sax->characters(ctxt->userData, out, 1);
7207
0
      } else {
7208
0
    if ((hex == 'x') || (hex == 'X'))
7209
0
        snprintf((char *)out, sizeof(out), "#x%X", value);
7210
0
    else
7211
0
        snprintf((char *)out, sizeof(out), "#%d", value);
7212
0
    if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
7213
0
        (!ctxt->disableSAX))
7214
0
        ctxt->sax->reference(ctxt->userData, out);
7215
0
      }
7216
3.69k
  } else {
7217
      /*
7218
       * Just encode the value in UTF-8
7219
       */
7220
3.69k
      COPY_BUF(0 ,out, i, value);
7221
3.69k
      out[i] = 0;
7222
3.69k
      if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
7223
3.69k
    (!ctxt->disableSAX))
7224
3.69k
    ctxt->sax->characters(ctxt->userData, out, i);
7225
3.69k
  }
7226
3.69k
  return;
7227
3.69k
    }
7228
7229
    /*
7230
     * We are seeing an entity reference
7231
     */
7232
0
    ent = xmlParseEntityRef(ctxt);
7233
0
    if (ent == NULL) return;
7234
0
    if (!ctxt->wellFormed)
7235
0
  return;
7236
0
    was_checked = ent->flags & XML_ENT_PARSED;
7237
7238
    /* special case of predefined entities */
7239
0
    if ((ent->name == NULL) ||
7240
0
        (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
7241
0
  val = ent->content;
7242
0
  if (val == NULL) return;
7243
  /*
7244
   * inline the entity.
7245
   */
7246
0
  if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
7247
0
      (!ctxt->disableSAX))
7248
0
      ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
7249
0
  return;
7250
0
    }
7251
7252
    /*
7253
     * The first reference to the entity trigger a parsing phase
7254
     * where the ent->children is filled with the result from
7255
     * the parsing.
7256
     * Note: external parsed entities will not be loaded, it is not
7257
     * required for a non-validating parser, unless the parsing option
7258
     * of validating, or substituting entities were given. Doing so is
7259
     * far more secure as the parser will only process data coming from
7260
     * the document entity by default.
7261
     */
7262
0
    if (((ent->flags & XML_ENT_PARSED) == 0) &&
7263
0
        ((ent->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY) ||
7264
0
         (ctxt->options & (XML_PARSE_NOENT | XML_PARSE_DTDVALID)))) {
7265
0
  unsigned long oldsizeentcopy = ctxt->sizeentcopy;
7266
7267
  /*
7268
   * This is a bit hackish but this seems the best
7269
   * way to make sure both SAX and DOM entity support
7270
   * behaves okay.
7271
   */
7272
0
  void *user_data;
7273
0
  if (ctxt->userData == ctxt)
7274
0
      user_data = NULL;
7275
0
  else
7276
0
      user_data = ctxt->userData;
7277
7278
        /* Avoid overflow as much as possible */
7279
0
        ctxt->sizeentcopy = 0;
7280
7281
0
        if (ent->flags & XML_ENT_EXPANDING) {
7282
0
            xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
7283
0
            xmlHaltParser(ctxt);
7284
0
            return;
7285
0
        }
7286
7287
0
        ent->flags |= XML_ENT_EXPANDING;
7288
7289
  /*
7290
   * Check that this entity is well formed
7291
   * 4.3.2: An internal general parsed entity is well-formed
7292
   * if its replacement text matches the production labeled
7293
   * content.
7294
   */
7295
0
  if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
7296
0
      ctxt->depth++;
7297
0
      ret = xmlParseBalancedChunkMemoryInternal(ctxt, ent->content,
7298
0
                                                user_data, &list);
7299
0
      ctxt->depth--;
7300
7301
0
  } else if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
7302
0
      ctxt->depth++;
7303
0
      ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt, ctxt->sax,
7304
0
                                     user_data, ctxt->depth, ent->URI,
7305
0
             ent->ExternalID, &list);
7306
0
      ctxt->depth--;
7307
0
  } else {
7308
0
      ret = XML_ERR_ENTITY_PE_INTERNAL;
7309
0
      xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
7310
0
       "invalid entity type found\n", NULL);
7311
0
  }
7312
7313
0
        ent->flags &= ~XML_ENT_EXPANDING;
7314
0
        ent->flags |= XML_ENT_PARSED | XML_ENT_CHECKED;
7315
0
        ent->expandedSize = ctxt->sizeentcopy;
7316
0
  if (ret == XML_ERR_ENTITY_LOOP) {
7317
0
            xmlHaltParser(ctxt);
7318
0
      xmlFreeNodeList(list);
7319
0
      return;
7320
0
  }
7321
0
  if (xmlParserEntityCheck(ctxt, oldsizeentcopy)) {
7322
0
      xmlFreeNodeList(list);
7323
0
      return;
7324
0
  }
7325
7326
0
  if ((ret == XML_ERR_OK) && (list != NULL)) {
7327
0
            ent->children = list;
7328
            /*
7329
             * Prune it directly in the generated document
7330
             * except for single text nodes.
7331
             */
7332
0
            if ((ctxt->replaceEntities == 0) ||
7333
0
                (ctxt->parseMode == XML_PARSE_READER) ||
7334
0
                ((list->type == XML_TEXT_NODE) &&
7335
0
                 (list->next == NULL))) {
7336
0
                ent->owner = 1;
7337
0
                while (list != NULL) {
7338
0
                    list->parent = (xmlNodePtr) ent;
7339
0
                    if (list->doc != ent->doc)
7340
0
                        xmlSetTreeDoc(list, ent->doc);
7341
0
                    if (list->next == NULL)
7342
0
                        ent->last = list;
7343
0
                    list = list->next;
7344
0
                }
7345
0
                list = NULL;
7346
0
            } else {
7347
0
                ent->owner = 0;
7348
0
                while (list != NULL) {
7349
0
                    list->parent = (xmlNodePtr) ctxt->node;
7350
0
                    list->doc = ctxt->myDoc;
7351
0
                    if (list->next == NULL)
7352
0
                        ent->last = list;
7353
0
                    list = list->next;
7354
0
                }
7355
0
                list = ent->children;
7356
#ifdef LIBXML_LEGACY_ENABLED
7357
                if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7358
                    xmlAddEntityReference(ent, list, NULL);
7359
#endif /* LIBXML_LEGACY_ENABLED */
7360
0
            }
7361
0
  } else if ((ret != XML_ERR_OK) &&
7362
0
       (ret != XML_WAR_UNDECLARED_ENTITY)) {
7363
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7364
0
         "Entity '%s' failed to parse\n", ent->name);
7365
0
            if (ent->content != NULL)
7366
0
                ent->content[0] = 0;
7367
0
  } else if (list != NULL) {
7368
0
      xmlFreeNodeList(list);
7369
0
      list = NULL;
7370
0
  }
7371
7372
        /* Prevent entity from being parsed and expanded twice (Bug 760367). */
7373
0
        was_checked = 0;
7374
0
    }
7375
7376
    /*
7377
     * Now that the entity content has been gathered
7378
     * provide it to the application, this can take different forms based
7379
     * on the parsing modes.
7380
     */
7381
0
    if (ent->children == NULL) {
7382
  /*
7383
   * Probably running in SAX mode and the callbacks don't
7384
   * build the entity content. So unless we already went
7385
   * though parsing for first checking go though the entity
7386
   * content to generate callbacks associated to the entity
7387
   */
7388
0
  if (was_checked != 0) {
7389
0
      void *user_data;
7390
      /*
7391
       * This is a bit hackish but this seems the best
7392
       * way to make sure both SAX and DOM entity support
7393
       * behaves okay.
7394
       */
7395
0
      if (ctxt->userData == ctxt)
7396
0
    user_data = NULL;
7397
0
      else
7398
0
    user_data = ctxt->userData;
7399
7400
0
      if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
7401
0
    ctxt->depth++;
7402
0
    ret = xmlParseBalancedChunkMemoryInternal(ctxt,
7403
0
           ent->content, user_data, NULL);
7404
0
    ctxt->depth--;
7405
0
      } else if (ent->etype ==
7406
0
           XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
7407
0
          unsigned long oldsizeentities = ctxt->sizeentities;
7408
7409
0
    ctxt->depth++;
7410
0
    ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt,
7411
0
         ctxt->sax, user_data, ctxt->depth,
7412
0
         ent->URI, ent->ExternalID, NULL);
7413
0
    ctxt->depth--;
7414
7415
                /* Undo the change to sizeentities */
7416
0
                ctxt->sizeentities = oldsizeentities;
7417
0
      } else {
7418
0
    ret = XML_ERR_ENTITY_PE_INTERNAL;
7419
0
    xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
7420
0
           "invalid entity type found\n", NULL);
7421
0
      }
7422
0
      if (ret == XML_ERR_ENTITY_LOOP) {
7423
0
    xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
7424
0
    return;
7425
0
      }
7426
0
            if (xmlParserEntityCheck(ctxt, 0))
7427
0
                return;
7428
0
  }
7429
0
  if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
7430
0
      (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
7431
      /*
7432
       * Entity reference callback comes second, it's somewhat
7433
       * superfluous but a compatibility to historical behaviour
7434
       */
7435
0
      ctxt->sax->reference(ctxt->userData, ent->name);
7436
0
  }
7437
0
  return;
7438
0
    }
7439
7440
    /*
7441
     * We also check for amplification if entities aren't substituted.
7442
     * They might be expanded later.
7443
     */
7444
0
    if ((was_checked != 0) &&
7445
0
        (xmlParserEntityCheck(ctxt, ent->expandedSize)))
7446
0
        return;
7447
7448
    /*
7449
     * If we didn't get any children for the entity being built
7450
     */
7451
0
    if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
7452
0
  (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
7453
  /*
7454
   * Create a node.
7455
   */
7456
0
  ctxt->sax->reference(ctxt->userData, ent->name);
7457
0
  return;
7458
0
    }
7459
7460
0
    if (ctxt->replaceEntities)  {
7461
  /*
7462
   * There is a problem on the handling of _private for entities
7463
   * (bug 155816): Should we copy the content of the field from
7464
   * the entity (possibly overwriting some value set by the user
7465
   * when a copy is created), should we leave it alone, or should
7466
   * we try to take care of different situations?  The problem
7467
   * is exacerbated by the usage of this field by the xmlReader.
7468
   * To fix this bug, we look at _private on the created node
7469
   * and, if it's NULL, we copy in whatever was in the entity.
7470
   * If it's not NULL we leave it alone.  This is somewhat of a
7471
   * hack - maybe we should have further tests to determine
7472
   * what to do.
7473
   */
7474
0
  if (ctxt->node != NULL) {
7475
      /*
7476
       * Seems we are generating the DOM content, do
7477
       * a simple tree copy for all references except the first
7478
       * In the first occurrence list contains the replacement.
7479
       */
7480
0
      if (((list == NULL) && (ent->owner == 0)) ||
7481
0
    (ctxt->parseMode == XML_PARSE_READER)) {
7482
0
    xmlNodePtr nw = NULL, cur, firstChild = NULL;
7483
7484
    /*
7485
     * when operating on a reader, the entities definitions
7486
     * are always owning the entities subtree.
7487
    if (ctxt->parseMode == XML_PARSE_READER)
7488
        ent->owner = 1;
7489
     */
7490
7491
0
    cur = ent->children;
7492
0
    while (cur != NULL) {
7493
0
        nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
7494
0
        if (nw != NULL) {
7495
0
      if (nw->_private == NULL)
7496
0
          nw->_private = cur->_private;
7497
0
      if (firstChild == NULL){
7498
0
          firstChild = nw;
7499
0
      }
7500
0
      nw = xmlAddChild(ctxt->node, nw);
7501
0
        }
7502
0
        if (cur == ent->last) {
7503
      /*
7504
       * needed to detect some strange empty
7505
       * node cases in the reader tests
7506
       */
7507
0
      if ((ctxt->parseMode == XML_PARSE_READER) &&
7508
0
          (nw != NULL) &&
7509
0
          (nw->type == XML_ELEMENT_NODE) &&
7510
0
          (nw->children == NULL))
7511
0
          nw->extra = 1;
7512
7513
0
      break;
7514
0
        }
7515
0
        cur = cur->next;
7516
0
    }
7517
#ifdef LIBXML_LEGACY_ENABLED
7518
    if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7519
      xmlAddEntityReference(ent, firstChild, nw);
7520
#endif /* LIBXML_LEGACY_ENABLED */
7521
0
      } else if ((list == NULL) || (ctxt->inputNr > 0)) {
7522
0
    xmlNodePtr nw = NULL, cur, next, last,
7523
0
         firstChild = NULL;
7524
7525
    /*
7526
     * Copy the entity child list and make it the new
7527
     * entity child list. The goal is to make sure any
7528
     * ID or REF referenced will be the one from the
7529
     * document content and not the entity copy.
7530
     */
7531
0
    cur = ent->children;
7532
0
    ent->children = NULL;
7533
0
    last = ent->last;
7534
0
    ent->last = NULL;
7535
0
    while (cur != NULL) {
7536
0
        next = cur->next;
7537
0
        cur->next = NULL;
7538
0
        cur->parent = NULL;
7539
0
        nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
7540
0
        if (nw != NULL) {
7541
0
      if (nw->_private == NULL)
7542
0
          nw->_private = cur->_private;
7543
0
      if (firstChild == NULL){
7544
0
          firstChild = cur;
7545
0
      }
7546
0
      xmlAddChild((xmlNodePtr) ent, nw);
7547
0
        }
7548
0
        xmlAddChild(ctxt->node, cur);
7549
0
        if (cur == last)
7550
0
      break;
7551
0
        cur = next;
7552
0
    }
7553
0
    if (ent->owner == 0)
7554
0
        ent->owner = 1;
7555
#ifdef LIBXML_LEGACY_ENABLED
7556
    if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7557
      xmlAddEntityReference(ent, firstChild, nw);
7558
#endif /* LIBXML_LEGACY_ENABLED */
7559
0
      } else {
7560
0
    const xmlChar *nbktext;
7561
7562
    /*
7563
     * the name change is to avoid coalescing of the
7564
     * node with a possible previous text one which
7565
     * would make ent->children a dangling pointer
7566
     */
7567
0
    nbktext = xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
7568
0
          -1);
7569
0
    if (ent->children->type == XML_TEXT_NODE)
7570
0
        ent->children->name = nbktext;
7571
0
    if ((ent->last != ent->children) &&
7572
0
        (ent->last->type == XML_TEXT_NODE))
7573
0
        ent->last->name = nbktext;
7574
0
    xmlAddChildList(ctxt->node, ent->children);
7575
0
      }
7576
7577
      /*
7578
       * This is to avoid a nasty side effect, see
7579
       * characters() in SAX.c
7580
       */
7581
0
      ctxt->nodemem = 0;
7582
0
      ctxt->nodelen = 0;
7583
0
      return;
7584
0
  }
7585
0
    }
7586
0
}
7587
7588
/**
7589
 * xmlParseEntityRef:
7590
 * @ctxt:  an XML parser context
7591
 *
7592
 * DEPRECATED: Internal function, don't use.
7593
 *
7594
 * Parse an entitiy reference. Always consumes '&'.
7595
 *
7596
 * [68] EntityRef ::= '&' Name ';'
7597
 *
7598
 * [ WFC: Entity Declared ]
7599
 * In a document without any DTD, a document with only an internal DTD
7600
 * subset which contains no parameter entity references, or a document
7601
 * with "standalone='yes'", the Name given in the entity reference
7602
 * must match that in an entity declaration, except that well-formed
7603
 * documents need not declare any of the following entities: amp, lt,
7604
 * gt, apos, quot.  The declaration of a parameter entity must precede
7605
 * any reference to it.  Similarly, the declaration of a general entity
7606
 * must precede any reference to it which appears in a default value in an
7607
 * attribute-list declaration. Note that if entities are declared in the
7608
 * external subset or in external parameter entities, a non-validating
7609
 * processor is not obligated to read and process their declarations;
7610
 * for such documents, the rule that an entity must be declared is a
7611
 * well-formedness constraint only if standalone='yes'.
7612
 *
7613
 * [ WFC: Parsed Entity ]
7614
 * An entity reference must not contain the name of an unparsed entity
7615
 *
7616
 * Returns the xmlEntityPtr if found, or NULL otherwise.
7617
 */
7618
xmlEntityPtr
7619
0
xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
7620
0
    const xmlChar *name;
7621
0
    xmlEntityPtr ent = NULL;
7622
7623
0
    GROW;
7624
0
    if (ctxt->instate == XML_PARSER_EOF)
7625
0
        return(NULL);
7626
7627
0
    if (RAW != '&')
7628
0
        return(NULL);
7629
0
    NEXT;
7630
0
    name = xmlParseName(ctxt);
7631
0
    if (name == NULL) {
7632
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7633
0
           "xmlParseEntityRef: no name\n");
7634
0
        return(NULL);
7635
0
    }
7636
0
    if (RAW != ';') {
7637
0
  xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
7638
0
  return(NULL);
7639
0
    }
7640
0
    NEXT;
7641
7642
    /*
7643
     * Predefined entities override any extra definition
7644
     */
7645
0
    if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
7646
0
        ent = xmlGetPredefinedEntity(name);
7647
0
        if (ent != NULL)
7648
0
            return(ent);
7649
0
    }
7650
7651
    /*
7652
     * Ask first SAX for entity resolution, otherwise try the
7653
     * entities which may have stored in the parser context.
7654
     */
7655
0
    if (ctxt->sax != NULL) {
7656
0
  if (ctxt->sax->getEntity != NULL)
7657
0
      ent = ctxt->sax->getEntity(ctxt->userData, name);
7658
0
  if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
7659
0
      (ctxt->options & XML_PARSE_OLDSAX))
7660
0
      ent = xmlGetPredefinedEntity(name);
7661
0
  if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
7662
0
      (ctxt->userData==ctxt)) {
7663
0
      ent = xmlSAX2GetEntity(ctxt, name);
7664
0
  }
7665
0
    }
7666
0
    if (ctxt->instate == XML_PARSER_EOF)
7667
0
  return(NULL);
7668
    /*
7669
     * [ WFC: Entity Declared ]
7670
     * In a document without any DTD, a document with only an
7671
     * internal DTD subset which contains no parameter entity
7672
     * references, or a document with "standalone='yes'", the
7673
     * Name given in the entity reference must match that in an
7674
     * entity declaration, except that well-formed documents
7675
     * need not declare any of the following entities: amp, lt,
7676
     * gt, apos, quot.
7677
     * The declaration of a parameter entity must precede any
7678
     * reference to it.
7679
     * Similarly, the declaration of a general entity must
7680
     * precede any reference to it which appears in a default
7681
     * value in an attribute-list declaration. Note that if
7682
     * entities are declared in the external subset or in
7683
     * external parameter entities, a non-validating processor
7684
     * is not obligated to read and process their declarations;
7685
     * for such documents, the rule that an entity must be
7686
     * declared is a well-formedness constraint only if
7687
     * standalone='yes'.
7688
     */
7689
0
    if (ent == NULL) {
7690
0
  if ((ctxt->standalone == 1) ||
7691
0
      ((ctxt->hasExternalSubset == 0) &&
7692
0
       (ctxt->hasPErefs == 0))) {
7693
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7694
0
         "Entity '%s' not defined\n", name);
7695
0
  } else {
7696
0
      xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
7697
0
         "Entity '%s' not defined\n", name);
7698
0
      if ((ctxt->inSubset == 0) &&
7699
0
    (ctxt->sax != NULL) &&
7700
0
    (ctxt->sax->reference != NULL)) {
7701
0
    ctxt->sax->reference(ctxt->userData, name);
7702
0
      }
7703
0
  }
7704
0
  ctxt->valid = 0;
7705
0
    }
7706
7707
    /*
7708
     * [ WFC: Parsed Entity ]
7709
     * An entity reference must not contain the name of an
7710
     * unparsed entity
7711
     */
7712
0
    else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
7713
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
7714
0
     "Entity reference to unparsed entity %s\n", name);
7715
0
    }
7716
7717
    /*
7718
     * [ WFC: No External Entity References ]
7719
     * Attribute values cannot contain direct or indirect
7720
     * entity references to external entities.
7721
     */
7722
0
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7723
0
       (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
7724
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
7725
0
       "Attribute references external entity '%s'\n", name);
7726
0
    }
7727
    /*
7728
     * [ WFC: No < in Attribute Values ]
7729
     * The replacement text of any entity referred to directly or
7730
     * indirectly in an attribute value (other than "&lt;") must
7731
     * not contain a <.
7732
     */
7733
0
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7734
0
       (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
7735
0
  if ((ent->flags & XML_ENT_CHECKED_LT) == 0) {
7736
0
            if ((ent->content != NULL) && (xmlStrchr(ent->content, '<')))
7737
0
                ent->flags |= XML_ENT_CONTAINS_LT;
7738
0
            ent->flags |= XML_ENT_CHECKED_LT;
7739
0
        }
7740
0
        if (ent->flags & XML_ENT_CONTAINS_LT)
7741
0
            xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
7742
0
                    "'<' in entity '%s' is not allowed in attributes "
7743
0
                    "values\n", name);
7744
0
    }
7745
7746
    /*
7747
     * Internal check, no parameter entities here ...
7748
     */
7749
0
    else {
7750
0
  switch (ent->etype) {
7751
0
      case XML_INTERNAL_PARAMETER_ENTITY:
7752
0
      case XML_EXTERNAL_PARAMETER_ENTITY:
7753
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
7754
0
       "Attempt to reference the parameter entity '%s'\n",
7755
0
            name);
7756
0
      break;
7757
0
      default:
7758
0
      break;
7759
0
  }
7760
0
    }
7761
7762
    /*
7763
     * [ WFC: No Recursion ]
7764
     * A parsed entity must not contain a recursive reference
7765
     * to itself, either directly or indirectly.
7766
     * Done somewhere else
7767
     */
7768
0
    return(ent);
7769
0
}
7770
7771
/**
7772
 * xmlParseStringEntityRef:
7773
 * @ctxt:  an XML parser context
7774
 * @str:  a pointer to an index in the string
7775
 *
7776
 * parse ENTITY references declarations, but this version parses it from
7777
 * a string value.
7778
 *
7779
 * [68] EntityRef ::= '&' Name ';'
7780
 *
7781
 * [ WFC: Entity Declared ]
7782
 * In a document without any DTD, a document with only an internal DTD
7783
 * subset which contains no parameter entity references, or a document
7784
 * with "standalone='yes'", the Name given in the entity reference
7785
 * must match that in an entity declaration, except that well-formed
7786
 * documents need not declare any of the following entities: amp, lt,
7787
 * gt, apos, quot.  The declaration of a parameter entity must precede
7788
 * any reference to it.  Similarly, the declaration of a general entity
7789
 * must precede any reference to it which appears in a default value in an
7790
 * attribute-list declaration. Note that if entities are declared in the
7791
 * external subset or in external parameter entities, a non-validating
7792
 * processor is not obligated to read and process their declarations;
7793
 * for such documents, the rule that an entity must be declared is a
7794
 * well-formedness constraint only if standalone='yes'.
7795
 *
7796
 * [ WFC: Parsed Entity ]
7797
 * An entity reference must not contain the name of an unparsed entity
7798
 *
7799
 * Returns the xmlEntityPtr if found, or NULL otherwise. The str pointer
7800
 * is updated to the current location in the string.
7801
 */
7802
static xmlEntityPtr
7803
0
xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
7804
0
    xmlChar *name;
7805
0
    const xmlChar *ptr;
7806
0
    xmlChar cur;
7807
0
    xmlEntityPtr ent = NULL;
7808
7809
0
    if ((str == NULL) || (*str == NULL))
7810
0
        return(NULL);
7811
0
    ptr = *str;
7812
0
    cur = *ptr;
7813
0
    if (cur != '&')
7814
0
  return(NULL);
7815
7816
0
    ptr++;
7817
0
    name = xmlParseStringName(ctxt, &ptr);
7818
0
    if (name == NULL) {
7819
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7820
0
           "xmlParseStringEntityRef: no name\n");
7821
0
  *str = ptr;
7822
0
  return(NULL);
7823
0
    }
7824
0
    if (*ptr != ';') {
7825
0
  xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
7826
0
        xmlFree(name);
7827
0
  *str = ptr;
7828
0
  return(NULL);
7829
0
    }
7830
0
    ptr++;
7831
7832
7833
    /*
7834
     * Predefined entities override any extra definition
7835
     */
7836
0
    if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
7837
0
        ent = xmlGetPredefinedEntity(name);
7838
0
        if (ent != NULL) {
7839
0
            xmlFree(name);
7840
0
            *str = ptr;
7841
0
            return(ent);
7842
0
        }
7843
0
    }
7844
7845
    /*
7846
     * Ask first SAX for entity resolution, otherwise try the
7847
     * entities which may have stored in the parser context.
7848
     */
7849
0
    if (ctxt->sax != NULL) {
7850
0
  if (ctxt->sax->getEntity != NULL)
7851
0
      ent = ctxt->sax->getEntity(ctxt->userData, name);
7852
0
  if ((ent == NULL) && (ctxt->options & XML_PARSE_OLDSAX))
7853
0
      ent = xmlGetPredefinedEntity(name);
7854
0
  if ((ent == NULL) && (ctxt->userData==ctxt)) {
7855
0
      ent = xmlSAX2GetEntity(ctxt, name);
7856
0
  }
7857
0
    }
7858
0
    if (ctxt->instate == XML_PARSER_EOF) {
7859
0
  xmlFree(name);
7860
0
  return(NULL);
7861
0
    }
7862
7863
    /*
7864
     * [ WFC: Entity Declared ]
7865
     * In a document without any DTD, a document with only an
7866
     * internal DTD subset which contains no parameter entity
7867
     * references, or a document with "standalone='yes'", the
7868
     * Name given in the entity reference must match that in an
7869
     * entity declaration, except that well-formed documents
7870
     * need not declare any of the following entities: amp, lt,
7871
     * gt, apos, quot.
7872
     * The declaration of a parameter entity must precede any
7873
     * reference to it.
7874
     * Similarly, the declaration of a general entity must
7875
     * precede any reference to it which appears in a default
7876
     * value in an attribute-list declaration. Note that if
7877
     * entities are declared in the external subset or in
7878
     * external parameter entities, a non-validating processor
7879
     * is not obligated to read and process their declarations;
7880
     * for such documents, the rule that an entity must be
7881
     * declared is a well-formedness constraint only if
7882
     * standalone='yes'.
7883
     */
7884
0
    if (ent == NULL) {
7885
0
  if ((ctxt->standalone == 1) ||
7886
0
      ((ctxt->hasExternalSubset == 0) &&
7887
0
       (ctxt->hasPErefs == 0))) {
7888
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7889
0
         "Entity '%s' not defined\n", name);
7890
0
  } else {
7891
0
      xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
7892
0
        "Entity '%s' not defined\n",
7893
0
        name);
7894
0
  }
7895
  /* TODO ? check regressions ctxt->valid = 0; */
7896
0
    }
7897
7898
    /*
7899
     * [ WFC: Parsed Entity ]
7900
     * An entity reference must not contain the name of an
7901
     * unparsed entity
7902
     */
7903
0
    else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
7904
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
7905
0
     "Entity reference to unparsed entity %s\n", name);
7906
0
    }
7907
7908
    /*
7909
     * [ WFC: No External Entity References ]
7910
     * Attribute values cannot contain direct or indirect
7911
     * entity references to external entities.
7912
     */
7913
0
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7914
0
       (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
7915
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
7916
0
   "Attribute references external entity '%s'\n", name);
7917
0
    }
7918
    /*
7919
     * [ WFC: No < in Attribute Values ]
7920
     * The replacement text of any entity referred to directly or
7921
     * indirectly in an attribute value (other than "&lt;") must
7922
     * not contain a <.
7923
     */
7924
0
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7925
0
       (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
7926
0
  if ((ent->flags & XML_ENT_CHECKED_LT) == 0) {
7927
0
            if ((ent->content != NULL) && (xmlStrchr(ent->content, '<')))
7928
0
                ent->flags |= XML_ENT_CONTAINS_LT;
7929
0
            ent->flags |= XML_ENT_CHECKED_LT;
7930
0
        }
7931
0
        if (ent->flags & XML_ENT_CONTAINS_LT)
7932
0
            xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
7933
0
                    "'<' in entity '%s' is not allowed in attributes "
7934
0
                    "values\n", name);
7935
0
    }
7936
7937
    /*
7938
     * Internal check, no parameter entities here ...
7939
     */
7940
0
    else {
7941
0
  switch (ent->etype) {
7942
0
      case XML_INTERNAL_PARAMETER_ENTITY:
7943
0
      case XML_EXTERNAL_PARAMETER_ENTITY:
7944
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
7945
0
       "Attempt to reference the parameter entity '%s'\n",
7946
0
          name);
7947
0
      break;
7948
0
      default:
7949
0
      break;
7950
0
  }
7951
0
    }
7952
7953
    /*
7954
     * [ WFC: No Recursion ]
7955
     * A parsed entity must not contain a recursive reference
7956
     * to itself, either directly or indirectly.
7957
     * Done somewhere else
7958
     */
7959
7960
0
    xmlFree(name);
7961
0
    *str = ptr;
7962
0
    return(ent);
7963
0
}
7964
7965
/**
7966
 * xmlParsePEReference:
7967
 * @ctxt:  an XML parser context
7968
 *
7969
 * DEPRECATED: Internal function, don't use.
7970
 *
7971
 * Parse a parameter entity reference. Always consumes '%'.
7972
 *
7973
 * The entity content is handled directly by pushing it's content as
7974
 * a new input stream.
7975
 *
7976
 * [69] PEReference ::= '%' Name ';'
7977
 *
7978
 * [ WFC: No Recursion ]
7979
 * A parsed entity must not contain a recursive
7980
 * reference to itself, either directly or indirectly.
7981
 *
7982
 * [ WFC: Entity Declared ]
7983
 * In a document without any DTD, a document with only an internal DTD
7984
 * subset which contains no parameter entity references, or a document
7985
 * with "standalone='yes'", ...  ... The declaration of a parameter
7986
 * entity must precede any reference to it...
7987
 *
7988
 * [ VC: Entity Declared ]
7989
 * In a document with an external subset or external parameter entities
7990
 * with "standalone='no'", ...  ... The declaration of a parameter entity
7991
 * must precede any reference to it...
7992
 *
7993
 * [ WFC: In DTD ]
7994
 * Parameter-entity references may only appear in the DTD.
7995
 * NOTE: misleading but this is handled.
7996
 */
7997
void
7998
xmlParsePEReference(xmlParserCtxtPtr ctxt)
7999
0
{
8000
0
    const xmlChar *name;
8001
0
    xmlEntityPtr entity = NULL;
8002
0
    xmlParserInputPtr input;
8003
8004
0
    if (RAW != '%')
8005
0
        return;
8006
0
    NEXT;
8007
0
    name = xmlParseName(ctxt);
8008
0
    if (name == NULL) {
8009
0
  xmlFatalErrMsg(ctxt, XML_ERR_PEREF_NO_NAME, "PEReference: no name\n");
8010
0
  return;
8011
0
    }
8012
0
    if (xmlParserDebugEntities)
8013
0
  xmlGenericError(xmlGenericErrorContext,
8014
0
    "PEReference: %s\n", name);
8015
0
    if (RAW != ';') {
8016
0
  xmlFatalErr(ctxt, XML_ERR_PEREF_SEMICOL_MISSING, NULL);
8017
0
        return;
8018
0
    }
8019
8020
0
    NEXT;
8021
8022
    /*
8023
     * Request the entity from SAX
8024
     */
8025
0
    if ((ctxt->sax != NULL) &&
8026
0
  (ctxt->sax->getParameterEntity != NULL))
8027
0
  entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
8028
0
    if (ctxt->instate == XML_PARSER_EOF)
8029
0
  return;
8030
0
    if (entity == NULL) {
8031
  /*
8032
   * [ WFC: Entity Declared ]
8033
   * In a document without any DTD, a document with only an
8034
   * internal DTD subset which contains no parameter entity
8035
   * references, or a document with "standalone='yes'", ...
8036
   * ... The declaration of a parameter entity must precede
8037
   * any reference to it...
8038
   */
8039
0
  if ((ctxt->standalone == 1) ||
8040
0
      ((ctxt->hasExternalSubset == 0) &&
8041
0
       (ctxt->hasPErefs == 0))) {
8042
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
8043
0
            "PEReference: %%%s; not found\n",
8044
0
            name);
8045
0
  } else {
8046
      /*
8047
       * [ VC: Entity Declared ]
8048
       * In a document with an external subset or external
8049
       * parameter entities with "standalone='no'", ...
8050
       * ... The declaration of a parameter entity must
8051
       * precede any reference to it...
8052
       */
8053
0
            if ((ctxt->validate) && (ctxt->vctxt.error != NULL)) {
8054
0
                xmlValidityError(ctxt, XML_WAR_UNDECLARED_ENTITY,
8055
0
                                 "PEReference: %%%s; not found\n",
8056
0
                                 name, NULL);
8057
0
            } else
8058
0
                xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8059
0
                              "PEReference: %%%s; not found\n",
8060
0
                              name, NULL);
8061
0
            ctxt->valid = 0;
8062
0
  }
8063
0
    } else {
8064
  /*
8065
   * Internal checking in case the entity quest barfed
8066
   */
8067
0
  if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
8068
0
      (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
8069
0
      xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8070
0
      "Internal: %%%s; is not a parameter entity\n",
8071
0
        name, NULL);
8072
0
  } else {
8073
0
            xmlChar start[4];
8074
0
            xmlCharEncoding enc;
8075
0
            unsigned long parentConsumed;
8076
0
            xmlEntityPtr oldEnt;
8077
8078
0
      if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
8079
0
          ((ctxt->options & XML_PARSE_NOENT) == 0) &&
8080
0
    ((ctxt->options & XML_PARSE_DTDVALID) == 0) &&
8081
0
    ((ctxt->options & XML_PARSE_DTDLOAD) == 0) &&
8082
0
    ((ctxt->options & XML_PARSE_DTDATTR) == 0) &&
8083
0
    (ctxt->replaceEntities == 0) &&
8084
0
    (ctxt->validate == 0))
8085
0
    return;
8086
8087
0
            if (entity->flags & XML_ENT_EXPANDING) {
8088
0
                xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
8089
0
                xmlHaltParser(ctxt);
8090
0
                return;
8091
0
            }
8092
8093
            /* Must be computed from old input before pushing new input. */
8094
0
            parentConsumed = ctxt->input->parentConsumed;
8095
0
            oldEnt = ctxt->input->entity;
8096
0
            if ((oldEnt == NULL) ||
8097
0
                ((oldEnt->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
8098
0
                 ((oldEnt->flags & XML_ENT_PARSED) == 0))) {
8099
0
                xmlSaturatedAdd(&parentConsumed, ctxt->input->consumed);
8100
0
                xmlSaturatedAddSizeT(&parentConsumed,
8101
0
                                     ctxt->input->cur - ctxt->input->base);
8102
0
            }
8103
8104
0
      input = xmlNewEntityInputStream(ctxt, entity);
8105
0
      if (xmlPushInput(ctxt, input) < 0) {
8106
0
                xmlFreeInputStream(input);
8107
0
    return;
8108
0
            }
8109
8110
0
            entity->flags |= XML_ENT_EXPANDING;
8111
8112
0
            input->parentConsumed = parentConsumed;
8113
8114
0
      if (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) {
8115
                /*
8116
                 * Get the 4 first bytes and decode the charset
8117
                 * if enc != XML_CHAR_ENCODING_NONE
8118
                 * plug some encoding conversion routines.
8119
                 * Note that, since we may have some non-UTF8
8120
                 * encoding (like UTF16, bug 135229), the 'length'
8121
                 * is not known, but we can calculate based upon
8122
                 * the amount of data in the buffer.
8123
                 */
8124
0
                GROW
8125
0
                if (ctxt->instate == XML_PARSER_EOF)
8126
0
                    return;
8127
0
                if ((ctxt->input->end - ctxt->input->cur)>=4) {
8128
0
                    start[0] = RAW;
8129
0
                    start[1] = NXT(1);
8130
0
                    start[2] = NXT(2);
8131
0
                    start[3] = NXT(3);
8132
0
                    enc = xmlDetectCharEncoding(start, 4);
8133
0
                    if (enc != XML_CHAR_ENCODING_NONE) {
8134
0
                        xmlSwitchEncoding(ctxt, enc);
8135
0
                    }
8136
0
                }
8137
8138
0
                if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) &&
8139
0
                    (IS_BLANK_CH(NXT(5)))) {
8140
0
                    xmlParseTextDecl(ctxt);
8141
0
                }
8142
0
            }
8143
0
  }
8144
0
    }
8145
0
    ctxt->hasPErefs = 1;
8146
0
}
8147
8148
/**
8149
 * xmlLoadEntityContent:
8150
 * @ctxt:  an XML parser context
8151
 * @entity: an unloaded system entity
8152
 *
8153
 * Load the original content of the given system entity from the
8154
 * ExternalID/SystemID given. This is to be used for Included in Literal
8155
 * http://www.w3.org/TR/REC-xml/#inliteral processing of entities references
8156
 *
8157
 * Returns 0 in case of success and -1 in case of failure
8158
 */
8159
static int
8160
0
xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
8161
0
    xmlParserInputPtr input;
8162
0
    xmlBufferPtr buf;
8163
0
    int l, c;
8164
0
    int count = 0;
8165
8166
0
    if ((ctxt == NULL) || (entity == NULL) ||
8167
0
        ((entity->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
8168
0
   (entity->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY)) ||
8169
0
  (entity->content != NULL)) {
8170
0
  xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8171
0
              "xmlLoadEntityContent parameter error");
8172
0
        return(-1);
8173
0
    }
8174
8175
0
    if (xmlParserDebugEntities)
8176
0
  xmlGenericError(xmlGenericErrorContext,
8177
0
    "Reading %s entity content input\n", entity->name);
8178
8179
0
    buf = xmlBufferCreate();
8180
0
    if (buf == NULL) {
8181
0
  xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8182
0
              "xmlLoadEntityContent parameter error");
8183
0
        return(-1);
8184
0
    }
8185
0
    xmlBufferSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);
8186
8187
0
    input = xmlNewEntityInputStream(ctxt, entity);
8188
0
    if (input == NULL) {
8189
0
  xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8190
0
              "xmlLoadEntityContent input error");
8191
0
  xmlBufferFree(buf);
8192
0
        return(-1);
8193
0
    }
8194
8195
    /*
8196
     * Push the entity as the current input, read char by char
8197
     * saving to the buffer until the end of the entity or an error
8198
     */
8199
0
    if (xmlPushInput(ctxt, input) < 0) {
8200
0
        xmlBufferFree(buf);
8201
0
  xmlFreeInputStream(input);
8202
0
  return(-1);
8203
0
    }
8204
8205
0
    GROW;
8206
0
    c = CUR_CHAR(l);
8207
0
    while ((ctxt->input == input) && (ctxt->input->cur < ctxt->input->end) &&
8208
0
           (IS_CHAR(c))) {
8209
0
        xmlBufferAdd(buf, ctxt->input->cur, l);
8210
0
  if (count++ > XML_PARSER_CHUNK_SIZE) {
8211
0
      count = 0;
8212
0
      GROW;
8213
0
            if (ctxt->instate == XML_PARSER_EOF) {
8214
0
                xmlBufferFree(buf);
8215
0
                return(-1);
8216
0
            }
8217
0
  }
8218
0
  NEXTL(l);
8219
0
  c = CUR_CHAR(l);
8220
0
  if (c == 0) {
8221
0
      count = 0;
8222
0
      GROW;
8223
0
            if (ctxt->instate == XML_PARSER_EOF) {
8224
0
                xmlBufferFree(buf);
8225
0
                return(-1);
8226
0
            }
8227
0
      c = CUR_CHAR(l);
8228
0
  }
8229
0
    }
8230
8231
0
    if ((ctxt->input == input) && (ctxt->input->cur >= ctxt->input->end)) {
8232
0
        xmlSaturatedAdd(&ctxt->sizeentities, ctxt->input->consumed);
8233
0
        xmlPopInput(ctxt);
8234
0
    } else if (!IS_CHAR(c)) {
8235
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
8236
0
                          "xmlLoadEntityContent: invalid char value %d\n",
8237
0
                    c);
8238
0
  xmlBufferFree(buf);
8239
0
  return(-1);
8240
0
    }
8241
0
    entity->content = buf->content;
8242
0
    entity->length = buf->use;
8243
0
    buf->content = NULL;
8244
0
    xmlBufferFree(buf);
8245
8246
0
    return(0);
8247
0
}
8248
8249
/**
8250
 * xmlParseStringPEReference:
8251
 * @ctxt:  an XML parser context
8252
 * @str:  a pointer to an index in the string
8253
 *
8254
 * parse PEReference declarations
8255
 *
8256
 * [69] PEReference ::= '%' Name ';'
8257
 *
8258
 * [ WFC: No Recursion ]
8259
 * A parsed entity must not contain a recursive
8260
 * reference to itself, either directly or indirectly.
8261
 *
8262
 * [ WFC: Entity Declared ]
8263
 * In a document without any DTD, a document with only an internal DTD
8264
 * subset which contains no parameter entity references, or a document
8265
 * with "standalone='yes'", ...  ... The declaration of a parameter
8266
 * entity must precede any reference to it...
8267
 *
8268
 * [ VC: Entity Declared ]
8269
 * In a document with an external subset or external parameter entities
8270
 * with "standalone='no'", ...  ... The declaration of a parameter entity
8271
 * must precede any reference to it...
8272
 *
8273
 * [ WFC: In DTD ]
8274
 * Parameter-entity references may only appear in the DTD.
8275
 * NOTE: misleading but this is handled.
8276
 *
8277
 * Returns the string of the entity content.
8278
 *         str is updated to the current value of the index
8279
 */
8280
static xmlEntityPtr
8281
0
xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
8282
0
    const xmlChar *ptr;
8283
0
    xmlChar cur;
8284
0
    xmlChar *name;
8285
0
    xmlEntityPtr entity = NULL;
8286
8287
0
    if ((str == NULL) || (*str == NULL)) return(NULL);
8288
0
    ptr = *str;
8289
0
    cur = *ptr;
8290
0
    if (cur != '%')
8291
0
        return(NULL);
8292
0
    ptr++;
8293
0
    name = xmlParseStringName(ctxt, &ptr);
8294
0
    if (name == NULL) {
8295
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8296
0
           "xmlParseStringPEReference: no name\n");
8297
0
  *str = ptr;
8298
0
  return(NULL);
8299
0
    }
8300
0
    cur = *ptr;
8301
0
    if (cur != ';') {
8302
0
  xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
8303
0
  xmlFree(name);
8304
0
  *str = ptr;
8305
0
  return(NULL);
8306
0
    }
8307
0
    ptr++;
8308
8309
    /*
8310
     * Request the entity from SAX
8311
     */
8312
0
    if ((ctxt->sax != NULL) &&
8313
0
  (ctxt->sax->getParameterEntity != NULL))
8314
0
  entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
8315
0
    if (ctxt->instate == XML_PARSER_EOF) {
8316
0
  xmlFree(name);
8317
0
  *str = ptr;
8318
0
  return(NULL);
8319
0
    }
8320
0
    if (entity == NULL) {
8321
  /*
8322
   * [ WFC: Entity Declared ]
8323
   * In a document without any DTD, a document with only an
8324
   * internal DTD subset which contains no parameter entity
8325
   * references, or a document with "standalone='yes'", ...
8326
   * ... The declaration of a parameter entity must precede
8327
   * any reference to it...
8328
   */
8329
0
  if ((ctxt->standalone == 1) ||
8330
0
      ((ctxt->hasExternalSubset == 0) && (ctxt->hasPErefs == 0))) {
8331
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
8332
0
     "PEReference: %%%s; not found\n", name);
8333
0
  } else {
8334
      /*
8335
       * [ VC: Entity Declared ]
8336
       * In a document with an external subset or external
8337
       * parameter entities with "standalone='no'", ...
8338
       * ... The declaration of a parameter entity must
8339
       * precede any reference to it...
8340
       */
8341
0
      xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8342
0
        "PEReference: %%%s; not found\n",
8343
0
        name, NULL);
8344
0
      ctxt->valid = 0;
8345
0
  }
8346
0
    } else {
8347
  /*
8348
   * Internal checking in case the entity quest barfed
8349
   */
8350
0
  if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
8351
0
      (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
8352
0
      xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8353
0
        "%%%s; is not a parameter entity\n",
8354
0
        name, NULL);
8355
0
  }
8356
0
    }
8357
0
    ctxt->hasPErefs = 1;
8358
0
    xmlFree(name);
8359
0
    *str = ptr;
8360
0
    return(entity);
8361
0
}
8362
8363
/**
8364
 * xmlParseDocTypeDecl:
8365
 * @ctxt:  an XML parser context
8366
 *
8367
 * DEPRECATED: Internal function, don't use.
8368
 *
8369
 * parse a DOCTYPE declaration
8370
 *
8371
 * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
8372
 *                      ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
8373
 *
8374
 * [ VC: Root Element Type ]
8375
 * The Name in the document type declaration must match the element
8376
 * type of the root element.
8377
 */
8378
8379
void
8380
0
xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
8381
0
    const xmlChar *name = NULL;
8382
0
    xmlChar *ExternalID = NULL;
8383
0
    xmlChar *URI = NULL;
8384
8385
    /*
8386
     * We know that '<!DOCTYPE' has been detected.
8387
     */
8388
0
    SKIP(9);
8389
8390
0
    SKIP_BLANKS;
8391
8392
    /*
8393
     * Parse the DOCTYPE name.
8394
     */
8395
0
    name = xmlParseName(ctxt);
8396
0
    if (name == NULL) {
8397
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8398
0
           "xmlParseDocTypeDecl : no DOCTYPE name !\n");
8399
0
    }
8400
0
    ctxt->intSubName = name;
8401
8402
0
    SKIP_BLANKS;
8403
8404
    /*
8405
     * Check for SystemID and ExternalID
8406
     */
8407
0
    URI = xmlParseExternalID(ctxt, &ExternalID, 1);
8408
8409
0
    if ((URI != NULL) || (ExternalID != NULL)) {
8410
0
        ctxt->hasExternalSubset = 1;
8411
0
    }
8412
0
    ctxt->extSubURI = URI;
8413
0
    ctxt->extSubSystem = ExternalID;
8414
8415
0
    SKIP_BLANKS;
8416
8417
    /*
8418
     * Create and update the internal subset.
8419
     */
8420
0
    if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL) &&
8421
0
  (!ctxt->disableSAX))
8422
0
  ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
8423
0
    if (ctxt->instate == XML_PARSER_EOF)
8424
0
  return;
8425
8426
    /*
8427
     * Is there any internal subset declarations ?
8428
     * they are handled separately in xmlParseInternalSubset()
8429
     */
8430
0
    if (RAW == '[')
8431
0
  return;
8432
8433
    /*
8434
     * We should be at the end of the DOCTYPE declaration.
8435
     */
8436
0
    if (RAW != '>') {
8437
0
  xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
8438
0
    }
8439
0
    NEXT;
8440
0
}
8441
8442
/**
8443
 * xmlParseInternalSubset:
8444
 * @ctxt:  an XML parser context
8445
 *
8446
 * parse the internal subset declaration
8447
 *
8448
 * [28 end] ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
8449
 */
8450
8451
static void
8452
0
xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
8453
    /*
8454
     * Is there any DTD definition ?
8455
     */
8456
0
    if (RAW == '[') {
8457
0
        int baseInputNr = ctxt->inputNr;
8458
0
        ctxt->instate = XML_PARSER_DTD;
8459
0
        NEXT;
8460
  /*
8461
   * Parse the succession of Markup declarations and
8462
   * PEReferences.
8463
   * Subsequence (markupdecl | PEReference | S)*
8464
   */
8465
0
  SKIP_BLANKS;
8466
0
  while (((RAW != ']') || (ctxt->inputNr > baseInputNr)) &&
8467
0
               (ctxt->instate != XML_PARSER_EOF)) {
8468
8469
            /*
8470
             * Conditional sections are allowed from external entities included
8471
             * by PE References in the internal subset.
8472
             */
8473
0
            if ((ctxt->inputNr > 1) && (ctxt->input->filename != NULL) &&
8474
0
                (RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
8475
0
                xmlParseConditionalSections(ctxt);
8476
0
            } else if ((RAW == '<') && ((NXT(1) == '!') || (NXT(1) == '?'))) {
8477
0
          xmlParseMarkupDecl(ctxt);
8478
0
            } else if (RAW == '%') {
8479
0
          xmlParsePEReference(ctxt);
8480
0
            } else {
8481
0
    xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8482
0
                        "xmlParseInternalSubset: error detected in"
8483
0
                        " Markup declaration\n");
8484
0
                xmlHaltParser(ctxt);
8485
0
                return;
8486
0
            }
8487
0
      SKIP_BLANKS;
8488
0
  }
8489
0
  if (RAW == ']') {
8490
0
      NEXT;
8491
0
      SKIP_BLANKS;
8492
0
  }
8493
0
    }
8494
8495
    /*
8496
     * We should be at the end of the DOCTYPE declaration.
8497
     */
8498
0
    if (RAW != '>') {
8499
0
  xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
8500
0
  return;
8501
0
    }
8502
0
    NEXT;
8503
0
}
8504
8505
#ifdef LIBXML_SAX1_ENABLED
8506
/**
8507
 * xmlParseAttribute:
8508
 * @ctxt:  an XML parser context
8509
 * @value:  a xmlChar ** used to store the value of the attribute
8510
 *
8511
 * DEPRECATED: Internal function, don't use.
8512
 *
8513
 * parse an attribute
8514
 *
8515
 * [41] Attribute ::= Name Eq AttValue
8516
 *
8517
 * [ WFC: No External Entity References ]
8518
 * Attribute values cannot contain direct or indirect entity references
8519
 * to external entities.
8520
 *
8521
 * [ WFC: No < in Attribute Values ]
8522
 * The replacement text of any entity referred to directly or indirectly in
8523
 * an attribute value (other than "&lt;") must not contain a <.
8524
 *
8525
 * [ VC: Attribute Value Type ]
8526
 * The attribute must have been declared; the value must be of the type
8527
 * declared for it.
8528
 *
8529
 * [25] Eq ::= S? '=' S?
8530
 *
8531
 * With namespace:
8532
 *
8533
 * [NS 11] Attribute ::= QName Eq AttValue
8534
 *
8535
 * Also the case QName == xmlns:??? is handled independently as a namespace
8536
 * definition.
8537
 *
8538
 * Returns the attribute name, and the value in *value.
8539
 */
8540
8541
const xmlChar *
8542
xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
8543
    const xmlChar *name;
8544
    xmlChar *val;
8545
8546
    *value = NULL;
8547
    GROW;
8548
    name = xmlParseName(ctxt);
8549
    if (name == NULL) {
8550
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8551
                 "error parsing attribute name\n");
8552
        return(NULL);
8553
    }
8554
8555
    /*
8556
     * read the value
8557
     */
8558
    SKIP_BLANKS;
8559
    if (RAW == '=') {
8560
        NEXT;
8561
  SKIP_BLANKS;
8562
  val = xmlParseAttValue(ctxt);
8563
  ctxt->instate = XML_PARSER_CONTENT;
8564
    } else {
8565
  xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
8566
         "Specification mandates value for attribute %s\n", name);
8567
  return(name);
8568
    }
8569
8570
    /*
8571
     * Check that xml:lang conforms to the specification
8572
     * No more registered as an error, just generate a warning now
8573
     * since this was deprecated in XML second edition
8574
     */
8575
    if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "xml:lang"))) {
8576
  if (!xmlCheckLanguageID(val)) {
8577
      xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
8578
              "Malformed value for xml:lang : %s\n",
8579
        val, NULL);
8580
  }
8581
    }
8582
8583
    /*
8584
     * Check that xml:space conforms to the specification
8585
     */
8586
    if (xmlStrEqual(name, BAD_CAST "xml:space")) {
8587
  if (xmlStrEqual(val, BAD_CAST "default"))
8588
      *(ctxt->space) = 0;
8589
  else if (xmlStrEqual(val, BAD_CAST "preserve"))
8590
      *(ctxt->space) = 1;
8591
  else {
8592
    xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
8593
"Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
8594
                                 val, NULL);
8595
  }
8596
    }
8597
8598
    *value = val;
8599
    return(name);
8600
}
8601
8602
/**
8603
 * xmlParseStartTag:
8604
 * @ctxt:  an XML parser context
8605
 *
8606
 * DEPRECATED: Internal function, don't use.
8607
 *
8608
 * Parse a start tag. Always consumes '<'.
8609
 *
8610
 * [40] STag ::= '<' Name (S Attribute)* S? '>'
8611
 *
8612
 * [ WFC: Unique Att Spec ]
8613
 * No attribute name may appear more than once in the same start-tag or
8614
 * empty-element tag.
8615
 *
8616
 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
8617
 *
8618
 * [ WFC: Unique Att Spec ]
8619
 * No attribute name may appear more than once in the same start-tag or
8620
 * empty-element tag.
8621
 *
8622
 * With namespace:
8623
 *
8624
 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
8625
 *
8626
 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
8627
 *
8628
 * Returns the element name parsed
8629
 */
8630
8631
const xmlChar *
8632
xmlParseStartTag(xmlParserCtxtPtr ctxt) {
8633
    const xmlChar *name;
8634
    const xmlChar *attname;
8635
    xmlChar *attvalue;
8636
    const xmlChar **atts = ctxt->atts;
8637
    int nbatts = 0;
8638
    int maxatts = ctxt->maxatts;
8639
    int i;
8640
8641
    if (RAW != '<') return(NULL);
8642
    NEXT1;
8643
8644
    name = xmlParseName(ctxt);
8645
    if (name == NULL) {
8646
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8647
       "xmlParseStartTag: invalid element name\n");
8648
        return(NULL);
8649
    }
8650
8651
    /*
8652
     * Now parse the attributes, it ends up with the ending
8653
     *
8654
     * (S Attribute)* S?
8655
     */
8656
    SKIP_BLANKS;
8657
    GROW;
8658
8659
    while (((RAW != '>') &&
8660
     ((RAW != '/') || (NXT(1) != '>')) &&
8661
     (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) {
8662
  attname = xmlParseAttribute(ctxt, &attvalue);
8663
        if (attname == NULL) {
8664
      xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
8665
         "xmlParseStartTag: problem parsing attributes\n");
8666
      break;
8667
  }
8668
        if (attvalue != NULL) {
8669
      /*
8670
       * [ WFC: Unique Att Spec ]
8671
       * No attribute name may appear more than once in the same
8672
       * start-tag or empty-element tag.
8673
       */
8674
      for (i = 0; i < nbatts;i += 2) {
8675
          if (xmlStrEqual(atts[i], attname)) {
8676
        xmlErrAttributeDup(ctxt, NULL, attname);
8677
        xmlFree(attvalue);
8678
        goto failed;
8679
    }
8680
      }
8681
      /*
8682
       * Add the pair to atts
8683
       */
8684
      if (atts == NULL) {
8685
          maxatts = 22; /* allow for 10 attrs by default */
8686
          atts = (const xmlChar **)
8687
           xmlMalloc(maxatts * sizeof(xmlChar *));
8688
    if (atts == NULL) {
8689
        xmlErrMemory(ctxt, NULL);
8690
        if (attvalue != NULL)
8691
      xmlFree(attvalue);
8692
        goto failed;
8693
    }
8694
    ctxt->atts = atts;
8695
    ctxt->maxatts = maxatts;
8696
      } else if (nbatts + 4 > maxatts) {
8697
          const xmlChar **n;
8698
8699
          maxatts *= 2;
8700
          n = (const xmlChar **) xmlRealloc((void *) atts,
8701
               maxatts * sizeof(const xmlChar *));
8702
    if (n == NULL) {
8703
        xmlErrMemory(ctxt, NULL);
8704
        if (attvalue != NULL)
8705
      xmlFree(attvalue);
8706
        goto failed;
8707
    }
8708
    atts = n;
8709
    ctxt->atts = atts;
8710
    ctxt->maxatts = maxatts;
8711
      }
8712
      atts[nbatts++] = attname;
8713
      atts[nbatts++] = attvalue;
8714
      atts[nbatts] = NULL;
8715
      atts[nbatts + 1] = NULL;
8716
  } else {
8717
      if (attvalue != NULL)
8718
    xmlFree(attvalue);
8719
  }
8720
8721
failed:
8722
8723
  GROW
8724
  if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
8725
      break;
8726
  if (SKIP_BLANKS == 0) {
8727
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
8728
         "attributes construct error\n");
8729
  }
8730
  SHRINK;
8731
        GROW;
8732
    }
8733
8734
    /*
8735
     * SAX: Start of Element !
8736
     */
8737
    if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL) &&
8738
  (!ctxt->disableSAX)) {
8739
  if (nbatts > 0)
8740
      ctxt->sax->startElement(ctxt->userData, name, atts);
8741
  else
8742
      ctxt->sax->startElement(ctxt->userData, name, NULL);
8743
    }
8744
8745
    if (atts != NULL) {
8746
        /* Free only the content strings */
8747
        for (i = 1;i < nbatts;i+=2)
8748
      if (atts[i] != NULL)
8749
         xmlFree((xmlChar *) atts[i]);
8750
    }
8751
    return(name);
8752
}
8753
8754
/**
8755
 * xmlParseEndTag1:
8756
 * @ctxt:  an XML parser context
8757
 * @line:  line of the start tag
8758
 * @nsNr:  number of namespaces on the start tag
8759
 *
8760
 * Parse an end tag. Always consumes '</'.
8761
 *
8762
 * [42] ETag ::= '</' Name S? '>'
8763
 *
8764
 * With namespace
8765
 *
8766
 * [NS 9] ETag ::= '</' QName S? '>'
8767
 */
8768
8769
static void
8770
xmlParseEndTag1(xmlParserCtxtPtr ctxt, int line) {
8771
    const xmlChar *name;
8772
8773
    GROW;
8774
    if ((RAW != '<') || (NXT(1) != '/')) {
8775
  xmlFatalErrMsg(ctxt, XML_ERR_LTSLASH_REQUIRED,
8776
           "xmlParseEndTag: '</' not found\n");
8777
  return;
8778
    }
8779
    SKIP(2);
8780
8781
    name = xmlParseNameAndCompare(ctxt,ctxt->name);
8782
8783
    /*
8784
     * We should definitely be at the ending "S? '>'" part
8785
     */
8786
    GROW;
8787
    SKIP_BLANKS;
8788
    if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
8789
  xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
8790
    } else
8791
  NEXT1;
8792
8793
    /*
8794
     * [ WFC: Element Type Match ]
8795
     * The Name in an element's end-tag must match the element type in the
8796
     * start-tag.
8797
     *
8798
     */
8799
    if (name != (xmlChar*)1) {
8800
        if (name == NULL) name = BAD_CAST "unparsable";
8801
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
8802
         "Opening and ending tag mismatch: %s line %d and %s\n",
8803
                    ctxt->name, line, name);
8804
    }
8805
8806
    /*
8807
     * SAX: End of Tag
8808
     */
8809
    if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
8810
  (!ctxt->disableSAX))
8811
        ctxt->sax->endElement(ctxt->userData, ctxt->name);
8812
8813
    namePop(ctxt);
8814
    spacePop(ctxt);
8815
    return;
8816
}
8817
8818
/**
8819
 * xmlParseEndTag:
8820
 * @ctxt:  an XML parser context
8821
 *
8822
 * DEPRECATED: Internal function, don't use.
8823
 *
8824
 * parse an end of tag
8825
 *
8826
 * [42] ETag ::= '</' Name S? '>'
8827
 *
8828
 * With namespace
8829
 *
8830
 * [NS 9] ETag ::= '</' QName S? '>'
8831
 */
8832
8833
void
8834
xmlParseEndTag(xmlParserCtxtPtr ctxt) {
8835
    xmlParseEndTag1(ctxt, 0);
8836
}
8837
#endif /* LIBXML_SAX1_ENABLED */
8838
8839
/************************************************************************
8840
 *                  *
8841
 *          SAX 2 specific operations       *
8842
 *                  *
8843
 ************************************************************************/
8844
8845
/*
8846
 * xmlGetNamespace:
8847
 * @ctxt:  an XML parser context
8848
 * @prefix:  the prefix to lookup
8849
 *
8850
 * Lookup the namespace name for the @prefix (which ca be NULL)
8851
 * The prefix must come from the @ctxt->dict dictionary
8852
 *
8853
 * Returns the namespace name or NULL if not bound
8854
 */
8855
static const xmlChar *
8856
44.3k
xmlGetNamespace(xmlParserCtxtPtr ctxt, const xmlChar *prefix) {
8857
44.3k
    int i;
8858
8859
44.3k
    if (prefix == ctxt->str_xml) return(ctxt->str_xml_ns);
8860
84.9k
    for (i = ctxt->nsNr - 2;i >= 0;i-=2)
8861
66.4k
        if (ctxt->nsTab[i] == prefix) {
8862
25.8k
      if ((prefix == NULL) && (*ctxt->nsTab[i + 1] == 0))
8863
0
          return(NULL);
8864
25.8k
      return(ctxt->nsTab[i + 1]);
8865
25.8k
  }
8866
18.4k
    return(NULL);
8867
44.3k
}
8868
8869
/**
8870
 * xmlParseQName:
8871
 * @ctxt:  an XML parser context
8872
 * @prefix:  pointer to store the prefix part
8873
 *
8874
 * parse an XML Namespace QName
8875
 *
8876
 * [6]  QName  ::= (Prefix ':')? LocalPart
8877
 * [7]  Prefix  ::= NCName
8878
 * [8]  LocalPart  ::= NCName
8879
 *
8880
 * Returns the Name parsed or NULL
8881
 */
8882
8883
static const xmlChar *
8884
88.6k
xmlParseQName(xmlParserCtxtPtr ctxt, const xmlChar **prefix) {
8885
88.6k
    const xmlChar *l, *p;
8886
8887
88.6k
    GROW;
8888
8889
88.6k
    l = xmlParseNCName(ctxt);
8890
88.6k
    if (l == NULL) {
8891
0
        if (CUR == ':') {
8892
0
      l = xmlParseName(ctxt);
8893
0
      if (l != NULL) {
8894
0
          xmlNsErr(ctxt, XML_NS_ERR_QNAME,
8895
0
             "Failed to parse QName '%s'\n", l, NULL, NULL);
8896
0
    *prefix = NULL;
8897
0
    return(l);
8898
0
      }
8899
0
  }
8900
0
        return(NULL);
8901
0
    }
8902
88.6k
    if (CUR == ':') {
8903
36.9k
        NEXT;
8904
36.9k
  p = l;
8905
36.9k
  l = xmlParseNCName(ctxt);
8906
36.9k
  if (l == NULL) {
8907
0
      xmlChar *tmp;
8908
8909
0
            if (ctxt->instate == XML_PARSER_EOF)
8910
0
                return(NULL);
8911
0
            xmlNsErr(ctxt, XML_NS_ERR_QNAME,
8912
0
               "Failed to parse QName '%s:'\n", p, NULL, NULL);
8913
0
      l = xmlParseNmtoken(ctxt);
8914
0
      if (l == NULL) {
8915
0
                if (ctxt->instate == XML_PARSER_EOF)
8916
0
                    return(NULL);
8917
0
    tmp = xmlBuildQName(BAD_CAST "", p, NULL, 0);
8918
0
            } else {
8919
0
    tmp = xmlBuildQName(l, p, NULL, 0);
8920
0
    xmlFree((char *)l);
8921
0
      }
8922
0
      p = xmlDictLookup(ctxt->dict, tmp, -1);
8923
0
      if (tmp != NULL) xmlFree(tmp);
8924
0
      *prefix = NULL;
8925
0
      return(p);
8926
0
  }
8927
36.9k
  if (CUR == ':') {
8928
0
      xmlChar *tmp;
8929
8930
0
            xmlNsErr(ctxt, XML_NS_ERR_QNAME,
8931
0
               "Failed to parse QName '%s:%s:'\n", p, l, NULL);
8932
0
      NEXT;
8933
0
      tmp = (xmlChar *) xmlParseName(ctxt);
8934
0
      if (tmp != NULL) {
8935
0
          tmp = xmlBuildQName(tmp, l, NULL, 0);
8936
0
    l = xmlDictLookup(ctxt->dict, tmp, -1);
8937
0
    if (tmp != NULL) xmlFree(tmp);
8938
0
    *prefix = p;
8939
0
    return(l);
8940
0
      }
8941
0
            if (ctxt->instate == XML_PARSER_EOF)
8942
0
                return(NULL);
8943
0
      tmp = xmlBuildQName(BAD_CAST "", l, NULL, 0);
8944
0
      l = xmlDictLookup(ctxt->dict, tmp, -1);
8945
0
      if (tmp != NULL) xmlFree(tmp);
8946
0
      *prefix = p;
8947
0
      return(l);
8948
0
  }
8949
36.9k
  *prefix = p;
8950
36.9k
    } else
8951
51.6k
        *prefix = NULL;
8952
88.6k
    return(l);
8953
88.6k
}
8954
8955
/**
8956
 * xmlParseQNameAndCompare:
8957
 * @ctxt:  an XML parser context
8958
 * @name:  the localname
8959
 * @prefix:  the prefix, if any.
8960
 *
8961
 * parse an XML name and compares for match
8962
 * (specialized for endtag parsing)
8963
 *
8964
 * Returns NULL for an illegal name, (xmlChar*) 1 for success
8965
 * and the name for mismatch
8966
 */
8967
8968
static const xmlChar *
8969
xmlParseQNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *name,
8970
18.4k
                        xmlChar const *prefix) {
8971
18.4k
    const xmlChar *cmp;
8972
18.4k
    const xmlChar *in;
8973
18.4k
    const xmlChar *ret;
8974
18.4k
    const xmlChar *prefix2;
8975
8976
18.4k
    if (prefix == NULL) return(xmlParseNameAndCompare(ctxt, name));
8977
8978
18.4k
    GROW;
8979
18.4k
    in = ctxt->input->cur;
8980
8981
18.4k
    cmp = prefix;
8982
36.9k
    while (*in != 0 && *in == *cmp) {
8983
18.4k
  ++in;
8984
18.4k
  ++cmp;
8985
18.4k
    }
8986
18.4k
    if ((*cmp == 0) && (*in == ':')) {
8987
18.4k
        in++;
8988
18.4k
  cmp = name;
8989
36.9k
  while (*in != 0 && *in == *cmp) {
8990
18.4k
      ++in;
8991
18.4k
      ++cmp;
8992
18.4k
  }
8993
18.4k
  if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
8994
      /* success */
8995
18.4k
            ctxt->input->col += in - ctxt->input->cur;
8996
18.4k
      ctxt->input->cur = in;
8997
18.4k
      return((const xmlChar*) 1);
8998
18.4k
  }
8999
18.4k
    }
9000
    /*
9001
     * all strings coms from the dictionary, equality can be done directly
9002
     */
9003
0
    ret = xmlParseQName (ctxt, &prefix2);
9004
0
    if ((ret == name) && (prefix == prefix2))
9005
0
  return((const xmlChar*) 1);
9006
0
    return ret;
9007
0
}
9008
9009
/**
9010
 * xmlParseAttValueInternal:
9011
 * @ctxt:  an XML parser context
9012
 * @len:  attribute len result
9013
 * @alloc:  whether the attribute was reallocated as a new string
9014
 * @normalize:  if 1 then further non-CDATA normalization must be done
9015
 *
9016
 * parse a value for an attribute.
9017
 * NOTE: if no normalization is needed, the routine will return pointers
9018
 *       directly from the data buffer.
9019
 *
9020
 * 3.3.3 Attribute-Value Normalization:
9021
 * Before the value of an attribute is passed to the application or
9022
 * checked for validity, the XML processor must normalize it as follows:
9023
 * - a character reference is processed by appending the referenced
9024
 *   character to the attribute value
9025
 * - an entity reference is processed by recursively processing the
9026
 *   replacement text of the entity
9027
 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
9028
 *   appending #x20 to the normalized value, except that only a single
9029
 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
9030
 *   parsed entity or the literal entity value of an internal parsed entity
9031
 * - other characters are processed by appending them to the normalized value
9032
 * If the declared value is not CDATA, then the XML processor must further
9033
 * process the normalized attribute value by discarding any leading and
9034
 * trailing space (#x20) characters, and by replacing sequences of space
9035
 * (#x20) characters by a single space (#x20) character.
9036
 * All attributes for which no declaration has been read should be treated
9037
 * by a non-validating parser as if declared CDATA.
9038
 *
9039
 * Returns the AttValue parsed or NULL. The value has to be freed by the
9040
 *     caller if it was copied, this can be detected by val[*len] == 0.
9041
 */
9042
9043
#define GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end) \
9044
0
    const xmlChar *oldbase = ctxt->input->base;\
9045
0
    GROW;\
9046
0
    if (ctxt->instate == XML_PARSER_EOF)\
9047
0
        return(NULL);\
9048
0
    if (oldbase != ctxt->input->base) {\
9049
0
        ptrdiff_t delta = ctxt->input->base - oldbase;\
9050
0
        start = start + delta;\
9051
0
        in = in + delta;\
9052
0
    }\
9053
0
    end = ctxt->input->end;
9054
9055
static xmlChar *
9056
xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
9057
                         int normalize)
9058
44.3k
{
9059
44.3k
    xmlChar limit = 0;
9060
44.3k
    const xmlChar *in = NULL, *start, *end, *last;
9061
44.3k
    xmlChar *ret = NULL;
9062
44.3k
    int line, col;
9063
44.3k
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
9064
0
                    XML_MAX_HUGE_LENGTH :
9065
44.3k
                    XML_MAX_TEXT_LENGTH;
9066
9067
44.3k
    GROW;
9068
44.3k
    in = (xmlChar *) CUR_PTR;
9069
44.3k
    line = ctxt->input->line;
9070
44.3k
    col = ctxt->input->col;
9071
44.3k
    if (*in != '"' && *in != '\'') {
9072
0
        xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
9073
0
        return (NULL);
9074
0
    }
9075
44.3k
    ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
9076
9077
    /*
9078
     * try to handle in this routine the most common case where no
9079
     * allocation of a new string is required and where content is
9080
     * pure ASCII.
9081
     */
9082
44.3k
    limit = *in++;
9083
44.3k
    col++;
9084
44.3k
    end = ctxt->input->end;
9085
44.3k
    start = in;
9086
44.3k
    if (in >= end) {
9087
0
        GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
9088
0
    }
9089
44.3k
    if (normalize) {
9090
        /*
9091
   * Skip any leading spaces
9092
   */
9093
0
  while ((in < end) && (*in != limit) &&
9094
0
         ((*in == 0x20) || (*in == 0x9) ||
9095
0
          (*in == 0xA) || (*in == 0xD))) {
9096
0
      if (*in == 0xA) {
9097
0
          line++; col = 1;
9098
0
      } else {
9099
0
          col++;
9100
0
      }
9101
0
      in++;
9102
0
      start = in;
9103
0
      if (in >= end) {
9104
0
                GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
9105
0
                if ((in - start) > maxLength) {
9106
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9107
0
                                   "AttValue length too long\n");
9108
0
                    return(NULL);
9109
0
                }
9110
0
      }
9111
0
  }
9112
0
  while ((in < end) && (*in != limit) && (*in >= 0x20) &&
9113
0
         (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
9114
0
      col++;
9115
0
      if ((*in++ == 0x20) && (*in == 0x20)) break;
9116
0
      if (in >= end) {
9117
0
                GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
9118
0
                if ((in - start) > maxLength) {
9119
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9120
0
                                   "AttValue length too long\n");
9121
0
                    return(NULL);
9122
0
                }
9123
0
      }
9124
0
  }
9125
0
  last = in;
9126
  /*
9127
   * skip the trailing blanks
9128
   */
9129
0
  while ((last[-1] == 0x20) && (last > start)) last--;
9130
0
  while ((in < end) && (*in != limit) &&
9131
0
         ((*in == 0x20) || (*in == 0x9) ||
9132
0
          (*in == 0xA) || (*in == 0xD))) {
9133
0
      if (*in == 0xA) {
9134
0
          line++, col = 1;
9135
0
      } else {
9136
0
          col++;
9137
0
      }
9138
0
      in++;
9139
0
      if (in >= end) {
9140
0
    const xmlChar *oldbase = ctxt->input->base;
9141
0
    GROW;
9142
0
                if (ctxt->instate == XML_PARSER_EOF)
9143
0
                    return(NULL);
9144
0
    if (oldbase != ctxt->input->base) {
9145
0
        ptrdiff_t delta = ctxt->input->base - oldbase;
9146
0
        start = start + delta;
9147
0
        in = in + delta;
9148
0
        last = last + delta;
9149
0
    }
9150
0
    end = ctxt->input->end;
9151
0
                if ((in - start) > maxLength) {
9152
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9153
0
                                   "AttValue length too long\n");
9154
0
                    return(NULL);
9155
0
                }
9156
0
      }
9157
0
  }
9158
0
        if ((in - start) > maxLength) {
9159
0
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9160
0
                           "AttValue length too long\n");
9161
0
            return(NULL);
9162
0
        }
9163
0
  if (*in != limit) goto need_complex;
9164
44.3k
    } else {
9165
84.9k
  while ((in < end) && (*in != limit) && (*in >= 0x20) &&
9166
84.9k
         (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
9167
40.6k
      in++;
9168
40.6k
      col++;
9169
40.6k
      if (in >= end) {
9170
0
                GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
9171
0
                if ((in - start) > maxLength) {
9172
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9173
0
                                   "AttValue length too long\n");
9174
0
                    return(NULL);
9175
0
                }
9176
0
      }
9177
40.6k
  }
9178
44.3k
  last = in;
9179
44.3k
        if ((in - start) > maxLength) {
9180
0
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9181
0
                           "AttValue length too long\n");
9182
0
            return(NULL);
9183
0
        }
9184
44.3k
  if (*in != limit) goto need_complex;
9185
44.3k
    }
9186
40.6k
    in++;
9187
40.6k
    col++;
9188
40.6k
    if (len != NULL) {
9189
40.6k
        if (alloc) *alloc = 0;
9190
40.6k
        *len = last - start;
9191
40.6k
        ret = (xmlChar *) start;
9192
40.6k
    } else {
9193
0
        if (alloc) *alloc = 1;
9194
0
        ret = xmlStrndup(start, last - start);
9195
0
    }
9196
40.6k
    CUR_PTR = in;
9197
40.6k
    ctxt->input->line = line;
9198
40.6k
    ctxt->input->col = col;
9199
40.6k
    return ret;
9200
3.69k
need_complex:
9201
3.69k
    if (alloc) *alloc = 1;
9202
3.69k
    return xmlParseAttValueComplex(ctxt, len, normalize);
9203
44.3k
}
9204
9205
/**
9206
 * xmlParseAttribute2:
9207
 * @ctxt:  an XML parser context
9208
 * @pref:  the element prefix
9209
 * @elem:  the element name
9210
 * @prefix:  a xmlChar ** used to store the value of the attribute prefix
9211
 * @value:  a xmlChar ** used to store the value of the attribute
9212
 * @len:  an int * to save the length of the attribute
9213
 * @alloc:  an int * to indicate if the attribute was allocated
9214
 *
9215
 * parse an attribute in the new SAX2 framework.
9216
 *
9217
 * Returns the attribute name, and the value in *value, .
9218
 */
9219
9220
static const xmlChar *
9221
xmlParseAttribute2(xmlParserCtxtPtr ctxt,
9222
                   const xmlChar * pref, const xmlChar * elem,
9223
                   const xmlChar ** prefix, xmlChar ** value,
9224
                   int *len, int *alloc)
9225
44.3k
{
9226
44.3k
    const xmlChar *name;
9227
44.3k
    xmlChar *val, *internal_val = NULL;
9228
44.3k
    int normalize = 0;
9229
9230
44.3k
    *value = NULL;
9231
44.3k
    GROW;
9232
44.3k
    name = xmlParseQName(ctxt, prefix);
9233
44.3k
    if (name == NULL) {
9234
0
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
9235
0
                       "error parsing attribute name\n");
9236
0
        return (NULL);
9237
0
    }
9238
9239
    /*
9240
     * get the type if needed
9241
     */
9242
44.3k
    if (ctxt->attsSpecial != NULL) {
9243
0
        int type;
9244
9245
0
        type = (int) (ptrdiff_t) xmlHashQLookup2(ctxt->attsSpecial,
9246
0
                                                 pref, elem, *prefix, name);
9247
0
        if (type != 0)
9248
0
            normalize = 1;
9249
0
    }
9250
9251
    /*
9252
     * read the value
9253
     */
9254
44.3k
    SKIP_BLANKS;
9255
44.3k
    if (RAW == '=') {
9256
44.3k
        NEXT;
9257
44.3k
        SKIP_BLANKS;
9258
44.3k
        val = xmlParseAttValueInternal(ctxt, len, alloc, normalize);
9259
44.3k
        if (val == NULL)
9260
0
            return (NULL);
9261
44.3k
  if (normalize) {
9262
      /*
9263
       * Sometimes a second normalisation pass for spaces is needed
9264
       * but that only happens if charrefs or entities references
9265
       * have been used in the attribute value, i.e. the attribute
9266
       * value have been extracted in an allocated string already.
9267
       */
9268
0
      if (*alloc) {
9269
0
          const xmlChar *val2;
9270
9271
0
          val2 = xmlAttrNormalizeSpace2(ctxt, val, len);
9272
0
    if ((val2 != NULL) && (val2 != val)) {
9273
0
        xmlFree(val);
9274
0
        val = (xmlChar *) val2;
9275
0
    }
9276
0
      }
9277
0
  }
9278
44.3k
        ctxt->instate = XML_PARSER_CONTENT;
9279
44.3k
    } else {
9280
0
        xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
9281
0
                          "Specification mandates value for attribute %s\n",
9282
0
                          name);
9283
0
        return (name);
9284
0
    }
9285
9286
44.3k
    if (*prefix == ctxt->str_xml) {
9287
        /*
9288
         * Check that xml:lang conforms to the specification
9289
         * No more registered as an error, just generate a warning now
9290
         * since this was deprecated in XML second edition
9291
         */
9292
0
        if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "lang"))) {
9293
0
            internal_val = xmlStrndup(val, *len);
9294
0
            if (!xmlCheckLanguageID(internal_val)) {
9295
0
                xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
9296
0
                              "Malformed value for xml:lang : %s\n",
9297
0
                              internal_val, NULL);
9298
0
            }
9299
0
        }
9300
9301
        /*
9302
         * Check that xml:space conforms to the specification
9303
         */
9304
0
        if (xmlStrEqual(name, BAD_CAST "space")) {
9305
0
            internal_val = xmlStrndup(val, *len);
9306
0
            if (xmlStrEqual(internal_val, BAD_CAST "default"))
9307
0
                *(ctxt->space) = 0;
9308
0
            else if (xmlStrEqual(internal_val, BAD_CAST "preserve"))
9309
0
                *(ctxt->space) = 1;
9310
0
            else {
9311
0
                xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
9312
0
                              "Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
9313
0
                              internal_val, NULL);
9314
0
            }
9315
0
        }
9316
0
        if (internal_val) {
9317
0
            xmlFree(internal_val);
9318
0
        }
9319
0
    }
9320
9321
44.3k
    *value = val;
9322
44.3k
    return (name);
9323
44.3k
}
9324
/**
9325
 * xmlParseStartTag2:
9326
 * @ctxt:  an XML parser context
9327
 *
9328
 * Parse a start tag. Always consumes '<'.
9329
 *
9330
 * This routine is called when running SAX2 parsing
9331
 *
9332
 * [40] STag ::= '<' Name (S Attribute)* S? '>'
9333
 *
9334
 * [ WFC: Unique Att Spec ]
9335
 * No attribute name may appear more than once in the same start-tag or
9336
 * empty-element tag.
9337
 *
9338
 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
9339
 *
9340
 * [ WFC: Unique Att Spec ]
9341
 * No attribute name may appear more than once in the same start-tag or
9342
 * empty-element tag.
9343
 *
9344
 * With namespace:
9345
 *
9346
 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
9347
 *
9348
 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
9349
 *
9350
 * Returns the element name parsed
9351
 */
9352
9353
static const xmlChar *
9354
xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
9355
44.3k
                  const xmlChar **URI, int *tlen) {
9356
44.3k
    const xmlChar *localname;
9357
44.3k
    const xmlChar *prefix;
9358
44.3k
    const xmlChar *attname;
9359
44.3k
    const xmlChar *aprefix;
9360
44.3k
    const xmlChar *nsname;
9361
44.3k
    xmlChar *attvalue;
9362
44.3k
    const xmlChar **atts = ctxt->atts;
9363
44.3k
    int maxatts = ctxt->maxatts;
9364
44.3k
    int nratts, nbatts, nbdef, inputid;
9365
44.3k
    int i, j, nbNs, attval;
9366
44.3k
    unsigned long cur;
9367
44.3k
    int nsNr = ctxt->nsNr;
9368
9369
44.3k
    if (RAW != '<') return(NULL);
9370
44.3k
    NEXT1;
9371
9372
    /*
9373
     * NOTE: it is crucial with the SAX2 API to never call SHRINK beyond that
9374
     *       point since the attribute values may be stored as pointers to
9375
     *       the buffer and calling SHRINK would destroy them !
9376
     *       The Shrinking is only possible once the full set of attribute
9377
     *       callbacks have been done.
9378
     */
9379
44.3k
    SHRINK;
9380
44.3k
    cur = ctxt->input->cur - ctxt->input->base;
9381
44.3k
    inputid = ctxt->input->id;
9382
44.3k
    nbatts = 0;
9383
44.3k
    nratts = 0;
9384
44.3k
    nbdef = 0;
9385
44.3k
    nbNs = 0;
9386
44.3k
    attval = 0;
9387
    /* Forget any namespaces added during an earlier parse of this element. */
9388
44.3k
    ctxt->nsNr = nsNr;
9389
9390
44.3k
    localname = xmlParseQName(ctxt, &prefix);
9391
44.3k
    if (localname == NULL) {
9392
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
9393
0
           "StartTag: invalid element name\n");
9394
0
        return(NULL);
9395
0
    }
9396
44.3k
    *tlen = ctxt->input->cur - ctxt->input->base - cur;
9397
9398
    /*
9399
     * Now parse the attributes, it ends up with the ending
9400
     *
9401
     * (S Attribute)* S?
9402
     */
9403
44.3k
    SKIP_BLANKS;
9404
44.3k
    GROW;
9405
9406
55.3k
    while (((RAW != '>') &&
9407
55.3k
     ((RAW != '/') || (NXT(1) != '>')) &&
9408
55.3k
     (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) {
9409
44.3k
  int len = -1, alloc = 0;
9410
9411
44.3k
  attname = xmlParseAttribute2(ctxt, prefix, localname,
9412
44.3k
                               &aprefix, &attvalue, &len, &alloc);
9413
44.3k
        if (attname == NULL) {
9414
0
      xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
9415
0
           "xmlParseStartTag: problem parsing attributes\n");
9416
0
      break;
9417
0
  }
9418
44.3k
        if (attvalue == NULL)
9419
0
            goto next_attr;
9420
44.3k
  if (len < 0) len = xmlStrlen(attvalue);
9421
9422
44.3k
        if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
9423
0
            const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
9424
0
            xmlURIPtr uri;
9425
9426
0
            if (URL == NULL) {
9427
0
                xmlErrMemory(ctxt, "dictionary allocation failure");
9428
0
                if ((attvalue != NULL) && (alloc != 0))
9429
0
                    xmlFree(attvalue);
9430
0
                localname = NULL;
9431
0
                goto done;
9432
0
            }
9433
0
            if (*URL != 0) {
9434
0
                uri = xmlParseURI((const char *) URL);
9435
0
                if (uri == NULL) {
9436
0
                    xmlNsErr(ctxt, XML_WAR_NS_URI,
9437
0
                             "xmlns: '%s' is not a valid URI\n",
9438
0
                                       URL, NULL, NULL);
9439
0
                } else {
9440
0
                    if (uri->scheme == NULL) {
9441
0
                        xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
9442
0
                                  "xmlns: URI %s is not absolute\n",
9443
0
                                  URL, NULL, NULL);
9444
0
                    }
9445
0
                    xmlFreeURI(uri);
9446
0
                }
9447
0
                if (URL == ctxt->str_xml_ns) {
9448
0
                    if (attname != ctxt->str_xml) {
9449
0
                        xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9450
0
                     "xml namespace URI cannot be the default namespace\n",
9451
0
                                 NULL, NULL, NULL);
9452
0
                    }
9453
0
                    goto next_attr;
9454
0
                }
9455
0
                if ((len == 29) &&
9456
0
                    (xmlStrEqual(URL,
9457
0
                             BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
9458
0
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9459
0
                         "reuse of the xmlns namespace name is forbidden\n",
9460
0
                             NULL, NULL, NULL);
9461
0
                    goto next_attr;
9462
0
                }
9463
0
            }
9464
            /*
9465
             * check that it's not a defined namespace
9466
             */
9467
0
            for (j = 1;j <= nbNs;j++)
9468
0
                if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
9469
0
                    break;
9470
0
            if (j <= nbNs)
9471
0
                xmlErrAttributeDup(ctxt, NULL, attname);
9472
0
            else
9473
0
                if (nsPush(ctxt, NULL, URL) > 0) nbNs++;
9474
9475
44.3k
        } else if (aprefix == ctxt->str_xmlns) {
9476
11.0k
            const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
9477
11.0k
            xmlURIPtr uri;
9478
9479
11.0k
            if (attname == ctxt->str_xml) {
9480
0
                if (URL != ctxt->str_xml_ns) {
9481
0
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9482
0
                             "xml namespace prefix mapped to wrong URI\n",
9483
0
                             NULL, NULL, NULL);
9484
0
                }
9485
                /*
9486
                 * Do not keep a namespace definition node
9487
                 */
9488
0
                goto next_attr;
9489
0
            }
9490
11.0k
            if (URL == ctxt->str_xml_ns) {
9491
0
                if (attname != ctxt->str_xml) {
9492
0
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9493
0
                             "xml namespace URI mapped to wrong prefix\n",
9494
0
                             NULL, NULL, NULL);
9495
0
                }
9496
0
                goto next_attr;
9497
0
            }
9498
11.0k
            if (attname == ctxt->str_xmlns) {
9499
0
                xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9500
0
                         "redefinition of the xmlns prefix is forbidden\n",
9501
0
                         NULL, NULL, NULL);
9502
0
                goto next_attr;
9503
0
            }
9504
11.0k
            if ((len == 29) &&
9505
11.0k
                (xmlStrEqual(URL,
9506
0
                             BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
9507
0
                xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9508
0
                         "reuse of the xmlns namespace name is forbidden\n",
9509
0
                         NULL, NULL, NULL);
9510
0
                goto next_attr;
9511
0
            }
9512
11.0k
            if ((URL == NULL) || (URL[0] == 0)) {
9513
0
                xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9514
0
                         "xmlns:%s: Empty XML namespace is not allowed\n",
9515
0
                              attname, NULL, NULL);
9516
0
                goto next_attr;
9517
11.0k
            } else {
9518
11.0k
                uri = xmlParseURI((const char *) URL);
9519
11.0k
                if (uri == NULL) {
9520
0
                    xmlNsErr(ctxt, XML_WAR_NS_URI,
9521
0
                         "xmlns:%s: '%s' is not a valid URI\n",
9522
0
                                       attname, URL, NULL);
9523
11.0k
                } else {
9524
11.0k
                    if ((ctxt->pedantic) && (uri->scheme == NULL)) {
9525
0
                        xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
9526
0
                                  "xmlns:%s: URI %s is not absolute\n",
9527
0
                                  attname, URL, NULL);
9528
0
                    }
9529
11.0k
                    xmlFreeURI(uri);
9530
11.0k
                }
9531
11.0k
            }
9532
9533
            /*
9534
             * check that it's not a defined namespace
9535
             */
9536
11.0k
            for (j = 1;j <= nbNs;j++)
9537
0
                if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
9538
0
                    break;
9539
11.0k
            if (j <= nbNs)
9540
0
                xmlErrAttributeDup(ctxt, aprefix, attname);
9541
11.0k
            else
9542
11.0k
                if (nsPush(ctxt, attname, URL) > 0) nbNs++;
9543
9544
33.2k
        } else {
9545
            /*
9546
             * Add the pair to atts
9547
             */
9548
33.2k
            if ((atts == NULL) || (nbatts + 5 > maxatts)) {
9549
3.69k
                if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
9550
0
                    goto next_attr;
9551
0
                }
9552
3.69k
                maxatts = ctxt->maxatts;
9553
3.69k
                atts = ctxt->atts;
9554
3.69k
            }
9555
33.2k
            ctxt->attallocs[nratts++] = alloc;
9556
33.2k
            atts[nbatts++] = attname;
9557
33.2k
            atts[nbatts++] = aprefix;
9558
            /*
9559
             * The namespace URI field is used temporarily to point at the
9560
             * base of the current input buffer for non-alloced attributes.
9561
             * When the input buffer is reallocated, all the pointers become
9562
             * invalid, but they can be reconstructed later.
9563
             */
9564
33.2k
            if (alloc)
9565
3.69k
                atts[nbatts++] = NULL;
9566
29.5k
            else
9567
29.5k
                atts[nbatts++] = ctxt->input->base;
9568
33.2k
            atts[nbatts++] = attvalue;
9569
33.2k
            attvalue += len;
9570
33.2k
            atts[nbatts++] = attvalue;
9571
            /*
9572
             * tag if some deallocation is needed
9573
             */
9574
33.2k
            if (alloc != 0) attval = 1;
9575
33.2k
            attvalue = NULL; /* moved into atts */
9576
33.2k
        }
9577
9578
44.3k
next_attr:
9579
44.3k
        if ((attvalue != NULL) && (alloc != 0)) {
9580
0
            xmlFree(attvalue);
9581
0
            attvalue = NULL;
9582
0
        }
9583
9584
44.3k
  GROW
9585
44.3k
        if (ctxt->instate == XML_PARSER_EOF)
9586
0
            break;
9587
44.3k
  if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
9588
33.2k
      break;
9589
11.0k
  if (SKIP_BLANKS == 0) {
9590
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
9591
0
         "attributes construct error\n");
9592
0
      break;
9593
0
  }
9594
11.0k
        GROW;
9595
11.0k
    }
9596
9597
44.3k
    if (ctxt->input->id != inputid) {
9598
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
9599
0
                    "Unexpected change of input\n");
9600
0
        localname = NULL;
9601
0
        goto done;
9602
0
    }
9603
9604
    /* Reconstruct attribute value pointers. */
9605
77.5k
    for (i = 0, j = 0; j < nratts; i += 5, j++) {
9606
33.2k
        if (atts[i+2] != NULL) {
9607
            /*
9608
             * Arithmetic on dangling pointers is technically undefined
9609
             * behavior, but well...
9610
             */
9611
29.5k
            const xmlChar *old = atts[i+2];
9612
29.5k
            atts[i+2]  = NULL;    /* Reset repurposed namespace URI */
9613
29.5k
            atts[i+3] = ctxt->input->base + (atts[i+3] - old);  /* value */
9614
29.5k
            atts[i+4] = ctxt->input->base + (atts[i+4] - old);  /* valuend */
9615
29.5k
        }
9616
33.2k
    }
9617
9618
    /*
9619
     * The attributes defaulting
9620
     */
9621
44.3k
    if (ctxt->attsDefault != NULL) {
9622
0
        xmlDefAttrsPtr defaults;
9623
9624
0
  defaults = xmlHashLookup2(ctxt->attsDefault, localname, prefix);
9625
0
  if (defaults != NULL) {
9626
0
      for (i = 0;i < defaults->nbAttrs;i++) {
9627
0
          attname = defaults->values[5 * i];
9628
0
    aprefix = defaults->values[5 * i + 1];
9629
9630
                /*
9631
     * special work for namespaces defaulted defs
9632
     */
9633
0
    if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
9634
        /*
9635
         * check that it's not a defined namespace
9636
         */
9637
0
        for (j = 1;j <= nbNs;j++)
9638
0
            if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
9639
0
          break;
9640
0
              if (j <= nbNs) continue;
9641
9642
0
        nsname = xmlGetNamespace(ctxt, NULL);
9643
0
        if (nsname != defaults->values[5 * i + 2]) {
9644
0
      if (nsPush(ctxt, NULL,
9645
0
                 defaults->values[5 * i + 2]) > 0)
9646
0
          nbNs++;
9647
0
        }
9648
0
    } else if (aprefix == ctxt->str_xmlns) {
9649
        /*
9650
         * check that it's not a defined namespace
9651
         */
9652
0
        for (j = 1;j <= nbNs;j++)
9653
0
            if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
9654
0
          break;
9655
0
              if (j <= nbNs) continue;
9656
9657
0
        nsname = xmlGetNamespace(ctxt, attname);
9658
0
        if (nsname != defaults->values[5 * i + 2]) {
9659
0
      if (nsPush(ctxt, attname,
9660
0
                 defaults->values[5 * i + 2]) > 0)
9661
0
          nbNs++;
9662
0
        }
9663
0
    } else {
9664
        /*
9665
         * check that it's not a defined attribute
9666
         */
9667
0
        for (j = 0;j < nbatts;j+=5) {
9668
0
      if ((attname == atts[j]) && (aprefix == atts[j+1]))
9669
0
          break;
9670
0
        }
9671
0
        if (j < nbatts) continue;
9672
9673
0
        if ((atts == NULL) || (nbatts + 5 > maxatts)) {
9674
0
      if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
9675
0
                            localname = NULL;
9676
0
                            goto done;
9677
0
      }
9678
0
      maxatts = ctxt->maxatts;
9679
0
      atts = ctxt->atts;
9680
0
        }
9681
0
        atts[nbatts++] = attname;
9682
0
        atts[nbatts++] = aprefix;
9683
0
        if (aprefix == NULL)
9684
0
      atts[nbatts++] = NULL;
9685
0
        else
9686
0
            atts[nbatts++] = xmlGetNamespace(ctxt, aprefix);
9687
0
        atts[nbatts++] = defaults->values[5 * i + 2];
9688
0
        atts[nbatts++] = defaults->values[5 * i + 3];
9689
0
        if ((ctxt->standalone == 1) &&
9690
0
            (defaults->values[5 * i + 4] != NULL)) {
9691
0
      xmlValidityError(ctxt, XML_DTD_STANDALONE_DEFAULTED,
9692
0
    "standalone: attribute %s on %s defaulted from external subset\n",
9693
0
                                   attname, localname);
9694
0
        }
9695
0
        nbdef++;
9696
0
    }
9697
0
      }
9698
0
  }
9699
0
    }
9700
9701
    /*
9702
     * The attributes checkings
9703
     */
9704
77.5k
    for (i = 0; i < nbatts;i += 5) {
9705
        /*
9706
  * The default namespace does not apply to attribute names.
9707
  */
9708
33.2k
  if (atts[i + 1] != NULL) {
9709
0
      nsname = xmlGetNamespace(ctxt, atts[i + 1]);
9710
0
      if (nsname == NULL) {
9711
0
    xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
9712
0
        "Namespace prefix %s for %s on %s is not defined\n",
9713
0
        atts[i + 1], atts[i], localname);
9714
0
      }
9715
0
      atts[i + 2] = nsname;
9716
0
  } else
9717
33.2k
      nsname = NULL;
9718
  /*
9719
   * [ WFC: Unique Att Spec ]
9720
   * No attribute name may appear more than once in the same
9721
   * start-tag or empty-element tag.
9722
   * As extended by the Namespace in XML REC.
9723
   */
9724
36.9k
        for (j = 0; j < i;j += 5) {
9725
3.69k
      if (atts[i] == atts[j]) {
9726
0
          if (atts[i+1] == atts[j+1]) {
9727
0
        xmlErrAttributeDup(ctxt, atts[i+1], atts[i]);
9728
0
        break;
9729
0
    }
9730
0
    if ((nsname != NULL) && (atts[j + 2] == nsname)) {
9731
0
        xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED,
9732
0
           "Namespaced Attribute %s in '%s' redefined\n",
9733
0
           atts[i], nsname, NULL);
9734
0
        break;
9735
0
    }
9736
0
      }
9737
3.69k
  }
9738
33.2k
    }
9739
9740
44.3k
    nsname = xmlGetNamespace(ctxt, prefix);
9741
44.3k
    if ((prefix != NULL) && (nsname == NULL)) {
9742
0
  xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
9743
0
           "Namespace prefix %s on %s is not defined\n",
9744
0
     prefix, localname, NULL);
9745
0
    }
9746
44.3k
    *pref = prefix;
9747
44.3k
    *URI = nsname;
9748
9749
    /*
9750
     * SAX: Start of Element !
9751
     */
9752
44.3k
    if ((ctxt->sax != NULL) && (ctxt->sax->startElementNs != NULL) &&
9753
44.3k
  (!ctxt->disableSAX)) {
9754
44.3k
  if (nbNs > 0)
9755
11.0k
      ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
9756
11.0k
        nsname, nbNs, &ctxt->nsTab[ctxt->nsNr - 2 * nbNs],
9757
11.0k
        nbatts / 5, nbdef, atts);
9758
33.2k
  else
9759
33.2k
      ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
9760
33.2k
                    nsname, 0, NULL, nbatts / 5, nbdef, atts);
9761
44.3k
    }
9762
9763
44.3k
done:
9764
    /*
9765
     * Free up attribute allocated strings if needed
9766
     */
9767
44.3k
    if (attval != 0) {
9768
7.38k
  for (i = 3,j = 0; j < nratts;i += 5,j++)
9769
3.69k
      if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
9770
3.69k
          xmlFree((xmlChar *) atts[i]);
9771
3.69k
    }
9772
9773
44.3k
    return(localname);
9774
44.3k
}
9775
9776
/**
9777
 * xmlParseEndTag2:
9778
 * @ctxt:  an XML parser context
9779
 * @line:  line of the start tag
9780
 * @nsNr:  number of namespaces on the start tag
9781
 *
9782
 * Parse an end tag. Always consumes '</'.
9783
 *
9784
 * [42] ETag ::= '</' Name S? '>'
9785
 *
9786
 * With namespace
9787
 *
9788
 * [NS 9] ETag ::= '</' QName S? '>'
9789
 */
9790
9791
static void
9792
33.2k
xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlStartTag *tag) {
9793
33.2k
    const xmlChar *name;
9794
9795
33.2k
    GROW;
9796
33.2k
    if ((RAW != '<') || (NXT(1) != '/')) {
9797
0
  xmlFatalErr(ctxt, XML_ERR_LTSLASH_REQUIRED, NULL);
9798
0
  return;
9799
0
    }
9800
33.2k
    SKIP(2);
9801
9802
33.2k
    if (tag->prefix == NULL)
9803
14.7k
        name = xmlParseNameAndCompare(ctxt, ctxt->name);
9804
18.4k
    else
9805
18.4k
        name = xmlParseQNameAndCompare(ctxt, ctxt->name, tag->prefix);
9806
9807
    /*
9808
     * We should definitely be at the ending "S? '>'" part
9809
     */
9810
33.2k
    GROW;
9811
33.2k
    if (ctxt->instate == XML_PARSER_EOF)
9812
0
        return;
9813
33.2k
    SKIP_BLANKS;
9814
33.2k
    if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
9815
0
  xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
9816
0
    } else
9817
33.2k
  NEXT1;
9818
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
33.2k
    if (name != (xmlChar*)1) {
9826
0
        if (name == NULL) name = BAD_CAST "unparsable";
9827
0
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
9828
0
         "Opening and ending tag mismatch: %s line %d and %s\n",
9829
0
                    ctxt->name, tag->line, name);
9830
0
    }
9831
9832
    /*
9833
     * SAX: End of Tag
9834
     */
9835
33.2k
    if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
9836
33.2k
  (!ctxt->disableSAX))
9837
33.2k
  ctxt->sax->endElementNs(ctxt->userData, ctxt->name, tag->prefix,
9838
33.2k
                                tag->URI);
9839
9840
33.2k
    spacePop(ctxt);
9841
33.2k
    if (tag->nsNr != 0)
9842
11.0k
  nsPop(ctxt, tag->nsNr);
9843
33.2k
}
9844
9845
/**
9846
 * xmlParseCDSect:
9847
 * @ctxt:  an XML parser context
9848
 *
9849
 * DEPRECATED: Internal function, don't use.
9850
 *
9851
 * Parse escaped pure raw content. Always consumes '<!['.
9852
 *
9853
 * [18] CDSect ::= CDStart CData CDEnd
9854
 *
9855
 * [19] CDStart ::= '<![CDATA['
9856
 *
9857
 * [20] Data ::= (Char* - (Char* ']]>' Char*))
9858
 *
9859
 * [21] CDEnd ::= ']]>'
9860
 */
9861
void
9862
3.69k
xmlParseCDSect(xmlParserCtxtPtr ctxt) {
9863
3.69k
    xmlChar *buf = NULL;
9864
3.69k
    int len = 0;
9865
3.69k
    int size = XML_PARSER_BUFFER_SIZE;
9866
3.69k
    int r, rl;
9867
3.69k
    int s, sl;
9868
3.69k
    int cur, l;
9869
3.69k
    int count = 0;
9870
3.69k
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
9871
0
                    XML_MAX_HUGE_LENGTH :
9872
3.69k
                    XML_MAX_TEXT_LENGTH;
9873
9874
3.69k
    if ((CUR != '<') || (NXT(1) != '!') || (NXT(2) != '['))
9875
0
        return;
9876
3.69k
    SKIP(3);
9877
9878
3.69k
    if (!CMP6(CUR_PTR, 'C', 'D', 'A', 'T', 'A', '['))
9879
0
        return;
9880
3.69k
    SKIP(6);
9881
9882
3.69k
    ctxt->instate = XML_PARSER_CDATA_SECTION;
9883
3.69k
    r = CUR_CHAR(rl);
9884
3.69k
    if (!IS_CHAR(r)) {
9885
0
  xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
9886
0
        goto out;
9887
0
    }
9888
3.69k
    NEXTL(rl);
9889
3.69k
    s = CUR_CHAR(sl);
9890
3.69k
    if (!IS_CHAR(s)) {
9891
0
  xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
9892
0
        goto out;
9893
0
    }
9894
3.69k
    NEXTL(sl);
9895
3.69k
    cur = CUR_CHAR(l);
9896
3.69k
    buf = (xmlChar *) xmlMallocAtomic(size);
9897
3.69k
    if (buf == NULL) {
9898
0
  xmlErrMemory(ctxt, NULL);
9899
0
        goto out;
9900
0
    }
9901
18.4k
    while (IS_CHAR(cur) &&
9902
18.4k
           ((r != ']') || (s != ']') || (cur != '>'))) {
9903
14.7k
  if (len + 5 >= size) {
9904
0
      xmlChar *tmp;
9905
9906
0
      tmp = (xmlChar *) xmlRealloc(buf, size * 2);
9907
0
      if (tmp == NULL) {
9908
0
    xmlErrMemory(ctxt, NULL);
9909
0
                goto out;
9910
0
      }
9911
0
      buf = tmp;
9912
0
      size *= 2;
9913
0
  }
9914
14.7k
  COPY_BUF(rl,buf,len,r);
9915
14.7k
  r = s;
9916
14.7k
  rl = sl;
9917
14.7k
  s = cur;
9918
14.7k
  sl = l;
9919
14.7k
  count++;
9920
14.7k
  if (count > 50) {
9921
0
      SHRINK;
9922
0
      GROW;
9923
0
            if (ctxt->instate == XML_PARSER_EOF) {
9924
0
                goto out;
9925
0
            }
9926
0
      count = 0;
9927
0
  }
9928
14.7k
  NEXTL(l);
9929
14.7k
  cur = CUR_CHAR(l);
9930
14.7k
        if (len > maxLength) {
9931
0
            xmlFatalErrMsg(ctxt, XML_ERR_CDATA_NOT_FINISHED,
9932
0
                           "CData section too big found\n");
9933
0
            goto out;
9934
0
        }
9935
14.7k
    }
9936
3.69k
    buf[len] = 0;
9937
3.69k
    if (cur != '>') {
9938
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED,
9939
0
                       "CData section not finished\n%.50s\n", buf);
9940
0
        goto out;
9941
0
    }
9942
3.69k
    NEXTL(l);
9943
9944
    /*
9945
     * OK the buffer is to be consumed as cdata.
9946
     */
9947
3.69k
    if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
9948
3.69k
  if (ctxt->sax->cdataBlock != NULL)
9949
3.69k
      ctxt->sax->cdataBlock(ctxt->userData, buf, len);
9950
0
  else if (ctxt->sax->characters != NULL)
9951
0
      ctxt->sax->characters(ctxt->userData, buf, len);
9952
3.69k
    }
9953
9954
3.69k
out:
9955
3.69k
    if (ctxt->instate != XML_PARSER_EOF)
9956
3.69k
        ctxt->instate = XML_PARSER_CONTENT;
9957
3.69k
    xmlFree(buf);
9958
3.69k
}
9959
9960
/**
9961
 * xmlParseContentInternal:
9962
 * @ctxt:  an XML parser context
9963
 *
9964
 * Parse a content sequence. Stops at EOF or '</'. Leaves checking of
9965
 * unexpected EOF to the caller.
9966
 */
9967
9968
static void
9969
3.69k
xmlParseContentInternal(xmlParserCtxtPtr ctxt) {
9970
3.69k
    int nameNr = ctxt->nameNr;
9971
9972
3.69k
    GROW;
9973
173k
    while ((RAW != 0) &&
9974
173k
     (ctxt->instate != XML_PARSER_EOF)) {
9975
173k
  const xmlChar *cur = ctxt->input->cur;
9976
9977
  /*
9978
   * First case : a Processing Instruction.
9979
   */
9980
173k
  if ((*cur == '<') && (cur[1] == '?')) {
9981
3.69k
      xmlParsePI(ctxt);
9982
3.69k
  }
9983
9984
  /*
9985
   * Second case : a CDSection
9986
   */
9987
  /* 2.6.0 test was *cur not RAW */
9988
169k
  else if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
9989
3.69k
      xmlParseCDSect(ctxt);
9990
3.69k
  }
9991
9992
  /*
9993
   * Third case :  a comment
9994
   */
9995
166k
  else if ((*cur == '<') && (NXT(1) == '!') &&
9996
166k
     (NXT(2) == '-') && (NXT(3) == '-')) {
9997
7.38k
      xmlParseComment(ctxt);
9998
7.38k
      ctxt->instate = XML_PARSER_CONTENT;
9999
7.38k
  }
10000
10001
  /*
10002
   * Fourth case :  a sub-element.
10003
   */
10004
158k
  else if (*cur == '<') {
10005
73.8k
            if (NXT(1) == '/') {
10006
33.2k
                if (ctxt->nameNr <= nameNr)
10007
3.69k
                    break;
10008
29.5k
          xmlParseElementEnd(ctxt);
10009
40.6k
            } else {
10010
40.6k
          xmlParseElementStart(ctxt);
10011
40.6k
            }
10012
73.8k
  }
10013
10014
  /*
10015
   * Fifth case : a reference. If if has not been resolved,
10016
   *    parsing returns it's Name, create the node
10017
   */
10018
10019
84.9k
  else if (*cur == '&') {
10020
3.69k
      xmlParseReference(ctxt);
10021
3.69k
  }
10022
10023
  /*
10024
   * Last case, text. Note that References are handled directly.
10025
   */
10026
81.2k
  else {
10027
81.2k
      xmlParseCharData(ctxt, 0);
10028
81.2k
  }
10029
10030
169k
  GROW;
10031
169k
  SHRINK;
10032
169k
    }
10033
3.69k
}
10034
10035
/**
10036
 * xmlParseContent:
10037
 * @ctxt:  an XML parser context
10038
 *
10039
 * Parse a content sequence. Stops at EOF or '</'.
10040
 *
10041
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
10042
 */
10043
10044
void
10045
0
xmlParseContent(xmlParserCtxtPtr ctxt) {
10046
0
    int nameNr = ctxt->nameNr;
10047
10048
0
    xmlParseContentInternal(ctxt);
10049
10050
0
    if ((ctxt->instate != XML_PARSER_EOF) && (ctxt->nameNr > nameNr)) {
10051
0
        const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
10052
0
        int line = ctxt->pushTab[ctxt->nameNr - 1].line;
10053
0
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
10054
0
                "Premature end of data in tag %s line %d\n",
10055
0
    name, line, NULL);
10056
0
    }
10057
0
}
10058
10059
/**
10060
 * xmlParseElement:
10061
 * @ctxt:  an XML parser context
10062
 *
10063
 * DEPRECATED: Internal function, don't use.
10064
 *
10065
 * parse an XML element
10066
 *
10067
 * [39] element ::= EmptyElemTag | STag content ETag
10068
 *
10069
 * [ WFC: Element Type Match ]
10070
 * The Name in an element's end-tag must match the element type in the
10071
 * start-tag.
10072
 *
10073
 */
10074
10075
void
10076
3.69k
xmlParseElement(xmlParserCtxtPtr ctxt) {
10077
3.69k
    if (xmlParseElementStart(ctxt) != 0)
10078
0
        return;
10079
10080
3.69k
    xmlParseContentInternal(ctxt);
10081
3.69k
    if (ctxt->instate == XML_PARSER_EOF)
10082
0
  return;
10083
10084
3.69k
    if (CUR == 0) {
10085
0
        const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
10086
0
        int line = ctxt->pushTab[ctxt->nameNr - 1].line;
10087
0
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
10088
0
                "Premature end of data in tag %s line %d\n",
10089
0
    name, line, NULL);
10090
0
        return;
10091
0
    }
10092
10093
3.69k
    xmlParseElementEnd(ctxt);
10094
3.69k
}
10095
10096
/**
10097
 * xmlParseElementStart:
10098
 * @ctxt:  an XML parser context
10099
 *
10100
 * Parse the start of an XML element. Returns -1 in case of error, 0 if an
10101
 * opening tag was parsed, 1 if an empty element was parsed.
10102
 *
10103
 * Always consumes '<'.
10104
 */
10105
static int
10106
44.3k
xmlParseElementStart(xmlParserCtxtPtr ctxt) {
10107
44.3k
    const xmlChar *name;
10108
44.3k
    const xmlChar *prefix = NULL;
10109
44.3k
    const xmlChar *URI = NULL;
10110
44.3k
    xmlParserNodeInfo node_info;
10111
44.3k
    int line, tlen = 0;
10112
44.3k
    xmlNodePtr ret;
10113
44.3k
    int nsNr = ctxt->nsNr;
10114
10115
44.3k
    if (((unsigned int) ctxt->nameNr > xmlParserMaxDepth) &&
10116
44.3k
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
10117
0
  xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
10118
0
     "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
10119
0
        xmlParserMaxDepth);
10120
0
  xmlHaltParser(ctxt);
10121
0
  return(-1);
10122
0
    }
10123
10124
    /* Capture start position */
10125
44.3k
    if (ctxt->record_info) {
10126
0
        node_info.begin_pos = ctxt->input->consumed +
10127
0
                          (CUR_PTR - ctxt->input->base);
10128
0
  node_info.begin_line = ctxt->input->line;
10129
0
    }
10130
10131
44.3k
    if (ctxt->spaceNr == 0)
10132
0
  spacePush(ctxt, -1);
10133
44.3k
    else if (*ctxt->space == -2)
10134
0
  spacePush(ctxt, -1);
10135
44.3k
    else
10136
44.3k
  spacePush(ctxt, *ctxt->space);
10137
10138
44.3k
    line = ctxt->input->line;
10139
#ifdef LIBXML_SAX1_ENABLED
10140
    if (ctxt->sax2)
10141
#endif /* LIBXML_SAX1_ENABLED */
10142
44.3k
        name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
10143
#ifdef LIBXML_SAX1_ENABLED
10144
    else
10145
  name = xmlParseStartTag(ctxt);
10146
#endif /* LIBXML_SAX1_ENABLED */
10147
44.3k
    if (ctxt->instate == XML_PARSER_EOF)
10148
0
  return(-1);
10149
44.3k
    if (name == NULL) {
10150
0
  spacePop(ctxt);
10151
0
        return(-1);
10152
0
    }
10153
44.3k
    nameNsPush(ctxt, name, prefix, URI, line, ctxt->nsNr - nsNr);
10154
44.3k
    ret = ctxt->node;
10155
10156
#ifdef LIBXML_VALID_ENABLED
10157
    /*
10158
     * [ VC: Root Element Type ]
10159
     * The Name in the document type declaration must match the element
10160
     * type of the root element.
10161
     */
10162
    if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
10163
        ctxt->node && (ctxt->node == ctxt->myDoc->children))
10164
        ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
10165
#endif /* LIBXML_VALID_ENABLED */
10166
10167
    /*
10168
     * Check for an Empty Element.
10169
     */
10170
44.3k
    if ((RAW == '/') && (NXT(1) == '>')) {
10171
11.0k
        SKIP(2);
10172
11.0k
  if (ctxt->sax2) {
10173
11.0k
      if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
10174
11.0k
    (!ctxt->disableSAX))
10175
11.0k
    ctxt->sax->endElementNs(ctxt->userData, name, prefix, URI);
10176
#ifdef LIBXML_SAX1_ENABLED
10177
  } else {
10178
      if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
10179
    (!ctxt->disableSAX))
10180
    ctxt->sax->endElement(ctxt->userData, name);
10181
#endif /* LIBXML_SAX1_ENABLED */
10182
11.0k
  }
10183
11.0k
  namePop(ctxt);
10184
11.0k
  spacePop(ctxt);
10185
11.0k
  if (nsNr != ctxt->nsNr)
10186
0
      nsPop(ctxt, ctxt->nsNr - nsNr);
10187
11.0k
  if ( ret != NULL && ctxt->record_info ) {
10188
0
     node_info.end_pos = ctxt->input->consumed +
10189
0
            (CUR_PTR - ctxt->input->base);
10190
0
     node_info.end_line = ctxt->input->line;
10191
0
     node_info.node = ret;
10192
0
     xmlParserAddNodeInfo(ctxt, &node_info);
10193
0
  }
10194
11.0k
  return(1);
10195
11.0k
    }
10196
33.2k
    if (RAW == '>') {
10197
33.2k
        NEXT1;
10198
33.2k
    } else {
10199
0
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_GT_REQUIRED,
10200
0
         "Couldn't find end of Start Tag %s line %d\n",
10201
0
                    name, line, NULL);
10202
10203
  /*
10204
   * end of parsing of this node.
10205
   */
10206
0
  nodePop(ctxt);
10207
0
  namePop(ctxt);
10208
0
  spacePop(ctxt);
10209
0
  if (nsNr != ctxt->nsNr)
10210
0
      nsPop(ctxt, ctxt->nsNr - nsNr);
10211
10212
  /*
10213
   * Capture end position and add node
10214
   */
10215
0
  if ( ret != NULL && ctxt->record_info ) {
10216
0
     node_info.end_pos = ctxt->input->consumed +
10217
0
            (CUR_PTR - ctxt->input->base);
10218
0
     node_info.end_line = ctxt->input->line;
10219
0
     node_info.node = ret;
10220
0
     xmlParserAddNodeInfo(ctxt, &node_info);
10221
0
  }
10222
0
  return(-1);
10223
0
    }
10224
10225
33.2k
    return(0);
10226
33.2k
}
10227
10228
/**
10229
 * xmlParseElementEnd:
10230
 * @ctxt:  an XML parser context
10231
 *
10232
 * Parse the end of an XML element. Always consumes '</'.
10233
 */
10234
static void
10235
33.2k
xmlParseElementEnd(xmlParserCtxtPtr ctxt) {
10236
33.2k
    xmlParserNodeInfo node_info;
10237
33.2k
    xmlNodePtr ret = ctxt->node;
10238
10239
33.2k
    if (ctxt->nameNr <= 0) {
10240
0
        if ((RAW == '<') && (NXT(1) == '/'))
10241
0
            SKIP(2);
10242
0
        return;
10243
0
    }
10244
10245
    /*
10246
     * parse the end of tag: '</' should be here.
10247
     */
10248
33.2k
    if (ctxt->sax2) {
10249
33.2k
  xmlParseEndTag2(ctxt, &ctxt->pushTab[ctxt->nameNr - 1]);
10250
33.2k
  namePop(ctxt);
10251
33.2k
    }
10252
#ifdef LIBXML_SAX1_ENABLED
10253
    else
10254
  xmlParseEndTag1(ctxt, 0);
10255
#endif /* LIBXML_SAX1_ENABLED */
10256
10257
    /*
10258
     * Capture end position and add node
10259
     */
10260
33.2k
    if ( ret != NULL && ctxt->record_info ) {
10261
0
       node_info.end_pos = ctxt->input->consumed +
10262
0
                          (CUR_PTR - ctxt->input->base);
10263
0
       node_info.end_line = ctxt->input->line;
10264
0
       node_info.node = ret;
10265
0
       xmlParserAddNodeInfo(ctxt, &node_info);
10266
0
    }
10267
33.2k
}
10268
10269
/**
10270
 * xmlParseVersionNum:
10271
 * @ctxt:  an XML parser context
10272
 *
10273
 * DEPRECATED: Internal function, don't use.
10274
 *
10275
 * parse the XML version value.
10276
 *
10277
 * [26] VersionNum ::= '1.' [0-9]+
10278
 *
10279
 * In practice allow [0-9].[0-9]+ at that level
10280
 *
10281
 * Returns the string giving the XML version number, or NULL
10282
 */
10283
xmlChar *
10284
0
xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
10285
0
    xmlChar *buf = NULL;
10286
0
    int len = 0;
10287
0
    int size = 10;
10288
0
    xmlChar cur;
10289
10290
0
    buf = (xmlChar *) xmlMallocAtomic(size);
10291
0
    if (buf == NULL) {
10292
0
  xmlErrMemory(ctxt, NULL);
10293
0
  return(NULL);
10294
0
    }
10295
0
    cur = CUR;
10296
0
    if (!((cur >= '0') && (cur <= '9'))) {
10297
0
  xmlFree(buf);
10298
0
  return(NULL);
10299
0
    }
10300
0
    buf[len++] = cur;
10301
0
    NEXT;
10302
0
    cur=CUR;
10303
0
    if (cur != '.') {
10304
0
  xmlFree(buf);
10305
0
  return(NULL);
10306
0
    }
10307
0
    buf[len++] = cur;
10308
0
    NEXT;
10309
0
    cur=CUR;
10310
0
    while ((cur >= '0') && (cur <= '9')) {
10311
0
  if (len + 1 >= size) {
10312
0
      xmlChar *tmp;
10313
10314
0
      size *= 2;
10315
0
      tmp = (xmlChar *) xmlRealloc(buf, size);
10316
0
      if (tmp == NULL) {
10317
0
          xmlFree(buf);
10318
0
    xmlErrMemory(ctxt, NULL);
10319
0
    return(NULL);
10320
0
      }
10321
0
      buf = tmp;
10322
0
  }
10323
0
  buf[len++] = cur;
10324
0
  NEXT;
10325
0
  cur=CUR;
10326
0
    }
10327
0
    buf[len] = 0;
10328
0
    return(buf);
10329
0
}
10330
10331
/**
10332
 * xmlParseVersionInfo:
10333
 * @ctxt:  an XML parser context
10334
 *
10335
 * DEPRECATED: Internal function, don't use.
10336
 *
10337
 * parse the XML version.
10338
 *
10339
 * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
10340
 *
10341
 * [25] Eq ::= S? '=' S?
10342
 *
10343
 * Returns the version string, e.g. "1.0"
10344
 */
10345
10346
xmlChar *
10347
0
xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
10348
0
    xmlChar *version = NULL;
10349
10350
0
    if (CMP7(CUR_PTR, 'v', 'e', 'r', 's', 'i', 'o', 'n')) {
10351
0
  SKIP(7);
10352
0
  SKIP_BLANKS;
10353
0
  if (RAW != '=') {
10354
0
      xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10355
0
      return(NULL);
10356
0
        }
10357
0
  NEXT;
10358
0
  SKIP_BLANKS;
10359
0
  if (RAW == '"') {
10360
0
      NEXT;
10361
0
      version = xmlParseVersionNum(ctxt);
10362
0
      if (RAW != '"') {
10363
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10364
0
      } else
10365
0
          NEXT;
10366
0
  } else if (RAW == '\''){
10367
0
      NEXT;
10368
0
      version = xmlParseVersionNum(ctxt);
10369
0
      if (RAW != '\'') {
10370
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10371
0
      } else
10372
0
          NEXT;
10373
0
  } else {
10374
0
      xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10375
0
  }
10376
0
    }
10377
0
    return(version);
10378
0
}
10379
10380
/**
10381
 * xmlParseEncName:
10382
 * @ctxt:  an XML parser context
10383
 *
10384
 * DEPRECATED: Internal function, don't use.
10385
 *
10386
 * parse the XML encoding name
10387
 *
10388
 * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
10389
 *
10390
 * Returns the encoding name value or NULL
10391
 */
10392
xmlChar *
10393
0
xmlParseEncName(xmlParserCtxtPtr ctxt) {
10394
0
    xmlChar *buf = NULL;
10395
0
    int len = 0;
10396
0
    int size = 10;
10397
0
    xmlChar cur;
10398
10399
0
    cur = CUR;
10400
0
    if (((cur >= 'a') && (cur <= 'z')) ||
10401
0
        ((cur >= 'A') && (cur <= 'Z'))) {
10402
0
  buf = (xmlChar *) xmlMallocAtomic(size);
10403
0
  if (buf == NULL) {
10404
0
      xmlErrMemory(ctxt, NULL);
10405
0
      return(NULL);
10406
0
  }
10407
10408
0
  buf[len++] = cur;
10409
0
  NEXT;
10410
0
  cur = CUR;
10411
0
  while (((cur >= 'a') && (cur <= 'z')) ||
10412
0
         ((cur >= 'A') && (cur <= 'Z')) ||
10413
0
         ((cur >= '0') && (cur <= '9')) ||
10414
0
         (cur == '.') || (cur == '_') ||
10415
0
         (cur == '-')) {
10416
0
      if (len + 1 >= size) {
10417
0
          xmlChar *tmp;
10418
10419
0
    size *= 2;
10420
0
    tmp = (xmlChar *) xmlRealloc(buf, size);
10421
0
    if (tmp == NULL) {
10422
0
        xmlErrMemory(ctxt, NULL);
10423
0
        xmlFree(buf);
10424
0
        return(NULL);
10425
0
    }
10426
0
    buf = tmp;
10427
0
      }
10428
0
      buf[len++] = cur;
10429
0
      NEXT;
10430
0
      cur = CUR;
10431
0
      if (cur == 0) {
10432
0
          SHRINK;
10433
0
    GROW;
10434
0
    cur = CUR;
10435
0
      }
10436
0
        }
10437
0
  buf[len] = 0;
10438
0
    } else {
10439
0
  xmlFatalErr(ctxt, XML_ERR_ENCODING_NAME, NULL);
10440
0
    }
10441
0
    return(buf);
10442
0
}
10443
10444
/**
10445
 * xmlParseEncodingDecl:
10446
 * @ctxt:  an XML parser context
10447
 *
10448
 * DEPRECATED: Internal function, don't use.
10449
 *
10450
 * parse the XML encoding declaration
10451
 *
10452
 * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' |  "'" EncName "'")
10453
 *
10454
 * this setups the conversion filters.
10455
 *
10456
 * Returns the encoding value or NULL
10457
 */
10458
10459
const xmlChar *
10460
0
xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
10461
0
    xmlChar *encoding = NULL;
10462
10463
0
    SKIP_BLANKS;
10464
0
    if (CMP8(CUR_PTR, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g')) {
10465
0
  SKIP(8);
10466
0
  SKIP_BLANKS;
10467
0
  if (RAW != '=') {
10468
0
      xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10469
0
      return(NULL);
10470
0
        }
10471
0
  NEXT;
10472
0
  SKIP_BLANKS;
10473
0
  if (RAW == '"') {
10474
0
      NEXT;
10475
0
      encoding = xmlParseEncName(ctxt);
10476
0
      if (RAW != '"') {
10477
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10478
0
    xmlFree((xmlChar *) encoding);
10479
0
    return(NULL);
10480
0
      } else
10481
0
          NEXT;
10482
0
  } else if (RAW == '\''){
10483
0
      NEXT;
10484
0
      encoding = xmlParseEncName(ctxt);
10485
0
      if (RAW != '\'') {
10486
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10487
0
    xmlFree((xmlChar *) encoding);
10488
0
    return(NULL);
10489
0
      } else
10490
0
          NEXT;
10491
0
  } else {
10492
0
      xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10493
0
  }
10494
10495
        /*
10496
         * Non standard parsing, allowing the user to ignore encoding
10497
         */
10498
0
        if (ctxt->options & XML_PARSE_IGNORE_ENC) {
10499
0
      xmlFree((xmlChar *) encoding);
10500
0
            return(NULL);
10501
0
  }
10502
10503
  /*
10504
   * UTF-16 encoding switch has already taken place at this stage,
10505
   * more over the little-endian/big-endian selection is already done
10506
   */
10507
0
        if ((encoding != NULL) &&
10508
0
      ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-16")) ||
10509
0
       (!xmlStrcasecmp(encoding, BAD_CAST "UTF16")))) {
10510
      /*
10511
       * If no encoding was passed to the parser, that we are
10512
       * using UTF-16 and no decoder is present i.e. the
10513
       * document is apparently UTF-8 compatible, then raise an
10514
       * encoding mismatch fatal error
10515
       */
10516
0
      if ((ctxt->encoding == NULL) &&
10517
0
          (ctxt->input->buf != NULL) &&
10518
0
          (ctxt->input->buf->encoder == NULL)) {
10519
0
    xmlFatalErrMsg(ctxt, XML_ERR_INVALID_ENCODING,
10520
0
      "Document labelled UTF-16 but has UTF-8 content\n");
10521
0
      }
10522
0
      if (ctxt->encoding != NULL)
10523
0
    xmlFree((xmlChar *) ctxt->encoding);
10524
0
      ctxt->encoding = encoding;
10525
0
  }
10526
  /*
10527
   * UTF-8 encoding is handled natively
10528
   */
10529
0
        else if ((encoding != NULL) &&
10530
0
      ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-8")) ||
10531
0
       (!xmlStrcasecmp(encoding, BAD_CAST "UTF8")))) {
10532
0
      if (ctxt->encoding != NULL)
10533
0
    xmlFree((xmlChar *) ctxt->encoding);
10534
0
      ctxt->encoding = encoding;
10535
0
  }
10536
0
  else if (encoding != NULL) {
10537
0
      xmlCharEncodingHandlerPtr handler;
10538
10539
0
      if (ctxt->input->encoding != NULL)
10540
0
    xmlFree((xmlChar *) ctxt->input->encoding);
10541
0
      ctxt->input->encoding = encoding;
10542
10543
0
            handler = xmlFindCharEncodingHandler((const char *) encoding);
10544
0
      if (handler != NULL) {
10545
0
    if (xmlSwitchToEncoding(ctxt, handler) < 0) {
10546
        /* failed to convert */
10547
0
        ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
10548
0
        return(NULL);
10549
0
    }
10550
0
      } else {
10551
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
10552
0
      "Unsupported encoding %s\n", encoding);
10553
0
    return(NULL);
10554
0
      }
10555
0
  }
10556
0
    }
10557
0
    return(encoding);
10558
0
}
10559
10560
/**
10561
 * xmlParseSDDecl:
10562
 * @ctxt:  an XML parser context
10563
 *
10564
 * DEPRECATED: Internal function, don't use.
10565
 *
10566
 * parse the XML standalone declaration
10567
 *
10568
 * [32] SDDecl ::= S 'standalone' Eq
10569
 *                 (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no')'"'))
10570
 *
10571
 * [ VC: Standalone Document Declaration ]
10572
 * TODO The standalone document declaration must have the value "no"
10573
 * if any external markup declarations contain declarations of:
10574
 *  - attributes with default values, if elements to which these
10575
 *    attributes apply appear in the document without specifications
10576
 *    of values for these attributes, or
10577
 *  - entities (other than amp, lt, gt, apos, quot), if references
10578
 *    to those entities appear in the document, or
10579
 *  - attributes with values subject to normalization, where the
10580
 *    attribute appears in the document with a value which will change
10581
 *    as a result of normalization, or
10582
 *  - element types with element content, if white space occurs directly
10583
 *    within any instance of those types.
10584
 *
10585
 * Returns:
10586
 *   1 if standalone="yes"
10587
 *   0 if standalone="no"
10588
 *  -2 if standalone attribute is missing or invalid
10589
 *    (A standalone value of -2 means that the XML declaration was found,
10590
 *     but no value was specified for the standalone attribute).
10591
 */
10592
10593
int
10594
0
xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
10595
0
    int standalone = -2;
10596
10597
0
    SKIP_BLANKS;
10598
0
    if (CMP10(CUR_PTR, 's', 't', 'a', 'n', 'd', 'a', 'l', 'o', 'n', 'e')) {
10599
0
  SKIP(10);
10600
0
        SKIP_BLANKS;
10601
0
  if (RAW != '=') {
10602
0
      xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10603
0
      return(standalone);
10604
0
        }
10605
0
  NEXT;
10606
0
  SKIP_BLANKS;
10607
0
        if (RAW == '\''){
10608
0
      NEXT;
10609
0
      if ((RAW == 'n') && (NXT(1) == 'o')) {
10610
0
          standalone = 0;
10611
0
                SKIP(2);
10612
0
      } else if ((RAW == 'y') && (NXT(1) == 'e') &&
10613
0
                 (NXT(2) == 's')) {
10614
0
          standalone = 1;
10615
0
    SKIP(3);
10616
0
            } else {
10617
0
    xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
10618
0
      }
10619
0
      if (RAW != '\'') {
10620
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10621
0
      } else
10622
0
          NEXT;
10623
0
  } else if (RAW == '"'){
10624
0
      NEXT;
10625
0
      if ((RAW == 'n') && (NXT(1) == 'o')) {
10626
0
          standalone = 0;
10627
0
    SKIP(2);
10628
0
      } else if ((RAW == 'y') && (NXT(1) == 'e') &&
10629
0
                 (NXT(2) == 's')) {
10630
0
          standalone = 1;
10631
0
                SKIP(3);
10632
0
            } else {
10633
0
    xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
10634
0
      }
10635
0
      if (RAW != '"') {
10636
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10637
0
      } else
10638
0
          NEXT;
10639
0
  } else {
10640
0
      xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10641
0
        }
10642
0
    }
10643
0
    return(standalone);
10644
0
}
10645
10646
/**
10647
 * xmlParseXMLDecl:
10648
 * @ctxt:  an XML parser context
10649
 *
10650
 * DEPRECATED: Internal function, don't use.
10651
 *
10652
 * parse an XML declaration header
10653
 *
10654
 * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
10655
 */
10656
10657
void
10658
0
xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
10659
0
    xmlChar *version;
10660
10661
    /*
10662
     * This value for standalone indicates that the document has an
10663
     * XML declaration but it does not have a standalone attribute.
10664
     * It will be overwritten later if a standalone attribute is found.
10665
     */
10666
0
    ctxt->input->standalone = -2;
10667
10668
    /*
10669
     * We know that '<?xml' is here.
10670
     */
10671
0
    SKIP(5);
10672
10673
0
    if (!IS_BLANK_CH(RAW)) {
10674
0
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
10675
0
                 "Blank needed after '<?xml'\n");
10676
0
    }
10677
0
    SKIP_BLANKS;
10678
10679
    /*
10680
     * We must have the VersionInfo here.
10681
     */
10682
0
    version = xmlParseVersionInfo(ctxt);
10683
0
    if (version == NULL) {
10684
0
  xmlFatalErr(ctxt, XML_ERR_VERSION_MISSING, NULL);
10685
0
    } else {
10686
0
  if (!xmlStrEqual(version, (const xmlChar *) XML_DEFAULT_VERSION)) {
10687
      /*
10688
       * Changed here for XML-1.0 5th edition
10689
       */
10690
0
      if (ctxt->options & XML_PARSE_OLD10) {
10691
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
10692
0
                "Unsupported version '%s'\n",
10693
0
                version);
10694
0
      } else {
10695
0
          if ((version[0] == '1') && ((version[1] == '.'))) {
10696
0
        xmlWarningMsg(ctxt, XML_WAR_UNKNOWN_VERSION,
10697
0
                      "Unsupported version '%s'\n",
10698
0
          version, NULL);
10699
0
    } else {
10700
0
        xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
10701
0
              "Unsupported version '%s'\n",
10702
0
              version);
10703
0
    }
10704
0
      }
10705
0
  }
10706
0
  if (ctxt->version != NULL)
10707
0
      xmlFree((void *) ctxt->version);
10708
0
  ctxt->version = version;
10709
0
    }
10710
10711
    /*
10712
     * We may have the encoding declaration
10713
     */
10714
0
    if (!IS_BLANK_CH(RAW)) {
10715
0
        if ((RAW == '?') && (NXT(1) == '>')) {
10716
0
      SKIP(2);
10717
0
      return;
10718
0
  }
10719
0
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
10720
0
    }
10721
0
    xmlParseEncodingDecl(ctxt);
10722
0
    if ((ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) ||
10723
0
         (ctxt->instate == XML_PARSER_EOF)) {
10724
  /*
10725
   * The XML REC instructs us to stop parsing right here
10726
   */
10727
0
        return;
10728
0
    }
10729
10730
    /*
10731
     * We may have the standalone status.
10732
     */
10733
0
    if ((ctxt->input->encoding != NULL) && (!IS_BLANK_CH(RAW))) {
10734
0
        if ((RAW == '?') && (NXT(1) == '>')) {
10735
0
      SKIP(2);
10736
0
      return;
10737
0
  }
10738
0
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
10739
0
    }
10740
10741
    /*
10742
     * We can grow the input buffer freely at that point
10743
     */
10744
0
    GROW;
10745
10746
0
    SKIP_BLANKS;
10747
0
    ctxt->input->standalone = xmlParseSDDecl(ctxt);
10748
10749
0
    SKIP_BLANKS;
10750
0
    if ((RAW == '?') && (NXT(1) == '>')) {
10751
0
        SKIP(2);
10752
0
    } else if (RAW == '>') {
10753
        /* Deprecated old WD ... */
10754
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
10755
0
  NEXT;
10756
0
    } else {
10757
0
        int c;
10758
10759
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
10760
0
        while ((c = CUR) != 0) {
10761
0
            NEXT;
10762
0
            if (c == '>')
10763
0
                break;
10764
0
        }
10765
0
    }
10766
0
}
10767
10768
/**
10769
 * xmlParseMisc:
10770
 * @ctxt:  an XML parser context
10771
 *
10772
 * DEPRECATED: Internal function, don't use.
10773
 *
10774
 * parse an XML Misc* optional field.
10775
 *
10776
 * [27] Misc ::= Comment | PI |  S
10777
 */
10778
10779
void
10780
7.38k
xmlParseMisc(xmlParserCtxtPtr ctxt) {
10781
11.0k
    while (ctxt->instate != XML_PARSER_EOF) {
10782
11.0k
        SKIP_BLANKS;
10783
11.0k
        GROW;
10784
11.0k
        if ((RAW == '<') && (NXT(1) == '?')) {
10785
3.69k
      xmlParsePI(ctxt);
10786
7.38k
        } else if (CMP4(CUR_PTR, '<', '!', '-', '-')) {
10787
0
      xmlParseComment(ctxt);
10788
7.38k
        } else {
10789
7.38k
            break;
10790
7.38k
        }
10791
11.0k
    }
10792
7.38k
}
10793
10794
/**
10795
 * xmlParseDocument:
10796
 * @ctxt:  an XML parser context
10797
 *
10798
 * parse an XML document (and build a tree if using the standard SAX
10799
 * interface).
10800
 *
10801
 * [1] document ::= prolog element Misc*
10802
 *
10803
 * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
10804
 *
10805
 * Returns 0, -1 in case of error. the parser context is augmented
10806
 *                as a result of the parsing.
10807
 */
10808
10809
int
10810
3.69k
xmlParseDocument(xmlParserCtxtPtr ctxt) {
10811
3.69k
    xmlChar start[4];
10812
3.69k
    xmlCharEncoding enc;
10813
10814
3.69k
    xmlInitParser();
10815
10816
3.69k
    if ((ctxt == NULL) || (ctxt->input == NULL))
10817
0
        return(-1);
10818
10819
3.69k
    GROW;
10820
10821
    /*
10822
     * SAX: detecting the level.
10823
     */
10824
3.69k
    xmlDetectSAX2(ctxt);
10825
10826
    /*
10827
     * SAX: beginning of the document processing.
10828
     */
10829
3.69k
    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
10830
3.69k
        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
10831
3.69k
    if (ctxt->instate == XML_PARSER_EOF)
10832
0
  return(-1);
10833
10834
3.69k
    if ((ctxt->encoding == NULL) &&
10835
3.69k
        ((ctxt->input->end - ctxt->input->cur) >= 4)) {
10836
  /*
10837
   * Get the 4 first bytes and decode the charset
10838
   * if enc != XML_CHAR_ENCODING_NONE
10839
   * plug some encoding conversion routines.
10840
   */
10841
3.69k
  start[0] = RAW;
10842
3.69k
  start[1] = NXT(1);
10843
3.69k
  start[2] = NXT(2);
10844
3.69k
  start[3] = NXT(3);
10845
3.69k
  enc = xmlDetectCharEncoding(&start[0], 4);
10846
3.69k
  if (enc != XML_CHAR_ENCODING_NONE) {
10847
0
      xmlSwitchEncoding(ctxt, enc);
10848
0
  }
10849
3.69k
    }
10850
10851
10852
3.69k
    if (CUR == 0) {
10853
0
  xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
10854
0
  return(-1);
10855
0
    }
10856
10857
    /*
10858
     * Check for the XMLDecl in the Prolog.
10859
     * do not GROW here to avoid the detected encoder to decode more
10860
     * than just the first line, unless the amount of data is really
10861
     * too small to hold "<?xml version="1.0" encoding="foo"
10862
     */
10863
3.69k
    if ((ctxt->input->end - ctxt->input->cur) < 35) {
10864
0
       GROW;
10865
0
    }
10866
3.69k
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
10867
10868
  /*
10869
   * Note that we will switch encoding on the fly.
10870
   */
10871
0
  xmlParseXMLDecl(ctxt);
10872
0
  if ((ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) ||
10873
0
      (ctxt->instate == XML_PARSER_EOF)) {
10874
      /*
10875
       * The XML REC instructs us to stop parsing right here
10876
       */
10877
0
      return(-1);
10878
0
  }
10879
0
  ctxt->standalone = ctxt->input->standalone;
10880
0
  SKIP_BLANKS;
10881
3.69k
    } else {
10882
3.69k
  ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
10883
3.69k
    }
10884
3.69k
    if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
10885
3.69k
        ctxt->sax->startDocument(ctxt->userData);
10886
3.69k
    if (ctxt->instate == XML_PARSER_EOF)
10887
0
  return(-1);
10888
3.69k
    if ((ctxt->myDoc != NULL) && (ctxt->input != NULL) &&
10889
3.69k
        (ctxt->input->buf != NULL) && (ctxt->input->buf->compressed >= 0)) {
10890
0
  ctxt->myDoc->compression = ctxt->input->buf->compressed;
10891
0
    }
10892
10893
    /*
10894
     * The Misc part of the Prolog
10895
     */
10896
3.69k
    xmlParseMisc(ctxt);
10897
10898
    /*
10899
     * Then possibly doc type declaration(s) and more Misc
10900
     * (doctypedecl Misc*)?
10901
     */
10902
3.69k
    GROW;
10903
3.69k
    if (CMP9(CUR_PTR, '<', '!', 'D', 'O', 'C', 'T', 'Y', 'P', 'E')) {
10904
10905
0
  ctxt->inSubset = 1;
10906
0
  xmlParseDocTypeDecl(ctxt);
10907
0
  if (RAW == '[') {
10908
0
      ctxt->instate = XML_PARSER_DTD;
10909
0
      xmlParseInternalSubset(ctxt);
10910
0
      if (ctxt->instate == XML_PARSER_EOF)
10911
0
    return(-1);
10912
0
  }
10913
10914
  /*
10915
   * Create and update the external subset.
10916
   */
10917
0
  ctxt->inSubset = 2;
10918
0
  if ((ctxt->sax != NULL) && (ctxt->sax->externalSubset != NULL) &&
10919
0
      (!ctxt->disableSAX))
10920
0
      ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
10921
0
                                ctxt->extSubSystem, ctxt->extSubURI);
10922
0
  if (ctxt->instate == XML_PARSER_EOF)
10923
0
      return(-1);
10924
0
  ctxt->inSubset = 0;
10925
10926
0
        xmlCleanSpecialAttr(ctxt);
10927
10928
0
  ctxt->instate = XML_PARSER_PROLOG;
10929
0
  xmlParseMisc(ctxt);
10930
0
    }
10931
10932
    /*
10933
     * Time to start parsing the tree itself
10934
     */
10935
3.69k
    GROW;
10936
3.69k
    if (RAW != '<') {
10937
0
  xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
10938
0
           "Start tag expected, '<' not found\n");
10939
3.69k
    } else {
10940
3.69k
  ctxt->instate = XML_PARSER_CONTENT;
10941
3.69k
  xmlParseElement(ctxt);
10942
3.69k
  ctxt->instate = XML_PARSER_EPILOG;
10943
10944
10945
  /*
10946
   * The Misc part at the end
10947
   */
10948
3.69k
  xmlParseMisc(ctxt);
10949
10950
3.69k
  if (RAW != 0) {
10951
0
      xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
10952
0
  }
10953
3.69k
  ctxt->instate = XML_PARSER_EOF;
10954
3.69k
    }
10955
10956
    /*
10957
     * SAX: end of the document processing.
10958
     */
10959
3.69k
    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
10960
3.69k
        ctxt->sax->endDocument(ctxt->userData);
10961
10962
    /*
10963
     * Remove locally kept entity definitions if the tree was not built
10964
     */
10965
3.69k
    if ((ctxt->myDoc != NULL) &&
10966
3.69k
  (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
10967
0
  xmlFreeDoc(ctxt->myDoc);
10968
0
  ctxt->myDoc = NULL;
10969
0
    }
10970
10971
3.69k
    if ((ctxt->wellFormed) && (ctxt->myDoc != NULL)) {
10972
3.69k
        ctxt->myDoc->properties |= XML_DOC_WELLFORMED;
10973
3.69k
  if (ctxt->valid)
10974
3.69k
      ctxt->myDoc->properties |= XML_DOC_DTDVALID;
10975
3.69k
  if (ctxt->nsWellFormed)
10976
3.69k
      ctxt->myDoc->properties |= XML_DOC_NSVALID;
10977
3.69k
  if (ctxt->options & XML_PARSE_OLD10)
10978
0
      ctxt->myDoc->properties |= XML_DOC_OLD10;
10979
3.69k
    }
10980
3.69k
    if (! ctxt->wellFormed) {
10981
0
  ctxt->valid = 0;
10982
0
  return(-1);
10983
0
    }
10984
3.69k
    return(0);
10985
3.69k
}
10986
10987
/**
10988
 * xmlParseExtParsedEnt:
10989
 * @ctxt:  an XML parser context
10990
 *
10991
 * parse a general parsed entity
10992
 * An external general parsed entity is well-formed if it matches the
10993
 * production labeled extParsedEnt.
10994
 *
10995
 * [78] extParsedEnt ::= TextDecl? content
10996
 *
10997
 * Returns 0, -1 in case of error. the parser context is augmented
10998
 *                as a result of the parsing.
10999
 */
11000
11001
int
11002
0
xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) {
11003
0
    xmlChar start[4];
11004
0
    xmlCharEncoding enc;
11005
11006
0
    if ((ctxt == NULL) || (ctxt->input == NULL))
11007
0
        return(-1);
11008
11009
0
    xmlDetectSAX2(ctxt);
11010
11011
0
    GROW;
11012
11013
    /*
11014
     * SAX: beginning of the document processing.
11015
     */
11016
0
    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
11017
0
        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
11018
11019
    /*
11020
     * Get the 4 first bytes and decode the charset
11021
     * if enc != XML_CHAR_ENCODING_NONE
11022
     * plug some encoding conversion routines.
11023
     */
11024
0
    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
11025
0
  start[0] = RAW;
11026
0
  start[1] = NXT(1);
11027
0
  start[2] = NXT(2);
11028
0
  start[3] = NXT(3);
11029
0
  enc = xmlDetectCharEncoding(start, 4);
11030
0
  if (enc != XML_CHAR_ENCODING_NONE) {
11031
0
      xmlSwitchEncoding(ctxt, enc);
11032
0
  }
11033
0
    }
11034
11035
11036
0
    if (CUR == 0) {
11037
0
  xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
11038
0
    }
11039
11040
    /*
11041
     * Check for the XMLDecl in the Prolog.
11042
     */
11043
0
    GROW;
11044
0
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
11045
11046
  /*
11047
   * Note that we will switch encoding on the fly.
11048
   */
11049
0
  xmlParseXMLDecl(ctxt);
11050
0
  if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
11051
      /*
11052
       * The XML REC instructs us to stop parsing right here
11053
       */
11054
0
      return(-1);
11055
0
  }
11056
0
  SKIP_BLANKS;
11057
0
    } else {
11058
0
  ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11059
0
    }
11060
0
    if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
11061
0
        ctxt->sax->startDocument(ctxt->userData);
11062
0
    if (ctxt->instate == XML_PARSER_EOF)
11063
0
  return(-1);
11064
11065
    /*
11066
     * Doing validity checking on chunk doesn't make sense
11067
     */
11068
0
    ctxt->instate = XML_PARSER_CONTENT;
11069
0
    ctxt->validate = 0;
11070
0
    ctxt->loadsubset = 0;
11071
0
    ctxt->depth = 0;
11072
11073
0
    xmlParseContent(ctxt);
11074
0
    if (ctxt->instate == XML_PARSER_EOF)
11075
0
  return(-1);
11076
11077
0
    if ((RAW == '<') && (NXT(1) == '/')) {
11078
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
11079
0
    } else if (RAW != 0) {
11080
0
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
11081
0
    }
11082
11083
    /*
11084
     * SAX: end of the document processing.
11085
     */
11086
0
    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11087
0
        ctxt->sax->endDocument(ctxt->userData);
11088
11089
0
    if (! ctxt->wellFormed) return(-1);
11090
0
    return(0);
11091
0
}
11092
11093
#ifdef LIBXML_PUSH_ENABLED
11094
/************************************************************************
11095
 *                  *
11096
 *    Progressive parsing interfaces        *
11097
 *                  *
11098
 ************************************************************************/
11099
11100
/**
11101
 * xmlParseLookupChar:
11102
 * @ctxt:  an XML parser context
11103
 * @c:  character
11104
 *
11105
 * Check whether the input buffer contains a character.
11106
 */
11107
static int
11108
xmlParseLookupChar(xmlParserCtxtPtr ctxt, int c) {
11109
    const xmlChar *cur;
11110
11111
    if (ctxt->checkIndex == 0) {
11112
        cur = ctxt->input->cur + 1;
11113
    } else {
11114
        cur = ctxt->input->cur + ctxt->checkIndex;
11115
    }
11116
11117
    if (memchr(cur, c, ctxt->input->end - cur) == NULL) {
11118
        ctxt->checkIndex = ctxt->input->end - ctxt->input->cur;
11119
        return(0);
11120
    } else {
11121
        ctxt->checkIndex = 0;
11122
        return(1);
11123
    }
11124
}
11125
11126
/**
11127
 * xmlParseLookupString:
11128
 * @ctxt:  an XML parser context
11129
 * @startDelta: delta to apply at the start
11130
 * @str:  string
11131
 * @strLen:  length of string
11132
 *
11133
 * Check whether the input buffer contains a string.
11134
 */
11135
static const xmlChar *
11136
xmlParseLookupString(xmlParserCtxtPtr ctxt, size_t startDelta,
11137
                     const char *str, size_t strLen) {
11138
    const xmlChar *cur, *term;
11139
11140
    if (ctxt->checkIndex == 0) {
11141
        cur = ctxt->input->cur + startDelta;
11142
    } else {
11143
        cur = ctxt->input->cur + ctxt->checkIndex;
11144
    }
11145
11146
    term = BAD_CAST strstr((const char *) cur, str);
11147
    if (term == NULL) {
11148
        const xmlChar *end = ctxt->input->end;
11149
11150
        /* Rescan (strLen - 1) characters. */
11151
        if ((size_t) (end - cur) < strLen)
11152
            end = cur;
11153
        else
11154
            end -= strLen - 1;
11155
        ctxt->checkIndex = end - ctxt->input->cur;
11156
    } else {
11157
        ctxt->checkIndex = 0;
11158
    }
11159
11160
    return(term);
11161
}
11162
11163
/**
11164
 * xmlParseLookupCharData:
11165
 * @ctxt:  an XML parser context
11166
 *
11167
 * Check whether the input buffer contains terminated char data.
11168
 */
11169
static int
11170
xmlParseLookupCharData(xmlParserCtxtPtr ctxt) {
11171
    const xmlChar *cur = ctxt->input->cur + ctxt->checkIndex;
11172
    const xmlChar *end = ctxt->input->end;
11173
11174
    while (cur < end) {
11175
        if ((*cur == '<') || (*cur == '&')) {
11176
            ctxt->checkIndex = 0;
11177
            return(1);
11178
        }
11179
        cur++;
11180
    }
11181
11182
    ctxt->checkIndex = cur - ctxt->input->cur;
11183
    return(0);
11184
}
11185
11186
/**
11187
 * xmlParseLookupGt:
11188
 * @ctxt:  an XML parser context
11189
 *
11190
 * Check whether there's enough data in the input buffer to finish parsing
11191
 * a start tag. This has to take quotes into account.
11192
 */
11193
static int
11194
xmlParseLookupGt(xmlParserCtxtPtr ctxt) {
11195
    const xmlChar *cur;
11196
    const xmlChar *end = ctxt->input->end;
11197
    int state = ctxt->endCheckState;
11198
11199
    if (ctxt->checkIndex == 0)
11200
        cur = ctxt->input->cur + 1;
11201
    else
11202
        cur = ctxt->input->cur + ctxt->checkIndex;
11203
11204
    while (cur < end) {
11205
        if (state) {
11206
            if (*cur == state)
11207
                state = 0;
11208
        } else if (*cur == '\'' || *cur == '"') {
11209
            state = *cur;
11210
        } else if (*cur == '>') {
11211
            ctxt->checkIndex = 0;
11212
            ctxt->endCheckState = 0;
11213
            return(1);
11214
        }
11215
        cur++;
11216
    }
11217
11218
    ctxt->checkIndex = cur - ctxt->input->cur;
11219
    ctxt->endCheckState = state;
11220
    return(0);
11221
}
11222
11223
/**
11224
 * xmlParseLookupInternalSubset:
11225
 * @ctxt:  an XML parser context
11226
 *
11227
 * Check whether there's enough data in the input buffer to finish parsing
11228
 * the internal subset.
11229
 */
11230
static int
11231
xmlParseLookupInternalSubset(xmlParserCtxtPtr ctxt) {
11232
    /*
11233
     * Sorry, but progressive parsing of the internal subset is not
11234
     * supported. We first check that the full content of the internal
11235
     * subset is available and parsing is launched only at that point.
11236
     * Internal subset ends with "']' S? '>'" in an unescaped section and
11237
     * not in a ']]>' sequence which are conditional sections.
11238
     */
11239
    const xmlChar *cur, *start;
11240
    const xmlChar *end = ctxt->input->end;
11241
    int state = ctxt->endCheckState;
11242
11243
    if (ctxt->checkIndex == 0) {
11244
        cur = ctxt->input->cur + 1;
11245
    } else {
11246
        cur = ctxt->input->cur + ctxt->checkIndex;
11247
    }
11248
    start = cur;
11249
11250
    while (cur < end) {
11251
        if (state == '-') {
11252
            if ((*cur == '-') &&
11253
                (cur[1] == '-') &&
11254
                (cur[2] == '>')) {
11255
                state = 0;
11256
                cur += 3;
11257
                start = cur;
11258
                continue;
11259
            }
11260
        }
11261
        else if (state == ']') {
11262
            if (*cur == '>') {
11263
                ctxt->checkIndex = 0;
11264
                ctxt->endCheckState = 0;
11265
                return(1);
11266
            }
11267
            if (IS_BLANK_CH(*cur)) {
11268
                state = ' ';
11269
            } else if (*cur != ']') {
11270
                state = 0;
11271
                start = cur;
11272
                continue;
11273
            }
11274
        }
11275
        else if (state == ' ') {
11276
            if (*cur == '>') {
11277
                ctxt->checkIndex = 0;
11278
                ctxt->endCheckState = 0;
11279
                return(1);
11280
            }
11281
            if (!IS_BLANK_CH(*cur)) {
11282
                state = 0;
11283
                start = cur;
11284
                continue;
11285
            }
11286
        }
11287
        else if (state != 0) {
11288
            if (*cur == state) {
11289
                state = 0;
11290
                start = cur + 1;
11291
            }
11292
        }
11293
        else if (*cur == '<') {
11294
            if ((cur[1] == '!') &&
11295
                (cur[2] == '-') &&
11296
                (cur[3] == '-')) {
11297
                state = '-';
11298
                cur += 4;
11299
                /* Don't treat <!--> as comment */
11300
                start = cur;
11301
                continue;
11302
            }
11303
        }
11304
        else if ((*cur == '"') || (*cur == '\'') || (*cur == ']')) {
11305
            state = *cur;
11306
        }
11307
11308
        cur++;
11309
    }
11310
11311
    /*
11312
     * Rescan the three last characters to detect "<!--" and "-->"
11313
     * split across chunks.
11314
     */
11315
    if ((state == 0) || (state == '-')) {
11316
        if (cur - start < 3)
11317
            cur = start;
11318
        else
11319
            cur -= 3;
11320
    }
11321
    ctxt->checkIndex = cur - ctxt->input->cur;
11322
    ctxt->endCheckState = state;
11323
    return(0);
11324
}
11325
11326
/**
11327
 * xmlCheckCdataPush:
11328
 * @cur: pointer to the block of characters
11329
 * @len: length of the block in bytes
11330
 * @complete: 1 if complete CDATA block is passed in, 0 if partial block
11331
 *
11332
 * Check that the block of characters is okay as SCdata content [20]
11333
 *
11334
 * Returns the number of bytes to pass if okay, a negative index where an
11335
 *         UTF-8 error occurred otherwise
11336
 */
11337
static int
11338
xmlCheckCdataPush(const xmlChar *utf, int len, int complete) {
11339
    int ix;
11340
    unsigned char c;
11341
    int codepoint;
11342
11343
    if ((utf == NULL) || (len <= 0))
11344
        return(0);
11345
11346
    for (ix = 0; ix < len;) {      /* string is 0-terminated */
11347
        c = utf[ix];
11348
        if ((c & 0x80) == 0x00) { /* 1-byte code, starts with 10 */
11349
      if (c >= 0x20)
11350
    ix++;
11351
      else if ((c == 0xA) || (c == 0xD) || (c == 0x9))
11352
          ix++;
11353
      else
11354
          return(-ix);
11355
  } else if ((c & 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */
11356
      if (ix + 2 > len) return(complete ? -ix : ix);
11357
      if ((utf[ix+1] & 0xc0 ) != 0x80)
11358
          return(-ix);
11359
      codepoint = (utf[ix] & 0x1f) << 6;
11360
      codepoint |= utf[ix+1] & 0x3f;
11361
      if (!xmlIsCharQ(codepoint))
11362
          return(-ix);
11363
      ix += 2;
11364
  } else if ((c & 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */
11365
      if (ix + 3 > len) return(complete ? -ix : ix);
11366
      if (((utf[ix+1] & 0xc0) != 0x80) ||
11367
          ((utf[ix+2] & 0xc0) != 0x80))
11368
        return(-ix);
11369
      codepoint = (utf[ix] & 0xf) << 12;
11370
      codepoint |= (utf[ix+1] & 0x3f) << 6;
11371
      codepoint |= utf[ix+2] & 0x3f;
11372
      if (!xmlIsCharQ(codepoint))
11373
          return(-ix);
11374
      ix += 3;
11375
  } else if ((c & 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */
11376
      if (ix + 4 > len) return(complete ? -ix : ix);
11377
      if (((utf[ix+1] & 0xc0) != 0x80) ||
11378
          ((utf[ix+2] & 0xc0) != 0x80) ||
11379
    ((utf[ix+3] & 0xc0) != 0x80))
11380
        return(-ix);
11381
      codepoint = (utf[ix] & 0x7) << 18;
11382
      codepoint |= (utf[ix+1] & 0x3f) << 12;
11383
      codepoint |= (utf[ix+2] & 0x3f) << 6;
11384
      codepoint |= utf[ix+3] & 0x3f;
11385
      if (!xmlIsCharQ(codepoint))
11386
          return(-ix);
11387
      ix += 4;
11388
  } else        /* unknown encoding */
11389
      return(-ix);
11390
      }
11391
      return(ix);
11392
}
11393
11394
/**
11395
 * xmlParseTryOrFinish:
11396
 * @ctxt:  an XML parser context
11397
 * @terminate:  last chunk indicator
11398
 *
11399
 * Try to progress on parsing
11400
 *
11401
 * Returns zero if no parsing was possible
11402
 */
11403
static int
11404
xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
11405
    int ret = 0;
11406
    int avail, tlen;
11407
    xmlChar cur, next;
11408
11409
    if (ctxt->input == NULL)
11410
        return(0);
11411
11412
#ifdef DEBUG_PUSH
11413
    switch (ctxt->instate) {
11414
  case XML_PARSER_EOF:
11415
      xmlGenericError(xmlGenericErrorContext,
11416
        "PP: try EOF\n"); break;
11417
  case XML_PARSER_START:
11418
      xmlGenericError(xmlGenericErrorContext,
11419
        "PP: try START\n"); break;
11420
  case XML_PARSER_MISC:
11421
      xmlGenericError(xmlGenericErrorContext,
11422
        "PP: try MISC\n");break;
11423
  case XML_PARSER_COMMENT:
11424
      xmlGenericError(xmlGenericErrorContext,
11425
        "PP: try COMMENT\n");break;
11426
  case XML_PARSER_PROLOG:
11427
      xmlGenericError(xmlGenericErrorContext,
11428
        "PP: try PROLOG\n");break;
11429
  case XML_PARSER_START_TAG:
11430
      xmlGenericError(xmlGenericErrorContext,
11431
        "PP: try START_TAG\n");break;
11432
  case XML_PARSER_CONTENT:
11433
      xmlGenericError(xmlGenericErrorContext,
11434
        "PP: try CONTENT\n");break;
11435
  case XML_PARSER_CDATA_SECTION:
11436
      xmlGenericError(xmlGenericErrorContext,
11437
        "PP: try CDATA_SECTION\n");break;
11438
  case XML_PARSER_END_TAG:
11439
      xmlGenericError(xmlGenericErrorContext,
11440
        "PP: try END_TAG\n");break;
11441
  case XML_PARSER_ENTITY_DECL:
11442
      xmlGenericError(xmlGenericErrorContext,
11443
        "PP: try ENTITY_DECL\n");break;
11444
  case XML_PARSER_ENTITY_VALUE:
11445
      xmlGenericError(xmlGenericErrorContext,
11446
        "PP: try ENTITY_VALUE\n");break;
11447
  case XML_PARSER_ATTRIBUTE_VALUE:
11448
      xmlGenericError(xmlGenericErrorContext,
11449
        "PP: try ATTRIBUTE_VALUE\n");break;
11450
  case XML_PARSER_DTD:
11451
      xmlGenericError(xmlGenericErrorContext,
11452
        "PP: try DTD\n");break;
11453
  case XML_PARSER_EPILOG:
11454
      xmlGenericError(xmlGenericErrorContext,
11455
        "PP: try EPILOG\n");break;
11456
  case XML_PARSER_PI:
11457
      xmlGenericError(xmlGenericErrorContext,
11458
        "PP: try PI\n");break;
11459
        case XML_PARSER_IGNORE:
11460
            xmlGenericError(xmlGenericErrorContext,
11461
        "PP: try IGNORE\n");break;
11462
    }
11463
#endif
11464
11465
    if ((ctxt->input != NULL) &&
11466
        (ctxt->input->cur - ctxt->input->base > 4096)) {
11467
        xmlParserInputShrink(ctxt->input);
11468
    }
11469
11470
    while (ctxt->instate != XML_PARSER_EOF) {
11471
  if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
11472
      return(0);
11473
11474
  if (ctxt->input == NULL) break;
11475
  if (ctxt->input->buf == NULL)
11476
      avail = ctxt->input->length -
11477
              (ctxt->input->cur - ctxt->input->base);
11478
  else {
11479
      /*
11480
       * If we are operating on converted input, try to flush
11481
       * remaining chars to avoid them stalling in the non-converted
11482
       * buffer. But do not do this in document start where
11483
       * encoding="..." may not have been read and we work on a
11484
       * guessed encoding.
11485
       */
11486
      if ((ctxt->instate != XML_PARSER_START) &&
11487
          (ctxt->input->buf->raw != NULL) &&
11488
    (xmlBufIsEmpty(ctxt->input->buf->raw) == 0)) {
11489
                size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer,
11490
                                                 ctxt->input);
11491
    size_t current = ctxt->input->cur - ctxt->input->base;
11492
11493
    xmlParserInputBufferPush(ctxt->input->buf, 0, "");
11494
                xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input,
11495
                                      base, current);
11496
      }
11497
      avail = xmlBufUse(ctxt->input->buf->buffer) -
11498
        (ctxt->input->cur - ctxt->input->base);
11499
  }
11500
        if (avail < 1)
11501
      goto done;
11502
        switch (ctxt->instate) {
11503
            case XML_PARSER_EOF:
11504
          /*
11505
     * Document parsing is done !
11506
     */
11507
          goto done;
11508
            case XML_PARSER_START:
11509
    if (ctxt->charset == XML_CHAR_ENCODING_NONE) {
11510
        xmlChar start[4];
11511
        xmlCharEncoding enc;
11512
11513
        /*
11514
         * Very first chars read from the document flow.
11515
         */
11516
        if (avail < 4)
11517
      goto done;
11518
11519
        /*
11520
         * Get the 4 first bytes and decode the charset
11521
         * if enc != XML_CHAR_ENCODING_NONE
11522
         * plug some encoding conversion routines,
11523
         * else xmlSwitchEncoding will set to (default)
11524
         * UTF8.
11525
         */
11526
        start[0] = RAW;
11527
        start[1] = NXT(1);
11528
        start[2] = NXT(2);
11529
        start[3] = NXT(3);
11530
        enc = xmlDetectCharEncoding(start, 4);
11531
        xmlSwitchEncoding(ctxt, enc);
11532
        break;
11533
    }
11534
11535
    if (avail < 2)
11536
        goto done;
11537
    cur = ctxt->input->cur[0];
11538
    next = ctxt->input->cur[1];
11539
    if (cur == 0) {
11540
        if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
11541
      ctxt->sax->setDocumentLocator(ctxt->userData,
11542
                  &xmlDefaultSAXLocator);
11543
        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
11544
        xmlHaltParser(ctxt);
11545
#ifdef DEBUG_PUSH
11546
        xmlGenericError(xmlGenericErrorContext,
11547
          "PP: entering EOF\n");
11548
#endif
11549
        if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11550
      ctxt->sax->endDocument(ctxt->userData);
11551
        goto done;
11552
    }
11553
          if ((cur == '<') && (next == '?')) {
11554
        /* PI or XML decl */
11555
        if (avail < 5) goto done;
11556
        if ((!terminate) &&
11557
                        (!xmlParseLookupString(ctxt, 2, "?>", 2)))
11558
      goto done;
11559
        if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
11560
      ctxt->sax->setDocumentLocator(ctxt->userData,
11561
                  &xmlDefaultSAXLocator);
11562
        if ((ctxt->input->cur[2] == 'x') &&
11563
      (ctxt->input->cur[3] == 'm') &&
11564
      (ctxt->input->cur[4] == 'l') &&
11565
      (IS_BLANK_CH(ctxt->input->cur[5]))) {
11566
      ret += 5;
11567
#ifdef DEBUG_PUSH
11568
      xmlGenericError(xmlGenericErrorContext,
11569
        "PP: Parsing XML Decl\n");
11570
#endif
11571
      xmlParseXMLDecl(ctxt);
11572
      if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
11573
          /*
11574
           * The XML REC instructs us to stop parsing right
11575
           * here
11576
           */
11577
          xmlHaltParser(ctxt);
11578
          return(0);
11579
      }
11580
      ctxt->standalone = ctxt->input->standalone;
11581
      if ((ctxt->encoding == NULL) &&
11582
          (ctxt->input->encoding != NULL))
11583
          ctxt->encoding = xmlStrdup(ctxt->input->encoding);
11584
      if ((ctxt->sax) && (ctxt->sax->startDocument) &&
11585
          (!ctxt->disableSAX))
11586
          ctxt->sax->startDocument(ctxt->userData);
11587
      ctxt->instate = XML_PARSER_MISC;
11588
#ifdef DEBUG_PUSH
11589
      xmlGenericError(xmlGenericErrorContext,
11590
        "PP: entering MISC\n");
11591
#endif
11592
        } else {
11593
      ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11594
      if ((ctxt->sax) && (ctxt->sax->startDocument) &&
11595
          (!ctxt->disableSAX))
11596
          ctxt->sax->startDocument(ctxt->userData);
11597
      ctxt->instate = XML_PARSER_MISC;
11598
#ifdef DEBUG_PUSH
11599
      xmlGenericError(xmlGenericErrorContext,
11600
        "PP: entering MISC\n");
11601
#endif
11602
        }
11603
    } else {
11604
        if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
11605
      ctxt->sax->setDocumentLocator(ctxt->userData,
11606
                  &xmlDefaultSAXLocator);
11607
        ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11608
        if (ctxt->version == NULL) {
11609
            xmlErrMemory(ctxt, NULL);
11610
      break;
11611
        }
11612
        if ((ctxt->sax) && (ctxt->sax->startDocument) &&
11613
            (!ctxt->disableSAX))
11614
      ctxt->sax->startDocument(ctxt->userData);
11615
        ctxt->instate = XML_PARSER_MISC;
11616
#ifdef DEBUG_PUSH
11617
        xmlGenericError(xmlGenericErrorContext,
11618
          "PP: entering MISC\n");
11619
#endif
11620
    }
11621
    break;
11622
            case XML_PARSER_START_TAG: {
11623
          const xmlChar *name;
11624
    const xmlChar *prefix = NULL;
11625
    const xmlChar *URI = NULL;
11626
                int line = ctxt->input->line;
11627
    int nsNr = ctxt->nsNr;
11628
11629
    if ((avail < 2) && (ctxt->inputNr == 1))
11630
        goto done;
11631
    cur = ctxt->input->cur[0];
11632
          if (cur != '<') {
11633
        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
11634
        xmlHaltParser(ctxt);
11635
        if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11636
      ctxt->sax->endDocument(ctxt->userData);
11637
        goto done;
11638
    }
11639
    if ((!terminate) && (!xmlParseLookupGt(ctxt)))
11640
                    goto done;
11641
    if (ctxt->spaceNr == 0)
11642
        spacePush(ctxt, -1);
11643
    else if (*ctxt->space == -2)
11644
        spacePush(ctxt, -1);
11645
    else
11646
        spacePush(ctxt, *ctxt->space);
11647
#ifdef LIBXML_SAX1_ENABLED
11648
    if (ctxt->sax2)
11649
#endif /* LIBXML_SAX1_ENABLED */
11650
        name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
11651
#ifdef LIBXML_SAX1_ENABLED
11652
    else
11653
        name = xmlParseStartTag(ctxt);
11654
#endif /* LIBXML_SAX1_ENABLED */
11655
    if (ctxt->instate == XML_PARSER_EOF)
11656
        goto done;
11657
    if (name == NULL) {
11658
        spacePop(ctxt);
11659
        xmlHaltParser(ctxt);
11660
        if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11661
      ctxt->sax->endDocument(ctxt->userData);
11662
        goto done;
11663
    }
11664
#ifdef LIBXML_VALID_ENABLED
11665
    /*
11666
     * [ VC: Root Element Type ]
11667
     * The Name in the document type declaration must match
11668
     * the element type of the root element.
11669
     */
11670
    if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
11671
        ctxt->node && (ctxt->node == ctxt->myDoc->children))
11672
        ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
11673
#endif /* LIBXML_VALID_ENABLED */
11674
11675
    /*
11676
     * Check for an Empty Element.
11677
     */
11678
    if ((RAW == '/') && (NXT(1) == '>')) {
11679
        SKIP(2);
11680
11681
        if (ctxt->sax2) {
11682
      if ((ctxt->sax != NULL) &&
11683
          (ctxt->sax->endElementNs != NULL) &&
11684
          (!ctxt->disableSAX))
11685
          ctxt->sax->endElementNs(ctxt->userData, name,
11686
                                  prefix, URI);
11687
      if (ctxt->nsNr - nsNr > 0)
11688
          nsPop(ctxt, ctxt->nsNr - nsNr);
11689
#ifdef LIBXML_SAX1_ENABLED
11690
        } else {
11691
      if ((ctxt->sax != NULL) &&
11692
          (ctxt->sax->endElement != NULL) &&
11693
          (!ctxt->disableSAX))
11694
          ctxt->sax->endElement(ctxt->userData, name);
11695
#endif /* LIBXML_SAX1_ENABLED */
11696
        }
11697
        if (ctxt->instate == XML_PARSER_EOF)
11698
      goto done;
11699
        spacePop(ctxt);
11700
        if (ctxt->nameNr == 0) {
11701
      ctxt->instate = XML_PARSER_EPILOG;
11702
        } else {
11703
      ctxt->instate = XML_PARSER_CONTENT;
11704
        }
11705
        break;
11706
    }
11707
    if (RAW == '>') {
11708
        NEXT;
11709
    } else {
11710
        xmlFatalErrMsgStr(ctxt, XML_ERR_GT_REQUIRED,
11711
           "Couldn't find end of Start Tag %s\n",
11712
           name);
11713
        nodePop(ctxt);
11714
        spacePop(ctxt);
11715
    }
11716
                nameNsPush(ctxt, name, prefix, URI, line, ctxt->nsNr - nsNr);
11717
11718
    ctxt->instate = XML_PARSER_CONTENT;
11719
                break;
11720
      }
11721
            case XML_PARSER_CONTENT: {
11722
    if ((avail < 2) && (ctxt->inputNr == 1))
11723
        goto done;
11724
    cur = ctxt->input->cur[0];
11725
    next = ctxt->input->cur[1];
11726
11727
    if ((cur == '<') && (next == '/')) {
11728
        ctxt->instate = XML_PARSER_END_TAG;
11729
        break;
11730
          } else if ((cur == '<') && (next == '?')) {
11731
        if ((!terminate) &&
11732
            (!xmlParseLookupString(ctxt, 2, "?>", 2)))
11733
      goto done;
11734
        xmlParsePI(ctxt);
11735
        ctxt->instate = XML_PARSER_CONTENT;
11736
    } else if ((cur == '<') && (next != '!')) {
11737
        ctxt->instate = XML_PARSER_START_TAG;
11738
        break;
11739
    } else if ((cur == '<') && (next == '!') &&
11740
               (ctxt->input->cur[2] == '-') &&
11741
         (ctxt->input->cur[3] == '-')) {
11742
        if ((!terminate) &&
11743
            (!xmlParseLookupString(ctxt, 4, "-->", 3)))
11744
      goto done;
11745
        xmlParseComment(ctxt);
11746
        ctxt->instate = XML_PARSER_CONTENT;
11747
    } else if ((cur == '<') && (ctxt->input->cur[1] == '!') &&
11748
        (ctxt->input->cur[2] == '[') &&
11749
        (ctxt->input->cur[3] == 'C') &&
11750
        (ctxt->input->cur[4] == 'D') &&
11751
        (ctxt->input->cur[5] == 'A') &&
11752
        (ctxt->input->cur[6] == 'T') &&
11753
        (ctxt->input->cur[7] == 'A') &&
11754
        (ctxt->input->cur[8] == '[')) {
11755
        SKIP(9);
11756
        ctxt->instate = XML_PARSER_CDATA_SECTION;
11757
        break;
11758
    } else if ((cur == '<') && (next == '!') &&
11759
               (avail < 9)) {
11760
        goto done;
11761
    } else if (cur == '<') {
11762
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
11763
                    "detected an error in element content\n");
11764
                    SKIP(1);
11765
    } else if (cur == '&') {
11766
        if ((!terminate) && (!xmlParseLookupChar(ctxt, ';')))
11767
      goto done;
11768
        xmlParseReference(ctxt);
11769
    } else {
11770
        /* TODO Avoid the extra copy, handle directly !!! */
11771
        /*
11772
         * Goal of the following test is:
11773
         *  - minimize calls to the SAX 'character' callback
11774
         *    when they are mergeable
11775
         *  - handle an problem for isBlank when we only parse
11776
         *    a sequence of blank chars and the next one is
11777
         *    not available to check against '<' presence.
11778
         *  - tries to homogenize the differences in SAX
11779
         *    callbacks between the push and pull versions
11780
         *    of the parser.
11781
         */
11782
        if ((ctxt->inputNr == 1) &&
11783
            (avail < XML_PARSER_BIG_BUFFER_SIZE)) {
11784
      if ((!terminate) && (!xmlParseLookupCharData(ctxt)))
11785
          goto done;
11786
                    }
11787
                    ctxt->checkIndex = 0;
11788
        xmlParseCharData(ctxt, 0);
11789
    }
11790
    break;
11791
      }
11792
            case XML_PARSER_END_TAG:
11793
    if (avail < 2)
11794
        goto done;
11795
    if ((!terminate) && (!xmlParseLookupChar(ctxt, '>')))
11796
        goto done;
11797
    if (ctxt->sax2) {
11798
              xmlParseEndTag2(ctxt, &ctxt->pushTab[ctxt->nameNr - 1]);
11799
        nameNsPop(ctxt);
11800
    }
11801
#ifdef LIBXML_SAX1_ENABLED
11802
      else
11803
        xmlParseEndTag1(ctxt, 0);
11804
#endif /* LIBXML_SAX1_ENABLED */
11805
    if (ctxt->instate == XML_PARSER_EOF) {
11806
        /* Nothing */
11807
    } else if (ctxt->nameNr == 0) {
11808
        ctxt->instate = XML_PARSER_EPILOG;
11809
    } else {
11810
        ctxt->instate = XML_PARSER_CONTENT;
11811
    }
11812
    break;
11813
            case XML_PARSER_CDATA_SECTION: {
11814
          /*
11815
     * The Push mode need to have the SAX callback for
11816
     * cdataBlock merge back contiguous callbacks.
11817
     */
11818
    const xmlChar *term;
11819
11820
                if (terminate) {
11821
                    /*
11822
                     * Don't call xmlParseLookupString. If 'terminate'
11823
                     * is set, checkIndex is invalid.
11824
                     */
11825
                    term = BAD_CAST strstr((const char *) ctxt->input->cur,
11826
                                           "]]>");
11827
                } else {
11828
        term = xmlParseLookupString(ctxt, 0, "]]>", 3);
11829
                }
11830
11831
    if (term == NULL) {
11832
        int tmp, size;
11833
11834
                    if (terminate) {
11835
                        /* Unfinished CDATA section */
11836
                        size = ctxt->input->end - ctxt->input->cur;
11837
                    } else {
11838
                        if (avail < XML_PARSER_BIG_BUFFER_SIZE + 2)
11839
                            goto done;
11840
                        ctxt->checkIndex = 0;
11841
                        /* XXX: Why don't we pass the full buffer? */
11842
                        size = XML_PARSER_BIG_BUFFER_SIZE;
11843
                    }
11844
                    tmp = xmlCheckCdataPush(ctxt->input->cur, size, 0);
11845
                    if (tmp <= 0) {
11846
                        tmp = -tmp;
11847
                        ctxt->input->cur += tmp;
11848
                        goto encoding_error;
11849
                    }
11850
                    if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
11851
                        if (ctxt->sax->cdataBlock != NULL)
11852
                            ctxt->sax->cdataBlock(ctxt->userData,
11853
                                                  ctxt->input->cur, tmp);
11854
                        else if (ctxt->sax->characters != NULL)
11855
                            ctxt->sax->characters(ctxt->userData,
11856
                                                  ctxt->input->cur, tmp);
11857
                    }
11858
                    if (ctxt->instate == XML_PARSER_EOF)
11859
                        goto done;
11860
                    SKIPL(tmp);
11861
    } else {
11862
                    int base = term - CUR_PTR;
11863
        int tmp;
11864
11865
        tmp = xmlCheckCdataPush(ctxt->input->cur, base, 1);
11866
        if ((tmp < 0) || (tmp != base)) {
11867
      tmp = -tmp;
11868
      ctxt->input->cur += tmp;
11869
      goto encoding_error;
11870
        }
11871
        if ((ctxt->sax != NULL) && (base == 0) &&
11872
            (ctxt->sax->cdataBlock != NULL) &&
11873
            (!ctxt->disableSAX)) {
11874
      /*
11875
       * Special case to provide identical behaviour
11876
       * between pull and push parsers on enpty CDATA
11877
       * sections
11878
       */
11879
       if ((ctxt->input->cur - ctxt->input->base >= 9) &&
11880
           (!strncmp((const char *)&ctxt->input->cur[-9],
11881
                     "<![CDATA[", 9)))
11882
           ctxt->sax->cdataBlock(ctxt->userData,
11883
                                 BAD_CAST "", 0);
11884
        } else if ((ctxt->sax != NULL) && (base > 0) &&
11885
      (!ctxt->disableSAX)) {
11886
      if (ctxt->sax->cdataBlock != NULL)
11887
          ctxt->sax->cdataBlock(ctxt->userData,
11888
              ctxt->input->cur, base);
11889
      else if (ctxt->sax->characters != NULL)
11890
          ctxt->sax->characters(ctxt->userData,
11891
              ctxt->input->cur, base);
11892
        }
11893
        if (ctxt->instate == XML_PARSER_EOF)
11894
      goto done;
11895
        SKIPL(base + 3);
11896
        ctxt->instate = XML_PARSER_CONTENT;
11897
#ifdef DEBUG_PUSH
11898
        xmlGenericError(xmlGenericErrorContext,
11899
          "PP: entering CONTENT\n");
11900
#endif
11901
    }
11902
    break;
11903
      }
11904
            case XML_PARSER_MISC:
11905
            case XML_PARSER_PROLOG:
11906
            case XML_PARSER_EPILOG:
11907
    SKIP_BLANKS;
11908
    if (ctxt->input->buf == NULL)
11909
        avail = ctxt->input->length -
11910
                (ctxt->input->cur - ctxt->input->base);
11911
    else
11912
        avail = xmlBufUse(ctxt->input->buf->buffer) -
11913
                (ctxt->input->cur - ctxt->input->base);
11914
    if (avail < 2)
11915
        goto done;
11916
    cur = ctxt->input->cur[0];
11917
    next = ctxt->input->cur[1];
11918
          if ((cur == '<') && (next == '?')) {
11919
        if ((!terminate) &&
11920
                        (!xmlParseLookupString(ctxt, 2, "?>", 2)))
11921
      goto done;
11922
#ifdef DEBUG_PUSH
11923
        xmlGenericError(xmlGenericErrorContext,
11924
          "PP: Parsing PI\n");
11925
#endif
11926
        xmlParsePI(ctxt);
11927
        if (ctxt->instate == XML_PARSER_EOF)
11928
      goto done;
11929
    } else if ((cur == '<') && (next == '!') &&
11930
        (ctxt->input->cur[2] == '-') &&
11931
        (ctxt->input->cur[3] == '-')) {
11932
        if ((!terminate) &&
11933
                        (!xmlParseLookupString(ctxt, 4, "-->", 3)))
11934
      goto done;
11935
#ifdef DEBUG_PUSH
11936
        xmlGenericError(xmlGenericErrorContext,
11937
          "PP: Parsing Comment\n");
11938
#endif
11939
        xmlParseComment(ctxt);
11940
        if (ctxt->instate == XML_PARSER_EOF)
11941
      goto done;
11942
    } else if ((ctxt->instate == XML_PARSER_MISC) &&
11943
                    (cur == '<') && (next == '!') &&
11944
        (ctxt->input->cur[2] == 'D') &&
11945
        (ctxt->input->cur[3] == 'O') &&
11946
        (ctxt->input->cur[4] == 'C') &&
11947
        (ctxt->input->cur[5] == 'T') &&
11948
        (ctxt->input->cur[6] == 'Y') &&
11949
        (ctxt->input->cur[7] == 'P') &&
11950
        (ctxt->input->cur[8] == 'E')) {
11951
        if ((!terminate) && (!xmlParseLookupGt(ctxt)))
11952
                        goto done;
11953
#ifdef DEBUG_PUSH
11954
        xmlGenericError(xmlGenericErrorContext,
11955
          "PP: Parsing internal subset\n");
11956
#endif
11957
        ctxt->inSubset = 1;
11958
        xmlParseDocTypeDecl(ctxt);
11959
        if (ctxt->instate == XML_PARSER_EOF)
11960
      goto done;
11961
        if (RAW == '[') {
11962
      ctxt->instate = XML_PARSER_DTD;
11963
#ifdef DEBUG_PUSH
11964
      xmlGenericError(xmlGenericErrorContext,
11965
        "PP: entering DTD\n");
11966
#endif
11967
        } else {
11968
      /*
11969
       * Create and update the external subset.
11970
       */
11971
      ctxt->inSubset = 2;
11972
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
11973
          (ctxt->sax->externalSubset != NULL))
11974
          ctxt->sax->externalSubset(ctxt->userData,
11975
            ctxt->intSubName, ctxt->extSubSystem,
11976
            ctxt->extSubURI);
11977
      ctxt->inSubset = 0;
11978
      xmlCleanSpecialAttr(ctxt);
11979
      ctxt->instate = XML_PARSER_PROLOG;
11980
#ifdef DEBUG_PUSH
11981
      xmlGenericError(xmlGenericErrorContext,
11982
        "PP: entering PROLOG\n");
11983
#endif
11984
        }
11985
    } else if ((cur == '<') && (next == '!') &&
11986
               (avail <
11987
                            (ctxt->instate == XML_PARSER_MISC ? 9 : 4))) {
11988
        goto done;
11989
    } else if (ctxt->instate == XML_PARSER_EPILOG) {
11990
        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
11991
        xmlHaltParser(ctxt);
11992
#ifdef DEBUG_PUSH
11993
        xmlGenericError(xmlGenericErrorContext,
11994
          "PP: entering EOF\n");
11995
#endif
11996
        if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11997
      ctxt->sax->endDocument(ctxt->userData);
11998
        goto done;
11999
                } else {
12000
        ctxt->instate = XML_PARSER_START_TAG;
12001
#ifdef DEBUG_PUSH
12002
        xmlGenericError(xmlGenericErrorContext,
12003
          "PP: entering START_TAG\n");
12004
#endif
12005
    }
12006
    break;
12007
            case XML_PARSER_DTD: {
12008
                if ((!terminate) && (!xmlParseLookupInternalSubset(ctxt)))
12009
                    goto done;
12010
    xmlParseInternalSubset(ctxt);
12011
    if (ctxt->instate == XML_PARSER_EOF)
12012
        goto done;
12013
    ctxt->inSubset = 2;
12014
    if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
12015
        (ctxt->sax->externalSubset != NULL))
12016
        ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
12017
          ctxt->extSubSystem, ctxt->extSubURI);
12018
    ctxt->inSubset = 0;
12019
    xmlCleanSpecialAttr(ctxt);
12020
    if (ctxt->instate == XML_PARSER_EOF)
12021
        goto done;
12022
    ctxt->instate = XML_PARSER_PROLOG;
12023
#ifdef DEBUG_PUSH
12024
    xmlGenericError(xmlGenericErrorContext,
12025
      "PP: entering PROLOG\n");
12026
#endif
12027
                break;
12028
      }
12029
            case XML_PARSER_COMMENT:
12030
    xmlGenericError(xmlGenericErrorContext,
12031
      "PP: internal error, state == COMMENT\n");
12032
    ctxt->instate = XML_PARSER_CONTENT;
12033
#ifdef DEBUG_PUSH
12034
    xmlGenericError(xmlGenericErrorContext,
12035
      "PP: entering CONTENT\n");
12036
#endif
12037
    break;
12038
            case XML_PARSER_IGNORE:
12039
    xmlGenericError(xmlGenericErrorContext,
12040
      "PP: internal error, state == IGNORE");
12041
          ctxt->instate = XML_PARSER_DTD;
12042
#ifdef DEBUG_PUSH
12043
    xmlGenericError(xmlGenericErrorContext,
12044
      "PP: entering DTD\n");
12045
#endif
12046
          break;
12047
            case XML_PARSER_PI:
12048
    xmlGenericError(xmlGenericErrorContext,
12049
      "PP: internal error, state == PI\n");
12050
    ctxt->instate = XML_PARSER_CONTENT;
12051
#ifdef DEBUG_PUSH
12052
    xmlGenericError(xmlGenericErrorContext,
12053
      "PP: entering CONTENT\n");
12054
#endif
12055
    break;
12056
            case XML_PARSER_ENTITY_DECL:
12057
    xmlGenericError(xmlGenericErrorContext,
12058
      "PP: internal error, state == ENTITY_DECL\n");
12059
    ctxt->instate = XML_PARSER_DTD;
12060
#ifdef DEBUG_PUSH
12061
    xmlGenericError(xmlGenericErrorContext,
12062
      "PP: entering DTD\n");
12063
#endif
12064
    break;
12065
            case XML_PARSER_ENTITY_VALUE:
12066
    xmlGenericError(xmlGenericErrorContext,
12067
      "PP: internal error, state == ENTITY_VALUE\n");
12068
    ctxt->instate = XML_PARSER_CONTENT;
12069
#ifdef DEBUG_PUSH
12070
    xmlGenericError(xmlGenericErrorContext,
12071
      "PP: entering DTD\n");
12072
#endif
12073
    break;
12074
            case XML_PARSER_ATTRIBUTE_VALUE:
12075
    xmlGenericError(xmlGenericErrorContext,
12076
      "PP: internal error, state == ATTRIBUTE_VALUE\n");
12077
    ctxt->instate = XML_PARSER_START_TAG;
12078
#ifdef DEBUG_PUSH
12079
    xmlGenericError(xmlGenericErrorContext,
12080
      "PP: entering START_TAG\n");
12081
#endif
12082
    break;
12083
            case XML_PARSER_SYSTEM_LITERAL:
12084
    xmlGenericError(xmlGenericErrorContext,
12085
      "PP: internal error, state == SYSTEM_LITERAL\n");
12086
    ctxt->instate = XML_PARSER_START_TAG;
12087
#ifdef DEBUG_PUSH
12088
    xmlGenericError(xmlGenericErrorContext,
12089
      "PP: entering START_TAG\n");
12090
#endif
12091
    break;
12092
            case XML_PARSER_PUBLIC_LITERAL:
12093
    xmlGenericError(xmlGenericErrorContext,
12094
      "PP: internal error, state == PUBLIC_LITERAL\n");
12095
    ctxt->instate = XML_PARSER_START_TAG;
12096
#ifdef DEBUG_PUSH
12097
    xmlGenericError(xmlGenericErrorContext,
12098
      "PP: entering START_TAG\n");
12099
#endif
12100
    break;
12101
  }
12102
    }
12103
done:
12104
#ifdef DEBUG_PUSH
12105
    xmlGenericError(xmlGenericErrorContext, "PP: done %d\n", ret);
12106
#endif
12107
    return(ret);
12108
encoding_error:
12109
    {
12110
        char buffer[150];
12111
12112
  snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
12113
      ctxt->input->cur[0], ctxt->input->cur[1],
12114
      ctxt->input->cur[2], ctxt->input->cur[3]);
12115
  __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
12116
         "Input is not proper UTF-8, indicate encoding !\n%s",
12117
         BAD_CAST buffer, NULL);
12118
    }
12119
    return(0);
12120
}
12121
12122
/**
12123
 * xmlParseChunk:
12124
 * @ctxt:  an XML parser context
12125
 * @chunk:  an char array
12126
 * @size:  the size in byte of the chunk
12127
 * @terminate:  last chunk indicator
12128
 *
12129
 * Parse a Chunk of memory
12130
 *
12131
 * Returns zero if no error, the xmlParserErrors otherwise.
12132
 */
12133
int
12134
xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
12135
              int terminate) {
12136
    int end_in_lf = 0;
12137
    int remain = 0;
12138
12139
    if (ctxt == NULL)
12140
        return(XML_ERR_INTERNAL_ERROR);
12141
    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
12142
        return(ctxt->errNo);
12143
    if (ctxt->instate == XML_PARSER_EOF)
12144
        return(-1);
12145
    if (ctxt->input == NULL)
12146
        return(-1);
12147
12148
    ctxt->progressive = 1;
12149
    if (ctxt->instate == XML_PARSER_START)
12150
        xmlDetectSAX2(ctxt);
12151
    if ((size > 0) && (chunk != NULL) && (!terminate) &&
12152
        (chunk[size - 1] == '\r')) {
12153
  end_in_lf = 1;
12154
  size--;
12155
    }
12156
12157
xmldecl_done:
12158
12159
    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
12160
        (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF))  {
12161
  size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
12162
  size_t cur = ctxt->input->cur - ctxt->input->base;
12163
  int res;
12164
12165
        /*
12166
         * Specific handling if we autodetected an encoding, we should not
12167
         * push more than the first line ... which depend on the encoding
12168
         * And only push the rest once the final encoding was detected
12169
         */
12170
        if ((ctxt->instate == XML_PARSER_START) && (ctxt->input != NULL) &&
12171
            (ctxt->input->buf != NULL) && (ctxt->input->buf->encoder != NULL)) {
12172
            unsigned int len = 45;
12173
12174
            if ((xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
12175
                               BAD_CAST "UTF-16")) ||
12176
                (xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
12177
                               BAD_CAST "UTF16")))
12178
                len = 90;
12179
            else if ((xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
12180
                                    BAD_CAST "UCS-4")) ||
12181
                     (xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
12182
                                    BAD_CAST "UCS4")))
12183
                len = 180;
12184
12185
            if (ctxt->input->buf->rawconsumed < len)
12186
                len -= ctxt->input->buf->rawconsumed;
12187
12188
            /*
12189
             * Change size for reading the initial declaration only
12190
             * if size is greater than len. Otherwise, memmove in xmlBufferAdd
12191
             * will blindly copy extra bytes from memory.
12192
             */
12193
            if ((unsigned int) size > len) {
12194
                remain = size - len;
12195
                size = len;
12196
            } else {
12197
                remain = 0;
12198
            }
12199
        }
12200
  res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
12201
        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
12202
  if (res < 0) {
12203
      ctxt->errNo = XML_PARSER_EOF;
12204
      xmlHaltParser(ctxt);
12205
      return (XML_PARSER_EOF);
12206
  }
12207
#ifdef DEBUG_PUSH
12208
  xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
12209
#endif
12210
12211
    } else if (ctxt->instate != XML_PARSER_EOF) {
12212
  if ((ctxt->input != NULL) && ctxt->input->buf != NULL) {
12213
      xmlParserInputBufferPtr in = ctxt->input->buf;
12214
      if ((in->encoder != NULL) && (in->buffer != NULL) &&
12215
        (in->raw != NULL)) {
12216
    int nbchars;
12217
    size_t base = xmlBufGetInputBase(in->buffer, ctxt->input);
12218
    size_t current = ctxt->input->cur - ctxt->input->base;
12219
12220
    nbchars = xmlCharEncInput(in, terminate);
12221
    xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
12222
    if (nbchars < 0) {
12223
        /* TODO 2.6.0 */
12224
        xmlGenericError(xmlGenericErrorContext,
12225
            "xmlParseChunk: encoder error\n");
12226
                    xmlHaltParser(ctxt);
12227
        return(XML_ERR_INVALID_ENCODING);
12228
    }
12229
      }
12230
  }
12231
    }
12232
12233
    if (remain != 0) {
12234
        xmlParseTryOrFinish(ctxt, 0);
12235
    } else {
12236
        xmlParseTryOrFinish(ctxt, terminate);
12237
    }
12238
    if (ctxt->instate == XML_PARSER_EOF)
12239
        return(ctxt->errNo);
12240
12241
    if ((ctxt->input != NULL) &&
12242
         (((ctxt->input->end - ctxt->input->cur) > XML_MAX_LOOKUP_LIMIT) ||
12243
         ((ctxt->input->cur - ctxt->input->base) > XML_MAX_LOOKUP_LIMIT)) &&
12244
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
12245
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
12246
        xmlHaltParser(ctxt);
12247
    }
12248
    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
12249
        return(ctxt->errNo);
12250
12251
    if (remain != 0) {
12252
        chunk += size;
12253
        size = remain;
12254
        remain = 0;
12255
        goto xmldecl_done;
12256
    }
12257
    if ((end_in_lf == 1) && (ctxt->input != NULL) &&
12258
        (ctxt->input->buf != NULL)) {
12259
  size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer,
12260
           ctxt->input);
12261
  size_t current = ctxt->input->cur - ctxt->input->base;
12262
12263
  xmlParserInputBufferPush(ctxt->input->buf, 1, "\r");
12264
12265
  xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input,
12266
            base, current);
12267
    }
12268
    if (terminate) {
12269
  /*
12270
   * Check for termination
12271
   */
12272
  int cur_avail = 0;
12273
12274
  if (ctxt->input != NULL) {
12275
      if (ctxt->input->buf == NULL)
12276
    cur_avail = ctxt->input->length -
12277
          (ctxt->input->cur - ctxt->input->base);
12278
      else
12279
    cur_avail = xmlBufUse(ctxt->input->buf->buffer) -
12280
                    (ctxt->input->cur - ctxt->input->base);
12281
  }
12282
12283
  if ((ctxt->instate != XML_PARSER_EOF) &&
12284
      (ctxt->instate != XML_PARSER_EPILOG)) {
12285
      xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
12286
  }
12287
  if ((ctxt->instate == XML_PARSER_EPILOG) && (cur_avail > 0)) {
12288
      xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
12289
  }
12290
  if (ctxt->instate != XML_PARSER_EOF) {
12291
      if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
12292
    ctxt->sax->endDocument(ctxt->userData);
12293
  }
12294
  ctxt->instate = XML_PARSER_EOF;
12295
    }
12296
    if (ctxt->wellFormed == 0)
12297
  return((xmlParserErrors) ctxt->errNo);
12298
    else
12299
        return(0);
12300
}
12301
12302
/************************************************************************
12303
 *                  *
12304
 *    I/O front end functions to the parser     *
12305
 *                  *
12306
 ************************************************************************/
12307
12308
/**
12309
 * xmlCreatePushParserCtxt:
12310
 * @sax:  a SAX handler
12311
 * @user_data:  The user data returned on SAX callbacks
12312
 * @chunk:  a pointer to an array of chars
12313
 * @size:  number of chars in the array
12314
 * @filename:  an optional file name or URI
12315
 *
12316
 * Create a parser context for using the XML parser in push mode.
12317
 * If @buffer and @size are non-NULL, the data is used to detect
12318
 * the encoding.  The remaining characters will be parsed so they
12319
 * don't need to be fed in again through xmlParseChunk.
12320
 * To allow content encoding detection, @size should be >= 4
12321
 * The value of @filename is used for fetching external entities
12322
 * and error/warning reports.
12323
 *
12324
 * Returns the new parser context or NULL
12325
 */
12326
12327
xmlParserCtxtPtr
12328
xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
12329
                        const char *chunk, int size, const char *filename) {
12330
    xmlParserCtxtPtr ctxt;
12331
    xmlParserInputPtr inputStream;
12332
    xmlParserInputBufferPtr buf;
12333
    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
12334
12335
    /*
12336
     * plug some encoding conversion routines
12337
     */
12338
    if ((chunk != NULL) && (size >= 4))
12339
  enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
12340
12341
    buf = xmlAllocParserInputBuffer(enc);
12342
    if (buf == NULL) return(NULL);
12343
12344
    ctxt = xmlNewSAXParserCtxt(sax, user_data);
12345
    if (ctxt == NULL) {
12346
        xmlErrMemory(NULL, "creating parser: out of memory\n");
12347
  xmlFreeParserInputBuffer(buf);
12348
  return(NULL);
12349
    }
12350
    ctxt->dictNames = 1;
12351
    if (filename == NULL) {
12352
  ctxt->directory = NULL;
12353
    } else {
12354
        ctxt->directory = xmlParserGetDirectory(filename);
12355
    }
12356
12357
    inputStream = xmlNewInputStream(ctxt);
12358
    if (inputStream == NULL) {
12359
  xmlFreeParserCtxt(ctxt);
12360
  xmlFreeParserInputBuffer(buf);
12361
  return(NULL);
12362
    }
12363
12364
    if (filename == NULL)
12365
  inputStream->filename = NULL;
12366
    else {
12367
  inputStream->filename = (char *)
12368
      xmlCanonicPath((const xmlChar *) filename);
12369
  if (inputStream->filename == NULL) {
12370
            xmlFreeInputStream(inputStream);
12371
      xmlFreeParserCtxt(ctxt);
12372
      xmlFreeParserInputBuffer(buf);
12373
      return(NULL);
12374
  }
12375
    }
12376
    inputStream->buf = buf;
12377
    xmlBufResetInput(inputStream->buf->buffer, inputStream);
12378
    inputPush(ctxt, inputStream);
12379
12380
    /*
12381
     * If the caller didn't provide an initial 'chunk' for determining
12382
     * the encoding, we set the context to XML_CHAR_ENCODING_NONE so
12383
     * that it can be automatically determined later
12384
     */
12385
    ctxt->charset = XML_CHAR_ENCODING_NONE;
12386
12387
    if ((size != 0) && (chunk != NULL) &&
12388
        (ctxt->input != NULL) && (ctxt->input->buf != NULL)) {
12389
  size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
12390
  size_t cur = ctxt->input->cur - ctxt->input->base;
12391
12392
  xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
12393
12394
        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
12395
#ifdef DEBUG_PUSH
12396
  xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
12397
#endif
12398
    }
12399
12400
    if (enc != XML_CHAR_ENCODING_NONE) {
12401
        xmlSwitchEncoding(ctxt, enc);
12402
    }
12403
12404
    return(ctxt);
12405
}
12406
#endif /* LIBXML_PUSH_ENABLED */
12407
12408
/**
12409
 * xmlHaltParser:
12410
 * @ctxt:  an XML parser context
12411
 *
12412
 * Blocks further parser processing don't override error
12413
 * for internal use
12414
 */
12415
static void
12416
0
xmlHaltParser(xmlParserCtxtPtr ctxt) {
12417
0
    if (ctxt == NULL)
12418
0
        return;
12419
0
    ctxt->instate = XML_PARSER_EOF;
12420
0
    ctxt->disableSAX = 1;
12421
0
    while (ctxt->inputNr > 1)
12422
0
        xmlFreeInputStream(inputPop(ctxt));
12423
0
    if (ctxt->input != NULL) {
12424
        /*
12425
   * in case there was a specific allocation deallocate before
12426
   * overriding base
12427
   */
12428
0
        if (ctxt->input->free != NULL) {
12429
0
      ctxt->input->free((xmlChar *) ctxt->input->base);
12430
0
      ctxt->input->free = NULL;
12431
0
  }
12432
0
        if (ctxt->input->buf != NULL) {
12433
0
            xmlFreeParserInputBuffer(ctxt->input->buf);
12434
0
            ctxt->input->buf = NULL;
12435
0
        }
12436
0
  ctxt->input->cur = BAD_CAST"";
12437
0
        ctxt->input->length = 0;
12438
0
  ctxt->input->base = ctxt->input->cur;
12439
0
        ctxt->input->end = ctxt->input->cur;
12440
0
    }
12441
0
}
12442
12443
/**
12444
 * xmlStopParser:
12445
 * @ctxt:  an XML parser context
12446
 *
12447
 * Blocks further parser processing
12448
 */
12449
void
12450
610k
xmlStopParser(xmlParserCtxtPtr ctxt) {
12451
610k
    if (ctxt == NULL)
12452
610k
        return;
12453
0
    xmlHaltParser(ctxt);
12454
0
    ctxt->errNo = XML_ERR_USER_STOP;
12455
0
}
12456
12457
/**
12458
 * xmlCreateIOParserCtxt:
12459
 * @sax:  a SAX handler
12460
 * @user_data:  The user data returned on SAX callbacks
12461
 * @ioread:  an I/O read function
12462
 * @ioclose:  an I/O close function
12463
 * @ioctx:  an I/O handler
12464
 * @enc:  the charset encoding if known
12465
 *
12466
 * Create a parser context for using the XML parser with an existing
12467
 * I/O stream
12468
 *
12469
 * Returns the new parser context or NULL
12470
 */
12471
xmlParserCtxtPtr
12472
xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
12473
  xmlInputReadCallback   ioread, xmlInputCloseCallback  ioclose,
12474
0
  void *ioctx, xmlCharEncoding enc) {
12475
0
    xmlParserCtxtPtr ctxt;
12476
0
    xmlParserInputPtr inputStream;
12477
0
    xmlParserInputBufferPtr buf;
12478
12479
0
    if (ioread == NULL) return(NULL);
12480
12481
0
    buf = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, enc);
12482
0
    if (buf == NULL) {
12483
0
        if (ioclose != NULL)
12484
0
            ioclose(ioctx);
12485
0
        return (NULL);
12486
0
    }
12487
12488
0
    ctxt = xmlNewSAXParserCtxt(sax, user_data);
12489
0
    if (ctxt == NULL) {
12490
0
  xmlFreeParserInputBuffer(buf);
12491
0
  return(NULL);
12492
0
    }
12493
12494
0
    inputStream = xmlNewIOInputStream(ctxt, buf, enc);
12495
0
    if (inputStream == NULL) {
12496
0
  xmlFreeParserCtxt(ctxt);
12497
0
  return(NULL);
12498
0
    }
12499
0
    inputPush(ctxt, inputStream);
12500
12501
0
    return(ctxt);
12502
0
}
12503
12504
#ifdef LIBXML_VALID_ENABLED
12505
/************************************************************************
12506
 *                  *
12507
 *    Front ends when parsing a DTD       *
12508
 *                  *
12509
 ************************************************************************/
12510
12511
/**
12512
 * xmlIOParseDTD:
12513
 * @sax:  the SAX handler block or NULL
12514
 * @input:  an Input Buffer
12515
 * @enc:  the charset encoding if known
12516
 *
12517
 * Load and parse a DTD
12518
 *
12519
 * Returns the resulting xmlDtdPtr or NULL in case of error.
12520
 * @input will be freed by the function in any case.
12521
 */
12522
12523
xmlDtdPtr
12524
xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
12525
        xmlCharEncoding enc) {
12526
    xmlDtdPtr ret = NULL;
12527
    xmlParserCtxtPtr ctxt;
12528
    xmlParserInputPtr pinput = NULL;
12529
    xmlChar start[4];
12530
12531
    if (input == NULL)
12532
  return(NULL);
12533
12534
    ctxt = xmlNewSAXParserCtxt(sax, NULL);
12535
    if (ctxt == NULL) {
12536
        xmlFreeParserInputBuffer(input);
12537
  return(NULL);
12538
    }
12539
12540
    /* We are loading a DTD */
12541
    ctxt->options |= XML_PARSE_DTDLOAD;
12542
12543
    xmlDetectSAX2(ctxt);
12544
12545
    /*
12546
     * generate a parser input from the I/O handler
12547
     */
12548
12549
    pinput = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
12550
    if (pinput == NULL) {
12551
        xmlFreeParserInputBuffer(input);
12552
  xmlFreeParserCtxt(ctxt);
12553
  return(NULL);
12554
    }
12555
12556
    /*
12557
     * plug some encoding conversion routines here.
12558
     */
12559
    if (xmlPushInput(ctxt, pinput) < 0) {
12560
  xmlFreeParserCtxt(ctxt);
12561
  return(NULL);
12562
    }
12563
    if (enc != XML_CHAR_ENCODING_NONE) {
12564
        xmlSwitchEncoding(ctxt, enc);
12565
    }
12566
12567
    pinput->filename = NULL;
12568
    pinput->line = 1;
12569
    pinput->col = 1;
12570
    pinput->base = ctxt->input->cur;
12571
    pinput->cur = ctxt->input->cur;
12572
    pinput->free = NULL;
12573
12574
    /*
12575
     * let's parse that entity knowing it's an external subset.
12576
     */
12577
    ctxt->inSubset = 2;
12578
    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
12579
    if (ctxt->myDoc == NULL) {
12580
  xmlErrMemory(ctxt, "New Doc failed");
12581
  return(NULL);
12582
    }
12583
    ctxt->myDoc->properties = XML_DOC_INTERNAL;
12584
    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
12585
                                 BAD_CAST "none", BAD_CAST "none");
12586
12587
    if ((enc == XML_CHAR_ENCODING_NONE) &&
12588
        ((ctxt->input->end - ctxt->input->cur) >= 4)) {
12589
  /*
12590
   * Get the 4 first bytes and decode the charset
12591
   * if enc != XML_CHAR_ENCODING_NONE
12592
   * plug some encoding conversion routines.
12593
   */
12594
  start[0] = RAW;
12595
  start[1] = NXT(1);
12596
  start[2] = NXT(2);
12597
  start[3] = NXT(3);
12598
  enc = xmlDetectCharEncoding(start, 4);
12599
  if (enc != XML_CHAR_ENCODING_NONE) {
12600
      xmlSwitchEncoding(ctxt, enc);
12601
  }
12602
    }
12603
12604
    xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none");
12605
12606
    if (ctxt->myDoc != NULL) {
12607
  if (ctxt->wellFormed) {
12608
      ret = ctxt->myDoc->extSubset;
12609
      ctxt->myDoc->extSubset = NULL;
12610
      if (ret != NULL) {
12611
    xmlNodePtr tmp;
12612
12613
    ret->doc = NULL;
12614
    tmp = ret->children;
12615
    while (tmp != NULL) {
12616
        tmp->doc = NULL;
12617
        tmp = tmp->next;
12618
    }
12619
      }
12620
  } else {
12621
      ret = NULL;
12622
  }
12623
        xmlFreeDoc(ctxt->myDoc);
12624
        ctxt->myDoc = NULL;
12625
    }
12626
    xmlFreeParserCtxt(ctxt);
12627
12628
    return(ret);
12629
}
12630
12631
/**
12632
 * xmlSAXParseDTD:
12633
 * @sax:  the SAX handler block
12634
 * @ExternalID:  a NAME* containing the External ID of the DTD
12635
 * @SystemID:  a NAME* containing the URL to the DTD
12636
 *
12637
 * DEPRECATED: Don't use.
12638
 *
12639
 * Load and parse an external subset.
12640
 *
12641
 * Returns the resulting xmlDtdPtr or NULL in case of error.
12642
 */
12643
12644
xmlDtdPtr
12645
xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
12646
                          const xmlChar *SystemID) {
12647
    xmlDtdPtr ret = NULL;
12648
    xmlParserCtxtPtr ctxt;
12649
    xmlParserInputPtr input = NULL;
12650
    xmlCharEncoding enc;
12651
    xmlChar* systemIdCanonic;
12652
12653
    if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
12654
12655
    ctxt = xmlNewSAXParserCtxt(sax, NULL);
12656
    if (ctxt == NULL) {
12657
  return(NULL);
12658
    }
12659
12660
    /* We are loading a DTD */
12661
    ctxt->options |= XML_PARSE_DTDLOAD;
12662
12663
    /*
12664
     * Canonicalise the system ID
12665
     */
12666
    systemIdCanonic = xmlCanonicPath(SystemID);
12667
    if ((SystemID != NULL) && (systemIdCanonic == NULL)) {
12668
  xmlFreeParserCtxt(ctxt);
12669
  return(NULL);
12670
    }
12671
12672
    /*
12673
     * Ask the Entity resolver to load the damn thing
12674
     */
12675
12676
    if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
12677
  input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
12678
                                   systemIdCanonic);
12679
    if (input == NULL) {
12680
  xmlFreeParserCtxt(ctxt);
12681
  if (systemIdCanonic != NULL)
12682
      xmlFree(systemIdCanonic);
12683
  return(NULL);
12684
    }
12685
12686
    /*
12687
     * plug some encoding conversion routines here.
12688
     */
12689
    if (xmlPushInput(ctxt, input) < 0) {
12690
  xmlFreeParserCtxt(ctxt);
12691
  if (systemIdCanonic != NULL)
12692
      xmlFree(systemIdCanonic);
12693
  return(NULL);
12694
    }
12695
    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
12696
  enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
12697
  xmlSwitchEncoding(ctxt, enc);
12698
    }
12699
12700
    if (input->filename == NULL)
12701
  input->filename = (char *) systemIdCanonic;
12702
    else
12703
  xmlFree(systemIdCanonic);
12704
    input->line = 1;
12705
    input->col = 1;
12706
    input->base = ctxt->input->cur;
12707
    input->cur = ctxt->input->cur;
12708
    input->free = NULL;
12709
12710
    /*
12711
     * let's parse that entity knowing it's an external subset.
12712
     */
12713
    ctxt->inSubset = 2;
12714
    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
12715
    if (ctxt->myDoc == NULL) {
12716
  xmlErrMemory(ctxt, "New Doc failed");
12717
  xmlFreeParserCtxt(ctxt);
12718
  return(NULL);
12719
    }
12720
    ctxt->myDoc->properties = XML_DOC_INTERNAL;
12721
    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
12722
                                 ExternalID, SystemID);
12723
    xmlParseExternalSubset(ctxt, ExternalID, SystemID);
12724
12725
    if (ctxt->myDoc != NULL) {
12726
  if (ctxt->wellFormed) {
12727
      ret = ctxt->myDoc->extSubset;
12728
      ctxt->myDoc->extSubset = NULL;
12729
      if (ret != NULL) {
12730
    xmlNodePtr tmp;
12731
12732
    ret->doc = NULL;
12733
    tmp = ret->children;
12734
    while (tmp != NULL) {
12735
        tmp->doc = NULL;
12736
        tmp = tmp->next;
12737
    }
12738
      }
12739
  } else {
12740
      ret = NULL;
12741
  }
12742
        xmlFreeDoc(ctxt->myDoc);
12743
        ctxt->myDoc = NULL;
12744
    }
12745
    xmlFreeParserCtxt(ctxt);
12746
12747
    return(ret);
12748
}
12749
12750
12751
/**
12752
 * xmlParseDTD:
12753
 * @ExternalID:  a NAME* containing the External ID of the DTD
12754
 * @SystemID:  a NAME* containing the URL to the DTD
12755
 *
12756
 * Load and parse an external subset.
12757
 *
12758
 * Returns the resulting xmlDtdPtr or NULL in case of error.
12759
 */
12760
12761
xmlDtdPtr
12762
xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
12763
    return(xmlSAXParseDTD(NULL, ExternalID, SystemID));
12764
}
12765
#endif /* LIBXML_VALID_ENABLED */
12766
12767
/************************************************************************
12768
 *                  *
12769
 *    Front ends when parsing an Entity     *
12770
 *                  *
12771
 ************************************************************************/
12772
12773
/**
12774
 * xmlParseCtxtExternalEntity:
12775
 * @ctx:  the existing parsing context
12776
 * @URL:  the URL for the entity to load
12777
 * @ID:  the System ID for the entity to load
12778
 * @lst:  the return value for the set of parsed nodes
12779
 *
12780
 * Parse an external general entity within an existing parsing context
12781
 * An external general parsed entity is well-formed if it matches the
12782
 * production labeled extParsedEnt.
12783
 *
12784
 * [78] extParsedEnt ::= TextDecl? content
12785
 *
12786
 * Returns 0 if the entity is well formed, -1 in case of args problem and
12787
 *    the parser error code otherwise
12788
 */
12789
12790
int
12791
xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
12792
0
                 const xmlChar *ID, xmlNodePtr *lst) {
12793
0
    void *userData;
12794
12795
0
    if (ctx == NULL) return(-1);
12796
    /*
12797
     * If the user provided their own SAX callbacks, then reuse the
12798
     * userData callback field, otherwise the expected setup in a
12799
     * DOM builder is to have userData == ctxt
12800
     */
12801
0
    if (ctx->userData == ctx)
12802
0
        userData = NULL;
12803
0
    else
12804
0
        userData = ctx->userData;
12805
0
    return xmlParseExternalEntityPrivate(ctx->myDoc, ctx, ctx->sax,
12806
0
                                         userData, ctx->depth + 1,
12807
0
                                         URL, ID, lst);
12808
0
}
12809
12810
/**
12811
 * xmlParseExternalEntityPrivate:
12812
 * @doc:  the document the chunk pertains to
12813
 * @oldctxt:  the previous parser context if available
12814
 * @sax:  the SAX handler block (possibly NULL)
12815
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
12816
 * @depth:  Used for loop detection, use 0
12817
 * @URL:  the URL for the entity to load
12818
 * @ID:  the System ID for the entity to load
12819
 * @list:  the return value for the set of parsed nodes
12820
 *
12821
 * Private version of xmlParseExternalEntity()
12822
 *
12823
 * Returns 0 if the entity is well formed, -1 in case of args problem and
12824
 *    the parser error code otherwise
12825
 */
12826
12827
static xmlParserErrors
12828
xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
12829
                xmlSAXHandlerPtr sax,
12830
          void *user_data, int depth, const xmlChar *URL,
12831
0
          const xmlChar *ID, xmlNodePtr *list) {
12832
0
    xmlParserCtxtPtr ctxt;
12833
0
    xmlDocPtr newDoc;
12834
0
    xmlNodePtr newRoot;
12835
0
    xmlParserErrors ret = XML_ERR_OK;
12836
0
    xmlChar start[4];
12837
0
    xmlCharEncoding enc;
12838
12839
0
    if (((depth > 40) &&
12840
0
  ((oldctxt == NULL) || (oldctxt->options & XML_PARSE_HUGE) == 0)) ||
12841
0
  (depth > 100)) {
12842
0
  xmlFatalErrMsg(oldctxt, XML_ERR_ENTITY_LOOP,
12843
0
                       "Maximum entity nesting depth exceeded");
12844
0
        return(XML_ERR_ENTITY_LOOP);
12845
0
    }
12846
12847
0
    if (list != NULL)
12848
0
        *list = NULL;
12849
0
    if ((URL == NULL) && (ID == NULL))
12850
0
  return(XML_ERR_INTERNAL_ERROR);
12851
0
    if (doc == NULL)
12852
0
  return(XML_ERR_INTERNAL_ERROR);
12853
12854
0
    ctxt = xmlCreateEntityParserCtxtInternal(sax, user_data, URL, ID, NULL,
12855
0
                                             oldctxt);
12856
0
    if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
12857
0
    if (oldctxt != NULL) {
12858
0
        ctxt->nbErrors = oldctxt->nbErrors;
12859
0
        ctxt->nbWarnings = oldctxt->nbWarnings;
12860
0
    }
12861
0
    xmlDetectSAX2(ctxt);
12862
12863
0
    newDoc = xmlNewDoc(BAD_CAST "1.0");
12864
0
    if (newDoc == NULL) {
12865
0
  xmlFreeParserCtxt(ctxt);
12866
0
  return(XML_ERR_INTERNAL_ERROR);
12867
0
    }
12868
0
    newDoc->properties = XML_DOC_INTERNAL;
12869
0
    if (doc) {
12870
0
        newDoc->intSubset = doc->intSubset;
12871
0
        newDoc->extSubset = doc->extSubset;
12872
0
        if (doc->dict) {
12873
0
            newDoc->dict = doc->dict;
12874
0
            xmlDictReference(newDoc->dict);
12875
0
        }
12876
0
        if (doc->URL != NULL) {
12877
0
            newDoc->URL = xmlStrdup(doc->URL);
12878
0
        }
12879
0
    }
12880
0
    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
12881
0
    if (newRoot == NULL) {
12882
0
  if (sax != NULL)
12883
0
  xmlFreeParserCtxt(ctxt);
12884
0
  newDoc->intSubset = NULL;
12885
0
  newDoc->extSubset = NULL;
12886
0
        xmlFreeDoc(newDoc);
12887
0
  return(XML_ERR_INTERNAL_ERROR);
12888
0
    }
12889
0
    xmlAddChild((xmlNodePtr) newDoc, newRoot);
12890
0
    nodePush(ctxt, newDoc->children);
12891
0
    if (doc == NULL) {
12892
0
        ctxt->myDoc = newDoc;
12893
0
    } else {
12894
0
        ctxt->myDoc = doc;
12895
0
        newRoot->doc = doc;
12896
0
    }
12897
12898
    /*
12899
     * Get the 4 first bytes and decode the charset
12900
     * if enc != XML_CHAR_ENCODING_NONE
12901
     * plug some encoding conversion routines.
12902
     */
12903
0
    GROW;
12904
0
    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
12905
0
  start[0] = RAW;
12906
0
  start[1] = NXT(1);
12907
0
  start[2] = NXT(2);
12908
0
  start[3] = NXT(3);
12909
0
  enc = xmlDetectCharEncoding(start, 4);
12910
0
  if (enc != XML_CHAR_ENCODING_NONE) {
12911
0
      xmlSwitchEncoding(ctxt, enc);
12912
0
  }
12913
0
    }
12914
12915
    /*
12916
     * Parse a possible text declaration first
12917
     */
12918
0
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
12919
0
  xmlParseTextDecl(ctxt);
12920
        /*
12921
         * An XML-1.0 document can't reference an entity not XML-1.0
12922
         */
12923
0
        if ((xmlStrEqual(oldctxt->version, BAD_CAST "1.0")) &&
12924
0
            (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) {
12925
0
            xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH,
12926
0
                           "Version mismatch between document and entity\n");
12927
0
        }
12928
0
    }
12929
12930
0
    ctxt->instate = XML_PARSER_CONTENT;
12931
0
    ctxt->depth = depth;
12932
0
    if (oldctxt != NULL) {
12933
0
  ctxt->_private = oldctxt->_private;
12934
0
  ctxt->loadsubset = oldctxt->loadsubset;
12935
0
  ctxt->validate = oldctxt->validate;
12936
0
  ctxt->valid = oldctxt->valid;
12937
0
  ctxt->replaceEntities = oldctxt->replaceEntities;
12938
0
        if (oldctxt->validate) {
12939
0
            ctxt->vctxt.error = oldctxt->vctxt.error;
12940
0
            ctxt->vctxt.warning = oldctxt->vctxt.warning;
12941
0
            ctxt->vctxt.userData = oldctxt->vctxt.userData;
12942
0
            ctxt->vctxt.flags = oldctxt->vctxt.flags;
12943
0
        }
12944
0
  ctxt->external = oldctxt->external;
12945
0
        if (ctxt->dict) xmlDictFree(ctxt->dict);
12946
0
        ctxt->dict = oldctxt->dict;
12947
0
        ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
12948
0
        ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
12949
0
        ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
12950
0
        ctxt->dictNames = oldctxt->dictNames;
12951
0
        ctxt->attsDefault = oldctxt->attsDefault;
12952
0
        ctxt->attsSpecial = oldctxt->attsSpecial;
12953
0
        ctxt->linenumbers = oldctxt->linenumbers;
12954
0
  ctxt->record_info = oldctxt->record_info;
12955
0
  ctxt->node_seq.maximum = oldctxt->node_seq.maximum;
12956
0
  ctxt->node_seq.length = oldctxt->node_seq.length;
12957
0
  ctxt->node_seq.buffer = oldctxt->node_seq.buffer;
12958
0
    } else {
12959
  /*
12960
   * Doing validity checking on chunk without context
12961
   * doesn't make sense
12962
   */
12963
0
  ctxt->_private = NULL;
12964
0
  ctxt->validate = 0;
12965
0
  ctxt->external = 2;
12966
0
  ctxt->loadsubset = 0;
12967
0
    }
12968
12969
0
    xmlParseContent(ctxt);
12970
12971
0
    if ((RAW == '<') && (NXT(1) == '/')) {
12972
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
12973
0
    } else if (RAW != 0) {
12974
0
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
12975
0
    }
12976
0
    if (ctxt->node != newDoc->children) {
12977
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
12978
0
    }
12979
12980
0
    if (!ctxt->wellFormed) {
12981
0
  ret = (xmlParserErrors)ctxt->errNo;
12982
0
        if (oldctxt != NULL) {
12983
0
            oldctxt->errNo = ctxt->errNo;
12984
0
            oldctxt->wellFormed = 0;
12985
0
            xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
12986
0
        }
12987
0
    } else {
12988
0
  if (list != NULL) {
12989
0
      xmlNodePtr cur;
12990
12991
      /*
12992
       * Return the newly created nodeset after unlinking it from
12993
       * they pseudo parent.
12994
       */
12995
0
      cur = newDoc->children->children;
12996
0
      *list = cur;
12997
0
      while (cur != NULL) {
12998
0
    cur->parent = NULL;
12999
0
    cur = cur->next;
13000
0
      }
13001
0
            newDoc->children->children = NULL;
13002
0
  }
13003
0
  ret = XML_ERR_OK;
13004
0
    }
13005
13006
    /*
13007
     * Also record the size of the entity parsed
13008
     */
13009
0
    if (ctxt->input != NULL && oldctxt != NULL) {
13010
0
        unsigned long consumed = ctxt->input->consumed;
13011
13012
0
        xmlSaturatedAddSizeT(&consumed, ctxt->input->cur - ctxt->input->base);
13013
13014
0
        xmlSaturatedAdd(&oldctxt->sizeentities, consumed);
13015
0
        xmlSaturatedAdd(&oldctxt->sizeentities, ctxt->sizeentities);
13016
13017
0
        xmlSaturatedAdd(&oldctxt->sizeentcopy, consumed);
13018
0
        xmlSaturatedAdd(&oldctxt->sizeentcopy, ctxt->sizeentcopy);
13019
0
    }
13020
13021
0
    if (oldctxt != NULL) {
13022
0
        ctxt->dict = NULL;
13023
0
        ctxt->attsDefault = NULL;
13024
0
        ctxt->attsSpecial = NULL;
13025
0
        oldctxt->nbErrors = ctxt->nbErrors;
13026
0
        oldctxt->nbWarnings = ctxt->nbWarnings;
13027
0
        oldctxt->validate = ctxt->validate;
13028
0
        oldctxt->valid = ctxt->valid;
13029
0
        oldctxt->node_seq.maximum = ctxt->node_seq.maximum;
13030
0
        oldctxt->node_seq.length = ctxt->node_seq.length;
13031
0
        oldctxt->node_seq.buffer = ctxt->node_seq.buffer;
13032
0
    }
13033
0
    ctxt->node_seq.maximum = 0;
13034
0
    ctxt->node_seq.length = 0;
13035
0
    ctxt->node_seq.buffer = NULL;
13036
0
    xmlFreeParserCtxt(ctxt);
13037
0
    newDoc->intSubset = NULL;
13038
0
    newDoc->extSubset = NULL;
13039
0
    xmlFreeDoc(newDoc);
13040
13041
0
    return(ret);
13042
0
}
13043
13044
#ifdef LIBXML_SAX1_ENABLED
13045
/**
13046
 * xmlParseExternalEntity:
13047
 * @doc:  the document the chunk pertains to
13048
 * @sax:  the SAX handler block (possibly NULL)
13049
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
13050
 * @depth:  Used for loop detection, use 0
13051
 * @URL:  the URL for the entity to load
13052
 * @ID:  the System ID for the entity to load
13053
 * @lst:  the return value for the set of parsed nodes
13054
 *
13055
 * Parse an external general entity
13056
 * An external general parsed entity is well-formed if it matches the
13057
 * production labeled extParsedEnt.
13058
 *
13059
 * [78] extParsedEnt ::= TextDecl? content
13060
 *
13061
 * Returns 0 if the entity is well formed, -1 in case of args problem and
13062
 *    the parser error code otherwise
13063
 */
13064
13065
int
13066
xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data,
13067
    int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *lst) {
13068
    return(xmlParseExternalEntityPrivate(doc, NULL, sax, user_data, depth, URL,
13069
                           ID, lst));
13070
}
13071
13072
/**
13073
 * xmlParseBalancedChunkMemory:
13074
 * @doc:  the document the chunk pertains to (must not be NULL)
13075
 * @sax:  the SAX handler block (possibly NULL)
13076
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
13077
 * @depth:  Used for loop detection, use 0
13078
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
13079
 * @lst:  the return value for the set of parsed nodes
13080
 *
13081
 * Parse a well-balanced chunk of an XML document
13082
 * called by the parser
13083
 * The allowed sequence for the Well Balanced Chunk is the one defined by
13084
 * the content production in the XML grammar:
13085
 *
13086
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13087
 *
13088
 * Returns 0 if the chunk is well balanced, -1 in case of args problem and
13089
 *    the parser error code otherwise
13090
 */
13091
13092
int
13093
xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax,
13094
     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst) {
13095
    return xmlParseBalancedChunkMemoryRecover( doc, sax, user_data,
13096
                                                depth, string, lst, 0 );
13097
}
13098
#endif /* LIBXML_SAX1_ENABLED */
13099
13100
/**
13101
 * xmlParseBalancedChunkMemoryInternal:
13102
 * @oldctxt:  the existing parsing context
13103
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
13104
 * @user_data:  the user data field for the parser context
13105
 * @lst:  the return value for the set of parsed nodes
13106
 *
13107
 *
13108
 * Parse a well-balanced chunk of an XML document
13109
 * called by the parser
13110
 * The allowed sequence for the Well Balanced Chunk is the one defined by
13111
 * the content production in the XML grammar:
13112
 *
13113
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13114
 *
13115
 * Returns XML_ERR_OK if the chunk is well balanced, and the parser
13116
 * error code otherwise
13117
 *
13118
 * In case recover is set to 1, the nodelist will not be empty even if
13119
 * the parsed chunk is not well balanced.
13120
 */
13121
static xmlParserErrors
13122
xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
13123
0
  const xmlChar *string, void *user_data, xmlNodePtr *lst) {
13124
0
    xmlParserCtxtPtr ctxt;
13125
0
    xmlDocPtr newDoc = NULL;
13126
0
    xmlNodePtr newRoot;
13127
0
    xmlSAXHandlerPtr oldsax = NULL;
13128
0
    xmlNodePtr content = NULL;
13129
0
    xmlNodePtr last = NULL;
13130
0
    int size;
13131
0
    xmlParserErrors ret = XML_ERR_OK;
13132
0
#ifdef SAX2
13133
0
    int i;
13134
0
#endif
13135
13136
0
    if (((oldctxt->depth > 40) && ((oldctxt->options & XML_PARSE_HUGE) == 0)) ||
13137
0
        (oldctxt->depth >  100)) {
13138
0
  xmlFatalErrMsg(oldctxt, XML_ERR_ENTITY_LOOP,
13139
0
                       "Maximum entity nesting depth exceeded");
13140
0
  return(XML_ERR_ENTITY_LOOP);
13141
0
    }
13142
13143
13144
0
    if (lst != NULL)
13145
0
        *lst = NULL;
13146
0
    if (string == NULL)
13147
0
        return(XML_ERR_INTERNAL_ERROR);
13148
13149
0
    size = xmlStrlen(string);
13150
13151
0
    ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
13152
0
    if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
13153
0
    ctxt->nbErrors = oldctxt->nbErrors;
13154
0
    ctxt->nbWarnings = oldctxt->nbWarnings;
13155
0
    if (user_data != NULL)
13156
0
  ctxt->userData = user_data;
13157
0
    else
13158
0
  ctxt->userData = ctxt;
13159
0
    if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
13160
0
    ctxt->dict = oldctxt->dict;
13161
0
    ctxt->input_id = oldctxt->input_id;
13162
0
    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
13163
0
    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
13164
0
    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
13165
13166
0
#ifdef SAX2
13167
    /* propagate namespaces down the entity */
13168
0
    for (i = 0;i < oldctxt->nsNr;i += 2) {
13169
0
        nsPush(ctxt, oldctxt->nsTab[i], oldctxt->nsTab[i+1]);
13170
0
    }
13171
0
#endif
13172
13173
0
    oldsax = ctxt->sax;
13174
0
    ctxt->sax = oldctxt->sax;
13175
0
    xmlDetectSAX2(ctxt);
13176
0
    ctxt->replaceEntities = oldctxt->replaceEntities;
13177
0
    ctxt->options = oldctxt->options;
13178
13179
0
    ctxt->_private = oldctxt->_private;
13180
0
    if (oldctxt->myDoc == NULL) {
13181
0
  newDoc = xmlNewDoc(BAD_CAST "1.0");
13182
0
  if (newDoc == NULL) {
13183
0
      ctxt->sax = oldsax;
13184
0
      ctxt->dict = NULL;
13185
0
      xmlFreeParserCtxt(ctxt);
13186
0
      return(XML_ERR_INTERNAL_ERROR);
13187
0
  }
13188
0
  newDoc->properties = XML_DOC_INTERNAL;
13189
0
  newDoc->dict = ctxt->dict;
13190
0
  xmlDictReference(newDoc->dict);
13191
0
  ctxt->myDoc = newDoc;
13192
0
    } else {
13193
0
  ctxt->myDoc = oldctxt->myDoc;
13194
0
        content = ctxt->myDoc->children;
13195
0
  last = ctxt->myDoc->last;
13196
0
    }
13197
0
    newRoot = xmlNewDocNode(ctxt->myDoc, NULL, BAD_CAST "pseudoroot", NULL);
13198
0
    if (newRoot == NULL) {
13199
0
  ctxt->sax = oldsax;
13200
0
  ctxt->dict = NULL;
13201
0
  xmlFreeParserCtxt(ctxt);
13202
0
  if (newDoc != NULL) {
13203
0
      xmlFreeDoc(newDoc);
13204
0
  }
13205
0
  return(XML_ERR_INTERNAL_ERROR);
13206
0
    }
13207
0
    ctxt->myDoc->children = NULL;
13208
0
    ctxt->myDoc->last = NULL;
13209
0
    xmlAddChild((xmlNodePtr) ctxt->myDoc, newRoot);
13210
0
    nodePush(ctxt, ctxt->myDoc->children);
13211
0
    ctxt->instate = XML_PARSER_CONTENT;
13212
0
    ctxt->depth = oldctxt->depth;
13213
13214
0
    ctxt->validate = 0;
13215
0
    ctxt->loadsubset = oldctxt->loadsubset;
13216
0
    if ((oldctxt->validate) || (oldctxt->replaceEntities != 0)) {
13217
  /*
13218
   * ID/IDREF registration will be done in xmlValidateElement below
13219
   */
13220
0
  ctxt->loadsubset |= XML_SKIP_IDS;
13221
0
    }
13222
0
    ctxt->dictNames = oldctxt->dictNames;
13223
0
    ctxt->attsDefault = oldctxt->attsDefault;
13224
0
    ctxt->attsSpecial = oldctxt->attsSpecial;
13225
13226
0
    xmlParseContent(ctxt);
13227
0
    if ((RAW == '<') && (NXT(1) == '/')) {
13228
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13229
0
    } else if (RAW != 0) {
13230
0
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13231
0
    }
13232
0
    if (ctxt->node != ctxt->myDoc->children) {
13233
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13234
0
    }
13235
13236
0
    if (!ctxt->wellFormed) {
13237
0
  ret = (xmlParserErrors)ctxt->errNo;
13238
0
        oldctxt->errNo = ctxt->errNo;
13239
0
        oldctxt->wellFormed = 0;
13240
0
        xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
13241
0
    } else {
13242
0
        ret = XML_ERR_OK;
13243
0
    }
13244
13245
0
    if ((lst != NULL) && (ret == XML_ERR_OK)) {
13246
0
  xmlNodePtr cur;
13247
13248
  /*
13249
   * Return the newly created nodeset after unlinking it from
13250
   * they pseudo parent.
13251
   */
13252
0
  cur = ctxt->myDoc->children->children;
13253
0
  *lst = cur;
13254
0
  while (cur != NULL) {
13255
#ifdef LIBXML_VALID_ENABLED
13256
      if ((oldctxt->validate) && (oldctxt->wellFormed) &&
13257
    (oldctxt->myDoc) && (oldctxt->myDoc->intSubset) &&
13258
    (cur->type == XML_ELEMENT_NODE)) {
13259
    oldctxt->valid &= xmlValidateElement(&oldctxt->vctxt,
13260
      oldctxt->myDoc, cur);
13261
      }
13262
#endif /* LIBXML_VALID_ENABLED */
13263
0
      cur->parent = NULL;
13264
0
      cur = cur->next;
13265
0
  }
13266
0
  ctxt->myDoc->children->children = NULL;
13267
0
    }
13268
0
    if (ctxt->myDoc != NULL) {
13269
0
  xmlFreeNode(ctxt->myDoc->children);
13270
0
        ctxt->myDoc->children = content;
13271
0
        ctxt->myDoc->last = last;
13272
0
    }
13273
13274
    /*
13275
     * Also record the size of the entity parsed
13276
     */
13277
0
    if (ctxt->input != NULL && oldctxt != NULL) {
13278
0
        unsigned long consumed = ctxt->input->consumed;
13279
13280
0
        xmlSaturatedAddSizeT(&consumed, ctxt->input->cur - ctxt->input->base);
13281
13282
0
        xmlSaturatedAdd(&oldctxt->sizeentcopy, consumed);
13283
0
        xmlSaturatedAdd(&oldctxt->sizeentcopy, ctxt->sizeentcopy);
13284
0
    }
13285
13286
0
    oldctxt->nbErrors = ctxt->nbErrors;
13287
0
    oldctxt->nbWarnings = ctxt->nbWarnings;
13288
0
    ctxt->sax = oldsax;
13289
0
    ctxt->dict = NULL;
13290
0
    ctxt->attsDefault = NULL;
13291
0
    ctxt->attsSpecial = NULL;
13292
0
    xmlFreeParserCtxt(ctxt);
13293
0
    if (newDoc != NULL) {
13294
0
  xmlFreeDoc(newDoc);
13295
0
    }
13296
13297
0
    return(ret);
13298
0
}
13299
13300
/**
13301
 * xmlParseInNodeContext:
13302
 * @node:  the context node
13303
 * @data:  the input string
13304
 * @datalen:  the input string length in bytes
13305
 * @options:  a combination of xmlParserOption
13306
 * @lst:  the return value for the set of parsed nodes
13307
 *
13308
 * Parse a well-balanced chunk of an XML document
13309
 * within the context (DTD, namespaces, etc ...) of the given node.
13310
 *
13311
 * The allowed sequence for the data is a Well Balanced Chunk defined by
13312
 * the content production in the XML grammar:
13313
 *
13314
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13315
 *
13316
 * Returns XML_ERR_OK if the chunk is well balanced, and the parser
13317
 * error code otherwise
13318
 */
13319
xmlParserErrors
13320
xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
13321
0
                      int options, xmlNodePtr *lst) {
13322
0
#ifdef SAX2
13323
0
    xmlParserCtxtPtr ctxt;
13324
0
    xmlDocPtr doc = NULL;
13325
0
    xmlNodePtr fake, cur;
13326
0
    int nsnr = 0;
13327
13328
0
    xmlParserErrors ret = XML_ERR_OK;
13329
13330
    /*
13331
     * check all input parameters, grab the document
13332
     */
13333
0
    if ((lst == NULL) || (node == NULL) || (data == NULL) || (datalen < 0))
13334
0
        return(XML_ERR_INTERNAL_ERROR);
13335
0
    switch (node->type) {
13336
0
        case XML_ELEMENT_NODE:
13337
0
        case XML_ATTRIBUTE_NODE:
13338
0
        case XML_TEXT_NODE:
13339
0
        case XML_CDATA_SECTION_NODE:
13340
0
        case XML_ENTITY_REF_NODE:
13341
0
        case XML_PI_NODE:
13342
0
        case XML_COMMENT_NODE:
13343
0
        case XML_DOCUMENT_NODE:
13344
0
        case XML_HTML_DOCUMENT_NODE:
13345
0
      break;
13346
0
  default:
13347
0
      return(XML_ERR_INTERNAL_ERROR);
13348
13349
0
    }
13350
0
    while ((node != NULL) && (node->type != XML_ELEMENT_NODE) &&
13351
0
           (node->type != XML_DOCUMENT_NODE) &&
13352
0
     (node->type != XML_HTML_DOCUMENT_NODE))
13353
0
  node = node->parent;
13354
0
    if (node == NULL)
13355
0
  return(XML_ERR_INTERNAL_ERROR);
13356
0
    if (node->type == XML_ELEMENT_NODE)
13357
0
  doc = node->doc;
13358
0
    else
13359
0
        doc = (xmlDocPtr) node;
13360
0
    if (doc == NULL)
13361
0
  return(XML_ERR_INTERNAL_ERROR);
13362
13363
    /*
13364
     * allocate a context and set-up everything not related to the
13365
     * node position in the tree
13366
     */
13367
0
    if (doc->type == XML_DOCUMENT_NODE)
13368
0
  ctxt = xmlCreateMemoryParserCtxt((char *) data, datalen);
13369
0
#ifdef LIBXML_HTML_ENABLED
13370
0
    else if (doc->type == XML_HTML_DOCUMENT_NODE) {
13371
0
  ctxt = htmlCreateMemoryParserCtxt((char *) data, datalen);
13372
        /*
13373
         * When parsing in context, it makes no sense to add implied
13374
         * elements like html/body/etc...
13375
         */
13376
0
        options |= HTML_PARSE_NOIMPLIED;
13377
0
    }
13378
0
#endif
13379
0
    else
13380
0
        return(XML_ERR_INTERNAL_ERROR);
13381
13382
0
    if (ctxt == NULL)
13383
0
        return(XML_ERR_NO_MEMORY);
13384
13385
    /*
13386
     * Use input doc's dict if present, else assure XML_PARSE_NODICT is set.
13387
     * We need a dictionary for xmlDetectSAX2, so if there's no doc dict
13388
     * we must wait until the last moment to free the original one.
13389
     */
13390
0
    if (doc->dict != NULL) {
13391
0
        if (ctxt->dict != NULL)
13392
0
      xmlDictFree(ctxt->dict);
13393
0
  ctxt->dict = doc->dict;
13394
0
    } else
13395
0
        options |= XML_PARSE_NODICT;
13396
13397
0
    if (doc->encoding != NULL) {
13398
0
        xmlCharEncodingHandlerPtr hdlr;
13399
13400
0
        if (ctxt->encoding != NULL)
13401
0
      xmlFree((xmlChar *) ctxt->encoding);
13402
0
        ctxt->encoding = xmlStrdup((const xmlChar *) doc->encoding);
13403
13404
0
        hdlr = xmlFindCharEncodingHandler((const char *) doc->encoding);
13405
0
        if (hdlr != NULL) {
13406
0
            xmlSwitchToEncoding(ctxt, hdlr);
13407
0
  } else {
13408
0
            return(XML_ERR_UNSUPPORTED_ENCODING);
13409
0
        }
13410
0
    }
13411
13412
0
    xmlCtxtUseOptionsInternal(ctxt, options, NULL);
13413
0
    xmlDetectSAX2(ctxt);
13414
0
    ctxt->myDoc = doc;
13415
    /* parsing in context, i.e. as within existing content */
13416
0
    ctxt->input_id = 2;
13417
0
    ctxt->instate = XML_PARSER_CONTENT;
13418
13419
0
    fake = xmlNewDocComment(node->doc, NULL);
13420
0
    if (fake == NULL) {
13421
0
        xmlFreeParserCtxt(ctxt);
13422
0
  return(XML_ERR_NO_MEMORY);
13423
0
    }
13424
0
    xmlAddChild(node, fake);
13425
13426
0
    if (node->type == XML_ELEMENT_NODE) {
13427
0
  nodePush(ctxt, node);
13428
  /*
13429
   * initialize the SAX2 namespaces stack
13430
   */
13431
0
  cur = node;
13432
0
  while ((cur != NULL) && (cur->type == XML_ELEMENT_NODE)) {
13433
0
      xmlNsPtr ns = cur->nsDef;
13434
0
      const xmlChar *iprefix, *ihref;
13435
13436
0
      while (ns != NULL) {
13437
0
    if (ctxt->dict) {
13438
0
        iprefix = xmlDictLookup(ctxt->dict, ns->prefix, -1);
13439
0
        ihref = xmlDictLookup(ctxt->dict, ns->href, -1);
13440
0
    } else {
13441
0
        iprefix = ns->prefix;
13442
0
        ihref = ns->href;
13443
0
    }
13444
13445
0
          if (xmlGetNamespace(ctxt, iprefix) == NULL) {
13446
0
        nsPush(ctxt, iprefix, ihref);
13447
0
        nsnr++;
13448
0
    }
13449
0
    ns = ns->next;
13450
0
      }
13451
0
      cur = cur->parent;
13452
0
  }
13453
0
    }
13454
13455
0
    if ((ctxt->validate) || (ctxt->replaceEntities != 0)) {
13456
  /*
13457
   * ID/IDREF registration will be done in xmlValidateElement below
13458
   */
13459
0
  ctxt->loadsubset |= XML_SKIP_IDS;
13460
0
    }
13461
13462
0
#ifdef LIBXML_HTML_ENABLED
13463
0
    if (doc->type == XML_HTML_DOCUMENT_NODE)
13464
0
        __htmlParseContent(ctxt);
13465
0
    else
13466
0
#endif
13467
0
  xmlParseContent(ctxt);
13468
13469
0
    nsPop(ctxt, nsnr);
13470
0
    if ((RAW == '<') && (NXT(1) == '/')) {
13471
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13472
0
    } else if (RAW != 0) {
13473
0
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13474
0
    }
13475
0
    if ((ctxt->node != NULL) && (ctxt->node != node)) {
13476
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13477
0
  ctxt->wellFormed = 0;
13478
0
    }
13479
13480
0
    if (!ctxt->wellFormed) {
13481
0
        if (ctxt->errNo == 0)
13482
0
      ret = XML_ERR_INTERNAL_ERROR;
13483
0
  else
13484
0
      ret = (xmlParserErrors)ctxt->errNo;
13485
0
    } else {
13486
0
        ret = XML_ERR_OK;
13487
0
    }
13488
13489
    /*
13490
     * Return the newly created nodeset after unlinking it from
13491
     * the pseudo sibling.
13492
     */
13493
13494
0
    cur = fake->next;
13495
0
    fake->next = NULL;
13496
0
    node->last = fake;
13497
13498
0
    if (cur != NULL) {
13499
0
  cur->prev = NULL;
13500
0
    }
13501
13502
0
    *lst = cur;
13503
13504
0
    while (cur != NULL) {
13505
0
  cur->parent = NULL;
13506
0
  cur = cur->next;
13507
0
    }
13508
13509
0
    xmlUnlinkNode(fake);
13510
0
    xmlFreeNode(fake);
13511
13512
13513
0
    if (ret != XML_ERR_OK) {
13514
0
        xmlFreeNodeList(*lst);
13515
0
  *lst = NULL;
13516
0
    }
13517
13518
0
    if (doc->dict != NULL)
13519
0
        ctxt->dict = NULL;
13520
0
    xmlFreeParserCtxt(ctxt);
13521
13522
0
    return(ret);
13523
#else /* !SAX2 */
13524
    return(XML_ERR_INTERNAL_ERROR);
13525
#endif
13526
0
}
13527
13528
#ifdef LIBXML_SAX1_ENABLED
13529
/**
13530
 * xmlParseBalancedChunkMemoryRecover:
13531
 * @doc:  the document the chunk pertains to (must not be NULL)
13532
 * @sax:  the SAX handler block (possibly NULL)
13533
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
13534
 * @depth:  Used for loop detection, use 0
13535
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
13536
 * @lst:  the return value for the set of parsed nodes
13537
 * @recover: return nodes even if the data is broken (use 0)
13538
 *
13539
 *
13540
 * Parse a well-balanced chunk of an XML document
13541
 * called by the parser
13542
 * The allowed sequence for the Well Balanced Chunk is the one defined by
13543
 * the content production in the XML grammar:
13544
 *
13545
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13546
 *
13547
 * Returns 0 if the chunk is well balanced, -1 in case of args problem and
13548
 *    the parser error code otherwise
13549
 *
13550
 * In case recover is set to 1, the nodelist will not be empty even if
13551
 * the parsed chunk is not well balanced, assuming the parsing succeeded to
13552
 * some extent.
13553
 */
13554
int
13555
xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
13556
     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst,
13557
     int recover) {
13558
    xmlParserCtxtPtr ctxt;
13559
    xmlDocPtr newDoc;
13560
    xmlSAXHandlerPtr oldsax = NULL;
13561
    xmlNodePtr content, newRoot;
13562
    int size;
13563
    int ret = 0;
13564
13565
    if (depth > 40) {
13566
  return(XML_ERR_ENTITY_LOOP);
13567
    }
13568
13569
13570
    if (lst != NULL)
13571
        *lst = NULL;
13572
    if (string == NULL)
13573
        return(-1);
13574
13575
    size = xmlStrlen(string);
13576
13577
    ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
13578
    if (ctxt == NULL) return(-1);
13579
    ctxt->userData = ctxt;
13580
    if (sax != NULL) {
13581
  oldsax = ctxt->sax;
13582
        ctxt->sax = sax;
13583
  if (user_data != NULL)
13584
      ctxt->userData = user_data;
13585
    }
13586
    newDoc = xmlNewDoc(BAD_CAST "1.0");
13587
    if (newDoc == NULL) {
13588
  xmlFreeParserCtxt(ctxt);
13589
  return(-1);
13590
    }
13591
    newDoc->properties = XML_DOC_INTERNAL;
13592
    if ((doc != NULL) && (doc->dict != NULL)) {
13593
        xmlDictFree(ctxt->dict);
13594
  ctxt->dict = doc->dict;
13595
  xmlDictReference(ctxt->dict);
13596
  ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
13597
  ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
13598
  ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
13599
  ctxt->dictNames = 1;
13600
    } else {
13601
  xmlCtxtUseOptionsInternal(ctxt, XML_PARSE_NODICT, NULL);
13602
    }
13603
    /* doc == NULL is only supported for historic reasons */
13604
    if (doc != NULL) {
13605
  newDoc->intSubset = doc->intSubset;
13606
  newDoc->extSubset = doc->extSubset;
13607
    }
13608
    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
13609
    if (newRoot == NULL) {
13610
  if (sax != NULL)
13611
      ctxt->sax = oldsax;
13612
  xmlFreeParserCtxt(ctxt);
13613
  newDoc->intSubset = NULL;
13614
  newDoc->extSubset = NULL;
13615
        xmlFreeDoc(newDoc);
13616
  return(-1);
13617
    }
13618
    xmlAddChild((xmlNodePtr) newDoc, newRoot);
13619
    nodePush(ctxt, newRoot);
13620
    /* doc == NULL is only supported for historic reasons */
13621
    if (doc == NULL) {
13622
  ctxt->myDoc = newDoc;
13623
    } else {
13624
  ctxt->myDoc = newDoc;
13625
  newDoc->children->doc = doc;
13626
  /* Ensure that doc has XML spec namespace */
13627
  xmlSearchNsByHref(doc, (xmlNodePtr)doc, XML_XML_NAMESPACE);
13628
  newDoc->oldNs = doc->oldNs;
13629
    }
13630
    ctxt->instate = XML_PARSER_CONTENT;
13631
    ctxt->input_id = 2;
13632
    ctxt->depth = depth;
13633
13634
    /*
13635
     * Doing validity checking on chunk doesn't make sense
13636
     */
13637
    ctxt->validate = 0;
13638
    ctxt->loadsubset = 0;
13639
    xmlDetectSAX2(ctxt);
13640
13641
    if ( doc != NULL ){
13642
        content = doc->children;
13643
        doc->children = NULL;
13644
        xmlParseContent(ctxt);
13645
        doc->children = content;
13646
    }
13647
    else {
13648
        xmlParseContent(ctxt);
13649
    }
13650
    if ((RAW == '<') && (NXT(1) == '/')) {
13651
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13652
    } else if (RAW != 0) {
13653
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13654
    }
13655
    if (ctxt->node != newDoc->children) {
13656
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13657
    }
13658
13659
    if (!ctxt->wellFormed) {
13660
        if (ctxt->errNo == 0)
13661
      ret = 1;
13662
  else
13663
      ret = ctxt->errNo;
13664
    } else {
13665
      ret = 0;
13666
    }
13667
13668
    if ((lst != NULL) && ((ret == 0) || (recover == 1))) {
13669
  xmlNodePtr cur;
13670
13671
  /*
13672
   * Return the newly created nodeset after unlinking it from
13673
   * they pseudo parent.
13674
   */
13675
  cur = newDoc->children->children;
13676
  *lst = cur;
13677
  while (cur != NULL) {
13678
      xmlSetTreeDoc(cur, doc);
13679
      cur->parent = NULL;
13680
      cur = cur->next;
13681
  }
13682
  newDoc->children->children = NULL;
13683
    }
13684
13685
    if (sax != NULL)
13686
  ctxt->sax = oldsax;
13687
    xmlFreeParserCtxt(ctxt);
13688
    newDoc->intSubset = NULL;
13689
    newDoc->extSubset = NULL;
13690
    /* This leaks the namespace list if doc == NULL */
13691
    newDoc->oldNs = NULL;
13692
    xmlFreeDoc(newDoc);
13693
13694
    return(ret);
13695
}
13696
13697
/**
13698
 * xmlSAXParseEntity:
13699
 * @sax:  the SAX handler block
13700
 * @filename:  the filename
13701
 *
13702
 * DEPRECATED: Don't use.
13703
 *
13704
 * parse an XML external entity out of context and build a tree.
13705
 * It use the given SAX function block to handle the parsing callback.
13706
 * If sax is NULL, fallback to the default DOM tree building routines.
13707
 *
13708
 * [78] extParsedEnt ::= TextDecl? content
13709
 *
13710
 * This correspond to a "Well Balanced" chunk
13711
 *
13712
 * Returns the resulting document tree
13713
 */
13714
13715
xmlDocPtr
13716
xmlSAXParseEntity(xmlSAXHandlerPtr sax, const char *filename) {
13717
    xmlDocPtr ret;
13718
    xmlParserCtxtPtr ctxt;
13719
13720
    ctxt = xmlCreateFileParserCtxt(filename);
13721
    if (ctxt == NULL) {
13722
  return(NULL);
13723
    }
13724
    if (sax != NULL) {
13725
  if (ctxt->sax != NULL)
13726
      xmlFree(ctxt->sax);
13727
        ctxt->sax = sax;
13728
        ctxt->userData = NULL;
13729
    }
13730
13731
    xmlParseExtParsedEnt(ctxt);
13732
13733
    if (ctxt->wellFormed)
13734
  ret = ctxt->myDoc;
13735
    else {
13736
        ret = NULL;
13737
        xmlFreeDoc(ctxt->myDoc);
13738
        ctxt->myDoc = NULL;
13739
    }
13740
    if (sax != NULL)
13741
        ctxt->sax = NULL;
13742
    xmlFreeParserCtxt(ctxt);
13743
13744
    return(ret);
13745
}
13746
13747
/**
13748
 * xmlParseEntity:
13749
 * @filename:  the filename
13750
 *
13751
 * parse an XML external entity out of context and build a tree.
13752
 *
13753
 * [78] extParsedEnt ::= TextDecl? content
13754
 *
13755
 * This correspond to a "Well Balanced" chunk
13756
 *
13757
 * Returns the resulting document tree
13758
 */
13759
13760
xmlDocPtr
13761
xmlParseEntity(const char *filename) {
13762
    return(xmlSAXParseEntity(NULL, filename));
13763
}
13764
#endif /* LIBXML_SAX1_ENABLED */
13765
13766
/**
13767
 * xmlCreateEntityParserCtxtInternal:
13768
 * @URL:  the entity URL
13769
 * @ID:  the entity PUBLIC ID
13770
 * @base:  a possible base for the target URI
13771
 * @pctx:  parser context used to set options on new context
13772
 *
13773
 * Create a parser context for an external entity
13774
 * Automatic support for ZLIB/Compress compressed document is provided
13775
 * by default if found at compile-time.
13776
 *
13777
 * Returns the new parser context or NULL
13778
 */
13779
static xmlParserCtxtPtr
13780
xmlCreateEntityParserCtxtInternal(xmlSAXHandlerPtr sax, void *userData,
13781
        const xmlChar *URL, const xmlChar *ID, const xmlChar *base,
13782
0
        xmlParserCtxtPtr pctx) {
13783
0
    xmlParserCtxtPtr ctxt;
13784
0
    xmlParserInputPtr inputStream;
13785
0
    char *directory = NULL;
13786
0
    xmlChar *uri;
13787
13788
0
    ctxt = xmlNewSAXParserCtxt(sax, userData);
13789
0
    if (ctxt == NULL) {
13790
0
  return(NULL);
13791
0
    }
13792
13793
0
    if (pctx != NULL) {
13794
0
        ctxt->options = pctx->options;
13795
0
        ctxt->_private = pctx->_private;
13796
0
  ctxt->input_id = pctx->input_id;
13797
0
    }
13798
13799
    /* Don't read from stdin. */
13800
0
    if (xmlStrcmp(URL, BAD_CAST "-") == 0)
13801
0
        URL = BAD_CAST "./-";
13802
13803
0
    uri = xmlBuildURI(URL, base);
13804
13805
0
    if (uri == NULL) {
13806
0
  inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
13807
0
  if (inputStream == NULL) {
13808
0
      xmlFreeParserCtxt(ctxt);
13809
0
      return(NULL);
13810
0
  }
13811
13812
0
  inputPush(ctxt, inputStream);
13813
13814
0
  if ((ctxt->directory == NULL) && (directory == NULL))
13815
0
      directory = xmlParserGetDirectory((char *)URL);
13816
0
  if ((ctxt->directory == NULL) && (directory != NULL))
13817
0
      ctxt->directory = directory;
13818
0
    } else {
13819
0
  inputStream = xmlLoadExternalEntity((char *)uri, (char *)ID, ctxt);
13820
0
  if (inputStream == NULL) {
13821
0
      xmlFree(uri);
13822
0
      xmlFreeParserCtxt(ctxt);
13823
0
      return(NULL);
13824
0
  }
13825
13826
0
  inputPush(ctxt, inputStream);
13827
13828
0
  if ((ctxt->directory == NULL) && (directory == NULL))
13829
0
      directory = xmlParserGetDirectory((char *)uri);
13830
0
  if ((ctxt->directory == NULL) && (directory != NULL))
13831
0
      ctxt->directory = directory;
13832
0
  xmlFree(uri);
13833
0
    }
13834
0
    return(ctxt);
13835
0
}
13836
13837
/**
13838
 * xmlCreateEntityParserCtxt:
13839
 * @URL:  the entity URL
13840
 * @ID:  the entity PUBLIC ID
13841
 * @base:  a possible base for the target URI
13842
 *
13843
 * Create a parser context for an external entity
13844
 * Automatic support for ZLIB/Compress compressed document is provided
13845
 * by default if found at compile-time.
13846
 *
13847
 * Returns the new parser context or NULL
13848
 */
13849
xmlParserCtxtPtr
13850
xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID,
13851
0
                    const xmlChar *base) {
13852
0
    return xmlCreateEntityParserCtxtInternal(NULL, NULL, URL, ID, base, NULL);
13853
13854
0
}
13855
13856
/************************************************************************
13857
 *                  *
13858
 *    Front ends when parsing from a file     *
13859
 *                  *
13860
 ************************************************************************/
13861
13862
/**
13863
 * xmlCreateURLParserCtxt:
13864
 * @filename:  the filename or URL
13865
 * @options:  a combination of xmlParserOption
13866
 *
13867
 * Create a parser context for a file or URL content.
13868
 * Automatic support for ZLIB/Compress compressed document is provided
13869
 * by default if found at compile-time and for file accesses
13870
 *
13871
 * Returns the new parser context or NULL
13872
 */
13873
xmlParserCtxtPtr
13874
xmlCreateURLParserCtxt(const char *filename, int options)
13875
3.69k
{
13876
3.69k
    xmlParserCtxtPtr ctxt;
13877
3.69k
    xmlParserInputPtr inputStream;
13878
3.69k
    char *directory = NULL;
13879
13880
3.69k
    ctxt = xmlNewParserCtxt();
13881
3.69k
    if (ctxt == NULL) {
13882
0
  xmlErrMemory(NULL, "cannot allocate parser context");
13883
0
  return(NULL);
13884
0
    }
13885
13886
3.69k
    if (options)
13887
0
  xmlCtxtUseOptionsInternal(ctxt, options, NULL);
13888
3.69k
    ctxt->linenumbers = 1;
13889
13890
3.69k
    inputStream = xmlLoadExternalEntity(filename, NULL, ctxt);
13891
3.69k
    if (inputStream == NULL) {
13892
0
  xmlFreeParserCtxt(ctxt);
13893
0
  return(NULL);
13894
0
    }
13895
13896
3.69k
    inputPush(ctxt, inputStream);
13897
3.69k
    if ((ctxt->directory == NULL) && (directory == NULL))
13898
0
        directory = xmlParserGetDirectory(filename);
13899
3.69k
    if ((ctxt->directory == NULL) && (directory != NULL))
13900
0
        ctxt->directory = directory;
13901
13902
3.69k
    return(ctxt);
13903
3.69k
}
13904
13905
/**
13906
 * xmlCreateFileParserCtxt:
13907
 * @filename:  the filename
13908
 *
13909
 * Create a parser context for a file content.
13910
 * Automatic support for ZLIB/Compress compressed document is provided
13911
 * by default if found at compile-time.
13912
 *
13913
 * Returns the new parser context or NULL
13914
 */
13915
xmlParserCtxtPtr
13916
xmlCreateFileParserCtxt(const char *filename)
13917
0
{
13918
0
    return(xmlCreateURLParserCtxt(filename, 0));
13919
0
}
13920
13921
#ifdef LIBXML_SAX1_ENABLED
13922
/**
13923
 * xmlSAXParseFileWithData:
13924
 * @sax:  the SAX handler block
13925
 * @filename:  the filename
13926
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
13927
 *             documents
13928
 * @data:  the userdata
13929
 *
13930
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadFile.
13931
 *
13932
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
13933
 * compressed document is provided by default if found at compile-time.
13934
 * It use the given SAX function block to handle the parsing callback.
13935
 * If sax is NULL, fallback to the default DOM tree building routines.
13936
 *
13937
 * User data (void *) is stored within the parser context in the
13938
 * context's _private member, so it is available nearly everywhere in libxml
13939
 *
13940
 * Returns the resulting document tree
13941
 */
13942
13943
xmlDocPtr
13944
xmlSAXParseFileWithData(xmlSAXHandlerPtr sax, const char *filename,
13945
                        int recovery, void *data) {
13946
    xmlDocPtr ret;
13947
    xmlParserCtxtPtr ctxt;
13948
13949
    xmlInitParser();
13950
13951
    ctxt = xmlCreateFileParserCtxt(filename);
13952
    if (ctxt == NULL) {
13953
  return(NULL);
13954
    }
13955
    if (sax != NULL) {
13956
  if (ctxt->sax != NULL)
13957
      xmlFree(ctxt->sax);
13958
        ctxt->sax = sax;
13959
    }
13960
    xmlDetectSAX2(ctxt);
13961
    if (data!=NULL) {
13962
  ctxt->_private = data;
13963
    }
13964
13965
    if (ctxt->directory == NULL)
13966
        ctxt->directory = xmlParserGetDirectory(filename);
13967
13968
    ctxt->recovery = recovery;
13969
13970
    xmlParseDocument(ctxt);
13971
13972
    if ((ctxt->wellFormed) || recovery) {
13973
        ret = ctxt->myDoc;
13974
  if ((ret != NULL) && (ctxt->input->buf != NULL)) {
13975
      if (ctxt->input->buf->compressed > 0)
13976
    ret->compression = 9;
13977
      else
13978
    ret->compression = ctxt->input->buf->compressed;
13979
  }
13980
    }
13981
    else {
13982
       ret = NULL;
13983
       xmlFreeDoc(ctxt->myDoc);
13984
       ctxt->myDoc = NULL;
13985
    }
13986
    if (sax != NULL)
13987
        ctxt->sax = NULL;
13988
    xmlFreeParserCtxt(ctxt);
13989
13990
    return(ret);
13991
}
13992
13993
/**
13994
 * xmlSAXParseFile:
13995
 * @sax:  the SAX handler block
13996
 * @filename:  the filename
13997
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
13998
 *             documents
13999
 *
14000
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadFile.
14001
 *
14002
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
14003
 * compressed document is provided by default if found at compile-time.
14004
 * It use the given SAX function block to handle the parsing callback.
14005
 * If sax is NULL, fallback to the default DOM tree building routines.
14006
 *
14007
 * Returns the resulting document tree
14008
 */
14009
14010
xmlDocPtr
14011
xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
14012
                          int recovery) {
14013
    return(xmlSAXParseFileWithData(sax,filename,recovery,NULL));
14014
}
14015
14016
/**
14017
 * xmlRecoverDoc:
14018
 * @cur:  a pointer to an array of xmlChar
14019
 *
14020
 * DEPRECATED: Use xmlReadDoc with XML_PARSE_RECOVER.
14021
 *
14022
 * parse an XML in-memory document and build a tree.
14023
 * In the case the document is not Well Formed, a attempt to build a
14024
 * tree is tried anyway
14025
 *
14026
 * Returns the resulting document tree or NULL in case of failure
14027
 */
14028
14029
xmlDocPtr
14030
xmlRecoverDoc(const xmlChar *cur) {
14031
    return(xmlSAXParseDoc(NULL, cur, 1));
14032
}
14033
14034
/**
14035
 * xmlParseFile:
14036
 * @filename:  the filename
14037
 *
14038
 * DEPRECATED: Use xmlReadFile.
14039
 *
14040
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
14041
 * compressed document is provided by default if found at compile-time.
14042
 *
14043
 * Returns the resulting document tree if the file was wellformed,
14044
 * NULL otherwise.
14045
 */
14046
14047
xmlDocPtr
14048
xmlParseFile(const char *filename) {
14049
    return(xmlSAXParseFile(NULL, filename, 0));
14050
}
14051
14052
/**
14053
 * xmlRecoverFile:
14054
 * @filename:  the filename
14055
 *
14056
 * DEPRECATED: Use xmlReadFile with XML_PARSE_RECOVER.
14057
 *
14058
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
14059
 * compressed document is provided by default if found at compile-time.
14060
 * In the case the document is not Well Formed, it attempts to build
14061
 * a tree anyway
14062
 *
14063
 * Returns the resulting document tree or NULL in case of failure
14064
 */
14065
14066
xmlDocPtr
14067
xmlRecoverFile(const char *filename) {
14068
    return(xmlSAXParseFile(NULL, filename, 1));
14069
}
14070
14071
14072
/**
14073
 * xmlSetupParserForBuffer:
14074
 * @ctxt:  an XML parser context
14075
 * @buffer:  a xmlChar * buffer
14076
 * @filename:  a file name
14077
 *
14078
 * DEPRECATED: Don't use.
14079
 *
14080
 * Setup the parser context to parse a new buffer; Clears any prior
14081
 * contents from the parser context. The buffer parameter must not be
14082
 * NULL, but the filename parameter can be
14083
 */
14084
void
14085
xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
14086
                             const char* filename)
14087
{
14088
    xmlParserInputPtr input;
14089
14090
    if ((ctxt == NULL) || (buffer == NULL))
14091
        return;
14092
14093
    input = xmlNewInputStream(ctxt);
14094
    if (input == NULL) {
14095
        xmlErrMemory(NULL, "parsing new buffer: out of memory\n");
14096
        xmlClearParserCtxt(ctxt);
14097
        return;
14098
    }
14099
14100
    xmlClearParserCtxt(ctxt);
14101
    if (filename != NULL)
14102
        input->filename = (char *) xmlCanonicPath((const xmlChar *)filename);
14103
    input->base = buffer;
14104
    input->cur = buffer;
14105
    input->end = &buffer[xmlStrlen(buffer)];
14106
    inputPush(ctxt, input);
14107
}
14108
14109
/**
14110
 * xmlSAXUserParseFile:
14111
 * @sax:  a SAX handler
14112
 * @user_data:  The user data returned on SAX callbacks
14113
 * @filename:  a file name
14114
 *
14115
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadFile.
14116
 *
14117
 * parse an XML file and call the given SAX handler routines.
14118
 * Automatic support for ZLIB/Compress compressed document is provided
14119
 *
14120
 * Returns 0 in case of success or a error number otherwise
14121
 */
14122
int
14123
xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
14124
                    const char *filename) {
14125
    int ret = 0;
14126
    xmlParserCtxtPtr ctxt;
14127
14128
    ctxt = xmlCreateFileParserCtxt(filename);
14129
    if (ctxt == NULL) return -1;
14130
    if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
14131
  xmlFree(ctxt->sax);
14132
    ctxt->sax = sax;
14133
    xmlDetectSAX2(ctxt);
14134
14135
    if (user_data != NULL)
14136
  ctxt->userData = user_data;
14137
14138
    xmlParseDocument(ctxt);
14139
14140
    if (ctxt->wellFormed)
14141
  ret = 0;
14142
    else {
14143
        if (ctxt->errNo != 0)
14144
      ret = ctxt->errNo;
14145
  else
14146
      ret = -1;
14147
    }
14148
    if (sax != NULL)
14149
  ctxt->sax = NULL;
14150
    if (ctxt->myDoc != NULL) {
14151
        xmlFreeDoc(ctxt->myDoc);
14152
  ctxt->myDoc = NULL;
14153
    }
14154
    xmlFreeParserCtxt(ctxt);
14155
14156
    return ret;
14157
}
14158
#endif /* LIBXML_SAX1_ENABLED */
14159
14160
/************************************************************************
14161
 *                  *
14162
 *    Front ends when parsing from memory     *
14163
 *                  *
14164
 ************************************************************************/
14165
14166
/**
14167
 * xmlCreateMemoryParserCtxt:
14168
 * @buffer:  a pointer to a char array
14169
 * @size:  the size of the array
14170
 *
14171
 * Create a parser context for an XML in-memory document.
14172
 *
14173
 * Returns the new parser context or NULL
14174
 */
14175
xmlParserCtxtPtr
14176
0
xmlCreateMemoryParserCtxt(const char *buffer, int size) {
14177
0
    xmlParserCtxtPtr ctxt;
14178
0
    xmlParserInputPtr input;
14179
0
    xmlParserInputBufferPtr buf;
14180
14181
0
    if (buffer == NULL)
14182
0
  return(NULL);
14183
0
    if (size <= 0)
14184
0
  return(NULL);
14185
14186
0
    ctxt = xmlNewParserCtxt();
14187
0
    if (ctxt == NULL)
14188
0
  return(NULL);
14189
14190
0
    buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
14191
0
    if (buf == NULL) {
14192
0
  xmlFreeParserCtxt(ctxt);
14193
0
  return(NULL);
14194
0
    }
14195
14196
0
    input = xmlNewInputStream(ctxt);
14197
0
    if (input == NULL) {
14198
0
  xmlFreeParserInputBuffer(buf);
14199
0
  xmlFreeParserCtxt(ctxt);
14200
0
  return(NULL);
14201
0
    }
14202
14203
0
    input->filename = NULL;
14204
0
    input->buf = buf;
14205
0
    xmlBufResetInput(input->buf->buffer, input);
14206
14207
0
    inputPush(ctxt, input);
14208
0
    return(ctxt);
14209
0
}
14210
14211
#ifdef LIBXML_SAX1_ENABLED
14212
/**
14213
 * xmlSAXParseMemoryWithData:
14214
 * @sax:  the SAX handler block
14215
 * @buffer:  an pointer to a char array
14216
 * @size:  the size of the array
14217
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14218
 *             documents
14219
 * @data:  the userdata
14220
 *
14221
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadMemory.
14222
 *
14223
 * parse an XML in-memory block and use the given SAX function block
14224
 * to handle the parsing callback. If sax is NULL, fallback to the default
14225
 * DOM tree building routines.
14226
 *
14227
 * User data (void *) is stored within the parser context in the
14228
 * context's _private member, so it is available nearly everywhere in libxml
14229
 *
14230
 * Returns the resulting document tree
14231
 */
14232
14233
xmlDocPtr
14234
xmlSAXParseMemoryWithData(xmlSAXHandlerPtr sax, const char *buffer,
14235
            int size, int recovery, void *data) {
14236
    xmlDocPtr ret;
14237
    xmlParserCtxtPtr ctxt;
14238
14239
    xmlInitParser();
14240
14241
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
14242
    if (ctxt == NULL) return(NULL);
14243
    if (sax != NULL) {
14244
  if (ctxt->sax != NULL)
14245
      xmlFree(ctxt->sax);
14246
        ctxt->sax = sax;
14247
    }
14248
    xmlDetectSAX2(ctxt);
14249
    if (data!=NULL) {
14250
  ctxt->_private=data;
14251
    }
14252
14253
    ctxt->recovery = recovery;
14254
14255
    xmlParseDocument(ctxt);
14256
14257
    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
14258
    else {
14259
       ret = NULL;
14260
       xmlFreeDoc(ctxt->myDoc);
14261
       ctxt->myDoc = NULL;
14262
    }
14263
    if (sax != NULL)
14264
  ctxt->sax = NULL;
14265
    xmlFreeParserCtxt(ctxt);
14266
14267
    return(ret);
14268
}
14269
14270
/**
14271
 * xmlSAXParseMemory:
14272
 * @sax:  the SAX handler block
14273
 * @buffer:  an pointer to a char array
14274
 * @size:  the size of the array
14275
 * @recovery:  work in recovery mode, i.e. tries to read not Well Formed
14276
 *             documents
14277
 *
14278
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadMemory.
14279
 *
14280
 * parse an XML in-memory block and use the given SAX function block
14281
 * to handle the parsing callback. If sax is NULL, fallback to the default
14282
 * DOM tree building routines.
14283
 *
14284
 * Returns the resulting document tree
14285
 */
14286
xmlDocPtr
14287
xmlSAXParseMemory(xmlSAXHandlerPtr sax, const char *buffer,
14288
            int size, int recovery) {
14289
    return xmlSAXParseMemoryWithData(sax, buffer, size, recovery, NULL);
14290
}
14291
14292
/**
14293
 * xmlParseMemory:
14294
 * @buffer:  an pointer to a char array
14295
 * @size:  the size of the array
14296
 *
14297
 * DEPRECATED: Use xmlReadMemory.
14298
 *
14299
 * parse an XML in-memory block and build a tree.
14300
 *
14301
 * Returns the resulting document tree
14302
 */
14303
14304
xmlDocPtr xmlParseMemory(const char *buffer, int size) {
14305
   return(xmlSAXParseMemory(NULL, buffer, size, 0));
14306
}
14307
14308
/**
14309
 * xmlRecoverMemory:
14310
 * @buffer:  an pointer to a char array
14311
 * @size:  the size of the array
14312
 *
14313
 * DEPRECATED: Use xmlReadMemory with XML_PARSE_RECOVER.
14314
 *
14315
 * parse an XML in-memory block and build a tree.
14316
 * In the case the document is not Well Formed, an attempt to
14317
 * build a tree is tried anyway
14318
 *
14319
 * Returns the resulting document tree or NULL in case of error
14320
 */
14321
14322
xmlDocPtr xmlRecoverMemory(const char *buffer, int size) {
14323
   return(xmlSAXParseMemory(NULL, buffer, size, 1));
14324
}
14325
14326
/**
14327
 * xmlSAXUserParseMemory:
14328
 * @sax:  a SAX handler
14329
 * @user_data:  The user data returned on SAX callbacks
14330
 * @buffer:  an in-memory XML document input
14331
 * @size:  the length of the XML document in bytes
14332
 *
14333
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadMemory.
14334
 *
14335
 * parse an XML in-memory buffer and call the given SAX handler routines.
14336
 *
14337
 * Returns 0 in case of success or a error number otherwise
14338
 */
14339
int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
14340
        const char *buffer, int size) {
14341
    int ret = 0;
14342
    xmlParserCtxtPtr ctxt;
14343
14344
    xmlInitParser();
14345
14346
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
14347
    if (ctxt == NULL) return -1;
14348
    if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
14349
        xmlFree(ctxt->sax);
14350
    ctxt->sax = sax;
14351
    xmlDetectSAX2(ctxt);
14352
14353
    if (user_data != NULL)
14354
  ctxt->userData = user_data;
14355
14356
    xmlParseDocument(ctxt);
14357
14358
    if (ctxt->wellFormed)
14359
  ret = 0;
14360
    else {
14361
        if (ctxt->errNo != 0)
14362
      ret = ctxt->errNo;
14363
  else
14364
      ret = -1;
14365
    }
14366
    if (sax != NULL)
14367
        ctxt->sax = NULL;
14368
    if (ctxt->myDoc != NULL) {
14369
        xmlFreeDoc(ctxt->myDoc);
14370
  ctxt->myDoc = NULL;
14371
    }
14372
    xmlFreeParserCtxt(ctxt);
14373
14374
    return ret;
14375
}
14376
#endif /* LIBXML_SAX1_ENABLED */
14377
14378
/**
14379
 * xmlCreateDocParserCtxt:
14380
 * @cur:  a pointer to an array of xmlChar
14381
 *
14382
 * Creates a parser context for an XML in-memory document.
14383
 *
14384
 * Returns the new parser context or NULL
14385
 */
14386
xmlParserCtxtPtr
14387
0
xmlCreateDocParserCtxt(const xmlChar *cur) {
14388
0
    int len;
14389
14390
0
    if (cur == NULL)
14391
0
  return(NULL);
14392
0
    len = xmlStrlen(cur);
14393
0
    return(xmlCreateMemoryParserCtxt((const char *)cur, len));
14394
0
}
14395
14396
#ifdef LIBXML_SAX1_ENABLED
14397
/**
14398
 * xmlSAXParseDoc:
14399
 * @sax:  the SAX handler block
14400
 * @cur:  a pointer to an array of xmlChar
14401
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14402
 *             documents
14403
 *
14404
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadDoc.
14405
 *
14406
 * parse an XML in-memory document and build a tree.
14407
 * It use the given SAX function block to handle the parsing callback.
14408
 * If sax is NULL, fallback to the default DOM tree building routines.
14409
 *
14410
 * Returns the resulting document tree
14411
 */
14412
14413
xmlDocPtr
14414
xmlSAXParseDoc(xmlSAXHandlerPtr sax, const xmlChar *cur, int recovery) {
14415
    xmlDocPtr ret;
14416
    xmlParserCtxtPtr ctxt;
14417
    xmlSAXHandlerPtr oldsax = NULL;
14418
14419
    if (cur == NULL) return(NULL);
14420
14421
14422
    ctxt = xmlCreateDocParserCtxt(cur);
14423
    if (ctxt == NULL) return(NULL);
14424
    if (sax != NULL) {
14425
        oldsax = ctxt->sax;
14426
        ctxt->sax = sax;
14427
        ctxt->userData = NULL;
14428
    }
14429
    xmlDetectSAX2(ctxt);
14430
14431
    xmlParseDocument(ctxt);
14432
    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
14433
    else {
14434
       ret = NULL;
14435
       xmlFreeDoc(ctxt->myDoc);
14436
       ctxt->myDoc = NULL;
14437
    }
14438
    if (sax != NULL)
14439
  ctxt->sax = oldsax;
14440
    xmlFreeParserCtxt(ctxt);
14441
14442
    return(ret);
14443
}
14444
14445
/**
14446
 * xmlParseDoc:
14447
 * @cur:  a pointer to an array of xmlChar
14448
 *
14449
 * DEPRECATED: Use xmlReadDoc.
14450
 *
14451
 * parse an XML in-memory document and build a tree.
14452
 *
14453
 * Returns the resulting document tree
14454
 */
14455
14456
xmlDocPtr
14457
xmlParseDoc(const xmlChar *cur) {
14458
    return(xmlSAXParseDoc(NULL, cur, 0));
14459
}
14460
#endif /* LIBXML_SAX1_ENABLED */
14461
14462
#ifdef LIBXML_LEGACY_ENABLED
14463
/************************************************************************
14464
 *                  *
14465
 *  Specific function to keep track of entities references    *
14466
 *  and used by the XSLT debugger         *
14467
 *                  *
14468
 ************************************************************************/
14469
14470
static xmlEntityReferenceFunc xmlEntityRefFunc = NULL;
14471
14472
/**
14473
 * xmlAddEntityReference:
14474
 * @ent : A valid entity
14475
 * @firstNode : A valid first node for children of entity
14476
 * @lastNode : A valid last node of children entity
14477
 *
14478
 * Notify of a reference to an entity of type XML_EXTERNAL_GENERAL_PARSED_ENTITY
14479
 */
14480
static void
14481
xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
14482
                      xmlNodePtr lastNode)
14483
{
14484
    if (xmlEntityRefFunc != NULL) {
14485
        (*xmlEntityRefFunc) (ent, firstNode, lastNode);
14486
    }
14487
}
14488
14489
14490
/**
14491
 * xmlSetEntityReferenceFunc:
14492
 * @func: A valid function
14493
 *
14494
 * Set the function to call call back when a xml reference has been made
14495
 */
14496
void
14497
xmlSetEntityReferenceFunc(xmlEntityReferenceFunc func)
14498
{
14499
    xmlEntityRefFunc = func;
14500
}
14501
#endif /* LIBXML_LEGACY_ENABLED */
14502
14503
/************************************************************************
14504
 *                  *
14505
 *        Miscellaneous       *
14506
 *                  *
14507
 ************************************************************************/
14508
14509
static int xmlParserInitialized = 0;
14510
14511
/**
14512
 * xmlInitParser:
14513
 *
14514
 * Initialization function for the XML parser.
14515
 * This is not reentrant. Call once before processing in case of
14516
 * use in multithreaded programs.
14517
 */
14518
14519
void
14520
44.5M
xmlInitParser(void) {
14521
    /*
14522
     * Note that the initialization code must not make memory allocations.
14523
     */
14524
44.5M
    if (xmlParserInitialized != 0)
14525
44.5M
  return;
14526
14527
3.69k
#ifdef LIBXML_THREAD_ENABLED
14528
3.69k
    __xmlGlobalInitMutexLock();
14529
3.69k
    if (xmlParserInitialized == 0) {
14530
3.69k
#endif
14531
#if defined(_WIN32) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
14532
        if (xmlFree == free)
14533
            atexit(xmlCleanupParser);
14534
#endif
14535
14536
3.69k
  xmlInitThreadsInternal();
14537
3.69k
  xmlInitGlobalsInternal();
14538
3.69k
  xmlInitMemoryInternal();
14539
3.69k
        __xmlInitializeDict();
14540
3.69k
  xmlInitEncodingInternal();
14541
3.69k
  xmlRegisterDefaultInputCallbacks();
14542
3.69k
#ifdef LIBXML_OUTPUT_ENABLED
14543
3.69k
  xmlRegisterDefaultOutputCallbacks();
14544
3.69k
#endif /* LIBXML_OUTPUT_ENABLED */
14545
3.69k
#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
14546
3.69k
  xmlInitXPathInternal();
14547
3.69k
#endif
14548
3.69k
  xmlParserInitialized = 1;
14549
3.69k
#ifdef LIBXML_THREAD_ENABLED
14550
3.69k
    }
14551
3.69k
    __xmlGlobalInitMutexUnlock();
14552
3.69k
#endif
14553
3.69k
}
14554
14555
/**
14556
 * xmlCleanupParser:
14557
 *
14558
 * This function name is somewhat misleading. It does not clean up
14559
 * parser state, it cleans up memory allocated by the library itself.
14560
 * It is a cleanup function for the XML library. It tries to reclaim all
14561
 * related global memory allocated for the library processing.
14562
 * It doesn't deallocate any document related memory. One should
14563
 * call xmlCleanupParser() only when the process has finished using
14564
 * the library and all XML/HTML documents built with it.
14565
 * See also xmlInitParser() which has the opposite function of preparing
14566
 * the library for operations.
14567
 *
14568
 * WARNING: if your application is multithreaded or has plugin support
14569
 *          calling this may crash the application if another thread or
14570
 *          a plugin is still using libxml2. It's sometimes very hard to
14571
 *          guess if libxml2 is in use in the application, some libraries
14572
 *          or plugins may use it without notice. In case of doubt abstain
14573
 *          from calling this function or do it just before calling exit()
14574
 *          to avoid leak reports from valgrind !
14575
 */
14576
14577
void
14578
0
xmlCleanupParser(void) {
14579
0
    if (!xmlParserInitialized)
14580
0
  return;
14581
14582
0
    xmlCleanupCharEncodingHandlers();
14583
0
#ifdef LIBXML_CATALOG_ENABLED
14584
0
    xmlCatalogCleanup();
14585
0
#endif
14586
0
    xmlCleanupDictInternal();
14587
0
    xmlCleanupInputCallbacks();
14588
0
#ifdef LIBXML_OUTPUT_ENABLED
14589
0
    xmlCleanupOutputCallbacks();
14590
0
#endif
14591
#ifdef LIBXML_SCHEMAS_ENABLED
14592
    xmlSchemaCleanupTypes();
14593
    xmlRelaxNGCleanupTypes();
14594
#endif
14595
0
    xmlCleanupGlobalsInternal();
14596
0
    xmlCleanupThreadsInternal();
14597
0
    xmlCleanupMemoryInternal();
14598
0
    xmlParserInitialized = 0;
14599
0
}
14600
14601
#if defined(HAVE_ATTRIBUTE_DESTRUCTOR) && !defined(LIBXML_STATIC) && \
14602
    !defined(_WIN32)
14603
static void
14604
ATTRIBUTE_DESTRUCTOR
14605
0
xmlDestructor(void) {
14606
    /*
14607
     * Calling custom deallocation functions in a destructor can cause
14608
     * problems, for example with Nokogiri.
14609
     */
14610
0
    if (xmlFree == free)
14611
0
        xmlCleanupParser();
14612
0
}
14613
#endif
14614
14615
/************************************************************************
14616
 *                  *
14617
 *  New set (2.6.0) of simpler and more flexible APIs   *
14618
 *                  *
14619
 ************************************************************************/
14620
14621
/**
14622
 * DICT_FREE:
14623
 * @str:  a string
14624
 *
14625
 * Free a string if it is not owned by the "dict" dictionary in the
14626
 * current scope
14627
 */
14628
#define DICT_FREE(str)            \
14629
0
  if ((str) && ((!dict) ||       \
14630
0
      (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))  \
14631
0
      xmlFree((char *)(str));
14632
14633
/**
14634
 * xmlCtxtReset:
14635
 * @ctxt: an XML parser context
14636
 *
14637
 * Reset a parser context
14638
 */
14639
void
14640
xmlCtxtReset(xmlParserCtxtPtr ctxt)
14641
0
{
14642
0
    xmlParserInputPtr input;
14643
0
    xmlDictPtr dict;
14644
14645
0
    if (ctxt == NULL)
14646
0
        return;
14647
14648
0
    dict = ctxt->dict;
14649
14650
0
    while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
14651
0
        xmlFreeInputStream(input);
14652
0
    }
14653
0
    ctxt->inputNr = 0;
14654
0
    ctxt->input = NULL;
14655
14656
0
    ctxt->spaceNr = 0;
14657
0
    if (ctxt->spaceTab != NULL) {
14658
0
  ctxt->spaceTab[0] = -1;
14659
0
  ctxt->space = &ctxt->spaceTab[0];
14660
0
    } else {
14661
0
        ctxt->space = NULL;
14662
0
    }
14663
14664
14665
0
    ctxt->nodeNr = 0;
14666
0
    ctxt->node = NULL;
14667
14668
0
    ctxt->nameNr = 0;
14669
0
    ctxt->name = NULL;
14670
14671
0
    ctxt->nsNr = 0;
14672
14673
0
    DICT_FREE(ctxt->version);
14674
0
    ctxt->version = NULL;
14675
0
    DICT_FREE(ctxt->encoding);
14676
0
    ctxt->encoding = NULL;
14677
0
    DICT_FREE(ctxt->directory);
14678
0
    ctxt->directory = NULL;
14679
0
    DICT_FREE(ctxt->extSubURI);
14680
0
    ctxt->extSubURI = NULL;
14681
0
    DICT_FREE(ctxt->extSubSystem);
14682
0
    ctxt->extSubSystem = NULL;
14683
0
    if (ctxt->myDoc != NULL)
14684
0
        xmlFreeDoc(ctxt->myDoc);
14685
0
    ctxt->myDoc = NULL;
14686
14687
0
    ctxt->standalone = -1;
14688
0
    ctxt->hasExternalSubset = 0;
14689
0
    ctxt->hasPErefs = 0;
14690
0
    ctxt->html = 0;
14691
0
    ctxt->external = 0;
14692
0
    ctxt->instate = XML_PARSER_START;
14693
0
    ctxt->token = 0;
14694
14695
0
    ctxt->wellFormed = 1;
14696
0
    ctxt->nsWellFormed = 1;
14697
0
    ctxt->disableSAX = 0;
14698
0
    ctxt->valid = 1;
14699
#if 0
14700
    ctxt->vctxt.userData = ctxt;
14701
    ctxt->vctxt.error = xmlParserValidityError;
14702
    ctxt->vctxt.warning = xmlParserValidityWarning;
14703
#endif
14704
0
    ctxt->record_info = 0;
14705
0
    ctxt->checkIndex = 0;
14706
0
    ctxt->endCheckState = 0;
14707
0
    ctxt->inSubset = 0;
14708
0
    ctxt->errNo = XML_ERR_OK;
14709
0
    ctxt->depth = 0;
14710
0
    ctxt->charset = XML_CHAR_ENCODING_UTF8;
14711
0
    ctxt->catalogs = NULL;
14712
0
    ctxt->sizeentities = 0;
14713
0
    ctxt->sizeentcopy = 0;
14714
0
    xmlInitNodeInfoSeq(&ctxt->node_seq);
14715
14716
0
    if (ctxt->attsDefault != NULL) {
14717
0
        xmlHashFree(ctxt->attsDefault, xmlHashDefaultDeallocator);
14718
0
        ctxt->attsDefault = NULL;
14719
0
    }
14720
0
    if (ctxt->attsSpecial != NULL) {
14721
0
        xmlHashFree(ctxt->attsSpecial, NULL);
14722
0
        ctxt->attsSpecial = NULL;
14723
0
    }
14724
14725
0
#ifdef LIBXML_CATALOG_ENABLED
14726
0
    if (ctxt->catalogs != NULL)
14727
0
  xmlCatalogFreeLocal(ctxt->catalogs);
14728
0
#endif
14729
0
    ctxt->nbErrors = 0;
14730
0
    ctxt->nbWarnings = 0;
14731
0
    if (ctxt->lastError.code != XML_ERR_OK)
14732
0
        xmlResetError(&ctxt->lastError);
14733
0
}
14734
14735
/**
14736
 * xmlCtxtResetPush:
14737
 * @ctxt: an XML parser context
14738
 * @chunk:  a pointer to an array of chars
14739
 * @size:  number of chars in the array
14740
 * @filename:  an optional file name or URI
14741
 * @encoding:  the document encoding, or NULL
14742
 *
14743
 * Reset a push parser context
14744
 *
14745
 * Returns 0 in case of success and 1 in case of error
14746
 */
14747
int
14748
xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk,
14749
                 int size, const char *filename, const char *encoding)
14750
0
{
14751
0
    xmlParserInputPtr inputStream;
14752
0
    xmlParserInputBufferPtr buf;
14753
0
    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
14754
14755
0
    if (ctxt == NULL)
14756
0
        return(1);
14757
14758
0
    if ((encoding == NULL) && (chunk != NULL) && (size >= 4))
14759
0
        enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
14760
14761
0
    buf = xmlAllocParserInputBuffer(enc);
14762
0
    if (buf == NULL)
14763
0
        return(1);
14764
14765
0
    if (ctxt == NULL) {
14766
0
        xmlFreeParserInputBuffer(buf);
14767
0
        return(1);
14768
0
    }
14769
14770
0
    xmlCtxtReset(ctxt);
14771
14772
0
    if (filename == NULL) {
14773
0
        ctxt->directory = NULL;
14774
0
    } else {
14775
0
        ctxt->directory = xmlParserGetDirectory(filename);
14776
0
    }
14777
14778
0
    inputStream = xmlNewInputStream(ctxt);
14779
0
    if (inputStream == NULL) {
14780
0
        xmlFreeParserInputBuffer(buf);
14781
0
        return(1);
14782
0
    }
14783
14784
0
    if (filename == NULL)
14785
0
        inputStream->filename = NULL;
14786
0
    else
14787
0
        inputStream->filename = (char *)
14788
0
            xmlCanonicPath((const xmlChar *) filename);
14789
0
    inputStream->buf = buf;
14790
0
    xmlBufResetInput(buf->buffer, inputStream);
14791
14792
0
    inputPush(ctxt, inputStream);
14793
14794
0
    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
14795
0
        (ctxt->input->buf != NULL)) {
14796
0
  size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
14797
0
        size_t cur = ctxt->input->cur - ctxt->input->base;
14798
14799
0
        xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
14800
14801
0
        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
14802
#ifdef DEBUG_PUSH
14803
        xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
14804
#endif
14805
0
    }
14806
14807
0
    if (encoding != NULL) {
14808
0
        xmlCharEncodingHandlerPtr hdlr;
14809
14810
0
        if (ctxt->encoding != NULL)
14811
0
      xmlFree((xmlChar *) ctxt->encoding);
14812
0
        ctxt->encoding = xmlStrdup((const xmlChar *) encoding);
14813
14814
0
        hdlr = xmlFindCharEncodingHandler(encoding);
14815
0
        if (hdlr != NULL) {
14816
0
            xmlSwitchToEncoding(ctxt, hdlr);
14817
0
  } else {
14818
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
14819
0
            "Unsupported encoding %s\n", BAD_CAST encoding);
14820
0
        }
14821
0
    } else if (enc != XML_CHAR_ENCODING_NONE) {
14822
0
        xmlSwitchEncoding(ctxt, enc);
14823
0
    }
14824
14825
0
    return(0);
14826
0
}
14827
14828
14829
/**
14830
 * xmlCtxtUseOptionsInternal:
14831
 * @ctxt: an XML parser context
14832
 * @options:  a combination of xmlParserOption
14833
 * @encoding:  the user provided encoding to use
14834
 *
14835
 * Applies the options to the parser context
14836
 *
14837
 * Returns 0 in case of success, the set of unknown or unimplemented options
14838
 *         in case of error.
14839
 */
14840
static int
14841
xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encoding)
14842
3.69k
{
14843
3.69k
    if (ctxt == NULL)
14844
0
        return(-1);
14845
3.69k
    if (encoding != NULL) {
14846
0
        if (ctxt->encoding != NULL)
14847
0
      xmlFree((xmlChar *) ctxt->encoding);
14848
0
        ctxt->encoding = xmlStrdup((const xmlChar *) encoding);
14849
0
    }
14850
3.69k
    if (options & XML_PARSE_RECOVER) {
14851
0
        ctxt->recovery = 1;
14852
0
        options -= XML_PARSE_RECOVER;
14853
0
  ctxt->options |= XML_PARSE_RECOVER;
14854
0
    } else
14855
3.69k
        ctxt->recovery = 0;
14856
3.69k
    if (options & XML_PARSE_DTDLOAD) {
14857
0
        ctxt->loadsubset = XML_DETECT_IDS;
14858
0
        options -= XML_PARSE_DTDLOAD;
14859
0
  ctxt->options |= XML_PARSE_DTDLOAD;
14860
0
    } else
14861
3.69k
        ctxt->loadsubset = 0;
14862
3.69k
    if (options & XML_PARSE_DTDATTR) {
14863
0
        ctxt->loadsubset |= XML_COMPLETE_ATTRS;
14864
0
        options -= XML_PARSE_DTDATTR;
14865
0
  ctxt->options |= XML_PARSE_DTDATTR;
14866
0
    }
14867
3.69k
    if (options & XML_PARSE_NOENT) {
14868
0
        ctxt->replaceEntities = 1;
14869
        /* ctxt->loadsubset |= XML_DETECT_IDS; */
14870
0
        options -= XML_PARSE_NOENT;
14871
0
  ctxt->options |= XML_PARSE_NOENT;
14872
0
    } else
14873
3.69k
        ctxt->replaceEntities = 0;
14874
3.69k
    if (options & XML_PARSE_PEDANTIC) {
14875
0
        ctxt->pedantic = 1;
14876
0
        options -= XML_PARSE_PEDANTIC;
14877
0
  ctxt->options |= XML_PARSE_PEDANTIC;
14878
0
    } else
14879
3.69k
        ctxt->pedantic = 0;
14880
3.69k
    if (options & XML_PARSE_NOBLANKS) {
14881
0
        ctxt->keepBlanks = 0;
14882
0
        ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
14883
0
        options -= XML_PARSE_NOBLANKS;
14884
0
  ctxt->options |= XML_PARSE_NOBLANKS;
14885
0
    } else
14886
3.69k
        ctxt->keepBlanks = 1;
14887
3.69k
    if (options & XML_PARSE_DTDVALID) {
14888
0
        ctxt->validate = 1;
14889
0
        if (options & XML_PARSE_NOWARNING)
14890
0
            ctxt->vctxt.warning = NULL;
14891
0
        if (options & XML_PARSE_NOERROR)
14892
0
            ctxt->vctxt.error = NULL;
14893
0
        options -= XML_PARSE_DTDVALID;
14894
0
  ctxt->options |= XML_PARSE_DTDVALID;
14895
0
    } else
14896
3.69k
        ctxt->validate = 0;
14897
3.69k
    if (options & XML_PARSE_NOWARNING) {
14898
0
        ctxt->sax->warning = NULL;
14899
0
        options -= XML_PARSE_NOWARNING;
14900
0
    }
14901
3.69k
    if (options & XML_PARSE_NOERROR) {
14902
0
        ctxt->sax->error = NULL;
14903
0
        ctxt->sax->fatalError = NULL;
14904
0
        options -= XML_PARSE_NOERROR;
14905
0
    }
14906
#ifdef LIBXML_SAX1_ENABLED
14907
    if (options & XML_PARSE_SAX1) {
14908
        ctxt->sax->startElement = xmlSAX2StartElement;
14909
        ctxt->sax->endElement = xmlSAX2EndElement;
14910
        ctxt->sax->startElementNs = NULL;
14911
        ctxt->sax->endElementNs = NULL;
14912
        ctxt->sax->initialized = 1;
14913
        options -= XML_PARSE_SAX1;
14914
  ctxt->options |= XML_PARSE_SAX1;
14915
    }
14916
#endif /* LIBXML_SAX1_ENABLED */
14917
3.69k
    if (options & XML_PARSE_NODICT) {
14918
0
        ctxt->dictNames = 0;
14919
0
        options -= XML_PARSE_NODICT;
14920
0
  ctxt->options |= XML_PARSE_NODICT;
14921
3.69k
    } else {
14922
3.69k
        ctxt->dictNames = 1;
14923
3.69k
    }
14924
3.69k
    if (options & XML_PARSE_NOCDATA) {
14925
0
        ctxt->sax->cdataBlock = NULL;
14926
0
        options -= XML_PARSE_NOCDATA;
14927
0
  ctxt->options |= XML_PARSE_NOCDATA;
14928
0
    }
14929
3.69k
    if (options & XML_PARSE_NSCLEAN) {
14930
0
  ctxt->options |= XML_PARSE_NSCLEAN;
14931
0
        options -= XML_PARSE_NSCLEAN;
14932
0
    }
14933
3.69k
    if (options & XML_PARSE_NONET) {
14934
0
  ctxt->options |= XML_PARSE_NONET;
14935
0
        options -= XML_PARSE_NONET;
14936
0
    }
14937
3.69k
    if (options & XML_PARSE_COMPACT) {
14938
0
  ctxt->options |= XML_PARSE_COMPACT;
14939
0
        options -= XML_PARSE_COMPACT;
14940
0
    }
14941
3.69k
    if (options & XML_PARSE_OLD10) {
14942
0
  ctxt->options |= XML_PARSE_OLD10;
14943
0
        options -= XML_PARSE_OLD10;
14944
0
    }
14945
3.69k
    if (options & XML_PARSE_NOBASEFIX) {
14946
0
  ctxt->options |= XML_PARSE_NOBASEFIX;
14947
0
        options -= XML_PARSE_NOBASEFIX;
14948
0
    }
14949
3.69k
    if (options & XML_PARSE_HUGE) {
14950
0
  ctxt->options |= XML_PARSE_HUGE;
14951
0
        options -= XML_PARSE_HUGE;
14952
0
        if (ctxt->dict != NULL)
14953
0
            xmlDictSetLimit(ctxt->dict, 0);
14954
0
    }
14955
3.69k
    if (options & XML_PARSE_OLDSAX) {
14956
0
  ctxt->options |= XML_PARSE_OLDSAX;
14957
0
        options -= XML_PARSE_OLDSAX;
14958
0
    }
14959
3.69k
    if (options & XML_PARSE_IGNORE_ENC) {
14960
0
  ctxt->options |= XML_PARSE_IGNORE_ENC;
14961
0
        options -= XML_PARSE_IGNORE_ENC;
14962
0
    }
14963
3.69k
    if (options & XML_PARSE_BIG_LINES) {
14964
0
  ctxt->options |= XML_PARSE_BIG_LINES;
14965
0
        options -= XML_PARSE_BIG_LINES;
14966
0
    }
14967
3.69k
    ctxt->linenumbers = 1;
14968
3.69k
    return (options);
14969
3.69k
}
14970
14971
/**
14972
 * xmlCtxtUseOptions:
14973
 * @ctxt: an XML parser context
14974
 * @options:  a combination of xmlParserOption
14975
 *
14976
 * Applies the options to the parser context
14977
 *
14978
 * Returns 0 in case of success, the set of unknown or unimplemented options
14979
 *         in case of error.
14980
 */
14981
int
14982
xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options)
14983
0
{
14984
0
   return(xmlCtxtUseOptionsInternal(ctxt, options, NULL));
14985
0
}
14986
14987
/**
14988
 * xmlDoRead:
14989
 * @ctxt:  an XML parser context
14990
 * @URL:  the base URL to use for the document
14991
 * @encoding:  the document encoding, or NULL
14992
 * @options:  a combination of xmlParserOption
14993
 * @reuse:  keep the context for reuse
14994
 *
14995
 * Common front-end for the xmlRead functions
14996
 *
14997
 * Returns the resulting document tree or NULL
14998
 */
14999
static xmlDocPtr
15000
xmlDoRead(xmlParserCtxtPtr ctxt, const char *URL, const char *encoding,
15001
          int options, int reuse)
15002
3.69k
{
15003
3.69k
    xmlDocPtr ret;
15004
15005
3.69k
    xmlCtxtUseOptionsInternal(ctxt, options, encoding);
15006
3.69k
    if (encoding != NULL) {
15007
0
        xmlCharEncodingHandlerPtr hdlr;
15008
15009
0
  hdlr = xmlFindCharEncodingHandler(encoding);
15010
0
  if (hdlr != NULL)
15011
0
      xmlSwitchToEncoding(ctxt, hdlr);
15012
0
    }
15013
3.69k
    if ((URL != NULL) && (ctxt->input != NULL) &&
15014
3.69k
        (ctxt->input->filename == NULL))
15015
0
        ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL);
15016
3.69k
    xmlParseDocument(ctxt);
15017
3.69k
    if ((ctxt->wellFormed) || ctxt->recovery)
15018
3.69k
        ret = ctxt->myDoc;
15019
0
    else {
15020
0
        ret = NULL;
15021
0
  if (ctxt->myDoc != NULL) {
15022
0
      xmlFreeDoc(ctxt->myDoc);
15023
0
  }
15024
0
    }
15025
3.69k
    ctxt->myDoc = NULL;
15026
3.69k
    if (!reuse) {
15027
3.69k
  xmlFreeParserCtxt(ctxt);
15028
3.69k
    }
15029
15030
3.69k
    return (ret);
15031
3.69k
}
15032
15033
/**
15034
 * xmlReadDoc:
15035
 * @cur:  a pointer to a zero terminated string
15036
 * @URL:  the base URL to use for the document
15037
 * @encoding:  the document encoding, or NULL
15038
 * @options:  a combination of xmlParserOption
15039
 *
15040
 * parse an XML in-memory document and build a tree.
15041
 *
15042
 * Returns the resulting document tree
15043
 */
15044
xmlDocPtr
15045
xmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int options)
15046
0
{
15047
0
    xmlParserCtxtPtr ctxt;
15048
15049
0
    if (cur == NULL)
15050
0
        return (NULL);
15051
0
    xmlInitParser();
15052
15053
0
    ctxt = xmlCreateDocParserCtxt(cur);
15054
0
    if (ctxt == NULL)
15055
0
        return (NULL);
15056
0
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
15057
0
}
15058
15059
/**
15060
 * xmlReadFile:
15061
 * @filename:  a file or URL
15062
 * @encoding:  the document encoding, or NULL
15063
 * @options:  a combination of xmlParserOption
15064
 *
15065
 * parse an XML file from the filesystem or the network.
15066
 *
15067
 * Returns the resulting document tree
15068
 */
15069
xmlDocPtr
15070
xmlReadFile(const char *filename, const char *encoding, int options)
15071
3.69k
{
15072
3.69k
    xmlParserCtxtPtr ctxt;
15073
15074
3.69k
    xmlInitParser();
15075
3.69k
    ctxt = xmlCreateURLParserCtxt(filename, options);
15076
3.69k
    if (ctxt == NULL)
15077
0
        return (NULL);
15078
3.69k
    return (xmlDoRead(ctxt, NULL, encoding, options, 0));
15079
3.69k
}
15080
15081
/**
15082
 * xmlReadMemory:
15083
 * @buffer:  a pointer to a char array
15084
 * @size:  the size of the array
15085
 * @URL:  the base URL to use for the document
15086
 * @encoding:  the document encoding, or NULL
15087
 * @options:  a combination of xmlParserOption
15088
 *
15089
 * parse an XML in-memory document and build a tree.
15090
 *
15091
 * Returns the resulting document tree
15092
 */
15093
xmlDocPtr
15094
xmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options)
15095
0
{
15096
0
    xmlParserCtxtPtr ctxt;
15097
15098
0
    xmlInitParser();
15099
0
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
15100
0
    if (ctxt == NULL)
15101
0
        return (NULL);
15102
0
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
15103
0
}
15104
15105
/**
15106
 * xmlReadFd:
15107
 * @fd:  an open file descriptor
15108
 * @URL:  the base URL to use for the document
15109
 * @encoding:  the document encoding, or NULL
15110
 * @options:  a combination of xmlParserOption
15111
 *
15112
 * parse an XML from a file descriptor and build a tree.
15113
 * NOTE that the file descriptor will not be closed when the
15114
 *      reader is closed or reset.
15115
 *
15116
 * Returns the resulting document tree
15117
 */
15118
xmlDocPtr
15119
xmlReadFd(int fd, const char *URL, const char *encoding, int options)
15120
0
{
15121
0
    xmlParserCtxtPtr ctxt;
15122
0
    xmlParserInputBufferPtr input;
15123
0
    xmlParserInputPtr stream;
15124
15125
0
    if (fd < 0)
15126
0
        return (NULL);
15127
0
    xmlInitParser();
15128
15129
0
    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
15130
0
    if (input == NULL)
15131
0
        return (NULL);
15132
0
    input->closecallback = NULL;
15133
0
    ctxt = xmlNewParserCtxt();
15134
0
    if (ctxt == NULL) {
15135
0
        xmlFreeParserInputBuffer(input);
15136
0
        return (NULL);
15137
0
    }
15138
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15139
0
    if (stream == NULL) {
15140
0
        xmlFreeParserInputBuffer(input);
15141
0
  xmlFreeParserCtxt(ctxt);
15142
0
        return (NULL);
15143
0
    }
15144
0
    inputPush(ctxt, stream);
15145
0
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
15146
0
}
15147
15148
/**
15149
 * xmlReadIO:
15150
 * @ioread:  an I/O read function
15151
 * @ioclose:  an I/O close function
15152
 * @ioctx:  an I/O handler
15153
 * @URL:  the base URL to use for the document
15154
 * @encoding:  the document encoding, or NULL
15155
 * @options:  a combination of xmlParserOption
15156
 *
15157
 * parse an XML document from I/O functions and source and build a tree.
15158
 *
15159
 * Returns the resulting document tree
15160
 */
15161
xmlDocPtr
15162
xmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
15163
          void *ioctx, const char *URL, const char *encoding, int options)
15164
0
{
15165
0
    xmlParserCtxtPtr ctxt;
15166
0
    xmlParserInputBufferPtr input;
15167
0
    xmlParserInputPtr stream;
15168
15169
0
    if (ioread == NULL)
15170
0
        return (NULL);
15171
0
    xmlInitParser();
15172
15173
0
    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
15174
0
                                         XML_CHAR_ENCODING_NONE);
15175
0
    if (input == NULL) {
15176
0
        if (ioclose != NULL)
15177
0
            ioclose(ioctx);
15178
0
        return (NULL);
15179
0
    }
15180
0
    ctxt = xmlNewParserCtxt();
15181
0
    if (ctxt == NULL) {
15182
0
        xmlFreeParserInputBuffer(input);
15183
0
        return (NULL);
15184
0
    }
15185
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15186
0
    if (stream == NULL) {
15187
0
        xmlFreeParserInputBuffer(input);
15188
0
  xmlFreeParserCtxt(ctxt);
15189
0
        return (NULL);
15190
0
    }
15191
0
    inputPush(ctxt, stream);
15192
0
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
15193
0
}
15194
15195
/**
15196
 * xmlCtxtReadDoc:
15197
 * @ctxt:  an XML parser context
15198
 * @cur:  a pointer to a zero terminated string
15199
 * @URL:  the base URL to use for the document
15200
 * @encoding:  the document encoding, or NULL
15201
 * @options:  a combination of xmlParserOption
15202
 *
15203
 * parse an XML in-memory document and build a tree.
15204
 * This reuses the existing @ctxt parser context
15205
 *
15206
 * Returns the resulting document tree
15207
 */
15208
xmlDocPtr
15209
xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar * cur,
15210
               const char *URL, const char *encoding, int options)
15211
0
{
15212
0
    if (cur == NULL)
15213
0
        return (NULL);
15214
0
    return (xmlCtxtReadMemory(ctxt, (const char *) cur, xmlStrlen(cur), URL,
15215
0
                              encoding, options));
15216
0
}
15217
15218
/**
15219
 * xmlCtxtReadFile:
15220
 * @ctxt:  an XML parser context
15221
 * @filename:  a file or URL
15222
 * @encoding:  the document encoding, or NULL
15223
 * @options:  a combination of xmlParserOption
15224
 *
15225
 * parse an XML file from the filesystem or the network.
15226
 * This reuses the existing @ctxt parser context
15227
 *
15228
 * Returns the resulting document tree
15229
 */
15230
xmlDocPtr
15231
xmlCtxtReadFile(xmlParserCtxtPtr ctxt, const char *filename,
15232
                const char *encoding, int options)
15233
0
{
15234
0
    xmlParserInputPtr stream;
15235
15236
0
    if (filename == NULL)
15237
0
        return (NULL);
15238
0
    if (ctxt == NULL)
15239
0
        return (NULL);
15240
0
    xmlInitParser();
15241
15242
0
    xmlCtxtReset(ctxt);
15243
15244
0
    stream = xmlLoadExternalEntity(filename, NULL, ctxt);
15245
0
    if (stream == NULL) {
15246
0
        return (NULL);
15247
0
    }
15248
0
    inputPush(ctxt, stream);
15249
0
    return (xmlDoRead(ctxt, NULL, encoding, options, 1));
15250
0
}
15251
15252
/**
15253
 * xmlCtxtReadMemory:
15254
 * @ctxt:  an XML parser context
15255
 * @buffer:  a pointer to a char array
15256
 * @size:  the size of the array
15257
 * @URL:  the base URL to use for the document
15258
 * @encoding:  the document encoding, or NULL
15259
 * @options:  a combination of xmlParserOption
15260
 *
15261
 * parse an XML in-memory document and build a tree.
15262
 * This reuses the existing @ctxt parser context
15263
 *
15264
 * Returns the resulting document tree
15265
 */
15266
xmlDocPtr
15267
xmlCtxtReadMemory(xmlParserCtxtPtr ctxt, const char *buffer, int size,
15268
                  const char *URL, const char *encoding, int options)
15269
0
{
15270
0
    xmlParserInputBufferPtr input;
15271
0
    xmlParserInputPtr stream;
15272
15273
0
    if (ctxt == NULL)
15274
0
        return (NULL);
15275
0
    if (buffer == NULL)
15276
0
        return (NULL);
15277
0
    xmlInitParser();
15278
15279
0
    xmlCtxtReset(ctxt);
15280
15281
0
    input = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
15282
0
    if (input == NULL) {
15283
0
  return(NULL);
15284
0
    }
15285
15286
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15287
0
    if (stream == NULL) {
15288
0
  xmlFreeParserInputBuffer(input);
15289
0
  return(NULL);
15290
0
    }
15291
15292
0
    inputPush(ctxt, stream);
15293
0
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15294
0
}
15295
15296
/**
15297
 * xmlCtxtReadFd:
15298
 * @ctxt:  an XML parser context
15299
 * @fd:  an open file descriptor
15300
 * @URL:  the base URL to use for the document
15301
 * @encoding:  the document encoding, or NULL
15302
 * @options:  a combination of xmlParserOption
15303
 *
15304
 * parse an XML from a file descriptor and build a tree.
15305
 * This reuses the existing @ctxt parser context
15306
 * NOTE that the file descriptor will not be closed when the
15307
 *      reader is closed or reset.
15308
 *
15309
 * Returns the resulting document tree
15310
 */
15311
xmlDocPtr
15312
xmlCtxtReadFd(xmlParserCtxtPtr ctxt, int fd,
15313
              const char *URL, const char *encoding, int options)
15314
0
{
15315
0
    xmlParserInputBufferPtr input;
15316
0
    xmlParserInputPtr stream;
15317
15318
0
    if (fd < 0)
15319
0
        return (NULL);
15320
0
    if (ctxt == NULL)
15321
0
        return (NULL);
15322
0
    xmlInitParser();
15323
15324
0
    xmlCtxtReset(ctxt);
15325
15326
15327
0
    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
15328
0
    if (input == NULL)
15329
0
        return (NULL);
15330
0
    input->closecallback = NULL;
15331
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15332
0
    if (stream == NULL) {
15333
0
        xmlFreeParserInputBuffer(input);
15334
0
        return (NULL);
15335
0
    }
15336
0
    inputPush(ctxt, stream);
15337
0
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15338
0
}
15339
15340
/**
15341
 * xmlCtxtReadIO:
15342
 * @ctxt:  an XML parser context
15343
 * @ioread:  an I/O read function
15344
 * @ioclose:  an I/O close function
15345
 * @ioctx:  an I/O handler
15346
 * @URL:  the base URL to use for the document
15347
 * @encoding:  the document encoding, or NULL
15348
 * @options:  a combination of xmlParserOption
15349
 *
15350
 * parse an XML document from I/O functions and source and build a tree.
15351
 * This reuses the existing @ctxt parser context
15352
 *
15353
 * Returns the resulting document tree
15354
 */
15355
xmlDocPtr
15356
xmlCtxtReadIO(xmlParserCtxtPtr ctxt, xmlInputReadCallback ioread,
15357
              xmlInputCloseCallback ioclose, void *ioctx,
15358
        const char *URL,
15359
              const char *encoding, int options)
15360
0
{
15361
0
    xmlParserInputBufferPtr input;
15362
0
    xmlParserInputPtr stream;
15363
15364
0
    if (ioread == NULL)
15365
0
        return (NULL);
15366
0
    if (ctxt == NULL)
15367
0
        return (NULL);
15368
0
    xmlInitParser();
15369
15370
0
    xmlCtxtReset(ctxt);
15371
15372
0
    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
15373
0
                                         XML_CHAR_ENCODING_NONE);
15374
0
    if (input == NULL) {
15375
0
        if (ioclose != NULL)
15376
0
            ioclose(ioctx);
15377
0
        return (NULL);
15378
0
    }
15379
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15380
0
    if (stream == NULL) {
15381
0
        xmlFreeParserInputBuffer(input);
15382
0
        return (NULL);
15383
0
    }
15384
0
    inputPush(ctxt, stream);
15385
0
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15386
0
}
15387