Coverage Report

Created: 2022-11-15 06:15

/src/libxml2/parser.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * parser.c : an XML 1.0 parser, namespaces and validity support are mostly
3
 *            implemented on top of the SAX interfaces
4
 *
5
 * References:
6
 *   The XML specification:
7
 *     http://www.w3.org/TR/REC-xml
8
 *   Original 1.0 version:
9
 *     http://www.w3.org/TR/1998/REC-xml-19980210
10
 *   XML second edition working draft
11
 *     http://www.w3.org/TR/2000/WD-xml-2e-20000814
12
 *
13
 * Okay this is a big file, the parser core is around 7000 lines, then it
14
 * is followed by the progressive parser top routines, then the various
15
 * high level APIs to call the parser and a few miscellaneous functions.
16
 * A number of helper functions and deprecated ones have been moved to
17
 * parserInternals.c to reduce this file size.
18
 * As much as possible the functions are associated with their relative
19
 * production in the XML specification. A few productions defining the
20
 * different ranges of character are actually implanted either in
21
 * parserInternals.h or parserInternals.c
22
 * The DOM tree build is realized from the default SAX callbacks in
23
 * the module SAX.c.
24
 * The routines doing the validation checks are in valid.c and called either
25
 * from the SAX callbacks or as standalone functions using a preparsed
26
 * document.
27
 *
28
 * See Copyright for the status of this software.
29
 *
30
 * daniel@veillard.com
31
 */
32
33
/* To avoid EBCDIC trouble when parsing on zOS */
34
#if defined(__MVS__)
35
#pragma convert("ISO8859-1")
36
#endif
37
38
#define IN_LIBXML
39
#include "libxml.h"
40
41
#if defined(_WIN32)
42
#define XML_DIR_SEP '\\'
43
#else
44
#define XML_DIR_SEP '/'
45
#endif
46
47
#include <stdlib.h>
48
#include <limits.h>
49
#include <string.h>
50
#include <stdarg.h>
51
#include <stddef.h>
52
#include <ctype.h>
53
#include <stdlib.h>
54
#include <libxml/xmlmemory.h>
55
#include <libxml/threads.h>
56
#include <libxml/globals.h>
57
#include <libxml/tree.h>
58
#include <libxml/parser.h>
59
#include <libxml/parserInternals.h>
60
#include <libxml/HTMLparser.h>
61
#include <libxml/valid.h>
62
#include <libxml/entities.h>
63
#include <libxml/xmlerror.h>
64
#include <libxml/encoding.h>
65
#include <libxml/xmlIO.h>
66
#include <libxml/uri.h>
67
#ifdef LIBXML_CATALOG_ENABLED
68
#include <libxml/catalog.h>
69
#endif
70
#ifdef LIBXML_SCHEMAS_ENABLED
71
#include <libxml/xmlschemastypes.h>
72
#include <libxml/relaxng.h>
73
#endif
74
#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
75
#include <libxml/xpath.h>
76
#endif
77
78
#include "private/buf.h"
79
#include "private/enc.h"
80
#include "private/error.h"
81
#include "private/html.h"
82
#include "private/io.h"
83
#include "private/parser.h"
84
#include "private/threads.h"
85
86
struct _xmlStartTag {
87
    const xmlChar *prefix;
88
    const xmlChar *URI;
89
    int line;
90
    int nsNr;
91
};
92
93
static void
94
xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info);
95
96
static xmlParserCtxtPtr
97
xmlCreateEntityParserCtxtInternal(xmlSAXHandlerPtr sax, void *userData,
98
        const xmlChar *URL, const xmlChar *ID, const xmlChar *base,
99
        xmlParserCtxtPtr pctx);
100
101
static void xmlHaltParser(xmlParserCtxtPtr ctxt);
102
103
static int
104
xmlParseElementStart(xmlParserCtxtPtr ctxt);
105
106
static void
107
xmlParseElementEnd(xmlParserCtxtPtr ctxt);
108
109
/************************************************************************
110
 *                  *
111
 *  Arbitrary limits set in the parser. See XML_PARSE_HUGE    *
112
 *                  *
113
 ************************************************************************/
114
115
0
#define XML_MAX_HUGE_LENGTH 1000000000
116
117
0
#define XML_PARSER_BIG_ENTITY 1000
118
#define XML_PARSER_LOT_ENTITY 5000
119
120
/*
121
 * XML_PARSER_NON_LINEAR is the threshold where the ratio of parsed entity
122
 *    replacement over the size in byte of the input indicates that you have
123
 *    and exponential behaviour. A value of 10 correspond to at least 3 entity
124
 *    replacement per byte of input.
125
 */
126
0
#define XML_PARSER_NON_LINEAR 10
127
128
/*
129
 * xmlParserEntityCheck
130
 *
131
 * Function to check non-linear entity expansion behaviour
132
 * This is here to detect and stop exponential linear entity expansion
133
 * This is not a limitation of the parser but a safety
134
 * boundary feature. It can be disabled with the XML_PARSE_HUGE
135
 * parser option.
136
 */
137
static int
138
xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
139
                     xmlEntityPtr ent, size_t replacement)
140
0
{
141
0
    size_t consumed = 0;
142
0
    int i;
143
144
0
    if ((ctxt == NULL) || (ctxt->options & XML_PARSE_HUGE))
145
0
        return (0);
146
0
    if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
147
0
        return (1);
148
149
    /*
150
     * This may look absurd but is needed to detect
151
     * entities problems
152
     */
153
0
    if ((ent != NULL) && (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
154
0
  (ent->content != NULL) && (ent->checked == 0) &&
155
0
  (ctxt->errNo != XML_ERR_ENTITY_LOOP)) {
156
0
  unsigned long oldnbent = ctxt->nbentities, diff;
157
0
  xmlChar *rep;
158
159
0
  ent->checked = 1;
160
161
0
        ++ctxt->depth;
162
0
  rep = xmlStringDecodeEntities(ctxt, ent->content,
163
0
          XML_SUBSTITUTE_REF, 0, 0, 0);
164
0
        --ctxt->depth;
165
0
  if ((rep == NULL) || (ctxt->errNo == XML_ERR_ENTITY_LOOP)) {
166
0
      ent->content[0] = 0;
167
0
  }
168
169
0
        diff = ctxt->nbentities - oldnbent + 1;
170
0
        if (diff > INT_MAX / 2)
171
0
            diff = INT_MAX / 2;
172
0
  ent->checked = diff * 2;
173
0
  if (rep != NULL) {
174
0
      if (xmlStrchr(rep, '<'))
175
0
    ent->checked |= 1;
176
0
      xmlFree(rep);
177
0
      rep = NULL;
178
0
  }
179
0
    }
180
181
    /*
182
     * Prevent entity exponential check, not just replacement while
183
     * parsing the DTD
184
     * The check is potentially costly so do that only once in a thousand
185
     */
186
0
    if ((ctxt->instate == XML_PARSER_DTD) && (ctxt->nbentities > 10000) &&
187
0
        (ctxt->nbentities % 1024 == 0)) {
188
0
  for (i = 0;i < ctxt->inputNr;i++) {
189
0
      consumed += ctxt->inputTab[i]->consumed +
190
0
                 (ctxt->inputTab[i]->cur - ctxt->inputTab[i]->base);
191
0
  }
192
0
  if (ctxt->nbentities > consumed * XML_PARSER_NON_LINEAR) {
193
0
      xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
194
0
      ctxt->instate = XML_PARSER_EOF;
195
0
      return (1);
196
0
  }
197
0
  consumed = 0;
198
0
    }
199
200
201
202
0
    if (replacement != 0) {
203
0
  if (replacement < XML_MAX_TEXT_LENGTH)
204
0
      return(0);
205
206
        /*
207
   * If the volume of entity copy reaches 10 times the
208
   * amount of parsed data and over the large text threshold
209
   * then that's very likely to be an abuse.
210
   */
211
0
        if (ctxt->input != NULL) {
212
0
      consumed = ctxt->input->consumed +
213
0
                 (ctxt->input->cur - ctxt->input->base);
214
0
  }
215
0
        consumed += ctxt->sizeentities;
216
217
0
        if (replacement < XML_PARSER_NON_LINEAR * consumed)
218
0
      return(0);
219
0
    } else if (size != 0) {
220
        /*
221
         * Do the check based on the replacement size of the entity
222
         */
223
0
        if (size < XML_PARSER_BIG_ENTITY)
224
0
      return(0);
225
226
        /*
227
         * A limit on the amount of text data reasonably used
228
         */
229
0
        if (ctxt->input != NULL) {
230
0
            consumed = ctxt->input->consumed +
231
0
                (ctxt->input->cur - ctxt->input->base);
232
0
        }
233
0
        consumed += ctxt->sizeentities;
234
235
0
        if ((size < XML_PARSER_NON_LINEAR * consumed) &&
236
0
      (ctxt->nbentities * 3 < XML_PARSER_NON_LINEAR * consumed))
237
0
            return (0);
238
0
    } else if (ent != NULL) {
239
        /*
240
         * use the number of parsed entities in the replacement
241
         */
242
0
        size = ent->checked / 2;
243
244
        /*
245
         * The amount of data parsed counting entities size only once
246
         */
247
0
        if (ctxt->input != NULL) {
248
0
            consumed = ctxt->input->consumed +
249
0
                (ctxt->input->cur - ctxt->input->base);
250
0
        }
251
0
        consumed += ctxt->sizeentities;
252
253
        /*
254
         * Check the density of entities for the amount of data
255
   * knowing an entity reference will take at least 3 bytes
256
         */
257
0
        if (size * 3 < consumed * XML_PARSER_NON_LINEAR)
258
0
            return (0);
259
0
    } else {
260
        /*
261
         * strange we got no data for checking
262
         */
263
0
  if (((ctxt->lastError.code != XML_ERR_UNDECLARED_ENTITY) &&
264
0
       (ctxt->lastError.code != XML_WAR_UNDECLARED_ENTITY)) ||
265
0
      (ctxt->nbentities <= 10000))
266
0
      return (0);
267
0
    }
268
0
    xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
269
0
    return (1);
270
0
}
271
272
/**
273
 * xmlParserMaxDepth:
274
 *
275
 * arbitrary depth limit for the XML documents that we allow to
276
 * process. This is not a limitation of the parser but a safety
277
 * boundary feature. It can be disabled with the XML_PARSE_HUGE
278
 * parser option.
279
 */
280
unsigned int xmlParserMaxDepth = 256;
281
282
283
284
#define SAX2 1
285
12
#define XML_PARSER_BIG_BUFFER_SIZE 300
286
12
#define XML_PARSER_BUFFER_SIZE 100
287
2
#define SAX_COMPAT_MODE BAD_CAST "SAX compatibility mode document"
288
289
/**
290
 * XML_PARSER_CHUNK_SIZE
291
 *
292
 * When calling GROW that's the minimal amount of data
293
 * the parser expected to have received. It is not a hard
294
 * limit but an optimization when reading strings like Names
295
 * It is not strictly needed as long as inputs available characters
296
 * are followed by 0, which should be provided by the I/O level
297
 */
298
0
#define XML_PARSER_CHUNK_SIZE 100
299
300
/*
301
 * List of XML prefixed PI allowed by W3C specs
302
 */
303
304
static const char* const xmlW3CPIs[] = {
305
    "xml-stylesheet",
306
    "xml-model",
307
    NULL
308
};
309
310
311
/* DEPR void xmlParserHandleReference(xmlParserCtxtPtr ctxt); */
312
static xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt,
313
                                              const xmlChar **str);
314
315
static xmlParserErrors
316
xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
317
                xmlSAXHandlerPtr sax,
318
          void *user_data, int depth, const xmlChar *URL,
319
          const xmlChar *ID, xmlNodePtr *list);
320
321
static int
322
xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options,
323
                          const char *encoding);
324
#ifdef LIBXML_LEGACY_ENABLED
325
static void
326
xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
327
                      xmlNodePtr lastNode);
328
#endif /* LIBXML_LEGACY_ENABLED */
329
330
static xmlParserErrors
331
xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
332
          const xmlChar *string, void *user_data, xmlNodePtr *lst);
333
334
static int
335
xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity);
336
337
/************************************************************************
338
 *                  *
339
 *    Some factorized error routines        *
340
 *                  *
341
 ************************************************************************/
342
343
/**
344
 * xmlErrAttributeDup:
345
 * @ctxt:  an XML parser context
346
 * @prefix:  the attribute prefix
347
 * @localname:  the attribute localname
348
 *
349
 * Handle a redefinition of attribute error
350
 */
351
static void
352
xmlErrAttributeDup(xmlParserCtxtPtr ctxt, const xmlChar * prefix,
353
                   const xmlChar * localname)
354
0
{
355
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
356
0
        (ctxt->instate == XML_PARSER_EOF))
357
0
  return;
358
0
    if (ctxt != NULL)
359
0
  ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
360
361
0
    if (prefix == NULL)
362
0
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
363
0
                        XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
364
0
                        (const char *) localname, NULL, NULL, 0, 0,
365
0
                        "Attribute %s redefined\n", localname);
366
0
    else
367
0
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
368
0
                        XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
369
0
                        (const char *) prefix, (const char *) localname,
370
0
                        NULL, 0, 0, "Attribute %s:%s redefined\n", prefix,
371
0
                        localname);
372
0
    if (ctxt != NULL) {
373
0
  ctxt->wellFormed = 0;
374
0
  if (ctxt->recovery == 0)
375
0
      ctxt->disableSAX = 1;
376
0
    }
377
0
}
378
379
/**
380
 * xmlFatalErr:
381
 * @ctxt:  an XML parser context
382
 * @error:  the error number
383
 * @extra:  extra information string
384
 *
385
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
386
 */
387
static void
388
xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
389
0
{
390
0
    const char *errmsg;
391
392
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
393
0
        (ctxt->instate == XML_PARSER_EOF))
394
0
  return;
395
0
    switch (error) {
396
0
        case XML_ERR_INVALID_HEX_CHARREF:
397
0
            errmsg = "CharRef: invalid hexadecimal value";
398
0
            break;
399
0
        case XML_ERR_INVALID_DEC_CHARREF:
400
0
            errmsg = "CharRef: invalid decimal value";
401
0
            break;
402
0
        case XML_ERR_INVALID_CHARREF:
403
0
            errmsg = "CharRef: invalid value";
404
0
            break;
405
0
        case XML_ERR_INTERNAL_ERROR:
406
0
            errmsg = "internal error";
407
0
            break;
408
0
        case XML_ERR_PEREF_AT_EOF:
409
0
            errmsg = "PEReference at end of document";
410
0
            break;
411
0
        case XML_ERR_PEREF_IN_PROLOG:
412
0
            errmsg = "PEReference in prolog";
413
0
            break;
414
0
        case XML_ERR_PEREF_IN_EPILOG:
415
0
            errmsg = "PEReference in epilog";
416
0
            break;
417
0
        case XML_ERR_PEREF_NO_NAME:
418
0
            errmsg = "PEReference: no name";
419
0
            break;
420
0
        case XML_ERR_PEREF_SEMICOL_MISSING:
421
0
            errmsg = "PEReference: expecting ';'";
422
0
            break;
423
0
        case XML_ERR_ENTITY_LOOP:
424
0
            errmsg = "Detected an entity reference loop";
425
0
            break;
426
0
        case XML_ERR_ENTITY_NOT_STARTED:
427
0
            errmsg = "EntityValue: \" or ' expected";
428
0
            break;
429
0
        case XML_ERR_ENTITY_PE_INTERNAL:
430
0
            errmsg = "PEReferences forbidden in internal subset";
431
0
            break;
432
0
        case XML_ERR_ENTITY_NOT_FINISHED:
433
0
            errmsg = "EntityValue: \" or ' expected";
434
0
            break;
435
0
        case XML_ERR_ATTRIBUTE_NOT_STARTED:
436
0
            errmsg = "AttValue: \" or ' expected";
437
0
            break;
438
0
        case XML_ERR_LT_IN_ATTRIBUTE:
439
0
            errmsg = "Unescaped '<' not allowed in attributes values";
440
0
            break;
441
0
        case XML_ERR_LITERAL_NOT_STARTED:
442
0
            errmsg = "SystemLiteral \" or ' expected";
443
0
            break;
444
0
        case XML_ERR_LITERAL_NOT_FINISHED:
445
0
            errmsg = "Unfinished System or Public ID \" or ' expected";
446
0
            break;
447
0
        case XML_ERR_MISPLACED_CDATA_END:
448
0
            errmsg = "Sequence ']]>' not allowed in content";
449
0
            break;
450
0
        case XML_ERR_URI_REQUIRED:
451
0
            errmsg = "SYSTEM or PUBLIC, the URI is missing";
452
0
            break;
453
0
        case XML_ERR_PUBID_REQUIRED:
454
0
            errmsg = "PUBLIC, the Public Identifier is missing";
455
0
            break;
456
0
        case XML_ERR_HYPHEN_IN_COMMENT:
457
0
            errmsg = "Comment must not contain '--' (double-hyphen)";
458
0
            break;
459
0
        case XML_ERR_PI_NOT_STARTED:
460
0
            errmsg = "xmlParsePI : no target name";
461
0
            break;
462
0
        case XML_ERR_RESERVED_XML_NAME:
463
0
            errmsg = "Invalid PI name";
464
0
            break;
465
0
        case XML_ERR_NOTATION_NOT_STARTED:
466
0
            errmsg = "NOTATION: Name expected here";
467
0
            break;
468
0
        case XML_ERR_NOTATION_NOT_FINISHED:
469
0
            errmsg = "'>' required to close NOTATION declaration";
470
0
            break;
471
0
        case XML_ERR_VALUE_REQUIRED:
472
0
            errmsg = "Entity value required";
473
0
            break;
474
0
        case XML_ERR_URI_FRAGMENT:
475
0
            errmsg = "Fragment not allowed";
476
0
            break;
477
0
        case XML_ERR_ATTLIST_NOT_STARTED:
478
0
            errmsg = "'(' required to start ATTLIST enumeration";
479
0
            break;
480
0
        case XML_ERR_NMTOKEN_REQUIRED:
481
0
            errmsg = "NmToken expected in ATTLIST enumeration";
482
0
            break;
483
0
        case XML_ERR_ATTLIST_NOT_FINISHED:
484
0
            errmsg = "')' required to finish ATTLIST enumeration";
485
0
            break;
486
0
        case XML_ERR_MIXED_NOT_STARTED:
487
0
            errmsg = "MixedContentDecl : '|' or ')*' expected";
488
0
            break;
489
0
        case XML_ERR_PCDATA_REQUIRED:
490
0
            errmsg = "MixedContentDecl : '#PCDATA' expected";
491
0
            break;
492
0
        case XML_ERR_ELEMCONTENT_NOT_STARTED:
493
0
            errmsg = "ContentDecl : Name or '(' expected";
494
0
            break;
495
0
        case XML_ERR_ELEMCONTENT_NOT_FINISHED:
496
0
            errmsg = "ContentDecl : ',' '|' or ')' expected";
497
0
            break;
498
0
        case XML_ERR_PEREF_IN_INT_SUBSET:
499
0
            errmsg =
500
0
                "PEReference: forbidden within markup decl in internal subset";
501
0
            break;
502
0
        case XML_ERR_GT_REQUIRED:
503
0
            errmsg = "expected '>'";
504
0
            break;
505
0
        case XML_ERR_CONDSEC_INVALID:
506
0
            errmsg = "XML conditional section '[' expected";
507
0
            break;
508
0
        case XML_ERR_EXT_SUBSET_NOT_FINISHED:
509
0
            errmsg = "Content error in the external subset";
510
0
            break;
511
0
        case XML_ERR_CONDSEC_INVALID_KEYWORD:
512
0
            errmsg =
513
0
                "conditional section INCLUDE or IGNORE keyword expected";
514
0
            break;
515
0
        case XML_ERR_CONDSEC_NOT_FINISHED:
516
0
            errmsg = "XML conditional section not closed";
517
0
            break;
518
0
        case XML_ERR_XMLDECL_NOT_STARTED:
519
0
            errmsg = "Text declaration '<?xml' required";
520
0
            break;
521
0
        case XML_ERR_XMLDECL_NOT_FINISHED:
522
0
            errmsg = "parsing XML declaration: '?>' expected";
523
0
            break;
524
0
        case XML_ERR_EXT_ENTITY_STANDALONE:
525
0
            errmsg = "external parsed entities cannot be standalone";
526
0
            break;
527
0
        case XML_ERR_ENTITYREF_SEMICOL_MISSING:
528
0
            errmsg = "EntityRef: expecting ';'";
529
0
            break;
530
0
        case XML_ERR_DOCTYPE_NOT_FINISHED:
531
0
            errmsg = "DOCTYPE improperly terminated";
532
0
            break;
533
0
        case XML_ERR_LTSLASH_REQUIRED:
534
0
            errmsg = "EndTag: '</' not found";
535
0
            break;
536
0
        case XML_ERR_EQUAL_REQUIRED:
537
0
            errmsg = "expected '='";
538
0
            break;
539
0
        case XML_ERR_STRING_NOT_CLOSED:
540
0
            errmsg = "String not closed expecting \" or '";
541
0
            break;
542
0
        case XML_ERR_STRING_NOT_STARTED:
543
0
            errmsg = "String not started expecting ' or \"";
544
0
            break;
545
0
        case XML_ERR_ENCODING_NAME:
546
0
            errmsg = "Invalid XML encoding name";
547
0
            break;
548
0
        case XML_ERR_STANDALONE_VALUE:
549
0
            errmsg = "standalone accepts only 'yes' or 'no'";
550
0
            break;
551
0
        case XML_ERR_DOCUMENT_EMPTY:
552
0
            errmsg = "Document is empty";
553
0
            break;
554
0
        case XML_ERR_DOCUMENT_END:
555
0
            errmsg = "Extra content at the end of the document";
556
0
            break;
557
0
        case XML_ERR_NOT_WELL_BALANCED:
558
0
            errmsg = "chunk is not well balanced";
559
0
            break;
560
0
        case XML_ERR_EXTRA_CONTENT:
561
0
            errmsg = "extra content at the end of well balanced chunk";
562
0
            break;
563
0
        case XML_ERR_VERSION_MISSING:
564
0
            errmsg = "Malformed declaration expecting version";
565
0
            break;
566
0
        case XML_ERR_NAME_TOO_LONG:
567
0
            errmsg = "Name too long";
568
0
            break;
569
#if 0
570
        case:
571
            errmsg = "";
572
            break;
573
#endif
574
0
        default:
575
0
            errmsg = "Unregistered error message";
576
0
    }
577
0
    if (ctxt != NULL)
578
0
  ctxt->errNo = error;
579
0
    if (info == NULL) {
580
0
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
581
0
                        XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s\n",
582
0
                        errmsg);
583
0
    } else {
584
0
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
585
0
                        XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s: %s\n",
586
0
                        errmsg, info);
587
0
    }
588
0
    if (ctxt != NULL) {
589
0
  ctxt->wellFormed = 0;
590
0
  if (ctxt->recovery == 0)
591
0
      ctxt->disableSAX = 1;
592
0
    }
593
0
}
594
595
/**
596
 * xmlFatalErrMsg:
597
 * @ctxt:  an XML parser context
598
 * @error:  the error number
599
 * @msg:  the error message
600
 *
601
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
602
 */
603
static void LIBXML_ATTR_FORMAT(3,0)
604
xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
605
               const char *msg)
606
0
{
607
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
608
0
        (ctxt->instate == XML_PARSER_EOF))
609
0
  return;
610
0
    if (ctxt != NULL)
611
0
  ctxt->errNo = error;
612
0
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
613
0
                    XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
614
0
    if (ctxt != NULL) {
615
0
  ctxt->wellFormed = 0;
616
0
  if (ctxt->recovery == 0)
617
0
      ctxt->disableSAX = 1;
618
0
    }
619
0
}
620
621
/**
622
 * xmlWarningMsg:
623
 * @ctxt:  an XML parser context
624
 * @error:  the error number
625
 * @msg:  the error message
626
 * @str1:  extra data
627
 * @str2:  extra data
628
 *
629
 * Handle a warning.
630
 */
631
static void LIBXML_ATTR_FORMAT(3,0)
632
xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
633
              const char *msg, const xmlChar *str1, const xmlChar *str2)
634
0
{
635
0
    xmlStructuredErrorFunc schannel = NULL;
636
637
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
638
0
        (ctxt->instate == XML_PARSER_EOF))
639
0
  return;
640
0
    if ((ctxt != NULL) && (ctxt->sax != NULL) &&
641
0
        (ctxt->sax->initialized == XML_SAX2_MAGIC))
642
0
        schannel = ctxt->sax->serror;
643
0
    if (ctxt != NULL) {
644
0
        __xmlRaiseError(schannel,
645
0
                    (ctxt->sax) ? ctxt->sax->warning : NULL,
646
0
                    ctxt->userData,
647
0
                    ctxt, NULL, XML_FROM_PARSER, error,
648
0
                    XML_ERR_WARNING, NULL, 0,
649
0
        (const char *) str1, (const char *) str2, NULL, 0, 0,
650
0
        msg, (const char *) str1, (const char *) str2);
651
0
    } else {
652
0
        __xmlRaiseError(schannel, NULL, NULL,
653
0
                    ctxt, NULL, XML_FROM_PARSER, error,
654
0
                    XML_ERR_WARNING, NULL, 0,
655
0
        (const char *) str1, (const char *) str2, NULL, 0, 0,
656
0
        msg, (const char *) str1, (const char *) str2);
657
0
    }
658
0
}
659
660
/**
661
 * xmlValidityError:
662
 * @ctxt:  an XML parser context
663
 * @error:  the error number
664
 * @msg:  the error message
665
 * @str1:  extra data
666
 *
667
 * Handle a validity error.
668
 */
669
static void LIBXML_ATTR_FORMAT(3,0)
670
xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error,
671
              const char *msg, const xmlChar *str1, const xmlChar *str2)
672
0
{
673
0
    xmlStructuredErrorFunc schannel = NULL;
674
675
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
676
0
        (ctxt->instate == XML_PARSER_EOF))
677
0
  return;
678
0
    if (ctxt != NULL) {
679
0
  ctxt->errNo = error;
680
0
  if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
681
0
      schannel = ctxt->sax->serror;
682
0
    }
683
0
    if (ctxt != NULL) {
684
0
        __xmlRaiseError(schannel,
685
0
                    ctxt->vctxt.error, ctxt->vctxt.userData,
686
0
                    ctxt, NULL, XML_FROM_DTD, error,
687
0
                    XML_ERR_ERROR, NULL, 0, (const char *) str1,
688
0
        (const char *) str2, NULL, 0, 0,
689
0
        msg, (const char *) str1, (const char *) str2);
690
0
  ctxt->valid = 0;
691
0
    } else {
692
0
        __xmlRaiseError(schannel, NULL, NULL,
693
0
                    ctxt, NULL, XML_FROM_DTD, error,
694
0
                    XML_ERR_ERROR, NULL, 0, (const char *) str1,
695
0
        (const char *) str2, NULL, 0, 0,
696
0
        msg, (const char *) str1, (const char *) str2);
697
0
    }
698
0
}
699
700
/**
701
 * xmlFatalErrMsgInt:
702
 * @ctxt:  an XML parser context
703
 * @error:  the error number
704
 * @msg:  the error message
705
 * @val:  an integer value
706
 *
707
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
708
 */
709
static void LIBXML_ATTR_FORMAT(3,0)
710
xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
711
                  const char *msg, int val)
712
0
{
713
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
714
0
        (ctxt->instate == XML_PARSER_EOF))
715
0
  return;
716
0
    if (ctxt != NULL)
717
0
  ctxt->errNo = error;
718
0
    __xmlRaiseError(NULL, NULL, NULL,
719
0
                    ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
720
0
                    NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
721
0
    if (ctxt != NULL) {
722
0
  ctxt->wellFormed = 0;
723
0
  if (ctxt->recovery == 0)
724
0
      ctxt->disableSAX = 1;
725
0
    }
726
0
}
727
728
/**
729
 * xmlFatalErrMsgStrIntStr:
730
 * @ctxt:  an XML parser context
731
 * @error:  the error number
732
 * @msg:  the error message
733
 * @str1:  an string info
734
 * @val:  an integer value
735
 * @str2:  an string info
736
 *
737
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
738
 */
739
static void LIBXML_ATTR_FORMAT(3,0)
740
xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
741
                  const char *msg, const xmlChar *str1, int val,
742
      const xmlChar *str2)
743
0
{
744
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
745
0
        (ctxt->instate == XML_PARSER_EOF))
746
0
  return;
747
0
    if (ctxt != NULL)
748
0
  ctxt->errNo = error;
749
0
    __xmlRaiseError(NULL, NULL, NULL,
750
0
                    ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
751
0
                    NULL, 0, (const char *) str1, (const char *) str2,
752
0
        NULL, val, 0, msg, str1, val, str2);
753
0
    if (ctxt != NULL) {
754
0
  ctxt->wellFormed = 0;
755
0
  if (ctxt->recovery == 0)
756
0
      ctxt->disableSAX = 1;
757
0
    }
758
0
}
759
760
/**
761
 * xmlFatalErrMsgStr:
762
 * @ctxt:  an XML parser context
763
 * @error:  the error number
764
 * @msg:  the error message
765
 * @val:  a string value
766
 *
767
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
768
 */
769
static void LIBXML_ATTR_FORMAT(3,0)
770
xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
771
                  const char *msg, const xmlChar * val)
772
0
{
773
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
774
0
        (ctxt->instate == XML_PARSER_EOF))
775
0
  return;
776
0
    if (ctxt != NULL)
777
0
  ctxt->errNo = error;
778
0
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
779
0
                    XML_FROM_PARSER, error, XML_ERR_FATAL,
780
0
                    NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
781
0
                    val);
782
0
    if (ctxt != NULL) {
783
0
  ctxt->wellFormed = 0;
784
0
  if (ctxt->recovery == 0)
785
0
      ctxt->disableSAX = 1;
786
0
    }
787
0
}
788
789
/**
790
 * xmlErrMsgStr:
791
 * @ctxt:  an XML parser context
792
 * @error:  the error number
793
 * @msg:  the error message
794
 * @val:  a string value
795
 *
796
 * Handle a non fatal parser error
797
 */
798
static void LIBXML_ATTR_FORMAT(3,0)
799
xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
800
                  const char *msg, const xmlChar * val)
801
0
{
802
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
803
0
        (ctxt->instate == XML_PARSER_EOF))
804
0
  return;
805
0
    if (ctxt != NULL)
806
0
  ctxt->errNo = error;
807
0
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
808
0
                    XML_FROM_PARSER, error, XML_ERR_ERROR,
809
0
                    NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
810
0
                    val);
811
0
}
812
813
/**
814
 * xmlNsErr:
815
 * @ctxt:  an XML parser context
816
 * @error:  the error number
817
 * @msg:  the message
818
 * @info1:  extra information string
819
 * @info2:  extra information string
820
 *
821
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
822
 */
823
static void LIBXML_ATTR_FORMAT(3,0)
824
xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
825
         const char *msg,
826
         const xmlChar * info1, const xmlChar * info2,
827
         const xmlChar * info3)
828
0
{
829
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
830
0
        (ctxt->instate == XML_PARSER_EOF))
831
0
  return;
832
0
    if (ctxt != NULL)
833
0
  ctxt->errNo = error;
834
0
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
835
0
                    XML_ERR_ERROR, NULL, 0, (const char *) info1,
836
0
                    (const char *) info2, (const char *) info3, 0, 0, msg,
837
0
                    info1, info2, info3);
838
0
    if (ctxt != NULL)
839
0
  ctxt->nsWellFormed = 0;
840
0
}
841
842
/**
843
 * xmlNsWarn
844
 * @ctxt:  an XML parser context
845
 * @error:  the error number
846
 * @msg:  the message
847
 * @info1:  extra information string
848
 * @info2:  extra information string
849
 *
850
 * Handle a namespace warning error
851
 */
852
static void LIBXML_ATTR_FORMAT(3,0)
853
xmlNsWarn(xmlParserCtxtPtr ctxt, xmlParserErrors error,
854
         const char *msg,
855
         const xmlChar * info1, const xmlChar * info2,
856
         const xmlChar * info3)
857
0
{
858
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
859
0
        (ctxt->instate == XML_PARSER_EOF))
860
0
  return;
861
0
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
862
0
                    XML_ERR_WARNING, NULL, 0, (const char *) info1,
863
0
                    (const char *) info2, (const char *) info3, 0, 0, msg,
864
0
                    info1, info2, info3);
865
0
}
866
867
/************************************************************************
868
 *                  *
869
 *    Library wide options          *
870
 *                  *
871
 ************************************************************************/
872
873
/**
874
  * xmlHasFeature:
875
  * @feature: the feature to be examined
876
  *
877
  * Examines if the library has been compiled with a given feature.
878
  *
879
  * Returns a non-zero value if the feature exist, otherwise zero.
880
  * Returns zero (0) if the feature does not exist or an unknown
881
  * unknown feature is requested, non-zero otherwise.
882
  */
883
int
884
xmlHasFeature(xmlFeature feature)
885
0
{
886
0
    switch (feature) {
887
0
  case XML_WITH_THREAD:
888
0
#ifdef LIBXML_THREAD_ENABLED
889
0
      return(1);
890
#else
891
      return(0);
892
#endif
893
0
        case XML_WITH_TREE:
894
0
#ifdef LIBXML_TREE_ENABLED
895
0
            return(1);
896
#else
897
            return(0);
898
#endif
899
0
        case XML_WITH_OUTPUT:
900
0
#ifdef LIBXML_OUTPUT_ENABLED
901
0
            return(1);
902
#else
903
            return(0);
904
#endif
905
0
        case XML_WITH_PUSH:
906
#ifdef LIBXML_PUSH_ENABLED
907
            return(1);
908
#else
909
0
            return(0);
910
0
#endif
911
0
        case XML_WITH_READER:
912
#ifdef LIBXML_READER_ENABLED
913
            return(1);
914
#else
915
0
            return(0);
916
0
#endif
917
0
        case XML_WITH_PATTERN:
918
0
#ifdef LIBXML_PATTERN_ENABLED
919
0
            return(1);
920
#else
921
            return(0);
922
#endif
923
0
        case XML_WITH_WRITER:
924
#ifdef LIBXML_WRITER_ENABLED
925
            return(1);
926
#else
927
0
            return(0);
928
0
#endif
929
0
        case XML_WITH_SAX1:
930
#ifdef LIBXML_SAX1_ENABLED
931
            return(1);
932
#else
933
0
            return(0);
934
0
#endif
935
0
        case XML_WITH_FTP:
936
#ifdef LIBXML_FTP_ENABLED
937
            return(1);
938
#else
939
0
            return(0);
940
0
#endif
941
0
        case XML_WITH_HTTP:
942
0
#ifdef LIBXML_HTTP_ENABLED
943
0
            return(1);
944
#else
945
            return(0);
946
#endif
947
0
        case XML_WITH_VALID:
948
#ifdef LIBXML_VALID_ENABLED
949
            return(1);
950
#else
951
0
            return(0);
952
0
#endif
953
0
        case XML_WITH_HTML:
954
0
#ifdef LIBXML_HTML_ENABLED
955
0
            return(1);
956
#else
957
            return(0);
958
#endif
959
0
        case XML_WITH_LEGACY:
960
#ifdef LIBXML_LEGACY_ENABLED
961
            return(1);
962
#else
963
0
            return(0);
964
0
#endif
965
0
        case XML_WITH_C14N:
966
#ifdef LIBXML_C14N_ENABLED
967
            return(1);
968
#else
969
0
            return(0);
970
0
#endif
971
0
        case XML_WITH_CATALOG:
972
0
#ifdef LIBXML_CATALOG_ENABLED
973
0
            return(1);
974
#else
975
            return(0);
976
#endif
977
0
        case XML_WITH_XPATH:
978
0
#ifdef LIBXML_XPATH_ENABLED
979
0
            return(1);
980
#else
981
            return(0);
982
#endif
983
0
        case XML_WITH_XPTR:
984
0
#ifdef LIBXML_XPTR_ENABLED
985
0
            return(1);
986
#else
987
            return(0);
988
#endif
989
0
        case XML_WITH_XINCLUDE:
990
0
#ifdef LIBXML_XINCLUDE_ENABLED
991
0
            return(1);
992
#else
993
            return(0);
994
#endif
995
0
        case XML_WITH_ICONV:
996
0
#ifdef LIBXML_ICONV_ENABLED
997
0
            return(1);
998
#else
999
            return(0);
1000
#endif
1001
0
        case XML_WITH_ISO8859X:
1002
0
#ifdef LIBXML_ISO8859X_ENABLED
1003
0
            return(1);
1004
#else
1005
            return(0);
1006
#endif
1007
0
        case XML_WITH_UNICODE:
1008
#ifdef LIBXML_UNICODE_ENABLED
1009
            return(1);
1010
#else
1011
0
            return(0);
1012
0
#endif
1013
0
        case XML_WITH_REGEXP:
1014
#ifdef LIBXML_REGEXP_ENABLED
1015
            return(1);
1016
#else
1017
0
            return(0);
1018
0
#endif
1019
0
        case XML_WITH_AUTOMATA:
1020
#ifdef LIBXML_AUTOMATA_ENABLED
1021
            return(1);
1022
#else
1023
0
            return(0);
1024
0
#endif
1025
0
        case XML_WITH_EXPR:
1026
#ifdef LIBXML_EXPR_ENABLED
1027
            return(1);
1028
#else
1029
0
            return(0);
1030
0
#endif
1031
0
        case XML_WITH_SCHEMAS:
1032
#ifdef LIBXML_SCHEMAS_ENABLED
1033
            return(1);
1034
#else
1035
0
            return(0);
1036
0
#endif
1037
0
        case XML_WITH_SCHEMATRON:
1038
#ifdef LIBXML_SCHEMATRON_ENABLED
1039
            return(1);
1040
#else
1041
0
            return(0);
1042
0
#endif
1043
0
        case XML_WITH_MODULES:
1044
0
#ifdef LIBXML_MODULES_ENABLED
1045
0
            return(1);
1046
#else
1047
            return(0);
1048
#endif
1049
0
        case XML_WITH_DEBUG:
1050
0
#ifdef LIBXML_DEBUG_ENABLED
1051
0
            return(1);
1052
#else
1053
            return(0);
1054
#endif
1055
0
        case XML_WITH_DEBUG_MEM:
1056
#ifdef DEBUG_MEMORY_LOCATION
1057
            return(1);
1058
#else
1059
0
            return(0);
1060
0
#endif
1061
0
        case XML_WITH_DEBUG_RUN:
1062
0
            return(0);
1063
0
        case XML_WITH_ZLIB:
1064
#ifdef LIBXML_ZLIB_ENABLED
1065
            return(1);
1066
#else
1067
0
            return(0);
1068
0
#endif
1069
0
        case XML_WITH_LZMA:
1070
#ifdef LIBXML_LZMA_ENABLED
1071
            return(1);
1072
#else
1073
0
            return(0);
1074
0
#endif
1075
0
        case XML_WITH_ICU:
1076
#ifdef LIBXML_ICU_ENABLED
1077
            return(1);
1078
#else
1079
0
            return(0);
1080
0
#endif
1081
0
        default:
1082
0
      break;
1083
0
     }
1084
0
     return(0);
1085
0
}
1086
1087
/************************************************************************
1088
 *                  *
1089
 *    SAX2 defaulted attributes handling      *
1090
 *                  *
1091
 ************************************************************************/
1092
1093
/**
1094
 * xmlDetectSAX2:
1095
 * @ctxt:  an XML parser context
1096
 *
1097
 * Do the SAX2 detection and specific initialization
1098
 */
1099
static void
1100
2
xmlDetectSAX2(xmlParserCtxtPtr ctxt) {
1101
2
    xmlSAXHandlerPtr sax;
1102
1103
    /* Avoid unused variable warning if features are disabled. */
1104
2
    (void) sax;
1105
1106
2
    if (ctxt == NULL) return;
1107
2
    sax = ctxt->sax;
1108
#ifdef LIBXML_SAX1_ENABLED
1109
    if ((sax) &&  (sax->initialized == XML_SAX2_MAGIC) &&
1110
        ((sax->startElementNs != NULL) ||
1111
         (sax->endElementNs != NULL) ||
1112
         ((sax->startElement == NULL) && (sax->endElement == NULL))))
1113
        ctxt->sax2 = 1;
1114
#else
1115
2
    ctxt->sax2 = 1;
1116
2
#endif /* LIBXML_SAX1_ENABLED */
1117
1118
2
    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
1119
2
    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
1120
2
    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
1121
2
    if ((ctxt->str_xml==NULL) || (ctxt->str_xmlns==NULL) ||
1122
2
    (ctxt->str_xml_ns == NULL)) {
1123
0
        xmlErrMemory(ctxt, NULL);
1124
0
    }
1125
2
}
1126
1127
typedef struct _xmlDefAttrs xmlDefAttrs;
1128
typedef xmlDefAttrs *xmlDefAttrsPtr;
1129
struct _xmlDefAttrs {
1130
    int nbAttrs;  /* number of defaulted attributes on that element */
1131
    int maxAttrs;       /* the size of the array */
1132
#if __STDC_VERSION__ >= 199901L
1133
    /* Using a C99 flexible array member avoids UBSan errors. */
1134
    const xmlChar *values[]; /* array of localname/prefix/values/external */
1135
#else
1136
    const xmlChar *values[5];
1137
#endif
1138
};
1139
1140
/**
1141
 * xmlAttrNormalizeSpace:
1142
 * @src: the source string
1143
 * @dst: the target string
1144
 *
1145
 * Normalize the space in non CDATA attribute values:
1146
 * If the attribute type is not CDATA, then the XML processor MUST further
1147
 * process the normalized attribute value by discarding any leading and
1148
 * trailing space (#x20) characters, and by replacing sequences of space
1149
 * (#x20) characters by a single space (#x20) character.
1150
 * Note that the size of dst need to be at least src, and if one doesn't need
1151
 * to preserve dst (and it doesn't come from a dictionary or read-only) then
1152
 * passing src as dst is just fine.
1153
 *
1154
 * Returns a pointer to the normalized value (dst) or NULL if no conversion
1155
 *         is needed.
1156
 */
1157
static xmlChar *
1158
xmlAttrNormalizeSpace(const xmlChar *src, xmlChar *dst)
1159
0
{
1160
0
    if ((src == NULL) || (dst == NULL))
1161
0
        return(NULL);
1162
1163
0
    while (*src == 0x20) src++;
1164
0
    while (*src != 0) {
1165
0
  if (*src == 0x20) {
1166
0
      while (*src == 0x20) src++;
1167
0
      if (*src != 0)
1168
0
    *dst++ = 0x20;
1169
0
  } else {
1170
0
      *dst++ = *src++;
1171
0
  }
1172
0
    }
1173
0
    *dst = 0;
1174
0
    if (dst == src)
1175
0
       return(NULL);
1176
0
    return(dst);
1177
0
}
1178
1179
/**
1180
 * xmlAttrNormalizeSpace2:
1181
 * @src: the source string
1182
 *
1183
 * Normalize the space in non CDATA attribute values, a slightly more complex
1184
 * front end to avoid allocation problems when running on attribute values
1185
 * coming from the input.
1186
 *
1187
 * Returns a pointer to the normalized value (dst) or NULL if no conversion
1188
 *         is needed.
1189
 */
1190
static const xmlChar *
1191
xmlAttrNormalizeSpace2(xmlParserCtxtPtr ctxt, xmlChar *src, int *len)
1192
0
{
1193
0
    int i;
1194
0
    int remove_head = 0;
1195
0
    int need_realloc = 0;
1196
0
    const xmlChar *cur;
1197
1198
0
    if ((ctxt == NULL) || (src == NULL) || (len == NULL))
1199
0
        return(NULL);
1200
0
    i = *len;
1201
0
    if (i <= 0)
1202
0
        return(NULL);
1203
1204
0
    cur = src;
1205
0
    while (*cur == 0x20) {
1206
0
        cur++;
1207
0
  remove_head++;
1208
0
    }
1209
0
    while (*cur != 0) {
1210
0
  if (*cur == 0x20) {
1211
0
      cur++;
1212
0
      if ((*cur == 0x20) || (*cur == 0)) {
1213
0
          need_realloc = 1;
1214
0
    break;
1215
0
      }
1216
0
  } else
1217
0
      cur++;
1218
0
    }
1219
0
    if (need_realloc) {
1220
0
        xmlChar *ret;
1221
1222
0
  ret = xmlStrndup(src + remove_head, i - remove_head + 1);
1223
0
  if (ret == NULL) {
1224
0
      xmlErrMemory(ctxt, NULL);
1225
0
      return(NULL);
1226
0
  }
1227
0
  xmlAttrNormalizeSpace(ret, ret);
1228
0
  *len = strlen((const char *)ret);
1229
0
        return(ret);
1230
0
    } else if (remove_head) {
1231
0
        *len -= remove_head;
1232
0
        memmove(src, src + remove_head, 1 + *len);
1233
0
  return(src);
1234
0
    }
1235
0
    return(NULL);
1236
0
}
1237
1238
/**
1239
 * xmlAddDefAttrs:
1240
 * @ctxt:  an XML parser context
1241
 * @fullname:  the element fullname
1242
 * @fullattr:  the attribute fullname
1243
 * @value:  the attribute value
1244
 *
1245
 * Add a defaulted attribute for an element
1246
 */
1247
static void
1248
xmlAddDefAttrs(xmlParserCtxtPtr ctxt,
1249
               const xmlChar *fullname,
1250
               const xmlChar *fullattr,
1251
0
               const xmlChar *value) {
1252
0
    xmlDefAttrsPtr defaults;
1253
0
    int len;
1254
0
    const xmlChar *name;
1255
0
    const xmlChar *prefix;
1256
1257
    /*
1258
     * Allows to detect attribute redefinitions
1259
     */
1260
0
    if (ctxt->attsSpecial != NULL) {
1261
0
        if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL)
1262
0
      return;
1263
0
    }
1264
1265
0
    if (ctxt->attsDefault == NULL) {
1266
0
        ctxt->attsDefault = xmlHashCreateDict(10, ctxt->dict);
1267
0
  if (ctxt->attsDefault == NULL)
1268
0
      goto mem_error;
1269
0
    }
1270
1271
    /*
1272
     * split the element name into prefix:localname , the string found
1273
     * are within the DTD and then not associated to namespace names.
1274
     */
1275
0
    name = xmlSplitQName3(fullname, &len);
1276
0
    if (name == NULL) {
1277
0
        name = xmlDictLookup(ctxt->dict, fullname, -1);
1278
0
  prefix = NULL;
1279
0
    } else {
1280
0
        name = xmlDictLookup(ctxt->dict, name, -1);
1281
0
  prefix = xmlDictLookup(ctxt->dict, fullname, len);
1282
0
    }
1283
1284
    /*
1285
     * make sure there is some storage
1286
     */
1287
0
    defaults = xmlHashLookup2(ctxt->attsDefault, name, prefix);
1288
0
    if (defaults == NULL) {
1289
0
        defaults = (xmlDefAttrsPtr) xmlMalloc(sizeof(xmlDefAttrs) +
1290
0
                     (4 * 5) * sizeof(const xmlChar *));
1291
0
  if (defaults == NULL)
1292
0
      goto mem_error;
1293
0
  defaults->nbAttrs = 0;
1294
0
  defaults->maxAttrs = 4;
1295
0
  if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix,
1296
0
                          defaults, NULL) < 0) {
1297
0
      xmlFree(defaults);
1298
0
      goto mem_error;
1299
0
  }
1300
0
    } else if (defaults->nbAttrs >= defaults->maxAttrs) {
1301
0
        xmlDefAttrsPtr temp;
1302
1303
0
        temp = (xmlDefAttrsPtr) xmlRealloc(defaults, sizeof(xmlDefAttrs) +
1304
0
           (2 * defaults->maxAttrs * 5) * sizeof(const xmlChar *));
1305
0
  if (temp == NULL)
1306
0
      goto mem_error;
1307
0
  defaults = temp;
1308
0
  defaults->maxAttrs *= 2;
1309
0
  if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix,
1310
0
                          defaults, NULL) < 0) {
1311
0
      xmlFree(defaults);
1312
0
      goto mem_error;
1313
0
  }
1314
0
    }
1315
1316
    /*
1317
     * Split the element name into prefix:localname , the string found
1318
     * are within the DTD and hen not associated to namespace names.
1319
     */
1320
0
    name = xmlSplitQName3(fullattr, &len);
1321
0
    if (name == NULL) {
1322
0
        name = xmlDictLookup(ctxt->dict, fullattr, -1);
1323
0
  prefix = NULL;
1324
0
    } else {
1325
0
        name = xmlDictLookup(ctxt->dict, name, -1);
1326
0
  prefix = xmlDictLookup(ctxt->dict, fullattr, len);
1327
0
    }
1328
1329
0
    defaults->values[5 * defaults->nbAttrs] = name;
1330
0
    defaults->values[5 * defaults->nbAttrs + 1] = prefix;
1331
    /* intern the string and precompute the end */
1332
0
    len = xmlStrlen(value);
1333
0
    value = xmlDictLookup(ctxt->dict, value, len);
1334
0
    defaults->values[5 * defaults->nbAttrs + 2] = value;
1335
0
    defaults->values[5 * defaults->nbAttrs + 3] = value + len;
1336
0
    if (ctxt->external)
1337
0
        defaults->values[5 * defaults->nbAttrs + 4] = BAD_CAST "external";
1338
0
    else
1339
0
        defaults->values[5 * defaults->nbAttrs + 4] = NULL;
1340
0
    defaults->nbAttrs++;
1341
1342
0
    return;
1343
1344
0
mem_error:
1345
0
    xmlErrMemory(ctxt, NULL);
1346
0
    return;
1347
0
}
1348
1349
/**
1350
 * xmlAddSpecialAttr:
1351
 * @ctxt:  an XML parser context
1352
 * @fullname:  the element fullname
1353
 * @fullattr:  the attribute fullname
1354
 * @type:  the attribute type
1355
 *
1356
 * Register this attribute type
1357
 */
1358
static void
1359
xmlAddSpecialAttr(xmlParserCtxtPtr ctxt,
1360
      const xmlChar *fullname,
1361
      const xmlChar *fullattr,
1362
      int type)
1363
0
{
1364
0
    if (ctxt->attsSpecial == NULL) {
1365
0
        ctxt->attsSpecial = xmlHashCreateDict(10, ctxt->dict);
1366
0
  if (ctxt->attsSpecial == NULL)
1367
0
      goto mem_error;
1368
0
    }
1369
1370
0
    if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL)
1371
0
        return;
1372
1373
0
    xmlHashAddEntry2(ctxt->attsSpecial, fullname, fullattr,
1374
0
                     (void *) (ptrdiff_t) type);
1375
0
    return;
1376
1377
0
mem_error:
1378
0
    xmlErrMemory(ctxt, NULL);
1379
0
    return;
1380
0
}
1381
1382
/**
1383
 * xmlCleanSpecialAttrCallback:
1384
 *
1385
 * Removes CDATA attributes from the special attribute table
1386
 */
1387
static void
1388
xmlCleanSpecialAttrCallback(void *payload, void *data,
1389
                            const xmlChar *fullname, const xmlChar *fullattr,
1390
0
                            const xmlChar *unused ATTRIBUTE_UNUSED) {
1391
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) data;
1392
1393
0
    if (((ptrdiff_t) payload) == XML_ATTRIBUTE_CDATA) {
1394
0
        xmlHashRemoveEntry2(ctxt->attsSpecial, fullname, fullattr, NULL);
1395
0
    }
1396
0
}
1397
1398
/**
1399
 * xmlCleanSpecialAttr:
1400
 * @ctxt:  an XML parser context
1401
 *
1402
 * Trim the list of attributes defined to remove all those of type
1403
 * CDATA as they are not special. This call should be done when finishing
1404
 * to parse the DTD and before starting to parse the document root.
1405
 */
1406
static void
1407
xmlCleanSpecialAttr(xmlParserCtxtPtr ctxt)
1408
0
{
1409
0
    if (ctxt->attsSpecial == NULL)
1410
0
        return;
1411
1412
0
    xmlHashScanFull(ctxt->attsSpecial, xmlCleanSpecialAttrCallback, ctxt);
1413
1414
0
    if (xmlHashSize(ctxt->attsSpecial) == 0) {
1415
0
        xmlHashFree(ctxt->attsSpecial, NULL);
1416
0
        ctxt->attsSpecial = NULL;
1417
0
    }
1418
0
    return;
1419
0
}
1420
1421
/**
1422
 * xmlCheckLanguageID:
1423
 * @lang:  pointer to the string value
1424
 *
1425
 * Checks that the value conforms to the LanguageID production:
1426
 *
1427
 * NOTE: this is somewhat deprecated, those productions were removed from
1428
 *       the XML Second edition.
1429
 *
1430
 * [33] LanguageID ::= Langcode ('-' Subcode)*
1431
 * [34] Langcode ::= ISO639Code |  IanaCode |  UserCode
1432
 * [35] ISO639Code ::= ([a-z] | [A-Z]) ([a-z] | [A-Z])
1433
 * [36] IanaCode ::= ('i' | 'I') '-' ([a-z] | [A-Z])+
1434
 * [37] UserCode ::= ('x' | 'X') '-' ([a-z] | [A-Z])+
1435
 * [38] Subcode ::= ([a-z] | [A-Z])+
1436
 *
1437
 * The current REC reference the successors of RFC 1766, currently 5646
1438
 *
1439
 * http://www.rfc-editor.org/rfc/rfc5646.txt
1440
 * langtag       = language
1441
 *                 ["-" script]
1442
 *                 ["-" region]
1443
 *                 *("-" variant)
1444
 *                 *("-" extension)
1445
 *                 ["-" privateuse]
1446
 * language      = 2*3ALPHA            ; shortest ISO 639 code
1447
 *                 ["-" extlang]       ; sometimes followed by
1448
 *                                     ; extended language subtags
1449
 *               / 4ALPHA              ; or reserved for future use
1450
 *               / 5*8ALPHA            ; or registered language subtag
1451
 *
1452
 * extlang       = 3ALPHA              ; selected ISO 639 codes
1453
 *                 *2("-" 3ALPHA)      ; permanently reserved
1454
 *
1455
 * script        = 4ALPHA              ; ISO 15924 code
1456
 *
1457
 * region        = 2ALPHA              ; ISO 3166-1 code
1458
 *               / 3DIGIT              ; UN M.49 code
1459
 *
1460
 * variant       = 5*8alphanum         ; registered variants
1461
 *               / (DIGIT 3alphanum)
1462
 *
1463
 * extension     = singleton 1*("-" (2*8alphanum))
1464
 *
1465
 *                                     ; Single alphanumerics
1466
 *                                     ; "x" reserved for private use
1467
 * singleton     = DIGIT               ; 0 - 9
1468
 *               / %x41-57             ; A - W
1469
 *               / %x59-5A             ; Y - Z
1470
 *               / %x61-77             ; a - w
1471
 *               / %x79-7A             ; y - z
1472
 *
1473
 * it sounds right to still allow Irregular i-xxx IANA and user codes too
1474
 * The parser below doesn't try to cope with extension or privateuse
1475
 * that could be added but that's not interoperable anyway
1476
 *
1477
 * Returns 1 if correct 0 otherwise
1478
 **/
1479
int
1480
xmlCheckLanguageID(const xmlChar * lang)
1481
0
{
1482
0
    const xmlChar *cur = lang, *nxt;
1483
1484
0
    if (cur == NULL)
1485
0
        return (0);
1486
0
    if (((cur[0] == 'i') && (cur[1] == '-')) ||
1487
0
        ((cur[0] == 'I') && (cur[1] == '-')) ||
1488
0
        ((cur[0] == 'x') && (cur[1] == '-')) ||
1489
0
        ((cur[0] == 'X') && (cur[1] == '-'))) {
1490
        /*
1491
         * Still allow IANA code and user code which were coming
1492
         * from the previous version of the XML-1.0 specification
1493
         * it's deprecated but we should not fail
1494
         */
1495
0
        cur += 2;
1496
0
        while (((cur[0] >= 'A') && (cur[0] <= 'Z')) ||
1497
0
               ((cur[0] >= 'a') && (cur[0] <= 'z')))
1498
0
            cur++;
1499
0
        return(cur[0] == 0);
1500
0
    }
1501
0
    nxt = cur;
1502
0
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1503
0
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1504
0
           nxt++;
1505
0
    if (nxt - cur >= 4) {
1506
        /*
1507
         * Reserved
1508
         */
1509
0
        if ((nxt - cur > 8) || (nxt[0] != 0))
1510
0
            return(0);
1511
0
        return(1);
1512
0
    }
1513
0
    if (nxt - cur < 2)
1514
0
        return(0);
1515
    /* we got an ISO 639 code */
1516
0
    if (nxt[0] == 0)
1517
0
        return(1);
1518
0
    if (nxt[0] != '-')
1519
0
        return(0);
1520
1521
0
    nxt++;
1522
0
    cur = nxt;
1523
    /* now we can have extlang or script or region or variant */
1524
0
    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1525
0
        goto region_m49;
1526
1527
0
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1528
0
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1529
0
           nxt++;
1530
0
    if (nxt - cur == 4)
1531
0
        goto script;
1532
0
    if (nxt - cur == 2)
1533
0
        goto region;
1534
0
    if ((nxt - cur >= 5) && (nxt - cur <= 8))
1535
0
        goto variant;
1536
0
    if (nxt - cur != 3)
1537
0
        return(0);
1538
    /* we parsed an extlang */
1539
0
    if (nxt[0] == 0)
1540
0
        return(1);
1541
0
    if (nxt[0] != '-')
1542
0
        return(0);
1543
1544
0
    nxt++;
1545
0
    cur = nxt;
1546
    /* now we can have script or region or variant */
1547
0
    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1548
0
        goto region_m49;
1549
1550
0
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1551
0
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1552
0
           nxt++;
1553
0
    if (nxt - cur == 2)
1554
0
        goto region;
1555
0
    if ((nxt - cur >= 5) && (nxt - cur <= 8))
1556
0
        goto variant;
1557
0
    if (nxt - cur != 4)
1558
0
        return(0);
1559
    /* we parsed a script */
1560
0
script:
1561
0
    if (nxt[0] == 0)
1562
0
        return(1);
1563
0
    if (nxt[0] != '-')
1564
0
        return(0);
1565
1566
0
    nxt++;
1567
0
    cur = nxt;
1568
    /* now we can have region or variant */
1569
0
    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1570
0
        goto region_m49;
1571
1572
0
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1573
0
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1574
0
           nxt++;
1575
1576
0
    if ((nxt - cur >= 5) && (nxt - cur <= 8))
1577
0
        goto variant;
1578
0
    if (nxt - cur != 2)
1579
0
        return(0);
1580
    /* we parsed a region */
1581
0
region:
1582
0
    if (nxt[0] == 0)
1583
0
        return(1);
1584
0
    if (nxt[0] != '-')
1585
0
        return(0);
1586
1587
0
    nxt++;
1588
0
    cur = nxt;
1589
    /* now we can just have a variant */
1590
0
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1591
0
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1592
0
           nxt++;
1593
1594
0
    if ((nxt - cur < 5) || (nxt - cur > 8))
1595
0
        return(0);
1596
1597
    /* we parsed a variant */
1598
0
variant:
1599
0
    if (nxt[0] == 0)
1600
0
        return(1);
1601
0
    if (nxt[0] != '-')
1602
0
        return(0);
1603
    /* extensions and private use subtags not checked */
1604
0
    return (1);
1605
1606
0
region_m49:
1607
0
    if (((nxt[1] >= '0') && (nxt[1] <= '9')) &&
1608
0
        ((nxt[2] >= '0') && (nxt[2] <= '9'))) {
1609
0
        nxt += 3;
1610
0
        goto region;
1611
0
    }
1612
0
    return(0);
1613
0
}
1614
1615
/************************************************************************
1616
 *                  *
1617
 *    Parser stacks related functions and macros    *
1618
 *                  *
1619
 ************************************************************************/
1620
1621
static xmlEntityPtr xmlParseStringEntityRef(xmlParserCtxtPtr ctxt,
1622
                                            const xmlChar ** str);
1623
1624
#ifdef SAX2
1625
/**
1626
 * nsPush:
1627
 * @ctxt:  an XML parser context
1628
 * @prefix:  the namespace prefix or NULL
1629
 * @URL:  the namespace name
1630
 *
1631
 * Pushes a new parser namespace on top of the ns stack
1632
 *
1633
 * Returns -1 in case of error, -2 if the namespace should be discarded
1634
 *     and the index in the stack otherwise.
1635
 */
1636
static int
1637
nsPush(xmlParserCtxtPtr ctxt, const xmlChar *prefix, const xmlChar *URL)
1638
6
{
1639
6
    if (ctxt->options & XML_PARSE_NSCLEAN) {
1640
0
        int i;
1641
0
  for (i = ctxt->nsNr - 2;i >= 0;i -= 2) {
1642
0
      if (ctxt->nsTab[i] == prefix) {
1643
    /* in scope */
1644
0
          if (ctxt->nsTab[i + 1] == URL)
1645
0
        return(-2);
1646
    /* out of scope keep it */
1647
0
    break;
1648
0
      }
1649
0
  }
1650
0
    }
1651
6
    if ((ctxt->nsMax == 0) || (ctxt->nsTab == NULL)) {
1652
2
  ctxt->nsMax = 10;
1653
2
  ctxt->nsNr = 0;
1654
2
  ctxt->nsTab = (const xmlChar **)
1655
2
                xmlMalloc(ctxt->nsMax * sizeof(xmlChar *));
1656
2
  if (ctxt->nsTab == NULL) {
1657
0
      xmlErrMemory(ctxt, NULL);
1658
0
      ctxt->nsMax = 0;
1659
0
            return (-1);
1660
0
  }
1661
4
    } else if (ctxt->nsNr >= ctxt->nsMax) {
1662
0
        const xmlChar ** tmp;
1663
0
        ctxt->nsMax *= 2;
1664
0
        tmp = (const xmlChar **) xmlRealloc((char *) ctxt->nsTab,
1665
0
            ctxt->nsMax * sizeof(ctxt->nsTab[0]));
1666
0
        if (tmp == NULL) {
1667
0
            xmlErrMemory(ctxt, NULL);
1668
0
      ctxt->nsMax /= 2;
1669
0
            return (-1);
1670
0
        }
1671
0
  ctxt->nsTab = tmp;
1672
0
    }
1673
6
    ctxt->nsTab[ctxt->nsNr++] = prefix;
1674
6
    ctxt->nsTab[ctxt->nsNr++] = URL;
1675
6
    return (ctxt->nsNr);
1676
6
}
1677
/**
1678
 * nsPop:
1679
 * @ctxt: an XML parser context
1680
 * @nr:  the number to pop
1681
 *
1682
 * Pops the top @nr parser prefix/namespace from the ns stack
1683
 *
1684
 * Returns the number of namespaces removed
1685
 */
1686
static int
1687
nsPop(xmlParserCtxtPtr ctxt, int nr)
1688
6
{
1689
6
    int i;
1690
1691
6
    if (ctxt->nsTab == NULL) return(0);
1692
6
    if (ctxt->nsNr < nr) {
1693
0
        xmlGenericError(xmlGenericErrorContext, "Pbm popping %d NS\n", nr);
1694
0
        nr = ctxt->nsNr;
1695
0
    }
1696
6
    if (ctxt->nsNr <= 0)
1697
0
        return (0);
1698
1699
18
    for (i = 0;i < nr;i++) {
1700
12
         ctxt->nsNr--;
1701
12
   ctxt->nsTab[ctxt->nsNr] = NULL;
1702
12
    }
1703
6
    return(nr);
1704
6
}
1705
#endif
1706
1707
static int
1708
2
xmlCtxtGrowAttrs(xmlParserCtxtPtr ctxt, int nr) {
1709
2
    const xmlChar **atts;
1710
2
    int *attallocs;
1711
2
    int maxatts;
1712
1713
2
    if (ctxt->atts == NULL) {
1714
2
  maxatts = 55; /* allow for 10 attrs by default */
1715
2
  atts = (const xmlChar **)
1716
2
         xmlMalloc(maxatts * sizeof(xmlChar *));
1717
2
  if (atts == NULL) goto mem_error;
1718
2
  ctxt->atts = atts;
1719
2
  attallocs = (int *) xmlMalloc((maxatts / 5) * sizeof(int));
1720
2
  if (attallocs == NULL) goto mem_error;
1721
2
  ctxt->attallocs = attallocs;
1722
2
  ctxt->maxatts = maxatts;
1723
2
    } else if (nr + 5 > ctxt->maxatts) {
1724
0
  maxatts = (nr + 5) * 2;
1725
0
  atts = (const xmlChar **) xmlRealloc((void *) ctxt->atts,
1726
0
             maxatts * sizeof(const xmlChar *));
1727
0
  if (atts == NULL) goto mem_error;
1728
0
  ctxt->atts = atts;
1729
0
  attallocs = (int *) xmlRealloc((void *) ctxt->attallocs,
1730
0
                               (maxatts / 5) * sizeof(int));
1731
0
  if (attallocs == NULL) goto mem_error;
1732
0
  ctxt->attallocs = attallocs;
1733
0
  ctxt->maxatts = maxatts;
1734
0
    }
1735
2
    return(ctxt->maxatts);
1736
0
mem_error:
1737
0
    xmlErrMemory(ctxt, NULL);
1738
0
    return(-1);
1739
2
}
1740
1741
/**
1742
 * inputPush:
1743
 * @ctxt:  an XML parser context
1744
 * @value:  the parser input
1745
 *
1746
 * Pushes a new parser input on top of the input stack
1747
 *
1748
 * Returns -1 in case of error, the index in the stack otherwise
1749
 */
1750
int
1751
inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value)
1752
2
{
1753
2
    if ((ctxt == NULL) || (value == NULL))
1754
0
        return(-1);
1755
2
    if (ctxt->inputNr >= ctxt->inputMax) {
1756
0
        ctxt->inputMax *= 2;
1757
0
        ctxt->inputTab =
1758
0
            (xmlParserInputPtr *) xmlRealloc(ctxt->inputTab,
1759
0
                                             ctxt->inputMax *
1760
0
                                             sizeof(ctxt->inputTab[0]));
1761
0
        if (ctxt->inputTab == NULL) {
1762
0
            xmlErrMemory(ctxt, NULL);
1763
0
      ctxt->inputMax /= 2;
1764
0
            return (-1);
1765
0
        }
1766
0
    }
1767
2
    ctxt->inputTab[ctxt->inputNr] = value;
1768
2
    ctxt->input = value;
1769
2
    return (ctxt->inputNr++);
1770
2
}
1771
/**
1772
 * inputPop:
1773
 * @ctxt: an XML parser context
1774
 *
1775
 * Pops the top parser input from the input stack
1776
 *
1777
 * Returns the input just removed
1778
 */
1779
xmlParserInputPtr
1780
inputPop(xmlParserCtxtPtr ctxt)
1781
6
{
1782
6
    xmlParserInputPtr ret;
1783
1784
6
    if (ctxt == NULL)
1785
0
        return(NULL);
1786
6
    if (ctxt->inputNr <= 0)
1787
4
        return (NULL);
1788
2
    ctxt->inputNr--;
1789
2
    if (ctxt->inputNr > 0)
1790
0
        ctxt->input = ctxt->inputTab[ctxt->inputNr - 1];
1791
2
    else
1792
2
        ctxt->input = NULL;
1793
2
    ret = ctxt->inputTab[ctxt->inputNr];
1794
2
    ctxt->inputTab[ctxt->inputNr] = NULL;
1795
2
    return (ret);
1796
6
}
1797
/**
1798
 * nodePush:
1799
 * @ctxt:  an XML parser context
1800
 * @value:  the element node
1801
 *
1802
 * Pushes a new element node on top of the node stack
1803
 *
1804
 * Returns -1 in case of error, the index in the stack otherwise
1805
 */
1806
int
1807
nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value)
1808
24
{
1809
24
    if (ctxt == NULL) return(0);
1810
24
    if (ctxt->nodeNr >= ctxt->nodeMax) {
1811
0
        xmlNodePtr *tmp;
1812
1813
0
  tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
1814
0
                                      ctxt->nodeMax * 2 *
1815
0
                                      sizeof(ctxt->nodeTab[0]));
1816
0
        if (tmp == NULL) {
1817
0
            xmlErrMemory(ctxt, NULL);
1818
0
            return (-1);
1819
0
        }
1820
0
        ctxt->nodeTab = tmp;
1821
0
  ctxt->nodeMax *= 2;
1822
0
    }
1823
24
    if ((((unsigned int) ctxt->nodeNr) > xmlParserMaxDepth) &&
1824
24
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
1825
0
  xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
1826
0
     "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
1827
0
        xmlParserMaxDepth);
1828
0
  xmlHaltParser(ctxt);
1829
0
  return(-1);
1830
0
    }
1831
24
    ctxt->nodeTab[ctxt->nodeNr] = value;
1832
24
    ctxt->node = value;
1833
24
    return (ctxt->nodeNr++);
1834
24
}
1835
1836
/**
1837
 * nodePop:
1838
 * @ctxt: an XML parser context
1839
 *
1840
 * Pops the top element node from the node stack
1841
 *
1842
 * Returns the node just removed
1843
 */
1844
xmlNodePtr
1845
nodePop(xmlParserCtxtPtr ctxt)
1846
24
{
1847
24
    xmlNodePtr ret;
1848
1849
24
    if (ctxt == NULL) return(NULL);
1850
24
    if (ctxt->nodeNr <= 0)
1851
0
        return (NULL);
1852
24
    ctxt->nodeNr--;
1853
24
    if (ctxt->nodeNr > 0)
1854
22
        ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1];
1855
2
    else
1856
2
        ctxt->node = NULL;
1857
24
    ret = ctxt->nodeTab[ctxt->nodeNr];
1858
24
    ctxt->nodeTab[ctxt->nodeNr] = NULL;
1859
24
    return (ret);
1860
24
}
1861
1862
/**
1863
 * nameNsPush:
1864
 * @ctxt:  an XML parser context
1865
 * @value:  the element name
1866
 * @prefix:  the element prefix
1867
 * @URI:  the element namespace name
1868
 * @line:  the current line number for error messages
1869
 * @nsNr:  the number of namespaces pushed on the namespace table
1870
 *
1871
 * Pushes a new element name/prefix/URL on top of the name stack
1872
 *
1873
 * Returns -1 in case of error, the index in the stack otherwise
1874
 */
1875
static int
1876
nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
1877
           const xmlChar *prefix, const xmlChar *URI, int line, int nsNr)
1878
24
{
1879
24
    xmlStartTag *tag;
1880
1881
24
    if (ctxt->nameNr >= ctxt->nameMax) {
1882
0
        const xmlChar * *tmp;
1883
0
        xmlStartTag *tmp2;
1884
0
        ctxt->nameMax *= 2;
1885
0
        tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
1886
0
                                    ctxt->nameMax *
1887
0
                                    sizeof(ctxt->nameTab[0]));
1888
0
        if (tmp == NULL) {
1889
0
      ctxt->nameMax /= 2;
1890
0
      goto mem_error;
1891
0
        }
1892
0
  ctxt->nameTab = tmp;
1893
0
        tmp2 = (xmlStartTag *) xmlRealloc((void * *)ctxt->pushTab,
1894
0
                                    ctxt->nameMax *
1895
0
                                    sizeof(ctxt->pushTab[0]));
1896
0
        if (tmp2 == NULL) {
1897
0
      ctxt->nameMax /= 2;
1898
0
      goto mem_error;
1899
0
        }
1900
0
  ctxt->pushTab = tmp2;
1901
24
    } else if (ctxt->pushTab == NULL) {
1902
2
        ctxt->pushTab = (xmlStartTag *) xmlMalloc(ctxt->nameMax *
1903
2
                                            sizeof(ctxt->pushTab[0]));
1904
2
        if (ctxt->pushTab == NULL)
1905
0
            goto mem_error;
1906
2
    }
1907
24
    ctxt->nameTab[ctxt->nameNr] = value;
1908
24
    ctxt->name = value;
1909
24
    tag = &ctxt->pushTab[ctxt->nameNr];
1910
24
    tag->prefix = prefix;
1911
24
    tag->URI = URI;
1912
24
    tag->line = line;
1913
24
    tag->nsNr = nsNr;
1914
24
    return (ctxt->nameNr++);
1915
0
mem_error:
1916
0
    xmlErrMemory(ctxt, NULL);
1917
0
    return (-1);
1918
24
}
1919
#ifdef LIBXML_PUSH_ENABLED
1920
/**
1921
 * nameNsPop:
1922
 * @ctxt: an XML parser context
1923
 *
1924
 * Pops the top element/prefix/URI name from the name stack
1925
 *
1926
 * Returns the name just removed
1927
 */
1928
static const xmlChar *
1929
nameNsPop(xmlParserCtxtPtr ctxt)
1930
{
1931
    const xmlChar *ret;
1932
1933
    if (ctxt->nameNr <= 0)
1934
        return (NULL);
1935
    ctxt->nameNr--;
1936
    if (ctxt->nameNr > 0)
1937
        ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
1938
    else
1939
        ctxt->name = NULL;
1940
    ret = ctxt->nameTab[ctxt->nameNr];
1941
    ctxt->nameTab[ctxt->nameNr] = NULL;
1942
    return (ret);
1943
}
1944
#endif /* LIBXML_PUSH_ENABLED */
1945
1946
/**
1947
 * namePush:
1948
 * @ctxt:  an XML parser context
1949
 * @value:  the element name
1950
 *
1951
 * Pushes a new element name on top of the name stack
1952
 *
1953
 * Returns -1 in case of error, the index in the stack otherwise
1954
 */
1955
int
1956
namePush(xmlParserCtxtPtr ctxt, const xmlChar * value)
1957
0
{
1958
0
    if (ctxt == NULL) return (-1);
1959
1960
0
    if (ctxt->nameNr >= ctxt->nameMax) {
1961
0
        const xmlChar * *tmp;
1962
0
        tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
1963
0
                                    ctxt->nameMax * 2 *
1964
0
                                    sizeof(ctxt->nameTab[0]));
1965
0
        if (tmp == NULL) {
1966
0
      goto mem_error;
1967
0
        }
1968
0
  ctxt->nameTab = tmp;
1969
0
        ctxt->nameMax *= 2;
1970
0
    }
1971
0
    ctxt->nameTab[ctxt->nameNr] = value;
1972
0
    ctxt->name = value;
1973
0
    return (ctxt->nameNr++);
1974
0
mem_error:
1975
0
    xmlErrMemory(ctxt, NULL);
1976
0
    return (-1);
1977
0
}
1978
/**
1979
 * namePop:
1980
 * @ctxt: an XML parser context
1981
 *
1982
 * Pops the top element name from the name stack
1983
 *
1984
 * Returns the name just removed
1985
 */
1986
const xmlChar *
1987
namePop(xmlParserCtxtPtr ctxt)
1988
24
{
1989
24
    const xmlChar *ret;
1990
1991
24
    if ((ctxt == NULL) || (ctxt->nameNr <= 0))
1992
0
        return (NULL);
1993
24
    ctxt->nameNr--;
1994
24
    if (ctxt->nameNr > 0)
1995
22
        ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
1996
2
    else
1997
2
        ctxt->name = NULL;
1998
24
    ret = ctxt->nameTab[ctxt->nameNr];
1999
24
    ctxt->nameTab[ctxt->nameNr] = NULL;
2000
24
    return (ret);
2001
24
}
2002
2003
24
static int spacePush(xmlParserCtxtPtr ctxt, int val) {
2004
24
    if (ctxt->spaceNr >= ctxt->spaceMax) {
2005
0
        int *tmp;
2006
2007
0
  ctxt->spaceMax *= 2;
2008
0
        tmp = (int *) xmlRealloc(ctxt->spaceTab,
2009
0
                           ctxt->spaceMax * sizeof(ctxt->spaceTab[0]));
2010
0
        if (tmp == NULL) {
2011
0
      xmlErrMemory(ctxt, NULL);
2012
0
      ctxt->spaceMax /=2;
2013
0
      return(-1);
2014
0
  }
2015
0
  ctxt->spaceTab = tmp;
2016
0
    }
2017
24
    ctxt->spaceTab[ctxt->spaceNr] = val;
2018
24
    ctxt->space = &ctxt->spaceTab[ctxt->spaceNr];
2019
24
    return(ctxt->spaceNr++);
2020
24
}
2021
2022
24
static int spacePop(xmlParserCtxtPtr ctxt) {
2023
24
    int ret;
2024
24
    if (ctxt->spaceNr <= 0) return(0);
2025
24
    ctxt->spaceNr--;
2026
24
    if (ctxt->spaceNr > 0)
2027
24
  ctxt->space = &ctxt->spaceTab[ctxt->spaceNr - 1];
2028
0
    else
2029
0
        ctxt->space = &ctxt->spaceTab[0];
2030
24
    ret = ctxt->spaceTab[ctxt->spaceNr];
2031
24
    ctxt->spaceTab[ctxt->spaceNr] = -1;
2032
24
    return(ret);
2033
24
}
2034
2035
/*
2036
 * Macros for accessing the content. Those should be used only by the parser,
2037
 * and not exported.
2038
 *
2039
 * Dirty macros, i.e. one often need to make assumption on the context to
2040
 * use them
2041
 *
2042
 *   CUR_PTR return the current pointer to the xmlChar to be parsed.
2043
 *           To be used with extreme caution since operations consuming
2044
 *           characters may move the input buffer to a different location !
2045
 *   CUR     returns the current xmlChar value, i.e. a 8 bit value if compiled
2046
 *           This should be used internally by the parser
2047
 *           only to compare to ASCII values otherwise it would break when
2048
 *           running with UTF-8 encoding.
2049
 *   RAW     same as CUR but in the input buffer, bypass any token
2050
 *           extraction that may have been done
2051
 *   NXT(n)  returns the n'th next xmlChar. Same as CUR is should be used only
2052
 *           to compare on ASCII based substring.
2053
 *   SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
2054
 *           strings without newlines within the parser.
2055
 *   NEXT1(l) Skip 1 xmlChar, and must also be used only to skip 1 non-newline ASCII
2056
 *           defined char within the parser.
2057
 * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
2058
 *
2059
 *   NEXT    Skip to the next character, this does the proper decoding
2060
 *           in UTF-8 mode. It also pop-up unfinished entities on the fly.
2061
 *   NEXTL(l) Skip the current unicode character of l xmlChars long.
2062
 *   CUR_CHAR(l) returns the current unicode character (int), set l
2063
 *           to the number of xmlChars used for the encoding [0-5].
2064
 *   CUR_SCHAR  same but operate on a string instead of the context
2065
 *   COPY_BUF  copy the current unicode char to the target buffer, increment
2066
 *            the index
2067
 *   GROW, SHRINK  handling of input buffers
2068
 */
2069
2070
380
#define RAW (*ctxt->input->cur)
2071
82
#define CUR (*ctxt->input->cur)
2072
170
#define NXT(val) ctxt->input->cur[(val)]
2073
46
#define CUR_PTR ctxt->input->cur
2074
0
#define BASE_PTR ctxt->input->base
2075
2076
#define CMP4( s, c1, c2, c3, c4 ) \
2077
200
  ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char *) s)[ 1 ] == c2 && \
2078
102
    ((unsigned char *) s)[ 2 ] == c3 && ((unsigned char *) s)[ 3 ] == c4 )
2079
#define CMP5( s, c1, c2, c3, c4, c5 ) \
2080
194
  ( CMP4( s, c1, c2, c3, c4 ) && ((unsigned char *) s)[ 4 ] == c5 )
2081
#define CMP6( s, c1, c2, c3, c4, c5, c6 ) \
2082
192
  ( CMP5( s, c1, c2, c3, c4, c5 ) && ((unsigned char *) s)[ 5 ] == c6 )
2083
#define CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) \
2084
192
  ( CMP6( s, c1, c2, c3, c4, c5, c6 ) && ((unsigned char *) s)[ 6 ] == c7 )
2085
#define CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) \
2086
192
  ( CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) && ((unsigned char *) s)[ 7 ] == c8 )
2087
#define CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) \
2088
96
  ( CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) && \
2089
96
    ((unsigned char *) s)[ 8 ] == c9 )
2090
#define CMP10( s, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 ) \
2091
0
  ( CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) && \
2092
0
    ((unsigned char *) s)[ 9 ] == c10 )
2093
2094
44
#define SKIP(val) do {             \
2095
44
    ctxt->input->cur += (val),ctxt->input->col+=(val);      \
2096
44
    if (*ctxt->input->cur == 0)           \
2097
44
        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);     \
2098
44
  } while (0)
2099
2100
#define SKIPL(val) do {             \
2101
    int skipl;                \
2102
    for(skipl=0; skipl<val; skipl++) {          \
2103
  if (*(ctxt->input->cur) == '\n') {        \
2104
  ctxt->input->line++; ctxt->input->col = 1;      \
2105
  } else ctxt->input->col++;          \
2106
  ctxt->input->cur++;           \
2107
    }                 \
2108
    if (*ctxt->input->cur == 0)           \
2109
        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);     \
2110
  } while (0)
2111
2112
180
#define SHRINK if ((ctxt->progressive == 0) &&       \
2113
180
       (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \
2114
180
       (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \
2115
180
  xmlSHRINK (ctxt);
2116
2117
0
static void xmlSHRINK (xmlParserCtxtPtr ctxt) {
2118
0
    xmlParserInputShrink(ctxt->input);
2119
0
    if (*ctxt->input->cur == 0)
2120
0
        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
2121
0
}
2122
2123
382
#define GROW if ((ctxt->progressive == 0) &&       \
2124
382
     (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK))  \
2125
382
  xmlGROW (ctxt);
2126
2127
222
static void xmlGROW (xmlParserCtxtPtr ctxt) {
2128
222
    ptrdiff_t curEnd = ctxt->input->end - ctxt->input->cur;
2129
222
    ptrdiff_t curBase = ctxt->input->cur - ctxt->input->base;
2130
2131
222
    if (((curEnd > XML_MAX_LOOKUP_LIMIT) ||
2132
222
         (curBase > XML_MAX_LOOKUP_LIMIT)) &&
2133
222
         ((ctxt->input->buf) &&
2134
0
          (ctxt->input->buf->readcallback != xmlInputReadCallbackNop)) &&
2135
222
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
2136
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
2137
0
        xmlHaltParser(ctxt);
2138
0
  return;
2139
0
    }
2140
222
    xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
2141
222
    if ((ctxt->input->cur > ctxt->input->end) ||
2142
222
        (ctxt->input->cur < ctxt->input->base)) {
2143
0
        xmlHaltParser(ctxt);
2144
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "cur index out of bound");
2145
0
  return;
2146
0
    }
2147
222
    if ((ctxt->input->cur != NULL) && (*ctxt->input->cur == 0))
2148
2
        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
2149
222
}
2150
2151
106
#define SKIP_BLANKS xmlSkipBlankChars(ctxt)
2152
2153
58
#define NEXT xmlNextChar(ctxt)
2154
2155
60
#define NEXT1 {               \
2156
60
  ctxt->input->col++;           \
2157
60
  ctxt->input->cur++;           \
2158
60
  if (*ctxt->input->cur == 0)         \
2159
60
      xmlParserInputGrow(ctxt->input, INPUT_CHUNK);   \
2160
60
    }
2161
2162
60
#define NEXTL(l) do {             \
2163
60
    if (*(ctxt->input->cur) == '\n') {         \
2164
0
  ctxt->input->line++; ctxt->input->col = 1;      \
2165
60
    } else ctxt->input->col++;           \
2166
60
    ctxt->input->cur += l;        \
2167
60
  } while (0)
2168
2169
70
#define CUR_CHAR(l) xmlCurrentChar(ctxt, &l)
2170
0
#define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l)
2171
2172
#define COPY_BUF(l,b,i,v)           \
2173
56
    if (l == 1) b[i++] = v;           \
2174
56
    else i += xmlCopyCharMultiByte(&b[i],v)
2175
2176
#define CUR_CONSUMED \
2177
216
    (ctxt->input->consumed + (ctxt->input->cur - ctxt->input->base))
2178
2179
/**
2180
 * xmlSkipBlankChars:
2181
 * @ctxt:  the XML parser context
2182
 *
2183
 * skip all blanks character found at that point in the input streams.
2184
 * It pops up finished entities in the process if allowable at that point.
2185
 *
2186
 * Returns the number of space chars skipped
2187
 */
2188
2189
int
2190
106
xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
2191
106
    int res = 0;
2192
2193
    /*
2194
     * It's Okay to use CUR/NEXT here since all the blanks are on
2195
     * the ASCII range.
2196
     */
2197
106
    if (((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) ||
2198
106
        (ctxt->instate == XML_PARSER_START)) {
2199
106
  const xmlChar *cur;
2200
  /*
2201
   * if we are in the document content, go really fast
2202
   */
2203
106
  cur = ctxt->input->cur;
2204
106
  while (IS_BLANK_CH(*cur)) {
2205
32
      if (*cur == '\n') {
2206
4
    ctxt->input->line++; ctxt->input->col = 1;
2207
28
      } else {
2208
28
    ctxt->input->col++;
2209
28
      }
2210
32
      cur++;
2211
32
      if (res < INT_MAX)
2212
32
    res++;
2213
32
      if (*cur == 0) {
2214
2
    ctxt->input->cur = cur;
2215
2
    xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
2216
2
    cur = ctxt->input->cur;
2217
2
      }
2218
32
  }
2219
106
  ctxt->input->cur = cur;
2220
106
    } else {
2221
0
        int expandPE = ((ctxt->external != 0) || (ctxt->inputNr != 1));
2222
2223
0
  while (ctxt->instate != XML_PARSER_EOF) {
2224
0
            if (IS_BLANK_CH(CUR)) { /* CHECKED tstblanks.xml */
2225
0
    NEXT;
2226
0
      } else if (CUR == '%') {
2227
                /*
2228
                 * Need to handle support of entities branching here
2229
                 */
2230
0
          if ((expandPE == 0) || (IS_BLANK_CH(NXT(1))) || (NXT(1) == 0))
2231
0
                    break;
2232
0
          xmlParsePEReference(ctxt);
2233
0
            } else if (CUR == 0) {
2234
0
                if (ctxt->inputNr <= 1)
2235
0
                    break;
2236
0
                xmlPopInput(ctxt);
2237
0
            } else {
2238
0
                break;
2239
0
            }
2240
2241
            /*
2242
             * Also increase the counter when entering or exiting a PERef.
2243
             * The spec says: "When a parameter-entity reference is recognized
2244
             * in the DTD and included, its replacement text MUST be enlarged
2245
             * by the attachment of one leading and one following space (#x20)
2246
             * character."
2247
             */
2248
0
      if (res < INT_MAX)
2249
0
    res++;
2250
0
        }
2251
0
    }
2252
106
    return(res);
2253
106
}
2254
2255
/************************************************************************
2256
 *                  *
2257
 *    Commodity functions to handle entities      *
2258
 *                  *
2259
 ************************************************************************/
2260
2261
/**
2262
 * xmlPopInput:
2263
 * @ctxt:  an XML parser context
2264
 *
2265
 * xmlPopInput: the current input pointed by ctxt->input came to an end
2266
 *          pop it and return the next char.
2267
 *
2268
 * Returns the current xmlChar in the parser context
2269
 */
2270
xmlChar
2271
0
xmlPopInput(xmlParserCtxtPtr ctxt) {
2272
0
    if ((ctxt == NULL) || (ctxt->inputNr <= 1)) return(0);
2273
0
    if (xmlParserDebugEntities)
2274
0
  xmlGenericError(xmlGenericErrorContext,
2275
0
    "Popping input %d\n", ctxt->inputNr);
2276
0
    if ((ctxt->inputNr > 1) && (ctxt->inSubset == 0) &&
2277
0
        (ctxt->instate != XML_PARSER_EOF))
2278
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
2279
0
                    "Unfinished entity outside the DTD");
2280
0
    xmlFreeInputStream(inputPop(ctxt));
2281
0
    if (*ctxt->input->cur == 0)
2282
0
        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
2283
0
    return(CUR);
2284
0
}
2285
2286
/**
2287
 * xmlPushInput:
2288
 * @ctxt:  an XML parser context
2289
 * @input:  an XML parser input fragment (entity, XML fragment ...).
2290
 *
2291
 * xmlPushInput: switch to a new input stream which is stacked on top
2292
 *               of the previous one(s).
2293
 * Returns -1 in case of error or the index in the input stack
2294
 */
2295
int
2296
0
xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
2297
0
    int ret;
2298
0
    if (input == NULL) return(-1);
2299
2300
0
    if (xmlParserDebugEntities) {
2301
0
  if ((ctxt->input != NULL) && (ctxt->input->filename))
2302
0
      xmlGenericError(xmlGenericErrorContext,
2303
0
        "%s(%d): ", ctxt->input->filename,
2304
0
        ctxt->input->line);
2305
0
  xmlGenericError(xmlGenericErrorContext,
2306
0
    "Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur);
2307
0
    }
2308
0
    if (((ctxt->inputNr > 40) && ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
2309
0
        (ctxt->inputNr > 1024)) {
2310
0
        xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
2311
0
        while (ctxt->inputNr > 1)
2312
0
            xmlFreeInputStream(inputPop(ctxt));
2313
0
  return(-1);
2314
0
    }
2315
0
    ret = inputPush(ctxt, input);
2316
0
    if (ctxt->instate == XML_PARSER_EOF)
2317
0
        return(-1);
2318
0
    GROW;
2319
0
    return(ret);
2320
0
}
2321
2322
/**
2323
 * xmlParseCharRef:
2324
 * @ctxt:  an XML parser context
2325
 *
2326
 * DEPRECATED: Internal function, don't use.
2327
 *
2328
 * parse Reference declarations
2329
 *
2330
 * [66] CharRef ::= '&#' [0-9]+ ';' |
2331
 *                  '&#x' [0-9a-fA-F]+ ';'
2332
 *
2333
 * [ WFC: Legal Character ]
2334
 * Characters referred to using character references must match the
2335
 * production for Char.
2336
 *
2337
 * Returns the value parsed (as an int), 0 in case of error
2338
 */
2339
int
2340
2
xmlParseCharRef(xmlParserCtxtPtr ctxt) {
2341
2
    int val = 0;
2342
2
    int count = 0;
2343
2344
    /*
2345
     * Using RAW/CUR/NEXT is okay since we are working on ASCII range here
2346
     */
2347
2
    if ((RAW == '&') && (NXT(1) == '#') &&
2348
2
        (NXT(2) == 'x')) {
2349
2
  SKIP(3);
2350
2
  GROW;
2351
12
  while (RAW != ';') { /* loop blocked by count */
2352
10
      if (count++ > 20) {
2353
0
    count = 0;
2354
0
    GROW;
2355
0
                if (ctxt->instate == XML_PARSER_EOF)
2356
0
                    return(0);
2357
0
      }
2358
10
      if ((RAW >= '0') && (RAW <= '9'))
2359
8
          val = val * 16 + (CUR - '0');
2360
2
      else if ((RAW >= 'a') && (RAW <= 'f') && (count < 20))
2361
2
          val = val * 16 + (CUR - 'a') + 10;
2362
0
      else if ((RAW >= 'A') && (RAW <= 'F') && (count < 20))
2363
0
          val = val * 16 + (CUR - 'A') + 10;
2364
0
      else {
2365
0
    xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
2366
0
    val = 0;
2367
0
    break;
2368
0
      }
2369
10
      if (val > 0x110000)
2370
0
          val = 0x110000;
2371
2372
10
      NEXT;
2373
10
      count++;
2374
10
  }
2375
2
  if (RAW == ';') {
2376
      /* on purpose to avoid reentrancy problems with NEXT and SKIP */
2377
2
      ctxt->input->col++;
2378
2
      ctxt->input->cur++;
2379
2
  }
2380
2
    } else if  ((RAW == '&') && (NXT(1) == '#')) {
2381
0
  SKIP(2);
2382
0
  GROW;
2383
0
  while (RAW != ';') { /* loop blocked by count */
2384
0
      if (count++ > 20) {
2385
0
    count = 0;
2386
0
    GROW;
2387
0
                if (ctxt->instate == XML_PARSER_EOF)
2388
0
                    return(0);
2389
0
      }
2390
0
      if ((RAW >= '0') && (RAW <= '9'))
2391
0
          val = val * 10 + (CUR - '0');
2392
0
      else {
2393
0
    xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
2394
0
    val = 0;
2395
0
    break;
2396
0
      }
2397
0
      if (val > 0x110000)
2398
0
          val = 0x110000;
2399
2400
0
      NEXT;
2401
0
      count++;
2402
0
  }
2403
0
  if (RAW == ';') {
2404
      /* on purpose to avoid reentrancy problems with NEXT and SKIP */
2405
0
      ctxt->input->col++;
2406
0
      ctxt->input->cur++;
2407
0
  }
2408
0
    } else {
2409
0
        xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
2410
0
    }
2411
2412
    /*
2413
     * [ WFC: Legal Character ]
2414
     * Characters referred to using character references must match the
2415
     * production for Char.
2416
     */
2417
2
    if (val >= 0x110000) {
2418
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2419
0
                "xmlParseCharRef: character reference out of bounds\n",
2420
0
          val);
2421
2
    } else if (IS_CHAR(val)) {
2422
2
        return(val);
2423
2
    } else {
2424
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2425
0
                          "xmlParseCharRef: invalid xmlChar value %d\n",
2426
0
                    val);
2427
0
    }
2428
0
    return(0);
2429
2
}
2430
2431
/**
2432
 * xmlParseStringCharRef:
2433
 * @ctxt:  an XML parser context
2434
 * @str:  a pointer to an index in the string
2435
 *
2436
 * parse Reference declarations, variant parsing from a string rather
2437
 * than an an input flow.
2438
 *
2439
 * [66] CharRef ::= '&#' [0-9]+ ';' |
2440
 *                  '&#x' [0-9a-fA-F]+ ';'
2441
 *
2442
 * [ WFC: Legal Character ]
2443
 * Characters referred to using character references must match the
2444
 * production for Char.
2445
 *
2446
 * Returns the value parsed (as an int), 0 in case of error, str will be
2447
 *         updated to the current value of the index
2448
 */
2449
static int
2450
0
xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
2451
0
    const xmlChar *ptr;
2452
0
    xmlChar cur;
2453
0
    int val = 0;
2454
2455
0
    if ((str == NULL) || (*str == NULL)) return(0);
2456
0
    ptr = *str;
2457
0
    cur = *ptr;
2458
0
    if ((cur == '&') && (ptr[1] == '#') && (ptr[2] == 'x')) {
2459
0
  ptr += 3;
2460
0
  cur = *ptr;
2461
0
  while (cur != ';') { /* Non input consuming loop */
2462
0
      if ((cur >= '0') && (cur <= '9'))
2463
0
          val = val * 16 + (cur - '0');
2464
0
      else if ((cur >= 'a') && (cur <= 'f'))
2465
0
          val = val * 16 + (cur - 'a') + 10;
2466
0
      else if ((cur >= 'A') && (cur <= 'F'))
2467
0
          val = val * 16 + (cur - 'A') + 10;
2468
0
      else {
2469
0
    xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
2470
0
    val = 0;
2471
0
    break;
2472
0
      }
2473
0
      if (val > 0x110000)
2474
0
          val = 0x110000;
2475
2476
0
      ptr++;
2477
0
      cur = *ptr;
2478
0
  }
2479
0
  if (cur == ';')
2480
0
      ptr++;
2481
0
    } else if  ((cur == '&') && (ptr[1] == '#')){
2482
0
  ptr += 2;
2483
0
  cur = *ptr;
2484
0
  while (cur != ';') { /* Non input consuming loops */
2485
0
      if ((cur >= '0') && (cur <= '9'))
2486
0
          val = val * 10 + (cur - '0');
2487
0
      else {
2488
0
    xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
2489
0
    val = 0;
2490
0
    break;
2491
0
      }
2492
0
      if (val > 0x110000)
2493
0
          val = 0x110000;
2494
2495
0
      ptr++;
2496
0
      cur = *ptr;
2497
0
  }
2498
0
  if (cur == ';')
2499
0
      ptr++;
2500
0
    } else {
2501
0
  xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
2502
0
  return(0);
2503
0
    }
2504
0
    *str = ptr;
2505
2506
    /*
2507
     * [ WFC: Legal Character ]
2508
     * Characters referred to using character references must match the
2509
     * production for Char.
2510
     */
2511
0
    if (val >= 0x110000) {
2512
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2513
0
                "xmlParseStringCharRef: character reference out of bounds\n",
2514
0
                val);
2515
0
    } else if (IS_CHAR(val)) {
2516
0
        return(val);
2517
0
    } else {
2518
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2519
0
        "xmlParseStringCharRef: invalid xmlChar value %d\n",
2520
0
        val);
2521
0
    }
2522
0
    return(0);
2523
0
}
2524
2525
/**
2526
 * xmlParserHandlePEReference:
2527
 * @ctxt:  the parser context
2528
 *
2529
 * [69] PEReference ::= '%' Name ';'
2530
 *
2531
 * [ WFC: No Recursion ]
2532
 * A parsed entity must not contain a recursive
2533
 * reference to itself, either directly or indirectly.
2534
 *
2535
 * [ WFC: Entity Declared ]
2536
 * In a document without any DTD, a document with only an internal DTD
2537
 * subset which contains no parameter entity references, or a document
2538
 * with "standalone='yes'", ...  ... The declaration of a parameter
2539
 * entity must precede any reference to it...
2540
 *
2541
 * [ VC: Entity Declared ]
2542
 * In a document with an external subset or external parameter entities
2543
 * with "standalone='no'", ...  ... The declaration of a parameter entity
2544
 * must precede any reference to it...
2545
 *
2546
 * [ WFC: In DTD ]
2547
 * Parameter-entity references may only appear in the DTD.
2548
 * NOTE: misleading but this is handled.
2549
 *
2550
 * A PEReference may have been detected in the current input stream
2551
 * the handling is done accordingly to
2552
 *      http://www.w3.org/TR/REC-xml#entproc
2553
 * i.e.
2554
 *   - Included in literal in entity values
2555
 *   - Included as Parameter Entity reference within DTDs
2556
 */
2557
void
2558
0
xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
2559
0
    switch(ctxt->instate) {
2560
0
  case XML_PARSER_CDATA_SECTION:
2561
0
      return;
2562
0
        case XML_PARSER_COMMENT:
2563
0
      return;
2564
0
  case XML_PARSER_START_TAG:
2565
0
      return;
2566
0
  case XML_PARSER_END_TAG:
2567
0
      return;
2568
0
        case XML_PARSER_EOF:
2569
0
      xmlFatalErr(ctxt, XML_ERR_PEREF_AT_EOF, NULL);
2570
0
      return;
2571
0
        case XML_PARSER_PROLOG:
2572
0
  case XML_PARSER_START:
2573
0
  case XML_PARSER_MISC:
2574
0
      xmlFatalErr(ctxt, XML_ERR_PEREF_IN_PROLOG, NULL);
2575
0
      return;
2576
0
  case XML_PARSER_ENTITY_DECL:
2577
0
        case XML_PARSER_CONTENT:
2578
0
        case XML_PARSER_ATTRIBUTE_VALUE:
2579
0
        case XML_PARSER_PI:
2580
0
  case XML_PARSER_SYSTEM_LITERAL:
2581
0
  case XML_PARSER_PUBLIC_LITERAL:
2582
      /* we just ignore it there */
2583
0
      return;
2584
0
        case XML_PARSER_EPILOG:
2585
0
      xmlFatalErr(ctxt, XML_ERR_PEREF_IN_EPILOG, NULL);
2586
0
      return;
2587
0
  case XML_PARSER_ENTITY_VALUE:
2588
      /*
2589
       * NOTE: in the case of entity values, we don't do the
2590
       *       substitution here since we need the literal
2591
       *       entity value to be able to save the internal
2592
       *       subset of the document.
2593
       *       This will be handled by xmlStringDecodeEntities
2594
       */
2595
0
      return;
2596
0
        case XML_PARSER_DTD:
2597
      /*
2598
       * [WFC: Well-Formedness Constraint: PEs in Internal Subset]
2599
       * In the internal DTD subset, parameter-entity references
2600
       * can occur only where markup declarations can occur, not
2601
       * within markup declarations.
2602
       * In that case this is handled in xmlParseMarkupDecl
2603
       */
2604
0
      if ((ctxt->external == 0) && (ctxt->inputNr == 1))
2605
0
    return;
2606
0
      if (IS_BLANK_CH(NXT(1)) || NXT(1) == 0)
2607
0
    return;
2608
0
            break;
2609
0
        case XML_PARSER_IGNORE:
2610
0
            return;
2611
0
    }
2612
2613
0
    xmlParsePEReference(ctxt);
2614
0
}
2615
2616
/*
2617
 * Macro used to grow the current buffer.
2618
 * buffer##_size is expected to be a size_t
2619
 * mem_error: is expected to handle memory allocation failures
2620
 */
2621
0
#define growBuffer(buffer, n) {           \
2622
0
    xmlChar *tmp;             \
2623
0
    size_t new_size = buffer##_size * 2 + n;                            \
2624
0
    if (new_size < buffer##_size) goto mem_error;                       \
2625
0
    tmp = (xmlChar *) xmlRealloc(buffer, new_size);                     \
2626
0
    if (tmp == NULL) goto mem_error;         \
2627
0
    buffer = tmp;             \
2628
0
    buffer##_size = new_size;                                           \
2629
0
}
2630
2631
/**
2632
 * xmlStringLenDecodeEntities:
2633
 * @ctxt:  the parser context
2634
 * @str:  the input string
2635
 * @len: the string length
2636
 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
2637
 * @end:  an end marker xmlChar, 0 if none
2638
 * @end2:  an end marker xmlChar, 0 if none
2639
 * @end3:  an end marker xmlChar, 0 if none
2640
 *
2641
 * Takes a entity string content and process to do the adequate substitutions.
2642
 *
2643
 * [67] Reference ::= EntityRef | CharRef
2644
 *
2645
 * [69] PEReference ::= '%' Name ';'
2646
 *
2647
 * Returns A newly allocated string with the substitution done. The caller
2648
 *      must deallocate it !
2649
 */
2650
xmlChar *
2651
xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
2652
0
          int what, xmlChar end, xmlChar  end2, xmlChar end3) {
2653
0
    xmlChar *buffer = NULL;
2654
0
    size_t buffer_size = 0;
2655
0
    size_t nbchars = 0;
2656
2657
0
    xmlChar *current = NULL;
2658
0
    xmlChar *rep = NULL;
2659
0
    const xmlChar *last;
2660
0
    xmlEntityPtr ent;
2661
0
    int c,l;
2662
2663
0
    if ((ctxt == NULL) || (str == NULL) || (len < 0))
2664
0
  return(NULL);
2665
0
    last = str + len;
2666
2667
0
    if (((ctxt->depth > 40) &&
2668
0
         ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
2669
0
  (ctxt->depth > 1024)) {
2670
0
  xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
2671
0
  return(NULL);
2672
0
    }
2673
2674
    /*
2675
     * allocate a translation buffer.
2676
     */
2677
0
    buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
2678
0
    buffer = (xmlChar *) xmlMallocAtomic(buffer_size);
2679
0
    if (buffer == NULL) goto mem_error;
2680
2681
    /*
2682
     * OK loop until we reach one of the ending char or a size limit.
2683
     * we are operating on already parsed values.
2684
     */
2685
0
    if (str < last)
2686
0
  c = CUR_SCHAR(str, l);
2687
0
    else
2688
0
        c = 0;
2689
0
    while ((c != 0) && (c != end) && /* non input consuming loop */
2690
0
           (c != end2) && (c != end3) &&
2691
0
           (ctxt->instate != XML_PARSER_EOF)) {
2692
2693
0
  if (c == 0) break;
2694
0
        if ((c == '&') && (str[1] == '#')) {
2695
0
      int val = xmlParseStringCharRef(ctxt, &str);
2696
0
      if (val == 0)
2697
0
                goto int_error;
2698
0
      COPY_BUF(0,buffer,nbchars,val);
2699
0
      if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2700
0
          growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2701
0
      }
2702
0
  } else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) {
2703
0
      if (xmlParserDebugEntities)
2704
0
    xmlGenericError(xmlGenericErrorContext,
2705
0
      "String decoding Entity Reference: %.30s\n",
2706
0
      str);
2707
0
      ent = xmlParseStringEntityRef(ctxt, &str);
2708
0
      xmlParserEntityCheck(ctxt, 0, ent, 0);
2709
0
      if (ent != NULL)
2710
0
          ctxt->nbentities += ent->checked / 2;
2711
0
      if ((ent != NULL) &&
2712
0
    (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
2713
0
    if (ent->content != NULL) {
2714
0
        COPY_BUF(0,buffer,nbchars,ent->content[0]);
2715
0
        if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2716
0
      growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2717
0
        }
2718
0
    } else {
2719
0
        xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
2720
0
          "predefined entity has no content\n");
2721
0
                    goto int_error;
2722
0
    }
2723
0
      } else if ((ent != NULL) && (ent->content != NULL)) {
2724
0
    ctxt->depth++;
2725
0
    rep = xmlStringDecodeEntities(ctxt, ent->content, what,
2726
0
                            0, 0, 0);
2727
0
    ctxt->depth--;
2728
0
    if (rep == NULL) {
2729
0
                    ent->content[0] = 0;
2730
0
                    goto int_error;
2731
0
                }
2732
2733
0
                current = rep;
2734
0
                while (*current != 0) { /* non input consuming loop */
2735
0
                    buffer[nbchars++] = *current++;
2736
0
                    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2737
0
                        if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
2738
0
                            goto int_error;
2739
0
                        growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2740
0
                    }
2741
0
                }
2742
0
                xmlFree(rep);
2743
0
                rep = NULL;
2744
0
      } else if (ent != NULL) {
2745
0
    int i = xmlStrlen(ent->name);
2746
0
    const xmlChar *cur = ent->name;
2747
2748
0
    buffer[nbchars++] = '&';
2749
0
    if (nbchars + i + XML_PARSER_BUFFER_SIZE > buffer_size) {
2750
0
        growBuffer(buffer, i + XML_PARSER_BUFFER_SIZE);
2751
0
    }
2752
0
    for (;i > 0;i--)
2753
0
        buffer[nbchars++] = *cur++;
2754
0
    buffer[nbchars++] = ';';
2755
0
      }
2756
0
  } else if (c == '%' && (what & XML_SUBSTITUTE_PEREF)) {
2757
0
      if (xmlParserDebugEntities)
2758
0
    xmlGenericError(xmlGenericErrorContext,
2759
0
      "String decoding PE Reference: %.30s\n", str);
2760
0
      ent = xmlParseStringPEReference(ctxt, &str);
2761
0
      xmlParserEntityCheck(ctxt, 0, ent, 0);
2762
0
      if (ent != NULL)
2763
0
          ctxt->nbentities += ent->checked / 2;
2764
0
      if (ent != NULL) {
2765
0
                if (ent->content == NULL) {
2766
        /*
2767
         * Note: external parsed entities will not be loaded,
2768
         * it is not required for a non-validating parser to
2769
         * complete external PEReferences coming from the
2770
         * internal subset
2771
         */
2772
0
        if (((ctxt->options & XML_PARSE_NOENT) != 0) ||
2773
0
      ((ctxt->options & XML_PARSE_DTDVALID) != 0) ||
2774
0
      (ctxt->validate != 0)) {
2775
0
      xmlLoadEntityContent(ctxt, ent);
2776
0
        } else {
2777
0
      xmlWarningMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
2778
0
      "not validating will not read content for PE entity %s\n",
2779
0
                          ent->name, NULL);
2780
0
        }
2781
0
    }
2782
0
    ctxt->depth++;
2783
0
    rep = xmlStringDecodeEntities(ctxt, ent->content, what,
2784
0
                            0, 0, 0);
2785
0
    ctxt->depth--;
2786
0
    if (rep == NULL) {
2787
0
                    if (ent->content != NULL)
2788
0
                        ent->content[0] = 0;
2789
0
                    goto int_error;
2790
0
                }
2791
0
                current = rep;
2792
0
                while (*current != 0) { /* non input consuming loop */
2793
0
                    buffer[nbchars++] = *current++;
2794
0
                    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2795
0
                        if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
2796
0
                            goto int_error;
2797
0
                        growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2798
0
                    }
2799
0
                }
2800
0
                xmlFree(rep);
2801
0
                rep = NULL;
2802
0
      }
2803
0
  } else {
2804
0
      COPY_BUF(l,buffer,nbchars,c);
2805
0
      str += l;
2806
0
      if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2807
0
          growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2808
0
      }
2809
0
  }
2810
0
  if (str < last)
2811
0
      c = CUR_SCHAR(str, l);
2812
0
  else
2813
0
      c = 0;
2814
0
    }
2815
0
    buffer[nbchars] = 0;
2816
0
    return(buffer);
2817
2818
0
mem_error:
2819
0
    xmlErrMemory(ctxt, NULL);
2820
0
int_error:
2821
0
    if (rep != NULL)
2822
0
        xmlFree(rep);
2823
0
    if (buffer != NULL)
2824
0
        xmlFree(buffer);
2825
0
    return(NULL);
2826
0
}
2827
2828
/**
2829
 * xmlStringDecodeEntities:
2830
 * @ctxt:  the parser context
2831
 * @str:  the input string
2832
 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
2833
 * @end:  an end marker xmlChar, 0 if none
2834
 * @end2:  an end marker xmlChar, 0 if none
2835
 * @end3:  an end marker xmlChar, 0 if none
2836
 *
2837
 * Takes a entity string content and process to do the adequate substitutions.
2838
 *
2839
 * [67] Reference ::= EntityRef | CharRef
2840
 *
2841
 * [69] PEReference ::= '%' Name ';'
2842
 *
2843
 * Returns A newly allocated string with the substitution done. The caller
2844
 *      must deallocate it !
2845
 */
2846
xmlChar *
2847
xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what,
2848
0
            xmlChar end, xmlChar  end2, xmlChar end3) {
2849
0
    if ((ctxt == NULL) || (str == NULL)) return(NULL);
2850
0
    return(xmlStringLenDecodeEntities(ctxt, str, xmlStrlen(str), what,
2851
0
           end, end2, end3));
2852
0
}
2853
2854
/************************************************************************
2855
 *                  *
2856
 *    Commodity functions, cleanup needed ?     *
2857
 *                  *
2858
 ************************************************************************/
2859
2860
/**
2861
 * areBlanks:
2862
 * @ctxt:  an XML parser context
2863
 * @str:  a xmlChar *
2864
 * @len:  the size of @str
2865
 * @blank_chars: we know the chars are blanks
2866
 *
2867
 * Is this a sequence of blank chars that one can ignore ?
2868
 *
2869
 * Returns 1 if ignorable 0 otherwise.
2870
 */
2871
2872
static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
2873
4
                     int blank_chars) {
2874
4
    int i, ret;
2875
4
    xmlNodePtr lastChild;
2876
2877
    /*
2878
     * Don't spend time trying to differentiate them, the same callback is
2879
     * used !
2880
     */
2881
4
    if (ctxt->sax->ignorableWhitespace == ctxt->sax->characters)
2882
4
  return(0);
2883
2884
    /*
2885
     * Check for xml:space value.
2886
     */
2887
0
    if ((ctxt->space == NULL) || (*(ctxt->space) == 1) ||
2888
0
        (*(ctxt->space) == -2))
2889
0
  return(0);
2890
2891
    /*
2892
     * Check that the string is made of blanks
2893
     */
2894
0
    if (blank_chars == 0) {
2895
0
  for (i = 0;i < len;i++)
2896
0
      if (!(IS_BLANK_CH(str[i]))) return(0);
2897
0
    }
2898
2899
    /*
2900
     * Look if the element is mixed content in the DTD if available
2901
     */
2902
0
    if (ctxt->node == NULL) return(0);
2903
0
    if (ctxt->myDoc != NULL) {
2904
0
  ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name);
2905
0
        if (ret == 0) return(1);
2906
0
        if (ret == 1) return(0);
2907
0
    }
2908
2909
    /*
2910
     * Otherwise, heuristic :-\
2911
     */
2912
0
    if ((RAW != '<') && (RAW != 0xD)) return(0);
2913
0
    if ((ctxt->node->children == NULL) &&
2914
0
  (RAW == '<') && (NXT(1) == '/')) return(0);
2915
2916
0
    lastChild = xmlGetLastChild(ctxt->node);
2917
0
    if (lastChild == NULL) {
2918
0
        if ((ctxt->node->type != XML_ELEMENT_NODE) &&
2919
0
            (ctxt->node->content != NULL)) return(0);
2920
0
    } else if (xmlNodeIsText(lastChild))
2921
0
        return(0);
2922
0
    else if ((ctxt->node->children != NULL) &&
2923
0
             (xmlNodeIsText(ctxt->node->children)))
2924
0
        return(0);
2925
0
    return(1);
2926
0
}
2927
2928
/************************************************************************
2929
 *                  *
2930
 *    Extra stuff for namespace support     *
2931
 *  Relates to http://www.w3.org/TR/WD-xml-names      *
2932
 *                  *
2933
 ************************************************************************/
2934
2935
/**
2936
 * xmlSplitQName:
2937
 * @ctxt:  an XML parser context
2938
 * @name:  an XML parser context
2939
 * @prefix:  a xmlChar **
2940
 *
2941
 * parse an UTF8 encoded XML qualified name string
2942
 *
2943
 * [NS 5] QName ::= (Prefix ':')? LocalPart
2944
 *
2945
 * [NS 6] Prefix ::= NCName
2946
 *
2947
 * [NS 7] LocalPart ::= NCName
2948
 *
2949
 * Returns the local part, and prefix is updated
2950
 *   to get the Prefix if any.
2951
 */
2952
2953
xmlChar *
2954
0
xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
2955
0
    xmlChar buf[XML_MAX_NAMELEN + 5];
2956
0
    xmlChar *buffer = NULL;
2957
0
    int len = 0;
2958
0
    int max = XML_MAX_NAMELEN;
2959
0
    xmlChar *ret = NULL;
2960
0
    const xmlChar *cur = name;
2961
0
    int c;
2962
2963
0
    if (prefix == NULL) return(NULL);
2964
0
    *prefix = NULL;
2965
2966
0
    if (cur == NULL) return(NULL);
2967
2968
#ifndef XML_XML_NAMESPACE
2969
    /* xml: prefix is not really a namespace */
2970
    if ((cur[0] == 'x') && (cur[1] == 'm') &&
2971
        (cur[2] == 'l') && (cur[3] == ':'))
2972
  return(xmlStrdup(name));
2973
#endif
2974
2975
    /* nasty but well=formed */
2976
0
    if (cur[0] == ':')
2977
0
  return(xmlStrdup(name));
2978
2979
0
    c = *cur++;
2980
0
    while ((c != 0) && (c != ':') && (len < max)) { /* tested bigname.xml */
2981
0
  buf[len++] = c;
2982
0
  c = *cur++;
2983
0
    }
2984
0
    if (len >= max) {
2985
  /*
2986
   * Okay someone managed to make a huge name, so he's ready to pay
2987
   * for the processing speed.
2988
   */
2989
0
  max = len * 2;
2990
2991
0
  buffer = (xmlChar *) xmlMallocAtomic(max);
2992
0
  if (buffer == NULL) {
2993
0
      xmlErrMemory(ctxt, NULL);
2994
0
      return(NULL);
2995
0
  }
2996
0
  memcpy(buffer, buf, len);
2997
0
  while ((c != 0) && (c != ':')) { /* tested bigname.xml */
2998
0
      if (len + 10 > max) {
2999
0
          xmlChar *tmp;
3000
3001
0
    max *= 2;
3002
0
    tmp = (xmlChar *) xmlRealloc(buffer, max);
3003
0
    if (tmp == NULL) {
3004
0
        xmlFree(buffer);
3005
0
        xmlErrMemory(ctxt, NULL);
3006
0
        return(NULL);
3007
0
    }
3008
0
    buffer = tmp;
3009
0
      }
3010
0
      buffer[len++] = c;
3011
0
      c = *cur++;
3012
0
  }
3013
0
  buffer[len] = 0;
3014
0
    }
3015
3016
0
    if ((c == ':') && (*cur == 0)) {
3017
0
        if (buffer != NULL)
3018
0
      xmlFree(buffer);
3019
0
  *prefix = NULL;
3020
0
  return(xmlStrdup(name));
3021
0
    }
3022
3023
0
    if (buffer == NULL)
3024
0
  ret = xmlStrndup(buf, len);
3025
0
    else {
3026
0
  ret = buffer;
3027
0
  buffer = NULL;
3028
0
  max = XML_MAX_NAMELEN;
3029
0
    }
3030
3031
3032
0
    if (c == ':') {
3033
0
  c = *cur;
3034
0
        *prefix = ret;
3035
0
  if (c == 0) {
3036
0
      return(xmlStrndup(BAD_CAST "", 0));
3037
0
  }
3038
0
  len = 0;
3039
3040
  /*
3041
   * Check that the first character is proper to start
3042
   * a new name
3043
   */
3044
0
  if (!(((c >= 0x61) && (c <= 0x7A)) ||
3045
0
        ((c >= 0x41) && (c <= 0x5A)) ||
3046
0
        (c == '_') || (c == ':'))) {
3047
0
      int l;
3048
0
      int first = CUR_SCHAR(cur, l);
3049
3050
0
      if (!IS_LETTER(first) && (first != '_')) {
3051
0
    xmlFatalErrMsgStr(ctxt, XML_NS_ERR_QNAME,
3052
0
          "Name %s is not XML Namespace compliant\n",
3053
0
          name);
3054
0
      }
3055
0
  }
3056
0
  cur++;
3057
3058
0
  while ((c != 0) && (len < max)) { /* tested bigname2.xml */
3059
0
      buf[len++] = c;
3060
0
      c = *cur++;
3061
0
  }
3062
0
  if (len >= max) {
3063
      /*
3064
       * Okay someone managed to make a huge name, so he's ready to pay
3065
       * for the processing speed.
3066
       */
3067
0
      max = len * 2;
3068
3069
0
      buffer = (xmlChar *) xmlMallocAtomic(max);
3070
0
      if (buffer == NULL) {
3071
0
          xmlErrMemory(ctxt, NULL);
3072
0
    return(NULL);
3073
0
      }
3074
0
      memcpy(buffer, buf, len);
3075
0
      while (c != 0) { /* tested bigname2.xml */
3076
0
    if (len + 10 > max) {
3077
0
        xmlChar *tmp;
3078
3079
0
        max *= 2;
3080
0
        tmp = (xmlChar *) xmlRealloc(buffer, max);
3081
0
        if (tmp == NULL) {
3082
0
      xmlErrMemory(ctxt, NULL);
3083
0
      xmlFree(buffer);
3084
0
      return(NULL);
3085
0
        }
3086
0
        buffer = tmp;
3087
0
    }
3088
0
    buffer[len++] = c;
3089
0
    c = *cur++;
3090
0
      }
3091
0
      buffer[len] = 0;
3092
0
  }
3093
3094
0
  if (buffer == NULL)
3095
0
      ret = xmlStrndup(buf, len);
3096
0
  else {
3097
0
      ret = buffer;
3098
0
  }
3099
0
    }
3100
3101
0
    return(ret);
3102
0
}
3103
3104
/************************************************************************
3105
 *                  *
3106
 *      The parser itself       *
3107
 *  Relates to http://www.w3.org/TR/REC-xml       *
3108
 *                  *
3109
 ************************************************************************/
3110
3111
/************************************************************************
3112
 *                  *
3113
 *  Routines to parse Name, NCName and NmToken      *
3114
 *                  *
3115
 ************************************************************************/
3116
#ifdef DEBUG
3117
static unsigned long nbParseName = 0;
3118
static unsigned long nbParseNmToken = 0;
3119
static unsigned long nbParseNCName = 0;
3120
static unsigned long nbParseNCNameComplex = 0;
3121
static unsigned long nbParseNameComplex = 0;
3122
static unsigned long nbParseStringName = 0;
3123
#endif
3124
3125
/*
3126
 * The two following functions are related to the change of accepted
3127
 * characters for Name and NmToken in the Revision 5 of XML-1.0
3128
 * They correspond to the modified production [4] and the new production [4a]
3129
 * changes in that revision. Also note that the macros used for the
3130
 * productions Letter, Digit, CombiningChar and Extender are not needed
3131
 * anymore.
3132
 * We still keep compatibility to pre-revision5 parsing semantic if the
3133
 * new XML_PARSE_OLD10 option is given to the parser.
3134
 */
3135
static int
3136
0
xmlIsNameStartChar(xmlParserCtxtPtr ctxt, int c) {
3137
0
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3138
        /*
3139
   * Use the new checks of production [4] [4a] amd [5] of the
3140
   * Update 5 of XML-1.0
3141
   */
3142
0
  if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3143
0
      (((c >= 'a') && (c <= 'z')) ||
3144
0
       ((c >= 'A') && (c <= 'Z')) ||
3145
0
       (c == '_') || (c == ':') ||
3146
0
       ((c >= 0xC0) && (c <= 0xD6)) ||
3147
0
       ((c >= 0xD8) && (c <= 0xF6)) ||
3148
0
       ((c >= 0xF8) && (c <= 0x2FF)) ||
3149
0
       ((c >= 0x370) && (c <= 0x37D)) ||
3150
0
       ((c >= 0x37F) && (c <= 0x1FFF)) ||
3151
0
       ((c >= 0x200C) && (c <= 0x200D)) ||
3152
0
       ((c >= 0x2070) && (c <= 0x218F)) ||
3153
0
       ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3154
0
       ((c >= 0x3001) && (c <= 0xD7FF)) ||
3155
0
       ((c >= 0xF900) && (c <= 0xFDCF)) ||
3156
0
       ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3157
0
       ((c >= 0x10000) && (c <= 0xEFFFF))))
3158
0
      return(1);
3159
0
    } else {
3160
0
        if (IS_LETTER(c) || (c == '_') || (c == ':'))
3161
0
      return(1);
3162
0
    }
3163
0
    return(0);
3164
0
}
3165
3166
static int
3167
0
xmlIsNameChar(xmlParserCtxtPtr ctxt, int c) {
3168
0
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3169
        /*
3170
   * Use the new checks of production [4] [4a] amd [5] of the
3171
   * Update 5 of XML-1.0
3172
   */
3173
0
  if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3174
0
      (((c >= 'a') && (c <= 'z')) ||
3175
0
       ((c >= 'A') && (c <= 'Z')) ||
3176
0
       ((c >= '0') && (c <= '9')) || /* !start */
3177
0
       (c == '_') || (c == ':') ||
3178
0
       (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3179
0
       ((c >= 0xC0) && (c <= 0xD6)) ||
3180
0
       ((c >= 0xD8) && (c <= 0xF6)) ||
3181
0
       ((c >= 0xF8) && (c <= 0x2FF)) ||
3182
0
       ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3183
0
       ((c >= 0x370) && (c <= 0x37D)) ||
3184
0
       ((c >= 0x37F) && (c <= 0x1FFF)) ||
3185
0
       ((c >= 0x200C) && (c <= 0x200D)) ||
3186
0
       ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3187
0
       ((c >= 0x2070) && (c <= 0x218F)) ||
3188
0
       ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3189
0
       ((c >= 0x3001) && (c <= 0xD7FF)) ||
3190
0
       ((c >= 0xF900) && (c <= 0xFDCF)) ||
3191
0
       ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3192
0
       ((c >= 0x10000) && (c <= 0xEFFFF))))
3193
0
       return(1);
3194
0
    } else {
3195
0
        if ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3196
0
            (c == '.') || (c == '-') ||
3197
0
      (c == '_') || (c == ':') ||
3198
0
      (IS_COMBINING(c)) ||
3199
0
      (IS_EXTENDER(c)))
3200
0
      return(1);
3201
0
    }
3202
0
    return(0);
3203
0
}
3204
3205
static xmlChar * xmlParseAttValueInternal(xmlParserCtxtPtr ctxt,
3206
                                          int *len, int *alloc, int normalize);
3207
3208
static const xmlChar *
3209
0
xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
3210
0
    int len = 0, l;
3211
0
    int c;
3212
0
    int count = 0;
3213
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3214
0
                    XML_MAX_TEXT_LENGTH :
3215
0
                    XML_MAX_NAME_LENGTH;
3216
3217
#ifdef DEBUG
3218
    nbParseNameComplex++;
3219
#endif
3220
3221
    /*
3222
     * Handler for more complex cases
3223
     */
3224
0
    GROW;
3225
0
    if (ctxt->instate == XML_PARSER_EOF)
3226
0
        return(NULL);
3227
0
    c = CUR_CHAR(l);
3228
0
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3229
        /*
3230
   * Use the new checks of production [4] [4a] amd [5] of the
3231
   * Update 5 of XML-1.0
3232
   */
3233
0
  if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3234
0
      (!(((c >= 'a') && (c <= 'z')) ||
3235
0
         ((c >= 'A') && (c <= 'Z')) ||
3236
0
         (c == '_') || (c == ':') ||
3237
0
         ((c >= 0xC0) && (c <= 0xD6)) ||
3238
0
         ((c >= 0xD8) && (c <= 0xF6)) ||
3239
0
         ((c >= 0xF8) && (c <= 0x2FF)) ||
3240
0
         ((c >= 0x370) && (c <= 0x37D)) ||
3241
0
         ((c >= 0x37F) && (c <= 0x1FFF)) ||
3242
0
         ((c >= 0x200C) && (c <= 0x200D)) ||
3243
0
         ((c >= 0x2070) && (c <= 0x218F)) ||
3244
0
         ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3245
0
         ((c >= 0x3001) && (c <= 0xD7FF)) ||
3246
0
         ((c >= 0xF900) && (c <= 0xFDCF)) ||
3247
0
         ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3248
0
         ((c >= 0x10000) && (c <= 0xEFFFF))))) {
3249
0
      return(NULL);
3250
0
  }
3251
0
  len += l;
3252
0
  NEXTL(l);
3253
0
  c = CUR_CHAR(l);
3254
0
  while ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3255
0
         (((c >= 'a') && (c <= 'z')) ||
3256
0
          ((c >= 'A') && (c <= 'Z')) ||
3257
0
          ((c >= '0') && (c <= '9')) || /* !start */
3258
0
          (c == '_') || (c == ':') ||
3259
0
          (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3260
0
          ((c >= 0xC0) && (c <= 0xD6)) ||
3261
0
          ((c >= 0xD8) && (c <= 0xF6)) ||
3262
0
          ((c >= 0xF8) && (c <= 0x2FF)) ||
3263
0
          ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3264
0
          ((c >= 0x370) && (c <= 0x37D)) ||
3265
0
          ((c >= 0x37F) && (c <= 0x1FFF)) ||
3266
0
          ((c >= 0x200C) && (c <= 0x200D)) ||
3267
0
          ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3268
0
          ((c >= 0x2070) && (c <= 0x218F)) ||
3269
0
          ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3270
0
          ((c >= 0x3001) && (c <= 0xD7FF)) ||
3271
0
          ((c >= 0xF900) && (c <= 0xFDCF)) ||
3272
0
          ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3273
0
          ((c >= 0x10000) && (c <= 0xEFFFF))
3274
0
    )) {
3275
0
      if (count++ > XML_PARSER_CHUNK_SIZE) {
3276
0
    count = 0;
3277
0
    GROW;
3278
0
                if (ctxt->instate == XML_PARSER_EOF)
3279
0
                    return(NULL);
3280
0
      }
3281
0
            if (len <= INT_MAX - l)
3282
0
          len += l;
3283
0
      NEXTL(l);
3284
0
      c = CUR_CHAR(l);
3285
0
  }
3286
0
    } else {
3287
0
  if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3288
0
      (!IS_LETTER(c) && (c != '_') &&
3289
0
       (c != ':'))) {
3290
0
      return(NULL);
3291
0
  }
3292
0
  len += l;
3293
0
  NEXTL(l);
3294
0
  c = CUR_CHAR(l);
3295
3296
0
  while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
3297
0
         ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3298
0
    (c == '.') || (c == '-') ||
3299
0
    (c == '_') || (c == ':') ||
3300
0
    (IS_COMBINING(c)) ||
3301
0
    (IS_EXTENDER(c)))) {
3302
0
      if (count++ > XML_PARSER_CHUNK_SIZE) {
3303
0
    count = 0;
3304
0
    GROW;
3305
0
                if (ctxt->instate == XML_PARSER_EOF)
3306
0
                    return(NULL);
3307
0
      }
3308
0
            if (len <= INT_MAX - l)
3309
0
          len += l;
3310
0
      NEXTL(l);
3311
0
      c = CUR_CHAR(l);
3312
0
  }
3313
0
    }
3314
0
    if (len > maxLength) {
3315
0
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
3316
0
        return(NULL);
3317
0
    }
3318
0
    if (ctxt->input->cur - ctxt->input->base < len) {
3319
        /*
3320
         * There were a couple of bugs where PERefs lead to to a change
3321
         * of the buffer. Check the buffer size to avoid passing an invalid
3322
         * pointer to xmlDictLookup.
3323
         */
3324
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
3325
0
                    "unexpected change of input buffer");
3326
0
        return (NULL);
3327
0
    }
3328
0
    if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r'))
3329
0
        return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len));
3330
0
    return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
3331
0
}
3332
3333
/**
3334
 * xmlParseName:
3335
 * @ctxt:  an XML parser context
3336
 *
3337
 * DEPRECATED: Internal function, don't use.
3338
 *
3339
 * parse an XML name.
3340
 *
3341
 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3342
 *                  CombiningChar | Extender
3343
 *
3344
 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3345
 *
3346
 * [6] Names ::= Name (#x20 Name)*
3347
 *
3348
 * Returns the Name parsed or NULL
3349
 */
3350
3351
const xmlChar *
3352
4
xmlParseName(xmlParserCtxtPtr ctxt) {
3353
4
    const xmlChar *in;
3354
4
    const xmlChar *ret;
3355
4
    size_t count = 0;
3356
4
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3357
0
                       XML_MAX_TEXT_LENGTH :
3358
4
                       XML_MAX_NAME_LENGTH;
3359
3360
4
    GROW;
3361
3362
#ifdef DEBUG
3363
    nbParseName++;
3364
#endif
3365
3366
    /*
3367
     * Accelerator for simple ASCII names
3368
     */
3369
4
    in = ctxt->input->cur;
3370
4
    if (((*in >= 0x61) && (*in <= 0x7A)) ||
3371
4
  ((*in >= 0x41) && (*in <= 0x5A)) ||
3372
4
  (*in == '_') || (*in == ':')) {
3373
4
  in++;
3374
8
  while (((*in >= 0x61) && (*in <= 0x7A)) ||
3375
8
         ((*in >= 0x41) && (*in <= 0x5A)) ||
3376
8
         ((*in >= 0x30) && (*in <= 0x39)) ||
3377
8
         (*in == '_') || (*in == '-') ||
3378
8
         (*in == ':') || (*in == '.'))
3379
4
      in++;
3380
4
  if ((*in > 0) && (*in < 0x80)) {
3381
4
      count = in - ctxt->input->cur;
3382
4
            if (count > maxLength) {
3383
0
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
3384
0
                return(NULL);
3385
0
            }
3386
4
      ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
3387
4
      ctxt->input->cur = in;
3388
4
      ctxt->input->col += count;
3389
4
      if (ret == NULL)
3390
0
          xmlErrMemory(ctxt, NULL);
3391
4
      return(ret);
3392
4
  }
3393
4
    }
3394
    /* accelerator for special cases */
3395
0
    return(xmlParseNameComplex(ctxt));
3396
4
}
3397
3398
static const xmlChar *
3399
0
xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
3400
0
    int len = 0, l;
3401
0
    int c;
3402
0
    int count = 0;
3403
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3404
0
                    XML_MAX_TEXT_LENGTH :
3405
0
                    XML_MAX_NAME_LENGTH;
3406
0
    size_t startPosition = 0;
3407
3408
#ifdef DEBUG
3409
    nbParseNCNameComplex++;
3410
#endif
3411
3412
    /*
3413
     * Handler for more complex cases
3414
     */
3415
0
    GROW;
3416
0
    startPosition = CUR_PTR - BASE_PTR;
3417
0
    c = CUR_CHAR(l);
3418
0
    if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3419
0
  (!xmlIsNameStartChar(ctxt, c) || (c == ':'))) {
3420
0
  return(NULL);
3421
0
    }
3422
3423
0
    while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
3424
0
     (xmlIsNameChar(ctxt, c) && (c != ':'))) {
3425
0
  if (count++ > XML_PARSER_CHUNK_SIZE) {
3426
0
      count = 0;
3427
0
      GROW;
3428
0
            if (ctxt->instate == XML_PARSER_EOF)
3429
0
                return(NULL);
3430
0
  }
3431
0
        if (len <= INT_MAX - l)
3432
0
      len += l;
3433
0
  NEXTL(l);
3434
0
  c = CUR_CHAR(l);
3435
0
  if (c == 0) {
3436
0
      count = 0;
3437
      /*
3438
       * when shrinking to extend the buffer we really need to preserve
3439
       * the part of the name we already parsed. Hence rolling back
3440
       * by current length.
3441
       */
3442
0
      ctxt->input->cur -= l;
3443
0
      GROW;
3444
0
            if (ctxt->instate == XML_PARSER_EOF)
3445
0
                return(NULL);
3446
0
      ctxt->input->cur += l;
3447
0
      c = CUR_CHAR(l);
3448
0
  }
3449
0
    }
3450
0
    if (len > maxLength) {
3451
0
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3452
0
        return(NULL);
3453
0
    }
3454
0
    return(xmlDictLookup(ctxt->dict, (BASE_PTR + startPosition), len));
3455
0
}
3456
3457
/**
3458
 * xmlParseNCName:
3459
 * @ctxt:  an XML parser context
3460
 * @len:  length of the string parsed
3461
 *
3462
 * parse an XML name.
3463
 *
3464
 * [4NS] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
3465
 *                      CombiningChar | Extender
3466
 *
3467
 * [5NS] NCName ::= (Letter | '_') (NCNameChar)*
3468
 *
3469
 * Returns the Name parsed or NULL
3470
 */
3471
3472
static const xmlChar *
3473
68
xmlParseNCName(xmlParserCtxtPtr ctxt) {
3474
68
    const xmlChar *in, *e;
3475
68
    const xmlChar *ret;
3476
68
    size_t count = 0;
3477
68
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3478
0
                       XML_MAX_TEXT_LENGTH :
3479
68
                       XML_MAX_NAME_LENGTH;
3480
3481
#ifdef DEBUG
3482
    nbParseNCName++;
3483
#endif
3484
3485
    /*
3486
     * Accelerator for simple ASCII names
3487
     */
3488
68
    in = ctxt->input->cur;
3489
68
    e = ctxt->input->end;
3490
68
    if ((((*in >= 0x61) && (*in <= 0x7A)) ||
3491
68
   ((*in >= 0x41) && (*in <= 0x5A)) ||
3492
68
   (*in == '_')) && (in < e)) {
3493
68
  in++;
3494
94
  while ((((*in >= 0x61) && (*in <= 0x7A)) ||
3495
94
          ((*in >= 0x41) && (*in <= 0x5A)) ||
3496
94
          ((*in >= 0x30) && (*in <= 0x39)) ||
3497
94
          (*in == '_') || (*in == '-') ||
3498
94
          (*in == '.')) && (in < e))
3499
26
      in++;
3500
68
  if (in >= e)
3501
0
      goto complex;
3502
68
  if ((*in > 0) && (*in < 0x80)) {
3503
68
      count = in - ctxt->input->cur;
3504
68
            if (count > maxLength) {
3505
0
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3506
0
                return(NULL);
3507
0
            }
3508
68
      ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
3509
68
      ctxt->input->cur = in;
3510
68
      ctxt->input->col += count;
3511
68
      if (ret == NULL) {
3512
0
          xmlErrMemory(ctxt, NULL);
3513
0
      }
3514
68
      return(ret);
3515
68
  }
3516
68
    }
3517
0
complex:
3518
0
    return(xmlParseNCNameComplex(ctxt));
3519
68
}
3520
3521
/**
3522
 * xmlParseNameAndCompare:
3523
 * @ctxt:  an XML parser context
3524
 *
3525
 * parse an XML name and compares for match
3526
 * (specialized for endtag parsing)
3527
 *
3528
 * Returns NULL for an illegal name, (xmlChar*) 1 for success
3529
 * and the name for mismatch
3530
 */
3531
3532
static const xmlChar *
3533
8
xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) {
3534
8
    register const xmlChar *cmp = other;
3535
8
    register const xmlChar *in;
3536
8
    const xmlChar *ret;
3537
3538
8
    GROW;
3539
8
    if (ctxt->instate == XML_PARSER_EOF)
3540
0
        return(NULL);
3541
3542
8
    in = ctxt->input->cur;
3543
16
    while (*in != 0 && *in == *cmp) {
3544
8
  ++in;
3545
8
  ++cmp;
3546
8
    }
3547
8
    if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
3548
  /* success */
3549
8
  ctxt->input->col += in - ctxt->input->cur;
3550
8
  ctxt->input->cur = in;
3551
8
  return (const xmlChar*) 1;
3552
8
    }
3553
    /* failure (or end of input buffer), check with full function */
3554
0
    ret = xmlParseName (ctxt);
3555
    /* strings coming from the dictionary direct compare possible */
3556
0
    if (ret == other) {
3557
0
  return (const xmlChar*) 1;
3558
0
    }
3559
0
    return ret;
3560
0
}
3561
3562
/**
3563
 * xmlParseStringName:
3564
 * @ctxt:  an XML parser context
3565
 * @str:  a pointer to the string pointer (IN/OUT)
3566
 *
3567
 * parse an XML name.
3568
 *
3569
 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3570
 *                  CombiningChar | Extender
3571
 *
3572
 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3573
 *
3574
 * [6] Names ::= Name (#x20 Name)*
3575
 *
3576
 * Returns the Name parsed or NULL. The @str pointer
3577
 * is updated to the current location in the string.
3578
 */
3579
3580
static xmlChar *
3581
0
xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
3582
0
    xmlChar buf[XML_MAX_NAMELEN + 5];
3583
0
    const xmlChar *cur = *str;
3584
0
    int len = 0, l;
3585
0
    int c;
3586
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3587
0
                    XML_MAX_TEXT_LENGTH :
3588
0
                    XML_MAX_NAME_LENGTH;
3589
3590
#ifdef DEBUG
3591
    nbParseStringName++;
3592
#endif
3593
3594
0
    c = CUR_SCHAR(cur, l);
3595
0
    if (!xmlIsNameStartChar(ctxt, c)) {
3596
0
  return(NULL);
3597
0
    }
3598
3599
0
    COPY_BUF(l,buf,len,c);
3600
0
    cur += l;
3601
0
    c = CUR_SCHAR(cur, l);
3602
0
    while (xmlIsNameChar(ctxt, c)) {
3603
0
  COPY_BUF(l,buf,len,c);
3604
0
  cur += l;
3605
0
  c = CUR_SCHAR(cur, l);
3606
0
  if (len >= XML_MAX_NAMELEN) { /* test bigentname.xml */
3607
      /*
3608
       * Okay someone managed to make a huge name, so he's ready to pay
3609
       * for the processing speed.
3610
       */
3611
0
      xmlChar *buffer;
3612
0
      int max = len * 2;
3613
3614
0
      buffer = (xmlChar *) xmlMallocAtomic(max);
3615
0
      if (buffer == NULL) {
3616
0
          xmlErrMemory(ctxt, NULL);
3617
0
    return(NULL);
3618
0
      }
3619
0
      memcpy(buffer, buf, len);
3620
0
      while (xmlIsNameChar(ctxt, c)) {
3621
0
    if (len + 10 > max) {
3622
0
        xmlChar *tmp;
3623
3624
0
        max *= 2;
3625
0
        tmp = (xmlChar *) xmlRealloc(buffer, max);
3626
0
        if (tmp == NULL) {
3627
0
      xmlErrMemory(ctxt, NULL);
3628
0
      xmlFree(buffer);
3629
0
      return(NULL);
3630
0
        }
3631
0
        buffer = tmp;
3632
0
    }
3633
0
    COPY_BUF(l,buffer,len,c);
3634
0
    cur += l;
3635
0
    c = CUR_SCHAR(cur, l);
3636
0
                if (len > maxLength) {
3637
0
                    xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3638
0
                    xmlFree(buffer);
3639
0
                    return(NULL);
3640
0
                }
3641
0
      }
3642
0
      buffer[len] = 0;
3643
0
      *str = cur;
3644
0
      return(buffer);
3645
0
  }
3646
0
    }
3647
0
    if (len > maxLength) {
3648
0
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3649
0
        return(NULL);
3650
0
    }
3651
0
    *str = cur;
3652
0
    return(xmlStrndup(buf, len));
3653
0
}
3654
3655
/**
3656
 * xmlParseNmtoken:
3657
 * @ctxt:  an XML parser context
3658
 *
3659
 * DEPRECATED: Internal function, don't use.
3660
 *
3661
 * parse an XML Nmtoken.
3662
 *
3663
 * [7] Nmtoken ::= (NameChar)+
3664
 *
3665
 * [8] Nmtokens ::= Nmtoken (#x20 Nmtoken)*
3666
 *
3667
 * Returns the Nmtoken parsed or NULL
3668
 */
3669
3670
xmlChar *
3671
0
xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
3672
0
    xmlChar buf[XML_MAX_NAMELEN + 5];
3673
0
    int len = 0, l;
3674
0
    int c;
3675
0
    int count = 0;
3676
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3677
0
                    XML_MAX_TEXT_LENGTH :
3678
0
                    XML_MAX_NAME_LENGTH;
3679
3680
#ifdef DEBUG
3681
    nbParseNmToken++;
3682
#endif
3683
3684
0
    GROW;
3685
0
    if (ctxt->instate == XML_PARSER_EOF)
3686
0
        return(NULL);
3687
0
    c = CUR_CHAR(l);
3688
3689
0
    while (xmlIsNameChar(ctxt, c)) {
3690
0
  if (count++ > XML_PARSER_CHUNK_SIZE) {
3691
0
      count = 0;
3692
0
      GROW;
3693
0
  }
3694
0
  COPY_BUF(l,buf,len,c);
3695
0
  NEXTL(l);
3696
0
  c = CUR_CHAR(l);
3697
0
  if (c == 0) {
3698
0
      count = 0;
3699
0
      GROW;
3700
0
      if (ctxt->instate == XML_PARSER_EOF)
3701
0
    return(NULL);
3702
0
            c = CUR_CHAR(l);
3703
0
  }
3704
0
  if (len >= XML_MAX_NAMELEN) {
3705
      /*
3706
       * Okay someone managed to make a huge token, so he's ready to pay
3707
       * for the processing speed.
3708
       */
3709
0
      xmlChar *buffer;
3710
0
      int max = len * 2;
3711
3712
0
      buffer = (xmlChar *) xmlMallocAtomic(max);
3713
0
      if (buffer == NULL) {
3714
0
          xmlErrMemory(ctxt, NULL);
3715
0
    return(NULL);
3716
0
      }
3717
0
      memcpy(buffer, buf, len);
3718
0
      while (xmlIsNameChar(ctxt, c)) {
3719
0
    if (count++ > XML_PARSER_CHUNK_SIZE) {
3720
0
        count = 0;
3721
0
        GROW;
3722
0
                    if (ctxt->instate == XML_PARSER_EOF) {
3723
0
                        xmlFree(buffer);
3724
0
                        return(NULL);
3725
0
                    }
3726
0
    }
3727
0
    if (len + 10 > max) {
3728
0
        xmlChar *tmp;
3729
3730
0
        max *= 2;
3731
0
        tmp = (xmlChar *) xmlRealloc(buffer, max);
3732
0
        if (tmp == NULL) {
3733
0
      xmlErrMemory(ctxt, NULL);
3734
0
      xmlFree(buffer);
3735
0
      return(NULL);
3736
0
        }
3737
0
        buffer = tmp;
3738
0
    }
3739
0
    COPY_BUF(l,buffer,len,c);
3740
0
    NEXTL(l);
3741
0
    c = CUR_CHAR(l);
3742
0
                if (len > maxLength) {
3743
0
                    xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
3744
0
                    xmlFree(buffer);
3745
0
                    return(NULL);
3746
0
                }
3747
0
      }
3748
0
      buffer[len] = 0;
3749
0
      return(buffer);
3750
0
  }
3751
0
    }
3752
0
    if (len == 0)
3753
0
        return(NULL);
3754
0
    if (len > maxLength) {
3755
0
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
3756
0
        return(NULL);
3757
0
    }
3758
0
    return(xmlStrndup(buf, len));
3759
0
}
3760
3761
/**
3762
 * xmlParseEntityValue:
3763
 * @ctxt:  an XML parser context
3764
 * @orig:  if non-NULL store a copy of the original entity value
3765
 *
3766
 * DEPRECATED: Internal function, don't use.
3767
 *
3768
 * parse a value for ENTITY declarations
3769
 *
3770
 * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
3771
 *                 "'" ([^%&'] | PEReference | Reference)* "'"
3772
 *
3773
 * Returns the EntityValue parsed with reference substituted or NULL
3774
 */
3775
3776
xmlChar *
3777
0
xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
3778
0
    xmlChar *buf = NULL;
3779
0
    int len = 0;
3780
0
    int size = XML_PARSER_BUFFER_SIZE;
3781
0
    int c, l;
3782
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3783
0
                    XML_MAX_HUGE_LENGTH :
3784
0
                    XML_MAX_TEXT_LENGTH;
3785
0
    xmlChar stop;
3786
0
    xmlChar *ret = NULL;
3787
0
    const xmlChar *cur = NULL;
3788
0
    xmlParserInputPtr input;
3789
3790
0
    if (RAW == '"') stop = '"';
3791
0
    else if (RAW == '\'') stop = '\'';
3792
0
    else {
3793
0
  xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_STARTED, NULL);
3794
0
  return(NULL);
3795
0
    }
3796
0
    buf = (xmlChar *) xmlMallocAtomic(size);
3797
0
    if (buf == NULL) {
3798
0
  xmlErrMemory(ctxt, NULL);
3799
0
  return(NULL);
3800
0
    }
3801
3802
    /*
3803
     * The content of the entity definition is copied in a buffer.
3804
     */
3805
3806
0
    ctxt->instate = XML_PARSER_ENTITY_VALUE;
3807
0
    input = ctxt->input;
3808
0
    GROW;
3809
0
    if (ctxt->instate == XML_PARSER_EOF)
3810
0
        goto error;
3811
0
    NEXT;
3812
0
    c = CUR_CHAR(l);
3813
    /*
3814
     * NOTE: 4.4.5 Included in Literal
3815
     * When a parameter entity reference appears in a literal entity
3816
     * value, ... a single or double quote character in the replacement
3817
     * text is always treated as a normal data character and will not
3818
     * terminate the literal.
3819
     * In practice it means we stop the loop only when back at parsing
3820
     * the initial entity and the quote is found
3821
     */
3822
0
    while (((IS_CHAR(c)) && ((c != stop) || /* checked */
3823
0
      (ctxt->input != input))) && (ctxt->instate != XML_PARSER_EOF)) {
3824
0
  if (len + 5 >= size) {
3825
0
      xmlChar *tmp;
3826
3827
0
      size *= 2;
3828
0
      tmp = (xmlChar *) xmlRealloc(buf, size);
3829
0
      if (tmp == NULL) {
3830
0
    xmlErrMemory(ctxt, NULL);
3831
0
                goto error;
3832
0
      }
3833
0
      buf = tmp;
3834
0
  }
3835
0
  COPY_BUF(l,buf,len,c);
3836
0
  NEXTL(l);
3837
3838
0
  GROW;
3839
0
  c = CUR_CHAR(l);
3840
0
  if (c == 0) {
3841
0
      GROW;
3842
0
      c = CUR_CHAR(l);
3843
0
  }
3844
3845
0
        if (len > maxLength) {
3846
0
            xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
3847
0
                           "entity value too long\n");
3848
0
            goto error;
3849
0
        }
3850
0
    }
3851
0
    buf[len] = 0;
3852
0
    if (ctxt->instate == XML_PARSER_EOF)
3853
0
        goto error;
3854
0
    if (c != stop) {
3855
0
        xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL);
3856
0
        goto error;
3857
0
    }
3858
0
    NEXT;
3859
3860
    /*
3861
     * Raise problem w.r.t. '&' and '%' being used in non-entities
3862
     * reference constructs. Note Charref will be handled in
3863
     * xmlStringDecodeEntities()
3864
     */
3865
0
    cur = buf;
3866
0
    while (*cur != 0) { /* non input consuming */
3867
0
  if ((*cur == '%') || ((*cur == '&') && (cur[1] != '#'))) {
3868
0
      xmlChar *name;
3869
0
      xmlChar tmp = *cur;
3870
0
            int nameOk = 0;
3871
3872
0
      cur++;
3873
0
      name = xmlParseStringName(ctxt, &cur);
3874
0
            if (name != NULL) {
3875
0
                nameOk = 1;
3876
0
                xmlFree(name);
3877
0
            }
3878
0
            if ((nameOk == 0) || (*cur != ';')) {
3879
0
    xmlFatalErrMsgInt(ctxt, XML_ERR_ENTITY_CHAR_ERROR,
3880
0
      "EntityValue: '%c' forbidden except for entities references\n",
3881
0
                            tmp);
3882
0
                goto error;
3883
0
      }
3884
0
      if ((tmp == '%') && (ctxt->inSubset == 1) &&
3885
0
    (ctxt->inputNr == 1)) {
3886
0
    xmlFatalErr(ctxt, XML_ERR_ENTITY_PE_INTERNAL, NULL);
3887
0
                goto error;
3888
0
      }
3889
0
      if (*cur == 0)
3890
0
          break;
3891
0
  }
3892
0
  cur++;
3893
0
    }
3894
3895
    /*
3896
     * Then PEReference entities are substituted.
3897
     *
3898
     * NOTE: 4.4.7 Bypassed
3899
     * When a general entity reference appears in the EntityValue in
3900
     * an entity declaration, it is bypassed and left as is.
3901
     * so XML_SUBSTITUTE_REF is not set here.
3902
     */
3903
0
    ++ctxt->depth;
3904
0
    ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF,
3905
0
                                  0, 0, 0);
3906
0
    --ctxt->depth;
3907
0
    if (orig != NULL) {
3908
0
        *orig = buf;
3909
0
        buf = NULL;
3910
0
    }
3911
3912
0
error:
3913
0
    if (buf != NULL)
3914
0
        xmlFree(buf);
3915
0
    return(ret);
3916
0
}
3917
3918
/**
3919
 * xmlParseAttValueComplex:
3920
 * @ctxt:  an XML parser context
3921
 * @len:   the resulting attribute len
3922
 * @normalize:  whether to apply the inner normalization
3923
 *
3924
 * parse a value for an attribute, this is the fallback function
3925
 * of xmlParseAttValue() when the attribute parsing requires handling
3926
 * of non-ASCII characters, or normalization compaction.
3927
 *
3928
 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
3929
 */
3930
static xmlChar *
3931
2
xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
3932
2
    xmlChar limit = 0;
3933
2
    xmlChar *buf = NULL;
3934
2
    xmlChar *rep = NULL;
3935
2
    size_t len = 0;
3936
2
    size_t buf_size = 0;
3937
2
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3938
0
                       XML_MAX_HUGE_LENGTH :
3939
2
                       XML_MAX_TEXT_LENGTH;
3940
2
    int c, l, in_space = 0;
3941
2
    xmlChar *current = NULL;
3942
2
    xmlEntityPtr ent;
3943
3944
2
    if (NXT(0) == '"') {
3945
2
  ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
3946
2
  limit = '"';
3947
2
        NEXT;
3948
2
    } else if (NXT(0) == '\'') {
3949
0
  limit = '\'';
3950
0
  ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
3951
0
        NEXT;
3952
0
    } else {
3953
0
  xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
3954
0
  return(NULL);
3955
0
    }
3956
3957
    /*
3958
     * allocate a translation buffer.
3959
     */
3960
2
    buf_size = XML_PARSER_BUFFER_SIZE;
3961
2
    buf = (xmlChar *) xmlMallocAtomic(buf_size);
3962
2
    if (buf == NULL) goto mem_error;
3963
3964
    /*
3965
     * OK loop until we reach one of the ending char or a size limit.
3966
     */
3967
2
    c = CUR_CHAR(l);
3968
8
    while (((NXT(0) != limit) && /* checked */
3969
8
            (IS_CHAR(c)) && (c != '<')) &&
3970
8
            (ctxt->instate != XML_PARSER_EOF)) {
3971
6
  if (c == '&') {
3972
0
      in_space = 0;
3973
0
      if (NXT(1) == '#') {
3974
0
    int val = xmlParseCharRef(ctxt);
3975
3976
0
    if (val == '&') {
3977
0
        if (ctxt->replaceEntities) {
3978
0
      if (len + 10 > buf_size) {
3979
0
          growBuffer(buf, 10);
3980
0
      }
3981
0
      buf[len++] = '&';
3982
0
        } else {
3983
      /*
3984
       * The reparsing will be done in xmlStringGetNodeList()
3985
       * called by the attribute() function in SAX.c
3986
       */
3987
0
      if (len + 10 > buf_size) {
3988
0
          growBuffer(buf, 10);
3989
0
      }
3990
0
      buf[len++] = '&';
3991
0
      buf[len++] = '#';
3992
0
      buf[len++] = '3';
3993
0
      buf[len++] = '8';
3994
0
      buf[len++] = ';';
3995
0
        }
3996
0
    } else if (val != 0) {
3997
0
        if (len + 10 > buf_size) {
3998
0
      growBuffer(buf, 10);
3999
0
        }
4000
0
        len += xmlCopyChar(0, &buf[len], val);
4001
0
    }
4002
0
      } else {
4003
0
    ent = xmlParseEntityRef(ctxt);
4004
0
    ctxt->nbentities++;
4005
0
    if (ent != NULL)
4006
0
        ctxt->nbentities += ent->owner;
4007
0
    if ((ent != NULL) &&
4008
0
        (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
4009
0
        if (len + 10 > buf_size) {
4010
0
      growBuffer(buf, 10);
4011
0
        }
4012
0
        if ((ctxt->replaceEntities == 0) &&
4013
0
            (ent->content[0] == '&')) {
4014
0
      buf[len++] = '&';
4015
0
      buf[len++] = '#';
4016
0
      buf[len++] = '3';
4017
0
      buf[len++] = '8';
4018
0
      buf[len++] = ';';
4019
0
        } else {
4020
0
      buf[len++] = ent->content[0];
4021
0
        }
4022
0
    } else if ((ent != NULL) &&
4023
0
               (ctxt->replaceEntities != 0)) {
4024
0
        if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
4025
0
      ++ctxt->depth;
4026
0
      rep = xmlStringDecodeEntities(ctxt, ent->content,
4027
0
                  XML_SUBSTITUTE_REF,
4028
0
                  0, 0, 0);
4029
0
      --ctxt->depth;
4030
0
      if (rep != NULL) {
4031
0
          current = rep;
4032
0
          while (*current != 0) { /* non input consuming */
4033
0
                                if ((*current == 0xD) || (*current == 0xA) ||
4034
0
                                    (*current == 0x9)) {
4035
0
                                    buf[len++] = 0x20;
4036
0
                                    current++;
4037
0
                                } else
4038
0
                                    buf[len++] = *current++;
4039
0
        if (len + 10 > buf_size) {
4040
0
            growBuffer(buf, 10);
4041
0
        }
4042
0
          }
4043
0
          xmlFree(rep);
4044
0
          rep = NULL;
4045
0
      }
4046
0
        } else {
4047
0
      if (len + 10 > buf_size) {
4048
0
          growBuffer(buf, 10);
4049
0
      }
4050
0
      if (ent->content != NULL)
4051
0
          buf[len++] = ent->content[0];
4052
0
        }
4053
0
    } else if (ent != NULL) {
4054
0
        int i = xmlStrlen(ent->name);
4055
0
        const xmlChar *cur = ent->name;
4056
4057
        /*
4058
         * This may look absurd but is needed to detect
4059
         * entities problems
4060
         */
4061
0
        if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
4062
0
      (ent->content != NULL) && (ent->checked == 0)) {
4063
0
      unsigned long oldnbent = ctxt->nbentities, diff;
4064
4065
0
      ++ctxt->depth;
4066
0
      rep = xmlStringDecodeEntities(ctxt, ent->content,
4067
0
              XML_SUBSTITUTE_REF, 0, 0, 0);
4068
0
      --ctxt->depth;
4069
4070
0
                        diff = ctxt->nbentities - oldnbent + 1;
4071
0
                        if (diff > INT_MAX / 2)
4072
0
                            diff = INT_MAX / 2;
4073
0
                        ent->checked = diff * 2;
4074
0
      if (rep != NULL) {
4075
0
          if (xmlStrchr(rep, '<'))
4076
0
              ent->checked |= 1;
4077
0
          xmlFree(rep);
4078
0
          rep = NULL;
4079
0
      } else {
4080
0
                            ent->content[0] = 0;
4081
0
                        }
4082
0
        }
4083
4084
        /*
4085
         * Just output the reference
4086
         */
4087
0
        buf[len++] = '&';
4088
0
        while (len + i + 10 > buf_size) {
4089
0
      growBuffer(buf, i + 10);
4090
0
        }
4091
0
        for (;i > 0;i--)
4092
0
      buf[len++] = *cur++;
4093
0
        buf[len++] = ';';
4094
0
    }
4095
0
      }
4096
6
  } else {
4097
6
      if ((c == 0x20) || (c == 0xD) || (c == 0xA) || (c == 0x9)) {
4098
0
          if ((len != 0) || (!normalize)) {
4099
0
        if ((!normalize) || (!in_space)) {
4100
0
      COPY_BUF(l,buf,len,0x20);
4101
0
      while (len + 10 > buf_size) {
4102
0
          growBuffer(buf, 10);
4103
0
      }
4104
0
        }
4105
0
        in_space = 1;
4106
0
    }
4107
6
      } else {
4108
6
          in_space = 0;
4109
6
    COPY_BUF(l,buf,len,c);
4110
6
    if (len + 10 > buf_size) {
4111
0
        growBuffer(buf, 10);
4112
0
    }
4113
6
      }
4114
6
      NEXTL(l);
4115
6
  }
4116
6
  GROW;
4117
6
  c = CUR_CHAR(l);
4118
6
        if (len > maxLength) {
4119
0
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
4120
0
                           "AttValue length too long\n");
4121
0
            goto mem_error;
4122
0
        }
4123
6
    }
4124
2
    if (ctxt->instate == XML_PARSER_EOF)
4125
0
        goto error;
4126
4127
2
    if ((in_space) && (normalize)) {
4128
0
        while ((len > 0) && (buf[len - 1] == 0x20)) len--;
4129
0
    }
4130
2
    buf[len] = 0;
4131
2
    if (RAW == '<') {
4132
0
  xmlFatalErr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, NULL);
4133
2
    } else if (RAW != limit) {
4134
0
  if ((c != 0) && (!IS_CHAR(c))) {
4135
0
      xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
4136
0
         "invalid character in attribute value\n");
4137
0
  } else {
4138
0
      xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
4139
0
         "AttValue: ' expected\n");
4140
0
        }
4141
0
    } else
4142
2
  NEXT;
4143
4144
2
    if (attlen != NULL) *attlen = len;
4145
2
    return(buf);
4146
4147
0
mem_error:
4148
0
    xmlErrMemory(ctxt, NULL);
4149
0
error:
4150
0
    if (buf != NULL)
4151
0
        xmlFree(buf);
4152
0
    if (rep != NULL)
4153
0
        xmlFree(rep);
4154
0
    return(NULL);
4155
0
}
4156
4157
/**
4158
 * xmlParseAttValue:
4159
 * @ctxt:  an XML parser context
4160
 *
4161
 * DEPRECATED: Internal function, don't use.
4162
 *
4163
 * parse a value for an attribute
4164
 * Note: the parser won't do substitution of entities here, this
4165
 * will be handled later in xmlStringGetNodeList
4166
 *
4167
 * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |
4168
 *                   "'" ([^<&'] | Reference)* "'"
4169
 *
4170
 * 3.3.3 Attribute-Value Normalization:
4171
 * Before the value of an attribute is passed to the application or
4172
 * checked for validity, the XML processor must normalize it as follows:
4173
 * - a character reference is processed by appending the referenced
4174
 *   character to the attribute value
4175
 * - an entity reference is processed by recursively processing the
4176
 *   replacement text of the entity
4177
 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
4178
 *   appending #x20 to the normalized value, except that only a single
4179
 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
4180
 *   parsed entity or the literal entity value of an internal parsed entity
4181
 * - other characters are processed by appending them to the normalized value
4182
 * If the declared value is not CDATA, then the XML processor must further
4183
 * process the normalized attribute value by discarding any leading and
4184
 * trailing space (#x20) characters, and by replacing sequences of space
4185
 * (#x20) characters by a single space (#x20) character.
4186
 * All attributes for which no declaration has been read should be treated
4187
 * by a non-validating parser as if declared CDATA.
4188
 *
4189
 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
4190
 */
4191
4192
4193
xmlChar *
4194
0
xmlParseAttValue(xmlParserCtxtPtr ctxt) {
4195
0
    if ((ctxt == NULL) || (ctxt->input == NULL)) return(NULL);
4196
0
    return(xmlParseAttValueInternal(ctxt, NULL, NULL, 0));
4197
0
}
4198
4199
/**
4200
 * xmlParseSystemLiteral:
4201
 * @ctxt:  an XML parser context
4202
 *
4203
 * DEPRECATED: Internal function, don't use.
4204
 *
4205
 * parse an XML Literal
4206
 *
4207
 * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
4208
 *
4209
 * Returns the SystemLiteral parsed or NULL
4210
 */
4211
4212
xmlChar *
4213
0
xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
4214
0
    xmlChar *buf = NULL;
4215
0
    int len = 0;
4216
0
    int size = XML_PARSER_BUFFER_SIZE;
4217
0
    int cur, l;
4218
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4219
0
                    XML_MAX_TEXT_LENGTH :
4220
0
                    XML_MAX_NAME_LENGTH;
4221
0
    xmlChar stop;
4222
0
    int state = ctxt->instate;
4223
0
    int count = 0;
4224
4225
0
    SHRINK;
4226
0
    if (RAW == '"') {
4227
0
        NEXT;
4228
0
  stop = '"';
4229
0
    } else if (RAW == '\'') {
4230
0
        NEXT;
4231
0
  stop = '\'';
4232
0
    } else {
4233
0
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
4234
0
  return(NULL);
4235
0
    }
4236
4237
0
    buf = (xmlChar *) xmlMallocAtomic(size);
4238
0
    if (buf == NULL) {
4239
0
        xmlErrMemory(ctxt, NULL);
4240
0
  return(NULL);
4241
0
    }
4242
0
    ctxt->instate = XML_PARSER_SYSTEM_LITERAL;
4243
0
    cur = CUR_CHAR(l);
4244
0
    while ((IS_CHAR(cur)) && (cur != stop)) { /* checked */
4245
0
  if (len + 5 >= size) {
4246
0
      xmlChar *tmp;
4247
4248
0
      size *= 2;
4249
0
      tmp = (xmlChar *) xmlRealloc(buf, size);
4250
0
      if (tmp == NULL) {
4251
0
          xmlFree(buf);
4252
0
    xmlErrMemory(ctxt, NULL);
4253
0
    ctxt->instate = (xmlParserInputState) state;
4254
0
    return(NULL);
4255
0
      }
4256
0
      buf = tmp;
4257
0
  }
4258
0
  count++;
4259
0
  if (count > 50) {
4260
0
      SHRINK;
4261
0
      GROW;
4262
0
      count = 0;
4263
0
            if (ctxt->instate == XML_PARSER_EOF) {
4264
0
          xmlFree(buf);
4265
0
    return(NULL);
4266
0
            }
4267
0
  }
4268
0
  COPY_BUF(l,buf,len,cur);
4269
0
  NEXTL(l);
4270
0
  cur = CUR_CHAR(l);
4271
0
  if (cur == 0) {
4272
0
      GROW;
4273
0
      SHRINK;
4274
0
      cur = CUR_CHAR(l);
4275
0
  }
4276
0
        if (len > maxLength) {
4277
0
            xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral");
4278
0
            xmlFree(buf);
4279
0
            ctxt->instate = (xmlParserInputState) state;
4280
0
            return(NULL);
4281
0
        }
4282
0
    }
4283
0
    buf[len] = 0;
4284
0
    ctxt->instate = (xmlParserInputState) state;
4285
0
    if (!IS_CHAR(cur)) {
4286
0
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
4287
0
    } else {
4288
0
  NEXT;
4289
0
    }
4290
0
    return(buf);
4291
0
}
4292
4293
/**
4294
 * xmlParsePubidLiteral:
4295
 * @ctxt:  an XML parser context
4296
 *
4297
 * DEPRECATED: Internal function, don't use.
4298
 *
4299
 * parse an XML public literal
4300
 *
4301
 * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
4302
 *
4303
 * Returns the PubidLiteral parsed or NULL.
4304
 */
4305
4306
xmlChar *
4307
0
xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
4308
0
    xmlChar *buf = NULL;
4309
0
    int len = 0;
4310
0
    int size = XML_PARSER_BUFFER_SIZE;
4311
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4312
0
                    XML_MAX_TEXT_LENGTH :
4313
0
                    XML_MAX_NAME_LENGTH;
4314
0
    xmlChar cur;
4315
0
    xmlChar stop;
4316
0
    int count = 0;
4317
0
    xmlParserInputState oldstate = ctxt->instate;
4318
4319
0
    SHRINK;
4320
0
    if (RAW == '"') {
4321
0
        NEXT;
4322
0
  stop = '"';
4323
0
    } else if (RAW == '\'') {
4324
0
        NEXT;
4325
0
  stop = '\'';
4326
0
    } else {
4327
0
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
4328
0
  return(NULL);
4329
0
    }
4330
0
    buf = (xmlChar *) xmlMallocAtomic(size);
4331
0
    if (buf == NULL) {
4332
0
  xmlErrMemory(ctxt, NULL);
4333
0
  return(NULL);
4334
0
    }
4335
0
    ctxt->instate = XML_PARSER_PUBLIC_LITERAL;
4336
0
    cur = CUR;
4337
0
    while ((IS_PUBIDCHAR_CH(cur)) && (cur != stop)) { /* checked */
4338
0
  if (len + 1 >= size) {
4339
0
      xmlChar *tmp;
4340
4341
0
      size *= 2;
4342
0
      tmp = (xmlChar *) xmlRealloc(buf, size);
4343
0
      if (tmp == NULL) {
4344
0
    xmlErrMemory(ctxt, NULL);
4345
0
    xmlFree(buf);
4346
0
    return(NULL);
4347
0
      }
4348
0
      buf = tmp;
4349
0
  }
4350
0
  buf[len++] = cur;
4351
0
  count++;
4352
0
  if (count > 50) {
4353
0
      SHRINK;
4354
0
      GROW;
4355
0
      count = 0;
4356
0
            if (ctxt->instate == XML_PARSER_EOF) {
4357
0
    xmlFree(buf);
4358
0
    return(NULL);
4359
0
            }
4360
0
  }
4361
0
  NEXT;
4362
0
  cur = CUR;
4363
0
  if (cur == 0) {
4364
0
      GROW;
4365
0
      SHRINK;
4366
0
      cur = CUR;
4367
0
  }
4368
0
        if (len > maxLength) {
4369
0
            xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Public ID");
4370
0
            xmlFree(buf);
4371
0
            return(NULL);
4372
0
        }
4373
0
    }
4374
0
    buf[len] = 0;
4375
0
    if (cur != stop) {
4376
0
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
4377
0
    } else {
4378
0
  NEXT;
4379
0
    }
4380
0
    ctxt->instate = oldstate;
4381
0
    return(buf);
4382
0
}
4383
4384
static void xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata);
4385
4386
/*
4387
 * used for the test in the inner loop of the char data testing
4388
 */
4389
static const unsigned char test_char_data[256] = {
4390
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4391
    0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9, CR/LF separated */
4392
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4393
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4394
    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x00, 0x27, /* & */
4395
    0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
4396
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
4397
    0x38, 0x39, 0x3A, 0x3B, 0x00, 0x3D, 0x3E, 0x3F, /* < */
4398
    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
4399
    0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
4400
    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
4401
    0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x00, 0x5E, 0x5F, /* ] */
4402
    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
4403
    0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
4404
    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
4405
    0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
4406
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* non-ascii */
4407
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4408
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4409
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4410
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4411
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4412
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4413
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4414
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4415
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4416
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4417
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4418
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4419
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4420
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4421
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4422
};
4423
4424
/**
4425
 * xmlParseCharData:
4426
 * @ctxt:  an XML parser context
4427
 * @cdata:  int indicating whether we are within a CDATA section
4428
 *
4429
 * DEPRECATED: Internal function, don't use.
4430
 *
4431
 * parse a CharData section.
4432
 * if we are within a CDATA section ']]>' marks an end of section.
4433
 *
4434
 * The right angle bracket (>) may be represented using the string "&gt;",
4435
 * and must, for compatibility, be escaped using "&gt;" or a character
4436
 * reference when it appears in the string "]]>" in content, when that
4437
 * string is not marking the end of a CDATA section.
4438
 *
4439
 * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
4440
 */
4441
4442
void
4443
44
xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) {
4444
44
    const xmlChar *in;
4445
44
    int nbchar = 0;
4446
44
    int line = ctxt->input->line;
4447
44
    int col = ctxt->input->col;
4448
44
    int ccol;
4449
4450
44
    SHRINK;
4451
44
    GROW;
4452
    /*
4453
     * Accelerated common case where input don't need to be
4454
     * modified before passing it to the handler.
4455
     */
4456
44
    if (!cdata) {
4457
44
  in = ctxt->input->cur;
4458
44
  do {
4459
78
get_more_space:
4460
270
      while (*in == 0x20) { in++; ctxt->input->col++; }
4461
78
      if (*in == 0xA) {
4462
34
    do {
4463
34
        ctxt->input->line++; ctxt->input->col = 1;
4464
34
        in++;
4465
34
    } while (*in == 0xA);
4466
34
    goto get_more_space;
4467
34
      }
4468
44
      if (*in == '<') {
4469
34
    nbchar = in - ctxt->input->cur;
4470
34
    if (nbchar > 0) {
4471
34
        const xmlChar *tmp = ctxt->input->cur;
4472
34
        ctxt->input->cur = in;
4473
4474
34
        if ((ctxt->sax != NULL) &&
4475
34
            (ctxt->sax->ignorableWhitespace !=
4476
34
             ctxt->sax->characters)) {
4477
0
      if (areBlanks(ctxt, tmp, nbchar, 1)) {
4478
0
          if (ctxt->sax->ignorableWhitespace != NULL)
4479
0
        ctxt->sax->ignorableWhitespace(ctxt->userData,
4480
0
                   tmp, nbchar);
4481
0
      } else {
4482
0
          if (ctxt->sax->characters != NULL)
4483
0
        ctxt->sax->characters(ctxt->userData,
4484
0
                  tmp, nbchar);
4485
0
          if (*ctxt->space == -1)
4486
0
              *ctxt->space = -2;
4487
0
      }
4488
34
        } else if ((ctxt->sax != NULL) &&
4489
34
                   (ctxt->sax->characters != NULL)) {
4490
34
      ctxt->sax->characters(ctxt->userData,
4491
34
                tmp, nbchar);
4492
34
        }
4493
34
    }
4494
34
    return;
4495
34
      }
4496
4497
10
get_more:
4498
10
            ccol = ctxt->input->col;
4499
36
      while (test_char_data[*in]) {
4500
26
    in++;
4501
26
    ccol++;
4502
26
      }
4503
10
      ctxt->input->col = ccol;
4504
10
      if (*in == 0xA) {
4505
0
    do {
4506
0
        ctxt->input->line++; ctxt->input->col = 1;
4507
0
        in++;
4508
0
    } while (*in == 0xA);
4509
0
    goto get_more;
4510
0
      }
4511
10
      if (*in == ']') {
4512
0
    if ((in[1] == ']') && (in[2] == '>')) {
4513
0
        xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
4514
0
        ctxt->input->cur = in + 1;
4515
0
        return;
4516
0
    }
4517
0
    in++;
4518
0
    ctxt->input->col++;
4519
0
    goto get_more;
4520
0
      }
4521
10
      nbchar = in - ctxt->input->cur;
4522
10
      if (nbchar > 0) {
4523
6
    if ((ctxt->sax != NULL) &&
4524
6
        (ctxt->sax->ignorableWhitespace !=
4525
6
         ctxt->sax->characters) &&
4526
6
        (IS_BLANK_CH(*ctxt->input->cur))) {
4527
0
        const xmlChar *tmp = ctxt->input->cur;
4528
0
        ctxt->input->cur = in;
4529
4530
0
        if (areBlanks(ctxt, tmp, nbchar, 0)) {
4531
0
            if (ctxt->sax->ignorableWhitespace != NULL)
4532
0
          ctxt->sax->ignorableWhitespace(ctxt->userData,
4533
0
                 tmp, nbchar);
4534
0
        } else {
4535
0
            if (ctxt->sax->characters != NULL)
4536
0
          ctxt->sax->characters(ctxt->userData,
4537
0
              tmp, nbchar);
4538
0
      if (*ctxt->space == -1)
4539
0
          *ctxt->space = -2;
4540
0
        }
4541
0
                    line = ctxt->input->line;
4542
0
                    col = ctxt->input->col;
4543
6
    } else if (ctxt->sax != NULL) {
4544
6
        if (ctxt->sax->characters != NULL)
4545
6
      ctxt->sax->characters(ctxt->userData,
4546
6
                ctxt->input->cur, nbchar);
4547
6
                    line = ctxt->input->line;
4548
6
                    col = ctxt->input->col;
4549
6
    }
4550
                /* something really bad happened in the SAX callback */
4551
6
                if (ctxt->instate != XML_PARSER_CONTENT)
4552
0
                    return;
4553
6
      }
4554
10
      ctxt->input->cur = in;
4555
10
      if (*in == 0xD) {
4556
0
    in++;
4557
0
    if (*in == 0xA) {
4558
0
        ctxt->input->cur = in;
4559
0
        in++;
4560
0
        ctxt->input->line++; ctxt->input->col = 1;
4561
0
        continue; /* while */
4562
0
    }
4563
0
    in--;
4564
0
      }
4565
10
      if (*in == '<') {
4566
6
    return;
4567
6
      }
4568
4
      if (*in == '&') {
4569
0
    return;
4570
0
      }
4571
4
      SHRINK;
4572
4
      GROW;
4573
4
            if (ctxt->instate == XML_PARSER_EOF)
4574
0
    return;
4575
4
      in = ctxt->input->cur;
4576
4
  } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09) || (*in == 0x0a));
4577
4
  nbchar = 0;
4578
4
    }
4579
4
    ctxt->input->line = line;
4580
4
    ctxt->input->col = col;
4581
4
    xmlParseCharDataComplex(ctxt, cdata);
4582
4
}
4583
4584
/**
4585
 * xmlParseCharDataComplex:
4586
 * @ctxt:  an XML parser context
4587
 * @cdata:  int indicating whether we are within a CDATA section
4588
 *
4589
 * parse a CharData section.this is the fallback function
4590
 * of xmlParseCharData() when the parsing requires handling
4591
 * of non-ASCII characters.
4592
 */
4593
static void
4594
4
xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) {
4595
4
    xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE + 5];
4596
4
    int nbchar = 0;
4597
4
    int cur, l;
4598
4
    int count = 0;
4599
4600
4
    SHRINK;
4601
4
    GROW;
4602
4
    cur = CUR_CHAR(l);
4603
16
    while ((cur != '<') && /* checked */
4604
16
           (cur != '&') &&
4605
16
     (IS_CHAR(cur))) /* test also done in xmlCurrentChar() */ {
4606
12
  if ((cur == ']') && (NXT(1) == ']') &&
4607
12
      (NXT(2) == '>')) {
4608
0
      if (cdata) break;
4609
0
      else {
4610
0
    xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
4611
0
      }
4612
0
  }
4613
12
  COPY_BUF(l,buf,nbchar,cur);
4614
  /* move current position before possible calling of ctxt->sax->characters */
4615
12
  NEXTL(l);
4616
12
  cur = CUR_CHAR(l);
4617
12
  if (nbchar >= XML_PARSER_BIG_BUFFER_SIZE) {
4618
0
      buf[nbchar] = 0;
4619
4620
      /*
4621
       * OK the segment is to be consumed as chars.
4622
       */
4623
0
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
4624
0
    if (areBlanks(ctxt, buf, nbchar, 0)) {
4625
0
        if (ctxt->sax->ignorableWhitespace != NULL)
4626
0
      ctxt->sax->ignorableWhitespace(ctxt->userData,
4627
0
                                     buf, nbchar);
4628
0
    } else {
4629
0
        if (ctxt->sax->characters != NULL)
4630
0
      ctxt->sax->characters(ctxt->userData, buf, nbchar);
4631
0
        if ((ctxt->sax->characters !=
4632
0
             ctxt->sax->ignorableWhitespace) &&
4633
0
      (*ctxt->space == -1))
4634
0
      *ctxt->space = -2;
4635
0
    }
4636
0
      }
4637
0
      nbchar = 0;
4638
            /* something really bad happened in the SAX callback */
4639
0
            if (ctxt->instate != XML_PARSER_CONTENT)
4640
0
                return;
4641
0
  }
4642
12
  count++;
4643
12
  if (count > 50) {
4644
0
      SHRINK;
4645
0
      GROW;
4646
0
      count = 0;
4647
0
            if (ctxt->instate == XML_PARSER_EOF)
4648
0
    return;
4649
0
  }
4650
12
    }
4651
4
    if (nbchar != 0) {
4652
4
        buf[nbchar] = 0;
4653
  /*
4654
   * OK the segment is to be consumed as chars.
4655
   */
4656
4
  if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
4657
4
      if (areBlanks(ctxt, buf, nbchar, 0)) {
4658
0
    if (ctxt->sax->ignorableWhitespace != NULL)
4659
0
        ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
4660
4
      } else {
4661
4
    if (ctxt->sax->characters != NULL)
4662
4
        ctxt->sax->characters(ctxt->userData, buf, nbchar);
4663
4
    if ((ctxt->sax->characters != ctxt->sax->ignorableWhitespace) &&
4664
4
        (*ctxt->space == -1))
4665
0
        *ctxt->space = -2;
4666
4
      }
4667
4
  }
4668
4
    }
4669
4
    if ((cur != 0) && (!IS_CHAR(cur))) {
4670
  /* Generate the error and skip the offending character */
4671
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4672
0
                          "PCDATA invalid Char value %d\n",
4673
0
                    cur);
4674
0
  NEXTL(l);
4675
0
    }
4676
4
}
4677
4678
/**
4679
 * xmlParseExternalID:
4680
 * @ctxt:  an XML parser context
4681
 * @publicID:  a xmlChar** receiving PubidLiteral
4682
 * @strict: indicate whether we should restrict parsing to only
4683
 *          production [75], see NOTE below
4684
 *
4685
 * DEPRECATED: Internal function, don't use.
4686
 *
4687
 * Parse an External ID or a Public ID
4688
 *
4689
 * NOTE: Productions [75] and [83] interact badly since [75] can generate
4690
 *       'PUBLIC' S PubidLiteral S SystemLiteral
4691
 *
4692
 * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
4693
 *                   | 'PUBLIC' S PubidLiteral S SystemLiteral
4694
 *
4695
 * [83] PublicID ::= 'PUBLIC' S PubidLiteral
4696
 *
4697
 * Returns the function returns SystemLiteral and in the second
4698
 *                case publicID receives PubidLiteral, is strict is off
4699
 *                it is possible to return NULL and have publicID set.
4700
 */
4701
4702
xmlChar *
4703
0
xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
4704
0
    xmlChar *URI = NULL;
4705
4706
0
    SHRINK;
4707
4708
0
    *publicID = NULL;
4709
0
    if (CMP6(CUR_PTR, 'S', 'Y', 'S', 'T', 'E', 'M')) {
4710
0
        SKIP(6);
4711
0
  if (SKIP_BLANKS == 0) {
4712
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4713
0
                     "Space required after 'SYSTEM'\n");
4714
0
  }
4715
0
  URI = xmlParseSystemLiteral(ctxt);
4716
0
  if (URI == NULL) {
4717
0
      xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
4718
0
        }
4719
0
    } else if (CMP6(CUR_PTR, 'P', 'U', 'B', 'L', 'I', 'C')) {
4720
0
        SKIP(6);
4721
0
  if (SKIP_BLANKS == 0) {
4722
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4723
0
        "Space required after 'PUBLIC'\n");
4724
0
  }
4725
0
  *publicID = xmlParsePubidLiteral(ctxt);
4726
0
  if (*publicID == NULL) {
4727
0
      xmlFatalErr(ctxt, XML_ERR_PUBID_REQUIRED, NULL);
4728
0
  }
4729
0
  if (strict) {
4730
      /*
4731
       * We don't handle [83] so "S SystemLiteral" is required.
4732
       */
4733
0
      if (SKIP_BLANKS == 0) {
4734
0
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4735
0
      "Space required after the Public Identifier\n");
4736
0
      }
4737
0
  } else {
4738
      /*
4739
       * We handle [83] so we return immediately, if
4740
       * "S SystemLiteral" is not detected. We skip blanks if no
4741
             * system literal was found, but this is harmless since we must
4742
             * be at the end of a NotationDecl.
4743
       */
4744
0
      if (SKIP_BLANKS == 0) return(NULL);
4745
0
      if ((CUR != '\'') && (CUR != '"')) return(NULL);
4746
0
  }
4747
0
  URI = xmlParseSystemLiteral(ctxt);
4748
0
  if (URI == NULL) {
4749
0
      xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
4750
0
        }
4751
0
    }
4752
0
    return(URI);
4753
0
}
4754
4755
/**
4756
 * xmlParseCommentComplex:
4757
 * @ctxt:  an XML parser context
4758
 * @buf:  the already parsed part of the buffer
4759
 * @len:  number of bytes in the buffer
4760
 * @size:  allocated size of the buffer
4761
 *
4762
 * Skip an XML (SGML) comment <!-- .... -->
4763
 *  The spec says that "For compatibility, the string "--" (double-hyphen)
4764
 *  must not occur within comments. "
4765
 * This is the slow routine in case the accelerator for ascii didn't work
4766
 *
4767
 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
4768
 */
4769
static void
4770
xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
4771
0
                       size_t len, size_t size) {
4772
0
    int q, ql;
4773
0
    int r, rl;
4774
0
    int cur, l;
4775
0
    size_t count = 0;
4776
0
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4777
0
                       XML_MAX_HUGE_LENGTH :
4778
0
                       XML_MAX_TEXT_LENGTH;
4779
0
    int inputid;
4780
4781
0
    inputid = ctxt->input->id;
4782
4783
0
    if (buf == NULL) {
4784
0
        len = 0;
4785
0
  size = XML_PARSER_BUFFER_SIZE;
4786
0
  buf = (xmlChar *) xmlMallocAtomic(size);
4787
0
  if (buf == NULL) {
4788
0
      xmlErrMemory(ctxt, NULL);
4789
0
      return;
4790
0
  }
4791
0
    }
4792
0
    GROW; /* Assure there's enough input data */
4793
0
    q = CUR_CHAR(ql);
4794
0
    if (q == 0)
4795
0
        goto not_terminated;
4796
0
    if (!IS_CHAR(q)) {
4797
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4798
0
                          "xmlParseComment: invalid xmlChar value %d\n",
4799
0
                    q);
4800
0
  xmlFree (buf);
4801
0
  return;
4802
0
    }
4803
0
    NEXTL(ql);
4804
0
    r = CUR_CHAR(rl);
4805
0
    if (r == 0)
4806
0
        goto not_terminated;
4807
0
    if (!IS_CHAR(r)) {
4808
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4809
0
                          "xmlParseComment: invalid xmlChar value %d\n",
4810
0
                    r);
4811
0
  xmlFree (buf);
4812
0
  return;
4813
0
    }
4814
0
    NEXTL(rl);
4815
0
    cur = CUR_CHAR(l);
4816
0
    if (cur == 0)
4817
0
        goto not_terminated;
4818
0
    while (IS_CHAR(cur) && /* checked */
4819
0
           ((cur != '>') ||
4820
0
      (r != '-') || (q != '-'))) {
4821
0
  if ((r == '-') && (q == '-')) {
4822
0
      xmlFatalErr(ctxt, XML_ERR_HYPHEN_IN_COMMENT, NULL);
4823
0
  }
4824
0
  if (len + 5 >= size) {
4825
0
      xmlChar *new_buf;
4826
0
            size_t new_size;
4827
4828
0
      new_size = size * 2;
4829
0
      new_buf = (xmlChar *) xmlRealloc(buf, new_size);
4830
0
      if (new_buf == NULL) {
4831
0
    xmlFree (buf);
4832
0
    xmlErrMemory(ctxt, NULL);
4833
0
    return;
4834
0
      }
4835
0
      buf = new_buf;
4836
0
            size = new_size;
4837
0
  }
4838
0
  COPY_BUF(ql,buf,len,q);
4839
0
  q = r;
4840
0
  ql = rl;
4841
0
  r = cur;
4842
0
  rl = l;
4843
4844
0
  count++;
4845
0
  if (count > 50) {
4846
0
      SHRINK;
4847
0
      GROW;
4848
0
      count = 0;
4849
0
            if (ctxt->instate == XML_PARSER_EOF) {
4850
0
    xmlFree(buf);
4851
0
    return;
4852
0
            }
4853
0
  }
4854
0
  NEXTL(l);
4855
0
  cur = CUR_CHAR(l);
4856
0
  if (cur == 0) {
4857
0
      SHRINK;
4858
0
      GROW;
4859
0
      cur = CUR_CHAR(l);
4860
0
  }
4861
4862
0
        if (len > maxLength) {
4863
0
            xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4864
0
                         "Comment too big found", NULL);
4865
0
            xmlFree (buf);
4866
0
            return;
4867
0
        }
4868
0
    }
4869
0
    buf[len] = 0;
4870
0
    if (cur == 0) {
4871
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4872
0
                       "Comment not terminated \n<!--%.50s\n", buf);
4873
0
    } else if (!IS_CHAR(cur)) {
4874
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4875
0
                          "xmlParseComment: invalid xmlChar value %d\n",
4876
0
                    cur);
4877
0
    } else {
4878
0
  if (inputid != ctxt->input->id) {
4879
0
      xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
4880
0
               "Comment doesn't start and stop in the same"
4881
0
                           " entity\n");
4882
0
  }
4883
0
        NEXT;
4884
0
  if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
4885
0
      (!ctxt->disableSAX))
4886
0
      ctxt->sax->comment(ctxt->userData, buf);
4887
0
    }
4888
0
    xmlFree(buf);
4889
0
    return;
4890
0
not_terminated:
4891
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4892
0
       "Comment not terminated\n", NULL);
4893
0
    xmlFree(buf);
4894
0
    return;
4895
0
}
4896
4897
/**
4898
 * xmlParseComment:
4899
 * @ctxt:  an XML parser context
4900
 *
4901
 * DEPRECATED: Internal function, don't use.
4902
 *
4903
 * Skip an XML (SGML) comment <!-- .... -->
4904
 *  The spec says that "For compatibility, the string "--" (double-hyphen)
4905
 *  must not occur within comments. "
4906
 *
4907
 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
4908
 */
4909
void
4910
4
xmlParseComment(xmlParserCtxtPtr ctxt) {
4911
4
    xmlChar *buf = NULL;
4912
4
    size_t size = XML_PARSER_BUFFER_SIZE;
4913
4
    size_t len = 0;
4914
4
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4915
0
                       XML_MAX_HUGE_LENGTH :
4916
4
                       XML_MAX_TEXT_LENGTH;
4917
4
    xmlParserInputState state;
4918
4
    const xmlChar *in;
4919
4
    size_t nbchar = 0;
4920
4
    int ccol;
4921
4
    int inputid;
4922
4923
    /*
4924
     * Check that there is a comment right here.
4925
     */
4926
4
    if ((RAW != '<') || (NXT(1) != '!') ||
4927
4
        (NXT(2) != '-') || (NXT(3) != '-')) return;
4928
4
    state = ctxt->instate;
4929
4
    ctxt->instate = XML_PARSER_COMMENT;
4930
4
    inputid = ctxt->input->id;
4931
4
    SKIP(4);
4932
4
    SHRINK;
4933
4
    GROW;
4934
4935
    /*
4936
     * Accelerated common case where input don't need to be
4937
     * modified before passing it to the handler.
4938
     */
4939
4
    in = ctxt->input->cur;
4940
4
    do {
4941
4
  if (*in == 0xA) {
4942
0
      do {
4943
0
    ctxt->input->line++; ctxt->input->col = 1;
4944
0
    in++;
4945
0
      } while (*in == 0xA);
4946
0
  }
4947
4
get_more:
4948
4
        ccol = ctxt->input->col;
4949
40
  while (((*in > '-') && (*in <= 0x7F)) ||
4950
40
         ((*in >= 0x20) && (*in < '-')) ||
4951
40
         (*in == 0x09)) {
4952
36
        in++;
4953
36
        ccol++;
4954
36
  }
4955
4
  ctxt->input->col = ccol;
4956
4
  if (*in == 0xA) {
4957
0
      do {
4958
0
    ctxt->input->line++; ctxt->input->col = 1;
4959
0
    in++;
4960
0
      } while (*in == 0xA);
4961
0
      goto get_more;
4962
0
  }
4963
4
  nbchar = in - ctxt->input->cur;
4964
  /*
4965
   * save current set of data
4966
   */
4967
4
  if (nbchar > 0) {
4968
4
      if ((ctxt->sax != NULL) &&
4969
4
    (ctxt->sax->comment != NULL)) {
4970
4
    if (buf == NULL) {
4971
4
        if ((*in == '-') && (in[1] == '-'))
4972
4
            size = nbchar + 1;
4973
0
        else
4974
0
            size = XML_PARSER_BUFFER_SIZE + nbchar;
4975
4
        buf = (xmlChar *) xmlMallocAtomic(size);
4976
4
        if (buf == NULL) {
4977
0
            xmlErrMemory(ctxt, NULL);
4978
0
      ctxt->instate = state;
4979
0
      return;
4980
0
        }
4981
4
        len = 0;
4982
4
    } else if (len + nbchar + 1 >= size) {
4983
0
        xmlChar *new_buf;
4984
0
        size  += len + nbchar + XML_PARSER_BUFFER_SIZE;
4985
0
        new_buf = (xmlChar *) xmlRealloc(buf, size);
4986
0
        if (new_buf == NULL) {
4987
0
            xmlFree (buf);
4988
0
      xmlErrMemory(ctxt, NULL);
4989
0
      ctxt->instate = state;
4990
0
      return;
4991
0
        }
4992
0
        buf = new_buf;
4993
0
    }
4994
4
    memcpy(&buf[len], ctxt->input->cur, nbchar);
4995
4
    len += nbchar;
4996
4
    buf[len] = 0;
4997
4
      }
4998
4
  }
4999
4
        if (len > maxLength) {
5000
0
            xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
5001
0
                         "Comment too big found", NULL);
5002
0
            xmlFree (buf);
5003
0
            return;
5004
0
        }
5005
4
  ctxt->input->cur = in;
5006
4
  if (*in == 0xA) {
5007
0
      in++;
5008
0
      ctxt->input->line++; ctxt->input->col = 1;
5009
0
  }
5010
4
  if (*in == 0xD) {
5011
0
      in++;
5012
0
      if (*in == 0xA) {
5013
0
    ctxt->input->cur = in;
5014
0
    in++;
5015
0
    ctxt->input->line++; ctxt->input->col = 1;
5016
0
    goto get_more;
5017
0
      }
5018
0
      in--;
5019
0
  }
5020
4
  SHRINK;
5021
4
  GROW;
5022
4
        if (ctxt->instate == XML_PARSER_EOF) {
5023
0
            xmlFree(buf);
5024
0
            return;
5025
0
        }
5026
4
  in = ctxt->input->cur;
5027
4
  if (*in == '-') {
5028
4
      if (in[1] == '-') {
5029
4
          if (in[2] == '>') {
5030
4
        if (ctxt->input->id != inputid) {
5031
0
      xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5032
0
                     "comment doesn't start and stop in the"
5033
0
                                       " same entity\n");
5034
0
        }
5035
4
        SKIP(3);
5036
4
        if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
5037
4
            (!ctxt->disableSAX)) {
5038
4
      if (buf != NULL)
5039
4
          ctxt->sax->comment(ctxt->userData, buf);
5040
0
      else
5041
0
          ctxt->sax->comment(ctxt->userData, BAD_CAST "");
5042
4
        }
5043
4
        if (buf != NULL)
5044
4
            xmlFree(buf);
5045
4
        if (ctxt->instate != XML_PARSER_EOF)
5046
4
      ctxt->instate = state;
5047
4
        return;
5048
4
    }
5049
0
    if (buf != NULL) {
5050
0
        xmlFatalErrMsgStr(ctxt, XML_ERR_HYPHEN_IN_COMMENT,
5051
0
                          "Double hyphen within comment: "
5052
0
                                      "<!--%.50s\n",
5053
0
              buf);
5054
0
    } else
5055
0
        xmlFatalErrMsgStr(ctxt, XML_ERR_HYPHEN_IN_COMMENT,
5056
0
                          "Double hyphen within comment\n", NULL);
5057
0
                if (ctxt->instate == XML_PARSER_EOF) {
5058
0
                    xmlFree(buf);
5059
0
                    return;
5060
0
                }
5061
0
    in++;
5062
0
    ctxt->input->col++;
5063
0
      }
5064
0
      in++;
5065
0
      ctxt->input->col++;
5066
0
      goto get_more;
5067
4
  }
5068
4
    } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09) || (*in == 0x0a));
5069
0
    xmlParseCommentComplex(ctxt, buf, len, size);
5070
0
    ctxt->instate = state;
5071
0
    return;
5072
4
}
5073
5074
5075
/**
5076
 * xmlParsePITarget:
5077
 * @ctxt:  an XML parser context
5078
 *
5079
 * DEPRECATED: Internal function, don't use.
5080
 *
5081
 * parse the name of a PI
5082
 *
5083
 * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
5084
 *
5085
 * Returns the PITarget name or NULL
5086
 */
5087
5088
const xmlChar *
5089
4
xmlParsePITarget(xmlParserCtxtPtr ctxt) {
5090
4
    const xmlChar *name;
5091
5092
4
    name = xmlParseName(ctxt);
5093
4
    if ((name != NULL) &&
5094
4
        ((name[0] == 'x') || (name[0] == 'X')) &&
5095
4
        ((name[1] == 'm') || (name[1] == 'M')) &&
5096
4
        ((name[2] == 'l') || (name[2] == 'L'))) {
5097
0
  int i;
5098
0
  if ((name[0] == 'x') && (name[1] == 'm') &&
5099
0
      (name[2] == 'l') && (name[3] == 0)) {
5100
0
      xmlFatalErrMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
5101
0
     "XML declaration allowed only at the start of the document\n");
5102
0
      return(name);
5103
0
  } else if (name[3] == 0) {
5104
0
      xmlFatalErr(ctxt, XML_ERR_RESERVED_XML_NAME, NULL);
5105
0
      return(name);
5106
0
  }
5107
0
  for (i = 0;;i++) {
5108
0
      if (xmlW3CPIs[i] == NULL) break;
5109
0
      if (xmlStrEqual(name, (const xmlChar *)xmlW3CPIs[i]))
5110
0
          return(name);
5111
0
  }
5112
0
  xmlWarningMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
5113
0
          "xmlParsePITarget: invalid name prefix 'xml'\n",
5114
0
          NULL, NULL);
5115
0
    }
5116
4
    if ((name != NULL) && (xmlStrchr(name, ':') != NULL)) {
5117
0
  xmlNsErr(ctxt, XML_NS_ERR_COLON,
5118
0
     "colons are forbidden from PI names '%s'\n", name, NULL, NULL);
5119
0
    }
5120
4
    return(name);
5121
4
}
5122
5123
#ifdef LIBXML_CATALOG_ENABLED
5124
/**
5125
 * xmlParseCatalogPI:
5126
 * @ctxt:  an XML parser context
5127
 * @catalog:  the PI value string
5128
 *
5129
 * parse an XML Catalog Processing Instruction.
5130
 *
5131
 * <?oasis-xml-catalog catalog="http://example.com/catalog.xml"?>
5132
 *
5133
 * Occurs only if allowed by the user and if happening in the Misc
5134
 * part of the document before any doctype information
5135
 * This will add the given catalog to the parsing context in order
5136
 * to be used if there is a resolution need further down in the document
5137
 */
5138
5139
static void
5140
0
xmlParseCatalogPI(xmlParserCtxtPtr ctxt, const xmlChar *catalog) {
5141
0
    xmlChar *URL = NULL;
5142
0
    const xmlChar *tmp, *base;
5143
0
    xmlChar marker;
5144
5145
0
    tmp = catalog;
5146
0
    while (IS_BLANK_CH(*tmp)) tmp++;
5147
0
    if (xmlStrncmp(tmp, BAD_CAST"catalog", 7))
5148
0
  goto error;
5149
0
    tmp += 7;
5150
0
    while (IS_BLANK_CH(*tmp)) tmp++;
5151
0
    if (*tmp != '=') {
5152
0
  return;
5153
0
    }
5154
0
    tmp++;
5155
0
    while (IS_BLANK_CH(*tmp)) tmp++;
5156
0
    marker = *tmp;
5157
0
    if ((marker != '\'') && (marker != '"'))
5158
0
  goto error;
5159
0
    tmp++;
5160
0
    base = tmp;
5161
0
    while ((*tmp != 0) && (*tmp != marker)) tmp++;
5162
0
    if (*tmp == 0)
5163
0
  goto error;
5164
0
    URL = xmlStrndup(base, tmp - base);
5165
0
    tmp++;
5166
0
    while (IS_BLANK_CH(*tmp)) tmp++;
5167
0
    if (*tmp != 0)
5168
0
  goto error;
5169
5170
0
    if (URL != NULL) {
5171
0
  ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
5172
0
  xmlFree(URL);
5173
0
    }
5174
0
    return;
5175
5176
0
error:
5177
0
    xmlWarningMsg(ctxt, XML_WAR_CATALOG_PI,
5178
0
            "Catalog PI syntax error: %s\n",
5179
0
      catalog, NULL);
5180
0
    if (URL != NULL)
5181
0
  xmlFree(URL);
5182
0
}
5183
#endif
5184
5185
/**
5186
 * xmlParsePI:
5187
 * @ctxt:  an XML parser context
5188
 *
5189
 * DEPRECATED: Internal function, don't use.
5190
 *
5191
 * parse an XML Processing Instruction.
5192
 *
5193
 * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
5194
 *
5195
 * The processing is transferred to SAX once parsed.
5196
 */
5197
5198
void
5199
4
xmlParsePI(xmlParserCtxtPtr ctxt) {
5200
4
    xmlChar *buf = NULL;
5201
4
    size_t len = 0;
5202
4
    size_t size = XML_PARSER_BUFFER_SIZE;
5203
4
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
5204
0
                       XML_MAX_HUGE_LENGTH :
5205
4
                       XML_MAX_TEXT_LENGTH;
5206
4
    int cur, l;
5207
4
    const xmlChar *target;
5208
4
    xmlParserInputState state;
5209
4
    int count = 0;
5210
5211
4
    if ((RAW == '<') && (NXT(1) == '?')) {
5212
4
  int inputid = ctxt->input->id;
5213
4
  state = ctxt->instate;
5214
4
        ctxt->instate = XML_PARSER_PI;
5215
  /*
5216
   * this is a Processing Instruction.
5217
   */
5218
4
  SKIP(2);
5219
4
  SHRINK;
5220
5221
  /*
5222
   * Parse the target name and check for special support like
5223
   * namespace.
5224
   */
5225
4
        target = xmlParsePITarget(ctxt);
5226
4
  if (target != NULL) {
5227
4
      if ((RAW == '?') && (NXT(1) == '>')) {
5228
0
    if (inputid != ctxt->input->id) {
5229
0
        xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5230
0
                             "PI declaration doesn't start and stop in"
5231
0
                                   " the same entity\n");
5232
0
    }
5233
0
    SKIP(2);
5234
5235
    /*
5236
     * SAX: PI detected.
5237
     */
5238
0
    if ((ctxt->sax) && (!ctxt->disableSAX) &&
5239
0
        (ctxt->sax->processingInstruction != NULL))
5240
0
        ctxt->sax->processingInstruction(ctxt->userData,
5241
0
                                         target, NULL);
5242
0
    if (ctxt->instate != XML_PARSER_EOF)
5243
0
        ctxt->instate = state;
5244
0
    return;
5245
0
      }
5246
4
      buf = (xmlChar *) xmlMallocAtomic(size);
5247
4
      if (buf == NULL) {
5248
0
    xmlErrMemory(ctxt, NULL);
5249
0
    ctxt->instate = state;
5250
0
    return;
5251
0
      }
5252
4
      if (SKIP_BLANKS == 0) {
5253
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_SPACE_REQUIRED,
5254
0
        "ParsePI: PI %s space expected\n", target);
5255
0
      }
5256
4
      cur = CUR_CHAR(l);
5257
32
      while (IS_CHAR(cur) && /* checked */
5258
32
       ((cur != '?') || (NXT(1) != '>'))) {
5259
28
    if (len + 5 >= size) {
5260
0
        xmlChar *tmp;
5261
0
                    size_t new_size = size * 2;
5262
0
        tmp = (xmlChar *) xmlRealloc(buf, new_size);
5263
0
        if (tmp == NULL) {
5264
0
      xmlErrMemory(ctxt, NULL);
5265
0
      xmlFree(buf);
5266
0
      ctxt->instate = state;
5267
0
      return;
5268
0
        }
5269
0
        buf = tmp;
5270
0
                    size = new_size;
5271
0
    }
5272
28
    count++;
5273
28
    if (count > 50) {
5274
0
        SHRINK;
5275
0
        GROW;
5276
0
                    if (ctxt->instate == XML_PARSER_EOF) {
5277
0
                        xmlFree(buf);
5278
0
                        return;
5279
0
                    }
5280
0
        count = 0;
5281
0
    }
5282
28
    COPY_BUF(l,buf,len,cur);
5283
28
    NEXTL(l);
5284
28
    cur = CUR_CHAR(l);
5285
28
    if (cur == 0) {
5286
0
        SHRINK;
5287
0
        GROW;
5288
0
        cur = CUR_CHAR(l);
5289
0
    }
5290
28
                if (len > maxLength) {
5291
0
                    xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
5292
0
                                      "PI %s too big found", target);
5293
0
                    xmlFree(buf);
5294
0
                    ctxt->instate = state;
5295
0
                    return;
5296
0
                }
5297
28
      }
5298
4
      buf[len] = 0;
5299
4
      if (cur != '?') {
5300
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
5301
0
          "ParsePI: PI %s never end ...\n", target);
5302
4
      } else {
5303
4
    if (inputid != ctxt->input->id) {
5304
0
        xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5305
0
                             "PI declaration doesn't start and stop in"
5306
0
                                   " the same entity\n");
5307
0
    }
5308
4
    SKIP(2);
5309
5310
4
#ifdef LIBXML_CATALOG_ENABLED
5311
4
    if (((state == XML_PARSER_MISC) ||
5312
4
               (state == XML_PARSER_START)) &&
5313
4
        (xmlStrEqual(target, XML_CATALOG_PI))) {
5314
0
        xmlCatalogAllow allow = xmlCatalogGetDefaults();
5315
0
        if ((allow == XML_CATA_ALLOW_DOCUMENT) ||
5316
0
      (allow == XML_CATA_ALLOW_ALL))
5317
0
      xmlParseCatalogPI(ctxt, buf);
5318
0
    }
5319
4
#endif
5320
5321
5322
    /*
5323
     * SAX: PI detected.
5324
     */
5325
4
    if ((ctxt->sax) && (!ctxt->disableSAX) &&
5326
4
        (ctxt->sax->processingInstruction != NULL))
5327
4
        ctxt->sax->processingInstruction(ctxt->userData,
5328
4
                                         target, buf);
5329
4
      }
5330
4
      xmlFree(buf);
5331
4
  } else {
5332
0
      xmlFatalErr(ctxt, XML_ERR_PI_NOT_STARTED, NULL);
5333
0
  }
5334
4
  if (ctxt->instate != XML_PARSER_EOF)
5335
4
      ctxt->instate = state;
5336
4
    }
5337
4
}
5338
5339
/**
5340
 * xmlParseNotationDecl:
5341
 * @ctxt:  an XML parser context
5342
 *
5343
 * DEPRECATED: Internal function, don't use.
5344
 *
5345
 * parse a notation declaration
5346
 *
5347
 * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID |  PublicID) S? '>'
5348
 *
5349
 * Hence there is actually 3 choices:
5350
 *     'PUBLIC' S PubidLiteral
5351
 *     'PUBLIC' S PubidLiteral S SystemLiteral
5352
 * and 'SYSTEM' S SystemLiteral
5353
 *
5354
 * See the NOTE on xmlParseExternalID().
5355
 */
5356
5357
void
5358
0
xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
5359
0
    const xmlChar *name;
5360
0
    xmlChar *Pubid;
5361
0
    xmlChar *Systemid;
5362
5363
0
    if (CMP10(CUR_PTR, '<', '!', 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
5364
0
  int inputid = ctxt->input->id;
5365
0
  SHRINK;
5366
0
  SKIP(10);
5367
0
  if (SKIP_BLANKS == 0) {
5368
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5369
0
         "Space required after '<!NOTATION'\n");
5370
0
      return;
5371
0
  }
5372
5373
0
        name = xmlParseName(ctxt);
5374
0
  if (name == NULL) {
5375
0
      xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
5376
0
      return;
5377
0
  }
5378
0
  if (xmlStrchr(name, ':') != NULL) {
5379
0
      xmlNsErr(ctxt, XML_NS_ERR_COLON,
5380
0
         "colons are forbidden from notation names '%s'\n",
5381
0
         name, NULL, NULL);
5382
0
  }
5383
0
  if (SKIP_BLANKS == 0) {
5384
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5385
0
         "Space required after the NOTATION name'\n");
5386
0
      return;
5387
0
  }
5388
5389
  /*
5390
   * Parse the IDs.
5391
   */
5392
0
  Systemid = xmlParseExternalID(ctxt, &Pubid, 0);
5393
0
  SKIP_BLANKS;
5394
5395
0
  if (RAW == '>') {
5396
0
      if (inputid != ctxt->input->id) {
5397
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5398
0
                         "Notation declaration doesn't start and stop"
5399
0
                               " in the same entity\n");
5400
0
      }
5401
0
      NEXT;
5402
0
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
5403
0
    (ctxt->sax->notationDecl != NULL))
5404
0
    ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
5405
0
  } else {
5406
0
      xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
5407
0
  }
5408
0
  if (Systemid != NULL) xmlFree(Systemid);
5409
0
  if (Pubid != NULL) xmlFree(Pubid);
5410
0
    }
5411
0
}
5412
5413
/**
5414
 * xmlParseEntityDecl:
5415
 * @ctxt:  an XML parser context
5416
 *
5417
 * DEPRECATED: Internal function, don't use.
5418
 *
5419
 * parse <!ENTITY declarations
5420
 *
5421
 * [70] EntityDecl ::= GEDecl | PEDecl
5422
 *
5423
 * [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
5424
 *
5425
 * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
5426
 *
5427
 * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
5428
 *
5429
 * [74] PEDef ::= EntityValue | ExternalID
5430
 *
5431
 * [76] NDataDecl ::= S 'NDATA' S Name
5432
 *
5433
 * [ VC: Notation Declared ]
5434
 * The Name must match the declared name of a notation.
5435
 */
5436
5437
void
5438
0
xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
5439
0
    const xmlChar *name = NULL;
5440
0
    xmlChar *value = NULL;
5441
0
    xmlChar *URI = NULL, *literal = NULL;
5442
0
    const xmlChar *ndata = NULL;
5443
0
    int isParameter = 0;
5444
0
    xmlChar *orig = NULL;
5445
5446
    /* GROW; done in the caller */
5447
0
    if (CMP8(CUR_PTR, '<', '!', 'E', 'N', 'T', 'I', 'T', 'Y')) {
5448
0
  int inputid = ctxt->input->id;
5449
0
  SHRINK;
5450
0
  SKIP(8);
5451
0
  if (SKIP_BLANKS == 0) {
5452
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5453
0
         "Space required after '<!ENTITY'\n");
5454
0
  }
5455
5456
0
  if (RAW == '%') {
5457
0
      NEXT;
5458
0
      if (SKIP_BLANKS == 0) {
5459
0
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5460
0
             "Space required after '%%'\n");
5461
0
      }
5462
0
      isParameter = 1;
5463
0
  }
5464
5465
0
        name = xmlParseName(ctxt);
5466
0
  if (name == NULL) {
5467
0
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
5468
0
                     "xmlParseEntityDecl: no name\n");
5469
0
            return;
5470
0
  }
5471
0
  if (xmlStrchr(name, ':') != NULL) {
5472
0
      xmlNsErr(ctxt, XML_NS_ERR_COLON,
5473
0
         "colons are forbidden from entities names '%s'\n",
5474
0
         name, NULL, NULL);
5475
0
  }
5476
0
  if (SKIP_BLANKS == 0) {
5477
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5478
0
         "Space required after the entity name\n");
5479
0
  }
5480
5481
0
  ctxt->instate = XML_PARSER_ENTITY_DECL;
5482
  /*
5483
   * handle the various case of definitions...
5484
   */
5485
0
  if (isParameter) {
5486
0
      if ((RAW == '"') || (RAW == '\'')) {
5487
0
          value = xmlParseEntityValue(ctxt, &orig);
5488
0
    if (value) {
5489
0
        if ((ctxt->sax != NULL) &&
5490
0
      (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5491
0
      ctxt->sax->entityDecl(ctxt->userData, name,
5492
0
                        XML_INTERNAL_PARAMETER_ENTITY,
5493
0
            NULL, NULL, value);
5494
0
    }
5495
0
      } else {
5496
0
          URI = xmlParseExternalID(ctxt, &literal, 1);
5497
0
    if ((URI == NULL) && (literal == NULL)) {
5498
0
        xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
5499
0
    }
5500
0
    if (URI) {
5501
0
        xmlURIPtr uri;
5502
5503
0
        uri = xmlParseURI((const char *) URI);
5504
0
        if (uri == NULL) {
5505
0
            xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
5506
0
             "Invalid URI: %s\n", URI);
5507
      /*
5508
       * This really ought to be a well formedness error
5509
       * but the XML Core WG decided otherwise c.f. issue
5510
       * E26 of the XML erratas.
5511
       */
5512
0
        } else {
5513
0
      if (uri->fragment != NULL) {
5514
          /*
5515
           * Okay this is foolish to block those but not
5516
           * invalid URIs.
5517
           */
5518
0
          xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
5519
0
      } else {
5520
0
          if ((ctxt->sax != NULL) &&
5521
0
        (!ctxt->disableSAX) &&
5522
0
        (ctxt->sax->entityDecl != NULL))
5523
0
        ctxt->sax->entityDecl(ctxt->userData, name,
5524
0
              XML_EXTERNAL_PARAMETER_ENTITY,
5525
0
              literal, URI, NULL);
5526
0
      }
5527
0
      xmlFreeURI(uri);
5528
0
        }
5529
0
    }
5530
0
      }
5531
0
  } else {
5532
0
      if ((RAW == '"') || (RAW == '\'')) {
5533
0
          value = xmlParseEntityValue(ctxt, &orig);
5534
0
    if ((ctxt->sax != NULL) &&
5535
0
        (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5536
0
        ctxt->sax->entityDecl(ctxt->userData, name,
5537
0
        XML_INTERNAL_GENERAL_ENTITY,
5538
0
        NULL, NULL, value);
5539
    /*
5540
     * For expat compatibility in SAX mode.
5541
     */
5542
0
    if ((ctxt->myDoc == NULL) ||
5543
0
        (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
5544
0
        if (ctxt->myDoc == NULL) {
5545
0
      ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
5546
0
      if (ctxt->myDoc == NULL) {
5547
0
          xmlErrMemory(ctxt, "New Doc failed");
5548
0
          return;
5549
0
      }
5550
0
      ctxt->myDoc->properties = XML_DOC_INTERNAL;
5551
0
        }
5552
0
        if (ctxt->myDoc->intSubset == NULL)
5553
0
      ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
5554
0
              BAD_CAST "fake", NULL, NULL);
5555
5556
0
        xmlSAX2EntityDecl(ctxt, name, XML_INTERNAL_GENERAL_ENTITY,
5557
0
                    NULL, NULL, value);
5558
0
    }
5559
0
      } else {
5560
0
          URI = xmlParseExternalID(ctxt, &literal, 1);
5561
0
    if ((URI == NULL) && (literal == NULL)) {
5562
0
        xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
5563
0
    }
5564
0
    if (URI) {
5565
0
        xmlURIPtr uri;
5566
5567
0
        uri = xmlParseURI((const char *)URI);
5568
0
        if (uri == NULL) {
5569
0
            xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
5570
0
             "Invalid URI: %s\n", URI);
5571
      /*
5572
       * This really ought to be a well formedness error
5573
       * but the XML Core WG decided otherwise c.f. issue
5574
       * E26 of the XML erratas.
5575
       */
5576
0
        } else {
5577
0
      if (uri->fragment != NULL) {
5578
          /*
5579
           * Okay this is foolish to block those but not
5580
           * invalid URIs.
5581
           */
5582
0
          xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
5583
0
      }
5584
0
      xmlFreeURI(uri);
5585
0
        }
5586
0
    }
5587
0
    if ((RAW != '>') && (SKIP_BLANKS == 0)) {
5588
0
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5589
0
           "Space required before 'NDATA'\n");
5590
0
    }
5591
0
    if (CMP5(CUR_PTR, 'N', 'D', 'A', 'T', 'A')) {
5592
0
        SKIP(5);
5593
0
        if (SKIP_BLANKS == 0) {
5594
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5595
0
               "Space required after 'NDATA'\n");
5596
0
        }
5597
0
        ndata = xmlParseName(ctxt);
5598
0
        if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
5599
0
            (ctxt->sax->unparsedEntityDecl != NULL))
5600
0
      ctxt->sax->unparsedEntityDecl(ctxt->userData, name,
5601
0
            literal, URI, ndata);
5602
0
    } else {
5603
0
        if ((ctxt->sax != NULL) &&
5604
0
            (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5605
0
      ctxt->sax->entityDecl(ctxt->userData, name,
5606
0
            XML_EXTERNAL_GENERAL_PARSED_ENTITY,
5607
0
            literal, URI, NULL);
5608
        /*
5609
         * For expat compatibility in SAX mode.
5610
         * assuming the entity replacement was asked for
5611
         */
5612
0
        if ((ctxt->replaceEntities != 0) &&
5613
0
      ((ctxt->myDoc == NULL) ||
5614
0
      (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE)))) {
5615
0
      if (ctxt->myDoc == NULL) {
5616
0
          ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
5617
0
          if (ctxt->myDoc == NULL) {
5618
0
              xmlErrMemory(ctxt, "New Doc failed");
5619
0
        return;
5620
0
          }
5621
0
          ctxt->myDoc->properties = XML_DOC_INTERNAL;
5622
0
      }
5623
5624
0
      if (ctxt->myDoc->intSubset == NULL)
5625
0
          ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
5626
0
            BAD_CAST "fake", NULL, NULL);
5627
0
      xmlSAX2EntityDecl(ctxt, name,
5628
0
                  XML_EXTERNAL_GENERAL_PARSED_ENTITY,
5629
0
                  literal, URI, NULL);
5630
0
        }
5631
0
    }
5632
0
      }
5633
0
  }
5634
0
  if (ctxt->instate == XML_PARSER_EOF)
5635
0
      goto done;
5636
0
  SKIP_BLANKS;
5637
0
  if (RAW != '>') {
5638
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
5639
0
              "xmlParseEntityDecl: entity %s not terminated\n", name);
5640
0
      xmlHaltParser(ctxt);
5641
0
  } else {
5642
0
      if (inputid != ctxt->input->id) {
5643
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5644
0
                         "Entity declaration doesn't start and stop in"
5645
0
                               " the same entity\n");
5646
0
      }
5647
0
      NEXT;
5648
0
  }
5649
0
  if (orig != NULL) {
5650
      /*
5651
       * Ugly mechanism to save the raw entity value.
5652
       */
5653
0
      xmlEntityPtr cur = NULL;
5654
5655
0
      if (isParameter) {
5656
0
          if ((ctxt->sax != NULL) &&
5657
0
        (ctxt->sax->getParameterEntity != NULL))
5658
0
        cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
5659
0
      } else {
5660
0
          if ((ctxt->sax != NULL) &&
5661
0
        (ctxt->sax->getEntity != NULL))
5662
0
        cur = ctxt->sax->getEntity(ctxt->userData, name);
5663
0
    if ((cur == NULL) && (ctxt->userData==ctxt)) {
5664
0
        cur = xmlSAX2GetEntity(ctxt, name);
5665
0
    }
5666
0
      }
5667
0
            if ((cur != NULL) && (cur->orig == NULL)) {
5668
0
    cur->orig = orig;
5669
0
                orig = NULL;
5670
0
      }
5671
0
  }
5672
5673
0
done:
5674
0
  if (value != NULL) xmlFree(value);
5675
0
  if (URI != NULL) xmlFree(URI);
5676
0
  if (literal != NULL) xmlFree(literal);
5677
0
        if (orig != NULL) xmlFree(orig);
5678
0
    }
5679
0
}
5680
5681
/**
5682
 * xmlParseDefaultDecl:
5683
 * @ctxt:  an XML parser context
5684
 * @value:  Receive a possible fixed default value for the attribute
5685
 *
5686
 * DEPRECATED: Internal function, don't use.
5687
 *
5688
 * Parse an attribute default declaration
5689
 *
5690
 * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
5691
 *
5692
 * [ VC: Required Attribute ]
5693
 * if the default declaration is the keyword #REQUIRED, then the
5694
 * attribute must be specified for all elements of the type in the
5695
 * attribute-list declaration.
5696
 *
5697
 * [ VC: Attribute Default Legal ]
5698
 * The declared default value must meet the lexical constraints of
5699
 * the declared attribute type c.f. xmlValidateAttributeDecl()
5700
 *
5701
 * [ VC: Fixed Attribute Default ]
5702
 * if an attribute has a default value declared with the #FIXED
5703
 * keyword, instances of that attribute must match the default value.
5704
 *
5705
 * [ WFC: No < in Attribute Values ]
5706
 * handled in xmlParseAttValue()
5707
 *
5708
 * returns: XML_ATTRIBUTE_NONE, XML_ATTRIBUTE_REQUIRED, XML_ATTRIBUTE_IMPLIED
5709
 *          or XML_ATTRIBUTE_FIXED.
5710
 */
5711
5712
int
5713
0
xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
5714
0
    int val;
5715
0
    xmlChar *ret;
5716
5717
0
    *value = NULL;
5718
0
    if (CMP9(CUR_PTR, '#', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D')) {
5719
0
  SKIP(9);
5720
0
  return(XML_ATTRIBUTE_REQUIRED);
5721
0
    }
5722
0
    if (CMP8(CUR_PTR, '#', 'I', 'M', 'P', 'L', 'I', 'E', 'D')) {
5723
0
  SKIP(8);
5724
0
  return(XML_ATTRIBUTE_IMPLIED);
5725
0
    }
5726
0
    val = XML_ATTRIBUTE_NONE;
5727
0
    if (CMP6(CUR_PTR, '#', 'F', 'I', 'X', 'E', 'D')) {
5728
0
  SKIP(6);
5729
0
  val = XML_ATTRIBUTE_FIXED;
5730
0
  if (SKIP_BLANKS == 0) {
5731
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5732
0
         "Space required after '#FIXED'\n");
5733
0
  }
5734
0
    }
5735
0
    ret = xmlParseAttValue(ctxt);
5736
0
    ctxt->instate = XML_PARSER_DTD;
5737
0
    if (ret == NULL) {
5738
0
  xmlFatalErrMsg(ctxt, (xmlParserErrors)ctxt->errNo,
5739
0
           "Attribute default value declaration error\n");
5740
0
    } else
5741
0
        *value = ret;
5742
0
    return(val);
5743
0
}
5744
5745
/**
5746
 * xmlParseNotationType:
5747
 * @ctxt:  an XML parser context
5748
 *
5749
 * DEPRECATED: Internal function, don't use.
5750
 *
5751
 * parse an Notation attribute type.
5752
 *
5753
 * Note: the leading 'NOTATION' S part has already being parsed...
5754
 *
5755
 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
5756
 *
5757
 * [ VC: Notation Attributes ]
5758
 * Values of this type must match one of the notation names included
5759
 * in the declaration; all notation names in the declaration must be declared.
5760
 *
5761
 * Returns: the notation attribute tree built while parsing
5762
 */
5763
5764
xmlEnumerationPtr
5765
0
xmlParseNotationType(xmlParserCtxtPtr ctxt) {
5766
0
    const xmlChar *name;
5767
0
    xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
5768
5769
0
    if (RAW != '(') {
5770
0
  xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
5771
0
  return(NULL);
5772
0
    }
5773
0
    SHRINK;
5774
0
    do {
5775
0
        NEXT;
5776
0
  SKIP_BLANKS;
5777
0
        name = xmlParseName(ctxt);
5778
0
  if (name == NULL) {
5779
0
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
5780
0
         "Name expected in NOTATION declaration\n");
5781
0
            xmlFreeEnumeration(ret);
5782
0
      return(NULL);
5783
0
  }
5784
0
  tmp = ret;
5785
0
  while (tmp != NULL) {
5786
0
      if (xmlStrEqual(name, tmp->name)) {
5787
0
    xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
5788
0
    "standalone: attribute notation value token %s duplicated\n",
5789
0
         name, NULL);
5790
0
    if (!xmlDictOwns(ctxt->dict, name))
5791
0
        xmlFree((xmlChar *) name);
5792
0
    break;
5793
0
      }
5794
0
      tmp = tmp->next;
5795
0
  }
5796
0
  if (tmp == NULL) {
5797
0
      cur = xmlCreateEnumeration(name);
5798
0
      if (cur == NULL) {
5799
0
                xmlFreeEnumeration(ret);
5800
0
                return(NULL);
5801
0
            }
5802
0
      if (last == NULL) ret = last = cur;
5803
0
      else {
5804
0
    last->next = cur;
5805
0
    last = cur;
5806
0
      }
5807
0
  }
5808
0
  SKIP_BLANKS;
5809
0
    } while (RAW == '|');
5810
0
    if (RAW != ')') {
5811
0
  xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
5812
0
        xmlFreeEnumeration(ret);
5813
0
  return(NULL);
5814
0
    }
5815
0
    NEXT;
5816
0
    return(ret);
5817
0
}
5818
5819
/**
5820
 * xmlParseEnumerationType:
5821
 * @ctxt:  an XML parser context
5822
 *
5823
 * DEPRECATED: Internal function, don't use.
5824
 *
5825
 * parse an Enumeration attribute type.
5826
 *
5827
 * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
5828
 *
5829
 * [ VC: Enumeration ]
5830
 * Values of this type must match one of the Nmtoken tokens in
5831
 * the declaration
5832
 *
5833
 * Returns: the enumeration attribute tree built while parsing
5834
 */
5835
5836
xmlEnumerationPtr
5837
0
xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
5838
0
    xmlChar *name;
5839
0
    xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
5840
5841
0
    if (RAW != '(') {
5842
0
  xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_STARTED, NULL);
5843
0
  return(NULL);
5844
0
    }
5845
0
    SHRINK;
5846
0
    do {
5847
0
        NEXT;
5848
0
  SKIP_BLANKS;
5849
0
        name = xmlParseNmtoken(ctxt);
5850
0
  if (name == NULL) {
5851
0
      xmlFatalErr(ctxt, XML_ERR_NMTOKEN_REQUIRED, NULL);
5852
0
      return(ret);
5853
0
  }
5854
0
  tmp = ret;
5855
0
  while (tmp != NULL) {
5856
0
      if (xmlStrEqual(name, tmp->name)) {
5857
0
    xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
5858
0
    "standalone: attribute enumeration value token %s duplicated\n",
5859
0
         name, NULL);
5860
0
    if (!xmlDictOwns(ctxt->dict, name))
5861
0
        xmlFree(name);
5862
0
    break;
5863
0
      }
5864
0
      tmp = tmp->next;
5865
0
  }
5866
0
  if (tmp == NULL) {
5867
0
      cur = xmlCreateEnumeration(name);
5868
0
      if (!xmlDictOwns(ctxt->dict, name))
5869
0
    xmlFree(name);
5870
0
      if (cur == NULL) {
5871
0
                xmlFreeEnumeration(ret);
5872
0
                return(NULL);
5873
0
            }
5874
0
      if (last == NULL) ret = last = cur;
5875
0
      else {
5876
0
    last->next = cur;
5877
0
    last = cur;
5878
0
      }
5879
0
  }
5880
0
  SKIP_BLANKS;
5881
0
    } while (RAW == '|');
5882
0
    if (RAW != ')') {
5883
0
  xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_FINISHED, NULL);
5884
0
  return(ret);
5885
0
    }
5886
0
    NEXT;
5887
0
    return(ret);
5888
0
}
5889
5890
/**
5891
 * xmlParseEnumeratedType:
5892
 * @ctxt:  an XML parser context
5893
 * @tree:  the enumeration tree built while parsing
5894
 *
5895
 * DEPRECATED: Internal function, don't use.
5896
 *
5897
 * parse an Enumerated attribute type.
5898
 *
5899
 * [57] EnumeratedType ::= NotationType | Enumeration
5900
 *
5901
 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
5902
 *
5903
 *
5904
 * Returns: XML_ATTRIBUTE_ENUMERATION or XML_ATTRIBUTE_NOTATION
5905
 */
5906
5907
int
5908
0
xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
5909
0
    if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
5910
0
  SKIP(8);
5911
0
  if (SKIP_BLANKS == 0) {
5912
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5913
0
         "Space required after 'NOTATION'\n");
5914
0
      return(0);
5915
0
  }
5916
0
  *tree = xmlParseNotationType(ctxt);
5917
0
  if (*tree == NULL) return(0);
5918
0
  return(XML_ATTRIBUTE_NOTATION);
5919
0
    }
5920
0
    *tree = xmlParseEnumerationType(ctxt);
5921
0
    if (*tree == NULL) return(0);
5922
0
    return(XML_ATTRIBUTE_ENUMERATION);
5923
0
}
5924
5925
/**
5926
 * xmlParseAttributeType:
5927
 * @ctxt:  an XML parser context
5928
 * @tree:  the enumeration tree built while parsing
5929
 *
5930
 * DEPRECATED: Internal function, don't use.
5931
 *
5932
 * parse the Attribute list def for an element
5933
 *
5934
 * [54] AttType ::= StringType | TokenizedType | EnumeratedType
5935
 *
5936
 * [55] StringType ::= 'CDATA'
5937
 *
5938
 * [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' |
5939
 *                        'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
5940
 *
5941
 * Validity constraints for attribute values syntax are checked in
5942
 * xmlValidateAttributeValue()
5943
 *
5944
 * [ VC: ID ]
5945
 * Values of type ID must match the Name production. A name must not
5946
 * appear more than once in an XML document as a value of this type;
5947
 * i.e., ID values must uniquely identify the elements which bear them.
5948
 *
5949
 * [ VC: One ID per Element Type ]
5950
 * No element type may have more than one ID attribute specified.
5951
 *
5952
 * [ VC: ID Attribute Default ]
5953
 * An ID attribute must have a declared default of #IMPLIED or #REQUIRED.
5954
 *
5955
 * [ VC: IDREF ]
5956
 * Values of type IDREF must match the Name production, and values
5957
 * of type IDREFS must match Names; each IDREF Name must match the value
5958
 * of an ID attribute on some element in the XML document; i.e. IDREF
5959
 * values must match the value of some ID attribute.
5960
 *
5961
 * [ VC: Entity Name ]
5962
 * Values of type ENTITY must match the Name production, values
5963
 * of type ENTITIES must match Names; each Entity Name must match the
5964
 * name of an unparsed entity declared in the DTD.
5965
 *
5966
 * [ VC: Name Token ]
5967
 * Values of type NMTOKEN must match the Nmtoken production; values
5968
 * of type NMTOKENS must match Nmtokens.
5969
 *
5970
 * Returns the attribute type
5971
 */
5972
int
5973
0
xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
5974
0
    SHRINK;
5975
0
    if (CMP5(CUR_PTR, 'C', 'D', 'A', 'T', 'A')) {
5976
0
  SKIP(5);
5977
0
  return(XML_ATTRIBUTE_CDATA);
5978
0
     } else if (CMP6(CUR_PTR, 'I', 'D', 'R', 'E', 'F', 'S')) {
5979
0
  SKIP(6);
5980
0
  return(XML_ATTRIBUTE_IDREFS);
5981
0
     } else if (CMP5(CUR_PTR, 'I', 'D', 'R', 'E', 'F')) {
5982
0
  SKIP(5);
5983
0
  return(XML_ATTRIBUTE_IDREF);
5984
0
     } else if ((RAW == 'I') && (NXT(1) == 'D')) {
5985
0
        SKIP(2);
5986
0
  return(XML_ATTRIBUTE_ID);
5987
0
     } else if (CMP6(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'Y')) {
5988
0
  SKIP(6);
5989
0
  return(XML_ATTRIBUTE_ENTITY);
5990
0
     } else if (CMP8(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S')) {
5991
0
  SKIP(8);
5992
0
  return(XML_ATTRIBUTE_ENTITIES);
5993
0
     } else if (CMP8(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S')) {
5994
0
  SKIP(8);
5995
0
  return(XML_ATTRIBUTE_NMTOKENS);
5996
0
     } else if (CMP7(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N')) {
5997
0
  SKIP(7);
5998
0
  return(XML_ATTRIBUTE_NMTOKEN);
5999
0
     }
6000
0
     return(xmlParseEnumeratedType(ctxt, tree));
6001
0
}
6002
6003
/**
6004
 * xmlParseAttributeListDecl:
6005
 * @ctxt:  an XML parser context
6006
 *
6007
 * DEPRECATED: Internal function, don't use.
6008
 *
6009
 * : parse the Attribute list def for an element
6010
 *
6011
 * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
6012
 *
6013
 * [53] AttDef ::= S Name S AttType S DefaultDecl
6014
 *
6015
 */
6016
void
6017
0
xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
6018
0
    const xmlChar *elemName;
6019
0
    const xmlChar *attrName;
6020
0
    xmlEnumerationPtr tree;
6021
6022
0
    if (CMP9(CUR_PTR, '<', '!', 'A', 'T', 'T', 'L', 'I', 'S', 'T')) {
6023
0
  int inputid = ctxt->input->id;
6024
6025
0
  SKIP(9);
6026
0
  if (SKIP_BLANKS == 0) {
6027
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6028
0
                     "Space required after '<!ATTLIST'\n");
6029
0
  }
6030
0
        elemName = xmlParseName(ctxt);
6031
0
  if (elemName == NULL) {
6032
0
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6033
0
         "ATTLIST: no name for Element\n");
6034
0
      return;
6035
0
  }
6036
0
  SKIP_BLANKS;
6037
0
  GROW;
6038
0
  while ((RAW != '>') && (ctxt->instate != XML_PARSER_EOF)) {
6039
0
      int type;
6040
0
      int def;
6041
0
      xmlChar *defaultValue = NULL;
6042
6043
0
      GROW;
6044
0
            tree = NULL;
6045
0
      attrName = xmlParseName(ctxt);
6046
0
      if (attrName == NULL) {
6047
0
    xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6048
0
             "ATTLIST: no name for Attribute\n");
6049
0
    break;
6050
0
      }
6051
0
      GROW;
6052
0
      if (SKIP_BLANKS == 0) {
6053
0
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6054
0
            "Space required after the attribute name\n");
6055
0
    break;
6056
0
      }
6057
6058
0
      type = xmlParseAttributeType(ctxt, &tree);
6059
0
      if (type <= 0) {
6060
0
          break;
6061
0
      }
6062
6063
0
      GROW;
6064
0
      if (SKIP_BLANKS == 0) {
6065
0
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6066
0
             "Space required after the attribute type\n");
6067
0
          if (tree != NULL)
6068
0
        xmlFreeEnumeration(tree);
6069
0
    break;
6070
0
      }
6071
6072
0
      def = xmlParseDefaultDecl(ctxt, &defaultValue);
6073
0
      if (def <= 0) {
6074
0
                if (defaultValue != NULL)
6075
0
        xmlFree(defaultValue);
6076
0
          if (tree != NULL)
6077
0
        xmlFreeEnumeration(tree);
6078
0
          break;
6079
0
      }
6080
0
      if ((type != XML_ATTRIBUTE_CDATA) && (defaultValue != NULL))
6081
0
          xmlAttrNormalizeSpace(defaultValue, defaultValue);
6082
6083
0
      GROW;
6084
0
            if (RAW != '>') {
6085
0
    if (SKIP_BLANKS == 0) {
6086
0
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6087
0
      "Space required after the attribute default value\n");
6088
0
        if (defaultValue != NULL)
6089
0
      xmlFree(defaultValue);
6090
0
        if (tree != NULL)
6091
0
      xmlFreeEnumeration(tree);
6092
0
        break;
6093
0
    }
6094
0
      }
6095
0
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
6096
0
    (ctxt->sax->attributeDecl != NULL))
6097
0
    ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
6098
0
                          type, def, defaultValue, tree);
6099
0
      else if (tree != NULL)
6100
0
    xmlFreeEnumeration(tree);
6101
6102
0
      if ((ctxt->sax2) && (defaultValue != NULL) &&
6103
0
          (def != XML_ATTRIBUTE_IMPLIED) &&
6104
0
    (def != XML_ATTRIBUTE_REQUIRED)) {
6105
0
    xmlAddDefAttrs(ctxt, elemName, attrName, defaultValue);
6106
0
      }
6107
0
      if (ctxt->sax2) {
6108
0
    xmlAddSpecialAttr(ctxt, elemName, attrName, type);
6109
0
      }
6110
0
      if (defaultValue != NULL)
6111
0
          xmlFree(defaultValue);
6112
0
      GROW;
6113
0
  }
6114
0
  if (RAW == '>') {
6115
0
      if (inputid != ctxt->input->id) {
6116
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6117
0
                               "Attribute list declaration doesn't start and"
6118
0
                               " stop in the same entity\n");
6119
0
      }
6120
0
      NEXT;
6121
0
  }
6122
0
    }
6123
0
}
6124
6125
/**
6126
 * xmlParseElementMixedContentDecl:
6127
 * @ctxt:  an XML parser context
6128
 * @inputchk:  the input used for the current entity, needed for boundary checks
6129
 *
6130
 * DEPRECATED: Internal function, don't use.
6131
 *
6132
 * parse the declaration for a Mixed Element content
6133
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6134
 *
6135
 * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' |
6136
 *                '(' S? '#PCDATA' S? ')'
6137
 *
6138
 * [ VC: Proper Group/PE Nesting ] applies to [51] too (see [49])
6139
 *
6140
 * [ VC: No Duplicate Types ]
6141
 * The same name must not appear more than once in a single
6142
 * mixed-content declaration.
6143
 *
6144
 * returns: the list of the xmlElementContentPtr describing the element choices
6145
 */
6146
xmlElementContentPtr
6147
0
xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
6148
0
    xmlElementContentPtr ret = NULL, cur = NULL, n;
6149
0
    const xmlChar *elem = NULL;
6150
6151
0
    GROW;
6152
0
    if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
6153
0
  SKIP(7);
6154
0
  SKIP_BLANKS;
6155
0
  SHRINK;
6156
0
  if (RAW == ')') {
6157
0
      if (ctxt->input->id != inputchk) {
6158
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6159
0
                               "Element content declaration doesn't start and"
6160
0
                               " stop in the same entity\n");
6161
0
      }
6162
0
      NEXT;
6163
0
      ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
6164
0
      if (ret == NULL)
6165
0
          return(NULL);
6166
0
      if (RAW == '*') {
6167
0
    ret->ocur = XML_ELEMENT_CONTENT_MULT;
6168
0
    NEXT;
6169
0
      }
6170
0
      return(ret);
6171
0
  }
6172
0
  if ((RAW == '(') || (RAW == '|')) {
6173
0
      ret = cur = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
6174
0
      if (ret == NULL) return(NULL);
6175
0
  }
6176
0
  while ((RAW == '|') && (ctxt->instate != XML_PARSER_EOF)) {
6177
0
      NEXT;
6178
0
      if (elem == NULL) {
6179
0
          ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6180
0
    if (ret == NULL) {
6181
0
        xmlFreeDocElementContent(ctxt->myDoc, cur);
6182
0
                    return(NULL);
6183
0
                }
6184
0
    ret->c1 = cur;
6185
0
    if (cur != NULL)
6186
0
        cur->parent = ret;
6187
0
    cur = ret;
6188
0
      } else {
6189
0
          n = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6190
0
    if (n == NULL) {
6191
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6192
0
                    return(NULL);
6193
0
                }
6194
0
    n->c1 = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6195
0
    if (n->c1 != NULL)
6196
0
        n->c1->parent = n;
6197
0
          cur->c2 = n;
6198
0
    if (n != NULL)
6199
0
        n->parent = cur;
6200
0
    cur = n;
6201
0
      }
6202
0
      SKIP_BLANKS;
6203
0
      elem = xmlParseName(ctxt);
6204
0
      if (elem == NULL) {
6205
0
    xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6206
0
      "xmlParseElementMixedContentDecl : Name expected\n");
6207
0
    xmlFreeDocElementContent(ctxt->myDoc, ret);
6208
0
    return(NULL);
6209
0
      }
6210
0
      SKIP_BLANKS;
6211
0
      GROW;
6212
0
  }
6213
0
  if ((RAW == ')') && (NXT(1) == '*')) {
6214
0
      if (elem != NULL) {
6215
0
    cur->c2 = xmlNewDocElementContent(ctxt->myDoc, elem,
6216
0
                                   XML_ELEMENT_CONTENT_ELEMENT);
6217
0
    if (cur->c2 != NULL)
6218
0
        cur->c2->parent = cur;
6219
0
            }
6220
0
            if (ret != NULL)
6221
0
                ret->ocur = XML_ELEMENT_CONTENT_MULT;
6222
0
      if (ctxt->input->id != inputchk) {
6223
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6224
0
                               "Element content declaration doesn't start and"
6225
0
                               " stop in the same entity\n");
6226
0
      }
6227
0
      SKIP(2);
6228
0
  } else {
6229
0
      xmlFreeDocElementContent(ctxt->myDoc, ret);
6230
0
      xmlFatalErr(ctxt, XML_ERR_MIXED_NOT_STARTED, NULL);
6231
0
      return(NULL);
6232
0
  }
6233
6234
0
    } else {
6235
0
  xmlFatalErr(ctxt, XML_ERR_PCDATA_REQUIRED, NULL);
6236
0
    }
6237
0
    return(ret);
6238
0
}
6239
6240
/**
6241
 * xmlParseElementChildrenContentDeclPriv:
6242
 * @ctxt:  an XML parser context
6243
 * @inputchk:  the input used for the current entity, needed for boundary checks
6244
 * @depth: the level of recursion
6245
 *
6246
 * parse the declaration for a Mixed Element content
6247
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6248
 *
6249
 *
6250
 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
6251
 *
6252
 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
6253
 *
6254
 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
6255
 *
6256
 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
6257
 *
6258
 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
6259
 * TODO Parameter-entity replacement text must be properly nested
6260
 *  with parenthesized groups. That is to say, if either of the
6261
 *  opening or closing parentheses in a choice, seq, or Mixed
6262
 *  construct is contained in the replacement text for a parameter
6263
 *  entity, both must be contained in the same replacement text. For
6264
 *  interoperability, if a parameter-entity reference appears in a
6265
 *  choice, seq, or Mixed construct, its replacement text should not
6266
 *  be empty, and neither the first nor last non-blank character of
6267
 *  the replacement text should be a connector (| or ,).
6268
 *
6269
 * Returns the tree of xmlElementContentPtr describing the element
6270
 *          hierarchy.
6271
 */
6272
static xmlElementContentPtr
6273
xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
6274
0
                                       int depth) {
6275
0
    xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
6276
0
    const xmlChar *elem;
6277
0
    xmlChar type = 0;
6278
6279
0
    if (((depth > 128) && ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
6280
0
        (depth >  2048)) {
6281
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED,
6282
0
"xmlParseElementChildrenContentDecl : depth %d too deep, use XML_PARSE_HUGE\n",
6283
0
                          depth);
6284
0
  return(NULL);
6285
0
    }
6286
0
    SKIP_BLANKS;
6287
0
    GROW;
6288
0
    if (RAW == '(') {
6289
0
  int inputid = ctxt->input->id;
6290
6291
        /* Recurse on first child */
6292
0
  NEXT;
6293
0
  SKIP_BLANKS;
6294
0
        cur = ret = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
6295
0
                                                           depth + 1);
6296
0
        if (cur == NULL)
6297
0
            return(NULL);
6298
0
  SKIP_BLANKS;
6299
0
  GROW;
6300
0
    } else {
6301
0
  elem = xmlParseName(ctxt);
6302
0
  if (elem == NULL) {
6303
0
      xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
6304
0
      return(NULL);
6305
0
  }
6306
0
        cur = ret = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6307
0
  if (cur == NULL) {
6308
0
      xmlErrMemory(ctxt, NULL);
6309
0
      return(NULL);
6310
0
  }
6311
0
  GROW;
6312
0
  if (RAW == '?') {
6313
0
      cur->ocur = XML_ELEMENT_CONTENT_OPT;
6314
0
      NEXT;
6315
0
  } else if (RAW == '*') {
6316
0
      cur->ocur = XML_ELEMENT_CONTENT_MULT;
6317
0
      NEXT;
6318
0
  } else if (RAW == '+') {
6319
0
      cur->ocur = XML_ELEMENT_CONTENT_PLUS;
6320
0
      NEXT;
6321
0
  } else {
6322
0
      cur->ocur = XML_ELEMENT_CONTENT_ONCE;
6323
0
  }
6324
0
  GROW;
6325
0
    }
6326
0
    SKIP_BLANKS;
6327
0
    SHRINK;
6328
0
    while ((RAW != ')') && (ctxt->instate != XML_PARSER_EOF)) {
6329
        /*
6330
   * Each loop we parse one separator and one element.
6331
   */
6332
0
        if (RAW == ',') {
6333
0
      if (type == 0) type = CUR;
6334
6335
      /*
6336
       * Detect "Name | Name , Name" error
6337
       */
6338
0
      else if (type != CUR) {
6339
0
    xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
6340
0
        "xmlParseElementChildrenContentDecl : '%c' expected\n",
6341
0
                      type);
6342
0
    if ((last != NULL) && (last != ret))
6343
0
        xmlFreeDocElementContent(ctxt->myDoc, last);
6344
0
    if (ret != NULL)
6345
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6346
0
    return(NULL);
6347
0
      }
6348
0
      NEXT;
6349
6350
0
      op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_SEQ);
6351
0
      if (op == NULL) {
6352
0
    if ((last != NULL) && (last != ret))
6353
0
        xmlFreeDocElementContent(ctxt->myDoc, last);
6354
0
          xmlFreeDocElementContent(ctxt->myDoc, ret);
6355
0
    return(NULL);
6356
0
      }
6357
0
      if (last == NULL) {
6358
0
    op->c1 = ret;
6359
0
    if (ret != NULL)
6360
0
        ret->parent = op;
6361
0
    ret = cur = op;
6362
0
      } else {
6363
0
          cur->c2 = op;
6364
0
    if (op != NULL)
6365
0
        op->parent = cur;
6366
0
    op->c1 = last;
6367
0
    if (last != NULL)
6368
0
        last->parent = op;
6369
0
    cur =op;
6370
0
    last = NULL;
6371
0
      }
6372
0
  } else if (RAW == '|') {
6373
0
      if (type == 0) type = CUR;
6374
6375
      /*
6376
       * Detect "Name , Name | Name" error
6377
       */
6378
0
      else if (type != CUR) {
6379
0
    xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
6380
0
        "xmlParseElementChildrenContentDecl : '%c' expected\n",
6381
0
          type);
6382
0
    if ((last != NULL) && (last != ret))
6383
0
        xmlFreeDocElementContent(ctxt->myDoc, last);
6384
0
    if (ret != NULL)
6385
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6386
0
    return(NULL);
6387
0
      }
6388
0
      NEXT;
6389
6390
0
      op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6391
0
      if (op == NULL) {
6392
0
    if ((last != NULL) && (last != ret))
6393
0
        xmlFreeDocElementContent(ctxt->myDoc, last);
6394
0
    if (ret != NULL)
6395
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6396
0
    return(NULL);
6397
0
      }
6398
0
      if (last == NULL) {
6399
0
    op->c1 = ret;
6400
0
    if (ret != NULL)
6401
0
        ret->parent = op;
6402
0
    ret = cur = op;
6403
0
      } else {
6404
0
          cur->c2 = op;
6405
0
    if (op != NULL)
6406
0
        op->parent = cur;
6407
0
    op->c1 = last;
6408
0
    if (last != NULL)
6409
0
        last->parent = op;
6410
0
    cur =op;
6411
0
    last = NULL;
6412
0
      }
6413
0
  } else {
6414
0
      xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED, NULL);
6415
0
      if ((last != NULL) && (last != ret))
6416
0
          xmlFreeDocElementContent(ctxt->myDoc, last);
6417
0
      if (ret != NULL)
6418
0
    xmlFreeDocElementContent(ctxt->myDoc, ret);
6419
0
      return(NULL);
6420
0
  }
6421
0
  GROW;
6422
0
  SKIP_BLANKS;
6423
0
  GROW;
6424
0
  if (RAW == '(') {
6425
0
      int inputid = ctxt->input->id;
6426
      /* Recurse on second child */
6427
0
      NEXT;
6428
0
      SKIP_BLANKS;
6429
0
      last = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
6430
0
                                                          depth + 1);
6431
0
            if (last == NULL) {
6432
0
    if (ret != NULL)
6433
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6434
0
    return(NULL);
6435
0
            }
6436
0
      SKIP_BLANKS;
6437
0
  } else {
6438
0
      elem = xmlParseName(ctxt);
6439
0
      if (elem == NULL) {
6440
0
    xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
6441
0
    if (ret != NULL)
6442
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6443
0
    return(NULL);
6444
0
      }
6445
0
      last = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6446
0
      if (last == NULL) {
6447
0
    if (ret != NULL)
6448
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6449
0
    return(NULL);
6450
0
      }
6451
0
      if (RAW == '?') {
6452
0
    last->ocur = XML_ELEMENT_CONTENT_OPT;
6453
0
    NEXT;
6454
0
      } else if (RAW == '*') {
6455
0
    last->ocur = XML_ELEMENT_CONTENT_MULT;
6456
0
    NEXT;
6457
0
      } else if (RAW == '+') {
6458
0
    last->ocur = XML_ELEMENT_CONTENT_PLUS;
6459
0
    NEXT;
6460
0
      } else {
6461
0
    last->ocur = XML_ELEMENT_CONTENT_ONCE;
6462
0
      }
6463
0
  }
6464
0
  SKIP_BLANKS;
6465
0
  GROW;
6466
0
    }
6467
0
    if ((cur != NULL) && (last != NULL)) {
6468
0
        cur->c2 = last;
6469
0
  if (last != NULL)
6470
0
      last->parent = cur;
6471
0
    }
6472
0
    if (ctxt->input->id != inputchk) {
6473
0
  xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6474
0
                       "Element content declaration doesn't start and stop in"
6475
0
                       " the same entity\n");
6476
0
    }
6477
0
    NEXT;
6478
0
    if (RAW == '?') {
6479
0
  if (ret != NULL) {
6480
0
      if ((ret->ocur == XML_ELEMENT_CONTENT_PLUS) ||
6481
0
          (ret->ocur == XML_ELEMENT_CONTENT_MULT))
6482
0
          ret->ocur = XML_ELEMENT_CONTENT_MULT;
6483
0
      else
6484
0
          ret->ocur = XML_ELEMENT_CONTENT_OPT;
6485
0
  }
6486
0
  NEXT;
6487
0
    } else if (RAW == '*') {
6488
0
  if (ret != NULL) {
6489
0
      ret->ocur = XML_ELEMENT_CONTENT_MULT;
6490
0
      cur = ret;
6491
      /*
6492
       * Some normalization:
6493
       * (a | b* | c?)* == (a | b | c)*
6494
       */
6495
0
      while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
6496
0
    if ((cur->c1 != NULL) &&
6497
0
              ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
6498
0
         (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT)))
6499
0
        cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
6500
0
    if ((cur->c2 != NULL) &&
6501
0
              ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
6502
0
         (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT)))
6503
0
        cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
6504
0
    cur = cur->c2;
6505
0
      }
6506
0
  }
6507
0
  NEXT;
6508
0
    } else if (RAW == '+') {
6509
0
  if (ret != NULL) {
6510
0
      int found = 0;
6511
6512
0
      if ((ret->ocur == XML_ELEMENT_CONTENT_OPT) ||
6513
0
          (ret->ocur == XML_ELEMENT_CONTENT_MULT))
6514
0
          ret->ocur = XML_ELEMENT_CONTENT_MULT;
6515
0
      else
6516
0
          ret->ocur = XML_ELEMENT_CONTENT_PLUS;
6517
      /*
6518
       * Some normalization:
6519
       * (a | b*)+ == (a | b)*
6520
       * (a | b?)+ == (a | b)*
6521
       */
6522
0
      while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
6523
0
    if ((cur->c1 != NULL) &&
6524
0
              ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
6525
0
         (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT))) {
6526
0
        cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
6527
0
        found = 1;
6528
0
    }
6529
0
    if ((cur->c2 != NULL) &&
6530
0
              ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
6531
0
         (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT))) {
6532
0
        cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
6533
0
        found = 1;
6534
0
    }
6535
0
    cur = cur->c2;
6536
0
      }
6537
0
      if (found)
6538
0
    ret->ocur = XML_ELEMENT_CONTENT_MULT;
6539
0
  }
6540
0
  NEXT;
6541
0
    }
6542
0
    return(ret);
6543
0
}
6544
6545
/**
6546
 * xmlParseElementChildrenContentDecl:
6547
 * @ctxt:  an XML parser context
6548
 * @inputchk:  the input used for the current entity, needed for boundary checks
6549
 *
6550
 * DEPRECATED: Internal function, don't use.
6551
 *
6552
 * parse the declaration for a Mixed Element content
6553
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6554
 *
6555
 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
6556
 *
6557
 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
6558
 *
6559
 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
6560
 *
6561
 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
6562
 *
6563
 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
6564
 * TODO Parameter-entity replacement text must be properly nested
6565
 *  with parenthesized groups. That is to say, if either of the
6566
 *  opening or closing parentheses in a choice, seq, or Mixed
6567
 *  construct is contained in the replacement text for a parameter
6568
 *  entity, both must be contained in the same replacement text. For
6569
 *  interoperability, if a parameter-entity reference appears in a
6570
 *  choice, seq, or Mixed construct, its replacement text should not
6571
 *  be empty, and neither the first nor last non-blank character of
6572
 *  the replacement text should be a connector (| or ,).
6573
 *
6574
 * Returns the tree of xmlElementContentPtr describing the element
6575
 *          hierarchy.
6576
 */
6577
xmlElementContentPtr
6578
0
xmlParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
6579
    /* stub left for API/ABI compat */
6580
0
    return(xmlParseElementChildrenContentDeclPriv(ctxt, inputchk, 1));
6581
0
}
6582
6583
/**
6584
 * xmlParseElementContentDecl:
6585
 * @ctxt:  an XML parser context
6586
 * @name:  the name of the element being defined.
6587
 * @result:  the Element Content pointer will be stored here if any
6588
 *
6589
 * DEPRECATED: Internal function, don't use.
6590
 *
6591
 * parse the declaration for an Element content either Mixed or Children,
6592
 * the cases EMPTY and ANY are handled directly in xmlParseElementDecl
6593
 *
6594
 * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
6595
 *
6596
 * returns: the type of element content XML_ELEMENT_TYPE_xxx
6597
 */
6598
6599
int
6600
xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, const xmlChar *name,
6601
0
                           xmlElementContentPtr *result) {
6602
6603
0
    xmlElementContentPtr tree = NULL;
6604
0
    int inputid = ctxt->input->id;
6605
0
    int res;
6606
6607
0
    *result = NULL;
6608
6609
0
    if (RAW != '(') {
6610
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
6611
0
    "xmlParseElementContentDecl : %s '(' expected\n", name);
6612
0
  return(-1);
6613
0
    }
6614
0
    NEXT;
6615
0
    GROW;
6616
0
    if (ctxt->instate == XML_PARSER_EOF)
6617
0
        return(-1);
6618
0
    SKIP_BLANKS;
6619
0
    if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
6620
0
        tree = xmlParseElementMixedContentDecl(ctxt, inputid);
6621
0
  res = XML_ELEMENT_TYPE_MIXED;
6622
0
    } else {
6623
0
        tree = xmlParseElementChildrenContentDeclPriv(ctxt, inputid, 1);
6624
0
  res = XML_ELEMENT_TYPE_ELEMENT;
6625
0
    }
6626
0
    SKIP_BLANKS;
6627
0
    *result = tree;
6628
0
    return(res);
6629
0
}
6630
6631
/**
6632
 * xmlParseElementDecl:
6633
 * @ctxt:  an XML parser context
6634
 *
6635
 * DEPRECATED: Internal function, don't use.
6636
 *
6637
 * parse an Element declaration.
6638
 *
6639
 * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
6640
 *
6641
 * [ VC: Unique Element Type Declaration ]
6642
 * No element type may be declared more than once
6643
 *
6644
 * Returns the type of the element, or -1 in case of error
6645
 */
6646
int
6647
0
xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
6648
0
    const xmlChar *name;
6649
0
    int ret = -1;
6650
0
    xmlElementContentPtr content  = NULL;
6651
6652
    /* GROW; done in the caller */
6653
0
    if (CMP9(CUR_PTR, '<', '!', 'E', 'L', 'E', 'M', 'E', 'N', 'T')) {
6654
0
  int inputid = ctxt->input->id;
6655
6656
0
  SKIP(9);
6657
0
  if (SKIP_BLANKS == 0) {
6658
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6659
0
               "Space required after 'ELEMENT'\n");
6660
0
      return(-1);
6661
0
  }
6662
0
        name = xmlParseName(ctxt);
6663
0
  if (name == NULL) {
6664
0
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6665
0
         "xmlParseElementDecl: no name for Element\n");
6666
0
      return(-1);
6667
0
  }
6668
0
  if (SKIP_BLANKS == 0) {
6669
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6670
0
         "Space required after the element name\n");
6671
0
  }
6672
0
  if (CMP5(CUR_PTR, 'E', 'M', 'P', 'T', 'Y')) {
6673
0
      SKIP(5);
6674
      /*
6675
       * Element must always be empty.
6676
       */
6677
0
      ret = XML_ELEMENT_TYPE_EMPTY;
6678
0
  } else if ((RAW == 'A') && (NXT(1) == 'N') &&
6679
0
             (NXT(2) == 'Y')) {
6680
0
      SKIP(3);
6681
      /*
6682
       * Element is a generic container.
6683
       */
6684
0
      ret = XML_ELEMENT_TYPE_ANY;
6685
0
  } else if (RAW == '(') {
6686
0
      ret = xmlParseElementContentDecl(ctxt, name, &content);
6687
0
  } else {
6688
      /*
6689
       * [ WFC: PEs in Internal Subset ] error handling.
6690
       */
6691
0
      if ((RAW == '%') && (ctxt->external == 0) &&
6692
0
          (ctxt->inputNr == 1)) {
6693
0
    xmlFatalErrMsg(ctxt, XML_ERR_PEREF_IN_INT_SUBSET,
6694
0
    "PEReference: forbidden within markup decl in internal subset\n");
6695
0
      } else {
6696
0
    xmlFatalErrMsg(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
6697
0
          "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
6698
0
            }
6699
0
      return(-1);
6700
0
  }
6701
6702
0
  SKIP_BLANKS;
6703
6704
0
  if (RAW != '>') {
6705
0
      xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
6706
0
      if (content != NULL) {
6707
0
    xmlFreeDocElementContent(ctxt->myDoc, content);
6708
0
      }
6709
0
  } else {
6710
0
      if (inputid != ctxt->input->id) {
6711
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6712
0
                               "Element declaration doesn't start and stop in"
6713
0
                               " the same entity\n");
6714
0
      }
6715
6716
0
      NEXT;
6717
0
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
6718
0
    (ctxt->sax->elementDecl != NULL)) {
6719
0
    if (content != NULL)
6720
0
        content->parent = NULL;
6721
0
          ctxt->sax->elementDecl(ctxt->userData, name, ret,
6722
0
                           content);
6723
0
    if ((content != NULL) && (content->parent == NULL)) {
6724
        /*
6725
         * this is a trick: if xmlAddElementDecl is called,
6726
         * instead of copying the full tree it is plugged directly
6727
         * if called from the parser. Avoid duplicating the
6728
         * interfaces or change the API/ABI
6729
         */
6730
0
        xmlFreeDocElementContent(ctxt->myDoc, content);
6731
0
    }
6732
0
      } else if (content != NULL) {
6733
0
    xmlFreeDocElementContent(ctxt->myDoc, content);
6734
0
      }
6735
0
  }
6736
0
    }
6737
0
    return(ret);
6738
0
}
6739
6740
/**
6741
 * xmlParseConditionalSections
6742
 * @ctxt:  an XML parser context
6743
 *
6744
 * [61] conditionalSect ::= includeSect | ignoreSect
6745
 * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
6746
 * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
6747
 * [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
6748
 * [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
6749
 */
6750
6751
static void
6752
0
xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
6753
0
    int *inputIds = NULL;
6754
0
    size_t inputIdsSize = 0;
6755
0
    size_t depth = 0;
6756
6757
0
    while (ctxt->instate != XML_PARSER_EOF) {
6758
0
        if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
6759
0
            int id = ctxt->input->id;
6760
6761
0
            SKIP(3);
6762
0
            SKIP_BLANKS;
6763
6764
0
            if (CMP7(CUR_PTR, 'I', 'N', 'C', 'L', 'U', 'D', 'E')) {
6765
0
                SKIP(7);
6766
0
                SKIP_BLANKS;
6767
0
                if (RAW != '[') {
6768
0
                    xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
6769
0
                    xmlHaltParser(ctxt);
6770
0
                    goto error;
6771
0
                }
6772
0
                if (ctxt->input->id != id) {
6773
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6774
0
                                   "All markup of the conditional section is"
6775
0
                                   " not in the same entity\n");
6776
0
                }
6777
0
                NEXT;
6778
6779
0
                if (inputIdsSize <= depth) {
6780
0
                    int *tmp;
6781
6782
0
                    inputIdsSize = (inputIdsSize == 0 ? 4 : inputIdsSize * 2);
6783
0
                    tmp = (int *) xmlRealloc(inputIds,
6784
0
                            inputIdsSize * sizeof(int));
6785
0
                    if (tmp == NULL) {
6786
0
                        xmlErrMemory(ctxt, NULL);
6787
0
                        goto error;
6788
0
                    }
6789
0
                    inputIds = tmp;
6790
0
                }
6791
0
                inputIds[depth] = id;
6792
0
                depth++;
6793
0
            } else if (CMP6(CUR_PTR, 'I', 'G', 'N', 'O', 'R', 'E')) {
6794
0
                int state;
6795
0
                xmlParserInputState instate;
6796
0
                size_t ignoreDepth = 0;
6797
6798
0
                SKIP(6);
6799
0
                SKIP_BLANKS;
6800
0
                if (RAW != '[') {
6801
0
                    xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
6802
0
                    xmlHaltParser(ctxt);
6803
0
                    goto error;
6804
0
                }
6805
0
                if (ctxt->input->id != id) {
6806
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6807
0
                                   "All markup of the conditional section is"
6808
0
                                   " not in the same entity\n");
6809
0
                }
6810
0
                NEXT;
6811
6812
                /*
6813
                 * Parse up to the end of the conditional section but disable
6814
                 * SAX event generating DTD building in the meantime
6815
                 */
6816
0
                state = ctxt->disableSAX;
6817
0
                instate = ctxt->instate;
6818
0
                if (ctxt->recovery == 0) ctxt->disableSAX = 1;
6819
0
                ctxt->instate = XML_PARSER_IGNORE;
6820
6821
0
                while (RAW != 0) {
6822
0
                    if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
6823
0
                        SKIP(3);
6824
0
                        ignoreDepth++;
6825
                        /* Check for integer overflow */
6826
0
                        if (ignoreDepth == 0) {
6827
0
                            xmlErrMemory(ctxt, NULL);
6828
0
                            goto error;
6829
0
                        }
6830
0
                    } else if ((RAW == ']') && (NXT(1) == ']') &&
6831
0
                               (NXT(2) == '>')) {
6832
0
                        if (ignoreDepth == 0)
6833
0
                            break;
6834
0
                        SKIP(3);
6835
0
                        ignoreDepth--;
6836
0
                    } else {
6837
0
                        NEXT;
6838
0
                    }
6839
0
                }
6840
6841
0
                ctxt->disableSAX = state;
6842
0
                ctxt->instate = instate;
6843
6844
0
    if (RAW == 0) {
6845
0
        xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
6846
0
                    goto error;
6847
0
    }
6848
0
                if (ctxt->input->id != id) {
6849
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6850
0
                                   "All markup of the conditional section is"
6851
0
                                   " not in the same entity\n");
6852
0
                }
6853
0
                SKIP(3);
6854
0
            } else {
6855
0
                xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
6856
0
                xmlHaltParser(ctxt);
6857
0
                goto error;
6858
0
            }
6859
0
        } else if ((depth > 0) &&
6860
0
                   (RAW == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
6861
0
            depth--;
6862
0
            if (ctxt->input->id != inputIds[depth]) {
6863
0
                xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6864
0
                               "All markup of the conditional section is not"
6865
0
                               " in the same entity\n");
6866
0
            }
6867
0
            SKIP(3);
6868
0
        } else {
6869
0
            int id = ctxt->input->id;
6870
0
            unsigned long cons = CUR_CONSUMED;
6871
6872
0
            xmlParseMarkupDecl(ctxt);
6873
6874
0
            if ((id == ctxt->input->id) && (cons == CUR_CONSUMED)) {
6875
0
                xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
6876
0
                xmlHaltParser(ctxt);
6877
0
                goto error;
6878
0
            }
6879
0
        }
6880
6881
0
        if (depth == 0)
6882
0
            break;
6883
6884
0
        SKIP_BLANKS;
6885
0
        GROW;
6886
0
    }
6887
6888
0
error:
6889
0
    xmlFree(inputIds);
6890
0
}
6891
6892
/**
6893
 * xmlParseMarkupDecl:
6894
 * @ctxt:  an XML parser context
6895
 *
6896
 * DEPRECATED: Internal function, don't use.
6897
 *
6898
 * parse Markup declarations
6899
 *
6900
 * [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
6901
 *                     NotationDecl | PI | Comment
6902
 *
6903
 * [ VC: Proper Declaration/PE Nesting ]
6904
 * Parameter-entity replacement text must be properly nested with
6905
 * markup declarations. That is to say, if either the first character
6906
 * or the last character of a markup declaration (markupdecl above) is
6907
 * contained in the replacement text for a parameter-entity reference,
6908
 * both must be contained in the same replacement text.
6909
 *
6910
 * [ WFC: PEs in Internal Subset ]
6911
 * In the internal DTD subset, parameter-entity references can occur
6912
 * only where markup declarations can occur, not within markup declarations.
6913
 * (This does not apply to references that occur in external parameter
6914
 * entities or to the external subset.)
6915
 */
6916
void
6917
0
xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
6918
0
    GROW;
6919
0
    if (CUR == '<') {
6920
0
        if (NXT(1) == '!') {
6921
0
      switch (NXT(2)) {
6922
0
          case 'E':
6923
0
        if (NXT(3) == 'L')
6924
0
      xmlParseElementDecl(ctxt);
6925
0
        else if (NXT(3) == 'N')
6926
0
      xmlParseEntityDecl(ctxt);
6927
0
        break;
6928
0
          case 'A':
6929
0
        xmlParseAttributeListDecl(ctxt);
6930
0
        break;
6931
0
          case 'N':
6932
0
        xmlParseNotationDecl(ctxt);
6933
0
        break;
6934
0
          case '-':
6935
0
        xmlParseComment(ctxt);
6936
0
        break;
6937
0
    default:
6938
        /* there is an error but it will be detected later */
6939
0
        break;
6940
0
      }
6941
0
  } else if (NXT(1) == '?') {
6942
0
      xmlParsePI(ctxt);
6943
0
  }
6944
0
    }
6945
6946
    /*
6947
     * detect requirement to exit there and act accordingly
6948
     * and avoid having instate overridden later on
6949
     */
6950
0
    if (ctxt->instate == XML_PARSER_EOF)
6951
0
        return;
6952
6953
0
    ctxt->instate = XML_PARSER_DTD;
6954
0
}
6955
6956
/**
6957
 * xmlParseTextDecl:
6958
 * @ctxt:  an XML parser context
6959
 *
6960
 * DEPRECATED: Internal function, don't use.
6961
 *
6962
 * parse an XML declaration header for external entities
6963
 *
6964
 * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
6965
 */
6966
6967
void
6968
0
xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
6969
0
    xmlChar *version;
6970
0
    const xmlChar *encoding;
6971
0
    int oldstate;
6972
6973
    /*
6974
     * We know that '<?xml' is here.
6975
     */
6976
0
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
6977
0
  SKIP(5);
6978
0
    } else {
6979
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_STARTED, NULL);
6980
0
  return;
6981
0
    }
6982
6983
    /* Avoid expansion of parameter entities when skipping blanks. */
6984
0
    oldstate = ctxt->instate;
6985
0
    ctxt->instate = XML_PARSER_START;
6986
6987
0
    if (SKIP_BLANKS == 0) {
6988
0
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6989
0
           "Space needed after '<?xml'\n");
6990
0
    }
6991
6992
    /*
6993
     * We may have the VersionInfo here.
6994
     */
6995
0
    version = xmlParseVersionInfo(ctxt);
6996
0
    if (version == NULL)
6997
0
  version = xmlCharStrdup(XML_DEFAULT_VERSION);
6998
0
    else {
6999
0
  if (SKIP_BLANKS == 0) {
7000
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
7001
0
               "Space needed here\n");
7002
0
  }
7003
0
    }
7004
0
    ctxt->input->version = version;
7005
7006
    /*
7007
     * We must have the encoding declaration
7008
     */
7009
0
    encoding = xmlParseEncodingDecl(ctxt);
7010
0
    if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
7011
  /*
7012
   * The XML REC instructs us to stop parsing right here
7013
   */
7014
0
        ctxt->instate = oldstate;
7015
0
        return;
7016
0
    }
7017
0
    if ((encoding == NULL) && (ctxt->errNo == XML_ERR_OK)) {
7018
0
  xmlFatalErrMsg(ctxt, XML_ERR_MISSING_ENCODING,
7019
0
           "Missing encoding in text declaration\n");
7020
0
    }
7021
7022
0
    SKIP_BLANKS;
7023
0
    if ((RAW == '?') && (NXT(1) == '>')) {
7024
0
        SKIP(2);
7025
0
    } else if (RAW == '>') {
7026
        /* Deprecated old WD ... */
7027
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
7028
0
  NEXT;
7029
0
    } else {
7030
0
        int c;
7031
7032
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
7033
0
        while ((c = CUR) != 0) {
7034
0
            NEXT;
7035
0
            if (c == '>')
7036
0
                break;
7037
0
        }
7038
0
    }
7039
7040
0
    ctxt->instate = oldstate;
7041
0
}
7042
7043
/**
7044
 * xmlParseExternalSubset:
7045
 * @ctxt:  an XML parser context
7046
 * @ExternalID: the external identifier
7047
 * @SystemID: the system identifier (or URL)
7048
 *
7049
 * parse Markup declarations from an external subset
7050
 *
7051
 * [30] extSubset ::= textDecl? extSubsetDecl
7052
 *
7053
 * [31] extSubsetDecl ::= (markupdecl | conditionalSect | PEReference | S) *
7054
 */
7055
void
7056
xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
7057
0
                       const xmlChar *SystemID) {
7058
0
    xmlDetectSAX2(ctxt);
7059
0
    GROW;
7060
7061
0
    if ((ctxt->encoding == NULL) &&
7062
0
        (ctxt->input->end - ctxt->input->cur >= 4)) {
7063
0
        xmlChar start[4];
7064
0
  xmlCharEncoding enc;
7065
7066
0
  start[0] = RAW;
7067
0
  start[1] = NXT(1);
7068
0
  start[2] = NXT(2);
7069
0
  start[3] = NXT(3);
7070
0
  enc = xmlDetectCharEncoding(start, 4);
7071
0
  if (enc != XML_CHAR_ENCODING_NONE)
7072
0
      xmlSwitchEncoding(ctxt, enc);
7073
0
    }
7074
7075
0
    if (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) {
7076
0
  xmlParseTextDecl(ctxt);
7077
0
  if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
7078
      /*
7079
       * The XML REC instructs us to stop parsing right here
7080
       */
7081
0
      xmlHaltParser(ctxt);
7082
0
      return;
7083
0
  }
7084
0
    }
7085
0
    if (ctxt->myDoc == NULL) {
7086
0
        ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
7087
0
  if (ctxt->myDoc == NULL) {
7088
0
      xmlErrMemory(ctxt, "New Doc failed");
7089
0
      return;
7090
0
  }
7091
0
  ctxt->myDoc->properties = XML_DOC_INTERNAL;
7092
0
    }
7093
0
    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
7094
0
        xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
7095
7096
0
    ctxt->instate = XML_PARSER_DTD;
7097
0
    ctxt->external = 1;
7098
0
    SKIP_BLANKS;
7099
0
    while (((RAW == '<') && (NXT(1) == '?')) ||
7100
0
           ((RAW == '<') && (NXT(1) == '!')) ||
7101
0
     (RAW == '%')) {
7102
0
  int id = ctxt->input->id;
7103
0
  unsigned long cons = CUR_CONSUMED;
7104
7105
0
  GROW;
7106
0
        if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
7107
0
      xmlParseConditionalSections(ctxt);
7108
0
  } else
7109
0
      xmlParseMarkupDecl(ctxt);
7110
0
        SKIP_BLANKS;
7111
7112
0
  if ((id == ctxt->input->id) && (cons == CUR_CONSUMED)) {
7113
0
      xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
7114
0
      break;
7115
0
  }
7116
0
    }
7117
7118
0
    if (RAW != 0) {
7119
0
  xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
7120
0
    }
7121
7122
0
}
7123
7124
/**
7125
 * xmlParseReference:
7126
 * @ctxt:  an XML parser context
7127
 *
7128
 * DEPRECATED: Internal function, don't use.
7129
 *
7130
 * parse and handle entity references in content, depending on the SAX
7131
 * interface, this may end-up in a call to character() if this is a
7132
 * CharRef, a predefined entity, if there is no reference() callback.
7133
 * or if the parser was asked to switch to that mode.
7134
 *
7135
 * [67] Reference ::= EntityRef | CharRef
7136
 */
7137
void
7138
2
xmlParseReference(xmlParserCtxtPtr ctxt) {
7139
2
    xmlEntityPtr ent;
7140
2
    xmlChar *val;
7141
2
    int was_checked;
7142
2
    xmlNodePtr list = NULL;
7143
2
    xmlParserErrors ret = XML_ERR_OK;
7144
7145
7146
2
    if (RAW != '&')
7147
0
        return;
7148
7149
    /*
7150
     * Simple case of a CharRef
7151
     */
7152
2
    if (NXT(1) == '#') {
7153
2
  int i = 0;
7154
2
  xmlChar out[16];
7155
2
  int hex = NXT(2);
7156
2
  int value = xmlParseCharRef(ctxt);
7157
7158
2
  if (value == 0)
7159
0
      return;
7160
2
  if (ctxt->charset != XML_CHAR_ENCODING_UTF8) {
7161
      /*
7162
       * So we are using non-UTF-8 buffers
7163
       * Check that the char fit on 8bits, if not
7164
       * generate a CharRef.
7165
       */
7166
0
      if (value <= 0xFF) {
7167
0
    out[0] = value;
7168
0
    out[1] = 0;
7169
0
    if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
7170
0
        (!ctxt->disableSAX))
7171
0
        ctxt->sax->characters(ctxt->userData, out, 1);
7172
0
      } else {
7173
0
    if ((hex == 'x') || (hex == 'X'))
7174
0
        snprintf((char *)out, sizeof(out), "#x%X", value);
7175
0
    else
7176
0
        snprintf((char *)out, sizeof(out), "#%d", value);
7177
0
    if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
7178
0
        (!ctxt->disableSAX))
7179
0
        ctxt->sax->reference(ctxt->userData, out);
7180
0
      }
7181
2
  } else {
7182
      /*
7183
       * Just encode the value in UTF-8
7184
       */
7185
2
      COPY_BUF(0 ,out, i, value);
7186
2
      out[i] = 0;
7187
2
      if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
7188
2
    (!ctxt->disableSAX))
7189
2
    ctxt->sax->characters(ctxt->userData, out, i);
7190
2
  }
7191
2
  return;
7192
2
    }
7193
7194
    /*
7195
     * We are seeing an entity reference
7196
     */
7197
0
    ent = xmlParseEntityRef(ctxt);
7198
0
    if (ent == NULL) return;
7199
0
    if (!ctxt->wellFormed)
7200
0
  return;
7201
0
    was_checked = ent->checked;
7202
7203
    /* special case of predefined entities */
7204
0
    if ((ent->name == NULL) ||
7205
0
        (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
7206
0
  val = ent->content;
7207
0
  if (val == NULL) return;
7208
  /*
7209
   * inline the entity.
7210
   */
7211
0
  if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
7212
0
      (!ctxt->disableSAX))
7213
0
      ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
7214
0
  return;
7215
0
    }
7216
7217
    /*
7218
     * The first reference to the entity trigger a parsing phase
7219
     * where the ent->children is filled with the result from
7220
     * the parsing.
7221
     * Note: external parsed entities will not be loaded, it is not
7222
     * required for a non-validating parser, unless the parsing option
7223
     * of validating, or substituting entities were given. Doing so is
7224
     * far more secure as the parser will only process data coming from
7225
     * the document entity by default.
7226
     */
7227
0
    if (((ent->checked == 0) ||
7228
0
         ((ent->children == NULL) && (ctxt->options & XML_PARSE_NOENT))) &&
7229
0
        ((ent->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY) ||
7230
0
         (ctxt->options & (XML_PARSE_NOENT | XML_PARSE_DTDVALID)))) {
7231
0
  unsigned long oldnbent = ctxt->nbentities, diff;
7232
7233
  /*
7234
   * This is a bit hackish but this seems the best
7235
   * way to make sure both SAX and DOM entity support
7236
   * behaves okay.
7237
   */
7238
0
  void *user_data;
7239
0
  if (ctxt->userData == ctxt)
7240
0
      user_data = NULL;
7241
0
  else
7242
0
      user_data = ctxt->userData;
7243
7244
  /*
7245
   * Check that this entity is well formed
7246
   * 4.3.2: An internal general parsed entity is well-formed
7247
   * if its replacement text matches the production labeled
7248
   * content.
7249
   */
7250
0
  if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
7251
0
      ctxt->depth++;
7252
0
      ret = xmlParseBalancedChunkMemoryInternal(ctxt, ent->content,
7253
0
                                                user_data, &list);
7254
0
      ctxt->depth--;
7255
7256
0
  } else if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
7257
0
      ctxt->depth++;
7258
0
      ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt, ctxt->sax,
7259
0
                                     user_data, ctxt->depth, ent->URI,
7260
0
             ent->ExternalID, &list);
7261
0
      ctxt->depth--;
7262
0
  } else {
7263
0
      ret = XML_ERR_ENTITY_PE_INTERNAL;
7264
0
      xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
7265
0
       "invalid entity type found\n", NULL);
7266
0
  }
7267
7268
  /*
7269
   * Store the number of entities needing parsing for this entity
7270
   * content and do checkings
7271
   */
7272
0
        diff = ctxt->nbentities - oldnbent + 1;
7273
0
        if (diff > INT_MAX / 2)
7274
0
            diff = INT_MAX / 2;
7275
0
        ent->checked = diff * 2;
7276
0
  if ((ent->content != NULL) && (xmlStrchr(ent->content, '<')))
7277
0
      ent->checked |= 1;
7278
0
  if (ret == XML_ERR_ENTITY_LOOP) {
7279
0
      xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
7280
0
            xmlHaltParser(ctxt);
7281
0
      xmlFreeNodeList(list);
7282
0
      return;
7283
0
  }
7284
0
  if (xmlParserEntityCheck(ctxt, 0, ent, 0)) {
7285
0
      xmlFreeNodeList(list);
7286
0
      return;
7287
0
  }
7288
7289
0
  if ((ret == XML_ERR_OK) && (list != NULL)) {
7290
0
      if (((ent->etype == XML_INTERNAL_GENERAL_ENTITY) ||
7291
0
       (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY))&&
7292
0
    (ent->children == NULL)) {
7293
0
    ent->children = list;
7294
                /*
7295
                 * Prune it directly in the generated document
7296
                 * except for single text nodes.
7297
                 */
7298
0
                if ((ctxt->replaceEntities == 0) ||
7299
0
                    (ctxt->parseMode == XML_PARSE_READER) ||
7300
0
                    ((list->type == XML_TEXT_NODE) &&
7301
0
                     (list->next == NULL))) {
7302
0
                    ent->owner = 1;
7303
0
                    while (list != NULL) {
7304
0
                        list->parent = (xmlNodePtr) ent;
7305
0
                        if (list->doc != ent->doc)
7306
0
                            xmlSetTreeDoc(list, ent->doc);
7307
0
                        if (list->next == NULL)
7308
0
                            ent->last = list;
7309
0
                        list = list->next;
7310
0
                    }
7311
0
                    list = NULL;
7312
0
                } else {
7313
0
                    ent->owner = 0;
7314
0
                    while (list != NULL) {
7315
0
                        list->parent = (xmlNodePtr) ctxt->node;
7316
0
                        list->doc = ctxt->myDoc;
7317
0
                        if (list->next == NULL)
7318
0
                            ent->last = list;
7319
0
                        list = list->next;
7320
0
                    }
7321
0
                    list = ent->children;
7322
#ifdef LIBXML_LEGACY_ENABLED
7323
                    if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7324
                        xmlAddEntityReference(ent, list, NULL);
7325
#endif /* LIBXML_LEGACY_ENABLED */
7326
0
                }
7327
0
      } else {
7328
0
    xmlFreeNodeList(list);
7329
0
    list = NULL;
7330
0
      }
7331
0
  } else if ((ret != XML_ERR_OK) &&
7332
0
       (ret != XML_WAR_UNDECLARED_ENTITY)) {
7333
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7334
0
         "Entity '%s' failed to parse\n", ent->name);
7335
0
            if (ent->content != NULL)
7336
0
                ent->content[0] = 0;
7337
0
      xmlParserEntityCheck(ctxt, 0, ent, 0);
7338
0
  } else if (list != NULL) {
7339
0
      xmlFreeNodeList(list);
7340
0
      list = NULL;
7341
0
  }
7342
0
  if (ent->checked == 0)
7343
0
      ent->checked = 2;
7344
7345
        /* Prevent entity from being parsed and expanded twice (Bug 760367). */
7346
0
        was_checked = 0;
7347
0
    } else if (ent->checked != 1) {
7348
0
  ctxt->nbentities += ent->checked / 2;
7349
0
    }
7350
7351
    /*
7352
     * Now that the entity content has been gathered
7353
     * provide it to the application, this can take different forms based
7354
     * on the parsing modes.
7355
     */
7356
0
    if (ent->children == NULL) {
7357
  /*
7358
   * Probably running in SAX mode and the callbacks don't
7359
   * build the entity content. So unless we already went
7360
   * though parsing for first checking go though the entity
7361
   * content to generate callbacks associated to the entity
7362
   */
7363
0
  if (was_checked != 0) {
7364
0
      void *user_data;
7365
      /*
7366
       * This is a bit hackish but this seems the best
7367
       * way to make sure both SAX and DOM entity support
7368
       * behaves okay.
7369
       */
7370
0
      if (ctxt->userData == ctxt)
7371
0
    user_data = NULL;
7372
0
      else
7373
0
    user_data = ctxt->userData;
7374
7375
0
      if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
7376
0
    ctxt->depth++;
7377
0
    ret = xmlParseBalancedChunkMemoryInternal(ctxt,
7378
0
           ent->content, user_data, NULL);
7379
0
    ctxt->depth--;
7380
0
      } else if (ent->etype ==
7381
0
           XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
7382
0
    ctxt->depth++;
7383
0
    ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt,
7384
0
         ctxt->sax, user_data, ctxt->depth,
7385
0
         ent->URI, ent->ExternalID, NULL);
7386
0
    ctxt->depth--;
7387
0
      } else {
7388
0
    ret = XML_ERR_ENTITY_PE_INTERNAL;
7389
0
    xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
7390
0
           "invalid entity type found\n", NULL);
7391
0
      }
7392
0
      if (ret == XML_ERR_ENTITY_LOOP) {
7393
0
    xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
7394
0
    return;
7395
0
      }
7396
0
  }
7397
0
  if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
7398
0
      (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
7399
      /*
7400
       * Entity reference callback comes second, it's somewhat
7401
       * superfluous but a compatibility to historical behaviour
7402
       */
7403
0
      ctxt->sax->reference(ctxt->userData, ent->name);
7404
0
  }
7405
0
  return;
7406
0
    }
7407
7408
    /*
7409
     * If we didn't get any children for the entity being built
7410
     */
7411
0
    if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
7412
0
  (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
7413
  /*
7414
   * Create a node.
7415
   */
7416
0
  ctxt->sax->reference(ctxt->userData, ent->name);
7417
0
  return;
7418
0
    }
7419
7420
0
    if ((ctxt->replaceEntities) || (ent->children == NULL))  {
7421
  /*
7422
   * There is a problem on the handling of _private for entities
7423
   * (bug 155816): Should we copy the content of the field from
7424
   * the entity (possibly overwriting some value set by the user
7425
   * when a copy is created), should we leave it alone, or should
7426
   * we try to take care of different situations?  The problem
7427
   * is exacerbated by the usage of this field by the xmlReader.
7428
   * To fix this bug, we look at _private on the created node
7429
   * and, if it's NULL, we copy in whatever was in the entity.
7430
   * If it's not NULL we leave it alone.  This is somewhat of a
7431
   * hack - maybe we should have further tests to determine
7432
   * what to do.
7433
   */
7434
0
  if ((ctxt->node != NULL) && (ent->children != NULL)) {
7435
      /*
7436
       * Seems we are generating the DOM content, do
7437
       * a simple tree copy for all references except the first
7438
       * In the first occurrence list contains the replacement.
7439
       */
7440
0
      if (((list == NULL) && (ent->owner == 0)) ||
7441
0
    (ctxt->parseMode == XML_PARSE_READER)) {
7442
0
    xmlNodePtr nw = NULL, cur, firstChild = NULL;
7443
7444
    /*
7445
     * We are copying here, make sure there is no abuse
7446
     */
7447
0
    ctxt->sizeentcopy += ent->length + 5;
7448
0
    if (xmlParserEntityCheck(ctxt, 0, ent, ctxt->sizeentcopy))
7449
0
        return;
7450
7451
    /*
7452
     * when operating on a reader, the entities definitions
7453
     * are always owning the entities subtree.
7454
    if (ctxt->parseMode == XML_PARSE_READER)
7455
        ent->owner = 1;
7456
     */
7457
7458
0
    cur = ent->children;
7459
0
    while (cur != NULL) {
7460
0
        nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
7461
0
        if (nw != NULL) {
7462
0
      if (nw->_private == NULL)
7463
0
          nw->_private = cur->_private;
7464
0
      if (firstChild == NULL){
7465
0
          firstChild = nw;
7466
0
      }
7467
0
      nw = xmlAddChild(ctxt->node, nw);
7468
0
        }
7469
0
        if (cur == ent->last) {
7470
      /*
7471
       * needed to detect some strange empty
7472
       * node cases in the reader tests
7473
       */
7474
0
      if ((ctxt->parseMode == XML_PARSE_READER) &&
7475
0
          (nw != NULL) &&
7476
0
          (nw->type == XML_ELEMENT_NODE) &&
7477
0
          (nw->children == NULL))
7478
0
          nw->extra = 1;
7479
7480
0
      break;
7481
0
        }
7482
0
        cur = cur->next;
7483
0
    }
7484
#ifdef LIBXML_LEGACY_ENABLED
7485
    if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7486
      xmlAddEntityReference(ent, firstChild, nw);
7487
#endif /* LIBXML_LEGACY_ENABLED */
7488
0
      } else if ((list == NULL) || (ctxt->inputNr > 0)) {
7489
0
    xmlNodePtr nw = NULL, cur, next, last,
7490
0
         firstChild = NULL;
7491
7492
    /*
7493
     * We are copying here, make sure there is no abuse
7494
     */
7495
0
    ctxt->sizeentcopy += ent->length + 5;
7496
0
    if (xmlParserEntityCheck(ctxt, 0, ent, ctxt->sizeentcopy))
7497
0
        return;
7498
7499
    /*
7500
     * Copy the entity child list and make it the new
7501
     * entity child list. The goal is to make sure any
7502
     * ID or REF referenced will be the one from the
7503
     * document content and not the entity copy.
7504
     */
7505
0
    cur = ent->children;
7506
0
    ent->children = NULL;
7507
0
    last = ent->last;
7508
0
    ent->last = NULL;
7509
0
    while (cur != NULL) {
7510
0
        next = cur->next;
7511
0
        cur->next = NULL;
7512
0
        cur->parent = NULL;
7513
0
        nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
7514
0
        if (nw != NULL) {
7515
0
      if (nw->_private == NULL)
7516
0
          nw->_private = cur->_private;
7517
0
      if (firstChild == NULL){
7518
0
          firstChild = cur;
7519
0
      }
7520
0
      xmlAddChild((xmlNodePtr) ent, nw);
7521
0
        }
7522
0
        xmlAddChild(ctxt->node, cur);
7523
0
        if (cur == last)
7524
0
      break;
7525
0
        cur = next;
7526
0
    }
7527
0
    if (ent->owner == 0)
7528
0
        ent->owner = 1;
7529
#ifdef LIBXML_LEGACY_ENABLED
7530
    if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7531
      xmlAddEntityReference(ent, firstChild, nw);
7532
#endif /* LIBXML_LEGACY_ENABLED */
7533
0
      } else {
7534
0
    const xmlChar *nbktext;
7535
7536
    /*
7537
     * the name change is to avoid coalescing of the
7538
     * node with a possible previous text one which
7539
     * would make ent->children a dangling pointer
7540
     */
7541
0
    nbktext = xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
7542
0
          -1);
7543
0
    if (ent->children->type == XML_TEXT_NODE)
7544
0
        ent->children->name = nbktext;
7545
0
    if ((ent->last != ent->children) &&
7546
0
        (ent->last->type == XML_TEXT_NODE))
7547
0
        ent->last->name = nbktext;
7548
0
    xmlAddChildList(ctxt->node, ent->children);
7549
0
      }
7550
7551
      /*
7552
       * This is to avoid a nasty side effect, see
7553
       * characters() in SAX.c
7554
       */
7555
0
      ctxt->nodemem = 0;
7556
0
      ctxt->nodelen = 0;
7557
0
      return;
7558
0
  }
7559
0
    }
7560
0
}
7561
7562
/**
7563
 * xmlParseEntityRef:
7564
 * @ctxt:  an XML parser context
7565
 *
7566
 * DEPRECATED: Internal function, don't use.
7567
 *
7568
 * parse ENTITY references declarations
7569
 *
7570
 * [68] EntityRef ::= '&' Name ';'
7571
 *
7572
 * [ WFC: Entity Declared ]
7573
 * In a document without any DTD, a document with only an internal DTD
7574
 * subset which contains no parameter entity references, or a document
7575
 * with "standalone='yes'", the Name given in the entity reference
7576
 * must match that in an entity declaration, except that well-formed
7577
 * documents need not declare any of the following entities: amp, lt,
7578
 * gt, apos, quot.  The declaration of a parameter entity must precede
7579
 * any reference to it.  Similarly, the declaration of a general entity
7580
 * must precede any reference to it which appears in a default value in an
7581
 * attribute-list declaration. Note that if entities are declared in the
7582
 * external subset or in external parameter entities, a non-validating
7583
 * processor is not obligated to read and process their declarations;
7584
 * for such documents, the rule that an entity must be declared is a
7585
 * well-formedness constraint only if standalone='yes'.
7586
 *
7587
 * [ WFC: Parsed Entity ]
7588
 * An entity reference must not contain the name of an unparsed entity
7589
 *
7590
 * Returns the xmlEntityPtr if found, or NULL otherwise.
7591
 */
7592
xmlEntityPtr
7593
0
xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
7594
0
    const xmlChar *name;
7595
0
    xmlEntityPtr ent = NULL;
7596
7597
0
    GROW;
7598
0
    if (ctxt->instate == XML_PARSER_EOF)
7599
0
        return(NULL);
7600
7601
0
    if (RAW != '&')
7602
0
        return(NULL);
7603
0
    NEXT;
7604
0
    name = xmlParseName(ctxt);
7605
0
    if (name == NULL) {
7606
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7607
0
           "xmlParseEntityRef: no name\n");
7608
0
        return(NULL);
7609
0
    }
7610
0
    if (RAW != ';') {
7611
0
  xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
7612
0
  return(NULL);
7613
0
    }
7614
0
    NEXT;
7615
7616
    /*
7617
     * Predefined entities override any extra definition
7618
     */
7619
0
    if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
7620
0
        ent = xmlGetPredefinedEntity(name);
7621
0
        if (ent != NULL)
7622
0
            return(ent);
7623
0
    }
7624
7625
    /*
7626
     * Increase the number of entity references parsed
7627
     */
7628
0
    ctxt->nbentities++;
7629
7630
    /*
7631
     * Ask first SAX for entity resolution, otherwise try the
7632
     * entities which may have stored in the parser context.
7633
     */
7634
0
    if (ctxt->sax != NULL) {
7635
0
  if (ctxt->sax->getEntity != NULL)
7636
0
      ent = ctxt->sax->getEntity(ctxt->userData, name);
7637
0
  if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
7638
0
      (ctxt->options & XML_PARSE_OLDSAX))
7639
0
      ent = xmlGetPredefinedEntity(name);
7640
0
  if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
7641
0
      (ctxt->userData==ctxt)) {
7642
0
      ent = xmlSAX2GetEntity(ctxt, name);
7643
0
  }
7644
0
    }
7645
0
    if (ctxt->instate == XML_PARSER_EOF)
7646
0
  return(NULL);
7647
    /*
7648
     * [ WFC: Entity Declared ]
7649
     * In a document without any DTD, a document with only an
7650
     * internal DTD subset which contains no parameter entity
7651
     * references, or a document with "standalone='yes'", the
7652
     * Name given in the entity reference must match that in an
7653
     * entity declaration, except that well-formed documents
7654
     * need not declare any of the following entities: amp, lt,
7655
     * gt, apos, quot.
7656
     * The declaration of a parameter entity must precede any
7657
     * reference to it.
7658
     * Similarly, the declaration of a general entity must
7659
     * precede any reference to it which appears in a default
7660
     * value in an attribute-list declaration. Note that if
7661
     * entities are declared in the external subset or in
7662
     * external parameter entities, a non-validating processor
7663
     * is not obligated to read and process their declarations;
7664
     * for such documents, the rule that an entity must be
7665
     * declared is a well-formedness constraint only if
7666
     * standalone='yes'.
7667
     */
7668
0
    if (ent == NULL) {
7669
0
  if ((ctxt->standalone == 1) ||
7670
0
      ((ctxt->hasExternalSubset == 0) &&
7671
0
       (ctxt->hasPErefs == 0))) {
7672
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7673
0
         "Entity '%s' not defined\n", name);
7674
0
  } else {
7675
0
      xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
7676
0
         "Entity '%s' not defined\n", name);
7677
0
      if ((ctxt->inSubset == 0) &&
7678
0
    (ctxt->sax != NULL) &&
7679
0
    (ctxt->sax->reference != NULL)) {
7680
0
    ctxt->sax->reference(ctxt->userData, name);
7681
0
      }
7682
0
  }
7683
0
  xmlParserEntityCheck(ctxt, 0, ent, 0);
7684
0
  ctxt->valid = 0;
7685
0
    }
7686
7687
    /*
7688
     * [ WFC: Parsed Entity ]
7689
     * An entity reference must not contain the name of an
7690
     * unparsed entity
7691
     */
7692
0
    else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
7693
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
7694
0
     "Entity reference to unparsed entity %s\n", name);
7695
0
    }
7696
7697
    /*
7698
     * [ WFC: No External Entity References ]
7699
     * Attribute values cannot contain direct or indirect
7700
     * entity references to external entities.
7701
     */
7702
0
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7703
0
       (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
7704
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
7705
0
       "Attribute references external entity '%s'\n", name);
7706
0
    }
7707
    /*
7708
     * [ WFC: No < in Attribute Values ]
7709
     * The replacement text of any entity referred to directly or
7710
     * indirectly in an attribute value (other than "&lt;") must
7711
     * not contain a <.
7712
     */
7713
0
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7714
0
       (ent != NULL) && 
7715
0
       (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
7716
0
  if (((ent->checked & 1) || (ent->checked == 0)) &&
7717
0
       (ent->content != NULL) && (xmlStrchr(ent->content, '<'))) {
7718
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
7719
0
  "'<' in entity '%s' is not allowed in attributes values\n", name);
7720
0
        }
7721
0
    }
7722
7723
    /*
7724
     * Internal check, no parameter entities here ...
7725
     */
7726
0
    else {
7727
0
  switch (ent->etype) {
7728
0
      case XML_INTERNAL_PARAMETER_ENTITY:
7729
0
      case XML_EXTERNAL_PARAMETER_ENTITY:
7730
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
7731
0
       "Attempt to reference the parameter entity '%s'\n",
7732
0
            name);
7733
0
      break;
7734
0
      default:
7735
0
      break;
7736
0
  }
7737
0
    }
7738
7739
    /*
7740
     * [ WFC: No Recursion ]
7741
     * A parsed entity must not contain a recursive reference
7742
     * to itself, either directly or indirectly.
7743
     * Done somewhere else
7744
     */
7745
0
    return(ent);
7746
0
}
7747
7748
/**
7749
 * xmlParseStringEntityRef:
7750
 * @ctxt:  an XML parser context
7751
 * @str:  a pointer to an index in the string
7752
 *
7753
 * parse ENTITY references declarations, but this version parses it from
7754
 * a string value.
7755
 *
7756
 * [68] EntityRef ::= '&' Name ';'
7757
 *
7758
 * [ WFC: Entity Declared ]
7759
 * In a document without any DTD, a document with only an internal DTD
7760
 * subset which contains no parameter entity references, or a document
7761
 * with "standalone='yes'", the Name given in the entity reference
7762
 * must match that in an entity declaration, except that well-formed
7763
 * documents need not declare any of the following entities: amp, lt,
7764
 * gt, apos, quot.  The declaration of a parameter entity must precede
7765
 * any reference to it.  Similarly, the declaration of a general entity
7766
 * must precede any reference to it which appears in a default value in an
7767
 * attribute-list declaration. Note that if entities are declared in the
7768
 * external subset or in external parameter entities, a non-validating
7769
 * processor is not obligated to read and process their declarations;
7770
 * for such documents, the rule that an entity must be declared is a
7771
 * well-formedness constraint only if standalone='yes'.
7772
 *
7773
 * [ WFC: Parsed Entity ]
7774
 * An entity reference must not contain the name of an unparsed entity
7775
 *
7776
 * Returns the xmlEntityPtr if found, or NULL otherwise. The str pointer
7777
 * is updated to the current location in the string.
7778
 */
7779
static xmlEntityPtr
7780
0
xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
7781
0
    xmlChar *name;
7782
0
    const xmlChar *ptr;
7783
0
    xmlChar cur;
7784
0
    xmlEntityPtr ent = NULL;
7785
7786
0
    if ((str == NULL) || (*str == NULL))
7787
0
        return(NULL);
7788
0
    ptr = *str;
7789
0
    cur = *ptr;
7790
0
    if (cur != '&')
7791
0
  return(NULL);
7792
7793
0
    ptr++;
7794
0
    name = xmlParseStringName(ctxt, &ptr);
7795
0
    if (name == NULL) {
7796
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7797
0
           "xmlParseStringEntityRef: no name\n");
7798
0
  *str = ptr;
7799
0
  return(NULL);
7800
0
    }
7801
0
    if (*ptr != ';') {
7802
0
  xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
7803
0
        xmlFree(name);
7804
0
  *str = ptr;
7805
0
  return(NULL);
7806
0
    }
7807
0
    ptr++;
7808
7809
7810
    /*
7811
     * Predefined entities override any extra definition
7812
     */
7813
0
    if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
7814
0
        ent = xmlGetPredefinedEntity(name);
7815
0
        if (ent != NULL) {
7816
0
            xmlFree(name);
7817
0
            *str = ptr;
7818
0
            return(ent);
7819
0
        }
7820
0
    }
7821
7822
    /*
7823
     * Increase the number of entity references parsed
7824
     */
7825
0
    ctxt->nbentities++;
7826
7827
    /*
7828
     * Ask first SAX for entity resolution, otherwise try the
7829
     * entities which may have stored in the parser context.
7830
     */
7831
0
    if (ctxt->sax != NULL) {
7832
0
  if (ctxt->sax->getEntity != NULL)
7833
0
      ent = ctxt->sax->getEntity(ctxt->userData, name);
7834
0
  if ((ent == NULL) && (ctxt->options & XML_PARSE_OLDSAX))
7835
0
      ent = xmlGetPredefinedEntity(name);
7836
0
  if ((ent == NULL) && (ctxt->userData==ctxt)) {
7837
0
      ent = xmlSAX2GetEntity(ctxt, name);
7838
0
  }
7839
0
    }
7840
0
    if (ctxt->instate == XML_PARSER_EOF) {
7841
0
  xmlFree(name);
7842
0
  return(NULL);
7843
0
    }
7844
7845
    /*
7846
     * [ WFC: Entity Declared ]
7847
     * In a document without any DTD, a document with only an
7848
     * internal DTD subset which contains no parameter entity
7849
     * references, or a document with "standalone='yes'", the
7850
     * Name given in the entity reference must match that in an
7851
     * entity declaration, except that well-formed documents
7852
     * need not declare any of the following entities: amp, lt,
7853
     * gt, apos, quot.
7854
     * The declaration of a parameter entity must precede any
7855
     * reference to it.
7856
     * Similarly, the declaration of a general entity must
7857
     * precede any reference to it which appears in a default
7858
     * value in an attribute-list declaration. Note that if
7859
     * entities are declared in the external subset or in
7860
     * external parameter entities, a non-validating processor
7861
     * is not obligated to read and process their declarations;
7862
     * for such documents, the rule that an entity must be
7863
     * declared is a well-formedness constraint only if
7864
     * standalone='yes'.
7865
     */
7866
0
    if (ent == NULL) {
7867
0
  if ((ctxt->standalone == 1) ||
7868
0
      ((ctxt->hasExternalSubset == 0) &&
7869
0
       (ctxt->hasPErefs == 0))) {
7870
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7871
0
         "Entity '%s' not defined\n", name);
7872
0
  } else {
7873
0
      xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
7874
0
        "Entity '%s' not defined\n",
7875
0
        name);
7876
0
  }
7877
0
  xmlParserEntityCheck(ctxt, 0, ent, 0);
7878
  /* TODO ? check regressions ctxt->valid = 0; */
7879
0
    }
7880
7881
    /*
7882
     * [ WFC: Parsed Entity ]
7883
     * An entity reference must not contain the name of an
7884
     * unparsed entity
7885
     */
7886
0
    else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
7887
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
7888
0
     "Entity reference to unparsed entity %s\n", name);
7889
0
    }
7890
7891
    /*
7892
     * [ WFC: No External Entity References ]
7893
     * Attribute values cannot contain direct or indirect
7894
     * entity references to external entities.
7895
     */
7896
0
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7897
0
       (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
7898
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
7899
0
   "Attribute references external entity '%s'\n", name);
7900
0
    }
7901
    /*
7902
     * [ WFC: No < in Attribute Values ]
7903
     * The replacement text of any entity referred to directly or
7904
     * indirectly in an attribute value (other than "&lt;") must
7905
     * not contain a <.
7906
     */
7907
0
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7908
0
       (ent != NULL) && (ent->content != NULL) &&
7909
0
       (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
7910
0
       (xmlStrchr(ent->content, '<'))) {
7911
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
7912
0
     "'<' in entity '%s' is not allowed in attributes values\n",
7913
0
        name);
7914
0
    }
7915
7916
    /*
7917
     * Internal check, no parameter entities here ...
7918
     */
7919
0
    else {
7920
0
  switch (ent->etype) {
7921
0
      case XML_INTERNAL_PARAMETER_ENTITY:
7922
0
      case XML_EXTERNAL_PARAMETER_ENTITY:
7923
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
7924
0
       "Attempt to reference the parameter entity '%s'\n",
7925
0
          name);
7926
0
      break;
7927
0
      default:
7928
0
      break;
7929
0
  }
7930
0
    }
7931
7932
    /*
7933
     * [ WFC: No Recursion ]
7934
     * A parsed entity must not contain a recursive reference
7935
     * to itself, either directly or indirectly.
7936
     * Done somewhere else
7937
     */
7938
7939
0
    xmlFree(name);
7940
0
    *str = ptr;
7941
0
    return(ent);
7942
0
}
7943
7944
/**
7945
 * xmlParsePEReference:
7946
 * @ctxt:  an XML parser context
7947
 *
7948
 * DEPRECATED: Internal function, don't use.
7949
 *
7950
 * parse PEReference declarations
7951
 * The entity content is handled directly by pushing it's content as
7952
 * a new input stream.
7953
 *
7954
 * [69] PEReference ::= '%' Name ';'
7955
 *
7956
 * [ WFC: No Recursion ]
7957
 * A parsed entity must not contain a recursive
7958
 * reference to itself, either directly or indirectly.
7959
 *
7960
 * [ WFC: Entity Declared ]
7961
 * In a document without any DTD, a document with only an internal DTD
7962
 * subset which contains no parameter entity references, or a document
7963
 * with "standalone='yes'", ...  ... The declaration of a parameter
7964
 * entity must precede any reference to it...
7965
 *
7966
 * [ VC: Entity Declared ]
7967
 * In a document with an external subset or external parameter entities
7968
 * with "standalone='no'", ...  ... The declaration of a parameter entity
7969
 * must precede any reference to it...
7970
 *
7971
 * [ WFC: In DTD ]
7972
 * Parameter-entity references may only appear in the DTD.
7973
 * NOTE: misleading but this is handled.
7974
 */
7975
void
7976
xmlParsePEReference(xmlParserCtxtPtr ctxt)
7977
0
{
7978
0
    const xmlChar *name;
7979
0
    xmlEntityPtr entity = NULL;
7980
0
    xmlParserInputPtr input;
7981
7982
0
    if (RAW != '%')
7983
0
        return;
7984
0
    NEXT;
7985
0
    name = xmlParseName(ctxt);
7986
0
    if (name == NULL) {
7987
0
  xmlFatalErrMsg(ctxt, XML_ERR_PEREF_NO_NAME, "PEReference: no name\n");
7988
0
  return;
7989
0
    }
7990
0
    if (xmlParserDebugEntities)
7991
0
  xmlGenericError(xmlGenericErrorContext,
7992
0
    "PEReference: %s\n", name);
7993
0
    if (RAW != ';') {
7994
0
  xmlFatalErr(ctxt, XML_ERR_PEREF_SEMICOL_MISSING, NULL);
7995
0
        return;
7996
0
    }
7997
7998
0
    NEXT;
7999
8000
    /*
8001
     * Increase the number of entity references parsed
8002
     */
8003
0
    ctxt->nbentities++;
8004
8005
    /*
8006
     * Request the entity from SAX
8007
     */
8008
0
    if ((ctxt->sax != NULL) &&
8009
0
  (ctxt->sax->getParameterEntity != NULL))
8010
0
  entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
8011
0
    if (ctxt->instate == XML_PARSER_EOF)
8012
0
  return;
8013
0
    if (entity == NULL) {
8014
  /*
8015
   * [ WFC: Entity Declared ]
8016
   * In a document without any DTD, a document with only an
8017
   * internal DTD subset which contains no parameter entity
8018
   * references, or a document with "standalone='yes'", ...
8019
   * ... The declaration of a parameter entity must precede
8020
   * any reference to it...
8021
   */
8022
0
  if ((ctxt->standalone == 1) ||
8023
0
      ((ctxt->hasExternalSubset == 0) &&
8024
0
       (ctxt->hasPErefs == 0))) {
8025
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
8026
0
            "PEReference: %%%s; not found\n",
8027
0
            name);
8028
0
  } else {
8029
      /*
8030
       * [ VC: Entity Declared ]
8031
       * In a document with an external subset or external
8032
       * parameter entities with "standalone='no'", ...
8033
       * ... The declaration of a parameter entity must
8034
       * precede any reference to it...
8035
       */
8036
0
            if ((ctxt->validate) && (ctxt->vctxt.error != NULL)) {
8037
0
                xmlValidityError(ctxt, XML_WAR_UNDECLARED_ENTITY,
8038
0
                                 "PEReference: %%%s; not found\n",
8039
0
                                 name, NULL);
8040
0
            } else
8041
0
                xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8042
0
                              "PEReference: %%%s; not found\n",
8043
0
                              name, NULL);
8044
0
            ctxt->valid = 0;
8045
0
  }
8046
0
  xmlParserEntityCheck(ctxt, 0, NULL, 0);
8047
0
    } else {
8048
  /*
8049
   * Internal checking in case the entity quest barfed
8050
   */
8051
0
  if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
8052
0
      (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
8053
0
      xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8054
0
      "Internal: %%%s; is not a parameter entity\n",
8055
0
        name, NULL);
8056
0
  } else {
8057
0
            xmlChar start[4];
8058
0
            xmlCharEncoding enc;
8059
8060
0
      if (xmlParserEntityCheck(ctxt, 0, entity, 0))
8061
0
          return;
8062
8063
0
      if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
8064
0
          ((ctxt->options & XML_PARSE_NOENT) == 0) &&
8065
0
    ((ctxt->options & XML_PARSE_DTDVALID) == 0) &&
8066
0
    ((ctxt->options & XML_PARSE_DTDLOAD) == 0) &&
8067
0
    ((ctxt->options & XML_PARSE_DTDATTR) == 0) &&
8068
0
    (ctxt->replaceEntities == 0) &&
8069
0
    (ctxt->validate == 0))
8070
0
    return;
8071
8072
0
      input = xmlNewEntityInputStream(ctxt, entity);
8073
0
      if (xmlPushInput(ctxt, input) < 0) {
8074
0
                xmlFreeInputStream(input);
8075
0
    return;
8076
0
            }
8077
8078
0
      if (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) {
8079
                /*
8080
                 * Get the 4 first bytes and decode the charset
8081
                 * if enc != XML_CHAR_ENCODING_NONE
8082
                 * plug some encoding conversion routines.
8083
                 * Note that, since we may have some non-UTF8
8084
                 * encoding (like UTF16, bug 135229), the 'length'
8085
                 * is not known, but we can calculate based upon
8086
                 * the amount of data in the buffer.
8087
                 */
8088
0
                GROW
8089
0
                if (ctxt->instate == XML_PARSER_EOF)
8090
0
                    return;
8091
0
                if ((ctxt->input->end - ctxt->input->cur)>=4) {
8092
0
                    start[0] = RAW;
8093
0
                    start[1] = NXT(1);
8094
0
                    start[2] = NXT(2);
8095
0
                    start[3] = NXT(3);
8096
0
                    enc = xmlDetectCharEncoding(start, 4);
8097
0
                    if (enc != XML_CHAR_ENCODING_NONE) {
8098
0
                        xmlSwitchEncoding(ctxt, enc);
8099
0
                    }
8100
0
                }
8101
8102
0
                if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) &&
8103
0
                    (IS_BLANK_CH(NXT(5)))) {
8104
0
                    xmlParseTextDecl(ctxt);
8105
0
                }
8106
0
            }
8107
0
  }
8108
0
    }
8109
0
    ctxt->hasPErefs = 1;
8110
0
}
8111
8112
/**
8113
 * xmlLoadEntityContent:
8114
 * @ctxt:  an XML parser context
8115
 * @entity: an unloaded system entity
8116
 *
8117
 * Load the original content of the given system entity from the
8118
 * ExternalID/SystemID given. This is to be used for Included in Literal
8119
 * http://www.w3.org/TR/REC-xml/#inliteral processing of entities references
8120
 *
8121
 * Returns 0 in case of success and -1 in case of failure
8122
 */
8123
static int
8124
0
xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
8125
0
    xmlParserInputPtr input;
8126
0
    xmlBufferPtr buf;
8127
0
    int l, c;
8128
0
    int count = 0;
8129
8130
0
    if ((ctxt == NULL) || (entity == NULL) ||
8131
0
        ((entity->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
8132
0
   (entity->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY)) ||
8133
0
  (entity->content != NULL)) {
8134
0
  xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8135
0
              "xmlLoadEntityContent parameter error");
8136
0
        return(-1);
8137
0
    }
8138
8139
0
    if (xmlParserDebugEntities)
8140
0
  xmlGenericError(xmlGenericErrorContext,
8141
0
    "Reading %s entity content input\n", entity->name);
8142
8143
0
    buf = xmlBufferCreate();
8144
0
    if (buf == NULL) {
8145
0
  xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8146
0
              "xmlLoadEntityContent parameter error");
8147
0
        return(-1);
8148
0
    }
8149
0
    xmlBufferSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);
8150
8151
0
    input = xmlNewEntityInputStream(ctxt, entity);
8152
0
    if (input == NULL) {
8153
0
  xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8154
0
              "xmlLoadEntityContent input error");
8155
0
  xmlBufferFree(buf);
8156
0
        return(-1);
8157
0
    }
8158
8159
    /*
8160
     * Push the entity as the current input, read char by char
8161
     * saving to the buffer until the end of the entity or an error
8162
     */
8163
0
    if (xmlPushInput(ctxt, input) < 0) {
8164
0
        xmlBufferFree(buf);
8165
0
  xmlFreeInputStream(input);
8166
0
  return(-1);
8167
0
    }
8168
8169
0
    GROW;
8170
0
    c = CUR_CHAR(l);
8171
0
    while ((ctxt->input == input) && (ctxt->input->cur < ctxt->input->end) &&
8172
0
           (IS_CHAR(c))) {
8173
0
        xmlBufferAdd(buf, ctxt->input->cur, l);
8174
0
  if (count++ > XML_PARSER_CHUNK_SIZE) {
8175
0
      count = 0;
8176
0
      GROW;
8177
0
            if (ctxt->instate == XML_PARSER_EOF) {
8178
0
                xmlBufferFree(buf);
8179
0
                return(-1);
8180
0
            }
8181
0
  }
8182
0
  NEXTL(l);
8183
0
  c = CUR_CHAR(l);
8184
0
  if (c == 0) {
8185
0
      count = 0;
8186
0
      GROW;
8187
0
            if (ctxt->instate == XML_PARSER_EOF) {
8188
0
                xmlBufferFree(buf);
8189
0
                return(-1);
8190
0
            }
8191
0
      c = CUR_CHAR(l);
8192
0
  }
8193
0
    }
8194
8195
0
    if ((ctxt->input == input) && (ctxt->input->cur >= ctxt->input->end)) {
8196
0
        xmlPopInput(ctxt);
8197
0
    } else if (!IS_CHAR(c)) {
8198
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
8199
0
                          "xmlLoadEntityContent: invalid char value %d\n",
8200
0
                    c);
8201
0
  xmlBufferFree(buf);
8202
0
  return(-1);
8203
0
    }
8204
0
    entity->content = buf->content;
8205
0
    buf->content = NULL;
8206
0
    xmlBufferFree(buf);
8207
8208
0
    return(0);
8209
0
}
8210
8211
/**
8212
 * xmlParseStringPEReference:
8213
 * @ctxt:  an XML parser context
8214
 * @str:  a pointer to an index in the string
8215
 *
8216
 * parse PEReference declarations
8217
 *
8218
 * [69] PEReference ::= '%' Name ';'
8219
 *
8220
 * [ WFC: No Recursion ]
8221
 * A parsed entity must not contain a recursive
8222
 * reference to itself, either directly or indirectly.
8223
 *
8224
 * [ WFC: Entity Declared ]
8225
 * In a document without any DTD, a document with only an internal DTD
8226
 * subset which contains no parameter entity references, or a document
8227
 * with "standalone='yes'", ...  ... The declaration of a parameter
8228
 * entity must precede any reference to it...
8229
 *
8230
 * [ VC: Entity Declared ]
8231
 * In a document with an external subset or external parameter entities
8232
 * with "standalone='no'", ...  ... The declaration of a parameter entity
8233
 * must precede any reference to it...
8234
 *
8235
 * [ WFC: In DTD ]
8236
 * Parameter-entity references may only appear in the DTD.
8237
 * NOTE: misleading but this is handled.
8238
 *
8239
 * Returns the string of the entity content.
8240
 *         str is updated to the current value of the index
8241
 */
8242
static xmlEntityPtr
8243
0
xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
8244
0
    const xmlChar *ptr;
8245
0
    xmlChar cur;
8246
0
    xmlChar *name;
8247
0
    xmlEntityPtr entity = NULL;
8248
8249
0
    if ((str == NULL) || (*str == NULL)) return(NULL);
8250
0
    ptr = *str;
8251
0
    cur = *ptr;
8252
0
    if (cur != '%')
8253
0
        return(NULL);
8254
0
    ptr++;
8255
0
    name = xmlParseStringName(ctxt, &ptr);
8256
0
    if (name == NULL) {
8257
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8258
0
           "xmlParseStringPEReference: no name\n");
8259
0
  *str = ptr;
8260
0
  return(NULL);
8261
0
    }
8262
0
    cur = *ptr;
8263
0
    if (cur != ';') {
8264
0
  xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
8265
0
  xmlFree(name);
8266
0
  *str = ptr;
8267
0
  return(NULL);
8268
0
    }
8269
0
    ptr++;
8270
8271
    /*
8272
     * Increase the number of entity references parsed
8273
     */
8274
0
    ctxt->nbentities++;
8275
8276
    /*
8277
     * Request the entity from SAX
8278
     */
8279
0
    if ((ctxt->sax != NULL) &&
8280
0
  (ctxt->sax->getParameterEntity != NULL))
8281
0
  entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
8282
0
    if (ctxt->instate == XML_PARSER_EOF) {
8283
0
  xmlFree(name);
8284
0
  *str = ptr;
8285
0
  return(NULL);
8286
0
    }
8287
0
    if (entity == NULL) {
8288
  /*
8289
   * [ WFC: Entity Declared ]
8290
   * In a document without any DTD, a document with only an
8291
   * internal DTD subset which contains no parameter entity
8292
   * references, or a document with "standalone='yes'", ...
8293
   * ... The declaration of a parameter entity must precede
8294
   * any reference to it...
8295
   */
8296
0
  if ((ctxt->standalone == 1) ||
8297
0
      ((ctxt->hasExternalSubset == 0) && (ctxt->hasPErefs == 0))) {
8298
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
8299
0
     "PEReference: %%%s; not found\n", name);
8300
0
  } else {
8301
      /*
8302
       * [ VC: Entity Declared ]
8303
       * In a document with an external subset or external
8304
       * parameter entities with "standalone='no'", ...
8305
       * ... The declaration of a parameter entity must
8306
       * precede any reference to it...
8307
       */
8308
0
      xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8309
0
        "PEReference: %%%s; not found\n",
8310
0
        name, NULL);
8311
0
      ctxt->valid = 0;
8312
0
  }
8313
0
  xmlParserEntityCheck(ctxt, 0, NULL, 0);
8314
0
    } else {
8315
  /*
8316
   * Internal checking in case the entity quest barfed
8317
   */
8318
0
  if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
8319
0
      (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
8320
0
      xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8321
0
        "%%%s; is not a parameter entity\n",
8322
0
        name, NULL);
8323
0
  }
8324
0
    }
8325
0
    ctxt->hasPErefs = 1;
8326
0
    xmlFree(name);
8327
0
    *str = ptr;
8328
0
    return(entity);
8329
0
}
8330
8331
/**
8332
 * xmlParseDocTypeDecl:
8333
 * @ctxt:  an XML parser context
8334
 *
8335
 * DEPRECATED: Internal function, don't use.
8336
 *
8337
 * parse a DOCTYPE declaration
8338
 *
8339
 * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
8340
 *                      ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
8341
 *
8342
 * [ VC: Root Element Type ]
8343
 * The Name in the document type declaration must match the element
8344
 * type of the root element.
8345
 */
8346
8347
void
8348
0
xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
8349
0
    const xmlChar *name = NULL;
8350
0
    xmlChar *ExternalID = NULL;
8351
0
    xmlChar *URI = NULL;
8352
8353
    /*
8354
     * We know that '<!DOCTYPE' has been detected.
8355
     */
8356
0
    SKIP(9);
8357
8358
0
    SKIP_BLANKS;
8359
8360
    /*
8361
     * Parse the DOCTYPE name.
8362
     */
8363
0
    name = xmlParseName(ctxt);
8364
0
    if (name == NULL) {
8365
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8366
0
           "xmlParseDocTypeDecl : no DOCTYPE name !\n");
8367
0
    }
8368
0
    ctxt->intSubName = name;
8369
8370
0
    SKIP_BLANKS;
8371
8372
    /*
8373
     * Check for SystemID and ExternalID
8374
     */
8375
0
    URI = xmlParseExternalID(ctxt, &ExternalID, 1);
8376
8377
0
    if ((URI != NULL) || (ExternalID != NULL)) {
8378
0
        ctxt->hasExternalSubset = 1;
8379
0
    }
8380
0
    ctxt->extSubURI = URI;
8381
0
    ctxt->extSubSystem = ExternalID;
8382
8383
0
    SKIP_BLANKS;
8384
8385
    /*
8386
     * Create and update the internal subset.
8387
     */
8388
0
    if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL) &&
8389
0
  (!ctxt->disableSAX))
8390
0
  ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
8391
0
    if (ctxt->instate == XML_PARSER_EOF)
8392
0
  return;
8393
8394
    /*
8395
     * Is there any internal subset declarations ?
8396
     * they are handled separately in xmlParseInternalSubset()
8397
     */
8398
0
    if (RAW == '[')
8399
0
  return;
8400
8401
    /*
8402
     * We should be at the end of the DOCTYPE declaration.
8403
     */
8404
0
    if (RAW != '>') {
8405
0
  xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
8406
0
    }
8407
0
    NEXT;
8408
0
}
8409
8410
/**
8411
 * xmlParseInternalSubset:
8412
 * @ctxt:  an XML parser context
8413
 *
8414
 * parse the internal subset declaration
8415
 *
8416
 * [28 end] ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
8417
 */
8418
8419
static void
8420
0
xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
8421
    /*
8422
     * Is there any DTD definition ?
8423
     */
8424
0
    if (RAW == '[') {
8425
0
        int baseInputNr = ctxt->inputNr;
8426
0
        ctxt->instate = XML_PARSER_DTD;
8427
0
        NEXT;
8428
  /*
8429
   * Parse the succession of Markup declarations and
8430
   * PEReferences.
8431
   * Subsequence (markupdecl | PEReference | S)*
8432
   */
8433
0
  while (((RAW != ']') || (ctxt->inputNr > baseInputNr)) &&
8434
0
               (ctxt->instate != XML_PARSER_EOF)) {
8435
0
      int id = ctxt->input->id;
8436
0
      unsigned long cons = CUR_CONSUMED;
8437
8438
0
      SKIP_BLANKS;
8439
0
      xmlParseMarkupDecl(ctxt);
8440
0
      xmlParsePEReference(ctxt);
8441
8442
            /*
8443
             * Conditional sections are allowed from external entities included
8444
             * by PE References in the internal subset.
8445
             */
8446
0
            if ((ctxt->inputNr > 1) && (ctxt->input->filename != NULL) &&
8447
0
                (RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
8448
0
                xmlParseConditionalSections(ctxt);
8449
0
            }
8450
8451
0
      if ((id == ctxt->input->id) && (cons == CUR_CONSUMED)) {
8452
0
    xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8453
0
       "xmlParseInternalSubset: error detected in Markup declaration\n");
8454
0
                if (ctxt->inputNr > baseInputNr)
8455
0
                    xmlPopInput(ctxt);
8456
0
                else
8457
0
        break;
8458
0
      }
8459
0
  }
8460
0
  if (RAW == ']') {
8461
0
      NEXT;
8462
0
      SKIP_BLANKS;
8463
0
  }
8464
0
    }
8465
8466
    /*
8467
     * We should be at the end of the DOCTYPE declaration.
8468
     */
8469
0
    if (RAW != '>') {
8470
0
  xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
8471
0
  return;
8472
0
    }
8473
0
    NEXT;
8474
0
}
8475
8476
#ifdef LIBXML_SAX1_ENABLED
8477
/**
8478
 * xmlParseAttribute:
8479
 * @ctxt:  an XML parser context
8480
 * @value:  a xmlChar ** used to store the value of the attribute
8481
 *
8482
 * DEPRECATED: Internal function, don't use.
8483
 *
8484
 * parse an attribute
8485
 *
8486
 * [41] Attribute ::= Name Eq AttValue
8487
 *
8488
 * [ WFC: No External Entity References ]
8489
 * Attribute values cannot contain direct or indirect entity references
8490
 * to external entities.
8491
 *
8492
 * [ WFC: No < in Attribute Values ]
8493
 * The replacement text of any entity referred to directly or indirectly in
8494
 * an attribute value (other than "&lt;") must not contain a <.
8495
 *
8496
 * [ VC: Attribute Value Type ]
8497
 * The attribute must have been declared; the value must be of the type
8498
 * declared for it.
8499
 *
8500
 * [25] Eq ::= S? '=' S?
8501
 *
8502
 * With namespace:
8503
 *
8504
 * [NS 11] Attribute ::= QName Eq AttValue
8505
 *
8506
 * Also the case QName == xmlns:??? is handled independently as a namespace
8507
 * definition.
8508
 *
8509
 * Returns the attribute name, and the value in *value.
8510
 */
8511
8512
const xmlChar *
8513
xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
8514
    const xmlChar *name;
8515
    xmlChar *val;
8516
8517
    *value = NULL;
8518
    GROW;
8519
    name = xmlParseName(ctxt);
8520
    if (name == NULL) {
8521
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8522
                 "error parsing attribute name\n");
8523
        return(NULL);
8524
    }
8525
8526
    /*
8527
     * read the value
8528
     */
8529
    SKIP_BLANKS;
8530
    if (RAW == '=') {
8531
        NEXT;
8532
  SKIP_BLANKS;
8533
  val = xmlParseAttValue(ctxt);
8534
  ctxt->instate = XML_PARSER_CONTENT;
8535
    } else {
8536
  xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
8537
         "Specification mandates value for attribute %s\n", name);
8538
  return(NULL);
8539
    }
8540
8541
    /*
8542
     * Check that xml:lang conforms to the specification
8543
     * No more registered as an error, just generate a warning now
8544
     * since this was deprecated in XML second edition
8545
     */
8546
    if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "xml:lang"))) {
8547
  if (!xmlCheckLanguageID(val)) {
8548
      xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
8549
              "Malformed value for xml:lang : %s\n",
8550
        val, NULL);
8551
  }
8552
    }
8553
8554
    /*
8555
     * Check that xml:space conforms to the specification
8556
     */
8557
    if (xmlStrEqual(name, BAD_CAST "xml:space")) {
8558
  if (xmlStrEqual(val, BAD_CAST "default"))
8559
      *(ctxt->space) = 0;
8560
  else if (xmlStrEqual(val, BAD_CAST "preserve"))
8561
      *(ctxt->space) = 1;
8562
  else {
8563
    xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
8564
"Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
8565
                                 val, NULL);
8566
  }
8567
    }
8568
8569
    *value = val;
8570
    return(name);
8571
}
8572
8573
/**
8574
 * xmlParseStartTag:
8575
 * @ctxt:  an XML parser context
8576
 *
8577
 * DEPRECATED: Internal function, don't use.
8578
 *
8579
 * parse a start of tag either for rule element or
8580
 * EmptyElement. In both case we don't parse the tag closing chars.
8581
 *
8582
 * [40] STag ::= '<' Name (S Attribute)* S? '>'
8583
 *
8584
 * [ WFC: Unique Att Spec ]
8585
 * No attribute name may appear more than once in the same start-tag or
8586
 * empty-element tag.
8587
 *
8588
 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
8589
 *
8590
 * [ WFC: Unique Att Spec ]
8591
 * No attribute name may appear more than once in the same start-tag or
8592
 * empty-element tag.
8593
 *
8594
 * With namespace:
8595
 *
8596
 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
8597
 *
8598
 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
8599
 *
8600
 * Returns the element name parsed
8601
 */
8602
8603
const xmlChar *
8604
xmlParseStartTag(xmlParserCtxtPtr ctxt) {
8605
    const xmlChar *name;
8606
    const xmlChar *attname;
8607
    xmlChar *attvalue;
8608
    const xmlChar **atts = ctxt->atts;
8609
    int nbatts = 0;
8610
    int maxatts = ctxt->maxatts;
8611
    int i;
8612
8613
    if (RAW != '<') return(NULL);
8614
    NEXT1;
8615
8616
    name = xmlParseName(ctxt);
8617
    if (name == NULL) {
8618
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8619
       "xmlParseStartTag: invalid element name\n");
8620
        return(NULL);
8621
    }
8622
8623
    /*
8624
     * Now parse the attributes, it ends up with the ending
8625
     *
8626
     * (S Attribute)* S?
8627
     */
8628
    SKIP_BLANKS;
8629
    GROW;
8630
8631
    while (((RAW != '>') &&
8632
     ((RAW != '/') || (NXT(1) != '>')) &&
8633
     (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) {
8634
        int id = ctxt->input->id;
8635
  unsigned long cons = CUR_CONSUMED;
8636
8637
  attname = xmlParseAttribute(ctxt, &attvalue);
8638
        if ((attname != NULL) && (attvalue != NULL)) {
8639
      /*
8640
       * [ WFC: Unique Att Spec ]
8641
       * No attribute name may appear more than once in the same
8642
       * start-tag or empty-element tag.
8643
       */
8644
      for (i = 0; i < nbatts;i += 2) {
8645
          if (xmlStrEqual(atts[i], attname)) {
8646
        xmlErrAttributeDup(ctxt, NULL, attname);
8647
        xmlFree(attvalue);
8648
        goto failed;
8649
    }
8650
      }
8651
      /*
8652
       * Add the pair to atts
8653
       */
8654
      if (atts == NULL) {
8655
          maxatts = 22; /* allow for 10 attrs by default */
8656
          atts = (const xmlChar **)
8657
           xmlMalloc(maxatts * sizeof(xmlChar *));
8658
    if (atts == NULL) {
8659
        xmlErrMemory(ctxt, NULL);
8660
        if (attvalue != NULL)
8661
      xmlFree(attvalue);
8662
        goto failed;
8663
    }
8664
    ctxt->atts = atts;
8665
    ctxt->maxatts = maxatts;
8666
      } else if (nbatts + 4 > maxatts) {
8667
          const xmlChar **n;
8668
8669
          maxatts *= 2;
8670
          n = (const xmlChar **) xmlRealloc((void *) atts,
8671
               maxatts * sizeof(const xmlChar *));
8672
    if (n == NULL) {
8673
        xmlErrMemory(ctxt, NULL);
8674
        if (attvalue != NULL)
8675
      xmlFree(attvalue);
8676
        goto failed;
8677
    }
8678
    atts = n;
8679
    ctxt->atts = atts;
8680
    ctxt->maxatts = maxatts;
8681
      }
8682
      atts[nbatts++] = attname;
8683
      atts[nbatts++] = attvalue;
8684
      atts[nbatts] = NULL;
8685
      atts[nbatts + 1] = NULL;
8686
  } else {
8687
      if (attvalue != NULL)
8688
    xmlFree(attvalue);
8689
  }
8690
8691
failed:
8692
8693
  GROW
8694
  if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
8695
      break;
8696
  if (SKIP_BLANKS == 0) {
8697
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
8698
         "attributes construct error\n");
8699
  }
8700
        if ((cons == CUR_CONSUMED) && (id == ctxt->input->id) &&
8701
            (attname == NULL) && (attvalue == NULL)) {
8702
      xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
8703
         "xmlParseStartTag: problem parsing attributes\n");
8704
      break;
8705
  }
8706
  SHRINK;
8707
        GROW;
8708
    }
8709
8710
    /*
8711
     * SAX: Start of Element !
8712
     */
8713
    if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL) &&
8714
  (!ctxt->disableSAX)) {
8715
  if (nbatts > 0)
8716
      ctxt->sax->startElement(ctxt->userData, name, atts);
8717
  else
8718
      ctxt->sax->startElement(ctxt->userData, name, NULL);
8719
    }
8720
8721
    if (atts != NULL) {
8722
        /* Free only the content strings */
8723
        for (i = 1;i < nbatts;i+=2)
8724
      if (atts[i] != NULL)
8725
         xmlFree((xmlChar *) atts[i]);
8726
    }
8727
    return(name);
8728
}
8729
8730
/**
8731
 * xmlParseEndTag1:
8732
 * @ctxt:  an XML parser context
8733
 * @line:  line of the start tag
8734
 * @nsNr:  number of namespaces on the start tag
8735
 *
8736
 * parse an end of tag
8737
 *
8738
 * [42] ETag ::= '</' Name S? '>'
8739
 *
8740
 * With namespace
8741
 *
8742
 * [NS 9] ETag ::= '</' QName S? '>'
8743
 */
8744
8745
static void
8746
xmlParseEndTag1(xmlParserCtxtPtr ctxt, int line) {
8747
    const xmlChar *name;
8748
8749
    GROW;
8750
    if ((RAW != '<') || (NXT(1) != '/')) {
8751
  xmlFatalErrMsg(ctxt, XML_ERR_LTSLASH_REQUIRED,
8752
           "xmlParseEndTag: '</' not found\n");
8753
  return;
8754
    }
8755
    SKIP(2);
8756
8757
    name = xmlParseNameAndCompare(ctxt,ctxt->name);
8758
8759
    /*
8760
     * We should definitely be at the ending "S? '>'" part
8761
     */
8762
    GROW;
8763
    SKIP_BLANKS;
8764
    if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
8765
  xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
8766
    } else
8767
  NEXT1;
8768
8769
    /*
8770
     * [ WFC: Element Type Match ]
8771
     * The Name in an element's end-tag must match the element type in the
8772
     * start-tag.
8773
     *
8774
     */
8775
    if (name != (xmlChar*)1) {
8776
        if (name == NULL) name = BAD_CAST "unparsable";
8777
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
8778
         "Opening and ending tag mismatch: %s line %d and %s\n",
8779
                    ctxt->name, line, name);
8780
    }
8781
8782
    /*
8783
     * SAX: End of Tag
8784
     */
8785
    if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
8786
  (!ctxt->disableSAX))
8787
        ctxt->sax->endElement(ctxt->userData, ctxt->name);
8788
8789
    namePop(ctxt);
8790
    spacePop(ctxt);
8791
    return;
8792
}
8793
8794
/**
8795
 * xmlParseEndTag:
8796
 * @ctxt:  an XML parser context
8797
 *
8798
 * DEPRECATED: Internal function, don't use.
8799
 *
8800
 * parse an end of tag
8801
 *
8802
 * [42] ETag ::= '</' Name S? '>'
8803
 *
8804
 * With namespace
8805
 *
8806
 * [NS 9] ETag ::= '</' QName S? '>'
8807
 */
8808
8809
void
8810
xmlParseEndTag(xmlParserCtxtPtr ctxt) {
8811
    xmlParseEndTag1(ctxt, 0);
8812
}
8813
#endif /* LIBXML_SAX1_ENABLED */
8814
8815
/************************************************************************
8816
 *                  *
8817
 *          SAX 2 specific operations       *
8818
 *                  *
8819
 ************************************************************************/
8820
8821
/*
8822
 * xmlGetNamespace:
8823
 * @ctxt:  an XML parser context
8824
 * @prefix:  the prefix to lookup
8825
 *
8826
 * Lookup the namespace name for the @prefix (which ca be NULL)
8827
 * The prefix must come from the @ctxt->dict dictionary
8828
 *
8829
 * Returns the namespace name or NULL if not bound
8830
 */
8831
static const xmlChar *
8832
24
xmlGetNamespace(xmlParserCtxtPtr ctxt, const xmlChar *prefix) {
8833
24
    int i;
8834
8835
24
    if (prefix == ctxt->str_xml) return(ctxt->str_xml_ns);
8836
46
    for (i = ctxt->nsNr - 2;i >= 0;i-=2)
8837
36
        if (ctxt->nsTab[i] == prefix) {
8838
14
      if ((prefix == NULL) && (*ctxt->nsTab[i + 1] == 0))
8839
0
          return(NULL);
8840
14
      return(ctxt->nsTab[i + 1]);
8841
14
  }
8842
10
    return(NULL);
8843
24
}
8844
8845
/**
8846
 * xmlParseQName:
8847
 * @ctxt:  an XML parser context
8848
 * @prefix:  pointer to store the prefix part
8849
 *
8850
 * parse an XML Namespace QName
8851
 *
8852
 * [6]  QName  ::= (Prefix ':')? LocalPart
8853
 * [7]  Prefix  ::= NCName
8854
 * [8]  LocalPart  ::= NCName
8855
 *
8856
 * Returns the Name parsed or NULL
8857
 */
8858
8859
static const xmlChar *
8860
48
xmlParseQName(xmlParserCtxtPtr ctxt, const xmlChar **prefix) {
8861
48
    const xmlChar *l, *p;
8862
8863
48
    GROW;
8864
8865
48
    l = xmlParseNCName(ctxt);
8866
48
    if (l == NULL) {
8867
0
        if (CUR == ':') {
8868
0
      l = xmlParseName(ctxt);
8869
0
      if (l != NULL) {
8870
0
          xmlNsErr(ctxt, XML_NS_ERR_QNAME,
8871
0
             "Failed to parse QName '%s'\n", l, NULL, NULL);
8872
0
    *prefix = NULL;
8873
0
    return(l);
8874
0
      }
8875
0
  }
8876
0
        return(NULL);
8877
0
    }
8878
48
    if (CUR == ':') {
8879
20
        NEXT;
8880
20
  p = l;
8881
20
  l = xmlParseNCName(ctxt);
8882
20
  if (l == NULL) {
8883
0
      xmlChar *tmp;
8884
8885
0
            if (ctxt->instate == XML_PARSER_EOF)
8886
0
                return(NULL);
8887
0
            xmlNsErr(ctxt, XML_NS_ERR_QNAME,
8888
0
               "Failed to parse QName '%s:'\n", p, NULL, NULL);
8889
0
      l = xmlParseNmtoken(ctxt);
8890
0
      if (l == NULL) {
8891
0
                if (ctxt->instate == XML_PARSER_EOF)
8892
0
                    return(NULL);
8893
0
    tmp = xmlBuildQName(BAD_CAST "", p, NULL, 0);
8894
0
            } else {
8895
0
    tmp = xmlBuildQName(l, p, NULL, 0);
8896
0
    xmlFree((char *)l);
8897
0
      }
8898
0
      p = xmlDictLookup(ctxt->dict, tmp, -1);
8899
0
      if (tmp != NULL) xmlFree(tmp);
8900
0
      *prefix = NULL;
8901
0
      return(p);
8902
0
  }
8903
20
  if (CUR == ':') {
8904
0
      xmlChar *tmp;
8905
8906
0
            xmlNsErr(ctxt, XML_NS_ERR_QNAME,
8907
0
               "Failed to parse QName '%s:%s:'\n", p, l, NULL);
8908
0
      NEXT;
8909
0
      tmp = (xmlChar *) xmlParseName(ctxt);
8910
0
      if (tmp != NULL) {
8911
0
          tmp = xmlBuildQName(tmp, l, NULL, 0);
8912
0
    l = xmlDictLookup(ctxt->dict, tmp, -1);
8913
0
    if (tmp != NULL) xmlFree(tmp);
8914
0
    *prefix = p;
8915
0
    return(l);
8916
0
      }
8917
0
            if (ctxt->instate == XML_PARSER_EOF)
8918
0
                return(NULL);
8919
0
      tmp = xmlBuildQName(BAD_CAST "", l, NULL, 0);
8920
0
      l = xmlDictLookup(ctxt->dict, tmp, -1);
8921
0
      if (tmp != NULL) xmlFree(tmp);
8922
0
      *prefix = p;
8923
0
      return(l);
8924
0
  }
8925
20
  *prefix = p;
8926
20
    } else
8927
28
        *prefix = NULL;
8928
48
    return(l);
8929
48
}
8930
8931
/**
8932
 * xmlParseQNameAndCompare:
8933
 * @ctxt:  an XML parser context
8934
 * @name:  the localname
8935
 * @prefix:  the prefix, if any.
8936
 *
8937
 * parse an XML name and compares for match
8938
 * (specialized for endtag parsing)
8939
 *
8940
 * Returns NULL for an illegal name, (xmlChar*) 1 for success
8941
 * and the name for mismatch
8942
 */
8943
8944
static const xmlChar *
8945
xmlParseQNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *name,
8946
10
                        xmlChar const *prefix) {
8947
10
    const xmlChar *cmp;
8948
10
    const xmlChar *in;
8949
10
    const xmlChar *ret;
8950
10
    const xmlChar *prefix2;
8951
8952
10
    if (prefix == NULL) return(xmlParseNameAndCompare(ctxt, name));
8953
8954
10
    GROW;
8955
10
    in = ctxt->input->cur;
8956
8957
10
    cmp = prefix;
8958
20
    while (*in != 0 && *in == *cmp) {
8959
10
  ++in;
8960
10
  ++cmp;
8961
10
    }
8962
10
    if ((*cmp == 0) && (*in == ':')) {
8963
10
        in++;
8964
10
  cmp = name;
8965
20
  while (*in != 0 && *in == *cmp) {
8966
10
      ++in;
8967
10
      ++cmp;
8968
10
  }
8969
10
  if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
8970
      /* success */
8971
10
            ctxt->input->col += in - ctxt->input->cur;
8972
10
      ctxt->input->cur = in;
8973
10
      return((const xmlChar*) 1);
8974
10
  }
8975
10
    }
8976
    /*
8977
     * all strings coms from the dictionary, equality can be done directly
8978
     */
8979
0
    ret = xmlParseQName (ctxt, &prefix2);
8980
0
    if ((ret == name) && (prefix == prefix2))
8981
0
  return((const xmlChar*) 1);
8982
0
    return ret;
8983
0
}
8984
8985
/**
8986
 * xmlParseAttValueInternal:
8987
 * @ctxt:  an XML parser context
8988
 * @len:  attribute len result
8989
 * @alloc:  whether the attribute was reallocated as a new string
8990
 * @normalize:  if 1 then further non-CDATA normalization must be done
8991
 *
8992
 * parse a value for an attribute.
8993
 * NOTE: if no normalization is needed, the routine will return pointers
8994
 *       directly from the data buffer.
8995
 *
8996
 * 3.3.3 Attribute-Value Normalization:
8997
 * Before the value of an attribute is passed to the application or
8998
 * checked for validity, the XML processor must normalize it as follows:
8999
 * - a character reference is processed by appending the referenced
9000
 *   character to the attribute value
9001
 * - an entity reference is processed by recursively processing the
9002
 *   replacement text of the entity
9003
 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
9004
 *   appending #x20 to the normalized value, except that only a single
9005
 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
9006
 *   parsed entity or the literal entity value of an internal parsed entity
9007
 * - other characters are processed by appending them to the normalized value
9008
 * If the declared value is not CDATA, then the XML processor must further
9009
 * process the normalized attribute value by discarding any leading and
9010
 * trailing space (#x20) characters, and by replacing sequences of space
9011
 * (#x20) characters by a single space (#x20) character.
9012
 * All attributes for which no declaration has been read should be treated
9013
 * by a non-validating parser as if declared CDATA.
9014
 *
9015
 * Returns the AttValue parsed or NULL. The value has to be freed by the
9016
 *     caller if it was copied, this can be detected by val[*len] == 0.
9017
 */
9018
9019
#define GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end) \
9020
0
    const xmlChar *oldbase = ctxt->input->base;\
9021
0
    GROW;\
9022
0
    if (ctxt->instate == XML_PARSER_EOF)\
9023
0
        return(NULL);\
9024
0
    if (oldbase != ctxt->input->base) {\
9025
0
        ptrdiff_t delta = ctxt->input->base - oldbase;\
9026
0
        start = start + delta;\
9027
0
        in = in + delta;\
9028
0
    }\
9029
0
    end = ctxt->input->end;
9030
9031
static xmlChar *
9032
xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
9033
                         int normalize)
9034
24
{
9035
24
    xmlChar limit = 0;
9036
24
    const xmlChar *in = NULL, *start, *end, *last;
9037
24
    xmlChar *ret = NULL;
9038
24
    int line, col;
9039
24
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
9040
0
                    XML_MAX_HUGE_LENGTH :
9041
24
                    XML_MAX_TEXT_LENGTH;
9042
9043
24
    GROW;
9044
24
    in = (xmlChar *) CUR_PTR;
9045
24
    line = ctxt->input->line;
9046
24
    col = ctxt->input->col;
9047
24
    if (*in != '"' && *in != '\'') {
9048
0
        xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
9049
0
        return (NULL);
9050
0
    }
9051
24
    ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
9052
9053
    /*
9054
     * try to handle in this routine the most common case where no
9055
     * allocation of a new string is required and where content is
9056
     * pure ASCII.
9057
     */
9058
24
    limit = *in++;
9059
24
    col++;
9060
24
    end = ctxt->input->end;
9061
24
    start = in;
9062
24
    if (in >= end) {
9063
0
        GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
9064
0
    }
9065
24
    if (normalize) {
9066
        /*
9067
   * Skip any leading spaces
9068
   */
9069
0
  while ((in < end) && (*in != limit) &&
9070
0
         ((*in == 0x20) || (*in == 0x9) ||
9071
0
          (*in == 0xA) || (*in == 0xD))) {
9072
0
      if (*in == 0xA) {
9073
0
          line++; col = 1;
9074
0
      } else {
9075
0
          col++;
9076
0
      }
9077
0
      in++;
9078
0
      start = in;
9079
0
      if (in >= end) {
9080
0
                GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
9081
0
                if ((in - start) > maxLength) {
9082
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9083
0
                                   "AttValue length too long\n");
9084
0
                    return(NULL);
9085
0
                }
9086
0
      }
9087
0
  }
9088
0
  while ((in < end) && (*in != limit) && (*in >= 0x20) &&
9089
0
         (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
9090
0
      col++;
9091
0
      if ((*in++ == 0x20) && (*in == 0x20)) break;
9092
0
      if (in >= end) {
9093
0
                GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
9094
0
                if ((in - start) > maxLength) {
9095
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9096
0
                                   "AttValue length too long\n");
9097
0
                    return(NULL);
9098
0
                }
9099
0
      }
9100
0
  }
9101
0
  last = in;
9102
  /*
9103
   * skip the trailing blanks
9104
   */
9105
0
  while ((last[-1] == 0x20) && (last > start)) last--;
9106
0
  while ((in < end) && (*in != limit) &&
9107
0
         ((*in == 0x20) || (*in == 0x9) ||
9108
0
          (*in == 0xA) || (*in == 0xD))) {
9109
0
      if (*in == 0xA) {
9110
0
          line++, col = 1;
9111
0
      } else {
9112
0
          col++;
9113
0
      }
9114
0
      in++;
9115
0
      if (in >= end) {
9116
0
    const xmlChar *oldbase = ctxt->input->base;
9117
0
    GROW;
9118
0
                if (ctxt->instate == XML_PARSER_EOF)
9119
0
                    return(NULL);
9120
0
    if (oldbase != ctxt->input->base) {
9121
0
        ptrdiff_t delta = ctxt->input->base - oldbase;
9122
0
        start = start + delta;
9123
0
        in = in + delta;
9124
0
        last = last + delta;
9125
0
    }
9126
0
    end = ctxt->input->end;
9127
0
                if ((in - start) > maxLength) {
9128
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9129
0
                                   "AttValue length too long\n");
9130
0
                    return(NULL);
9131
0
                }
9132
0
      }
9133
0
  }
9134
0
        if ((in - start) > maxLength) {
9135
0
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9136
0
                           "AttValue length too long\n");
9137
0
            return(NULL);
9138
0
        }
9139
0
  if (*in != limit) goto need_complex;
9140
24
    } else {
9141
46
  while ((in < end) && (*in != limit) && (*in >= 0x20) &&
9142
46
         (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
9143
22
      in++;
9144
22
      col++;
9145
22
      if (in >= end) {
9146
0
                GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
9147
0
                if ((in - start) > maxLength) {
9148
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9149
0
                                   "AttValue length too long\n");
9150
0
                    return(NULL);
9151
0
                }
9152
0
      }
9153
22
  }
9154
24
  last = in;
9155
24
        if ((in - start) > maxLength) {
9156
0
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9157
0
                           "AttValue length too long\n");
9158
0
            return(NULL);
9159
0
        }
9160
24
  if (*in != limit) goto need_complex;
9161
24
    }
9162
22
    in++;
9163
22
    col++;
9164
22
    if (len != NULL) {
9165
22
        if (alloc) *alloc = 0;
9166
22
        *len = last - start;
9167
22
        ret = (xmlChar *) start;
9168
22
    } else {
9169
0
        if (alloc) *alloc = 1;
9170
0
        ret = xmlStrndup(start, last - start);
9171
0
    }
9172
22
    CUR_PTR = in;
9173
22
    ctxt->input->line = line;
9174
22
    ctxt->input->col = col;
9175
22
    return ret;
9176
2
need_complex:
9177
2
    if (alloc) *alloc = 1;
9178
2
    return xmlParseAttValueComplex(ctxt, len, normalize);
9179
24
}
9180
9181
/**
9182
 * xmlParseAttribute2:
9183
 * @ctxt:  an XML parser context
9184
 * @pref:  the element prefix
9185
 * @elem:  the element name
9186
 * @prefix:  a xmlChar ** used to store the value of the attribute prefix
9187
 * @value:  a xmlChar ** used to store the value of the attribute
9188
 * @len:  an int * to save the length of the attribute
9189
 * @alloc:  an int * to indicate if the attribute was allocated
9190
 *
9191
 * parse an attribute in the new SAX2 framework.
9192
 *
9193
 * Returns the attribute name, and the value in *value, .
9194
 */
9195
9196
static const xmlChar *
9197
xmlParseAttribute2(xmlParserCtxtPtr ctxt,
9198
                   const xmlChar * pref, const xmlChar * elem,
9199
                   const xmlChar ** prefix, xmlChar ** value,
9200
                   int *len, int *alloc)
9201
24
{
9202
24
    const xmlChar *name;
9203
24
    xmlChar *val, *internal_val = NULL;
9204
24
    int normalize = 0;
9205
9206
24
    *value = NULL;
9207
24
    GROW;
9208
24
    name = xmlParseQName(ctxt, prefix);
9209
24
    if (name == NULL) {
9210
0
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
9211
0
                       "error parsing attribute name\n");
9212
0
        return (NULL);
9213
0
    }
9214
9215
    /*
9216
     * get the type if needed
9217
     */
9218
24
    if (ctxt->attsSpecial != NULL) {
9219
0
        int type;
9220
9221
0
        type = (int) (ptrdiff_t) xmlHashQLookup2(ctxt->attsSpecial,
9222
0
                                                 pref, elem, *prefix, name);
9223
0
        if (type != 0)
9224
0
            normalize = 1;
9225
0
    }
9226
9227
    /*
9228
     * read the value
9229
     */
9230
24
    SKIP_BLANKS;
9231
24
    if (RAW == '=') {
9232
24
        NEXT;
9233
24
        SKIP_BLANKS;
9234
24
        val = xmlParseAttValueInternal(ctxt, len, alloc, normalize);
9235
24
  if (normalize) {
9236
      /*
9237
       * Sometimes a second normalisation pass for spaces is needed
9238
       * but that only happens if charrefs or entities references
9239
       * have been used in the attribute value, i.e. the attribute
9240
       * value have been extracted in an allocated string already.
9241
       */
9242
0
      if (*alloc) {
9243
0
          const xmlChar *val2;
9244
9245
0
          val2 = xmlAttrNormalizeSpace2(ctxt, val, len);
9246
0
    if ((val2 != NULL) && (val2 != val)) {
9247
0
        xmlFree(val);
9248
0
        val = (xmlChar *) val2;
9249
0
    }
9250
0
      }
9251
0
  }
9252
24
        ctxt->instate = XML_PARSER_CONTENT;
9253
24
    } else {
9254
0
        xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
9255
0
                          "Specification mandates value for attribute %s\n",
9256
0
                          name);
9257
0
        return (NULL);
9258
0
    }
9259
9260
24
    if (*prefix == ctxt->str_xml) {
9261
        /*
9262
         * Check that xml:lang conforms to the specification
9263
         * No more registered as an error, just generate a warning now
9264
         * since this was deprecated in XML second edition
9265
         */
9266
0
        if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "lang"))) {
9267
0
            internal_val = xmlStrndup(val, *len);
9268
0
            if (!xmlCheckLanguageID(internal_val)) {
9269
0
                xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
9270
0
                              "Malformed value for xml:lang : %s\n",
9271
0
                              internal_val, NULL);
9272
0
            }
9273
0
        }
9274
9275
        /*
9276
         * Check that xml:space conforms to the specification
9277
         */
9278
0
        if (xmlStrEqual(name, BAD_CAST "space")) {
9279
0
            internal_val = xmlStrndup(val, *len);
9280
0
            if (xmlStrEqual(internal_val, BAD_CAST "default"))
9281
0
                *(ctxt->space) = 0;
9282
0
            else if (xmlStrEqual(internal_val, BAD_CAST "preserve"))
9283
0
                *(ctxt->space) = 1;
9284
0
            else {
9285
0
                xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
9286
0
                              "Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
9287
0
                              internal_val, NULL);
9288
0
            }
9289
0
        }
9290
0
        if (internal_val) {
9291
0
            xmlFree(internal_val);
9292
0
        }
9293
0
    }
9294
9295
24
    *value = val;
9296
24
    return (name);
9297
24
}
9298
/**
9299
 * xmlParseStartTag2:
9300
 * @ctxt:  an XML parser context
9301
 *
9302
 * parse a start of tag either for rule element or
9303
 * EmptyElement. In both case we don't parse the tag closing chars.
9304
 * This routine is called when running SAX2 parsing
9305
 *
9306
 * [40] STag ::= '<' Name (S Attribute)* S? '>'
9307
 *
9308
 * [ WFC: Unique Att Spec ]
9309
 * No attribute name may appear more than once in the same start-tag or
9310
 * empty-element tag.
9311
 *
9312
 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
9313
 *
9314
 * [ WFC: Unique Att Spec ]
9315
 * No attribute name may appear more than once in the same start-tag or
9316
 * empty-element tag.
9317
 *
9318
 * With namespace:
9319
 *
9320
 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
9321
 *
9322
 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
9323
 *
9324
 * Returns the element name parsed
9325
 */
9326
9327
static const xmlChar *
9328
xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
9329
24
                  const xmlChar **URI, int *tlen) {
9330
24
    const xmlChar *localname;
9331
24
    const xmlChar *prefix;
9332
24
    const xmlChar *attname;
9333
24
    const xmlChar *aprefix;
9334
24
    const xmlChar *nsname;
9335
24
    xmlChar *attvalue;
9336
24
    const xmlChar **atts = ctxt->atts;
9337
24
    int maxatts = ctxt->maxatts;
9338
24
    int nratts, nbatts, nbdef, inputid;
9339
24
    int i, j, nbNs, attval;
9340
24
    unsigned long cur;
9341
24
    int nsNr = ctxt->nsNr;
9342
9343
24
    if (RAW != '<') return(NULL);
9344
24
    NEXT1;
9345
9346
    /*
9347
     * NOTE: it is crucial with the SAX2 API to never call SHRINK beyond that
9348
     *       point since the attribute values may be stored as pointers to
9349
     *       the buffer and calling SHRINK would destroy them !
9350
     *       The Shrinking is only possible once the full set of attribute
9351
     *       callbacks have been done.
9352
     */
9353
24
    SHRINK;
9354
24
    cur = ctxt->input->cur - ctxt->input->base;
9355
24
    inputid = ctxt->input->id;
9356
24
    nbatts = 0;
9357
24
    nratts = 0;
9358
24
    nbdef = 0;
9359
24
    nbNs = 0;
9360
24
    attval = 0;
9361
    /* Forget any namespaces added during an earlier parse of this element. */
9362
24
    ctxt->nsNr = nsNr;
9363
9364
24
    localname = xmlParseQName(ctxt, &prefix);
9365
24
    if (localname == NULL) {
9366
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
9367
0
           "StartTag: invalid element name\n");
9368
0
        return(NULL);
9369
0
    }
9370
24
    *tlen = ctxt->input->cur - ctxt->input->base - cur;
9371
9372
    /*
9373
     * Now parse the attributes, it ends up with the ending
9374
     *
9375
     * (S Attribute)* S?
9376
     */
9377
24
    SKIP_BLANKS;
9378
24
    GROW;
9379
9380
30
    while (((RAW != '>') &&
9381
30
     ((RAW != '/') || (NXT(1) != '>')) &&
9382
30
     (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) {
9383
24
  int id = ctxt->input->id;
9384
24
  unsigned long cons = CUR_CONSUMED;
9385
24
  int len = -1, alloc = 0;
9386
9387
24
  attname = xmlParseAttribute2(ctxt, prefix, localname,
9388
24
                               &aprefix, &attvalue, &len, &alloc);
9389
24
        if ((attname == NULL) || (attvalue == NULL))
9390
0
            goto next_attr;
9391
24
  if (len < 0) len = xmlStrlen(attvalue);
9392
9393
24
        if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
9394
0
            const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
9395
0
            xmlURIPtr uri;
9396
9397
0
            if (URL == NULL) {
9398
0
                xmlErrMemory(ctxt, "dictionary allocation failure");
9399
0
                if ((attvalue != NULL) && (alloc != 0))
9400
0
                    xmlFree(attvalue);
9401
0
                localname = NULL;
9402
0
                goto done;
9403
0
            }
9404
0
            if (*URL != 0) {
9405
0
                uri = xmlParseURI((const char *) URL);
9406
0
                if (uri == NULL) {
9407
0
                    xmlNsErr(ctxt, XML_WAR_NS_URI,
9408
0
                             "xmlns: '%s' is not a valid URI\n",
9409
0
                                       URL, NULL, NULL);
9410
0
                } else {
9411
0
                    if (uri->scheme == NULL) {
9412
0
                        xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
9413
0
                                  "xmlns: URI %s is not absolute\n",
9414
0
                                  URL, NULL, NULL);
9415
0
                    }
9416
0
                    xmlFreeURI(uri);
9417
0
                }
9418
0
                if (URL == ctxt->str_xml_ns) {
9419
0
                    if (attname != ctxt->str_xml) {
9420
0
                        xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9421
0
                     "xml namespace URI cannot be the default namespace\n",
9422
0
                                 NULL, NULL, NULL);
9423
0
                    }
9424
0
                    goto next_attr;
9425
0
                }
9426
0
                if ((len == 29) &&
9427
0
                    (xmlStrEqual(URL,
9428
0
                             BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
9429
0
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9430
0
                         "reuse of the xmlns namespace name is forbidden\n",
9431
0
                             NULL, NULL, NULL);
9432
0
                    goto next_attr;
9433
0
                }
9434
0
            }
9435
            /*
9436
             * check that it's not a defined namespace
9437
             */
9438
0
            for (j = 1;j <= nbNs;j++)
9439
0
                if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
9440
0
                    break;
9441
0
            if (j <= nbNs)
9442
0
                xmlErrAttributeDup(ctxt, NULL, attname);
9443
0
            else
9444
0
                if (nsPush(ctxt, NULL, URL) > 0) nbNs++;
9445
9446
24
        } else if (aprefix == ctxt->str_xmlns) {
9447
6
            const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
9448
6
            xmlURIPtr uri;
9449
9450
6
            if (attname == ctxt->str_xml) {
9451
0
                if (URL != ctxt->str_xml_ns) {
9452
0
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9453
0
                             "xml namespace prefix mapped to wrong URI\n",
9454
0
                             NULL, NULL, NULL);
9455
0
                }
9456
                /*
9457
                 * Do not keep a namespace definition node
9458
                 */
9459
0
                goto next_attr;
9460
0
            }
9461
6
            if (URL == ctxt->str_xml_ns) {
9462
0
                if (attname != ctxt->str_xml) {
9463
0
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9464
0
                             "xml namespace URI mapped to wrong prefix\n",
9465
0
                             NULL, NULL, NULL);
9466
0
                }
9467
0
                goto next_attr;
9468
0
            }
9469
6
            if (attname == ctxt->str_xmlns) {
9470
0
                xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9471
0
                         "redefinition of the xmlns prefix is forbidden\n",
9472
0
                         NULL, NULL, NULL);
9473
0
                goto next_attr;
9474
0
            }
9475
6
            if ((len == 29) &&
9476
6
                (xmlStrEqual(URL,
9477
0
                             BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
9478
0
                xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9479
0
                         "reuse of the xmlns namespace name is forbidden\n",
9480
0
                         NULL, NULL, NULL);
9481
0
                goto next_attr;
9482
0
            }
9483
6
            if ((URL == NULL) || (URL[0] == 0)) {
9484
0
                xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9485
0
                         "xmlns:%s: Empty XML namespace is not allowed\n",
9486
0
                              attname, NULL, NULL);
9487
0
                goto next_attr;
9488
6
            } else {
9489
6
                uri = xmlParseURI((const char *) URL);
9490
6
                if (uri == NULL) {
9491
0
                    xmlNsErr(ctxt, XML_WAR_NS_URI,
9492
0
                         "xmlns:%s: '%s' is not a valid URI\n",
9493
0
                                       attname, URL, NULL);
9494
6
                } else {
9495
6
                    if ((ctxt->pedantic) && (uri->scheme == NULL)) {
9496
0
                        xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
9497
0
                                  "xmlns:%s: URI %s is not absolute\n",
9498
0
                                  attname, URL, NULL);
9499
0
                    }
9500
6
                    xmlFreeURI(uri);
9501
6
                }
9502
6
            }
9503
9504
            /*
9505
             * check that it's not a defined namespace
9506
             */
9507
6
            for (j = 1;j <= nbNs;j++)
9508
0
                if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
9509
0
                    break;
9510
6
            if (j <= nbNs)
9511
0
                xmlErrAttributeDup(ctxt, aprefix, attname);
9512
6
            else
9513
6
                if (nsPush(ctxt, attname, URL) > 0) nbNs++;
9514
9515
18
        } else {
9516
            /*
9517
             * Add the pair to atts
9518
             */
9519
18
            if ((atts == NULL) || (nbatts + 5 > maxatts)) {
9520
2
                if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
9521
0
                    goto next_attr;
9522
0
                }
9523
2
                maxatts = ctxt->maxatts;
9524
2
                atts = ctxt->atts;
9525
2
            }
9526
18
            ctxt->attallocs[nratts++] = alloc;
9527
18
            atts[nbatts++] = attname;
9528
18
            atts[nbatts++] = aprefix;
9529
            /*
9530
             * The namespace URI field is used temporarily to point at the
9531
             * base of the current input buffer for non-alloced attributes.
9532
             * When the input buffer is reallocated, all the pointers become
9533
             * invalid, but they can be reconstructed later.
9534
             */
9535
18
            if (alloc)
9536
2
                atts[nbatts++] = NULL;
9537
16
            else
9538
16
                atts[nbatts++] = ctxt->input->base;
9539
18
            atts[nbatts++] = attvalue;
9540
18
            attvalue += len;
9541
18
            atts[nbatts++] = attvalue;
9542
            /*
9543
             * tag if some deallocation is needed
9544
             */
9545
18
            if (alloc != 0) attval = 1;
9546
18
            attvalue = NULL; /* moved into atts */
9547
18
        }
9548
9549
24
next_attr:
9550
24
        if ((attvalue != NULL) && (alloc != 0)) {
9551
0
            xmlFree(attvalue);
9552
0
            attvalue = NULL;
9553
0
        }
9554
9555
24
  GROW
9556
24
        if (ctxt->instate == XML_PARSER_EOF)
9557
0
            break;
9558
24
  if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
9559
18
      break;
9560
6
  if (SKIP_BLANKS == 0) {
9561
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
9562
0
         "attributes construct error\n");
9563
0
      break;
9564
0
  }
9565
6
        if ((cons == CUR_CONSUMED) && (id == ctxt->input->id) &&
9566
6
            (attname == NULL) && (attvalue == NULL)) {
9567
0
      xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
9568
0
           "xmlParseStartTag: problem parsing attributes\n");
9569
0
      break;
9570
0
  }
9571
6
        GROW;
9572
6
    }
9573
9574
24
    if (ctxt->input->id != inputid) {
9575
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
9576
0
                    "Unexpected change of input\n");
9577
0
        localname = NULL;
9578
0
        goto done;
9579
0
    }
9580
9581
    /* Reconstruct attribute value pointers. */
9582
42
    for (i = 0, j = 0; j < nratts; i += 5, j++) {
9583
18
        if (atts[i+2] != NULL) {
9584
            /*
9585
             * Arithmetic on dangling pointers is technically undefined
9586
             * behavior, but well...
9587
             */
9588
16
            ptrdiff_t offset = ctxt->input->base - atts[i+2];
9589
16
            atts[i+2]  = NULL;    /* Reset repurposed namespace URI */
9590
16
            atts[i+3] += offset;  /* value */
9591
16
            atts[i+4] += offset;  /* valuend */
9592
16
        }
9593
18
    }
9594
9595
    /*
9596
     * The attributes defaulting
9597
     */
9598
24
    if (ctxt->attsDefault != NULL) {
9599
0
        xmlDefAttrsPtr defaults;
9600
9601
0
  defaults = xmlHashLookup2(ctxt->attsDefault, localname, prefix);
9602
0
  if (defaults != NULL) {
9603
0
      for (i = 0;i < defaults->nbAttrs;i++) {
9604
0
          attname = defaults->values[5 * i];
9605
0
    aprefix = defaults->values[5 * i + 1];
9606
9607
                /*
9608
     * special work for namespaces defaulted defs
9609
     */
9610
0
    if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
9611
        /*
9612
         * check that it's not a defined namespace
9613
         */
9614
0
        for (j = 1;j <= nbNs;j++)
9615
0
            if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
9616
0
          break;
9617
0
              if (j <= nbNs) continue;
9618
9619
0
        nsname = xmlGetNamespace(ctxt, NULL);
9620
0
        if (nsname != defaults->values[5 * i + 2]) {
9621
0
      if (nsPush(ctxt, NULL,
9622
0
                 defaults->values[5 * i + 2]) > 0)
9623
0
          nbNs++;
9624
0
        }
9625
0
    } else if (aprefix == ctxt->str_xmlns) {
9626
        /*
9627
         * check that it's not a defined namespace
9628
         */
9629
0
        for (j = 1;j <= nbNs;j++)
9630
0
            if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
9631
0
          break;
9632
0
              if (j <= nbNs) continue;
9633
9634
0
        nsname = xmlGetNamespace(ctxt, attname);
9635
0
        if (nsname != defaults->values[2]) {
9636
0
      if (nsPush(ctxt, attname,
9637
0
                 defaults->values[5 * i + 2]) > 0)
9638
0
          nbNs++;
9639
0
        }
9640
0
    } else {
9641
        /*
9642
         * check that it's not a defined attribute
9643
         */
9644
0
        for (j = 0;j < nbatts;j+=5) {
9645
0
      if ((attname == atts[j]) && (aprefix == atts[j+1]))
9646
0
          break;
9647
0
        }
9648
0
        if (j < nbatts) continue;
9649
9650
0
        if ((atts == NULL) || (nbatts + 5 > maxatts)) {
9651
0
      if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
9652
0
                            localname = NULL;
9653
0
                            goto done;
9654
0
      }
9655
0
      maxatts = ctxt->maxatts;
9656
0
      atts = ctxt->atts;
9657
0
        }
9658
0
        atts[nbatts++] = attname;
9659
0
        atts[nbatts++] = aprefix;
9660
0
        if (aprefix == NULL)
9661
0
      atts[nbatts++] = NULL;
9662
0
        else
9663
0
            atts[nbatts++] = xmlGetNamespace(ctxt, aprefix);
9664
0
        atts[nbatts++] = defaults->values[5 * i + 2];
9665
0
        atts[nbatts++] = defaults->values[5 * i + 3];
9666
0
        if ((ctxt->standalone == 1) &&
9667
0
            (defaults->values[5 * i + 4] != NULL)) {
9668
0
      xmlValidityError(ctxt, XML_DTD_STANDALONE_DEFAULTED,
9669
0
    "standalone: attribute %s on %s defaulted from external subset\n",
9670
0
                                   attname, localname);
9671
0
        }
9672
0
        nbdef++;
9673
0
    }
9674
0
      }
9675
0
  }
9676
0
    }
9677
9678
    /*
9679
     * The attributes checkings
9680
     */
9681
42
    for (i = 0; i < nbatts;i += 5) {
9682
        /*
9683
  * The default namespace does not apply to attribute names.
9684
  */
9685
18
  if (atts[i + 1] != NULL) {
9686
0
      nsname = xmlGetNamespace(ctxt, atts[i + 1]);
9687
0
      if (nsname == NULL) {
9688
0
    xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
9689
0
        "Namespace prefix %s for %s on %s is not defined\n",
9690
0
        atts[i + 1], atts[i], localname);
9691
0
      }
9692
0
      atts[i + 2] = nsname;
9693
0
  } else
9694
18
      nsname = NULL;
9695
  /*
9696
   * [ WFC: Unique Att Spec ]
9697
   * No attribute name may appear more than once in the same
9698
   * start-tag or empty-element tag.
9699
   * As extended by the Namespace in XML REC.
9700
   */
9701
20
        for (j = 0; j < i;j += 5) {
9702
2
      if (atts[i] == atts[j]) {
9703
0
          if (atts[i+1] == atts[j+1]) {
9704
0
        xmlErrAttributeDup(ctxt, atts[i+1], atts[i]);
9705
0
        break;
9706
0
    }
9707
0
    if ((nsname != NULL) && (atts[j + 2] == nsname)) {
9708
0
        xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED,
9709
0
           "Namespaced Attribute %s in '%s' redefined\n",
9710
0
           atts[i], nsname, NULL);
9711
0
        break;
9712
0
    }
9713
0
      }
9714
2
  }
9715
18
    }
9716
9717
24
    nsname = xmlGetNamespace(ctxt, prefix);
9718
24
    if ((prefix != NULL) && (nsname == NULL)) {
9719
0
  xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
9720
0
           "Namespace prefix %s on %s is not defined\n",
9721
0
     prefix, localname, NULL);
9722
0
    }
9723
24
    *pref = prefix;
9724
24
    *URI = nsname;
9725
9726
    /*
9727
     * SAX: Start of Element !
9728
     */
9729
24
    if ((ctxt->sax != NULL) && (ctxt->sax->startElementNs != NULL) &&
9730
24
  (!ctxt->disableSAX)) {
9731
24
  if (nbNs > 0)
9732
6
      ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
9733
6
        nsname, nbNs, &ctxt->nsTab[ctxt->nsNr - 2 * nbNs],
9734
6
        nbatts / 5, nbdef, atts);
9735
18
  else
9736
18
      ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
9737
18
                    nsname, 0, NULL, nbatts / 5, nbdef, atts);
9738
24
    }
9739
9740
24
done:
9741
    /*
9742
     * Free up attribute allocated strings if needed
9743
     */
9744
24
    if (attval != 0) {
9745
4
  for (i = 3,j = 0; j < nratts;i += 5,j++)
9746
2
      if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
9747
2
          xmlFree((xmlChar *) atts[i]);
9748
2
    }
9749
9750
24
    return(localname);
9751
24
}
9752
9753
/**
9754
 * xmlParseEndTag2:
9755
 * @ctxt:  an XML parser context
9756
 * @line:  line of the start tag
9757
 * @nsNr:  number of namespaces on the start tag
9758
 *
9759
 * parse an end of tag
9760
 *
9761
 * [42] ETag ::= '</' Name S? '>'
9762
 *
9763
 * With namespace
9764
 *
9765
 * [NS 9] ETag ::= '</' QName S? '>'
9766
 */
9767
9768
static void
9769
18
xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlStartTag *tag) {
9770
18
    const xmlChar *name;
9771
9772
18
    GROW;
9773
18
    if ((RAW != '<') || (NXT(1) != '/')) {
9774
0
  xmlFatalErr(ctxt, XML_ERR_LTSLASH_REQUIRED, NULL);
9775
0
  return;
9776
0
    }
9777
18
    SKIP(2);
9778
9779
18
    if (tag->prefix == NULL)
9780
8
        name = xmlParseNameAndCompare(ctxt, ctxt->name);
9781
10
    else
9782
10
        name = xmlParseQNameAndCompare(ctxt, ctxt->name, tag->prefix);
9783
9784
    /*
9785
     * We should definitely be at the ending "S? '>'" part
9786
     */
9787
18
    GROW;
9788
18
    if (ctxt->instate == XML_PARSER_EOF)
9789
0
        return;
9790
18
    SKIP_BLANKS;
9791
18
    if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
9792
0
  xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
9793
0
    } else
9794
18
  NEXT1;
9795
9796
    /*
9797
     * [ WFC: Element Type Match ]
9798
     * The Name in an element's end-tag must match the element type in the
9799
     * start-tag.
9800
     *
9801
     */
9802
18
    if (name != (xmlChar*)1) {
9803
0
        if (name == NULL) name = BAD_CAST "unparsable";
9804
0
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
9805
0
         "Opening and ending tag mismatch: %s line %d and %s\n",
9806
0
                    ctxt->name, tag->line, name);
9807
0
    }
9808
9809
    /*
9810
     * SAX: End of Tag
9811
     */
9812
18
    if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
9813
18
  (!ctxt->disableSAX))
9814
18
  ctxt->sax->endElementNs(ctxt->userData, ctxt->name, tag->prefix,
9815
18
                                tag->URI);
9816
9817
18
    spacePop(ctxt);
9818
18
    if (tag->nsNr != 0)
9819
6
  nsPop(ctxt, tag->nsNr);
9820
18
}
9821
9822
/**
9823
 * xmlParseCDSect:
9824
 * @ctxt:  an XML parser context
9825
 *
9826
 * DEPRECATED: Internal function, don't use.
9827
 *
9828
 * Parse escaped pure raw content.
9829
 *
9830
 * [18] CDSect ::= CDStart CData CDEnd
9831
 *
9832
 * [19] CDStart ::= '<![CDATA['
9833
 *
9834
 * [20] Data ::= (Char* - (Char* ']]>' Char*))
9835
 *
9836
 * [21] CDEnd ::= ']]>'
9837
 */
9838
void
9839
2
xmlParseCDSect(xmlParserCtxtPtr ctxt) {
9840
2
    xmlChar *buf = NULL;
9841
2
    int len = 0;
9842
2
    int size = XML_PARSER_BUFFER_SIZE;
9843
2
    int r, rl;
9844
2
    int s, sl;
9845
2
    int cur, l;
9846
2
    int count = 0;
9847
2
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
9848
0
                    XML_MAX_HUGE_LENGTH :
9849
2
                    XML_MAX_TEXT_LENGTH;
9850
9851
    /* Check 2.6.0 was NXT(0) not RAW */
9852
2
    if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
9853
2
  SKIP(9);
9854
2
    } else
9855
0
        return;
9856
9857
2
    ctxt->instate = XML_PARSER_CDATA_SECTION;
9858
2
    r = CUR_CHAR(rl);
9859
2
    if (!IS_CHAR(r)) {
9860
0
  xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
9861
0
  ctxt->instate = XML_PARSER_CONTENT;
9862
0
        return;
9863
0
    }
9864
2
    NEXTL(rl);
9865
2
    s = CUR_CHAR(sl);
9866
2
    if (!IS_CHAR(s)) {
9867
0
  xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
9868
0
  ctxt->instate = XML_PARSER_CONTENT;
9869
0
        return;
9870
0
    }
9871
2
    NEXTL(sl);
9872
2
    cur = CUR_CHAR(l);
9873
2
    buf = (xmlChar *) xmlMallocAtomic(size);
9874
2
    if (buf == NULL) {
9875
0
  xmlErrMemory(ctxt, NULL);
9876
0
  return;
9877
0
    }
9878
10
    while (IS_CHAR(cur) &&
9879
10
           ((r != ']') || (s != ']') || (cur != '>'))) {
9880
8
  if (len + 5 >= size) {
9881
0
      xmlChar *tmp;
9882
9883
0
      tmp = (xmlChar *) xmlRealloc(buf, size * 2);
9884
0
      if (tmp == NULL) {
9885
0
          xmlFree(buf);
9886
0
    xmlErrMemory(ctxt, NULL);
9887
0
    return;
9888
0
      }
9889
0
      buf = tmp;
9890
0
      size *= 2;
9891
0
  }
9892
8
  COPY_BUF(rl,buf,len,r);
9893
8
  r = s;
9894
8
  rl = sl;
9895
8
  s = cur;
9896
8
  sl = l;
9897
8
  count++;
9898
8
  if (count > 50) {
9899
0
      SHRINK;
9900
0
      GROW;
9901
0
            if (ctxt->instate == XML_PARSER_EOF) {
9902
0
    xmlFree(buf);
9903
0
    return;
9904
0
            }
9905
0
      count = 0;
9906
0
  }
9907
8
  NEXTL(l);
9908
8
  cur = CUR_CHAR(l);
9909
8
        if (len > maxLength) {
9910
0
            xmlFatalErrMsg(ctxt, XML_ERR_CDATA_NOT_FINISHED,
9911
0
                           "CData section too big found\n");
9912
0
            xmlFree(buf);
9913
0
            return;
9914
0
        }
9915
8
    }
9916
2
    buf[len] = 0;
9917
2
    ctxt->instate = XML_PARSER_CONTENT;
9918
2
    if (cur != '>') {
9919
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED,
9920
0
                       "CData section not finished\n%.50s\n", buf);
9921
0
  xmlFree(buf);
9922
0
        return;
9923
0
    }
9924
2
    NEXTL(l);
9925
9926
    /*
9927
     * OK the buffer is to be consumed as cdata.
9928
     */
9929
2
    if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
9930
2
  if (ctxt->sax->cdataBlock != NULL)
9931
2
      ctxt->sax->cdataBlock(ctxt->userData, buf, len);
9932
0
  else if (ctxt->sax->characters != NULL)
9933
0
      ctxt->sax->characters(ctxt->userData, buf, len);
9934
2
    }
9935
2
    xmlFree(buf);
9936
2
}
9937
9938
/**
9939
 * xmlParseContentInternal:
9940
 * @ctxt:  an XML parser context
9941
 *
9942
 * Parse a content sequence. Stops at EOF or '</'. Leaves checking of
9943
 * unexpected EOF to the caller.
9944
 */
9945
9946
static void
9947
2
xmlParseContentInternal(xmlParserCtxtPtr ctxt) {
9948
2
    int nameNr = ctxt->nameNr;
9949
9950
2
    GROW;
9951
94
    while ((RAW != 0) &&
9952
94
     (ctxt->instate != XML_PARSER_EOF)) {
9953
94
        int id = ctxt->input->id;
9954
94
  unsigned long cons = CUR_CONSUMED;
9955
94
  const xmlChar *cur = ctxt->input->cur;
9956
9957
  /*
9958
   * First case : a Processing Instruction.
9959
   */
9960
94
  if ((*cur == '<') && (cur[1] == '?')) {
9961
2
      xmlParsePI(ctxt);
9962
2
  }
9963
9964
  /*
9965
   * Second case : a CDSection
9966
   */
9967
  /* 2.6.0 test was *cur not RAW */
9968
92
  else if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
9969
2
      xmlParseCDSect(ctxt);
9970
2
  }
9971
9972
  /*
9973
   * Third case :  a comment
9974
   */
9975
90
  else if ((*cur == '<') && (NXT(1) == '!') &&
9976
90
     (NXT(2) == '-') && (NXT(3) == '-')) {
9977
4
      xmlParseComment(ctxt);
9978
4
      ctxt->instate = XML_PARSER_CONTENT;
9979
4
  }
9980
9981
  /*
9982
   * Fourth case :  a sub-element.
9983
   */
9984
86
  else if (*cur == '<') {
9985
40
            if (NXT(1) == '/') {
9986
18
                if (ctxt->nameNr <= nameNr)
9987
2
                    break;
9988
16
          xmlParseElementEnd(ctxt);
9989
22
            } else {
9990
22
          xmlParseElementStart(ctxt);
9991
22
            }
9992
40
  }
9993
9994
  /*
9995
   * Fifth case : a reference. If if has not been resolved,
9996
   *    parsing returns it's Name, create the node
9997
   */
9998
9999
46
  else if (*cur == '&') {
10000
2
      xmlParseReference(ctxt);
10001
2
  }
10002
10003
  /*
10004
   * Last case, text. Note that References are handled directly.
10005
   */
10006
44
  else {
10007
44
      xmlParseCharData(ctxt, 0);
10008
44
  }
10009
10010
92
  GROW;
10011
92
  SHRINK;
10012
10013
92
  if ((cons == CUR_CONSUMED) && (id == ctxt->input->id)) {
10014
0
      xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
10015
0
                  "detected an error in element content\n");
10016
0
      xmlHaltParser(ctxt);
10017
0
            break;
10018
0
  }
10019
92
    }
10020
2
}
10021
10022
/**
10023
 * xmlParseContent:
10024
 * @ctxt:  an XML parser context
10025
 *
10026
 * Parse a content sequence. Stops at EOF or '</'.
10027
 *
10028
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
10029
 */
10030
10031
void
10032
0
xmlParseContent(xmlParserCtxtPtr ctxt) {
10033
0
    int nameNr = ctxt->nameNr;
10034
10035
0
    xmlParseContentInternal(ctxt);
10036
10037
0
    if ((ctxt->instate != XML_PARSER_EOF) && (ctxt->nameNr > nameNr)) {
10038
0
        const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
10039
0
        int line = ctxt->pushTab[ctxt->nameNr - 1].line;
10040
0
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
10041
0
                "Premature end of data in tag %s line %d\n",
10042
0
    name, line, NULL);
10043
0
    }
10044
0
}
10045
10046
/**
10047
 * xmlParseElement:
10048
 * @ctxt:  an XML parser context
10049
 *
10050
 * DEPRECATED: Internal function, don't use.
10051
 *
10052
 * parse an XML element
10053
 *
10054
 * [39] element ::= EmptyElemTag | STag content ETag
10055
 *
10056
 * [ WFC: Element Type Match ]
10057
 * The Name in an element's end-tag must match the element type in the
10058
 * start-tag.
10059
 *
10060
 */
10061
10062
void
10063
2
xmlParseElement(xmlParserCtxtPtr ctxt) {
10064
2
    if (xmlParseElementStart(ctxt) != 0)
10065
0
        return;
10066
10067
2
    xmlParseContentInternal(ctxt);
10068
2
    if (ctxt->instate == XML_PARSER_EOF)
10069
0
  return;
10070
10071
2
    if (CUR == 0) {
10072
0
        const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
10073
0
        int line = ctxt->pushTab[ctxt->nameNr - 1].line;
10074
0
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
10075
0
                "Premature end of data in tag %s line %d\n",
10076
0
    name, line, NULL);
10077
0
        return;
10078
0
    }
10079
10080
2
    xmlParseElementEnd(ctxt);
10081
2
}
10082
10083
/**
10084
 * xmlParseElementStart:
10085
 * @ctxt:  an XML parser context
10086
 *
10087
 * Parse the start of an XML element. Returns -1 in case of error, 0 if an
10088
 * opening tag was parsed, 1 if an empty element was parsed.
10089
 */
10090
static int
10091
24
xmlParseElementStart(xmlParserCtxtPtr ctxt) {
10092
24
    const xmlChar *name;
10093
24
    const xmlChar *prefix = NULL;
10094
24
    const xmlChar *URI = NULL;
10095
24
    xmlParserNodeInfo node_info;
10096
24
    int line, tlen = 0;
10097
24
    xmlNodePtr ret;
10098
24
    int nsNr = ctxt->nsNr;
10099
10100
24
    if (((unsigned int) ctxt->nameNr > xmlParserMaxDepth) &&
10101
24
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
10102
0
  xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
10103
0
     "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
10104
0
        xmlParserMaxDepth);
10105
0
  xmlHaltParser(ctxt);
10106
0
  return(-1);
10107
0
    }
10108
10109
    /* Capture start position */
10110
24
    if (ctxt->record_info) {
10111
0
        node_info.begin_pos = ctxt->input->consumed +
10112
0
                          (CUR_PTR - ctxt->input->base);
10113
0
  node_info.begin_line = ctxt->input->line;
10114
0
    }
10115
10116
24
    if (ctxt->spaceNr == 0)
10117
0
  spacePush(ctxt, -1);
10118
24
    else if (*ctxt->space == -2)
10119
0
  spacePush(ctxt, -1);
10120
24
    else
10121
24
  spacePush(ctxt, *ctxt->space);
10122
10123
24
    line = ctxt->input->line;
10124
#ifdef LIBXML_SAX1_ENABLED
10125
    if (ctxt->sax2)
10126
#endif /* LIBXML_SAX1_ENABLED */
10127
24
        name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
10128
#ifdef LIBXML_SAX1_ENABLED
10129
    else
10130
  name = xmlParseStartTag(ctxt);
10131
#endif /* LIBXML_SAX1_ENABLED */
10132
24
    if (ctxt->instate == XML_PARSER_EOF)
10133
0
  return(-1);
10134
24
    if (name == NULL) {
10135
0
  spacePop(ctxt);
10136
0
        return(-1);
10137
0
    }
10138
24
    nameNsPush(ctxt, name, prefix, URI, line, ctxt->nsNr - nsNr);
10139
24
    ret = ctxt->node;
10140
10141
#ifdef LIBXML_VALID_ENABLED
10142
    /*
10143
     * [ VC: Root Element Type ]
10144
     * The Name in the document type declaration must match the element
10145
     * type of the root element.
10146
     */
10147
    if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
10148
        ctxt->node && (ctxt->node == ctxt->myDoc->children))
10149
        ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
10150
#endif /* LIBXML_VALID_ENABLED */
10151
10152
    /*
10153
     * Check for an Empty Element.
10154
     */
10155
24
    if ((RAW == '/') && (NXT(1) == '>')) {
10156
6
        SKIP(2);
10157
6
  if (ctxt->sax2) {
10158
6
      if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
10159
6
    (!ctxt->disableSAX))
10160
6
    ctxt->sax->endElementNs(ctxt->userData, name, prefix, URI);
10161
#ifdef LIBXML_SAX1_ENABLED
10162
  } else {
10163
      if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
10164
    (!ctxt->disableSAX))
10165
    ctxt->sax->endElement(ctxt->userData, name);
10166
#endif /* LIBXML_SAX1_ENABLED */
10167
6
  }
10168
6
  namePop(ctxt);
10169
6
  spacePop(ctxt);
10170
6
  if (nsNr != ctxt->nsNr)
10171
0
      nsPop(ctxt, ctxt->nsNr - nsNr);
10172
6
  if ( ret != NULL && ctxt->record_info ) {
10173
0
     node_info.end_pos = ctxt->input->consumed +
10174
0
            (CUR_PTR - ctxt->input->base);
10175
0
     node_info.end_line = ctxt->input->line;
10176
0
     node_info.node = ret;
10177
0
     xmlParserAddNodeInfo(ctxt, &node_info);
10178
0
  }
10179
6
  return(1);
10180
6
    }
10181
18
    if (RAW == '>') {
10182
18
        NEXT1;
10183
18
    } else {
10184
0
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_GT_REQUIRED,
10185
0
         "Couldn't find end of Start Tag %s line %d\n",
10186
0
                    name, line, NULL);
10187
10188
  /*
10189
   * end of parsing of this node.
10190
   */
10191
0
  nodePop(ctxt);
10192
0
  namePop(ctxt);
10193
0
  spacePop(ctxt);
10194
0
  if (nsNr != ctxt->nsNr)
10195
0
      nsPop(ctxt, ctxt->nsNr - nsNr);
10196
10197
  /*
10198
   * Capture end position and add node
10199
   */
10200
0
  if ( ret != NULL && ctxt->record_info ) {
10201
0
     node_info.end_pos = ctxt->input->consumed +
10202
0
            (CUR_PTR - ctxt->input->base);
10203
0
     node_info.end_line = ctxt->input->line;
10204
0
     node_info.node = ret;
10205
0
     xmlParserAddNodeInfo(ctxt, &node_info);
10206
0
  }
10207
0
  return(-1);
10208
0
    }
10209
10210
18
    return(0);
10211
18
}
10212
10213
/**
10214
 * xmlParseElementEnd:
10215
 * @ctxt:  an XML parser context
10216
 *
10217
 * Parse the end of an XML element.
10218
 */
10219
static void
10220
18
xmlParseElementEnd(xmlParserCtxtPtr ctxt) {
10221
18
    xmlParserNodeInfo node_info;
10222
18
    xmlNodePtr ret = ctxt->node;
10223
10224
18
    if (ctxt->nameNr <= 0)
10225
0
        return;
10226
10227
    /*
10228
     * parse the end of tag: '</' should be here.
10229
     */
10230
18
    if (ctxt->sax2) {
10231
18
  xmlParseEndTag2(ctxt, &ctxt->pushTab[ctxt->nameNr - 1]);
10232
18
  namePop(ctxt);
10233
18
    }
10234
#ifdef LIBXML_SAX1_ENABLED
10235
    else
10236
  xmlParseEndTag1(ctxt, 0);
10237
#endif /* LIBXML_SAX1_ENABLED */
10238
10239
    /*
10240
     * Capture end position and add node
10241
     */
10242
18
    if ( ret != NULL && ctxt->record_info ) {
10243
0
       node_info.end_pos = ctxt->input->consumed +
10244
0
                          (CUR_PTR - ctxt->input->base);
10245
0
       node_info.end_line = ctxt->input->line;
10246
0
       node_info.node = ret;
10247
0
       xmlParserAddNodeInfo(ctxt, &node_info);
10248
0
    }
10249
18
}
10250
10251
/**
10252
 * xmlParseVersionNum:
10253
 * @ctxt:  an XML parser context
10254
 *
10255
 * DEPRECATED: Internal function, don't use.
10256
 *
10257
 * parse the XML version value.
10258
 *
10259
 * [26] VersionNum ::= '1.' [0-9]+
10260
 *
10261
 * In practice allow [0-9].[0-9]+ at that level
10262
 *
10263
 * Returns the string giving the XML version number, or NULL
10264
 */
10265
xmlChar *
10266
0
xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
10267
0
    xmlChar *buf = NULL;
10268
0
    int len = 0;
10269
0
    int size = 10;
10270
0
    xmlChar cur;
10271
10272
0
    buf = (xmlChar *) xmlMallocAtomic(size);
10273
0
    if (buf == NULL) {
10274
0
  xmlErrMemory(ctxt, NULL);
10275
0
  return(NULL);
10276
0
    }
10277
0
    cur = CUR;
10278
0
    if (!((cur >= '0') && (cur <= '9'))) {
10279
0
  xmlFree(buf);
10280
0
  return(NULL);
10281
0
    }
10282
0
    buf[len++] = cur;
10283
0
    NEXT;
10284
0
    cur=CUR;
10285
0
    if (cur != '.') {
10286
0
  xmlFree(buf);
10287
0
  return(NULL);
10288
0
    }
10289
0
    buf[len++] = cur;
10290
0
    NEXT;
10291
0
    cur=CUR;
10292
0
    while ((cur >= '0') && (cur <= '9')) {
10293
0
  if (len + 1 >= size) {
10294
0
      xmlChar *tmp;
10295
10296
0
      size *= 2;
10297
0
      tmp = (xmlChar *) xmlRealloc(buf, size);
10298
0
      if (tmp == NULL) {
10299
0
          xmlFree(buf);
10300
0
    xmlErrMemory(ctxt, NULL);
10301
0
    return(NULL);
10302
0
      }
10303
0
      buf = tmp;
10304
0
  }
10305
0
  buf[len++] = cur;
10306
0
  NEXT;
10307
0
  cur=CUR;
10308
0
    }
10309
0
    buf[len] = 0;
10310
0
    return(buf);
10311
0
}
10312
10313
/**
10314
 * xmlParseVersionInfo:
10315
 * @ctxt:  an XML parser context
10316
 *
10317
 * DEPRECATED: Internal function, don't use.
10318
 *
10319
 * parse the XML version.
10320
 *
10321
 * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
10322
 *
10323
 * [25] Eq ::= S? '=' S?
10324
 *
10325
 * Returns the version string, e.g. "1.0"
10326
 */
10327
10328
xmlChar *
10329
0
xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
10330
0
    xmlChar *version = NULL;
10331
10332
0
    if (CMP7(CUR_PTR, 'v', 'e', 'r', 's', 'i', 'o', 'n')) {
10333
0
  SKIP(7);
10334
0
  SKIP_BLANKS;
10335
0
  if (RAW != '=') {
10336
0
      xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10337
0
      return(NULL);
10338
0
        }
10339
0
  NEXT;
10340
0
  SKIP_BLANKS;
10341
0
  if (RAW == '"') {
10342
0
      NEXT;
10343
0
      version = xmlParseVersionNum(ctxt);
10344
0
      if (RAW != '"') {
10345
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10346
0
      } else
10347
0
          NEXT;
10348
0
  } else if (RAW == '\''){
10349
0
      NEXT;
10350
0
      version = xmlParseVersionNum(ctxt);
10351
0
      if (RAW != '\'') {
10352
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10353
0
      } else
10354
0
          NEXT;
10355
0
  } else {
10356
0
      xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10357
0
  }
10358
0
    }
10359
0
    return(version);
10360
0
}
10361
10362
/**
10363
 * xmlParseEncName:
10364
 * @ctxt:  an XML parser context
10365
 *
10366
 * DEPRECATED: Internal function, don't use.
10367
 *
10368
 * parse the XML encoding name
10369
 *
10370
 * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
10371
 *
10372
 * Returns the encoding name value or NULL
10373
 */
10374
xmlChar *
10375
0
xmlParseEncName(xmlParserCtxtPtr ctxt) {
10376
0
    xmlChar *buf = NULL;
10377
0
    int len = 0;
10378
0
    int size = 10;
10379
0
    xmlChar cur;
10380
10381
0
    cur = CUR;
10382
0
    if (((cur >= 'a') && (cur <= 'z')) ||
10383
0
        ((cur >= 'A') && (cur <= 'Z'))) {
10384
0
  buf = (xmlChar *) xmlMallocAtomic(size);
10385
0
  if (buf == NULL) {
10386
0
      xmlErrMemory(ctxt, NULL);
10387
0
      return(NULL);
10388
0
  }
10389
10390
0
  buf[len++] = cur;
10391
0
  NEXT;
10392
0
  cur = CUR;
10393
0
  while (((cur >= 'a') && (cur <= 'z')) ||
10394
0
         ((cur >= 'A') && (cur <= 'Z')) ||
10395
0
         ((cur >= '0') && (cur <= '9')) ||
10396
0
         (cur == '.') || (cur == '_') ||
10397
0
         (cur == '-')) {
10398
0
      if (len + 1 >= size) {
10399
0
          xmlChar *tmp;
10400
10401
0
    size *= 2;
10402
0
    tmp = (xmlChar *) xmlRealloc(buf, size);
10403
0
    if (tmp == NULL) {
10404
0
        xmlErrMemory(ctxt, NULL);
10405
0
        xmlFree(buf);
10406
0
        return(NULL);
10407
0
    }
10408
0
    buf = tmp;
10409
0
      }
10410
0
      buf[len++] = cur;
10411
0
      NEXT;
10412
0
      cur = CUR;
10413
0
      if (cur == 0) {
10414
0
          SHRINK;
10415
0
    GROW;
10416
0
    cur = CUR;
10417
0
      }
10418
0
        }
10419
0
  buf[len] = 0;
10420
0
    } else {
10421
0
  xmlFatalErr(ctxt, XML_ERR_ENCODING_NAME, NULL);
10422
0
    }
10423
0
    return(buf);
10424
0
}
10425
10426
/**
10427
 * xmlParseEncodingDecl:
10428
 * @ctxt:  an XML parser context
10429
 *
10430
 * DEPRECATED: Internal function, don't use.
10431
 *
10432
 * parse the XML encoding declaration
10433
 *
10434
 * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' |  "'" EncName "'")
10435
 *
10436
 * this setups the conversion filters.
10437
 *
10438
 * Returns the encoding value or NULL
10439
 */
10440
10441
const xmlChar *
10442
0
xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
10443
0
    xmlChar *encoding = NULL;
10444
10445
0
    SKIP_BLANKS;
10446
0
    if (CMP8(CUR_PTR, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g')) {
10447
0
  SKIP(8);
10448
0
  SKIP_BLANKS;
10449
0
  if (RAW != '=') {
10450
0
      xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10451
0
      return(NULL);
10452
0
        }
10453
0
  NEXT;
10454
0
  SKIP_BLANKS;
10455
0
  if (RAW == '"') {
10456
0
      NEXT;
10457
0
      encoding = xmlParseEncName(ctxt);
10458
0
      if (RAW != '"') {
10459
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10460
0
    xmlFree((xmlChar *) encoding);
10461
0
    return(NULL);
10462
0
      } else
10463
0
          NEXT;
10464
0
  } else if (RAW == '\''){
10465
0
      NEXT;
10466
0
      encoding = xmlParseEncName(ctxt);
10467
0
      if (RAW != '\'') {
10468
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10469
0
    xmlFree((xmlChar *) encoding);
10470
0
    return(NULL);
10471
0
      } else
10472
0
          NEXT;
10473
0
  } else {
10474
0
      xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10475
0
  }
10476
10477
        /*
10478
         * Non standard parsing, allowing the user to ignore encoding
10479
         */
10480
0
        if (ctxt->options & XML_PARSE_IGNORE_ENC) {
10481
0
      xmlFree((xmlChar *) encoding);
10482
0
            return(NULL);
10483
0
  }
10484
10485
  /*
10486
   * UTF-16 encoding switch has already taken place at this stage,
10487
   * more over the little-endian/big-endian selection is already done
10488
   */
10489
0
        if ((encoding != NULL) &&
10490
0
      ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-16")) ||
10491
0
       (!xmlStrcasecmp(encoding, BAD_CAST "UTF16")))) {
10492
      /*
10493
       * If no encoding was passed to the parser, that we are
10494
       * using UTF-16 and no decoder is present i.e. the
10495
       * document is apparently UTF-8 compatible, then raise an
10496
       * encoding mismatch fatal error
10497
       */
10498
0
      if ((ctxt->encoding == NULL) &&
10499
0
          (ctxt->input->buf != NULL) &&
10500
0
          (ctxt->input->buf->encoder == NULL)) {
10501
0
    xmlFatalErrMsg(ctxt, XML_ERR_INVALID_ENCODING,
10502
0
      "Document labelled UTF-16 but has UTF-8 content\n");
10503
0
      }
10504
0
      if (ctxt->encoding != NULL)
10505
0
    xmlFree((xmlChar *) ctxt->encoding);
10506
0
      ctxt->encoding = encoding;
10507
0
  }
10508
  /*
10509
   * UTF-8 encoding is handled natively
10510
   */
10511
0
        else if ((encoding != NULL) &&
10512
0
      ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-8")) ||
10513
0
       (!xmlStrcasecmp(encoding, BAD_CAST "UTF8")))) {
10514
0
      if (ctxt->encoding != NULL)
10515
0
    xmlFree((xmlChar *) ctxt->encoding);
10516
0
      ctxt->encoding = encoding;
10517
0
  }
10518
0
  else if (encoding != NULL) {
10519
0
      xmlCharEncodingHandlerPtr handler;
10520
10521
0
      if (ctxt->input->encoding != NULL)
10522
0
    xmlFree((xmlChar *) ctxt->input->encoding);
10523
0
      ctxt->input->encoding = encoding;
10524
10525
0
            handler = xmlFindCharEncodingHandler((const char *) encoding);
10526
0
      if (handler != NULL) {
10527
0
    if (xmlSwitchToEncoding(ctxt, handler) < 0) {
10528
        /* failed to convert */
10529
0
        ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
10530
0
        return(NULL);
10531
0
    }
10532
0
      } else {
10533
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
10534
0
      "Unsupported encoding %s\n", encoding);
10535
0
    return(NULL);
10536
0
      }
10537
0
  }
10538
0
    }
10539
0
    return(encoding);
10540
0
}
10541
10542
/**
10543
 * xmlParseSDDecl:
10544
 * @ctxt:  an XML parser context
10545
 *
10546
 * DEPRECATED: Internal function, don't use.
10547
 *
10548
 * parse the XML standalone declaration
10549
 *
10550
 * [32] SDDecl ::= S 'standalone' Eq
10551
 *                 (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no')'"'))
10552
 *
10553
 * [ VC: Standalone Document Declaration ]
10554
 * TODO The standalone document declaration must have the value "no"
10555
 * if any external markup declarations contain declarations of:
10556
 *  - attributes with default values, if elements to which these
10557
 *    attributes apply appear in the document without specifications
10558
 *    of values for these attributes, or
10559
 *  - entities (other than amp, lt, gt, apos, quot), if references
10560
 *    to those entities appear in the document, or
10561
 *  - attributes with values subject to normalization, where the
10562
 *    attribute appears in the document with a value which will change
10563
 *    as a result of normalization, or
10564
 *  - element types with element content, if white space occurs directly
10565
 *    within any instance of those types.
10566
 *
10567
 * Returns:
10568
 *   1 if standalone="yes"
10569
 *   0 if standalone="no"
10570
 *  -2 if standalone attribute is missing or invalid
10571
 *    (A standalone value of -2 means that the XML declaration was found,
10572
 *     but no value was specified for the standalone attribute).
10573
 */
10574
10575
int
10576
0
xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
10577
0
    int standalone = -2;
10578
10579
0
    SKIP_BLANKS;
10580
0
    if (CMP10(CUR_PTR, 's', 't', 'a', 'n', 'd', 'a', 'l', 'o', 'n', 'e')) {
10581
0
  SKIP(10);
10582
0
        SKIP_BLANKS;
10583
0
  if (RAW != '=') {
10584
0
      xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10585
0
      return(standalone);
10586
0
        }
10587
0
  NEXT;
10588
0
  SKIP_BLANKS;
10589
0
        if (RAW == '\''){
10590
0
      NEXT;
10591
0
      if ((RAW == 'n') && (NXT(1) == 'o')) {
10592
0
          standalone = 0;
10593
0
                SKIP(2);
10594
0
      } else if ((RAW == 'y') && (NXT(1) == 'e') &&
10595
0
                 (NXT(2) == 's')) {
10596
0
          standalone = 1;
10597
0
    SKIP(3);
10598
0
            } else {
10599
0
    xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
10600
0
      }
10601
0
      if (RAW != '\'') {
10602
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10603
0
      } else
10604
0
          NEXT;
10605
0
  } else if (RAW == '"'){
10606
0
      NEXT;
10607
0
      if ((RAW == 'n') && (NXT(1) == 'o')) {
10608
0
          standalone = 0;
10609
0
    SKIP(2);
10610
0
      } else if ((RAW == 'y') && (NXT(1) == 'e') &&
10611
0
                 (NXT(2) == 's')) {
10612
0
          standalone = 1;
10613
0
                SKIP(3);
10614
0
            } else {
10615
0
    xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
10616
0
      }
10617
0
      if (RAW != '"') {
10618
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10619
0
      } else
10620
0
          NEXT;
10621
0
  } else {
10622
0
      xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10623
0
        }
10624
0
    }
10625
0
    return(standalone);
10626
0
}
10627
10628
/**
10629
 * xmlParseXMLDecl:
10630
 * @ctxt:  an XML parser context
10631
 *
10632
 * DEPRECATED: Internal function, don't use.
10633
 *
10634
 * parse an XML declaration header
10635
 *
10636
 * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
10637
 */
10638
10639
void
10640
0
xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
10641
0
    xmlChar *version;
10642
10643
    /*
10644
     * This value for standalone indicates that the document has an
10645
     * XML declaration but it does not have a standalone attribute.
10646
     * It will be overwritten later if a standalone attribute is found.
10647
     */
10648
0
    ctxt->input->standalone = -2;
10649
10650
    /*
10651
     * We know that '<?xml' is here.
10652
     */
10653
0
    SKIP(5);
10654
10655
0
    if (!IS_BLANK_CH(RAW)) {
10656
0
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
10657
0
                 "Blank needed after '<?xml'\n");
10658
0
    }
10659
0
    SKIP_BLANKS;
10660
10661
    /*
10662
     * We must have the VersionInfo here.
10663
     */
10664
0
    version = xmlParseVersionInfo(ctxt);
10665
0
    if (version == NULL) {
10666
0
  xmlFatalErr(ctxt, XML_ERR_VERSION_MISSING, NULL);
10667
0
    } else {
10668
0
  if (!xmlStrEqual(version, (const xmlChar *) XML_DEFAULT_VERSION)) {
10669
      /*
10670
       * Changed here for XML-1.0 5th edition
10671
       */
10672
0
      if (ctxt->options & XML_PARSE_OLD10) {
10673
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
10674
0
                "Unsupported version '%s'\n",
10675
0
                version);
10676
0
      } else {
10677
0
          if ((version[0] == '1') && ((version[1] == '.'))) {
10678
0
        xmlWarningMsg(ctxt, XML_WAR_UNKNOWN_VERSION,
10679
0
                      "Unsupported version '%s'\n",
10680
0
          version, NULL);
10681
0
    } else {
10682
0
        xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
10683
0
              "Unsupported version '%s'\n",
10684
0
              version);
10685
0
    }
10686
0
      }
10687
0
  }
10688
0
  if (ctxt->version != NULL)
10689
0
      xmlFree((void *) ctxt->version);
10690
0
  ctxt->version = version;
10691
0
    }
10692
10693
    /*
10694
     * We may have the encoding declaration
10695
     */
10696
0
    if (!IS_BLANK_CH(RAW)) {
10697
0
        if ((RAW == '?') && (NXT(1) == '>')) {
10698
0
      SKIP(2);
10699
0
      return;
10700
0
  }
10701
0
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
10702
0
    }
10703
0
    xmlParseEncodingDecl(ctxt);
10704
0
    if ((ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) ||
10705
0
         (ctxt->instate == XML_PARSER_EOF)) {
10706
  /*
10707
   * The XML REC instructs us to stop parsing right here
10708
   */
10709
0
        return;
10710
0
    }
10711
10712
    /*
10713
     * We may have the standalone status.
10714
     */
10715
0
    if ((ctxt->input->encoding != NULL) && (!IS_BLANK_CH(RAW))) {
10716
0
        if ((RAW == '?') && (NXT(1) == '>')) {
10717
0
      SKIP(2);
10718
0
      return;
10719
0
  }
10720
0
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
10721
0
    }
10722
10723
    /*
10724
     * We can grow the input buffer freely at that point
10725
     */
10726
0
    GROW;
10727
10728
0
    SKIP_BLANKS;
10729
0
    ctxt->input->standalone = xmlParseSDDecl(ctxt);
10730
10731
0
    SKIP_BLANKS;
10732
0
    if ((RAW == '?') && (NXT(1) == '>')) {
10733
0
        SKIP(2);
10734
0
    } else if (RAW == '>') {
10735
        /* Deprecated old WD ... */
10736
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
10737
0
  NEXT;
10738
0
    } else {
10739
0
        int c;
10740
10741
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
10742
0
        while ((c = CUR) != 0) {
10743
0
            NEXT;
10744
0
            if (c == '>')
10745
0
                break;
10746
0
        }
10747
0
    }
10748
0
}
10749
10750
/**
10751
 * xmlParseMisc:
10752
 * @ctxt:  an XML parser context
10753
 *
10754
 * DEPRECATED: Internal function, don't use.
10755
 *
10756
 * parse an XML Misc* optional field.
10757
 *
10758
 * [27] Misc ::= Comment | PI |  S
10759
 */
10760
10761
void
10762
4
xmlParseMisc(xmlParserCtxtPtr ctxt) {
10763
6
    while (ctxt->instate != XML_PARSER_EOF) {
10764
6
        SKIP_BLANKS;
10765
6
        GROW;
10766
6
        if ((RAW == '<') && (NXT(1) == '?')) {
10767
2
      xmlParsePI(ctxt);
10768
4
        } else if (CMP4(CUR_PTR, '<', '!', '-', '-')) {
10769
0
      xmlParseComment(ctxt);
10770
4
        } else {
10771
4
            break;
10772
4
        }
10773
6
    }
10774
4
}
10775
10776
/**
10777
 * xmlParseDocument:
10778
 * @ctxt:  an XML parser context
10779
 *
10780
 * parse an XML document (and build a tree if using the standard SAX
10781
 * interface).
10782
 *
10783
 * [1] document ::= prolog element Misc*
10784
 *
10785
 * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
10786
 *
10787
 * Returns 0, -1 in case of error. the parser context is augmented
10788
 *                as a result of the parsing.
10789
 */
10790
10791
int
10792
2
xmlParseDocument(xmlParserCtxtPtr ctxt) {
10793
2
    xmlChar start[4];
10794
2
    xmlCharEncoding enc;
10795
10796
2
    xmlInitParser();
10797
10798
2
    if ((ctxt == NULL) || (ctxt->input == NULL))
10799
0
        return(-1);
10800
10801
2
    GROW;
10802
10803
    /*
10804
     * SAX: detecting the level.
10805
     */
10806
2
    xmlDetectSAX2(ctxt);
10807
10808
    /*
10809
     * SAX: beginning of the document processing.
10810
     */
10811
2
    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
10812
2
        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
10813
2
    if (ctxt->instate == XML_PARSER_EOF)
10814
0
  return(-1);
10815
10816
2
    if ((ctxt->encoding == NULL) &&
10817
2
        ((ctxt->input->end - ctxt->input->cur) >= 4)) {
10818
  /*
10819
   * Get the 4 first bytes and decode the charset
10820
   * if enc != XML_CHAR_ENCODING_NONE
10821
   * plug some encoding conversion routines.
10822
   */
10823
2
  start[0] = RAW;
10824
2
  start[1] = NXT(1);
10825
2
  start[2] = NXT(2);
10826
2
  start[3] = NXT(3);
10827
2
  enc = xmlDetectCharEncoding(&start[0], 4);
10828
2
  if (enc != XML_CHAR_ENCODING_NONE) {
10829
0
      xmlSwitchEncoding(ctxt, enc);
10830
0
  }
10831
2
    }
10832
10833
10834
2
    if (CUR == 0) {
10835
0
  xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
10836
0
  return(-1);
10837
0
    }
10838
10839
    /*
10840
     * Check for the XMLDecl in the Prolog.
10841
     * do not GROW here to avoid the detected encoder to decode more
10842
     * than just the first line, unless the amount of data is really
10843
     * too small to hold "<?xml version="1.0" encoding="foo"
10844
     */
10845
2
    if ((ctxt->input->end - ctxt->input->cur) < 35) {
10846
0
       GROW;
10847
0
    }
10848
2
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
10849
10850
  /*
10851
   * Note that we will switch encoding on the fly.
10852
   */
10853
0
  xmlParseXMLDecl(ctxt);
10854
0
  if ((ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) ||
10855
0
      (ctxt->instate == XML_PARSER_EOF)) {
10856
      /*
10857
       * The XML REC instructs us to stop parsing right here
10858
       */
10859
0
      return(-1);
10860
0
  }
10861
0
  ctxt->standalone = ctxt->input->standalone;
10862
0
  SKIP_BLANKS;
10863
2
    } else {
10864
2
  ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
10865
2
    }
10866
2
    if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
10867
2
        ctxt->sax->startDocument(ctxt->userData);
10868
2
    if (ctxt->instate == XML_PARSER_EOF)
10869
0
  return(-1);
10870
2
    if ((ctxt->myDoc != NULL) && (ctxt->input != NULL) &&
10871
2
        (ctxt->input->buf != NULL) && (ctxt->input->buf->compressed >= 0)) {
10872
0
  ctxt->myDoc->compression = ctxt->input->buf->compressed;
10873
0
    }
10874
10875
    /*
10876
     * The Misc part of the Prolog
10877
     */
10878
2
    xmlParseMisc(ctxt);
10879
10880
    /*
10881
     * Then possibly doc type declaration(s) and more Misc
10882
     * (doctypedecl Misc*)?
10883
     */
10884
2
    GROW;
10885
2
    if (CMP9(CUR_PTR, '<', '!', 'D', 'O', 'C', 'T', 'Y', 'P', 'E')) {
10886
10887
0
  ctxt->inSubset = 1;
10888
0
  xmlParseDocTypeDecl(ctxt);
10889
0
  if (RAW == '[') {
10890
0
      ctxt->instate = XML_PARSER_DTD;
10891
0
      xmlParseInternalSubset(ctxt);
10892
0
      if (ctxt->instate == XML_PARSER_EOF)
10893
0
    return(-1);
10894
0
  }
10895
10896
  /*
10897
   * Create and update the external subset.
10898
   */
10899
0
  ctxt->inSubset = 2;
10900
0
  if ((ctxt->sax != NULL) && (ctxt->sax->externalSubset != NULL) &&
10901
0
      (!ctxt->disableSAX))
10902
0
      ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
10903
0
                                ctxt->extSubSystem, ctxt->extSubURI);
10904
0
  if (ctxt->instate == XML_PARSER_EOF)
10905
0
      return(-1);
10906
0
  ctxt->inSubset = 0;
10907
10908
0
        xmlCleanSpecialAttr(ctxt);
10909
10910
0
  ctxt->instate = XML_PARSER_PROLOG;
10911
0
  xmlParseMisc(ctxt);
10912
0
    }
10913
10914
    /*
10915
     * Time to start parsing the tree itself
10916
     */
10917
2
    GROW;
10918
2
    if (RAW != '<') {
10919
0
  xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
10920
0
           "Start tag expected, '<' not found\n");
10921
2
    } else {
10922
2
  ctxt->instate = XML_PARSER_CONTENT;
10923
2
  xmlParseElement(ctxt);
10924
2
  ctxt->instate = XML_PARSER_EPILOG;
10925
10926
10927
  /*
10928
   * The Misc part at the end
10929
   */
10930
2
  xmlParseMisc(ctxt);
10931
10932
2
  if (RAW != 0) {
10933
0
      xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
10934
0
  }
10935
2
  ctxt->instate = XML_PARSER_EOF;
10936
2
    }
10937
10938
    /*
10939
     * SAX: end of the document processing.
10940
     */
10941
2
    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
10942
2
        ctxt->sax->endDocument(ctxt->userData);
10943
10944
    /*
10945
     * Remove locally kept entity definitions if the tree was not built
10946
     */
10947
2
    if ((ctxt->myDoc != NULL) &&
10948
2
  (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
10949
0
  xmlFreeDoc(ctxt->myDoc);
10950
0
  ctxt->myDoc = NULL;
10951
0
    }
10952
10953
2
    if ((ctxt->wellFormed) && (ctxt->myDoc != NULL)) {
10954
2
        ctxt->myDoc->properties |= XML_DOC_WELLFORMED;
10955
2
  if (ctxt->valid)
10956
2
      ctxt->myDoc->properties |= XML_DOC_DTDVALID;
10957
2
  if (ctxt->nsWellFormed)
10958
2
      ctxt->myDoc->properties |= XML_DOC_NSVALID;
10959
2
  if (ctxt->options & XML_PARSE_OLD10)
10960
0
      ctxt->myDoc->properties |= XML_DOC_OLD10;
10961
2
    }
10962
2
    if (! ctxt->wellFormed) {
10963
0
  ctxt->valid = 0;
10964
0
  return(-1);
10965
0
    }
10966
2
    return(0);
10967
2
}
10968
10969
/**
10970
 * xmlParseExtParsedEnt:
10971
 * @ctxt:  an XML parser context
10972
 *
10973
 * parse a general parsed entity
10974
 * An external general parsed entity is well-formed if it matches the
10975
 * production labeled extParsedEnt.
10976
 *
10977
 * [78] extParsedEnt ::= TextDecl? content
10978
 *
10979
 * Returns 0, -1 in case of error. the parser context is augmented
10980
 *                as a result of the parsing.
10981
 */
10982
10983
int
10984
0
xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) {
10985
0
    xmlChar start[4];
10986
0
    xmlCharEncoding enc;
10987
10988
0
    if ((ctxt == NULL) || (ctxt->input == NULL))
10989
0
        return(-1);
10990
10991
0
    xmlDetectSAX2(ctxt);
10992
10993
0
    GROW;
10994
10995
    /*
10996
     * SAX: beginning of the document processing.
10997
     */
10998
0
    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
10999
0
        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
11000
11001
    /*
11002
     * Get the 4 first bytes and decode the charset
11003
     * if enc != XML_CHAR_ENCODING_NONE
11004
     * plug some encoding conversion routines.
11005
     */
11006
0
    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
11007
0
  start[0] = RAW;
11008
0
  start[1] = NXT(1);
11009
0
  start[2] = NXT(2);
11010
0
  start[3] = NXT(3);
11011
0
  enc = xmlDetectCharEncoding(start, 4);
11012
0
  if (enc != XML_CHAR_ENCODING_NONE) {
11013
0
      xmlSwitchEncoding(ctxt, enc);
11014
0
  }
11015
0
    }
11016
11017
11018
0
    if (CUR == 0) {
11019
0
  xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
11020
0
    }
11021
11022
    /*
11023
     * Check for the XMLDecl in the Prolog.
11024
     */
11025
0
    GROW;
11026
0
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
11027
11028
  /*
11029
   * Note that we will switch encoding on the fly.
11030
   */
11031
0
  xmlParseXMLDecl(ctxt);
11032
0
  if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
11033
      /*
11034
       * The XML REC instructs us to stop parsing right here
11035
       */
11036
0
      return(-1);
11037
0
  }
11038
0
  SKIP_BLANKS;
11039
0
    } else {
11040
0
  ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11041
0
    }
11042
0
    if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
11043
0
        ctxt->sax->startDocument(ctxt->userData);
11044
0
    if (ctxt->instate == XML_PARSER_EOF)
11045
0
  return(-1);
11046
11047
    /*
11048
     * Doing validity checking on chunk doesn't make sense
11049
     */
11050
0
    ctxt->instate = XML_PARSER_CONTENT;
11051
0
    ctxt->validate = 0;
11052
0
    ctxt->loadsubset = 0;
11053
0
    ctxt->depth = 0;
11054
11055
0
    xmlParseContent(ctxt);
11056
0
    if (ctxt->instate == XML_PARSER_EOF)
11057
0
  return(-1);
11058
11059
0
    if ((RAW == '<') && (NXT(1) == '/')) {
11060
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
11061
0
    } else if (RAW != 0) {
11062
0
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
11063
0
    }
11064
11065
    /*
11066
     * SAX: end of the document processing.
11067
     */
11068
0
    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11069
0
        ctxt->sax->endDocument(ctxt->userData);
11070
11071
0
    if (! ctxt->wellFormed) return(-1);
11072
0
    return(0);
11073
0
}
11074
11075
#ifdef LIBXML_PUSH_ENABLED
11076
/************************************************************************
11077
 *                  *
11078
 *    Progressive parsing interfaces        *
11079
 *                  *
11080
 ************************************************************************/
11081
11082
/**
11083
 * xmlParseLookupSequence:
11084
 * @ctxt:  an XML parser context
11085
 * @first:  the first char to lookup
11086
 * @next:  the next char to lookup or zero
11087
 * @third:  the next char to lookup or zero
11088
 *
11089
 * Try to find if a sequence (first, next, third) or  just (first next) or
11090
 * (first) is available in the input stream.
11091
 * This function has a side effect of (possibly) incrementing ctxt->checkIndex
11092
 * to avoid rescanning sequences of bytes, it DOES change the state of the
11093
 * parser, do not use liberally.
11094
 *
11095
 * Returns the index to the current parsing point if the full sequence
11096
 *      is available, -1 otherwise.
11097
 */
11098
static int
11099
xmlParseLookupSequence(xmlParserCtxtPtr ctxt, xmlChar first,
11100
                       xmlChar next, xmlChar third) {
11101
    int base, len;
11102
    xmlParserInputPtr in;
11103
    const xmlChar *buf;
11104
11105
    in = ctxt->input;
11106
    if (in == NULL) return(-1);
11107
    base = in->cur - in->base;
11108
    if (base < 0) return(-1);
11109
    if (ctxt->checkIndex > base)
11110
        base = ctxt->checkIndex;
11111
    if (in->buf == NULL) {
11112
  buf = in->base;
11113
  len = in->length;
11114
    } else {
11115
  buf = xmlBufContent(in->buf->buffer);
11116
  len = xmlBufUse(in->buf->buffer);
11117
    }
11118
    /* take into account the sequence length */
11119
    if (third) len -= 2;
11120
    else if (next) len --;
11121
    for (;base < len;base++) {
11122
        if (buf[base] == first) {
11123
      if (third != 0) {
11124
    if ((buf[base + 1] != next) ||
11125
        (buf[base + 2] != third)) continue;
11126
      } else if (next != 0) {
11127
    if (buf[base + 1] != next) continue;
11128
      }
11129
      ctxt->checkIndex = 0;
11130
#ifdef DEBUG_PUSH
11131
      if (next == 0)
11132
    xmlGenericError(xmlGenericErrorContext,
11133
      "PP: lookup '%c' found at %d\n",
11134
      first, base);
11135
      else if (third == 0)
11136
    xmlGenericError(xmlGenericErrorContext,
11137
      "PP: lookup '%c%c' found at %d\n",
11138
      first, next, base);
11139
      else
11140
    xmlGenericError(xmlGenericErrorContext,
11141
      "PP: lookup '%c%c%c' found at %d\n",
11142
      first, next, third, base);
11143
#endif
11144
      return(base - (in->cur - in->base));
11145
  }
11146
    }
11147
    ctxt->checkIndex = base;
11148
#ifdef DEBUG_PUSH
11149
    if (next == 0)
11150
  xmlGenericError(xmlGenericErrorContext,
11151
    "PP: lookup '%c' failed\n", first);
11152
    else if (third == 0)
11153
  xmlGenericError(xmlGenericErrorContext,
11154
    "PP: lookup '%c%c' failed\n", first, next);
11155
    else
11156
  xmlGenericError(xmlGenericErrorContext,
11157
    "PP: lookup '%c%c%c' failed\n", first, next, third);
11158
#endif
11159
    return(-1);
11160
}
11161
11162
/**
11163
 * xmlParseGetLasts:
11164
 * @ctxt:  an XML parser context
11165
 * @lastlt:  pointer to store the last '<' from the input
11166
 * @lastgt:  pointer to store the last '>' from the input
11167
 *
11168
 * Lookup the last < and > in the current chunk
11169
 */
11170
static void
11171
xmlParseGetLasts(xmlParserCtxtPtr ctxt, const xmlChar **lastlt,
11172
                 const xmlChar **lastgt) {
11173
    const xmlChar *tmp;
11174
11175
    if ((ctxt == NULL) || (lastlt == NULL) || (lastgt == NULL)) {
11176
  xmlGenericError(xmlGenericErrorContext,
11177
        "Internal error: xmlParseGetLasts\n");
11178
  return;
11179
    }
11180
    if ((ctxt->progressive != 0) && (ctxt->inputNr == 1)) {
11181
        tmp = ctxt->input->end;
11182
  tmp--;
11183
  while ((tmp >= ctxt->input->base) && (*tmp != '<')) tmp--;
11184
  if (tmp < ctxt->input->base) {
11185
      *lastlt = NULL;
11186
      *lastgt = NULL;
11187
  } else {
11188
      *lastlt = tmp;
11189
      tmp++;
11190
      while ((tmp < ctxt->input->end) && (*tmp != '>')) {
11191
          if (*tmp == '\'') {
11192
        tmp++;
11193
        while ((tmp < ctxt->input->end) && (*tmp != '\'')) tmp++;
11194
        if (tmp < ctxt->input->end) tmp++;
11195
    } else if (*tmp == '"') {
11196
        tmp++;
11197
        while ((tmp < ctxt->input->end) && (*tmp != '"')) tmp++;
11198
        if (tmp < ctxt->input->end) tmp++;
11199
    } else
11200
        tmp++;
11201
      }
11202
      if (tmp < ctxt->input->end)
11203
          *lastgt = tmp;
11204
      else {
11205
          tmp = *lastlt;
11206
    tmp--;
11207
    while ((tmp >= ctxt->input->base) && (*tmp != '>')) tmp--;
11208
    if (tmp >= ctxt->input->base)
11209
        *lastgt = tmp;
11210
    else
11211
        *lastgt = NULL;
11212
      }
11213
  }
11214
    } else {
11215
        *lastlt = NULL;
11216
  *lastgt = NULL;
11217
    }
11218
}
11219
/**
11220
 * xmlCheckCdataPush:
11221
 * @cur: pointer to the block of characters
11222
 * @len: length of the block in bytes
11223
 * @complete: 1 if complete CDATA block is passed in, 0 if partial block
11224
 *
11225
 * Check that the block of characters is okay as SCdata content [20]
11226
 *
11227
 * Returns the number of bytes to pass if okay, a negative index where an
11228
 *         UTF-8 error occurred otherwise
11229
 */
11230
static int
11231
xmlCheckCdataPush(const xmlChar *utf, int len, int complete) {
11232
    int ix;
11233
    unsigned char c;
11234
    int codepoint;
11235
11236
    if ((utf == NULL) || (len <= 0))
11237
        return(0);
11238
11239
    for (ix = 0; ix < len;) {      /* string is 0-terminated */
11240
        c = utf[ix];
11241
        if ((c & 0x80) == 0x00) { /* 1-byte code, starts with 10 */
11242
      if (c >= 0x20)
11243
    ix++;
11244
      else if ((c == 0xA) || (c == 0xD) || (c == 0x9))
11245
          ix++;
11246
      else
11247
          return(-ix);
11248
  } else if ((c & 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */
11249
      if (ix + 2 > len) return(complete ? -ix : ix);
11250
      if ((utf[ix+1] & 0xc0 ) != 0x80)
11251
          return(-ix);
11252
      codepoint = (utf[ix] & 0x1f) << 6;
11253
      codepoint |= utf[ix+1] & 0x3f;
11254
      if (!xmlIsCharQ(codepoint))
11255
          return(-ix);
11256
      ix += 2;
11257
  } else if ((c & 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */
11258
      if (ix + 3 > len) return(complete ? -ix : ix);
11259
      if (((utf[ix+1] & 0xc0) != 0x80) ||
11260
          ((utf[ix+2] & 0xc0) != 0x80))
11261
        return(-ix);
11262
      codepoint = (utf[ix] & 0xf) << 12;
11263
      codepoint |= (utf[ix+1] & 0x3f) << 6;
11264
      codepoint |= utf[ix+2] & 0x3f;
11265
      if (!xmlIsCharQ(codepoint))
11266
          return(-ix);
11267
      ix += 3;
11268
  } else if ((c & 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */
11269
      if (ix + 4 > len) return(complete ? -ix : ix);
11270
      if (((utf[ix+1] & 0xc0) != 0x80) ||
11271
          ((utf[ix+2] & 0xc0) != 0x80) ||
11272
    ((utf[ix+3] & 0xc0) != 0x80))
11273
        return(-ix);
11274
      codepoint = (utf[ix] & 0x7) << 18;
11275
      codepoint |= (utf[ix+1] & 0x3f) << 12;
11276
      codepoint |= (utf[ix+2] & 0x3f) << 6;
11277
      codepoint |= utf[ix+3] & 0x3f;
11278
      if (!xmlIsCharQ(codepoint))
11279
          return(-ix);
11280
      ix += 4;
11281
  } else        /* unknown encoding */
11282
      return(-ix);
11283
      }
11284
      return(ix);
11285
}
11286
11287
/**
11288
 * xmlParseTryOrFinish:
11289
 * @ctxt:  an XML parser context
11290
 * @terminate:  last chunk indicator
11291
 *
11292
 * Try to progress on parsing
11293
 *
11294
 * Returns zero if no parsing was possible
11295
 */
11296
static int
11297
xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
11298
    int ret = 0;
11299
    int avail, tlen;
11300
    xmlChar cur, next;
11301
    const xmlChar *lastlt, *lastgt;
11302
11303
    if (ctxt->input == NULL)
11304
        return(0);
11305
11306
#ifdef DEBUG_PUSH
11307
    switch (ctxt->instate) {
11308
  case XML_PARSER_EOF:
11309
      xmlGenericError(xmlGenericErrorContext,
11310
        "PP: try EOF\n"); break;
11311
  case XML_PARSER_START:
11312
      xmlGenericError(xmlGenericErrorContext,
11313
        "PP: try START\n"); break;
11314
  case XML_PARSER_MISC:
11315
      xmlGenericError(xmlGenericErrorContext,
11316
        "PP: try MISC\n");break;
11317
  case XML_PARSER_COMMENT:
11318
      xmlGenericError(xmlGenericErrorContext,
11319
        "PP: try COMMENT\n");break;
11320
  case XML_PARSER_PROLOG:
11321
      xmlGenericError(xmlGenericErrorContext,
11322
        "PP: try PROLOG\n");break;
11323
  case XML_PARSER_START_TAG:
11324
      xmlGenericError(xmlGenericErrorContext,
11325
        "PP: try START_TAG\n");break;
11326
  case XML_PARSER_CONTENT:
11327
      xmlGenericError(xmlGenericErrorContext,
11328
        "PP: try CONTENT\n");break;
11329
  case XML_PARSER_CDATA_SECTION:
11330
      xmlGenericError(xmlGenericErrorContext,
11331
        "PP: try CDATA_SECTION\n");break;
11332
  case XML_PARSER_END_TAG:
11333
      xmlGenericError(xmlGenericErrorContext,
11334
        "PP: try END_TAG\n");break;
11335
  case XML_PARSER_ENTITY_DECL:
11336
      xmlGenericError(xmlGenericErrorContext,
11337
        "PP: try ENTITY_DECL\n");break;
11338
  case XML_PARSER_ENTITY_VALUE:
11339
      xmlGenericError(xmlGenericErrorContext,
11340
        "PP: try ENTITY_VALUE\n");break;
11341
  case XML_PARSER_ATTRIBUTE_VALUE:
11342
      xmlGenericError(xmlGenericErrorContext,
11343
        "PP: try ATTRIBUTE_VALUE\n");break;
11344
  case XML_PARSER_DTD:
11345
      xmlGenericError(xmlGenericErrorContext,
11346
        "PP: try DTD\n");break;
11347
  case XML_PARSER_EPILOG:
11348
      xmlGenericError(xmlGenericErrorContext,
11349
        "PP: try EPILOG\n");break;
11350
  case XML_PARSER_PI:
11351
      xmlGenericError(xmlGenericErrorContext,
11352
        "PP: try PI\n");break;
11353
        case XML_PARSER_IGNORE:
11354
            xmlGenericError(xmlGenericErrorContext,
11355
        "PP: try IGNORE\n");break;
11356
    }
11357
#endif
11358
11359
    if ((ctxt->input != NULL) &&
11360
        (ctxt->input->cur - ctxt->input->base > 4096)) {
11361
  xmlSHRINK(ctxt);
11362
  ctxt->checkIndex = 0;
11363
    }
11364
    xmlParseGetLasts(ctxt, &lastlt, &lastgt);
11365
11366
    while (ctxt->instate != XML_PARSER_EOF) {
11367
  if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
11368
      return(0);
11369
11370
  if (ctxt->input == NULL) break;
11371
  if (ctxt->input->buf == NULL)
11372
      avail = ctxt->input->length -
11373
              (ctxt->input->cur - ctxt->input->base);
11374
  else {
11375
      /*
11376
       * If we are operating on converted input, try to flush
11377
       * remaining chars to avoid them stalling in the non-converted
11378
       * buffer. But do not do this in document start where
11379
       * encoding="..." may not have been read and we work on a
11380
       * guessed encoding.
11381
       */
11382
      if ((ctxt->instate != XML_PARSER_START) &&
11383
          (ctxt->input->buf->raw != NULL) &&
11384
    (xmlBufIsEmpty(ctxt->input->buf->raw) == 0)) {
11385
                size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer,
11386
                                                 ctxt->input);
11387
    size_t current = ctxt->input->cur - ctxt->input->base;
11388
11389
    xmlParserInputBufferPush(ctxt->input->buf, 0, "");
11390
                xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input,
11391
                                      base, current);
11392
      }
11393
      avail = xmlBufUse(ctxt->input->buf->buffer) -
11394
        (ctxt->input->cur - ctxt->input->base);
11395
  }
11396
        if (avail < 1)
11397
      goto done;
11398
        switch (ctxt->instate) {
11399
            case XML_PARSER_EOF:
11400
          /*
11401
     * Document parsing is done !
11402
     */
11403
          goto done;
11404
            case XML_PARSER_START:
11405
    if (ctxt->charset == XML_CHAR_ENCODING_NONE) {
11406
        xmlChar start[4];
11407
        xmlCharEncoding enc;
11408
11409
        /*
11410
         * Very first chars read from the document flow.
11411
         */
11412
        if (avail < 4)
11413
      goto done;
11414
11415
        /*
11416
         * Get the 4 first bytes and decode the charset
11417
         * if enc != XML_CHAR_ENCODING_NONE
11418
         * plug some encoding conversion routines,
11419
         * else xmlSwitchEncoding will set to (default)
11420
         * UTF8.
11421
         */
11422
        start[0] = RAW;
11423
        start[1] = NXT(1);
11424
        start[2] = NXT(2);
11425
        start[3] = NXT(3);
11426
        enc = xmlDetectCharEncoding(start, 4);
11427
        xmlSwitchEncoding(ctxt, enc);
11428
        break;
11429
    }
11430
11431
    if (avail < 2)
11432
        goto done;
11433
    cur = ctxt->input->cur[0];
11434
    next = ctxt->input->cur[1];
11435
    if (cur == 0) {
11436
        if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
11437
      ctxt->sax->setDocumentLocator(ctxt->userData,
11438
                  &xmlDefaultSAXLocator);
11439
        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
11440
        xmlHaltParser(ctxt);
11441
#ifdef DEBUG_PUSH
11442
        xmlGenericError(xmlGenericErrorContext,
11443
          "PP: entering EOF\n");
11444
#endif
11445
        if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11446
      ctxt->sax->endDocument(ctxt->userData);
11447
        goto done;
11448
    }
11449
          if ((cur == '<') && (next == '?')) {
11450
        /* PI or XML decl */
11451
        if (avail < 5) return(ret);
11452
        if ((!terminate) &&
11453
            (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
11454
      return(ret);
11455
        if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
11456
      ctxt->sax->setDocumentLocator(ctxt->userData,
11457
                  &xmlDefaultSAXLocator);
11458
        if ((ctxt->input->cur[2] == 'x') &&
11459
      (ctxt->input->cur[3] == 'm') &&
11460
      (ctxt->input->cur[4] == 'l') &&
11461
      (IS_BLANK_CH(ctxt->input->cur[5]))) {
11462
      ret += 5;
11463
#ifdef DEBUG_PUSH
11464
      xmlGenericError(xmlGenericErrorContext,
11465
        "PP: Parsing XML Decl\n");
11466
#endif
11467
      xmlParseXMLDecl(ctxt);
11468
      if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
11469
          /*
11470
           * The XML REC instructs us to stop parsing right
11471
           * here
11472
           */
11473
          xmlHaltParser(ctxt);
11474
          return(0);
11475
      }
11476
      ctxt->standalone = ctxt->input->standalone;
11477
      if ((ctxt->encoding == NULL) &&
11478
          (ctxt->input->encoding != NULL))
11479
          ctxt->encoding = xmlStrdup(ctxt->input->encoding);
11480
      if ((ctxt->sax) && (ctxt->sax->startDocument) &&
11481
          (!ctxt->disableSAX))
11482
          ctxt->sax->startDocument(ctxt->userData);
11483
      ctxt->instate = XML_PARSER_MISC;
11484
#ifdef DEBUG_PUSH
11485
      xmlGenericError(xmlGenericErrorContext,
11486
        "PP: entering MISC\n");
11487
#endif
11488
        } else {
11489
      ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11490
      if ((ctxt->sax) && (ctxt->sax->startDocument) &&
11491
          (!ctxt->disableSAX))
11492
          ctxt->sax->startDocument(ctxt->userData);
11493
      ctxt->instate = XML_PARSER_MISC;
11494
#ifdef DEBUG_PUSH
11495
      xmlGenericError(xmlGenericErrorContext,
11496
        "PP: entering MISC\n");
11497
#endif
11498
        }
11499
    } else {
11500
        if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
11501
      ctxt->sax->setDocumentLocator(ctxt->userData,
11502
                  &xmlDefaultSAXLocator);
11503
        ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11504
        if (ctxt->version == NULL) {
11505
            xmlErrMemory(ctxt, NULL);
11506
      break;
11507
        }
11508
        if ((ctxt->sax) && (ctxt->sax->startDocument) &&
11509
            (!ctxt->disableSAX))
11510
      ctxt->sax->startDocument(ctxt->userData);
11511
        ctxt->instate = XML_PARSER_MISC;
11512
#ifdef DEBUG_PUSH
11513
        xmlGenericError(xmlGenericErrorContext,
11514
          "PP: entering MISC\n");
11515
#endif
11516
    }
11517
    break;
11518
            case XML_PARSER_START_TAG: {
11519
          const xmlChar *name;
11520
    const xmlChar *prefix = NULL;
11521
    const xmlChar *URI = NULL;
11522
                int line = ctxt->input->line;
11523
    int nsNr = ctxt->nsNr;
11524
11525
    if ((avail < 2) && (ctxt->inputNr == 1))
11526
        goto done;
11527
    cur = ctxt->input->cur[0];
11528
          if (cur != '<') {
11529
        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
11530
        xmlHaltParser(ctxt);
11531
        if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11532
      ctxt->sax->endDocument(ctxt->userData);
11533
        goto done;
11534
    }
11535
    if (!terminate) {
11536
        if (ctxt->progressive) {
11537
            /* > can be found unescaped in attribute values */
11538
            if ((lastgt == NULL) || (ctxt->input->cur >= lastgt))
11539
          goto done;
11540
        } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) {
11541
      goto done;
11542
        }
11543
    }
11544
    if (ctxt->spaceNr == 0)
11545
        spacePush(ctxt, -1);
11546
    else if (*ctxt->space == -2)
11547
        spacePush(ctxt, -1);
11548
    else
11549
        spacePush(ctxt, *ctxt->space);
11550
#ifdef LIBXML_SAX1_ENABLED
11551
    if (ctxt->sax2)
11552
#endif /* LIBXML_SAX1_ENABLED */
11553
        name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
11554
#ifdef LIBXML_SAX1_ENABLED
11555
    else
11556
        name = xmlParseStartTag(ctxt);
11557
#endif /* LIBXML_SAX1_ENABLED */
11558
    if (ctxt->instate == XML_PARSER_EOF)
11559
        goto done;
11560
    if (name == NULL) {
11561
        spacePop(ctxt);
11562
        xmlHaltParser(ctxt);
11563
        if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11564
      ctxt->sax->endDocument(ctxt->userData);
11565
        goto done;
11566
    }
11567
#ifdef LIBXML_VALID_ENABLED
11568
    /*
11569
     * [ VC: Root Element Type ]
11570
     * The Name in the document type declaration must match
11571
     * the element type of the root element.
11572
     */
11573
    if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
11574
        ctxt->node && (ctxt->node == ctxt->myDoc->children))
11575
        ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
11576
#endif /* LIBXML_VALID_ENABLED */
11577
11578
    /*
11579
     * Check for an Empty Element.
11580
     */
11581
    if ((RAW == '/') && (NXT(1) == '>')) {
11582
        SKIP(2);
11583
11584
        if (ctxt->sax2) {
11585
      if ((ctxt->sax != NULL) &&
11586
          (ctxt->sax->endElementNs != NULL) &&
11587
          (!ctxt->disableSAX))
11588
          ctxt->sax->endElementNs(ctxt->userData, name,
11589
                                  prefix, URI);
11590
      if (ctxt->nsNr - nsNr > 0)
11591
          nsPop(ctxt, ctxt->nsNr - nsNr);
11592
#ifdef LIBXML_SAX1_ENABLED
11593
        } else {
11594
      if ((ctxt->sax != NULL) &&
11595
          (ctxt->sax->endElement != NULL) &&
11596
          (!ctxt->disableSAX))
11597
          ctxt->sax->endElement(ctxt->userData, name);
11598
#endif /* LIBXML_SAX1_ENABLED */
11599
        }
11600
        if (ctxt->instate == XML_PARSER_EOF)
11601
      goto done;
11602
        spacePop(ctxt);
11603
        if (ctxt->nameNr == 0) {
11604
      ctxt->instate = XML_PARSER_EPILOG;
11605
        } else {
11606
      ctxt->instate = XML_PARSER_CONTENT;
11607
        }
11608
                    ctxt->progressive = 1;
11609
        break;
11610
    }
11611
    if (RAW == '>') {
11612
        NEXT;
11613
    } else {
11614
        xmlFatalErrMsgStr(ctxt, XML_ERR_GT_REQUIRED,
11615
           "Couldn't find end of Start Tag %s\n",
11616
           name);
11617
        nodePop(ctxt);
11618
        spacePop(ctxt);
11619
    }
11620
                nameNsPush(ctxt, name, prefix, URI, line, ctxt->nsNr - nsNr);
11621
11622
    ctxt->instate = XML_PARSER_CONTENT;
11623
                ctxt->progressive = 1;
11624
                break;
11625
      }
11626
            case XML_PARSER_CONTENT: {
11627
    int id;
11628
    unsigned long cons;
11629
    if ((avail < 2) && (ctxt->inputNr == 1))
11630
        goto done;
11631
    cur = ctxt->input->cur[0];
11632
    next = ctxt->input->cur[1];
11633
11634
    id = ctxt->input->id;
11635
          cons = CUR_CONSUMED;
11636
    if ((cur == '<') && (next == '/')) {
11637
        ctxt->instate = XML_PARSER_END_TAG;
11638
        break;
11639
          } else if ((cur == '<') && (next == '?')) {
11640
        if ((!terminate) &&
11641
            (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
11642
                        ctxt->progressive = XML_PARSER_PI;
11643
      goto done;
11644
                    }
11645
        xmlParsePI(ctxt);
11646
        ctxt->instate = XML_PARSER_CONTENT;
11647
                    ctxt->progressive = 1;
11648
    } else if ((cur == '<') && (next != '!')) {
11649
        ctxt->instate = XML_PARSER_START_TAG;
11650
        break;
11651
    } else if ((cur == '<') && (next == '!') &&
11652
               (ctxt->input->cur[2] == '-') &&
11653
         (ctxt->input->cur[3] == '-')) {
11654
        int term;
11655
11656
              if (avail < 4)
11657
            goto done;
11658
        ctxt->input->cur += 4;
11659
        term = xmlParseLookupSequence(ctxt, '-', '-', '>');
11660
        ctxt->input->cur -= 4;
11661
        if ((!terminate) && (term < 0)) {
11662
                        ctxt->progressive = XML_PARSER_COMMENT;
11663
      goto done;
11664
                    }
11665
        xmlParseComment(ctxt);
11666
        ctxt->instate = XML_PARSER_CONTENT;
11667
                    ctxt->progressive = 1;
11668
    } else if ((cur == '<') && (ctxt->input->cur[1] == '!') &&
11669
        (ctxt->input->cur[2] == '[') &&
11670
        (ctxt->input->cur[3] == 'C') &&
11671
        (ctxt->input->cur[4] == 'D') &&
11672
        (ctxt->input->cur[5] == 'A') &&
11673
        (ctxt->input->cur[6] == 'T') &&
11674
        (ctxt->input->cur[7] == 'A') &&
11675
        (ctxt->input->cur[8] == '[')) {
11676
        SKIP(9);
11677
        ctxt->instate = XML_PARSER_CDATA_SECTION;
11678
        break;
11679
    } else if ((cur == '<') && (next == '!') &&
11680
               (avail < 9)) {
11681
        goto done;
11682
    } else if (cur == '&') {
11683
        if ((!terminate) &&
11684
            (xmlParseLookupSequence(ctxt, ';', 0, 0) < 0))
11685
      goto done;
11686
        xmlParseReference(ctxt);
11687
    } else {
11688
        /* TODO Avoid the extra copy, handle directly !!! */
11689
        /*
11690
         * Goal of the following test is:
11691
         *  - minimize calls to the SAX 'character' callback
11692
         *    when they are mergeable
11693
         *  - handle an problem for isBlank when we only parse
11694
         *    a sequence of blank chars and the next one is
11695
         *    not available to check against '<' presence.
11696
         *  - tries to homogenize the differences in SAX
11697
         *    callbacks between the push and pull versions
11698
         *    of the parser.
11699
         */
11700
        if ((ctxt->inputNr == 1) &&
11701
            (avail < XML_PARSER_BIG_BUFFER_SIZE)) {
11702
      if (!terminate) {
11703
          if (ctxt->progressive) {
11704
        if ((lastlt == NULL) ||
11705
            (ctxt->input->cur > lastlt))
11706
            goto done;
11707
          } else if (xmlParseLookupSequence(ctxt,
11708
                                            '<', 0, 0) < 0) {
11709
        goto done;
11710
          }
11711
      }
11712
                    }
11713
        ctxt->checkIndex = 0;
11714
        xmlParseCharData(ctxt, 0);
11715
    }
11716
    if ((cons == CUR_CONSUMED) && (id == ctxt->input->id)) {
11717
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
11718
                    "detected an error in element content\n");
11719
        xmlHaltParser(ctxt);
11720
        break;
11721
    }
11722
    break;
11723
      }
11724
            case XML_PARSER_END_TAG:
11725
    if (avail < 2)
11726
        goto done;
11727
    if (!terminate) {
11728
        if (ctxt->progressive) {
11729
            /* > can be found unescaped in attribute values */
11730
            if ((lastgt == NULL) || (ctxt->input->cur >= lastgt))
11731
          goto done;
11732
        } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) {
11733
      goto done;
11734
        }
11735
    }
11736
    if (ctxt->sax2) {
11737
              xmlParseEndTag2(ctxt, &ctxt->pushTab[ctxt->nameNr - 1]);
11738
        nameNsPop(ctxt);
11739
    }
11740
#ifdef LIBXML_SAX1_ENABLED
11741
      else
11742
        xmlParseEndTag1(ctxt, 0);
11743
#endif /* LIBXML_SAX1_ENABLED */
11744
    if (ctxt->instate == XML_PARSER_EOF) {
11745
        /* Nothing */
11746
    } else if (ctxt->nameNr == 0) {
11747
        ctxt->instate = XML_PARSER_EPILOG;
11748
    } else {
11749
        ctxt->instate = XML_PARSER_CONTENT;
11750
    }
11751
    break;
11752
            case XML_PARSER_CDATA_SECTION: {
11753
          /*
11754
     * The Push mode need to have the SAX callback for
11755
     * cdataBlock merge back contiguous callbacks.
11756
     */
11757
    int base;
11758
11759
    base = xmlParseLookupSequence(ctxt, ']', ']', '>');
11760
    if (base < 0) {
11761
        if (avail >= XML_PARSER_BIG_BUFFER_SIZE + 2) {
11762
            int tmp;
11763
11764
      tmp = xmlCheckCdataPush(ctxt->input->cur,
11765
                              XML_PARSER_BIG_BUFFER_SIZE, 0);
11766
      if (tmp < 0) {
11767
          tmp = -tmp;
11768
          ctxt->input->cur += tmp;
11769
          goto encoding_error;
11770
      }
11771
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
11772
          if (ctxt->sax->cdataBlock != NULL)
11773
        ctxt->sax->cdataBlock(ctxt->userData,
11774
                              ctxt->input->cur, tmp);
11775
          else if (ctxt->sax->characters != NULL)
11776
        ctxt->sax->characters(ctxt->userData,
11777
                              ctxt->input->cur, tmp);
11778
      }
11779
      if (ctxt->instate == XML_PARSER_EOF)
11780
          goto done;
11781
      SKIPL(tmp);
11782
      ctxt->checkIndex = 0;
11783
        }
11784
        goto done;
11785
    } else {
11786
        int tmp;
11787
11788
        tmp = xmlCheckCdataPush(ctxt->input->cur, base, 1);
11789
        if ((tmp < 0) || (tmp != base)) {
11790
      tmp = -tmp;
11791
      ctxt->input->cur += tmp;
11792
      goto encoding_error;
11793
        }
11794
        if ((ctxt->sax != NULL) && (base == 0) &&
11795
            (ctxt->sax->cdataBlock != NULL) &&
11796
            (!ctxt->disableSAX)) {
11797
      /*
11798
       * Special case to provide identical behaviour
11799
       * between pull and push parsers on enpty CDATA
11800
       * sections
11801
       */
11802
       if ((ctxt->input->cur - ctxt->input->base >= 9) &&
11803
           (!strncmp((const char *)&ctxt->input->cur[-9],
11804
                     "<![CDATA[", 9)))
11805
           ctxt->sax->cdataBlock(ctxt->userData,
11806
                                 BAD_CAST "", 0);
11807
        } else if ((ctxt->sax != NULL) && (base > 0) &&
11808
      (!ctxt->disableSAX)) {
11809
      if (ctxt->sax->cdataBlock != NULL)
11810
          ctxt->sax->cdataBlock(ctxt->userData,
11811
              ctxt->input->cur, base);
11812
      else if (ctxt->sax->characters != NULL)
11813
          ctxt->sax->characters(ctxt->userData,
11814
              ctxt->input->cur, base);
11815
        }
11816
        if (ctxt->instate == XML_PARSER_EOF)
11817
      goto done;
11818
        SKIPL(base + 3);
11819
        ctxt->checkIndex = 0;
11820
        ctxt->instate = XML_PARSER_CONTENT;
11821
#ifdef DEBUG_PUSH
11822
        xmlGenericError(xmlGenericErrorContext,
11823
          "PP: entering CONTENT\n");
11824
#endif
11825
    }
11826
    break;
11827
      }
11828
            case XML_PARSER_MISC:
11829
    SKIP_BLANKS;
11830
    if (ctxt->input->buf == NULL)
11831
        avail = ctxt->input->length -
11832
                (ctxt->input->cur - ctxt->input->base);
11833
    else
11834
        avail = xmlBufUse(ctxt->input->buf->buffer) -
11835
                (ctxt->input->cur - ctxt->input->base);
11836
    if (avail < 2)
11837
        goto done;
11838
    cur = ctxt->input->cur[0];
11839
    next = ctxt->input->cur[1];
11840
          if ((cur == '<') && (next == '?')) {
11841
        if ((!terminate) &&
11842
            (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
11843
                        ctxt->progressive = XML_PARSER_PI;
11844
      goto done;
11845
                    }
11846
#ifdef DEBUG_PUSH
11847
        xmlGenericError(xmlGenericErrorContext,
11848
          "PP: Parsing PI\n");
11849
#endif
11850
        xmlParsePI(ctxt);
11851
        if (ctxt->instate == XML_PARSER_EOF)
11852
      goto done;
11853
        ctxt->instate = XML_PARSER_MISC;
11854
                    ctxt->progressive = 1;
11855
        ctxt->checkIndex = 0;
11856
    } else if ((cur == '<') && (next == '!') &&
11857
        (ctxt->input->cur[2] == '-') &&
11858
        (ctxt->input->cur[3] == '-')) {
11859
        if ((!terminate) &&
11860
            (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
11861
                        ctxt->progressive = XML_PARSER_COMMENT;
11862
      goto done;
11863
                    }
11864
#ifdef DEBUG_PUSH
11865
        xmlGenericError(xmlGenericErrorContext,
11866
          "PP: Parsing Comment\n");
11867
#endif
11868
        xmlParseComment(ctxt);
11869
        if (ctxt->instate == XML_PARSER_EOF)
11870
      goto done;
11871
        ctxt->instate = XML_PARSER_MISC;
11872
                    ctxt->progressive = 1;
11873
        ctxt->checkIndex = 0;
11874
    } else if ((cur == '<') && (next == '!') &&
11875
        (ctxt->input->cur[2] == 'D') &&
11876
        (ctxt->input->cur[3] == 'O') &&
11877
        (ctxt->input->cur[4] == 'C') &&
11878
        (ctxt->input->cur[5] == 'T') &&
11879
        (ctxt->input->cur[6] == 'Y') &&
11880
        (ctxt->input->cur[7] == 'P') &&
11881
        (ctxt->input->cur[8] == 'E')) {
11882
        if ((!terminate) &&
11883
            (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0)) {
11884
                        ctxt->progressive = XML_PARSER_DTD;
11885
      goto done;
11886
                    }
11887
#ifdef DEBUG_PUSH
11888
        xmlGenericError(xmlGenericErrorContext,
11889
          "PP: Parsing internal subset\n");
11890
#endif
11891
        ctxt->inSubset = 1;
11892
                    ctxt->progressive = 0;
11893
        ctxt->checkIndex = 0;
11894
        xmlParseDocTypeDecl(ctxt);
11895
        if (ctxt->instate == XML_PARSER_EOF)
11896
      goto done;
11897
        if (RAW == '[') {
11898
      ctxt->instate = XML_PARSER_DTD;
11899
#ifdef DEBUG_PUSH
11900
      xmlGenericError(xmlGenericErrorContext,
11901
        "PP: entering DTD\n");
11902
#endif
11903
        } else {
11904
      /*
11905
       * Create and update the external subset.
11906
       */
11907
      ctxt->inSubset = 2;
11908
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
11909
          (ctxt->sax->externalSubset != NULL))
11910
          ctxt->sax->externalSubset(ctxt->userData,
11911
            ctxt->intSubName, ctxt->extSubSystem,
11912
            ctxt->extSubURI);
11913
      ctxt->inSubset = 0;
11914
      xmlCleanSpecialAttr(ctxt);
11915
      ctxt->instate = XML_PARSER_PROLOG;
11916
#ifdef DEBUG_PUSH
11917
      xmlGenericError(xmlGenericErrorContext,
11918
        "PP: entering PROLOG\n");
11919
#endif
11920
        }
11921
    } else if ((cur == '<') && (next == '!') &&
11922
               (avail < 9)) {
11923
        goto done;
11924
    } else {
11925
        ctxt->instate = XML_PARSER_START_TAG;
11926
        ctxt->progressive = XML_PARSER_START_TAG;
11927
        xmlParseGetLasts(ctxt, &lastlt, &lastgt);
11928
#ifdef DEBUG_PUSH
11929
        xmlGenericError(xmlGenericErrorContext,
11930
          "PP: entering START_TAG\n");
11931
#endif
11932
    }
11933
    break;
11934
            case XML_PARSER_PROLOG:
11935
    SKIP_BLANKS;
11936
    if (ctxt->input->buf == NULL)
11937
        avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
11938
    else
11939
        avail = xmlBufUse(ctxt->input->buf->buffer) -
11940
                            (ctxt->input->cur - ctxt->input->base);
11941
    if (avail < 2)
11942
        goto done;
11943
    cur = ctxt->input->cur[0];
11944
    next = ctxt->input->cur[1];
11945
          if ((cur == '<') && (next == '?')) {
11946
        if ((!terminate) &&
11947
            (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
11948
                        ctxt->progressive = XML_PARSER_PI;
11949
      goto done;
11950
                    }
11951
#ifdef DEBUG_PUSH
11952
        xmlGenericError(xmlGenericErrorContext,
11953
          "PP: Parsing PI\n");
11954
#endif
11955
        xmlParsePI(ctxt);
11956
        if (ctxt->instate == XML_PARSER_EOF)
11957
      goto done;
11958
        ctxt->instate = XML_PARSER_PROLOG;
11959
                    ctxt->progressive = 1;
11960
    } else if ((cur == '<') && (next == '!') &&
11961
        (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
11962
        if ((!terminate) &&
11963
            (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
11964
                        ctxt->progressive = XML_PARSER_COMMENT;
11965
      goto done;
11966
                    }
11967
#ifdef DEBUG_PUSH
11968
        xmlGenericError(xmlGenericErrorContext,
11969
          "PP: Parsing Comment\n");
11970
#endif
11971
        xmlParseComment(ctxt);
11972
        if (ctxt->instate == XML_PARSER_EOF)
11973
      goto done;
11974
        ctxt->instate = XML_PARSER_PROLOG;
11975
                    ctxt->progressive = 1;
11976
    } else if ((cur == '<') && (next == '!') &&
11977
               (avail < 4)) {
11978
        goto done;
11979
    } else {
11980
        ctxt->instate = XML_PARSER_START_TAG;
11981
        if (ctxt->progressive == 0)
11982
      ctxt->progressive = XML_PARSER_START_TAG;
11983
        xmlParseGetLasts(ctxt, &lastlt, &lastgt);
11984
#ifdef DEBUG_PUSH
11985
        xmlGenericError(xmlGenericErrorContext,
11986
          "PP: entering START_TAG\n");
11987
#endif
11988
    }
11989
    break;
11990
            case XML_PARSER_EPILOG:
11991
    SKIP_BLANKS;
11992
    if (ctxt->input->buf == NULL)
11993
        avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
11994
    else
11995
        avail = xmlBufUse(ctxt->input->buf->buffer) -
11996
                            (ctxt->input->cur - ctxt->input->base);
11997
    if (avail < 2)
11998
        goto done;
11999
    cur = ctxt->input->cur[0];
12000
    next = ctxt->input->cur[1];
12001
          if ((cur == '<') && (next == '?')) {
12002
        if ((!terminate) &&
12003
            (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
12004
                        ctxt->progressive = XML_PARSER_PI;
12005
      goto done;
12006
                    }
12007
#ifdef DEBUG_PUSH
12008
        xmlGenericError(xmlGenericErrorContext,
12009
          "PP: Parsing PI\n");
12010
#endif
12011
        xmlParsePI(ctxt);
12012
        if (ctxt->instate == XML_PARSER_EOF)
12013
      goto done;
12014
        ctxt->instate = XML_PARSER_EPILOG;
12015
                    ctxt->progressive = 1;
12016
    } else if ((cur == '<') && (next == '!') &&
12017
        (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
12018
        if ((!terminate) &&
12019
            (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
12020
                        ctxt->progressive = XML_PARSER_COMMENT;
12021
      goto done;
12022
                    }
12023
#ifdef DEBUG_PUSH
12024
        xmlGenericError(xmlGenericErrorContext,
12025
          "PP: Parsing Comment\n");
12026
#endif
12027
        xmlParseComment(ctxt);
12028
        if (ctxt->instate == XML_PARSER_EOF)
12029
      goto done;
12030
        ctxt->instate = XML_PARSER_EPILOG;
12031
                    ctxt->progressive = 1;
12032
    } else if ((cur == '<') && (next == '!') &&
12033
               (avail < 4)) {
12034
        goto done;
12035
    } else {
12036
        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
12037
        xmlHaltParser(ctxt);
12038
#ifdef DEBUG_PUSH
12039
        xmlGenericError(xmlGenericErrorContext,
12040
          "PP: entering EOF\n");
12041
#endif
12042
        if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
12043
      ctxt->sax->endDocument(ctxt->userData);
12044
        goto done;
12045
    }
12046
    break;
12047
            case XML_PARSER_DTD: {
12048
          /*
12049
     * Sorry but progressive parsing of the internal subset
12050
     * is not expected to be supported. We first check that
12051
     * the full content of the internal subset is available and
12052
     * the parsing is launched only at that point.
12053
     * Internal subset ends up with "']' S? '>'" in an unescaped
12054
     * section and not in a ']]>' sequence which are conditional
12055
     * sections (whoever argued to keep that crap in XML deserve
12056
     * a place in hell !).
12057
     */
12058
    int base, i;
12059
    xmlChar *buf;
12060
          xmlChar quote = 0;
12061
                size_t use;
12062
12063
    base = ctxt->input->cur - ctxt->input->base;
12064
    if (base < 0) return(0);
12065
    if (ctxt->checkIndex > base)
12066
        base = ctxt->checkIndex;
12067
    buf = xmlBufContent(ctxt->input->buf->buffer);
12068
                use = xmlBufUse(ctxt->input->buf->buffer);
12069
    for (;(unsigned int) base < use; base++) {
12070
        if (quote != 0) {
12071
            if (buf[base] == quote)
12072
          quote = 0;
12073
      continue;
12074
        }
12075
        if ((quote == 0) && (buf[base] == '<')) {
12076
            int found  = 0;
12077
      /* special handling of comments */
12078
            if (((unsigned int) base + 4 < use) &&
12079
          (buf[base + 1] == '!') &&
12080
          (buf[base + 2] == '-') &&
12081
          (buf[base + 3] == '-')) {
12082
          for (;(unsigned int) base + 3 < use; base++) {
12083
        if ((buf[base] == '-') &&
12084
            (buf[base + 1] == '-') &&
12085
            (buf[base + 2] == '>')) {
12086
            found = 1;
12087
            base += 2;
12088
            break;
12089
        }
12090
                }
12091
          if (!found) {
12092
#if 0
12093
              fprintf(stderr, "unfinished comment\n");
12094
#endif
12095
              break; /* for */
12096
                }
12097
                continue;
12098
      }
12099
        }
12100
        if (buf[base] == '"') {
12101
            quote = '"';
12102
      continue;
12103
        }
12104
        if (buf[base] == '\'') {
12105
            quote = '\'';
12106
      continue;
12107
        }
12108
        if (buf[base] == ']') {
12109
#if 0
12110
            fprintf(stderr, "%c%c%c%c: ", buf[base],
12111
              buf[base + 1], buf[base + 2], buf[base + 3]);
12112
#endif
12113
            if ((unsigned int) base +1 >= use)
12114
          break;
12115
      if (buf[base + 1] == ']') {
12116
          /* conditional crap, skip both ']' ! */
12117
          base++;
12118
          continue;
12119
      }
12120
            for (i = 1; (unsigned int) base + i < use; i++) {
12121
          if (buf[base + i] == '>') {
12122
#if 0
12123
              fprintf(stderr, "found\n");
12124
#endif
12125
              goto found_end_int_subset;
12126
          }
12127
          if (!IS_BLANK_CH(buf[base + i])) {
12128
#if 0
12129
              fprintf(stderr, "not found\n");
12130
#endif
12131
              goto not_end_of_int_subset;
12132
          }
12133
      }
12134
#if 0
12135
      fprintf(stderr, "end of stream\n");
12136
#endif
12137
            break;
12138
12139
        }
12140
not_end_of_int_subset:
12141
                    continue; /* for */
12142
    }
12143
    /*
12144
     * We didn't found the end of the Internal subset
12145
     */
12146
                if (quote == 0)
12147
                    ctxt->checkIndex = base;
12148
                else
12149
                    ctxt->checkIndex = 0;
12150
#ifdef DEBUG_PUSH
12151
    if (next == 0)
12152
        xmlGenericError(xmlGenericErrorContext,
12153
          "PP: lookup of int subset end filed\n");
12154
#endif
12155
          goto done;
12156
12157
found_end_int_subset:
12158
                ctxt->checkIndex = 0;
12159
    xmlParseInternalSubset(ctxt);
12160
    if (ctxt->instate == XML_PARSER_EOF)
12161
        goto done;
12162
    ctxt->inSubset = 2;
12163
    if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
12164
        (ctxt->sax->externalSubset != NULL))
12165
        ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
12166
          ctxt->extSubSystem, ctxt->extSubURI);
12167
    ctxt->inSubset = 0;
12168
    xmlCleanSpecialAttr(ctxt);
12169
    if (ctxt->instate == XML_PARSER_EOF)
12170
        goto done;
12171
    ctxt->instate = XML_PARSER_PROLOG;
12172
    ctxt->checkIndex = 0;
12173
#ifdef DEBUG_PUSH
12174
    xmlGenericError(xmlGenericErrorContext,
12175
      "PP: entering PROLOG\n");
12176
#endif
12177
                break;
12178
      }
12179
            case XML_PARSER_COMMENT:
12180
    xmlGenericError(xmlGenericErrorContext,
12181
      "PP: internal error, state == COMMENT\n");
12182
    ctxt->instate = XML_PARSER_CONTENT;
12183
#ifdef DEBUG_PUSH
12184
    xmlGenericError(xmlGenericErrorContext,
12185
      "PP: entering CONTENT\n");
12186
#endif
12187
    break;
12188
            case XML_PARSER_IGNORE:
12189
    xmlGenericError(xmlGenericErrorContext,
12190
      "PP: internal error, state == IGNORE");
12191
          ctxt->instate = XML_PARSER_DTD;
12192
#ifdef DEBUG_PUSH
12193
    xmlGenericError(xmlGenericErrorContext,
12194
      "PP: entering DTD\n");
12195
#endif
12196
          break;
12197
            case XML_PARSER_PI:
12198
    xmlGenericError(xmlGenericErrorContext,
12199
      "PP: internal error, state == PI\n");
12200
    ctxt->instate = XML_PARSER_CONTENT;
12201
#ifdef DEBUG_PUSH
12202
    xmlGenericError(xmlGenericErrorContext,
12203
      "PP: entering CONTENT\n");
12204
#endif
12205
    break;
12206
            case XML_PARSER_ENTITY_DECL:
12207
    xmlGenericError(xmlGenericErrorContext,
12208
      "PP: internal error, state == ENTITY_DECL\n");
12209
    ctxt->instate = XML_PARSER_DTD;
12210
#ifdef DEBUG_PUSH
12211
    xmlGenericError(xmlGenericErrorContext,
12212
      "PP: entering DTD\n");
12213
#endif
12214
    break;
12215
            case XML_PARSER_ENTITY_VALUE:
12216
    xmlGenericError(xmlGenericErrorContext,
12217
      "PP: internal error, state == ENTITY_VALUE\n");
12218
    ctxt->instate = XML_PARSER_CONTENT;
12219
#ifdef DEBUG_PUSH
12220
    xmlGenericError(xmlGenericErrorContext,
12221
      "PP: entering DTD\n");
12222
#endif
12223
    break;
12224
            case XML_PARSER_ATTRIBUTE_VALUE:
12225
    xmlGenericError(xmlGenericErrorContext,
12226
      "PP: internal error, state == ATTRIBUTE_VALUE\n");
12227
    ctxt->instate = XML_PARSER_START_TAG;
12228
#ifdef DEBUG_PUSH
12229
    xmlGenericError(xmlGenericErrorContext,
12230
      "PP: entering START_TAG\n");
12231
#endif
12232
    break;
12233
            case XML_PARSER_SYSTEM_LITERAL:
12234
    xmlGenericError(xmlGenericErrorContext,
12235
      "PP: internal error, state == SYSTEM_LITERAL\n");
12236
    ctxt->instate = XML_PARSER_START_TAG;
12237
#ifdef DEBUG_PUSH
12238
    xmlGenericError(xmlGenericErrorContext,
12239
      "PP: entering START_TAG\n");
12240
#endif
12241
    break;
12242
            case XML_PARSER_PUBLIC_LITERAL:
12243
    xmlGenericError(xmlGenericErrorContext,
12244
      "PP: internal error, state == PUBLIC_LITERAL\n");
12245
    ctxt->instate = XML_PARSER_START_TAG;
12246
#ifdef DEBUG_PUSH
12247
    xmlGenericError(xmlGenericErrorContext,
12248
      "PP: entering START_TAG\n");
12249
#endif
12250
    break;
12251
  }
12252
    }
12253
done:
12254
#ifdef DEBUG_PUSH
12255
    xmlGenericError(xmlGenericErrorContext, "PP: done %d\n", ret);
12256
#endif
12257
    return(ret);
12258
encoding_error:
12259
    {
12260
        char buffer[150];
12261
12262
  snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
12263
      ctxt->input->cur[0], ctxt->input->cur[1],
12264
      ctxt->input->cur[2], ctxt->input->cur[3]);
12265
  __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
12266
         "Input is not proper UTF-8, indicate encoding !\n%s",
12267
         BAD_CAST buffer, NULL);
12268
    }
12269
    return(0);
12270
}
12271
12272
/**
12273
 * xmlParseCheckTransition:
12274
 * @ctxt:  an XML parser context
12275
 * @chunk:  a char array
12276
 * @size:  the size in byte of the chunk
12277
 *
12278
 * Check depending on the current parser state if the chunk given must be
12279
 * processed immediately or one need more data to advance on parsing.
12280
 *
12281
 * Returns -1 in case of error, 0 if the push is not needed and 1 if needed
12282
 */
12283
static int
12284
xmlParseCheckTransition(xmlParserCtxtPtr ctxt, const char *chunk, int size) {
12285
    if ((ctxt == NULL) || (chunk == NULL) || (size < 0))
12286
        return(-1);
12287
    if (ctxt->instate == XML_PARSER_START_TAG) {
12288
        if (memchr(chunk, '>', size) != NULL)
12289
            return(1);
12290
        return(0);
12291
    }
12292
    if (ctxt->progressive == XML_PARSER_COMMENT) {
12293
        if (memchr(chunk, '>', size) != NULL)
12294
            return(1);
12295
        return(0);
12296
    }
12297
    if (ctxt->instate == XML_PARSER_CDATA_SECTION) {
12298
        if (memchr(chunk, '>', size) != NULL)
12299
            return(1);
12300
        return(0);
12301
    }
12302
    if (ctxt->progressive == XML_PARSER_PI) {
12303
        if (memchr(chunk, '>', size) != NULL)
12304
            return(1);
12305
        return(0);
12306
    }
12307
    if (ctxt->instate == XML_PARSER_END_TAG) {
12308
        if (memchr(chunk, '>', size) != NULL)
12309
            return(1);
12310
        return(0);
12311
    }
12312
    if ((ctxt->progressive == XML_PARSER_DTD) ||
12313
        (ctxt->instate == XML_PARSER_DTD)) {
12314
        if (memchr(chunk, '>', size) != NULL)
12315
            return(1);
12316
        return(0);
12317
    }
12318
    return(1);
12319
}
12320
12321
/**
12322
 * xmlParseChunk:
12323
 * @ctxt:  an XML parser context
12324
 * @chunk:  an char array
12325
 * @size:  the size in byte of the chunk
12326
 * @terminate:  last chunk indicator
12327
 *
12328
 * Parse a Chunk of memory
12329
 *
12330
 * Returns zero if no error, the xmlParserErrors otherwise.
12331
 */
12332
int
12333
xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
12334
              int terminate) {
12335
    int end_in_lf = 0;
12336
    int remain = 0;
12337
    size_t old_avail = 0;
12338
    size_t avail = 0;
12339
12340
    if (ctxt == NULL)
12341
        return(XML_ERR_INTERNAL_ERROR);
12342
    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
12343
        return(ctxt->errNo);
12344
    if (ctxt->instate == XML_PARSER_EOF)
12345
        return(-1);
12346
    if (ctxt->instate == XML_PARSER_START)
12347
        xmlDetectSAX2(ctxt);
12348
    if ((size > 0) && (chunk != NULL) && (!terminate) &&
12349
        (chunk[size - 1] == '\r')) {
12350
  end_in_lf = 1;
12351
  size--;
12352
    }
12353
12354
xmldecl_done:
12355
12356
    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
12357
        (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF))  {
12358
  size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
12359
  size_t cur = ctxt->input->cur - ctxt->input->base;
12360
  int res;
12361
12362
        old_avail = xmlBufUse(ctxt->input->buf->buffer);
12363
        /*
12364
         * Specific handling if we autodetected an encoding, we should not
12365
         * push more than the first line ... which depend on the encoding
12366
         * And only push the rest once the final encoding was detected
12367
         */
12368
        if ((ctxt->instate == XML_PARSER_START) && (ctxt->input != NULL) &&
12369
            (ctxt->input->buf != NULL) && (ctxt->input->buf->encoder != NULL)) {
12370
            unsigned int len = 45;
12371
12372
            if ((xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
12373
                               BAD_CAST "UTF-16")) ||
12374
                (xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
12375
                               BAD_CAST "UTF16")))
12376
                len = 90;
12377
            else if ((xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
12378
                                    BAD_CAST "UCS-4")) ||
12379
                     (xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
12380
                                    BAD_CAST "UCS4")))
12381
                len = 180;
12382
12383
            if (ctxt->input->buf->rawconsumed < len)
12384
                len -= ctxt->input->buf->rawconsumed;
12385
12386
            /*
12387
             * Change size for reading the initial declaration only
12388
             * if size is greater than len. Otherwise, memmove in xmlBufferAdd
12389
             * will blindly copy extra bytes from memory.
12390
             */
12391
            if ((unsigned int) size > len) {
12392
                remain = size - len;
12393
                size = len;
12394
            } else {
12395
                remain = 0;
12396
            }
12397
        }
12398
  res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
12399
        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
12400
  if (res < 0) {
12401
      ctxt->errNo = XML_PARSER_EOF;
12402
      xmlHaltParser(ctxt);
12403
      return (XML_PARSER_EOF);
12404
  }
12405
#ifdef DEBUG_PUSH
12406
  xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
12407
#endif
12408
12409
    } else if (ctxt->instate != XML_PARSER_EOF) {
12410
  if ((ctxt->input != NULL) && ctxt->input->buf != NULL) {
12411
      xmlParserInputBufferPtr in = ctxt->input->buf;
12412
      if ((in->encoder != NULL) && (in->buffer != NULL) &&
12413
        (in->raw != NULL)) {
12414
    int nbchars;
12415
    size_t base = xmlBufGetInputBase(in->buffer, ctxt->input);
12416
    size_t current = ctxt->input->cur - ctxt->input->base;
12417
12418
    nbchars = xmlCharEncInput(in, terminate);
12419
    xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
12420
    if (nbchars < 0) {
12421
        /* TODO 2.6.0 */
12422
        xmlGenericError(xmlGenericErrorContext,
12423
            "xmlParseChunk: encoder error\n");
12424
                    xmlHaltParser(ctxt);
12425
        return(XML_ERR_INVALID_ENCODING);
12426
    }
12427
      }
12428
  }
12429
    }
12430
    if (remain != 0) {
12431
        xmlParseTryOrFinish(ctxt, 0);
12432
    } else {
12433
        if ((ctxt->input != NULL) && (ctxt->input->buf != NULL))
12434
            avail = xmlBufUse(ctxt->input->buf->buffer);
12435
        /*
12436
         * Depending on the current state it may not be such
12437
         * a good idea to try parsing if there is nothing in the chunk
12438
         * which would be worth doing a parser state transition and we
12439
         * need to wait for more data
12440
         */
12441
        if ((terminate) || (avail > XML_MAX_TEXT_LENGTH) ||
12442
            (old_avail == 0) || (avail == 0) ||
12443
            (xmlParseCheckTransition(ctxt,
12444
                       (const char *)&ctxt->input->base[old_avail],
12445
                                     avail - old_avail)))
12446
            xmlParseTryOrFinish(ctxt, terminate);
12447
    }
12448
    if (ctxt->instate == XML_PARSER_EOF)
12449
        return(ctxt->errNo);
12450
12451
    if ((ctxt->input != NULL) &&
12452
         (((ctxt->input->end - ctxt->input->cur) > XML_MAX_LOOKUP_LIMIT) ||
12453
         ((ctxt->input->cur - ctxt->input->base) > XML_MAX_LOOKUP_LIMIT)) &&
12454
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
12455
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
12456
        xmlHaltParser(ctxt);
12457
    }
12458
    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
12459
        return(ctxt->errNo);
12460
12461
    if (remain != 0) {
12462
        chunk += size;
12463
        size = remain;
12464
        remain = 0;
12465
        goto xmldecl_done;
12466
    }
12467
    if ((end_in_lf == 1) && (ctxt->input != NULL) &&
12468
        (ctxt->input->buf != NULL)) {
12469
  size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer,
12470
           ctxt->input);
12471
  size_t current = ctxt->input->cur - ctxt->input->base;
12472
12473
  xmlParserInputBufferPush(ctxt->input->buf, 1, "\r");
12474
12475
  xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input,
12476
            base, current);
12477
    }
12478
    if (terminate) {
12479
  /*
12480
   * Check for termination
12481
   */
12482
  int cur_avail = 0;
12483
12484
  if (ctxt->input != NULL) {
12485
      if (ctxt->input->buf == NULL)
12486
    cur_avail = ctxt->input->length -
12487
          (ctxt->input->cur - ctxt->input->base);
12488
      else
12489
    cur_avail = xmlBufUse(ctxt->input->buf->buffer) -
12490
                    (ctxt->input->cur - ctxt->input->base);
12491
  }
12492
12493
  if ((ctxt->instate != XML_PARSER_EOF) &&
12494
      (ctxt->instate != XML_PARSER_EPILOG)) {
12495
      xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
12496
  }
12497
  if ((ctxt->instate == XML_PARSER_EPILOG) && (cur_avail > 0)) {
12498
      xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
12499
  }
12500
  if (ctxt->instate != XML_PARSER_EOF) {
12501
      if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
12502
    ctxt->sax->endDocument(ctxt->userData);
12503
  }
12504
  ctxt->instate = XML_PARSER_EOF;
12505
    }
12506
    if (ctxt->wellFormed == 0)
12507
  return((xmlParserErrors) ctxt->errNo);
12508
    else
12509
        return(0);
12510
}
12511
12512
/************************************************************************
12513
 *                  *
12514
 *    I/O front end functions to the parser     *
12515
 *                  *
12516
 ************************************************************************/
12517
12518
/**
12519
 * xmlCreatePushParserCtxt:
12520
 * @sax:  a SAX handler
12521
 * @user_data:  The user data returned on SAX callbacks
12522
 * @chunk:  a pointer to an array of chars
12523
 * @size:  number of chars in the array
12524
 * @filename:  an optional file name or URI
12525
 *
12526
 * Create a parser context for using the XML parser in push mode.
12527
 * If @buffer and @size are non-NULL, the data is used to detect
12528
 * the encoding.  The remaining characters will be parsed so they
12529
 * don't need to be fed in again through xmlParseChunk.
12530
 * To allow content encoding detection, @size should be >= 4
12531
 * The value of @filename is used for fetching external entities
12532
 * and error/warning reports.
12533
 *
12534
 * Returns the new parser context or NULL
12535
 */
12536
12537
xmlParserCtxtPtr
12538
xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
12539
                        const char *chunk, int size, const char *filename) {
12540
    xmlParserCtxtPtr ctxt;
12541
    xmlParserInputPtr inputStream;
12542
    xmlParserInputBufferPtr buf;
12543
    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
12544
12545
    /*
12546
     * plug some encoding conversion routines
12547
     */
12548
    if ((chunk != NULL) && (size >= 4))
12549
  enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
12550
12551
    buf = xmlAllocParserInputBuffer(enc);
12552
    if (buf == NULL) return(NULL);
12553
12554
    ctxt = xmlNewSAXParserCtxt(sax, user_data);
12555
    if (ctxt == NULL) {
12556
        xmlErrMemory(NULL, "creating parser: out of memory\n");
12557
  xmlFreeParserInputBuffer(buf);
12558
  return(NULL);
12559
    }
12560
    ctxt->dictNames = 1;
12561
    if (filename == NULL) {
12562
  ctxt->directory = NULL;
12563
    } else {
12564
        ctxt->directory = xmlParserGetDirectory(filename);
12565
    }
12566
12567
    inputStream = xmlNewInputStream(ctxt);
12568
    if (inputStream == NULL) {
12569
  xmlFreeParserCtxt(ctxt);
12570
  xmlFreeParserInputBuffer(buf);
12571
  return(NULL);
12572
    }
12573
12574
    if (filename == NULL)
12575
  inputStream->filename = NULL;
12576
    else {
12577
  inputStream->filename = (char *)
12578
      xmlCanonicPath((const xmlChar *) filename);
12579
  if (inputStream->filename == NULL) {
12580
            xmlFreeInputStream(inputStream);
12581
      xmlFreeParserCtxt(ctxt);
12582
      xmlFreeParserInputBuffer(buf);
12583
      return(NULL);
12584
  }
12585
    }
12586
    inputStream->buf = buf;
12587
    xmlBufResetInput(inputStream->buf->buffer, inputStream);
12588
    inputPush(ctxt, inputStream);
12589
12590
    /*
12591
     * If the caller didn't provide an initial 'chunk' for determining
12592
     * the encoding, we set the context to XML_CHAR_ENCODING_NONE so
12593
     * that it can be automatically determined later
12594
     */
12595
    if ((size == 0) || (chunk == NULL)) {
12596
  ctxt->charset = XML_CHAR_ENCODING_NONE;
12597
    } else if ((ctxt->input != NULL) && (ctxt->input->buf != NULL)) {
12598
  size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
12599
  size_t cur = ctxt->input->cur - ctxt->input->base;
12600
12601
  xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
12602
12603
        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
12604
#ifdef DEBUG_PUSH
12605
  xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
12606
#endif
12607
    }
12608
12609
    if (enc != XML_CHAR_ENCODING_NONE) {
12610
        xmlSwitchEncoding(ctxt, enc);
12611
    }
12612
12613
    return(ctxt);
12614
}
12615
#endif /* LIBXML_PUSH_ENABLED */
12616
12617
/**
12618
 * xmlHaltParser:
12619
 * @ctxt:  an XML parser context
12620
 *
12621
 * Blocks further parser processing don't override error
12622
 * for internal use
12623
 */
12624
static void
12625
0
xmlHaltParser(xmlParserCtxtPtr ctxt) {
12626
0
    if (ctxt == NULL)
12627
0
        return;
12628
0
    ctxt->instate = XML_PARSER_EOF;
12629
0
    ctxt->disableSAX = 1;
12630
0
    while (ctxt->inputNr > 1)
12631
0
        xmlFreeInputStream(inputPop(ctxt));
12632
0
    if (ctxt->input != NULL) {
12633
        /*
12634
   * in case there was a specific allocation deallocate before
12635
   * overriding base
12636
   */
12637
0
        if (ctxt->input->free != NULL) {
12638
0
      ctxt->input->free((xmlChar *) ctxt->input->base);
12639
0
      ctxt->input->free = NULL;
12640
0
  }
12641
0
        if (ctxt->input->buf != NULL) {
12642
0
            xmlFreeParserInputBuffer(ctxt->input->buf);
12643
0
            ctxt->input->buf = NULL;
12644
0
        }
12645
0
  ctxt->input->cur = BAD_CAST"";
12646
0
        ctxt->input->length = 0;
12647
0
  ctxt->input->base = ctxt->input->cur;
12648
0
        ctxt->input->end = ctxt->input->cur;
12649
0
    }
12650
0
}
12651
12652
/**
12653
 * xmlStopParser:
12654
 * @ctxt:  an XML parser context
12655
 *
12656
 * Blocks further parser processing
12657
 */
12658
void
12659
259
xmlStopParser(xmlParserCtxtPtr ctxt) {
12660
259
    if (ctxt == NULL)
12661
259
        return;
12662
0
    xmlHaltParser(ctxt);
12663
0
    ctxt->errNo = XML_ERR_USER_STOP;
12664
0
}
12665
12666
/**
12667
 * xmlCreateIOParserCtxt:
12668
 * @sax:  a SAX handler
12669
 * @user_data:  The user data returned on SAX callbacks
12670
 * @ioread:  an I/O read function
12671
 * @ioclose:  an I/O close function
12672
 * @ioctx:  an I/O handler
12673
 * @enc:  the charset encoding if known
12674
 *
12675
 * Create a parser context for using the XML parser with an existing
12676
 * I/O stream
12677
 *
12678
 * Returns the new parser context or NULL
12679
 */
12680
xmlParserCtxtPtr
12681
xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
12682
  xmlInputReadCallback   ioread, xmlInputCloseCallback  ioclose,
12683
0
  void *ioctx, xmlCharEncoding enc) {
12684
0
    xmlParserCtxtPtr ctxt;
12685
0
    xmlParserInputPtr inputStream;
12686
0
    xmlParserInputBufferPtr buf;
12687
12688
0
    if (ioread == NULL) return(NULL);
12689
12690
0
    buf = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, enc);
12691
0
    if (buf == NULL) {
12692
0
        if (ioclose != NULL)
12693
0
            ioclose(ioctx);
12694
0
        return (NULL);
12695
0
    }
12696
12697
0
    ctxt = xmlNewSAXParserCtxt(sax, user_data);
12698
0
    if (ctxt == NULL) {
12699
0
  xmlFreeParserInputBuffer(buf);
12700
0
  return(NULL);
12701
0
    }
12702
12703
0
    inputStream = xmlNewIOInputStream(ctxt, buf, enc);
12704
0
    if (inputStream == NULL) {
12705
0
  xmlFreeParserCtxt(ctxt);
12706
0
  return(NULL);
12707
0
    }
12708
0
    inputPush(ctxt, inputStream);
12709
12710
0
    return(ctxt);
12711
0
}
12712
12713
#ifdef LIBXML_VALID_ENABLED
12714
/************************************************************************
12715
 *                  *
12716
 *    Front ends when parsing a DTD       *
12717
 *                  *
12718
 ************************************************************************/
12719
12720
/**
12721
 * xmlIOParseDTD:
12722
 * @sax:  the SAX handler block or NULL
12723
 * @input:  an Input Buffer
12724
 * @enc:  the charset encoding if known
12725
 *
12726
 * Load and parse a DTD
12727
 *
12728
 * Returns the resulting xmlDtdPtr or NULL in case of error.
12729
 * @input will be freed by the function in any case.
12730
 */
12731
12732
xmlDtdPtr
12733
xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
12734
        xmlCharEncoding enc) {
12735
    xmlDtdPtr ret = NULL;
12736
    xmlParserCtxtPtr ctxt;
12737
    xmlParserInputPtr pinput = NULL;
12738
    xmlChar start[4];
12739
12740
    if (input == NULL)
12741
  return(NULL);
12742
12743
    ctxt = xmlNewSAXParserCtxt(sax, NULL);
12744
    if (ctxt == NULL) {
12745
        xmlFreeParserInputBuffer(input);
12746
  return(NULL);
12747
    }
12748
12749
    /* We are loading a DTD */
12750
    ctxt->options |= XML_PARSE_DTDLOAD;
12751
12752
    xmlDetectSAX2(ctxt);
12753
12754
    /*
12755
     * generate a parser input from the I/O handler
12756
     */
12757
12758
    pinput = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
12759
    if (pinput == NULL) {
12760
        xmlFreeParserInputBuffer(input);
12761
  xmlFreeParserCtxt(ctxt);
12762
  return(NULL);
12763
    }
12764
12765
    /*
12766
     * plug some encoding conversion routines here.
12767
     */
12768
    if (xmlPushInput(ctxt, pinput) < 0) {
12769
  xmlFreeParserCtxt(ctxt);
12770
  return(NULL);
12771
    }
12772
    if (enc != XML_CHAR_ENCODING_NONE) {
12773
        xmlSwitchEncoding(ctxt, enc);
12774
    }
12775
12776
    pinput->filename = NULL;
12777
    pinput->line = 1;
12778
    pinput->col = 1;
12779
    pinput->base = ctxt->input->cur;
12780
    pinput->cur = ctxt->input->cur;
12781
    pinput->free = NULL;
12782
12783
    /*
12784
     * let's parse that entity knowing it's an external subset.
12785
     */
12786
    ctxt->inSubset = 2;
12787
    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
12788
    if (ctxt->myDoc == NULL) {
12789
  xmlErrMemory(ctxt, "New Doc failed");
12790
  return(NULL);
12791
    }
12792
    ctxt->myDoc->properties = XML_DOC_INTERNAL;
12793
    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
12794
                                 BAD_CAST "none", BAD_CAST "none");
12795
12796
    if ((enc == XML_CHAR_ENCODING_NONE) &&
12797
        ((ctxt->input->end - ctxt->input->cur) >= 4)) {
12798
  /*
12799
   * Get the 4 first bytes and decode the charset
12800
   * if enc != XML_CHAR_ENCODING_NONE
12801
   * plug some encoding conversion routines.
12802
   */
12803
  start[0] = RAW;
12804
  start[1] = NXT(1);
12805
  start[2] = NXT(2);
12806
  start[3] = NXT(3);
12807
  enc = xmlDetectCharEncoding(start, 4);
12808
  if (enc != XML_CHAR_ENCODING_NONE) {
12809
      xmlSwitchEncoding(ctxt, enc);
12810
  }
12811
    }
12812
12813
    xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none");
12814
12815
    if (ctxt->myDoc != NULL) {
12816
  if (ctxt->wellFormed) {
12817
      ret = ctxt->myDoc->extSubset;
12818
      ctxt->myDoc->extSubset = NULL;
12819
      if (ret != NULL) {
12820
    xmlNodePtr tmp;
12821
12822
    ret->doc = NULL;
12823
    tmp = ret->children;
12824
    while (tmp != NULL) {
12825
        tmp->doc = NULL;
12826
        tmp = tmp->next;
12827
    }
12828
      }
12829
  } else {
12830
      ret = NULL;
12831
  }
12832
        xmlFreeDoc(ctxt->myDoc);
12833
        ctxt->myDoc = NULL;
12834
    }
12835
    xmlFreeParserCtxt(ctxt);
12836
12837
    return(ret);
12838
}
12839
12840
/**
12841
 * xmlSAXParseDTD:
12842
 * @sax:  the SAX handler block
12843
 * @ExternalID:  a NAME* containing the External ID of the DTD
12844
 * @SystemID:  a NAME* containing the URL to the DTD
12845
 *
12846
 * DEPRECATED: Don't use.
12847
 *
12848
 * Load and parse an external subset.
12849
 *
12850
 * Returns the resulting xmlDtdPtr or NULL in case of error.
12851
 */
12852
12853
xmlDtdPtr
12854
xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
12855
                          const xmlChar *SystemID) {
12856
    xmlDtdPtr ret = NULL;
12857
    xmlParserCtxtPtr ctxt;
12858
    xmlParserInputPtr input = NULL;
12859
    xmlCharEncoding enc;
12860
    xmlChar* systemIdCanonic;
12861
12862
    if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
12863
12864
    ctxt = xmlNewSAXParserCtxt(sax, NULL);
12865
    if (ctxt == NULL) {
12866
  return(NULL);
12867
    }
12868
12869
    /* We are loading a DTD */
12870
    ctxt->options |= XML_PARSE_DTDLOAD;
12871
12872
    /*
12873
     * Canonicalise the system ID
12874
     */
12875
    systemIdCanonic = xmlCanonicPath(SystemID);
12876
    if ((SystemID != NULL) && (systemIdCanonic == NULL)) {
12877
  xmlFreeParserCtxt(ctxt);
12878
  return(NULL);
12879
    }
12880
12881
    /*
12882
     * Ask the Entity resolver to load the damn thing
12883
     */
12884
12885
    if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
12886
  input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
12887
                                   systemIdCanonic);
12888
    if (input == NULL) {
12889
  xmlFreeParserCtxt(ctxt);
12890
  if (systemIdCanonic != NULL)
12891
      xmlFree(systemIdCanonic);
12892
  return(NULL);
12893
    }
12894
12895
    /*
12896
     * plug some encoding conversion routines here.
12897
     */
12898
    if (xmlPushInput(ctxt, input) < 0) {
12899
  xmlFreeParserCtxt(ctxt);
12900
  if (systemIdCanonic != NULL)
12901
      xmlFree(systemIdCanonic);
12902
  return(NULL);
12903
    }
12904
    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
12905
  enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
12906
  xmlSwitchEncoding(ctxt, enc);
12907
    }
12908
12909
    if (input->filename == NULL)
12910
  input->filename = (char *) systemIdCanonic;
12911
    else
12912
  xmlFree(systemIdCanonic);
12913
    input->line = 1;
12914
    input->col = 1;
12915
    input->base = ctxt->input->cur;
12916
    input->cur = ctxt->input->cur;
12917
    input->free = NULL;
12918
12919
    /*
12920
     * let's parse that entity knowing it's an external subset.
12921
     */
12922
    ctxt->inSubset = 2;
12923
    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
12924
    if (ctxt->myDoc == NULL) {
12925
  xmlErrMemory(ctxt, "New Doc failed");
12926
  xmlFreeParserCtxt(ctxt);
12927
  return(NULL);
12928
    }
12929
    ctxt->myDoc->properties = XML_DOC_INTERNAL;
12930
    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
12931
                                 ExternalID, SystemID);
12932
    xmlParseExternalSubset(ctxt, ExternalID, SystemID);
12933
12934
    if (ctxt->myDoc != NULL) {
12935
  if (ctxt->wellFormed) {
12936
      ret = ctxt->myDoc->extSubset;
12937
      ctxt->myDoc->extSubset = NULL;
12938
      if (ret != NULL) {
12939
    xmlNodePtr tmp;
12940
12941
    ret->doc = NULL;
12942
    tmp = ret->children;
12943
    while (tmp != NULL) {
12944
        tmp->doc = NULL;
12945
        tmp = tmp->next;
12946
    }
12947
      }
12948
  } else {
12949
      ret = NULL;
12950
  }
12951
        xmlFreeDoc(ctxt->myDoc);
12952
        ctxt->myDoc = NULL;
12953
    }
12954
    xmlFreeParserCtxt(ctxt);
12955
12956
    return(ret);
12957
}
12958
12959
12960
/**
12961
 * xmlParseDTD:
12962
 * @ExternalID:  a NAME* containing the External ID of the DTD
12963
 * @SystemID:  a NAME* containing the URL to the DTD
12964
 *
12965
 * Load and parse an external subset.
12966
 *
12967
 * Returns the resulting xmlDtdPtr or NULL in case of error.
12968
 */
12969
12970
xmlDtdPtr
12971
xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
12972
    return(xmlSAXParseDTD(NULL, ExternalID, SystemID));
12973
}
12974
#endif /* LIBXML_VALID_ENABLED */
12975
12976
/************************************************************************
12977
 *                  *
12978
 *    Front ends when parsing an Entity     *
12979
 *                  *
12980
 ************************************************************************/
12981
12982
/**
12983
 * xmlParseCtxtExternalEntity:
12984
 * @ctx:  the existing parsing context
12985
 * @URL:  the URL for the entity to load
12986
 * @ID:  the System ID for the entity to load
12987
 * @lst:  the return value for the set of parsed nodes
12988
 *
12989
 * Parse an external general entity within an existing parsing context
12990
 * An external general parsed entity is well-formed if it matches the
12991
 * production labeled extParsedEnt.
12992
 *
12993
 * [78] extParsedEnt ::= TextDecl? content
12994
 *
12995
 * Returns 0 if the entity is well formed, -1 in case of args problem and
12996
 *    the parser error code otherwise
12997
 */
12998
12999
int
13000
xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
13001
0
                 const xmlChar *ID, xmlNodePtr *lst) {
13002
0
    void *userData;
13003
13004
0
    if (ctx == NULL) return(-1);
13005
    /*
13006
     * If the user provided their own SAX callbacks, then reuse the
13007
     * userData callback field, otherwise the expected setup in a
13008
     * DOM builder is to have userData == ctxt
13009
     */
13010
0
    if (ctx->userData == ctx)
13011
0
        userData = NULL;
13012
0
    else
13013
0
        userData = ctx->userData;
13014
0
    return xmlParseExternalEntityPrivate(ctx->myDoc, ctx, ctx->sax,
13015
0
                                         userData, ctx->depth + 1,
13016
0
                                         URL, ID, lst);
13017
0
}
13018
13019
/**
13020
 * xmlParseExternalEntityPrivate:
13021
 * @doc:  the document the chunk pertains to
13022
 * @oldctxt:  the previous parser context if available
13023
 * @sax:  the SAX handler block (possibly NULL)
13024
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
13025
 * @depth:  Used for loop detection, use 0
13026
 * @URL:  the URL for the entity to load
13027
 * @ID:  the System ID for the entity to load
13028
 * @list:  the return value for the set of parsed nodes
13029
 *
13030
 * Private version of xmlParseExternalEntity()
13031
 *
13032
 * Returns 0 if the entity is well formed, -1 in case of args problem and
13033
 *    the parser error code otherwise
13034
 */
13035
13036
static xmlParserErrors
13037
xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
13038
                xmlSAXHandlerPtr sax,
13039
          void *user_data, int depth, const xmlChar *URL,
13040
0
          const xmlChar *ID, xmlNodePtr *list) {
13041
0
    xmlParserCtxtPtr ctxt;
13042
0
    xmlDocPtr newDoc;
13043
0
    xmlNodePtr newRoot;
13044
0
    xmlParserErrors ret = XML_ERR_OK;
13045
0
    xmlChar start[4];
13046
0
    xmlCharEncoding enc;
13047
13048
0
    if (((depth > 40) &&
13049
0
  ((oldctxt == NULL) || (oldctxt->options & XML_PARSE_HUGE) == 0)) ||
13050
0
  (depth > 1024)) {
13051
0
  return(XML_ERR_ENTITY_LOOP);
13052
0
    }
13053
13054
0
    if (list != NULL)
13055
0
        *list = NULL;
13056
0
    if ((URL == NULL) && (ID == NULL))
13057
0
  return(XML_ERR_INTERNAL_ERROR);
13058
0
    if (doc == NULL)
13059
0
  return(XML_ERR_INTERNAL_ERROR);
13060
13061
0
    ctxt = xmlCreateEntityParserCtxtInternal(sax, user_data, URL, ID, NULL,
13062
0
                                             oldctxt);
13063
0
    if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
13064
0
    xmlDetectSAX2(ctxt);
13065
13066
0
    newDoc = xmlNewDoc(BAD_CAST "1.0");
13067
0
    if (newDoc == NULL) {
13068
0
  xmlFreeParserCtxt(ctxt);
13069
0
  return(XML_ERR_INTERNAL_ERROR);
13070
0
    }
13071
0
    newDoc->properties = XML_DOC_INTERNAL;
13072
0
    if (doc) {
13073
0
        newDoc->intSubset = doc->intSubset;
13074
0
        newDoc->extSubset = doc->extSubset;
13075
0
        if (doc->dict) {
13076
0
            newDoc->dict = doc->dict;
13077
0
            xmlDictReference(newDoc->dict);
13078
0
        }
13079
0
        if (doc->URL != NULL) {
13080
0
            newDoc->URL = xmlStrdup(doc->URL);
13081
0
        }
13082
0
    }
13083
0
    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
13084
0
    if (newRoot == NULL) {
13085
0
  if (sax != NULL)
13086
0
  xmlFreeParserCtxt(ctxt);
13087
0
  newDoc->intSubset = NULL;
13088
0
  newDoc->extSubset = NULL;
13089
0
        xmlFreeDoc(newDoc);
13090
0
  return(XML_ERR_INTERNAL_ERROR);
13091
0
    }
13092
0
    xmlAddChild((xmlNodePtr) newDoc, newRoot);
13093
0
    nodePush(ctxt, newDoc->children);
13094
0
    if (doc == NULL) {
13095
0
        ctxt->myDoc = newDoc;
13096
0
    } else {
13097
0
        ctxt->myDoc = doc;
13098
0
        newRoot->doc = doc;
13099
0
    }
13100
13101
    /*
13102
     * Get the 4 first bytes and decode the charset
13103
     * if enc != XML_CHAR_ENCODING_NONE
13104
     * plug some encoding conversion routines.
13105
     */
13106
0
    GROW;
13107
0
    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
13108
0
  start[0] = RAW;
13109
0
  start[1] = NXT(1);
13110
0
  start[2] = NXT(2);
13111
0
  start[3] = NXT(3);
13112
0
  enc = xmlDetectCharEncoding(start, 4);
13113
0
  if (enc != XML_CHAR_ENCODING_NONE) {
13114
0
      xmlSwitchEncoding(ctxt, enc);
13115
0
  }
13116
0
    }
13117
13118
    /*
13119
     * Parse a possible text declaration first
13120
     */
13121
0
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
13122
0
  xmlParseTextDecl(ctxt);
13123
        /*
13124
         * An XML-1.0 document can't reference an entity not XML-1.0
13125
         */
13126
0
        if ((xmlStrEqual(oldctxt->version, BAD_CAST "1.0")) &&
13127
0
            (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) {
13128
0
            xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH,
13129
0
                           "Version mismatch between document and entity\n");
13130
0
        }
13131
0
    }
13132
13133
0
    ctxt->instate = XML_PARSER_CONTENT;
13134
0
    ctxt->depth = depth;
13135
0
    if (oldctxt != NULL) {
13136
0
  ctxt->_private = oldctxt->_private;
13137
0
  ctxt->loadsubset = oldctxt->loadsubset;
13138
0
  ctxt->validate = oldctxt->validate;
13139
0
  ctxt->valid = oldctxt->valid;
13140
0
  ctxt->replaceEntities = oldctxt->replaceEntities;
13141
0
        if (oldctxt->validate) {
13142
0
            ctxt->vctxt.error = oldctxt->vctxt.error;
13143
0
            ctxt->vctxt.warning = oldctxt->vctxt.warning;
13144
0
            ctxt->vctxt.userData = oldctxt->vctxt.userData;
13145
0
        }
13146
0
  ctxt->external = oldctxt->external;
13147
0
        if (ctxt->dict) xmlDictFree(ctxt->dict);
13148
0
        ctxt->dict = oldctxt->dict;
13149
0
        ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
13150
0
        ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
13151
0
        ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
13152
0
        ctxt->dictNames = oldctxt->dictNames;
13153
0
        ctxt->attsDefault = oldctxt->attsDefault;
13154
0
        ctxt->attsSpecial = oldctxt->attsSpecial;
13155
0
        ctxt->linenumbers = oldctxt->linenumbers;
13156
0
  ctxt->record_info = oldctxt->record_info;
13157
0
  ctxt->node_seq.maximum = oldctxt->node_seq.maximum;
13158
0
  ctxt->node_seq.length = oldctxt->node_seq.length;
13159
0
  ctxt->node_seq.buffer = oldctxt->node_seq.buffer;
13160
0
    } else {
13161
  /*
13162
   * Doing validity checking on chunk without context
13163
   * doesn't make sense
13164
   */
13165
0
  ctxt->_private = NULL;
13166
0
  ctxt->validate = 0;
13167
0
  ctxt->external = 2;
13168
0
  ctxt->loadsubset = 0;
13169
0
    }
13170
13171
0
    xmlParseContent(ctxt);
13172
13173
0
    if ((RAW == '<') && (NXT(1) == '/')) {
13174
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13175
0
    } else if (RAW != 0) {
13176
0
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13177
0
    }
13178
0
    if (ctxt->node != newDoc->children) {
13179
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13180
0
    }
13181
13182
0
    if (!ctxt->wellFormed) {
13183
0
        if (ctxt->errNo == 0)
13184
0
      ret = XML_ERR_INTERNAL_ERROR;
13185
0
  else
13186
0
      ret = (xmlParserErrors)ctxt->errNo;
13187
0
    } else {
13188
0
  if (list != NULL) {
13189
0
      xmlNodePtr cur;
13190
13191
      /*
13192
       * Return the newly created nodeset after unlinking it from
13193
       * they pseudo parent.
13194
       */
13195
0
      cur = newDoc->children->children;
13196
0
      *list = cur;
13197
0
      while (cur != NULL) {
13198
0
    cur->parent = NULL;
13199
0
    cur = cur->next;
13200
0
      }
13201
0
            newDoc->children->children = NULL;
13202
0
  }
13203
0
  ret = XML_ERR_OK;
13204
0
    }
13205
13206
    /*
13207
     * Record in the parent context the number of entities replacement
13208
     * done when parsing that reference.
13209
     */
13210
0
    if (oldctxt != NULL)
13211
0
        oldctxt->nbentities += ctxt->nbentities;
13212
13213
    /*
13214
     * Also record the size of the entity parsed
13215
     */
13216
0
    if (ctxt->input != NULL && oldctxt != NULL) {
13217
0
  oldctxt->sizeentities += ctxt->input->consumed;
13218
0
  oldctxt->sizeentities += (ctxt->input->cur - ctxt->input->base);
13219
0
    }
13220
    /*
13221
     * And record the last error if any
13222
     */
13223
0
    if ((oldctxt != NULL) && (ctxt->lastError.code != XML_ERR_OK))
13224
0
        xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
13225
13226
0
    if (oldctxt != NULL) {
13227
0
        ctxt->dict = NULL;
13228
0
        ctxt->attsDefault = NULL;
13229
0
        ctxt->attsSpecial = NULL;
13230
0
        oldctxt->validate = ctxt->validate;
13231
0
        oldctxt->valid = ctxt->valid;
13232
0
        oldctxt->node_seq.maximum = ctxt->node_seq.maximum;
13233
0
        oldctxt->node_seq.length = ctxt->node_seq.length;
13234
0
        oldctxt->node_seq.buffer = ctxt->node_seq.buffer;
13235
0
    }
13236
0
    ctxt->node_seq.maximum = 0;
13237
0
    ctxt->node_seq.length = 0;
13238
0
    ctxt->node_seq.buffer = NULL;
13239
0
    xmlFreeParserCtxt(ctxt);
13240
0
    newDoc->intSubset = NULL;
13241
0
    newDoc->extSubset = NULL;
13242
0
    xmlFreeDoc(newDoc);
13243
13244
0
    return(ret);
13245
0
}
13246
13247
#ifdef LIBXML_SAX1_ENABLED
13248
/**
13249
 * xmlParseExternalEntity:
13250
 * @doc:  the document the chunk pertains to
13251
 * @sax:  the SAX handler block (possibly NULL)
13252
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
13253
 * @depth:  Used for loop detection, use 0
13254
 * @URL:  the URL for the entity to load
13255
 * @ID:  the System ID for the entity to load
13256
 * @lst:  the return value for the set of parsed nodes
13257
 *
13258
 * Parse an external general entity
13259
 * An external general parsed entity is well-formed if it matches the
13260
 * production labeled extParsedEnt.
13261
 *
13262
 * [78] extParsedEnt ::= TextDecl? content
13263
 *
13264
 * Returns 0 if the entity is well formed, -1 in case of args problem and
13265
 *    the parser error code otherwise
13266
 */
13267
13268
int
13269
xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data,
13270
    int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *lst) {
13271
    return(xmlParseExternalEntityPrivate(doc, NULL, sax, user_data, depth, URL,
13272
                           ID, lst));
13273
}
13274
13275
/**
13276
 * xmlParseBalancedChunkMemory:
13277
 * @doc:  the document the chunk pertains to (must not be NULL)
13278
 * @sax:  the SAX handler block (possibly NULL)
13279
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
13280
 * @depth:  Used for loop detection, use 0
13281
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
13282
 * @lst:  the return value for the set of parsed nodes
13283
 *
13284
 * Parse a well-balanced chunk of an XML document
13285
 * called by the parser
13286
 * The allowed sequence for the Well Balanced Chunk is the one defined by
13287
 * the content production in the XML grammar:
13288
 *
13289
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13290
 *
13291
 * Returns 0 if the chunk is well balanced, -1 in case of args problem and
13292
 *    the parser error code otherwise
13293
 */
13294
13295
int
13296
xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax,
13297
     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst) {
13298
    return xmlParseBalancedChunkMemoryRecover( doc, sax, user_data,
13299
                                                depth, string, lst, 0 );
13300
}
13301
#endif /* LIBXML_SAX1_ENABLED */
13302
13303
/**
13304
 * xmlParseBalancedChunkMemoryInternal:
13305
 * @oldctxt:  the existing parsing context
13306
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
13307
 * @user_data:  the user data field for the parser context
13308
 * @lst:  the return value for the set of parsed nodes
13309
 *
13310
 *
13311
 * Parse a well-balanced chunk of an XML document
13312
 * called by the parser
13313
 * The allowed sequence for the Well Balanced Chunk is the one defined by
13314
 * the content production in the XML grammar:
13315
 *
13316
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13317
 *
13318
 * Returns XML_ERR_OK if the chunk is well balanced, and the parser
13319
 * error code otherwise
13320
 *
13321
 * In case recover is set to 1, the nodelist will not be empty even if
13322
 * the parsed chunk is not well balanced.
13323
 */
13324
static xmlParserErrors
13325
xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
13326
0
  const xmlChar *string, void *user_data, xmlNodePtr *lst) {
13327
0
    xmlParserCtxtPtr ctxt;
13328
0
    xmlDocPtr newDoc = NULL;
13329
0
    xmlNodePtr newRoot;
13330
0
    xmlSAXHandlerPtr oldsax = NULL;
13331
0
    xmlNodePtr content = NULL;
13332
0
    xmlNodePtr last = NULL;
13333
0
    int size;
13334
0
    xmlParserErrors ret = XML_ERR_OK;
13335
0
#ifdef SAX2
13336
0
    int i;
13337
0
#endif
13338
13339
0
    if (((oldctxt->depth > 40) && ((oldctxt->options & XML_PARSE_HUGE) == 0)) ||
13340
0
        (oldctxt->depth >  1024)) {
13341
0
  return(XML_ERR_ENTITY_LOOP);
13342
0
    }
13343
13344
13345
0
    if (lst != NULL)
13346
0
        *lst = NULL;
13347
0
    if (string == NULL)
13348
0
        return(XML_ERR_INTERNAL_ERROR);
13349
13350
0
    size = xmlStrlen(string);
13351
13352
0
    ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
13353
0
    if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
13354
0
    if (user_data != NULL)
13355
0
  ctxt->userData = user_data;
13356
0
    else
13357
0
  ctxt->userData = ctxt;
13358
0
    if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
13359
0
    ctxt->dict = oldctxt->dict;
13360
0
    ctxt->input_id = oldctxt->input_id + 1;
13361
0
    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
13362
0
    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
13363
0
    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
13364
13365
0
#ifdef SAX2
13366
    /* propagate namespaces down the entity */
13367
0
    for (i = 0;i < oldctxt->nsNr;i += 2) {
13368
0
        nsPush(ctxt, oldctxt->nsTab[i], oldctxt->nsTab[i+1]);
13369
0
    }
13370
0
#endif
13371
13372
0
    oldsax = ctxt->sax;
13373
0
    ctxt->sax = oldctxt->sax;
13374
0
    xmlDetectSAX2(ctxt);
13375
0
    ctxt->replaceEntities = oldctxt->replaceEntities;
13376
0
    ctxt->options = oldctxt->options;
13377
13378
0
    ctxt->_private = oldctxt->_private;
13379
0
    if (oldctxt->myDoc == NULL) {
13380
0
  newDoc = xmlNewDoc(BAD_CAST "1.0");
13381
0
  if (newDoc == NULL) {
13382
0
      ctxt->sax = oldsax;
13383
0
      ctxt->dict = NULL;
13384
0
      xmlFreeParserCtxt(ctxt);
13385
0
      return(XML_ERR_INTERNAL_ERROR);
13386
0
  }
13387
0
  newDoc->properties = XML_DOC_INTERNAL;
13388
0
  newDoc->dict = ctxt->dict;
13389
0
  xmlDictReference(newDoc->dict);
13390
0
  ctxt->myDoc = newDoc;
13391
0
    } else {
13392
0
  ctxt->myDoc = oldctxt->myDoc;
13393
0
        content = ctxt->myDoc->children;
13394
0
  last = ctxt->myDoc->last;
13395
0
    }
13396
0
    newRoot = xmlNewDocNode(ctxt->myDoc, NULL, BAD_CAST "pseudoroot", NULL);
13397
0
    if (newRoot == NULL) {
13398
0
  ctxt->sax = oldsax;
13399
0
  ctxt->dict = NULL;
13400
0
  xmlFreeParserCtxt(ctxt);
13401
0
  if (newDoc != NULL) {
13402
0
      xmlFreeDoc(newDoc);
13403
0
  }
13404
0
  return(XML_ERR_INTERNAL_ERROR);
13405
0
    }
13406
0
    ctxt->myDoc->children = NULL;
13407
0
    ctxt->myDoc->last = NULL;
13408
0
    xmlAddChild((xmlNodePtr) ctxt->myDoc, newRoot);
13409
0
    nodePush(ctxt, ctxt->myDoc->children);
13410
0
    ctxt->instate = XML_PARSER_CONTENT;
13411
0
    ctxt->depth = oldctxt->depth + 1;
13412
13413
0
    ctxt->validate = 0;
13414
0
    ctxt->loadsubset = oldctxt->loadsubset;
13415
0
    if ((oldctxt->validate) || (oldctxt->replaceEntities != 0)) {
13416
  /*
13417
   * ID/IDREF registration will be done in xmlValidateElement below
13418
   */
13419
0
  ctxt->loadsubset |= XML_SKIP_IDS;
13420
0
    }
13421
0
    ctxt->dictNames = oldctxt->dictNames;
13422
0
    ctxt->attsDefault = oldctxt->attsDefault;
13423
0
    ctxt->attsSpecial = oldctxt->attsSpecial;
13424
13425
0
    xmlParseContent(ctxt);
13426
0
    if ((RAW == '<') && (NXT(1) == '/')) {
13427
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13428
0
    } else if (RAW != 0) {
13429
0
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13430
0
    }
13431
0
    if (ctxt->node != ctxt->myDoc->children) {
13432
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13433
0
    }
13434
13435
0
    if (!ctxt->wellFormed) {
13436
0
        if (ctxt->errNo == 0)
13437
0
      ret = XML_ERR_INTERNAL_ERROR;
13438
0
  else
13439
0
      ret = (xmlParserErrors)ctxt->errNo;
13440
0
    } else {
13441
0
      ret = XML_ERR_OK;
13442
0
    }
13443
13444
0
    if ((lst != NULL) && (ret == XML_ERR_OK)) {
13445
0
  xmlNodePtr cur;
13446
13447
  /*
13448
   * Return the newly created nodeset after unlinking it from
13449
   * they pseudo parent.
13450
   */
13451
0
  cur = ctxt->myDoc->children->children;
13452
0
  *lst = cur;
13453
0
  while (cur != NULL) {
13454
#ifdef LIBXML_VALID_ENABLED
13455
      if ((oldctxt->validate) && (oldctxt->wellFormed) &&
13456
    (oldctxt->myDoc) && (oldctxt->myDoc->intSubset) &&
13457
    (cur->type == XML_ELEMENT_NODE)) {
13458
    oldctxt->valid &= xmlValidateElement(&oldctxt->vctxt,
13459
      oldctxt->myDoc, cur);
13460
      }
13461
#endif /* LIBXML_VALID_ENABLED */
13462
0
      cur->parent = NULL;
13463
0
      cur = cur->next;
13464
0
  }
13465
0
  ctxt->myDoc->children->children = NULL;
13466
0
    }
13467
0
    if (ctxt->myDoc != NULL) {
13468
0
  xmlFreeNode(ctxt->myDoc->children);
13469
0
        ctxt->myDoc->children = content;
13470
0
        ctxt->myDoc->last = last;
13471
0
    }
13472
13473
    /*
13474
     * Record in the parent context the number of entities replacement
13475
     * done when parsing that reference.
13476
     */
13477
0
    if (oldctxt != NULL)
13478
0
        oldctxt->nbentities += ctxt->nbentities;
13479
13480
    /*
13481
     * Also record the last error if any
13482
     */
13483
0
    if (ctxt->lastError.code != XML_ERR_OK)
13484
0
        xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
13485
13486
0
    ctxt->sax = oldsax;
13487
0
    ctxt->dict = NULL;
13488
0
    ctxt->attsDefault = NULL;
13489
0
    ctxt->attsSpecial = NULL;
13490
0
    xmlFreeParserCtxt(ctxt);
13491
0
    if (newDoc != NULL) {
13492
0
  xmlFreeDoc(newDoc);
13493
0
    }
13494
13495
0
    return(ret);
13496
0
}
13497
13498
/**
13499
 * xmlParseInNodeContext:
13500
 * @node:  the context node
13501
 * @data:  the input string
13502
 * @datalen:  the input string length in bytes
13503
 * @options:  a combination of xmlParserOption
13504
 * @lst:  the return value for the set of parsed nodes
13505
 *
13506
 * Parse a well-balanced chunk of an XML document
13507
 * within the context (DTD, namespaces, etc ...) of the given node.
13508
 *
13509
 * The allowed sequence for the data is a Well Balanced Chunk defined by
13510
 * the content production in the XML grammar:
13511
 *
13512
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13513
 *
13514
 * Returns XML_ERR_OK if the chunk is well balanced, and the parser
13515
 * error code otherwise
13516
 */
13517
xmlParserErrors
13518
xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
13519
0
                      int options, xmlNodePtr *lst) {
13520
0
#ifdef SAX2
13521
0
    xmlParserCtxtPtr ctxt;
13522
0
    xmlDocPtr doc = NULL;
13523
0
    xmlNodePtr fake, cur;
13524
0
    int nsnr = 0;
13525
13526
0
    xmlParserErrors ret = XML_ERR_OK;
13527
13528
    /*
13529
     * check all input parameters, grab the document
13530
     */
13531
0
    if ((lst == NULL) || (node == NULL) || (data == NULL) || (datalen < 0))
13532
0
        return(XML_ERR_INTERNAL_ERROR);
13533
0
    switch (node->type) {
13534
0
        case XML_ELEMENT_NODE:
13535
0
        case XML_ATTRIBUTE_NODE:
13536
0
        case XML_TEXT_NODE:
13537
0
        case XML_CDATA_SECTION_NODE:
13538
0
        case XML_ENTITY_REF_NODE:
13539
0
        case XML_PI_NODE:
13540
0
        case XML_COMMENT_NODE:
13541
0
        case XML_DOCUMENT_NODE:
13542
0
        case XML_HTML_DOCUMENT_NODE:
13543
0
      break;
13544
0
  default:
13545
0
      return(XML_ERR_INTERNAL_ERROR);
13546
13547
0
    }
13548
0
    while ((node != NULL) && (node->type != XML_ELEMENT_NODE) &&
13549
0
           (node->type != XML_DOCUMENT_NODE) &&
13550
0
     (node->type != XML_HTML_DOCUMENT_NODE))
13551
0
  node = node->parent;
13552
0
    if (node == NULL)
13553
0
  return(XML_ERR_INTERNAL_ERROR);
13554
0
    if (node->type == XML_ELEMENT_NODE)
13555
0
  doc = node->doc;
13556
0
    else
13557
0
        doc = (xmlDocPtr) node;
13558
0
    if (doc == NULL)
13559
0
  return(XML_ERR_INTERNAL_ERROR);
13560
13561
    /*
13562
     * allocate a context and set-up everything not related to the
13563
     * node position in the tree
13564
     */
13565
0
    if (doc->type == XML_DOCUMENT_NODE)
13566
0
  ctxt = xmlCreateMemoryParserCtxt((char *) data, datalen);
13567
0
#ifdef LIBXML_HTML_ENABLED
13568
0
    else if (doc->type == XML_HTML_DOCUMENT_NODE) {
13569
0
  ctxt = htmlCreateMemoryParserCtxt((char *) data, datalen);
13570
        /*
13571
         * When parsing in context, it makes no sense to add implied
13572
         * elements like html/body/etc...
13573
         */
13574
0
        options |= HTML_PARSE_NOIMPLIED;
13575
0
    }
13576
0
#endif
13577
0
    else
13578
0
        return(XML_ERR_INTERNAL_ERROR);
13579
13580
0
    if (ctxt == NULL)
13581
0
        return(XML_ERR_NO_MEMORY);
13582
13583
    /*
13584
     * Use input doc's dict if present, else assure XML_PARSE_NODICT is set.
13585
     * We need a dictionary for xmlDetectSAX2, so if there's no doc dict
13586
     * we must wait until the last moment to free the original one.
13587
     */
13588
0
    if (doc->dict != NULL) {
13589
0
        if (ctxt->dict != NULL)
13590
0
      xmlDictFree(ctxt->dict);
13591
0
  ctxt->dict = doc->dict;
13592
0
    } else
13593
0
        options |= XML_PARSE_NODICT;
13594
13595
0
    if (doc->encoding != NULL) {
13596
0
        xmlCharEncodingHandlerPtr hdlr;
13597
13598
0
        if (ctxt->encoding != NULL)
13599
0
      xmlFree((xmlChar *) ctxt->encoding);
13600
0
        ctxt->encoding = xmlStrdup((const xmlChar *) doc->encoding);
13601
13602
0
        hdlr = xmlFindCharEncodingHandler((const char *) doc->encoding);
13603
0
        if (hdlr != NULL) {
13604
0
            xmlSwitchToEncoding(ctxt, hdlr);
13605
0
  } else {
13606
0
            return(XML_ERR_UNSUPPORTED_ENCODING);
13607
0
        }
13608
0
    }
13609
13610
0
    xmlCtxtUseOptionsInternal(ctxt, options, NULL);
13611
0
    xmlDetectSAX2(ctxt);
13612
0
    ctxt->myDoc = doc;
13613
    /* parsing in context, i.e. as within existing content */
13614
0
    ctxt->input_id = 2;
13615
0
    ctxt->instate = XML_PARSER_CONTENT;
13616
13617
0
    fake = xmlNewDocComment(node->doc, NULL);
13618
0
    if (fake == NULL) {
13619
0
        xmlFreeParserCtxt(ctxt);
13620
0
  return(XML_ERR_NO_MEMORY);
13621
0
    }
13622
0
    xmlAddChild(node, fake);
13623
13624
0
    if (node->type == XML_ELEMENT_NODE) {
13625
0
  nodePush(ctxt, node);
13626
  /*
13627
   * initialize the SAX2 namespaces stack
13628
   */
13629
0
  cur = node;
13630
0
  while ((cur != NULL) && (cur->type == XML_ELEMENT_NODE)) {
13631
0
      xmlNsPtr ns = cur->nsDef;
13632
0
      const xmlChar *iprefix, *ihref;
13633
13634
0
      while (ns != NULL) {
13635
0
    if (ctxt->dict) {
13636
0
        iprefix = xmlDictLookup(ctxt->dict, ns->prefix, -1);
13637
0
        ihref = xmlDictLookup(ctxt->dict, ns->href, -1);
13638
0
    } else {
13639
0
        iprefix = ns->prefix;
13640
0
        ihref = ns->href;
13641
0
    }
13642
13643
0
          if (xmlGetNamespace(ctxt, iprefix) == NULL) {
13644
0
        nsPush(ctxt, iprefix, ihref);
13645
0
        nsnr++;
13646
0
    }
13647
0
    ns = ns->next;
13648
0
      }
13649
0
      cur = cur->parent;
13650
0
  }
13651
0
    }
13652
13653
0
    if ((ctxt->validate) || (ctxt->replaceEntities != 0)) {
13654
  /*
13655
   * ID/IDREF registration will be done in xmlValidateElement below
13656
   */
13657
0
  ctxt->loadsubset |= XML_SKIP_IDS;
13658
0
    }
13659
13660
0
#ifdef LIBXML_HTML_ENABLED
13661
0
    if (doc->type == XML_HTML_DOCUMENT_NODE)
13662
0
        __htmlParseContent(ctxt);
13663
0
    else
13664
0
#endif
13665
0
  xmlParseContent(ctxt);
13666
13667
0
    nsPop(ctxt, nsnr);
13668
0
    if ((RAW == '<') && (NXT(1) == '/')) {
13669
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13670
0
    } else if (RAW != 0) {
13671
0
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13672
0
    }
13673
0
    if ((ctxt->node != NULL) && (ctxt->node != node)) {
13674
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13675
0
  ctxt->wellFormed = 0;
13676
0
    }
13677
13678
0
    if (!ctxt->wellFormed) {
13679
0
        if (ctxt->errNo == 0)
13680
0
      ret = XML_ERR_INTERNAL_ERROR;
13681
0
  else
13682
0
      ret = (xmlParserErrors)ctxt->errNo;
13683
0
    } else {
13684
0
        ret = XML_ERR_OK;
13685
0
    }
13686
13687
    /*
13688
     * Return the newly created nodeset after unlinking it from
13689
     * the pseudo sibling.
13690
     */
13691
13692
0
    cur = fake->next;
13693
0
    fake->next = NULL;
13694
0
    node->last = fake;
13695
13696
0
    if (cur != NULL) {
13697
0
  cur->prev = NULL;
13698
0
    }
13699
13700
0
    *lst = cur;
13701
13702
0
    while (cur != NULL) {
13703
0
  cur->parent = NULL;
13704
0
  cur = cur->next;
13705
0
    }
13706
13707
0
    xmlUnlinkNode(fake);
13708
0
    xmlFreeNode(fake);
13709
13710
13711
0
    if (ret != XML_ERR_OK) {
13712
0
        xmlFreeNodeList(*lst);
13713
0
  *lst = NULL;
13714
0
    }
13715
13716
0
    if (doc->dict != NULL)
13717
0
        ctxt->dict = NULL;
13718
0
    xmlFreeParserCtxt(ctxt);
13719
13720
0
    return(ret);
13721
#else /* !SAX2 */
13722
    return(XML_ERR_INTERNAL_ERROR);
13723
#endif
13724
0
}
13725
13726
#ifdef LIBXML_SAX1_ENABLED
13727
/**
13728
 * xmlParseBalancedChunkMemoryRecover:
13729
 * @doc:  the document the chunk pertains to (must not be NULL)
13730
 * @sax:  the SAX handler block (possibly NULL)
13731
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
13732
 * @depth:  Used for loop detection, use 0
13733
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
13734
 * @lst:  the return value for the set of parsed nodes
13735
 * @recover: return nodes even if the data is broken (use 0)
13736
 *
13737
 *
13738
 * Parse a well-balanced chunk of an XML document
13739
 * called by the parser
13740
 * The allowed sequence for the Well Balanced Chunk is the one defined by
13741
 * the content production in the XML grammar:
13742
 *
13743
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13744
 *
13745
 * Returns 0 if the chunk is well balanced, -1 in case of args problem and
13746
 *    the parser error code otherwise
13747
 *
13748
 * In case recover is set to 1, the nodelist will not be empty even if
13749
 * the parsed chunk is not well balanced, assuming the parsing succeeded to
13750
 * some extent.
13751
 */
13752
int
13753
xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
13754
     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst,
13755
     int recover) {
13756
    xmlParserCtxtPtr ctxt;
13757
    xmlDocPtr newDoc;
13758
    xmlSAXHandlerPtr oldsax = NULL;
13759
    xmlNodePtr content, newRoot;
13760
    int size;
13761
    int ret = 0;
13762
13763
    if (depth > 40) {
13764
  return(XML_ERR_ENTITY_LOOP);
13765
    }
13766
13767
13768
    if (lst != NULL)
13769
        *lst = NULL;
13770
    if (string == NULL)
13771
        return(-1);
13772
13773
    size = xmlStrlen(string);
13774
13775
    ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
13776
    if (ctxt == NULL) return(-1);
13777
    ctxt->userData = ctxt;
13778
    if (sax != NULL) {
13779
  oldsax = ctxt->sax;
13780
        ctxt->sax = sax;
13781
  if (user_data != NULL)
13782
      ctxt->userData = user_data;
13783
    }
13784
    newDoc = xmlNewDoc(BAD_CAST "1.0");
13785
    if (newDoc == NULL) {
13786
  xmlFreeParserCtxt(ctxt);
13787
  return(-1);
13788
    }
13789
    newDoc->properties = XML_DOC_INTERNAL;
13790
    if ((doc != NULL) && (doc->dict != NULL)) {
13791
        xmlDictFree(ctxt->dict);
13792
  ctxt->dict = doc->dict;
13793
  xmlDictReference(ctxt->dict);
13794
  ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
13795
  ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
13796
  ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
13797
  ctxt->dictNames = 1;
13798
    } else {
13799
  xmlCtxtUseOptionsInternal(ctxt, XML_PARSE_NODICT, NULL);
13800
    }
13801
    /* doc == NULL is only supported for historic reasons */
13802
    if (doc != NULL) {
13803
  newDoc->intSubset = doc->intSubset;
13804
  newDoc->extSubset = doc->extSubset;
13805
    }
13806
    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
13807
    if (newRoot == NULL) {
13808
  if (sax != NULL)
13809
      ctxt->sax = oldsax;
13810
  xmlFreeParserCtxt(ctxt);
13811
  newDoc->intSubset = NULL;
13812
  newDoc->extSubset = NULL;
13813
        xmlFreeDoc(newDoc);
13814
  return(-1);
13815
    }
13816
    xmlAddChild((xmlNodePtr) newDoc, newRoot);
13817
    nodePush(ctxt, newRoot);
13818
    /* doc == NULL is only supported for historic reasons */
13819
    if (doc == NULL) {
13820
  ctxt->myDoc = newDoc;
13821
    } else {
13822
  ctxt->myDoc = newDoc;
13823
  newDoc->children->doc = doc;
13824
  /* Ensure that doc has XML spec namespace */
13825
  xmlSearchNsByHref(doc, (xmlNodePtr)doc, XML_XML_NAMESPACE);
13826
  newDoc->oldNs = doc->oldNs;
13827
    }
13828
    ctxt->instate = XML_PARSER_CONTENT;
13829
    ctxt->input_id = 2;
13830
    ctxt->depth = depth;
13831
13832
    /*
13833
     * Doing validity checking on chunk doesn't make sense
13834
     */
13835
    ctxt->validate = 0;
13836
    ctxt->loadsubset = 0;
13837
    xmlDetectSAX2(ctxt);
13838
13839
    if ( doc != NULL ){
13840
        content = doc->children;
13841
        doc->children = NULL;
13842
        xmlParseContent(ctxt);
13843
        doc->children = content;
13844
    }
13845
    else {
13846
        xmlParseContent(ctxt);
13847
    }
13848
    if ((RAW == '<') && (NXT(1) == '/')) {
13849
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13850
    } else if (RAW != 0) {
13851
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13852
    }
13853
    if (ctxt->node != newDoc->children) {
13854
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13855
    }
13856
13857
    if (!ctxt->wellFormed) {
13858
        if (ctxt->errNo == 0)
13859
      ret = 1;
13860
  else
13861
      ret = ctxt->errNo;
13862
    } else {
13863
      ret = 0;
13864
    }
13865
13866
    if ((lst != NULL) && ((ret == 0) || (recover == 1))) {
13867
  xmlNodePtr cur;
13868
13869
  /*
13870
   * Return the newly created nodeset after unlinking it from
13871
   * they pseudo parent.
13872
   */
13873
  cur = newDoc->children->children;
13874
  *lst = cur;
13875
  while (cur != NULL) {
13876
      xmlSetTreeDoc(cur, doc);
13877
      cur->parent = NULL;
13878
      cur = cur->next;
13879
  }
13880
  newDoc->children->children = NULL;
13881
    }
13882
13883
    if (sax != NULL)
13884
  ctxt->sax = oldsax;
13885
    xmlFreeParserCtxt(ctxt);
13886
    newDoc->intSubset = NULL;
13887
    newDoc->extSubset = NULL;
13888
    /* This leaks the namespace list if doc == NULL */
13889
    newDoc->oldNs = NULL;
13890
    xmlFreeDoc(newDoc);
13891
13892
    return(ret);
13893
}
13894
13895
/**
13896
 * xmlSAXParseEntity:
13897
 * @sax:  the SAX handler block
13898
 * @filename:  the filename
13899
 *
13900
 * DEPRECATED: Don't use.
13901
 *
13902
 * parse an XML external entity out of context and build a tree.
13903
 * It use the given SAX function block to handle the parsing callback.
13904
 * If sax is NULL, fallback to the default DOM tree building routines.
13905
 *
13906
 * [78] extParsedEnt ::= TextDecl? content
13907
 *
13908
 * This correspond to a "Well Balanced" chunk
13909
 *
13910
 * Returns the resulting document tree
13911
 */
13912
13913
xmlDocPtr
13914
xmlSAXParseEntity(xmlSAXHandlerPtr sax, const char *filename) {
13915
    xmlDocPtr ret;
13916
    xmlParserCtxtPtr ctxt;
13917
13918
    ctxt = xmlCreateFileParserCtxt(filename);
13919
    if (ctxt == NULL) {
13920
  return(NULL);
13921
    }
13922
    if (sax != NULL) {
13923
  if (ctxt->sax != NULL)
13924
      xmlFree(ctxt->sax);
13925
        ctxt->sax = sax;
13926
        ctxt->userData = NULL;
13927
    }
13928
13929
    xmlParseExtParsedEnt(ctxt);
13930
13931
    if (ctxt->wellFormed)
13932
  ret = ctxt->myDoc;
13933
    else {
13934
        ret = NULL;
13935
        xmlFreeDoc(ctxt->myDoc);
13936
        ctxt->myDoc = NULL;
13937
    }
13938
    if (sax != NULL)
13939
        ctxt->sax = NULL;
13940
    xmlFreeParserCtxt(ctxt);
13941
13942
    return(ret);
13943
}
13944
13945
/**
13946
 * xmlParseEntity:
13947
 * @filename:  the filename
13948
 *
13949
 * parse an XML external entity out of context and build a tree.
13950
 *
13951
 * [78] extParsedEnt ::= TextDecl? content
13952
 *
13953
 * This correspond to a "Well Balanced" chunk
13954
 *
13955
 * Returns the resulting document tree
13956
 */
13957
13958
xmlDocPtr
13959
xmlParseEntity(const char *filename) {
13960
    return(xmlSAXParseEntity(NULL, filename));
13961
}
13962
#endif /* LIBXML_SAX1_ENABLED */
13963
13964
/**
13965
 * xmlCreateEntityParserCtxtInternal:
13966
 * @URL:  the entity URL
13967
 * @ID:  the entity PUBLIC ID
13968
 * @base:  a possible base for the target URI
13969
 * @pctx:  parser context used to set options on new context
13970
 *
13971
 * Create a parser context for an external entity
13972
 * Automatic support for ZLIB/Compress compressed document is provided
13973
 * by default if found at compile-time.
13974
 *
13975
 * Returns the new parser context or NULL
13976
 */
13977
static xmlParserCtxtPtr
13978
xmlCreateEntityParserCtxtInternal(xmlSAXHandlerPtr sax, void *userData,
13979
        const xmlChar *URL, const xmlChar *ID, const xmlChar *base,
13980
0
        xmlParserCtxtPtr pctx) {
13981
0
    xmlParserCtxtPtr ctxt;
13982
0
    xmlParserInputPtr inputStream;
13983
0
    char *directory = NULL;
13984
0
    xmlChar *uri;
13985
13986
0
    ctxt = xmlNewSAXParserCtxt(sax, userData);
13987
0
    if (ctxt == NULL) {
13988
0
  return(NULL);
13989
0
    }
13990
13991
0
    if (pctx != NULL) {
13992
0
        ctxt->options = pctx->options;
13993
0
        ctxt->_private = pctx->_private;
13994
  /*
13995
   * this is a subparser of pctx, so the input_id should be
13996
   * incremented to distinguish from main entity
13997
   */
13998
0
  ctxt->input_id = pctx->input_id + 1;
13999
0
    }
14000
14001
    /* Don't read from stdin. */
14002
0
    if (xmlStrcmp(URL, BAD_CAST "-") == 0)
14003
0
        URL = BAD_CAST "./-";
14004
14005
0
    uri = xmlBuildURI(URL, base);
14006
14007
0
    if (uri == NULL) {
14008
0
  inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
14009
0
  if (inputStream == NULL) {
14010
0
      xmlFreeParserCtxt(ctxt);
14011
0
      return(NULL);
14012
0
  }
14013
14014
0
  inputPush(ctxt, inputStream);
14015
14016
0
  if ((ctxt->directory == NULL) && (directory == NULL))
14017
0
      directory = xmlParserGetDirectory((char *)URL);
14018
0
  if ((ctxt->directory == NULL) && (directory != NULL))
14019
0
      ctxt->directory = directory;
14020
0
    } else {
14021
0
  inputStream = xmlLoadExternalEntity((char *)uri, (char *)ID, ctxt);
14022
0
  if (inputStream == NULL) {
14023
0
      xmlFree(uri);
14024
0
      xmlFreeParserCtxt(ctxt);
14025
0
      return(NULL);
14026
0
  }
14027
14028
0
  inputPush(ctxt, inputStream);
14029
14030
0
  if ((ctxt->directory == NULL) && (directory == NULL))
14031
0
      directory = xmlParserGetDirectory((char *)uri);
14032
0
  if ((ctxt->directory == NULL) && (directory != NULL))
14033
0
      ctxt->directory = directory;
14034
0
  xmlFree(uri);
14035
0
    }
14036
0
    return(ctxt);
14037
0
}
14038
14039
/**
14040
 * xmlCreateEntityParserCtxt:
14041
 * @URL:  the entity URL
14042
 * @ID:  the entity PUBLIC ID
14043
 * @base:  a possible base for the target URI
14044
 *
14045
 * Create a parser context for an external entity
14046
 * Automatic support for ZLIB/Compress compressed document is provided
14047
 * by default if found at compile-time.
14048
 *
14049
 * Returns the new parser context or NULL
14050
 */
14051
xmlParserCtxtPtr
14052
xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID,
14053
0
                    const xmlChar *base) {
14054
0
    return xmlCreateEntityParserCtxtInternal(NULL, NULL, URL, ID, base, NULL);
14055
14056
0
}
14057
14058
/************************************************************************
14059
 *                  *
14060
 *    Front ends when parsing from a file     *
14061
 *                  *
14062
 ************************************************************************/
14063
14064
/**
14065
 * xmlCreateURLParserCtxt:
14066
 * @filename:  the filename or URL
14067
 * @options:  a combination of xmlParserOption
14068
 *
14069
 * Create a parser context for a file or URL content.
14070
 * Automatic support for ZLIB/Compress compressed document is provided
14071
 * by default if found at compile-time and for file accesses
14072
 *
14073
 * Returns the new parser context or NULL
14074
 */
14075
xmlParserCtxtPtr
14076
xmlCreateURLParserCtxt(const char *filename, int options)
14077
2
{
14078
2
    xmlParserCtxtPtr ctxt;
14079
2
    xmlParserInputPtr inputStream;
14080
2
    char *directory = NULL;
14081
14082
2
    ctxt = xmlNewParserCtxt();
14083
2
    if (ctxt == NULL) {
14084
0
  xmlErrMemory(NULL, "cannot allocate parser context");
14085
0
  return(NULL);
14086
0
    }
14087
14088
2
    if (options)
14089
0
  xmlCtxtUseOptionsInternal(ctxt, options, NULL);
14090
2
    ctxt->linenumbers = 1;
14091
14092
2
    inputStream = xmlLoadExternalEntity(filename, NULL, ctxt);
14093
2
    if (inputStream == NULL) {
14094
0
  xmlFreeParserCtxt(ctxt);
14095
0
  return(NULL);
14096
0
    }
14097
14098
2
    inputPush(ctxt, inputStream);
14099
2
    if ((ctxt->directory == NULL) && (directory == NULL))
14100
0
        directory = xmlParserGetDirectory(filename);
14101
2
    if ((ctxt->directory == NULL) && (directory != NULL))
14102
0
        ctxt->directory = directory;
14103
14104
2
    return(ctxt);
14105
2
}
14106
14107
/**
14108
 * xmlCreateFileParserCtxt:
14109
 * @filename:  the filename
14110
 *
14111
 * Create a parser context for a file content.
14112
 * Automatic support for ZLIB/Compress compressed document is provided
14113
 * by default if found at compile-time.
14114
 *
14115
 * Returns the new parser context or NULL
14116
 */
14117
xmlParserCtxtPtr
14118
xmlCreateFileParserCtxt(const char *filename)
14119
0
{
14120
0
    return(xmlCreateURLParserCtxt(filename, 0));
14121
0
}
14122
14123
#ifdef LIBXML_SAX1_ENABLED
14124
/**
14125
 * xmlSAXParseFileWithData:
14126
 * @sax:  the SAX handler block
14127
 * @filename:  the filename
14128
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14129
 *             documents
14130
 * @data:  the userdata
14131
 *
14132
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadFile.
14133
 *
14134
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
14135
 * compressed document is provided by default if found at compile-time.
14136
 * It use the given SAX function block to handle the parsing callback.
14137
 * If sax is NULL, fallback to the default DOM tree building routines.
14138
 *
14139
 * User data (void *) is stored within the parser context in the
14140
 * context's _private member, so it is available nearly everywhere in libxml
14141
 *
14142
 * Returns the resulting document tree
14143
 */
14144
14145
xmlDocPtr
14146
xmlSAXParseFileWithData(xmlSAXHandlerPtr sax, const char *filename,
14147
                        int recovery, void *data) {
14148
    xmlDocPtr ret;
14149
    xmlParserCtxtPtr ctxt;
14150
14151
    xmlInitParser();
14152
14153
    ctxt = xmlCreateFileParserCtxt(filename);
14154
    if (ctxt == NULL) {
14155
  return(NULL);
14156
    }
14157
    if (sax != NULL) {
14158
  if (ctxt->sax != NULL)
14159
      xmlFree(ctxt->sax);
14160
        ctxt->sax = sax;
14161
    }
14162
    xmlDetectSAX2(ctxt);
14163
    if (data!=NULL) {
14164
  ctxt->_private = data;
14165
    }
14166
14167
    if (ctxt->directory == NULL)
14168
        ctxt->directory = xmlParserGetDirectory(filename);
14169
14170
    ctxt->recovery = recovery;
14171
14172
    xmlParseDocument(ctxt);
14173
14174
    if ((ctxt->wellFormed) || recovery) {
14175
        ret = ctxt->myDoc;
14176
  if ((ret != NULL) && (ctxt->input->buf != NULL)) {
14177
      if (ctxt->input->buf->compressed > 0)
14178
    ret->compression = 9;
14179
      else
14180
    ret->compression = ctxt->input->buf->compressed;
14181
  }
14182
    }
14183
    else {
14184
       ret = NULL;
14185
       xmlFreeDoc(ctxt->myDoc);
14186
       ctxt->myDoc = NULL;
14187
    }
14188
    if (sax != NULL)
14189
        ctxt->sax = NULL;
14190
    xmlFreeParserCtxt(ctxt);
14191
14192
    return(ret);
14193
}
14194
14195
/**
14196
 * xmlSAXParseFile:
14197
 * @sax:  the SAX handler block
14198
 * @filename:  the filename
14199
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14200
 *             documents
14201
 *
14202
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadFile.
14203
 *
14204
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
14205
 * compressed document is provided by default if found at compile-time.
14206
 * It use the given SAX function block to handle the parsing callback.
14207
 * If sax is NULL, fallback to the default DOM tree building routines.
14208
 *
14209
 * Returns the resulting document tree
14210
 */
14211
14212
xmlDocPtr
14213
xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
14214
                          int recovery) {
14215
    return(xmlSAXParseFileWithData(sax,filename,recovery,NULL));
14216
}
14217
14218
/**
14219
 * xmlRecoverDoc:
14220
 * @cur:  a pointer to an array of xmlChar
14221
 *
14222
 * DEPRECATED: Use xmlReadDoc with XML_PARSE_RECOVER.
14223
 *
14224
 * parse an XML in-memory document and build a tree.
14225
 * In the case the document is not Well Formed, a attempt to build a
14226
 * tree is tried anyway
14227
 *
14228
 * Returns the resulting document tree or NULL in case of failure
14229
 */
14230
14231
xmlDocPtr
14232
xmlRecoverDoc(const xmlChar *cur) {
14233
    return(xmlSAXParseDoc(NULL, cur, 1));
14234
}
14235
14236
/**
14237
 * xmlParseFile:
14238
 * @filename:  the filename
14239
 *
14240
 * DEPRECATED: Use xmlReadFile.
14241
 *
14242
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
14243
 * compressed document is provided by default if found at compile-time.
14244
 *
14245
 * Returns the resulting document tree if the file was wellformed,
14246
 * NULL otherwise.
14247
 */
14248
14249
xmlDocPtr
14250
xmlParseFile(const char *filename) {
14251
    return(xmlSAXParseFile(NULL, filename, 0));
14252
}
14253
14254
/**
14255
 * xmlRecoverFile:
14256
 * @filename:  the filename
14257
 *
14258
 * DEPRECATED: Use xmlReadFile with XML_PARSE_RECOVER.
14259
 *
14260
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
14261
 * compressed document is provided by default if found at compile-time.
14262
 * In the case the document is not Well Formed, it attempts to build
14263
 * a tree anyway
14264
 *
14265
 * Returns the resulting document tree or NULL in case of failure
14266
 */
14267
14268
xmlDocPtr
14269
xmlRecoverFile(const char *filename) {
14270
    return(xmlSAXParseFile(NULL, filename, 1));
14271
}
14272
14273
14274
/**
14275
 * xmlSetupParserForBuffer:
14276
 * @ctxt:  an XML parser context
14277
 * @buffer:  a xmlChar * buffer
14278
 * @filename:  a file name
14279
 *
14280
 * DEPRECATED: Don't use.
14281
 *
14282
 * Setup the parser context to parse a new buffer; Clears any prior
14283
 * contents from the parser context. The buffer parameter must not be
14284
 * NULL, but the filename parameter can be
14285
 */
14286
void
14287
xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
14288
                             const char* filename)
14289
{
14290
    xmlParserInputPtr input;
14291
14292
    if ((ctxt == NULL) || (buffer == NULL))
14293
        return;
14294
14295
    input = xmlNewInputStream(ctxt);
14296
    if (input == NULL) {
14297
        xmlErrMemory(NULL, "parsing new buffer: out of memory\n");
14298
        xmlClearParserCtxt(ctxt);
14299
        return;
14300
    }
14301
14302
    xmlClearParserCtxt(ctxt);
14303
    if (filename != NULL)
14304
        input->filename = (char *) xmlCanonicPath((const xmlChar *)filename);
14305
    input->base = buffer;
14306
    input->cur = buffer;
14307
    input->end = &buffer[xmlStrlen(buffer)];
14308
    inputPush(ctxt, input);
14309
}
14310
14311
/**
14312
 * xmlSAXUserParseFile:
14313
 * @sax:  a SAX handler
14314
 * @user_data:  The user data returned on SAX callbacks
14315
 * @filename:  a file name
14316
 *
14317
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadFile.
14318
 *
14319
 * parse an XML file and call the given SAX handler routines.
14320
 * Automatic support for ZLIB/Compress compressed document is provided
14321
 *
14322
 * Returns 0 in case of success or a error number otherwise
14323
 */
14324
int
14325
xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
14326
                    const char *filename) {
14327
    int ret = 0;
14328
    xmlParserCtxtPtr ctxt;
14329
14330
    ctxt = xmlCreateFileParserCtxt(filename);
14331
    if (ctxt == NULL) return -1;
14332
    if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
14333
  xmlFree(ctxt->sax);
14334
    ctxt->sax = sax;
14335
    xmlDetectSAX2(ctxt);
14336
14337
    if (user_data != NULL)
14338
  ctxt->userData = user_data;
14339
14340
    xmlParseDocument(ctxt);
14341
14342
    if (ctxt->wellFormed)
14343
  ret = 0;
14344
    else {
14345
        if (ctxt->errNo != 0)
14346
      ret = ctxt->errNo;
14347
  else
14348
      ret = -1;
14349
    }
14350
    if (sax != NULL)
14351
  ctxt->sax = NULL;
14352
    if (ctxt->myDoc != NULL) {
14353
        xmlFreeDoc(ctxt->myDoc);
14354
  ctxt->myDoc = NULL;
14355
    }
14356
    xmlFreeParserCtxt(ctxt);
14357
14358
    return ret;
14359
}
14360
#endif /* LIBXML_SAX1_ENABLED */
14361
14362
/************************************************************************
14363
 *                  *
14364
 *    Front ends when parsing from memory     *
14365
 *                  *
14366
 ************************************************************************/
14367
14368
/**
14369
 * xmlCreateMemoryParserCtxt:
14370
 * @buffer:  a pointer to a char array
14371
 * @size:  the size of the array
14372
 *
14373
 * Create a parser context for an XML in-memory document.
14374
 *
14375
 * Returns the new parser context or NULL
14376
 */
14377
xmlParserCtxtPtr
14378
0
xmlCreateMemoryParserCtxt(const char *buffer, int size) {
14379
0
    xmlParserCtxtPtr ctxt;
14380
0
    xmlParserInputPtr input;
14381
0
    xmlParserInputBufferPtr buf;
14382
14383
0
    if (buffer == NULL)
14384
0
  return(NULL);
14385
0
    if (size <= 0)
14386
0
  return(NULL);
14387
14388
0
    ctxt = xmlNewParserCtxt();
14389
0
    if (ctxt == NULL)
14390
0
  return(NULL);
14391
14392
    /* TODO: xmlParserInputBufferCreateStatic, requires some serious changes */
14393
0
    buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
14394
0
    if (buf == NULL) {
14395
0
  xmlFreeParserCtxt(ctxt);
14396
0
  return(NULL);
14397
0
    }
14398
14399
0
    input = xmlNewInputStream(ctxt);
14400
0
    if (input == NULL) {
14401
0
  xmlFreeParserInputBuffer(buf);
14402
0
  xmlFreeParserCtxt(ctxt);
14403
0
  return(NULL);
14404
0
    }
14405
14406
0
    input->filename = NULL;
14407
0
    input->buf = buf;
14408
0
    xmlBufResetInput(input->buf->buffer, input);
14409
14410
0
    inputPush(ctxt, input);
14411
0
    return(ctxt);
14412
0
}
14413
14414
#ifdef LIBXML_SAX1_ENABLED
14415
/**
14416
 * xmlSAXParseMemoryWithData:
14417
 * @sax:  the SAX handler block
14418
 * @buffer:  an pointer to a char array
14419
 * @size:  the size of the array
14420
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14421
 *             documents
14422
 * @data:  the userdata
14423
 *
14424
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadMemory.
14425
 *
14426
 * parse an XML in-memory block and use the given SAX function block
14427
 * to handle the parsing callback. If sax is NULL, fallback to the default
14428
 * DOM tree building routines.
14429
 *
14430
 * User data (void *) is stored within the parser context in the
14431
 * context's _private member, so it is available nearly everywhere in libxml
14432
 *
14433
 * Returns the resulting document tree
14434
 */
14435
14436
xmlDocPtr
14437
xmlSAXParseMemoryWithData(xmlSAXHandlerPtr sax, const char *buffer,
14438
            int size, int recovery, void *data) {
14439
    xmlDocPtr ret;
14440
    xmlParserCtxtPtr ctxt;
14441
14442
    xmlInitParser();
14443
14444
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
14445
    if (ctxt == NULL) return(NULL);
14446
    if (sax != NULL) {
14447
  if (ctxt->sax != NULL)
14448
      xmlFree(ctxt->sax);
14449
        ctxt->sax = sax;
14450
    }
14451
    xmlDetectSAX2(ctxt);
14452
    if (data!=NULL) {
14453
  ctxt->_private=data;
14454
    }
14455
14456
    ctxt->recovery = recovery;
14457
14458
    xmlParseDocument(ctxt);
14459
14460
    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
14461
    else {
14462
       ret = NULL;
14463
       xmlFreeDoc(ctxt->myDoc);
14464
       ctxt->myDoc = NULL;
14465
    }
14466
    if (sax != NULL)
14467
  ctxt->sax = NULL;
14468
    xmlFreeParserCtxt(ctxt);
14469
14470
    return(ret);
14471
}
14472
14473
/**
14474
 * xmlSAXParseMemory:
14475
 * @sax:  the SAX handler block
14476
 * @buffer:  an pointer to a char array
14477
 * @size:  the size of the array
14478
 * @recovery:  work in recovery mode, i.e. tries to read not Well Formed
14479
 *             documents
14480
 *
14481
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadMemory.
14482
 *
14483
 * parse an XML in-memory block and use the given SAX function block
14484
 * to handle the parsing callback. If sax is NULL, fallback to the default
14485
 * DOM tree building routines.
14486
 *
14487
 * Returns the resulting document tree
14488
 */
14489
xmlDocPtr
14490
xmlSAXParseMemory(xmlSAXHandlerPtr sax, const char *buffer,
14491
            int size, int recovery) {
14492
    return xmlSAXParseMemoryWithData(sax, buffer, size, recovery, NULL);
14493
}
14494
14495
/**
14496
 * xmlParseMemory:
14497
 * @buffer:  an pointer to a char array
14498
 * @size:  the size of the array
14499
 *
14500
 * DEPRECATED: Use xmlReadMemory.
14501
 *
14502
 * parse an XML in-memory block and build a tree.
14503
 *
14504
 * Returns the resulting document tree
14505
 */
14506
14507
xmlDocPtr xmlParseMemory(const char *buffer, int size) {
14508
   return(xmlSAXParseMemory(NULL, buffer, size, 0));
14509
}
14510
14511
/**
14512
 * xmlRecoverMemory:
14513
 * @buffer:  an pointer to a char array
14514
 * @size:  the size of the array
14515
 *
14516
 * DEPRECATED: Use xmlReadMemory with XML_PARSE_RECOVER.
14517
 *
14518
 * parse an XML in-memory block and build a tree.
14519
 * In the case the document is not Well Formed, an attempt to
14520
 * build a tree is tried anyway
14521
 *
14522
 * Returns the resulting document tree or NULL in case of error
14523
 */
14524
14525
xmlDocPtr xmlRecoverMemory(const char *buffer, int size) {
14526
   return(xmlSAXParseMemory(NULL, buffer, size, 1));
14527
}
14528
14529
/**
14530
 * xmlSAXUserParseMemory:
14531
 * @sax:  a SAX handler
14532
 * @user_data:  The user data returned on SAX callbacks
14533
 * @buffer:  an in-memory XML document input
14534
 * @size:  the length of the XML document in bytes
14535
 *
14536
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadMemory.
14537
 *
14538
 * parse an XML in-memory buffer and call the given SAX handler routines.
14539
 *
14540
 * Returns 0 in case of success or a error number otherwise
14541
 */
14542
int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
14543
        const char *buffer, int size) {
14544
    int ret = 0;
14545
    xmlParserCtxtPtr ctxt;
14546
14547
    xmlInitParser();
14548
14549
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
14550
    if (ctxt == NULL) return -1;
14551
    if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
14552
        xmlFree(ctxt->sax);
14553
    ctxt->sax = sax;
14554
    xmlDetectSAX2(ctxt);
14555
14556
    if (user_data != NULL)
14557
  ctxt->userData = user_data;
14558
14559
    xmlParseDocument(ctxt);
14560
14561
    if (ctxt->wellFormed)
14562
  ret = 0;
14563
    else {
14564
        if (ctxt->errNo != 0)
14565
      ret = ctxt->errNo;
14566
  else
14567
      ret = -1;
14568
    }
14569
    if (sax != NULL)
14570
        ctxt->sax = NULL;
14571
    if (ctxt->myDoc != NULL) {
14572
        xmlFreeDoc(ctxt->myDoc);
14573
  ctxt->myDoc = NULL;
14574
    }
14575
    xmlFreeParserCtxt(ctxt);
14576
14577
    return ret;
14578
}
14579
#endif /* LIBXML_SAX1_ENABLED */
14580
14581
/**
14582
 * xmlCreateDocParserCtxt:
14583
 * @cur:  a pointer to an array of xmlChar
14584
 *
14585
 * Creates a parser context for an XML in-memory document.
14586
 *
14587
 * Returns the new parser context or NULL
14588
 */
14589
xmlParserCtxtPtr
14590
0
xmlCreateDocParserCtxt(const xmlChar *cur) {
14591
0
    int len;
14592
14593
0
    if (cur == NULL)
14594
0
  return(NULL);
14595
0
    len = xmlStrlen(cur);
14596
0
    return(xmlCreateMemoryParserCtxt((const char *)cur, len));
14597
0
}
14598
14599
#ifdef LIBXML_SAX1_ENABLED
14600
/**
14601
 * xmlSAXParseDoc:
14602
 * @sax:  the SAX handler block
14603
 * @cur:  a pointer to an array of xmlChar
14604
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14605
 *             documents
14606
 *
14607
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadDoc.
14608
 *
14609
 * parse an XML in-memory document and build a tree.
14610
 * It use the given SAX function block to handle the parsing callback.
14611
 * If sax is NULL, fallback to the default DOM tree building routines.
14612
 *
14613
 * Returns the resulting document tree
14614
 */
14615
14616
xmlDocPtr
14617
xmlSAXParseDoc(xmlSAXHandlerPtr sax, const xmlChar *cur, int recovery) {
14618
    xmlDocPtr ret;
14619
    xmlParserCtxtPtr ctxt;
14620
    xmlSAXHandlerPtr oldsax = NULL;
14621
14622
    if (cur == NULL) return(NULL);
14623
14624
14625
    ctxt = xmlCreateDocParserCtxt(cur);
14626
    if (ctxt == NULL) return(NULL);
14627
    if (sax != NULL) {
14628
        oldsax = ctxt->sax;
14629
        ctxt->sax = sax;
14630
        ctxt->userData = NULL;
14631
    }
14632
    xmlDetectSAX2(ctxt);
14633
14634
    xmlParseDocument(ctxt);
14635
    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
14636
    else {
14637
       ret = NULL;
14638
       xmlFreeDoc(ctxt->myDoc);
14639
       ctxt->myDoc = NULL;
14640
    }
14641
    if (sax != NULL)
14642
  ctxt->sax = oldsax;
14643
    xmlFreeParserCtxt(ctxt);
14644
14645
    return(ret);
14646
}
14647
14648
/**
14649
 * xmlParseDoc:
14650
 * @cur:  a pointer to an array of xmlChar
14651
 *
14652
 * DEPRECATED: Use xmlReadDoc.
14653
 *
14654
 * parse an XML in-memory document and build a tree.
14655
 *
14656
 * Returns the resulting document tree
14657
 */
14658
14659
xmlDocPtr
14660
xmlParseDoc(const xmlChar *cur) {
14661
    return(xmlSAXParseDoc(NULL, cur, 0));
14662
}
14663
#endif /* LIBXML_SAX1_ENABLED */
14664
14665
#ifdef LIBXML_LEGACY_ENABLED
14666
/************************************************************************
14667
 *                  *
14668
 *  Specific function to keep track of entities references    *
14669
 *  and used by the XSLT debugger         *
14670
 *                  *
14671
 ************************************************************************/
14672
14673
static xmlEntityReferenceFunc xmlEntityRefFunc = NULL;
14674
14675
/**
14676
 * xmlAddEntityReference:
14677
 * @ent : A valid entity
14678
 * @firstNode : A valid first node for children of entity
14679
 * @lastNode : A valid last node of children entity
14680
 *
14681
 * Notify of a reference to an entity of type XML_EXTERNAL_GENERAL_PARSED_ENTITY
14682
 */
14683
static void
14684
xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
14685
                      xmlNodePtr lastNode)
14686
{
14687
    if (xmlEntityRefFunc != NULL) {
14688
        (*xmlEntityRefFunc) (ent, firstNode, lastNode);
14689
    }
14690
}
14691
14692
14693
/**
14694
 * xmlSetEntityReferenceFunc:
14695
 * @func: A valid function
14696
 *
14697
 * Set the function to call call back when a xml reference has been made
14698
 */
14699
void
14700
xmlSetEntityReferenceFunc(xmlEntityReferenceFunc func)
14701
{
14702
    xmlEntityRefFunc = func;
14703
}
14704
#endif /* LIBXML_LEGACY_ENABLED */
14705
14706
/************************************************************************
14707
 *                  *
14708
 *        Miscellaneous       *
14709
 *                  *
14710
 ************************************************************************/
14711
14712
static int xmlParserInitialized = 0;
14713
14714
/**
14715
 * xmlInitParser:
14716
 *
14717
 * Initialization function for the XML parser.
14718
 * This is not reentrant. Call once before processing in case of
14719
 * use in multithreaded programs.
14720
 */
14721
14722
void
14723
721
xmlInitParser(void) {
14724
721
    if (xmlParserInitialized != 0)
14725
719
  return;
14726
14727
#if defined(_WIN32) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
14728
    if (xmlFree == free)
14729
        atexit(xmlCleanupParser);
14730
#endif
14731
14732
2
#ifdef LIBXML_THREAD_ENABLED
14733
2
    __xmlGlobalInitMutexLock();
14734
2
    if (xmlParserInitialized == 0) {
14735
2
#endif
14736
2
  xmlInitThreads();
14737
2
  xmlInitGlobals();
14738
2
  xmlInitMemory();
14739
2
        xmlInitializeDict();
14740
2
  xmlInitCharEncodingHandlers();
14741
2
  xmlDefaultSAXHandlerInit();
14742
2
  xmlRegisterDefaultInputCallbacks();
14743
2
#ifdef LIBXML_OUTPUT_ENABLED
14744
2
  xmlRegisterDefaultOutputCallbacks();
14745
2
#endif /* LIBXML_OUTPUT_ENABLED */
14746
2
#ifdef LIBXML_HTML_ENABLED
14747
2
  htmlInitAutoClose();
14748
2
  htmlDefaultSAXHandlerInit();
14749
2
#endif
14750
2
#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
14751
2
  xmlXPathInit();
14752
2
#endif
14753
2
  xmlParserInitialized = 1;
14754
2
#ifdef LIBXML_THREAD_ENABLED
14755
2
    }
14756
2
    __xmlGlobalInitMutexUnlock();
14757
2
#endif
14758
2
}
14759
14760
/**
14761
 * xmlCleanupParser:
14762
 *
14763
 * This function name is somewhat misleading. It does not clean up
14764
 * parser state, it cleans up memory allocated by the library itself.
14765
 * It is a cleanup function for the XML library. It tries to reclaim all
14766
 * related global memory allocated for the library processing.
14767
 * It doesn't deallocate any document related memory. One should
14768
 * call xmlCleanupParser() only when the process has finished using
14769
 * the library and all XML/HTML documents built with it.
14770
 * See also xmlInitParser() which has the opposite function of preparing
14771
 * the library for operations.
14772
 *
14773
 * WARNING: if your application is multithreaded or has plugin support
14774
 *          calling this may crash the application if another thread or
14775
 *          a plugin is still using libxml2. It's sometimes very hard to
14776
 *          guess if libxml2 is in use in the application, some libraries
14777
 *          or plugins may use it without notice. In case of doubt abstain
14778
 *          from calling this function or do it just before calling exit()
14779
 *          to avoid leak reports from valgrind !
14780
 */
14781
14782
void
14783
0
xmlCleanupParser(void) {
14784
0
    if (!xmlParserInitialized)
14785
0
  return;
14786
14787
0
    xmlCleanupCharEncodingHandlers();
14788
0
#ifdef LIBXML_CATALOG_ENABLED
14789
0
    xmlCatalogCleanup();
14790
0
#endif
14791
0
    xmlDictCleanup();
14792
0
    xmlCleanupInputCallbacks();
14793
0
#ifdef LIBXML_OUTPUT_ENABLED
14794
0
    xmlCleanupOutputCallbacks();
14795
0
#endif
14796
#ifdef LIBXML_SCHEMAS_ENABLED
14797
    xmlSchemaCleanupTypes();
14798
    xmlRelaxNGCleanupTypes();
14799
#endif
14800
0
    xmlCleanupGlobals();
14801
0
    xmlCleanupThreads(); /* must be last if called not from the main thread */
14802
0
    xmlCleanupMemory();
14803
0
    xmlParserInitialized = 0;
14804
0
}
14805
14806
#if defined(HAVE_ATTRIBUTE_DESTRUCTOR) && !defined(LIBXML_STATIC) && \
14807
    !defined(_WIN32)
14808
static void
14809
ATTRIBUTE_DESTRUCTOR
14810
xmlDestructor(void) {
14811
    /*
14812
     * Calling custom deallocation functions in a destructor can cause
14813
     * problems, for example with Nokogiri.
14814
     */
14815
    if (xmlFree == free)
14816
        xmlCleanupParser();
14817
}
14818
#endif
14819
14820
/************************************************************************
14821
 *                  *
14822
 *  New set (2.6.0) of simpler and more flexible APIs   *
14823
 *                  *
14824
 ************************************************************************/
14825
14826
/**
14827
 * DICT_FREE:
14828
 * @str:  a string
14829
 *
14830
 * Free a string if it is not owned by the "dict" dictionary in the
14831
 * current scope
14832
 */
14833
#define DICT_FREE(str)            \
14834
0
  if ((str) && ((!dict) ||       \
14835
0
      (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))  \
14836
0
      xmlFree((char *)(str));
14837
14838
/**
14839
 * xmlCtxtReset:
14840
 * @ctxt: an XML parser context
14841
 *
14842
 * Reset a parser context
14843
 */
14844
void
14845
xmlCtxtReset(xmlParserCtxtPtr ctxt)
14846
0
{
14847
0
    xmlParserInputPtr input;
14848
0
    xmlDictPtr dict;
14849
14850
0
    if (ctxt == NULL)
14851
0
        return;
14852
14853
0
    dict = ctxt->dict;
14854
14855
0
    while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
14856
0
        xmlFreeInputStream(input);
14857
0
    }
14858
0
    ctxt->inputNr = 0;
14859
0
    ctxt->input = NULL;
14860
14861
0
    ctxt->spaceNr = 0;
14862
0
    if (ctxt->spaceTab != NULL) {
14863
0
  ctxt->spaceTab[0] = -1;
14864
0
  ctxt->space = &ctxt->spaceTab[0];
14865
0
    } else {
14866
0
        ctxt->space = NULL;
14867
0
    }
14868
14869
14870
0
    ctxt->nodeNr = 0;
14871
0
    ctxt->node = NULL;
14872
14873
0
    ctxt->nameNr = 0;
14874
0
    ctxt->name = NULL;
14875
14876
0
    ctxt->nsNr = 0;
14877
14878
0
    DICT_FREE(ctxt->version);
14879
0
    ctxt->version = NULL;
14880
0
    DICT_FREE(ctxt->encoding);
14881
0
    ctxt->encoding = NULL;
14882
0
    DICT_FREE(ctxt->directory);
14883
0
    ctxt->directory = NULL;
14884
0
    DICT_FREE(ctxt->extSubURI);
14885
0
    ctxt->extSubURI = NULL;
14886
0
    DICT_FREE(ctxt->extSubSystem);
14887
0
    ctxt->extSubSystem = NULL;
14888
0
    if (ctxt->myDoc != NULL)
14889
0
        xmlFreeDoc(ctxt->myDoc);
14890
0
    ctxt->myDoc = NULL;
14891
14892
0
    ctxt->standalone = -1;
14893
0
    ctxt->hasExternalSubset = 0;
14894
0
    ctxt->hasPErefs = 0;
14895
0
    ctxt->html = 0;
14896
0
    ctxt->external = 0;
14897
0
    ctxt->instate = XML_PARSER_START;
14898
0
    ctxt->token = 0;
14899
14900
0
    ctxt->wellFormed = 1;
14901
0
    ctxt->nsWellFormed = 1;
14902
0
    ctxt->disableSAX = 0;
14903
0
    ctxt->valid = 1;
14904
#if 0
14905
    ctxt->vctxt.userData = ctxt;
14906
    ctxt->vctxt.error = xmlParserValidityError;
14907
    ctxt->vctxt.warning = xmlParserValidityWarning;
14908
#endif
14909
0
    ctxt->record_info = 0;
14910
0
    ctxt->checkIndex = 0;
14911
0
    ctxt->inSubset = 0;
14912
0
    ctxt->errNo = XML_ERR_OK;
14913
0
    ctxt->depth = 0;
14914
0
    ctxt->charset = XML_CHAR_ENCODING_UTF8;
14915
0
    ctxt->catalogs = NULL;
14916
0
    ctxt->nbentities = 0;
14917
0
    ctxt->sizeentities = 0;
14918
0
    ctxt->sizeentcopy = 0;
14919
0
    xmlInitNodeInfoSeq(&ctxt->node_seq);
14920
14921
0
    if (ctxt->attsDefault != NULL) {
14922
0
        xmlHashFree(ctxt->attsDefault, xmlHashDefaultDeallocator);
14923
0
        ctxt->attsDefault = NULL;
14924
0
    }
14925
0
    if (ctxt->attsSpecial != NULL) {
14926
0
        xmlHashFree(ctxt->attsSpecial, NULL);
14927
0
        ctxt->attsSpecial = NULL;
14928
0
    }
14929
14930
0
#ifdef LIBXML_CATALOG_ENABLED
14931
0
    if (ctxt->catalogs != NULL)
14932
0
  xmlCatalogFreeLocal(ctxt->catalogs);
14933
0
#endif
14934
0
    if (ctxt->lastError.code != XML_ERR_OK)
14935
0
        xmlResetError(&ctxt->lastError);
14936
0
}
14937
14938
/**
14939
 * xmlCtxtResetPush:
14940
 * @ctxt: an XML parser context
14941
 * @chunk:  a pointer to an array of chars
14942
 * @size:  number of chars in the array
14943
 * @filename:  an optional file name or URI
14944
 * @encoding:  the document encoding, or NULL
14945
 *
14946
 * Reset a push parser context
14947
 *
14948
 * Returns 0 in case of success and 1 in case of error
14949
 */
14950
int
14951
xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk,
14952
                 int size, const char *filename, const char *encoding)
14953
0
{
14954
0
    xmlParserInputPtr inputStream;
14955
0
    xmlParserInputBufferPtr buf;
14956
0
    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
14957
14958
0
    if (ctxt == NULL)
14959
0
        return(1);
14960
14961
0
    if ((encoding == NULL) && (chunk != NULL) && (size >= 4))
14962
0
        enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
14963
14964
0
    buf = xmlAllocParserInputBuffer(enc);
14965
0
    if (buf == NULL)
14966
0
        return(1);
14967
14968
0
    if (ctxt == NULL) {
14969
0
        xmlFreeParserInputBuffer(buf);
14970
0
        return(1);
14971
0
    }
14972
14973
0
    xmlCtxtReset(ctxt);
14974
14975
0
    if (filename == NULL) {
14976
0
        ctxt->directory = NULL;
14977
0
    } else {
14978
0
        ctxt->directory = xmlParserGetDirectory(filename);
14979
0
    }
14980
14981
0
    inputStream = xmlNewInputStream(ctxt);
14982
0
    if (inputStream == NULL) {
14983
0
        xmlFreeParserInputBuffer(buf);
14984
0
        return(1);
14985
0
    }
14986
14987
0
    if (filename == NULL)
14988
0
        inputStream->filename = NULL;
14989
0
    else
14990
0
        inputStream->filename = (char *)
14991
0
            xmlCanonicPath((const xmlChar *) filename);
14992
0
    inputStream->buf = buf;
14993
0
    xmlBufResetInput(buf->buffer, inputStream);
14994
14995
0
    inputPush(ctxt, inputStream);
14996
14997
0
    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
14998
0
        (ctxt->input->buf != NULL)) {
14999
0
  size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
15000
0
        size_t cur = ctxt->input->cur - ctxt->input->base;
15001
15002
0
        xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
15003
15004
0
        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
15005
#ifdef DEBUG_PUSH
15006
        xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
15007
#endif
15008
0
    }
15009
15010
0
    if (encoding != NULL) {
15011
0
        xmlCharEncodingHandlerPtr hdlr;
15012
15013
0
        if (ctxt->encoding != NULL)
15014
0
      xmlFree((xmlChar *) ctxt->encoding);
15015
0
        ctxt->encoding = xmlStrdup((const xmlChar *) encoding);
15016
15017
0
        hdlr = xmlFindCharEncodingHandler(encoding);
15018
0
        if (hdlr != NULL) {
15019
0
            xmlSwitchToEncoding(ctxt, hdlr);
15020
0
  } else {
15021
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
15022
0
            "Unsupported encoding %s\n", BAD_CAST encoding);
15023
0
        }
15024
0
    } else if (enc != XML_CHAR_ENCODING_NONE) {
15025
0
        xmlSwitchEncoding(ctxt, enc);
15026
0
    }
15027
15028
0
    return(0);
15029
0
}
15030
15031
15032
/**
15033
 * xmlCtxtUseOptionsInternal:
15034
 * @ctxt: an XML parser context
15035
 * @options:  a combination of xmlParserOption
15036
 * @encoding:  the user provided encoding to use
15037
 *
15038
 * Applies the options to the parser context
15039
 *
15040
 * Returns 0 in case of success, the set of unknown or unimplemented options
15041
 *         in case of error.
15042
 */
15043
static int
15044
xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encoding)
15045
2
{
15046
2
    if (ctxt == NULL)
15047
0
        return(-1);
15048
2
    if (encoding != NULL) {
15049
0
        if (ctxt->encoding != NULL)
15050
0
      xmlFree((xmlChar *) ctxt->encoding);
15051
0
        ctxt->encoding = xmlStrdup((const xmlChar *) encoding);
15052
0
    }
15053
2
    if (options & XML_PARSE_RECOVER) {
15054
0
        ctxt->recovery = 1;
15055
0
        options -= XML_PARSE_RECOVER;
15056
0
  ctxt->options |= XML_PARSE_RECOVER;
15057
0
    } else
15058
2
        ctxt->recovery = 0;
15059
2
    if (options & XML_PARSE_DTDLOAD) {
15060
0
        ctxt->loadsubset = XML_DETECT_IDS;
15061
0
        options -= XML_PARSE_DTDLOAD;
15062
0
  ctxt->options |= XML_PARSE_DTDLOAD;
15063
0
    } else
15064
2
        ctxt->loadsubset = 0;
15065
2
    if (options & XML_PARSE_DTDATTR) {
15066
0
        ctxt->loadsubset |= XML_COMPLETE_ATTRS;
15067
0
        options -= XML_PARSE_DTDATTR;
15068
0
  ctxt->options |= XML_PARSE_DTDATTR;
15069
0
    }
15070
2
    if (options & XML_PARSE_NOENT) {
15071
0
        ctxt->replaceEntities = 1;
15072
        /* ctxt->loadsubset |= XML_DETECT_IDS; */
15073
0
        options -= XML_PARSE_NOENT;
15074
0
  ctxt->options |= XML_PARSE_NOENT;
15075
0
    } else
15076
2
        ctxt->replaceEntities = 0;
15077
2
    if (options & XML_PARSE_PEDANTIC) {
15078
0
        ctxt->pedantic = 1;
15079
0
        options -= XML_PARSE_PEDANTIC;
15080
0
  ctxt->options |= XML_PARSE_PEDANTIC;
15081
0
    } else
15082
2
        ctxt->pedantic = 0;
15083
2
    if (options & XML_PARSE_NOBLANKS) {
15084
0
        ctxt->keepBlanks = 0;
15085
0
        ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
15086
0
        options -= XML_PARSE_NOBLANKS;
15087
0
  ctxt->options |= XML_PARSE_NOBLANKS;
15088
0
    } else
15089
2
        ctxt->keepBlanks = 1;
15090
2
    if (options & XML_PARSE_DTDVALID) {
15091
0
        ctxt->validate = 1;
15092
0
        if (options & XML_PARSE_NOWARNING)
15093
0
            ctxt->vctxt.warning = NULL;
15094
0
        if (options & XML_PARSE_NOERROR)
15095
0
            ctxt->vctxt.error = NULL;
15096
0
        options -= XML_PARSE_DTDVALID;
15097
0
  ctxt->options |= XML_PARSE_DTDVALID;
15098
0
    } else
15099
2
        ctxt->validate = 0;
15100
2
    if (options & XML_PARSE_NOWARNING) {
15101
0
        ctxt->sax->warning = NULL;
15102
0
        options -= XML_PARSE_NOWARNING;
15103
0
    }
15104
2
    if (options & XML_PARSE_NOERROR) {
15105
0
        ctxt->sax->error = NULL;
15106
0
        ctxt->sax->fatalError = NULL;
15107
0
        options -= XML_PARSE_NOERROR;
15108
0
    }
15109
#ifdef LIBXML_SAX1_ENABLED
15110
    if (options & XML_PARSE_SAX1) {
15111
        ctxt->sax->startElement = xmlSAX2StartElement;
15112
        ctxt->sax->endElement = xmlSAX2EndElement;
15113
        ctxt->sax->startElementNs = NULL;
15114
        ctxt->sax->endElementNs = NULL;
15115
        ctxt->sax->initialized = 1;
15116
        options -= XML_PARSE_SAX1;
15117
  ctxt->options |= XML_PARSE_SAX1;
15118
    }
15119
#endif /* LIBXML_SAX1_ENABLED */
15120
2
    if (options & XML_PARSE_NODICT) {
15121
0
        ctxt->dictNames = 0;
15122
0
        options -= XML_PARSE_NODICT;
15123
0
  ctxt->options |= XML_PARSE_NODICT;
15124
2
    } else {
15125
2
        ctxt->dictNames = 1;
15126
2
    }
15127
2
    if (options & XML_PARSE_NOCDATA) {
15128
0
        ctxt->sax->cdataBlock = NULL;
15129
0
        options -= XML_PARSE_NOCDATA;
15130
0
  ctxt->options |= XML_PARSE_NOCDATA;
15131
0
    }
15132
2
    if (options & XML_PARSE_NSCLEAN) {
15133
0
  ctxt->options |= XML_PARSE_NSCLEAN;
15134
0
        options -= XML_PARSE_NSCLEAN;
15135
0
    }
15136
2
    if (options & XML_PARSE_NONET) {
15137
0
  ctxt->options |= XML_PARSE_NONET;
15138
0
        options -= XML_PARSE_NONET;
15139
0
    }
15140
2
    if (options & XML_PARSE_COMPACT) {
15141
0
  ctxt->options |= XML_PARSE_COMPACT;
15142
0
        options -= XML_PARSE_COMPACT;
15143
0
    }
15144
2
    if (options & XML_PARSE_OLD10) {
15145
0
  ctxt->options |= XML_PARSE_OLD10;
15146
0
        options -= XML_PARSE_OLD10;
15147
0
    }
15148
2
    if (options & XML_PARSE_NOBASEFIX) {
15149
0
  ctxt->options |= XML_PARSE_NOBASEFIX;
15150
0
        options -= XML_PARSE_NOBASEFIX;
15151
0
    }
15152
2
    if (options & XML_PARSE_HUGE) {
15153
0
  ctxt->options |= XML_PARSE_HUGE;
15154
0
        options -= XML_PARSE_HUGE;
15155
0
        if (ctxt->dict != NULL)
15156
0
            xmlDictSetLimit(ctxt->dict, 0);
15157
0
    }
15158
2
    if (options & XML_PARSE_OLDSAX) {
15159
0
  ctxt->options |= XML_PARSE_OLDSAX;
15160
0
        options -= XML_PARSE_OLDSAX;
15161
0
    }
15162
2
    if (options & XML_PARSE_IGNORE_ENC) {
15163
0
  ctxt->options |= XML_PARSE_IGNORE_ENC;
15164
0
        options -= XML_PARSE_IGNORE_ENC;
15165
0
    }
15166
2
    if (options & XML_PARSE_BIG_LINES) {
15167
0
  ctxt->options |= XML_PARSE_BIG_LINES;
15168
0
        options -= XML_PARSE_BIG_LINES;
15169
0
    }
15170
2
    ctxt->linenumbers = 1;
15171
2
    return (options);
15172
2
}
15173
15174
/**
15175
 * xmlCtxtUseOptions:
15176
 * @ctxt: an XML parser context
15177
 * @options:  a combination of xmlParserOption
15178
 *
15179
 * Applies the options to the parser context
15180
 *
15181
 * Returns 0 in case of success, the set of unknown or unimplemented options
15182
 *         in case of error.
15183
 */
15184
int
15185
xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options)
15186
0
{
15187
0
   return(xmlCtxtUseOptionsInternal(ctxt, options, NULL));
15188
0
}
15189
15190
/**
15191
 * xmlDoRead:
15192
 * @ctxt:  an XML parser context
15193
 * @URL:  the base URL to use for the document
15194
 * @encoding:  the document encoding, or NULL
15195
 * @options:  a combination of xmlParserOption
15196
 * @reuse:  keep the context for reuse
15197
 *
15198
 * Common front-end for the xmlRead functions
15199
 *
15200
 * Returns the resulting document tree or NULL
15201
 */
15202
static xmlDocPtr
15203
xmlDoRead(xmlParserCtxtPtr ctxt, const char *URL, const char *encoding,
15204
          int options, int reuse)
15205
2
{
15206
2
    xmlDocPtr ret;
15207
15208
2
    xmlCtxtUseOptionsInternal(ctxt, options, encoding);
15209
2
    if (encoding != NULL) {
15210
0
        xmlCharEncodingHandlerPtr hdlr;
15211
15212
0
  hdlr = xmlFindCharEncodingHandler(encoding);
15213
0
  if (hdlr != NULL)
15214
0
      xmlSwitchToEncoding(ctxt, hdlr);
15215
0
    }
15216
2
    if ((URL != NULL) && (ctxt->input != NULL) &&
15217
2
        (ctxt->input->filename == NULL))
15218
0
        ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL);
15219
2
    xmlParseDocument(ctxt);
15220
2
    if ((ctxt->wellFormed) || ctxt->recovery)
15221
2
        ret = ctxt->myDoc;
15222
0
    else {
15223
0
        ret = NULL;
15224
0
  if (ctxt->myDoc != NULL) {
15225
0
      xmlFreeDoc(ctxt->myDoc);
15226
0
  }
15227
0
    }
15228
2
    ctxt->myDoc = NULL;
15229
2
    if (!reuse) {
15230
2
  xmlFreeParserCtxt(ctxt);
15231
2
    }
15232
15233
2
    return (ret);
15234
2
}
15235
15236
/**
15237
 * xmlReadDoc:
15238
 * @cur:  a pointer to a zero terminated string
15239
 * @URL:  the base URL to use for the document
15240
 * @encoding:  the document encoding, or NULL
15241
 * @options:  a combination of xmlParserOption
15242
 *
15243
 * parse an XML in-memory document and build a tree.
15244
 *
15245
 * Returns the resulting document tree
15246
 */
15247
xmlDocPtr
15248
xmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int options)
15249
0
{
15250
0
    xmlParserCtxtPtr ctxt;
15251
15252
0
    if (cur == NULL)
15253
0
        return (NULL);
15254
0
    xmlInitParser();
15255
15256
0
    ctxt = xmlCreateDocParserCtxt(cur);
15257
0
    if (ctxt == NULL)
15258
0
        return (NULL);
15259
0
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
15260
0
}
15261
15262
/**
15263
 * xmlReadFile:
15264
 * @filename:  a file or URL
15265
 * @encoding:  the document encoding, or NULL
15266
 * @options:  a combination of xmlParserOption
15267
 *
15268
 * parse an XML file from the filesystem or the network.
15269
 *
15270
 * Returns the resulting document tree
15271
 */
15272
xmlDocPtr
15273
xmlReadFile(const char *filename, const char *encoding, int options)
15274
2
{
15275
2
    xmlParserCtxtPtr ctxt;
15276
15277
2
    xmlInitParser();
15278
2
    ctxt = xmlCreateURLParserCtxt(filename, options);
15279
2
    if (ctxt == NULL)
15280
0
        return (NULL);
15281
2
    return (xmlDoRead(ctxt, NULL, encoding, options, 0));
15282
2
}
15283
15284
/**
15285
 * xmlReadMemory:
15286
 * @buffer:  a pointer to a char array
15287
 * @size:  the size of the array
15288
 * @URL:  the base URL to use for the document
15289
 * @encoding:  the document encoding, or NULL
15290
 * @options:  a combination of xmlParserOption
15291
 *
15292
 * parse an XML in-memory document and build a tree.
15293
 *
15294
 * Returns the resulting document tree
15295
 */
15296
xmlDocPtr
15297
xmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options)
15298
0
{
15299
0
    xmlParserCtxtPtr ctxt;
15300
15301
0
    xmlInitParser();
15302
0
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
15303
0
    if (ctxt == NULL)
15304
0
        return (NULL);
15305
0
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
15306
0
}
15307
15308
/**
15309
 * xmlReadFd:
15310
 * @fd:  an open file descriptor
15311
 * @URL:  the base URL to use for the document
15312
 * @encoding:  the document encoding, or NULL
15313
 * @options:  a combination of xmlParserOption
15314
 *
15315
 * parse an XML from a file descriptor and build a tree.
15316
 * NOTE that the file descriptor will not be closed when the
15317
 *      reader is closed or reset.
15318
 *
15319
 * Returns the resulting document tree
15320
 */
15321
xmlDocPtr
15322
xmlReadFd(int fd, const char *URL, const char *encoding, int options)
15323
0
{
15324
0
    xmlParserCtxtPtr ctxt;
15325
0
    xmlParserInputBufferPtr input;
15326
0
    xmlParserInputPtr stream;
15327
15328
0
    if (fd < 0)
15329
0
        return (NULL);
15330
0
    xmlInitParser();
15331
15332
0
    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
15333
0
    if (input == NULL)
15334
0
        return (NULL);
15335
0
    input->closecallback = NULL;
15336
0
    ctxt = xmlNewParserCtxt();
15337
0
    if (ctxt == NULL) {
15338
0
        xmlFreeParserInputBuffer(input);
15339
0
        return (NULL);
15340
0
    }
15341
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15342
0
    if (stream == NULL) {
15343
0
        xmlFreeParserInputBuffer(input);
15344
0
  xmlFreeParserCtxt(ctxt);
15345
0
        return (NULL);
15346
0
    }
15347
0
    inputPush(ctxt, stream);
15348
0
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
15349
0
}
15350
15351
/**
15352
 * xmlReadIO:
15353
 * @ioread:  an I/O read function
15354
 * @ioclose:  an I/O close function
15355
 * @ioctx:  an I/O handler
15356
 * @URL:  the base URL to use for the document
15357
 * @encoding:  the document encoding, or NULL
15358
 * @options:  a combination of xmlParserOption
15359
 *
15360
 * parse an XML document from I/O functions and source and build a tree.
15361
 *
15362
 * Returns the resulting document tree
15363
 */
15364
xmlDocPtr
15365
xmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
15366
          void *ioctx, const char *URL, const char *encoding, int options)
15367
0
{
15368
0
    xmlParserCtxtPtr ctxt;
15369
0
    xmlParserInputBufferPtr input;
15370
0
    xmlParserInputPtr stream;
15371
15372
0
    if (ioread == NULL)
15373
0
        return (NULL);
15374
0
    xmlInitParser();
15375
15376
0
    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
15377
0
                                         XML_CHAR_ENCODING_NONE);
15378
0
    if (input == NULL) {
15379
0
        if (ioclose != NULL)
15380
0
            ioclose(ioctx);
15381
0
        return (NULL);
15382
0
    }
15383
0
    ctxt = xmlNewParserCtxt();
15384
0
    if (ctxt == NULL) {
15385
0
        xmlFreeParserInputBuffer(input);
15386
0
        return (NULL);
15387
0
    }
15388
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15389
0
    if (stream == NULL) {
15390
0
        xmlFreeParserInputBuffer(input);
15391
0
  xmlFreeParserCtxt(ctxt);
15392
0
        return (NULL);
15393
0
    }
15394
0
    inputPush(ctxt, stream);
15395
0
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
15396
0
}
15397
15398
/**
15399
 * xmlCtxtReadDoc:
15400
 * @ctxt:  an XML parser context
15401
 * @cur:  a pointer to a zero terminated string
15402
 * @URL:  the base URL to use for the document
15403
 * @encoding:  the document encoding, or NULL
15404
 * @options:  a combination of xmlParserOption
15405
 *
15406
 * parse an XML in-memory document and build a tree.
15407
 * This reuses the existing @ctxt parser context
15408
 *
15409
 * Returns the resulting document tree
15410
 */
15411
xmlDocPtr
15412
xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar * cur,
15413
               const char *URL, const char *encoding, int options)
15414
0
{
15415
0
    if (cur == NULL)
15416
0
        return (NULL);
15417
0
    return (xmlCtxtReadMemory(ctxt, (const char *) cur, xmlStrlen(cur), URL,
15418
0
                              encoding, options));
15419
0
}
15420
15421
/**
15422
 * xmlCtxtReadFile:
15423
 * @ctxt:  an XML parser context
15424
 * @filename:  a file or URL
15425
 * @encoding:  the document encoding, or NULL
15426
 * @options:  a combination of xmlParserOption
15427
 *
15428
 * parse an XML file from the filesystem or the network.
15429
 * This reuses the existing @ctxt parser context
15430
 *
15431
 * Returns the resulting document tree
15432
 */
15433
xmlDocPtr
15434
xmlCtxtReadFile(xmlParserCtxtPtr ctxt, const char *filename,
15435
                const char *encoding, int options)
15436
0
{
15437
0
    xmlParserInputPtr stream;
15438
15439
0
    if (filename == NULL)
15440
0
        return (NULL);
15441
0
    if (ctxt == NULL)
15442
0
        return (NULL);
15443
0
    xmlInitParser();
15444
15445
0
    xmlCtxtReset(ctxt);
15446
15447
0
    stream = xmlLoadExternalEntity(filename, NULL, ctxt);
15448
0
    if (stream == NULL) {
15449
0
        return (NULL);
15450
0
    }
15451
0
    inputPush(ctxt, stream);
15452
0
    return (xmlDoRead(ctxt, NULL, encoding, options, 1));
15453
0
}
15454
15455
/**
15456
 * xmlCtxtReadMemory:
15457
 * @ctxt:  an XML parser context
15458
 * @buffer:  a pointer to a char array
15459
 * @size:  the size of the array
15460
 * @URL:  the base URL to use for the document
15461
 * @encoding:  the document encoding, or NULL
15462
 * @options:  a combination of xmlParserOption
15463
 *
15464
 * parse an XML in-memory document and build a tree.
15465
 * This reuses the existing @ctxt parser context
15466
 *
15467
 * Returns the resulting document tree
15468
 */
15469
xmlDocPtr
15470
xmlCtxtReadMemory(xmlParserCtxtPtr ctxt, const char *buffer, int size,
15471
                  const char *URL, const char *encoding, int options)
15472
0
{
15473
0
    xmlParserInputBufferPtr input;
15474
0
    xmlParserInputPtr stream;
15475
15476
0
    if (ctxt == NULL)
15477
0
        return (NULL);
15478
0
    if (buffer == NULL)
15479
0
        return (NULL);
15480
0
    xmlInitParser();
15481
15482
0
    xmlCtxtReset(ctxt);
15483
15484
0
    input = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
15485
0
    if (input == NULL) {
15486
0
  return(NULL);
15487
0
    }
15488
15489
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15490
0
    if (stream == NULL) {
15491
0
  xmlFreeParserInputBuffer(input);
15492
0
  return(NULL);
15493
0
    }
15494
15495
0
    inputPush(ctxt, stream);
15496
0
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15497
0
}
15498
15499
/**
15500
 * xmlCtxtReadFd:
15501
 * @ctxt:  an XML parser context
15502
 * @fd:  an open file descriptor
15503
 * @URL:  the base URL to use for the document
15504
 * @encoding:  the document encoding, or NULL
15505
 * @options:  a combination of xmlParserOption
15506
 *
15507
 * parse an XML from a file descriptor and build a tree.
15508
 * This reuses the existing @ctxt parser context
15509
 * NOTE that the file descriptor will not be closed when the
15510
 *      reader is closed or reset.
15511
 *
15512
 * Returns the resulting document tree
15513
 */
15514
xmlDocPtr
15515
xmlCtxtReadFd(xmlParserCtxtPtr ctxt, int fd,
15516
              const char *URL, const char *encoding, int options)
15517
0
{
15518
0
    xmlParserInputBufferPtr input;
15519
0
    xmlParserInputPtr stream;
15520
15521
0
    if (fd < 0)
15522
0
        return (NULL);
15523
0
    if (ctxt == NULL)
15524
0
        return (NULL);
15525
0
    xmlInitParser();
15526
15527
0
    xmlCtxtReset(ctxt);
15528
15529
15530
0
    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
15531
0
    if (input == NULL)
15532
0
        return (NULL);
15533
0
    input->closecallback = NULL;
15534
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15535
0
    if (stream == NULL) {
15536
0
        xmlFreeParserInputBuffer(input);
15537
0
        return (NULL);
15538
0
    }
15539
0
    inputPush(ctxt, stream);
15540
0
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15541
0
}
15542
15543
/**
15544
 * xmlCtxtReadIO:
15545
 * @ctxt:  an XML parser context
15546
 * @ioread:  an I/O read function
15547
 * @ioclose:  an I/O close function
15548
 * @ioctx:  an I/O handler
15549
 * @URL:  the base URL to use for the document
15550
 * @encoding:  the document encoding, or NULL
15551
 * @options:  a combination of xmlParserOption
15552
 *
15553
 * parse an XML document from I/O functions and source and build a tree.
15554
 * This reuses the existing @ctxt parser context
15555
 *
15556
 * Returns the resulting document tree
15557
 */
15558
xmlDocPtr
15559
xmlCtxtReadIO(xmlParserCtxtPtr ctxt, xmlInputReadCallback ioread,
15560
              xmlInputCloseCallback ioclose, void *ioctx,
15561
        const char *URL,
15562
              const char *encoding, int options)
15563
0
{
15564
0
    xmlParserInputBufferPtr input;
15565
0
    xmlParserInputPtr stream;
15566
15567
0
    if (ioread == NULL)
15568
0
        return (NULL);
15569
0
    if (ctxt == NULL)
15570
0
        return (NULL);
15571
0
    xmlInitParser();
15572
15573
0
    xmlCtxtReset(ctxt);
15574
15575
0
    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
15576
0
                                         XML_CHAR_ENCODING_NONE);
15577
0
    if (input == NULL) {
15578
0
        if (ioclose != NULL)
15579
0
            ioclose(ioctx);
15580
0
        return (NULL);
15581
0
    }
15582
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15583
0
    if (stream == NULL) {
15584
0
        xmlFreeParserInputBuffer(input);
15585
0
        return (NULL);
15586
0
    }
15587
0
    inputPush(ctxt, stream);
15588
0
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15589
0
}
15590