Coverage Report

Created: 2025-07-23 08:13

/src/fontconfig/subprojects/libxml2-2.12.6/parser.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * parser.c : an XML 1.0 parser, namespaces and validity support are mostly
3
 *            implemented on top of the SAX interfaces
4
 *
5
 * References:
6
 *   The XML specification:
7
 *     http://www.w3.org/TR/REC-xml
8
 *   Original 1.0 version:
9
 *     http://www.w3.org/TR/1998/REC-xml-19980210
10
 *   XML second edition working draft
11
 *     http://www.w3.org/TR/2000/WD-xml-2e-20000814
12
 *
13
 * Okay this is a big file, the parser core is around 7000 lines, then it
14
 * is followed by the progressive parser top routines, then the various
15
 * high level APIs to call the parser and a few miscellaneous functions.
16
 * A number of helper functions and deprecated ones have been moved to
17
 * parserInternals.c to reduce this file size.
18
 * As much as possible the functions are associated with their relative
19
 * production in the XML specification. A few productions defining the
20
 * different ranges of character are actually implanted either in
21
 * parserInternals.h or parserInternals.c
22
 * The DOM tree build is realized from the default SAX callbacks in
23
 * the module SAX.c.
24
 * The routines doing the validation checks are in valid.c and called either
25
 * from the SAX callbacks or as standalone functions using a preparsed
26
 * document.
27
 *
28
 * See Copyright for the status of this software.
29
 *
30
 * daniel@veillard.com
31
 */
32
33
/* To avoid EBCDIC trouble when parsing on zOS */
34
#if defined(__MVS__)
35
#pragma convert("ISO8859-1")
36
#endif
37
38
#define IN_LIBXML
39
#include "libxml.h"
40
41
#if defined(_WIN32)
42
#define XML_DIR_SEP '\\'
43
#else
44
#define XML_DIR_SEP '/'
45
#endif
46
47
#include <stdlib.h>
48
#include <limits.h>
49
#include <string.h>
50
#include <stdarg.h>
51
#include <stddef.h>
52
#include <ctype.h>
53
#include <stdlib.h>
54
#include <libxml/parser.h>
55
#include <libxml/xmlmemory.h>
56
#include <libxml/tree.h>
57
#include <libxml/parserInternals.h>
58
#include <libxml/valid.h>
59
#include <libxml/entities.h>
60
#include <libxml/xmlerror.h>
61
#include <libxml/encoding.h>
62
#include <libxml/xmlIO.h>
63
#include <libxml/uri.h>
64
#include <libxml/SAX2.h>
65
#ifdef LIBXML_CATALOG_ENABLED
66
#include <libxml/catalog.h>
67
#endif
68
69
#include "private/buf.h"
70
#include "private/dict.h"
71
#include "private/entities.h"
72
#include "private/error.h"
73
#include "private/html.h"
74
#include "private/io.h"
75
#include "private/parser.h"
76
77
0
#define NS_INDEX_EMPTY  INT_MAX
78
0
#define NS_INDEX_XML    (INT_MAX - 1)
79
0
#define URI_HASH_EMPTY  0xD943A04E
80
0
#define URI_HASH_XML    0xF0451F02
81
82
struct _xmlStartTag {
83
    const xmlChar *prefix;
84
    const xmlChar *URI;
85
    int line;
86
    int nsNr;
87
};
88
89
typedef struct {
90
    void *saxData;
91
    unsigned prefixHashValue;
92
    unsigned uriHashValue;
93
    unsigned elementId;
94
    int oldIndex;
95
} xmlParserNsExtra;
96
97
typedef struct {
98
    unsigned hashValue;
99
    int index;
100
} xmlParserNsBucket;
101
102
struct _xmlParserNsData {
103
    xmlParserNsExtra *extra;
104
105
    unsigned hashSize;
106
    unsigned hashElems;
107
    xmlParserNsBucket *hash;
108
109
    unsigned elementId;
110
    int defaultNsIndex;
111
};
112
113
struct _xmlAttrHashBucket {
114
    int index;
115
};
116
117
static xmlParserCtxtPtr
118
xmlCreateEntityParserCtxtInternal(xmlSAXHandlerPtr sax, void *userData,
119
        const xmlChar *URL, const xmlChar *ID, const xmlChar *base,
120
        xmlParserCtxtPtr pctx);
121
122
static int
123
xmlParseElementStart(xmlParserCtxtPtr ctxt);
124
125
static void
126
xmlParseElementEnd(xmlParserCtxtPtr ctxt);
127
128
/************************************************************************
129
 *                  *
130
 *  Arbitrary limits set in the parser. See XML_PARSE_HUGE    *
131
 *                  *
132
 ************************************************************************/
133
134
#define XML_PARSER_BIG_ENTITY 1000
135
#define XML_PARSER_LOT_ENTITY 5000
136
137
/*
138
 * Constants for protection against abusive entity expansion
139
 * ("billion laughs").
140
 */
141
142
/*
143
 * A certain amount of entity expansion which is always allowed.
144
 */
145
0
#define XML_PARSER_ALLOWED_EXPANSION 1000000
146
147
/*
148
 * Fixed cost for each entity reference. This crudely models processing time
149
 * as well to protect, for example, against exponential expansion of empty
150
 * or very short entities.
151
 */
152
0
#define XML_ENT_FIXED_COST 20
153
154
/**
155
 * xmlParserMaxDepth:
156
 *
157
 * arbitrary depth limit for the XML documents that we allow to
158
 * process. This is not a limitation of the parser but a safety
159
 * boundary feature. It can be disabled with the XML_PARSE_HUGE
160
 * parser option.
161
 */
162
unsigned int xmlParserMaxDepth = 256;
163
164
165
166
176
#define XML_PARSER_BIG_BUFFER_SIZE 300
167
0
#define XML_PARSER_BUFFER_SIZE 100
168
0
#define SAX_COMPAT_MODE BAD_CAST "SAX compatibility mode document"
169
170
/**
171
 * XML_PARSER_CHUNK_SIZE
172
 *
173
 * When calling GROW that's the minimal amount of data
174
 * the parser expected to have received. It is not a hard
175
 * limit but an optimization when reading strings like Names
176
 * It is not strictly needed as long as inputs available characters
177
 * are followed by 0, which should be provided by the I/O level
178
 */
179
#define XML_PARSER_CHUNK_SIZE 100
180
181
/**
182
 * xmlParserVersion:
183
 *
184
 * Constant string describing the internal version of the library
185
 */
186
const char *const
187
xmlParserVersion = LIBXML_VERSION_STRING LIBXML_VERSION_EXTRA;
188
189
/*
190
 * List of XML prefixed PI allowed by W3C specs
191
 */
192
193
static const char* const xmlW3CPIs[] = {
194
    "xml-stylesheet",
195
    "xml-model",
196
    NULL
197
};
198
199
200
/* DEPR void xmlParserHandleReference(xmlParserCtxtPtr ctxt); */
201
static xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt,
202
                                              const xmlChar **str);
203
204
static xmlParserErrors
205
xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
206
                xmlSAXHandlerPtr sax,
207
          void *user_data, int depth, const xmlChar *URL,
208
          const xmlChar *ID, xmlNodePtr *list);
209
210
static int
211
xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options);
212
#ifdef LIBXML_LEGACY_ENABLED
213
static void
214
xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
215
                      xmlNodePtr lastNode);
216
#endif /* LIBXML_LEGACY_ENABLED */
217
218
static xmlParserErrors
219
xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
220
          const xmlChar *string, void *user_data, xmlNodePtr *lst);
221
222
static int
223
xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity);
224
225
/************************************************************************
226
 *                  *
227
 *    Some factorized error routines        *
228
 *                  *
229
 ************************************************************************/
230
231
/**
232
 * xmlErrAttributeDup:
233
 * @ctxt:  an XML parser context
234
 * @prefix:  the attribute prefix
235
 * @localname:  the attribute localname
236
 *
237
 * Handle a redefinition of attribute error
238
 */
239
static void
240
xmlErrAttributeDup(xmlParserCtxtPtr ctxt, const xmlChar * prefix,
241
                   const xmlChar * localname)
242
0
{
243
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
244
0
        (ctxt->instate == XML_PARSER_EOF))
245
0
  return;
246
0
    if (ctxt != NULL)
247
0
  ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
248
249
0
    if (prefix == NULL)
250
0
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
251
0
                        XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
252
0
                        (const char *) localname, NULL, NULL, 0, 0,
253
0
                        "Attribute %s redefined\n", localname);
254
0
    else
255
0
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
256
0
                        XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
257
0
                        (const char *) prefix, (const char *) localname,
258
0
                        NULL, 0, 0, "Attribute %s:%s redefined\n", prefix,
259
0
                        localname);
260
0
    if (ctxt != NULL) {
261
0
  ctxt->wellFormed = 0;
262
0
  if (ctxt->recovery == 0)
263
0
      ctxt->disableSAX = 1;
264
0
    }
265
0
}
266
267
/**
268
 * xmlFatalErrMsg:
269
 * @ctxt:  an XML parser context
270
 * @error:  the error number
271
 * @msg:  the error message
272
 *
273
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
274
 */
275
static void LIBXML_ATTR_FORMAT(3,0)
276
xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
277
               const char *msg)
278
0
{
279
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
280
0
        (ctxt->instate == XML_PARSER_EOF))
281
0
  return;
282
0
    if (ctxt != NULL)
283
0
  ctxt->errNo = error;
284
0
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
285
0
                    XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
286
0
    if (ctxt != NULL) {
287
0
  ctxt->wellFormed = 0;
288
0
  if (ctxt->recovery == 0)
289
0
      ctxt->disableSAX = 1;
290
0
    }
291
0
}
292
293
/**
294
 * xmlWarningMsg:
295
 * @ctxt:  an XML parser context
296
 * @error:  the error number
297
 * @msg:  the error message
298
 * @str1:  extra data
299
 * @str2:  extra data
300
 *
301
 * Handle a warning.
302
 */
303
void LIBXML_ATTR_FORMAT(3,0)
304
xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
305
              const char *msg, const xmlChar *str1, const xmlChar *str2)
306
0
{
307
0
    xmlStructuredErrorFunc schannel = NULL;
308
309
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
310
0
        (ctxt->instate == XML_PARSER_EOF))
311
0
  return;
312
0
    if ((ctxt != NULL) && (ctxt->sax != NULL) &&
313
0
        (ctxt->sax->initialized == XML_SAX2_MAGIC))
314
0
        schannel = ctxt->sax->serror;
315
0
    if (ctxt != NULL) {
316
0
        __xmlRaiseError(schannel,
317
0
                    (ctxt->sax) ? ctxt->sax->warning : NULL,
318
0
                    ctxt->userData,
319
0
                    ctxt, NULL, XML_FROM_PARSER, error,
320
0
                    XML_ERR_WARNING, NULL, 0,
321
0
        (const char *) str1, (const char *) str2, NULL, 0, 0,
322
0
        msg, (const char *) str1, (const char *) str2);
323
0
    } else {
324
0
        __xmlRaiseError(schannel, NULL, NULL,
325
0
                    ctxt, NULL, XML_FROM_PARSER, error,
326
0
                    XML_ERR_WARNING, NULL, 0,
327
0
        (const char *) str1, (const char *) str2, NULL, 0, 0,
328
0
        msg, (const char *) str1, (const char *) str2);
329
0
    }
330
0
}
331
332
/**
333
 * xmlValidityError:
334
 * @ctxt:  an XML parser context
335
 * @error:  the error number
336
 * @msg:  the error message
337
 * @str1:  extra data
338
 *
339
 * Handle a validity error.
340
 */
341
static void LIBXML_ATTR_FORMAT(3,0)
342
xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error,
343
              const char *msg, const xmlChar *str1, const xmlChar *str2)
344
0
{
345
0
    xmlStructuredErrorFunc schannel = NULL;
346
347
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
348
0
        (ctxt->instate == XML_PARSER_EOF))
349
0
  return;
350
0
    if (ctxt != NULL) {
351
0
  ctxt->errNo = error;
352
0
  if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
353
0
      schannel = ctxt->sax->serror;
354
0
    }
355
0
    if (ctxt != NULL) {
356
0
        __xmlRaiseError(schannel,
357
0
                    ctxt->vctxt.error, ctxt->vctxt.userData,
358
0
                    ctxt, NULL, XML_FROM_DTD, error,
359
0
                    XML_ERR_ERROR, NULL, 0, (const char *) str1,
360
0
        (const char *) str2, NULL, 0, 0,
361
0
        msg, (const char *) str1, (const char *) str2);
362
0
  ctxt->valid = 0;
363
0
    } else {
364
0
        __xmlRaiseError(schannel, NULL, NULL,
365
0
                    ctxt, NULL, XML_FROM_DTD, error,
366
0
                    XML_ERR_ERROR, NULL, 0, (const char *) str1,
367
0
        (const char *) str2, NULL, 0, 0,
368
0
        msg, (const char *) str1, (const char *) str2);
369
0
    }
370
0
}
371
372
/**
373
 * xmlFatalErrMsgInt:
374
 * @ctxt:  an XML parser context
375
 * @error:  the error number
376
 * @msg:  the error message
377
 * @val:  an integer value
378
 *
379
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
380
 */
381
static void LIBXML_ATTR_FORMAT(3,0)
382
xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
383
                  const char *msg, int val)
384
0
{
385
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
386
0
        (ctxt->instate == XML_PARSER_EOF))
387
0
  return;
388
0
    if (ctxt != NULL)
389
0
  ctxt->errNo = error;
390
0
    __xmlRaiseError(NULL, NULL, NULL,
391
0
                    ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
392
0
                    NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
393
0
    if (ctxt != NULL) {
394
0
  ctxt->wellFormed = 0;
395
0
  if (ctxt->recovery == 0)
396
0
      ctxt->disableSAX = 1;
397
0
    }
398
0
}
399
400
/**
401
 * xmlFatalErrMsgStrIntStr:
402
 * @ctxt:  an XML parser context
403
 * @error:  the error number
404
 * @msg:  the error message
405
 * @str1:  an string info
406
 * @val:  an integer value
407
 * @str2:  an string info
408
 *
409
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
410
 */
411
static void LIBXML_ATTR_FORMAT(3,0)
412
xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
413
                  const char *msg, const xmlChar *str1, int val,
414
      const xmlChar *str2)
415
0
{
416
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
417
0
        (ctxt->instate == XML_PARSER_EOF))
418
0
  return;
419
0
    if (ctxt != NULL)
420
0
  ctxt->errNo = error;
421
0
    __xmlRaiseError(NULL, NULL, NULL,
422
0
                    ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
423
0
                    NULL, 0, (const char *) str1, (const char *) str2,
424
0
        NULL, val, 0, msg, str1, val, str2);
425
0
    if (ctxt != NULL) {
426
0
  ctxt->wellFormed = 0;
427
0
  if (ctxt->recovery == 0)
428
0
      ctxt->disableSAX = 1;
429
0
    }
430
0
}
431
432
/**
433
 * xmlFatalErrMsgStr:
434
 * @ctxt:  an XML parser context
435
 * @error:  the error number
436
 * @msg:  the error message
437
 * @val:  a string value
438
 *
439
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
440
 */
441
static void LIBXML_ATTR_FORMAT(3,0)
442
xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
443
                  const char *msg, const xmlChar * val)
444
0
{
445
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
446
0
        (ctxt->instate == XML_PARSER_EOF))
447
0
  return;
448
0
    if (ctxt != NULL)
449
0
  ctxt->errNo = error;
450
0
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
451
0
                    XML_FROM_PARSER, error, XML_ERR_FATAL,
452
0
                    NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
453
0
                    val);
454
0
    if (ctxt != NULL) {
455
0
  ctxt->wellFormed = 0;
456
0
  if (ctxt->recovery == 0)
457
0
      ctxt->disableSAX = 1;
458
0
    }
459
0
}
460
461
/**
462
 * xmlErrMsgStr:
463
 * @ctxt:  an XML parser context
464
 * @error:  the error number
465
 * @msg:  the error message
466
 * @val:  a string value
467
 *
468
 * Handle a non fatal parser error
469
 */
470
static void LIBXML_ATTR_FORMAT(3,0)
471
xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
472
                  const char *msg, const xmlChar * val)
473
0
{
474
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
475
0
        (ctxt->instate == XML_PARSER_EOF))
476
0
  return;
477
0
    if (ctxt != NULL)
478
0
  ctxt->errNo = error;
479
0
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
480
0
                    XML_FROM_PARSER, error, XML_ERR_ERROR,
481
0
                    NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
482
0
                    val);
483
0
}
484
485
/**
486
 * xmlNsErr:
487
 * @ctxt:  an XML parser context
488
 * @error:  the error number
489
 * @msg:  the message
490
 * @info1:  extra information string
491
 * @info2:  extra information string
492
 *
493
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
494
 */
495
static void LIBXML_ATTR_FORMAT(3,0)
496
xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
497
         const char *msg,
498
         const xmlChar * info1, const xmlChar * info2,
499
         const xmlChar * info3)
500
0
{
501
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
502
0
        (ctxt->instate == XML_PARSER_EOF))
503
0
  return;
504
0
    if (ctxt != NULL)
505
0
  ctxt->errNo = error;
506
0
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
507
0
                    XML_ERR_ERROR, NULL, 0, (const char *) info1,
508
0
                    (const char *) info2, (const char *) info3, 0, 0, msg,
509
0
                    info1, info2, info3);
510
0
    if (ctxt != NULL)
511
0
  ctxt->nsWellFormed = 0;
512
0
}
513
514
/**
515
 * xmlNsWarn
516
 * @ctxt:  an XML parser context
517
 * @error:  the error number
518
 * @msg:  the message
519
 * @info1:  extra information string
520
 * @info2:  extra information string
521
 *
522
 * Handle a namespace warning error
523
 */
524
static void LIBXML_ATTR_FORMAT(3,0)
525
xmlNsWarn(xmlParserCtxtPtr ctxt, xmlParserErrors error,
526
         const char *msg,
527
         const xmlChar * info1, const xmlChar * info2,
528
         const xmlChar * info3)
529
0
{
530
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
531
0
        (ctxt->instate == XML_PARSER_EOF))
532
0
  return;
533
0
    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
534
0
                    XML_ERR_WARNING, NULL, 0, (const char *) info1,
535
0
                    (const char *) info2, (const char *) info3, 0, 0, msg,
536
0
                    info1, info2, info3);
537
0
}
538
539
static void
540
0
xmlSaturatedAdd(unsigned long *dst, unsigned long val) {
541
0
    if (val > ULONG_MAX - *dst)
542
0
        *dst = ULONG_MAX;
543
0
    else
544
0
        *dst += val;
545
0
}
546
547
static void
548
0
xmlSaturatedAddSizeT(unsigned long *dst, unsigned long val) {
549
0
    if (val > ULONG_MAX - *dst)
550
0
        *dst = ULONG_MAX;
551
0
    else
552
0
        *dst += val;
553
0
}
554
555
/**
556
 * xmlParserEntityCheck:
557
 * @ctxt:  parser context
558
 * @extra:  sum of unexpanded entity sizes
559
 *
560
 * Check for non-linear entity expansion behaviour.
561
 *
562
 * In some cases like xmlStringDecodeEntities, this function is called
563
 * for each, possibly nested entity and its unexpanded content length.
564
 *
565
 * In other cases like xmlParseReference, it's only called for each
566
 * top-level entity with its unexpanded content length plus the sum of
567
 * the unexpanded content lengths (plus fixed cost) of all nested
568
 * entities.
569
 *
570
 * Summing the unexpanded lengths also adds the length of the reference.
571
 * This is by design. Taking the length of the entity name into account
572
 * discourages attacks that try to waste CPU time with abusively long
573
 * entity names. See test/recurse/lol6.xml for example. Each call also
574
 * adds some fixed cost XML_ENT_FIXED_COST to discourage attacks with
575
 * short entities.
576
 *
577
 * Returns 1 on error, 0 on success.
578
 */
579
static int
580
xmlParserEntityCheck(xmlParserCtxtPtr ctxt, unsigned long extra)
581
0
{
582
0
    unsigned long consumed;
583
0
    xmlParserInputPtr input = ctxt->input;
584
0
    xmlEntityPtr entity = input->entity;
585
586
    /*
587
     * Compute total consumed bytes so far, including input streams of
588
     * external entities.
589
     */
590
0
    consumed = input->parentConsumed;
591
0
    if ((entity == NULL) ||
592
0
        ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
593
0
         ((entity->flags & XML_ENT_PARSED) == 0))) {
594
0
        xmlSaturatedAdd(&consumed, input->consumed);
595
0
        xmlSaturatedAddSizeT(&consumed, input->cur - input->base);
596
0
    }
597
0
    xmlSaturatedAdd(&consumed, ctxt->sizeentities);
598
599
    /*
600
     * Add extra cost and some fixed cost.
601
     */
602
0
    xmlSaturatedAdd(&ctxt->sizeentcopy, extra);
603
0
    xmlSaturatedAdd(&ctxt->sizeentcopy, XML_ENT_FIXED_COST);
604
605
    /*
606
     * It's important to always use saturation arithmetic when tracking
607
     * entity sizes to make the size checks reliable. If "sizeentcopy"
608
     * overflows, we have to abort.
609
     */
610
0
    if ((ctxt->sizeentcopy > XML_PARSER_ALLOWED_EXPANSION) &&
611
0
        ((ctxt->sizeentcopy >= ULONG_MAX) ||
612
0
         (ctxt->sizeentcopy / ctxt->maxAmpl > consumed))) {
613
0
        xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_LOOP,
614
0
                       "Maximum entity amplification factor exceeded, see "
615
0
                       "xmlCtxtSetMaxAmplification.\n");
616
0
        xmlHaltParser(ctxt);
617
0
        return(1);
618
0
    }
619
620
0
    return(0);
621
0
}
622
623
/************************************************************************
624
 *                  *
625
 *    Library wide options          *
626
 *                  *
627
 ************************************************************************/
628
629
/**
630
  * xmlHasFeature:
631
  * @feature: the feature to be examined
632
  *
633
  * Examines if the library has been compiled with a given feature.
634
  *
635
  * Returns a non-zero value if the feature exist, otherwise zero.
636
  * Returns zero (0) if the feature does not exist or an unknown
637
  * unknown feature is requested, non-zero otherwise.
638
  */
639
int
640
xmlHasFeature(xmlFeature feature)
641
0
{
642
0
    switch (feature) {
643
0
  case XML_WITH_THREAD:
644
0
#ifdef LIBXML_THREAD_ENABLED
645
0
      return(1);
646
#else
647
      return(0);
648
#endif
649
0
        case XML_WITH_TREE:
650
0
#ifdef LIBXML_TREE_ENABLED
651
0
            return(1);
652
#else
653
            return(0);
654
#endif
655
0
        case XML_WITH_OUTPUT:
656
0
#ifdef LIBXML_OUTPUT_ENABLED
657
0
            return(1);
658
#else
659
            return(0);
660
#endif
661
0
        case XML_WITH_PUSH:
662
0
#ifdef LIBXML_PUSH_ENABLED
663
0
            return(1);
664
#else
665
            return(0);
666
#endif
667
0
        case XML_WITH_READER:
668
0
#ifdef LIBXML_READER_ENABLED
669
0
            return(1);
670
#else
671
            return(0);
672
#endif
673
0
        case XML_WITH_PATTERN:
674
0
#ifdef LIBXML_PATTERN_ENABLED
675
0
            return(1);
676
#else
677
            return(0);
678
#endif
679
0
        case XML_WITH_WRITER:
680
0
#ifdef LIBXML_WRITER_ENABLED
681
0
            return(1);
682
#else
683
            return(0);
684
#endif
685
0
        case XML_WITH_SAX1:
686
0
#ifdef LIBXML_SAX1_ENABLED
687
0
            return(1);
688
#else
689
            return(0);
690
#endif
691
0
        case XML_WITH_FTP:
692
#ifdef LIBXML_FTP_ENABLED
693
            return(1);
694
#else
695
0
            return(0);
696
0
#endif
697
0
        case XML_WITH_HTTP:
698
0
#ifdef LIBXML_HTTP_ENABLED
699
0
            return(1);
700
#else
701
            return(0);
702
#endif
703
0
        case XML_WITH_VALID:
704
0
#ifdef LIBXML_VALID_ENABLED
705
0
            return(1);
706
#else
707
            return(0);
708
#endif
709
0
        case XML_WITH_HTML:
710
0
#ifdef LIBXML_HTML_ENABLED
711
0
            return(1);
712
#else
713
            return(0);
714
#endif
715
0
        case XML_WITH_LEGACY:
716
#ifdef LIBXML_LEGACY_ENABLED
717
            return(1);
718
#else
719
0
            return(0);
720
0
#endif
721
0
        case XML_WITH_C14N:
722
0
#ifdef LIBXML_C14N_ENABLED
723
0
            return(1);
724
#else
725
            return(0);
726
#endif
727
0
        case XML_WITH_CATALOG:
728
0
#ifdef LIBXML_CATALOG_ENABLED
729
0
            return(1);
730
#else
731
            return(0);
732
#endif
733
0
        case XML_WITH_XPATH:
734
0
#ifdef LIBXML_XPATH_ENABLED
735
0
            return(1);
736
#else
737
            return(0);
738
#endif
739
0
        case XML_WITH_XPTR:
740
0
#ifdef LIBXML_XPTR_ENABLED
741
0
            return(1);
742
#else
743
            return(0);
744
#endif
745
0
        case XML_WITH_XINCLUDE:
746
0
#ifdef LIBXML_XINCLUDE_ENABLED
747
0
            return(1);
748
#else
749
            return(0);
750
#endif
751
0
        case XML_WITH_ICONV:
752
0
#ifdef LIBXML_ICONV_ENABLED
753
0
            return(1);
754
#else
755
            return(0);
756
#endif
757
0
        case XML_WITH_ISO8859X:
758
0
#ifdef LIBXML_ISO8859X_ENABLED
759
0
            return(1);
760
#else
761
            return(0);
762
#endif
763
0
        case XML_WITH_UNICODE:
764
0
#ifdef LIBXML_UNICODE_ENABLED
765
0
            return(1);
766
#else
767
            return(0);
768
#endif
769
0
        case XML_WITH_REGEXP:
770
0
#ifdef LIBXML_REGEXP_ENABLED
771
0
            return(1);
772
#else
773
            return(0);
774
#endif
775
0
        case XML_WITH_AUTOMATA:
776
0
#ifdef LIBXML_AUTOMATA_ENABLED
777
0
            return(1);
778
#else
779
            return(0);
780
#endif
781
0
        case XML_WITH_EXPR:
782
#ifdef LIBXML_EXPR_ENABLED
783
            return(1);
784
#else
785
0
            return(0);
786
0
#endif
787
0
        case XML_WITH_SCHEMAS:
788
0
#ifdef LIBXML_SCHEMAS_ENABLED
789
0
            return(1);
790
#else
791
            return(0);
792
#endif
793
0
        case XML_WITH_SCHEMATRON:
794
0
#ifdef LIBXML_SCHEMATRON_ENABLED
795
0
            return(1);
796
#else
797
            return(0);
798
#endif
799
0
        case XML_WITH_MODULES:
800
0
#ifdef LIBXML_MODULES_ENABLED
801
0
            return(1);
802
#else
803
            return(0);
804
#endif
805
0
        case XML_WITH_DEBUG:
806
0
#ifdef LIBXML_DEBUG_ENABLED
807
0
            return(1);
808
#else
809
            return(0);
810
#endif
811
0
        case XML_WITH_DEBUG_MEM:
812
#ifdef DEBUG_MEMORY_LOCATION
813
            return(1);
814
#else
815
0
            return(0);
816
0
#endif
817
0
        case XML_WITH_DEBUG_RUN:
818
0
            return(0);
819
0
        case XML_WITH_ZLIB:
820
0
#ifdef LIBXML_ZLIB_ENABLED
821
0
            return(1);
822
#else
823
            return(0);
824
#endif
825
0
        case XML_WITH_LZMA:
826
#ifdef LIBXML_LZMA_ENABLED
827
            return(1);
828
#else
829
0
            return(0);
830
0
#endif
831
0
        case XML_WITH_ICU:
832
#ifdef LIBXML_ICU_ENABLED
833
            return(1);
834
#else
835
0
            return(0);
836
0
#endif
837
0
        default:
838
0
      break;
839
0
     }
840
0
     return(0);
841
0
}
842
843
/************************************************************************
844
 *                  *
845
 *    SAX2 defaulted attributes handling      *
846
 *                  *
847
 ************************************************************************/
848
849
/**
850
 * xmlDetectSAX2:
851
 * @ctxt:  an XML parser context
852
 *
853
 * Do the SAX2 detection and specific initialization
854
 */
855
static void
856
11
xmlDetectSAX2(xmlParserCtxtPtr ctxt) {
857
11
    xmlSAXHandlerPtr sax;
858
859
    /* Avoid unused variable warning if features are disabled. */
860
11
    (void) sax;
861
862
11
    if (ctxt == NULL) return;
863
11
    sax = ctxt->sax;
864
11
#ifdef LIBXML_SAX1_ENABLED
865
    /*
866
     * Only enable SAX2 if there SAX2 element handlers, except when there
867
     * are no element handlers at all.
868
     */
869
11
    if ((sax) && (sax->initialized == XML_SAX2_MAGIC) &&
870
11
        ((sax->startElementNs != NULL) ||
871
0
         (sax->endElementNs != NULL) ||
872
0
         ((sax->startElement == NULL) && (sax->endElement == NULL))))
873
0
        ctxt->sax2 = 1;
874
#else
875
    ctxt->sax2 = 1;
876
#endif /* LIBXML_SAX1_ENABLED */
877
878
11
    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
879
11
    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
880
11
    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
881
11
    if ((ctxt->str_xml==NULL) || (ctxt->str_xmlns==NULL) ||
882
11
    (ctxt->str_xml_ns == NULL)) {
883
0
        xmlErrMemory(ctxt, NULL);
884
0
    }
885
11
}
886
887
typedef struct {
888
    xmlHashedString prefix;
889
    xmlHashedString name;
890
    xmlHashedString value;
891
    const xmlChar *valueEnd;
892
    int external;
893
    int expandedSize;
894
} xmlDefAttr;
895
896
typedef struct _xmlDefAttrs xmlDefAttrs;
897
typedef xmlDefAttrs *xmlDefAttrsPtr;
898
struct _xmlDefAttrs {
899
    int nbAttrs;  /* number of defaulted attributes on that element */
900
    int maxAttrs;       /* the size of the array */
901
#if __STDC_VERSION__ >= 199901L
902
    /* Using a C99 flexible array member avoids UBSan errors. */
903
    xmlDefAttr attrs[]; /* array of localname/prefix/values/external */
904
#else
905
    xmlDefAttr attrs[1];
906
#endif
907
};
908
909
/**
910
 * xmlAttrNormalizeSpace:
911
 * @src: the source string
912
 * @dst: the target string
913
 *
914
 * Normalize the space in non CDATA attribute values:
915
 * If the attribute type is not CDATA, then the XML processor MUST further
916
 * process the normalized attribute value by discarding any leading and
917
 * trailing space (#x20) characters, and by replacing sequences of space
918
 * (#x20) characters by a single space (#x20) character.
919
 * Note that the size of dst need to be at least src, and if one doesn't need
920
 * to preserve dst (and it doesn't come from a dictionary or read-only) then
921
 * passing src as dst is just fine.
922
 *
923
 * Returns a pointer to the normalized value (dst) or NULL if no conversion
924
 *         is needed.
925
 */
926
static xmlChar *
927
xmlAttrNormalizeSpace(const xmlChar *src, xmlChar *dst)
928
0
{
929
0
    if ((src == NULL) || (dst == NULL))
930
0
        return(NULL);
931
932
0
    while (*src == 0x20) src++;
933
0
    while (*src != 0) {
934
0
  if (*src == 0x20) {
935
0
      while (*src == 0x20) src++;
936
0
      if (*src != 0)
937
0
    *dst++ = 0x20;
938
0
  } else {
939
0
      *dst++ = *src++;
940
0
  }
941
0
    }
942
0
    *dst = 0;
943
0
    if (dst == src)
944
0
       return(NULL);
945
0
    return(dst);
946
0
}
947
948
/**
949
 * xmlAttrNormalizeSpace2:
950
 * @src: the source string
951
 *
952
 * Normalize the space in non CDATA attribute values, a slightly more complex
953
 * front end to avoid allocation problems when running on attribute values
954
 * coming from the input.
955
 *
956
 * Returns a pointer to the normalized value (dst) or NULL if no conversion
957
 *         is needed.
958
 */
959
static const xmlChar *
960
xmlAttrNormalizeSpace2(xmlParserCtxtPtr ctxt, xmlChar *src, int *len)
961
0
{
962
0
    int i;
963
0
    int remove_head = 0;
964
0
    int need_realloc = 0;
965
0
    const xmlChar *cur;
966
967
0
    if ((ctxt == NULL) || (src == NULL) || (len == NULL))
968
0
        return(NULL);
969
0
    i = *len;
970
0
    if (i <= 0)
971
0
        return(NULL);
972
973
0
    cur = src;
974
0
    while (*cur == 0x20) {
975
0
        cur++;
976
0
  remove_head++;
977
0
    }
978
0
    while (*cur != 0) {
979
0
  if (*cur == 0x20) {
980
0
      cur++;
981
0
      if ((*cur == 0x20) || (*cur == 0)) {
982
0
          need_realloc = 1;
983
0
    break;
984
0
      }
985
0
  } else
986
0
      cur++;
987
0
    }
988
0
    if (need_realloc) {
989
0
        xmlChar *ret;
990
991
0
  ret = xmlStrndup(src + remove_head, i - remove_head + 1);
992
0
  if (ret == NULL) {
993
0
      xmlErrMemory(ctxt, NULL);
994
0
      return(NULL);
995
0
  }
996
0
  xmlAttrNormalizeSpace(ret, ret);
997
0
  *len = strlen((const char *)ret);
998
0
        return(ret);
999
0
    } else if (remove_head) {
1000
0
        *len -= remove_head;
1001
0
        memmove(src, src + remove_head, 1 + *len);
1002
0
  return(src);
1003
0
    }
1004
0
    return(NULL);
1005
0
}
1006
1007
/**
1008
 * xmlAddDefAttrs:
1009
 * @ctxt:  an XML parser context
1010
 * @fullname:  the element fullname
1011
 * @fullattr:  the attribute fullname
1012
 * @value:  the attribute value
1013
 *
1014
 * Add a defaulted attribute for an element
1015
 */
1016
static void
1017
xmlAddDefAttrs(xmlParserCtxtPtr ctxt,
1018
               const xmlChar *fullname,
1019
               const xmlChar *fullattr,
1020
0
               const xmlChar *value) {
1021
0
    xmlDefAttrsPtr defaults;
1022
0
    xmlDefAttr *attr;
1023
0
    int len, expandedSize;
1024
0
    xmlHashedString name;
1025
0
    xmlHashedString prefix;
1026
0
    xmlHashedString hvalue;
1027
0
    const xmlChar *localname;
1028
1029
    /*
1030
     * Allows to detect attribute redefinitions
1031
     */
1032
0
    if (ctxt->attsSpecial != NULL) {
1033
0
        if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL)
1034
0
      return;
1035
0
    }
1036
1037
0
    if (ctxt->attsDefault == NULL) {
1038
0
        ctxt->attsDefault = xmlHashCreateDict(10, ctxt->dict);
1039
0
  if (ctxt->attsDefault == NULL)
1040
0
      goto mem_error;
1041
0
    }
1042
1043
    /*
1044
     * split the element name into prefix:localname , the string found
1045
     * are within the DTD and then not associated to namespace names.
1046
     */
1047
0
    localname = xmlSplitQName3(fullname, &len);
1048
0
    if (localname == NULL) {
1049
0
        name = xmlDictLookupHashed(ctxt->dict, fullname, -1);
1050
0
  prefix.name = NULL;
1051
0
    } else {
1052
0
        name = xmlDictLookupHashed(ctxt->dict, localname, -1);
1053
0
  prefix = xmlDictLookupHashed(ctxt->dict, fullname, len);
1054
0
        if (prefix.name == NULL)
1055
0
            goto mem_error;
1056
0
    }
1057
0
    if (name.name == NULL)
1058
0
        goto mem_error;
1059
1060
    /*
1061
     * make sure there is some storage
1062
     */
1063
0
    defaults = xmlHashLookup2(ctxt->attsDefault, name.name, prefix.name);
1064
0
    if ((defaults == NULL) ||
1065
0
        (defaults->nbAttrs >= defaults->maxAttrs)) {
1066
0
        xmlDefAttrsPtr temp;
1067
0
        int newSize;
1068
1069
0
        newSize = (defaults != NULL) ? 2 * defaults->maxAttrs : 4;
1070
0
        temp = xmlRealloc(defaults,
1071
0
                          sizeof(*defaults) + newSize * sizeof(xmlDefAttr));
1072
0
  if (temp == NULL)
1073
0
      goto mem_error;
1074
0
        if (defaults == NULL)
1075
0
            temp->nbAttrs = 0;
1076
0
  temp->maxAttrs = newSize;
1077
0
        defaults = temp;
1078
0
  if (xmlHashUpdateEntry2(ctxt->attsDefault, name.name, prefix.name,
1079
0
                          defaults, NULL) < 0) {
1080
0
      xmlFree(defaults);
1081
0
      goto mem_error;
1082
0
  }
1083
0
    }
1084
1085
    /*
1086
     * Split the attribute name into prefix:localname , the string found
1087
     * are within the DTD and hen not associated to namespace names.
1088
     */
1089
0
    localname = xmlSplitQName3(fullattr, &len);
1090
0
    if (localname == NULL) {
1091
0
        name = xmlDictLookupHashed(ctxt->dict, fullattr, -1);
1092
0
  prefix.name = NULL;
1093
0
    } else {
1094
0
        name = xmlDictLookupHashed(ctxt->dict, localname, -1);
1095
0
  prefix = xmlDictLookupHashed(ctxt->dict, fullattr, len);
1096
0
        if (prefix.name == NULL)
1097
0
            goto mem_error;
1098
0
    }
1099
0
    if (name.name == NULL)
1100
0
        goto mem_error;
1101
1102
    /* intern the string and precompute the end */
1103
0
    len = strlen((const char *) value);
1104
0
    hvalue = xmlDictLookupHashed(ctxt->dict, value, len);
1105
0
    if (hvalue.name == NULL)
1106
0
        goto mem_error;
1107
1108
0
    expandedSize = strlen((const char *) name.name);
1109
0
    if (prefix.name != NULL)
1110
0
        expandedSize += strlen((const char *) prefix.name);
1111
0
    expandedSize += len;
1112
1113
0
    attr = &defaults->attrs[defaults->nbAttrs++];
1114
0
    attr->name = name;
1115
0
    attr->prefix = prefix;
1116
0
    attr->value = hvalue;
1117
0
    attr->valueEnd = hvalue.name + len;
1118
0
    attr->external = ctxt->external;
1119
0
    attr->expandedSize = expandedSize;
1120
1121
0
    return;
1122
1123
0
mem_error:
1124
0
    xmlErrMemory(ctxt, NULL);
1125
0
    return;
1126
0
}
1127
1128
/**
1129
 * xmlAddSpecialAttr:
1130
 * @ctxt:  an XML parser context
1131
 * @fullname:  the element fullname
1132
 * @fullattr:  the attribute fullname
1133
 * @type:  the attribute type
1134
 *
1135
 * Register this attribute type
1136
 */
1137
static void
1138
xmlAddSpecialAttr(xmlParserCtxtPtr ctxt,
1139
      const xmlChar *fullname,
1140
      const xmlChar *fullattr,
1141
      int type)
1142
0
{
1143
0
    if (ctxt->attsSpecial == NULL) {
1144
0
        ctxt->attsSpecial = xmlHashCreateDict(10, ctxt->dict);
1145
0
  if (ctxt->attsSpecial == NULL)
1146
0
      goto mem_error;
1147
0
    }
1148
1149
0
    if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL)
1150
0
        return;
1151
1152
0
    xmlHashAddEntry2(ctxt->attsSpecial, fullname, fullattr,
1153
0
                     (void *) (ptrdiff_t) type);
1154
0
    return;
1155
1156
0
mem_error:
1157
0
    xmlErrMemory(ctxt, NULL);
1158
0
    return;
1159
0
}
1160
1161
/**
1162
 * xmlCleanSpecialAttrCallback:
1163
 *
1164
 * Removes CDATA attributes from the special attribute table
1165
 */
1166
static void
1167
xmlCleanSpecialAttrCallback(void *payload, void *data,
1168
                            const xmlChar *fullname, const xmlChar *fullattr,
1169
0
                            const xmlChar *unused ATTRIBUTE_UNUSED) {
1170
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) data;
1171
1172
0
    if (((ptrdiff_t) payload) == XML_ATTRIBUTE_CDATA) {
1173
0
        xmlHashRemoveEntry2(ctxt->attsSpecial, fullname, fullattr, NULL);
1174
0
    }
1175
0
}
1176
1177
/**
1178
 * xmlCleanSpecialAttr:
1179
 * @ctxt:  an XML parser context
1180
 *
1181
 * Trim the list of attributes defined to remove all those of type
1182
 * CDATA as they are not special. This call should be done when finishing
1183
 * to parse the DTD and before starting to parse the document root.
1184
 */
1185
static void
1186
xmlCleanSpecialAttr(xmlParserCtxtPtr ctxt)
1187
0
{
1188
0
    if (ctxt->attsSpecial == NULL)
1189
0
        return;
1190
1191
0
    xmlHashScanFull(ctxt->attsSpecial, xmlCleanSpecialAttrCallback, ctxt);
1192
1193
0
    if (xmlHashSize(ctxt->attsSpecial) == 0) {
1194
0
        xmlHashFree(ctxt->attsSpecial, NULL);
1195
0
        ctxt->attsSpecial = NULL;
1196
0
    }
1197
0
    return;
1198
0
}
1199
1200
/**
1201
 * xmlCheckLanguageID:
1202
 * @lang:  pointer to the string value
1203
 *
1204
 * DEPRECATED: Internal function, do not use.
1205
 *
1206
 * Checks that the value conforms to the LanguageID production:
1207
 *
1208
 * NOTE: this is somewhat deprecated, those productions were removed from
1209
 *       the XML Second edition.
1210
 *
1211
 * [33] LanguageID ::= Langcode ('-' Subcode)*
1212
 * [34] Langcode ::= ISO639Code |  IanaCode |  UserCode
1213
 * [35] ISO639Code ::= ([a-z] | [A-Z]) ([a-z] | [A-Z])
1214
 * [36] IanaCode ::= ('i' | 'I') '-' ([a-z] | [A-Z])+
1215
 * [37] UserCode ::= ('x' | 'X') '-' ([a-z] | [A-Z])+
1216
 * [38] Subcode ::= ([a-z] | [A-Z])+
1217
 *
1218
 * The current REC reference the successors of RFC 1766, currently 5646
1219
 *
1220
 * http://www.rfc-editor.org/rfc/rfc5646.txt
1221
 * langtag       = language
1222
 *                 ["-" script]
1223
 *                 ["-" region]
1224
 *                 *("-" variant)
1225
 *                 *("-" extension)
1226
 *                 ["-" privateuse]
1227
 * language      = 2*3ALPHA            ; shortest ISO 639 code
1228
 *                 ["-" extlang]       ; sometimes followed by
1229
 *                                     ; extended language subtags
1230
 *               / 4ALPHA              ; or reserved for future use
1231
 *               / 5*8ALPHA            ; or registered language subtag
1232
 *
1233
 * extlang       = 3ALPHA              ; selected ISO 639 codes
1234
 *                 *2("-" 3ALPHA)      ; permanently reserved
1235
 *
1236
 * script        = 4ALPHA              ; ISO 15924 code
1237
 *
1238
 * region        = 2ALPHA              ; ISO 3166-1 code
1239
 *               / 3DIGIT              ; UN M.49 code
1240
 *
1241
 * variant       = 5*8alphanum         ; registered variants
1242
 *               / (DIGIT 3alphanum)
1243
 *
1244
 * extension     = singleton 1*("-" (2*8alphanum))
1245
 *
1246
 *                                     ; Single alphanumerics
1247
 *                                     ; "x" reserved for private use
1248
 * singleton     = DIGIT               ; 0 - 9
1249
 *               / %x41-57             ; A - W
1250
 *               / %x59-5A             ; Y - Z
1251
 *               / %x61-77             ; a - w
1252
 *               / %x79-7A             ; y - z
1253
 *
1254
 * it sounds right to still allow Irregular i-xxx IANA and user codes too
1255
 * The parser below doesn't try to cope with extension or privateuse
1256
 * that could be added but that's not interoperable anyway
1257
 *
1258
 * Returns 1 if correct 0 otherwise
1259
 **/
1260
int
1261
xmlCheckLanguageID(const xmlChar * lang)
1262
0
{
1263
0
    const xmlChar *cur = lang, *nxt;
1264
1265
0
    if (cur == NULL)
1266
0
        return (0);
1267
0
    if (((cur[0] == 'i') && (cur[1] == '-')) ||
1268
0
        ((cur[0] == 'I') && (cur[1] == '-')) ||
1269
0
        ((cur[0] == 'x') && (cur[1] == '-')) ||
1270
0
        ((cur[0] == 'X') && (cur[1] == '-'))) {
1271
        /*
1272
         * Still allow IANA code and user code which were coming
1273
         * from the previous version of the XML-1.0 specification
1274
         * it's deprecated but we should not fail
1275
         */
1276
0
        cur += 2;
1277
0
        while (((cur[0] >= 'A') && (cur[0] <= 'Z')) ||
1278
0
               ((cur[0] >= 'a') && (cur[0] <= 'z')))
1279
0
            cur++;
1280
0
        return(cur[0] == 0);
1281
0
    }
1282
0
    nxt = cur;
1283
0
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1284
0
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1285
0
           nxt++;
1286
0
    if (nxt - cur >= 4) {
1287
        /*
1288
         * Reserved
1289
         */
1290
0
        if ((nxt - cur > 8) || (nxt[0] != 0))
1291
0
            return(0);
1292
0
        return(1);
1293
0
    }
1294
0
    if (nxt - cur < 2)
1295
0
        return(0);
1296
    /* we got an ISO 639 code */
1297
0
    if (nxt[0] == 0)
1298
0
        return(1);
1299
0
    if (nxt[0] != '-')
1300
0
        return(0);
1301
1302
0
    nxt++;
1303
0
    cur = nxt;
1304
    /* now we can have extlang or script or region or variant */
1305
0
    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1306
0
        goto region_m49;
1307
1308
0
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1309
0
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1310
0
           nxt++;
1311
0
    if (nxt - cur == 4)
1312
0
        goto script;
1313
0
    if (nxt - cur == 2)
1314
0
        goto region;
1315
0
    if ((nxt - cur >= 5) && (nxt - cur <= 8))
1316
0
        goto variant;
1317
0
    if (nxt - cur != 3)
1318
0
        return(0);
1319
    /* we parsed an extlang */
1320
0
    if (nxt[0] == 0)
1321
0
        return(1);
1322
0
    if (nxt[0] != '-')
1323
0
        return(0);
1324
1325
0
    nxt++;
1326
0
    cur = nxt;
1327
    /* now we can have script or region or variant */
1328
0
    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1329
0
        goto region_m49;
1330
1331
0
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1332
0
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1333
0
           nxt++;
1334
0
    if (nxt - cur == 2)
1335
0
        goto region;
1336
0
    if ((nxt - cur >= 5) && (nxt - cur <= 8))
1337
0
        goto variant;
1338
0
    if (nxt - cur != 4)
1339
0
        return(0);
1340
    /* we parsed a script */
1341
0
script:
1342
0
    if (nxt[0] == 0)
1343
0
        return(1);
1344
0
    if (nxt[0] != '-')
1345
0
        return(0);
1346
1347
0
    nxt++;
1348
0
    cur = nxt;
1349
    /* now we can have region or variant */
1350
0
    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1351
0
        goto region_m49;
1352
1353
0
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1354
0
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1355
0
           nxt++;
1356
1357
0
    if ((nxt - cur >= 5) && (nxt - cur <= 8))
1358
0
        goto variant;
1359
0
    if (nxt - cur != 2)
1360
0
        return(0);
1361
    /* we parsed a region */
1362
0
region:
1363
0
    if (nxt[0] == 0)
1364
0
        return(1);
1365
0
    if (nxt[0] != '-')
1366
0
        return(0);
1367
1368
0
    nxt++;
1369
0
    cur = nxt;
1370
    /* now we can just have a variant */
1371
0
    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1372
0
           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1373
0
           nxt++;
1374
1375
0
    if ((nxt - cur < 5) || (nxt - cur > 8))
1376
0
        return(0);
1377
1378
    /* we parsed a variant */
1379
0
variant:
1380
0
    if (nxt[0] == 0)
1381
0
        return(1);
1382
0
    if (nxt[0] != '-')
1383
0
        return(0);
1384
    /* extensions and private use subtags not checked */
1385
0
    return (1);
1386
1387
0
region_m49:
1388
0
    if (((nxt[1] >= '0') && (nxt[1] <= '9')) &&
1389
0
        ((nxt[2] >= '0') && (nxt[2] <= '9'))) {
1390
0
        nxt += 3;
1391
0
        goto region;
1392
0
    }
1393
0
    return(0);
1394
0
}
1395
1396
/************************************************************************
1397
 *                  *
1398
 *    Parser stacks related functions and macros    *
1399
 *                  *
1400
 ************************************************************************/
1401
1402
static xmlEntityPtr xmlParseStringEntityRef(xmlParserCtxtPtr ctxt,
1403
                                            const xmlChar ** str);
1404
1405
/**
1406
 * xmlParserNsCreate:
1407
 *
1408
 * Create a new namespace database.
1409
 *
1410
 * Returns the new obejct.
1411
 */
1412
xmlParserNsData *
1413
11
xmlParserNsCreate(void) {
1414
11
    xmlParserNsData *nsdb = xmlMalloc(sizeof(*nsdb));
1415
1416
11
    if (nsdb == NULL)
1417
0
        return(NULL);
1418
11
    memset(nsdb, 0, sizeof(*nsdb));
1419
11
    nsdb->defaultNsIndex = INT_MAX;
1420
1421
11
    return(nsdb);
1422
11
}
1423
1424
/**
1425
 * xmlParserNsFree:
1426
 * @nsdb: namespace database
1427
 *
1428
 * Free a namespace database.
1429
 */
1430
void
1431
11
xmlParserNsFree(xmlParserNsData *nsdb) {
1432
11
    if (nsdb == NULL)
1433
0
        return;
1434
1435
11
    xmlFree(nsdb->extra);
1436
11
    xmlFree(nsdb->hash);
1437
11
    xmlFree(nsdb);
1438
11
}
1439
1440
/**
1441
 * xmlParserNsReset:
1442
 * @nsdb: namespace database
1443
 *
1444
 * Reset a namespace database.
1445
 */
1446
static void
1447
0
xmlParserNsReset(xmlParserNsData *nsdb) {
1448
0
    if (nsdb == NULL)
1449
0
        return;
1450
1451
0
    nsdb->hashElems = 0;
1452
0
    nsdb->elementId = 0;
1453
0
    nsdb->defaultNsIndex = INT_MAX;
1454
1455
0
    if (nsdb->hash)
1456
0
        memset(nsdb->hash, 0, nsdb->hashSize * sizeof(nsdb->hash[0]));
1457
0
}
1458
1459
/**
1460
 * xmlParserStartElement:
1461
 * @nsdb: namespace database
1462
 *
1463
 * Signal that a new element has started.
1464
 *
1465
 * Returns 0 on success, -1 if the element counter overflowed.
1466
 */
1467
static int
1468
0
xmlParserNsStartElement(xmlParserNsData *nsdb) {
1469
0
    if (nsdb->elementId == UINT_MAX)
1470
0
        return(-1);
1471
0
    nsdb->elementId++;
1472
1473
0
    return(0);
1474
0
}
1475
1476
/**
1477
 * xmlParserNsLookup:
1478
 * @ctxt: parser context
1479
 * @prefix: namespace prefix
1480
 * @bucketPtr: optional bucket (return value)
1481
 *
1482
 * Lookup namespace with given prefix. If @bucketPtr is non-NULL, it will
1483
 * be set to the matching bucket, or the first empty bucket if no match
1484
 * was found.
1485
 *
1486
 * Returns the namespace index on success, INT_MAX if no namespace was
1487
 * found.
1488
 */
1489
static int
1490
xmlParserNsLookup(xmlParserCtxtPtr ctxt, const xmlHashedString *prefix,
1491
0
                  xmlParserNsBucket **bucketPtr) {
1492
0
    xmlParserNsBucket *bucket;
1493
0
    unsigned index, hashValue;
1494
1495
0
    if (prefix->name == NULL)
1496
0
        return(ctxt->nsdb->defaultNsIndex);
1497
1498
0
    if (ctxt->nsdb->hashSize == 0)
1499
0
        return(INT_MAX);
1500
1501
0
    hashValue = prefix->hashValue;
1502
0
    index = hashValue & (ctxt->nsdb->hashSize - 1);
1503
0
    bucket = &ctxt->nsdb->hash[index];
1504
1505
0
    while (bucket->hashValue) {
1506
0
        if ((bucket->hashValue == hashValue) &&
1507
0
            (bucket->index != INT_MAX)) {
1508
0
            if (ctxt->nsTab[bucket->index * 2] == prefix->name) {
1509
0
                if (bucketPtr != NULL)
1510
0
                    *bucketPtr = bucket;
1511
0
                return(bucket->index);
1512
0
            }
1513
0
        }
1514
1515
0
        index++;
1516
0
        bucket++;
1517
0
        if (index == ctxt->nsdb->hashSize) {
1518
0
            index = 0;
1519
0
            bucket = ctxt->nsdb->hash;
1520
0
        }
1521
0
    }
1522
1523
0
    if (bucketPtr != NULL)
1524
0
        *bucketPtr = bucket;
1525
0
    return(INT_MAX);
1526
0
}
1527
1528
/**
1529
 * xmlParserNsLookupUri:
1530
 * @ctxt: parser context
1531
 * @prefix: namespace prefix
1532
 *
1533
 * Lookup namespace URI with given prefix.
1534
 *
1535
 * Returns the namespace URI on success, NULL if no namespace was found.
1536
 */
1537
static const xmlChar *
1538
0
xmlParserNsLookupUri(xmlParserCtxtPtr ctxt, const xmlHashedString *prefix) {
1539
0
    const xmlChar *ret;
1540
0
    int nsIndex;
1541
1542
0
    if (prefix->name == ctxt->str_xml)
1543
0
        return(ctxt->str_xml_ns);
1544
1545
0
    nsIndex = xmlParserNsLookup(ctxt, prefix, NULL);
1546
0
    if (nsIndex == INT_MAX)
1547
0
        return(NULL);
1548
1549
0
    ret = ctxt->nsTab[nsIndex * 2 + 1];
1550
0
    if (ret[0] == 0)
1551
0
        ret = NULL;
1552
0
    return(ret);
1553
0
}
1554
1555
/**
1556
 * xmlParserNsLookupSax:
1557
 * @ctxt: parser context
1558
 * @prefix: namespace prefix
1559
 *
1560
 * Lookup extra data for the given prefix. This returns data stored
1561
 * with xmlParserNsUdpateSax.
1562
 *
1563
 * Returns the data on success, NULL if no namespace was found.
1564
 */
1565
void *
1566
0
xmlParserNsLookupSax(xmlParserCtxtPtr ctxt, const xmlChar *prefix) {
1567
0
    xmlHashedString hprefix;
1568
0
    int nsIndex;
1569
1570
0
    if (prefix == ctxt->str_xml)
1571
0
        return(NULL);
1572
1573
0
    hprefix.name = prefix;
1574
0
    if (prefix != NULL)
1575
0
        hprefix.hashValue = xmlDictComputeHash(ctxt->dict, prefix);
1576
0
    else
1577
0
        hprefix.hashValue = 0;
1578
0
    nsIndex = xmlParserNsLookup(ctxt, &hprefix, NULL);
1579
0
    if (nsIndex == INT_MAX)
1580
0
        return(NULL);
1581
1582
0
    return(ctxt->nsdb->extra[nsIndex].saxData);
1583
0
}
1584
1585
/**
1586
 * xmlParserNsUpdateSax:
1587
 * @ctxt: parser context
1588
 * @prefix: namespace prefix
1589
 * @saxData: extra data for SAX handler
1590
 *
1591
 * Sets or updates extra data for the given prefix. This value will be
1592
 * returned by xmlParserNsLookupSax as long as the namespace with the
1593
 * given prefix is in scope.
1594
 *
1595
 * Returns the data on success, NULL if no namespace was found.
1596
 */
1597
int
1598
xmlParserNsUpdateSax(xmlParserCtxtPtr ctxt, const xmlChar *prefix,
1599
0
                     void *saxData) {
1600
0
    xmlHashedString hprefix;
1601
0
    int nsIndex;
1602
1603
0
    if (prefix == ctxt->str_xml)
1604
0
        return(-1);
1605
1606
0
    hprefix.name = prefix;
1607
0
    if (prefix != NULL)
1608
0
        hprefix.hashValue = xmlDictComputeHash(ctxt->dict, prefix);
1609
0
    else
1610
0
        hprefix.hashValue = 0;
1611
0
    nsIndex = xmlParserNsLookup(ctxt, &hprefix, NULL);
1612
0
    if (nsIndex == INT_MAX)
1613
0
        return(-1);
1614
1615
0
    ctxt->nsdb->extra[nsIndex].saxData = saxData;
1616
0
    return(0);
1617
0
}
1618
1619
/**
1620
 * xmlParserNsGrow:
1621
 * @ctxt: parser context
1622
 *
1623
 * Grows the namespace tables.
1624
 *
1625
 * Returns 0 on success, -1 if a memory allocation failed.
1626
 */
1627
static int
1628
0
xmlParserNsGrow(xmlParserCtxtPtr ctxt) {
1629
0
    const xmlChar **table;
1630
0
    xmlParserNsExtra *extra;
1631
0
    int newSize;
1632
1633
0
    if (ctxt->nsMax > INT_MAX / 2)
1634
0
        goto error;
1635
0
    newSize = ctxt->nsMax ? ctxt->nsMax * 2 : 16;
1636
1637
0
    table = xmlRealloc(ctxt->nsTab, 2 * newSize * sizeof(table[0]));
1638
0
    if (table == NULL)
1639
0
        goto error;
1640
0
    ctxt->nsTab = table;
1641
1642
0
    extra = xmlRealloc(ctxt->nsdb->extra, newSize * sizeof(extra[0]));
1643
0
    if (extra == NULL)
1644
0
        goto error;
1645
0
    ctxt->nsdb->extra = extra;
1646
1647
0
    ctxt->nsMax = newSize;
1648
0
    return(0);
1649
1650
0
error:
1651
0
    xmlErrMemory(ctxt, NULL);
1652
0
    return(-1);
1653
0
}
1654
1655
/**
1656
 * xmlParserNsPush:
1657
 * @ctxt: parser context
1658
 * @prefix: prefix with hash value
1659
 * @uri: uri with hash value
1660
 * @saxData: extra data for SAX handler
1661
 * @defAttr: whether the namespace comes from a default attribute
1662
 *
1663
 * Push a new namespace on the table.
1664
 *
1665
 * Returns 1 if the namespace was pushed, 0 if the namespace was ignored,
1666
 * -1 if a memory allocation failed.
1667
 */
1668
static int
1669
xmlParserNsPush(xmlParserCtxtPtr ctxt, const xmlHashedString *prefix,
1670
0
                const xmlHashedString *uri, void *saxData, int defAttr) {
1671
0
    xmlParserNsBucket *bucket = NULL;
1672
0
    xmlParserNsExtra *extra;
1673
0
    const xmlChar **ns;
1674
0
    unsigned hashValue, nsIndex, oldIndex;
1675
1676
0
    if ((prefix != NULL) && (prefix->name == ctxt->str_xml))
1677
0
        return(0);
1678
1679
0
    if ((ctxt->nsNr >= ctxt->nsMax) && (xmlParserNsGrow(ctxt) < 0)) {
1680
0
        xmlErrMemory(ctxt, NULL);
1681
0
        return(-1);
1682
0
    }
1683
1684
    /*
1685
     * Default namespace and 'xml' namespace
1686
     */
1687
0
    if ((prefix == NULL) || (prefix->name == NULL)) {
1688
0
        oldIndex = ctxt->nsdb->defaultNsIndex;
1689
1690
0
        if (oldIndex != INT_MAX) {
1691
0
            extra = &ctxt->nsdb->extra[oldIndex];
1692
1693
0
            if (extra->elementId == ctxt->nsdb->elementId) {
1694
0
                if (defAttr == 0)
1695
0
                    xmlErrAttributeDup(ctxt, NULL, BAD_CAST "xmlns");
1696
0
                return(0);
1697
0
            }
1698
1699
0
            if ((ctxt->options & XML_PARSE_NSCLEAN) &&
1700
0
                (uri->name == ctxt->nsTab[oldIndex * 2 + 1]))
1701
0
                return(0);
1702
0
        }
1703
1704
0
        ctxt->nsdb->defaultNsIndex = ctxt->nsNr;
1705
0
        goto populate_entry;
1706
0
    }
1707
1708
    /*
1709
     * Hash table lookup
1710
     */
1711
0
    oldIndex = xmlParserNsLookup(ctxt, prefix, &bucket);
1712
0
    if (oldIndex != INT_MAX) {
1713
0
        extra = &ctxt->nsdb->extra[oldIndex];
1714
1715
        /*
1716
         * Check for duplicate definitions on the same element.
1717
         */
1718
0
        if (extra->elementId == ctxt->nsdb->elementId) {
1719
0
            if (defAttr == 0)
1720
0
                xmlErrAttributeDup(ctxt, BAD_CAST "xmlns", prefix->name);
1721
0
            return(0);
1722
0
        }
1723
1724
0
        if ((ctxt->options & XML_PARSE_NSCLEAN) &&
1725
0
            (uri->name == ctxt->nsTab[bucket->index * 2 + 1]))
1726
0
            return(0);
1727
1728
0
        bucket->index = ctxt->nsNr;
1729
0
        goto populate_entry;
1730
0
    }
1731
1732
    /*
1733
     * Insert new bucket
1734
     */
1735
1736
0
    hashValue = prefix->hashValue;
1737
1738
    /*
1739
     * Grow hash table, 50% fill factor
1740
     */
1741
0
    if (ctxt->nsdb->hashElems + 1 > ctxt->nsdb->hashSize / 2) {
1742
0
        xmlParserNsBucket *newHash;
1743
0
        unsigned newSize, i, index;
1744
1745
0
        if (ctxt->nsdb->hashSize > UINT_MAX / 2) {
1746
0
            xmlErrMemory(ctxt, NULL);
1747
0
            return(-1);
1748
0
        }
1749
0
        newSize = ctxt->nsdb->hashSize ? ctxt->nsdb->hashSize * 2 : 16;
1750
0
        newHash = xmlMalloc(newSize * sizeof(newHash[0]));
1751
0
        if (newHash == NULL) {
1752
0
            xmlErrMemory(ctxt, NULL);
1753
0
            return(-1);
1754
0
        }
1755
0
        memset(newHash, 0, newSize * sizeof(newHash[0]));
1756
1757
0
        for (i = 0; i < ctxt->nsdb->hashSize; i++) {
1758
0
            unsigned hv = ctxt->nsdb->hash[i].hashValue;
1759
0
            unsigned newIndex;
1760
1761
0
            if (hv == 0)
1762
0
                continue;
1763
0
            newIndex = hv & (newSize - 1);
1764
1765
0
            while (newHash[newIndex].hashValue != 0) {
1766
0
                newIndex++;
1767
0
                if (newIndex == newSize)
1768
0
                    newIndex = 0;
1769
0
            }
1770
1771
0
            newHash[newIndex] = ctxt->nsdb->hash[i];
1772
0
        }
1773
1774
0
        xmlFree(ctxt->nsdb->hash);
1775
0
        ctxt->nsdb->hash = newHash;
1776
0
        ctxt->nsdb->hashSize = newSize;
1777
1778
        /*
1779
         * Relookup
1780
         */
1781
0
        index = hashValue & (newSize - 1);
1782
1783
0
        while (newHash[index].hashValue != 0) {
1784
0
            index++;
1785
0
            if (index == newSize)
1786
0
                index = 0;
1787
0
        }
1788
1789
0
        bucket = &newHash[index];
1790
0
    }
1791
1792
0
    bucket->hashValue = hashValue;
1793
0
    bucket->index = ctxt->nsNr;
1794
0
    ctxt->nsdb->hashElems++;
1795
0
    oldIndex = INT_MAX;
1796
1797
0
populate_entry:
1798
0
    nsIndex = ctxt->nsNr;
1799
1800
0
    ns = &ctxt->nsTab[nsIndex * 2];
1801
0
    ns[0] = prefix ? prefix->name : NULL;
1802
0
    ns[1] = uri->name;
1803
1804
0
    extra = &ctxt->nsdb->extra[nsIndex];
1805
0
    extra->saxData = saxData;
1806
0
    extra->prefixHashValue = prefix ? prefix->hashValue : 0;
1807
0
    extra->uriHashValue = uri->hashValue;
1808
0
    extra->elementId = ctxt->nsdb->elementId;
1809
0
    extra->oldIndex = oldIndex;
1810
1811
0
    ctxt->nsNr++;
1812
1813
0
    return(1);
1814
0
}
1815
1816
/**
1817
 * xmlParserNsPop:
1818
 * @ctxt: an XML parser context
1819
 * @nr:  the number to pop
1820
 *
1821
 * Pops the top @nr namespaces and restores the hash table.
1822
 *
1823
 * Returns the number of namespaces popped.
1824
 */
1825
static int
1826
xmlParserNsPop(xmlParserCtxtPtr ctxt, int nr)
1827
0
{
1828
0
    int i;
1829
1830
    /* assert(nr <= ctxt->nsNr); */
1831
1832
0
    for (i = ctxt->nsNr - 1; i >= ctxt->nsNr - nr; i--) {
1833
0
        const xmlChar *prefix = ctxt->nsTab[i * 2];
1834
0
        xmlParserNsExtra *extra = &ctxt->nsdb->extra[i];
1835
1836
0
        if (prefix == NULL) {
1837
0
            ctxt->nsdb->defaultNsIndex = extra->oldIndex;
1838
0
        } else {
1839
0
            xmlHashedString hprefix;
1840
0
            xmlParserNsBucket *bucket = NULL;
1841
1842
0
            hprefix.name = prefix;
1843
0
            hprefix.hashValue = extra->prefixHashValue;
1844
0
            xmlParserNsLookup(ctxt, &hprefix, &bucket);
1845
            /* assert(bucket && bucket->hashValue); */
1846
0
            bucket->index = extra->oldIndex;
1847
0
        }
1848
0
    }
1849
1850
0
    ctxt->nsNr -= nr;
1851
0
    return(nr);
1852
0
}
1853
1854
static int
1855
0
xmlCtxtGrowAttrs(xmlParserCtxtPtr ctxt, int nr) {
1856
0
    const xmlChar **atts;
1857
0
    unsigned *attallocs;
1858
0
    int maxatts;
1859
1860
0
    if (nr + 5 > ctxt->maxatts) {
1861
0
  maxatts = ctxt->maxatts == 0 ? 55 : (nr + 5) * 2;
1862
0
  atts = (const xmlChar **) xmlMalloc(
1863
0
             maxatts * sizeof(const xmlChar *));
1864
0
  if (atts == NULL) goto mem_error;
1865
0
  attallocs = xmlRealloc(ctxt->attallocs,
1866
0
                               (maxatts / 5) * sizeof(attallocs[0]));
1867
0
  if (attallocs == NULL) {
1868
0
            xmlFree(atts);
1869
0
            goto mem_error;
1870
0
        }
1871
0
        if (ctxt->maxatts > 0)
1872
0
            memcpy(atts, ctxt->atts, ctxt->maxatts * sizeof(const xmlChar *));
1873
0
        xmlFree(ctxt->atts);
1874
0
  ctxt->atts = atts;
1875
0
  ctxt->attallocs = attallocs;
1876
0
  ctxt->maxatts = maxatts;
1877
0
    }
1878
0
    return(ctxt->maxatts);
1879
0
mem_error:
1880
0
    xmlErrMemory(ctxt, NULL);
1881
0
    return(-1);
1882
0
}
1883
1884
/**
1885
 * inputPush:
1886
 * @ctxt:  an XML parser context
1887
 * @value:  the parser input
1888
 *
1889
 * Pushes a new parser input on top of the input stack
1890
 *
1891
 * Returns -1 in case of error, the index in the stack otherwise
1892
 */
1893
int
1894
inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value)
1895
11
{
1896
11
    if ((ctxt == NULL) || (value == NULL))
1897
0
        return(-1);
1898
11
    if (ctxt->inputNr >= ctxt->inputMax) {
1899
0
        size_t newSize = ctxt->inputMax * 2;
1900
0
        xmlParserInputPtr *tmp;
1901
1902
0
        tmp = (xmlParserInputPtr *) xmlRealloc(ctxt->inputTab,
1903
0
                                               newSize * sizeof(*tmp));
1904
0
        if (tmp == NULL) {
1905
0
            xmlErrMemory(ctxt, NULL);
1906
0
            return (-1);
1907
0
        }
1908
0
        ctxt->inputTab = tmp;
1909
0
        ctxt->inputMax = newSize;
1910
0
    }
1911
11
    ctxt->inputTab[ctxt->inputNr] = value;
1912
11
    ctxt->input = value;
1913
11
    return (ctxt->inputNr++);
1914
11
}
1915
/**
1916
 * inputPop:
1917
 * @ctxt: an XML parser context
1918
 *
1919
 * Pops the top parser input from the input stack
1920
 *
1921
 * Returns the input just removed
1922
 */
1923
xmlParserInputPtr
1924
inputPop(xmlParserCtxtPtr ctxt)
1925
33
{
1926
33
    xmlParserInputPtr ret;
1927
1928
33
    if (ctxt == NULL)
1929
0
        return(NULL);
1930
33
    if (ctxt->inputNr <= 0)
1931
22
        return (NULL);
1932
11
    ctxt->inputNr--;
1933
11
    if (ctxt->inputNr > 0)
1934
0
        ctxt->input = ctxt->inputTab[ctxt->inputNr - 1];
1935
11
    else
1936
11
        ctxt->input = NULL;
1937
11
    ret = ctxt->inputTab[ctxt->inputNr];
1938
11
    ctxt->inputTab[ctxt->inputNr] = NULL;
1939
11
    return (ret);
1940
33
}
1941
/**
1942
 * nodePush:
1943
 * @ctxt:  an XML parser context
1944
 * @value:  the element node
1945
 *
1946
 * DEPRECATED: Internal function, do not use.
1947
 *
1948
 * Pushes a new element node on top of the node stack
1949
 *
1950
 * Returns -1 in case of error, the index in the stack otherwise
1951
 */
1952
int
1953
nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value)
1954
0
{
1955
0
    if (ctxt == NULL) return(0);
1956
0
    if (ctxt->nodeNr >= ctxt->nodeMax) {
1957
0
        xmlNodePtr *tmp;
1958
1959
0
  tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
1960
0
                                      ctxt->nodeMax * 2 *
1961
0
                                      sizeof(ctxt->nodeTab[0]));
1962
0
        if (tmp == NULL) {
1963
0
            xmlErrMemory(ctxt, NULL);
1964
0
            return (-1);
1965
0
        }
1966
0
        ctxt->nodeTab = tmp;
1967
0
  ctxt->nodeMax *= 2;
1968
0
    }
1969
0
    if ((((unsigned int) ctxt->nodeNr) > xmlParserMaxDepth) &&
1970
0
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
1971
0
  xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
1972
0
     "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
1973
0
        xmlParserMaxDepth);
1974
0
  xmlHaltParser(ctxt);
1975
0
  return(-1);
1976
0
    }
1977
0
    ctxt->nodeTab[ctxt->nodeNr] = value;
1978
0
    ctxt->node = value;
1979
0
    return (ctxt->nodeNr++);
1980
0
}
1981
1982
/**
1983
 * nodePop:
1984
 * @ctxt: an XML parser context
1985
 *
1986
 * DEPRECATED: Internal function, do not use.
1987
 *
1988
 * Pops the top element node from the node stack
1989
 *
1990
 * Returns the node just removed
1991
 */
1992
xmlNodePtr
1993
nodePop(xmlParserCtxtPtr ctxt)
1994
0
{
1995
0
    xmlNodePtr ret;
1996
1997
0
    if (ctxt == NULL) return(NULL);
1998
0
    if (ctxt->nodeNr <= 0)
1999
0
        return (NULL);
2000
0
    ctxt->nodeNr--;
2001
0
    if (ctxt->nodeNr > 0)
2002
0
        ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1];
2003
0
    else
2004
0
        ctxt->node = NULL;
2005
0
    ret = ctxt->nodeTab[ctxt->nodeNr];
2006
0
    ctxt->nodeTab[ctxt->nodeNr] = NULL;
2007
0
    return (ret);
2008
0
}
2009
2010
/**
2011
 * nameNsPush:
2012
 * @ctxt:  an XML parser context
2013
 * @value:  the element name
2014
 * @prefix:  the element prefix
2015
 * @URI:  the element namespace name
2016
 * @line:  the current line number for error messages
2017
 * @nsNr:  the number of namespaces pushed on the namespace table
2018
 *
2019
 * Pushes a new element name/prefix/URL on top of the name stack
2020
 *
2021
 * Returns -1 in case of error, the index in the stack otherwise
2022
 */
2023
static int
2024
nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
2025
           const xmlChar *prefix, const xmlChar *URI, int line, int nsNr)
2026
99
{
2027
99
    xmlStartTag *tag;
2028
2029
99
    if (ctxt->nameNr >= ctxt->nameMax) {
2030
0
        const xmlChar * *tmp;
2031
0
        xmlStartTag *tmp2;
2032
0
        ctxt->nameMax *= 2;
2033
0
        tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
2034
0
                                    ctxt->nameMax *
2035
0
                                    sizeof(ctxt->nameTab[0]));
2036
0
        if (tmp == NULL) {
2037
0
      ctxt->nameMax /= 2;
2038
0
      goto mem_error;
2039
0
        }
2040
0
  ctxt->nameTab = tmp;
2041
0
        tmp2 = (xmlStartTag *) xmlRealloc((void * *)ctxt->pushTab,
2042
0
                                    ctxt->nameMax *
2043
0
                                    sizeof(ctxt->pushTab[0]));
2044
0
        if (tmp2 == NULL) {
2045
0
      ctxt->nameMax /= 2;
2046
0
      goto mem_error;
2047
0
        }
2048
0
  ctxt->pushTab = tmp2;
2049
99
    } else if (ctxt->pushTab == NULL) {
2050
11
        ctxt->pushTab = (xmlStartTag *) xmlMalloc(ctxt->nameMax *
2051
11
                                            sizeof(ctxt->pushTab[0]));
2052
11
        if (ctxt->pushTab == NULL)
2053
0
            goto mem_error;
2054
11
    }
2055
99
    ctxt->nameTab[ctxt->nameNr] = value;
2056
99
    ctxt->name = value;
2057
99
    tag = &ctxt->pushTab[ctxt->nameNr];
2058
99
    tag->prefix = prefix;
2059
99
    tag->URI = URI;
2060
99
    tag->line = line;
2061
99
    tag->nsNr = nsNr;
2062
99
    return (ctxt->nameNr++);
2063
0
mem_error:
2064
0
    xmlErrMemory(ctxt, NULL);
2065
0
    return (-1);
2066
99
}
2067
#ifdef LIBXML_PUSH_ENABLED
2068
/**
2069
 * nameNsPop:
2070
 * @ctxt: an XML parser context
2071
 *
2072
 * Pops the top element/prefix/URI name from the name stack
2073
 *
2074
 * Returns the name just removed
2075
 */
2076
static const xmlChar *
2077
nameNsPop(xmlParserCtxtPtr ctxt)
2078
0
{
2079
0
    const xmlChar *ret;
2080
2081
0
    if (ctxt->nameNr <= 0)
2082
0
        return (NULL);
2083
0
    ctxt->nameNr--;
2084
0
    if (ctxt->nameNr > 0)
2085
0
        ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
2086
0
    else
2087
0
        ctxt->name = NULL;
2088
0
    ret = ctxt->nameTab[ctxt->nameNr];
2089
0
    ctxt->nameTab[ctxt->nameNr] = NULL;
2090
0
    return (ret);
2091
0
}
2092
#endif /* LIBXML_PUSH_ENABLED */
2093
2094
/**
2095
 * namePush:
2096
 * @ctxt:  an XML parser context
2097
 * @value:  the element name
2098
 *
2099
 * DEPRECATED: Internal function, do not use.
2100
 *
2101
 * Pushes a new element name on top of the name stack
2102
 *
2103
 * Returns -1 in case of error, the index in the stack otherwise
2104
 */
2105
int
2106
namePush(xmlParserCtxtPtr ctxt, const xmlChar * value)
2107
0
{
2108
0
    if (ctxt == NULL) return (-1);
2109
2110
0
    if (ctxt->nameNr >= ctxt->nameMax) {
2111
0
        const xmlChar * *tmp;
2112
0
        tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
2113
0
                                    ctxt->nameMax * 2 *
2114
0
                                    sizeof(ctxt->nameTab[0]));
2115
0
        if (tmp == NULL) {
2116
0
      goto mem_error;
2117
0
        }
2118
0
  ctxt->nameTab = tmp;
2119
0
        ctxt->nameMax *= 2;
2120
0
    }
2121
0
    ctxt->nameTab[ctxt->nameNr] = value;
2122
0
    ctxt->name = value;
2123
0
    return (ctxt->nameNr++);
2124
0
mem_error:
2125
0
    xmlErrMemory(ctxt, NULL);
2126
0
    return (-1);
2127
0
}
2128
2129
/**
2130
 * namePop:
2131
 * @ctxt: an XML parser context
2132
 *
2133
 * DEPRECATED: Internal function, do not use.
2134
 *
2135
 * Pops the top element name from the name stack
2136
 *
2137
 * Returns the name just removed
2138
 */
2139
const xmlChar *
2140
namePop(xmlParserCtxtPtr ctxt)
2141
99
{
2142
99
    const xmlChar *ret;
2143
2144
99
    if ((ctxt == NULL) || (ctxt->nameNr <= 0))
2145
0
        return (NULL);
2146
99
    ctxt->nameNr--;
2147
99
    if (ctxt->nameNr > 0)
2148
88
        ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
2149
11
    else
2150
11
        ctxt->name = NULL;
2151
99
    ret = ctxt->nameTab[ctxt->nameNr];
2152
99
    ctxt->nameTab[ctxt->nameNr] = NULL;
2153
99
    return (ret);
2154
99
}
2155
2156
99
static int spacePush(xmlParserCtxtPtr ctxt, int val) {
2157
99
    if (ctxt->spaceNr >= ctxt->spaceMax) {
2158
0
        int *tmp;
2159
2160
0
  ctxt->spaceMax *= 2;
2161
0
        tmp = (int *) xmlRealloc(ctxt->spaceTab,
2162
0
                           ctxt->spaceMax * sizeof(ctxt->spaceTab[0]));
2163
0
        if (tmp == NULL) {
2164
0
      xmlErrMemory(ctxt, NULL);
2165
0
      ctxt->spaceMax /=2;
2166
0
      return(-1);
2167
0
  }
2168
0
  ctxt->spaceTab = tmp;
2169
0
    }
2170
99
    ctxt->spaceTab[ctxt->spaceNr] = val;
2171
99
    ctxt->space = &ctxt->spaceTab[ctxt->spaceNr];
2172
99
    return(ctxt->spaceNr++);
2173
99
}
2174
2175
99
static int spacePop(xmlParserCtxtPtr ctxt) {
2176
99
    int ret;
2177
99
    if (ctxt->spaceNr <= 0) return(0);
2178
99
    ctxt->spaceNr--;
2179
99
    if (ctxt->spaceNr > 0)
2180
99
  ctxt->space = &ctxt->spaceTab[ctxt->spaceNr - 1];
2181
0
    else
2182
0
        ctxt->space = &ctxt->spaceTab[0];
2183
99
    ret = ctxt->spaceTab[ctxt->spaceNr];
2184
99
    ctxt->spaceTab[ctxt->spaceNr] = -1;
2185
99
    return(ret);
2186
99
}
2187
2188
/*
2189
 * Macros for accessing the content. Those should be used only by the parser,
2190
 * and not exported.
2191
 *
2192
 * Dirty macros, i.e. one often need to make assumption on the context to
2193
 * use them
2194
 *
2195
 *   CUR_PTR return the current pointer to the xmlChar to be parsed.
2196
 *           To be used with extreme caution since operations consuming
2197
 *           characters may move the input buffer to a different location !
2198
 *   CUR     returns the current xmlChar value, i.e. a 8 bit value if compiled
2199
 *           This should be used internally by the parser
2200
 *           only to compare to ASCII values otherwise it would break when
2201
 *           running with UTF-8 encoding.
2202
 *   RAW     same as CUR but in the input buffer, bypass any token
2203
 *           extraction that may have been done
2204
 *   NXT(n)  returns the n'th next xmlChar. Same as CUR is should be used only
2205
 *           to compare on ASCII based substring.
2206
 *   SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
2207
 *           strings without newlines within the parser.
2208
 *   NEXT1(l) Skip 1 xmlChar, and must also be used only to skip 1 non-newline ASCII
2209
 *           defined char within the parser.
2210
 * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
2211
 *
2212
 *   NEXT    Skip to the next character, this does the proper decoding
2213
 *           in UTF-8 mode. It also pop-up unfinished entities on the fly.
2214
 *   NEXTL(l) Skip the current unicode character of l xmlChars long.
2215
 *   CUR_CHAR(l) returns the current unicode character (int), set l
2216
 *           to the number of xmlChars used for the encoding [0-5].
2217
 *   CUR_SCHAR  same but operate on a string instead of the context
2218
 *   COPY_BUF  copy the current unicode char to the target buffer, increment
2219
 *            the index
2220
 *   GROW, SHRINK  handling of input buffers
2221
 */
2222
2223
869
#define RAW (*ctxt->input->cur)
2224
0
#define CUR (*ctxt->input->cur)
2225
99
#define NXT(val) ctxt->input->cur[(val)]
2226
154
#define CUR_PTR ctxt->input->cur
2227
0
#define BASE_PTR ctxt->input->base
2228
2229
#define CMP4( s, c1, c2, c3, c4 ) \
2230
11
  ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char *) s)[ 1 ] == c2 && \
2231
11
    ((unsigned char *) s)[ 2 ] == c3 && ((unsigned char *) s)[ 3 ] == c4 )
2232
#define CMP5( s, c1, c2, c3, c4, c5 ) \
2233
0
  ( CMP4( s, c1, c2, c3, c4 ) && ((unsigned char *) s)[ 4 ] == c5 )
2234
#define CMP6( s, c1, c2, c3, c4, c5, c6 ) \
2235
0
  ( CMP5( s, c1, c2, c3, c4, c5 ) && ((unsigned char *) s)[ 5 ] == c6 )
2236
#define CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) \
2237
0
  ( CMP6( s, c1, c2, c3, c4, c5, c6 ) && ((unsigned char *) s)[ 6 ] == c7 )
2238
#define CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) \
2239
0
  ( CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) && ((unsigned char *) s)[ 7 ] == c8 )
2240
#define CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) \
2241
0
  ( CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) && \
2242
0
    ((unsigned char *) s)[ 8 ] == c9 )
2243
#define CMP10( s, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 ) \
2244
0
  ( CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) && \
2245
0
    ((unsigned char *) s)[ 9 ] == c10 )
2246
2247
99
#define SKIP(val) do {             \
2248
99
    ctxt->input->cur += (val),ctxt->input->col+=(val);      \
2249
99
    if (*ctxt->input->cur == 0)           \
2250
99
        xmlParserGrow(ctxt);           \
2251
99
  } while (0)
2252
2253
0
#define SKIPL(val) do {             \
2254
0
    int skipl;                \
2255
0
    for(skipl=0; skipl<val; skipl++) {         \
2256
0
  if (*(ctxt->input->cur) == '\n') {       \
2257
0
  ctxt->input->line++; ctxt->input->col = 1;      \
2258
0
  } else ctxt->input->col++;         \
2259
0
  ctxt->input->cur++;           \
2260
0
    }                 \
2261
0
    if (*ctxt->input->cur == 0)           \
2262
0
        xmlParserGrow(ctxt);           \
2263
0
  } while (0)
2264
2265
/* Don't shrink push parser buffer. */
2266
#define SHRINK \
2267
22
    if (((ctxt->progressive == 0) || (ctxt->inputNr > 1)) && \
2268
22
        (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \
2269
22
  (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \
2270
22
  xmlParserShrink(ctxt);
2271
2272
1.00k
#define GROW if (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK) \
2273
1.00k
  xmlParserGrow(ctxt);
2274
2275
385
#define SKIP_BLANKS xmlSkipBlankChars(ctxt)
2276
2277
176
#define NEXT xmlNextChar(ctxt)
2278
2279
198
#define NEXT1 {               \
2280
198
  ctxt->input->col++;           \
2281
198
  ctxt->input->cur++;           \
2282
198
  if (*ctxt->input->cur == 0)         \
2283
198
      xmlParserGrow(ctxt);           \
2284
198
    }
2285
2286
0
#define NEXTL(l) do {             \
2287
0
    if (*(ctxt->input->cur) == '\n') {         \
2288
0
  ctxt->input->line++; ctxt->input->col = 1;      \
2289
0
    } else ctxt->input->col++;           \
2290
0
    ctxt->input->cur += l;        \
2291
0
  } while (0)
2292
2293
0
#define CUR_CHAR(l) xmlCurrentChar(ctxt, &l)
2294
0
#define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l)
2295
2296
#define COPY_BUF(b, i, v)           \
2297
0
    if (v < 0x80) b[i++] = v;           \
2298
0
    else i += xmlCopyCharMultiByte(&b[i],v)
2299
2300
/**
2301
 * xmlSkipBlankChars:
2302
 * @ctxt:  the XML parser context
2303
 *
2304
 * DEPRECATED: Internal function, do not use.
2305
 *
2306
 * skip all blanks character found at that point in the input streams.
2307
 * It pops up finished entities in the process if allowable at that point.
2308
 *
2309
 * Returns the number of space chars skipped
2310
 */
2311
2312
int
2313
385
xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
2314
385
    int res = 0;
2315
2316
    /*
2317
     * It's Okay to use CUR/NEXT here since all the blanks are on
2318
     * the ASCII range.
2319
     */
2320
385
    if (((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) ||
2321
385
        (ctxt->instate == XML_PARSER_START)) {
2322
385
  const xmlChar *cur;
2323
  /*
2324
   * if we are in the document content, go really fast
2325
   */
2326
385
  cur = ctxt->input->cur;
2327
385
  while (IS_BLANK_CH(*cur)) {
2328
77
      if (*cur == '\n') {
2329
0
    ctxt->input->line++; ctxt->input->col = 1;
2330
77
      } else {
2331
77
    ctxt->input->col++;
2332
77
      }
2333
77
      cur++;
2334
77
      if (res < INT_MAX)
2335
77
    res++;
2336
77
      if (*cur == 0) {
2337
0
    ctxt->input->cur = cur;
2338
0
    xmlParserGrow(ctxt);
2339
0
    cur = ctxt->input->cur;
2340
0
      }
2341
77
  }
2342
385
  ctxt->input->cur = cur;
2343
385
    } else {
2344
0
        int expandPE = ((ctxt->external != 0) || (ctxt->inputNr != 1));
2345
2346
0
  while (ctxt->instate != XML_PARSER_EOF) {
2347
0
            if (IS_BLANK_CH(CUR)) { /* CHECKED tstblanks.xml */
2348
0
    NEXT;
2349
0
      } else if (CUR == '%') {
2350
                /*
2351
                 * Need to handle support of entities branching here
2352
                 */
2353
0
          if ((expandPE == 0) || (IS_BLANK_CH(NXT(1))) || (NXT(1) == 0))
2354
0
                    break;
2355
0
          xmlParsePEReference(ctxt);
2356
0
            } else if (CUR == 0) {
2357
0
                unsigned long consumed;
2358
0
                xmlEntityPtr ent;
2359
2360
0
                if (ctxt->inputNr <= 1)
2361
0
                    break;
2362
2363
0
                consumed = ctxt->input->consumed;
2364
0
                xmlSaturatedAddSizeT(&consumed,
2365
0
                                     ctxt->input->cur - ctxt->input->base);
2366
2367
                /*
2368
                 * Add to sizeentities when parsing an external entity
2369
                 * for the first time.
2370
                 */
2371
0
                ent = ctxt->input->entity;
2372
0
                if ((ent->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
2373
0
                    ((ent->flags & XML_ENT_PARSED) == 0)) {
2374
0
                    ent->flags |= XML_ENT_PARSED;
2375
2376
0
                    xmlSaturatedAdd(&ctxt->sizeentities, consumed);
2377
0
                }
2378
2379
0
                xmlParserEntityCheck(ctxt, consumed);
2380
2381
0
                xmlPopInput(ctxt);
2382
0
            } else {
2383
0
                break;
2384
0
            }
2385
2386
            /*
2387
             * Also increase the counter when entering or exiting a PERef.
2388
             * The spec says: "When a parameter-entity reference is recognized
2389
             * in the DTD and included, its replacement text MUST be enlarged
2390
             * by the attachment of one leading and one following space (#x20)
2391
             * character."
2392
             */
2393
0
      if (res < INT_MAX)
2394
0
    res++;
2395
0
        }
2396
0
    }
2397
385
    return(res);
2398
385
}
2399
2400
/************************************************************************
2401
 *                  *
2402
 *    Commodity functions to handle entities      *
2403
 *                  *
2404
 ************************************************************************/
2405
2406
/**
2407
 * xmlPopInput:
2408
 * @ctxt:  an XML parser context
2409
 *
2410
 * xmlPopInput: the current input pointed by ctxt->input came to an end
2411
 *          pop it and return the next char.
2412
 *
2413
 * Returns the current xmlChar in the parser context
2414
 */
2415
xmlChar
2416
0
xmlPopInput(xmlParserCtxtPtr ctxt) {
2417
0
    xmlParserInputPtr input;
2418
2419
0
    if ((ctxt == NULL) || (ctxt->inputNr <= 1)) return(0);
2420
0
    if (xmlParserDebugEntities)
2421
0
  xmlGenericError(xmlGenericErrorContext,
2422
0
    "Popping input %d\n", ctxt->inputNr);
2423
0
    if ((ctxt->inputNr > 1) && (ctxt->inSubset == 0) &&
2424
0
        (ctxt->instate != XML_PARSER_EOF))
2425
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
2426
0
                    "Unfinished entity outside the DTD");
2427
0
    input = inputPop(ctxt);
2428
0
    if (input->entity != NULL)
2429
0
        input->entity->flags &= ~XML_ENT_EXPANDING;
2430
0
    xmlFreeInputStream(input);
2431
0
    if (*ctxt->input->cur == 0)
2432
0
        xmlParserGrow(ctxt);
2433
0
    return(CUR);
2434
0
}
2435
2436
/**
2437
 * xmlPushInput:
2438
 * @ctxt:  an XML parser context
2439
 * @input:  an XML parser input fragment (entity, XML fragment ...).
2440
 *
2441
 * xmlPushInput: switch to a new input stream which is stacked on top
2442
 *               of the previous one(s).
2443
 * Returns -1 in case of error or the index in the input stack
2444
 */
2445
int
2446
0
xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
2447
0
    int ret;
2448
0
    if (input == NULL) return(-1);
2449
2450
0
    if (xmlParserDebugEntities) {
2451
0
  if ((ctxt->input != NULL) && (ctxt->input->filename))
2452
0
      xmlGenericError(xmlGenericErrorContext,
2453
0
        "%s(%d): ", ctxt->input->filename,
2454
0
        ctxt->input->line);
2455
0
  xmlGenericError(xmlGenericErrorContext,
2456
0
    "Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur);
2457
0
    }
2458
0
    if (((ctxt->inputNr > 40) && ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
2459
0
        (ctxt->inputNr > 100)) {
2460
0
        xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
2461
0
        while (ctxt->inputNr > 1)
2462
0
            xmlFreeInputStream(inputPop(ctxt));
2463
0
  return(-1);
2464
0
    }
2465
0
    ret = inputPush(ctxt, input);
2466
0
    if (ctxt->instate == XML_PARSER_EOF)
2467
0
        return(-1);
2468
0
    GROW;
2469
0
    return(ret);
2470
0
}
2471
2472
/**
2473
 * xmlParseCharRef:
2474
 * @ctxt:  an XML parser context
2475
 *
2476
 * DEPRECATED: Internal function, don't use.
2477
 *
2478
 * Parse a numeric character reference. Always consumes '&'.
2479
 *
2480
 * [66] CharRef ::= '&#' [0-9]+ ';' |
2481
 *                  '&#x' [0-9a-fA-F]+ ';'
2482
 *
2483
 * [ WFC: Legal Character ]
2484
 * Characters referred to using character references must match the
2485
 * production for Char.
2486
 *
2487
 * Returns the value parsed (as an int), 0 in case of error
2488
 */
2489
int
2490
0
xmlParseCharRef(xmlParserCtxtPtr ctxt) {
2491
0
    int val = 0;
2492
0
    int count = 0;
2493
2494
    /*
2495
     * Using RAW/CUR/NEXT is okay since we are working on ASCII range here
2496
     */
2497
0
    if ((RAW == '&') && (NXT(1) == '#') &&
2498
0
        (NXT(2) == 'x')) {
2499
0
  SKIP(3);
2500
0
  GROW;
2501
0
  while (RAW != ';') { /* loop blocked by count */
2502
0
      if (count++ > 20) {
2503
0
    count = 0;
2504
0
    GROW;
2505
0
                if (ctxt->instate == XML_PARSER_EOF)
2506
0
                    return(0);
2507
0
      }
2508
0
      if ((RAW >= '0') && (RAW <= '9'))
2509
0
          val = val * 16 + (CUR - '0');
2510
0
      else if ((RAW >= 'a') && (RAW <= 'f') && (count < 20))
2511
0
          val = val * 16 + (CUR - 'a') + 10;
2512
0
      else if ((RAW >= 'A') && (RAW <= 'F') && (count < 20))
2513
0
          val = val * 16 + (CUR - 'A') + 10;
2514
0
      else {
2515
0
    xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
2516
0
    val = 0;
2517
0
    break;
2518
0
      }
2519
0
      if (val > 0x110000)
2520
0
          val = 0x110000;
2521
2522
0
      NEXT;
2523
0
      count++;
2524
0
  }
2525
0
  if (RAW == ';') {
2526
      /* on purpose to avoid reentrancy problems with NEXT and SKIP */
2527
0
      ctxt->input->col++;
2528
0
      ctxt->input->cur++;
2529
0
  }
2530
0
    } else if  ((RAW == '&') && (NXT(1) == '#')) {
2531
0
  SKIP(2);
2532
0
  GROW;
2533
0
  while (RAW != ';') { /* loop blocked by count */
2534
0
      if (count++ > 20) {
2535
0
    count = 0;
2536
0
    GROW;
2537
0
                if (ctxt->instate == XML_PARSER_EOF)
2538
0
                    return(0);
2539
0
      }
2540
0
      if ((RAW >= '0') && (RAW <= '9'))
2541
0
          val = val * 10 + (CUR - '0');
2542
0
      else {
2543
0
    xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
2544
0
    val = 0;
2545
0
    break;
2546
0
      }
2547
0
      if (val > 0x110000)
2548
0
          val = 0x110000;
2549
2550
0
      NEXT;
2551
0
      count++;
2552
0
  }
2553
0
  if (RAW == ';') {
2554
      /* on purpose to avoid reentrancy problems with NEXT and SKIP */
2555
0
      ctxt->input->col++;
2556
0
      ctxt->input->cur++;
2557
0
  }
2558
0
    } else {
2559
0
        if (RAW == '&')
2560
0
            SKIP(1);
2561
0
        xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
2562
0
    }
2563
2564
    /*
2565
     * [ WFC: Legal Character ]
2566
     * Characters referred to using character references must match the
2567
     * production for Char.
2568
     */
2569
0
    if (val >= 0x110000) {
2570
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2571
0
                "xmlParseCharRef: character reference out of bounds\n",
2572
0
          val);
2573
0
    } else if (IS_CHAR(val)) {
2574
0
        return(val);
2575
0
    } else {
2576
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2577
0
                          "xmlParseCharRef: invalid xmlChar value %d\n",
2578
0
                    val);
2579
0
    }
2580
0
    return(0);
2581
0
}
2582
2583
/**
2584
 * xmlParseStringCharRef:
2585
 * @ctxt:  an XML parser context
2586
 * @str:  a pointer to an index in the string
2587
 *
2588
 * parse Reference declarations, variant parsing from a string rather
2589
 * than an an input flow.
2590
 *
2591
 * [66] CharRef ::= '&#' [0-9]+ ';' |
2592
 *                  '&#x' [0-9a-fA-F]+ ';'
2593
 *
2594
 * [ WFC: Legal Character ]
2595
 * Characters referred to using character references must match the
2596
 * production for Char.
2597
 *
2598
 * Returns the value parsed (as an int), 0 in case of error, str will be
2599
 *         updated to the current value of the index
2600
 */
2601
static int
2602
0
xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
2603
0
    const xmlChar *ptr;
2604
0
    xmlChar cur;
2605
0
    int val = 0;
2606
2607
0
    if ((str == NULL) || (*str == NULL)) return(0);
2608
0
    ptr = *str;
2609
0
    cur = *ptr;
2610
0
    if ((cur == '&') && (ptr[1] == '#') && (ptr[2] == 'x')) {
2611
0
  ptr += 3;
2612
0
  cur = *ptr;
2613
0
  while (cur != ';') { /* Non input consuming loop */
2614
0
      if ((cur >= '0') && (cur <= '9'))
2615
0
          val = val * 16 + (cur - '0');
2616
0
      else if ((cur >= 'a') && (cur <= 'f'))
2617
0
          val = val * 16 + (cur - 'a') + 10;
2618
0
      else if ((cur >= 'A') && (cur <= 'F'))
2619
0
          val = val * 16 + (cur - 'A') + 10;
2620
0
      else {
2621
0
    xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
2622
0
    val = 0;
2623
0
    break;
2624
0
      }
2625
0
      if (val > 0x110000)
2626
0
          val = 0x110000;
2627
2628
0
      ptr++;
2629
0
      cur = *ptr;
2630
0
  }
2631
0
  if (cur == ';')
2632
0
      ptr++;
2633
0
    } else if  ((cur == '&') && (ptr[1] == '#')){
2634
0
  ptr += 2;
2635
0
  cur = *ptr;
2636
0
  while (cur != ';') { /* Non input consuming loops */
2637
0
      if ((cur >= '0') && (cur <= '9'))
2638
0
          val = val * 10 + (cur - '0');
2639
0
      else {
2640
0
    xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
2641
0
    val = 0;
2642
0
    break;
2643
0
      }
2644
0
      if (val > 0x110000)
2645
0
          val = 0x110000;
2646
2647
0
      ptr++;
2648
0
      cur = *ptr;
2649
0
  }
2650
0
  if (cur == ';')
2651
0
      ptr++;
2652
0
    } else {
2653
0
  xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
2654
0
  return(0);
2655
0
    }
2656
0
    *str = ptr;
2657
2658
    /*
2659
     * [ WFC: Legal Character ]
2660
     * Characters referred to using character references must match the
2661
     * production for Char.
2662
     */
2663
0
    if (val >= 0x110000) {
2664
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2665
0
                "xmlParseStringCharRef: character reference out of bounds\n",
2666
0
                val);
2667
0
    } else if (IS_CHAR(val)) {
2668
0
        return(val);
2669
0
    } else {
2670
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2671
0
        "xmlParseStringCharRef: invalid xmlChar value %d\n",
2672
0
        val);
2673
0
    }
2674
0
    return(0);
2675
0
}
2676
2677
/**
2678
 * xmlParserHandlePEReference:
2679
 * @ctxt:  the parser context
2680
 *
2681
 * DEPRECATED: Internal function, do not use.
2682
 *
2683
 * [69] PEReference ::= '%' Name ';'
2684
 *
2685
 * [ WFC: No Recursion ]
2686
 * A parsed entity must not contain a recursive
2687
 * reference to itself, either directly or indirectly.
2688
 *
2689
 * [ WFC: Entity Declared ]
2690
 * In a document without any DTD, a document with only an internal DTD
2691
 * subset which contains no parameter entity references, or a document
2692
 * with "standalone='yes'", ...  ... The declaration of a parameter
2693
 * entity must precede any reference to it...
2694
 *
2695
 * [ VC: Entity Declared ]
2696
 * In a document with an external subset or external parameter entities
2697
 * with "standalone='no'", ...  ... The declaration of a parameter entity
2698
 * must precede any reference to it...
2699
 *
2700
 * [ WFC: In DTD ]
2701
 * Parameter-entity references may only appear in the DTD.
2702
 * NOTE: misleading but this is handled.
2703
 *
2704
 * A PEReference may have been detected in the current input stream
2705
 * the handling is done accordingly to
2706
 *      http://www.w3.org/TR/REC-xml#entproc
2707
 * i.e.
2708
 *   - Included in literal in entity values
2709
 *   - Included as Parameter Entity reference within DTDs
2710
 */
2711
void
2712
0
xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
2713
0
    switch(ctxt->instate) {
2714
0
  case XML_PARSER_CDATA_SECTION:
2715
0
      return;
2716
0
        case XML_PARSER_COMMENT:
2717
0
      return;
2718
0
  case XML_PARSER_START_TAG:
2719
0
      return;
2720
0
  case XML_PARSER_END_TAG:
2721
0
      return;
2722
0
        case XML_PARSER_EOF:
2723
0
      xmlFatalErr(ctxt, XML_ERR_PEREF_AT_EOF, NULL);
2724
0
      return;
2725
0
        case XML_PARSER_PROLOG:
2726
0
  case XML_PARSER_START:
2727
0
  case XML_PARSER_XML_DECL:
2728
0
  case XML_PARSER_MISC:
2729
0
      xmlFatalErr(ctxt, XML_ERR_PEREF_IN_PROLOG, NULL);
2730
0
      return;
2731
0
  case XML_PARSER_ENTITY_DECL:
2732
0
        case XML_PARSER_CONTENT:
2733
0
        case XML_PARSER_ATTRIBUTE_VALUE:
2734
0
        case XML_PARSER_PI:
2735
0
  case XML_PARSER_SYSTEM_LITERAL:
2736
0
  case XML_PARSER_PUBLIC_LITERAL:
2737
      /* we just ignore it there */
2738
0
      return;
2739
0
        case XML_PARSER_EPILOG:
2740
0
      xmlFatalErr(ctxt, XML_ERR_PEREF_IN_EPILOG, NULL);
2741
0
      return;
2742
0
  case XML_PARSER_ENTITY_VALUE:
2743
      /*
2744
       * NOTE: in the case of entity values, we don't do the
2745
       *       substitution here since we need the literal
2746
       *       entity value to be able to save the internal
2747
       *       subset of the document.
2748
       *       This will be handled by xmlStringDecodeEntities
2749
       */
2750
0
      return;
2751
0
        case XML_PARSER_DTD:
2752
      /*
2753
       * [WFC: Well-Formedness Constraint: PEs in Internal Subset]
2754
       * In the internal DTD subset, parameter-entity references
2755
       * can occur only where markup declarations can occur, not
2756
       * within markup declarations.
2757
       * In that case this is handled in xmlParseMarkupDecl
2758
       */
2759
0
      if ((ctxt->external == 0) && (ctxt->inputNr == 1))
2760
0
    return;
2761
0
      if (IS_BLANK_CH(NXT(1)) || NXT(1) == 0)
2762
0
    return;
2763
0
            break;
2764
0
        case XML_PARSER_IGNORE:
2765
0
            return;
2766
0
    }
2767
2768
0
    xmlParsePEReference(ctxt);
2769
0
}
2770
2771
/*
2772
 * Macro used to grow the current buffer.
2773
 * buffer##_size is expected to be a size_t
2774
 * mem_error: is expected to handle memory allocation failures
2775
 */
2776
0
#define growBuffer(buffer, n) {           \
2777
0
    xmlChar *tmp;             \
2778
0
    size_t new_size = buffer##_size * 2 + n;                            \
2779
0
    if (new_size < buffer##_size) goto mem_error;                       \
2780
0
    tmp = (xmlChar *) xmlRealloc(buffer, new_size);                     \
2781
0
    if (tmp == NULL) goto mem_error;         \
2782
0
    buffer = tmp;             \
2783
0
    buffer##_size = new_size;                                           \
2784
0
}
2785
2786
/**
2787
 * xmlStringDecodeEntitiesInt:
2788
 * @ctxt:  the parser context
2789
 * @str:  the input string
2790
 * @len: the string length
2791
 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
2792
 * @end:  an end marker xmlChar, 0 if none
2793
 * @end2:  an end marker xmlChar, 0 if none
2794
 * @end3:  an end marker xmlChar, 0 if none
2795
 * @check:  whether to perform entity checks
2796
 */
2797
static xmlChar *
2798
xmlStringDecodeEntitiesInt(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
2799
               int what, xmlChar end, xmlChar  end2, xmlChar end3,
2800
0
                           int check) {
2801
0
    xmlChar *buffer = NULL;
2802
0
    size_t buffer_size = 0;
2803
0
    size_t nbchars = 0;
2804
2805
0
    xmlChar *current = NULL;
2806
0
    xmlChar *rep = NULL;
2807
0
    const xmlChar *last;
2808
0
    xmlEntityPtr ent;
2809
0
    int c,l;
2810
2811
0
    if (str == NULL)
2812
0
        return(NULL);
2813
0
    last = str + len;
2814
2815
0
    if (((ctxt->depth > 40) &&
2816
0
         ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
2817
0
  (ctxt->depth > 100)) {
2818
0
  xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_LOOP,
2819
0
                       "Maximum entity nesting depth exceeded");
2820
0
  return(NULL);
2821
0
    }
2822
2823
    /*
2824
     * allocate a translation buffer.
2825
     */
2826
0
    buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
2827
0
    buffer = (xmlChar *) xmlMallocAtomic(buffer_size);
2828
0
    if (buffer == NULL) goto mem_error;
2829
2830
    /*
2831
     * OK loop until we reach one of the ending char or a size limit.
2832
     * we are operating on already parsed values.
2833
     */
2834
0
    if (str < last)
2835
0
  c = CUR_SCHAR(str, l);
2836
0
    else
2837
0
        c = 0;
2838
0
    while ((c != 0) && (c != end) && /* non input consuming loop */
2839
0
           (c != end2) && (c != end3) &&
2840
0
           (ctxt->instate != XML_PARSER_EOF)) {
2841
2842
0
  if (c == 0) break;
2843
0
        if ((c == '&') && (str[1] == '#')) {
2844
0
      int val = xmlParseStringCharRef(ctxt, &str);
2845
0
      if (val == 0)
2846
0
                goto int_error;
2847
0
      COPY_BUF(buffer, nbchars, val);
2848
0
      if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2849
0
          growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2850
0
      }
2851
0
  } else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) {
2852
0
      if (xmlParserDebugEntities)
2853
0
    xmlGenericError(xmlGenericErrorContext,
2854
0
      "String decoding Entity Reference: %.30s\n",
2855
0
      str);
2856
0
      ent = xmlParseStringEntityRef(ctxt, &str);
2857
0
      if ((ent != NULL) &&
2858
0
    (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
2859
0
    if (ent->content != NULL) {
2860
0
        COPY_BUF(buffer, nbchars, ent->content[0]);
2861
0
        if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2862
0
      growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2863
0
        }
2864
0
    } else {
2865
0
        xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
2866
0
          "predefined entity has no content\n");
2867
0
                    goto int_error;
2868
0
    }
2869
0
      } else if ((ent != NULL) && (ent->content != NULL)) {
2870
0
          if ((check) && (xmlParserEntityCheck(ctxt, ent->length)))
2871
0
                    goto int_error;
2872
2873
0
                if (ent->flags & XML_ENT_EXPANDING) {
2874
0
              xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
2875
0
                    xmlHaltParser(ctxt);
2876
0
                    ent->content[0] = 0;
2877
0
                    goto int_error;
2878
0
                }
2879
2880
0
                ent->flags |= XML_ENT_EXPANDING;
2881
0
    ctxt->depth++;
2882
0
    rep = xmlStringDecodeEntitiesInt(ctxt, ent->content,
2883
0
                        ent->length, what, 0, 0, 0, check);
2884
0
    ctxt->depth--;
2885
0
                ent->flags &= ~XML_ENT_EXPANDING;
2886
2887
0
    if (rep == NULL) {
2888
0
                    ent->content[0] = 0;
2889
0
                    goto int_error;
2890
0
                }
2891
2892
0
                current = rep;
2893
0
                while (*current != 0) { /* non input consuming loop */
2894
0
                    buffer[nbchars++] = *current++;
2895
0
                    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2896
0
                        growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2897
0
                    }
2898
0
                }
2899
0
                xmlFree(rep);
2900
0
                rep = NULL;
2901
0
      } else if (ent != NULL) {
2902
0
    int i = xmlStrlen(ent->name);
2903
0
    const xmlChar *cur = ent->name;
2904
2905
0
    buffer[nbchars++] = '&';
2906
0
    if (nbchars + i + XML_PARSER_BUFFER_SIZE > buffer_size) {
2907
0
        growBuffer(buffer, i + XML_PARSER_BUFFER_SIZE);
2908
0
    }
2909
0
    for (;i > 0;i--)
2910
0
        buffer[nbchars++] = *cur++;
2911
0
    buffer[nbchars++] = ';';
2912
0
      }
2913
0
  } else if (c == '%' && (what & XML_SUBSTITUTE_PEREF)) {
2914
0
      if (xmlParserDebugEntities)
2915
0
    xmlGenericError(xmlGenericErrorContext,
2916
0
      "String decoding PE Reference: %.30s\n", str);
2917
0
      ent = xmlParseStringPEReference(ctxt, &str);
2918
0
      if (ent != NULL) {
2919
0
                if (ent->content == NULL) {
2920
        /*
2921
         * Note: external parsed entities will not be loaded,
2922
         * it is not required for a non-validating parser to
2923
         * complete external PEReferences coming from the
2924
         * internal subset
2925
         */
2926
0
        if (((ctxt->options & XML_PARSE_NOENT) != 0) ||
2927
0
      ((ctxt->options & XML_PARSE_DTDVALID) != 0) ||
2928
0
      (ctxt->validate != 0)) {
2929
0
      xmlLoadEntityContent(ctxt, ent);
2930
0
        } else {
2931
0
      xmlWarningMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
2932
0
      "not validating will not read content for PE entity %s\n",
2933
0
                          ent->name, NULL);
2934
0
        }
2935
0
    }
2936
2937
0
          if ((check) && (xmlParserEntityCheck(ctxt, ent->length)))
2938
0
                    goto int_error;
2939
2940
0
                if (ent->flags & XML_ENT_EXPANDING) {
2941
0
              xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
2942
0
                    xmlHaltParser(ctxt);
2943
0
                    if (ent->content != NULL)
2944
0
                        ent->content[0] = 0;
2945
0
                    goto int_error;
2946
0
                }
2947
2948
0
                ent->flags |= XML_ENT_EXPANDING;
2949
0
    ctxt->depth++;
2950
0
    rep = xmlStringDecodeEntitiesInt(ctxt, ent->content,
2951
0
                        ent->length, what, 0, 0, 0, check);
2952
0
    ctxt->depth--;
2953
0
                ent->flags &= ~XML_ENT_EXPANDING;
2954
2955
0
    if (rep == NULL) {
2956
0
                    if (ent->content != NULL)
2957
0
                        ent->content[0] = 0;
2958
0
                    goto int_error;
2959
0
                }
2960
0
                current = rep;
2961
0
                while (*current != 0) { /* non input consuming loop */
2962
0
                    buffer[nbchars++] = *current++;
2963
0
                    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2964
0
                        growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2965
0
                    }
2966
0
                }
2967
0
                xmlFree(rep);
2968
0
                rep = NULL;
2969
0
      }
2970
0
  } else {
2971
0
      COPY_BUF(buffer, nbchars, c);
2972
0
      str += l;
2973
0
      if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2974
0
          growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2975
0
      }
2976
0
  }
2977
0
  if (str < last)
2978
0
      c = CUR_SCHAR(str, l);
2979
0
  else
2980
0
      c = 0;
2981
0
    }
2982
0
    buffer[nbchars] = 0;
2983
0
    return(buffer);
2984
2985
0
mem_error:
2986
0
    xmlErrMemory(ctxt, NULL);
2987
0
int_error:
2988
0
    if (rep != NULL)
2989
0
        xmlFree(rep);
2990
0
    if (buffer != NULL)
2991
0
        xmlFree(buffer);
2992
0
    return(NULL);
2993
0
}
2994
2995
/**
2996
 * xmlStringLenDecodeEntities:
2997
 * @ctxt:  the parser context
2998
 * @str:  the input string
2999
 * @len: the string length
3000
 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
3001
 * @end:  an end marker xmlChar, 0 if none
3002
 * @end2:  an end marker xmlChar, 0 if none
3003
 * @end3:  an end marker xmlChar, 0 if none
3004
 *
3005
 * DEPRECATED: Internal function, don't use.
3006
 *
3007
 * Takes a entity string content and process to do the adequate substitutions.
3008
 *
3009
 * [67] Reference ::= EntityRef | CharRef
3010
 *
3011
 * [69] PEReference ::= '%' Name ';'
3012
 *
3013
 * Returns A newly allocated string with the substitution done. The caller
3014
 *      must deallocate it !
3015
 */
3016
xmlChar *
3017
xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
3018
                           int what, xmlChar end, xmlChar  end2,
3019
0
                           xmlChar end3) {
3020
0
    if ((ctxt == NULL) || (str == NULL) || (len < 0))
3021
0
        return(NULL);
3022
0
    return(xmlStringDecodeEntitiesInt(ctxt, str, len, what,
3023
0
                                      end, end2, end3, 0));
3024
0
}
3025
3026
/**
3027
 * xmlStringDecodeEntities:
3028
 * @ctxt:  the parser context
3029
 * @str:  the input string
3030
 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
3031
 * @end:  an end marker xmlChar, 0 if none
3032
 * @end2:  an end marker xmlChar, 0 if none
3033
 * @end3:  an end marker xmlChar, 0 if none
3034
 *
3035
 * DEPRECATED: Internal function, don't use.
3036
 *
3037
 * Takes a entity string content and process to do the adequate substitutions.
3038
 *
3039
 * [67] Reference ::= EntityRef | CharRef
3040
 *
3041
 * [69] PEReference ::= '%' Name ';'
3042
 *
3043
 * Returns A newly allocated string with the substitution done. The caller
3044
 *      must deallocate it !
3045
 */
3046
xmlChar *
3047
xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what,
3048
0
            xmlChar end, xmlChar  end2, xmlChar end3) {
3049
0
    if ((ctxt == NULL) || (str == NULL)) return(NULL);
3050
0
    return(xmlStringDecodeEntitiesInt(ctxt, str, xmlStrlen(str), what,
3051
0
                                      end, end2, end3, 0));
3052
0
}
3053
3054
/************************************************************************
3055
 *                  *
3056
 *    Commodity functions, cleanup needed ?     *
3057
 *                  *
3058
 ************************************************************************/
3059
3060
/**
3061
 * areBlanks:
3062
 * @ctxt:  an XML parser context
3063
 * @str:  a xmlChar *
3064
 * @len:  the size of @str
3065
 * @blank_chars: we know the chars are blanks
3066
 *
3067
 * Is this a sequence of blank chars that one can ignore ?
3068
 *
3069
 * Returns 1 if ignorable 0 otherwise.
3070
 */
3071
3072
static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
3073
88
                     int blank_chars) {
3074
88
    int i, ret;
3075
88
    xmlNodePtr lastChild;
3076
3077
    /*
3078
     * Don't spend time trying to differentiate them, the same callback is
3079
     * used !
3080
     */
3081
88
    if (ctxt->sax->ignorableWhitespace == ctxt->sax->characters)
3082
0
  return(0);
3083
3084
    /*
3085
     * Check for xml:space value.
3086
     */
3087
88
    if ((ctxt->space == NULL) || (*(ctxt->space) == 1) ||
3088
88
        (*(ctxt->space) == -2))
3089
77
  return(0);
3090
3091
    /*
3092
     * Check that the string is made of blanks
3093
     */
3094
11
    if (blank_chars == 0) {
3095
22
  for (i = 0;i < len;i++)
3096
11
      if (!(IS_BLANK_CH(str[i]))) return(0);
3097
11
    }
3098
3099
    /*
3100
     * Look if the element is mixed content in the DTD if available
3101
     */
3102
11
    if (ctxt->node == NULL) return(0);
3103
0
    if (ctxt->myDoc != NULL) {
3104
0
  ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name);
3105
0
        if (ret == 0) return(1);
3106
0
        if (ret == 1) return(0);
3107
0
    }
3108
3109
    /*
3110
     * Otherwise, heuristic :-\
3111
     */
3112
0
    if ((RAW != '<') && (RAW != 0xD)) return(0);
3113
0
    if ((ctxt->node->children == NULL) &&
3114
0
  (RAW == '<') && (NXT(1) == '/')) return(0);
3115
3116
0
    lastChild = xmlGetLastChild(ctxt->node);
3117
0
    if (lastChild == NULL) {
3118
0
        if ((ctxt->node->type != XML_ELEMENT_NODE) &&
3119
0
            (ctxt->node->content != NULL)) return(0);
3120
0
    } else if (xmlNodeIsText(lastChild))
3121
0
        return(0);
3122
0
    else if ((ctxt->node->children != NULL) &&
3123
0
             (xmlNodeIsText(ctxt->node->children)))
3124
0
        return(0);
3125
0
    return(1);
3126
0
}
3127
3128
/************************************************************************
3129
 *                  *
3130
 *    Extra stuff for namespace support     *
3131
 *  Relates to http://www.w3.org/TR/WD-xml-names      *
3132
 *                  *
3133
 ************************************************************************/
3134
3135
/**
3136
 * xmlSplitQName:
3137
 * @ctxt:  an XML parser context
3138
 * @name:  an XML parser context
3139
 * @prefix:  a xmlChar **
3140
 *
3141
 * parse an UTF8 encoded XML qualified name string
3142
 *
3143
 * [NS 5] QName ::= (Prefix ':')? LocalPart
3144
 *
3145
 * [NS 6] Prefix ::= NCName
3146
 *
3147
 * [NS 7] LocalPart ::= NCName
3148
 *
3149
 * Returns the local part, and prefix is updated
3150
 *   to get the Prefix if any.
3151
 */
3152
3153
xmlChar *
3154
0
xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
3155
0
    xmlChar buf[XML_MAX_NAMELEN + 5];
3156
0
    xmlChar *buffer = NULL;
3157
0
    int len = 0;
3158
0
    int max = XML_MAX_NAMELEN;
3159
0
    xmlChar *ret = NULL;
3160
0
    const xmlChar *cur = name;
3161
0
    int c;
3162
3163
0
    if (prefix == NULL) return(NULL);
3164
0
    *prefix = NULL;
3165
3166
0
    if (cur == NULL) return(NULL);
3167
3168
#ifndef XML_XML_NAMESPACE
3169
    /* xml: prefix is not really a namespace */
3170
    if ((cur[0] == 'x') && (cur[1] == 'm') &&
3171
        (cur[2] == 'l') && (cur[3] == ':'))
3172
  return(xmlStrdup(name));
3173
#endif
3174
3175
    /* nasty but well=formed */
3176
0
    if (cur[0] == ':')
3177
0
  return(xmlStrdup(name));
3178
3179
0
    c = *cur++;
3180
0
    while ((c != 0) && (c != ':') && (len < max)) { /* tested bigname.xml */
3181
0
  buf[len++] = c;
3182
0
  c = *cur++;
3183
0
    }
3184
0
    if (len >= max) {
3185
  /*
3186
   * Okay someone managed to make a huge name, so he's ready to pay
3187
   * for the processing speed.
3188
   */
3189
0
  max = len * 2;
3190
3191
0
  buffer = (xmlChar *) xmlMallocAtomic(max);
3192
0
  if (buffer == NULL) {
3193
0
      xmlErrMemory(ctxt, NULL);
3194
0
      return(NULL);
3195
0
  }
3196
0
  memcpy(buffer, buf, len);
3197
0
  while ((c != 0) && (c != ':')) { /* tested bigname.xml */
3198
0
      if (len + 10 > max) {
3199
0
          xmlChar *tmp;
3200
3201
0
    max *= 2;
3202
0
    tmp = (xmlChar *) xmlRealloc(buffer, max);
3203
0
    if (tmp == NULL) {
3204
0
        xmlFree(buffer);
3205
0
        xmlErrMemory(ctxt, NULL);
3206
0
        return(NULL);
3207
0
    }
3208
0
    buffer = tmp;
3209
0
      }
3210
0
      buffer[len++] = c;
3211
0
      c = *cur++;
3212
0
  }
3213
0
  buffer[len] = 0;
3214
0
    }
3215
3216
0
    if ((c == ':') && (*cur == 0)) {
3217
0
        if (buffer != NULL)
3218
0
      xmlFree(buffer);
3219
0
  *prefix = NULL;
3220
0
  return(xmlStrdup(name));
3221
0
    }
3222
3223
0
    if (buffer == NULL)
3224
0
  ret = xmlStrndup(buf, len);
3225
0
    else {
3226
0
  ret = buffer;
3227
0
  buffer = NULL;
3228
0
  max = XML_MAX_NAMELEN;
3229
0
    }
3230
3231
3232
0
    if (c == ':') {
3233
0
  c = *cur;
3234
0
        *prefix = ret;
3235
0
  if (c == 0) {
3236
0
      return(xmlStrndup(BAD_CAST "", 0));
3237
0
  }
3238
0
  len = 0;
3239
3240
  /*
3241
   * Check that the first character is proper to start
3242
   * a new name
3243
   */
3244
0
  if (!(((c >= 0x61) && (c <= 0x7A)) ||
3245
0
        ((c >= 0x41) && (c <= 0x5A)) ||
3246
0
        (c == '_') || (c == ':'))) {
3247
0
      int l;
3248
0
      int first = CUR_SCHAR(cur, l);
3249
3250
0
      if (!IS_LETTER(first) && (first != '_')) {
3251
0
    xmlFatalErrMsgStr(ctxt, XML_NS_ERR_QNAME,
3252
0
          "Name %s is not XML Namespace compliant\n",
3253
0
          name);
3254
0
      }
3255
0
  }
3256
0
  cur++;
3257
3258
0
  while ((c != 0) && (len < max)) { /* tested bigname2.xml */
3259
0
      buf[len++] = c;
3260
0
      c = *cur++;
3261
0
  }
3262
0
  if (len >= max) {
3263
      /*
3264
       * Okay someone managed to make a huge name, so he's ready to pay
3265
       * for the processing speed.
3266
       */
3267
0
      max = len * 2;
3268
3269
0
      buffer = (xmlChar *) xmlMallocAtomic(max);
3270
0
      if (buffer == NULL) {
3271
0
          xmlErrMemory(ctxt, NULL);
3272
0
    return(NULL);
3273
0
      }
3274
0
      memcpy(buffer, buf, len);
3275
0
      while (c != 0) { /* tested bigname2.xml */
3276
0
    if (len + 10 > max) {
3277
0
        xmlChar *tmp;
3278
3279
0
        max *= 2;
3280
0
        tmp = (xmlChar *) xmlRealloc(buffer, max);
3281
0
        if (tmp == NULL) {
3282
0
      xmlErrMemory(ctxt, NULL);
3283
0
      xmlFree(buffer);
3284
0
      return(NULL);
3285
0
        }
3286
0
        buffer = tmp;
3287
0
    }
3288
0
    buffer[len++] = c;
3289
0
    c = *cur++;
3290
0
      }
3291
0
      buffer[len] = 0;
3292
0
  }
3293
3294
0
  if (buffer == NULL)
3295
0
      ret = xmlStrndup(buf, len);
3296
0
  else {
3297
0
      ret = buffer;
3298
0
  }
3299
0
    }
3300
3301
0
    return(ret);
3302
0
}
3303
3304
/************************************************************************
3305
 *                  *
3306
 *      The parser itself       *
3307
 *  Relates to http://www.w3.org/TR/REC-xml       *
3308
 *                  *
3309
 ************************************************************************/
3310
3311
/************************************************************************
3312
 *                  *
3313
 *  Routines to parse Name, NCName and NmToken      *
3314
 *                  *
3315
 ************************************************************************/
3316
3317
/*
3318
 * The two following functions are related to the change of accepted
3319
 * characters for Name and NmToken in the Revision 5 of XML-1.0
3320
 * They correspond to the modified production [4] and the new production [4a]
3321
 * changes in that revision. Also note that the macros used for the
3322
 * productions Letter, Digit, CombiningChar and Extender are not needed
3323
 * anymore.
3324
 * We still keep compatibility to pre-revision5 parsing semantic if the
3325
 * new XML_PARSE_OLD10 option is given to the parser.
3326
 */
3327
static int
3328
0
xmlIsNameStartChar(xmlParserCtxtPtr ctxt, int c) {
3329
0
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3330
        /*
3331
   * Use the new checks of production [4] [4a] amd [5] of the
3332
   * Update 5 of XML-1.0
3333
   */
3334
0
  if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3335
0
      (((c >= 'a') && (c <= 'z')) ||
3336
0
       ((c >= 'A') && (c <= 'Z')) ||
3337
0
       (c == '_') || (c == ':') ||
3338
0
       ((c >= 0xC0) && (c <= 0xD6)) ||
3339
0
       ((c >= 0xD8) && (c <= 0xF6)) ||
3340
0
       ((c >= 0xF8) && (c <= 0x2FF)) ||
3341
0
       ((c >= 0x370) && (c <= 0x37D)) ||
3342
0
       ((c >= 0x37F) && (c <= 0x1FFF)) ||
3343
0
       ((c >= 0x200C) && (c <= 0x200D)) ||
3344
0
       ((c >= 0x2070) && (c <= 0x218F)) ||
3345
0
       ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3346
0
       ((c >= 0x3001) && (c <= 0xD7FF)) ||
3347
0
       ((c >= 0xF900) && (c <= 0xFDCF)) ||
3348
0
       ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3349
0
       ((c >= 0x10000) && (c <= 0xEFFFF))))
3350
0
      return(1);
3351
0
    } else {
3352
0
        if (IS_LETTER(c) || (c == '_') || (c == ':'))
3353
0
      return(1);
3354
0
    }
3355
0
    return(0);
3356
0
}
3357
3358
static int
3359
0
xmlIsNameChar(xmlParserCtxtPtr ctxt, int c) {
3360
0
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3361
        /*
3362
   * Use the new checks of production [4] [4a] amd [5] of the
3363
   * Update 5 of XML-1.0
3364
   */
3365
0
  if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3366
0
      (((c >= 'a') && (c <= 'z')) ||
3367
0
       ((c >= 'A') && (c <= 'Z')) ||
3368
0
       ((c >= '0') && (c <= '9')) || /* !start */
3369
0
       (c == '_') || (c == ':') ||
3370
0
       (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3371
0
       ((c >= 0xC0) && (c <= 0xD6)) ||
3372
0
       ((c >= 0xD8) && (c <= 0xF6)) ||
3373
0
       ((c >= 0xF8) && (c <= 0x2FF)) ||
3374
0
       ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3375
0
       ((c >= 0x370) && (c <= 0x37D)) ||
3376
0
       ((c >= 0x37F) && (c <= 0x1FFF)) ||
3377
0
       ((c >= 0x200C) && (c <= 0x200D)) ||
3378
0
       ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3379
0
       ((c >= 0x2070) && (c <= 0x218F)) ||
3380
0
       ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3381
0
       ((c >= 0x3001) && (c <= 0xD7FF)) ||
3382
0
       ((c >= 0xF900) && (c <= 0xFDCF)) ||
3383
0
       ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3384
0
       ((c >= 0x10000) && (c <= 0xEFFFF))))
3385
0
       return(1);
3386
0
    } else {
3387
0
        if ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3388
0
            (c == '.') || (c == '-') ||
3389
0
      (c == '_') || (c == ':') ||
3390
0
      (IS_COMBINING(c)) ||
3391
0
      (IS_EXTENDER(c)))
3392
0
      return(1);
3393
0
    }
3394
0
    return(0);
3395
0
}
3396
3397
static xmlChar * xmlParseAttValueInternal(xmlParserCtxtPtr ctxt,
3398
                                          int *len, int *alloc, int normalize);
3399
3400
static const xmlChar *
3401
0
xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
3402
0
    int len = 0, l;
3403
0
    int c;
3404
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3405
0
                    XML_MAX_TEXT_LENGTH :
3406
0
                    XML_MAX_NAME_LENGTH;
3407
3408
    /*
3409
     * Handler for more complex cases
3410
     */
3411
0
    c = CUR_CHAR(l);
3412
0
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3413
        /*
3414
   * Use the new checks of production [4] [4a] amd [5] of the
3415
   * Update 5 of XML-1.0
3416
   */
3417
0
  if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3418
0
      (!(((c >= 'a') && (c <= 'z')) ||
3419
0
         ((c >= 'A') && (c <= 'Z')) ||
3420
0
         (c == '_') || (c == ':') ||
3421
0
         ((c >= 0xC0) && (c <= 0xD6)) ||
3422
0
         ((c >= 0xD8) && (c <= 0xF6)) ||
3423
0
         ((c >= 0xF8) && (c <= 0x2FF)) ||
3424
0
         ((c >= 0x370) && (c <= 0x37D)) ||
3425
0
         ((c >= 0x37F) && (c <= 0x1FFF)) ||
3426
0
         ((c >= 0x200C) && (c <= 0x200D)) ||
3427
0
         ((c >= 0x2070) && (c <= 0x218F)) ||
3428
0
         ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3429
0
         ((c >= 0x3001) && (c <= 0xD7FF)) ||
3430
0
         ((c >= 0xF900) && (c <= 0xFDCF)) ||
3431
0
         ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3432
0
         ((c >= 0x10000) && (c <= 0xEFFFF))))) {
3433
0
      return(NULL);
3434
0
  }
3435
0
  len += l;
3436
0
  NEXTL(l);
3437
0
  c = CUR_CHAR(l);
3438
0
  while ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3439
0
         (((c >= 'a') && (c <= 'z')) ||
3440
0
          ((c >= 'A') && (c <= 'Z')) ||
3441
0
          ((c >= '0') && (c <= '9')) || /* !start */
3442
0
          (c == '_') || (c == ':') ||
3443
0
          (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3444
0
          ((c >= 0xC0) && (c <= 0xD6)) ||
3445
0
          ((c >= 0xD8) && (c <= 0xF6)) ||
3446
0
          ((c >= 0xF8) && (c <= 0x2FF)) ||
3447
0
          ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3448
0
          ((c >= 0x370) && (c <= 0x37D)) ||
3449
0
          ((c >= 0x37F) && (c <= 0x1FFF)) ||
3450
0
          ((c >= 0x200C) && (c <= 0x200D)) ||
3451
0
          ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3452
0
          ((c >= 0x2070) && (c <= 0x218F)) ||
3453
0
          ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3454
0
          ((c >= 0x3001) && (c <= 0xD7FF)) ||
3455
0
          ((c >= 0xF900) && (c <= 0xFDCF)) ||
3456
0
          ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3457
0
          ((c >= 0x10000) && (c <= 0xEFFFF))
3458
0
    )) {
3459
0
            if (len <= INT_MAX - l)
3460
0
          len += l;
3461
0
      NEXTL(l);
3462
0
      c = CUR_CHAR(l);
3463
0
  }
3464
0
    } else {
3465
0
  if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3466
0
      (!IS_LETTER(c) && (c != '_') &&
3467
0
       (c != ':'))) {
3468
0
      return(NULL);
3469
0
  }
3470
0
  len += l;
3471
0
  NEXTL(l);
3472
0
  c = CUR_CHAR(l);
3473
3474
0
  while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
3475
0
         ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3476
0
    (c == '.') || (c == '-') ||
3477
0
    (c == '_') || (c == ':') ||
3478
0
    (IS_COMBINING(c)) ||
3479
0
    (IS_EXTENDER(c)))) {
3480
0
            if (len <= INT_MAX - l)
3481
0
          len += l;
3482
0
      NEXTL(l);
3483
0
      c = CUR_CHAR(l);
3484
0
  }
3485
0
    }
3486
0
    if (ctxt->instate == XML_PARSER_EOF)
3487
0
        return(NULL);
3488
0
    if (len > maxLength) {
3489
0
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
3490
0
        return(NULL);
3491
0
    }
3492
0
    if (ctxt->input->cur - ctxt->input->base < len) {
3493
        /*
3494
         * There were a couple of bugs where PERefs lead to to a change
3495
         * of the buffer. Check the buffer size to avoid passing an invalid
3496
         * pointer to xmlDictLookup.
3497
         */
3498
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
3499
0
                    "unexpected change of input buffer");
3500
0
        return (NULL);
3501
0
    }
3502
0
    if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r'))
3503
0
        return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len));
3504
0
    return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
3505
0
}
3506
3507
/**
3508
 * xmlParseName:
3509
 * @ctxt:  an XML parser context
3510
 *
3511
 * DEPRECATED: Internal function, don't use.
3512
 *
3513
 * parse an XML name.
3514
 *
3515
 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3516
 *                  CombiningChar | Extender
3517
 *
3518
 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3519
 *
3520
 * [6] Names ::= Name (#x20 Name)*
3521
 *
3522
 * Returns the Name parsed or NULL
3523
 */
3524
3525
const xmlChar *
3526
176
xmlParseName(xmlParserCtxtPtr ctxt) {
3527
176
    const xmlChar *in;
3528
176
    const xmlChar *ret;
3529
176
    size_t count = 0;
3530
176
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3531
0
                       XML_MAX_TEXT_LENGTH :
3532
176
                       XML_MAX_NAME_LENGTH;
3533
3534
176
    GROW;
3535
176
    if (ctxt->instate == XML_PARSER_EOF)
3536
0
        return(NULL);
3537
3538
    /*
3539
     * Accelerator for simple ASCII names
3540
     */
3541
176
    in = ctxt->input->cur;
3542
176
    if (((*in >= 0x61) && (*in <= 0x7A)) ||
3543
176
  ((*in >= 0x41) && (*in <= 0x5A)) ||
3544
176
  (*in == '_') || (*in == ':')) {
3545
176
  in++;
3546
1.34k
  while (((*in >= 0x61) && (*in <= 0x7A)) ||
3547
1.34k
         ((*in >= 0x41) && (*in <= 0x5A)) ||
3548
1.34k
         ((*in >= 0x30) && (*in <= 0x39)) ||
3549
1.34k
         (*in == '_') || (*in == '-') ||
3550
1.34k
         (*in == ':') || (*in == '.'))
3551
1.16k
      in++;
3552
176
  if ((*in > 0) && (*in < 0x80)) {
3553
176
      count = in - ctxt->input->cur;
3554
176
            if (count > maxLength) {
3555
0
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
3556
0
                return(NULL);
3557
0
            }
3558
176
      ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
3559
176
      ctxt->input->cur = in;
3560
176
      ctxt->input->col += count;
3561
176
      if (ret == NULL)
3562
0
          xmlErrMemory(ctxt, NULL);
3563
176
      return(ret);
3564
176
  }
3565
176
    }
3566
    /* accelerator for special cases */
3567
0
    return(xmlParseNameComplex(ctxt));
3568
176
}
3569
3570
static xmlHashedString
3571
0
xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
3572
0
    xmlHashedString ret;
3573
0
    int len = 0, l;
3574
0
    int c;
3575
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3576
0
                    XML_MAX_TEXT_LENGTH :
3577
0
                    XML_MAX_NAME_LENGTH;
3578
0
    size_t startPosition = 0;
3579
3580
0
    ret.name = NULL;
3581
0
    ret.hashValue = 0;
3582
3583
    /*
3584
     * Handler for more complex cases
3585
     */
3586
0
    startPosition = CUR_PTR - BASE_PTR;
3587
0
    c = CUR_CHAR(l);
3588
0
    if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3589
0
  (!xmlIsNameStartChar(ctxt, c) || (c == ':'))) {
3590
0
  return(ret);
3591
0
    }
3592
3593
0
    while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
3594
0
     (xmlIsNameChar(ctxt, c) && (c != ':'))) {
3595
0
        if (len <= INT_MAX - l)
3596
0
      len += l;
3597
0
  NEXTL(l);
3598
0
  c = CUR_CHAR(l);
3599
0
    }
3600
0
    if (ctxt->instate == XML_PARSER_EOF)
3601
0
        return(ret);
3602
0
    if (len > maxLength) {
3603
0
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3604
0
        return(ret);
3605
0
    }
3606
0
    ret = xmlDictLookupHashed(ctxt->dict, (BASE_PTR + startPosition), len);
3607
0
    return(ret);
3608
0
}
3609
3610
/**
3611
 * xmlParseNCName:
3612
 * @ctxt:  an XML parser context
3613
 * @len:  length of the string parsed
3614
 *
3615
 * parse an XML name.
3616
 *
3617
 * [4NS] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
3618
 *                      CombiningChar | Extender
3619
 *
3620
 * [5NS] NCName ::= (Letter | '_') (NCNameChar)*
3621
 *
3622
 * Returns the Name parsed or NULL
3623
 */
3624
3625
static xmlHashedString
3626
0
xmlParseNCName(xmlParserCtxtPtr ctxt) {
3627
0
    const xmlChar *in, *e;
3628
0
    xmlHashedString ret;
3629
0
    size_t count = 0;
3630
0
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3631
0
                       XML_MAX_TEXT_LENGTH :
3632
0
                       XML_MAX_NAME_LENGTH;
3633
3634
0
    ret.name = NULL;
3635
3636
    /*
3637
     * Accelerator for simple ASCII names
3638
     */
3639
0
    in = ctxt->input->cur;
3640
0
    e = ctxt->input->end;
3641
0
    if ((((*in >= 0x61) && (*in <= 0x7A)) ||
3642
0
   ((*in >= 0x41) && (*in <= 0x5A)) ||
3643
0
   (*in == '_')) && (in < e)) {
3644
0
  in++;
3645
0
  while ((((*in >= 0x61) && (*in <= 0x7A)) ||
3646
0
          ((*in >= 0x41) && (*in <= 0x5A)) ||
3647
0
          ((*in >= 0x30) && (*in <= 0x39)) ||
3648
0
          (*in == '_') || (*in == '-') ||
3649
0
          (*in == '.')) && (in < e))
3650
0
      in++;
3651
0
  if (in >= e)
3652
0
      goto complex;
3653
0
  if ((*in > 0) && (*in < 0x80)) {
3654
0
      count = in - ctxt->input->cur;
3655
0
            if (count > maxLength) {
3656
0
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3657
0
                return(ret);
3658
0
            }
3659
0
      ret = xmlDictLookupHashed(ctxt->dict, ctxt->input->cur, count);
3660
0
      ctxt->input->cur = in;
3661
0
      ctxt->input->col += count;
3662
0
      if (ret.name == NULL) {
3663
0
          xmlErrMemory(ctxt, NULL);
3664
0
      }
3665
0
      return(ret);
3666
0
  }
3667
0
    }
3668
0
complex:
3669
0
    return(xmlParseNCNameComplex(ctxt));
3670
0
}
3671
3672
/**
3673
 * xmlParseNameAndCompare:
3674
 * @ctxt:  an XML parser context
3675
 *
3676
 * parse an XML name and compares for match
3677
 * (specialized for endtag parsing)
3678
 *
3679
 * Returns NULL for an illegal name, (xmlChar*) 1 for success
3680
 * and the name for mismatch
3681
 */
3682
3683
static const xmlChar *
3684
99
xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) {
3685
99
    register const xmlChar *cmp = other;
3686
99
    register const xmlChar *in;
3687
99
    const xmlChar *ret;
3688
3689
99
    GROW;
3690
99
    if (ctxt->instate == XML_PARSER_EOF)
3691
0
        return(NULL);
3692
3693
99
    in = ctxt->input->cur;
3694
715
    while (*in != 0 && *in == *cmp) {
3695
616
  ++in;
3696
616
  ++cmp;
3697
616
    }
3698
99
    if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
3699
  /* success */
3700
99
  ctxt->input->col += in - ctxt->input->cur;
3701
99
  ctxt->input->cur = in;
3702
99
  return (const xmlChar*) 1;
3703
99
    }
3704
    /* failure (or end of input buffer), check with full function */
3705
0
    ret = xmlParseName (ctxt);
3706
    /* strings coming from the dictionary direct compare possible */
3707
0
    if (ret == other) {
3708
0
  return (const xmlChar*) 1;
3709
0
    }
3710
0
    return ret;
3711
0
}
3712
3713
/**
3714
 * xmlParseStringName:
3715
 * @ctxt:  an XML parser context
3716
 * @str:  a pointer to the string pointer (IN/OUT)
3717
 *
3718
 * parse an XML name.
3719
 *
3720
 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3721
 *                  CombiningChar | Extender
3722
 *
3723
 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3724
 *
3725
 * [6] Names ::= Name (#x20 Name)*
3726
 *
3727
 * Returns the Name parsed or NULL. The @str pointer
3728
 * is updated to the current location in the string.
3729
 */
3730
3731
static xmlChar *
3732
0
xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
3733
0
    xmlChar buf[XML_MAX_NAMELEN + 5];
3734
0
    const xmlChar *cur = *str;
3735
0
    int len = 0, l;
3736
0
    int c;
3737
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3738
0
                    XML_MAX_TEXT_LENGTH :
3739
0
                    XML_MAX_NAME_LENGTH;
3740
3741
0
    c = CUR_SCHAR(cur, l);
3742
0
    if (!xmlIsNameStartChar(ctxt, c)) {
3743
0
  return(NULL);
3744
0
    }
3745
3746
0
    COPY_BUF(buf, len, c);
3747
0
    cur += l;
3748
0
    c = CUR_SCHAR(cur, l);
3749
0
    while (xmlIsNameChar(ctxt, c)) {
3750
0
  COPY_BUF(buf, len, c);
3751
0
  cur += l;
3752
0
  c = CUR_SCHAR(cur, l);
3753
0
  if (len >= XML_MAX_NAMELEN) { /* test bigentname.xml */
3754
      /*
3755
       * Okay someone managed to make a huge name, so he's ready to pay
3756
       * for the processing speed.
3757
       */
3758
0
      xmlChar *buffer;
3759
0
      int max = len * 2;
3760
3761
0
      buffer = (xmlChar *) xmlMallocAtomic(max);
3762
0
      if (buffer == NULL) {
3763
0
          xmlErrMemory(ctxt, NULL);
3764
0
    return(NULL);
3765
0
      }
3766
0
      memcpy(buffer, buf, len);
3767
0
      while (xmlIsNameChar(ctxt, c)) {
3768
0
    if (len + 10 > max) {
3769
0
        xmlChar *tmp;
3770
3771
0
        max *= 2;
3772
0
        tmp = (xmlChar *) xmlRealloc(buffer, max);
3773
0
        if (tmp == NULL) {
3774
0
      xmlErrMemory(ctxt, NULL);
3775
0
      xmlFree(buffer);
3776
0
      return(NULL);
3777
0
        }
3778
0
        buffer = tmp;
3779
0
    }
3780
0
    COPY_BUF(buffer, len, c);
3781
0
    cur += l;
3782
0
    c = CUR_SCHAR(cur, l);
3783
0
                if (len > maxLength) {
3784
0
                    xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3785
0
                    xmlFree(buffer);
3786
0
                    return(NULL);
3787
0
                }
3788
0
      }
3789
0
      buffer[len] = 0;
3790
0
      *str = cur;
3791
0
      return(buffer);
3792
0
  }
3793
0
    }
3794
0
    if (len > maxLength) {
3795
0
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3796
0
        return(NULL);
3797
0
    }
3798
0
    *str = cur;
3799
0
    return(xmlStrndup(buf, len));
3800
0
}
3801
3802
/**
3803
 * xmlParseNmtoken:
3804
 * @ctxt:  an XML parser context
3805
 *
3806
 * DEPRECATED: Internal function, don't use.
3807
 *
3808
 * parse an XML Nmtoken.
3809
 *
3810
 * [7] Nmtoken ::= (NameChar)+
3811
 *
3812
 * [8] Nmtokens ::= Nmtoken (#x20 Nmtoken)*
3813
 *
3814
 * Returns the Nmtoken parsed or NULL
3815
 */
3816
3817
xmlChar *
3818
0
xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
3819
0
    xmlChar buf[XML_MAX_NAMELEN + 5];
3820
0
    int len = 0, l;
3821
0
    int c;
3822
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3823
0
                    XML_MAX_TEXT_LENGTH :
3824
0
                    XML_MAX_NAME_LENGTH;
3825
3826
0
    c = CUR_CHAR(l);
3827
3828
0
    while (xmlIsNameChar(ctxt, c)) {
3829
0
  COPY_BUF(buf, len, c);
3830
0
  NEXTL(l);
3831
0
  c = CUR_CHAR(l);
3832
0
  if (len >= XML_MAX_NAMELEN) {
3833
      /*
3834
       * Okay someone managed to make a huge token, so he's ready to pay
3835
       * for the processing speed.
3836
       */
3837
0
      xmlChar *buffer;
3838
0
      int max = len * 2;
3839
3840
0
      buffer = (xmlChar *) xmlMallocAtomic(max);
3841
0
      if (buffer == NULL) {
3842
0
          xmlErrMemory(ctxt, NULL);
3843
0
    return(NULL);
3844
0
      }
3845
0
      memcpy(buffer, buf, len);
3846
0
      while (xmlIsNameChar(ctxt, c)) {
3847
0
    if (len + 10 > max) {
3848
0
        xmlChar *tmp;
3849
3850
0
        max *= 2;
3851
0
        tmp = (xmlChar *) xmlRealloc(buffer, max);
3852
0
        if (tmp == NULL) {
3853
0
      xmlErrMemory(ctxt, NULL);
3854
0
      xmlFree(buffer);
3855
0
      return(NULL);
3856
0
        }
3857
0
        buffer = tmp;
3858
0
    }
3859
0
    COPY_BUF(buffer, len, c);
3860
0
                if (len > maxLength) {
3861
0
                    xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
3862
0
                    xmlFree(buffer);
3863
0
                    return(NULL);
3864
0
                }
3865
0
    NEXTL(l);
3866
0
    c = CUR_CHAR(l);
3867
0
      }
3868
0
      buffer[len] = 0;
3869
0
            if (ctxt->instate == XML_PARSER_EOF) {
3870
0
                xmlFree(buffer);
3871
0
                return(NULL);
3872
0
            }
3873
0
      return(buffer);
3874
0
  }
3875
0
    }
3876
0
    if (ctxt->instate == XML_PARSER_EOF)
3877
0
        return(NULL);
3878
0
    if (len == 0)
3879
0
        return(NULL);
3880
0
    if (len > maxLength) {
3881
0
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
3882
0
        return(NULL);
3883
0
    }
3884
0
    return(xmlStrndup(buf, len));
3885
0
}
3886
3887
/**
3888
 * xmlParseEntityValue:
3889
 * @ctxt:  an XML parser context
3890
 * @orig:  if non-NULL store a copy of the original entity value
3891
 *
3892
 * DEPRECATED: Internal function, don't use.
3893
 *
3894
 * parse a value for ENTITY declarations
3895
 *
3896
 * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
3897
 *                 "'" ([^%&'] | PEReference | Reference)* "'"
3898
 *
3899
 * Returns the EntityValue parsed with reference substituted or NULL
3900
 */
3901
3902
xmlChar *
3903
0
xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
3904
0
    xmlChar *buf = NULL;
3905
0
    int len = 0;
3906
0
    int size = XML_PARSER_BUFFER_SIZE;
3907
0
    int c, l;
3908
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3909
0
                    XML_MAX_HUGE_LENGTH :
3910
0
                    XML_MAX_TEXT_LENGTH;
3911
0
    xmlChar stop;
3912
0
    xmlChar *ret = NULL;
3913
0
    const xmlChar *cur = NULL;
3914
0
    xmlParserInputPtr input;
3915
3916
0
    if (RAW == '"') stop = '"';
3917
0
    else if (RAW == '\'') stop = '\'';
3918
0
    else {
3919
0
  xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_STARTED, NULL);
3920
0
  return(NULL);
3921
0
    }
3922
0
    buf = (xmlChar *) xmlMallocAtomic(size);
3923
0
    if (buf == NULL) {
3924
0
  xmlErrMemory(ctxt, NULL);
3925
0
  return(NULL);
3926
0
    }
3927
3928
    /*
3929
     * The content of the entity definition is copied in a buffer.
3930
     */
3931
3932
0
    ctxt->instate = XML_PARSER_ENTITY_VALUE;
3933
0
    input = ctxt->input;
3934
0
    GROW;
3935
0
    if (ctxt->instate == XML_PARSER_EOF)
3936
0
        goto error;
3937
0
    NEXT;
3938
0
    c = CUR_CHAR(l);
3939
    /*
3940
     * NOTE: 4.4.5 Included in Literal
3941
     * When a parameter entity reference appears in a literal entity
3942
     * value, ... a single or double quote character in the replacement
3943
     * text is always treated as a normal data character and will not
3944
     * terminate the literal.
3945
     * In practice it means we stop the loop only when back at parsing
3946
     * the initial entity and the quote is found
3947
     */
3948
0
    while (((IS_CHAR(c)) && ((c != stop) || /* checked */
3949
0
      (ctxt->input != input))) && (ctxt->instate != XML_PARSER_EOF)) {
3950
0
  if (len + 5 >= size) {
3951
0
      xmlChar *tmp;
3952
3953
0
      size *= 2;
3954
0
      tmp = (xmlChar *) xmlRealloc(buf, size);
3955
0
      if (tmp == NULL) {
3956
0
    xmlErrMemory(ctxt, NULL);
3957
0
                goto error;
3958
0
      }
3959
0
      buf = tmp;
3960
0
  }
3961
0
  COPY_BUF(buf, len, c);
3962
0
  NEXTL(l);
3963
3964
0
  GROW;
3965
0
  c = CUR_CHAR(l);
3966
0
  if (c == 0) {
3967
0
      GROW;
3968
0
      c = CUR_CHAR(l);
3969
0
  }
3970
3971
0
        if (len > maxLength) {
3972
0
            xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
3973
0
                           "entity value too long\n");
3974
0
            goto error;
3975
0
        }
3976
0
    }
3977
0
    buf[len] = 0;
3978
0
    if (ctxt->instate == XML_PARSER_EOF)
3979
0
        goto error;
3980
0
    if (c != stop) {
3981
0
        xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL);
3982
0
        goto error;
3983
0
    }
3984
0
    NEXT;
3985
3986
    /*
3987
     * Raise problem w.r.t. '&' and '%' being used in non-entities
3988
     * reference constructs. Note Charref will be handled in
3989
     * xmlStringDecodeEntities()
3990
     */
3991
0
    cur = buf;
3992
0
    while (*cur != 0) { /* non input consuming */
3993
0
  if ((*cur == '%') || ((*cur == '&') && (cur[1] != '#'))) {
3994
0
      xmlChar *name;
3995
0
      xmlChar tmp = *cur;
3996
0
            int nameOk = 0;
3997
3998
0
      cur++;
3999
0
      name = xmlParseStringName(ctxt, &cur);
4000
0
            if (name != NULL) {
4001
0
                nameOk = 1;
4002
0
                xmlFree(name);
4003
0
            }
4004
0
            if ((nameOk == 0) || (*cur != ';')) {
4005
0
    xmlFatalErrMsgInt(ctxt, XML_ERR_ENTITY_CHAR_ERROR,
4006
0
      "EntityValue: '%c' forbidden except for entities references\n",
4007
0
                            tmp);
4008
0
                goto error;
4009
0
      }
4010
0
      if ((tmp == '%') && (ctxt->inSubset == 1) &&
4011
0
    (ctxt->inputNr == 1)) {
4012
0
    xmlFatalErr(ctxt, XML_ERR_ENTITY_PE_INTERNAL, NULL);
4013
0
                goto error;
4014
0
      }
4015
0
      if (*cur == 0)
4016
0
          break;
4017
0
  }
4018
0
  cur++;
4019
0
    }
4020
4021
    /*
4022
     * Then PEReference entities are substituted.
4023
     *
4024
     * NOTE: 4.4.7 Bypassed
4025
     * When a general entity reference appears in the EntityValue in
4026
     * an entity declaration, it is bypassed and left as is.
4027
     * so XML_SUBSTITUTE_REF is not set here.
4028
     */
4029
0
    ++ctxt->depth;
4030
0
    ret = xmlStringDecodeEntitiesInt(ctxt, buf, len, XML_SUBSTITUTE_PEREF,
4031
0
                                     0, 0, 0, /* check */ 1);
4032
0
    --ctxt->depth;
4033
4034
0
    if (orig != NULL) {
4035
0
        *orig = buf;
4036
0
        buf = NULL;
4037
0
    }
4038
4039
0
error:
4040
0
    if (buf != NULL)
4041
0
        xmlFree(buf);
4042
0
    return(ret);
4043
0
}
4044
4045
/**
4046
 * xmlParseAttValueComplex:
4047
 * @ctxt:  an XML parser context
4048
 * @len:   the resulting attribute len
4049
 * @normalize:  whether to apply the inner normalization
4050
 *
4051
 * parse a value for an attribute, this is the fallback function
4052
 * of xmlParseAttValue() when the attribute parsing requires handling
4053
 * of non-ASCII characters, or normalization compaction.
4054
 *
4055
 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
4056
 */
4057
static xmlChar *
4058
0
xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
4059
0
    xmlChar limit = 0;
4060
0
    xmlChar *buf = NULL;
4061
0
    xmlChar *rep = NULL;
4062
0
    size_t len = 0;
4063
0
    size_t buf_size = 0;
4064
0
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4065
0
                       XML_MAX_HUGE_LENGTH :
4066
0
                       XML_MAX_TEXT_LENGTH;
4067
0
    int c, l, in_space = 0;
4068
0
    xmlChar *current = NULL;
4069
0
    xmlEntityPtr ent;
4070
4071
0
    if (NXT(0) == '"') {
4072
0
  ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
4073
0
  limit = '"';
4074
0
        NEXT;
4075
0
    } else if (NXT(0) == '\'') {
4076
0
  limit = '\'';
4077
0
  ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
4078
0
        NEXT;
4079
0
    } else {
4080
0
  xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
4081
0
  return(NULL);
4082
0
    }
4083
4084
    /*
4085
     * allocate a translation buffer.
4086
     */
4087
0
    buf_size = XML_PARSER_BUFFER_SIZE;
4088
0
    buf = (xmlChar *) xmlMallocAtomic(buf_size);
4089
0
    if (buf == NULL) goto mem_error;
4090
4091
    /*
4092
     * OK loop until we reach one of the ending char or a size limit.
4093
     */
4094
0
    c = CUR_CHAR(l);
4095
0
    while (((NXT(0) != limit) && /* checked */
4096
0
            (IS_CHAR(c)) && (c != '<')) &&
4097
0
            (ctxt->instate != XML_PARSER_EOF)) {
4098
0
  if (c == '&') {
4099
0
      in_space = 0;
4100
0
      if (NXT(1) == '#') {
4101
0
    int val = xmlParseCharRef(ctxt);
4102
4103
0
    if (val == '&') {
4104
0
        if (ctxt->replaceEntities) {
4105
0
      if (len + 10 > buf_size) {
4106
0
          growBuffer(buf, 10);
4107
0
      }
4108
0
      buf[len++] = '&';
4109
0
        } else {
4110
      /*
4111
       * The reparsing will be done in xmlStringGetNodeList()
4112
       * called by the attribute() function in SAX.c
4113
       */
4114
0
      if (len + 10 > buf_size) {
4115
0
          growBuffer(buf, 10);
4116
0
      }
4117
0
      buf[len++] = '&';
4118
0
      buf[len++] = '#';
4119
0
      buf[len++] = '3';
4120
0
      buf[len++] = '8';
4121
0
      buf[len++] = ';';
4122
0
        }
4123
0
    } else if (val != 0) {
4124
0
        if (len + 10 > buf_size) {
4125
0
      growBuffer(buf, 10);
4126
0
        }
4127
0
        len += xmlCopyChar(0, &buf[len], val);
4128
0
    }
4129
0
      } else {
4130
0
    ent = xmlParseEntityRef(ctxt);
4131
0
    if ((ent != NULL) &&
4132
0
        (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
4133
0
        if (len + 10 > buf_size) {
4134
0
      growBuffer(buf, 10);
4135
0
        }
4136
0
        if ((ctxt->replaceEntities == 0) &&
4137
0
            (ent->content[0] == '&')) {
4138
0
      buf[len++] = '&';
4139
0
      buf[len++] = '#';
4140
0
      buf[len++] = '3';
4141
0
      buf[len++] = '8';
4142
0
      buf[len++] = ';';
4143
0
        } else {
4144
0
      buf[len++] = ent->content[0];
4145
0
        }
4146
0
    } else if ((ent != NULL) &&
4147
0
               (ctxt->replaceEntities != 0)) {
4148
0
        if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
4149
0
                        if (xmlParserEntityCheck(ctxt, ent->length))
4150
0
                            goto error;
4151
4152
0
      ++ctxt->depth;
4153
0
      rep = xmlStringDecodeEntitiesInt(ctxt, ent->content,
4154
0
                                ent->length, XML_SUBSTITUTE_REF, 0, 0, 0,
4155
0
                                /* check */ 1);
4156
0
      --ctxt->depth;
4157
0
      if (rep != NULL) {
4158
0
          current = rep;
4159
0
          while (*current != 0) { /* non input consuming */
4160
0
                                if ((*current == 0xD) || (*current == 0xA) ||
4161
0
                                    (*current == 0x9)) {
4162
0
                                    buf[len++] = 0x20;
4163
0
                                    current++;
4164
0
                                } else
4165
0
                                    buf[len++] = *current++;
4166
0
        if (len + 10 > buf_size) {
4167
0
            growBuffer(buf, 10);
4168
0
        }
4169
0
          }
4170
0
          xmlFree(rep);
4171
0
          rep = NULL;
4172
0
      }
4173
0
        } else {
4174
0
      if (len + 10 > buf_size) {
4175
0
          growBuffer(buf, 10);
4176
0
      }
4177
0
      if (ent->content != NULL)
4178
0
          buf[len++] = ent->content[0];
4179
0
        }
4180
0
    } else if (ent != NULL) {
4181
0
        int i = xmlStrlen(ent->name);
4182
0
        const xmlChar *cur = ent->name;
4183
4184
        /*
4185
                     * We also check for recursion and amplification
4186
                     * when entities are not substituted. They're
4187
                     * often expanded later.
4188
         */
4189
0
        if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
4190
0
      (ent->content != NULL)) {
4191
0
                        if ((ent->flags & XML_ENT_CHECKED) == 0) {
4192
0
                            unsigned long oldCopy = ctxt->sizeentcopy;
4193
4194
0
                            ctxt->sizeentcopy = ent->length;
4195
4196
0
                            ++ctxt->depth;
4197
0
                            rep = xmlStringDecodeEntitiesInt(ctxt,
4198
0
                                    ent->content, ent->length,
4199
0
                                    XML_SUBSTITUTE_REF, 0, 0, 0,
4200
0
                                    /* check */ 1);
4201
0
                            --ctxt->depth;
4202
4203
                            /*
4204
                             * If we're parsing DTD content, the entity
4205
                             * might reference other entities which
4206
                             * weren't defined yet, so the check isn't
4207
                             * reliable.
4208
                             */
4209
0
                            if (ctxt->inSubset == 0) {
4210
0
                                ent->flags |= XML_ENT_CHECKED;
4211
0
                                ent->expandedSize = ctxt->sizeentcopy;
4212
0
                            }
4213
4214
0
                            if (rep != NULL) {
4215
0
                                xmlFree(rep);
4216
0
                                rep = NULL;
4217
0
                            } else {
4218
0
                                ent->content[0] = 0;
4219
0
                            }
4220
4221
0
                            if (xmlParserEntityCheck(ctxt, oldCopy))
4222
0
                                goto error;
4223
0
                        } else {
4224
0
                            if (xmlParserEntityCheck(ctxt, ent->expandedSize))
4225
0
                                goto error;
4226
0
                        }
4227
0
        }
4228
4229
        /*
4230
         * Just output the reference
4231
         */
4232
0
        buf[len++] = '&';
4233
0
        while (len + i + 10 > buf_size) {
4234
0
      growBuffer(buf, i + 10);
4235
0
        }
4236
0
        for (;i > 0;i--)
4237
0
      buf[len++] = *cur++;
4238
0
        buf[len++] = ';';
4239
0
    }
4240
0
      }
4241
0
  } else {
4242
0
      if ((c == 0x20) || (c == 0xD) || (c == 0xA) || (c == 0x9)) {
4243
0
          if ((len != 0) || (!normalize)) {
4244
0
        if ((!normalize) || (!in_space)) {
4245
0
      COPY_BUF(buf, len, 0x20);
4246
0
      while (len + 10 > buf_size) {
4247
0
          growBuffer(buf, 10);
4248
0
      }
4249
0
        }
4250
0
        in_space = 1;
4251
0
    }
4252
0
      } else {
4253
0
          in_space = 0;
4254
0
    COPY_BUF(buf, len, c);
4255
0
    if (len + 10 > buf_size) {
4256
0
        growBuffer(buf, 10);
4257
0
    }
4258
0
      }
4259
0
      NEXTL(l);
4260
0
  }
4261
0
  GROW;
4262
0
  c = CUR_CHAR(l);
4263
0
        if (len > maxLength) {
4264
0
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
4265
0
                           "AttValue length too long\n");
4266
0
            goto mem_error;
4267
0
        }
4268
0
    }
4269
0
    if (ctxt->instate == XML_PARSER_EOF)
4270
0
        goto error;
4271
4272
0
    if ((in_space) && (normalize)) {
4273
0
        while ((len > 0) && (buf[len - 1] == 0x20)) len--;
4274
0
    }
4275
0
    buf[len] = 0;
4276
0
    if (RAW == '<') {
4277
0
  xmlFatalErr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, NULL);
4278
0
    } else if (RAW != limit) {
4279
0
  if ((c != 0) && (!IS_CHAR(c))) {
4280
0
      xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
4281
0
         "invalid character in attribute value\n");
4282
0
  } else {
4283
0
      xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
4284
0
         "AttValue: ' expected\n");
4285
0
        }
4286
0
    } else
4287
0
  NEXT;
4288
4289
0
    if (attlen != NULL) *attlen = len;
4290
0
    return(buf);
4291
4292
0
mem_error:
4293
0
    xmlErrMemory(ctxt, NULL);
4294
0
error:
4295
0
    if (buf != NULL)
4296
0
        xmlFree(buf);
4297
0
    if (rep != NULL)
4298
0
        xmlFree(rep);
4299
0
    return(NULL);
4300
0
}
4301
4302
/**
4303
 * xmlParseAttValue:
4304
 * @ctxt:  an XML parser context
4305
 *
4306
 * DEPRECATED: Internal function, don't use.
4307
 *
4308
 * parse a value for an attribute
4309
 * Note: the parser won't do substitution of entities here, this
4310
 * will be handled later in xmlStringGetNodeList
4311
 *
4312
 * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |
4313
 *                   "'" ([^<&'] | Reference)* "'"
4314
 *
4315
 * 3.3.3 Attribute-Value Normalization:
4316
 * Before the value of an attribute is passed to the application or
4317
 * checked for validity, the XML processor must normalize it as follows:
4318
 * - a character reference is processed by appending the referenced
4319
 *   character to the attribute value
4320
 * - an entity reference is processed by recursively processing the
4321
 *   replacement text of the entity
4322
 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
4323
 *   appending #x20 to the normalized value, except that only a single
4324
 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
4325
 *   parsed entity or the literal entity value of an internal parsed entity
4326
 * - other characters are processed by appending them to the normalized value
4327
 * If the declared value is not CDATA, then the XML processor must further
4328
 * process the normalized attribute value by discarding any leading and
4329
 * trailing space (#x20) characters, and by replacing sequences of space
4330
 * (#x20) characters by a single space (#x20) character.
4331
 * All attributes for which no declaration has been read should be treated
4332
 * by a non-validating parser as if declared CDATA.
4333
 *
4334
 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
4335
 */
4336
4337
4338
xmlChar *
4339
77
xmlParseAttValue(xmlParserCtxtPtr ctxt) {
4340
77
    if ((ctxt == NULL) || (ctxt->input == NULL)) return(NULL);
4341
77
    return(xmlParseAttValueInternal(ctxt, NULL, NULL, 0));
4342
77
}
4343
4344
/**
4345
 * xmlParseSystemLiteral:
4346
 * @ctxt:  an XML parser context
4347
 *
4348
 * DEPRECATED: Internal function, don't use.
4349
 *
4350
 * parse an XML Literal
4351
 *
4352
 * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
4353
 *
4354
 * Returns the SystemLiteral parsed or NULL
4355
 */
4356
4357
xmlChar *
4358
0
xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
4359
0
    xmlChar *buf = NULL;
4360
0
    int len = 0;
4361
0
    int size = XML_PARSER_BUFFER_SIZE;
4362
0
    int cur, l;
4363
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4364
0
                    XML_MAX_TEXT_LENGTH :
4365
0
                    XML_MAX_NAME_LENGTH;
4366
0
    xmlChar stop;
4367
0
    int state = ctxt->instate;
4368
4369
0
    if (RAW == '"') {
4370
0
        NEXT;
4371
0
  stop = '"';
4372
0
    } else if (RAW == '\'') {
4373
0
        NEXT;
4374
0
  stop = '\'';
4375
0
    } else {
4376
0
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
4377
0
  return(NULL);
4378
0
    }
4379
4380
0
    buf = (xmlChar *) xmlMallocAtomic(size);
4381
0
    if (buf == NULL) {
4382
0
        xmlErrMemory(ctxt, NULL);
4383
0
  return(NULL);
4384
0
    }
4385
0
    ctxt->instate = XML_PARSER_SYSTEM_LITERAL;
4386
0
    cur = CUR_CHAR(l);
4387
0
    while ((IS_CHAR(cur)) && (cur != stop)) { /* checked */
4388
0
  if (len + 5 >= size) {
4389
0
      xmlChar *tmp;
4390
4391
0
      size *= 2;
4392
0
      tmp = (xmlChar *) xmlRealloc(buf, size);
4393
0
      if (tmp == NULL) {
4394
0
          xmlFree(buf);
4395
0
    xmlErrMemory(ctxt, NULL);
4396
0
    ctxt->instate = (xmlParserInputState) state;
4397
0
    return(NULL);
4398
0
      }
4399
0
      buf = tmp;
4400
0
  }
4401
0
  COPY_BUF(buf, len, cur);
4402
0
        if (len > maxLength) {
4403
0
            xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral");
4404
0
            xmlFree(buf);
4405
0
            ctxt->instate = (xmlParserInputState) state;
4406
0
            return(NULL);
4407
0
        }
4408
0
  NEXTL(l);
4409
0
  cur = CUR_CHAR(l);
4410
0
    }
4411
0
    buf[len] = 0;
4412
0
    if (ctxt->instate == XML_PARSER_EOF) {
4413
0
        xmlFree(buf);
4414
0
        return(NULL);
4415
0
    }
4416
0
    ctxt->instate = (xmlParserInputState) state;
4417
0
    if (!IS_CHAR(cur)) {
4418
0
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
4419
0
    } else {
4420
0
  NEXT;
4421
0
    }
4422
0
    return(buf);
4423
0
}
4424
4425
/**
4426
 * xmlParsePubidLiteral:
4427
 * @ctxt:  an XML parser context
4428
 *
4429
 * DEPRECATED: Internal function, don't use.
4430
 *
4431
 * parse an XML public literal
4432
 *
4433
 * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
4434
 *
4435
 * Returns the PubidLiteral parsed or NULL.
4436
 */
4437
4438
xmlChar *
4439
0
xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
4440
0
    xmlChar *buf = NULL;
4441
0
    int len = 0;
4442
0
    int size = XML_PARSER_BUFFER_SIZE;
4443
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4444
0
                    XML_MAX_TEXT_LENGTH :
4445
0
                    XML_MAX_NAME_LENGTH;
4446
0
    xmlChar cur;
4447
0
    xmlChar stop;
4448
0
    xmlParserInputState oldstate = ctxt->instate;
4449
4450
0
    if (RAW == '"') {
4451
0
        NEXT;
4452
0
  stop = '"';
4453
0
    } else if (RAW == '\'') {
4454
0
        NEXT;
4455
0
  stop = '\'';
4456
0
    } else {
4457
0
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
4458
0
  return(NULL);
4459
0
    }
4460
0
    buf = (xmlChar *) xmlMallocAtomic(size);
4461
0
    if (buf == NULL) {
4462
0
  xmlErrMemory(ctxt, NULL);
4463
0
  return(NULL);
4464
0
    }
4465
0
    ctxt->instate = XML_PARSER_PUBLIC_LITERAL;
4466
0
    cur = CUR;
4467
0
    while ((IS_PUBIDCHAR_CH(cur)) && (cur != stop)) { /* checked */
4468
0
  if (len + 1 >= size) {
4469
0
      xmlChar *tmp;
4470
4471
0
      size *= 2;
4472
0
      tmp = (xmlChar *) xmlRealloc(buf, size);
4473
0
      if (tmp == NULL) {
4474
0
    xmlErrMemory(ctxt, NULL);
4475
0
    xmlFree(buf);
4476
0
    return(NULL);
4477
0
      }
4478
0
      buf = tmp;
4479
0
  }
4480
0
  buf[len++] = cur;
4481
0
        if (len > maxLength) {
4482
0
            xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Public ID");
4483
0
            xmlFree(buf);
4484
0
            return(NULL);
4485
0
        }
4486
0
  NEXT;
4487
0
  cur = CUR;
4488
0
    }
4489
0
    buf[len] = 0;
4490
0
    if (ctxt->instate == XML_PARSER_EOF) {
4491
0
        xmlFree(buf);
4492
0
        return(NULL);
4493
0
    }
4494
0
    if (cur != stop) {
4495
0
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
4496
0
    } else {
4497
0
  NEXTL(1);
4498
0
    }
4499
0
    ctxt->instate = oldstate;
4500
0
    return(buf);
4501
0
}
4502
4503
static void xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int partial);
4504
4505
/*
4506
 * used for the test in the inner loop of the char data testing
4507
 */
4508
static const unsigned char test_char_data[256] = {
4509
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4510
    0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9, CR/LF separated */
4511
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4512
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4513
    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x00, 0x27, /* & */
4514
    0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
4515
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
4516
    0x38, 0x39, 0x3A, 0x3B, 0x00, 0x3D, 0x3E, 0x3F, /* < */
4517
    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
4518
    0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
4519
    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
4520
    0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x00, 0x5E, 0x5F, /* ] */
4521
    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
4522
    0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
4523
    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
4524
    0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
4525
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* non-ascii */
4526
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4527
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4528
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4529
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4530
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4531
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4532
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4533
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4534
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4535
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4536
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4537
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4538
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4539
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4540
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4541
};
4542
4543
/**
4544
 * xmlParseCharDataInternal:
4545
 * @ctxt:  an XML parser context
4546
 * @partial:  buffer may contain partial UTF-8 sequences
4547
 *
4548
 * Parse character data. Always makes progress if the first char isn't
4549
 * '<' or '&'.
4550
 *
4551
 * The right angle bracket (>) may be represented using the string "&gt;",
4552
 * and must, for compatibility, be escaped using "&gt;" or a character
4553
 * reference when it appears in the string "]]>" in content, when that
4554
 * string is not marking the end of a CDATA section.
4555
 *
4556
 * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
4557
 */
4558
static void
4559
176
xmlParseCharDataInternal(xmlParserCtxtPtr ctxt, int partial) {
4560
176
    const xmlChar *in;
4561
176
    int nbchar = 0;
4562
176
    int line = ctxt->input->line;
4563
176
    int col = ctxt->input->col;
4564
176
    int ccol;
4565
4566
176
    GROW;
4567
    /*
4568
     * Accelerated common case where input don't need to be
4569
     * modified before passing it to the handler.
4570
     */
4571
176
    in = ctxt->input->cur;
4572
176
    do {
4573
198
get_more_space:
4574
330
        while (*in == 0x20) { in++; ctxt->input->col++; }
4575
198
        if (*in == 0xA) {
4576
22
            do {
4577
22
                ctxt->input->line++; ctxt->input->col = 1;
4578
22
                in++;
4579
22
            } while (*in == 0xA);
4580
22
            goto get_more_space;
4581
22
        }
4582
176
        if (*in == '<') {
4583
66
            nbchar = in - ctxt->input->cur;
4584
66
            if (nbchar > 0) {
4585
66
                const xmlChar *tmp = ctxt->input->cur;
4586
66
                ctxt->input->cur = in;
4587
4588
66
                if ((ctxt->sax != NULL) &&
4589
66
                    (ctxt->disableSAX == 0) &&
4590
66
                    (ctxt->sax->ignorableWhitespace !=
4591
66
                     ctxt->sax->characters)) {
4592
66
                    if (areBlanks(ctxt, tmp, nbchar, 1)) {
4593
0
                        if (ctxt->sax->ignorableWhitespace != NULL)
4594
0
                            ctxt->sax->ignorableWhitespace(ctxt->userData,
4595
0
                                                   tmp, nbchar);
4596
66
                    } else {
4597
66
                        if (ctxt->sax->characters != NULL)
4598
66
                            ctxt->sax->characters(ctxt->userData,
4599
66
                                                  tmp, nbchar);
4600
66
                        if (*ctxt->space == -1)
4601
0
                            *ctxt->space = -2;
4602
66
                    }
4603
66
                } else if ((ctxt->sax != NULL) &&
4604
0
                           (ctxt->disableSAX == 0) &&
4605
0
                           (ctxt->sax->characters != NULL)) {
4606
0
                    ctxt->sax->characters(ctxt->userData,
4607
0
                                          tmp, nbchar);
4608
0
                }
4609
66
            }
4610
66
            return;
4611
66
        }
4612
4613
110
get_more:
4614
110
        ccol = ctxt->input->col;
4615
1.81k
        while (test_char_data[*in]) {
4616
1.70k
            in++;
4617
1.70k
            ccol++;
4618
1.70k
        }
4619
110
        ctxt->input->col = ccol;
4620
110
        if (*in == 0xA) {
4621
0
            do {
4622
0
                ctxt->input->line++; ctxt->input->col = 1;
4623
0
                in++;
4624
0
            } while (*in == 0xA);
4625
0
            goto get_more;
4626
0
        }
4627
110
        if (*in == ']') {
4628
0
            if ((in[1] == ']') && (in[2] == '>')) {
4629
0
                xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
4630
0
                if (ctxt->instate != XML_PARSER_EOF)
4631
0
                    ctxt->input->cur = in + 1;
4632
0
                return;
4633
0
            }
4634
0
            in++;
4635
0
            ctxt->input->col++;
4636
0
            goto get_more;
4637
0
        }
4638
110
        nbchar = in - ctxt->input->cur;
4639
110
        if (nbchar > 0) {
4640
110
            if ((ctxt->sax != NULL) &&
4641
110
                (ctxt->disableSAX == 0) &&
4642
110
                (ctxt->sax->ignorableWhitespace !=
4643
110
                 ctxt->sax->characters) &&
4644
110
                (IS_BLANK_CH(*ctxt->input->cur))) {
4645
22
                const xmlChar *tmp = ctxt->input->cur;
4646
22
                ctxt->input->cur = in;
4647
4648
22
                if (areBlanks(ctxt, tmp, nbchar, 0)) {
4649
0
                    if (ctxt->sax->ignorableWhitespace != NULL)
4650
0
                        ctxt->sax->ignorableWhitespace(ctxt->userData,
4651
0
                                                       tmp, nbchar);
4652
22
                } else {
4653
22
                    if (ctxt->sax->characters != NULL)
4654
22
                        ctxt->sax->characters(ctxt->userData,
4655
22
                                              tmp, nbchar);
4656
22
                    if (*ctxt->space == -1)
4657
11
                        *ctxt->space = -2;
4658
22
                }
4659
22
                line = ctxt->input->line;
4660
22
                col = ctxt->input->col;
4661
88
            } else if ((ctxt->sax != NULL) &&
4662
88
                       (ctxt->disableSAX == 0)) {
4663
88
                if (ctxt->sax->characters != NULL)
4664
88
                    ctxt->sax->characters(ctxt->userData,
4665
88
                                          ctxt->input->cur, nbchar);
4666
88
                line = ctxt->input->line;
4667
88
                col = ctxt->input->col;
4668
88
            }
4669
110
            if (ctxt->instate == XML_PARSER_EOF)
4670
0
                return;
4671
110
        }
4672
110
        ctxt->input->cur = in;
4673
110
        if (*in == 0xD) {
4674
0
            in++;
4675
0
            if (*in == 0xA) {
4676
0
                ctxt->input->cur = in;
4677
0
                in++;
4678
0
                ctxt->input->line++; ctxt->input->col = 1;
4679
0
                continue; /* while */
4680
0
            }
4681
0
            in--;
4682
0
        }
4683
110
        if (*in == '<') {
4684
110
            return;
4685
110
        }
4686
0
        if (*in == '&') {
4687
0
            return;
4688
0
        }
4689
0
        SHRINK;
4690
0
        GROW;
4691
0
        if (ctxt->instate == XML_PARSER_EOF)
4692
0
            return;
4693
0
        in = ctxt->input->cur;
4694
0
    } while (((*in >= 0x20) && (*in <= 0x7F)) ||
4695
0
             (*in == 0x09) || (*in == 0x0a));
4696
0
    ctxt->input->line = line;
4697
0
    ctxt->input->col = col;
4698
0
    xmlParseCharDataComplex(ctxt, partial);
4699
0
}
4700
4701
/**
4702
 * xmlParseCharDataComplex:
4703
 * @ctxt:  an XML parser context
4704
 * @cdata:  int indicating whether we are within a CDATA section
4705
 *
4706
 * Always makes progress if the first char isn't '<' or '&'.
4707
 *
4708
 * parse a CharData section.this is the fallback function
4709
 * of xmlParseCharData() when the parsing requires handling
4710
 * of non-ASCII characters.
4711
 */
4712
static void
4713
0
xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int partial) {
4714
0
    xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE + 5];
4715
0
    int nbchar = 0;
4716
0
    int cur, l;
4717
4718
0
    cur = CUR_CHAR(l);
4719
0
    while ((cur != '<') && /* checked */
4720
0
           (cur != '&') &&
4721
0
     (IS_CHAR(cur))) {
4722
0
  if ((cur == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
4723
0
      xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
4724
0
  }
4725
0
  COPY_BUF(buf, nbchar, cur);
4726
  /* move current position before possible calling of ctxt->sax->characters */
4727
0
  NEXTL(l);
4728
0
  if (nbchar >= XML_PARSER_BIG_BUFFER_SIZE) {
4729
0
      buf[nbchar] = 0;
4730
4731
      /*
4732
       * OK the segment is to be consumed as chars.
4733
       */
4734
0
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
4735
0
    if (areBlanks(ctxt, buf, nbchar, 0)) {
4736
0
        if (ctxt->sax->ignorableWhitespace != NULL)
4737
0
      ctxt->sax->ignorableWhitespace(ctxt->userData,
4738
0
                                     buf, nbchar);
4739
0
    } else {
4740
0
        if (ctxt->sax->characters != NULL)
4741
0
      ctxt->sax->characters(ctxt->userData, buf, nbchar);
4742
0
        if ((ctxt->sax->characters !=
4743
0
             ctxt->sax->ignorableWhitespace) &&
4744
0
      (*ctxt->space == -1))
4745
0
      *ctxt->space = -2;
4746
0
    }
4747
0
      }
4748
0
      nbchar = 0;
4749
            /* something really bad happened in the SAX callback */
4750
0
            if (ctxt->instate != XML_PARSER_CONTENT)
4751
0
                return;
4752
0
            SHRINK;
4753
0
  }
4754
0
  cur = CUR_CHAR(l);
4755
0
    }
4756
0
    if (ctxt->instate == XML_PARSER_EOF)
4757
0
        return;
4758
0
    if (nbchar != 0) {
4759
0
        buf[nbchar] = 0;
4760
  /*
4761
   * OK the segment is to be consumed as chars.
4762
   */
4763
0
  if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
4764
0
      if (areBlanks(ctxt, buf, nbchar, 0)) {
4765
0
    if (ctxt->sax->ignorableWhitespace != NULL)
4766
0
        ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
4767
0
      } else {
4768
0
    if (ctxt->sax->characters != NULL)
4769
0
        ctxt->sax->characters(ctxt->userData, buf, nbchar);
4770
0
    if ((ctxt->sax->characters != ctxt->sax->ignorableWhitespace) &&
4771
0
        (*ctxt->space == -1))
4772
0
        *ctxt->space = -2;
4773
0
      }
4774
0
  }
4775
0
    }
4776
    /*
4777
     * cur == 0 can mean
4778
     *
4779
     * - XML_PARSER_EOF or memory error. This is checked above.
4780
     * - An actual 0 character.
4781
     * - End of buffer.
4782
     * - An incomplete UTF-8 sequence. This is allowed if partial is set.
4783
     */
4784
0
    if (ctxt->input->cur < ctxt->input->end) {
4785
0
        if ((cur == 0) && (CUR != 0)) {
4786
0
            if (partial == 0) {
4787
0
                xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4788
0
                        "Incomplete UTF-8 sequence starting with %02X\n", CUR);
4789
0
                NEXTL(1);
4790
0
            }
4791
0
        } else if ((cur != '<') && (cur != '&')) {
4792
            /* Generate the error and skip the offending character */
4793
0
            xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4794
0
                              "PCDATA invalid Char value %d\n", cur);
4795
0
            NEXTL(l);
4796
0
        }
4797
0
    }
4798
0
}
4799
4800
/**
4801
 * xmlParseCharData:
4802
 * @ctxt:  an XML parser context
4803
 * @cdata:  unused
4804
 *
4805
 * DEPRECATED: Internal function, don't use.
4806
 */
4807
void
4808
0
xmlParseCharData(xmlParserCtxtPtr ctxt, ATTRIBUTE_UNUSED int cdata) {
4809
0
    xmlParseCharDataInternal(ctxt, 0);
4810
0
}
4811
4812
/**
4813
 * xmlParseExternalID:
4814
 * @ctxt:  an XML parser context
4815
 * @publicID:  a xmlChar** receiving PubidLiteral
4816
 * @strict: indicate whether we should restrict parsing to only
4817
 *          production [75], see NOTE below
4818
 *
4819
 * DEPRECATED: Internal function, don't use.
4820
 *
4821
 * Parse an External ID or a Public ID
4822
 *
4823
 * NOTE: Productions [75] and [83] interact badly since [75] can generate
4824
 *       'PUBLIC' S PubidLiteral S SystemLiteral
4825
 *
4826
 * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
4827
 *                   | 'PUBLIC' S PubidLiteral S SystemLiteral
4828
 *
4829
 * [83] PublicID ::= 'PUBLIC' S PubidLiteral
4830
 *
4831
 * Returns the function returns SystemLiteral and in the second
4832
 *                case publicID receives PubidLiteral, is strict is off
4833
 *                it is possible to return NULL and have publicID set.
4834
 */
4835
4836
xmlChar *
4837
0
xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
4838
0
    xmlChar *URI = NULL;
4839
4840
0
    *publicID = NULL;
4841
0
    if (CMP6(CUR_PTR, 'S', 'Y', 'S', 'T', 'E', 'M')) {
4842
0
        SKIP(6);
4843
0
  if (SKIP_BLANKS == 0) {
4844
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4845
0
                     "Space required after 'SYSTEM'\n");
4846
0
  }
4847
0
  URI = xmlParseSystemLiteral(ctxt);
4848
0
  if (URI == NULL) {
4849
0
      xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
4850
0
        }
4851
0
    } else if (CMP6(CUR_PTR, 'P', 'U', 'B', 'L', 'I', 'C')) {
4852
0
        SKIP(6);
4853
0
  if (SKIP_BLANKS == 0) {
4854
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4855
0
        "Space required after 'PUBLIC'\n");
4856
0
  }
4857
0
  *publicID = xmlParsePubidLiteral(ctxt);
4858
0
  if (*publicID == NULL) {
4859
0
      xmlFatalErr(ctxt, XML_ERR_PUBID_REQUIRED, NULL);
4860
0
  }
4861
0
  if (strict) {
4862
      /*
4863
       * We don't handle [83] so "S SystemLiteral" is required.
4864
       */
4865
0
      if (SKIP_BLANKS == 0) {
4866
0
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4867
0
      "Space required after the Public Identifier\n");
4868
0
      }
4869
0
  } else {
4870
      /*
4871
       * We handle [83] so we return immediately, if
4872
       * "S SystemLiteral" is not detected. We skip blanks if no
4873
             * system literal was found, but this is harmless since we must
4874
             * be at the end of a NotationDecl.
4875
       */
4876
0
      if (SKIP_BLANKS == 0) return(NULL);
4877
0
      if ((CUR != '\'') && (CUR != '"')) return(NULL);
4878
0
  }
4879
0
  URI = xmlParseSystemLiteral(ctxt);
4880
0
  if (URI == NULL) {
4881
0
      xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
4882
0
        }
4883
0
    }
4884
0
    return(URI);
4885
0
}
4886
4887
/**
4888
 * xmlParseCommentComplex:
4889
 * @ctxt:  an XML parser context
4890
 * @buf:  the already parsed part of the buffer
4891
 * @len:  number of bytes in the buffer
4892
 * @size:  allocated size of the buffer
4893
 *
4894
 * Skip an XML (SGML) comment <!-- .... -->
4895
 *  The spec says that "For compatibility, the string "--" (double-hyphen)
4896
 *  must not occur within comments. "
4897
 * This is the slow routine in case the accelerator for ascii didn't work
4898
 *
4899
 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
4900
 */
4901
static void
4902
xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
4903
0
                       size_t len, size_t size) {
4904
0
    int q, ql;
4905
0
    int r, rl;
4906
0
    int cur, l;
4907
0
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4908
0
                       XML_MAX_HUGE_LENGTH :
4909
0
                       XML_MAX_TEXT_LENGTH;
4910
0
    int inputid;
4911
4912
0
    inputid = ctxt->input->id;
4913
4914
0
    if (buf == NULL) {
4915
0
        len = 0;
4916
0
  size = XML_PARSER_BUFFER_SIZE;
4917
0
  buf = (xmlChar *) xmlMallocAtomic(size);
4918
0
  if (buf == NULL) {
4919
0
      xmlErrMemory(ctxt, NULL);
4920
0
      return;
4921
0
  }
4922
0
    }
4923
0
    q = CUR_CHAR(ql);
4924
0
    if (q == 0)
4925
0
        goto not_terminated;
4926
0
    if (!IS_CHAR(q)) {
4927
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4928
0
                          "xmlParseComment: invalid xmlChar value %d\n",
4929
0
                    q);
4930
0
  xmlFree (buf);
4931
0
  return;
4932
0
    }
4933
0
    NEXTL(ql);
4934
0
    r = CUR_CHAR(rl);
4935
0
    if (r == 0)
4936
0
        goto not_terminated;
4937
0
    if (!IS_CHAR(r)) {
4938
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4939
0
                          "xmlParseComment: invalid xmlChar value %d\n",
4940
0
                    r);
4941
0
  xmlFree (buf);
4942
0
  return;
4943
0
    }
4944
0
    NEXTL(rl);
4945
0
    cur = CUR_CHAR(l);
4946
0
    if (cur == 0)
4947
0
        goto not_terminated;
4948
0
    while (IS_CHAR(cur) && /* checked */
4949
0
           ((cur != '>') ||
4950
0
      (r != '-') || (q != '-'))) {
4951
0
  if ((r == '-') && (q == '-')) {
4952
0
      xmlFatalErr(ctxt, XML_ERR_HYPHEN_IN_COMMENT, NULL);
4953
0
  }
4954
0
  if (len + 5 >= size) {
4955
0
      xmlChar *new_buf;
4956
0
            size_t new_size;
4957
4958
0
      new_size = size * 2;
4959
0
      new_buf = (xmlChar *) xmlRealloc(buf, new_size);
4960
0
      if (new_buf == NULL) {
4961
0
    xmlFree (buf);
4962
0
    xmlErrMemory(ctxt, NULL);
4963
0
    return;
4964
0
      }
4965
0
      buf = new_buf;
4966
0
            size = new_size;
4967
0
  }
4968
0
  COPY_BUF(buf, len, q);
4969
0
        if (len > maxLength) {
4970
0
            xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4971
0
                         "Comment too big found", NULL);
4972
0
            xmlFree (buf);
4973
0
            return;
4974
0
        }
4975
4976
0
  q = r;
4977
0
  ql = rl;
4978
0
  r = cur;
4979
0
  rl = l;
4980
4981
0
  NEXTL(l);
4982
0
  cur = CUR_CHAR(l);
4983
4984
0
    }
4985
0
    buf[len] = 0;
4986
0
    if (ctxt->instate == XML_PARSER_EOF) {
4987
0
        xmlFree(buf);
4988
0
        return;
4989
0
    }
4990
0
    if (cur == 0) {
4991
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4992
0
                       "Comment not terminated \n<!--%.50s\n", buf);
4993
0
    } else if (!IS_CHAR(cur)) {
4994
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4995
0
                          "xmlParseComment: invalid xmlChar value %d\n",
4996
0
                    cur);
4997
0
    } else {
4998
0
  if (inputid != ctxt->input->id) {
4999
0
      xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5000
0
               "Comment doesn't start and stop in the same"
5001
0
                           " entity\n");
5002
0
  }
5003
0
        NEXT;
5004
0
  if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
5005
0
      (!ctxt->disableSAX))
5006
0
      ctxt->sax->comment(ctxt->userData, buf);
5007
0
    }
5008
0
    xmlFree(buf);
5009
0
    return;
5010
0
not_terminated:
5011
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
5012
0
       "Comment not terminated\n", NULL);
5013
0
    xmlFree(buf);
5014
0
    return;
5015
0
}
5016
5017
/**
5018
 * xmlParseComment:
5019
 * @ctxt:  an XML parser context
5020
 *
5021
 * DEPRECATED: Internal function, don't use.
5022
 *
5023
 * Parse an XML (SGML) comment. Always consumes '<!'.
5024
 *
5025
 *  The spec says that "For compatibility, the string "--" (double-hyphen)
5026
 *  must not occur within comments. "
5027
 *
5028
 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
5029
 */
5030
void
5031
0
xmlParseComment(xmlParserCtxtPtr ctxt) {
5032
0
    xmlChar *buf = NULL;
5033
0
    size_t size = XML_PARSER_BUFFER_SIZE;
5034
0
    size_t len = 0;
5035
0
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
5036
0
                       XML_MAX_HUGE_LENGTH :
5037
0
                       XML_MAX_TEXT_LENGTH;
5038
0
    xmlParserInputState state;
5039
0
    const xmlChar *in;
5040
0
    size_t nbchar = 0;
5041
0
    int ccol;
5042
0
    int inputid;
5043
5044
    /*
5045
     * Check that there is a comment right here.
5046
     */
5047
0
    if ((RAW != '<') || (NXT(1) != '!'))
5048
0
        return;
5049
0
    SKIP(2);
5050
0
    if ((RAW != '-') || (NXT(1) != '-'))
5051
0
        return;
5052
0
    state = ctxt->instate;
5053
0
    ctxt->instate = XML_PARSER_COMMENT;
5054
0
    inputid = ctxt->input->id;
5055
0
    SKIP(2);
5056
0
    GROW;
5057
5058
    /*
5059
     * Accelerated common case where input don't need to be
5060
     * modified before passing it to the handler.
5061
     */
5062
0
    in = ctxt->input->cur;
5063
0
    do {
5064
0
  if (*in == 0xA) {
5065
0
      do {
5066
0
    ctxt->input->line++; ctxt->input->col = 1;
5067
0
    in++;
5068
0
      } while (*in == 0xA);
5069
0
  }
5070
0
get_more:
5071
0
        ccol = ctxt->input->col;
5072
0
  while (((*in > '-') && (*in <= 0x7F)) ||
5073
0
         ((*in >= 0x20) && (*in < '-')) ||
5074
0
         (*in == 0x09)) {
5075
0
        in++;
5076
0
        ccol++;
5077
0
  }
5078
0
  ctxt->input->col = ccol;
5079
0
  if (*in == 0xA) {
5080
0
      do {
5081
0
    ctxt->input->line++; ctxt->input->col = 1;
5082
0
    in++;
5083
0
      } while (*in == 0xA);
5084
0
      goto get_more;
5085
0
  }
5086
0
  nbchar = in - ctxt->input->cur;
5087
  /*
5088
   * save current set of data
5089
   */
5090
0
  if (nbchar > 0) {
5091
0
            if (buf == NULL) {
5092
0
                if ((*in == '-') && (in[1] == '-'))
5093
0
                    size = nbchar + 1;
5094
0
                else
5095
0
                    size = XML_PARSER_BUFFER_SIZE + nbchar;
5096
0
                buf = (xmlChar *) xmlMallocAtomic(size);
5097
0
                if (buf == NULL) {
5098
0
                    xmlErrMemory(ctxt, NULL);
5099
0
                    ctxt->instate = state;
5100
0
                    return;
5101
0
                }
5102
0
                len = 0;
5103
0
            } else if (len + nbchar + 1 >= size) {
5104
0
                xmlChar *new_buf;
5105
0
                size  += len + nbchar + XML_PARSER_BUFFER_SIZE;
5106
0
                new_buf = (xmlChar *) xmlRealloc(buf, size);
5107
0
                if (new_buf == NULL) {
5108
0
                    xmlFree (buf);
5109
0
                    xmlErrMemory(ctxt, NULL);
5110
0
                    ctxt->instate = state;
5111
0
                    return;
5112
0
                }
5113
0
                buf = new_buf;
5114
0
            }
5115
0
            memcpy(&buf[len], ctxt->input->cur, nbchar);
5116
0
            len += nbchar;
5117
0
            buf[len] = 0;
5118
0
  }
5119
0
        if (len > maxLength) {
5120
0
            xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
5121
0
                         "Comment too big found", NULL);
5122
0
            xmlFree (buf);
5123
0
            return;
5124
0
        }
5125
0
  ctxt->input->cur = in;
5126
0
  if (*in == 0xA) {
5127
0
      in++;
5128
0
      ctxt->input->line++; ctxt->input->col = 1;
5129
0
  }
5130
0
  if (*in == 0xD) {
5131
0
      in++;
5132
0
      if (*in == 0xA) {
5133
0
    ctxt->input->cur = in;
5134
0
    in++;
5135
0
    ctxt->input->line++; ctxt->input->col = 1;
5136
0
    goto get_more;
5137
0
      }
5138
0
      in--;
5139
0
  }
5140
0
  SHRINK;
5141
0
  GROW;
5142
0
        if (ctxt->instate == XML_PARSER_EOF) {
5143
0
            xmlFree(buf);
5144
0
            return;
5145
0
        }
5146
0
  in = ctxt->input->cur;
5147
0
  if (*in == '-') {
5148
0
      if (in[1] == '-') {
5149
0
          if (in[2] == '>') {
5150
0
        if (ctxt->input->id != inputid) {
5151
0
      xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5152
0
                     "comment doesn't start and stop in the"
5153
0
                                       " same entity\n");
5154
0
        }
5155
0
        SKIP(3);
5156
0
        if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
5157
0
            (!ctxt->disableSAX)) {
5158
0
      if (buf != NULL)
5159
0
          ctxt->sax->comment(ctxt->userData, buf);
5160
0
      else
5161
0
          ctxt->sax->comment(ctxt->userData, BAD_CAST "");
5162
0
        }
5163
0
        if (buf != NULL)
5164
0
            xmlFree(buf);
5165
0
        if (ctxt->instate != XML_PARSER_EOF)
5166
0
      ctxt->instate = state;
5167
0
        return;
5168
0
    }
5169
0
    if (buf != NULL) {
5170
0
        xmlFatalErrMsgStr(ctxt, XML_ERR_HYPHEN_IN_COMMENT,
5171
0
                          "Double hyphen within comment: "
5172
0
                                      "<!--%.50s\n",
5173
0
              buf);
5174
0
    } else
5175
0
        xmlFatalErrMsgStr(ctxt, XML_ERR_HYPHEN_IN_COMMENT,
5176
0
                          "Double hyphen within comment\n", NULL);
5177
0
                if (ctxt->instate == XML_PARSER_EOF) {
5178
0
                    xmlFree(buf);
5179
0
                    return;
5180
0
                }
5181
0
    in++;
5182
0
    ctxt->input->col++;
5183
0
      }
5184
0
      in++;
5185
0
      ctxt->input->col++;
5186
0
      goto get_more;
5187
0
  }
5188
0
    } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09) || (*in == 0x0a));
5189
0
    xmlParseCommentComplex(ctxt, buf, len, size);
5190
0
    ctxt->instate = state;
5191
0
    return;
5192
0
}
5193
5194
5195
/**
5196
 * xmlParsePITarget:
5197
 * @ctxt:  an XML parser context
5198
 *
5199
 * DEPRECATED: Internal function, don't use.
5200
 *
5201
 * parse the name of a PI
5202
 *
5203
 * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
5204
 *
5205
 * Returns the PITarget name or NULL
5206
 */
5207
5208
const xmlChar *
5209
0
xmlParsePITarget(xmlParserCtxtPtr ctxt) {
5210
0
    const xmlChar *name;
5211
5212
0
    name = xmlParseName(ctxt);
5213
0
    if ((name != NULL) &&
5214
0
        ((name[0] == 'x') || (name[0] == 'X')) &&
5215
0
        ((name[1] == 'm') || (name[1] == 'M')) &&
5216
0
        ((name[2] == 'l') || (name[2] == 'L'))) {
5217
0
  int i;
5218
0
  if ((name[0] == 'x') && (name[1] == 'm') &&
5219
0
      (name[2] == 'l') && (name[3] == 0)) {
5220
0
      xmlFatalErrMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
5221
0
     "XML declaration allowed only at the start of the document\n");
5222
0
      return(name);
5223
0
  } else if (name[3] == 0) {
5224
0
      xmlFatalErr(ctxt, XML_ERR_RESERVED_XML_NAME, NULL);
5225
0
      return(name);
5226
0
  }
5227
0
  for (i = 0;;i++) {
5228
0
      if (xmlW3CPIs[i] == NULL) break;
5229
0
      if (xmlStrEqual(name, (const xmlChar *)xmlW3CPIs[i]))
5230
0
          return(name);
5231
0
  }
5232
0
  xmlWarningMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
5233
0
          "xmlParsePITarget: invalid name prefix 'xml'\n",
5234
0
          NULL, NULL);
5235
0
    }
5236
0
    if ((name != NULL) && (xmlStrchr(name, ':') != NULL)) {
5237
0
  xmlNsErr(ctxt, XML_NS_ERR_COLON,
5238
0
     "colons are forbidden from PI names '%s'\n", name, NULL, NULL);
5239
0
    }
5240
0
    return(name);
5241
0
}
5242
5243
#ifdef LIBXML_CATALOG_ENABLED
5244
/**
5245
 * xmlParseCatalogPI:
5246
 * @ctxt:  an XML parser context
5247
 * @catalog:  the PI value string
5248
 *
5249
 * parse an XML Catalog Processing Instruction.
5250
 *
5251
 * <?oasis-xml-catalog catalog="http://example.com/catalog.xml"?>
5252
 *
5253
 * Occurs only if allowed by the user and if happening in the Misc
5254
 * part of the document before any doctype information
5255
 * This will add the given catalog to the parsing context in order
5256
 * to be used if there is a resolution need further down in the document
5257
 */
5258
5259
static void
5260
0
xmlParseCatalogPI(xmlParserCtxtPtr ctxt, const xmlChar *catalog) {
5261
0
    xmlChar *URL = NULL;
5262
0
    const xmlChar *tmp, *base;
5263
0
    xmlChar marker;
5264
5265
0
    tmp = catalog;
5266
0
    while (IS_BLANK_CH(*tmp)) tmp++;
5267
0
    if (xmlStrncmp(tmp, BAD_CAST"catalog", 7))
5268
0
  goto error;
5269
0
    tmp += 7;
5270
0
    while (IS_BLANK_CH(*tmp)) tmp++;
5271
0
    if (*tmp != '=') {
5272
0
  return;
5273
0
    }
5274
0
    tmp++;
5275
0
    while (IS_BLANK_CH(*tmp)) tmp++;
5276
0
    marker = *tmp;
5277
0
    if ((marker != '\'') && (marker != '"'))
5278
0
  goto error;
5279
0
    tmp++;
5280
0
    base = tmp;
5281
0
    while ((*tmp != 0) && (*tmp != marker)) tmp++;
5282
0
    if (*tmp == 0)
5283
0
  goto error;
5284
0
    URL = xmlStrndup(base, tmp - base);
5285
0
    tmp++;
5286
0
    while (IS_BLANK_CH(*tmp)) tmp++;
5287
0
    if (*tmp != 0)
5288
0
  goto error;
5289
5290
0
    if (URL != NULL) {
5291
0
  ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
5292
0
  xmlFree(URL);
5293
0
    }
5294
0
    return;
5295
5296
0
error:
5297
0
    xmlWarningMsg(ctxt, XML_WAR_CATALOG_PI,
5298
0
            "Catalog PI syntax error: %s\n",
5299
0
      catalog, NULL);
5300
0
    if (URL != NULL)
5301
0
  xmlFree(URL);
5302
0
}
5303
#endif
5304
5305
/**
5306
 * xmlParsePI:
5307
 * @ctxt:  an XML parser context
5308
 *
5309
 * DEPRECATED: Internal function, don't use.
5310
 *
5311
 * parse an XML Processing Instruction.
5312
 *
5313
 * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
5314
 *
5315
 * The processing is transferred to SAX once parsed.
5316
 */
5317
5318
void
5319
0
xmlParsePI(xmlParserCtxtPtr ctxt) {
5320
0
    xmlChar *buf = NULL;
5321
0
    size_t len = 0;
5322
0
    size_t size = XML_PARSER_BUFFER_SIZE;
5323
0
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
5324
0
                       XML_MAX_HUGE_LENGTH :
5325
0
                       XML_MAX_TEXT_LENGTH;
5326
0
    int cur, l;
5327
0
    const xmlChar *target;
5328
0
    xmlParserInputState state;
5329
5330
0
    if ((RAW == '<') && (NXT(1) == '?')) {
5331
0
  int inputid = ctxt->input->id;
5332
0
  state = ctxt->instate;
5333
0
        ctxt->instate = XML_PARSER_PI;
5334
  /*
5335
   * this is a Processing Instruction.
5336
   */
5337
0
  SKIP(2);
5338
5339
  /*
5340
   * Parse the target name and check for special support like
5341
   * namespace.
5342
   */
5343
0
        target = xmlParsePITarget(ctxt);
5344
0
  if (target != NULL) {
5345
0
      if ((RAW == '?') && (NXT(1) == '>')) {
5346
0
    if (inputid != ctxt->input->id) {
5347
0
        xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5348
0
                             "PI declaration doesn't start and stop in"
5349
0
                                   " the same entity\n");
5350
0
    }
5351
0
    SKIP(2);
5352
5353
    /*
5354
     * SAX: PI detected.
5355
     */
5356
0
    if ((ctxt->sax) && (!ctxt->disableSAX) &&
5357
0
        (ctxt->sax->processingInstruction != NULL))
5358
0
        ctxt->sax->processingInstruction(ctxt->userData,
5359
0
                                         target, NULL);
5360
0
    if (ctxt->instate != XML_PARSER_EOF)
5361
0
        ctxt->instate = state;
5362
0
    return;
5363
0
      }
5364
0
      buf = (xmlChar *) xmlMallocAtomic(size);
5365
0
      if (buf == NULL) {
5366
0
    xmlErrMemory(ctxt, NULL);
5367
0
    ctxt->instate = state;
5368
0
    return;
5369
0
      }
5370
0
      if (SKIP_BLANKS == 0) {
5371
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_SPACE_REQUIRED,
5372
0
        "ParsePI: PI %s space expected\n", target);
5373
0
      }
5374
0
      cur = CUR_CHAR(l);
5375
0
      while (IS_CHAR(cur) && /* checked */
5376
0
       ((cur != '?') || (NXT(1) != '>'))) {
5377
0
    if (len + 5 >= size) {
5378
0
        xmlChar *tmp;
5379
0
                    size_t new_size = size * 2;
5380
0
        tmp = (xmlChar *) xmlRealloc(buf, new_size);
5381
0
        if (tmp == NULL) {
5382
0
      xmlErrMemory(ctxt, NULL);
5383
0
      xmlFree(buf);
5384
0
      ctxt->instate = state;
5385
0
      return;
5386
0
        }
5387
0
        buf = tmp;
5388
0
                    size = new_size;
5389
0
    }
5390
0
    COPY_BUF(buf, len, cur);
5391
0
                if (len > maxLength) {
5392
0
                    xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
5393
0
                                      "PI %s too big found", target);
5394
0
                    xmlFree(buf);
5395
0
                    ctxt->instate = state;
5396
0
                    return;
5397
0
                }
5398
0
    NEXTL(l);
5399
0
    cur = CUR_CHAR(l);
5400
0
      }
5401
0
      buf[len] = 0;
5402
0
            if (ctxt->instate == XML_PARSER_EOF) {
5403
0
                xmlFree(buf);
5404
0
                return;
5405
0
            }
5406
0
      if (cur != '?') {
5407
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
5408
0
          "ParsePI: PI %s never end ...\n", target);
5409
0
      } else {
5410
0
    if (inputid != ctxt->input->id) {
5411
0
        xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5412
0
                             "PI declaration doesn't start and stop in"
5413
0
                                   " the same entity\n");
5414
0
    }
5415
0
    SKIP(2);
5416
5417
0
#ifdef LIBXML_CATALOG_ENABLED
5418
0
    if (((state == XML_PARSER_MISC) ||
5419
0
               (state == XML_PARSER_START)) &&
5420
0
        (xmlStrEqual(target, XML_CATALOG_PI))) {
5421
0
        xmlCatalogAllow allow = xmlCatalogGetDefaults();
5422
0
        if ((allow == XML_CATA_ALLOW_DOCUMENT) ||
5423
0
      (allow == XML_CATA_ALLOW_ALL))
5424
0
      xmlParseCatalogPI(ctxt, buf);
5425
0
    }
5426
0
#endif
5427
5428
5429
    /*
5430
     * SAX: PI detected.
5431
     */
5432
0
    if ((ctxt->sax) && (!ctxt->disableSAX) &&
5433
0
        (ctxt->sax->processingInstruction != NULL))
5434
0
        ctxt->sax->processingInstruction(ctxt->userData,
5435
0
                                         target, buf);
5436
0
      }
5437
0
      xmlFree(buf);
5438
0
  } else {
5439
0
      xmlFatalErr(ctxt, XML_ERR_PI_NOT_STARTED, NULL);
5440
0
  }
5441
0
  if (ctxt->instate != XML_PARSER_EOF)
5442
0
      ctxt->instate = state;
5443
0
    }
5444
0
}
5445
5446
/**
5447
 * xmlParseNotationDecl:
5448
 * @ctxt:  an XML parser context
5449
 *
5450
 * DEPRECATED: Internal function, don't use.
5451
 *
5452
 * Parse a notation declaration. Always consumes '<!'.
5453
 *
5454
 * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID |  PublicID) S? '>'
5455
 *
5456
 * Hence there is actually 3 choices:
5457
 *     'PUBLIC' S PubidLiteral
5458
 *     'PUBLIC' S PubidLiteral S SystemLiteral
5459
 * and 'SYSTEM' S SystemLiteral
5460
 *
5461
 * See the NOTE on xmlParseExternalID().
5462
 */
5463
5464
void
5465
0
xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
5466
0
    const xmlChar *name;
5467
0
    xmlChar *Pubid;
5468
0
    xmlChar *Systemid;
5469
5470
0
    if ((CUR != '<') || (NXT(1) != '!'))
5471
0
        return;
5472
0
    SKIP(2);
5473
5474
0
    if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
5475
0
  int inputid = ctxt->input->id;
5476
0
  SKIP(8);
5477
0
  if (SKIP_BLANKS == 0) {
5478
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5479
0
         "Space required after '<!NOTATION'\n");
5480
0
      return;
5481
0
  }
5482
5483
0
        name = xmlParseName(ctxt);
5484
0
  if (name == NULL) {
5485
0
      xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
5486
0
      return;
5487
0
  }
5488
0
  if (xmlStrchr(name, ':') != NULL) {
5489
0
      xmlNsErr(ctxt, XML_NS_ERR_COLON,
5490
0
         "colons are forbidden from notation names '%s'\n",
5491
0
         name, NULL, NULL);
5492
0
  }
5493
0
  if (SKIP_BLANKS == 0) {
5494
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5495
0
         "Space required after the NOTATION name'\n");
5496
0
      return;
5497
0
  }
5498
5499
  /*
5500
   * Parse the IDs.
5501
   */
5502
0
  Systemid = xmlParseExternalID(ctxt, &Pubid, 0);
5503
0
  SKIP_BLANKS;
5504
5505
0
  if (RAW == '>') {
5506
0
      if (inputid != ctxt->input->id) {
5507
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5508
0
                         "Notation declaration doesn't start and stop"
5509
0
                               " in the same entity\n");
5510
0
      }
5511
0
      NEXT;
5512
0
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
5513
0
    (ctxt->sax->notationDecl != NULL))
5514
0
    ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
5515
0
  } else {
5516
0
      xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
5517
0
  }
5518
0
  if (Systemid != NULL) xmlFree(Systemid);
5519
0
  if (Pubid != NULL) xmlFree(Pubid);
5520
0
    }
5521
0
}
5522
5523
/**
5524
 * xmlParseEntityDecl:
5525
 * @ctxt:  an XML parser context
5526
 *
5527
 * DEPRECATED: Internal function, don't use.
5528
 *
5529
 * Parse an entity declaration. Always consumes '<!'.
5530
 *
5531
 * [70] EntityDecl ::= GEDecl | PEDecl
5532
 *
5533
 * [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
5534
 *
5535
 * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
5536
 *
5537
 * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
5538
 *
5539
 * [74] PEDef ::= EntityValue | ExternalID
5540
 *
5541
 * [76] NDataDecl ::= S 'NDATA' S Name
5542
 *
5543
 * [ VC: Notation Declared ]
5544
 * The Name must match the declared name of a notation.
5545
 */
5546
5547
void
5548
0
xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
5549
0
    const xmlChar *name = NULL;
5550
0
    xmlChar *value = NULL;
5551
0
    xmlChar *URI = NULL, *literal = NULL;
5552
0
    const xmlChar *ndata = NULL;
5553
0
    int isParameter = 0;
5554
0
    xmlChar *orig = NULL;
5555
5556
0
    if ((CUR != '<') || (NXT(1) != '!'))
5557
0
        return;
5558
0
    SKIP(2);
5559
5560
    /* GROW; done in the caller */
5561
0
    if (CMP6(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'Y')) {
5562
0
  int inputid = ctxt->input->id;
5563
0
  SKIP(6);
5564
0
  if (SKIP_BLANKS == 0) {
5565
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5566
0
         "Space required after '<!ENTITY'\n");
5567
0
  }
5568
5569
0
  if (RAW == '%') {
5570
0
      NEXT;
5571
0
      if (SKIP_BLANKS == 0) {
5572
0
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5573
0
             "Space required after '%%'\n");
5574
0
      }
5575
0
      isParameter = 1;
5576
0
  }
5577
5578
0
        name = xmlParseName(ctxt);
5579
0
  if (name == NULL) {
5580
0
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
5581
0
                     "xmlParseEntityDecl: no name\n");
5582
0
            return;
5583
0
  }
5584
0
  if (xmlStrchr(name, ':') != NULL) {
5585
0
      xmlNsErr(ctxt, XML_NS_ERR_COLON,
5586
0
         "colons are forbidden from entities names '%s'\n",
5587
0
         name, NULL, NULL);
5588
0
  }
5589
0
  if (SKIP_BLANKS == 0) {
5590
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5591
0
         "Space required after the entity name\n");
5592
0
  }
5593
5594
0
  ctxt->instate = XML_PARSER_ENTITY_DECL;
5595
  /*
5596
   * handle the various case of definitions...
5597
   */
5598
0
  if (isParameter) {
5599
0
      if ((RAW == '"') || (RAW == '\'')) {
5600
0
          value = xmlParseEntityValue(ctxt, &orig);
5601
0
    if (value) {
5602
0
        if ((ctxt->sax != NULL) &&
5603
0
      (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5604
0
      ctxt->sax->entityDecl(ctxt->userData, name,
5605
0
                        XML_INTERNAL_PARAMETER_ENTITY,
5606
0
            NULL, NULL, value);
5607
0
    }
5608
0
      } else {
5609
0
          URI = xmlParseExternalID(ctxt, &literal, 1);
5610
0
    if ((URI == NULL) && (literal == NULL)) {
5611
0
        xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
5612
0
    }
5613
0
    if (URI) {
5614
0
        xmlURIPtr uri;
5615
5616
0
        uri = xmlParseURI((const char *) URI);
5617
0
        if (uri == NULL) {
5618
0
            xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
5619
0
             "Invalid URI: %s\n", URI);
5620
      /*
5621
       * This really ought to be a well formedness error
5622
       * but the XML Core WG decided otherwise c.f. issue
5623
       * E26 of the XML erratas.
5624
       */
5625
0
        } else {
5626
0
      if (uri->fragment != NULL) {
5627
          /*
5628
           * Okay this is foolish to block those but not
5629
           * invalid URIs.
5630
           */
5631
0
          xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
5632
0
      } else {
5633
0
          if ((ctxt->sax != NULL) &&
5634
0
        (!ctxt->disableSAX) &&
5635
0
        (ctxt->sax->entityDecl != NULL))
5636
0
        ctxt->sax->entityDecl(ctxt->userData, name,
5637
0
              XML_EXTERNAL_PARAMETER_ENTITY,
5638
0
              literal, URI, NULL);
5639
0
      }
5640
0
      xmlFreeURI(uri);
5641
0
        }
5642
0
    }
5643
0
      }
5644
0
  } else {
5645
0
      if ((RAW == '"') || (RAW == '\'')) {
5646
0
          value = xmlParseEntityValue(ctxt, &orig);
5647
0
    if ((ctxt->sax != NULL) &&
5648
0
        (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5649
0
        ctxt->sax->entityDecl(ctxt->userData, name,
5650
0
        XML_INTERNAL_GENERAL_ENTITY,
5651
0
        NULL, NULL, value);
5652
    /*
5653
     * For expat compatibility in SAX mode.
5654
     */
5655
0
    if ((ctxt->myDoc == NULL) ||
5656
0
        (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
5657
0
        if (ctxt->myDoc == NULL) {
5658
0
      ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
5659
0
      if (ctxt->myDoc == NULL) {
5660
0
          xmlErrMemory(ctxt, "New Doc failed");
5661
0
          goto done;
5662
0
      }
5663
0
      ctxt->myDoc->properties = XML_DOC_INTERNAL;
5664
0
        }
5665
0
        if (ctxt->myDoc->intSubset == NULL)
5666
0
      ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
5667
0
              BAD_CAST "fake", NULL, NULL);
5668
5669
0
        xmlSAX2EntityDecl(ctxt, name, XML_INTERNAL_GENERAL_ENTITY,
5670
0
                    NULL, NULL, value);
5671
0
    }
5672
0
      } else {
5673
0
          URI = xmlParseExternalID(ctxt, &literal, 1);
5674
0
    if ((URI == NULL) && (literal == NULL)) {
5675
0
        xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
5676
0
    }
5677
0
    if (URI) {
5678
0
        xmlURIPtr uri;
5679
5680
0
        uri = xmlParseURI((const char *)URI);
5681
0
        if (uri == NULL) {
5682
0
            xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
5683
0
             "Invalid URI: %s\n", URI);
5684
      /*
5685
       * This really ought to be a well formedness error
5686
       * but the XML Core WG decided otherwise c.f. issue
5687
       * E26 of the XML erratas.
5688
       */
5689
0
        } else {
5690
0
      if (uri->fragment != NULL) {
5691
          /*
5692
           * Okay this is foolish to block those but not
5693
           * invalid URIs.
5694
           */
5695
0
          xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
5696
0
      }
5697
0
      xmlFreeURI(uri);
5698
0
        }
5699
0
    }
5700
0
    if ((RAW != '>') && (SKIP_BLANKS == 0)) {
5701
0
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5702
0
           "Space required before 'NDATA'\n");
5703
0
    }
5704
0
    if (CMP5(CUR_PTR, 'N', 'D', 'A', 'T', 'A')) {
5705
0
        SKIP(5);
5706
0
        if (SKIP_BLANKS == 0) {
5707
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5708
0
               "Space required after 'NDATA'\n");
5709
0
        }
5710
0
        ndata = xmlParseName(ctxt);
5711
0
        if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
5712
0
            (ctxt->sax->unparsedEntityDecl != NULL))
5713
0
      ctxt->sax->unparsedEntityDecl(ctxt->userData, name,
5714
0
            literal, URI, ndata);
5715
0
    } else {
5716
0
        if ((ctxt->sax != NULL) &&
5717
0
            (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5718
0
      ctxt->sax->entityDecl(ctxt->userData, name,
5719
0
            XML_EXTERNAL_GENERAL_PARSED_ENTITY,
5720
0
            literal, URI, NULL);
5721
        /*
5722
         * For expat compatibility in SAX mode.
5723
         * assuming the entity replacement was asked for
5724
         */
5725
0
        if ((ctxt->replaceEntities != 0) &&
5726
0
      ((ctxt->myDoc == NULL) ||
5727
0
      (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE)))) {
5728
0
      if (ctxt->myDoc == NULL) {
5729
0
          ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
5730
0
          if (ctxt->myDoc == NULL) {
5731
0
              xmlErrMemory(ctxt, "New Doc failed");
5732
0
        goto done;
5733
0
          }
5734
0
          ctxt->myDoc->properties = XML_DOC_INTERNAL;
5735
0
      }
5736
5737
0
      if (ctxt->myDoc->intSubset == NULL)
5738
0
          ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
5739
0
            BAD_CAST "fake", NULL, NULL);
5740
0
      xmlSAX2EntityDecl(ctxt, name,
5741
0
                  XML_EXTERNAL_GENERAL_PARSED_ENTITY,
5742
0
                  literal, URI, NULL);
5743
0
        }
5744
0
    }
5745
0
      }
5746
0
  }
5747
0
  if (ctxt->instate == XML_PARSER_EOF)
5748
0
      goto done;
5749
0
  SKIP_BLANKS;
5750
0
  if (RAW != '>') {
5751
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
5752
0
              "xmlParseEntityDecl: entity %s not terminated\n", name);
5753
0
      xmlHaltParser(ctxt);
5754
0
  } else {
5755
0
      if (inputid != ctxt->input->id) {
5756
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5757
0
                         "Entity declaration doesn't start and stop in"
5758
0
                               " the same entity\n");
5759
0
      }
5760
0
      NEXT;
5761
0
  }
5762
0
  if (orig != NULL) {
5763
      /*
5764
       * Ugly mechanism to save the raw entity value.
5765
       */
5766
0
      xmlEntityPtr cur = NULL;
5767
5768
0
      if (isParameter) {
5769
0
          if ((ctxt->sax != NULL) &&
5770
0
        (ctxt->sax->getParameterEntity != NULL))
5771
0
        cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
5772
0
      } else {
5773
0
          if ((ctxt->sax != NULL) &&
5774
0
        (ctxt->sax->getEntity != NULL))
5775
0
        cur = ctxt->sax->getEntity(ctxt->userData, name);
5776
0
    if ((cur == NULL) && (ctxt->userData==ctxt)) {
5777
0
        cur = xmlSAX2GetEntity(ctxt, name);
5778
0
    }
5779
0
      }
5780
0
            if ((cur != NULL) && (cur->orig == NULL)) {
5781
0
    cur->orig = orig;
5782
0
                orig = NULL;
5783
0
      }
5784
0
  }
5785
5786
0
done:
5787
0
  if (value != NULL) xmlFree(value);
5788
0
  if (URI != NULL) xmlFree(URI);
5789
0
  if (literal != NULL) xmlFree(literal);
5790
0
        if (orig != NULL) xmlFree(orig);
5791
0
    }
5792
0
}
5793
5794
/**
5795
 * xmlParseDefaultDecl:
5796
 * @ctxt:  an XML parser context
5797
 * @value:  Receive a possible fixed default value for the attribute
5798
 *
5799
 * DEPRECATED: Internal function, don't use.
5800
 *
5801
 * Parse an attribute default declaration
5802
 *
5803
 * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
5804
 *
5805
 * [ VC: Required Attribute ]
5806
 * if the default declaration is the keyword #REQUIRED, then the
5807
 * attribute must be specified for all elements of the type in the
5808
 * attribute-list declaration.
5809
 *
5810
 * [ VC: Attribute Default Legal ]
5811
 * The declared default value must meet the lexical constraints of
5812
 * the declared attribute type c.f. xmlValidateAttributeDecl()
5813
 *
5814
 * [ VC: Fixed Attribute Default ]
5815
 * if an attribute has a default value declared with the #FIXED
5816
 * keyword, instances of that attribute must match the default value.
5817
 *
5818
 * [ WFC: No < in Attribute Values ]
5819
 * handled in xmlParseAttValue()
5820
 *
5821
 * returns: XML_ATTRIBUTE_NONE, XML_ATTRIBUTE_REQUIRED, XML_ATTRIBUTE_IMPLIED
5822
 *          or XML_ATTRIBUTE_FIXED.
5823
 */
5824
5825
int
5826
0
xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
5827
0
    int val;
5828
0
    xmlChar *ret;
5829
5830
0
    *value = NULL;
5831
0
    if (CMP9(CUR_PTR, '#', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D')) {
5832
0
  SKIP(9);
5833
0
  return(XML_ATTRIBUTE_REQUIRED);
5834
0
    }
5835
0
    if (CMP8(CUR_PTR, '#', 'I', 'M', 'P', 'L', 'I', 'E', 'D')) {
5836
0
  SKIP(8);
5837
0
  return(XML_ATTRIBUTE_IMPLIED);
5838
0
    }
5839
0
    val = XML_ATTRIBUTE_NONE;
5840
0
    if (CMP6(CUR_PTR, '#', 'F', 'I', 'X', 'E', 'D')) {
5841
0
  SKIP(6);
5842
0
  val = XML_ATTRIBUTE_FIXED;
5843
0
  if (SKIP_BLANKS == 0) {
5844
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5845
0
         "Space required after '#FIXED'\n");
5846
0
  }
5847
0
    }
5848
0
    ret = xmlParseAttValue(ctxt);
5849
0
    ctxt->instate = XML_PARSER_DTD;
5850
0
    if (ret == NULL) {
5851
0
  xmlFatalErrMsg(ctxt, (xmlParserErrors)ctxt->errNo,
5852
0
           "Attribute default value declaration error\n");
5853
0
    } else
5854
0
        *value = ret;
5855
0
    return(val);
5856
0
}
5857
5858
/**
5859
 * xmlParseNotationType:
5860
 * @ctxt:  an XML parser context
5861
 *
5862
 * DEPRECATED: Internal function, don't use.
5863
 *
5864
 * parse an Notation attribute type.
5865
 *
5866
 * Note: the leading 'NOTATION' S part has already being parsed...
5867
 *
5868
 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
5869
 *
5870
 * [ VC: Notation Attributes ]
5871
 * Values of this type must match one of the notation names included
5872
 * in the declaration; all notation names in the declaration must be declared.
5873
 *
5874
 * Returns: the notation attribute tree built while parsing
5875
 */
5876
5877
xmlEnumerationPtr
5878
0
xmlParseNotationType(xmlParserCtxtPtr ctxt) {
5879
0
    const xmlChar *name;
5880
0
    xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
5881
5882
0
    if (RAW != '(') {
5883
0
  xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
5884
0
  return(NULL);
5885
0
    }
5886
0
    do {
5887
0
        NEXT;
5888
0
  SKIP_BLANKS;
5889
0
        name = xmlParseName(ctxt);
5890
0
  if (name == NULL) {
5891
0
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
5892
0
         "Name expected in NOTATION declaration\n");
5893
0
            xmlFreeEnumeration(ret);
5894
0
      return(NULL);
5895
0
  }
5896
0
  tmp = ret;
5897
0
  while (tmp != NULL) {
5898
0
      if (xmlStrEqual(name, tmp->name)) {
5899
0
    xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
5900
0
    "standalone: attribute notation value token %s duplicated\n",
5901
0
         name, NULL);
5902
0
    if (!xmlDictOwns(ctxt->dict, name))
5903
0
        xmlFree((xmlChar *) name);
5904
0
    break;
5905
0
      }
5906
0
      tmp = tmp->next;
5907
0
  }
5908
0
  if (tmp == NULL) {
5909
0
      cur = xmlCreateEnumeration(name);
5910
0
      if (cur == NULL) {
5911
0
                xmlFreeEnumeration(ret);
5912
0
                return(NULL);
5913
0
            }
5914
0
      if (last == NULL) ret = last = cur;
5915
0
      else {
5916
0
    last->next = cur;
5917
0
    last = cur;
5918
0
      }
5919
0
  }
5920
0
  SKIP_BLANKS;
5921
0
    } while (RAW == '|');
5922
0
    if (RAW != ')') {
5923
0
  xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
5924
0
        xmlFreeEnumeration(ret);
5925
0
  return(NULL);
5926
0
    }
5927
0
    NEXT;
5928
0
    return(ret);
5929
0
}
5930
5931
/**
5932
 * xmlParseEnumerationType:
5933
 * @ctxt:  an XML parser context
5934
 *
5935
 * DEPRECATED: Internal function, don't use.
5936
 *
5937
 * parse an Enumeration attribute type.
5938
 *
5939
 * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
5940
 *
5941
 * [ VC: Enumeration ]
5942
 * Values of this type must match one of the Nmtoken tokens in
5943
 * the declaration
5944
 *
5945
 * Returns: the enumeration attribute tree built while parsing
5946
 */
5947
5948
xmlEnumerationPtr
5949
0
xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
5950
0
    xmlChar *name;
5951
0
    xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
5952
5953
0
    if (RAW != '(') {
5954
0
  xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_STARTED, NULL);
5955
0
  return(NULL);
5956
0
    }
5957
0
    do {
5958
0
        NEXT;
5959
0
  SKIP_BLANKS;
5960
0
        name = xmlParseNmtoken(ctxt);
5961
0
  if (name == NULL) {
5962
0
      xmlFatalErr(ctxt, XML_ERR_NMTOKEN_REQUIRED, NULL);
5963
0
      return(ret);
5964
0
  }
5965
0
  tmp = ret;
5966
0
  while (tmp != NULL) {
5967
0
      if (xmlStrEqual(name, tmp->name)) {
5968
0
    xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
5969
0
    "standalone: attribute enumeration value token %s duplicated\n",
5970
0
         name, NULL);
5971
0
    if (!xmlDictOwns(ctxt->dict, name))
5972
0
        xmlFree(name);
5973
0
    break;
5974
0
      }
5975
0
      tmp = tmp->next;
5976
0
  }
5977
0
  if (tmp == NULL) {
5978
0
      cur = xmlCreateEnumeration(name);
5979
0
      if (!xmlDictOwns(ctxt->dict, name))
5980
0
    xmlFree(name);
5981
0
      if (cur == NULL) {
5982
0
                xmlFreeEnumeration(ret);
5983
0
                return(NULL);
5984
0
            }
5985
0
      if (last == NULL) ret = last = cur;
5986
0
      else {
5987
0
    last->next = cur;
5988
0
    last = cur;
5989
0
      }
5990
0
  }
5991
0
  SKIP_BLANKS;
5992
0
    } while (RAW == '|');
5993
0
    if (RAW != ')') {
5994
0
  xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_FINISHED, NULL);
5995
0
  return(ret);
5996
0
    }
5997
0
    NEXT;
5998
0
    return(ret);
5999
0
}
6000
6001
/**
6002
 * xmlParseEnumeratedType:
6003
 * @ctxt:  an XML parser context
6004
 * @tree:  the enumeration tree built while parsing
6005
 *
6006
 * DEPRECATED: Internal function, don't use.
6007
 *
6008
 * parse an Enumerated attribute type.
6009
 *
6010
 * [57] EnumeratedType ::= NotationType | Enumeration
6011
 *
6012
 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
6013
 *
6014
 *
6015
 * Returns: XML_ATTRIBUTE_ENUMERATION or XML_ATTRIBUTE_NOTATION
6016
 */
6017
6018
int
6019
0
xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
6020
0
    if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
6021
0
  SKIP(8);
6022
0
  if (SKIP_BLANKS == 0) {
6023
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6024
0
         "Space required after 'NOTATION'\n");
6025
0
      return(0);
6026
0
  }
6027
0
  *tree = xmlParseNotationType(ctxt);
6028
0
  if (*tree == NULL) return(0);
6029
0
  return(XML_ATTRIBUTE_NOTATION);
6030
0
    }
6031
0
    *tree = xmlParseEnumerationType(ctxt);
6032
0
    if (*tree == NULL) return(0);
6033
0
    return(XML_ATTRIBUTE_ENUMERATION);
6034
0
}
6035
6036
/**
6037
 * xmlParseAttributeType:
6038
 * @ctxt:  an XML parser context
6039
 * @tree:  the enumeration tree built while parsing
6040
 *
6041
 * DEPRECATED: Internal function, don't use.
6042
 *
6043
 * parse the Attribute list def for an element
6044
 *
6045
 * [54] AttType ::= StringType | TokenizedType | EnumeratedType
6046
 *
6047
 * [55] StringType ::= 'CDATA'
6048
 *
6049
 * [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' |
6050
 *                        'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
6051
 *
6052
 * Validity constraints for attribute values syntax are checked in
6053
 * xmlValidateAttributeValue()
6054
 *
6055
 * [ VC: ID ]
6056
 * Values of type ID must match the Name production. A name must not
6057
 * appear more than once in an XML document as a value of this type;
6058
 * i.e., ID values must uniquely identify the elements which bear them.
6059
 *
6060
 * [ VC: One ID per Element Type ]
6061
 * No element type may have more than one ID attribute specified.
6062
 *
6063
 * [ VC: ID Attribute Default ]
6064
 * An ID attribute must have a declared default of #IMPLIED or #REQUIRED.
6065
 *
6066
 * [ VC: IDREF ]
6067
 * Values of type IDREF must match the Name production, and values
6068
 * of type IDREFS must match Names; each IDREF Name must match the value
6069
 * of an ID attribute on some element in the XML document; i.e. IDREF
6070
 * values must match the value of some ID attribute.
6071
 *
6072
 * [ VC: Entity Name ]
6073
 * Values of type ENTITY must match the Name production, values
6074
 * of type ENTITIES must match Names; each Entity Name must match the
6075
 * name of an unparsed entity declared in the DTD.
6076
 *
6077
 * [ VC: Name Token ]
6078
 * Values of type NMTOKEN must match the Nmtoken production; values
6079
 * of type NMTOKENS must match Nmtokens.
6080
 *
6081
 * Returns the attribute type
6082
 */
6083
int
6084
0
xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
6085
0
    if (CMP5(CUR_PTR, 'C', 'D', 'A', 'T', 'A')) {
6086
0
  SKIP(5);
6087
0
  return(XML_ATTRIBUTE_CDATA);
6088
0
     } else if (CMP6(CUR_PTR, 'I', 'D', 'R', 'E', 'F', 'S')) {
6089
0
  SKIP(6);
6090
0
  return(XML_ATTRIBUTE_IDREFS);
6091
0
     } else if (CMP5(CUR_PTR, 'I', 'D', 'R', 'E', 'F')) {
6092
0
  SKIP(5);
6093
0
  return(XML_ATTRIBUTE_IDREF);
6094
0
     } else if ((RAW == 'I') && (NXT(1) == 'D')) {
6095
0
        SKIP(2);
6096
0
  return(XML_ATTRIBUTE_ID);
6097
0
     } else if (CMP6(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'Y')) {
6098
0
  SKIP(6);
6099
0
  return(XML_ATTRIBUTE_ENTITY);
6100
0
     } else if (CMP8(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S')) {
6101
0
  SKIP(8);
6102
0
  return(XML_ATTRIBUTE_ENTITIES);
6103
0
     } else if (CMP8(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S')) {
6104
0
  SKIP(8);
6105
0
  return(XML_ATTRIBUTE_NMTOKENS);
6106
0
     } else if (CMP7(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N')) {
6107
0
  SKIP(7);
6108
0
  return(XML_ATTRIBUTE_NMTOKEN);
6109
0
     }
6110
0
     return(xmlParseEnumeratedType(ctxt, tree));
6111
0
}
6112
6113
/**
6114
 * xmlParseAttributeListDecl:
6115
 * @ctxt:  an XML parser context
6116
 *
6117
 * DEPRECATED: Internal function, don't use.
6118
 *
6119
 * Parse an attribute list declaration for an element. Always consumes '<!'.
6120
 *
6121
 * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
6122
 *
6123
 * [53] AttDef ::= S Name S AttType S DefaultDecl
6124
 *
6125
 */
6126
void
6127
0
xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
6128
0
    const xmlChar *elemName;
6129
0
    const xmlChar *attrName;
6130
0
    xmlEnumerationPtr tree;
6131
6132
0
    if ((CUR != '<') || (NXT(1) != '!'))
6133
0
        return;
6134
0
    SKIP(2);
6135
6136
0
    if (CMP7(CUR_PTR, 'A', 'T', 'T', 'L', 'I', 'S', 'T')) {
6137
0
  int inputid = ctxt->input->id;
6138
6139
0
  SKIP(7);
6140
0
  if (SKIP_BLANKS == 0) {
6141
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6142
0
                     "Space required after '<!ATTLIST'\n");
6143
0
  }
6144
0
        elemName = xmlParseName(ctxt);
6145
0
  if (elemName == NULL) {
6146
0
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6147
0
         "ATTLIST: no name for Element\n");
6148
0
      return;
6149
0
  }
6150
0
  SKIP_BLANKS;
6151
0
  GROW;
6152
0
  while ((RAW != '>') && (ctxt->instate != XML_PARSER_EOF)) {
6153
0
      int type;
6154
0
      int def;
6155
0
      xmlChar *defaultValue = NULL;
6156
6157
0
      GROW;
6158
0
            tree = NULL;
6159
0
      attrName = xmlParseName(ctxt);
6160
0
      if (attrName == NULL) {
6161
0
    xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6162
0
             "ATTLIST: no name for Attribute\n");
6163
0
    break;
6164
0
      }
6165
0
      GROW;
6166
0
      if (SKIP_BLANKS == 0) {
6167
0
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6168
0
            "Space required after the attribute name\n");
6169
0
    break;
6170
0
      }
6171
6172
0
      type = xmlParseAttributeType(ctxt, &tree);
6173
0
      if (type <= 0) {
6174
0
          break;
6175
0
      }
6176
6177
0
      GROW;
6178
0
      if (SKIP_BLANKS == 0) {
6179
0
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6180
0
             "Space required after the attribute type\n");
6181
0
          if (tree != NULL)
6182
0
        xmlFreeEnumeration(tree);
6183
0
    break;
6184
0
      }
6185
6186
0
      def = xmlParseDefaultDecl(ctxt, &defaultValue);
6187
0
      if (def <= 0) {
6188
0
                if (defaultValue != NULL)
6189
0
        xmlFree(defaultValue);
6190
0
          if (tree != NULL)
6191
0
        xmlFreeEnumeration(tree);
6192
0
          break;
6193
0
      }
6194
0
      if ((type != XML_ATTRIBUTE_CDATA) && (defaultValue != NULL))
6195
0
          xmlAttrNormalizeSpace(defaultValue, defaultValue);
6196
6197
0
      GROW;
6198
0
            if (RAW != '>') {
6199
0
    if (SKIP_BLANKS == 0) {
6200
0
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6201
0
      "Space required after the attribute default value\n");
6202
0
        if (defaultValue != NULL)
6203
0
      xmlFree(defaultValue);
6204
0
        if (tree != NULL)
6205
0
      xmlFreeEnumeration(tree);
6206
0
        break;
6207
0
    }
6208
0
      }
6209
0
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
6210
0
    (ctxt->sax->attributeDecl != NULL))
6211
0
    ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
6212
0
                          type, def, defaultValue, tree);
6213
0
      else if (tree != NULL)
6214
0
    xmlFreeEnumeration(tree);
6215
6216
0
      if ((ctxt->sax2) && (defaultValue != NULL) &&
6217
0
          (def != XML_ATTRIBUTE_IMPLIED) &&
6218
0
    (def != XML_ATTRIBUTE_REQUIRED)) {
6219
0
    xmlAddDefAttrs(ctxt, elemName, attrName, defaultValue);
6220
0
      }
6221
0
      if (ctxt->sax2) {
6222
0
    xmlAddSpecialAttr(ctxt, elemName, attrName, type);
6223
0
      }
6224
0
      if (defaultValue != NULL)
6225
0
          xmlFree(defaultValue);
6226
0
      GROW;
6227
0
  }
6228
0
  if (RAW == '>') {
6229
0
      if (inputid != ctxt->input->id) {
6230
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6231
0
                               "Attribute list declaration doesn't start and"
6232
0
                               " stop in the same entity\n");
6233
0
      }
6234
0
      NEXT;
6235
0
  }
6236
0
    }
6237
0
}
6238
6239
/**
6240
 * xmlParseElementMixedContentDecl:
6241
 * @ctxt:  an XML parser context
6242
 * @inputchk:  the input used for the current entity, needed for boundary checks
6243
 *
6244
 * DEPRECATED: Internal function, don't use.
6245
 *
6246
 * parse the declaration for a Mixed Element content
6247
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6248
 *
6249
 * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' |
6250
 *                '(' S? '#PCDATA' S? ')'
6251
 *
6252
 * [ VC: Proper Group/PE Nesting ] applies to [51] too (see [49])
6253
 *
6254
 * [ VC: No Duplicate Types ]
6255
 * The same name must not appear more than once in a single
6256
 * mixed-content declaration.
6257
 *
6258
 * returns: the list of the xmlElementContentPtr describing the element choices
6259
 */
6260
xmlElementContentPtr
6261
0
xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
6262
0
    xmlElementContentPtr ret = NULL, cur = NULL, n;
6263
0
    const xmlChar *elem = NULL;
6264
6265
0
    GROW;
6266
0
    if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
6267
0
  SKIP(7);
6268
0
  SKIP_BLANKS;
6269
0
  if (RAW == ')') {
6270
0
      if (ctxt->input->id != inputchk) {
6271
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6272
0
                               "Element content declaration doesn't start and"
6273
0
                               " stop in the same entity\n");
6274
0
      }
6275
0
      NEXT;
6276
0
      ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
6277
0
      if (ret == NULL)
6278
0
          return(NULL);
6279
0
      if (RAW == '*') {
6280
0
    ret->ocur = XML_ELEMENT_CONTENT_MULT;
6281
0
    NEXT;
6282
0
      }
6283
0
      return(ret);
6284
0
  }
6285
0
  if ((RAW == '(') || (RAW == '|')) {
6286
0
      ret = cur = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
6287
0
      if (ret == NULL) return(NULL);
6288
0
  }
6289
0
  while ((RAW == '|') && (ctxt->instate != XML_PARSER_EOF)) {
6290
0
      NEXT;
6291
0
      if (elem == NULL) {
6292
0
          ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6293
0
    if (ret == NULL) {
6294
0
        xmlFreeDocElementContent(ctxt->myDoc, cur);
6295
0
                    return(NULL);
6296
0
                }
6297
0
    ret->c1 = cur;
6298
0
    if (cur != NULL)
6299
0
        cur->parent = ret;
6300
0
    cur = ret;
6301
0
      } else {
6302
0
          n = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6303
0
    if (n == NULL) {
6304
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6305
0
                    return(NULL);
6306
0
                }
6307
0
    n->c1 = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6308
0
    if (n->c1 != NULL)
6309
0
        n->c1->parent = n;
6310
0
          cur->c2 = n;
6311
0
    if (n != NULL)
6312
0
        n->parent = cur;
6313
0
    cur = n;
6314
0
      }
6315
0
      SKIP_BLANKS;
6316
0
      elem = xmlParseName(ctxt);
6317
0
      if (elem == NULL) {
6318
0
    xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6319
0
      "xmlParseElementMixedContentDecl : Name expected\n");
6320
0
    xmlFreeDocElementContent(ctxt->myDoc, ret);
6321
0
    return(NULL);
6322
0
      }
6323
0
      SKIP_BLANKS;
6324
0
      GROW;
6325
0
  }
6326
0
  if ((RAW == ')') && (NXT(1) == '*')) {
6327
0
      if (elem != NULL) {
6328
0
    cur->c2 = xmlNewDocElementContent(ctxt->myDoc, elem,
6329
0
                                   XML_ELEMENT_CONTENT_ELEMENT);
6330
0
    if (cur->c2 != NULL)
6331
0
        cur->c2->parent = cur;
6332
0
            }
6333
0
            if (ret != NULL)
6334
0
                ret->ocur = XML_ELEMENT_CONTENT_MULT;
6335
0
      if (ctxt->input->id != inputchk) {
6336
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6337
0
                               "Element content declaration doesn't start and"
6338
0
                               " stop in the same entity\n");
6339
0
      }
6340
0
      SKIP(2);
6341
0
  } else {
6342
0
      xmlFreeDocElementContent(ctxt->myDoc, ret);
6343
0
      xmlFatalErr(ctxt, XML_ERR_MIXED_NOT_STARTED, NULL);
6344
0
      return(NULL);
6345
0
  }
6346
6347
0
    } else {
6348
0
  xmlFatalErr(ctxt, XML_ERR_PCDATA_REQUIRED, NULL);
6349
0
    }
6350
0
    return(ret);
6351
0
}
6352
6353
/**
6354
 * xmlParseElementChildrenContentDeclPriv:
6355
 * @ctxt:  an XML parser context
6356
 * @inputchk:  the input used for the current entity, needed for boundary checks
6357
 * @depth: the level of recursion
6358
 *
6359
 * parse the declaration for a Mixed Element content
6360
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6361
 *
6362
 *
6363
 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
6364
 *
6365
 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
6366
 *
6367
 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
6368
 *
6369
 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
6370
 *
6371
 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
6372
 * TODO Parameter-entity replacement text must be properly nested
6373
 *  with parenthesized groups. That is to say, if either of the
6374
 *  opening or closing parentheses in a choice, seq, or Mixed
6375
 *  construct is contained in the replacement text for a parameter
6376
 *  entity, both must be contained in the same replacement text. For
6377
 *  interoperability, if a parameter-entity reference appears in a
6378
 *  choice, seq, or Mixed construct, its replacement text should not
6379
 *  be empty, and neither the first nor last non-blank character of
6380
 *  the replacement text should be a connector (| or ,).
6381
 *
6382
 * Returns the tree of xmlElementContentPtr describing the element
6383
 *          hierarchy.
6384
 */
6385
static xmlElementContentPtr
6386
xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
6387
0
                                       int depth) {
6388
0
    xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
6389
0
    const xmlChar *elem;
6390
0
    xmlChar type = 0;
6391
6392
0
    if (((depth > 128) && ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
6393
0
        (depth >  2048)) {
6394
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED,
6395
0
"xmlParseElementChildrenContentDecl : depth %d too deep, use XML_PARSE_HUGE\n",
6396
0
                          depth);
6397
0
  return(NULL);
6398
0
    }
6399
0
    SKIP_BLANKS;
6400
0
    GROW;
6401
0
    if (RAW == '(') {
6402
0
  int inputid = ctxt->input->id;
6403
6404
        /* Recurse on first child */
6405
0
  NEXT;
6406
0
  SKIP_BLANKS;
6407
0
        cur = ret = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
6408
0
                                                           depth + 1);
6409
0
        if (cur == NULL)
6410
0
            return(NULL);
6411
0
  SKIP_BLANKS;
6412
0
  GROW;
6413
0
    } else {
6414
0
  elem = xmlParseName(ctxt);
6415
0
  if (elem == NULL) {
6416
0
      xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
6417
0
      return(NULL);
6418
0
  }
6419
0
        cur = ret = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6420
0
  if (cur == NULL) {
6421
0
      xmlErrMemory(ctxt, NULL);
6422
0
      return(NULL);
6423
0
  }
6424
0
  GROW;
6425
0
  if (RAW == '?') {
6426
0
      cur->ocur = XML_ELEMENT_CONTENT_OPT;
6427
0
      NEXT;
6428
0
  } else if (RAW == '*') {
6429
0
      cur->ocur = XML_ELEMENT_CONTENT_MULT;
6430
0
      NEXT;
6431
0
  } else if (RAW == '+') {
6432
0
      cur->ocur = XML_ELEMENT_CONTENT_PLUS;
6433
0
      NEXT;
6434
0
  } else {
6435
0
      cur->ocur = XML_ELEMENT_CONTENT_ONCE;
6436
0
  }
6437
0
  GROW;
6438
0
    }
6439
0
    SKIP_BLANKS;
6440
0
    while ((RAW != ')') && (ctxt->instate != XML_PARSER_EOF)) {
6441
        /*
6442
   * Each loop we parse one separator and one element.
6443
   */
6444
0
        if (RAW == ',') {
6445
0
      if (type == 0) type = CUR;
6446
6447
      /*
6448
       * Detect "Name | Name , Name" error
6449
       */
6450
0
      else if (type != CUR) {
6451
0
    xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
6452
0
        "xmlParseElementChildrenContentDecl : '%c' expected\n",
6453
0
                      type);
6454
0
    if ((last != NULL) && (last != ret))
6455
0
        xmlFreeDocElementContent(ctxt->myDoc, last);
6456
0
    if (ret != NULL)
6457
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6458
0
    return(NULL);
6459
0
      }
6460
0
      NEXT;
6461
6462
0
      op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_SEQ);
6463
0
      if (op == NULL) {
6464
0
    if ((last != NULL) && (last != ret))
6465
0
        xmlFreeDocElementContent(ctxt->myDoc, last);
6466
0
          xmlFreeDocElementContent(ctxt->myDoc, ret);
6467
0
    return(NULL);
6468
0
      }
6469
0
      if (last == NULL) {
6470
0
    op->c1 = ret;
6471
0
    if (ret != NULL)
6472
0
        ret->parent = op;
6473
0
    ret = cur = op;
6474
0
      } else {
6475
0
          cur->c2 = op;
6476
0
    if (op != NULL)
6477
0
        op->parent = cur;
6478
0
    op->c1 = last;
6479
0
    if (last != NULL)
6480
0
        last->parent = op;
6481
0
    cur =op;
6482
0
    last = NULL;
6483
0
      }
6484
0
  } else if (RAW == '|') {
6485
0
      if (type == 0) type = CUR;
6486
6487
      /*
6488
       * Detect "Name , Name | Name" error
6489
       */
6490
0
      else if (type != CUR) {
6491
0
    xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
6492
0
        "xmlParseElementChildrenContentDecl : '%c' expected\n",
6493
0
          type);
6494
0
    if ((last != NULL) && (last != ret))
6495
0
        xmlFreeDocElementContent(ctxt->myDoc, last);
6496
0
    if (ret != NULL)
6497
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6498
0
    return(NULL);
6499
0
      }
6500
0
      NEXT;
6501
6502
0
      op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6503
0
      if (op == NULL) {
6504
0
    if ((last != NULL) && (last != ret))
6505
0
        xmlFreeDocElementContent(ctxt->myDoc, last);
6506
0
    if (ret != NULL)
6507
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6508
0
    return(NULL);
6509
0
      }
6510
0
      if (last == NULL) {
6511
0
    op->c1 = ret;
6512
0
    if (ret != NULL)
6513
0
        ret->parent = op;
6514
0
    ret = cur = op;
6515
0
      } else {
6516
0
          cur->c2 = op;
6517
0
    if (op != NULL)
6518
0
        op->parent = cur;
6519
0
    op->c1 = last;
6520
0
    if (last != NULL)
6521
0
        last->parent = op;
6522
0
    cur =op;
6523
0
    last = NULL;
6524
0
      }
6525
0
  } else {
6526
0
      xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED, NULL);
6527
0
      if ((last != NULL) && (last != ret))
6528
0
          xmlFreeDocElementContent(ctxt->myDoc, last);
6529
0
      if (ret != NULL)
6530
0
    xmlFreeDocElementContent(ctxt->myDoc, ret);
6531
0
      return(NULL);
6532
0
  }
6533
0
  GROW;
6534
0
  SKIP_BLANKS;
6535
0
  GROW;
6536
0
  if (RAW == '(') {
6537
0
      int inputid = ctxt->input->id;
6538
      /* Recurse on second child */
6539
0
      NEXT;
6540
0
      SKIP_BLANKS;
6541
0
      last = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
6542
0
                                                          depth + 1);
6543
0
            if (last == NULL) {
6544
0
    if (ret != NULL)
6545
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6546
0
    return(NULL);
6547
0
            }
6548
0
      SKIP_BLANKS;
6549
0
  } else {
6550
0
      elem = xmlParseName(ctxt);
6551
0
      if (elem == NULL) {
6552
0
    xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
6553
0
    if (ret != NULL)
6554
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6555
0
    return(NULL);
6556
0
      }
6557
0
      last = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6558
0
      if (last == NULL) {
6559
0
    if (ret != NULL)
6560
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6561
0
    return(NULL);
6562
0
      }
6563
0
      if (RAW == '?') {
6564
0
    last->ocur = XML_ELEMENT_CONTENT_OPT;
6565
0
    NEXT;
6566
0
      } else if (RAW == '*') {
6567
0
    last->ocur = XML_ELEMENT_CONTENT_MULT;
6568
0
    NEXT;
6569
0
      } else if (RAW == '+') {
6570
0
    last->ocur = XML_ELEMENT_CONTENT_PLUS;
6571
0
    NEXT;
6572
0
      } else {
6573
0
    last->ocur = XML_ELEMENT_CONTENT_ONCE;
6574
0
      }
6575
0
  }
6576
0
  SKIP_BLANKS;
6577
0
  GROW;
6578
0
    }
6579
0
    if ((cur != NULL) && (last != NULL)) {
6580
0
        cur->c2 = last;
6581
0
  if (last != NULL)
6582
0
      last->parent = cur;
6583
0
    }
6584
0
    if (ctxt->input->id != inputchk) {
6585
0
  xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6586
0
                       "Element content declaration doesn't start and stop in"
6587
0
                       " the same entity\n");
6588
0
    }
6589
0
    NEXT;
6590
0
    if (RAW == '?') {
6591
0
  if (ret != NULL) {
6592
0
      if ((ret->ocur == XML_ELEMENT_CONTENT_PLUS) ||
6593
0
          (ret->ocur == XML_ELEMENT_CONTENT_MULT))
6594
0
          ret->ocur = XML_ELEMENT_CONTENT_MULT;
6595
0
      else
6596
0
          ret->ocur = XML_ELEMENT_CONTENT_OPT;
6597
0
  }
6598
0
  NEXT;
6599
0
    } else if (RAW == '*') {
6600
0
  if (ret != NULL) {
6601
0
      ret->ocur = XML_ELEMENT_CONTENT_MULT;
6602
0
      cur = ret;
6603
      /*
6604
       * Some normalization:
6605
       * (a | b* | c?)* == (a | b | c)*
6606
       */
6607
0
      while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
6608
0
    if ((cur->c1 != NULL) &&
6609
0
              ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
6610
0
         (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT)))
6611
0
        cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
6612
0
    if ((cur->c2 != NULL) &&
6613
0
              ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
6614
0
         (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT)))
6615
0
        cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
6616
0
    cur = cur->c2;
6617
0
      }
6618
0
  }
6619
0
  NEXT;
6620
0
    } else if (RAW == '+') {
6621
0
  if (ret != NULL) {
6622
0
      int found = 0;
6623
6624
0
      if ((ret->ocur == XML_ELEMENT_CONTENT_OPT) ||
6625
0
          (ret->ocur == XML_ELEMENT_CONTENT_MULT))
6626
0
          ret->ocur = XML_ELEMENT_CONTENT_MULT;
6627
0
      else
6628
0
          ret->ocur = XML_ELEMENT_CONTENT_PLUS;
6629
      /*
6630
       * Some normalization:
6631
       * (a | b*)+ == (a | b)*
6632
       * (a | b?)+ == (a | b)*
6633
       */
6634
0
      while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
6635
0
    if ((cur->c1 != NULL) &&
6636
0
              ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
6637
0
         (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT))) {
6638
0
        cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
6639
0
        found = 1;
6640
0
    }
6641
0
    if ((cur->c2 != NULL) &&
6642
0
              ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
6643
0
         (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT))) {
6644
0
        cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
6645
0
        found = 1;
6646
0
    }
6647
0
    cur = cur->c2;
6648
0
      }
6649
0
      if (found)
6650
0
    ret->ocur = XML_ELEMENT_CONTENT_MULT;
6651
0
  }
6652
0
  NEXT;
6653
0
    }
6654
0
    return(ret);
6655
0
}
6656
6657
/**
6658
 * xmlParseElementChildrenContentDecl:
6659
 * @ctxt:  an XML parser context
6660
 * @inputchk:  the input used for the current entity, needed for boundary checks
6661
 *
6662
 * DEPRECATED: Internal function, don't use.
6663
 *
6664
 * parse the declaration for a Mixed Element content
6665
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6666
 *
6667
 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
6668
 *
6669
 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
6670
 *
6671
 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
6672
 *
6673
 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
6674
 *
6675
 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
6676
 * TODO Parameter-entity replacement text must be properly nested
6677
 *  with parenthesized groups. That is to say, if either of the
6678
 *  opening or closing parentheses in a choice, seq, or Mixed
6679
 *  construct is contained in the replacement text for a parameter
6680
 *  entity, both must be contained in the same replacement text. For
6681
 *  interoperability, if a parameter-entity reference appears in a
6682
 *  choice, seq, or Mixed construct, its replacement text should not
6683
 *  be empty, and neither the first nor last non-blank character of
6684
 *  the replacement text should be a connector (| or ,).
6685
 *
6686
 * Returns the tree of xmlElementContentPtr describing the element
6687
 *          hierarchy.
6688
 */
6689
xmlElementContentPtr
6690
0
xmlParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
6691
    /* stub left for API/ABI compat */
6692
0
    return(xmlParseElementChildrenContentDeclPriv(ctxt, inputchk, 1));
6693
0
}
6694
6695
/**
6696
 * xmlParseElementContentDecl:
6697
 * @ctxt:  an XML parser context
6698
 * @name:  the name of the element being defined.
6699
 * @result:  the Element Content pointer will be stored here if any
6700
 *
6701
 * DEPRECATED: Internal function, don't use.
6702
 *
6703
 * parse the declaration for an Element content either Mixed or Children,
6704
 * the cases EMPTY and ANY are handled directly in xmlParseElementDecl
6705
 *
6706
 * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
6707
 *
6708
 * returns: the type of element content XML_ELEMENT_TYPE_xxx
6709
 */
6710
6711
int
6712
xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, const xmlChar *name,
6713
0
                           xmlElementContentPtr *result) {
6714
6715
0
    xmlElementContentPtr tree = NULL;
6716
0
    int inputid = ctxt->input->id;
6717
0
    int res;
6718
6719
0
    *result = NULL;
6720
6721
0
    if (RAW != '(') {
6722
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
6723
0
    "xmlParseElementContentDecl : %s '(' expected\n", name);
6724
0
  return(-1);
6725
0
    }
6726
0
    NEXT;
6727
0
    GROW;
6728
0
    if (ctxt->instate == XML_PARSER_EOF)
6729
0
        return(-1);
6730
0
    SKIP_BLANKS;
6731
0
    if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
6732
0
        tree = xmlParseElementMixedContentDecl(ctxt, inputid);
6733
0
  res = XML_ELEMENT_TYPE_MIXED;
6734
0
    } else {
6735
0
        tree = xmlParseElementChildrenContentDeclPriv(ctxt, inputid, 1);
6736
0
  res = XML_ELEMENT_TYPE_ELEMENT;
6737
0
    }
6738
0
    SKIP_BLANKS;
6739
0
    *result = tree;
6740
0
    return(res);
6741
0
}
6742
6743
/**
6744
 * xmlParseElementDecl:
6745
 * @ctxt:  an XML parser context
6746
 *
6747
 * DEPRECATED: Internal function, don't use.
6748
 *
6749
 * Parse an element declaration. Always consumes '<!'.
6750
 *
6751
 * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
6752
 *
6753
 * [ VC: Unique Element Type Declaration ]
6754
 * No element type may be declared more than once
6755
 *
6756
 * Returns the type of the element, or -1 in case of error
6757
 */
6758
int
6759
0
xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
6760
0
    const xmlChar *name;
6761
0
    int ret = -1;
6762
0
    xmlElementContentPtr content  = NULL;
6763
6764
0
    if ((CUR != '<') || (NXT(1) != '!'))
6765
0
        return(ret);
6766
0
    SKIP(2);
6767
6768
    /* GROW; done in the caller */
6769
0
    if (CMP7(CUR_PTR, 'E', 'L', 'E', 'M', 'E', 'N', 'T')) {
6770
0
  int inputid = ctxt->input->id;
6771
6772
0
  SKIP(7);
6773
0
  if (SKIP_BLANKS == 0) {
6774
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6775
0
               "Space required after 'ELEMENT'\n");
6776
0
      return(-1);
6777
0
  }
6778
0
        name = xmlParseName(ctxt);
6779
0
  if (name == NULL) {
6780
0
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6781
0
         "xmlParseElementDecl: no name for Element\n");
6782
0
      return(-1);
6783
0
  }
6784
0
  if (SKIP_BLANKS == 0) {
6785
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6786
0
         "Space required after the element name\n");
6787
0
  }
6788
0
  if (CMP5(CUR_PTR, 'E', 'M', 'P', 'T', 'Y')) {
6789
0
      SKIP(5);
6790
      /*
6791
       * Element must always be empty.
6792
       */
6793
0
      ret = XML_ELEMENT_TYPE_EMPTY;
6794
0
  } else if ((RAW == 'A') && (NXT(1) == 'N') &&
6795
0
             (NXT(2) == 'Y')) {
6796
0
      SKIP(3);
6797
      /*
6798
       * Element is a generic container.
6799
       */
6800
0
      ret = XML_ELEMENT_TYPE_ANY;
6801
0
  } else if (RAW == '(') {
6802
0
      ret = xmlParseElementContentDecl(ctxt, name, &content);
6803
0
  } else {
6804
      /*
6805
       * [ WFC: PEs in Internal Subset ] error handling.
6806
       */
6807
0
      if ((RAW == '%') && (ctxt->external == 0) &&
6808
0
          (ctxt->inputNr == 1)) {
6809
0
    xmlFatalErrMsg(ctxt, XML_ERR_PEREF_IN_INT_SUBSET,
6810
0
    "PEReference: forbidden within markup decl in internal subset\n");
6811
0
      } else {
6812
0
    xmlFatalErrMsg(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
6813
0
          "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
6814
0
            }
6815
0
      return(-1);
6816
0
  }
6817
6818
0
  SKIP_BLANKS;
6819
6820
0
  if (RAW != '>') {
6821
0
      xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
6822
0
      if (content != NULL) {
6823
0
    xmlFreeDocElementContent(ctxt->myDoc, content);
6824
0
      }
6825
0
  } else {
6826
0
      if (inputid != ctxt->input->id) {
6827
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6828
0
                               "Element declaration doesn't start and stop in"
6829
0
                               " the same entity\n");
6830
0
      }
6831
6832
0
      NEXT;
6833
0
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
6834
0
    (ctxt->sax->elementDecl != NULL)) {
6835
0
    if (content != NULL)
6836
0
        content->parent = NULL;
6837
0
          ctxt->sax->elementDecl(ctxt->userData, name, ret,
6838
0
                           content);
6839
0
    if ((content != NULL) && (content->parent == NULL)) {
6840
        /*
6841
         * this is a trick: if xmlAddElementDecl is called,
6842
         * instead of copying the full tree it is plugged directly
6843
         * if called from the parser. Avoid duplicating the
6844
         * interfaces or change the API/ABI
6845
         */
6846
0
        xmlFreeDocElementContent(ctxt->myDoc, content);
6847
0
    }
6848
0
      } else if (content != NULL) {
6849
0
    xmlFreeDocElementContent(ctxt->myDoc, content);
6850
0
      }
6851
0
  }
6852
0
    }
6853
0
    return(ret);
6854
0
}
6855
6856
/**
6857
 * xmlParseConditionalSections
6858
 * @ctxt:  an XML parser context
6859
 *
6860
 * Parse a conditional section. Always consumes '<!['.
6861
 *
6862
 * [61] conditionalSect ::= includeSect | ignoreSect
6863
 * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
6864
 * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
6865
 * [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
6866
 * [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
6867
 */
6868
6869
static void
6870
0
xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
6871
0
    int *inputIds = NULL;
6872
0
    size_t inputIdsSize = 0;
6873
0
    size_t depth = 0;
6874
6875
0
    while (ctxt->instate != XML_PARSER_EOF) {
6876
0
        if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
6877
0
            int id = ctxt->input->id;
6878
6879
0
            SKIP(3);
6880
0
            SKIP_BLANKS;
6881
6882
0
            if (CMP7(CUR_PTR, 'I', 'N', 'C', 'L', 'U', 'D', 'E')) {
6883
0
                SKIP(7);
6884
0
                SKIP_BLANKS;
6885
0
                if (RAW != '[') {
6886
0
                    xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
6887
0
                    xmlHaltParser(ctxt);
6888
0
                    goto error;
6889
0
                }
6890
0
                if (ctxt->input->id != id) {
6891
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6892
0
                                   "All markup of the conditional section is"
6893
0
                                   " not in the same entity\n");
6894
0
                }
6895
0
                NEXT;
6896
6897
0
                if (inputIdsSize <= depth) {
6898
0
                    int *tmp;
6899
6900
0
                    inputIdsSize = (inputIdsSize == 0 ? 4 : inputIdsSize * 2);
6901
0
                    tmp = (int *) xmlRealloc(inputIds,
6902
0
                            inputIdsSize * sizeof(int));
6903
0
                    if (tmp == NULL) {
6904
0
                        xmlErrMemory(ctxt, NULL);
6905
0
                        goto error;
6906
0
                    }
6907
0
                    inputIds = tmp;
6908
0
                }
6909
0
                inputIds[depth] = id;
6910
0
                depth++;
6911
0
            } else if (CMP6(CUR_PTR, 'I', 'G', 'N', 'O', 'R', 'E')) {
6912
0
                size_t ignoreDepth = 0;
6913
6914
0
                SKIP(6);
6915
0
                SKIP_BLANKS;
6916
0
                if (RAW != '[') {
6917
0
                    xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
6918
0
                    xmlHaltParser(ctxt);
6919
0
                    goto error;
6920
0
                }
6921
0
                if (ctxt->input->id != id) {
6922
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6923
0
                                   "All markup of the conditional section is"
6924
0
                                   " not in the same entity\n");
6925
0
                }
6926
0
                NEXT;
6927
6928
0
                while (RAW != 0) {
6929
0
                    if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
6930
0
                        SKIP(3);
6931
0
                        ignoreDepth++;
6932
                        /* Check for integer overflow */
6933
0
                        if (ignoreDepth == 0) {
6934
0
                            xmlErrMemory(ctxt, NULL);
6935
0
                            goto error;
6936
0
                        }
6937
0
                    } else if ((RAW == ']') && (NXT(1) == ']') &&
6938
0
                               (NXT(2) == '>')) {
6939
0
                        if (ignoreDepth == 0)
6940
0
                            break;
6941
0
                        SKIP(3);
6942
0
                        ignoreDepth--;
6943
0
                    } else {
6944
0
                        NEXT;
6945
0
                    }
6946
0
                }
6947
6948
0
    if (RAW == 0) {
6949
0
        xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
6950
0
                    goto error;
6951
0
    }
6952
0
                if (ctxt->input->id != id) {
6953
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6954
0
                                   "All markup of the conditional section is"
6955
0
                                   " not in the same entity\n");
6956
0
                }
6957
0
                SKIP(3);
6958
0
            } else {
6959
0
                xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
6960
0
                xmlHaltParser(ctxt);
6961
0
                goto error;
6962
0
            }
6963
0
        } else if ((depth > 0) &&
6964
0
                   (RAW == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
6965
0
            depth--;
6966
0
            if (ctxt->input->id != inputIds[depth]) {
6967
0
                xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6968
0
                               "All markup of the conditional section is not"
6969
0
                               " in the same entity\n");
6970
0
            }
6971
0
            SKIP(3);
6972
0
        } else if ((RAW == '<') && ((NXT(1) == '!') || (NXT(1) == '?'))) {
6973
0
            xmlParseMarkupDecl(ctxt);
6974
0
        } else {
6975
0
            xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
6976
0
            xmlHaltParser(ctxt);
6977
0
            goto error;
6978
0
        }
6979
6980
0
        if (depth == 0)
6981
0
            break;
6982
6983
0
        SKIP_BLANKS;
6984
0
        SHRINK;
6985
0
        GROW;
6986
0
    }
6987
6988
0
error:
6989
0
    xmlFree(inputIds);
6990
0
}
6991
6992
/**
6993
 * xmlParseMarkupDecl:
6994
 * @ctxt:  an XML parser context
6995
 *
6996
 * DEPRECATED: Internal function, don't use.
6997
 *
6998
 * Parse markup declarations. Always consumes '<!' or '<?'.
6999
 *
7000
 * [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
7001
 *                     NotationDecl | PI | Comment
7002
 *
7003
 * [ VC: Proper Declaration/PE Nesting ]
7004
 * Parameter-entity replacement text must be properly nested with
7005
 * markup declarations. That is to say, if either the first character
7006
 * or the last character of a markup declaration (markupdecl above) is
7007
 * contained in the replacement text for a parameter-entity reference,
7008
 * both must be contained in the same replacement text.
7009
 *
7010
 * [ WFC: PEs in Internal Subset ]
7011
 * In the internal DTD subset, parameter-entity references can occur
7012
 * only where markup declarations can occur, not within markup declarations.
7013
 * (This does not apply to references that occur in external parameter
7014
 * entities or to the external subset.)
7015
 */
7016
void
7017
0
xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
7018
0
    GROW;
7019
0
    if (CUR == '<') {
7020
0
        if (NXT(1) == '!') {
7021
0
      switch (NXT(2)) {
7022
0
          case 'E':
7023
0
        if (NXT(3) == 'L')
7024
0
      xmlParseElementDecl(ctxt);
7025
0
        else if (NXT(3) == 'N')
7026
0
      xmlParseEntityDecl(ctxt);
7027
0
                    else
7028
0
                        SKIP(2);
7029
0
        break;
7030
0
          case 'A':
7031
0
        xmlParseAttributeListDecl(ctxt);
7032
0
        break;
7033
0
          case 'N':
7034
0
        xmlParseNotationDecl(ctxt);
7035
0
        break;
7036
0
          case '-':
7037
0
        xmlParseComment(ctxt);
7038
0
        break;
7039
0
    default:
7040
        /* there is an error but it will be detected later */
7041
0
                    SKIP(2);
7042
0
        break;
7043
0
      }
7044
0
  } else if (NXT(1) == '?') {
7045
0
      xmlParsePI(ctxt);
7046
0
  }
7047
0
    }
7048
7049
    /*
7050
     * detect requirement to exit there and act accordingly
7051
     * and avoid having instate overridden later on
7052
     */
7053
0
    if (ctxt->instate == XML_PARSER_EOF)
7054
0
        return;
7055
7056
0
    ctxt->instate = XML_PARSER_DTD;
7057
0
}
7058
7059
/**
7060
 * xmlParseTextDecl:
7061
 * @ctxt:  an XML parser context
7062
 *
7063
 * DEPRECATED: Internal function, don't use.
7064
 *
7065
 * parse an XML declaration header for external entities
7066
 *
7067
 * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
7068
 */
7069
7070
void
7071
0
xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
7072
0
    xmlChar *version;
7073
0
    int oldstate;
7074
7075
    /*
7076
     * We know that '<?xml' is here.
7077
     */
7078
0
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
7079
0
  SKIP(5);
7080
0
    } else {
7081
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_STARTED, NULL);
7082
0
  return;
7083
0
    }
7084
7085
    /* Avoid expansion of parameter entities when skipping blanks. */
7086
0
    oldstate = ctxt->instate;
7087
0
    ctxt->instate = XML_PARSER_START;
7088
7089
0
    if (SKIP_BLANKS == 0) {
7090
0
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
7091
0
           "Space needed after '<?xml'\n");
7092
0
    }
7093
7094
    /*
7095
     * We may have the VersionInfo here.
7096
     */
7097
0
    version = xmlParseVersionInfo(ctxt);
7098
0
    if (version == NULL)
7099
0
  version = xmlCharStrdup(XML_DEFAULT_VERSION);
7100
0
    else {
7101
0
  if (SKIP_BLANKS == 0) {
7102
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
7103
0
               "Space needed here\n");
7104
0
  }
7105
0
    }
7106
0
    ctxt->input->version = version;
7107
7108
    /*
7109
     * We must have the encoding declaration
7110
     */
7111
0
    xmlParseEncodingDecl(ctxt);
7112
0
    if (ctxt->instate == XML_PARSER_EOF)
7113
0
        return;
7114
0
    if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
7115
  /*
7116
   * The XML REC instructs us to stop parsing right here
7117
   */
7118
0
        ctxt->instate = oldstate;
7119
0
        return;
7120
0
    }
7121
7122
0
    SKIP_BLANKS;
7123
0
    if ((RAW == '?') && (NXT(1) == '>')) {
7124
0
        SKIP(2);
7125
0
    } else if (RAW == '>') {
7126
        /* Deprecated old WD ... */
7127
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
7128
0
  NEXT;
7129
0
    } else {
7130
0
        int c;
7131
7132
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
7133
0
        while ((c = CUR) != 0) {
7134
0
            NEXT;
7135
0
            if (c == '>')
7136
0
                break;
7137
0
        }
7138
0
    }
7139
7140
0
    if (ctxt->instate != XML_PARSER_EOF)
7141
0
        ctxt->instate = oldstate;
7142
0
}
7143
7144
/**
7145
 * xmlParseExternalSubset:
7146
 * @ctxt:  an XML parser context
7147
 * @ExternalID: the external identifier
7148
 * @SystemID: the system identifier (or URL)
7149
 *
7150
 * parse Markup declarations from an external subset
7151
 *
7152
 * [30] extSubset ::= textDecl? extSubsetDecl
7153
 *
7154
 * [31] extSubsetDecl ::= (markupdecl | conditionalSect | PEReference | S) *
7155
 */
7156
void
7157
xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
7158
0
                       const xmlChar *SystemID) {
7159
0
    xmlDetectSAX2(ctxt);
7160
7161
0
    xmlDetectEncoding(ctxt);
7162
7163
0
    if (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) {
7164
0
  xmlParseTextDecl(ctxt);
7165
0
  if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
7166
      /*
7167
       * The XML REC instructs us to stop parsing right here
7168
       */
7169
0
      xmlHaltParser(ctxt);
7170
0
      return;
7171
0
  }
7172
0
    }
7173
0
    if (ctxt->myDoc == NULL) {
7174
0
        ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
7175
0
  if (ctxt->myDoc == NULL) {
7176
0
      xmlErrMemory(ctxt, "New Doc failed");
7177
0
      return;
7178
0
  }
7179
0
  ctxt->myDoc->properties = XML_DOC_INTERNAL;
7180
0
    }
7181
0
    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
7182
0
        xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
7183
7184
0
    ctxt->instate = XML_PARSER_DTD;
7185
0
    ctxt->external = 1;
7186
0
    SKIP_BLANKS;
7187
0
    while ((ctxt->instate != XML_PARSER_EOF) && (RAW != 0)) {
7188
0
  GROW;
7189
0
        if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
7190
0
            xmlParseConditionalSections(ctxt);
7191
0
        } else if ((RAW == '<') && ((NXT(1) == '!') || (NXT(1) == '?'))) {
7192
0
            xmlParseMarkupDecl(ctxt);
7193
0
        } else {
7194
0
            xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
7195
0
            xmlHaltParser(ctxt);
7196
0
            return;
7197
0
        }
7198
0
        SKIP_BLANKS;
7199
0
        SHRINK;
7200
0
    }
7201
7202
0
    if (RAW != 0) {
7203
0
  xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
7204
0
    }
7205
7206
0
}
7207
7208
/**
7209
 * xmlParseReference:
7210
 * @ctxt:  an XML parser context
7211
 *
7212
 * DEPRECATED: Internal function, don't use.
7213
 *
7214
 * parse and handle entity references in content, depending on the SAX
7215
 * interface, this may end-up in a call to character() if this is a
7216
 * CharRef, a predefined entity, if there is no reference() callback.
7217
 * or if the parser was asked to switch to that mode.
7218
 *
7219
 * Always consumes '&'.
7220
 *
7221
 * [67] Reference ::= EntityRef | CharRef
7222
 */
7223
void
7224
0
xmlParseReference(xmlParserCtxtPtr ctxt) {
7225
0
    xmlEntityPtr ent;
7226
0
    xmlChar *val;
7227
0
    int was_checked;
7228
0
    xmlNodePtr list = NULL;
7229
0
    xmlParserErrors ret = XML_ERR_OK;
7230
7231
7232
0
    if (RAW != '&')
7233
0
        return;
7234
7235
    /*
7236
     * Simple case of a CharRef
7237
     */
7238
0
    if (NXT(1) == '#') {
7239
0
  int i = 0;
7240
0
  xmlChar out[16];
7241
0
  int value = xmlParseCharRef(ctxt);
7242
7243
0
  if (value == 0)
7244
0
      return;
7245
7246
        /*
7247
         * Just encode the value in UTF-8
7248
         */
7249
0
        COPY_BUF(out, i, value);
7250
0
        out[i] = 0;
7251
0
        if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
7252
0
            (!ctxt->disableSAX))
7253
0
            ctxt->sax->characters(ctxt->userData, out, i);
7254
0
  return;
7255
0
    }
7256
7257
    /*
7258
     * We are seeing an entity reference
7259
     */
7260
0
    ent = xmlParseEntityRef(ctxt);
7261
0
    if (ent == NULL) return;
7262
0
    if (!ctxt->wellFormed)
7263
0
  return;
7264
0
    was_checked = ent->flags & XML_ENT_PARSED;
7265
7266
    /* special case of predefined entities */
7267
0
    if ((ent->name == NULL) ||
7268
0
        (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
7269
0
  val = ent->content;
7270
0
  if (val == NULL) return;
7271
  /*
7272
   * inline the entity.
7273
   */
7274
0
  if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
7275
0
      (!ctxt->disableSAX))
7276
0
      ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
7277
0
  return;
7278
0
    }
7279
7280
    /*
7281
     * The first reference to the entity trigger a parsing phase
7282
     * where the ent->children is filled with the result from
7283
     * the parsing.
7284
     * Note: external parsed entities will not be loaded, it is not
7285
     * required for a non-validating parser, unless the parsing option
7286
     * of validating, or substituting entities were given. Doing so is
7287
     * far more secure as the parser will only process data coming from
7288
     * the document entity by default.
7289
     *
7290
     * FIXME: This doesn't work correctly since entities can be
7291
     * expanded with different namespace declarations in scope.
7292
     * For example:
7293
     *
7294
     * <!DOCTYPE doc [
7295
     *   <!ENTITY ent "<ns:elem/>">
7296
     * ]>
7297
     * <doc>
7298
     *   <decl1 xmlns:ns="urn:ns1">
7299
     *     &ent;
7300
     *   </decl1>
7301
     *   <decl2 xmlns:ns="urn:ns2">
7302
     *     &ent;
7303
     *   </decl2>
7304
     * </doc>
7305
     *
7306
     * Proposed fix:
7307
     *
7308
     * - Remove the ent->owner optimization which tries to avoid the
7309
     *   initial copy of the entity. Always make entities own the
7310
     *   subtree.
7311
     * - Ignore current namespace declarations when parsing the
7312
     *   entity. If a prefix can't be resolved, don't report an error
7313
     *   but mark it as unresolved.
7314
     * - Try to resolve these prefixes when expanding the entity.
7315
     *   This will require a specialized version of xmlStaticCopyNode
7316
     *   which can also make use of the namespace hash table to avoid
7317
     *   quadratic behavior.
7318
     *
7319
     * Alternatively, we could simply reparse the entity on each
7320
     * expansion like we already do with custom SAX callbacks.
7321
     * External entity content should be cached in this case.
7322
     */
7323
0
    if (((ent->flags & XML_ENT_PARSED) == 0) &&
7324
0
        ((ent->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY) ||
7325
0
         (ctxt->options & (XML_PARSE_NOENT | XML_PARSE_DTDVALID)))) {
7326
0
  unsigned long oldsizeentcopy = ctxt->sizeentcopy;
7327
7328
  /*
7329
   * This is a bit hackish but this seems the best
7330
   * way to make sure both SAX and DOM entity support
7331
   * behaves okay.
7332
   */
7333
0
  void *user_data;
7334
0
  if (ctxt->userData == ctxt)
7335
0
      user_data = NULL;
7336
0
  else
7337
0
      user_data = ctxt->userData;
7338
7339
        /* Avoid overflow as much as possible */
7340
0
        ctxt->sizeentcopy = 0;
7341
7342
0
        if (ent->flags & XML_ENT_EXPANDING) {
7343
0
            xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
7344
0
            xmlHaltParser(ctxt);
7345
0
            return;
7346
0
        }
7347
7348
0
        ent->flags |= XML_ENT_EXPANDING;
7349
7350
  /*
7351
   * Check that this entity is well formed
7352
   * 4.3.2: An internal general parsed entity is well-formed
7353
   * if its replacement text matches the production labeled
7354
   * content.
7355
   */
7356
0
  if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
7357
0
      ctxt->depth++;
7358
0
      ret = xmlParseBalancedChunkMemoryInternal(ctxt, ent->content,
7359
0
                                                user_data, &list);
7360
0
      ctxt->depth--;
7361
7362
0
  } else if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
7363
0
      ctxt->depth++;
7364
0
      ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt, ctxt->sax,
7365
0
                                     user_data, ctxt->depth, ent->URI,
7366
0
             ent->ExternalID, &list);
7367
0
      ctxt->depth--;
7368
0
  } else {
7369
0
      ret = XML_ERR_ENTITY_PE_INTERNAL;
7370
0
      xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
7371
0
       "invalid entity type found\n", NULL);
7372
0
  }
7373
7374
0
        ent->flags &= ~XML_ENT_EXPANDING;
7375
0
        ent->flags |= XML_ENT_PARSED | XML_ENT_CHECKED;
7376
0
        ent->expandedSize = ctxt->sizeentcopy;
7377
0
  if (ret == XML_ERR_ENTITY_LOOP) {
7378
0
            xmlHaltParser(ctxt);
7379
0
      xmlFreeNodeList(list);
7380
0
      return;
7381
0
  }
7382
0
  if (xmlParserEntityCheck(ctxt, oldsizeentcopy)) {
7383
0
      xmlFreeNodeList(list);
7384
0
      return;
7385
0
  }
7386
7387
0
  if ((ret == XML_ERR_OK) && (list != NULL)) {
7388
0
            ent->children = list;
7389
            /*
7390
             * Prune it directly in the generated document
7391
             * except for single text nodes.
7392
             */
7393
0
            if ((ctxt->replaceEntities == 0) ||
7394
0
                (ctxt->parseMode == XML_PARSE_READER) ||
7395
0
                ((list->type == XML_TEXT_NODE) &&
7396
0
                 (list->next == NULL))) {
7397
0
                ent->owner = 1;
7398
0
                while (list != NULL) {
7399
0
                    list->parent = (xmlNodePtr) ent;
7400
0
                    if (list->doc != ent->doc)
7401
0
                        xmlSetTreeDoc(list, ent->doc);
7402
0
                    if (list->next == NULL)
7403
0
                        ent->last = list;
7404
0
                    list = list->next;
7405
0
                }
7406
0
                list = NULL;
7407
0
            } else {
7408
0
                ent->owner = 0;
7409
0
                while (list != NULL) {
7410
0
                    list->parent = (xmlNodePtr) ctxt->node;
7411
0
                    list->doc = ctxt->myDoc;
7412
0
                    if (list->next == NULL)
7413
0
                        ent->last = list;
7414
0
                    list = list->next;
7415
0
                }
7416
0
                list = ent->children;
7417
#ifdef LIBXML_LEGACY_ENABLED
7418
                if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7419
                    xmlAddEntityReference(ent, list, NULL);
7420
#endif /* LIBXML_LEGACY_ENABLED */
7421
0
            }
7422
0
  } else if ((ret != XML_ERR_OK) &&
7423
0
       (ret != XML_WAR_UNDECLARED_ENTITY)) {
7424
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7425
0
         "Entity '%s' failed to parse\n", ent->name);
7426
0
            if (ent->content != NULL)
7427
0
                ent->content[0] = 0;
7428
0
  } else if (list != NULL) {
7429
0
      xmlFreeNodeList(list);
7430
0
      list = NULL;
7431
0
  }
7432
7433
        /* Prevent entity from being parsed and expanded twice (Bug 760367). */
7434
0
        was_checked = 0;
7435
0
    }
7436
7437
    /*
7438
     * Now that the entity content has been gathered
7439
     * provide it to the application, this can take different forms based
7440
     * on the parsing modes.
7441
     */
7442
0
    if (ent->children == NULL) {
7443
  /*
7444
   * Probably running in SAX mode and the callbacks don't
7445
   * build the entity content. So unless we already went
7446
   * though parsing for first checking go though the entity
7447
   * content to generate callbacks associated to the entity
7448
   */
7449
0
  if (was_checked != 0) {
7450
0
      void *user_data;
7451
      /*
7452
       * This is a bit hackish but this seems the best
7453
       * way to make sure both SAX and DOM entity support
7454
       * behaves okay.
7455
       */
7456
0
      if (ctxt->userData == ctxt)
7457
0
    user_data = NULL;
7458
0
      else
7459
0
    user_data = ctxt->userData;
7460
7461
0
      if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
7462
0
    ctxt->depth++;
7463
0
    ret = xmlParseBalancedChunkMemoryInternal(ctxt,
7464
0
           ent->content, user_data, NULL);
7465
0
    ctxt->depth--;
7466
0
      } else if (ent->etype ==
7467
0
           XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
7468
0
          unsigned long oldsizeentities = ctxt->sizeentities;
7469
7470
0
    ctxt->depth++;
7471
0
    ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt,
7472
0
         ctxt->sax, user_data, ctxt->depth,
7473
0
         ent->URI, ent->ExternalID, NULL);
7474
0
    ctxt->depth--;
7475
7476
                /* Undo the change to sizeentities */
7477
0
                ctxt->sizeentities = oldsizeentities;
7478
0
      } else {
7479
0
    ret = XML_ERR_ENTITY_PE_INTERNAL;
7480
0
    xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
7481
0
           "invalid entity type found\n", NULL);
7482
0
      }
7483
0
      if (ret == XML_ERR_ENTITY_LOOP) {
7484
0
    xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
7485
0
    return;
7486
0
      }
7487
0
            if (xmlParserEntityCheck(ctxt, 0))
7488
0
                return;
7489
0
  }
7490
0
  if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
7491
0
      (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
7492
      /*
7493
       * Entity reference callback comes second, it's somewhat
7494
       * superfluous but a compatibility to historical behaviour
7495
       */
7496
0
      ctxt->sax->reference(ctxt->userData, ent->name);
7497
0
  }
7498
0
  return;
7499
0
    }
7500
7501
    /*
7502
     * We also check for amplification if entities aren't substituted.
7503
     * They might be expanded later.
7504
     */
7505
0
    if ((was_checked != 0) &&
7506
0
        (xmlParserEntityCheck(ctxt, ent->expandedSize)))
7507
0
        return;
7508
7509
    /*
7510
     * If we didn't get any children for the entity being built
7511
     */
7512
0
    if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
7513
0
  (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
7514
  /*
7515
   * Create a node.
7516
   */
7517
0
  ctxt->sax->reference(ctxt->userData, ent->name);
7518
0
  return;
7519
0
    }
7520
7521
0
    if (ctxt->replaceEntities)  {
7522
  /*
7523
   * There is a problem on the handling of _private for entities
7524
   * (bug 155816): Should we copy the content of the field from
7525
   * the entity (possibly overwriting some value set by the user
7526
   * when a copy is created), should we leave it alone, or should
7527
   * we try to take care of different situations?  The problem
7528
   * is exacerbated by the usage of this field by the xmlReader.
7529
   * To fix this bug, we look at _private on the created node
7530
   * and, if it's NULL, we copy in whatever was in the entity.
7531
   * If it's not NULL we leave it alone.  This is somewhat of a
7532
   * hack - maybe we should have further tests to determine
7533
   * what to do.
7534
   */
7535
0
  if (ctxt->node != NULL) {
7536
      /*
7537
       * Seems we are generating the DOM content, do
7538
       * a simple tree copy for all references except the first
7539
       * In the first occurrence list contains the replacement.
7540
       */
7541
0
      if (((list == NULL) && (ent->owner == 0)) ||
7542
0
    (ctxt->parseMode == XML_PARSE_READER)) {
7543
0
    xmlNodePtr nw = NULL, cur, firstChild = NULL;
7544
7545
    /*
7546
     * when operating on a reader, the entities definitions
7547
     * are always owning the entities subtree.
7548
    if (ctxt->parseMode == XML_PARSE_READER)
7549
        ent->owner = 1;
7550
     */
7551
7552
0
    cur = ent->children;
7553
0
    while (cur != NULL) {
7554
0
        nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
7555
0
        if (nw != NULL) {
7556
0
      if (nw->_private == NULL)
7557
0
          nw->_private = cur->_private;
7558
0
      if (firstChild == NULL){
7559
0
          firstChild = nw;
7560
0
      }
7561
0
      nw = xmlAddChild(ctxt->node, nw);
7562
0
        }
7563
0
        if (cur == ent->last) {
7564
      /*
7565
       * needed to detect some strange empty
7566
       * node cases in the reader tests
7567
       */
7568
0
      if ((ctxt->parseMode == XML_PARSE_READER) &&
7569
0
          (nw != NULL) &&
7570
0
          (nw->type == XML_ELEMENT_NODE) &&
7571
0
          (nw->children == NULL))
7572
0
          nw->extra = 1;
7573
7574
0
      break;
7575
0
        }
7576
0
        cur = cur->next;
7577
0
    }
7578
#ifdef LIBXML_LEGACY_ENABLED
7579
    if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7580
      xmlAddEntityReference(ent, firstChild, nw);
7581
#endif /* LIBXML_LEGACY_ENABLED */
7582
0
      } else if ((list == NULL) || (ctxt->inputNr > 0)) {
7583
0
    xmlNodePtr nw = NULL, cur, next, last,
7584
0
         firstChild = NULL;
7585
7586
    /*
7587
     * Copy the entity child list and make it the new
7588
     * entity child list. The goal is to make sure any
7589
     * ID or REF referenced will be the one from the
7590
     * document content and not the entity copy.
7591
     */
7592
0
    cur = ent->children;
7593
0
    ent->children = NULL;
7594
0
    last = ent->last;
7595
0
    ent->last = NULL;
7596
0
    while (cur != NULL) {
7597
0
        next = cur->next;
7598
0
        cur->next = NULL;
7599
0
        cur->parent = NULL;
7600
0
        nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
7601
0
        if (nw != NULL) {
7602
0
      if (nw->_private == NULL)
7603
0
          nw->_private = cur->_private;
7604
0
      if (firstChild == NULL){
7605
0
          firstChild = cur;
7606
0
      }
7607
0
      xmlAddChild((xmlNodePtr) ent, nw);
7608
0
        }
7609
0
        xmlAddChild(ctxt->node, cur);
7610
0
        if (cur == last)
7611
0
      break;
7612
0
        cur = next;
7613
0
    }
7614
0
    if (ent->owner == 0)
7615
0
        ent->owner = 1;
7616
#ifdef LIBXML_LEGACY_ENABLED
7617
    if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7618
      xmlAddEntityReference(ent, firstChild, nw);
7619
#endif /* LIBXML_LEGACY_ENABLED */
7620
0
      } else {
7621
0
    const xmlChar *nbktext;
7622
7623
    /*
7624
     * the name change is to avoid coalescing of the
7625
     * node with a possible previous text one which
7626
     * would make ent->children a dangling pointer
7627
     */
7628
0
    nbktext = xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
7629
0
          -1);
7630
0
    if (ent->children->type == XML_TEXT_NODE)
7631
0
        ent->children->name = nbktext;
7632
0
    if ((ent->last != ent->children) &&
7633
0
        (ent->last->type == XML_TEXT_NODE))
7634
0
        ent->last->name = nbktext;
7635
0
    xmlAddChildList(ctxt->node, ent->children);
7636
0
      }
7637
7638
      /*
7639
       * This is to avoid a nasty side effect, see
7640
       * characters() in SAX.c
7641
       */
7642
0
      ctxt->nodemem = 0;
7643
0
      ctxt->nodelen = 0;
7644
0
      return;
7645
0
  }
7646
0
    }
7647
0
}
7648
7649
/**
7650
 * xmlParseEntityRef:
7651
 * @ctxt:  an XML parser context
7652
 *
7653
 * DEPRECATED: Internal function, don't use.
7654
 *
7655
 * Parse an entitiy reference. Always consumes '&'.
7656
 *
7657
 * [68] EntityRef ::= '&' Name ';'
7658
 *
7659
 * [ WFC: Entity Declared ]
7660
 * In a document without any DTD, a document with only an internal DTD
7661
 * subset which contains no parameter entity references, or a document
7662
 * with "standalone='yes'", the Name given in the entity reference
7663
 * must match that in an entity declaration, except that well-formed
7664
 * documents need not declare any of the following entities: amp, lt,
7665
 * gt, apos, quot.  The declaration of a parameter entity must precede
7666
 * any reference to it.  Similarly, the declaration of a general entity
7667
 * must precede any reference to it which appears in a default value in an
7668
 * attribute-list declaration. Note that if entities are declared in the
7669
 * external subset or in external parameter entities, a non-validating
7670
 * processor is not obligated to read and process their declarations;
7671
 * for such documents, the rule that an entity must be declared is a
7672
 * well-formedness constraint only if standalone='yes'.
7673
 *
7674
 * [ WFC: Parsed Entity ]
7675
 * An entity reference must not contain the name of an unparsed entity
7676
 *
7677
 * Returns the xmlEntityPtr if found, or NULL otherwise.
7678
 */
7679
xmlEntityPtr
7680
0
xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
7681
0
    const xmlChar *name;
7682
0
    xmlEntityPtr ent = NULL;
7683
7684
0
    GROW;
7685
0
    if (ctxt->instate == XML_PARSER_EOF)
7686
0
        return(NULL);
7687
7688
0
    if (RAW != '&')
7689
0
        return(NULL);
7690
0
    NEXT;
7691
0
    name = xmlParseName(ctxt);
7692
0
    if (name == NULL) {
7693
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7694
0
           "xmlParseEntityRef: no name\n");
7695
0
        return(NULL);
7696
0
    }
7697
0
    if (RAW != ';') {
7698
0
  xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
7699
0
  return(NULL);
7700
0
    }
7701
0
    NEXT;
7702
7703
    /*
7704
     * Predefined entities override any extra definition
7705
     */
7706
0
    if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
7707
0
        ent = xmlGetPredefinedEntity(name);
7708
0
        if (ent != NULL)
7709
0
            return(ent);
7710
0
    }
7711
7712
    /*
7713
     * Ask first SAX for entity resolution, otherwise try the
7714
     * entities which may have stored in the parser context.
7715
     */
7716
0
    if (ctxt->sax != NULL) {
7717
0
  if (ctxt->sax->getEntity != NULL)
7718
0
      ent = ctxt->sax->getEntity(ctxt->userData, name);
7719
0
  if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
7720
0
      (ctxt->options & XML_PARSE_OLDSAX))
7721
0
      ent = xmlGetPredefinedEntity(name);
7722
0
  if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
7723
0
      (ctxt->userData==ctxt)) {
7724
0
      ent = xmlSAX2GetEntity(ctxt, name);
7725
0
  }
7726
0
    }
7727
0
    if (ctxt->instate == XML_PARSER_EOF)
7728
0
  return(NULL);
7729
    /*
7730
     * [ WFC: Entity Declared ]
7731
     * In a document without any DTD, a document with only an
7732
     * internal DTD subset which contains no parameter entity
7733
     * references, or a document with "standalone='yes'", the
7734
     * Name given in the entity reference must match that in an
7735
     * entity declaration, except that well-formed documents
7736
     * need not declare any of the following entities: amp, lt,
7737
     * gt, apos, quot.
7738
     * The declaration of a parameter entity must precede any
7739
     * reference to it.
7740
     * Similarly, the declaration of a general entity must
7741
     * precede any reference to it which appears in a default
7742
     * value in an attribute-list declaration. Note that if
7743
     * entities are declared in the external subset or in
7744
     * external parameter entities, a non-validating processor
7745
     * is not obligated to read and process their declarations;
7746
     * for such documents, the rule that an entity must be
7747
     * declared is a well-formedness constraint only if
7748
     * standalone='yes'.
7749
     */
7750
0
    if (ent == NULL) {
7751
0
  if ((ctxt->standalone == 1) ||
7752
0
      ((ctxt->hasExternalSubset == 0) &&
7753
0
       (ctxt->hasPErefs == 0))) {
7754
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7755
0
         "Entity '%s' not defined\n", name);
7756
0
  } else {
7757
0
      xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
7758
0
         "Entity '%s' not defined\n", name);
7759
0
      if ((ctxt->inSubset == 0) &&
7760
0
    (ctxt->sax != NULL) &&
7761
0
                (ctxt->disableSAX == 0) &&
7762
0
    (ctxt->sax->reference != NULL)) {
7763
0
    ctxt->sax->reference(ctxt->userData, name);
7764
0
      }
7765
0
  }
7766
0
  ctxt->valid = 0;
7767
0
    }
7768
7769
    /*
7770
     * [ WFC: Parsed Entity ]
7771
     * An entity reference must not contain the name of an
7772
     * unparsed entity
7773
     */
7774
0
    else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
7775
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
7776
0
     "Entity reference to unparsed entity %s\n", name);
7777
0
    }
7778
7779
    /*
7780
     * [ WFC: No External Entity References ]
7781
     * Attribute values cannot contain direct or indirect
7782
     * entity references to external entities.
7783
     */
7784
0
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7785
0
       (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
7786
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
7787
0
       "Attribute references external entity '%s'\n", name);
7788
0
    }
7789
    /*
7790
     * [ WFC: No < in Attribute Values ]
7791
     * The replacement text of any entity referred to directly or
7792
     * indirectly in an attribute value (other than "&lt;") must
7793
     * not contain a <.
7794
     */
7795
0
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7796
0
       (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
7797
0
  if ((ent->flags & XML_ENT_CHECKED_LT) == 0) {
7798
0
            if ((ent->content != NULL) && (xmlStrchr(ent->content, '<')))
7799
0
                ent->flags |= XML_ENT_CONTAINS_LT;
7800
0
            ent->flags |= XML_ENT_CHECKED_LT;
7801
0
        }
7802
0
        if (ent->flags & XML_ENT_CONTAINS_LT)
7803
0
            xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
7804
0
                    "'<' in entity '%s' is not allowed in attributes "
7805
0
                    "values\n", name);
7806
0
    }
7807
7808
    /*
7809
     * Internal check, no parameter entities here ...
7810
     */
7811
0
    else {
7812
0
  switch (ent->etype) {
7813
0
      case XML_INTERNAL_PARAMETER_ENTITY:
7814
0
      case XML_EXTERNAL_PARAMETER_ENTITY:
7815
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
7816
0
       "Attempt to reference the parameter entity '%s'\n",
7817
0
            name);
7818
0
      break;
7819
0
      default:
7820
0
      break;
7821
0
  }
7822
0
    }
7823
7824
    /*
7825
     * [ WFC: No Recursion ]
7826
     * A parsed entity must not contain a recursive reference
7827
     * to itself, either directly or indirectly.
7828
     * Done somewhere else
7829
     */
7830
0
    return(ent);
7831
0
}
7832
7833
/**
7834
 * xmlParseStringEntityRef:
7835
 * @ctxt:  an XML parser context
7836
 * @str:  a pointer to an index in the string
7837
 *
7838
 * parse ENTITY references declarations, but this version parses it from
7839
 * a string value.
7840
 *
7841
 * [68] EntityRef ::= '&' Name ';'
7842
 *
7843
 * [ WFC: Entity Declared ]
7844
 * In a document without any DTD, a document with only an internal DTD
7845
 * subset which contains no parameter entity references, or a document
7846
 * with "standalone='yes'", the Name given in the entity reference
7847
 * must match that in an entity declaration, except that well-formed
7848
 * documents need not declare any of the following entities: amp, lt,
7849
 * gt, apos, quot.  The declaration of a parameter entity must precede
7850
 * any reference to it.  Similarly, the declaration of a general entity
7851
 * must precede any reference to it which appears in a default value in an
7852
 * attribute-list declaration. Note that if entities are declared in the
7853
 * external subset or in external parameter entities, a non-validating
7854
 * processor is not obligated to read and process their declarations;
7855
 * for such documents, the rule that an entity must be declared is a
7856
 * well-formedness constraint only if standalone='yes'.
7857
 *
7858
 * [ WFC: Parsed Entity ]
7859
 * An entity reference must not contain the name of an unparsed entity
7860
 *
7861
 * Returns the xmlEntityPtr if found, or NULL otherwise. The str pointer
7862
 * is updated to the current location in the string.
7863
 */
7864
static xmlEntityPtr
7865
0
xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
7866
0
    xmlChar *name;
7867
0
    const xmlChar *ptr;
7868
0
    xmlChar cur;
7869
0
    xmlEntityPtr ent = NULL;
7870
7871
0
    if ((str == NULL) || (*str == NULL))
7872
0
        return(NULL);
7873
0
    ptr = *str;
7874
0
    cur = *ptr;
7875
0
    if (cur != '&')
7876
0
  return(NULL);
7877
7878
0
    ptr++;
7879
0
    name = xmlParseStringName(ctxt, &ptr);
7880
0
    if (name == NULL) {
7881
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7882
0
           "xmlParseStringEntityRef: no name\n");
7883
0
  *str = ptr;
7884
0
  return(NULL);
7885
0
    }
7886
0
    if (*ptr != ';') {
7887
0
  xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
7888
0
        xmlFree(name);
7889
0
  *str = ptr;
7890
0
  return(NULL);
7891
0
    }
7892
0
    ptr++;
7893
7894
7895
    /*
7896
     * Predefined entities override any extra definition
7897
     */
7898
0
    if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
7899
0
        ent = xmlGetPredefinedEntity(name);
7900
0
        if (ent != NULL) {
7901
0
            xmlFree(name);
7902
0
            *str = ptr;
7903
0
            return(ent);
7904
0
        }
7905
0
    }
7906
7907
    /*
7908
     * Ask first SAX for entity resolution, otherwise try the
7909
     * entities which may have stored in the parser context.
7910
     */
7911
0
    if (ctxt->sax != NULL) {
7912
0
  if (ctxt->sax->getEntity != NULL)
7913
0
      ent = ctxt->sax->getEntity(ctxt->userData, name);
7914
0
  if ((ent == NULL) && (ctxt->options & XML_PARSE_OLDSAX))
7915
0
      ent = xmlGetPredefinedEntity(name);
7916
0
  if ((ent == NULL) && (ctxt->userData==ctxt)) {
7917
0
      ent = xmlSAX2GetEntity(ctxt, name);
7918
0
  }
7919
0
    }
7920
0
    if (ctxt->instate == XML_PARSER_EOF) {
7921
0
  xmlFree(name);
7922
0
  return(NULL);
7923
0
    }
7924
7925
    /*
7926
     * [ WFC: Entity Declared ]
7927
     * In a document without any DTD, a document with only an
7928
     * internal DTD subset which contains no parameter entity
7929
     * references, or a document with "standalone='yes'", the
7930
     * Name given in the entity reference must match that in an
7931
     * entity declaration, except that well-formed documents
7932
     * need not declare any of the following entities: amp, lt,
7933
     * gt, apos, quot.
7934
     * The declaration of a parameter entity must precede any
7935
     * reference to it.
7936
     * Similarly, the declaration of a general entity must
7937
     * precede any reference to it which appears in a default
7938
     * value in an attribute-list declaration. Note that if
7939
     * entities are declared in the external subset or in
7940
     * external parameter entities, a non-validating processor
7941
     * is not obligated to read and process their declarations;
7942
     * for such documents, the rule that an entity must be
7943
     * declared is a well-formedness constraint only if
7944
     * standalone='yes'.
7945
     */
7946
0
    if (ent == NULL) {
7947
0
  if ((ctxt->standalone == 1) ||
7948
0
      ((ctxt->hasExternalSubset == 0) &&
7949
0
       (ctxt->hasPErefs == 0))) {
7950
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7951
0
         "Entity '%s' not defined\n", name);
7952
0
  } else {
7953
0
      xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
7954
0
        "Entity '%s' not defined\n",
7955
0
        name);
7956
0
  }
7957
  /* TODO ? check regressions ctxt->valid = 0; */
7958
0
    }
7959
7960
    /*
7961
     * [ WFC: Parsed Entity ]
7962
     * An entity reference must not contain the name of an
7963
     * unparsed entity
7964
     */
7965
0
    else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
7966
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
7967
0
     "Entity reference to unparsed entity %s\n", name);
7968
0
    }
7969
7970
    /*
7971
     * [ WFC: No External Entity References ]
7972
     * Attribute values cannot contain direct or indirect
7973
     * entity references to external entities.
7974
     */
7975
0
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7976
0
       (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
7977
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
7978
0
   "Attribute references external entity '%s'\n", name);
7979
0
    }
7980
    /*
7981
     * [ WFC: No < in Attribute Values ]
7982
     * The replacement text of any entity referred to directly or
7983
     * indirectly in an attribute value (other than "&lt;") must
7984
     * not contain a <.
7985
     */
7986
0
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7987
0
       (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
7988
0
  if ((ent->flags & XML_ENT_CHECKED_LT) == 0) {
7989
0
            if ((ent->content != NULL) && (xmlStrchr(ent->content, '<')))
7990
0
                ent->flags |= XML_ENT_CONTAINS_LT;
7991
0
            ent->flags |= XML_ENT_CHECKED_LT;
7992
0
        }
7993
0
        if (ent->flags & XML_ENT_CONTAINS_LT)
7994
0
            xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
7995
0
                    "'<' in entity '%s' is not allowed in attributes "
7996
0
                    "values\n", name);
7997
0
    }
7998
7999
    /*
8000
     * Internal check, no parameter entities here ...
8001
     */
8002
0
    else {
8003
0
  switch (ent->etype) {
8004
0
      case XML_INTERNAL_PARAMETER_ENTITY:
8005
0
      case XML_EXTERNAL_PARAMETER_ENTITY:
8006
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
8007
0
       "Attempt to reference the parameter entity '%s'\n",
8008
0
          name);
8009
0
      break;
8010
0
      default:
8011
0
      break;
8012
0
  }
8013
0
    }
8014
8015
    /*
8016
     * [ WFC: No Recursion ]
8017
     * A parsed entity must not contain a recursive reference
8018
     * to itself, either directly or indirectly.
8019
     * Done somewhere else
8020
     */
8021
8022
0
    xmlFree(name);
8023
0
    *str = ptr;
8024
0
    return(ent);
8025
0
}
8026
8027
/**
8028
 * xmlParsePEReference:
8029
 * @ctxt:  an XML parser context
8030
 *
8031
 * DEPRECATED: Internal function, don't use.
8032
 *
8033
 * Parse a parameter entity reference. Always consumes '%'.
8034
 *
8035
 * The entity content is handled directly by pushing it's content as
8036
 * a new input stream.
8037
 *
8038
 * [69] PEReference ::= '%' Name ';'
8039
 *
8040
 * [ WFC: No Recursion ]
8041
 * A parsed entity must not contain a recursive
8042
 * reference to itself, either directly or indirectly.
8043
 *
8044
 * [ WFC: Entity Declared ]
8045
 * In a document without any DTD, a document with only an internal DTD
8046
 * subset which contains no parameter entity references, or a document
8047
 * with "standalone='yes'", ...  ... The declaration of a parameter
8048
 * entity must precede any reference to it...
8049
 *
8050
 * [ VC: Entity Declared ]
8051
 * In a document with an external subset or external parameter entities
8052
 * with "standalone='no'", ...  ... The declaration of a parameter entity
8053
 * must precede any reference to it...
8054
 *
8055
 * [ WFC: In DTD ]
8056
 * Parameter-entity references may only appear in the DTD.
8057
 * NOTE: misleading but this is handled.
8058
 */
8059
void
8060
xmlParsePEReference(xmlParserCtxtPtr ctxt)
8061
0
{
8062
0
    const xmlChar *name;
8063
0
    xmlEntityPtr entity = NULL;
8064
0
    xmlParserInputPtr input;
8065
8066
0
    if (RAW != '%')
8067
0
        return;
8068
0
    NEXT;
8069
0
    name = xmlParseName(ctxt);
8070
0
    if (name == NULL) {
8071
0
  xmlFatalErrMsg(ctxt, XML_ERR_PEREF_NO_NAME, "PEReference: no name\n");
8072
0
  return;
8073
0
    }
8074
0
    if (xmlParserDebugEntities)
8075
0
  xmlGenericError(xmlGenericErrorContext,
8076
0
    "PEReference: %s\n", name);
8077
0
    if (RAW != ';') {
8078
0
  xmlFatalErr(ctxt, XML_ERR_PEREF_SEMICOL_MISSING, NULL);
8079
0
        return;
8080
0
    }
8081
8082
0
    NEXT;
8083
8084
    /*
8085
     * Request the entity from SAX
8086
     */
8087
0
    if ((ctxt->sax != NULL) &&
8088
0
  (ctxt->sax->getParameterEntity != NULL))
8089
0
  entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
8090
0
    if (ctxt->instate == XML_PARSER_EOF)
8091
0
  return;
8092
0
    if (entity == NULL) {
8093
  /*
8094
   * [ WFC: Entity Declared ]
8095
   * In a document without any DTD, a document with only an
8096
   * internal DTD subset which contains no parameter entity
8097
   * references, or a document with "standalone='yes'", ...
8098
   * ... The declaration of a parameter entity must precede
8099
   * any reference to it...
8100
   */
8101
0
  if ((ctxt->standalone == 1) ||
8102
0
      ((ctxt->hasExternalSubset == 0) &&
8103
0
       (ctxt->hasPErefs == 0))) {
8104
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
8105
0
            "PEReference: %%%s; not found\n",
8106
0
            name);
8107
0
  } else {
8108
      /*
8109
       * [ VC: Entity Declared ]
8110
       * In a document with an external subset or external
8111
       * parameter entities with "standalone='no'", ...
8112
       * ... The declaration of a parameter entity must
8113
       * precede any reference to it...
8114
       */
8115
0
            if ((ctxt->validate) && (ctxt->vctxt.error != NULL)) {
8116
0
                xmlValidityError(ctxt, XML_WAR_UNDECLARED_ENTITY,
8117
0
                                 "PEReference: %%%s; not found\n",
8118
0
                                 name, NULL);
8119
0
            } else
8120
0
                xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8121
0
                              "PEReference: %%%s; not found\n",
8122
0
                              name, NULL);
8123
0
            ctxt->valid = 0;
8124
0
  }
8125
0
    } else {
8126
  /*
8127
   * Internal checking in case the entity quest barfed
8128
   */
8129
0
  if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
8130
0
      (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
8131
0
      xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8132
0
      "Internal: %%%s; is not a parameter entity\n",
8133
0
        name, NULL);
8134
0
  } else {
8135
0
            unsigned long parentConsumed;
8136
0
            xmlEntityPtr oldEnt;
8137
8138
0
      if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
8139
0
          ((ctxt->options & XML_PARSE_NOENT) == 0) &&
8140
0
    ((ctxt->options & XML_PARSE_DTDVALID) == 0) &&
8141
0
    ((ctxt->options & XML_PARSE_DTDLOAD) == 0) &&
8142
0
    ((ctxt->options & XML_PARSE_DTDATTR) == 0) &&
8143
0
    (ctxt->replaceEntities == 0) &&
8144
0
    (ctxt->validate == 0))
8145
0
    return;
8146
8147
0
            if (entity->flags & XML_ENT_EXPANDING) {
8148
0
                xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
8149
0
                xmlHaltParser(ctxt);
8150
0
                return;
8151
0
            }
8152
8153
            /* Must be computed from old input before pushing new input. */
8154
0
            parentConsumed = ctxt->input->parentConsumed;
8155
0
            oldEnt = ctxt->input->entity;
8156
0
            if ((oldEnt == NULL) ||
8157
0
                ((oldEnt->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
8158
0
                 ((oldEnt->flags & XML_ENT_PARSED) == 0))) {
8159
0
                xmlSaturatedAdd(&parentConsumed, ctxt->input->consumed);
8160
0
                xmlSaturatedAddSizeT(&parentConsumed,
8161
0
                                     ctxt->input->cur - ctxt->input->base);
8162
0
            }
8163
8164
0
      input = xmlNewEntityInputStream(ctxt, entity);
8165
0
      if (xmlPushInput(ctxt, input) < 0) {
8166
0
                xmlFreeInputStream(input);
8167
0
    return;
8168
0
            }
8169
8170
0
            entity->flags |= XML_ENT_EXPANDING;
8171
8172
0
            input->parentConsumed = parentConsumed;
8173
8174
0
      if (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) {
8175
0
                xmlDetectEncoding(ctxt);
8176
8177
0
                if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) &&
8178
0
                    (IS_BLANK_CH(NXT(5)))) {
8179
0
                    xmlParseTextDecl(ctxt);
8180
0
                }
8181
0
            }
8182
0
  }
8183
0
    }
8184
0
    ctxt->hasPErefs = 1;
8185
0
}
8186
8187
/**
8188
 * xmlLoadEntityContent:
8189
 * @ctxt:  an XML parser context
8190
 * @entity: an unloaded system entity
8191
 *
8192
 * Load the original content of the given system entity from the
8193
 * ExternalID/SystemID given. This is to be used for Included in Literal
8194
 * http://www.w3.org/TR/REC-xml/#inliteral processing of entities references
8195
 *
8196
 * Returns 0 in case of success and -1 in case of failure
8197
 */
8198
static int
8199
0
xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
8200
0
    xmlParserInputPtr oldinput, input = NULL;
8201
0
    xmlParserInputPtr *oldinputTab;
8202
0
    const xmlChar *oldencoding;
8203
0
    xmlChar *content = NULL;
8204
0
    size_t length, i;
8205
0
    int oldinputNr, oldinputMax, oldprogressive;
8206
0
    int ret = -1;
8207
0
    int res;
8208
8209
0
    if ((ctxt == NULL) || (entity == NULL) ||
8210
0
        ((entity->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
8211
0
   (entity->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY)) ||
8212
0
  (entity->content != NULL)) {
8213
0
  xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8214
0
              "xmlLoadEntityContent parameter error");
8215
0
        return(-1);
8216
0
    }
8217
8218
0
    if (xmlParserDebugEntities)
8219
0
  xmlGenericError(xmlGenericErrorContext,
8220
0
    "Reading %s entity content input\n", entity->name);
8221
8222
0
    input = xmlLoadExternalEntity((char *) entity->URI,
8223
0
           (char *) entity->ExternalID, ctxt);
8224
0
    if (input == NULL) {
8225
0
  xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8226
0
              "xmlLoadEntityContent input error");
8227
0
        return(-1);
8228
0
    }
8229
8230
0
    oldinput = ctxt->input;
8231
0
    oldinputNr = ctxt->inputNr;
8232
0
    oldinputMax = ctxt->inputMax;
8233
0
    oldinputTab = ctxt->inputTab;
8234
0
    oldencoding = ctxt->encoding;
8235
0
    oldprogressive = ctxt->progressive;
8236
8237
0
    ctxt->input = NULL;
8238
0
    ctxt->inputNr = 0;
8239
0
    ctxt->inputMax = 1;
8240
0
    ctxt->encoding = NULL;
8241
0
    ctxt->progressive = 0;
8242
0
    ctxt->inputTab = xmlMalloc(sizeof(xmlParserInputPtr));
8243
0
    if (ctxt->inputTab == NULL) {
8244
0
        xmlErrMemory(ctxt, NULL);
8245
0
        xmlFreeInputStream(input);
8246
0
        goto error;
8247
0
    }
8248
8249
0
    xmlBufResetInput(input->buf->buffer, input);
8250
8251
0
    inputPush(ctxt, input);
8252
8253
0
    xmlDetectEncoding(ctxt);
8254
8255
    /*
8256
     * Parse a possible text declaration first
8257
     */
8258
0
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
8259
0
  xmlParseTextDecl(ctxt);
8260
        /*
8261
         * An XML-1.0 document can't reference an entity not XML-1.0
8262
         */
8263
0
        if ((xmlStrEqual(ctxt->version, BAD_CAST "1.0")) &&
8264
0
            (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) {
8265
0
            xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH,
8266
0
                           "Version mismatch between document and entity\n");
8267
0
        }
8268
0
    }
8269
8270
0
    if (ctxt->instate == XML_PARSER_EOF)
8271
0
        goto error;
8272
8273
0
    length = input->cur - input->base;
8274
0
    xmlBufShrink(input->buf->buffer, length);
8275
0
    xmlSaturatedAdd(&ctxt->sizeentities, length);
8276
8277
0
    while ((res = xmlParserInputBufferGrow(input->buf, 4096)) > 0)
8278
0
        ;
8279
8280
0
    xmlBufResetInput(input->buf->buffer, input);
8281
8282
0
    if (res < 0) {
8283
0
        xmlFatalErr(ctxt, input->buf->error, NULL);
8284
0
        goto error;
8285
0
    }
8286
8287
0
    length = xmlBufUse(input->buf->buffer);
8288
0
    content = xmlBufDetach(input->buf->buffer);
8289
8290
0
    if (length > INT_MAX) {
8291
0
        xmlErrMemory(ctxt, NULL);
8292
0
        goto error;
8293
0
    }
8294
8295
0
    for (i = 0; i < length; ) {
8296
0
        int clen = length - i;
8297
0
        int c = xmlGetUTF8Char(content + i, &clen);
8298
8299
0
        if ((c < 0) || (!IS_CHAR(c))) {
8300
0
            xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
8301
0
                              "xmlLoadEntityContent: invalid char value %d\n",
8302
0
                              content[i]);
8303
0
            goto error;
8304
0
        }
8305
0
        i += clen;
8306
0
    }
8307
8308
0
    xmlSaturatedAdd(&ctxt->sizeentities, length);
8309
0
    entity->content = content;
8310
0
    entity->length = length;
8311
0
    content = NULL;
8312
0
    ret = 0;
8313
8314
0
error:
8315
0
    while (ctxt->inputNr > 0)
8316
0
        xmlFreeInputStream(inputPop(ctxt));
8317
0
    xmlFree(ctxt->inputTab);
8318
0
    xmlFree((xmlChar *) ctxt->encoding);
8319
8320
0
    ctxt->input = oldinput;
8321
0
    ctxt->inputNr = oldinputNr;
8322
0
    ctxt->inputMax = oldinputMax;
8323
0
    ctxt->inputTab = oldinputTab;
8324
0
    ctxt->encoding = oldencoding;
8325
0
    ctxt->progressive = oldprogressive;
8326
8327
0
    xmlFree(content);
8328
8329
0
    return(ret);
8330
0
}
8331
8332
/**
8333
 * xmlParseStringPEReference:
8334
 * @ctxt:  an XML parser context
8335
 * @str:  a pointer to an index in the string
8336
 *
8337
 * parse PEReference declarations
8338
 *
8339
 * [69] PEReference ::= '%' Name ';'
8340
 *
8341
 * [ WFC: No Recursion ]
8342
 * A parsed entity must not contain a recursive
8343
 * reference to itself, either directly or indirectly.
8344
 *
8345
 * [ WFC: Entity Declared ]
8346
 * In a document without any DTD, a document with only an internal DTD
8347
 * subset which contains no parameter entity references, or a document
8348
 * with "standalone='yes'", ...  ... The declaration of a parameter
8349
 * entity must precede any reference to it...
8350
 *
8351
 * [ VC: Entity Declared ]
8352
 * In a document with an external subset or external parameter entities
8353
 * with "standalone='no'", ...  ... The declaration of a parameter entity
8354
 * must precede any reference to it...
8355
 *
8356
 * [ WFC: In DTD ]
8357
 * Parameter-entity references may only appear in the DTD.
8358
 * NOTE: misleading but this is handled.
8359
 *
8360
 * Returns the string of the entity content.
8361
 *         str is updated to the current value of the index
8362
 */
8363
static xmlEntityPtr
8364
0
xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
8365
0
    const xmlChar *ptr;
8366
0
    xmlChar cur;
8367
0
    xmlChar *name;
8368
0
    xmlEntityPtr entity = NULL;
8369
8370
0
    if ((str == NULL) || (*str == NULL)) return(NULL);
8371
0
    ptr = *str;
8372
0
    cur = *ptr;
8373
0
    if (cur != '%')
8374
0
        return(NULL);
8375
0
    ptr++;
8376
0
    name = xmlParseStringName(ctxt, &ptr);
8377
0
    if (name == NULL) {
8378
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8379
0
           "xmlParseStringPEReference: no name\n");
8380
0
  *str = ptr;
8381
0
  return(NULL);
8382
0
    }
8383
0
    cur = *ptr;
8384
0
    if (cur != ';') {
8385
0
  xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
8386
0
  xmlFree(name);
8387
0
  *str = ptr;
8388
0
  return(NULL);
8389
0
    }
8390
0
    ptr++;
8391
8392
    /*
8393
     * Request the entity from SAX
8394
     */
8395
0
    if ((ctxt->sax != NULL) &&
8396
0
  (ctxt->sax->getParameterEntity != NULL))
8397
0
  entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
8398
0
    if (ctxt->instate == XML_PARSER_EOF) {
8399
0
  xmlFree(name);
8400
0
  *str = ptr;
8401
0
  return(NULL);
8402
0
    }
8403
0
    if (entity == NULL) {
8404
  /*
8405
   * [ WFC: Entity Declared ]
8406
   * In a document without any DTD, a document with only an
8407
   * internal DTD subset which contains no parameter entity
8408
   * references, or a document with "standalone='yes'", ...
8409
   * ... The declaration of a parameter entity must precede
8410
   * any reference to it...
8411
   */
8412
0
  if ((ctxt->standalone == 1) ||
8413
0
      ((ctxt->hasExternalSubset == 0) && (ctxt->hasPErefs == 0))) {
8414
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
8415
0
     "PEReference: %%%s; not found\n", name);
8416
0
  } else {
8417
      /*
8418
       * [ VC: Entity Declared ]
8419
       * In a document with an external subset or external
8420
       * parameter entities with "standalone='no'", ...
8421
       * ... The declaration of a parameter entity must
8422
       * precede any reference to it...
8423
       */
8424
0
      xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8425
0
        "PEReference: %%%s; not found\n",
8426
0
        name, NULL);
8427
0
      ctxt->valid = 0;
8428
0
  }
8429
0
    } else {
8430
  /*
8431
   * Internal checking in case the entity quest barfed
8432
   */
8433
0
  if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
8434
0
      (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
8435
0
      xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8436
0
        "%%%s; is not a parameter entity\n",
8437
0
        name, NULL);
8438
0
  }
8439
0
    }
8440
0
    ctxt->hasPErefs = 1;
8441
0
    xmlFree(name);
8442
0
    *str = ptr;
8443
0
    return(entity);
8444
0
}
8445
8446
/**
8447
 * xmlParseDocTypeDecl:
8448
 * @ctxt:  an XML parser context
8449
 *
8450
 * DEPRECATED: Internal function, don't use.
8451
 *
8452
 * parse a DOCTYPE declaration
8453
 *
8454
 * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
8455
 *                      ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
8456
 *
8457
 * [ VC: Root Element Type ]
8458
 * The Name in the document type declaration must match the element
8459
 * type of the root element.
8460
 */
8461
8462
void
8463
0
xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
8464
0
    const xmlChar *name = NULL;
8465
0
    xmlChar *ExternalID = NULL;
8466
0
    xmlChar *URI = NULL;
8467
8468
    /*
8469
     * We know that '<!DOCTYPE' has been detected.
8470
     */
8471
0
    SKIP(9);
8472
8473
0
    SKIP_BLANKS;
8474
8475
    /*
8476
     * Parse the DOCTYPE name.
8477
     */
8478
0
    name = xmlParseName(ctxt);
8479
0
    if (name == NULL) {
8480
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8481
0
           "xmlParseDocTypeDecl : no DOCTYPE name !\n");
8482
0
    }
8483
0
    ctxt->intSubName = name;
8484
8485
0
    SKIP_BLANKS;
8486
8487
    /*
8488
     * Check for SystemID and ExternalID
8489
     */
8490
0
    URI = xmlParseExternalID(ctxt, &ExternalID, 1);
8491
8492
0
    if ((URI != NULL) || (ExternalID != NULL)) {
8493
0
        ctxt->hasExternalSubset = 1;
8494
0
    }
8495
0
    ctxt->extSubURI = URI;
8496
0
    ctxt->extSubSystem = ExternalID;
8497
8498
0
    SKIP_BLANKS;
8499
8500
    /*
8501
     * Create and update the internal subset.
8502
     */
8503
0
    if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL) &&
8504
0
  (!ctxt->disableSAX))
8505
0
  ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
8506
0
    if (ctxt->instate == XML_PARSER_EOF)
8507
0
  return;
8508
8509
    /*
8510
     * Is there any internal subset declarations ?
8511
     * they are handled separately in xmlParseInternalSubset()
8512
     */
8513
0
    if (RAW == '[')
8514
0
  return;
8515
8516
    /*
8517
     * We should be at the end of the DOCTYPE declaration.
8518
     */
8519
0
    if (RAW != '>') {
8520
0
  xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
8521
0
    }
8522
0
    NEXT;
8523
0
}
8524
8525
/**
8526
 * xmlParseInternalSubset:
8527
 * @ctxt:  an XML parser context
8528
 *
8529
 * parse the internal subset declaration
8530
 *
8531
 * [28 end] ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
8532
 */
8533
8534
static void
8535
0
xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
8536
    /*
8537
     * Is there any DTD definition ?
8538
     */
8539
0
    if (RAW == '[') {
8540
0
        int baseInputNr = ctxt->inputNr;
8541
0
        ctxt->instate = XML_PARSER_DTD;
8542
0
        NEXT;
8543
  /*
8544
   * Parse the succession of Markup declarations and
8545
   * PEReferences.
8546
   * Subsequence (markupdecl | PEReference | S)*
8547
   */
8548
0
  SKIP_BLANKS;
8549
0
  while (((RAW != ']') || (ctxt->inputNr > baseInputNr)) &&
8550
0
               (ctxt->instate != XML_PARSER_EOF)) {
8551
8552
            /*
8553
             * Conditional sections are allowed from external entities included
8554
             * by PE References in the internal subset.
8555
             */
8556
0
            if ((ctxt->inputNr > 1) && (ctxt->input->filename != NULL) &&
8557
0
                (RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
8558
0
                xmlParseConditionalSections(ctxt);
8559
0
            } else if ((RAW == '<') && ((NXT(1) == '!') || (NXT(1) == '?'))) {
8560
0
          xmlParseMarkupDecl(ctxt);
8561
0
            } else if (RAW == '%') {
8562
0
          xmlParsePEReference(ctxt);
8563
0
            } else {
8564
0
    xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8565
0
                        "xmlParseInternalSubset: error detected in"
8566
0
                        " Markup declaration\n");
8567
0
                xmlHaltParser(ctxt);
8568
0
                return;
8569
0
            }
8570
0
      SKIP_BLANKS;
8571
0
            SHRINK;
8572
0
            GROW;
8573
0
  }
8574
0
  if (RAW == ']') {
8575
0
      NEXT;
8576
0
      SKIP_BLANKS;
8577
0
  }
8578
0
    }
8579
8580
    /*
8581
     * We should be at the end of the DOCTYPE declaration.
8582
     */
8583
0
    if (RAW != '>') {
8584
0
  xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
8585
0
  return;
8586
0
    }
8587
0
    NEXT;
8588
0
}
8589
8590
#ifdef LIBXML_SAX1_ENABLED
8591
/**
8592
 * xmlParseAttribute:
8593
 * @ctxt:  an XML parser context
8594
 * @value:  a xmlChar ** used to store the value of the attribute
8595
 *
8596
 * DEPRECATED: Internal function, don't use.
8597
 *
8598
 * parse an attribute
8599
 *
8600
 * [41] Attribute ::= Name Eq AttValue
8601
 *
8602
 * [ WFC: No External Entity References ]
8603
 * Attribute values cannot contain direct or indirect entity references
8604
 * to external entities.
8605
 *
8606
 * [ WFC: No < in Attribute Values ]
8607
 * The replacement text of any entity referred to directly or indirectly in
8608
 * an attribute value (other than "&lt;") must not contain a <.
8609
 *
8610
 * [ VC: Attribute Value Type ]
8611
 * The attribute must have been declared; the value must be of the type
8612
 * declared for it.
8613
 *
8614
 * [25] Eq ::= S? '=' S?
8615
 *
8616
 * With namespace:
8617
 *
8618
 * [NS 11] Attribute ::= QName Eq AttValue
8619
 *
8620
 * Also the case QName == xmlns:??? is handled independently as a namespace
8621
 * definition.
8622
 *
8623
 * Returns the attribute name, and the value in *value.
8624
 */
8625
8626
const xmlChar *
8627
77
xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
8628
77
    const xmlChar *name;
8629
77
    xmlChar *val;
8630
8631
77
    *value = NULL;
8632
77
    GROW;
8633
77
    name = xmlParseName(ctxt);
8634
77
    if (name == NULL) {
8635
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8636
0
                 "error parsing attribute name\n");
8637
0
        return(NULL);
8638
0
    }
8639
8640
    /*
8641
     * read the value
8642
     */
8643
77
    SKIP_BLANKS;
8644
77
    if (RAW == '=') {
8645
77
        NEXT;
8646
77
  SKIP_BLANKS;
8647
77
  val = xmlParseAttValue(ctxt);
8648
77
  ctxt->instate = XML_PARSER_CONTENT;
8649
77
    } else {
8650
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
8651
0
         "Specification mandates value for attribute %s\n", name);
8652
0
  return(name);
8653
0
    }
8654
8655
    /*
8656
     * Check that xml:lang conforms to the specification
8657
     * No more registered as an error, just generate a warning now
8658
     * since this was deprecated in XML second edition
8659
     */
8660
77
    if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "xml:lang"))) {
8661
0
  if (!xmlCheckLanguageID(val)) {
8662
0
      xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
8663
0
              "Malformed value for xml:lang : %s\n",
8664
0
        val, NULL);
8665
0
  }
8666
0
    }
8667
8668
    /*
8669
     * Check that xml:space conforms to the specification
8670
     */
8671
77
    if (xmlStrEqual(name, BAD_CAST "xml:space")) {
8672
0
  if (xmlStrEqual(val, BAD_CAST "default"))
8673
0
      *(ctxt->space) = 0;
8674
0
  else if (xmlStrEqual(val, BAD_CAST "preserve"))
8675
0
      *(ctxt->space) = 1;
8676
0
  else {
8677
0
    xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
8678
0
"Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
8679
0
                                 val, NULL);
8680
0
  }
8681
0
    }
8682
8683
77
    *value = val;
8684
77
    return(name);
8685
77
}
8686
8687
/**
8688
 * xmlParseStartTag:
8689
 * @ctxt:  an XML parser context
8690
 *
8691
 * DEPRECATED: Internal function, don't use.
8692
 *
8693
 * Parse a start tag. Always consumes '<'.
8694
 *
8695
 * [40] STag ::= '<' Name (S Attribute)* S? '>'
8696
 *
8697
 * [ WFC: Unique Att Spec ]
8698
 * No attribute name may appear more than once in the same start-tag or
8699
 * empty-element tag.
8700
 *
8701
 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
8702
 *
8703
 * [ WFC: Unique Att Spec ]
8704
 * No attribute name may appear more than once in the same start-tag or
8705
 * empty-element tag.
8706
 *
8707
 * With namespace:
8708
 *
8709
 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
8710
 *
8711
 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
8712
 *
8713
 * Returns the element name parsed
8714
 */
8715
8716
const xmlChar *
8717
99
xmlParseStartTag(xmlParserCtxtPtr ctxt) {
8718
99
    const xmlChar *name;
8719
99
    const xmlChar *attname;
8720
99
    xmlChar *attvalue;
8721
99
    const xmlChar **atts = ctxt->atts;
8722
99
    int nbatts = 0;
8723
99
    int maxatts = ctxt->maxatts;
8724
99
    int i;
8725
8726
99
    if (RAW != '<') return(NULL);
8727
99
    NEXT1;
8728
8729
99
    name = xmlParseName(ctxt);
8730
99
    if (name == NULL) {
8731
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8732
0
       "xmlParseStartTag: invalid element name\n");
8733
0
        return(NULL);
8734
0
    }
8735
8736
    /*
8737
     * Now parse the attributes, it ends up with the ending
8738
     *
8739
     * (S Attribute)* S?
8740
     */
8741
99
    SKIP_BLANKS;
8742
99
    GROW;
8743
8744
121
    while (((RAW != '>') &&
8745
121
     ((RAW != '/') || (NXT(1) != '>')) &&
8746
121
     (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) {
8747
77
  attname = xmlParseAttribute(ctxt, &attvalue);
8748
77
        if (attname == NULL) {
8749
0
      xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
8750
0
         "xmlParseStartTag: problem parsing attributes\n");
8751
0
      break;
8752
0
  }
8753
77
        if (attvalue != NULL) {
8754
      /*
8755
       * [ WFC: Unique Att Spec ]
8756
       * No attribute name may appear more than once in the same
8757
       * start-tag or empty-element tag.
8758
       */
8759
99
      for (i = 0; i < nbatts;i += 2) {
8760
22
          if (xmlStrEqual(atts[i], attname)) {
8761
0
        xmlErrAttributeDup(ctxt, NULL, attname);
8762
0
        xmlFree(attvalue);
8763
0
        goto failed;
8764
0
    }
8765
22
      }
8766
      /*
8767
       * Add the pair to atts
8768
       */
8769
77
      if (atts == NULL) {
8770
11
          maxatts = 22; /* allow for 10 attrs by default */
8771
11
          atts = (const xmlChar **)
8772
11
           xmlMalloc(maxatts * sizeof(xmlChar *));
8773
11
    if (atts == NULL) {
8774
0
        xmlErrMemory(ctxt, NULL);
8775
0
        if (attvalue != NULL)
8776
0
      xmlFree(attvalue);
8777
0
        goto failed;
8778
0
    }
8779
11
    ctxt->atts = atts;
8780
11
    ctxt->maxatts = maxatts;
8781
66
      } else if (nbatts + 4 > maxatts) {
8782
0
          const xmlChar **n;
8783
8784
0
          maxatts *= 2;
8785
0
          n = (const xmlChar **) xmlRealloc((void *) atts,
8786
0
               maxatts * sizeof(const xmlChar *));
8787
0
    if (n == NULL) {
8788
0
        xmlErrMemory(ctxt, NULL);
8789
0
        if (attvalue != NULL)
8790
0
      xmlFree(attvalue);
8791
0
        goto failed;
8792
0
    }
8793
0
    atts = n;
8794
0
    ctxt->atts = atts;
8795
0
    ctxt->maxatts = maxatts;
8796
0
      }
8797
77
      atts[nbatts++] = attname;
8798
77
      atts[nbatts++] = attvalue;
8799
77
      atts[nbatts] = NULL;
8800
77
      atts[nbatts + 1] = NULL;
8801
77
  } else {
8802
0
      if (attvalue != NULL)
8803
0
    xmlFree(attvalue);
8804
0
  }
8805
8806
77
failed:
8807
8808
77
  GROW
8809
77
  if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
8810
55
      break;
8811
22
  if (SKIP_BLANKS == 0) {
8812
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
8813
0
         "attributes construct error\n");
8814
0
  }
8815
22
  SHRINK;
8816
22
        GROW;
8817
22
    }
8818
8819
    /*
8820
     * SAX: Start of Element !
8821
     */
8822
99
    if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL) &&
8823
99
  (!ctxt->disableSAX)) {
8824
99
  if (nbatts > 0)
8825
55
      ctxt->sax->startElement(ctxt->userData, name, atts);
8826
44
  else
8827
44
      ctxt->sax->startElement(ctxt->userData, name, NULL);
8828
99
    }
8829
8830
99
    if (atts != NULL) {
8831
        /* Free only the content strings */
8832
143
        for (i = 1;i < nbatts;i+=2)
8833
77
      if (atts[i] != NULL)
8834
77
         xmlFree((xmlChar *) atts[i]);
8835
66
    }
8836
99
    return(name);
8837
99
}
8838
8839
/**
8840
 * xmlParseEndTag1:
8841
 * @ctxt:  an XML parser context
8842
 * @line:  line of the start tag
8843
 * @nsNr:  number of namespaces on the start tag
8844
 *
8845
 * Parse an end tag. Always consumes '</'.
8846
 *
8847
 * [42] ETag ::= '</' Name S? '>'
8848
 *
8849
 * With namespace
8850
 *
8851
 * [NS 9] ETag ::= '</' QName S? '>'
8852
 */
8853
8854
static void
8855
99
xmlParseEndTag1(xmlParserCtxtPtr ctxt, int line) {
8856
99
    const xmlChar *name;
8857
8858
99
    GROW;
8859
99
    if ((RAW != '<') || (NXT(1) != '/')) {
8860
0
  xmlFatalErrMsg(ctxt, XML_ERR_LTSLASH_REQUIRED,
8861
0
           "xmlParseEndTag: '</' not found\n");
8862
0
  return;
8863
0
    }
8864
99
    SKIP(2);
8865
8866
99
    name = xmlParseNameAndCompare(ctxt,ctxt->name);
8867
8868
    /*
8869
     * We should definitely be at the ending "S? '>'" part
8870
     */
8871
99
    GROW;
8872
99
    SKIP_BLANKS;
8873
99
    if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
8874
0
  xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
8875
0
    } else
8876
99
  NEXT1;
8877
8878
    /*
8879
     * [ WFC: Element Type Match ]
8880
     * The Name in an element's end-tag must match the element type in the
8881
     * start-tag.
8882
     *
8883
     */
8884
99
    if (name != (xmlChar*)1) {
8885
0
        if (name == NULL) name = BAD_CAST "unparsable";
8886
0
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
8887
0
         "Opening and ending tag mismatch: %s line %d and %s\n",
8888
0
                    ctxt->name, line, name);
8889
0
    }
8890
8891
    /*
8892
     * SAX: End of Tag
8893
     */
8894
99
    if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
8895
99
  (!ctxt->disableSAX))
8896
99
        ctxt->sax->endElement(ctxt->userData, ctxt->name);
8897
8898
99
    namePop(ctxt);
8899
99
    spacePop(ctxt);
8900
99
    return;
8901
99
}
8902
8903
/**
8904
 * xmlParseEndTag:
8905
 * @ctxt:  an XML parser context
8906
 *
8907
 * DEPRECATED: Internal function, don't use.
8908
 *
8909
 * parse an end of tag
8910
 *
8911
 * [42] ETag ::= '</' Name S? '>'
8912
 *
8913
 * With namespace
8914
 *
8915
 * [NS 9] ETag ::= '</' QName S? '>'
8916
 */
8917
8918
void
8919
0
xmlParseEndTag(xmlParserCtxtPtr ctxt) {
8920
0
    xmlParseEndTag1(ctxt, 0);
8921
0
}
8922
#endif /* LIBXML_SAX1_ENABLED */
8923
8924
/************************************************************************
8925
 *                  *
8926
 *          SAX 2 specific operations       *
8927
 *                  *
8928
 ************************************************************************/
8929
8930
/**
8931
 * xmlParseQNameHashed:
8932
 * @ctxt:  an XML parser context
8933
 * @prefix:  pointer to store the prefix part
8934
 *
8935
 * parse an XML Namespace QName
8936
 *
8937
 * [6]  QName  ::= (Prefix ':')? LocalPart
8938
 * [7]  Prefix  ::= NCName
8939
 * [8]  LocalPart  ::= NCName
8940
 *
8941
 * Returns the Name parsed or NULL
8942
 */
8943
8944
static xmlHashedString
8945
0
xmlParseQNameHashed(xmlParserCtxtPtr ctxt, xmlHashedString *prefix) {
8946
0
    xmlHashedString l, p;
8947
0
    int start, isNCName = 0;
8948
8949
0
    l.name = NULL;
8950
0
    p.name = NULL;
8951
8952
0
    GROW;
8953
0
    if (ctxt->instate == XML_PARSER_EOF)
8954
0
        return(l);
8955
0
    start = CUR_PTR - BASE_PTR;
8956
8957
0
    l = xmlParseNCName(ctxt);
8958
0
    if (l.name != NULL) {
8959
0
        isNCName = 1;
8960
0
        if (CUR == ':') {
8961
0
            NEXT;
8962
0
            p = l;
8963
0
            l = xmlParseNCName(ctxt);
8964
0
        }
8965
0
    }
8966
0
    if ((l.name == NULL) || (CUR == ':')) {
8967
0
        xmlChar *tmp;
8968
8969
0
        l.name = NULL;
8970
0
        p.name = NULL;
8971
0
        if (ctxt->instate == XML_PARSER_EOF)
8972
0
            return(l);
8973
0
        if ((isNCName == 0) && (CUR != ':'))
8974
0
            return(l);
8975
0
        tmp = xmlParseNmtoken(ctxt);
8976
0
        if (tmp != NULL)
8977
0
            xmlFree(tmp);
8978
0
        if (ctxt->instate == XML_PARSER_EOF)
8979
0
            return(l);
8980
0
        l = xmlDictLookupHashed(ctxt->dict, BASE_PTR + start,
8981
0
                                CUR_PTR - (BASE_PTR + start));
8982
0
        xmlNsErr(ctxt, XML_NS_ERR_QNAME,
8983
0
                 "Failed to parse QName '%s'\n", l.name, NULL, NULL);
8984
0
    }
8985
8986
0
    *prefix = p;
8987
0
    return(l);
8988
0
}
8989
8990
/**
8991
 * xmlParseQName:
8992
 * @ctxt:  an XML parser context
8993
 * @prefix:  pointer to store the prefix part
8994
 *
8995
 * parse an XML Namespace QName
8996
 *
8997
 * [6]  QName  ::= (Prefix ':')? LocalPart
8998
 * [7]  Prefix  ::= NCName
8999
 * [8]  LocalPart  ::= NCName
9000
 *
9001
 * Returns the Name parsed or NULL
9002
 */
9003
9004
static const xmlChar *
9005
0
xmlParseQName(xmlParserCtxtPtr ctxt, const xmlChar **prefix) {
9006
0
    xmlHashedString n, p;
9007
9008
0
    n = xmlParseQNameHashed(ctxt, &p);
9009
0
    if (n.name == NULL)
9010
0
        return(NULL);
9011
0
    *prefix = p.name;
9012
0
    return(n.name);
9013
0
}
9014
9015
/**
9016
 * xmlParseQNameAndCompare:
9017
 * @ctxt:  an XML parser context
9018
 * @name:  the localname
9019
 * @prefix:  the prefix, if any.
9020
 *
9021
 * parse an XML name and compares for match
9022
 * (specialized for endtag parsing)
9023
 *
9024
 * Returns NULL for an illegal name, (xmlChar*) 1 for success
9025
 * and the name for mismatch
9026
 */
9027
9028
static const xmlChar *
9029
xmlParseQNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *name,
9030
0
                        xmlChar const *prefix) {
9031
0
    const xmlChar *cmp;
9032
0
    const xmlChar *in;
9033
0
    const xmlChar *ret;
9034
0
    const xmlChar *prefix2;
9035
9036
0
    if (prefix == NULL) return(xmlParseNameAndCompare(ctxt, name));
9037
9038
0
    GROW;
9039
0
    in = ctxt->input->cur;
9040
9041
0
    cmp = prefix;
9042
0
    while (*in != 0 && *in == *cmp) {
9043
0
  ++in;
9044
0
  ++cmp;
9045
0
    }
9046
0
    if ((*cmp == 0) && (*in == ':')) {
9047
0
        in++;
9048
0
  cmp = name;
9049
0
  while (*in != 0 && *in == *cmp) {
9050
0
      ++in;
9051
0
      ++cmp;
9052
0
  }
9053
0
  if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
9054
      /* success */
9055
0
            ctxt->input->col += in - ctxt->input->cur;
9056
0
      ctxt->input->cur = in;
9057
0
      return((const xmlChar*) 1);
9058
0
  }
9059
0
    }
9060
    /*
9061
     * all strings coms from the dictionary, equality can be done directly
9062
     */
9063
0
    ret = xmlParseQName (ctxt, &prefix2);
9064
0
    if (ret == NULL)
9065
0
        return(NULL);
9066
0
    if ((ret == name) && (prefix == prefix2))
9067
0
  return((const xmlChar*) 1);
9068
0
    return ret;
9069
0
}
9070
9071
/**
9072
 * xmlParseAttValueInternal:
9073
 * @ctxt:  an XML parser context
9074
 * @len:  attribute len result
9075
 * @alloc:  whether the attribute was reallocated as a new string
9076
 * @normalize:  if 1 then further non-CDATA normalization must be done
9077
 *
9078
 * parse a value for an attribute.
9079
 * NOTE: if no normalization is needed, the routine will return pointers
9080
 *       directly from the data buffer.
9081
 *
9082
 * 3.3.3 Attribute-Value Normalization:
9083
 * Before the value of an attribute is passed to the application or
9084
 * checked for validity, the XML processor must normalize it as follows:
9085
 * - a character reference is processed by appending the referenced
9086
 *   character to the attribute value
9087
 * - an entity reference is processed by recursively processing the
9088
 *   replacement text of the entity
9089
 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
9090
 *   appending #x20 to the normalized value, except that only a single
9091
 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
9092
 *   parsed entity or the literal entity value of an internal parsed entity
9093
 * - other characters are processed by appending them to the normalized value
9094
 * If the declared value is not CDATA, then the XML processor must further
9095
 * process the normalized attribute value by discarding any leading and
9096
 * trailing space (#x20) characters, and by replacing sequences of space
9097
 * (#x20) characters by a single space (#x20) character.
9098
 * All attributes for which no declaration has been read should be treated
9099
 * by a non-validating parser as if declared CDATA.
9100
 *
9101
 * Returns the AttValue parsed or NULL. The value has to be freed by the
9102
 *     caller if it was copied, this can be detected by val[*len] == 0.
9103
 */
9104
9105
#define GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end) \
9106
0
    const xmlChar *oldbase = ctxt->input->base;\
9107
0
    GROW;\
9108
0
    if (ctxt->instate == XML_PARSER_EOF)\
9109
0
        return(NULL);\
9110
0
    if (oldbase != ctxt->input->base) {\
9111
0
        ptrdiff_t delta = ctxt->input->base - oldbase;\
9112
0
        start = start + delta;\
9113
0
        in = in + delta;\
9114
0
    }\
9115
0
    end = ctxt->input->end;
9116
9117
static xmlChar *
9118
xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
9119
                         int normalize)
9120
77
{
9121
77
    xmlChar limit = 0;
9122
77
    const xmlChar *in = NULL, *start, *end, *last;
9123
77
    xmlChar *ret = NULL;
9124
77
    int line, col;
9125
77
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
9126
0
                    XML_MAX_HUGE_LENGTH :
9127
77
                    XML_MAX_TEXT_LENGTH;
9128
9129
77
    GROW;
9130
77
    in = (xmlChar *) CUR_PTR;
9131
77
    line = ctxt->input->line;
9132
77
    col = ctxt->input->col;
9133
77
    if (*in != '"' && *in != '\'') {
9134
0
        xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
9135
0
        return (NULL);
9136
0
    }
9137
77
    ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
9138
9139
    /*
9140
     * try to handle in this routine the most common case where no
9141
     * allocation of a new string is required and where content is
9142
     * pure ASCII.
9143
     */
9144
77
    limit = *in++;
9145
77
    col++;
9146
77
    end = ctxt->input->end;
9147
77
    start = in;
9148
77
    if (in >= end) {
9149
0
        GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
9150
0
    }
9151
77
    if (normalize) {
9152
        /*
9153
   * Skip any leading spaces
9154
   */
9155
0
  while ((in < end) && (*in != limit) &&
9156
0
         ((*in == 0x20) || (*in == 0x9) ||
9157
0
          (*in == 0xA) || (*in == 0xD))) {
9158
0
      if (*in == 0xA) {
9159
0
          line++; col = 1;
9160
0
      } else {
9161
0
          col++;
9162
0
      }
9163
0
      in++;
9164
0
      start = in;
9165
0
      if (in >= end) {
9166
0
                GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
9167
0
                if ((in - start) > maxLength) {
9168
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9169
0
                                   "AttValue length too long\n");
9170
0
                    return(NULL);
9171
0
                }
9172
0
      }
9173
0
  }
9174
0
  while ((in < end) && (*in != limit) && (*in >= 0x20) &&
9175
0
         (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
9176
0
      col++;
9177
0
      if ((*in++ == 0x20) && (*in == 0x20)) break;
9178
0
      if (in >= end) {
9179
0
                GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
9180
0
                if ((in - start) > maxLength) {
9181
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9182
0
                                   "AttValue length too long\n");
9183
0
                    return(NULL);
9184
0
                }
9185
0
      }
9186
0
  }
9187
0
  last = in;
9188
  /*
9189
   * skip the trailing blanks
9190
   */
9191
0
  while ((last[-1] == 0x20) && (last > start)) last--;
9192
0
  while ((in < end) && (*in != limit) &&
9193
0
         ((*in == 0x20) || (*in == 0x9) ||
9194
0
          (*in == 0xA) || (*in == 0xD))) {
9195
0
      if (*in == 0xA) {
9196
0
          line++, col = 1;
9197
0
      } else {
9198
0
          col++;
9199
0
      }
9200
0
      in++;
9201
0
      if (in >= end) {
9202
0
    const xmlChar *oldbase = ctxt->input->base;
9203
0
    GROW;
9204
0
                if (ctxt->instate == XML_PARSER_EOF)
9205
0
                    return(NULL);
9206
0
    if (oldbase != ctxt->input->base) {
9207
0
        ptrdiff_t delta = ctxt->input->base - oldbase;
9208
0
        start = start + delta;
9209
0
        in = in + delta;
9210
0
        last = last + delta;
9211
0
    }
9212
0
    end = ctxt->input->end;
9213
0
                if ((in - start) > maxLength) {
9214
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9215
0
                                   "AttValue length too long\n");
9216
0
                    return(NULL);
9217
0
                }
9218
0
      }
9219
0
  }
9220
0
        if ((in - start) > maxLength) {
9221
0
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9222
0
                           "AttValue length too long\n");
9223
0
            return(NULL);
9224
0
        }
9225
0
  if (*in != limit) goto need_complex;
9226
77
    } else {
9227
308
  while ((in < end) && (*in != limit) && (*in >= 0x20) &&
9228
308
         (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
9229
231
      in++;
9230
231
      col++;
9231
231
      if (in >= end) {
9232
0
                GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
9233
0
                if ((in - start) > maxLength) {
9234
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9235
0
                                   "AttValue length too long\n");
9236
0
                    return(NULL);
9237
0
                }
9238
0
      }
9239
231
  }
9240
77
  last = in;
9241
77
        if ((in - start) > maxLength) {
9242
0
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9243
0
                           "AttValue length too long\n");
9244
0
            return(NULL);
9245
0
        }
9246
77
  if (*in != limit) goto need_complex;
9247
77
    }
9248
77
    in++;
9249
77
    col++;
9250
77
    if (len != NULL) {
9251
0
        if (alloc) *alloc = 0;
9252
0
        *len = last - start;
9253
0
        ret = (xmlChar *) start;
9254
77
    } else {
9255
77
        if (alloc) *alloc = 1;
9256
77
        ret = xmlStrndup(start, last - start);
9257
77
    }
9258
77
    CUR_PTR = in;
9259
77
    ctxt->input->line = line;
9260
77
    ctxt->input->col = col;
9261
77
    return ret;
9262
0
need_complex:
9263
0
    if (alloc) *alloc = 1;
9264
0
    return xmlParseAttValueComplex(ctxt, len, normalize);
9265
77
}
9266
9267
/**
9268
 * xmlParseAttribute2:
9269
 * @ctxt:  an XML parser context
9270
 * @pref:  the element prefix
9271
 * @elem:  the element name
9272
 * @prefix:  a xmlChar ** used to store the value of the attribute prefix
9273
 * @value:  a xmlChar ** used to store the value of the attribute
9274
 * @len:  an int * to save the length of the attribute
9275
 * @alloc:  an int * to indicate if the attribute was allocated
9276
 *
9277
 * parse an attribute in the new SAX2 framework.
9278
 *
9279
 * Returns the attribute name, and the value in *value, .
9280
 */
9281
9282
static xmlHashedString
9283
xmlParseAttribute2(xmlParserCtxtPtr ctxt,
9284
                   const xmlChar * pref, const xmlChar * elem,
9285
                   xmlHashedString * hprefix, xmlChar ** value,
9286
                   int *len, int *alloc)
9287
0
{
9288
0
    xmlHashedString hname;
9289
0
    const xmlChar *prefix, *name;
9290
0
    xmlChar *val, *internal_val = NULL;
9291
0
    int normalize = 0;
9292
9293
0
    *value = NULL;
9294
0
    GROW;
9295
0
    hname = xmlParseQNameHashed(ctxt, hprefix);
9296
0
    if (hname.name == NULL) {
9297
0
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
9298
0
                       "error parsing attribute name\n");
9299
0
        return(hname);
9300
0
    }
9301
0
    name = hname.name;
9302
0
    if (hprefix->name != NULL)
9303
0
        prefix = hprefix->name;
9304
0
    else
9305
0
        prefix = NULL;
9306
9307
    /*
9308
     * get the type if needed
9309
     */
9310
0
    if (ctxt->attsSpecial != NULL) {
9311
0
        int type;
9312
9313
0
        type = (int) (ptrdiff_t) xmlHashQLookup2(ctxt->attsSpecial,
9314
0
                                                 pref, elem,
9315
0
                                                 prefix, name);
9316
0
        if (type != 0)
9317
0
            normalize = 1;
9318
0
    }
9319
9320
    /*
9321
     * read the value
9322
     */
9323
0
    SKIP_BLANKS;
9324
0
    if (RAW == '=') {
9325
0
        NEXT;
9326
0
        SKIP_BLANKS;
9327
0
        val = xmlParseAttValueInternal(ctxt, len, alloc, normalize);
9328
0
        if (val == NULL) {
9329
0
            hname.name = NULL;
9330
0
            return(hname);
9331
0
        }
9332
0
  if (normalize) {
9333
      /*
9334
       * Sometimes a second normalisation pass for spaces is needed
9335
       * but that only happens if charrefs or entities references
9336
       * have been used in the attribute value, i.e. the attribute
9337
       * value have been extracted in an allocated string already.
9338
       */
9339
0
      if (*alloc) {
9340
0
          const xmlChar *val2;
9341
9342
0
          val2 = xmlAttrNormalizeSpace2(ctxt, val, len);
9343
0
    if ((val2 != NULL) && (val2 != val)) {
9344
0
        xmlFree(val);
9345
0
        val = (xmlChar *) val2;
9346
0
    }
9347
0
      }
9348
0
  }
9349
0
        ctxt->instate = XML_PARSER_CONTENT;
9350
0
    } else {
9351
0
        xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
9352
0
                          "Specification mandates value for attribute %s\n",
9353
0
                          name);
9354
0
        return(hname);
9355
0
    }
9356
9357
0
    if (prefix == ctxt->str_xml) {
9358
        /*
9359
         * Check that xml:lang conforms to the specification
9360
         * No more registered as an error, just generate a warning now
9361
         * since this was deprecated in XML second edition
9362
         */
9363
0
        if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "lang"))) {
9364
0
            internal_val = xmlStrndup(val, *len);
9365
0
            if (!xmlCheckLanguageID(internal_val)) {
9366
0
                xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
9367
0
                              "Malformed value for xml:lang : %s\n",
9368
0
                              internal_val, NULL);
9369
0
            }
9370
0
        }
9371
9372
        /*
9373
         * Check that xml:space conforms to the specification
9374
         */
9375
0
        if (xmlStrEqual(name, BAD_CAST "space")) {
9376
0
            internal_val = xmlStrndup(val, *len);
9377
0
            if (xmlStrEqual(internal_val, BAD_CAST "default"))
9378
0
                *(ctxt->space) = 0;
9379
0
            else if (xmlStrEqual(internal_val, BAD_CAST "preserve"))
9380
0
                *(ctxt->space) = 1;
9381
0
            else {
9382
0
                xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
9383
0
                              "Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
9384
0
                              internal_val, NULL);
9385
0
            }
9386
0
        }
9387
0
        if (internal_val) {
9388
0
            xmlFree(internal_val);
9389
0
        }
9390
0
    }
9391
9392
0
    *value = val;
9393
0
    return (hname);
9394
0
}
9395
9396
/**
9397
 * xmlAttrHashInsert:
9398
 * @ctxt: parser context
9399
 * @size: size of the hash table
9400
 * @name: attribute name
9401
 * @uri: namespace uri
9402
 * @hashValue: combined hash value of name and uri
9403
 * @aindex: attribute index (this is a multiple of 5)
9404
 *
9405
 * Inserts a new attribute into the hash table.
9406
 *
9407
 * Returns INT_MAX if no existing attribute was found, the attribute
9408
 * index if an attribute was found, -1 if a memory allocation failed.
9409
 */
9410
static int
9411
xmlAttrHashInsert(xmlParserCtxtPtr ctxt, unsigned size, const xmlChar *name,
9412
0
                  const xmlChar *uri, unsigned hashValue, int aindex) {
9413
0
    xmlAttrHashBucket *table = ctxt->attrHash;
9414
0
    xmlAttrHashBucket *bucket;
9415
0
    unsigned hindex;
9416
9417
0
    hindex = hashValue & (size - 1);
9418
0
    bucket = &table[hindex];
9419
9420
0
    while (bucket->index >= 0) {
9421
0
        const xmlChar **atts = &ctxt->atts[bucket->index];
9422
9423
0
        if (name == atts[0]) {
9424
0
            int nsIndex = (int) (ptrdiff_t) atts[2];
9425
9426
0
            if ((nsIndex == NS_INDEX_EMPTY) ? (uri == NULL) :
9427
0
                (nsIndex == NS_INDEX_XML) ? (uri == ctxt->str_xml_ns) :
9428
0
                (uri == ctxt->nsTab[nsIndex * 2 + 1]))
9429
0
                return(bucket->index);
9430
0
        }
9431
9432
0
        hindex++;
9433
0
        bucket++;
9434
0
        if (hindex >= size) {
9435
0
            hindex = 0;
9436
0
            bucket = table;
9437
0
        }
9438
0
    }
9439
9440
0
    bucket->index = aindex;
9441
9442
0
    return(INT_MAX);
9443
0
}
9444
9445
/**
9446
 * xmlParseStartTag2:
9447
 * @ctxt:  an XML parser context
9448
 *
9449
 * Parse a start tag. Always consumes '<'.
9450
 *
9451
 * This routine is called when running SAX2 parsing
9452
 *
9453
 * [40] STag ::= '<' Name (S Attribute)* S? '>'
9454
 *
9455
 * [ WFC: Unique Att Spec ]
9456
 * No attribute name may appear more than once in the same start-tag or
9457
 * empty-element tag.
9458
 *
9459
 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
9460
 *
9461
 * [ WFC: Unique Att Spec ]
9462
 * No attribute name may appear more than once in the same start-tag or
9463
 * empty-element tag.
9464
 *
9465
 * With namespace:
9466
 *
9467
 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
9468
 *
9469
 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
9470
 *
9471
 * Returns the element name parsed
9472
 */
9473
9474
static const xmlChar *
9475
xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
9476
0
                  const xmlChar **URI, int *nbNsPtr) {
9477
0
    xmlHashedString hlocalname;
9478
0
    xmlHashedString hprefix;
9479
0
    xmlHashedString hattname;
9480
0
    xmlHashedString haprefix;
9481
0
    const xmlChar *localname;
9482
0
    const xmlChar *prefix;
9483
0
    const xmlChar *attname;
9484
0
    const xmlChar *aprefix;
9485
0
    const xmlChar *uri;
9486
0
    xmlChar *attvalue = NULL;
9487
0
    const xmlChar **atts = ctxt->atts;
9488
0
    unsigned attrHashSize = 0;
9489
0
    int maxatts = ctxt->maxatts;
9490
0
    int nratts, nbatts, nbdef, inputid;
9491
0
    int i, j, nbNs, nbTotalDef, attval, nsIndex, maxAtts;
9492
0
    int alloc = 0;
9493
9494
0
    if (RAW != '<') return(NULL);
9495
0
    NEXT1;
9496
9497
0
    inputid = ctxt->input->id;
9498
0
    nbatts = 0;
9499
0
    nratts = 0;
9500
0
    nbdef = 0;
9501
0
    nbNs = 0;
9502
0
    nbTotalDef = 0;
9503
0
    attval = 0;
9504
9505
0
    if (xmlParserNsStartElement(ctxt->nsdb) < 0) {
9506
0
        xmlErrMemory(ctxt, NULL);
9507
0
        return(NULL);
9508
0
    }
9509
9510
0
    hlocalname = xmlParseQNameHashed(ctxt, &hprefix);
9511
0
    if (hlocalname.name == NULL) {
9512
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
9513
0
           "StartTag: invalid element name\n");
9514
0
        return(NULL);
9515
0
    }
9516
0
    localname = hlocalname.name;
9517
0
    prefix = hprefix.name;
9518
9519
    /*
9520
     * Now parse the attributes, it ends up with the ending
9521
     *
9522
     * (S Attribute)* S?
9523
     */
9524
0
    SKIP_BLANKS;
9525
0
    GROW;
9526
9527
    /*
9528
     * The ctxt->atts array will be ultimately passed to the SAX callback
9529
     * containing five xmlChar pointers for each attribute:
9530
     *
9531
     * [0] attribute name
9532
     * [1] attribute prefix
9533
     * [2] namespace URI
9534
     * [3] attribute value
9535
     * [4] end of attribute value
9536
     *
9537
     * To save memory, we reuse this array temporarily and store integers
9538
     * in these pointer variables.
9539
     *
9540
     * [0] attribute name
9541
     * [1] attribute prefix
9542
     * [2] hash value of attribute prefix, and later namespace index
9543
     * [3] for non-allocated values: ptrdiff_t offset into input buffer
9544
     * [4] for non-allocated values: ptrdiff_t offset into input buffer
9545
     *
9546
     * The ctxt->attallocs array contains an additional unsigned int for
9547
     * each attribute, containing the hash value of the attribute name
9548
     * and the alloc flag in bit 31.
9549
     */
9550
9551
0
    while (((RAW != '>') &&
9552
0
     ((RAW != '/') || (NXT(1) != '>')) &&
9553
0
     (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) {
9554
0
  int len = -1;
9555
9556
0
  hattname = xmlParseAttribute2(ctxt, prefix, localname,
9557
0
                                          &haprefix, &attvalue, &len,
9558
0
                                          &alloc);
9559
0
        if (hattname.name == NULL) {
9560
0
      xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
9561
0
           "xmlParseStartTag: problem parsing attributes\n");
9562
0
      break;
9563
0
  }
9564
0
        if (attvalue == NULL)
9565
0
            goto next_attr;
9566
0
        attname = hattname.name;
9567
0
        aprefix = haprefix.name;
9568
0
  if (len < 0) len = xmlStrlen(attvalue);
9569
9570
0
        if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
9571
0
            xmlHashedString huri;
9572
0
            xmlURIPtr parsedUri;
9573
9574
0
            huri = xmlDictLookupHashed(ctxt->dict, attvalue, len);
9575
0
            uri = huri.name;
9576
0
            if (uri == NULL) {
9577
0
                xmlErrMemory(ctxt, NULL);
9578
0
                goto next_attr;
9579
0
            }
9580
0
            if (*uri != 0) {
9581
0
                parsedUri = xmlParseURI((const char *) uri);
9582
0
                if (parsedUri == NULL) {
9583
0
                    xmlNsErr(ctxt, XML_WAR_NS_URI,
9584
0
                             "xmlns: '%s' is not a valid URI\n",
9585
0
                                       uri, NULL, NULL);
9586
0
                } else {
9587
0
                    if (parsedUri->scheme == NULL) {
9588
0
                        xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
9589
0
                                  "xmlns: URI %s is not absolute\n",
9590
0
                                  uri, NULL, NULL);
9591
0
                    }
9592
0
                    xmlFreeURI(parsedUri);
9593
0
                }
9594
0
                if (uri == ctxt->str_xml_ns) {
9595
0
                    if (attname != ctxt->str_xml) {
9596
0
                        xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9597
0
                     "xml namespace URI cannot be the default namespace\n",
9598
0
                                 NULL, NULL, NULL);
9599
0
                    }
9600
0
                    goto next_attr;
9601
0
                }
9602
0
                if ((len == 29) &&
9603
0
                    (xmlStrEqual(uri,
9604
0
                             BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
9605
0
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9606
0
                         "reuse of the xmlns namespace name is forbidden\n",
9607
0
                             NULL, NULL, NULL);
9608
0
                    goto next_attr;
9609
0
                }
9610
0
            }
9611
9612
0
            if (xmlParserNsPush(ctxt, NULL, &huri, NULL, 0) > 0)
9613
0
                nbNs++;
9614
0
        } else if (aprefix == ctxt->str_xmlns) {
9615
0
            xmlHashedString huri;
9616
0
            xmlURIPtr parsedUri;
9617
9618
0
            huri = xmlDictLookupHashed(ctxt->dict, attvalue, len);
9619
0
            uri = huri.name;
9620
0
            if (uri == NULL) {
9621
0
                xmlErrMemory(ctxt, NULL);
9622
0
                goto next_attr;
9623
0
            }
9624
9625
0
            if (attname == ctxt->str_xml) {
9626
0
                if (uri != ctxt->str_xml_ns) {
9627
0
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9628
0
                             "xml namespace prefix mapped to wrong URI\n",
9629
0
                             NULL, NULL, NULL);
9630
0
                }
9631
                /*
9632
                 * Do not keep a namespace definition node
9633
                 */
9634
0
                goto next_attr;
9635
0
            }
9636
0
            if (uri == ctxt->str_xml_ns) {
9637
0
                if (attname != ctxt->str_xml) {
9638
0
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9639
0
                             "xml namespace URI mapped to wrong prefix\n",
9640
0
                             NULL, NULL, NULL);
9641
0
                }
9642
0
                goto next_attr;
9643
0
            }
9644
0
            if (attname == ctxt->str_xmlns) {
9645
0
                xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9646
0
                         "redefinition of the xmlns prefix is forbidden\n",
9647
0
                         NULL, NULL, NULL);
9648
0
                goto next_attr;
9649
0
            }
9650
0
            if ((len == 29) &&
9651
0
                (xmlStrEqual(uri,
9652
0
                             BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
9653
0
                xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9654
0
                         "reuse of the xmlns namespace name is forbidden\n",
9655
0
                         NULL, NULL, NULL);
9656
0
                goto next_attr;
9657
0
            }
9658
0
            if ((uri == NULL) || (uri[0] == 0)) {
9659
0
                xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9660
0
                         "xmlns:%s: Empty XML namespace is not allowed\n",
9661
0
                              attname, NULL, NULL);
9662
0
                goto next_attr;
9663
0
            } else {
9664
0
                parsedUri = xmlParseURI((const char *) uri);
9665
0
                if (parsedUri == NULL) {
9666
0
                    xmlNsErr(ctxt, XML_WAR_NS_URI,
9667
0
                         "xmlns:%s: '%s' is not a valid URI\n",
9668
0
                                       attname, uri, NULL);
9669
0
                } else {
9670
0
                    if ((ctxt->pedantic) && (parsedUri->scheme == NULL)) {
9671
0
                        xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
9672
0
                                  "xmlns:%s: URI %s is not absolute\n",
9673
0
                                  attname, uri, NULL);
9674
0
                    }
9675
0
                    xmlFreeURI(parsedUri);
9676
0
                }
9677
0
            }
9678
9679
0
            if (xmlParserNsPush(ctxt, &hattname, &huri, NULL, 0) > 0)
9680
0
                nbNs++;
9681
0
        } else {
9682
            /*
9683
             * Populate attributes array, see above for repurposing
9684
             * of xmlChar pointers.
9685
             */
9686
0
            if ((atts == NULL) || (nbatts + 5 > maxatts)) {
9687
0
                if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
9688
0
                    goto next_attr;
9689
0
                }
9690
0
                maxatts = ctxt->maxatts;
9691
0
                atts = ctxt->atts;
9692
0
            }
9693
0
            ctxt->attallocs[nratts++] = (hattname.hashValue & 0x7FFFFFFF) |
9694
0
                                        ((unsigned) alloc << 31);
9695
0
            atts[nbatts++] = attname;
9696
0
            atts[nbatts++] = aprefix;
9697
0
            atts[nbatts++] = (const xmlChar *) (size_t) haprefix.hashValue;
9698
0
            if (alloc) {
9699
0
                atts[nbatts++] = attvalue;
9700
0
                attvalue += len;
9701
0
                atts[nbatts++] = attvalue;
9702
0
            } else {
9703
                /*
9704
                 * attvalue points into the input buffer which can be
9705
                 * reallocated. Store differences to input->base instead.
9706
                 * The pointers will be reconstructed later.
9707
                 */
9708
0
                atts[nbatts++] = (void *) (attvalue - BASE_PTR);
9709
0
                attvalue += len;
9710
0
                atts[nbatts++] = (void *) (attvalue - BASE_PTR);
9711
0
            }
9712
            /*
9713
             * tag if some deallocation is needed
9714
             */
9715
0
            if (alloc != 0) attval = 1;
9716
0
            attvalue = NULL; /* moved into atts */
9717
0
        }
9718
9719
0
next_attr:
9720
0
        if ((attvalue != NULL) && (alloc != 0)) {
9721
0
            xmlFree(attvalue);
9722
0
            attvalue = NULL;
9723
0
        }
9724
9725
0
  GROW
9726
0
        if (ctxt->instate == XML_PARSER_EOF)
9727
0
            break;
9728
0
  if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
9729
0
      break;
9730
0
  if (SKIP_BLANKS == 0) {
9731
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
9732
0
         "attributes construct error\n");
9733
0
      break;
9734
0
  }
9735
0
        GROW;
9736
0
    }
9737
9738
0
    if (ctxt->input->id != inputid) {
9739
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
9740
0
                    "Unexpected change of input\n");
9741
0
        localname = NULL;
9742
0
        goto done;
9743
0
    }
9744
9745
    /*
9746
     * Namespaces from default attributes
9747
     */
9748
0
    if (ctxt->attsDefault != NULL) {
9749
0
        xmlDefAttrsPtr defaults;
9750
9751
0
  defaults = xmlHashLookup2(ctxt->attsDefault, localname, prefix);
9752
0
  if (defaults != NULL) {
9753
0
      for (i = 0; i < defaults->nbAttrs; i++) {
9754
0
                xmlDefAttr *attr = &defaults->attrs[i];
9755
9756
0
          attname = attr->name.name;
9757
0
    aprefix = attr->prefix.name;
9758
9759
0
    if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
9760
0
                    xmlParserEntityCheck(ctxt, attr->expandedSize);
9761
9762
0
                    if (xmlParserNsPush(ctxt, NULL, &attr->value, NULL, 1) > 0)
9763
0
                        nbNs++;
9764
0
    } else if (aprefix == ctxt->str_xmlns) {
9765
0
                    xmlParserEntityCheck(ctxt, attr->expandedSize);
9766
9767
0
                    if (xmlParserNsPush(ctxt, &attr->name, &attr->value,
9768
0
                                      NULL, 1) > 0)
9769
0
                        nbNs++;
9770
0
    } else {
9771
0
                    nbTotalDef += 1;
9772
0
                }
9773
0
      }
9774
0
  }
9775
0
    }
9776
9777
    /*
9778
     * Resolve attribute namespaces
9779
     */
9780
0
    for (i = 0; i < nbatts; i += 5) {
9781
0
        attname = atts[i];
9782
0
        aprefix = atts[i+1];
9783
9784
        /*
9785
  * The default namespace does not apply to attribute names.
9786
  */
9787
0
  if (aprefix == NULL) {
9788
0
            nsIndex = NS_INDEX_EMPTY;
9789
0
        } else if (aprefix == ctxt->str_xml) {
9790
0
            nsIndex = NS_INDEX_XML;
9791
0
        } else {
9792
0
            haprefix.name = aprefix;
9793
0
            haprefix.hashValue = (size_t) atts[i+2];
9794
0
            nsIndex = xmlParserNsLookup(ctxt, &haprefix, NULL);
9795
0
      if (nsIndex == INT_MAX) {
9796
0
                xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
9797
0
        "Namespace prefix %s for %s on %s is not defined\n",
9798
0
        aprefix, attname, localname);
9799
0
                nsIndex = NS_INDEX_EMPTY;
9800
0
            }
9801
0
        }
9802
9803
0
        atts[i+2] = (const xmlChar *) (ptrdiff_t) nsIndex;
9804
0
    }
9805
9806
    /*
9807
     * Maximum number of attributes including default attributes.
9808
     */
9809
0
    maxAtts = nratts + nbTotalDef;
9810
9811
    /*
9812
     * Verify that attribute names are unique.
9813
     */
9814
0
    if (maxAtts > 1) {
9815
0
        attrHashSize = 4;
9816
0
        while (attrHashSize / 2 < (unsigned) maxAtts)
9817
0
            attrHashSize *= 2;
9818
9819
0
        if (attrHashSize > ctxt->attrHashMax) {
9820
0
            xmlAttrHashBucket *tmp;
9821
9822
0
            tmp = xmlRealloc(ctxt->attrHash, attrHashSize * sizeof(tmp[0]));
9823
0
            if (tmp == NULL) {
9824
0
                xmlErrMemory(ctxt, NULL);
9825
0
                goto done;
9826
0
            }
9827
9828
0
            ctxt->attrHash = tmp;
9829
0
            ctxt->attrHashMax = attrHashSize;
9830
0
        }
9831
9832
0
        memset(ctxt->attrHash, -1, attrHashSize * sizeof(ctxt->attrHash[0]));
9833
9834
0
        for (i = 0, j = 0; j < nratts; i += 5, j++) {
9835
0
            const xmlChar *nsuri;
9836
0
            unsigned hashValue, nameHashValue, uriHashValue;
9837
0
            int res;
9838
9839
0
            attname = atts[i];
9840
0
            aprefix = atts[i+1];
9841
0
            nsIndex = (ptrdiff_t) atts[i+2];
9842
            /* Hash values always have bit 31 set, see dict.c */
9843
0
            nameHashValue = ctxt->attallocs[j] | 0x80000000;
9844
9845
0
            if (nsIndex == NS_INDEX_EMPTY) {
9846
0
                nsuri = NULL;
9847
0
                uriHashValue = URI_HASH_EMPTY;
9848
0
            } else if (nsIndex == NS_INDEX_XML) {
9849
0
                nsuri = ctxt->str_xml_ns;
9850
0
                uriHashValue = URI_HASH_XML;
9851
0
            } else {
9852
0
                nsuri = ctxt->nsTab[nsIndex * 2 + 1];
9853
0
                uriHashValue = ctxt->nsdb->extra[nsIndex].uriHashValue;
9854
0
            }
9855
9856
0
            hashValue = xmlDictCombineHash(nameHashValue, uriHashValue);
9857
0
            res = xmlAttrHashInsert(ctxt, attrHashSize, attname, nsuri,
9858
0
                                    hashValue, i);
9859
0
            if (res < 0)
9860
0
                continue;
9861
9862
            /*
9863
             * [ WFC: Unique Att Spec ]
9864
             * No attribute name may appear more than once in the same
9865
             * start-tag or empty-element tag.
9866
             * As extended by the Namespace in XML REC.
9867
             */
9868
0
            if (res < INT_MAX) {
9869
0
                if (aprefix == atts[res+1]) {
9870
0
                    xmlErrAttributeDup(ctxt, aprefix, attname);
9871
0
                } else {
9872
0
                    xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED,
9873
0
                             "Namespaced Attribute %s in '%s' redefined\n",
9874
0
                             attname, nsuri, NULL);
9875
0
                }
9876
0
            }
9877
0
        }
9878
0
    }
9879
9880
    /*
9881
     * Default attributes
9882
     */
9883
0
    if (ctxt->attsDefault != NULL) {
9884
0
        xmlDefAttrsPtr defaults;
9885
9886
0
  defaults = xmlHashLookup2(ctxt->attsDefault, localname, prefix);
9887
0
  if (defaults != NULL) {
9888
0
      for (i = 0; i < defaults->nbAttrs; i++) {
9889
0
                xmlDefAttr *attr = &defaults->attrs[i];
9890
0
                const xmlChar *nsuri;
9891
0
                unsigned hashValue, uriHashValue;
9892
0
                int res;
9893
9894
0
          attname = attr->name.name;
9895
0
    aprefix = attr->prefix.name;
9896
9897
0
    if ((attname == ctxt->str_xmlns) && (aprefix == NULL))
9898
0
                    continue;
9899
0
    if (aprefix == ctxt->str_xmlns)
9900
0
                    continue;
9901
9902
0
                if (aprefix == NULL) {
9903
0
                    nsIndex = NS_INDEX_EMPTY;
9904
0
                    nsuri = NULL;
9905
0
                    uriHashValue = URI_HASH_EMPTY;
9906
0
                } if (aprefix == ctxt->str_xml) {
9907
0
                    nsIndex = NS_INDEX_XML;
9908
0
                    nsuri = ctxt->str_xml_ns;
9909
0
                    uriHashValue = URI_HASH_XML;
9910
0
                } else if (aprefix != NULL) {
9911
0
                    nsIndex = xmlParserNsLookup(ctxt, &attr->prefix, NULL);
9912
0
                    if (nsIndex == INT_MAX) {
9913
0
                        xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
9914
0
                                 "Namespace prefix %s for %s on %s is not "
9915
0
                                 "defined\n",
9916
0
                                 aprefix, attname, localname);
9917
0
                        nsIndex = NS_INDEX_EMPTY;
9918
0
                        nsuri = NULL;
9919
0
                        uriHashValue = URI_HASH_EMPTY;
9920
0
                    } else {
9921
0
                        nsuri = ctxt->nsTab[nsIndex * 2 + 1];
9922
0
                        uriHashValue = ctxt->nsdb->extra[nsIndex].uriHashValue;
9923
0
                    }
9924
0
                }
9925
9926
                /*
9927
                 * Check whether the attribute exists
9928
                 */
9929
0
                if (maxAtts > 1) {
9930
0
                    hashValue = xmlDictCombineHash(attr->name.hashValue,
9931
0
                                                   uriHashValue);
9932
0
                    res = xmlAttrHashInsert(ctxt, attrHashSize, attname, nsuri,
9933
0
                                            hashValue, nbatts);
9934
0
                    if (res < 0)
9935
0
                        continue;
9936
0
                    if (res < INT_MAX) {
9937
0
                        if (aprefix == atts[res+1])
9938
0
                            continue;
9939
0
                        xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED,
9940
0
                                 "Namespaced Attribute %s in '%s' redefined\n",
9941
0
                                 attname, nsuri, NULL);
9942
0
                    }
9943
0
                }
9944
9945
0
                xmlParserEntityCheck(ctxt, attr->expandedSize);
9946
9947
0
                if ((atts == NULL) || (nbatts + 5 > maxatts)) {
9948
0
                    if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
9949
0
                        localname = NULL;
9950
0
                        goto done;
9951
0
                    }
9952
0
                    maxatts = ctxt->maxatts;
9953
0
                    atts = ctxt->atts;
9954
0
                }
9955
9956
0
                atts[nbatts++] = attname;
9957
0
                atts[nbatts++] = aprefix;
9958
0
                atts[nbatts++] = (const xmlChar *) (ptrdiff_t) nsIndex;
9959
0
                atts[nbatts++] = attr->value.name;
9960
0
                atts[nbatts++] = attr->valueEnd;
9961
0
                if ((ctxt->standalone == 1) && (attr->external != 0)) {
9962
0
                    xmlValidityError(ctxt, XML_DTD_STANDALONE_DEFAULTED,
9963
0
                            "standalone: attribute %s on %s defaulted "
9964
0
                            "from external subset\n",
9965
0
                            attname, localname);
9966
0
                }
9967
0
                nbdef++;
9968
0
      }
9969
0
  }
9970
0
    }
9971
9972
    /*
9973
     * Reconstruct attribute pointers
9974
     */
9975
0
    for (i = 0, j = 0; i < nbatts; i += 5, j++) {
9976
        /* namespace URI */
9977
0
        nsIndex = (ptrdiff_t) atts[i+2];
9978
0
        if (nsIndex == INT_MAX)
9979
0
            atts[i+2] = NULL;
9980
0
        else if (nsIndex == INT_MAX - 1)
9981
0
            atts[i+2] = ctxt->str_xml_ns;
9982
0
        else
9983
0
            atts[i+2] = ctxt->nsTab[nsIndex * 2 + 1];
9984
9985
0
        if ((j < nratts) && (ctxt->attallocs[j] & 0x80000000) == 0) {
9986
0
            atts[i+3] = BASE_PTR + (ptrdiff_t) atts[i+3];  /* value */
9987
0
            atts[i+4] = BASE_PTR + (ptrdiff_t) atts[i+4];  /* valuend */
9988
0
        }
9989
0
    }
9990
9991
0
    uri = xmlParserNsLookupUri(ctxt, &hprefix);
9992
0
    if ((prefix != NULL) && (uri == NULL)) {
9993
0
  xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
9994
0
           "Namespace prefix %s on %s is not defined\n",
9995
0
     prefix, localname, NULL);
9996
0
    }
9997
0
    *pref = prefix;
9998
0
    *URI = uri;
9999
10000
    /*
10001
     * SAX callback
10002
     */
10003
0
    if ((ctxt->sax != NULL) && (ctxt->sax->startElementNs != NULL) &&
10004
0
  (!ctxt->disableSAX)) {
10005
0
  if (nbNs > 0)
10006
0
      ctxt->sax->startElementNs(ctxt->userData, localname, prefix, uri,
10007
0
                          nbNs, ctxt->nsTab + 2 * (ctxt->nsNr - nbNs),
10008
0
        nbatts / 5, nbdef, atts);
10009
0
  else
10010
0
      ctxt->sax->startElementNs(ctxt->userData, localname, prefix, uri,
10011
0
                          0, NULL, nbatts / 5, nbdef, atts);
10012
0
    }
10013
10014
0
done:
10015
    /*
10016
     * Free allocated attribute values
10017
     */
10018
0
    if (attval != 0) {
10019
0
  for (i = 0, j = 0; j < nratts; i += 5, j++)
10020
0
      if (ctxt->attallocs[j] & 0x80000000)
10021
0
          xmlFree((xmlChar *) atts[i+3]);
10022
0
    }
10023
10024
0
    *nbNsPtr = nbNs;
10025
0
    return(localname);
10026
0
}
10027
10028
/**
10029
 * xmlParseEndTag2:
10030
 * @ctxt:  an XML parser context
10031
 * @line:  line of the start tag
10032
 * @nsNr:  number of namespaces on the start tag
10033
 *
10034
 * Parse an end tag. Always consumes '</'.
10035
 *
10036
 * [42] ETag ::= '</' Name S? '>'
10037
 *
10038
 * With namespace
10039
 *
10040
 * [NS 9] ETag ::= '</' QName S? '>'
10041
 */
10042
10043
static void
10044
0
xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlStartTag *tag) {
10045
0
    const xmlChar *name;
10046
10047
0
    GROW;
10048
0
    if ((RAW != '<') || (NXT(1) != '/')) {
10049
0
  xmlFatalErr(ctxt, XML_ERR_LTSLASH_REQUIRED, NULL);
10050
0
  return;
10051
0
    }
10052
0
    SKIP(2);
10053
10054
0
    if (tag->prefix == NULL)
10055
0
        name = xmlParseNameAndCompare(ctxt, ctxt->name);
10056
0
    else
10057
0
        name = xmlParseQNameAndCompare(ctxt, ctxt->name, tag->prefix);
10058
10059
    /*
10060
     * We should definitely be at the ending "S? '>'" part
10061
     */
10062
0
    GROW;
10063
0
    if (ctxt->instate == XML_PARSER_EOF)
10064
0
        return;
10065
0
    SKIP_BLANKS;
10066
0
    if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
10067
0
  xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
10068
0
    } else
10069
0
  NEXT1;
10070
10071
    /*
10072
     * [ WFC: Element Type Match ]
10073
     * The Name in an element's end-tag must match the element type in the
10074
     * start-tag.
10075
     *
10076
     */
10077
0
    if (name != (xmlChar*)1) {
10078
0
        if (name == NULL) name = BAD_CAST "unparsable";
10079
0
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
10080
0
         "Opening and ending tag mismatch: %s line %d and %s\n",
10081
0
                    ctxt->name, tag->line, name);
10082
0
    }
10083
10084
    /*
10085
     * SAX: End of Tag
10086
     */
10087
0
    if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
10088
0
  (!ctxt->disableSAX))
10089
0
  ctxt->sax->endElementNs(ctxt->userData, ctxt->name, tag->prefix,
10090
0
                                tag->URI);
10091
10092
0
    spacePop(ctxt);
10093
0
    if (tag->nsNr != 0)
10094
0
  xmlParserNsPop(ctxt, tag->nsNr);
10095
0
}
10096
10097
/**
10098
 * xmlParseCDSect:
10099
 * @ctxt:  an XML parser context
10100
 *
10101
 * DEPRECATED: Internal function, don't use.
10102
 *
10103
 * Parse escaped pure raw content. Always consumes '<!['.
10104
 *
10105
 * [18] CDSect ::= CDStart CData CDEnd
10106
 *
10107
 * [19] CDStart ::= '<![CDATA['
10108
 *
10109
 * [20] Data ::= (Char* - (Char* ']]>' Char*))
10110
 *
10111
 * [21] CDEnd ::= ']]>'
10112
 */
10113
void
10114
0
xmlParseCDSect(xmlParserCtxtPtr ctxt) {
10115
0
    xmlChar *buf = NULL;
10116
0
    int len = 0;
10117
0
    int size = XML_PARSER_BUFFER_SIZE;
10118
0
    int r, rl;
10119
0
    int s, sl;
10120
0
    int cur, l;
10121
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
10122
0
                    XML_MAX_HUGE_LENGTH :
10123
0
                    XML_MAX_TEXT_LENGTH;
10124
10125
0
    if ((CUR != '<') || (NXT(1) != '!') || (NXT(2) != '['))
10126
0
        return;
10127
0
    SKIP(3);
10128
10129
0
    if (!CMP6(CUR_PTR, 'C', 'D', 'A', 'T', 'A', '['))
10130
0
        return;
10131
0
    SKIP(6);
10132
10133
0
    ctxt->instate = XML_PARSER_CDATA_SECTION;
10134
0
    r = CUR_CHAR(rl);
10135
0
    if (!IS_CHAR(r)) {
10136
0
  xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
10137
0
        goto out;
10138
0
    }
10139
0
    NEXTL(rl);
10140
0
    s = CUR_CHAR(sl);
10141
0
    if (!IS_CHAR(s)) {
10142
0
  xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
10143
0
        goto out;
10144
0
    }
10145
0
    NEXTL(sl);
10146
0
    cur = CUR_CHAR(l);
10147
0
    buf = (xmlChar *) xmlMallocAtomic(size);
10148
0
    if (buf == NULL) {
10149
0
  xmlErrMemory(ctxt, NULL);
10150
0
        goto out;
10151
0
    }
10152
0
    while (IS_CHAR(cur) &&
10153
0
           ((r != ']') || (s != ']') || (cur != '>'))) {
10154
0
  if (len + 5 >= size) {
10155
0
      xmlChar *tmp;
10156
10157
0
      tmp = (xmlChar *) xmlRealloc(buf, size * 2);
10158
0
      if (tmp == NULL) {
10159
0
    xmlErrMemory(ctxt, NULL);
10160
0
                goto out;
10161
0
      }
10162
0
      buf = tmp;
10163
0
      size *= 2;
10164
0
  }
10165
0
  COPY_BUF(buf, len, r);
10166
0
        if (len > maxLength) {
10167
0
            xmlFatalErrMsg(ctxt, XML_ERR_CDATA_NOT_FINISHED,
10168
0
                           "CData section too big found\n");
10169
0
            goto out;
10170
0
        }
10171
0
  r = s;
10172
0
  rl = sl;
10173
0
  s = cur;
10174
0
  sl = l;
10175
0
  NEXTL(l);
10176
0
  cur = CUR_CHAR(l);
10177
0
    }
10178
0
    buf[len] = 0;
10179
0
    if (ctxt->instate == XML_PARSER_EOF) {
10180
0
        xmlFree(buf);
10181
0
        return;
10182
0
    }
10183
0
    if (cur != '>') {
10184
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED,
10185
0
                       "CData section not finished\n%.50s\n", buf);
10186
0
        goto out;
10187
0
    }
10188
0
    NEXTL(l);
10189
10190
    /*
10191
     * OK the buffer is to be consumed as cdata.
10192
     */
10193
0
    if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
10194
0
  if (ctxt->sax->cdataBlock != NULL)
10195
0
      ctxt->sax->cdataBlock(ctxt->userData, buf, len);
10196
0
  else if (ctxt->sax->characters != NULL)
10197
0
      ctxt->sax->characters(ctxt->userData, buf, len);
10198
0
    }
10199
10200
0
out:
10201
0
    if (ctxt->instate != XML_PARSER_EOF)
10202
0
        ctxt->instate = XML_PARSER_CONTENT;
10203
0
    xmlFree(buf);
10204
0
}
10205
10206
/**
10207
 * xmlParseContentInternal:
10208
 * @ctxt:  an XML parser context
10209
 *
10210
 * Parse a content sequence. Stops at EOF or '</'. Leaves checking of
10211
 * unexpected EOF to the caller.
10212
 */
10213
10214
static void
10215
0
xmlParseContentInternal(xmlParserCtxtPtr ctxt) {
10216
0
    int nameNr = ctxt->nameNr;
10217
10218
0
    GROW;
10219
0
    while ((ctxt->input->cur < ctxt->input->end) &&
10220
0
     (ctxt->instate != XML_PARSER_EOF)) {
10221
0
  const xmlChar *cur = ctxt->input->cur;
10222
10223
  /*
10224
   * First case : a Processing Instruction.
10225
   */
10226
0
  if ((*cur == '<') && (cur[1] == '?')) {
10227
0
      xmlParsePI(ctxt);
10228
0
  }
10229
10230
  /*
10231
   * Second case : a CDSection
10232
   */
10233
  /* 2.6.0 test was *cur not RAW */
10234
0
  else if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
10235
0
      xmlParseCDSect(ctxt);
10236
0
  }
10237
10238
  /*
10239
   * Third case :  a comment
10240
   */
10241
0
  else if ((*cur == '<') && (NXT(1) == '!') &&
10242
0
     (NXT(2) == '-') && (NXT(3) == '-')) {
10243
0
      xmlParseComment(ctxt);
10244
0
      ctxt->instate = XML_PARSER_CONTENT;
10245
0
  }
10246
10247
  /*
10248
   * Fourth case :  a sub-element.
10249
   */
10250
0
  else if (*cur == '<') {
10251
0
            if (NXT(1) == '/') {
10252
0
                if (ctxt->nameNr <= nameNr)
10253
0
                    break;
10254
0
          xmlParseElementEnd(ctxt);
10255
0
            } else {
10256
0
          xmlParseElementStart(ctxt);
10257
0
            }
10258
0
  }
10259
10260
  /*
10261
   * Fifth case : a reference. If if has not been resolved,
10262
   *    parsing returns it's Name, create the node
10263
   */
10264
10265
0
  else if (*cur == '&') {
10266
0
      xmlParseReference(ctxt);
10267
0
  }
10268
10269
  /*
10270
   * Last case, text. Note that References are handled directly.
10271
   */
10272
0
  else {
10273
0
      xmlParseCharDataInternal(ctxt, 0);
10274
0
  }
10275
10276
0
  SHRINK;
10277
0
  GROW;
10278
0
    }
10279
0
}
10280
10281
/**
10282
 * xmlParseContent:
10283
 * @ctxt:  an XML parser context
10284
 *
10285
 * Parse a content sequence. Stops at EOF or '</'.
10286
 *
10287
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
10288
 */
10289
10290
void
10291
0
xmlParseContent(xmlParserCtxtPtr ctxt) {
10292
0
    int nameNr = ctxt->nameNr;
10293
10294
0
    xmlParseContentInternal(ctxt);
10295
10296
0
    if ((ctxt->instate != XML_PARSER_EOF) &&
10297
0
        (ctxt->errNo == XML_ERR_OK) &&
10298
0
        (ctxt->nameNr > nameNr)) {
10299
0
        const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
10300
0
        int line = ctxt->pushTab[ctxt->nameNr - 1].line;
10301
0
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
10302
0
                "Premature end of data in tag %s line %d\n",
10303
0
    name, line, NULL);
10304
0
    }
10305
0
}
10306
10307
/**
10308
 * xmlParseElement:
10309
 * @ctxt:  an XML parser context
10310
 *
10311
 * DEPRECATED: Internal function, don't use.
10312
 *
10313
 * parse an XML element
10314
 *
10315
 * [39] element ::= EmptyElemTag | STag content ETag
10316
 *
10317
 * [ WFC: Element Type Match ]
10318
 * The Name in an element's end-tag must match the element type in the
10319
 * start-tag.
10320
 *
10321
 */
10322
10323
void
10324
0
xmlParseElement(xmlParserCtxtPtr ctxt) {
10325
0
    if (xmlParseElementStart(ctxt) != 0)
10326
0
        return;
10327
10328
0
    xmlParseContentInternal(ctxt);
10329
0
    if (ctxt->instate == XML_PARSER_EOF)
10330
0
  return;
10331
10332
0
    if (ctxt->input->cur >= ctxt->input->end) {
10333
0
        if (ctxt->errNo == XML_ERR_OK) {
10334
0
            const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
10335
0
            int line = ctxt->pushTab[ctxt->nameNr - 1].line;
10336
0
            xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
10337
0
                    "Premature end of data in tag %s line %d\n",
10338
0
                    name, line, NULL);
10339
0
        }
10340
0
        return;
10341
0
    }
10342
10343
0
    xmlParseElementEnd(ctxt);
10344
0
}
10345
10346
/**
10347
 * xmlParseElementStart:
10348
 * @ctxt:  an XML parser context
10349
 *
10350
 * Parse the start of an XML element. Returns -1 in case of error, 0 if an
10351
 * opening tag was parsed, 1 if an empty element was parsed.
10352
 *
10353
 * Always consumes '<'.
10354
 */
10355
static int
10356
0
xmlParseElementStart(xmlParserCtxtPtr ctxt) {
10357
0
    const xmlChar *name;
10358
0
    const xmlChar *prefix = NULL;
10359
0
    const xmlChar *URI = NULL;
10360
0
    xmlParserNodeInfo node_info;
10361
0
    int line;
10362
0
    xmlNodePtr cur;
10363
0
    int nbNs = 0;
10364
10365
0
    if (((unsigned int) ctxt->nameNr > xmlParserMaxDepth) &&
10366
0
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
10367
0
  xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
10368
0
     "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
10369
0
        xmlParserMaxDepth);
10370
0
  xmlHaltParser(ctxt);
10371
0
  return(-1);
10372
0
    }
10373
10374
    /* Capture start position */
10375
0
    if (ctxt->record_info) {
10376
0
        node_info.begin_pos = ctxt->input->consumed +
10377
0
                          (CUR_PTR - ctxt->input->base);
10378
0
  node_info.begin_line = ctxt->input->line;
10379
0
    }
10380
10381
0
    if (ctxt->spaceNr == 0)
10382
0
  spacePush(ctxt, -1);
10383
0
    else if (*ctxt->space == -2)
10384
0
  spacePush(ctxt, -1);
10385
0
    else
10386
0
  spacePush(ctxt, *ctxt->space);
10387
10388
0
    line = ctxt->input->line;
10389
0
#ifdef LIBXML_SAX1_ENABLED
10390
0
    if (ctxt->sax2)
10391
0
#endif /* LIBXML_SAX1_ENABLED */
10392
0
        name = xmlParseStartTag2(ctxt, &prefix, &URI, &nbNs);
10393
0
#ifdef LIBXML_SAX1_ENABLED
10394
0
    else
10395
0
  name = xmlParseStartTag(ctxt);
10396
0
#endif /* LIBXML_SAX1_ENABLED */
10397
0
    if (ctxt->instate == XML_PARSER_EOF)
10398
0
  return(-1);
10399
0
    if (name == NULL) {
10400
0
  spacePop(ctxt);
10401
0
        return(-1);
10402
0
    }
10403
0
    nameNsPush(ctxt, name, prefix, URI, line, nbNs);
10404
0
    cur = ctxt->node;
10405
10406
0
#ifdef LIBXML_VALID_ENABLED
10407
    /*
10408
     * [ VC: Root Element Type ]
10409
     * The Name in the document type declaration must match the element
10410
     * type of the root element.
10411
     */
10412
0
    if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
10413
0
        ctxt->node && (ctxt->node == ctxt->myDoc->children))
10414
0
        ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
10415
0
#endif /* LIBXML_VALID_ENABLED */
10416
10417
    /*
10418
     * Check for an Empty Element.
10419
     */
10420
0
    if ((RAW == '/') && (NXT(1) == '>')) {
10421
0
        SKIP(2);
10422
0
  if (ctxt->sax2) {
10423
0
      if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
10424
0
    (!ctxt->disableSAX))
10425
0
    ctxt->sax->endElementNs(ctxt->userData, name, prefix, URI);
10426
0
#ifdef LIBXML_SAX1_ENABLED
10427
0
  } else {
10428
0
      if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
10429
0
    (!ctxt->disableSAX))
10430
0
    ctxt->sax->endElement(ctxt->userData, name);
10431
0
#endif /* LIBXML_SAX1_ENABLED */
10432
0
  }
10433
0
  namePop(ctxt);
10434
0
  spacePop(ctxt);
10435
0
  if (nbNs > 0)
10436
0
      xmlParserNsPop(ctxt, nbNs);
10437
0
  if (cur != NULL && ctxt->record_info) {
10438
0
            node_info.node = cur;
10439
0
            node_info.end_pos = ctxt->input->consumed +
10440
0
                                (CUR_PTR - ctxt->input->base);
10441
0
            node_info.end_line = ctxt->input->line;
10442
0
            xmlParserAddNodeInfo(ctxt, &node_info);
10443
0
  }
10444
0
  return(1);
10445
0
    }
10446
0
    if (RAW == '>') {
10447
0
        NEXT1;
10448
0
        if (cur != NULL && ctxt->record_info) {
10449
0
            node_info.node = cur;
10450
0
            node_info.end_pos = 0;
10451
0
            node_info.end_line = 0;
10452
0
            xmlParserAddNodeInfo(ctxt, &node_info);
10453
0
        }
10454
0
    } else {
10455
0
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_GT_REQUIRED,
10456
0
         "Couldn't find end of Start Tag %s line %d\n",
10457
0
                    name, line, NULL);
10458
10459
  /*
10460
   * end of parsing of this node.
10461
   */
10462
0
  nodePop(ctxt);
10463
0
  namePop(ctxt);
10464
0
  spacePop(ctxt);
10465
0
  if (nbNs > 0)
10466
0
      xmlParserNsPop(ctxt, nbNs);
10467
0
  return(-1);
10468
0
    }
10469
10470
0
    return(0);
10471
0
}
10472
10473
/**
10474
 * xmlParseElementEnd:
10475
 * @ctxt:  an XML parser context
10476
 *
10477
 * Parse the end of an XML element. Always consumes '</'.
10478
 */
10479
static void
10480
0
xmlParseElementEnd(xmlParserCtxtPtr ctxt) {
10481
0
    xmlNodePtr cur = ctxt->node;
10482
10483
0
    if (ctxt->nameNr <= 0) {
10484
0
        if ((RAW == '<') && (NXT(1) == '/'))
10485
0
            SKIP(2);
10486
0
        return;
10487
0
    }
10488
10489
    /*
10490
     * parse the end of tag: '</' should be here.
10491
     */
10492
0
    if (ctxt->sax2) {
10493
0
  xmlParseEndTag2(ctxt, &ctxt->pushTab[ctxt->nameNr - 1]);
10494
0
  namePop(ctxt);
10495
0
    }
10496
0
#ifdef LIBXML_SAX1_ENABLED
10497
0
    else
10498
0
  xmlParseEndTag1(ctxt, 0);
10499
0
#endif /* LIBXML_SAX1_ENABLED */
10500
10501
    /*
10502
     * Capture end position
10503
     */
10504
0
    if (cur != NULL && ctxt->record_info) {
10505
0
        xmlParserNodeInfoPtr node_info;
10506
10507
0
        node_info = (xmlParserNodeInfoPtr) xmlParserFindNodeInfo(ctxt, cur);
10508
0
        if (node_info != NULL) {
10509
0
            node_info->end_pos = ctxt->input->consumed +
10510
0
                                 (CUR_PTR - ctxt->input->base);
10511
0
            node_info->end_line = ctxt->input->line;
10512
0
        }
10513
0
    }
10514
0
}
10515
10516
/**
10517
 * xmlParseVersionNum:
10518
 * @ctxt:  an XML parser context
10519
 *
10520
 * DEPRECATED: Internal function, don't use.
10521
 *
10522
 * parse the XML version value.
10523
 *
10524
 * [26] VersionNum ::= '1.' [0-9]+
10525
 *
10526
 * In practice allow [0-9].[0-9]+ at that level
10527
 *
10528
 * Returns the string giving the XML version number, or NULL
10529
 */
10530
xmlChar *
10531
0
xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
10532
0
    xmlChar *buf = NULL;
10533
0
    int len = 0;
10534
0
    int size = 10;
10535
0
    xmlChar cur;
10536
10537
0
    buf = (xmlChar *) xmlMallocAtomic(size);
10538
0
    if (buf == NULL) {
10539
0
  xmlErrMemory(ctxt, NULL);
10540
0
  return(NULL);
10541
0
    }
10542
0
    cur = CUR;
10543
0
    if (!((cur >= '0') && (cur <= '9'))) {
10544
0
  xmlFree(buf);
10545
0
  return(NULL);
10546
0
    }
10547
0
    buf[len++] = cur;
10548
0
    NEXT;
10549
0
    cur=CUR;
10550
0
    if (cur != '.') {
10551
0
  xmlFree(buf);
10552
0
  return(NULL);
10553
0
    }
10554
0
    buf[len++] = cur;
10555
0
    NEXT;
10556
0
    cur=CUR;
10557
0
    while ((cur >= '0') && (cur <= '9')) {
10558
0
  if (len + 1 >= size) {
10559
0
      xmlChar *tmp;
10560
10561
0
      size *= 2;
10562
0
      tmp = (xmlChar *) xmlRealloc(buf, size);
10563
0
      if (tmp == NULL) {
10564
0
          xmlFree(buf);
10565
0
    xmlErrMemory(ctxt, NULL);
10566
0
    return(NULL);
10567
0
      }
10568
0
      buf = tmp;
10569
0
  }
10570
0
  buf[len++] = cur;
10571
0
  NEXT;
10572
0
  cur=CUR;
10573
0
    }
10574
0
    buf[len] = 0;
10575
0
    return(buf);
10576
0
}
10577
10578
/**
10579
 * xmlParseVersionInfo:
10580
 * @ctxt:  an XML parser context
10581
 *
10582
 * DEPRECATED: Internal function, don't use.
10583
 *
10584
 * parse the XML version.
10585
 *
10586
 * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
10587
 *
10588
 * [25] Eq ::= S? '=' S?
10589
 *
10590
 * Returns the version string, e.g. "1.0"
10591
 */
10592
10593
xmlChar *
10594
0
xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
10595
0
    xmlChar *version = NULL;
10596
10597
0
    if (CMP7(CUR_PTR, 'v', 'e', 'r', 's', 'i', 'o', 'n')) {
10598
0
  SKIP(7);
10599
0
  SKIP_BLANKS;
10600
0
  if (RAW != '=') {
10601
0
      xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10602
0
      return(NULL);
10603
0
        }
10604
0
  NEXT;
10605
0
  SKIP_BLANKS;
10606
0
  if (RAW == '"') {
10607
0
      NEXT;
10608
0
      version = xmlParseVersionNum(ctxt);
10609
0
      if (RAW != '"') {
10610
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10611
0
      } else
10612
0
          NEXT;
10613
0
  } else if (RAW == '\''){
10614
0
      NEXT;
10615
0
      version = xmlParseVersionNum(ctxt);
10616
0
      if (RAW != '\'') {
10617
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10618
0
      } else
10619
0
          NEXT;
10620
0
  } else {
10621
0
      xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10622
0
  }
10623
0
    }
10624
0
    return(version);
10625
0
}
10626
10627
/**
10628
 * xmlParseEncName:
10629
 * @ctxt:  an XML parser context
10630
 *
10631
 * DEPRECATED: Internal function, don't use.
10632
 *
10633
 * parse the XML encoding name
10634
 *
10635
 * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
10636
 *
10637
 * Returns the encoding name value or NULL
10638
 */
10639
xmlChar *
10640
0
xmlParseEncName(xmlParserCtxtPtr ctxt) {
10641
0
    xmlChar *buf = NULL;
10642
0
    int len = 0;
10643
0
    int size = 10;
10644
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
10645
0
                    XML_MAX_TEXT_LENGTH :
10646
0
                    XML_MAX_NAME_LENGTH;
10647
0
    xmlChar cur;
10648
10649
0
    cur = CUR;
10650
0
    if (((cur >= 'a') && (cur <= 'z')) ||
10651
0
        ((cur >= 'A') && (cur <= 'Z'))) {
10652
0
  buf = (xmlChar *) xmlMallocAtomic(size);
10653
0
  if (buf == NULL) {
10654
0
      xmlErrMemory(ctxt, NULL);
10655
0
      return(NULL);
10656
0
  }
10657
10658
0
  buf[len++] = cur;
10659
0
  NEXT;
10660
0
  cur = CUR;
10661
0
  while (((cur >= 'a') && (cur <= 'z')) ||
10662
0
         ((cur >= 'A') && (cur <= 'Z')) ||
10663
0
         ((cur >= '0') && (cur <= '9')) ||
10664
0
         (cur == '.') || (cur == '_') ||
10665
0
         (cur == '-')) {
10666
0
      if (len + 1 >= size) {
10667
0
          xmlChar *tmp;
10668
10669
0
    size *= 2;
10670
0
    tmp = (xmlChar *) xmlRealloc(buf, size);
10671
0
    if (tmp == NULL) {
10672
0
        xmlErrMemory(ctxt, NULL);
10673
0
        xmlFree(buf);
10674
0
        return(NULL);
10675
0
    }
10676
0
    buf = tmp;
10677
0
      }
10678
0
      buf[len++] = cur;
10679
0
            if (len > maxLength) {
10680
0
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "EncName");
10681
0
                xmlFree(buf);
10682
0
                return(NULL);
10683
0
            }
10684
0
      NEXT;
10685
0
      cur = CUR;
10686
0
        }
10687
0
  buf[len] = 0;
10688
0
    } else {
10689
0
  xmlFatalErr(ctxt, XML_ERR_ENCODING_NAME, NULL);
10690
0
    }
10691
0
    return(buf);
10692
0
}
10693
10694
/**
10695
 * xmlParseEncodingDecl:
10696
 * @ctxt:  an XML parser context
10697
 *
10698
 * DEPRECATED: Internal function, don't use.
10699
 *
10700
 * parse the XML encoding declaration
10701
 *
10702
 * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' |  "'" EncName "'")
10703
 *
10704
 * this setups the conversion filters.
10705
 *
10706
 * Returns the encoding value or NULL
10707
 */
10708
10709
const xmlChar *
10710
0
xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
10711
0
    xmlChar *encoding = NULL;
10712
10713
0
    SKIP_BLANKS;
10714
0
    if (CMP8(CUR_PTR, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g') == 0)
10715
0
        return(NULL);
10716
10717
0
    SKIP(8);
10718
0
    SKIP_BLANKS;
10719
0
    if (RAW != '=') {
10720
0
        xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10721
0
        return(NULL);
10722
0
    }
10723
0
    NEXT;
10724
0
    SKIP_BLANKS;
10725
0
    if (RAW == '"') {
10726
0
        NEXT;
10727
0
        encoding = xmlParseEncName(ctxt);
10728
0
        if (RAW != '"') {
10729
0
            xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10730
0
            xmlFree((xmlChar *) encoding);
10731
0
            return(NULL);
10732
0
        } else
10733
0
            NEXT;
10734
0
    } else if (RAW == '\''){
10735
0
        NEXT;
10736
0
        encoding = xmlParseEncName(ctxt);
10737
0
        if (RAW != '\'') {
10738
0
            xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10739
0
            xmlFree((xmlChar *) encoding);
10740
0
            return(NULL);
10741
0
        } else
10742
0
            NEXT;
10743
0
    } else {
10744
0
        xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10745
0
    }
10746
10747
0
    if (encoding == NULL)
10748
0
        return(NULL);
10749
10750
0
    xmlSetDeclaredEncoding(ctxt, encoding);
10751
10752
0
    return(ctxt->encoding);
10753
0
}
10754
10755
/**
10756
 * xmlParseSDDecl:
10757
 * @ctxt:  an XML parser context
10758
 *
10759
 * DEPRECATED: Internal function, don't use.
10760
 *
10761
 * parse the XML standalone declaration
10762
 *
10763
 * [32] SDDecl ::= S 'standalone' Eq
10764
 *                 (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no')'"'))
10765
 *
10766
 * [ VC: Standalone Document Declaration ]
10767
 * TODO The standalone document declaration must have the value "no"
10768
 * if any external markup declarations contain declarations of:
10769
 *  - attributes with default values, if elements to which these
10770
 *    attributes apply appear in the document without specifications
10771
 *    of values for these attributes, or
10772
 *  - entities (other than amp, lt, gt, apos, quot), if references
10773
 *    to those entities appear in the document, or
10774
 *  - attributes with values subject to normalization, where the
10775
 *    attribute appears in the document with a value which will change
10776
 *    as a result of normalization, or
10777
 *  - element types with element content, if white space occurs directly
10778
 *    within any instance of those types.
10779
 *
10780
 * Returns:
10781
 *   1 if standalone="yes"
10782
 *   0 if standalone="no"
10783
 *  -2 if standalone attribute is missing or invalid
10784
 *    (A standalone value of -2 means that the XML declaration was found,
10785
 *     but no value was specified for the standalone attribute).
10786
 */
10787
10788
int
10789
0
xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
10790
0
    int standalone = -2;
10791
10792
0
    SKIP_BLANKS;
10793
0
    if (CMP10(CUR_PTR, 's', 't', 'a', 'n', 'd', 'a', 'l', 'o', 'n', 'e')) {
10794
0
  SKIP(10);
10795
0
        SKIP_BLANKS;
10796
0
  if (RAW != '=') {
10797
0
      xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10798
0
      return(standalone);
10799
0
        }
10800
0
  NEXT;
10801
0
  SKIP_BLANKS;
10802
0
        if (RAW == '\''){
10803
0
      NEXT;
10804
0
      if ((RAW == 'n') && (NXT(1) == 'o')) {
10805
0
          standalone = 0;
10806
0
                SKIP(2);
10807
0
      } else if ((RAW == 'y') && (NXT(1) == 'e') &&
10808
0
                 (NXT(2) == 's')) {
10809
0
          standalone = 1;
10810
0
    SKIP(3);
10811
0
            } else {
10812
0
    xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
10813
0
      }
10814
0
      if (RAW != '\'') {
10815
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10816
0
      } else
10817
0
          NEXT;
10818
0
  } else if (RAW == '"'){
10819
0
      NEXT;
10820
0
      if ((RAW == 'n') && (NXT(1) == 'o')) {
10821
0
          standalone = 0;
10822
0
    SKIP(2);
10823
0
      } else if ((RAW == 'y') && (NXT(1) == 'e') &&
10824
0
                 (NXT(2) == 's')) {
10825
0
          standalone = 1;
10826
0
                SKIP(3);
10827
0
            } else {
10828
0
    xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
10829
0
      }
10830
0
      if (RAW != '"') {
10831
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10832
0
      } else
10833
0
          NEXT;
10834
0
  } else {
10835
0
      xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10836
0
        }
10837
0
    }
10838
0
    return(standalone);
10839
0
}
10840
10841
/**
10842
 * xmlParseXMLDecl:
10843
 * @ctxt:  an XML parser context
10844
 *
10845
 * DEPRECATED: Internal function, don't use.
10846
 *
10847
 * parse an XML declaration header
10848
 *
10849
 * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
10850
 */
10851
10852
void
10853
0
xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
10854
0
    xmlChar *version;
10855
10856
    /*
10857
     * This value for standalone indicates that the document has an
10858
     * XML declaration but it does not have a standalone attribute.
10859
     * It will be overwritten later if a standalone attribute is found.
10860
     */
10861
10862
0
    ctxt->standalone = -2;
10863
10864
    /*
10865
     * We know that '<?xml' is here.
10866
     */
10867
0
    SKIP(5);
10868
10869
0
    if (!IS_BLANK_CH(RAW)) {
10870
0
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
10871
0
                 "Blank needed after '<?xml'\n");
10872
0
    }
10873
0
    SKIP_BLANKS;
10874
10875
    /*
10876
     * We must have the VersionInfo here.
10877
     */
10878
0
    version = xmlParseVersionInfo(ctxt);
10879
0
    if (version == NULL) {
10880
0
  xmlFatalErr(ctxt, XML_ERR_VERSION_MISSING, NULL);
10881
0
    } else {
10882
0
  if (!xmlStrEqual(version, (const xmlChar *) XML_DEFAULT_VERSION)) {
10883
      /*
10884
       * Changed here for XML-1.0 5th edition
10885
       */
10886
0
      if (ctxt->options & XML_PARSE_OLD10) {
10887
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
10888
0
                "Unsupported version '%s'\n",
10889
0
                version);
10890
0
      } else {
10891
0
          if ((version[0] == '1') && ((version[1] == '.'))) {
10892
0
        xmlWarningMsg(ctxt, XML_WAR_UNKNOWN_VERSION,
10893
0
                      "Unsupported version '%s'\n",
10894
0
          version, NULL);
10895
0
    } else {
10896
0
        xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
10897
0
              "Unsupported version '%s'\n",
10898
0
              version);
10899
0
    }
10900
0
      }
10901
0
  }
10902
0
  if (ctxt->version != NULL)
10903
0
      xmlFree((void *) ctxt->version);
10904
0
  ctxt->version = version;
10905
0
    }
10906
10907
    /*
10908
     * We may have the encoding declaration
10909
     */
10910
0
    if (!IS_BLANK_CH(RAW)) {
10911
0
        if ((RAW == '?') && (NXT(1) == '>')) {
10912
0
      SKIP(2);
10913
0
      return;
10914
0
  }
10915
0
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
10916
0
    }
10917
0
    xmlParseEncodingDecl(ctxt);
10918
0
    if ((ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) ||
10919
0
         (ctxt->instate == XML_PARSER_EOF)) {
10920
  /*
10921
   * The XML REC instructs us to stop parsing right here
10922
   */
10923
0
        return;
10924
0
    }
10925
10926
    /*
10927
     * We may have the standalone status.
10928
     */
10929
0
    if ((ctxt->encoding != NULL) && (!IS_BLANK_CH(RAW))) {
10930
0
        if ((RAW == '?') && (NXT(1) == '>')) {
10931
0
      SKIP(2);
10932
0
      return;
10933
0
  }
10934
0
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
10935
0
    }
10936
10937
    /*
10938
     * We can grow the input buffer freely at that point
10939
     */
10940
0
    GROW;
10941
10942
0
    SKIP_BLANKS;
10943
0
    ctxt->standalone = xmlParseSDDecl(ctxt);
10944
10945
0
    SKIP_BLANKS;
10946
0
    if ((RAW == '?') && (NXT(1) == '>')) {
10947
0
        SKIP(2);
10948
0
    } else if (RAW == '>') {
10949
        /* Deprecated old WD ... */
10950
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
10951
0
  NEXT;
10952
0
    } else {
10953
0
        int c;
10954
10955
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
10956
0
        while ((c = CUR) != 0) {
10957
0
            NEXT;
10958
0
            if (c == '>')
10959
0
                break;
10960
0
        }
10961
0
    }
10962
0
}
10963
10964
/**
10965
 * xmlParseMisc:
10966
 * @ctxt:  an XML parser context
10967
 *
10968
 * DEPRECATED: Internal function, don't use.
10969
 *
10970
 * parse an XML Misc* optional field.
10971
 *
10972
 * [27] Misc ::= Comment | PI |  S
10973
 */
10974
10975
void
10976
0
xmlParseMisc(xmlParserCtxtPtr ctxt) {
10977
0
    while (ctxt->instate != XML_PARSER_EOF) {
10978
0
        SKIP_BLANKS;
10979
0
        GROW;
10980
0
        if ((RAW == '<') && (NXT(1) == '?')) {
10981
0
      xmlParsePI(ctxt);
10982
0
        } else if (CMP4(CUR_PTR, '<', '!', '-', '-')) {
10983
0
      xmlParseComment(ctxt);
10984
0
        } else {
10985
0
            break;
10986
0
        }
10987
0
    }
10988
0
}
10989
10990
/**
10991
 * xmlParseDocument:
10992
 * @ctxt:  an XML parser context
10993
 *
10994
 * parse an XML document (and build a tree if using the standard SAX
10995
 * interface).
10996
 *
10997
 * [1] document ::= prolog element Misc*
10998
 *
10999
 * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
11000
 *
11001
 * Returns 0, -1 in case of error. the parser context is augmented
11002
 *                as a result of the parsing.
11003
 */
11004
11005
int
11006
0
xmlParseDocument(xmlParserCtxtPtr ctxt) {
11007
0
    xmlInitParser();
11008
11009
0
    if ((ctxt == NULL) || (ctxt->input == NULL))
11010
0
        return(-1);
11011
11012
0
    GROW;
11013
11014
    /*
11015
     * SAX: detecting the level.
11016
     */
11017
0
    xmlDetectSAX2(ctxt);
11018
11019
    /*
11020
     * SAX: beginning of the document processing.
11021
     */
11022
0
    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
11023
0
        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
11024
0
    if (ctxt->instate == XML_PARSER_EOF)
11025
0
  return(-1);
11026
11027
0
    xmlDetectEncoding(ctxt);
11028
11029
0
    if (CUR == 0) {
11030
0
  xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
11031
0
  return(-1);
11032
0
    }
11033
11034
0
    GROW;
11035
0
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
11036
11037
  /*
11038
   * Note that we will switch encoding on the fly.
11039
   */
11040
0
  xmlParseXMLDecl(ctxt);
11041
0
  if ((ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) ||
11042
0
      (ctxt->instate == XML_PARSER_EOF)) {
11043
      /*
11044
       * The XML REC instructs us to stop parsing right here
11045
       */
11046
0
      return(-1);
11047
0
  }
11048
0
  SKIP_BLANKS;
11049
0
    } else {
11050
0
  ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11051
0
    }
11052
0
    if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
11053
0
        ctxt->sax->startDocument(ctxt->userData);
11054
0
    if (ctxt->instate == XML_PARSER_EOF)
11055
0
  return(-1);
11056
0
    if ((ctxt->myDoc != NULL) && (ctxt->input != NULL) &&
11057
0
        (ctxt->input->buf != NULL) && (ctxt->input->buf->compressed >= 0)) {
11058
0
  ctxt->myDoc->compression = ctxt->input->buf->compressed;
11059
0
    }
11060
11061
    /*
11062
     * The Misc part of the Prolog
11063
     */
11064
0
    xmlParseMisc(ctxt);
11065
11066
    /*
11067
     * Then possibly doc type declaration(s) and more Misc
11068
     * (doctypedecl Misc*)?
11069
     */
11070
0
    GROW;
11071
0
    if (CMP9(CUR_PTR, '<', '!', 'D', 'O', 'C', 'T', 'Y', 'P', 'E')) {
11072
11073
0
  ctxt->inSubset = 1;
11074
0
  xmlParseDocTypeDecl(ctxt);
11075
0
  if (RAW == '[') {
11076
0
      ctxt->instate = XML_PARSER_DTD;
11077
0
      xmlParseInternalSubset(ctxt);
11078
0
      if (ctxt->instate == XML_PARSER_EOF)
11079
0
    return(-1);
11080
0
  }
11081
11082
  /*
11083
   * Create and update the external subset.
11084
   */
11085
0
  ctxt->inSubset = 2;
11086
0
  if ((ctxt->sax != NULL) && (ctxt->sax->externalSubset != NULL) &&
11087
0
      (!ctxt->disableSAX))
11088
0
      ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
11089
0
                                ctxt->extSubSystem, ctxt->extSubURI);
11090
0
  if (ctxt->instate == XML_PARSER_EOF)
11091
0
      return(-1);
11092
0
  ctxt->inSubset = 0;
11093
11094
0
        xmlCleanSpecialAttr(ctxt);
11095
11096
0
  ctxt->instate = XML_PARSER_PROLOG;
11097
0
  xmlParseMisc(ctxt);
11098
0
    }
11099
11100
    /*
11101
     * Time to start parsing the tree itself
11102
     */
11103
0
    GROW;
11104
0
    if (RAW != '<') {
11105
0
  xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
11106
0
           "Start tag expected, '<' not found\n");
11107
0
    } else {
11108
0
  ctxt->instate = XML_PARSER_CONTENT;
11109
0
  xmlParseElement(ctxt);
11110
0
  ctxt->instate = XML_PARSER_EPILOG;
11111
11112
11113
  /*
11114
   * The Misc part at the end
11115
   */
11116
0
  xmlParseMisc(ctxt);
11117
11118
0
        if (ctxt->input->cur < ctxt->input->end) {
11119
0
            if (ctxt->errNo == XML_ERR_OK)
11120
0
          xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
11121
0
        } else if ((ctxt->input->buf != NULL) &&
11122
0
                   (ctxt->input->buf->encoder != NULL) &&
11123
0
                   (!xmlBufIsEmpty(ctxt->input->buf->raw))) {
11124
0
            xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
11125
0
                           "Truncated multi-byte sequence at EOF\n");
11126
0
        }
11127
0
  ctxt->instate = XML_PARSER_EOF;
11128
0
    }
11129
11130
    /*
11131
     * SAX: end of the document processing.
11132
     */
11133
0
    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11134
0
        ctxt->sax->endDocument(ctxt->userData);
11135
11136
    /*
11137
     * Remove locally kept entity definitions if the tree was not built
11138
     */
11139
0
    if ((ctxt->myDoc != NULL) &&
11140
0
  (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
11141
0
  xmlFreeDoc(ctxt->myDoc);
11142
0
  ctxt->myDoc = NULL;
11143
0
    }
11144
11145
0
    if ((ctxt->wellFormed) && (ctxt->myDoc != NULL)) {
11146
0
        ctxt->myDoc->properties |= XML_DOC_WELLFORMED;
11147
0
  if (ctxt->valid)
11148
0
      ctxt->myDoc->properties |= XML_DOC_DTDVALID;
11149
0
  if (ctxt->nsWellFormed)
11150
0
      ctxt->myDoc->properties |= XML_DOC_NSVALID;
11151
0
  if (ctxt->options & XML_PARSE_OLD10)
11152
0
      ctxt->myDoc->properties |= XML_DOC_OLD10;
11153
0
    }
11154
0
    if (! ctxt->wellFormed) {
11155
0
  ctxt->valid = 0;
11156
0
  return(-1);
11157
0
    }
11158
0
    return(0);
11159
0
}
11160
11161
/**
11162
 * xmlParseExtParsedEnt:
11163
 * @ctxt:  an XML parser context
11164
 *
11165
 * parse a general parsed entity
11166
 * An external general parsed entity is well-formed if it matches the
11167
 * production labeled extParsedEnt.
11168
 *
11169
 * [78] extParsedEnt ::= TextDecl? content
11170
 *
11171
 * Returns 0, -1 in case of error. the parser context is augmented
11172
 *                as a result of the parsing.
11173
 */
11174
11175
int
11176
0
xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) {
11177
0
    if ((ctxt == NULL) || (ctxt->input == NULL))
11178
0
        return(-1);
11179
11180
0
    xmlDetectSAX2(ctxt);
11181
11182
    /*
11183
     * SAX: beginning of the document processing.
11184
     */
11185
0
    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
11186
0
        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
11187
11188
0
    xmlDetectEncoding(ctxt);
11189
11190
0
    if (CUR == 0) {
11191
0
  xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
11192
0
    }
11193
11194
    /*
11195
     * Check for the XMLDecl in the Prolog.
11196
     */
11197
0
    GROW;
11198
0
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
11199
11200
  /*
11201
   * Note that we will switch encoding on the fly.
11202
   */
11203
0
  xmlParseXMLDecl(ctxt);
11204
0
  if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
11205
      /*
11206
       * The XML REC instructs us to stop parsing right here
11207
       */
11208
0
      return(-1);
11209
0
  }
11210
0
  SKIP_BLANKS;
11211
0
    } else {
11212
0
  ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11213
0
    }
11214
0
    if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
11215
0
        ctxt->sax->startDocument(ctxt->userData);
11216
0
    if (ctxt->instate == XML_PARSER_EOF)
11217
0
  return(-1);
11218
11219
    /*
11220
     * Doing validity checking on chunk doesn't make sense
11221
     */
11222
0
    ctxt->instate = XML_PARSER_CONTENT;
11223
0
    ctxt->validate = 0;
11224
0
    ctxt->loadsubset = 0;
11225
0
    ctxt->depth = 0;
11226
11227
0
    xmlParseContent(ctxt);
11228
0
    if (ctxt->instate == XML_PARSER_EOF)
11229
0
  return(-1);
11230
11231
0
    if ((RAW == '<') && (NXT(1) == '/')) {
11232
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
11233
0
    } else if (RAW != 0) {
11234
0
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
11235
0
    }
11236
11237
    /*
11238
     * SAX: end of the document processing.
11239
     */
11240
0
    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11241
0
        ctxt->sax->endDocument(ctxt->userData);
11242
11243
0
    if (! ctxt->wellFormed) return(-1);
11244
0
    return(0);
11245
0
}
11246
11247
#ifdef LIBXML_PUSH_ENABLED
11248
/************************************************************************
11249
 *                  *
11250
 *    Progressive parsing interfaces        *
11251
 *                  *
11252
 ************************************************************************/
11253
11254
/**
11255
 * xmlParseLookupChar:
11256
 * @ctxt:  an XML parser context
11257
 * @c:  character
11258
 *
11259
 * Check whether the input buffer contains a character.
11260
 */
11261
static int
11262
99
xmlParseLookupChar(xmlParserCtxtPtr ctxt, int c) {
11263
99
    const xmlChar *cur;
11264
11265
99
    if (ctxt->checkIndex == 0) {
11266
99
        cur = ctxt->input->cur + 1;
11267
99
    } else {
11268
0
        cur = ctxt->input->cur + ctxt->checkIndex;
11269
0
    }
11270
11271
99
    if (memchr(cur, c, ctxt->input->end - cur) == NULL) {
11272
0
        size_t index = ctxt->input->end - ctxt->input->cur;
11273
11274
0
        if (index > LONG_MAX) {
11275
0
            ctxt->checkIndex = 0;
11276
0
            return(1);
11277
0
        }
11278
0
        ctxt->checkIndex = index;
11279
0
        return(0);
11280
99
    } else {
11281
99
        ctxt->checkIndex = 0;
11282
99
        return(1);
11283
99
    }
11284
99
}
11285
11286
/**
11287
 * xmlParseLookupString:
11288
 * @ctxt:  an XML parser context
11289
 * @startDelta: delta to apply at the start
11290
 * @str:  string
11291
 * @strLen:  length of string
11292
 *
11293
 * Check whether the input buffer contains a string.
11294
 */
11295
static const xmlChar *
11296
xmlParseLookupString(xmlParserCtxtPtr ctxt, size_t startDelta,
11297
0
                     const char *str, size_t strLen) {
11298
0
    const xmlChar *cur, *term;
11299
11300
0
    if (ctxt->checkIndex == 0) {
11301
0
        cur = ctxt->input->cur + startDelta;
11302
0
    } else {
11303
0
        cur = ctxt->input->cur + ctxt->checkIndex;
11304
0
    }
11305
11306
0
    term = BAD_CAST strstr((const char *) cur, str);
11307
0
    if (term == NULL) {
11308
0
        const xmlChar *end = ctxt->input->end;
11309
0
        size_t index;
11310
11311
        /* Rescan (strLen - 1) characters. */
11312
0
        if ((size_t) (end - cur) < strLen)
11313
0
            end = cur;
11314
0
        else
11315
0
            end -= strLen - 1;
11316
0
        index = end - ctxt->input->cur;
11317
0
        if (index > LONG_MAX) {
11318
0
            ctxt->checkIndex = 0;
11319
0
            return(ctxt->input->end - strLen);
11320
0
        }
11321
0
        ctxt->checkIndex = index;
11322
0
    } else {
11323
0
        ctxt->checkIndex = 0;
11324
0
    }
11325
11326
0
    return(term);
11327
0
}
11328
11329
/**
11330
 * xmlParseLookupCharData:
11331
 * @ctxt:  an XML parser context
11332
 *
11333
 * Check whether the input buffer contains terminated char data.
11334
 */
11335
static int
11336
88
xmlParseLookupCharData(xmlParserCtxtPtr ctxt) {
11337
88
    const xmlChar *cur = ctxt->input->cur + ctxt->checkIndex;
11338
88
    const xmlChar *end = ctxt->input->end;
11339
88
    size_t index;
11340
11341
1.02k
    while (cur < end) {
11342
1.02k
        if ((*cur == '<') || (*cur == '&')) {
11343
88
            ctxt->checkIndex = 0;
11344
88
            return(1);
11345
88
        }
11346
935
        cur++;
11347
935
    }
11348
11349
0
    index = cur - ctxt->input->cur;
11350
0
    if (index > LONG_MAX) {
11351
0
        ctxt->checkIndex = 0;
11352
0
        return(1);
11353
0
    }
11354
0
    ctxt->checkIndex = index;
11355
0
    return(0);
11356
0
}
11357
11358
/**
11359
 * xmlParseLookupGt:
11360
 * @ctxt:  an XML parser context
11361
 *
11362
 * Check whether there's enough data in the input buffer to finish parsing
11363
 * a start tag. This has to take quotes into account.
11364
 */
11365
static int
11366
99
xmlParseLookupGt(xmlParserCtxtPtr ctxt) {
11367
99
    const xmlChar *cur;
11368
99
    const xmlChar *end = ctxt->input->end;
11369
99
    int state = ctxt->endCheckState;
11370
99
    size_t index;
11371
11372
99
    if (ctxt->checkIndex == 0)
11373
99
        cur = ctxt->input->cur + 1;
11374
0
    else
11375
0
        cur = ctxt->input->cur + ctxt->checkIndex;
11376
11377
1.98k
    while (cur < end) {
11378
1.98k
        if (state) {
11379
308
            if (*cur == state)
11380
77
                state = 0;
11381
1.67k
        } else if (*cur == '\'' || *cur == '"') {
11382
77
            state = *cur;
11383
1.59k
        } else if (*cur == '>') {
11384
99
            ctxt->checkIndex = 0;
11385
99
            ctxt->endCheckState = 0;
11386
99
            return(1);
11387
99
        }
11388
1.88k
        cur++;
11389
1.88k
    }
11390
11391
0
    index = cur - ctxt->input->cur;
11392
0
    if (index > LONG_MAX) {
11393
0
        ctxt->checkIndex = 0;
11394
0
        ctxt->endCheckState = 0;
11395
0
        return(1);
11396
0
    }
11397
0
    ctxt->checkIndex = index;
11398
0
    ctxt->endCheckState = state;
11399
0
    return(0);
11400
0
}
11401
11402
/**
11403
 * xmlParseLookupInternalSubset:
11404
 * @ctxt:  an XML parser context
11405
 *
11406
 * Check whether there's enough data in the input buffer to finish parsing
11407
 * the internal subset.
11408
 */
11409
static int
11410
0
xmlParseLookupInternalSubset(xmlParserCtxtPtr ctxt) {
11411
    /*
11412
     * Sorry, but progressive parsing of the internal subset is not
11413
     * supported. We first check that the full content of the internal
11414
     * subset is available and parsing is launched only at that point.
11415
     * Internal subset ends with "']' S? '>'" in an unescaped section and
11416
     * not in a ']]>' sequence which are conditional sections.
11417
     */
11418
0
    const xmlChar *cur, *start;
11419
0
    const xmlChar *end = ctxt->input->end;
11420
0
    int state = ctxt->endCheckState;
11421
0
    size_t index;
11422
11423
0
    if (ctxt->checkIndex == 0) {
11424
0
        cur = ctxt->input->cur + 1;
11425
0
    } else {
11426
0
        cur = ctxt->input->cur + ctxt->checkIndex;
11427
0
    }
11428
0
    start = cur;
11429
11430
0
    while (cur < end) {
11431
0
        if (state == '-') {
11432
0
            if ((*cur == '-') &&
11433
0
                (cur[1] == '-') &&
11434
0
                (cur[2] == '>')) {
11435
0
                state = 0;
11436
0
                cur += 3;
11437
0
                start = cur;
11438
0
                continue;
11439
0
            }
11440
0
        }
11441
0
        else if (state == ']') {
11442
0
            if (*cur == '>') {
11443
0
                ctxt->checkIndex = 0;
11444
0
                ctxt->endCheckState = 0;
11445
0
                return(1);
11446
0
            }
11447
0
            if (IS_BLANK_CH(*cur)) {
11448
0
                state = ' ';
11449
0
            } else if (*cur != ']') {
11450
0
                state = 0;
11451
0
                start = cur;
11452
0
                continue;
11453
0
            }
11454
0
        }
11455
0
        else if (state == ' ') {
11456
0
            if (*cur == '>') {
11457
0
                ctxt->checkIndex = 0;
11458
0
                ctxt->endCheckState = 0;
11459
0
                return(1);
11460
0
            }
11461
0
            if (!IS_BLANK_CH(*cur)) {
11462
0
                state = 0;
11463
0
                start = cur;
11464
0
                continue;
11465
0
            }
11466
0
        }
11467
0
        else if (state != 0) {
11468
0
            if (*cur == state) {
11469
0
                state = 0;
11470
0
                start = cur + 1;
11471
0
            }
11472
0
        }
11473
0
        else if (*cur == '<') {
11474
0
            if ((cur[1] == '!') &&
11475
0
                (cur[2] == '-') &&
11476
0
                (cur[3] == '-')) {
11477
0
                state = '-';
11478
0
                cur += 4;
11479
                /* Don't treat <!--> as comment */
11480
0
                start = cur;
11481
0
                continue;
11482
0
            }
11483
0
        }
11484
0
        else if ((*cur == '"') || (*cur == '\'') || (*cur == ']')) {
11485
0
            state = *cur;
11486
0
        }
11487
11488
0
        cur++;
11489
0
    }
11490
11491
    /*
11492
     * Rescan the three last characters to detect "<!--" and "-->"
11493
     * split across chunks.
11494
     */
11495
0
    if ((state == 0) || (state == '-')) {
11496
0
        if (cur - start < 3)
11497
0
            cur = start;
11498
0
        else
11499
0
            cur -= 3;
11500
0
    }
11501
0
    index = cur - ctxt->input->cur;
11502
0
    if (index > LONG_MAX) {
11503
0
        ctxt->checkIndex = 0;
11504
0
        ctxt->endCheckState = 0;
11505
0
        return(1);
11506
0
    }
11507
0
    ctxt->checkIndex = index;
11508
0
    ctxt->endCheckState = state;
11509
0
    return(0);
11510
0
}
11511
11512
/**
11513
 * xmlCheckCdataPush:
11514
 * @cur: pointer to the block of characters
11515
 * @len: length of the block in bytes
11516
 * @complete: 1 if complete CDATA block is passed in, 0 if partial block
11517
 *
11518
 * Check that the block of characters is okay as SCdata content [20]
11519
 *
11520
 * Returns the number of bytes to pass if okay, a negative index where an
11521
 *         UTF-8 error occurred otherwise
11522
 */
11523
static int
11524
0
xmlCheckCdataPush(const xmlChar *utf, int len, int complete) {
11525
0
    int ix;
11526
0
    unsigned char c;
11527
0
    int codepoint;
11528
11529
0
    if ((utf == NULL) || (len <= 0))
11530
0
        return(0);
11531
11532
0
    for (ix = 0; ix < len;) {      /* string is 0-terminated */
11533
0
        c = utf[ix];
11534
0
        if ((c & 0x80) == 0x00) { /* 1-byte code, starts with 10 */
11535
0
      if (c >= 0x20)
11536
0
    ix++;
11537
0
      else if ((c == 0xA) || (c == 0xD) || (c == 0x9))
11538
0
          ix++;
11539
0
      else
11540
0
          return(-ix);
11541
0
  } else if ((c & 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */
11542
0
      if (ix + 2 > len) return(complete ? -ix : ix);
11543
0
      if ((utf[ix+1] & 0xc0 ) != 0x80)
11544
0
          return(-ix);
11545
0
      codepoint = (utf[ix] & 0x1f) << 6;
11546
0
      codepoint |= utf[ix+1] & 0x3f;
11547
0
      if (!xmlIsCharQ(codepoint))
11548
0
          return(-ix);
11549
0
      ix += 2;
11550
0
  } else if ((c & 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */
11551
0
      if (ix + 3 > len) return(complete ? -ix : ix);
11552
0
      if (((utf[ix+1] & 0xc0) != 0x80) ||
11553
0
          ((utf[ix+2] & 0xc0) != 0x80))
11554
0
        return(-ix);
11555
0
      codepoint = (utf[ix] & 0xf) << 12;
11556
0
      codepoint |= (utf[ix+1] & 0x3f) << 6;
11557
0
      codepoint |= utf[ix+2] & 0x3f;
11558
0
      if (!xmlIsCharQ(codepoint))
11559
0
          return(-ix);
11560
0
      ix += 3;
11561
0
  } else if ((c & 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */
11562
0
      if (ix + 4 > len) return(complete ? -ix : ix);
11563
0
      if (((utf[ix+1] & 0xc0) != 0x80) ||
11564
0
          ((utf[ix+2] & 0xc0) != 0x80) ||
11565
0
    ((utf[ix+3] & 0xc0) != 0x80))
11566
0
        return(-ix);
11567
0
      codepoint = (utf[ix] & 0x7) << 18;
11568
0
      codepoint |= (utf[ix+1] & 0x3f) << 12;
11569
0
      codepoint |= (utf[ix+2] & 0x3f) << 6;
11570
0
      codepoint |= utf[ix+3] & 0x3f;
11571
0
      if (!xmlIsCharQ(codepoint))
11572
0
          return(-ix);
11573
0
      ix += 4;
11574
0
  } else       /* unknown encoding */
11575
0
      return(-ix);
11576
0
      }
11577
0
      return(ix);
11578
0
}
11579
11580
/**
11581
 * xmlParseTryOrFinish:
11582
 * @ctxt:  an XML parser context
11583
 * @terminate:  last chunk indicator
11584
 *
11585
 * Try to progress on parsing
11586
 *
11587
 * Returns zero if no parsing was possible
11588
 */
11589
static int
11590
11
xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
11591
11
    int ret = 0;
11592
11
    size_t avail;
11593
11
    xmlChar cur, next;
11594
11595
11
    if (ctxt->input == NULL)
11596
0
        return(0);
11597
11598
11
    if ((ctxt->input != NULL) &&
11599
11
        (ctxt->input->cur - ctxt->input->base > 4096)) {
11600
0
        xmlParserShrink(ctxt);
11601
0
    }
11602
11603
605
    while (ctxt->instate != XML_PARSER_EOF) {
11604
605
  if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
11605
0
      return(0);
11606
11607
605
        avail = ctxt->input->end - ctxt->input->cur;
11608
605
        if (avail < 1)
11609
11
      goto done;
11610
594
        switch (ctxt->instate) {
11611
0
            case XML_PARSER_EOF:
11612
          /*
11613
     * Document parsing is done !
11614
     */
11615
0
          goto done;
11616
11
            case XML_PARSER_START:
11617
                /*
11618
                 * Very first chars read from the document flow.
11619
                 */
11620
11
                if ((!terminate) && (avail < 4))
11621
0
                    goto done;
11622
11623
                /*
11624
                 * We need more bytes to detect EBCDIC code pages.
11625
                 * See xmlDetectEBCDIC.
11626
                 */
11627
11
                if ((CMP4(CUR_PTR, 0x4C, 0x6F, 0xA7, 0x94)) &&
11628
11
                    (!terminate) && (avail < 200))
11629
0
                    goto done;
11630
11631
11
                xmlDetectEncoding(ctxt);
11632
11
                if (ctxt->instate == XML_PARSER_EOF)
11633
0
                    goto done;
11634
11
                ctxt->instate = XML_PARSER_XML_DECL;
11635
11
    break;
11636
11637
11
            case XML_PARSER_XML_DECL:
11638
11
    if ((!terminate) && (avail < 2))
11639
0
        goto done;
11640
11
    cur = ctxt->input->cur[0];
11641
11
    next = ctxt->input->cur[1];
11642
11
          if ((cur == '<') && (next == '?')) {
11643
        /* PI or XML decl */
11644
0
        if ((!terminate) &&
11645
0
                        (!xmlParseLookupString(ctxt, 2, "?>", 2)))
11646
0
      goto done;
11647
0
        if ((ctxt->input->cur[2] == 'x') &&
11648
0
      (ctxt->input->cur[3] == 'm') &&
11649
0
      (ctxt->input->cur[4] == 'l') &&
11650
0
      (IS_BLANK_CH(ctxt->input->cur[5]))) {
11651
0
      ret += 5;
11652
0
      xmlParseXMLDecl(ctxt);
11653
0
      if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
11654
          /*
11655
           * The XML REC instructs us to stop parsing right
11656
           * here
11657
           */
11658
0
          xmlHaltParser(ctxt);
11659
0
          return(0);
11660
0
      }
11661
0
        } else {
11662
0
      ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11663
0
        }
11664
11
    } else {
11665
11
        ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11666
11
        if (ctxt->version == NULL) {
11667
0
            xmlErrMemory(ctxt, NULL);
11668
0
      break;
11669
0
        }
11670
11
    }
11671
11
                if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
11672
0
                    ctxt->sax->setDocumentLocator(ctxt->userData,
11673
0
                                                  &xmlDefaultSAXLocator);
11674
11
                if ((ctxt->sax) && (ctxt->sax->startDocument) &&
11675
11
                    (!ctxt->disableSAX))
11676
0
                    ctxt->sax->startDocument(ctxt->userData);
11677
11
                if (ctxt->instate == XML_PARSER_EOF)
11678
0
                    goto done;
11679
11
                ctxt->instate = XML_PARSER_MISC;
11680
11
    break;
11681
99
            case XML_PARSER_START_TAG: {
11682
99
          const xmlChar *name;
11683
99
    const xmlChar *prefix = NULL;
11684
99
    const xmlChar *URI = NULL;
11685
99
                int line = ctxt->input->line;
11686
99
    int nbNs = 0;
11687
11688
99
    if ((!terminate) && (avail < 2))
11689
0
        goto done;
11690
99
    cur = ctxt->input->cur[0];
11691
99
          if (cur != '<') {
11692
0
        xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
11693
0
                                   "Start tag expected, '<' not found");
11694
0
        xmlHaltParser(ctxt);
11695
0
        if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11696
0
      ctxt->sax->endDocument(ctxt->userData);
11697
0
        goto done;
11698
0
    }
11699
99
    if ((!terminate) && (!xmlParseLookupGt(ctxt)))
11700
0
                    goto done;
11701
99
    if (ctxt->spaceNr == 0)
11702
0
        spacePush(ctxt, -1);
11703
99
    else if (*ctxt->space == -2)
11704
88
        spacePush(ctxt, -1);
11705
11
    else
11706
11
        spacePush(ctxt, *ctxt->space);
11707
99
#ifdef LIBXML_SAX1_ENABLED
11708
99
    if (ctxt->sax2)
11709
0
#endif /* LIBXML_SAX1_ENABLED */
11710
0
        name = xmlParseStartTag2(ctxt, &prefix, &URI, &nbNs);
11711
99
#ifdef LIBXML_SAX1_ENABLED
11712
99
    else
11713
99
        name = xmlParseStartTag(ctxt);
11714
99
#endif /* LIBXML_SAX1_ENABLED */
11715
99
    if (ctxt->instate == XML_PARSER_EOF)
11716
0
        goto done;
11717
99
    if (name == NULL) {
11718
0
        spacePop(ctxt);
11719
0
        xmlHaltParser(ctxt);
11720
0
        if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11721
0
      ctxt->sax->endDocument(ctxt->userData);
11722
0
        goto done;
11723
0
    }
11724
99
#ifdef LIBXML_VALID_ENABLED
11725
    /*
11726
     * [ VC: Root Element Type ]
11727
     * The Name in the document type declaration must match
11728
     * the element type of the root element.
11729
     */
11730
99
    if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
11731
99
        ctxt->node && (ctxt->node == ctxt->myDoc->children))
11732
0
        ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
11733
99
#endif /* LIBXML_VALID_ENABLED */
11734
11735
    /*
11736
     * Check for an Empty Element.
11737
     */
11738
99
    if ((RAW == '/') && (NXT(1) == '>')) {
11739
0
        SKIP(2);
11740
11741
0
        if (ctxt->sax2) {
11742
0
      if ((ctxt->sax != NULL) &&
11743
0
          (ctxt->sax->endElementNs != NULL) &&
11744
0
          (!ctxt->disableSAX))
11745
0
          ctxt->sax->endElementNs(ctxt->userData, name,
11746
0
                                  prefix, URI);
11747
0
      if (nbNs > 0)
11748
0
          xmlParserNsPop(ctxt, nbNs);
11749
0
#ifdef LIBXML_SAX1_ENABLED
11750
0
        } else {
11751
0
      if ((ctxt->sax != NULL) &&
11752
0
          (ctxt->sax->endElement != NULL) &&
11753
0
          (!ctxt->disableSAX))
11754
0
          ctxt->sax->endElement(ctxt->userData, name);
11755
0
#endif /* LIBXML_SAX1_ENABLED */
11756
0
        }
11757
0
        spacePop(ctxt);
11758
99
    } else if (RAW == '>') {
11759
99
        NEXT;
11760
99
                    nameNsPush(ctxt, name, prefix, URI, line, nbNs);
11761
99
    } else {
11762
0
        xmlFatalErrMsgStr(ctxt, XML_ERR_GT_REQUIRED,
11763
0
           "Couldn't find end of Start Tag %s\n",
11764
0
           name);
11765
0
        nodePop(ctxt);
11766
0
        spacePop(ctxt);
11767
0
                    if (nbNs > 0)
11768
0
                        xmlParserNsPop(ctxt, nbNs);
11769
0
    }
11770
11771
99
                if (ctxt->instate == XML_PARSER_EOF)
11772
0
                    goto done;
11773
99
                if (ctxt->nameNr == 0)
11774
0
                    ctxt->instate = XML_PARSER_EPILOG;
11775
99
                else
11776
99
                    ctxt->instate = XML_PARSER_CONTENT;
11777
99
                break;
11778
99
      }
11779
363
            case XML_PARSER_CONTENT: {
11780
363
    cur = ctxt->input->cur[0];
11781
11782
363
    if (cur == '<') {
11783
187
                    if ((!terminate) && (avail < 2))
11784
0
                        goto done;
11785
187
        next = ctxt->input->cur[1];
11786
11787
187
                    if (next == '/') {
11788
99
                        ctxt->instate = XML_PARSER_END_TAG;
11789
99
                        break;
11790
99
                    } else if (next == '?') {
11791
0
                        if ((!terminate) &&
11792
0
                            (!xmlParseLookupString(ctxt, 2, "?>", 2)))
11793
0
                            goto done;
11794
0
                        xmlParsePI(ctxt);
11795
0
                        if (ctxt->instate == XML_PARSER_EOF)
11796
0
                            goto done;
11797
0
                        ctxt->instate = XML_PARSER_CONTENT;
11798
0
                        break;
11799
88
                    } else if (next == '!') {
11800
0
                        if ((!terminate) && (avail < 3))
11801
0
                            goto done;
11802
0
                        next = ctxt->input->cur[2];
11803
11804
0
                        if (next == '-') {
11805
0
                            if ((!terminate) && (avail < 4))
11806
0
                                goto done;
11807
0
                            if (ctxt->input->cur[3] == '-') {
11808
0
                                if ((!terminate) &&
11809
0
                                    (!xmlParseLookupString(ctxt, 4, "-->", 3)))
11810
0
                                    goto done;
11811
0
                                xmlParseComment(ctxt);
11812
0
                                if (ctxt->instate == XML_PARSER_EOF)
11813
0
                                    goto done;
11814
0
                                ctxt->instate = XML_PARSER_CONTENT;
11815
0
                                break;
11816
0
                            }
11817
0
                        } else if (next == '[') {
11818
0
                            if ((!terminate) && (avail < 9))
11819
0
                                goto done;
11820
0
                            if ((ctxt->input->cur[2] == '[') &&
11821
0
                                (ctxt->input->cur[3] == 'C') &&
11822
0
                                (ctxt->input->cur[4] == 'D') &&
11823
0
                                (ctxt->input->cur[5] == 'A') &&
11824
0
                                (ctxt->input->cur[6] == 'T') &&
11825
0
                                (ctxt->input->cur[7] == 'A') &&
11826
0
                                (ctxt->input->cur[8] == '[')) {
11827
0
                                SKIP(9);
11828
0
                                ctxt->instate = XML_PARSER_CDATA_SECTION;
11829
0
                                break;
11830
0
                            }
11831
0
                        }
11832
0
                    }
11833
187
    } else if (cur == '&') {
11834
0
        if ((!terminate) && (!xmlParseLookupChar(ctxt, ';')))
11835
0
      goto done;
11836
0
        xmlParseReference(ctxt);
11837
0
                    break;
11838
176
    } else {
11839
        /* TODO Avoid the extra copy, handle directly !!! */
11840
        /*
11841
         * Goal of the following test is:
11842
         *  - minimize calls to the SAX 'character' callback
11843
         *    when they are mergeable
11844
         *  - handle an problem for isBlank when we only parse
11845
         *    a sequence of blank chars and the next one is
11846
         *    not available to check against '<' presence.
11847
         *  - tries to homogenize the differences in SAX
11848
         *    callbacks between the push and pull versions
11849
         *    of the parser.
11850
         */
11851
176
        if (avail < XML_PARSER_BIG_BUFFER_SIZE) {
11852
88
      if ((!terminate) && (!xmlParseLookupCharData(ctxt)))
11853
0
          goto done;
11854
88
                    }
11855
176
                    ctxt->checkIndex = 0;
11856
176
        xmlParseCharDataInternal(ctxt, !terminate);
11857
176
                    break;
11858
176
    }
11859
11860
88
                ctxt->instate = XML_PARSER_START_TAG;
11861
88
    break;
11862
363
      }
11863
99
            case XML_PARSER_END_TAG:
11864
99
    if ((!terminate) && (!xmlParseLookupChar(ctxt, '>')))
11865
0
        goto done;
11866
99
    if (ctxt->sax2) {
11867
0
              xmlParseEndTag2(ctxt, &ctxt->pushTab[ctxt->nameNr - 1]);
11868
0
        nameNsPop(ctxt);
11869
0
    }
11870
99
#ifdef LIBXML_SAX1_ENABLED
11871
99
      else
11872
99
        xmlParseEndTag1(ctxt, 0);
11873
99
#endif /* LIBXML_SAX1_ENABLED */
11874
99
                if (ctxt->instate == XML_PARSER_EOF)
11875
0
                    goto done;
11876
99
    if (ctxt->nameNr == 0) {
11877
11
        ctxt->instate = XML_PARSER_EPILOG;
11878
88
    } else {
11879
88
        ctxt->instate = XML_PARSER_CONTENT;
11880
88
    }
11881
99
    break;
11882
0
            case XML_PARSER_CDATA_SECTION: {
11883
          /*
11884
     * The Push mode need to have the SAX callback for
11885
     * cdataBlock merge back contiguous callbacks.
11886
     */
11887
0
    const xmlChar *term;
11888
11889
0
                if (terminate) {
11890
                    /*
11891
                     * Don't call xmlParseLookupString. If 'terminate'
11892
                     * is set, checkIndex is invalid.
11893
                     */
11894
0
                    term = BAD_CAST strstr((const char *) ctxt->input->cur,
11895
0
                                           "]]>");
11896
0
                } else {
11897
0
        term = xmlParseLookupString(ctxt, 0, "]]>", 3);
11898
0
                }
11899
11900
0
    if (term == NULL) {
11901
0
        int tmp, size;
11902
11903
0
                    if (terminate) {
11904
                        /* Unfinished CDATA section */
11905
0
                        size = ctxt->input->end - ctxt->input->cur;
11906
0
                    } else {
11907
0
                        if (avail < XML_PARSER_BIG_BUFFER_SIZE + 2)
11908
0
                            goto done;
11909
0
                        ctxt->checkIndex = 0;
11910
                        /* XXX: Why don't we pass the full buffer? */
11911
0
                        size = XML_PARSER_BIG_BUFFER_SIZE;
11912
0
                    }
11913
0
                    tmp = xmlCheckCdataPush(ctxt->input->cur, size, 0);
11914
0
                    if (tmp <= 0) {
11915
0
                        tmp = -tmp;
11916
0
                        ctxt->input->cur += tmp;
11917
0
                        goto encoding_error;
11918
0
                    }
11919
0
                    if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
11920
0
                        if (ctxt->sax->cdataBlock != NULL)
11921
0
                            ctxt->sax->cdataBlock(ctxt->userData,
11922
0
                                                  ctxt->input->cur, tmp);
11923
0
                        else if (ctxt->sax->characters != NULL)
11924
0
                            ctxt->sax->characters(ctxt->userData,
11925
0
                                                  ctxt->input->cur, tmp);
11926
0
                    }
11927
0
                    if (ctxt->instate == XML_PARSER_EOF)
11928
0
                        goto done;
11929
0
                    SKIPL(tmp);
11930
0
    } else {
11931
0
                    int base = term - CUR_PTR;
11932
0
        int tmp;
11933
11934
0
        tmp = xmlCheckCdataPush(ctxt->input->cur, base, 1);
11935
0
        if ((tmp < 0) || (tmp != base)) {
11936
0
      tmp = -tmp;
11937
0
      ctxt->input->cur += tmp;
11938
0
      goto encoding_error;
11939
0
        }
11940
0
        if ((ctxt->sax != NULL) && (base == 0) &&
11941
0
            (ctxt->sax->cdataBlock != NULL) &&
11942
0
            (!ctxt->disableSAX)) {
11943
      /*
11944
       * Special case to provide identical behaviour
11945
       * between pull and push parsers on enpty CDATA
11946
       * sections
11947
       */
11948
0
       if ((ctxt->input->cur - ctxt->input->base >= 9) &&
11949
0
           (!strncmp((const char *)&ctxt->input->cur[-9],
11950
0
                     "<![CDATA[", 9)))
11951
0
           ctxt->sax->cdataBlock(ctxt->userData,
11952
0
                                 BAD_CAST "", 0);
11953
0
        } else if ((ctxt->sax != NULL) && (base > 0) &&
11954
0
      (!ctxt->disableSAX)) {
11955
0
      if (ctxt->sax->cdataBlock != NULL)
11956
0
          ctxt->sax->cdataBlock(ctxt->userData,
11957
0
              ctxt->input->cur, base);
11958
0
      else if (ctxt->sax->characters != NULL)
11959
0
          ctxt->sax->characters(ctxt->userData,
11960
0
              ctxt->input->cur, base);
11961
0
        }
11962
0
        if (ctxt->instate == XML_PARSER_EOF)
11963
0
      goto done;
11964
0
        SKIPL(base + 3);
11965
0
        ctxt->instate = XML_PARSER_CONTENT;
11966
0
    }
11967
0
    break;
11968
0
      }
11969
11
            case XML_PARSER_MISC:
11970
11
            case XML_PARSER_PROLOG:
11971
11
            case XML_PARSER_EPILOG:
11972
11
    SKIP_BLANKS;
11973
11
                avail = ctxt->input->end - ctxt->input->cur;
11974
11
    if (avail < 1)
11975
0
        goto done;
11976
11
    if (ctxt->input->cur[0] == '<') {
11977
11
                    if ((!terminate) && (avail < 2))
11978
0
                        goto done;
11979
11
                    next = ctxt->input->cur[1];
11980
11
                    if (next == '?') {
11981
0
                        if ((!terminate) &&
11982
0
                            (!xmlParseLookupString(ctxt, 2, "?>", 2)))
11983
0
                            goto done;
11984
0
                        xmlParsePI(ctxt);
11985
0
                        if (ctxt->instate == XML_PARSER_EOF)
11986
0
                            goto done;
11987
0
                        break;
11988
11
                    } else if (next == '!') {
11989
0
                        if ((!terminate) && (avail < 3))
11990
0
                            goto done;
11991
11992
0
                        if (ctxt->input->cur[2] == '-') {
11993
0
                            if ((!terminate) && (avail < 4))
11994
0
                                goto done;
11995
0
                            if (ctxt->input->cur[3] == '-') {
11996
0
                                if ((!terminate) &&
11997
0
                                    (!xmlParseLookupString(ctxt, 4, "-->", 3)))
11998
0
                                    goto done;
11999
0
                                xmlParseComment(ctxt);
12000
0
                                if (ctxt->instate == XML_PARSER_EOF)
12001
0
                                    goto done;
12002
0
                                break;
12003
0
                            }
12004
0
                        } else if (ctxt->instate == XML_PARSER_MISC) {
12005
0
                            if ((!terminate) && (avail < 9))
12006
0
                                goto done;
12007
0
                            if ((ctxt->input->cur[2] == 'D') &&
12008
0
                                (ctxt->input->cur[3] == 'O') &&
12009
0
                                (ctxt->input->cur[4] == 'C') &&
12010
0
                                (ctxt->input->cur[5] == 'T') &&
12011
0
                                (ctxt->input->cur[6] == 'Y') &&
12012
0
                                (ctxt->input->cur[7] == 'P') &&
12013
0
                                (ctxt->input->cur[8] == 'E')) {
12014
0
                                if ((!terminate) && (!xmlParseLookupGt(ctxt)))
12015
0
                                    goto done;
12016
0
                                ctxt->inSubset = 1;
12017
0
                                xmlParseDocTypeDecl(ctxt);
12018
0
                                if (ctxt->instate == XML_PARSER_EOF)
12019
0
                                    goto done;
12020
0
                                if (RAW == '[') {
12021
0
                                    ctxt->instate = XML_PARSER_DTD;
12022
0
                                } else {
12023
                                    /*
12024
                                     * Create and update the external subset.
12025
                                     */
12026
0
                                    ctxt->inSubset = 2;
12027
0
                                    if ((ctxt->sax != NULL) &&
12028
0
                                        (!ctxt->disableSAX) &&
12029
0
                                        (ctxt->sax->externalSubset != NULL))
12030
0
                                        ctxt->sax->externalSubset(
12031
0
                                                ctxt->userData,
12032
0
                                                ctxt->intSubName,
12033
0
                                                ctxt->extSubSystem,
12034
0
                                                ctxt->extSubURI);
12035
0
                                    ctxt->inSubset = 0;
12036
0
                                    xmlCleanSpecialAttr(ctxt);
12037
0
                                    if (ctxt->instate == XML_PARSER_EOF)
12038
0
                                        goto done;
12039
0
                                    ctxt->instate = XML_PARSER_PROLOG;
12040
0
                                }
12041
0
                                break;
12042
0
                            }
12043
0
                        }
12044
0
                    }
12045
11
                }
12046
12047
11
                if (ctxt->instate == XML_PARSER_EPILOG) {
12048
0
                    if (ctxt->errNo == XML_ERR_OK)
12049
0
                        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
12050
0
        ctxt->instate = XML_PARSER_EOF;
12051
0
                    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
12052
0
                        ctxt->sax->endDocument(ctxt->userData);
12053
11
                } else {
12054
11
        ctxt->instate = XML_PARSER_START_TAG;
12055
11
    }
12056
11
    break;
12057
0
            case XML_PARSER_DTD: {
12058
0
                if ((!terminate) && (!xmlParseLookupInternalSubset(ctxt)))
12059
0
                    goto done;
12060
0
    xmlParseInternalSubset(ctxt);
12061
0
    if (ctxt->instate == XML_PARSER_EOF)
12062
0
        goto done;
12063
0
    ctxt->inSubset = 2;
12064
0
    if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
12065
0
        (ctxt->sax->externalSubset != NULL))
12066
0
        ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
12067
0
          ctxt->extSubSystem, ctxt->extSubURI);
12068
0
    ctxt->inSubset = 0;
12069
0
    xmlCleanSpecialAttr(ctxt);
12070
0
    if (ctxt->instate == XML_PARSER_EOF)
12071
0
        goto done;
12072
0
    ctxt->instate = XML_PARSER_PROLOG;
12073
0
                break;
12074
0
      }
12075
0
            default:
12076
0
    xmlGenericError(xmlGenericErrorContext,
12077
0
      "PP: internal error\n");
12078
0
    ctxt->instate = XML_PARSER_EOF;
12079
0
    break;
12080
594
  }
12081
594
    }
12082
11
done:
12083
11
    return(ret);
12084
0
encoding_error:
12085
0
    if (ctxt->input->end - ctxt->input->cur < 4) {
12086
0
  __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
12087
0
         "Input is not proper UTF-8, indicate encoding !\n",
12088
0
         NULL, NULL);
12089
0
    } else {
12090
0
        char buffer[150];
12091
12092
0
  snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
12093
0
      ctxt->input->cur[0], ctxt->input->cur[1],
12094
0
      ctxt->input->cur[2], ctxt->input->cur[3]);
12095
0
  __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
12096
0
         "Input is not proper UTF-8, indicate encoding !\n%s",
12097
0
         BAD_CAST buffer, NULL);
12098
0
    }
12099
0
    return(0);
12100
11
}
12101
12102
/**
12103
 * xmlParseChunk:
12104
 * @ctxt:  an XML parser context
12105
 * @chunk:  an char array
12106
 * @size:  the size in byte of the chunk
12107
 * @terminate:  last chunk indicator
12108
 *
12109
 * Parse a Chunk of memory
12110
 *
12111
 * Returns zero if no error, the xmlParserErrors otherwise.
12112
 */
12113
int
12114
xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
12115
11
              int terminate) {
12116
11
    int end_in_lf = 0;
12117
12118
11
    if (ctxt == NULL)
12119
0
        return(XML_ERR_INTERNAL_ERROR);
12120
11
    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
12121
0
        return(ctxt->errNo);
12122
11
    if (ctxt->instate == XML_PARSER_EOF)
12123
0
        return(-1);
12124
11
    if (ctxt->input == NULL)
12125
0
        return(-1);
12126
12127
11
    ctxt->progressive = 1;
12128
11
    if (ctxt->instate == XML_PARSER_START)
12129
11
        xmlDetectSAX2(ctxt);
12130
11
    if ((size > 0) && (chunk != NULL) && (!terminate) &&
12131
11
        (chunk[size - 1] == '\r')) {
12132
0
  end_in_lf = 1;
12133
0
  size--;
12134
0
    }
12135
12136
11
    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
12137
11
        (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF))  {
12138
11
  size_t pos = ctxt->input->cur - ctxt->input->base;
12139
11
  int res;
12140
12141
11
  res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
12142
11
        xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos);
12143
11
  if (res < 0) {
12144
0
            xmlFatalErr(ctxt, ctxt->input->buf->error, NULL);
12145
0
      xmlHaltParser(ctxt);
12146
0
      return(ctxt->errNo);
12147
0
  }
12148
11
    }
12149
12150
11
    xmlParseTryOrFinish(ctxt, terminate);
12151
11
    if (ctxt->instate == XML_PARSER_EOF)
12152
0
        return(ctxt->errNo);
12153
12154
11
    if ((ctxt->input != NULL) &&
12155
11
         (((ctxt->input->end - ctxt->input->cur) > XML_MAX_LOOKUP_LIMIT) ||
12156
11
         ((ctxt->input->cur - ctxt->input->base) > XML_MAX_LOOKUP_LIMIT)) &&
12157
11
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
12158
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
12159
0
        xmlHaltParser(ctxt);
12160
0
    }
12161
11
    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
12162
0
        return(ctxt->errNo);
12163
12164
11
    if ((end_in_lf == 1) && (ctxt->input != NULL) &&
12165
11
        (ctxt->input->buf != NULL)) {
12166
0
  size_t pos = ctxt->input->cur - ctxt->input->base;
12167
0
        int res;
12168
12169
0
  res = xmlParserInputBufferPush(ctxt->input->buf, 1, "\r");
12170
0
  xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos);
12171
0
        if (res < 0) {
12172
0
            xmlFatalErr(ctxt, ctxt->input->buf->error, NULL);
12173
0
            xmlHaltParser(ctxt);
12174
0
            return(ctxt->errNo);
12175
0
        }
12176
0
    }
12177
11
    if (terminate) {
12178
  /*
12179
   * Check for termination
12180
   */
12181
0
        if ((ctxt->instate != XML_PARSER_EOF) &&
12182
0
            (ctxt->instate != XML_PARSER_EPILOG)) {
12183
0
            if (ctxt->nameNr > 0) {
12184
0
                const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
12185
0
                int line = ctxt->pushTab[ctxt->nameNr - 1].line;
12186
0
                xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
12187
0
                        "Premature end of data in tag %s line %d\n",
12188
0
                        name, line, NULL);
12189
0
            } else if (ctxt->instate == XML_PARSER_START) {
12190
0
                xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
12191
0
            } else {
12192
0
                xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
12193
0
                               "Start tag expected, '<' not found\n");
12194
0
            }
12195
0
        } else if ((ctxt->input->buf != NULL) &&
12196
0
                   (ctxt->input->buf->encoder != NULL) &&
12197
0
                   (!xmlBufIsEmpty(ctxt->input->buf->raw))) {
12198
0
            xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
12199
0
                           "Truncated multi-byte sequence at EOF\n");
12200
0
        }
12201
0
  if (ctxt->instate != XML_PARSER_EOF) {
12202
0
      if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
12203
0
    ctxt->sax->endDocument(ctxt->userData);
12204
0
  }
12205
0
  ctxt->instate = XML_PARSER_EOF;
12206
0
    }
12207
11
    if (ctxt->wellFormed == 0)
12208
0
  return((xmlParserErrors) ctxt->errNo);
12209
11
    else
12210
11
        return(0);
12211
11
}
12212
12213
/************************************************************************
12214
 *                  *
12215
 *    I/O front end functions to the parser     *
12216
 *                  *
12217
 ************************************************************************/
12218
12219
/**
12220
 * xmlCreatePushParserCtxt:
12221
 * @sax:  a SAX handler
12222
 * @user_data:  The user data returned on SAX callbacks
12223
 * @chunk:  a pointer to an array of chars
12224
 * @size:  number of chars in the array
12225
 * @filename:  an optional file name or URI
12226
 *
12227
 * Create a parser context for using the XML parser in push mode.
12228
 * If @buffer and @size are non-NULL, the data is used to detect
12229
 * the encoding.  The remaining characters will be parsed so they
12230
 * don't need to be fed in again through xmlParseChunk.
12231
 * To allow content encoding detection, @size should be >= 4
12232
 * The value of @filename is used for fetching external entities
12233
 * and error/warning reports.
12234
 *
12235
 * Returns the new parser context or NULL
12236
 */
12237
12238
xmlParserCtxtPtr
12239
xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
12240
11
                        const char *chunk, int size, const char *filename) {
12241
11
    xmlParserCtxtPtr ctxt;
12242
11
    xmlParserInputPtr inputStream;
12243
11
    xmlParserInputBufferPtr buf;
12244
12245
11
    buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE);
12246
11
    if (buf == NULL) return(NULL);
12247
12248
11
    ctxt = xmlNewSAXParserCtxt(sax, user_data);
12249
11
    if (ctxt == NULL) {
12250
0
        xmlErrMemory(NULL, "creating parser: out of memory\n");
12251
0
  xmlFreeParserInputBuffer(buf);
12252
0
  return(NULL);
12253
0
    }
12254
11
    ctxt->dictNames = 1;
12255
11
    if (filename == NULL) {
12256
0
  ctxt->directory = NULL;
12257
11
    } else {
12258
11
        ctxt->directory = xmlParserGetDirectory(filename);
12259
11
    }
12260
12261
11
    inputStream = xmlNewInputStream(ctxt);
12262
11
    if (inputStream == NULL) {
12263
0
  xmlFreeParserCtxt(ctxt);
12264
0
  xmlFreeParserInputBuffer(buf);
12265
0
  return(NULL);
12266
0
    }
12267
12268
11
    if (filename == NULL)
12269
0
  inputStream->filename = NULL;
12270
11
    else {
12271
11
  inputStream->filename = (char *)
12272
11
      xmlCanonicPath((const xmlChar *) filename);
12273
11
  if (inputStream->filename == NULL) {
12274
0
            xmlFreeInputStream(inputStream);
12275
0
      xmlFreeParserCtxt(ctxt);
12276
0
      xmlFreeParserInputBuffer(buf);
12277
0
      return(NULL);
12278
0
  }
12279
11
    }
12280
11
    inputStream->buf = buf;
12281
11
    xmlBufResetInput(inputStream->buf->buffer, inputStream);
12282
11
    inputPush(ctxt, inputStream);
12283
12284
11
    if ((size != 0) && (chunk != NULL) &&
12285
11
        (ctxt->input != NULL) && (ctxt->input->buf != NULL)) {
12286
0
  size_t pos = ctxt->input->cur - ctxt->input->base;
12287
0
        int res;
12288
12289
0
  res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
12290
0
        xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos);
12291
0
        if (res < 0) {
12292
0
            xmlFatalErr(ctxt, ctxt->input->buf->error, NULL);
12293
0
            xmlHaltParser(ctxt);
12294
0
        }
12295
0
    }
12296
12297
11
    return(ctxt);
12298
11
}
12299
#endif /* LIBXML_PUSH_ENABLED */
12300
12301
/**
12302
 * xmlStopParser:
12303
 * @ctxt:  an XML parser context
12304
 *
12305
 * Blocks further parser processing
12306
 */
12307
void
12308
0
xmlStopParser(xmlParserCtxtPtr ctxt) {
12309
0
    if (ctxt == NULL)
12310
0
        return;
12311
0
    xmlHaltParser(ctxt);
12312
0
    ctxt->errNo = XML_ERR_USER_STOP;
12313
0
}
12314
12315
/**
12316
 * xmlCreateIOParserCtxt:
12317
 * @sax:  a SAX handler
12318
 * @user_data:  The user data returned on SAX callbacks
12319
 * @ioread:  an I/O read function
12320
 * @ioclose:  an I/O close function
12321
 * @ioctx:  an I/O handler
12322
 * @enc:  the charset encoding if known
12323
 *
12324
 * Create a parser context for using the XML parser with an existing
12325
 * I/O stream
12326
 *
12327
 * Returns the new parser context or NULL
12328
 */
12329
xmlParserCtxtPtr
12330
xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
12331
  xmlInputReadCallback   ioread, xmlInputCloseCallback  ioclose,
12332
0
  void *ioctx, xmlCharEncoding enc) {
12333
0
    xmlParserCtxtPtr ctxt;
12334
0
    xmlParserInputPtr inputStream;
12335
0
    xmlParserInputBufferPtr buf;
12336
12337
0
    if (ioread == NULL) return(NULL);
12338
12339
0
    buf = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, enc);
12340
0
    if (buf == NULL) {
12341
0
        if (ioclose != NULL)
12342
0
            ioclose(ioctx);
12343
0
        return (NULL);
12344
0
    }
12345
12346
0
    ctxt = xmlNewSAXParserCtxt(sax, user_data);
12347
0
    if (ctxt == NULL) {
12348
0
  xmlFreeParserInputBuffer(buf);
12349
0
  return(NULL);
12350
0
    }
12351
12352
0
    inputStream = xmlNewIOInputStream(ctxt, buf, enc);
12353
0
    if (inputStream == NULL) {
12354
0
  xmlFreeParserCtxt(ctxt);
12355
0
  return(NULL);
12356
0
    }
12357
0
    inputPush(ctxt, inputStream);
12358
12359
0
    return(ctxt);
12360
0
}
12361
12362
#ifdef LIBXML_VALID_ENABLED
12363
/************************************************************************
12364
 *                  *
12365
 *    Front ends when parsing a DTD       *
12366
 *                  *
12367
 ************************************************************************/
12368
12369
/**
12370
 * xmlIOParseDTD:
12371
 * @sax:  the SAX handler block or NULL
12372
 * @input:  an Input Buffer
12373
 * @enc:  the charset encoding if known
12374
 *
12375
 * Load and parse a DTD
12376
 *
12377
 * Returns the resulting xmlDtdPtr or NULL in case of error.
12378
 * @input will be freed by the function in any case.
12379
 */
12380
12381
xmlDtdPtr
12382
xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
12383
0
        xmlCharEncoding enc) {
12384
0
    xmlDtdPtr ret = NULL;
12385
0
    xmlParserCtxtPtr ctxt;
12386
0
    xmlParserInputPtr pinput = NULL;
12387
12388
0
    if (input == NULL)
12389
0
  return(NULL);
12390
12391
0
    ctxt = xmlNewSAXParserCtxt(sax, NULL);
12392
0
    if (ctxt == NULL) {
12393
0
        xmlFreeParserInputBuffer(input);
12394
0
  return(NULL);
12395
0
    }
12396
12397
    /* We are loading a DTD */
12398
0
    ctxt->options |= XML_PARSE_DTDLOAD;
12399
12400
0
    xmlDetectSAX2(ctxt);
12401
12402
    /*
12403
     * generate a parser input from the I/O handler
12404
     */
12405
12406
0
    pinput = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
12407
0
    if (pinput == NULL) {
12408
0
        xmlFreeParserInputBuffer(input);
12409
0
  xmlFreeParserCtxt(ctxt);
12410
0
  return(NULL);
12411
0
    }
12412
12413
    /*
12414
     * plug some encoding conversion routines here.
12415
     */
12416
0
    if (xmlPushInput(ctxt, pinput) < 0) {
12417
0
  xmlFreeParserCtxt(ctxt);
12418
0
  return(NULL);
12419
0
    }
12420
0
    if (enc != XML_CHAR_ENCODING_NONE) {
12421
0
        xmlSwitchEncoding(ctxt, enc);
12422
0
    }
12423
12424
    /*
12425
     * let's parse that entity knowing it's an external subset.
12426
     */
12427
0
    ctxt->inSubset = 2;
12428
0
    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
12429
0
    if (ctxt->myDoc == NULL) {
12430
0
  xmlErrMemory(ctxt, "New Doc failed");
12431
0
  return(NULL);
12432
0
    }
12433
0
    ctxt->myDoc->properties = XML_DOC_INTERNAL;
12434
0
    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
12435
0
                                 BAD_CAST "none", BAD_CAST "none");
12436
12437
0
    xmlDetectEncoding(ctxt);
12438
12439
0
    xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none");
12440
12441
0
    if (ctxt->myDoc != NULL) {
12442
0
  if (ctxt->wellFormed) {
12443
0
      ret = ctxt->myDoc->extSubset;
12444
0
      ctxt->myDoc->extSubset = NULL;
12445
0
      if (ret != NULL) {
12446
0
    xmlNodePtr tmp;
12447
12448
0
    ret->doc = NULL;
12449
0
    tmp = ret->children;
12450
0
    while (tmp != NULL) {
12451
0
        tmp->doc = NULL;
12452
0
        tmp = tmp->next;
12453
0
    }
12454
0
      }
12455
0
  } else {
12456
0
      ret = NULL;
12457
0
  }
12458
0
        xmlFreeDoc(ctxt->myDoc);
12459
0
        ctxt->myDoc = NULL;
12460
0
    }
12461
0
    xmlFreeParserCtxt(ctxt);
12462
12463
0
    return(ret);
12464
0
}
12465
12466
/**
12467
 * xmlSAXParseDTD:
12468
 * @sax:  the SAX handler block
12469
 * @ExternalID:  a NAME* containing the External ID of the DTD
12470
 * @SystemID:  a NAME* containing the URL to the DTD
12471
 *
12472
 * DEPRECATED: Don't use.
12473
 *
12474
 * Load and parse an external subset.
12475
 *
12476
 * Returns the resulting xmlDtdPtr or NULL in case of error.
12477
 */
12478
12479
xmlDtdPtr
12480
xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
12481
0
                          const xmlChar *SystemID) {
12482
0
    xmlDtdPtr ret = NULL;
12483
0
    xmlParserCtxtPtr ctxt;
12484
0
    xmlParserInputPtr input = NULL;
12485
0
    xmlChar* systemIdCanonic;
12486
12487
0
    if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
12488
12489
0
    ctxt = xmlNewSAXParserCtxt(sax, NULL);
12490
0
    if (ctxt == NULL) {
12491
0
  return(NULL);
12492
0
    }
12493
12494
    /* We are loading a DTD */
12495
0
    ctxt->options |= XML_PARSE_DTDLOAD;
12496
12497
    /*
12498
     * Canonicalise the system ID
12499
     */
12500
0
    systemIdCanonic = xmlCanonicPath(SystemID);
12501
0
    if ((SystemID != NULL) && (systemIdCanonic == NULL)) {
12502
0
  xmlFreeParserCtxt(ctxt);
12503
0
  return(NULL);
12504
0
    }
12505
12506
    /*
12507
     * Ask the Entity resolver to load the damn thing
12508
     */
12509
12510
0
    if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
12511
0
  input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
12512
0
                                   systemIdCanonic);
12513
0
    if (input == NULL) {
12514
0
  xmlFreeParserCtxt(ctxt);
12515
0
  if (systemIdCanonic != NULL)
12516
0
      xmlFree(systemIdCanonic);
12517
0
  return(NULL);
12518
0
    }
12519
12520
    /*
12521
     * plug some encoding conversion routines here.
12522
     */
12523
0
    if (xmlPushInput(ctxt, input) < 0) {
12524
0
  xmlFreeParserCtxt(ctxt);
12525
0
  if (systemIdCanonic != NULL)
12526
0
      xmlFree(systemIdCanonic);
12527
0
  return(NULL);
12528
0
    }
12529
12530
0
    xmlDetectEncoding(ctxt);
12531
12532
0
    if (input->filename == NULL)
12533
0
  input->filename = (char *) systemIdCanonic;
12534
0
    else
12535
0
  xmlFree(systemIdCanonic);
12536
12537
    /*
12538
     * let's parse that entity knowing it's an external subset.
12539
     */
12540
0
    ctxt->inSubset = 2;
12541
0
    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
12542
0
    if (ctxt->myDoc == NULL) {
12543
0
  xmlErrMemory(ctxt, "New Doc failed");
12544
0
  xmlFreeParserCtxt(ctxt);
12545
0
  return(NULL);
12546
0
    }
12547
0
    ctxt->myDoc->properties = XML_DOC_INTERNAL;
12548
0
    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
12549
0
                                 ExternalID, SystemID);
12550
0
    xmlParseExternalSubset(ctxt, ExternalID, SystemID);
12551
12552
0
    if (ctxt->myDoc != NULL) {
12553
0
  if (ctxt->wellFormed) {
12554
0
      ret = ctxt->myDoc->extSubset;
12555
0
      ctxt->myDoc->extSubset = NULL;
12556
0
      if (ret != NULL) {
12557
0
    xmlNodePtr tmp;
12558
12559
0
    ret->doc = NULL;
12560
0
    tmp = ret->children;
12561
0
    while (tmp != NULL) {
12562
0
        tmp->doc = NULL;
12563
0
        tmp = tmp->next;
12564
0
    }
12565
0
      }
12566
0
  } else {
12567
0
      ret = NULL;
12568
0
  }
12569
0
        xmlFreeDoc(ctxt->myDoc);
12570
0
        ctxt->myDoc = NULL;
12571
0
    }
12572
0
    xmlFreeParserCtxt(ctxt);
12573
12574
0
    return(ret);
12575
0
}
12576
12577
12578
/**
12579
 * xmlParseDTD:
12580
 * @ExternalID:  a NAME* containing the External ID of the DTD
12581
 * @SystemID:  a NAME* containing the URL to the DTD
12582
 *
12583
 * Load and parse an external subset.
12584
 *
12585
 * Returns the resulting xmlDtdPtr or NULL in case of error.
12586
 */
12587
12588
xmlDtdPtr
12589
0
xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
12590
0
    return(xmlSAXParseDTD(NULL, ExternalID, SystemID));
12591
0
}
12592
#endif /* LIBXML_VALID_ENABLED */
12593
12594
/************************************************************************
12595
 *                  *
12596
 *    Front ends when parsing an Entity     *
12597
 *                  *
12598
 ************************************************************************/
12599
12600
/**
12601
 * xmlParseCtxtExternalEntity:
12602
 * @ctx:  the existing parsing context
12603
 * @URL:  the URL for the entity to load
12604
 * @ID:  the System ID for the entity to load
12605
 * @lst:  the return value for the set of parsed nodes
12606
 *
12607
 * Parse an external general entity within an existing parsing context
12608
 * An external general parsed entity is well-formed if it matches the
12609
 * production labeled extParsedEnt.
12610
 *
12611
 * [78] extParsedEnt ::= TextDecl? content
12612
 *
12613
 * Returns 0 if the entity is well formed, -1 in case of args problem and
12614
 *    the parser error code otherwise
12615
 */
12616
12617
int
12618
xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
12619
0
                 const xmlChar *ID, xmlNodePtr *lst) {
12620
0
    void *userData;
12621
12622
0
    if (ctx == NULL) return(-1);
12623
    /*
12624
     * If the user provided their own SAX callbacks, then reuse the
12625
     * userData callback field, otherwise the expected setup in a
12626
     * DOM builder is to have userData == ctxt
12627
     */
12628
0
    if (ctx->userData == ctx)
12629
0
        userData = NULL;
12630
0
    else
12631
0
        userData = ctx->userData;
12632
0
    return xmlParseExternalEntityPrivate(ctx->myDoc, ctx, ctx->sax,
12633
0
                                         userData, ctx->depth + 1,
12634
0
                                         URL, ID, lst);
12635
0
}
12636
12637
/**
12638
 * xmlParseExternalEntityPrivate:
12639
 * @doc:  the document the chunk pertains to
12640
 * @oldctxt:  the previous parser context if available
12641
 * @sax:  the SAX handler block (possibly NULL)
12642
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
12643
 * @depth:  Used for loop detection, use 0
12644
 * @URL:  the URL for the entity to load
12645
 * @ID:  the System ID for the entity to load
12646
 * @list:  the return value for the set of parsed nodes
12647
 *
12648
 * Private version of xmlParseExternalEntity()
12649
 *
12650
 * Returns 0 if the entity is well formed, -1 in case of args problem and
12651
 *    the parser error code otherwise
12652
 */
12653
12654
static xmlParserErrors
12655
xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
12656
                xmlSAXHandlerPtr sax,
12657
          void *user_data, int depth, const xmlChar *URL,
12658
0
          const xmlChar *ID, xmlNodePtr *list) {
12659
0
    xmlParserCtxtPtr ctxt;
12660
0
    xmlDocPtr newDoc;
12661
0
    xmlNodePtr newRoot;
12662
0
    xmlParserErrors ret = XML_ERR_OK;
12663
12664
0
    if (((depth > 40) &&
12665
0
  ((oldctxt == NULL) || (oldctxt->options & XML_PARSE_HUGE) == 0)) ||
12666
0
  (depth > 100)) {
12667
0
  xmlFatalErrMsg(oldctxt, XML_ERR_ENTITY_LOOP,
12668
0
                       "Maximum entity nesting depth exceeded");
12669
0
        return(XML_ERR_ENTITY_LOOP);
12670
0
    }
12671
12672
0
    if (list != NULL)
12673
0
        *list = NULL;
12674
0
    if ((URL == NULL) && (ID == NULL))
12675
0
  return(XML_ERR_INTERNAL_ERROR);
12676
0
    if (doc == NULL)
12677
0
  return(XML_ERR_INTERNAL_ERROR);
12678
12679
0
    ctxt = xmlCreateEntityParserCtxtInternal(sax, user_data, URL, ID, NULL,
12680
0
                                             oldctxt);
12681
0
    if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
12682
0
    if (oldctxt != NULL) {
12683
0
        ctxt->nbErrors = oldctxt->nbErrors;
12684
0
        ctxt->nbWarnings = oldctxt->nbWarnings;
12685
0
    }
12686
0
    xmlDetectSAX2(ctxt);
12687
12688
0
    newDoc = xmlNewDoc(BAD_CAST "1.0");
12689
0
    if (newDoc == NULL) {
12690
0
  xmlFreeParserCtxt(ctxt);
12691
0
  return(XML_ERR_INTERNAL_ERROR);
12692
0
    }
12693
0
    newDoc->properties = XML_DOC_INTERNAL;
12694
0
    if (doc) {
12695
0
        newDoc->intSubset = doc->intSubset;
12696
0
        newDoc->extSubset = doc->extSubset;
12697
0
        if (doc->dict) {
12698
0
            newDoc->dict = doc->dict;
12699
0
            xmlDictReference(newDoc->dict);
12700
0
        }
12701
0
        if (doc->URL != NULL) {
12702
0
            newDoc->URL = xmlStrdup(doc->URL);
12703
0
        }
12704
0
    }
12705
0
    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
12706
0
    if (newRoot == NULL) {
12707
0
  if (sax != NULL)
12708
0
  xmlFreeParserCtxt(ctxt);
12709
0
  newDoc->intSubset = NULL;
12710
0
  newDoc->extSubset = NULL;
12711
0
        xmlFreeDoc(newDoc);
12712
0
  return(XML_ERR_INTERNAL_ERROR);
12713
0
    }
12714
0
    xmlAddChild((xmlNodePtr) newDoc, newRoot);
12715
0
    nodePush(ctxt, newDoc->children);
12716
0
    if (doc == NULL) {
12717
0
        ctxt->myDoc = newDoc;
12718
0
    } else {
12719
0
        ctxt->myDoc = doc;
12720
0
        newRoot->doc = doc;
12721
0
    }
12722
12723
0
    xmlDetectEncoding(ctxt);
12724
12725
    /*
12726
     * Parse a possible text declaration first
12727
     */
12728
0
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
12729
0
  xmlParseTextDecl(ctxt);
12730
        /*
12731
         * An XML-1.0 document can't reference an entity not XML-1.0
12732
         */
12733
0
        if ((xmlStrEqual(oldctxt->version, BAD_CAST "1.0")) &&
12734
0
            (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) {
12735
0
            xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH,
12736
0
                           "Version mismatch between document and entity\n");
12737
0
        }
12738
0
    }
12739
12740
0
    ctxt->instate = XML_PARSER_CONTENT;
12741
0
    ctxt->depth = depth;
12742
0
    if (oldctxt != NULL) {
12743
0
  ctxt->_private = oldctxt->_private;
12744
0
  ctxt->loadsubset = oldctxt->loadsubset;
12745
0
  ctxt->validate = oldctxt->validate;
12746
0
  ctxt->valid = oldctxt->valid;
12747
0
  ctxt->replaceEntities = oldctxt->replaceEntities;
12748
0
        if (oldctxt->validate) {
12749
0
            ctxt->vctxt.error = oldctxt->vctxt.error;
12750
0
            ctxt->vctxt.warning = oldctxt->vctxt.warning;
12751
0
            ctxt->vctxt.userData = oldctxt->vctxt.userData;
12752
0
            ctxt->vctxt.flags = oldctxt->vctxt.flags;
12753
0
        }
12754
0
  ctxt->external = oldctxt->external;
12755
0
        if (ctxt->dict) xmlDictFree(ctxt->dict);
12756
0
        ctxt->dict = oldctxt->dict;
12757
0
        ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
12758
0
        ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
12759
0
        ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
12760
0
        ctxt->dictNames = oldctxt->dictNames;
12761
0
        ctxt->attsDefault = oldctxt->attsDefault;
12762
0
        ctxt->attsSpecial = oldctxt->attsSpecial;
12763
0
        ctxt->linenumbers = oldctxt->linenumbers;
12764
0
  ctxt->record_info = oldctxt->record_info;
12765
0
  ctxt->node_seq.maximum = oldctxt->node_seq.maximum;
12766
0
  ctxt->node_seq.length = oldctxt->node_seq.length;
12767
0
  ctxt->node_seq.buffer = oldctxt->node_seq.buffer;
12768
0
    } else {
12769
  /*
12770
   * Doing validity checking on chunk without context
12771
   * doesn't make sense
12772
   */
12773
0
  ctxt->_private = NULL;
12774
0
  ctxt->validate = 0;
12775
0
  ctxt->external = 2;
12776
0
  ctxt->loadsubset = 0;
12777
0
    }
12778
12779
0
    xmlParseContent(ctxt);
12780
12781
0
    if ((RAW == '<') && (NXT(1) == '/')) {
12782
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
12783
0
    } else if (RAW != 0) {
12784
0
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
12785
0
    }
12786
0
    if (ctxt->node != newDoc->children) {
12787
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
12788
0
    }
12789
12790
0
    if (!ctxt->wellFormed) {
12791
0
  ret = (xmlParserErrors)ctxt->errNo;
12792
0
        if (oldctxt != NULL) {
12793
0
            oldctxt->errNo = ctxt->errNo;
12794
0
            oldctxt->wellFormed = 0;
12795
0
            xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
12796
0
        }
12797
0
    } else {
12798
0
  if (list != NULL) {
12799
0
      xmlNodePtr cur;
12800
12801
      /*
12802
       * Return the newly created nodeset after unlinking it from
12803
       * they pseudo parent.
12804
       */
12805
0
      cur = newDoc->children->children;
12806
0
      *list = cur;
12807
0
      while (cur != NULL) {
12808
0
    cur->parent = NULL;
12809
0
    cur = cur->next;
12810
0
      }
12811
0
            newDoc->children->children = NULL;
12812
0
  }
12813
0
  ret = XML_ERR_OK;
12814
0
    }
12815
12816
    /*
12817
     * Also record the size of the entity parsed
12818
     */
12819
0
    if (ctxt->input != NULL && oldctxt != NULL) {
12820
0
        unsigned long consumed = ctxt->input->consumed;
12821
12822
0
        xmlSaturatedAddSizeT(&consumed, ctxt->input->cur - ctxt->input->base);
12823
12824
0
        xmlSaturatedAdd(&oldctxt->sizeentities, consumed);
12825
0
        xmlSaturatedAdd(&oldctxt->sizeentities, ctxt->sizeentities);
12826
12827
0
        xmlSaturatedAdd(&oldctxt->sizeentcopy, consumed);
12828
0
        xmlSaturatedAdd(&oldctxt->sizeentcopy, ctxt->sizeentcopy);
12829
0
    }
12830
12831
0
    if (oldctxt != NULL) {
12832
0
        ctxt->dict = NULL;
12833
0
        ctxt->attsDefault = NULL;
12834
0
        ctxt->attsSpecial = NULL;
12835
0
        oldctxt->nbErrors = ctxt->nbErrors;
12836
0
        oldctxt->nbWarnings = ctxt->nbWarnings;
12837
0
        oldctxt->validate = ctxt->validate;
12838
0
        oldctxt->valid = ctxt->valid;
12839
0
        oldctxt->node_seq.maximum = ctxt->node_seq.maximum;
12840
0
        oldctxt->node_seq.length = ctxt->node_seq.length;
12841
0
        oldctxt->node_seq.buffer = ctxt->node_seq.buffer;
12842
0
    }
12843
0
    ctxt->node_seq.maximum = 0;
12844
0
    ctxt->node_seq.length = 0;
12845
0
    ctxt->node_seq.buffer = NULL;
12846
0
    xmlFreeParserCtxt(ctxt);
12847
0
    newDoc->intSubset = NULL;
12848
0
    newDoc->extSubset = NULL;
12849
0
    xmlFreeDoc(newDoc);
12850
12851
0
    return(ret);
12852
0
}
12853
12854
#ifdef LIBXML_SAX1_ENABLED
12855
/**
12856
 * xmlParseExternalEntity:
12857
 * @doc:  the document the chunk pertains to
12858
 * @sax:  the SAX handler block (possibly NULL)
12859
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
12860
 * @depth:  Used for loop detection, use 0
12861
 * @URL:  the URL for the entity to load
12862
 * @ID:  the System ID for the entity to load
12863
 * @lst:  the return value for the set of parsed nodes
12864
 *
12865
 * Parse an external general entity
12866
 * An external general parsed entity is well-formed if it matches the
12867
 * production labeled extParsedEnt.
12868
 *
12869
 * [78] extParsedEnt ::= TextDecl? content
12870
 *
12871
 * Returns 0 if the entity is well formed, -1 in case of args problem and
12872
 *    the parser error code otherwise
12873
 */
12874
12875
int
12876
xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data,
12877
0
    int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *lst) {
12878
0
    return(xmlParseExternalEntityPrivate(doc, NULL, sax, user_data, depth, URL,
12879
0
                           ID, lst));
12880
0
}
12881
12882
/**
12883
 * xmlParseBalancedChunkMemory:
12884
 * @doc:  the document the chunk pertains to (must not be NULL)
12885
 * @sax:  the SAX handler block (possibly NULL)
12886
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
12887
 * @depth:  Used for loop detection, use 0
12888
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
12889
 * @lst:  the return value for the set of parsed nodes
12890
 *
12891
 * Parse a well-balanced chunk of an XML document
12892
 * called by the parser
12893
 * The allowed sequence for the Well Balanced Chunk is the one defined by
12894
 * the content production in the XML grammar:
12895
 *
12896
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
12897
 *
12898
 * Returns 0 if the chunk is well balanced, -1 in case of args problem and
12899
 *    the parser error code otherwise
12900
 */
12901
12902
int
12903
xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax,
12904
0
     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst) {
12905
0
    return xmlParseBalancedChunkMemoryRecover( doc, sax, user_data,
12906
0
                                                depth, string, lst, 0 );
12907
0
}
12908
#endif /* LIBXML_SAX1_ENABLED */
12909
12910
/**
12911
 * xmlParseBalancedChunkMemoryInternal:
12912
 * @oldctxt:  the existing parsing context
12913
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
12914
 * @user_data:  the user data field for the parser context
12915
 * @lst:  the return value for the set of parsed nodes
12916
 *
12917
 *
12918
 * Parse a well-balanced chunk of an XML document
12919
 * called by the parser
12920
 * The allowed sequence for the Well Balanced Chunk is the one defined by
12921
 * the content production in the XML grammar:
12922
 *
12923
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
12924
 *
12925
 * Returns XML_ERR_OK if the chunk is well balanced, and the parser
12926
 * error code otherwise
12927
 *
12928
 * In case recover is set to 1, the nodelist will not be empty even if
12929
 * the parsed chunk is not well balanced.
12930
 */
12931
static xmlParserErrors
12932
xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
12933
0
  const xmlChar *string, void *user_data, xmlNodePtr *lst) {
12934
0
    xmlParserCtxtPtr ctxt;
12935
0
    xmlDocPtr newDoc = NULL;
12936
0
    xmlNodePtr newRoot;
12937
0
    xmlSAXHandlerPtr oldsax = NULL;
12938
0
    xmlNodePtr content = NULL;
12939
0
    xmlNodePtr last = NULL;
12940
0
    xmlParserErrors ret = XML_ERR_OK;
12941
0
    xmlHashedString hprefix, huri;
12942
0
    unsigned i;
12943
12944
0
    if (((oldctxt->depth > 40) && ((oldctxt->options & XML_PARSE_HUGE) == 0)) ||
12945
0
        (oldctxt->depth >  100)) {
12946
0
  xmlFatalErrMsg(oldctxt, XML_ERR_ENTITY_LOOP,
12947
0
                       "Maximum entity nesting depth exceeded");
12948
0
  return(XML_ERR_ENTITY_LOOP);
12949
0
    }
12950
12951
12952
0
    if (lst != NULL)
12953
0
        *lst = NULL;
12954
0
    if (string == NULL)
12955
0
        return(XML_ERR_INTERNAL_ERROR);
12956
12957
0
    ctxt = xmlCreateDocParserCtxt(string);
12958
0
    if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
12959
0
    ctxt->nbErrors = oldctxt->nbErrors;
12960
0
    ctxt->nbWarnings = oldctxt->nbWarnings;
12961
0
    if (user_data != NULL)
12962
0
  ctxt->userData = user_data;
12963
0
    else
12964
0
  ctxt->userData = ctxt;
12965
0
    if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
12966
0
    ctxt->dict = oldctxt->dict;
12967
0
    ctxt->input_id = oldctxt->input_id;
12968
0
    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
12969
0
    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
12970
0
    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
12971
12972
    /*
12973
     * Propagate namespaces down the entity
12974
     *
12975
     * Making entities and namespaces work correctly requires additional
12976
     * changes, see xmlParseReference.
12977
     */
12978
12979
    /* Default namespace */
12980
0
    hprefix.name = NULL;
12981
0
    hprefix.hashValue = 0;
12982
0
    huri.name = xmlParserNsLookupUri(oldctxt, &hprefix);
12983
0
    huri.hashValue = 0;
12984
0
    if (huri.name != NULL)
12985
0
        xmlParserNsPush(ctxt, NULL, &huri, NULL, 0);
12986
12987
0
    for (i = 0; i < oldctxt->nsdb->hashSize; i++) {
12988
0
        xmlParserNsBucket *bucket = &oldctxt->nsdb->hash[i];
12989
0
        const xmlChar **ns;
12990
0
        xmlParserNsExtra *extra;
12991
0
        unsigned nsIndex;
12992
12993
0
        if ((bucket->hashValue != 0) &&
12994
0
            (bucket->index != INT_MAX)) {
12995
0
            nsIndex = bucket->index;
12996
0
            ns = &oldctxt->nsTab[nsIndex * 2];
12997
0
            extra = &oldctxt->nsdb->extra[nsIndex];
12998
12999
0
            hprefix.name = ns[0];
13000
0
            hprefix.hashValue = bucket->hashValue;
13001
0
            huri.name = ns[1];
13002
0
            huri.hashValue = extra->uriHashValue;
13003
            /*
13004
             * Don't copy SAX data to avoid a use-after-free with XML reader.
13005
             * This matches the pre-2.12 behavior.
13006
             */
13007
0
            xmlParserNsPush(ctxt, &hprefix, &huri, NULL, 0);
13008
0
        }
13009
0
    }
13010
13011
0
    oldsax = ctxt->sax;
13012
0
    ctxt->sax = oldctxt->sax;
13013
0
    xmlDetectSAX2(ctxt);
13014
0
    ctxt->replaceEntities = oldctxt->replaceEntities;
13015
0
    ctxt->options = oldctxt->options;
13016
13017
0
    ctxt->_private = oldctxt->_private;
13018
0
    if (oldctxt->myDoc == NULL) {
13019
0
  newDoc = xmlNewDoc(BAD_CAST "1.0");
13020
0
  if (newDoc == NULL) {
13021
0
            ret = XML_ERR_INTERNAL_ERROR;
13022
0
            goto error;
13023
0
  }
13024
0
  newDoc->properties = XML_DOC_INTERNAL;
13025
0
  newDoc->dict = ctxt->dict;
13026
0
  xmlDictReference(newDoc->dict);
13027
0
  ctxt->myDoc = newDoc;
13028
0
    } else {
13029
0
  ctxt->myDoc = oldctxt->myDoc;
13030
0
        content = ctxt->myDoc->children;
13031
0
  last = ctxt->myDoc->last;
13032
0
    }
13033
0
    newRoot = xmlNewDocNode(ctxt->myDoc, NULL, BAD_CAST "pseudoroot", NULL);
13034
0
    if (newRoot == NULL) {
13035
0
        ret = XML_ERR_INTERNAL_ERROR;
13036
0
        goto error;
13037
0
    }
13038
0
    ctxt->myDoc->children = NULL;
13039
0
    ctxt->myDoc->last = NULL;
13040
0
    xmlAddChild((xmlNodePtr) ctxt->myDoc, newRoot);
13041
0
    nodePush(ctxt, ctxt->myDoc->children);
13042
0
    ctxt->instate = XML_PARSER_CONTENT;
13043
0
    ctxt->depth = oldctxt->depth;
13044
13045
0
    ctxt->validate = 0;
13046
0
    ctxt->loadsubset = oldctxt->loadsubset;
13047
0
    if ((oldctxt->validate) || (oldctxt->replaceEntities != 0)) {
13048
  /*
13049
   * ID/IDREF registration will be done in xmlValidateElement below
13050
   */
13051
0
  ctxt->loadsubset |= XML_SKIP_IDS;
13052
0
    }
13053
0
    ctxt->dictNames = oldctxt->dictNames;
13054
0
    ctxt->attsDefault = oldctxt->attsDefault;
13055
0
    ctxt->attsSpecial = oldctxt->attsSpecial;
13056
13057
0
    xmlParseContent(ctxt);
13058
0
    if ((RAW == '<') && (NXT(1) == '/')) {
13059
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13060
0
    } else if (RAW != 0) {
13061
0
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13062
0
    }
13063
0
    if (ctxt->node != ctxt->myDoc->children) {
13064
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13065
0
    }
13066
13067
0
    if (!ctxt->wellFormed) {
13068
0
  ret = (xmlParserErrors)ctxt->errNo;
13069
0
        oldctxt->errNo = ctxt->errNo;
13070
0
        oldctxt->wellFormed = 0;
13071
0
        xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
13072
0
    } else {
13073
0
        ret = XML_ERR_OK;
13074
0
    }
13075
13076
0
    if ((lst != NULL) && (ret == XML_ERR_OK)) {
13077
0
  xmlNodePtr cur;
13078
13079
  /*
13080
   * Return the newly created nodeset after unlinking it from
13081
   * they pseudo parent.
13082
   */
13083
0
  cur = ctxt->myDoc->children->children;
13084
0
  *lst = cur;
13085
0
  while (cur != NULL) {
13086
0
#ifdef LIBXML_VALID_ENABLED
13087
0
      if ((oldctxt->validate) && (oldctxt->wellFormed) &&
13088
0
    (oldctxt->myDoc) && (oldctxt->myDoc->intSubset) &&
13089
0
    (cur->type == XML_ELEMENT_NODE)) {
13090
0
    oldctxt->valid &= xmlValidateElement(&oldctxt->vctxt,
13091
0
      oldctxt->myDoc, cur);
13092
0
      }
13093
0
#endif /* LIBXML_VALID_ENABLED */
13094
0
      cur->parent = NULL;
13095
0
      cur = cur->next;
13096
0
  }
13097
0
  ctxt->myDoc->children->children = NULL;
13098
0
    }
13099
0
    if (ctxt->myDoc != NULL) {
13100
0
  xmlFreeNode(ctxt->myDoc->children);
13101
0
        ctxt->myDoc->children = content;
13102
0
        ctxt->myDoc->last = last;
13103
0
    }
13104
13105
    /*
13106
     * Also record the size of the entity parsed
13107
     */
13108
0
    if (ctxt->input != NULL && oldctxt != NULL) {
13109
0
        unsigned long consumed = ctxt->input->consumed;
13110
13111
0
        xmlSaturatedAddSizeT(&consumed, ctxt->input->cur - ctxt->input->base);
13112
13113
0
        xmlSaturatedAdd(&oldctxt->sizeentcopy, consumed);
13114
0
        xmlSaturatedAdd(&oldctxt->sizeentcopy, ctxt->sizeentcopy);
13115
0
    }
13116
13117
0
    oldctxt->nbErrors = ctxt->nbErrors;
13118
0
    oldctxt->nbWarnings = ctxt->nbWarnings;
13119
13120
0
error:
13121
0
    ctxt->sax = oldsax;
13122
0
    ctxt->dict = NULL;
13123
0
    ctxt->attsDefault = NULL;
13124
0
    ctxt->attsSpecial = NULL;
13125
0
    xmlFreeParserCtxt(ctxt);
13126
0
    if (newDoc != NULL) {
13127
0
  xmlFreeDoc(newDoc);
13128
0
    }
13129
13130
0
    return(ret);
13131
0
}
13132
13133
/**
13134
 * xmlParseInNodeContext:
13135
 * @node:  the context node
13136
 * @data:  the input string
13137
 * @datalen:  the input string length in bytes
13138
 * @options:  a combination of xmlParserOption
13139
 * @lst:  the return value for the set of parsed nodes
13140
 *
13141
 * Parse a well-balanced chunk of an XML document
13142
 * within the context (DTD, namespaces, etc ...) of the given node.
13143
 *
13144
 * The allowed sequence for the data is a Well Balanced Chunk defined by
13145
 * the content production in the XML grammar:
13146
 *
13147
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13148
 *
13149
 * Returns XML_ERR_OK if the chunk is well balanced, and the parser
13150
 * error code otherwise
13151
 */
13152
xmlParserErrors
13153
xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
13154
0
                      int options, xmlNodePtr *lst) {
13155
0
    xmlParserCtxtPtr ctxt;
13156
0
    xmlDocPtr doc = NULL;
13157
0
    xmlNodePtr fake, cur;
13158
0
    int nsnr = 0;
13159
13160
0
    xmlParserErrors ret = XML_ERR_OK;
13161
13162
    /*
13163
     * check all input parameters, grab the document
13164
     */
13165
0
    if ((lst == NULL) || (node == NULL) || (data == NULL) || (datalen < 0))
13166
0
        return(XML_ERR_INTERNAL_ERROR);
13167
0
    switch (node->type) {
13168
0
        case XML_ELEMENT_NODE:
13169
0
        case XML_ATTRIBUTE_NODE:
13170
0
        case XML_TEXT_NODE:
13171
0
        case XML_CDATA_SECTION_NODE:
13172
0
        case XML_ENTITY_REF_NODE:
13173
0
        case XML_PI_NODE:
13174
0
        case XML_COMMENT_NODE:
13175
0
        case XML_DOCUMENT_NODE:
13176
0
        case XML_HTML_DOCUMENT_NODE:
13177
0
      break;
13178
0
  default:
13179
0
      return(XML_ERR_INTERNAL_ERROR);
13180
13181
0
    }
13182
0
    while ((node != NULL) && (node->type != XML_ELEMENT_NODE) &&
13183
0
           (node->type != XML_DOCUMENT_NODE) &&
13184
0
     (node->type != XML_HTML_DOCUMENT_NODE))
13185
0
  node = node->parent;
13186
0
    if (node == NULL)
13187
0
  return(XML_ERR_INTERNAL_ERROR);
13188
0
    if (node->type == XML_ELEMENT_NODE)
13189
0
  doc = node->doc;
13190
0
    else
13191
0
        doc = (xmlDocPtr) node;
13192
0
    if (doc == NULL)
13193
0
  return(XML_ERR_INTERNAL_ERROR);
13194
13195
    /*
13196
     * allocate a context and set-up everything not related to the
13197
     * node position in the tree
13198
     */
13199
0
    if (doc->type == XML_DOCUMENT_NODE)
13200
0
  ctxt = xmlCreateMemoryParserCtxt((char *) data, datalen);
13201
0
#ifdef LIBXML_HTML_ENABLED
13202
0
    else if (doc->type == XML_HTML_DOCUMENT_NODE) {
13203
0
  ctxt = htmlCreateMemoryParserCtxt((char *) data, datalen);
13204
        /*
13205
         * When parsing in context, it makes no sense to add implied
13206
         * elements like html/body/etc...
13207
         */
13208
0
        options |= HTML_PARSE_NOIMPLIED;
13209
0
    }
13210
0
#endif
13211
0
    else
13212
0
        return(XML_ERR_INTERNAL_ERROR);
13213
13214
0
    if (ctxt == NULL)
13215
0
        return(XML_ERR_NO_MEMORY);
13216
13217
    /*
13218
     * Use input doc's dict if present, else assure XML_PARSE_NODICT is set.
13219
     * We need a dictionary for xmlDetectSAX2, so if there's no doc dict
13220
     * we must wait until the last moment to free the original one.
13221
     */
13222
0
    if (doc->dict != NULL) {
13223
0
        if (ctxt->dict != NULL)
13224
0
      xmlDictFree(ctxt->dict);
13225
0
  ctxt->dict = doc->dict;
13226
0
    } else
13227
0
        options |= XML_PARSE_NODICT;
13228
13229
0
    if (doc->encoding != NULL) {
13230
0
        xmlCharEncodingHandlerPtr hdlr;
13231
13232
0
        hdlr = xmlFindCharEncodingHandler((const char *) doc->encoding);
13233
0
        if (hdlr != NULL) {
13234
0
            xmlSwitchToEncoding(ctxt, hdlr);
13235
0
  } else {
13236
0
            return(XML_ERR_UNSUPPORTED_ENCODING);
13237
0
        }
13238
0
    }
13239
13240
0
    xmlCtxtUseOptionsInternal(ctxt, options);
13241
0
    xmlDetectSAX2(ctxt);
13242
0
    ctxt->myDoc = doc;
13243
    /* parsing in context, i.e. as within existing content */
13244
0
    ctxt->input_id = 2;
13245
0
    ctxt->instate = XML_PARSER_CONTENT;
13246
13247
0
    fake = xmlNewDocComment(node->doc, NULL);
13248
0
    if (fake == NULL) {
13249
0
        xmlFreeParserCtxt(ctxt);
13250
0
  return(XML_ERR_NO_MEMORY);
13251
0
    }
13252
0
    xmlAddChild(node, fake);
13253
13254
0
    if (node->type == XML_ELEMENT_NODE)
13255
0
  nodePush(ctxt, node);
13256
13257
0
    if ((ctxt->html == 0) && (node->type == XML_ELEMENT_NODE)) {
13258
  /*
13259
   * initialize the SAX2 namespaces stack
13260
   */
13261
0
  cur = node;
13262
0
  while ((cur != NULL) && (cur->type == XML_ELEMENT_NODE)) {
13263
0
      xmlNsPtr ns = cur->nsDef;
13264
0
            xmlHashedString hprefix, huri;
13265
13266
0
      while (ns != NULL) {
13267
0
                hprefix = xmlDictLookupHashed(ctxt->dict, ns->prefix, -1);
13268
0
                huri = xmlDictLookupHashed(ctxt->dict, ns->href, -1);
13269
0
                if (xmlParserNsPush(ctxt, &hprefix, &huri, ns, 1) > 0)
13270
0
                    nsnr++;
13271
0
    ns = ns->next;
13272
0
      }
13273
0
      cur = cur->parent;
13274
0
  }
13275
0
    }
13276
13277
0
    if ((ctxt->validate) || (ctxt->replaceEntities != 0)) {
13278
  /*
13279
   * ID/IDREF registration will be done in xmlValidateElement below
13280
   */
13281
0
  ctxt->loadsubset |= XML_SKIP_IDS;
13282
0
    }
13283
13284
0
#ifdef LIBXML_HTML_ENABLED
13285
0
    if (doc->type == XML_HTML_DOCUMENT_NODE)
13286
0
        __htmlParseContent(ctxt);
13287
0
    else
13288
0
#endif
13289
0
  xmlParseContent(ctxt);
13290
13291
0
    xmlParserNsPop(ctxt, nsnr);
13292
0
    if ((RAW == '<') && (NXT(1) == '/')) {
13293
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13294
0
    } else if (RAW != 0) {
13295
0
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13296
0
    }
13297
0
    if ((ctxt->node != NULL) && (ctxt->node != node)) {
13298
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13299
0
  ctxt->wellFormed = 0;
13300
0
    }
13301
13302
0
    if (!ctxt->wellFormed) {
13303
0
        if (ctxt->errNo == 0)
13304
0
      ret = XML_ERR_INTERNAL_ERROR;
13305
0
  else
13306
0
      ret = (xmlParserErrors)ctxt->errNo;
13307
0
    } else {
13308
0
        ret = XML_ERR_OK;
13309
0
    }
13310
13311
    /*
13312
     * Return the newly created nodeset after unlinking it from
13313
     * the pseudo sibling.
13314
     */
13315
13316
0
    cur = fake->next;
13317
0
    fake->next = NULL;
13318
0
    node->last = fake;
13319
13320
0
    if (cur != NULL) {
13321
0
  cur->prev = NULL;
13322
0
    }
13323
13324
0
    *lst = cur;
13325
13326
0
    while (cur != NULL) {
13327
0
  cur->parent = NULL;
13328
0
  cur = cur->next;
13329
0
    }
13330
13331
0
    xmlUnlinkNode(fake);
13332
0
    xmlFreeNode(fake);
13333
13334
13335
0
    if (ret != XML_ERR_OK) {
13336
0
        xmlFreeNodeList(*lst);
13337
0
  *lst = NULL;
13338
0
    }
13339
13340
0
    if (doc->dict != NULL)
13341
0
        ctxt->dict = NULL;
13342
0
    xmlFreeParserCtxt(ctxt);
13343
13344
0
    return(ret);
13345
0
}
13346
13347
#ifdef LIBXML_SAX1_ENABLED
13348
/**
13349
 * xmlParseBalancedChunkMemoryRecover:
13350
 * @doc:  the document the chunk pertains to (must not be NULL)
13351
 * @sax:  the SAX handler block (possibly NULL)
13352
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
13353
 * @depth:  Used for loop detection, use 0
13354
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
13355
 * @lst:  the return value for the set of parsed nodes
13356
 * @recover: return nodes even if the data is broken (use 0)
13357
 *
13358
 *
13359
 * Parse a well-balanced chunk of an XML document
13360
 * called by the parser
13361
 * The allowed sequence for the Well Balanced Chunk is the one defined by
13362
 * the content production in the XML grammar:
13363
 *
13364
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13365
 *
13366
 * Returns 0 if the chunk is well balanced, -1 in case of args problem and
13367
 *    the parser error code otherwise
13368
 *
13369
 * In case recover is set to 1, the nodelist will not be empty even if
13370
 * the parsed chunk is not well balanced, assuming the parsing succeeded to
13371
 * some extent.
13372
 */
13373
int
13374
xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
13375
     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst,
13376
0
     int recover) {
13377
0
    xmlParserCtxtPtr ctxt;
13378
0
    xmlDocPtr newDoc;
13379
0
    xmlSAXHandlerPtr oldsax = NULL;
13380
0
    xmlNodePtr content, newRoot;
13381
0
    int ret = 0;
13382
13383
0
    if (depth > 40) {
13384
0
  return(XML_ERR_ENTITY_LOOP);
13385
0
    }
13386
13387
13388
0
    if (lst != NULL)
13389
0
        *lst = NULL;
13390
0
    if (string == NULL)
13391
0
        return(-1);
13392
13393
0
    ctxt = xmlCreateDocParserCtxt(string);
13394
0
    if (ctxt == NULL) return(-1);
13395
0
    ctxt->userData = ctxt;
13396
0
    if (sax != NULL) {
13397
0
  oldsax = ctxt->sax;
13398
0
        ctxt->sax = sax;
13399
0
  if (user_data != NULL)
13400
0
      ctxt->userData = user_data;
13401
0
    }
13402
0
    newDoc = xmlNewDoc(BAD_CAST "1.0");
13403
0
    if (newDoc == NULL) {
13404
0
  xmlFreeParserCtxt(ctxt);
13405
0
  return(-1);
13406
0
    }
13407
0
    newDoc->properties = XML_DOC_INTERNAL;
13408
0
    if ((doc != NULL) && (doc->dict != NULL)) {
13409
0
        xmlDictFree(ctxt->dict);
13410
0
  ctxt->dict = doc->dict;
13411
0
  xmlDictReference(ctxt->dict);
13412
0
  ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
13413
0
  ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
13414
0
  ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
13415
0
  ctxt->dictNames = 1;
13416
0
        newDoc->dict = ctxt->dict;
13417
0
        xmlDictReference(newDoc->dict);
13418
0
    } else {
13419
0
  xmlCtxtUseOptionsInternal(ctxt, XML_PARSE_NODICT);
13420
0
    }
13421
    /* doc == NULL is only supported for historic reasons */
13422
0
    if (doc != NULL) {
13423
0
  newDoc->intSubset = doc->intSubset;
13424
0
  newDoc->extSubset = doc->extSubset;
13425
0
    }
13426
0
    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
13427
0
    if (newRoot == NULL) {
13428
0
  if (sax != NULL)
13429
0
      ctxt->sax = oldsax;
13430
0
  xmlFreeParserCtxt(ctxt);
13431
0
  newDoc->intSubset = NULL;
13432
0
  newDoc->extSubset = NULL;
13433
0
        xmlFreeDoc(newDoc);
13434
0
  return(-1);
13435
0
    }
13436
0
    xmlAddChild((xmlNodePtr) newDoc, newRoot);
13437
0
    nodePush(ctxt, newRoot);
13438
    /* doc == NULL is only supported for historic reasons */
13439
0
    if (doc == NULL) {
13440
0
  ctxt->myDoc = newDoc;
13441
0
    } else {
13442
0
  ctxt->myDoc = newDoc;
13443
  /* Ensure that doc has XML spec namespace */
13444
0
  xmlSearchNsByHref(doc, (xmlNodePtr)doc, XML_XML_NAMESPACE);
13445
0
  newDoc->oldNs = doc->oldNs;
13446
0
    }
13447
0
    ctxt->instate = XML_PARSER_CONTENT;
13448
0
    ctxt->input_id = 2;
13449
0
    ctxt->depth = depth;
13450
13451
    /*
13452
     * Doing validity checking on chunk doesn't make sense
13453
     */
13454
0
    ctxt->validate = 0;
13455
0
    ctxt->loadsubset = 0;
13456
0
    xmlDetectSAX2(ctxt);
13457
13458
0
    if ( doc != NULL ){
13459
0
        content = doc->children;
13460
0
        doc->children = NULL;
13461
0
        xmlParseContent(ctxt);
13462
0
        doc->children = content;
13463
0
    }
13464
0
    else {
13465
0
        xmlParseContent(ctxt);
13466
0
    }
13467
0
    if ((RAW == '<') && (NXT(1) == '/')) {
13468
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13469
0
    } else if (RAW != 0) {
13470
0
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13471
0
    }
13472
0
    if (ctxt->node != newDoc->children) {
13473
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13474
0
    }
13475
13476
0
    if (!ctxt->wellFormed) {
13477
0
        if (ctxt->errNo == 0)
13478
0
      ret = 1;
13479
0
  else
13480
0
      ret = ctxt->errNo;
13481
0
    } else {
13482
0
      ret = 0;
13483
0
    }
13484
13485
0
    if ((lst != NULL) && ((ret == 0) || (recover == 1))) {
13486
0
  xmlNodePtr cur;
13487
13488
  /*
13489
   * Return the newly created nodeset after unlinking it from
13490
   * they pseudo parent.
13491
   */
13492
0
  cur = newDoc->children->children;
13493
0
  *lst = cur;
13494
0
  while (cur != NULL) {
13495
0
      xmlSetTreeDoc(cur, doc);
13496
0
      cur->parent = NULL;
13497
0
      cur = cur->next;
13498
0
  }
13499
0
  newDoc->children->children = NULL;
13500
0
    }
13501
13502
0
    if (sax != NULL)
13503
0
  ctxt->sax = oldsax;
13504
0
    xmlFreeParserCtxt(ctxt);
13505
0
    newDoc->intSubset = NULL;
13506
0
    newDoc->extSubset = NULL;
13507
    /* This leaks the namespace list if doc == NULL */
13508
0
    newDoc->oldNs = NULL;
13509
0
    xmlFreeDoc(newDoc);
13510
13511
0
    return(ret);
13512
0
}
13513
13514
/**
13515
 * xmlSAXParseEntity:
13516
 * @sax:  the SAX handler block
13517
 * @filename:  the filename
13518
 *
13519
 * DEPRECATED: Don't use.
13520
 *
13521
 * parse an XML external entity out of context and build a tree.
13522
 * It use the given SAX function block to handle the parsing callback.
13523
 * If sax is NULL, fallback to the default DOM tree building routines.
13524
 *
13525
 * [78] extParsedEnt ::= TextDecl? content
13526
 *
13527
 * This correspond to a "Well Balanced" chunk
13528
 *
13529
 * Returns the resulting document tree
13530
 */
13531
13532
xmlDocPtr
13533
0
xmlSAXParseEntity(xmlSAXHandlerPtr sax, const char *filename) {
13534
0
    xmlDocPtr ret;
13535
0
    xmlParserCtxtPtr ctxt;
13536
13537
0
    ctxt = xmlCreateFileParserCtxt(filename);
13538
0
    if (ctxt == NULL) {
13539
0
  return(NULL);
13540
0
    }
13541
0
    if (sax != NULL) {
13542
0
  if (ctxt->sax != NULL)
13543
0
      xmlFree(ctxt->sax);
13544
0
        ctxt->sax = sax;
13545
0
        ctxt->userData = NULL;
13546
0
    }
13547
13548
0
    xmlParseExtParsedEnt(ctxt);
13549
13550
0
    if (ctxt->wellFormed)
13551
0
  ret = ctxt->myDoc;
13552
0
    else {
13553
0
        ret = NULL;
13554
0
        xmlFreeDoc(ctxt->myDoc);
13555
0
        ctxt->myDoc = NULL;
13556
0
    }
13557
0
    if (sax != NULL)
13558
0
        ctxt->sax = NULL;
13559
0
    xmlFreeParserCtxt(ctxt);
13560
13561
0
    return(ret);
13562
0
}
13563
13564
/**
13565
 * xmlParseEntity:
13566
 * @filename:  the filename
13567
 *
13568
 * parse an XML external entity out of context and build a tree.
13569
 *
13570
 * [78] extParsedEnt ::= TextDecl? content
13571
 *
13572
 * This correspond to a "Well Balanced" chunk
13573
 *
13574
 * Returns the resulting document tree
13575
 */
13576
13577
xmlDocPtr
13578
0
xmlParseEntity(const char *filename) {
13579
0
    return(xmlSAXParseEntity(NULL, filename));
13580
0
}
13581
#endif /* LIBXML_SAX1_ENABLED */
13582
13583
/**
13584
 * xmlCreateEntityParserCtxtInternal:
13585
 * @URL:  the entity URL
13586
 * @ID:  the entity PUBLIC ID
13587
 * @base:  a possible base for the target URI
13588
 * @pctx:  parser context used to set options on new context
13589
 *
13590
 * Create a parser context for an external entity
13591
 * Automatic support for ZLIB/Compress compressed document is provided
13592
 * by default if found at compile-time.
13593
 *
13594
 * Returns the new parser context or NULL
13595
 */
13596
static xmlParserCtxtPtr
13597
xmlCreateEntityParserCtxtInternal(xmlSAXHandlerPtr sax, void *userData,
13598
        const xmlChar *URL, const xmlChar *ID, const xmlChar *base,
13599
0
        xmlParserCtxtPtr pctx) {
13600
0
    xmlParserCtxtPtr ctxt;
13601
0
    xmlParserInputPtr inputStream;
13602
0
    char *directory = NULL;
13603
0
    xmlChar *uri;
13604
13605
0
    ctxt = xmlNewSAXParserCtxt(sax, userData);
13606
0
    if (ctxt == NULL) {
13607
0
  return(NULL);
13608
0
    }
13609
13610
0
    if (pctx != NULL) {
13611
0
        ctxt->options = pctx->options;
13612
0
        ctxt->_private = pctx->_private;
13613
0
  ctxt->input_id = pctx->input_id;
13614
0
    }
13615
13616
    /* Don't read from stdin. */
13617
0
    if (xmlStrcmp(URL, BAD_CAST "-") == 0)
13618
0
        URL = BAD_CAST "./-";
13619
13620
0
    uri = xmlBuildURI(URL, base);
13621
13622
0
    if (uri == NULL) {
13623
0
  inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
13624
0
  if (inputStream == NULL) {
13625
0
      xmlFreeParserCtxt(ctxt);
13626
0
      return(NULL);
13627
0
  }
13628
13629
0
  inputPush(ctxt, inputStream);
13630
13631
0
  if ((ctxt->directory == NULL) && (directory == NULL))
13632
0
      directory = xmlParserGetDirectory((char *)URL);
13633
0
  if ((ctxt->directory == NULL) && (directory != NULL))
13634
0
      ctxt->directory = directory;
13635
0
    } else {
13636
0
  inputStream = xmlLoadExternalEntity((char *)uri, (char *)ID, ctxt);
13637
0
  if (inputStream == NULL) {
13638
0
      xmlFree(uri);
13639
0
      xmlFreeParserCtxt(ctxt);
13640
0
      return(NULL);
13641
0
  }
13642
13643
0
  inputPush(ctxt, inputStream);
13644
13645
0
  if ((ctxt->directory == NULL) && (directory == NULL))
13646
0
      directory = xmlParserGetDirectory((char *)uri);
13647
0
  if ((ctxt->directory == NULL) && (directory != NULL))
13648
0
      ctxt->directory = directory;
13649
0
  xmlFree(uri);
13650
0
    }
13651
0
    return(ctxt);
13652
0
}
13653
13654
/**
13655
 * xmlCreateEntityParserCtxt:
13656
 * @URL:  the entity URL
13657
 * @ID:  the entity PUBLIC ID
13658
 * @base:  a possible base for the target URI
13659
 *
13660
 * Create a parser context for an external entity
13661
 * Automatic support for ZLIB/Compress compressed document is provided
13662
 * by default if found at compile-time.
13663
 *
13664
 * Returns the new parser context or NULL
13665
 */
13666
xmlParserCtxtPtr
13667
xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID,
13668
0
                    const xmlChar *base) {
13669
0
    return xmlCreateEntityParserCtxtInternal(NULL, NULL, URL, ID, base, NULL);
13670
13671
0
}
13672
13673
/************************************************************************
13674
 *                  *
13675
 *    Front ends when parsing from a file     *
13676
 *                  *
13677
 ************************************************************************/
13678
13679
/**
13680
 * xmlCreateURLParserCtxt:
13681
 * @filename:  the filename or URL
13682
 * @options:  a combination of xmlParserOption
13683
 *
13684
 * Create a parser context for a file or URL content.
13685
 * Automatic support for ZLIB/Compress compressed document is provided
13686
 * by default if found at compile-time and for file accesses
13687
 *
13688
 * Returns the new parser context or NULL
13689
 */
13690
xmlParserCtxtPtr
13691
xmlCreateURLParserCtxt(const char *filename, int options)
13692
0
{
13693
0
    xmlParserCtxtPtr ctxt;
13694
0
    xmlParserInputPtr inputStream;
13695
0
    char *directory = NULL;
13696
13697
0
    ctxt = xmlNewParserCtxt();
13698
0
    if (ctxt == NULL) {
13699
0
  xmlErrMemory(NULL, "cannot allocate parser context");
13700
0
  return(NULL);
13701
0
    }
13702
13703
0
    if (options)
13704
0
  xmlCtxtUseOptionsInternal(ctxt, options);
13705
0
    ctxt->linenumbers = 1;
13706
13707
0
    inputStream = xmlLoadExternalEntity(filename, NULL, ctxt);
13708
0
    if (inputStream == NULL) {
13709
0
  xmlFreeParserCtxt(ctxt);
13710
0
  return(NULL);
13711
0
    }
13712
13713
0
    inputPush(ctxt, inputStream);
13714
0
    if ((ctxt->directory == NULL) && (directory == NULL))
13715
0
        directory = xmlParserGetDirectory(filename);
13716
0
    if ((ctxt->directory == NULL) && (directory != NULL))
13717
0
        ctxt->directory = directory;
13718
13719
0
    return(ctxt);
13720
0
}
13721
13722
/**
13723
 * xmlCreateFileParserCtxt:
13724
 * @filename:  the filename
13725
 *
13726
 * Create a parser context for a file content.
13727
 * Automatic support for ZLIB/Compress compressed document is provided
13728
 * by default if found at compile-time.
13729
 *
13730
 * Returns the new parser context or NULL
13731
 */
13732
xmlParserCtxtPtr
13733
xmlCreateFileParserCtxt(const char *filename)
13734
0
{
13735
0
    return(xmlCreateURLParserCtxt(filename, 0));
13736
0
}
13737
13738
#ifdef LIBXML_SAX1_ENABLED
13739
/**
13740
 * xmlSAXParseFileWithData:
13741
 * @sax:  the SAX handler block
13742
 * @filename:  the filename
13743
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
13744
 *             documents
13745
 * @data:  the userdata
13746
 *
13747
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadFile.
13748
 *
13749
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
13750
 * compressed document is provided by default if found at compile-time.
13751
 * It use the given SAX function block to handle the parsing callback.
13752
 * If sax is NULL, fallback to the default DOM tree building routines.
13753
 *
13754
 * User data (void *) is stored within the parser context in the
13755
 * context's _private member, so it is available nearly everywhere in libxml
13756
 *
13757
 * Returns the resulting document tree
13758
 */
13759
13760
xmlDocPtr
13761
xmlSAXParseFileWithData(xmlSAXHandlerPtr sax, const char *filename,
13762
0
                        int recovery, void *data) {
13763
0
    xmlDocPtr ret;
13764
0
    xmlParserCtxtPtr ctxt;
13765
13766
0
    xmlInitParser();
13767
13768
0
    ctxt = xmlCreateFileParserCtxt(filename);
13769
0
    if (ctxt == NULL) {
13770
0
  return(NULL);
13771
0
    }
13772
0
    if (sax != NULL) {
13773
0
  if (ctxt->sax != NULL)
13774
0
      xmlFree(ctxt->sax);
13775
0
        ctxt->sax = sax;
13776
0
    }
13777
0
    xmlDetectSAX2(ctxt);
13778
0
    if (data!=NULL) {
13779
0
  ctxt->_private = data;
13780
0
    }
13781
13782
0
    if (ctxt->directory == NULL)
13783
0
        ctxt->directory = xmlParserGetDirectory(filename);
13784
13785
0
    ctxt->recovery = recovery;
13786
13787
0
    xmlParseDocument(ctxt);
13788
13789
0
    if ((ctxt->wellFormed) || recovery) {
13790
0
        ret = ctxt->myDoc;
13791
0
  if ((ret != NULL) && (ctxt->input->buf != NULL)) {
13792
0
      if (ctxt->input->buf->compressed > 0)
13793
0
    ret->compression = 9;
13794
0
      else
13795
0
    ret->compression = ctxt->input->buf->compressed;
13796
0
  }
13797
0
    }
13798
0
    else {
13799
0
       ret = NULL;
13800
0
       xmlFreeDoc(ctxt->myDoc);
13801
0
       ctxt->myDoc = NULL;
13802
0
    }
13803
0
    if (sax != NULL)
13804
0
        ctxt->sax = NULL;
13805
0
    xmlFreeParserCtxt(ctxt);
13806
13807
0
    return(ret);
13808
0
}
13809
13810
/**
13811
 * xmlSAXParseFile:
13812
 * @sax:  the SAX handler block
13813
 * @filename:  the filename
13814
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
13815
 *             documents
13816
 *
13817
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadFile.
13818
 *
13819
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
13820
 * compressed document is provided by default if found at compile-time.
13821
 * It use the given SAX function block to handle the parsing callback.
13822
 * If sax is NULL, fallback to the default DOM tree building routines.
13823
 *
13824
 * Returns the resulting document tree
13825
 */
13826
13827
xmlDocPtr
13828
xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
13829
0
                          int recovery) {
13830
0
    return(xmlSAXParseFileWithData(sax,filename,recovery,NULL));
13831
0
}
13832
13833
/**
13834
 * xmlRecoverDoc:
13835
 * @cur:  a pointer to an array of xmlChar
13836
 *
13837
 * DEPRECATED: Use xmlReadDoc with XML_PARSE_RECOVER.
13838
 *
13839
 * parse an XML in-memory document and build a tree.
13840
 * In the case the document is not Well Formed, a attempt to build a
13841
 * tree is tried anyway
13842
 *
13843
 * Returns the resulting document tree or NULL in case of failure
13844
 */
13845
13846
xmlDocPtr
13847
0
xmlRecoverDoc(const xmlChar *cur) {
13848
0
    return(xmlSAXParseDoc(NULL, cur, 1));
13849
0
}
13850
13851
/**
13852
 * xmlParseFile:
13853
 * @filename:  the filename
13854
 *
13855
 * DEPRECATED: Use xmlReadFile.
13856
 *
13857
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
13858
 * compressed document is provided by default if found at compile-time.
13859
 *
13860
 * Returns the resulting document tree if the file was wellformed,
13861
 * NULL otherwise.
13862
 */
13863
13864
xmlDocPtr
13865
0
xmlParseFile(const char *filename) {
13866
0
    return(xmlSAXParseFile(NULL, filename, 0));
13867
0
}
13868
13869
/**
13870
 * xmlRecoverFile:
13871
 * @filename:  the filename
13872
 *
13873
 * DEPRECATED: Use xmlReadFile with XML_PARSE_RECOVER.
13874
 *
13875
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
13876
 * compressed document is provided by default if found at compile-time.
13877
 * In the case the document is not Well Formed, it attempts to build
13878
 * a tree anyway
13879
 *
13880
 * Returns the resulting document tree or NULL in case of failure
13881
 */
13882
13883
xmlDocPtr
13884
0
xmlRecoverFile(const char *filename) {
13885
0
    return(xmlSAXParseFile(NULL, filename, 1));
13886
0
}
13887
13888
13889
/**
13890
 * xmlSetupParserForBuffer:
13891
 * @ctxt:  an XML parser context
13892
 * @buffer:  a xmlChar * buffer
13893
 * @filename:  a file name
13894
 *
13895
 * DEPRECATED: Don't use.
13896
 *
13897
 * Setup the parser context to parse a new buffer; Clears any prior
13898
 * contents from the parser context. The buffer parameter must not be
13899
 * NULL, but the filename parameter can be
13900
 */
13901
void
13902
xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
13903
                             const char* filename)
13904
0
{
13905
0
    xmlParserInputPtr input;
13906
13907
0
    if ((ctxt == NULL) || (buffer == NULL))
13908
0
        return;
13909
13910
0
    input = xmlNewInputStream(ctxt);
13911
0
    if (input == NULL) {
13912
0
        xmlErrMemory(NULL, "parsing new buffer: out of memory\n");
13913
0
        xmlClearParserCtxt(ctxt);
13914
0
        return;
13915
0
    }
13916
13917
0
    xmlClearParserCtxt(ctxt);
13918
0
    if (filename != NULL)
13919
0
        input->filename = (char *) xmlCanonicPath((const xmlChar *)filename);
13920
0
    input->base = buffer;
13921
0
    input->cur = buffer;
13922
0
    input->end = &buffer[xmlStrlen(buffer)];
13923
0
    inputPush(ctxt, input);
13924
0
}
13925
13926
/**
13927
 * xmlSAXUserParseFile:
13928
 * @sax:  a SAX handler
13929
 * @user_data:  The user data returned on SAX callbacks
13930
 * @filename:  a file name
13931
 *
13932
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadFile.
13933
 *
13934
 * parse an XML file and call the given SAX handler routines.
13935
 * Automatic support for ZLIB/Compress compressed document is provided
13936
 *
13937
 * Returns 0 in case of success or a error number otherwise
13938
 */
13939
int
13940
xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
13941
0
                    const char *filename) {
13942
0
    int ret = 0;
13943
0
    xmlParserCtxtPtr ctxt;
13944
13945
0
    ctxt = xmlCreateFileParserCtxt(filename);
13946
0
    if (ctxt == NULL) return -1;
13947
0
    if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
13948
0
  xmlFree(ctxt->sax);
13949
0
    ctxt->sax = sax;
13950
0
    xmlDetectSAX2(ctxt);
13951
13952
0
    if (user_data != NULL)
13953
0
  ctxt->userData = user_data;
13954
13955
0
    xmlParseDocument(ctxt);
13956
13957
0
    if (ctxt->wellFormed)
13958
0
  ret = 0;
13959
0
    else {
13960
0
        if (ctxt->errNo != 0)
13961
0
      ret = ctxt->errNo;
13962
0
  else
13963
0
      ret = -1;
13964
0
    }
13965
0
    if (sax != NULL)
13966
0
  ctxt->sax = NULL;
13967
0
    if (ctxt->myDoc != NULL) {
13968
0
        xmlFreeDoc(ctxt->myDoc);
13969
0
  ctxt->myDoc = NULL;
13970
0
    }
13971
0
    xmlFreeParserCtxt(ctxt);
13972
13973
0
    return ret;
13974
0
}
13975
#endif /* LIBXML_SAX1_ENABLED */
13976
13977
/************************************************************************
13978
 *                  *
13979
 *    Front ends when parsing from memory     *
13980
 *                  *
13981
 ************************************************************************/
13982
13983
/**
13984
 * xmlCreateMemoryParserCtxt:
13985
 * @buffer:  a pointer to a char array
13986
 * @size:  the size of the array
13987
 *
13988
 * Create a parser context for an XML in-memory document.
13989
 *
13990
 * Returns the new parser context or NULL
13991
 */
13992
xmlParserCtxtPtr
13993
0
xmlCreateMemoryParserCtxt(const char *buffer, int size) {
13994
0
    xmlParserCtxtPtr ctxt;
13995
0
    xmlParserInputPtr input;
13996
0
    xmlParserInputBufferPtr buf;
13997
13998
0
    if (buffer == NULL)
13999
0
  return(NULL);
14000
0
    if (size <= 0)
14001
0
  return(NULL);
14002
14003
0
    ctxt = xmlNewParserCtxt();
14004
0
    if (ctxt == NULL)
14005
0
  return(NULL);
14006
14007
0
    buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
14008
0
    if (buf == NULL) {
14009
0
  xmlFreeParserCtxt(ctxt);
14010
0
  return(NULL);
14011
0
    }
14012
14013
0
    input = xmlNewInputStream(ctxt);
14014
0
    if (input == NULL) {
14015
0
  xmlFreeParserInputBuffer(buf);
14016
0
  xmlFreeParserCtxt(ctxt);
14017
0
  return(NULL);
14018
0
    }
14019
14020
0
    input->filename = NULL;
14021
0
    input->buf = buf;
14022
0
    xmlBufResetInput(input->buf->buffer, input);
14023
14024
0
    inputPush(ctxt, input);
14025
0
    return(ctxt);
14026
0
}
14027
14028
#ifdef LIBXML_SAX1_ENABLED
14029
/**
14030
 * xmlSAXParseMemoryWithData:
14031
 * @sax:  the SAX handler block
14032
 * @buffer:  an pointer to a char array
14033
 * @size:  the size of the array
14034
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14035
 *             documents
14036
 * @data:  the userdata
14037
 *
14038
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadMemory.
14039
 *
14040
 * parse an XML in-memory block and use the given SAX function block
14041
 * to handle the parsing callback. If sax is NULL, fallback to the default
14042
 * DOM tree building routines.
14043
 *
14044
 * User data (void *) is stored within the parser context in the
14045
 * context's _private member, so it is available nearly everywhere in libxml
14046
 *
14047
 * Returns the resulting document tree
14048
 */
14049
14050
xmlDocPtr
14051
xmlSAXParseMemoryWithData(xmlSAXHandlerPtr sax, const char *buffer,
14052
0
            int size, int recovery, void *data) {
14053
0
    xmlDocPtr ret;
14054
0
    xmlParserCtxtPtr ctxt;
14055
14056
0
    xmlInitParser();
14057
14058
0
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
14059
0
    if (ctxt == NULL) return(NULL);
14060
0
    if (sax != NULL) {
14061
0
  if (ctxt->sax != NULL)
14062
0
      xmlFree(ctxt->sax);
14063
0
        ctxt->sax = sax;
14064
0
    }
14065
0
    xmlDetectSAX2(ctxt);
14066
0
    if (data!=NULL) {
14067
0
  ctxt->_private=data;
14068
0
    }
14069
14070
0
    ctxt->recovery = recovery;
14071
14072
0
    xmlParseDocument(ctxt);
14073
14074
0
    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
14075
0
    else {
14076
0
       ret = NULL;
14077
0
       xmlFreeDoc(ctxt->myDoc);
14078
0
       ctxt->myDoc = NULL;
14079
0
    }
14080
0
    if (sax != NULL)
14081
0
  ctxt->sax = NULL;
14082
0
    xmlFreeParserCtxt(ctxt);
14083
14084
0
    return(ret);
14085
0
}
14086
14087
/**
14088
 * xmlSAXParseMemory:
14089
 * @sax:  the SAX handler block
14090
 * @buffer:  an pointer to a char array
14091
 * @size:  the size of the array
14092
 * @recovery:  work in recovery mode, i.e. tries to read not Well Formed
14093
 *             documents
14094
 *
14095
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadMemory.
14096
 *
14097
 * parse an XML in-memory block and use the given SAX function block
14098
 * to handle the parsing callback. If sax is NULL, fallback to the default
14099
 * DOM tree building routines.
14100
 *
14101
 * Returns the resulting document tree
14102
 */
14103
xmlDocPtr
14104
xmlSAXParseMemory(xmlSAXHandlerPtr sax, const char *buffer,
14105
0
            int size, int recovery) {
14106
0
    return xmlSAXParseMemoryWithData(sax, buffer, size, recovery, NULL);
14107
0
}
14108
14109
/**
14110
 * xmlParseMemory:
14111
 * @buffer:  an pointer to a char array
14112
 * @size:  the size of the array
14113
 *
14114
 * DEPRECATED: Use xmlReadMemory.
14115
 *
14116
 * parse an XML in-memory block and build a tree.
14117
 *
14118
 * Returns the resulting document tree
14119
 */
14120
14121
0
xmlDocPtr xmlParseMemory(const char *buffer, int size) {
14122
0
   return(xmlSAXParseMemory(NULL, buffer, size, 0));
14123
0
}
14124
14125
/**
14126
 * xmlRecoverMemory:
14127
 * @buffer:  an pointer to a char array
14128
 * @size:  the size of the array
14129
 *
14130
 * DEPRECATED: Use xmlReadMemory with XML_PARSE_RECOVER.
14131
 *
14132
 * parse an XML in-memory block and build a tree.
14133
 * In the case the document is not Well Formed, an attempt to
14134
 * build a tree is tried anyway
14135
 *
14136
 * Returns the resulting document tree or NULL in case of error
14137
 */
14138
14139
0
xmlDocPtr xmlRecoverMemory(const char *buffer, int size) {
14140
0
   return(xmlSAXParseMemory(NULL, buffer, size, 1));
14141
0
}
14142
14143
/**
14144
 * xmlSAXUserParseMemory:
14145
 * @sax:  a SAX handler
14146
 * @user_data:  The user data returned on SAX callbacks
14147
 * @buffer:  an in-memory XML document input
14148
 * @size:  the length of the XML document in bytes
14149
 *
14150
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadMemory.
14151
 *
14152
 * parse an XML in-memory buffer and call the given SAX handler routines.
14153
 *
14154
 * Returns 0 in case of success or a error number otherwise
14155
 */
14156
int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
14157
0
        const char *buffer, int size) {
14158
0
    int ret = 0;
14159
0
    xmlParserCtxtPtr ctxt;
14160
14161
0
    xmlInitParser();
14162
14163
0
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
14164
0
    if (ctxt == NULL) return -1;
14165
0
    if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
14166
0
        xmlFree(ctxt->sax);
14167
0
    ctxt->sax = sax;
14168
0
    xmlDetectSAX2(ctxt);
14169
14170
0
    if (user_data != NULL)
14171
0
  ctxt->userData = user_data;
14172
14173
0
    xmlParseDocument(ctxt);
14174
14175
0
    if (ctxt->wellFormed)
14176
0
  ret = 0;
14177
0
    else {
14178
0
        if (ctxt->errNo != 0)
14179
0
      ret = ctxt->errNo;
14180
0
  else
14181
0
      ret = -1;
14182
0
    }
14183
0
    if (sax != NULL)
14184
0
        ctxt->sax = NULL;
14185
0
    if (ctxt->myDoc != NULL) {
14186
0
        xmlFreeDoc(ctxt->myDoc);
14187
0
  ctxt->myDoc = NULL;
14188
0
    }
14189
0
    xmlFreeParserCtxt(ctxt);
14190
14191
0
    return ret;
14192
0
}
14193
#endif /* LIBXML_SAX1_ENABLED */
14194
14195
/**
14196
 * xmlCreateDocParserCtxt:
14197
 * @str:  a pointer to an array of xmlChar
14198
 *
14199
 * Creates a parser context for an XML in-memory document.
14200
 *
14201
 * Returns the new parser context or NULL
14202
 */
14203
xmlParserCtxtPtr
14204
0
xmlCreateDocParserCtxt(const xmlChar *str) {
14205
0
    xmlParserCtxtPtr ctxt;
14206
0
    xmlParserInputPtr input;
14207
0
    xmlParserInputBufferPtr buf;
14208
14209
0
    if (str == NULL)
14210
0
  return(NULL);
14211
14212
0
    ctxt = xmlNewParserCtxt();
14213
0
    if (ctxt == NULL)
14214
0
  return(NULL);
14215
14216
0
    buf = xmlParserInputBufferCreateString(str);
14217
0
    if (buf == NULL) {
14218
0
  xmlFreeParserCtxt(ctxt);
14219
0
  return(NULL);
14220
0
    }
14221
14222
0
    input = xmlNewInputStream(ctxt);
14223
0
    if (input == NULL) {
14224
0
  xmlFreeParserInputBuffer(buf);
14225
0
  xmlFreeParserCtxt(ctxt);
14226
0
  return(NULL);
14227
0
    }
14228
14229
0
    input->filename = NULL;
14230
0
    input->buf = buf;
14231
0
    xmlBufResetInput(input->buf->buffer, input);
14232
14233
0
    inputPush(ctxt, input);
14234
0
    return(ctxt);
14235
0
}
14236
14237
#ifdef LIBXML_SAX1_ENABLED
14238
/**
14239
 * xmlSAXParseDoc:
14240
 * @sax:  the SAX handler block
14241
 * @cur:  a pointer to an array of xmlChar
14242
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14243
 *             documents
14244
 *
14245
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadDoc.
14246
 *
14247
 * parse an XML in-memory document and build a tree.
14248
 * It use the given SAX function block to handle the parsing callback.
14249
 * If sax is NULL, fallback to the default DOM tree building routines.
14250
 *
14251
 * Returns the resulting document tree
14252
 */
14253
14254
xmlDocPtr
14255
0
xmlSAXParseDoc(xmlSAXHandlerPtr sax, const xmlChar *cur, int recovery) {
14256
0
    xmlDocPtr ret;
14257
0
    xmlParserCtxtPtr ctxt;
14258
0
    xmlSAXHandlerPtr oldsax = NULL;
14259
14260
0
    if (cur == NULL) return(NULL);
14261
14262
14263
0
    ctxt = xmlCreateDocParserCtxt(cur);
14264
0
    if (ctxt == NULL) return(NULL);
14265
0
    if (sax != NULL) {
14266
0
        oldsax = ctxt->sax;
14267
0
        ctxt->sax = sax;
14268
0
        ctxt->userData = NULL;
14269
0
    }
14270
0
    xmlDetectSAX2(ctxt);
14271
14272
0
    xmlParseDocument(ctxt);
14273
0
    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
14274
0
    else {
14275
0
       ret = NULL;
14276
0
       xmlFreeDoc(ctxt->myDoc);
14277
0
       ctxt->myDoc = NULL;
14278
0
    }
14279
0
    if (sax != NULL)
14280
0
  ctxt->sax = oldsax;
14281
0
    xmlFreeParserCtxt(ctxt);
14282
14283
0
    return(ret);
14284
0
}
14285
14286
/**
14287
 * xmlParseDoc:
14288
 * @cur:  a pointer to an array of xmlChar
14289
 *
14290
 * DEPRECATED: Use xmlReadDoc.
14291
 *
14292
 * parse an XML in-memory document and build a tree.
14293
 *
14294
 * Returns the resulting document tree
14295
 */
14296
14297
xmlDocPtr
14298
0
xmlParseDoc(const xmlChar *cur) {
14299
0
    return(xmlSAXParseDoc(NULL, cur, 0));
14300
0
}
14301
#endif /* LIBXML_SAX1_ENABLED */
14302
14303
#ifdef LIBXML_LEGACY_ENABLED
14304
/************************************************************************
14305
 *                  *
14306
 *  Specific function to keep track of entities references    *
14307
 *  and used by the XSLT debugger         *
14308
 *                  *
14309
 ************************************************************************/
14310
14311
static xmlEntityReferenceFunc xmlEntityRefFunc = NULL;
14312
14313
/**
14314
 * xmlAddEntityReference:
14315
 * @ent : A valid entity
14316
 * @firstNode : A valid first node for children of entity
14317
 * @lastNode : A valid last node of children entity
14318
 *
14319
 * Notify of a reference to an entity of type XML_EXTERNAL_GENERAL_PARSED_ENTITY
14320
 */
14321
static void
14322
xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
14323
                      xmlNodePtr lastNode)
14324
{
14325
    if (xmlEntityRefFunc != NULL) {
14326
        (*xmlEntityRefFunc) (ent, firstNode, lastNode);
14327
    }
14328
}
14329
14330
14331
/**
14332
 * xmlSetEntityReferenceFunc:
14333
 * @func: A valid function
14334
 *
14335
 * Set the function to call call back when a xml reference has been made
14336
 */
14337
void
14338
xmlSetEntityReferenceFunc(xmlEntityReferenceFunc func)
14339
{
14340
    xmlEntityRefFunc = func;
14341
}
14342
#endif /* LIBXML_LEGACY_ENABLED */
14343
14344
/************************************************************************
14345
 *                  *
14346
 *  New set (2.6.0) of simpler and more flexible APIs   *
14347
 *                  *
14348
 ************************************************************************/
14349
14350
/**
14351
 * DICT_FREE:
14352
 * @str:  a string
14353
 *
14354
 * Free a string if it is not owned by the "dict" dictionary in the
14355
 * current scope
14356
 */
14357
#define DICT_FREE(str)            \
14358
0
  if ((str) && ((!dict) ||       \
14359
0
      (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))  \
14360
0
      xmlFree((char *)(str));
14361
14362
/**
14363
 * xmlCtxtReset:
14364
 * @ctxt: an XML parser context
14365
 *
14366
 * Reset a parser context
14367
 */
14368
void
14369
xmlCtxtReset(xmlParserCtxtPtr ctxt)
14370
0
{
14371
0
    xmlParserInputPtr input;
14372
0
    xmlDictPtr dict;
14373
14374
0
    if (ctxt == NULL)
14375
0
        return;
14376
14377
0
    dict = ctxt->dict;
14378
14379
0
    while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
14380
0
        xmlFreeInputStream(input);
14381
0
    }
14382
0
    ctxt->inputNr = 0;
14383
0
    ctxt->input = NULL;
14384
14385
0
    ctxt->spaceNr = 0;
14386
0
    if (ctxt->spaceTab != NULL) {
14387
0
  ctxt->spaceTab[0] = -1;
14388
0
  ctxt->space = &ctxt->spaceTab[0];
14389
0
    } else {
14390
0
        ctxt->space = NULL;
14391
0
    }
14392
14393
14394
0
    ctxt->nodeNr = 0;
14395
0
    ctxt->node = NULL;
14396
14397
0
    ctxt->nameNr = 0;
14398
0
    ctxt->name = NULL;
14399
14400
0
    ctxt->nsNr = 0;
14401
0
    xmlParserNsReset(ctxt->nsdb);
14402
14403
0
    DICT_FREE(ctxt->version);
14404
0
    ctxt->version = NULL;
14405
0
    DICT_FREE(ctxt->encoding);
14406
0
    ctxt->encoding = NULL;
14407
0
    DICT_FREE(ctxt->directory);
14408
0
    ctxt->directory = NULL;
14409
0
    DICT_FREE(ctxt->extSubURI);
14410
0
    ctxt->extSubURI = NULL;
14411
0
    DICT_FREE(ctxt->extSubSystem);
14412
0
    ctxt->extSubSystem = NULL;
14413
0
    if (ctxt->myDoc != NULL)
14414
0
        xmlFreeDoc(ctxt->myDoc);
14415
0
    ctxt->myDoc = NULL;
14416
14417
0
    ctxt->standalone = -1;
14418
0
    ctxt->hasExternalSubset = 0;
14419
0
    ctxt->hasPErefs = 0;
14420
0
    ctxt->html = 0;
14421
0
    ctxt->external = 0;
14422
0
    ctxt->instate = XML_PARSER_START;
14423
0
    ctxt->token = 0;
14424
14425
0
    ctxt->wellFormed = 1;
14426
0
    ctxt->nsWellFormed = 1;
14427
0
    ctxt->disableSAX = 0;
14428
0
    ctxt->valid = 1;
14429
#if 0
14430
    ctxt->vctxt.userData = ctxt;
14431
    ctxt->vctxt.error = xmlParserValidityError;
14432
    ctxt->vctxt.warning = xmlParserValidityWarning;
14433
#endif
14434
0
    ctxt->record_info = 0;
14435
0
    ctxt->checkIndex = 0;
14436
0
    ctxt->endCheckState = 0;
14437
0
    ctxt->inSubset = 0;
14438
0
    ctxt->errNo = XML_ERR_OK;
14439
0
    ctxt->depth = 0;
14440
0
    ctxt->catalogs = NULL;
14441
0
    ctxt->sizeentities = 0;
14442
0
    ctxt->sizeentcopy = 0;
14443
0
    xmlInitNodeInfoSeq(&ctxt->node_seq);
14444
14445
0
    if (ctxt->attsDefault != NULL) {
14446
0
        xmlHashFree(ctxt->attsDefault, xmlHashDefaultDeallocator);
14447
0
        ctxt->attsDefault = NULL;
14448
0
    }
14449
0
    if (ctxt->attsSpecial != NULL) {
14450
0
        xmlHashFree(ctxt->attsSpecial, NULL);
14451
0
        ctxt->attsSpecial = NULL;
14452
0
    }
14453
14454
0
#ifdef LIBXML_CATALOG_ENABLED
14455
0
    if (ctxt->catalogs != NULL)
14456
0
  xmlCatalogFreeLocal(ctxt->catalogs);
14457
0
#endif
14458
0
    ctxt->nbErrors = 0;
14459
0
    ctxt->nbWarnings = 0;
14460
0
    if (ctxt->lastError.code != XML_ERR_OK)
14461
0
        xmlResetError(&ctxt->lastError);
14462
0
}
14463
14464
/**
14465
 * xmlCtxtResetPush:
14466
 * @ctxt: an XML parser context
14467
 * @chunk:  a pointer to an array of chars
14468
 * @size:  number of chars in the array
14469
 * @filename:  an optional file name or URI
14470
 * @encoding:  the document encoding, or NULL
14471
 *
14472
 * Reset a push parser context
14473
 *
14474
 * Returns 0 in case of success and 1 in case of error
14475
 */
14476
int
14477
xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk,
14478
                 int size, const char *filename, const char *encoding)
14479
0
{
14480
0
    xmlParserInputPtr inputStream;
14481
0
    xmlParserInputBufferPtr buf;
14482
14483
0
    if (ctxt == NULL)
14484
0
        return(1);
14485
14486
0
    buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE);
14487
0
    if (buf == NULL)
14488
0
        return(1);
14489
14490
0
    if (ctxt == NULL) {
14491
0
        xmlFreeParserInputBuffer(buf);
14492
0
        return(1);
14493
0
    }
14494
14495
0
    xmlCtxtReset(ctxt);
14496
14497
0
    if (filename == NULL) {
14498
0
        ctxt->directory = NULL;
14499
0
    } else {
14500
0
        ctxt->directory = xmlParserGetDirectory(filename);
14501
0
    }
14502
14503
0
    inputStream = xmlNewInputStream(ctxt);
14504
0
    if (inputStream == NULL) {
14505
0
        xmlFreeParserInputBuffer(buf);
14506
0
        return(1);
14507
0
    }
14508
14509
0
    if (filename == NULL)
14510
0
        inputStream->filename = NULL;
14511
0
    else
14512
0
        inputStream->filename = (char *)
14513
0
            xmlCanonicPath((const xmlChar *) filename);
14514
0
    inputStream->buf = buf;
14515
0
    xmlBufResetInput(buf->buffer, inputStream);
14516
14517
0
    inputPush(ctxt, inputStream);
14518
14519
0
    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
14520
0
        (ctxt->input->buf != NULL)) {
14521
0
        size_t pos = ctxt->input->cur - ctxt->input->base;
14522
0
        int res;
14523
14524
0
        res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
14525
0
        xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos);
14526
0
        if (res < 0) {
14527
0
            xmlFatalErr(ctxt, ctxt->input->buf->error, NULL);
14528
0
            xmlHaltParser(ctxt);
14529
0
            return(1);
14530
0
        }
14531
0
    }
14532
14533
0
    if (encoding != NULL) {
14534
0
        xmlCharEncodingHandlerPtr hdlr;
14535
14536
0
        hdlr = xmlFindCharEncodingHandler(encoding);
14537
0
        if (hdlr != NULL) {
14538
0
            xmlSwitchToEncoding(ctxt, hdlr);
14539
0
  } else {
14540
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
14541
0
            "Unsupported encoding %s\n", BAD_CAST encoding);
14542
0
        }
14543
0
    }
14544
14545
0
    return(0);
14546
0
}
14547
14548
14549
/**
14550
 * xmlCtxtUseOptionsInternal:
14551
 * @ctxt: an XML parser context
14552
 * @options:  a combination of xmlParserOption
14553
 * @encoding:  the user provided encoding to use
14554
 *
14555
 * Applies the options to the parser context
14556
 *
14557
 * Returns 0 in case of success, the set of unknown or unimplemented options
14558
 *         in case of error.
14559
 */
14560
static int
14561
xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options)
14562
0
{
14563
0
    if (ctxt == NULL)
14564
0
        return(-1);
14565
0
    if (options & XML_PARSE_RECOVER) {
14566
0
        ctxt->recovery = 1;
14567
0
        options -= XML_PARSE_RECOVER;
14568
0
  ctxt->options |= XML_PARSE_RECOVER;
14569
0
    } else
14570
0
        ctxt->recovery = 0;
14571
0
    if (options & XML_PARSE_DTDLOAD) {
14572
0
        ctxt->loadsubset = XML_DETECT_IDS;
14573
0
        options -= XML_PARSE_DTDLOAD;
14574
0
  ctxt->options |= XML_PARSE_DTDLOAD;
14575
0
    } else
14576
0
        ctxt->loadsubset = 0;
14577
0
    if (options & XML_PARSE_DTDATTR) {
14578
0
        ctxt->loadsubset |= XML_COMPLETE_ATTRS;
14579
0
        options -= XML_PARSE_DTDATTR;
14580
0
  ctxt->options |= XML_PARSE_DTDATTR;
14581
0
    }
14582
0
    if (options & XML_PARSE_NOENT) {
14583
0
        ctxt->replaceEntities = 1;
14584
        /* ctxt->loadsubset |= XML_DETECT_IDS; */
14585
0
        options -= XML_PARSE_NOENT;
14586
0
  ctxt->options |= XML_PARSE_NOENT;
14587
0
    } else
14588
0
        ctxt->replaceEntities = 0;
14589
0
    if (options & XML_PARSE_PEDANTIC) {
14590
0
        ctxt->pedantic = 1;
14591
0
        options -= XML_PARSE_PEDANTIC;
14592
0
  ctxt->options |= XML_PARSE_PEDANTIC;
14593
0
    } else
14594
0
        ctxt->pedantic = 0;
14595
0
    if (options & XML_PARSE_NOBLANKS) {
14596
0
        ctxt->keepBlanks = 0;
14597
0
        ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
14598
0
        options -= XML_PARSE_NOBLANKS;
14599
0
  ctxt->options |= XML_PARSE_NOBLANKS;
14600
0
    } else
14601
0
        ctxt->keepBlanks = 1;
14602
0
    if (options & XML_PARSE_DTDVALID) {
14603
0
        ctxt->validate = 1;
14604
0
        if (options & XML_PARSE_NOWARNING)
14605
0
            ctxt->vctxt.warning = NULL;
14606
0
        if (options & XML_PARSE_NOERROR)
14607
0
            ctxt->vctxt.error = NULL;
14608
0
        options -= XML_PARSE_DTDVALID;
14609
0
  ctxt->options |= XML_PARSE_DTDVALID;
14610
0
    } else
14611
0
        ctxt->validate = 0;
14612
0
    if (options & XML_PARSE_NOWARNING) {
14613
0
        ctxt->sax->warning = NULL;
14614
0
        options -= XML_PARSE_NOWARNING;
14615
0
    }
14616
0
    if (options & XML_PARSE_NOERROR) {
14617
0
        ctxt->sax->error = NULL;
14618
0
        ctxt->sax->fatalError = NULL;
14619
0
        options -= XML_PARSE_NOERROR;
14620
0
    }
14621
0
#ifdef LIBXML_SAX1_ENABLED
14622
0
    if (options & XML_PARSE_SAX1) {
14623
0
        ctxt->sax->startElementNs = NULL;
14624
0
        ctxt->sax->endElementNs = NULL;
14625
0
        ctxt->sax->initialized = 1;
14626
0
        options -= XML_PARSE_SAX1;
14627
0
  ctxt->options |= XML_PARSE_SAX1;
14628
0
    }
14629
0
#endif /* LIBXML_SAX1_ENABLED */
14630
0
    if (options & XML_PARSE_NODICT) {
14631
0
        ctxt->dictNames = 0;
14632
0
        options -= XML_PARSE_NODICT;
14633
0
  ctxt->options |= XML_PARSE_NODICT;
14634
0
    } else {
14635
0
        ctxt->dictNames = 1;
14636
0
    }
14637
0
    if (options & XML_PARSE_NOCDATA) {
14638
0
        ctxt->sax->cdataBlock = NULL;
14639
0
        options -= XML_PARSE_NOCDATA;
14640
0
  ctxt->options |= XML_PARSE_NOCDATA;
14641
0
    }
14642
0
    if (options & XML_PARSE_NSCLEAN) {
14643
0
  ctxt->options |= XML_PARSE_NSCLEAN;
14644
0
        options -= XML_PARSE_NSCLEAN;
14645
0
    }
14646
0
    if (options & XML_PARSE_NONET) {
14647
0
  ctxt->options |= XML_PARSE_NONET;
14648
0
        options -= XML_PARSE_NONET;
14649
0
    }
14650
0
    if (options & XML_PARSE_COMPACT) {
14651
0
  ctxt->options |= XML_PARSE_COMPACT;
14652
0
        options -= XML_PARSE_COMPACT;
14653
0
    }
14654
0
    if (options & XML_PARSE_OLD10) {
14655
0
  ctxt->options |= XML_PARSE_OLD10;
14656
0
        options -= XML_PARSE_OLD10;
14657
0
    }
14658
0
    if (options & XML_PARSE_NOBASEFIX) {
14659
0
  ctxt->options |= XML_PARSE_NOBASEFIX;
14660
0
        options -= XML_PARSE_NOBASEFIX;
14661
0
    }
14662
0
    if (options & XML_PARSE_HUGE) {
14663
0
  ctxt->options |= XML_PARSE_HUGE;
14664
0
        options -= XML_PARSE_HUGE;
14665
0
        if (ctxt->dict != NULL)
14666
0
            xmlDictSetLimit(ctxt->dict, 0);
14667
0
    }
14668
0
    if (options & XML_PARSE_OLDSAX) {
14669
0
  ctxt->options |= XML_PARSE_OLDSAX;
14670
0
        options -= XML_PARSE_OLDSAX;
14671
0
    }
14672
0
    if (options & XML_PARSE_IGNORE_ENC) {
14673
0
  ctxt->options |= XML_PARSE_IGNORE_ENC;
14674
0
        options -= XML_PARSE_IGNORE_ENC;
14675
0
    }
14676
0
    if (options & XML_PARSE_BIG_LINES) {
14677
0
  ctxt->options |= XML_PARSE_BIG_LINES;
14678
0
        options -= XML_PARSE_BIG_LINES;
14679
0
    }
14680
0
    ctxt->linenumbers = 1;
14681
0
    return (options);
14682
0
}
14683
14684
/**
14685
 * xmlCtxtUseOptions:
14686
 * @ctxt: an XML parser context
14687
 * @options:  a combination of xmlParserOption
14688
 *
14689
 * Applies the options to the parser context
14690
 *
14691
 * Returns 0 in case of success, the set of unknown or unimplemented options
14692
 *         in case of error.
14693
 */
14694
int
14695
xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options)
14696
0
{
14697
0
   return(xmlCtxtUseOptionsInternal(ctxt, options));
14698
0
}
14699
14700
/**
14701
 * xmlCtxtSetMaxAmplification:
14702
 * @ctxt: an XML parser context
14703
 * @maxAmpl:  maximum amplification factor
14704
 *
14705
 * To protect against exponential entity expansion ("billion laughs"), the
14706
 * size of serialized output is (roughly) limited to the input size
14707
 * multiplied by this factor. The default value is 5.
14708
 *
14709
 * When working with documents making heavy use of entity expansion, it can
14710
 * be necessary to increase the value. For security reasons, this should only
14711
 * be considered when processing trusted input.
14712
 */
14713
void
14714
xmlCtxtSetMaxAmplification(xmlParserCtxtPtr ctxt, unsigned maxAmpl)
14715
0
{
14716
0
    ctxt->maxAmpl = maxAmpl;
14717
0
}
14718
14719
/**
14720
 * xmlDoRead:
14721
 * @ctxt:  an XML parser context
14722
 * @URL:  the base URL to use for the document
14723
 * @encoding:  the document encoding, or NULL
14724
 * @options:  a combination of xmlParserOption
14725
 * @reuse:  keep the context for reuse
14726
 *
14727
 * Common front-end for the xmlRead functions
14728
 *
14729
 * Returns the resulting document tree or NULL
14730
 */
14731
static xmlDocPtr
14732
xmlDoRead(xmlParserCtxtPtr ctxt, const char *URL, const char *encoding,
14733
          int options, int reuse)
14734
0
{
14735
0
    xmlDocPtr ret;
14736
14737
0
    xmlCtxtUseOptionsInternal(ctxt, options);
14738
0
    if (encoding != NULL) {
14739
0
        xmlCharEncodingHandlerPtr hdlr;
14740
14741
        /*
14742
         * TODO: We should consider to set XML_PARSE_IGNORE_ENC if the
14743
         * caller provided an encoding. Otherwise, we might switch to
14744
         * the encoding from the XML declaration which is likely to
14745
         * break things. Also see xmlSwitchInputEncoding.
14746
         */
14747
0
  hdlr = xmlFindCharEncodingHandler(encoding);
14748
0
  if (hdlr != NULL)
14749
0
      xmlSwitchToEncoding(ctxt, hdlr);
14750
0
    }
14751
0
    if ((URL != NULL) && (ctxt->input != NULL) &&
14752
0
        (ctxt->input->filename == NULL))
14753
0
        ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL);
14754
0
    xmlParseDocument(ctxt);
14755
0
    if ((ctxt->wellFormed) || ctxt->recovery)
14756
0
        ret = ctxt->myDoc;
14757
0
    else {
14758
0
        ret = NULL;
14759
0
  if (ctxt->myDoc != NULL) {
14760
0
      xmlFreeDoc(ctxt->myDoc);
14761
0
  }
14762
0
    }
14763
0
    ctxt->myDoc = NULL;
14764
0
    if (!reuse) {
14765
0
  xmlFreeParserCtxt(ctxt);
14766
0
    }
14767
14768
0
    return (ret);
14769
0
}
14770
14771
/**
14772
 * xmlReadDoc:
14773
 * @cur:  a pointer to a zero terminated string
14774
 * @URL:  the base URL to use for the document
14775
 * @encoding:  the document encoding, or NULL
14776
 * @options:  a combination of xmlParserOption
14777
 *
14778
 * parse an XML in-memory document and build a tree.
14779
 *
14780
 * Returns the resulting document tree
14781
 */
14782
xmlDocPtr
14783
xmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int options)
14784
0
{
14785
0
    xmlParserCtxtPtr ctxt;
14786
14787
0
    if (cur == NULL)
14788
0
        return (NULL);
14789
0
    xmlInitParser();
14790
14791
0
    ctxt = xmlCreateDocParserCtxt(cur);
14792
0
    if (ctxt == NULL)
14793
0
        return (NULL);
14794
0
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
14795
0
}
14796
14797
/**
14798
 * xmlReadFile:
14799
 * @filename:  a file or URL
14800
 * @encoding:  the document encoding, or NULL
14801
 * @options:  a combination of xmlParserOption
14802
 *
14803
 * parse an XML file from the filesystem or the network.
14804
 *
14805
 * Returns the resulting document tree
14806
 */
14807
xmlDocPtr
14808
xmlReadFile(const char *filename, const char *encoding, int options)
14809
0
{
14810
0
    xmlParserCtxtPtr ctxt;
14811
14812
0
    xmlInitParser();
14813
0
    ctxt = xmlCreateURLParserCtxt(filename, options);
14814
0
    if (ctxt == NULL)
14815
0
        return (NULL);
14816
0
    return (xmlDoRead(ctxt, NULL, encoding, options, 0));
14817
0
}
14818
14819
/**
14820
 * xmlReadMemory:
14821
 * @buffer:  a pointer to a char array
14822
 * @size:  the size of the array
14823
 * @URL:  the base URL to use for the document
14824
 * @encoding:  the document encoding, or NULL
14825
 * @options:  a combination of xmlParserOption
14826
 *
14827
 * parse an XML in-memory document and build a tree.
14828
 *
14829
 * Returns the resulting document tree
14830
 */
14831
xmlDocPtr
14832
xmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options)
14833
0
{
14834
0
    xmlParserCtxtPtr ctxt;
14835
14836
0
    xmlInitParser();
14837
0
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
14838
0
    if (ctxt == NULL)
14839
0
        return (NULL);
14840
0
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
14841
0
}
14842
14843
/**
14844
 * xmlReadFd:
14845
 * @fd:  an open file descriptor
14846
 * @URL:  the base URL to use for the document
14847
 * @encoding:  the document encoding, or NULL
14848
 * @options:  a combination of xmlParserOption
14849
 *
14850
 * parse an XML from a file descriptor and build a tree.
14851
 * NOTE that the file descriptor will not be closed when the
14852
 *      reader is closed or reset.
14853
 *
14854
 * Returns the resulting document tree
14855
 */
14856
xmlDocPtr
14857
xmlReadFd(int fd, const char *URL, const char *encoding, int options)
14858
0
{
14859
0
    xmlParserCtxtPtr ctxt;
14860
0
    xmlParserInputBufferPtr input;
14861
0
    xmlParserInputPtr stream;
14862
14863
0
    if (fd < 0)
14864
0
        return (NULL);
14865
0
    xmlInitParser();
14866
14867
0
    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
14868
0
    if (input == NULL)
14869
0
        return (NULL);
14870
0
    input->closecallback = NULL;
14871
0
    ctxt = xmlNewParserCtxt();
14872
0
    if (ctxt == NULL) {
14873
0
        xmlFreeParserInputBuffer(input);
14874
0
        return (NULL);
14875
0
    }
14876
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
14877
0
    if (stream == NULL) {
14878
0
        xmlFreeParserInputBuffer(input);
14879
0
  xmlFreeParserCtxt(ctxt);
14880
0
        return (NULL);
14881
0
    }
14882
0
    inputPush(ctxt, stream);
14883
0
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
14884
0
}
14885
14886
/**
14887
 * xmlReadIO:
14888
 * @ioread:  an I/O read function
14889
 * @ioclose:  an I/O close function
14890
 * @ioctx:  an I/O handler
14891
 * @URL:  the base URL to use for the document
14892
 * @encoding:  the document encoding, or NULL
14893
 * @options:  a combination of xmlParserOption
14894
 *
14895
 * parse an XML document from I/O functions and source and build a tree.
14896
 *
14897
 * Returns the resulting document tree
14898
 */
14899
xmlDocPtr
14900
xmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
14901
          void *ioctx, const char *URL, const char *encoding, int options)
14902
0
{
14903
0
    xmlParserCtxtPtr ctxt;
14904
0
    xmlParserInputBufferPtr input;
14905
0
    xmlParserInputPtr stream;
14906
14907
0
    if (ioread == NULL)
14908
0
        return (NULL);
14909
0
    xmlInitParser();
14910
14911
0
    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
14912
0
                                         XML_CHAR_ENCODING_NONE);
14913
0
    if (input == NULL) {
14914
0
        if (ioclose != NULL)
14915
0
            ioclose(ioctx);
14916
0
        return (NULL);
14917
0
    }
14918
0
    ctxt = xmlNewParserCtxt();
14919
0
    if (ctxt == NULL) {
14920
0
        xmlFreeParserInputBuffer(input);
14921
0
        return (NULL);
14922
0
    }
14923
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
14924
0
    if (stream == NULL) {
14925
0
        xmlFreeParserInputBuffer(input);
14926
0
  xmlFreeParserCtxt(ctxt);
14927
0
        return (NULL);
14928
0
    }
14929
0
    inputPush(ctxt, stream);
14930
0
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
14931
0
}
14932
14933
/**
14934
 * xmlCtxtReadDoc:
14935
 * @ctxt:  an XML parser context
14936
 * @str:  a pointer to a zero terminated string
14937
 * @URL:  the base URL to use for the document
14938
 * @encoding:  the document encoding, or NULL
14939
 * @options:  a combination of xmlParserOption
14940
 *
14941
 * parse an XML in-memory document and build a tree.
14942
 * This reuses the existing @ctxt parser context
14943
 *
14944
 * Returns the resulting document tree
14945
 */
14946
xmlDocPtr
14947
xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar *str,
14948
               const char *URL, const char *encoding, int options)
14949
0
{
14950
0
    xmlParserInputBufferPtr input;
14951
0
    xmlParserInputPtr stream;
14952
14953
0
    if (ctxt == NULL)
14954
0
        return (NULL);
14955
0
    if (str == NULL)
14956
0
        return (NULL);
14957
0
    xmlInitParser();
14958
14959
0
    xmlCtxtReset(ctxt);
14960
14961
0
    input = xmlParserInputBufferCreateString(str);
14962
0
    if (input == NULL) {
14963
0
  return(NULL);
14964
0
    }
14965
14966
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
14967
0
    if (stream == NULL) {
14968
0
  xmlFreeParserInputBuffer(input);
14969
0
  return(NULL);
14970
0
    }
14971
14972
0
    inputPush(ctxt, stream);
14973
0
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
14974
0
}
14975
14976
/**
14977
 * xmlCtxtReadFile:
14978
 * @ctxt:  an XML parser context
14979
 * @filename:  a file or URL
14980
 * @encoding:  the document encoding, or NULL
14981
 * @options:  a combination of xmlParserOption
14982
 *
14983
 * parse an XML file from the filesystem or the network.
14984
 * This reuses the existing @ctxt parser context
14985
 *
14986
 * Returns the resulting document tree
14987
 */
14988
xmlDocPtr
14989
xmlCtxtReadFile(xmlParserCtxtPtr ctxt, const char *filename,
14990
                const char *encoding, int options)
14991
0
{
14992
0
    xmlParserInputPtr stream;
14993
14994
0
    if (filename == NULL)
14995
0
        return (NULL);
14996
0
    if (ctxt == NULL)
14997
0
        return (NULL);
14998
0
    xmlInitParser();
14999
15000
0
    xmlCtxtReset(ctxt);
15001
15002
0
    stream = xmlLoadExternalEntity(filename, NULL, ctxt);
15003
0
    if (stream == NULL) {
15004
0
        return (NULL);
15005
0
    }
15006
0
    inputPush(ctxt, stream);
15007
0
    return (xmlDoRead(ctxt, NULL, encoding, options, 1));
15008
0
}
15009
15010
/**
15011
 * xmlCtxtReadMemory:
15012
 * @ctxt:  an XML parser context
15013
 * @buffer:  a pointer to a char array
15014
 * @size:  the size of the array
15015
 * @URL:  the base URL to use for the document
15016
 * @encoding:  the document encoding, or NULL
15017
 * @options:  a combination of xmlParserOption
15018
 *
15019
 * parse an XML in-memory document and build a tree.
15020
 * This reuses the existing @ctxt parser context
15021
 *
15022
 * Returns the resulting document tree
15023
 */
15024
xmlDocPtr
15025
xmlCtxtReadMemory(xmlParserCtxtPtr ctxt, const char *buffer, int size,
15026
                  const char *URL, const char *encoding, int options)
15027
0
{
15028
0
    xmlParserInputBufferPtr input;
15029
0
    xmlParserInputPtr stream;
15030
15031
0
    if (ctxt == NULL)
15032
0
        return (NULL);
15033
0
    if (buffer == NULL)
15034
0
        return (NULL);
15035
0
    xmlInitParser();
15036
15037
0
    xmlCtxtReset(ctxt);
15038
15039
0
    input = xmlParserInputBufferCreateStatic(buffer, size,
15040
0
                                             XML_CHAR_ENCODING_NONE);
15041
0
    if (input == NULL) {
15042
0
  return(NULL);
15043
0
    }
15044
15045
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15046
0
    if (stream == NULL) {
15047
0
  xmlFreeParserInputBuffer(input);
15048
0
  return(NULL);
15049
0
    }
15050
15051
0
    inputPush(ctxt, stream);
15052
0
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15053
0
}
15054
15055
/**
15056
 * xmlCtxtReadFd:
15057
 * @ctxt:  an XML parser context
15058
 * @fd:  an open file descriptor
15059
 * @URL:  the base URL to use for the document
15060
 * @encoding:  the document encoding, or NULL
15061
 * @options:  a combination of xmlParserOption
15062
 *
15063
 * parse an XML from a file descriptor and build a tree.
15064
 * This reuses the existing @ctxt parser context
15065
 * NOTE that the file descriptor will not be closed when the
15066
 *      reader is closed or reset.
15067
 *
15068
 * Returns the resulting document tree
15069
 */
15070
xmlDocPtr
15071
xmlCtxtReadFd(xmlParserCtxtPtr ctxt, int fd,
15072
              const char *URL, const char *encoding, int options)
15073
0
{
15074
0
    xmlParserInputBufferPtr input;
15075
0
    xmlParserInputPtr stream;
15076
15077
0
    if (fd < 0)
15078
0
        return (NULL);
15079
0
    if (ctxt == NULL)
15080
0
        return (NULL);
15081
0
    xmlInitParser();
15082
15083
0
    xmlCtxtReset(ctxt);
15084
15085
15086
0
    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
15087
0
    if (input == NULL)
15088
0
        return (NULL);
15089
0
    input->closecallback = NULL;
15090
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15091
0
    if (stream == NULL) {
15092
0
        xmlFreeParserInputBuffer(input);
15093
0
        return (NULL);
15094
0
    }
15095
0
    inputPush(ctxt, stream);
15096
0
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15097
0
}
15098
15099
/**
15100
 * xmlCtxtReadIO:
15101
 * @ctxt:  an XML parser context
15102
 * @ioread:  an I/O read function
15103
 * @ioclose:  an I/O close function
15104
 * @ioctx:  an I/O handler
15105
 * @URL:  the base URL to use for the document
15106
 * @encoding:  the document encoding, or NULL
15107
 * @options:  a combination of xmlParserOption
15108
 *
15109
 * parse an XML document from I/O functions and source and build a tree.
15110
 * This reuses the existing @ctxt parser context
15111
 *
15112
 * Returns the resulting document tree
15113
 */
15114
xmlDocPtr
15115
xmlCtxtReadIO(xmlParserCtxtPtr ctxt, xmlInputReadCallback ioread,
15116
              xmlInputCloseCallback ioclose, void *ioctx,
15117
        const char *URL,
15118
              const char *encoding, int options)
15119
0
{
15120
0
    xmlParserInputBufferPtr input;
15121
0
    xmlParserInputPtr stream;
15122
15123
0
    if (ioread == NULL)
15124
0
        return (NULL);
15125
0
    if (ctxt == NULL)
15126
0
        return (NULL);
15127
0
    xmlInitParser();
15128
15129
0
    xmlCtxtReset(ctxt);
15130
15131
0
    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
15132
0
                                         XML_CHAR_ENCODING_NONE);
15133
0
    if (input == NULL) {
15134
0
        if (ioclose != NULL)
15135
0
            ioclose(ioctx);
15136
0
        return (NULL);
15137
0
    }
15138
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15139
0
    if (stream == NULL) {
15140
0
        xmlFreeParserInputBuffer(input);
15141
0
        return (NULL);
15142
0
    }
15143
0
    inputPush(ctxt, stream);
15144
0
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15145
0
}
15146