Coverage Report

Created: 2026-03-30 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libxml2-2.12.10/parser.c
Line
Count
Source
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
0
#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
#ifdef LIBXML_ZLIB_ENABLED
821
            return(1);
822
#else
823
0
            return(0);
824
0
#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
0
xmlDetectSAX2(xmlParserCtxtPtr ctxt) {
857
0
    xmlSAXHandlerPtr sax;
858
859
    /* Avoid unused variable warning if features are disabled. */
860
0
    (void) sax;
861
862
0
    if (ctxt == NULL) return;
863
0
    sax = ctxt->sax;
864
0
#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
0
    if ((sax) && (sax->initialized == XML_SAX2_MAGIC) &&
870
0
        ((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
0
    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
879
0
    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
880
0
    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
881
0
    if ((ctxt->str_xml==NULL) || (ctxt->str_xmlns==NULL) ||
882
0
    (ctxt->str_xml_ns == NULL)) {
883
0
        xmlErrMemory(ctxt, NULL);
884
0
    }
885
0
}
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
0
xmlParserNsCreate(void) {
1414
0
    xmlParserNsData *nsdb = xmlMalloc(sizeof(*nsdb));
1415
1416
0
    if (nsdb == NULL)
1417
0
        return(NULL);
1418
0
    memset(nsdb, 0, sizeof(*nsdb));
1419
0
    nsdb->defaultNsIndex = INT_MAX;
1420
1421
0
    return(nsdb);
1422
0
}
1423
1424
/**
1425
 * xmlParserNsFree:
1426
 * @nsdb: namespace database
1427
 *
1428
 * Free a namespace database.
1429
 */
1430
void
1431
0
xmlParserNsFree(xmlParserNsData *nsdb) {
1432
0
    if (nsdb == NULL)
1433
0
        return;
1434
1435
0
    xmlFree(nsdb->extra);
1436
0
    xmlFree(nsdb->hash);
1437
0
    xmlFree(nsdb);
1438
0
}
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, *tombstone;
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
0
    tombstone = NULL;
1505
1506
0
    while (bucket->hashValue) {
1507
0
        if (bucket->index == INT_MAX) {
1508
0
            if (tombstone == NULL)
1509
0
                tombstone = bucket;
1510
0
        } else if (bucket->hashValue == hashValue) {
1511
0
            if (ctxt->nsTab[bucket->index * 2] == prefix->name) {
1512
0
                if (bucketPtr != NULL)
1513
0
                    *bucketPtr = bucket;
1514
0
                return(bucket->index);
1515
0
            }
1516
0
        }
1517
1518
0
        index++;
1519
0
        bucket++;
1520
0
        if (index == ctxt->nsdb->hashSize) {
1521
0
            index = 0;
1522
0
            bucket = ctxt->nsdb->hash;
1523
0
        }
1524
0
    }
1525
1526
0
    if (bucketPtr != NULL)
1527
0
        *bucketPtr = tombstone ? tombstone : bucket;
1528
0
    return(INT_MAX);
1529
0
}
1530
1531
/**
1532
 * xmlParserNsLookupUri:
1533
 * @ctxt: parser context
1534
 * @prefix: namespace prefix
1535
 *
1536
 * Lookup namespace URI with given prefix.
1537
 *
1538
 * Returns the namespace URI on success, NULL if no namespace was found.
1539
 */
1540
static const xmlChar *
1541
0
xmlParserNsLookupUri(xmlParserCtxtPtr ctxt, const xmlHashedString *prefix) {
1542
0
    const xmlChar *ret;
1543
0
    int nsIndex;
1544
1545
0
    if (prefix->name == ctxt->str_xml)
1546
0
        return(ctxt->str_xml_ns);
1547
1548
0
    nsIndex = xmlParserNsLookup(ctxt, prefix, NULL);
1549
0
    if (nsIndex == INT_MAX)
1550
0
        return(NULL);
1551
1552
0
    ret = ctxt->nsTab[nsIndex * 2 + 1];
1553
0
    if (ret[0] == 0)
1554
0
        ret = NULL;
1555
0
    return(ret);
1556
0
}
1557
1558
/**
1559
 * xmlParserNsLookupSax:
1560
 * @ctxt: parser context
1561
 * @prefix: namespace prefix
1562
 *
1563
 * Lookup extra data for the given prefix. This returns data stored
1564
 * with xmlParserNsUdpateSax.
1565
 *
1566
 * Returns the data on success, NULL if no namespace was found.
1567
 */
1568
void *
1569
0
xmlParserNsLookupSax(xmlParserCtxtPtr ctxt, const xmlChar *prefix) {
1570
0
    xmlHashedString hprefix;
1571
0
    int nsIndex;
1572
1573
0
    if (prefix == ctxt->str_xml)
1574
0
        return(NULL);
1575
1576
0
    hprefix.name = prefix;
1577
0
    if (prefix != NULL)
1578
0
        hprefix.hashValue = xmlDictComputeHash(ctxt->dict, prefix);
1579
0
    else
1580
0
        hprefix.hashValue = 0;
1581
0
    nsIndex = xmlParserNsLookup(ctxt, &hprefix, NULL);
1582
0
    if (nsIndex == INT_MAX)
1583
0
        return(NULL);
1584
1585
0
    return(ctxt->nsdb->extra[nsIndex].saxData);
1586
0
}
1587
1588
/**
1589
 * xmlParserNsUpdateSax:
1590
 * @ctxt: parser context
1591
 * @prefix: namespace prefix
1592
 * @saxData: extra data for SAX handler
1593
 *
1594
 * Sets or updates extra data for the given prefix. This value will be
1595
 * returned by xmlParserNsLookupSax as long as the namespace with the
1596
 * given prefix is in scope.
1597
 *
1598
 * Returns the data on success, NULL if no namespace was found.
1599
 */
1600
int
1601
xmlParserNsUpdateSax(xmlParserCtxtPtr ctxt, const xmlChar *prefix,
1602
0
                     void *saxData) {
1603
0
    xmlHashedString hprefix;
1604
0
    int nsIndex;
1605
1606
0
    if (prefix == ctxt->str_xml)
1607
0
        return(-1);
1608
1609
0
    hprefix.name = prefix;
1610
0
    if (prefix != NULL)
1611
0
        hprefix.hashValue = xmlDictComputeHash(ctxt->dict, prefix);
1612
0
    else
1613
0
        hprefix.hashValue = 0;
1614
0
    nsIndex = xmlParserNsLookup(ctxt, &hprefix, NULL);
1615
0
    if (nsIndex == INT_MAX)
1616
0
        return(-1);
1617
1618
0
    ctxt->nsdb->extra[nsIndex].saxData = saxData;
1619
0
    return(0);
1620
0
}
1621
1622
/**
1623
 * xmlParserNsGrow:
1624
 * @ctxt: parser context
1625
 *
1626
 * Grows the namespace tables.
1627
 *
1628
 * Returns 0 on success, -1 if a memory allocation failed.
1629
 */
1630
static int
1631
0
xmlParserNsGrow(xmlParserCtxtPtr ctxt) {
1632
0
    const xmlChar **table;
1633
0
    xmlParserNsExtra *extra;
1634
0
    int newSize;
1635
1636
0
    if (ctxt->nsMax > INT_MAX / 2)
1637
0
        goto error;
1638
0
    newSize = ctxt->nsMax ? ctxt->nsMax * 2 : 16;
1639
1640
0
    table = xmlRealloc(ctxt->nsTab, 2 * newSize * sizeof(table[0]));
1641
0
    if (table == NULL)
1642
0
        goto error;
1643
0
    ctxt->nsTab = table;
1644
1645
0
    extra = xmlRealloc(ctxt->nsdb->extra, newSize * sizeof(extra[0]));
1646
0
    if (extra == NULL)
1647
0
        goto error;
1648
0
    ctxt->nsdb->extra = extra;
1649
1650
0
    ctxt->nsMax = newSize;
1651
0
    return(0);
1652
1653
0
error:
1654
0
    xmlErrMemory(ctxt, NULL);
1655
0
    return(-1);
1656
0
}
1657
1658
/**
1659
 * xmlParserNsPush:
1660
 * @ctxt: parser context
1661
 * @prefix: prefix with hash value
1662
 * @uri: uri with hash value
1663
 * @saxData: extra data for SAX handler
1664
 * @defAttr: whether the namespace comes from a default attribute
1665
 *
1666
 * Push a new namespace on the table.
1667
 *
1668
 * Returns 1 if the namespace was pushed, 0 if the namespace was ignored,
1669
 * -1 if a memory allocation failed.
1670
 */
1671
static int
1672
xmlParserNsPush(xmlParserCtxtPtr ctxt, const xmlHashedString *prefix,
1673
0
                const xmlHashedString *uri, void *saxData, int defAttr) {
1674
0
    xmlParserNsBucket *bucket = NULL;
1675
0
    xmlParserNsExtra *extra;
1676
0
    const xmlChar **ns;
1677
0
    unsigned hashValue, nsIndex, oldIndex;
1678
1679
0
    if ((prefix != NULL) && (prefix->name == ctxt->str_xml))
1680
0
        return(0);
1681
1682
0
    if ((ctxt->nsNr >= ctxt->nsMax) && (xmlParserNsGrow(ctxt) < 0)) {
1683
0
        xmlErrMemory(ctxt, NULL);
1684
0
        return(-1);
1685
0
    }
1686
1687
    /*
1688
     * Default namespace and 'xml' namespace
1689
     */
1690
0
    if ((prefix == NULL) || (prefix->name == NULL)) {
1691
0
        oldIndex = ctxt->nsdb->defaultNsIndex;
1692
1693
0
        if (oldIndex != INT_MAX) {
1694
0
            extra = &ctxt->nsdb->extra[oldIndex];
1695
1696
0
            if (extra->elementId == ctxt->nsdb->elementId) {
1697
0
                if (defAttr == 0)
1698
0
                    xmlErrAttributeDup(ctxt, NULL, BAD_CAST "xmlns");
1699
0
                return(0);
1700
0
            }
1701
1702
0
            if ((ctxt->options & XML_PARSE_NSCLEAN) &&
1703
0
                (uri->name == ctxt->nsTab[oldIndex * 2 + 1]))
1704
0
                return(0);
1705
0
        }
1706
1707
0
        ctxt->nsdb->defaultNsIndex = ctxt->nsNr;
1708
0
        goto populate_entry;
1709
0
    }
1710
1711
    /*
1712
     * Hash table lookup
1713
     */
1714
0
    oldIndex = xmlParserNsLookup(ctxt, prefix, &bucket);
1715
0
    if (oldIndex != INT_MAX) {
1716
0
        extra = &ctxt->nsdb->extra[oldIndex];
1717
1718
        /*
1719
         * Check for duplicate definitions on the same element.
1720
         */
1721
0
        if (extra->elementId == ctxt->nsdb->elementId) {
1722
0
            if (defAttr == 0)
1723
0
                xmlErrAttributeDup(ctxt, BAD_CAST "xmlns", prefix->name);
1724
0
            return(0);
1725
0
        }
1726
1727
0
        if ((ctxt->options & XML_PARSE_NSCLEAN) &&
1728
0
            (uri->name == ctxt->nsTab[bucket->index * 2 + 1]))
1729
0
            return(0);
1730
1731
0
        bucket->index = ctxt->nsNr;
1732
0
        goto populate_entry;
1733
0
    }
1734
1735
    /*
1736
     * Insert new bucket
1737
     */
1738
1739
0
    hashValue = prefix->hashValue;
1740
1741
    /*
1742
     * Grow hash table, 50% fill factor
1743
     */
1744
0
    if (ctxt->nsdb->hashElems + 1 > ctxt->nsdb->hashSize / 2) {
1745
0
        xmlParserNsBucket *newHash;
1746
0
        unsigned newSize, i, index;
1747
1748
0
        if (ctxt->nsdb->hashSize > UINT_MAX / 2) {
1749
0
            xmlErrMemory(ctxt, NULL);
1750
0
            return(-1);
1751
0
        }
1752
0
        newSize = ctxt->nsdb->hashSize ? ctxt->nsdb->hashSize * 2 : 16;
1753
0
        newHash = xmlMalloc(newSize * sizeof(newHash[0]));
1754
0
        if (newHash == NULL) {
1755
0
            xmlErrMemory(ctxt, NULL);
1756
0
            return(-1);
1757
0
        }
1758
0
        memset(newHash, 0, newSize * sizeof(newHash[0]));
1759
1760
0
        for (i = 0; i < ctxt->nsdb->hashSize; i++) {
1761
0
            unsigned hv = ctxt->nsdb->hash[i].hashValue;
1762
0
            unsigned newIndex;
1763
1764
0
            if ((hv == 0) || (ctxt->nsdb->hash[i].index == INT_MAX))
1765
0
                continue;
1766
0
            newIndex = hv & (newSize - 1);
1767
1768
0
            while (newHash[newIndex].hashValue != 0) {
1769
0
                newIndex++;
1770
0
                if (newIndex == newSize)
1771
0
                    newIndex = 0;
1772
0
            }
1773
1774
0
            newHash[newIndex] = ctxt->nsdb->hash[i];
1775
0
        }
1776
1777
0
        xmlFree(ctxt->nsdb->hash);
1778
0
        ctxt->nsdb->hash = newHash;
1779
0
        ctxt->nsdb->hashSize = newSize;
1780
1781
        /*
1782
         * Relookup
1783
         */
1784
0
        index = hashValue & (newSize - 1);
1785
1786
0
        while (newHash[index].hashValue != 0) {
1787
0
            index++;
1788
0
            if (index == newSize)
1789
0
                index = 0;
1790
0
        }
1791
1792
0
        bucket = &newHash[index];
1793
0
    }
1794
1795
0
    bucket->hashValue = hashValue;
1796
0
    bucket->index = ctxt->nsNr;
1797
0
    ctxt->nsdb->hashElems++;
1798
0
    oldIndex = INT_MAX;
1799
1800
0
populate_entry:
1801
0
    nsIndex = ctxt->nsNr;
1802
1803
0
    ns = &ctxt->nsTab[nsIndex * 2];
1804
0
    ns[0] = prefix ? prefix->name : NULL;
1805
0
    ns[1] = uri->name;
1806
1807
0
    extra = &ctxt->nsdb->extra[nsIndex];
1808
0
    extra->saxData = saxData;
1809
0
    extra->prefixHashValue = prefix ? prefix->hashValue : 0;
1810
0
    extra->uriHashValue = uri->hashValue;
1811
0
    extra->elementId = ctxt->nsdb->elementId;
1812
0
    extra->oldIndex = oldIndex;
1813
1814
0
    ctxt->nsNr++;
1815
1816
0
    return(1);
1817
0
}
1818
1819
/**
1820
 * xmlParserNsPop:
1821
 * @ctxt: an XML parser context
1822
 * @nr:  the number to pop
1823
 *
1824
 * Pops the top @nr namespaces and restores the hash table.
1825
 *
1826
 * Returns the number of namespaces popped.
1827
 */
1828
static int
1829
xmlParserNsPop(xmlParserCtxtPtr ctxt, int nr)
1830
0
{
1831
0
    int i;
1832
1833
    /* assert(nr <= ctxt->nsNr); */
1834
1835
0
    for (i = ctxt->nsNr - 1; i >= ctxt->nsNr - nr; i--) {
1836
0
        const xmlChar *prefix = ctxt->nsTab[i * 2];
1837
0
        xmlParserNsExtra *extra = &ctxt->nsdb->extra[i];
1838
1839
0
        if (prefix == NULL) {
1840
0
            ctxt->nsdb->defaultNsIndex = extra->oldIndex;
1841
0
        } else {
1842
0
            xmlHashedString hprefix;
1843
0
            xmlParserNsBucket *bucket = NULL;
1844
1845
0
            hprefix.name = prefix;
1846
0
            hprefix.hashValue = extra->prefixHashValue;
1847
0
            xmlParserNsLookup(ctxt, &hprefix, &bucket);
1848
            /* assert(bucket && bucket->hashValue); */
1849
0
            bucket->index = extra->oldIndex;
1850
0
        }
1851
0
    }
1852
1853
0
    ctxt->nsNr -= nr;
1854
0
    return(nr);
1855
0
}
1856
1857
static int
1858
0
xmlCtxtGrowAttrs(xmlParserCtxtPtr ctxt, int nr) {
1859
0
    const xmlChar **atts;
1860
0
    unsigned *attallocs;
1861
0
    int maxatts;
1862
1863
0
    if (nr + 5 > ctxt->maxatts) {
1864
0
  maxatts = ctxt->maxatts == 0 ? 55 : (nr + 5) * 2;
1865
0
  atts = (const xmlChar **) xmlMalloc(
1866
0
             maxatts * sizeof(const xmlChar *));
1867
0
  if (atts == NULL) goto mem_error;
1868
0
  attallocs = xmlRealloc(ctxt->attallocs,
1869
0
                               (maxatts / 5) * sizeof(attallocs[0]));
1870
0
  if (attallocs == NULL) {
1871
0
            xmlFree(atts);
1872
0
            goto mem_error;
1873
0
        }
1874
0
        if (ctxt->maxatts > 0)
1875
0
            memcpy(atts, ctxt->atts, ctxt->maxatts * sizeof(const xmlChar *));
1876
0
        xmlFree(ctxt->atts);
1877
0
  ctxt->atts = atts;
1878
0
  ctxt->attallocs = attallocs;
1879
0
  ctxt->maxatts = maxatts;
1880
0
    }
1881
0
    return(ctxt->maxatts);
1882
0
mem_error:
1883
0
    xmlErrMemory(ctxt, NULL);
1884
0
    return(-1);
1885
0
}
1886
1887
/**
1888
 * inputPush:
1889
 * @ctxt:  an XML parser context
1890
 * @value:  the parser input
1891
 *
1892
 * Pushes a new parser input on top of the input stack
1893
 *
1894
 * Returns -1 in case of error, the index in the stack otherwise
1895
 */
1896
int
1897
inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value)
1898
0
{
1899
0
    if ((ctxt == NULL) || (value == NULL))
1900
0
        return(-1);
1901
0
    if (ctxt->inputNr >= ctxt->inputMax) {
1902
0
        size_t newSize = ctxt->inputMax * 2;
1903
0
        xmlParserInputPtr *tmp;
1904
1905
0
        tmp = (xmlParserInputPtr *) xmlRealloc(ctxt->inputTab,
1906
0
                                               newSize * sizeof(*tmp));
1907
0
        if (tmp == NULL) {
1908
0
            xmlErrMemory(ctxt, NULL);
1909
0
            return (-1);
1910
0
        }
1911
0
        ctxt->inputTab = tmp;
1912
0
        ctxt->inputMax = newSize;
1913
0
    }
1914
0
    ctxt->inputTab[ctxt->inputNr] = value;
1915
0
    ctxt->input = value;
1916
0
    return (ctxt->inputNr++);
1917
0
}
1918
/**
1919
 * inputPop:
1920
 * @ctxt: an XML parser context
1921
 *
1922
 * Pops the top parser input from the input stack
1923
 *
1924
 * Returns the input just removed
1925
 */
1926
xmlParserInputPtr
1927
inputPop(xmlParserCtxtPtr ctxt)
1928
0
{
1929
0
    xmlParserInputPtr ret;
1930
1931
0
    if (ctxt == NULL)
1932
0
        return(NULL);
1933
0
    if (ctxt->inputNr <= 0)
1934
0
        return (NULL);
1935
0
    ctxt->inputNr--;
1936
0
    if (ctxt->inputNr > 0)
1937
0
        ctxt->input = ctxt->inputTab[ctxt->inputNr - 1];
1938
0
    else
1939
0
        ctxt->input = NULL;
1940
0
    ret = ctxt->inputTab[ctxt->inputNr];
1941
0
    ctxt->inputTab[ctxt->inputNr] = NULL;
1942
0
    return (ret);
1943
0
}
1944
/**
1945
 * nodePush:
1946
 * @ctxt:  an XML parser context
1947
 * @value:  the element node
1948
 *
1949
 * DEPRECATED: Internal function, do not use.
1950
 *
1951
 * Pushes a new element node on top of the node stack
1952
 *
1953
 * Returns -1 in case of error, the index in the stack otherwise
1954
 */
1955
int
1956
nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value)
1957
0
{
1958
0
    if (ctxt == NULL) return(0);
1959
0
    if (ctxt->nodeNr >= ctxt->nodeMax) {
1960
0
        xmlNodePtr *tmp;
1961
1962
0
  tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
1963
0
                                      ctxt->nodeMax * 2 *
1964
0
                                      sizeof(ctxt->nodeTab[0]));
1965
0
        if (tmp == NULL) {
1966
0
            xmlErrMemory(ctxt, NULL);
1967
0
            return (-1);
1968
0
        }
1969
0
        ctxt->nodeTab = tmp;
1970
0
  ctxt->nodeMax *= 2;
1971
0
    }
1972
0
    if ((((unsigned int) ctxt->nodeNr) > xmlParserMaxDepth) &&
1973
0
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
1974
0
  xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
1975
0
     "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
1976
0
        xmlParserMaxDepth);
1977
0
  xmlHaltParser(ctxt);
1978
0
  return(-1);
1979
0
    }
1980
0
    ctxt->nodeTab[ctxt->nodeNr] = value;
1981
0
    ctxt->node = value;
1982
0
    return (ctxt->nodeNr++);
1983
0
}
1984
1985
/**
1986
 * nodePop:
1987
 * @ctxt: an XML parser context
1988
 *
1989
 * DEPRECATED: Internal function, do not use.
1990
 *
1991
 * Pops the top element node from the node stack
1992
 *
1993
 * Returns the node just removed
1994
 */
1995
xmlNodePtr
1996
nodePop(xmlParserCtxtPtr ctxt)
1997
0
{
1998
0
    xmlNodePtr ret;
1999
2000
0
    if (ctxt == NULL) return(NULL);
2001
0
    if (ctxt->nodeNr <= 0)
2002
0
        return (NULL);
2003
0
    ctxt->nodeNr--;
2004
0
    if (ctxt->nodeNr > 0)
2005
0
        ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1];
2006
0
    else
2007
0
        ctxt->node = NULL;
2008
0
    ret = ctxt->nodeTab[ctxt->nodeNr];
2009
0
    ctxt->nodeTab[ctxt->nodeNr] = NULL;
2010
0
    return (ret);
2011
0
}
2012
2013
/**
2014
 * nameNsPush:
2015
 * @ctxt:  an XML parser context
2016
 * @value:  the element name
2017
 * @prefix:  the element prefix
2018
 * @URI:  the element namespace name
2019
 * @line:  the current line number for error messages
2020
 * @nsNr:  the number of namespaces pushed on the namespace table
2021
 *
2022
 * Pushes a new element name/prefix/URL on top of the name stack
2023
 *
2024
 * Returns -1 in case of error, the index in the stack otherwise
2025
 */
2026
static int
2027
nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
2028
           const xmlChar *prefix, const xmlChar *URI, int line, int nsNr)
2029
0
{
2030
0
    xmlStartTag *tag;
2031
2032
0
    if (ctxt->nameNr >= ctxt->nameMax) {
2033
0
        const xmlChar * *tmp;
2034
0
        xmlStartTag *tmp2;
2035
0
        ctxt->nameMax *= 2;
2036
0
        tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
2037
0
                                    ctxt->nameMax *
2038
0
                                    sizeof(ctxt->nameTab[0]));
2039
0
        if (tmp == NULL) {
2040
0
      ctxt->nameMax /= 2;
2041
0
      goto mem_error;
2042
0
        }
2043
0
  ctxt->nameTab = tmp;
2044
0
        tmp2 = (xmlStartTag *) xmlRealloc((void * *)ctxt->pushTab,
2045
0
                                    ctxt->nameMax *
2046
0
                                    sizeof(ctxt->pushTab[0]));
2047
0
        if (tmp2 == NULL) {
2048
0
      ctxt->nameMax /= 2;
2049
0
      goto mem_error;
2050
0
        }
2051
0
  ctxt->pushTab = tmp2;
2052
0
    } else if (ctxt->pushTab == NULL) {
2053
0
        ctxt->pushTab = (xmlStartTag *) xmlMalloc(ctxt->nameMax *
2054
0
                                            sizeof(ctxt->pushTab[0]));
2055
0
        if (ctxt->pushTab == NULL)
2056
0
            goto mem_error;
2057
0
    }
2058
0
    ctxt->nameTab[ctxt->nameNr] = value;
2059
0
    ctxt->name = value;
2060
0
    tag = &ctxt->pushTab[ctxt->nameNr];
2061
0
    tag->prefix = prefix;
2062
0
    tag->URI = URI;
2063
0
    tag->line = line;
2064
0
    tag->nsNr = nsNr;
2065
0
    return (ctxt->nameNr++);
2066
0
mem_error:
2067
0
    xmlErrMemory(ctxt, NULL);
2068
0
    return (-1);
2069
0
}
2070
#ifdef LIBXML_PUSH_ENABLED
2071
/**
2072
 * nameNsPop:
2073
 * @ctxt: an XML parser context
2074
 *
2075
 * Pops the top element/prefix/URI name from the name stack
2076
 *
2077
 * Returns the name just removed
2078
 */
2079
static const xmlChar *
2080
nameNsPop(xmlParserCtxtPtr ctxt)
2081
0
{
2082
0
    const xmlChar *ret;
2083
2084
0
    if (ctxt->nameNr <= 0)
2085
0
        return (NULL);
2086
0
    ctxt->nameNr--;
2087
0
    if (ctxt->nameNr > 0)
2088
0
        ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
2089
0
    else
2090
0
        ctxt->name = NULL;
2091
0
    ret = ctxt->nameTab[ctxt->nameNr];
2092
0
    ctxt->nameTab[ctxt->nameNr] = NULL;
2093
0
    return (ret);
2094
0
}
2095
#endif /* LIBXML_PUSH_ENABLED */
2096
2097
/**
2098
 * namePush:
2099
 * @ctxt:  an XML parser context
2100
 * @value:  the element name
2101
 *
2102
 * DEPRECATED: Internal function, do not use.
2103
 *
2104
 * Pushes a new element name on top of the name stack
2105
 *
2106
 * Returns -1 in case of error, the index in the stack otherwise
2107
 */
2108
int
2109
namePush(xmlParserCtxtPtr ctxt, const xmlChar * value)
2110
0
{
2111
0
    if (ctxt == NULL) return (-1);
2112
2113
0
    if (ctxt->nameNr >= ctxt->nameMax) {
2114
0
        const xmlChar * *tmp;
2115
0
        tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
2116
0
                                    ctxt->nameMax * 2 *
2117
0
                                    sizeof(ctxt->nameTab[0]));
2118
0
        if (tmp == NULL) {
2119
0
      goto mem_error;
2120
0
        }
2121
0
  ctxt->nameTab = tmp;
2122
0
        ctxt->nameMax *= 2;
2123
0
    }
2124
0
    ctxt->nameTab[ctxt->nameNr] = value;
2125
0
    ctxt->name = value;
2126
0
    return (ctxt->nameNr++);
2127
0
mem_error:
2128
0
    xmlErrMemory(ctxt, NULL);
2129
0
    return (-1);
2130
0
}
2131
2132
/**
2133
 * namePop:
2134
 * @ctxt: an XML parser context
2135
 *
2136
 * DEPRECATED: Internal function, do not use.
2137
 *
2138
 * Pops the top element name from the name stack
2139
 *
2140
 * Returns the name just removed
2141
 */
2142
const xmlChar *
2143
namePop(xmlParserCtxtPtr ctxt)
2144
0
{
2145
0
    const xmlChar *ret;
2146
2147
0
    if ((ctxt == NULL) || (ctxt->nameNr <= 0))
2148
0
        return (NULL);
2149
0
    ctxt->nameNr--;
2150
0
    if (ctxt->nameNr > 0)
2151
0
        ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
2152
0
    else
2153
0
        ctxt->name = NULL;
2154
0
    ret = ctxt->nameTab[ctxt->nameNr];
2155
0
    ctxt->nameTab[ctxt->nameNr] = NULL;
2156
0
    return (ret);
2157
0
}
2158
2159
0
static int spacePush(xmlParserCtxtPtr ctxt, int val) {
2160
0
    if (ctxt->spaceNr >= ctxt->spaceMax) {
2161
0
        int *tmp;
2162
2163
0
  ctxt->spaceMax *= 2;
2164
0
        tmp = (int *) xmlRealloc(ctxt->spaceTab,
2165
0
                           ctxt->spaceMax * sizeof(ctxt->spaceTab[0]));
2166
0
        if (tmp == NULL) {
2167
0
      xmlErrMemory(ctxt, NULL);
2168
0
      ctxt->spaceMax /=2;
2169
0
      return(-1);
2170
0
  }
2171
0
  ctxt->spaceTab = tmp;
2172
0
    }
2173
0
    ctxt->spaceTab[ctxt->spaceNr] = val;
2174
0
    ctxt->space = &ctxt->spaceTab[ctxt->spaceNr];
2175
0
    return(ctxt->spaceNr++);
2176
0
}
2177
2178
0
static int spacePop(xmlParserCtxtPtr ctxt) {
2179
0
    int ret;
2180
0
    if (ctxt->spaceNr <= 0) return(0);
2181
0
    ctxt->spaceNr--;
2182
0
    if (ctxt->spaceNr > 0)
2183
0
  ctxt->space = &ctxt->spaceTab[ctxt->spaceNr - 1];
2184
0
    else
2185
0
        ctxt->space = &ctxt->spaceTab[0];
2186
0
    ret = ctxt->spaceTab[ctxt->spaceNr];
2187
0
    ctxt->spaceTab[ctxt->spaceNr] = -1;
2188
0
    return(ret);
2189
0
}
2190
2191
/*
2192
 * Macros for accessing the content. Those should be used only by the parser,
2193
 * and not exported.
2194
 *
2195
 * Dirty macros, i.e. one often need to make assumption on the context to
2196
 * use them
2197
 *
2198
 *   CUR_PTR return the current pointer to the xmlChar to be parsed.
2199
 *           To be used with extreme caution since operations consuming
2200
 *           characters may move the input buffer to a different location !
2201
 *   CUR     returns the current xmlChar value, i.e. a 8 bit value if compiled
2202
 *           This should be used internally by the parser
2203
 *           only to compare to ASCII values otherwise it would break when
2204
 *           running with UTF-8 encoding.
2205
 *   RAW     same as CUR but in the input buffer, bypass any token
2206
 *           extraction that may have been done
2207
 *   NXT(n)  returns the n'th next xmlChar. Same as CUR is should be used only
2208
 *           to compare on ASCII based substring.
2209
 *   SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
2210
 *           strings without newlines within the parser.
2211
 *   NEXT1(l) Skip 1 xmlChar, and must also be used only to skip 1 non-newline ASCII
2212
 *           defined char within the parser.
2213
 * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
2214
 *
2215
 *   NEXT    Skip to the next character, this does the proper decoding
2216
 *           in UTF-8 mode. It also pop-up unfinished entities on the fly.
2217
 *   NEXTL(l) Skip the current unicode character of l xmlChars long.
2218
 *   CUR_CHAR(l) returns the current unicode character (int), set l
2219
 *           to the number of xmlChars used for the encoding [0-5].
2220
 *   CUR_SCHAR  same but operate on a string instead of the context
2221
 *   COPY_BUF  copy the current unicode char to the target buffer, increment
2222
 *            the index
2223
 *   GROW, SHRINK  handling of input buffers
2224
 */
2225
2226
0
#define RAW (*ctxt->input->cur)
2227
0
#define CUR (*ctxt->input->cur)
2228
0
#define NXT(val) ctxt->input->cur[(val)]
2229
0
#define CUR_PTR ctxt->input->cur
2230
0
#define BASE_PTR ctxt->input->base
2231
2232
#define CMP4( s, c1, c2, c3, c4 ) \
2233
0
  ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char *) s)[ 1 ] == c2 && \
2234
0
    ((unsigned char *) s)[ 2 ] == c3 && ((unsigned char *) s)[ 3 ] == c4 )
2235
#define CMP5( s, c1, c2, c3, c4, c5 ) \
2236
0
  ( CMP4( s, c1, c2, c3, c4 ) && ((unsigned char *) s)[ 4 ] == c5 )
2237
#define CMP6( s, c1, c2, c3, c4, c5, c6 ) \
2238
0
  ( CMP5( s, c1, c2, c3, c4, c5 ) && ((unsigned char *) s)[ 5 ] == c6 )
2239
#define CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) \
2240
0
  ( CMP6( s, c1, c2, c3, c4, c5, c6 ) && ((unsigned char *) s)[ 6 ] == c7 )
2241
#define CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) \
2242
0
  ( CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) && ((unsigned char *) s)[ 7 ] == c8 )
2243
#define CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) \
2244
0
  ( CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) && \
2245
0
    ((unsigned char *) s)[ 8 ] == c9 )
2246
#define CMP10( s, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 ) \
2247
0
  ( CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) && \
2248
0
    ((unsigned char *) s)[ 9 ] == c10 )
2249
2250
0
#define SKIP(val) do {             \
2251
0
    ctxt->input->cur += (val),ctxt->input->col+=(val);      \
2252
0
    if (*ctxt->input->cur == 0)           \
2253
0
        xmlParserGrow(ctxt);           \
2254
0
  } while (0)
2255
2256
0
#define SKIPL(val) do {             \
2257
0
    int skipl;                \
2258
0
    for(skipl=0; skipl<val; skipl++) {         \
2259
0
  if (*(ctxt->input->cur) == '\n') {       \
2260
0
  ctxt->input->line++; ctxt->input->col = 1;      \
2261
0
  } else ctxt->input->col++;         \
2262
0
  ctxt->input->cur++;           \
2263
0
    }                 \
2264
0
    if (*ctxt->input->cur == 0)           \
2265
0
        xmlParserGrow(ctxt);           \
2266
0
  } while (0)
2267
2268
/* Don't shrink push parser buffer. */
2269
#define SHRINK \
2270
0
    if (((ctxt->progressive == 0) || (ctxt->inputNr > 1)) && \
2271
0
        (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \
2272
0
  (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \
2273
0
  xmlParserShrink(ctxt);
2274
2275
0
#define GROW if (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK) \
2276
0
  xmlParserGrow(ctxt);
2277
2278
0
#define SKIP_BLANKS xmlSkipBlankChars(ctxt)
2279
2280
0
#define NEXT xmlNextChar(ctxt)
2281
2282
0
#define NEXT1 {               \
2283
0
  ctxt->input->col++;           \
2284
0
  ctxt->input->cur++;           \
2285
0
  if (*ctxt->input->cur == 0)         \
2286
0
      xmlParserGrow(ctxt);           \
2287
0
    }
2288
2289
0
#define NEXTL(l) do {             \
2290
0
    if (*(ctxt->input->cur) == '\n') {         \
2291
0
  ctxt->input->line++; ctxt->input->col = 1;      \
2292
0
    } else ctxt->input->col++;           \
2293
0
    ctxt->input->cur += l;        \
2294
0
  } while (0)
2295
2296
0
#define CUR_CHAR(l) xmlCurrentChar(ctxt, &l)
2297
0
#define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l)
2298
2299
#define COPY_BUF(b, i, v)           \
2300
0
    if (v < 0x80) b[i++] = v;           \
2301
0
    else i += xmlCopyCharMultiByte(&b[i],v)
2302
2303
/**
2304
 * xmlSkipBlankChars:
2305
 * @ctxt:  the XML parser context
2306
 *
2307
 * DEPRECATED: Internal function, do not use.
2308
 *
2309
 * skip all blanks character found at that point in the input streams.
2310
 * It pops up finished entities in the process if allowable at that point.
2311
 *
2312
 * Returns the number of space chars skipped
2313
 */
2314
2315
int
2316
0
xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
2317
0
    int res = 0;
2318
2319
    /*
2320
     * It's Okay to use CUR/NEXT here since all the blanks are on
2321
     * the ASCII range.
2322
     */
2323
0
    if (((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) ||
2324
0
        (ctxt->instate == XML_PARSER_START)) {
2325
0
  const xmlChar *cur;
2326
  /*
2327
   * if we are in the document content, go really fast
2328
   */
2329
0
  cur = ctxt->input->cur;
2330
0
  while (IS_BLANK_CH(*cur)) {
2331
0
      if (*cur == '\n') {
2332
0
    ctxt->input->line++; ctxt->input->col = 1;
2333
0
      } else {
2334
0
    ctxt->input->col++;
2335
0
      }
2336
0
      cur++;
2337
0
      if (res < INT_MAX)
2338
0
    res++;
2339
0
      if (*cur == 0) {
2340
0
    ctxt->input->cur = cur;
2341
0
    xmlParserGrow(ctxt);
2342
0
    cur = ctxt->input->cur;
2343
0
      }
2344
0
  }
2345
0
  ctxt->input->cur = cur;
2346
0
    } else {
2347
0
        int expandPE = ((ctxt->external != 0) || (ctxt->inputNr != 1));
2348
2349
0
  while (ctxt->instate != XML_PARSER_EOF) {
2350
0
            if (IS_BLANK_CH(CUR)) { /* CHECKED tstblanks.xml */
2351
0
    NEXT;
2352
0
      } else if (CUR == '%') {
2353
                /*
2354
                 * Need to handle support of entities branching here
2355
                 */
2356
0
          if ((expandPE == 0) || (IS_BLANK_CH(NXT(1))) || (NXT(1) == 0))
2357
0
                    break;
2358
0
          xmlParsePEReference(ctxt);
2359
0
            } else if (CUR == 0) {
2360
0
                unsigned long consumed;
2361
0
                xmlEntityPtr ent;
2362
2363
0
                if (ctxt->inputNr <= 1)
2364
0
                    break;
2365
2366
0
                consumed = ctxt->input->consumed;
2367
0
                xmlSaturatedAddSizeT(&consumed,
2368
0
                                     ctxt->input->cur - ctxt->input->base);
2369
2370
                /*
2371
                 * Add to sizeentities when parsing an external entity
2372
                 * for the first time.
2373
                 */
2374
0
                ent = ctxt->input->entity;
2375
0
                if ((ent->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
2376
0
                    ((ent->flags & XML_ENT_PARSED) == 0)) {
2377
0
                    ent->flags |= XML_ENT_PARSED;
2378
2379
0
                    xmlSaturatedAdd(&ctxt->sizeentities, consumed);
2380
0
                }
2381
2382
0
                xmlParserEntityCheck(ctxt, consumed);
2383
2384
0
                xmlPopInput(ctxt);
2385
0
            } else {
2386
0
                break;
2387
0
            }
2388
2389
            /*
2390
             * Also increase the counter when entering or exiting a PERef.
2391
             * The spec says: "When a parameter-entity reference is recognized
2392
             * in the DTD and included, its replacement text MUST be enlarged
2393
             * by the attachment of one leading and one following space (#x20)
2394
             * character."
2395
             */
2396
0
      if (res < INT_MAX)
2397
0
    res++;
2398
0
        }
2399
0
    }
2400
0
    return(res);
2401
0
}
2402
2403
/************************************************************************
2404
 *                  *
2405
 *    Commodity functions to handle entities      *
2406
 *                  *
2407
 ************************************************************************/
2408
2409
/**
2410
 * xmlPopInput:
2411
 * @ctxt:  an XML parser context
2412
 *
2413
 * xmlPopInput: the current input pointed by ctxt->input came to an end
2414
 *          pop it and return the next char.
2415
 *
2416
 * Returns the current xmlChar in the parser context
2417
 */
2418
xmlChar
2419
0
xmlPopInput(xmlParserCtxtPtr ctxt) {
2420
0
    xmlParserInputPtr input;
2421
2422
0
    if ((ctxt == NULL) || (ctxt->inputNr <= 1)) return(0);
2423
0
    if (xmlParserDebugEntities)
2424
0
  xmlGenericError(xmlGenericErrorContext,
2425
0
    "Popping input %d\n", ctxt->inputNr);
2426
0
    if ((ctxt->inputNr > 1) && (ctxt->inSubset == 0) &&
2427
0
        (ctxt->instate != XML_PARSER_EOF))
2428
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
2429
0
                    "Unfinished entity outside the DTD");
2430
0
    input = inputPop(ctxt);
2431
0
    if (input->entity != NULL)
2432
0
        input->entity->flags &= ~XML_ENT_EXPANDING;
2433
0
    xmlFreeInputStream(input);
2434
0
    if (*ctxt->input->cur == 0)
2435
0
        xmlParserGrow(ctxt);
2436
0
    return(CUR);
2437
0
}
2438
2439
/**
2440
 * xmlPushInput:
2441
 * @ctxt:  an XML parser context
2442
 * @input:  an XML parser input fragment (entity, XML fragment ...).
2443
 *
2444
 * xmlPushInput: switch to a new input stream which is stacked on top
2445
 *               of the previous one(s).
2446
 * Returns -1 in case of error or the index in the input stack
2447
 */
2448
int
2449
0
xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
2450
0
    int ret;
2451
0
    if (input == NULL) return(-1);
2452
2453
0
    if (xmlParserDebugEntities) {
2454
0
  if ((ctxt->input != NULL) && (ctxt->input->filename))
2455
0
      xmlGenericError(xmlGenericErrorContext,
2456
0
        "%s(%d): ", ctxt->input->filename,
2457
0
        ctxt->input->line);
2458
0
  xmlGenericError(xmlGenericErrorContext,
2459
0
    "Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur);
2460
0
    }
2461
0
    if (((ctxt->inputNr > 40) && ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
2462
0
        (ctxt->inputNr > 100)) {
2463
0
        xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
2464
0
        while (ctxt->inputNr > 1)
2465
0
            xmlFreeInputStream(inputPop(ctxt));
2466
0
  return(-1);
2467
0
    }
2468
0
    ret = inputPush(ctxt, input);
2469
0
    if (ctxt->instate == XML_PARSER_EOF)
2470
0
        return(-1);
2471
0
    GROW;
2472
0
    return(ret);
2473
0
}
2474
2475
/**
2476
 * xmlParseCharRef:
2477
 * @ctxt:  an XML parser context
2478
 *
2479
 * DEPRECATED: Internal function, don't use.
2480
 *
2481
 * Parse a numeric character reference. Always consumes '&'.
2482
 *
2483
 * [66] CharRef ::= '&#' [0-9]+ ';' |
2484
 *                  '&#x' [0-9a-fA-F]+ ';'
2485
 *
2486
 * [ WFC: Legal Character ]
2487
 * Characters referred to using character references must match the
2488
 * production for Char.
2489
 *
2490
 * Returns the value parsed (as an int), 0 in case of error
2491
 */
2492
int
2493
0
xmlParseCharRef(xmlParserCtxtPtr ctxt) {
2494
0
    int val = 0;
2495
0
    int count = 0;
2496
2497
    /*
2498
     * Using RAW/CUR/NEXT is okay since we are working on ASCII range here
2499
     */
2500
0
    if ((RAW == '&') && (NXT(1) == '#') &&
2501
0
        (NXT(2) == 'x')) {
2502
0
  SKIP(3);
2503
0
  GROW;
2504
0
  while (RAW != ';') { /* loop blocked by count */
2505
0
      if (count++ > 20) {
2506
0
    count = 0;
2507
0
    GROW;
2508
0
                if (ctxt->instate == XML_PARSER_EOF)
2509
0
                    return(0);
2510
0
      }
2511
0
      if ((RAW >= '0') && (RAW <= '9'))
2512
0
          val = val * 16 + (CUR - '0');
2513
0
      else if ((RAW >= 'a') && (RAW <= 'f') && (count < 20))
2514
0
          val = val * 16 + (CUR - 'a') + 10;
2515
0
      else if ((RAW >= 'A') && (RAW <= 'F') && (count < 20))
2516
0
          val = val * 16 + (CUR - 'A') + 10;
2517
0
      else {
2518
0
    xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
2519
0
    val = 0;
2520
0
    break;
2521
0
      }
2522
0
      if (val > 0x110000)
2523
0
          val = 0x110000;
2524
2525
0
      NEXT;
2526
0
      count++;
2527
0
  }
2528
0
  if (RAW == ';') {
2529
      /* on purpose to avoid reentrancy problems with NEXT and SKIP */
2530
0
      ctxt->input->col++;
2531
0
      ctxt->input->cur++;
2532
0
  }
2533
0
    } else if  ((RAW == '&') && (NXT(1) == '#')) {
2534
0
  SKIP(2);
2535
0
  GROW;
2536
0
  while (RAW != ';') { /* loop blocked by count */
2537
0
      if (count++ > 20) {
2538
0
    count = 0;
2539
0
    GROW;
2540
0
                if (ctxt->instate == XML_PARSER_EOF)
2541
0
                    return(0);
2542
0
      }
2543
0
      if ((RAW >= '0') && (RAW <= '9'))
2544
0
          val = val * 10 + (CUR - '0');
2545
0
      else {
2546
0
    xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
2547
0
    val = 0;
2548
0
    break;
2549
0
      }
2550
0
      if (val > 0x110000)
2551
0
          val = 0x110000;
2552
2553
0
      NEXT;
2554
0
      count++;
2555
0
  }
2556
0
  if (RAW == ';') {
2557
      /* on purpose to avoid reentrancy problems with NEXT and SKIP */
2558
0
      ctxt->input->col++;
2559
0
      ctxt->input->cur++;
2560
0
  }
2561
0
    } else {
2562
0
        if (RAW == '&')
2563
0
            SKIP(1);
2564
0
        xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
2565
0
    }
2566
2567
    /*
2568
     * [ WFC: Legal Character ]
2569
     * Characters referred to using character references must match the
2570
     * production for Char.
2571
     */
2572
0
    if (val >= 0x110000) {
2573
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2574
0
                "xmlParseCharRef: character reference out of bounds\n",
2575
0
          val);
2576
0
    } else if (IS_CHAR(val)) {
2577
0
        return(val);
2578
0
    } else {
2579
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2580
0
                          "xmlParseCharRef: invalid xmlChar value %d\n",
2581
0
                    val);
2582
0
    }
2583
0
    return(0);
2584
0
}
2585
2586
/**
2587
 * xmlParseStringCharRef:
2588
 * @ctxt:  an XML parser context
2589
 * @str:  a pointer to an index in the string
2590
 *
2591
 * parse Reference declarations, variant parsing from a string rather
2592
 * than an an input flow.
2593
 *
2594
 * [66] CharRef ::= '&#' [0-9]+ ';' |
2595
 *                  '&#x' [0-9a-fA-F]+ ';'
2596
 *
2597
 * [ WFC: Legal Character ]
2598
 * Characters referred to using character references must match the
2599
 * production for Char.
2600
 *
2601
 * Returns the value parsed (as an int), 0 in case of error, str will be
2602
 *         updated to the current value of the index
2603
 */
2604
static int
2605
0
xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
2606
0
    const xmlChar *ptr;
2607
0
    xmlChar cur;
2608
0
    int val = 0;
2609
2610
0
    if ((str == NULL) || (*str == NULL)) return(0);
2611
0
    ptr = *str;
2612
0
    cur = *ptr;
2613
0
    if ((cur == '&') && (ptr[1] == '#') && (ptr[2] == 'x')) {
2614
0
  ptr += 3;
2615
0
  cur = *ptr;
2616
0
  while (cur != ';') { /* Non input consuming loop */
2617
0
      if ((cur >= '0') && (cur <= '9'))
2618
0
          val = val * 16 + (cur - '0');
2619
0
      else if ((cur >= 'a') && (cur <= 'f'))
2620
0
          val = val * 16 + (cur - 'a') + 10;
2621
0
      else if ((cur >= 'A') && (cur <= 'F'))
2622
0
          val = val * 16 + (cur - 'A') + 10;
2623
0
      else {
2624
0
    xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
2625
0
    val = 0;
2626
0
    break;
2627
0
      }
2628
0
      if (val > 0x110000)
2629
0
          val = 0x110000;
2630
2631
0
      ptr++;
2632
0
      cur = *ptr;
2633
0
  }
2634
0
  if (cur == ';')
2635
0
      ptr++;
2636
0
    } else if  ((cur == '&') && (ptr[1] == '#')){
2637
0
  ptr += 2;
2638
0
  cur = *ptr;
2639
0
  while (cur != ';') { /* Non input consuming loops */
2640
0
      if ((cur >= '0') && (cur <= '9'))
2641
0
          val = val * 10 + (cur - '0');
2642
0
      else {
2643
0
    xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
2644
0
    val = 0;
2645
0
    break;
2646
0
      }
2647
0
      if (val > 0x110000)
2648
0
          val = 0x110000;
2649
2650
0
      ptr++;
2651
0
      cur = *ptr;
2652
0
  }
2653
0
  if (cur == ';')
2654
0
      ptr++;
2655
0
    } else {
2656
0
  xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
2657
0
  return(0);
2658
0
    }
2659
0
    *str = ptr;
2660
2661
    /*
2662
     * [ WFC: Legal Character ]
2663
     * Characters referred to using character references must match the
2664
     * production for Char.
2665
     */
2666
0
    if (val >= 0x110000) {
2667
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2668
0
                "xmlParseStringCharRef: character reference out of bounds\n",
2669
0
                val);
2670
0
    } else if (IS_CHAR(val)) {
2671
0
        return(val);
2672
0
    } else {
2673
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2674
0
        "xmlParseStringCharRef: invalid xmlChar value %d\n",
2675
0
        val);
2676
0
    }
2677
0
    return(0);
2678
0
}
2679
2680
/**
2681
 * xmlParserHandlePEReference:
2682
 * @ctxt:  the parser context
2683
 *
2684
 * DEPRECATED: Internal function, do not use.
2685
 *
2686
 * [69] PEReference ::= '%' Name ';'
2687
 *
2688
 * [ WFC: No Recursion ]
2689
 * A parsed entity must not contain a recursive
2690
 * reference to itself, either directly or indirectly.
2691
 *
2692
 * [ WFC: Entity Declared ]
2693
 * In a document without any DTD, a document with only an internal DTD
2694
 * subset which contains no parameter entity references, or a document
2695
 * with "standalone='yes'", ...  ... The declaration of a parameter
2696
 * entity must precede any reference to it...
2697
 *
2698
 * [ VC: Entity Declared ]
2699
 * In a document with an external subset or external parameter entities
2700
 * with "standalone='no'", ...  ... The declaration of a parameter entity
2701
 * must precede any reference to it...
2702
 *
2703
 * [ WFC: In DTD ]
2704
 * Parameter-entity references may only appear in the DTD.
2705
 * NOTE: misleading but this is handled.
2706
 *
2707
 * A PEReference may have been detected in the current input stream
2708
 * the handling is done accordingly to
2709
 *      http://www.w3.org/TR/REC-xml#entproc
2710
 * i.e.
2711
 *   - Included in literal in entity values
2712
 *   - Included as Parameter Entity reference within DTDs
2713
 */
2714
void
2715
0
xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
2716
0
    switch(ctxt->instate) {
2717
0
  case XML_PARSER_CDATA_SECTION:
2718
0
      return;
2719
0
        case XML_PARSER_COMMENT:
2720
0
      return;
2721
0
  case XML_PARSER_START_TAG:
2722
0
      return;
2723
0
  case XML_PARSER_END_TAG:
2724
0
      return;
2725
0
        case XML_PARSER_EOF:
2726
0
      xmlFatalErr(ctxt, XML_ERR_PEREF_AT_EOF, NULL);
2727
0
      return;
2728
0
        case XML_PARSER_PROLOG:
2729
0
  case XML_PARSER_START:
2730
0
  case XML_PARSER_XML_DECL:
2731
0
  case XML_PARSER_MISC:
2732
0
      xmlFatalErr(ctxt, XML_ERR_PEREF_IN_PROLOG, NULL);
2733
0
      return;
2734
0
  case XML_PARSER_ENTITY_DECL:
2735
0
        case XML_PARSER_CONTENT:
2736
0
        case XML_PARSER_ATTRIBUTE_VALUE:
2737
0
        case XML_PARSER_PI:
2738
0
  case XML_PARSER_SYSTEM_LITERAL:
2739
0
  case XML_PARSER_PUBLIC_LITERAL:
2740
      /* we just ignore it there */
2741
0
      return;
2742
0
        case XML_PARSER_EPILOG:
2743
0
      xmlFatalErr(ctxt, XML_ERR_PEREF_IN_EPILOG, NULL);
2744
0
      return;
2745
0
  case XML_PARSER_ENTITY_VALUE:
2746
      /*
2747
       * NOTE: in the case of entity values, we don't do the
2748
       *       substitution here since we need the literal
2749
       *       entity value to be able to save the internal
2750
       *       subset of the document.
2751
       *       This will be handled by xmlStringDecodeEntities
2752
       */
2753
0
      return;
2754
0
        case XML_PARSER_DTD:
2755
      /*
2756
       * [WFC: Well-Formedness Constraint: PEs in Internal Subset]
2757
       * In the internal DTD subset, parameter-entity references
2758
       * can occur only where markup declarations can occur, not
2759
       * within markup declarations.
2760
       * In that case this is handled in xmlParseMarkupDecl
2761
       */
2762
0
      if ((ctxt->external == 0) && (ctxt->inputNr == 1))
2763
0
    return;
2764
0
      if (IS_BLANK_CH(NXT(1)) || NXT(1) == 0)
2765
0
    return;
2766
0
            break;
2767
0
        case XML_PARSER_IGNORE:
2768
0
            return;
2769
0
    }
2770
2771
0
    xmlParsePEReference(ctxt);
2772
0
}
2773
2774
/*
2775
 * Macro used to grow the current buffer.
2776
 * buffer##_size is expected to be a size_t
2777
 * mem_error: is expected to handle memory allocation failures
2778
 */
2779
0
#define growBuffer(buffer, n) {           \
2780
0
    xmlChar *tmp;             \
2781
0
    size_t new_size = buffer##_size * 2 + n;                            \
2782
0
    if (new_size < buffer##_size) goto mem_error;                       \
2783
0
    tmp = (xmlChar *) xmlRealloc(buffer, new_size);                     \
2784
0
    if (tmp == NULL) goto mem_error;         \
2785
0
    buffer = tmp;             \
2786
0
    buffer##_size = new_size;                                           \
2787
0
}
2788
2789
/**
2790
 * xmlStringDecodeEntitiesInt:
2791
 * @ctxt:  the parser context
2792
 * @str:  the input string
2793
 * @len: the string length
2794
 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
2795
 * @end:  an end marker xmlChar, 0 if none
2796
 * @end2:  an end marker xmlChar, 0 if none
2797
 * @end3:  an end marker xmlChar, 0 if none
2798
 * @check:  whether to perform entity checks
2799
 */
2800
static xmlChar *
2801
xmlStringDecodeEntitiesInt(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
2802
               int what, xmlChar end, xmlChar  end2, xmlChar end3,
2803
0
                           int check) {
2804
0
    xmlChar *buffer = NULL;
2805
0
    size_t buffer_size = 0;
2806
0
    size_t nbchars = 0;
2807
2808
0
    xmlChar *current = NULL;
2809
0
    xmlChar *rep = NULL;
2810
0
    const xmlChar *last;
2811
0
    xmlEntityPtr ent;
2812
0
    int c,l;
2813
2814
0
    if (str == NULL)
2815
0
        return(NULL);
2816
0
    last = str + len;
2817
2818
0
    if (((ctxt->depth > 40) &&
2819
0
         ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
2820
0
  (ctxt->depth > 100)) {
2821
0
  xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_LOOP,
2822
0
                       "Maximum entity nesting depth exceeded");
2823
0
  return(NULL);
2824
0
    }
2825
2826
    /*
2827
     * allocate a translation buffer.
2828
     */
2829
0
    buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
2830
0
    buffer = (xmlChar *) xmlMallocAtomic(buffer_size);
2831
0
    if (buffer == NULL) goto mem_error;
2832
2833
    /*
2834
     * OK loop until we reach one of the ending char or a size limit.
2835
     * we are operating on already parsed values.
2836
     */
2837
0
    if (str < last)
2838
0
  c = CUR_SCHAR(str, l);
2839
0
    else
2840
0
        c = 0;
2841
0
    while ((c != 0) && (c != end) && /* non input consuming loop */
2842
0
           (c != end2) && (c != end3) &&
2843
0
           (ctxt->instate != XML_PARSER_EOF)) {
2844
2845
0
  if (c == 0) break;
2846
0
        if ((c == '&') && (str[1] == '#')) {
2847
0
      int val = xmlParseStringCharRef(ctxt, &str);
2848
0
      if (val == 0)
2849
0
                goto int_error;
2850
0
      COPY_BUF(buffer, nbchars, val);
2851
0
      if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2852
0
          growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2853
0
      }
2854
0
  } else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) {
2855
0
      if (xmlParserDebugEntities)
2856
0
    xmlGenericError(xmlGenericErrorContext,
2857
0
      "String decoding Entity Reference: %.30s\n",
2858
0
      str);
2859
0
      ent = xmlParseStringEntityRef(ctxt, &str);
2860
0
      if ((ent != NULL) &&
2861
0
    (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
2862
0
    if (ent->content != NULL) {
2863
0
        COPY_BUF(buffer, nbchars, ent->content[0]);
2864
0
        if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2865
0
      growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2866
0
        }
2867
0
    } else {
2868
0
        xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
2869
0
          "predefined entity has no content\n");
2870
0
                    goto int_error;
2871
0
    }
2872
0
      } else if ((ent != NULL) && (ent->content != NULL)) {
2873
0
          if ((check) && (xmlParserEntityCheck(ctxt, ent->length)))
2874
0
                    goto int_error;
2875
2876
0
                if (ent->flags & XML_ENT_EXPANDING) {
2877
0
              xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
2878
0
                    xmlHaltParser(ctxt);
2879
0
                    ent->content[0] = 0;
2880
0
                    goto int_error;
2881
0
                }
2882
2883
0
                ent->flags |= XML_ENT_EXPANDING;
2884
0
    ctxt->depth++;
2885
0
    rep = xmlStringDecodeEntitiesInt(ctxt, ent->content,
2886
0
                        ent->length, what, 0, 0, 0, check);
2887
0
    ctxt->depth--;
2888
0
                ent->flags &= ~XML_ENT_EXPANDING;
2889
2890
0
    if (rep == NULL) {
2891
0
                    ent->content[0] = 0;
2892
0
                    goto int_error;
2893
0
                }
2894
2895
0
                current = rep;
2896
0
                while (*current != 0) { /* non input consuming loop */
2897
0
                    buffer[nbchars++] = *current++;
2898
0
                    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2899
0
                        growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2900
0
                    }
2901
0
                }
2902
0
                xmlFree(rep);
2903
0
                rep = NULL;
2904
0
      } else if (ent != NULL) {
2905
0
    int i = xmlStrlen(ent->name);
2906
0
    const xmlChar *cur = ent->name;
2907
2908
0
    buffer[nbchars++] = '&';
2909
0
    if (nbchars + i + XML_PARSER_BUFFER_SIZE > buffer_size) {
2910
0
        growBuffer(buffer, i + XML_PARSER_BUFFER_SIZE);
2911
0
    }
2912
0
    for (;i > 0;i--)
2913
0
        buffer[nbchars++] = *cur++;
2914
0
    buffer[nbchars++] = ';';
2915
0
      }
2916
0
  } else if (c == '%' && (what & XML_SUBSTITUTE_PEREF)) {
2917
0
      if (xmlParserDebugEntities)
2918
0
    xmlGenericError(xmlGenericErrorContext,
2919
0
      "String decoding PE Reference: %.30s\n", str);
2920
0
      ent = xmlParseStringPEReference(ctxt, &str);
2921
0
      if (ent != NULL) {
2922
0
                if (ent->content == NULL) {
2923
        /*
2924
         * Note: external parsed entities will not be loaded,
2925
         * it is not required for a non-validating parser to
2926
         * complete external PEReferences coming from the
2927
         * internal subset
2928
         */
2929
0
        if (((ctxt->options & XML_PARSE_NOENT) != 0) ||
2930
0
      ((ctxt->options & XML_PARSE_DTDVALID) != 0) ||
2931
0
      (ctxt->validate != 0)) {
2932
0
      xmlLoadEntityContent(ctxt, ent);
2933
0
        } else {
2934
0
      xmlWarningMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
2935
0
      "not validating will not read content for PE entity %s\n",
2936
0
                          ent->name, NULL);
2937
0
        }
2938
0
    }
2939
2940
0
          if ((check) && (xmlParserEntityCheck(ctxt, ent->length)))
2941
0
                    goto int_error;
2942
2943
0
                if (ent->flags & XML_ENT_EXPANDING) {
2944
0
              xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
2945
0
                    xmlHaltParser(ctxt);
2946
0
                    if (ent->content != NULL)
2947
0
                        ent->content[0] = 0;
2948
0
                    goto int_error;
2949
0
                }
2950
2951
0
                ent->flags |= XML_ENT_EXPANDING;
2952
0
    ctxt->depth++;
2953
0
    rep = xmlStringDecodeEntitiesInt(ctxt, ent->content,
2954
0
                        ent->length, what, 0, 0, 0, check);
2955
0
    ctxt->depth--;
2956
0
                ent->flags &= ~XML_ENT_EXPANDING;
2957
2958
0
    if (rep == NULL) {
2959
0
                    if (ent->content != NULL)
2960
0
                        ent->content[0] = 0;
2961
0
                    goto int_error;
2962
0
                }
2963
0
                current = rep;
2964
0
                while (*current != 0) { /* non input consuming loop */
2965
0
                    buffer[nbchars++] = *current++;
2966
0
                    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2967
0
                        growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2968
0
                    }
2969
0
                }
2970
0
                xmlFree(rep);
2971
0
                rep = NULL;
2972
0
      }
2973
0
  } else {
2974
0
      COPY_BUF(buffer, nbchars, c);
2975
0
      str += l;
2976
0
      if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2977
0
          growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2978
0
      }
2979
0
  }
2980
0
  if (str < last)
2981
0
      c = CUR_SCHAR(str, l);
2982
0
  else
2983
0
      c = 0;
2984
0
    }
2985
0
    buffer[nbchars] = 0;
2986
0
    return(buffer);
2987
2988
0
mem_error:
2989
0
    xmlErrMemory(ctxt, NULL);
2990
0
int_error:
2991
0
    if (rep != NULL)
2992
0
        xmlFree(rep);
2993
0
    if (buffer != NULL)
2994
0
        xmlFree(buffer);
2995
0
    return(NULL);
2996
0
}
2997
2998
/**
2999
 * xmlStringLenDecodeEntities:
3000
 * @ctxt:  the parser context
3001
 * @str:  the input string
3002
 * @len: the string length
3003
 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
3004
 * @end:  an end marker xmlChar, 0 if none
3005
 * @end2:  an end marker xmlChar, 0 if none
3006
 * @end3:  an end marker xmlChar, 0 if none
3007
 *
3008
 * DEPRECATED: Internal function, don't use.
3009
 *
3010
 * Takes a entity string content and process to do the adequate substitutions.
3011
 *
3012
 * [67] Reference ::= EntityRef | CharRef
3013
 *
3014
 * [69] PEReference ::= '%' Name ';'
3015
 *
3016
 * Returns A newly allocated string with the substitution done. The caller
3017
 *      must deallocate it !
3018
 */
3019
xmlChar *
3020
xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
3021
                           int what, xmlChar end, xmlChar  end2,
3022
0
                           xmlChar end3) {
3023
0
    if ((ctxt == NULL) || (str == NULL) || (len < 0))
3024
0
        return(NULL);
3025
0
    return(xmlStringDecodeEntitiesInt(ctxt, str, len, what,
3026
0
                                      end, end2, end3, 0));
3027
0
}
3028
3029
/**
3030
 * xmlStringDecodeEntities:
3031
 * @ctxt:  the parser context
3032
 * @str:  the input string
3033
 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
3034
 * @end:  an end marker xmlChar, 0 if none
3035
 * @end2:  an end marker xmlChar, 0 if none
3036
 * @end3:  an end marker xmlChar, 0 if none
3037
 *
3038
 * DEPRECATED: Internal function, don't use.
3039
 *
3040
 * Takes a entity string content and process to do the adequate substitutions.
3041
 *
3042
 * [67] Reference ::= EntityRef | CharRef
3043
 *
3044
 * [69] PEReference ::= '%' Name ';'
3045
 *
3046
 * Returns A newly allocated string with the substitution done. The caller
3047
 *      must deallocate it !
3048
 */
3049
xmlChar *
3050
xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what,
3051
0
            xmlChar end, xmlChar  end2, xmlChar end3) {
3052
0
    if ((ctxt == NULL) || (str == NULL)) return(NULL);
3053
0
    return(xmlStringDecodeEntitiesInt(ctxt, str, xmlStrlen(str), what,
3054
0
                                      end, end2, end3, 0));
3055
0
}
3056
3057
/************************************************************************
3058
 *                  *
3059
 *    Commodity functions, cleanup needed ?     *
3060
 *                  *
3061
 ************************************************************************/
3062
3063
/**
3064
 * areBlanks:
3065
 * @ctxt:  an XML parser context
3066
 * @str:  a xmlChar *
3067
 * @len:  the size of @str
3068
 * @blank_chars: we know the chars are blanks
3069
 *
3070
 * Is this a sequence of blank chars that one can ignore ?
3071
 *
3072
 * Returns 1 if ignorable 0 otherwise.
3073
 */
3074
3075
static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
3076
0
                     int blank_chars) {
3077
0
    int i, ret;
3078
0
    xmlNodePtr lastChild;
3079
3080
    /*
3081
     * Don't spend time trying to differentiate them, the same callback is
3082
     * used !
3083
     */
3084
0
    if (ctxt->sax->ignorableWhitespace == ctxt->sax->characters)
3085
0
  return(0);
3086
3087
    /*
3088
     * Check for xml:space value.
3089
     */
3090
0
    if ((ctxt->space == NULL) || (*(ctxt->space) == 1) ||
3091
0
        (*(ctxt->space) == -2))
3092
0
  return(0);
3093
3094
    /*
3095
     * Check that the string is made of blanks
3096
     */
3097
0
    if (blank_chars == 0) {
3098
0
  for (i = 0;i < len;i++)
3099
0
      if (!(IS_BLANK_CH(str[i]))) return(0);
3100
0
    }
3101
3102
    /*
3103
     * Look if the element is mixed content in the DTD if available
3104
     */
3105
0
    if (ctxt->node == NULL) return(0);
3106
0
    if (ctxt->myDoc != NULL) {
3107
0
  ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name);
3108
0
        if (ret == 0) return(1);
3109
0
        if (ret == 1) return(0);
3110
0
    }
3111
3112
    /*
3113
     * Otherwise, heuristic :-\
3114
     */
3115
0
    if ((RAW != '<') && (RAW != 0xD)) return(0);
3116
0
    if ((ctxt->node->children == NULL) &&
3117
0
  (RAW == '<') && (NXT(1) == '/')) return(0);
3118
3119
0
    lastChild = xmlGetLastChild(ctxt->node);
3120
0
    if (lastChild == NULL) {
3121
0
        if ((ctxt->node->type != XML_ELEMENT_NODE) &&
3122
0
            (ctxt->node->content != NULL)) return(0);
3123
0
    } else if (xmlNodeIsText(lastChild))
3124
0
        return(0);
3125
0
    else if ((ctxt->node->children != NULL) &&
3126
0
             (xmlNodeIsText(ctxt->node->children)))
3127
0
        return(0);
3128
0
    return(1);
3129
0
}
3130
3131
/************************************************************************
3132
 *                  *
3133
 *    Extra stuff for namespace support     *
3134
 *  Relates to http://www.w3.org/TR/WD-xml-names      *
3135
 *                  *
3136
 ************************************************************************/
3137
3138
/**
3139
 * xmlSplitQName:
3140
 * @ctxt:  an XML parser context
3141
 * @name:  an XML parser context
3142
 * @prefix:  a xmlChar **
3143
 *
3144
 * parse an UTF8 encoded XML qualified name string
3145
 *
3146
 * [NS 5] QName ::= (Prefix ':')? LocalPart
3147
 *
3148
 * [NS 6] Prefix ::= NCName
3149
 *
3150
 * [NS 7] LocalPart ::= NCName
3151
 *
3152
 * Returns the local part, and prefix is updated
3153
 *   to get the Prefix if any.
3154
 */
3155
3156
xmlChar *
3157
0
xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
3158
0
    xmlChar buf[XML_MAX_NAMELEN + 5];
3159
0
    xmlChar *buffer = NULL;
3160
0
    int len = 0;
3161
0
    int max = XML_MAX_NAMELEN;
3162
0
    xmlChar *ret = NULL;
3163
0
    const xmlChar *cur = name;
3164
0
    int c;
3165
3166
0
    if (prefix == NULL) return(NULL);
3167
0
    *prefix = NULL;
3168
3169
0
    if (cur == NULL) return(NULL);
3170
3171
#ifndef XML_XML_NAMESPACE
3172
    /* xml: prefix is not really a namespace */
3173
    if ((cur[0] == 'x') && (cur[1] == 'm') &&
3174
        (cur[2] == 'l') && (cur[3] == ':'))
3175
  return(xmlStrdup(name));
3176
#endif
3177
3178
    /* nasty but well=formed */
3179
0
    if (cur[0] == ':')
3180
0
  return(xmlStrdup(name));
3181
3182
0
    c = *cur++;
3183
0
    while ((c != 0) && (c != ':') && (len < max)) { /* tested bigname.xml */
3184
0
  buf[len++] = c;
3185
0
  c = *cur++;
3186
0
    }
3187
0
    if (len >= max) {
3188
  /*
3189
   * Okay someone managed to make a huge name, so he's ready to pay
3190
   * for the processing speed.
3191
   */
3192
0
  max = len * 2;
3193
3194
0
  buffer = (xmlChar *) xmlMallocAtomic(max);
3195
0
  if (buffer == NULL) {
3196
0
      xmlErrMemory(ctxt, NULL);
3197
0
      return(NULL);
3198
0
  }
3199
0
  memcpy(buffer, buf, len);
3200
0
  while ((c != 0) && (c != ':')) { /* tested bigname.xml */
3201
0
      if (len + 10 > max) {
3202
0
          xmlChar *tmp;
3203
3204
0
    max *= 2;
3205
0
    tmp = (xmlChar *) xmlRealloc(buffer, max);
3206
0
    if (tmp == NULL) {
3207
0
        xmlFree(buffer);
3208
0
        xmlErrMemory(ctxt, NULL);
3209
0
        return(NULL);
3210
0
    }
3211
0
    buffer = tmp;
3212
0
      }
3213
0
      buffer[len++] = c;
3214
0
      c = *cur++;
3215
0
  }
3216
0
  buffer[len] = 0;
3217
0
    }
3218
3219
0
    if ((c == ':') && (*cur == 0)) {
3220
0
        if (buffer != NULL)
3221
0
      xmlFree(buffer);
3222
0
  *prefix = NULL;
3223
0
  return(xmlStrdup(name));
3224
0
    }
3225
3226
0
    if (buffer == NULL)
3227
0
  ret = xmlStrndup(buf, len);
3228
0
    else {
3229
0
  ret = buffer;
3230
0
  buffer = NULL;
3231
0
  max = XML_MAX_NAMELEN;
3232
0
    }
3233
3234
3235
0
    if (c == ':') {
3236
0
  c = *cur;
3237
0
        *prefix = ret;
3238
0
  if (c == 0) {
3239
0
      return(xmlStrndup(BAD_CAST "", 0));
3240
0
  }
3241
0
  len = 0;
3242
3243
  /*
3244
   * Check that the first character is proper to start
3245
   * a new name
3246
   */
3247
0
  if (!(((c >= 0x61) && (c <= 0x7A)) ||
3248
0
        ((c >= 0x41) && (c <= 0x5A)) ||
3249
0
        (c == '_') || (c == ':'))) {
3250
0
      int l;
3251
0
      int first = CUR_SCHAR(cur, l);
3252
3253
0
      if (!IS_LETTER(first) && (first != '_')) {
3254
0
    xmlFatalErrMsgStr(ctxt, XML_NS_ERR_QNAME,
3255
0
          "Name %s is not XML Namespace compliant\n",
3256
0
          name);
3257
0
      }
3258
0
  }
3259
0
  cur++;
3260
3261
0
  while ((c != 0) && (len < max)) { /* tested bigname2.xml */
3262
0
      buf[len++] = c;
3263
0
      c = *cur++;
3264
0
  }
3265
0
  if (len >= max) {
3266
      /*
3267
       * Okay someone managed to make a huge name, so he's ready to pay
3268
       * for the processing speed.
3269
       */
3270
0
      max = len * 2;
3271
3272
0
      buffer = (xmlChar *) xmlMallocAtomic(max);
3273
0
      if (buffer == NULL) {
3274
0
          xmlErrMemory(ctxt, NULL);
3275
0
    return(NULL);
3276
0
      }
3277
0
      memcpy(buffer, buf, len);
3278
0
      while (c != 0) { /* tested bigname2.xml */
3279
0
    if (len + 10 > max) {
3280
0
        xmlChar *tmp;
3281
3282
0
        max *= 2;
3283
0
        tmp = (xmlChar *) xmlRealloc(buffer, max);
3284
0
        if (tmp == NULL) {
3285
0
      xmlErrMemory(ctxt, NULL);
3286
0
      xmlFree(buffer);
3287
0
      return(NULL);
3288
0
        }
3289
0
        buffer = tmp;
3290
0
    }
3291
0
    buffer[len++] = c;
3292
0
    c = *cur++;
3293
0
      }
3294
0
      buffer[len] = 0;
3295
0
  }
3296
3297
0
  if (buffer == NULL)
3298
0
      ret = xmlStrndup(buf, len);
3299
0
  else {
3300
0
      ret = buffer;
3301
0
  }
3302
0
    }
3303
3304
0
    return(ret);
3305
0
}
3306
3307
/************************************************************************
3308
 *                  *
3309
 *      The parser itself       *
3310
 *  Relates to http://www.w3.org/TR/REC-xml       *
3311
 *                  *
3312
 ************************************************************************/
3313
3314
/************************************************************************
3315
 *                  *
3316
 *  Routines to parse Name, NCName and NmToken      *
3317
 *                  *
3318
 ************************************************************************/
3319
3320
/*
3321
 * The two following functions are related to the change of accepted
3322
 * characters for Name and NmToken in the Revision 5 of XML-1.0
3323
 * They correspond to the modified production [4] and the new production [4a]
3324
 * changes in that revision. Also note that the macros used for the
3325
 * productions Letter, Digit, CombiningChar and Extender are not needed
3326
 * anymore.
3327
 * We still keep compatibility to pre-revision5 parsing semantic if the
3328
 * new XML_PARSE_OLD10 option is given to the parser.
3329
 */
3330
static int
3331
0
xmlIsNameStartChar(xmlParserCtxtPtr ctxt, int c) {
3332
0
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3333
        /*
3334
   * Use the new checks of production [4] [4a] amd [5] of the
3335
   * Update 5 of XML-1.0
3336
   */
3337
0
  if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3338
0
      (((c >= 'a') && (c <= 'z')) ||
3339
0
       ((c >= 'A') && (c <= 'Z')) ||
3340
0
       (c == '_') || (c == ':') ||
3341
0
       ((c >= 0xC0) && (c <= 0xD6)) ||
3342
0
       ((c >= 0xD8) && (c <= 0xF6)) ||
3343
0
       ((c >= 0xF8) && (c <= 0x2FF)) ||
3344
0
       ((c >= 0x370) && (c <= 0x37D)) ||
3345
0
       ((c >= 0x37F) && (c <= 0x1FFF)) ||
3346
0
       ((c >= 0x200C) && (c <= 0x200D)) ||
3347
0
       ((c >= 0x2070) && (c <= 0x218F)) ||
3348
0
       ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3349
0
       ((c >= 0x3001) && (c <= 0xD7FF)) ||
3350
0
       ((c >= 0xF900) && (c <= 0xFDCF)) ||
3351
0
       ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3352
0
       ((c >= 0x10000) && (c <= 0xEFFFF))))
3353
0
      return(1);
3354
0
    } else {
3355
0
        if (IS_LETTER(c) || (c == '_') || (c == ':'))
3356
0
      return(1);
3357
0
    }
3358
0
    return(0);
3359
0
}
3360
3361
static int
3362
0
xmlIsNameChar(xmlParserCtxtPtr ctxt, int c) {
3363
0
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3364
        /*
3365
   * Use the new checks of production [4] [4a] amd [5] of the
3366
   * Update 5 of XML-1.0
3367
   */
3368
0
  if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3369
0
      (((c >= 'a') && (c <= 'z')) ||
3370
0
       ((c >= 'A') && (c <= 'Z')) ||
3371
0
       ((c >= '0') && (c <= '9')) || /* !start */
3372
0
       (c == '_') || (c == ':') ||
3373
0
       (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3374
0
       ((c >= 0xC0) && (c <= 0xD6)) ||
3375
0
       ((c >= 0xD8) && (c <= 0xF6)) ||
3376
0
       ((c >= 0xF8) && (c <= 0x2FF)) ||
3377
0
       ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3378
0
       ((c >= 0x370) && (c <= 0x37D)) ||
3379
0
       ((c >= 0x37F) && (c <= 0x1FFF)) ||
3380
0
       ((c >= 0x200C) && (c <= 0x200D)) ||
3381
0
       ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3382
0
       ((c >= 0x2070) && (c <= 0x218F)) ||
3383
0
       ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3384
0
       ((c >= 0x3001) && (c <= 0xD7FF)) ||
3385
0
       ((c >= 0xF900) && (c <= 0xFDCF)) ||
3386
0
       ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3387
0
       ((c >= 0x10000) && (c <= 0xEFFFF))))
3388
0
       return(1);
3389
0
    } else {
3390
0
        if ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3391
0
            (c == '.') || (c == '-') ||
3392
0
      (c == '_') || (c == ':') ||
3393
0
      (IS_COMBINING(c)) ||
3394
0
      (IS_EXTENDER(c)))
3395
0
      return(1);
3396
0
    }
3397
0
    return(0);
3398
0
}
3399
3400
static xmlChar * xmlParseAttValueInternal(xmlParserCtxtPtr ctxt,
3401
                                          int *len, int *alloc, int normalize);
3402
3403
static const xmlChar *
3404
0
xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
3405
0
    int len = 0, l;
3406
0
    int c;
3407
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3408
0
                    XML_MAX_TEXT_LENGTH :
3409
0
                    XML_MAX_NAME_LENGTH;
3410
3411
    /*
3412
     * Handler for more complex cases
3413
     */
3414
0
    c = CUR_CHAR(l);
3415
0
    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3416
        /*
3417
   * Use the new checks of production [4] [4a] amd [5] of the
3418
   * Update 5 of XML-1.0
3419
   */
3420
0
  if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3421
0
      (!(((c >= 'a') && (c <= 'z')) ||
3422
0
         ((c >= 'A') && (c <= 'Z')) ||
3423
0
         (c == '_') || (c == ':') ||
3424
0
         ((c >= 0xC0) && (c <= 0xD6)) ||
3425
0
         ((c >= 0xD8) && (c <= 0xF6)) ||
3426
0
         ((c >= 0xF8) && (c <= 0x2FF)) ||
3427
0
         ((c >= 0x370) && (c <= 0x37D)) ||
3428
0
         ((c >= 0x37F) && (c <= 0x1FFF)) ||
3429
0
         ((c >= 0x200C) && (c <= 0x200D)) ||
3430
0
         ((c >= 0x2070) && (c <= 0x218F)) ||
3431
0
         ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3432
0
         ((c >= 0x3001) && (c <= 0xD7FF)) ||
3433
0
         ((c >= 0xF900) && (c <= 0xFDCF)) ||
3434
0
         ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3435
0
         ((c >= 0x10000) && (c <= 0xEFFFF))))) {
3436
0
      return(NULL);
3437
0
  }
3438
0
  len += l;
3439
0
  NEXTL(l);
3440
0
  c = CUR_CHAR(l);
3441
0
  while ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3442
0
         (((c >= 'a') && (c <= 'z')) ||
3443
0
          ((c >= 'A') && (c <= 'Z')) ||
3444
0
          ((c >= '0') && (c <= '9')) || /* !start */
3445
0
          (c == '_') || (c == ':') ||
3446
0
          (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3447
0
          ((c >= 0xC0) && (c <= 0xD6)) ||
3448
0
          ((c >= 0xD8) && (c <= 0xF6)) ||
3449
0
          ((c >= 0xF8) && (c <= 0x2FF)) ||
3450
0
          ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3451
0
          ((c >= 0x370) && (c <= 0x37D)) ||
3452
0
          ((c >= 0x37F) && (c <= 0x1FFF)) ||
3453
0
          ((c >= 0x200C) && (c <= 0x200D)) ||
3454
0
          ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3455
0
          ((c >= 0x2070) && (c <= 0x218F)) ||
3456
0
          ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3457
0
          ((c >= 0x3001) && (c <= 0xD7FF)) ||
3458
0
          ((c >= 0xF900) && (c <= 0xFDCF)) ||
3459
0
          ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3460
0
          ((c >= 0x10000) && (c <= 0xEFFFF))
3461
0
    )) {
3462
0
            if (len <= INT_MAX - l)
3463
0
          len += l;
3464
0
      NEXTL(l);
3465
0
      c = CUR_CHAR(l);
3466
0
  }
3467
0
    } else {
3468
0
  if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3469
0
      (!IS_LETTER(c) && (c != '_') &&
3470
0
       (c != ':'))) {
3471
0
      return(NULL);
3472
0
  }
3473
0
  len += l;
3474
0
  NEXTL(l);
3475
0
  c = CUR_CHAR(l);
3476
3477
0
  while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
3478
0
         ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3479
0
    (c == '.') || (c == '-') ||
3480
0
    (c == '_') || (c == ':') ||
3481
0
    (IS_COMBINING(c)) ||
3482
0
    (IS_EXTENDER(c)))) {
3483
0
            if (len <= INT_MAX - l)
3484
0
          len += l;
3485
0
      NEXTL(l);
3486
0
      c = CUR_CHAR(l);
3487
0
  }
3488
0
    }
3489
0
    if (ctxt->instate == XML_PARSER_EOF)
3490
0
        return(NULL);
3491
0
    if (len > maxLength) {
3492
0
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
3493
0
        return(NULL);
3494
0
    }
3495
0
    if (ctxt->input->cur - ctxt->input->base < len) {
3496
        /*
3497
         * There were a couple of bugs where PERefs lead to to a change
3498
         * of the buffer. Check the buffer size to avoid passing an invalid
3499
         * pointer to xmlDictLookup.
3500
         */
3501
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
3502
0
                    "unexpected change of input buffer");
3503
0
        return (NULL);
3504
0
    }
3505
0
    if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r'))
3506
0
        return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len));
3507
0
    return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
3508
0
}
3509
3510
/**
3511
 * xmlParseName:
3512
 * @ctxt:  an XML parser context
3513
 *
3514
 * DEPRECATED: Internal function, don't use.
3515
 *
3516
 * parse an XML name.
3517
 *
3518
 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3519
 *                  CombiningChar | Extender
3520
 *
3521
 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3522
 *
3523
 * [6] Names ::= Name (#x20 Name)*
3524
 *
3525
 * Returns the Name parsed or NULL
3526
 */
3527
3528
const xmlChar *
3529
0
xmlParseName(xmlParserCtxtPtr ctxt) {
3530
0
    const xmlChar *in;
3531
0
    const xmlChar *ret;
3532
0
    size_t count = 0;
3533
0
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3534
0
                       XML_MAX_TEXT_LENGTH :
3535
0
                       XML_MAX_NAME_LENGTH;
3536
3537
0
    GROW;
3538
0
    if (ctxt->instate == XML_PARSER_EOF)
3539
0
        return(NULL);
3540
3541
    /*
3542
     * Accelerator for simple ASCII names
3543
     */
3544
0
    in = ctxt->input->cur;
3545
0
    if (((*in >= 0x61) && (*in <= 0x7A)) ||
3546
0
  ((*in >= 0x41) && (*in <= 0x5A)) ||
3547
0
  (*in == '_') || (*in == ':')) {
3548
0
  in++;
3549
0
  while (((*in >= 0x61) && (*in <= 0x7A)) ||
3550
0
         ((*in >= 0x41) && (*in <= 0x5A)) ||
3551
0
         ((*in >= 0x30) && (*in <= 0x39)) ||
3552
0
         (*in == '_') || (*in == '-') ||
3553
0
         (*in == ':') || (*in == '.'))
3554
0
      in++;
3555
0
  if ((*in > 0) && (*in < 0x80)) {
3556
0
      count = in - ctxt->input->cur;
3557
0
            if (count > maxLength) {
3558
0
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
3559
0
                return(NULL);
3560
0
            }
3561
0
      ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
3562
0
      ctxt->input->cur = in;
3563
0
      ctxt->input->col += count;
3564
0
      if (ret == NULL)
3565
0
          xmlErrMemory(ctxt, NULL);
3566
0
      return(ret);
3567
0
  }
3568
0
    }
3569
    /* accelerator for special cases */
3570
0
    return(xmlParseNameComplex(ctxt));
3571
0
}
3572
3573
static xmlHashedString
3574
0
xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
3575
0
    xmlHashedString ret;
3576
0
    int len = 0, l;
3577
0
    int c;
3578
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3579
0
                    XML_MAX_TEXT_LENGTH :
3580
0
                    XML_MAX_NAME_LENGTH;
3581
0
    size_t startPosition = 0;
3582
3583
0
    ret.name = NULL;
3584
0
    ret.hashValue = 0;
3585
3586
    /*
3587
     * Handler for more complex cases
3588
     */
3589
0
    startPosition = CUR_PTR - BASE_PTR;
3590
0
    c = CUR_CHAR(l);
3591
0
    if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3592
0
  (!xmlIsNameStartChar(ctxt, c) || (c == ':'))) {
3593
0
  return(ret);
3594
0
    }
3595
3596
0
    while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
3597
0
     (xmlIsNameChar(ctxt, c) && (c != ':'))) {
3598
0
        if (len <= INT_MAX - l)
3599
0
      len += l;
3600
0
  NEXTL(l);
3601
0
  c = CUR_CHAR(l);
3602
0
    }
3603
0
    if (ctxt->instate == XML_PARSER_EOF)
3604
0
        return(ret);
3605
0
    if (len > maxLength) {
3606
0
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3607
0
        return(ret);
3608
0
    }
3609
0
    ret = xmlDictLookupHashed(ctxt->dict, (BASE_PTR + startPosition), len);
3610
0
    return(ret);
3611
0
}
3612
3613
/**
3614
 * xmlParseNCName:
3615
 * @ctxt:  an XML parser context
3616
 * @len:  length of the string parsed
3617
 *
3618
 * parse an XML name.
3619
 *
3620
 * [4NS] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
3621
 *                      CombiningChar | Extender
3622
 *
3623
 * [5NS] NCName ::= (Letter | '_') (NCNameChar)*
3624
 *
3625
 * Returns the Name parsed or NULL
3626
 */
3627
3628
static xmlHashedString
3629
0
xmlParseNCName(xmlParserCtxtPtr ctxt) {
3630
0
    const xmlChar *in, *e;
3631
0
    xmlHashedString ret;
3632
0
    size_t count = 0;
3633
0
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3634
0
                       XML_MAX_TEXT_LENGTH :
3635
0
                       XML_MAX_NAME_LENGTH;
3636
3637
0
    ret.name = NULL;
3638
3639
    /*
3640
     * Accelerator for simple ASCII names
3641
     */
3642
0
    in = ctxt->input->cur;
3643
0
    e = ctxt->input->end;
3644
0
    if ((((*in >= 0x61) && (*in <= 0x7A)) ||
3645
0
   ((*in >= 0x41) && (*in <= 0x5A)) ||
3646
0
   (*in == '_')) && (in < e)) {
3647
0
  in++;
3648
0
  while ((((*in >= 0x61) && (*in <= 0x7A)) ||
3649
0
          ((*in >= 0x41) && (*in <= 0x5A)) ||
3650
0
          ((*in >= 0x30) && (*in <= 0x39)) ||
3651
0
          (*in == '_') || (*in == '-') ||
3652
0
          (*in == '.')) && (in < e))
3653
0
      in++;
3654
0
  if (in >= e)
3655
0
      goto complex;
3656
0
  if ((*in > 0) && (*in < 0x80)) {
3657
0
      count = in - ctxt->input->cur;
3658
0
            if (count > maxLength) {
3659
0
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3660
0
                return(ret);
3661
0
            }
3662
0
      ret = xmlDictLookupHashed(ctxt->dict, ctxt->input->cur, count);
3663
0
      ctxt->input->cur = in;
3664
0
      ctxt->input->col += count;
3665
0
      if (ret.name == NULL) {
3666
0
          xmlErrMemory(ctxt, NULL);
3667
0
      }
3668
0
      return(ret);
3669
0
  }
3670
0
    }
3671
0
complex:
3672
0
    return(xmlParseNCNameComplex(ctxt));
3673
0
}
3674
3675
/**
3676
 * xmlParseNameAndCompare:
3677
 * @ctxt:  an XML parser context
3678
 *
3679
 * parse an XML name and compares for match
3680
 * (specialized for endtag parsing)
3681
 *
3682
 * Returns NULL for an illegal name, (xmlChar*) 1 for success
3683
 * and the name for mismatch
3684
 */
3685
3686
static const xmlChar *
3687
0
xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) {
3688
0
    register const xmlChar *cmp = other;
3689
0
    register const xmlChar *in;
3690
0
    const xmlChar *ret;
3691
3692
0
    GROW;
3693
0
    if (ctxt->instate == XML_PARSER_EOF)
3694
0
        return(NULL);
3695
3696
0
    in = ctxt->input->cur;
3697
0
    while (*in != 0 && *in == *cmp) {
3698
0
  ++in;
3699
0
  ++cmp;
3700
0
    }
3701
0
    if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
3702
  /* success */
3703
0
  ctxt->input->col += in - ctxt->input->cur;
3704
0
  ctxt->input->cur = in;
3705
0
  return (const xmlChar*) 1;
3706
0
    }
3707
    /* failure (or end of input buffer), check with full function */
3708
0
    ret = xmlParseName (ctxt);
3709
    /* strings coming from the dictionary direct compare possible */
3710
0
    if (ret == other) {
3711
0
  return (const xmlChar*) 1;
3712
0
    }
3713
0
    return ret;
3714
0
}
3715
3716
/**
3717
 * xmlParseStringName:
3718
 * @ctxt:  an XML parser context
3719
 * @str:  a pointer to the string pointer (IN/OUT)
3720
 *
3721
 * parse an XML name.
3722
 *
3723
 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3724
 *                  CombiningChar | Extender
3725
 *
3726
 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3727
 *
3728
 * [6] Names ::= Name (#x20 Name)*
3729
 *
3730
 * Returns the Name parsed or NULL. The @str pointer
3731
 * is updated to the current location in the string.
3732
 */
3733
3734
static xmlChar *
3735
0
xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
3736
0
    xmlChar buf[XML_MAX_NAMELEN + 5];
3737
0
    const xmlChar *cur = *str;
3738
0
    int len = 0, l;
3739
0
    int c;
3740
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3741
0
                    XML_MAX_TEXT_LENGTH :
3742
0
                    XML_MAX_NAME_LENGTH;
3743
3744
0
    c = CUR_SCHAR(cur, l);
3745
0
    if (!xmlIsNameStartChar(ctxt, c)) {
3746
0
  return(NULL);
3747
0
    }
3748
3749
0
    COPY_BUF(buf, len, c);
3750
0
    cur += l;
3751
0
    c = CUR_SCHAR(cur, l);
3752
0
    while (xmlIsNameChar(ctxt, c)) {
3753
0
  COPY_BUF(buf, len, c);
3754
0
  cur += l;
3755
0
  c = CUR_SCHAR(cur, l);
3756
0
  if (len >= XML_MAX_NAMELEN) { /* test bigentname.xml */
3757
      /*
3758
       * Okay someone managed to make a huge name, so he's ready to pay
3759
       * for the processing speed.
3760
       */
3761
0
      xmlChar *buffer;
3762
0
      int max = len * 2;
3763
3764
0
      buffer = (xmlChar *) xmlMallocAtomic(max);
3765
0
      if (buffer == NULL) {
3766
0
          xmlErrMemory(ctxt, NULL);
3767
0
    return(NULL);
3768
0
      }
3769
0
      memcpy(buffer, buf, len);
3770
0
      while (xmlIsNameChar(ctxt, c)) {
3771
0
    if (len + 10 > max) {
3772
0
        xmlChar *tmp;
3773
3774
0
        max *= 2;
3775
0
        tmp = (xmlChar *) xmlRealloc(buffer, max);
3776
0
        if (tmp == NULL) {
3777
0
      xmlErrMemory(ctxt, NULL);
3778
0
      xmlFree(buffer);
3779
0
      return(NULL);
3780
0
        }
3781
0
        buffer = tmp;
3782
0
    }
3783
0
    COPY_BUF(buffer, len, c);
3784
0
    cur += l;
3785
0
    c = CUR_SCHAR(cur, l);
3786
0
                if (len > maxLength) {
3787
0
                    xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3788
0
                    xmlFree(buffer);
3789
0
                    return(NULL);
3790
0
                }
3791
0
      }
3792
0
      buffer[len] = 0;
3793
0
      *str = cur;
3794
0
      return(buffer);
3795
0
  }
3796
0
    }
3797
0
    if (len > maxLength) {
3798
0
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3799
0
        return(NULL);
3800
0
    }
3801
0
    *str = cur;
3802
0
    return(xmlStrndup(buf, len));
3803
0
}
3804
3805
/**
3806
 * xmlParseNmtoken:
3807
 * @ctxt:  an XML parser context
3808
 *
3809
 * DEPRECATED: Internal function, don't use.
3810
 *
3811
 * parse an XML Nmtoken.
3812
 *
3813
 * [7] Nmtoken ::= (NameChar)+
3814
 *
3815
 * [8] Nmtokens ::= Nmtoken (#x20 Nmtoken)*
3816
 *
3817
 * Returns the Nmtoken parsed or NULL
3818
 */
3819
3820
xmlChar *
3821
0
xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
3822
0
    xmlChar buf[XML_MAX_NAMELEN + 5];
3823
0
    int len = 0, l;
3824
0
    int c;
3825
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3826
0
                    XML_MAX_TEXT_LENGTH :
3827
0
                    XML_MAX_NAME_LENGTH;
3828
3829
0
    c = CUR_CHAR(l);
3830
3831
0
    while (xmlIsNameChar(ctxt, c)) {
3832
0
  COPY_BUF(buf, len, c);
3833
0
  NEXTL(l);
3834
0
  c = CUR_CHAR(l);
3835
0
  if (len >= XML_MAX_NAMELEN) {
3836
      /*
3837
       * Okay someone managed to make a huge token, so he's ready to pay
3838
       * for the processing speed.
3839
       */
3840
0
      xmlChar *buffer;
3841
0
      int max = len * 2;
3842
3843
0
      buffer = (xmlChar *) xmlMallocAtomic(max);
3844
0
      if (buffer == NULL) {
3845
0
          xmlErrMemory(ctxt, NULL);
3846
0
    return(NULL);
3847
0
      }
3848
0
      memcpy(buffer, buf, len);
3849
0
      while (xmlIsNameChar(ctxt, c)) {
3850
0
    if (len + 10 > max) {
3851
0
        xmlChar *tmp;
3852
3853
0
        max *= 2;
3854
0
        tmp = (xmlChar *) xmlRealloc(buffer, max);
3855
0
        if (tmp == NULL) {
3856
0
      xmlErrMemory(ctxt, NULL);
3857
0
      xmlFree(buffer);
3858
0
      return(NULL);
3859
0
        }
3860
0
        buffer = tmp;
3861
0
    }
3862
0
    COPY_BUF(buffer, len, c);
3863
0
                if (len > maxLength) {
3864
0
                    xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
3865
0
                    xmlFree(buffer);
3866
0
                    return(NULL);
3867
0
                }
3868
0
    NEXTL(l);
3869
0
    c = CUR_CHAR(l);
3870
0
      }
3871
0
      buffer[len] = 0;
3872
0
            if (ctxt->instate == XML_PARSER_EOF) {
3873
0
                xmlFree(buffer);
3874
0
                return(NULL);
3875
0
            }
3876
0
      return(buffer);
3877
0
  }
3878
0
    }
3879
0
    if (ctxt->instate == XML_PARSER_EOF)
3880
0
        return(NULL);
3881
0
    if (len == 0)
3882
0
        return(NULL);
3883
0
    if (len > maxLength) {
3884
0
        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
3885
0
        return(NULL);
3886
0
    }
3887
0
    return(xmlStrndup(buf, len));
3888
0
}
3889
3890
/**
3891
 * xmlParseEntityValue:
3892
 * @ctxt:  an XML parser context
3893
 * @orig:  if non-NULL store a copy of the original entity value
3894
 *
3895
 * DEPRECATED: Internal function, don't use.
3896
 *
3897
 * parse a value for ENTITY declarations
3898
 *
3899
 * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
3900
 *                 "'" ([^%&'] | PEReference | Reference)* "'"
3901
 *
3902
 * Returns the EntityValue parsed with reference substituted or NULL
3903
 */
3904
3905
xmlChar *
3906
0
xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
3907
0
    xmlChar *buf = NULL;
3908
0
    int len = 0;
3909
0
    int size = XML_PARSER_BUFFER_SIZE;
3910
0
    int c, l;
3911
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
3912
0
                    XML_MAX_HUGE_LENGTH :
3913
0
                    XML_MAX_TEXT_LENGTH;
3914
0
    xmlChar stop;
3915
0
    xmlChar *ret = NULL;
3916
0
    const xmlChar *cur = NULL;
3917
0
    xmlParserInputPtr input;
3918
3919
0
    if (RAW == '"') stop = '"';
3920
0
    else if (RAW == '\'') stop = '\'';
3921
0
    else {
3922
0
  xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_STARTED, NULL);
3923
0
  return(NULL);
3924
0
    }
3925
0
    buf = (xmlChar *) xmlMallocAtomic(size);
3926
0
    if (buf == NULL) {
3927
0
  xmlErrMemory(ctxt, NULL);
3928
0
  return(NULL);
3929
0
    }
3930
3931
    /*
3932
     * The content of the entity definition is copied in a buffer.
3933
     */
3934
3935
0
    ctxt->instate = XML_PARSER_ENTITY_VALUE;
3936
0
    input = ctxt->input;
3937
0
    GROW;
3938
0
    if (ctxt->instate == XML_PARSER_EOF)
3939
0
        goto error;
3940
0
    NEXT;
3941
0
    c = CUR_CHAR(l);
3942
    /*
3943
     * NOTE: 4.4.5 Included in Literal
3944
     * When a parameter entity reference appears in a literal entity
3945
     * value, ... a single or double quote character in the replacement
3946
     * text is always treated as a normal data character and will not
3947
     * terminate the literal.
3948
     * In practice it means we stop the loop only when back at parsing
3949
     * the initial entity and the quote is found
3950
     */
3951
0
    while (((IS_CHAR(c)) && ((c != stop) || /* checked */
3952
0
      (ctxt->input != input))) && (ctxt->instate != XML_PARSER_EOF)) {
3953
0
  if (len + 5 >= size) {
3954
0
      xmlChar *tmp;
3955
3956
0
      size *= 2;
3957
0
      tmp = (xmlChar *) xmlRealloc(buf, size);
3958
0
      if (tmp == NULL) {
3959
0
    xmlErrMemory(ctxt, NULL);
3960
0
                goto error;
3961
0
      }
3962
0
      buf = tmp;
3963
0
  }
3964
0
  COPY_BUF(buf, len, c);
3965
0
  NEXTL(l);
3966
3967
0
  GROW;
3968
0
  c = CUR_CHAR(l);
3969
0
  if (c == 0) {
3970
0
      GROW;
3971
0
      c = CUR_CHAR(l);
3972
0
  }
3973
3974
0
        if (len > maxLength) {
3975
0
            xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
3976
0
                           "entity value too long\n");
3977
0
            goto error;
3978
0
        }
3979
0
    }
3980
0
    buf[len] = 0;
3981
0
    if (ctxt->instate == XML_PARSER_EOF)
3982
0
        goto error;
3983
0
    if (c != stop) {
3984
0
        xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL);
3985
0
        goto error;
3986
0
    }
3987
0
    NEXT;
3988
3989
    /*
3990
     * Raise problem w.r.t. '&' and '%' being used in non-entities
3991
     * reference constructs. Note Charref will be handled in
3992
     * xmlStringDecodeEntities()
3993
     */
3994
0
    cur = buf;
3995
0
    while (*cur != 0) { /* non input consuming */
3996
0
  if ((*cur == '%') || ((*cur == '&') && (cur[1] != '#'))) {
3997
0
      xmlChar *name;
3998
0
      xmlChar tmp = *cur;
3999
0
            int nameOk = 0;
4000
4001
0
      cur++;
4002
0
      name = xmlParseStringName(ctxt, &cur);
4003
0
            if (name != NULL) {
4004
0
                nameOk = 1;
4005
0
                xmlFree(name);
4006
0
            }
4007
0
            if ((nameOk == 0) || (*cur != ';')) {
4008
0
    xmlFatalErrMsgInt(ctxt, XML_ERR_ENTITY_CHAR_ERROR,
4009
0
      "EntityValue: '%c' forbidden except for entities references\n",
4010
0
                            tmp);
4011
0
                goto error;
4012
0
      }
4013
0
      if ((tmp == '%') && (ctxt->inSubset == 1) &&
4014
0
    (ctxt->inputNr == 1)) {
4015
0
    xmlFatalErr(ctxt, XML_ERR_ENTITY_PE_INTERNAL, NULL);
4016
0
                goto error;
4017
0
      }
4018
0
      if (*cur == 0)
4019
0
          break;
4020
0
  }
4021
0
  cur++;
4022
0
    }
4023
4024
    /*
4025
     * Then PEReference entities are substituted.
4026
     *
4027
     * NOTE: 4.4.7 Bypassed
4028
     * When a general entity reference appears in the EntityValue in
4029
     * an entity declaration, it is bypassed and left as is.
4030
     * so XML_SUBSTITUTE_REF is not set here.
4031
     */
4032
0
    ++ctxt->depth;
4033
0
    ret = xmlStringDecodeEntitiesInt(ctxt, buf, len, XML_SUBSTITUTE_PEREF,
4034
0
                                     0, 0, 0, /* check */ 1);
4035
0
    --ctxt->depth;
4036
4037
0
    if (orig != NULL) {
4038
0
        *orig = buf;
4039
0
        buf = NULL;
4040
0
    }
4041
4042
0
error:
4043
0
    if (buf != NULL)
4044
0
        xmlFree(buf);
4045
0
    return(ret);
4046
0
}
4047
4048
/**
4049
 * xmlParseAttValueComplex:
4050
 * @ctxt:  an XML parser context
4051
 * @len:   the resulting attribute len
4052
 * @normalize:  whether to apply the inner normalization
4053
 *
4054
 * parse a value for an attribute, this is the fallback function
4055
 * of xmlParseAttValue() when the attribute parsing requires handling
4056
 * of non-ASCII characters, or normalization compaction.
4057
 *
4058
 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
4059
 */
4060
static xmlChar *
4061
0
xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
4062
0
    xmlChar limit = 0;
4063
0
    xmlChar *buf = NULL;
4064
0
    xmlChar *rep = NULL;
4065
0
    size_t len = 0;
4066
0
    size_t buf_size = 0;
4067
0
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4068
0
                       XML_MAX_HUGE_LENGTH :
4069
0
                       XML_MAX_TEXT_LENGTH;
4070
0
    int c, l, in_space = 0;
4071
0
    xmlChar *current = NULL;
4072
0
    xmlEntityPtr ent;
4073
4074
0
    if (NXT(0) == '"') {
4075
0
  ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
4076
0
  limit = '"';
4077
0
        NEXT;
4078
0
    } else if (NXT(0) == '\'') {
4079
0
  limit = '\'';
4080
0
  ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
4081
0
        NEXT;
4082
0
    } else {
4083
0
  xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
4084
0
  return(NULL);
4085
0
    }
4086
4087
    /*
4088
     * allocate a translation buffer.
4089
     */
4090
0
    buf_size = XML_PARSER_BUFFER_SIZE;
4091
0
    buf = (xmlChar *) xmlMallocAtomic(buf_size);
4092
0
    if (buf == NULL) goto mem_error;
4093
4094
    /*
4095
     * OK loop until we reach one of the ending char or a size limit.
4096
     */
4097
0
    c = CUR_CHAR(l);
4098
0
    while (((NXT(0) != limit) && /* checked */
4099
0
            (IS_CHAR(c)) && (c != '<')) &&
4100
0
            (ctxt->instate != XML_PARSER_EOF)) {
4101
0
  if (c == '&') {
4102
0
      in_space = 0;
4103
0
      if (NXT(1) == '#') {
4104
0
    int val = xmlParseCharRef(ctxt);
4105
4106
0
    if (val == '&') {
4107
0
        if (ctxt->replaceEntities) {
4108
0
      if (len + 10 > buf_size) {
4109
0
          growBuffer(buf, 10);
4110
0
      }
4111
0
      buf[len++] = '&';
4112
0
        } else {
4113
      /*
4114
       * The reparsing will be done in xmlStringGetNodeList()
4115
       * called by the attribute() function in SAX.c
4116
       */
4117
0
      if (len + 10 > buf_size) {
4118
0
          growBuffer(buf, 10);
4119
0
      }
4120
0
      buf[len++] = '&';
4121
0
      buf[len++] = '#';
4122
0
      buf[len++] = '3';
4123
0
      buf[len++] = '8';
4124
0
      buf[len++] = ';';
4125
0
        }
4126
0
    } else if (val != 0) {
4127
0
        if (len + 10 > buf_size) {
4128
0
      growBuffer(buf, 10);
4129
0
        }
4130
0
        len += xmlCopyChar(0, &buf[len], val);
4131
0
    }
4132
0
      } else {
4133
0
    ent = xmlParseEntityRef(ctxt);
4134
0
    if ((ent != NULL) &&
4135
0
        (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
4136
0
        if (len + 10 > buf_size) {
4137
0
      growBuffer(buf, 10);
4138
0
        }
4139
0
        if ((ctxt->replaceEntities == 0) &&
4140
0
            (ent->content[0] == '&')) {
4141
0
      buf[len++] = '&';
4142
0
      buf[len++] = '#';
4143
0
      buf[len++] = '3';
4144
0
      buf[len++] = '8';
4145
0
      buf[len++] = ';';
4146
0
        } else {
4147
0
      buf[len++] = ent->content[0];
4148
0
        }
4149
0
    } else if ((ent != NULL) &&
4150
0
               (ctxt->replaceEntities != 0)) {
4151
0
        if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
4152
0
                        if (xmlParserEntityCheck(ctxt, ent->length))
4153
0
                            goto error;
4154
4155
0
      ++ctxt->depth;
4156
0
      rep = xmlStringDecodeEntitiesInt(ctxt, ent->content,
4157
0
                                ent->length, XML_SUBSTITUTE_REF, 0, 0, 0,
4158
0
                                /* check */ 1);
4159
0
      --ctxt->depth;
4160
0
      if (rep != NULL) {
4161
0
          current = rep;
4162
0
          while (*current != 0) { /* non input consuming */
4163
0
                                if ((*current == 0xD) || (*current == 0xA) ||
4164
0
                                    (*current == 0x9)) {
4165
0
                                    buf[len++] = 0x20;
4166
0
                                    current++;
4167
0
                                } else
4168
0
                                    buf[len++] = *current++;
4169
0
        if (len + 10 > buf_size) {
4170
0
            growBuffer(buf, 10);
4171
0
        }
4172
0
          }
4173
0
          xmlFree(rep);
4174
0
          rep = NULL;
4175
0
      }
4176
0
        } else {
4177
0
      if (len + 10 > buf_size) {
4178
0
          growBuffer(buf, 10);
4179
0
      }
4180
0
      if (ent->content != NULL)
4181
0
          buf[len++] = ent->content[0];
4182
0
        }
4183
0
    } else if (ent != NULL) {
4184
0
        int i = xmlStrlen(ent->name);
4185
0
        const xmlChar *cur = ent->name;
4186
4187
        /*
4188
                     * We also check for recursion and amplification
4189
                     * when entities are not substituted. They're
4190
                     * often expanded later.
4191
         */
4192
0
        if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
4193
0
      (ent->content != NULL)) {
4194
0
                        if ((ent->flags & XML_ENT_CHECKED) == 0) {
4195
0
                            unsigned long oldCopy = ctxt->sizeentcopy;
4196
4197
0
                            ctxt->sizeentcopy = ent->length;
4198
4199
0
                            ++ctxt->depth;
4200
0
                            rep = xmlStringDecodeEntitiesInt(ctxt,
4201
0
                                    ent->content, ent->length,
4202
0
                                    XML_SUBSTITUTE_REF, 0, 0, 0,
4203
0
                                    /* check */ 1);
4204
0
                            --ctxt->depth;
4205
4206
                            /*
4207
                             * If we're parsing DTD content, the entity
4208
                             * might reference other entities which
4209
                             * weren't defined yet, so the check isn't
4210
                             * reliable.
4211
                             */
4212
0
                            if (ctxt->inSubset == 0) {
4213
0
                                ent->flags |= XML_ENT_CHECKED;
4214
0
                                ent->expandedSize = ctxt->sizeentcopy;
4215
0
                            }
4216
4217
0
                            if (rep != NULL) {
4218
0
                                xmlFree(rep);
4219
0
                                rep = NULL;
4220
0
                            } else {
4221
0
                                ent->content[0] = 0;
4222
0
                            }
4223
4224
0
                            if (xmlParserEntityCheck(ctxt, oldCopy))
4225
0
                                goto error;
4226
0
                        } else {
4227
0
                            if (xmlParserEntityCheck(ctxt, ent->expandedSize))
4228
0
                                goto error;
4229
0
                        }
4230
0
        }
4231
4232
        /*
4233
         * Just output the reference
4234
         */
4235
0
        buf[len++] = '&';
4236
0
        while (len + i + 10 > buf_size) {
4237
0
      growBuffer(buf, i + 10);
4238
0
        }
4239
0
        for (;i > 0;i--)
4240
0
      buf[len++] = *cur++;
4241
0
        buf[len++] = ';';
4242
0
    }
4243
0
      }
4244
0
  } else {
4245
0
      if ((c == 0x20) || (c == 0xD) || (c == 0xA) || (c == 0x9)) {
4246
0
          if ((len != 0) || (!normalize)) {
4247
0
        if ((!normalize) || (!in_space)) {
4248
0
      COPY_BUF(buf, len, 0x20);
4249
0
      while (len + 10 > buf_size) {
4250
0
          growBuffer(buf, 10);
4251
0
      }
4252
0
        }
4253
0
        in_space = 1;
4254
0
    }
4255
0
      } else {
4256
0
          in_space = 0;
4257
0
    COPY_BUF(buf, len, c);
4258
0
    if (len + 10 > buf_size) {
4259
0
        growBuffer(buf, 10);
4260
0
    }
4261
0
      }
4262
0
      NEXTL(l);
4263
0
  }
4264
0
  GROW;
4265
0
  c = CUR_CHAR(l);
4266
0
        if (len > maxLength) {
4267
0
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
4268
0
                           "AttValue length too long\n");
4269
0
            goto mem_error;
4270
0
        }
4271
0
    }
4272
0
    if (ctxt->instate == XML_PARSER_EOF)
4273
0
        goto error;
4274
4275
0
    if ((in_space) && (normalize)) {
4276
0
        while ((len > 0) && (buf[len - 1] == 0x20)) len--;
4277
0
    }
4278
0
    buf[len] = 0;
4279
0
    if (RAW == '<') {
4280
0
  xmlFatalErr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, NULL);
4281
0
    } else if (RAW != limit) {
4282
0
  if ((c != 0) && (!IS_CHAR(c))) {
4283
0
      xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
4284
0
         "invalid character in attribute value\n");
4285
0
  } else {
4286
0
      xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
4287
0
         "AttValue: ' expected\n");
4288
0
        }
4289
0
    } else
4290
0
  NEXT;
4291
4292
0
    if (attlen != NULL) *attlen = len;
4293
0
    return(buf);
4294
4295
0
mem_error:
4296
0
    xmlErrMemory(ctxt, NULL);
4297
0
error:
4298
0
    if (buf != NULL)
4299
0
        xmlFree(buf);
4300
0
    if (rep != NULL)
4301
0
        xmlFree(rep);
4302
0
    return(NULL);
4303
0
}
4304
4305
/**
4306
 * xmlParseAttValue:
4307
 * @ctxt:  an XML parser context
4308
 *
4309
 * DEPRECATED: Internal function, don't use.
4310
 *
4311
 * parse a value for an attribute
4312
 * Note: the parser won't do substitution of entities here, this
4313
 * will be handled later in xmlStringGetNodeList
4314
 *
4315
 * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |
4316
 *                   "'" ([^<&'] | Reference)* "'"
4317
 *
4318
 * 3.3.3 Attribute-Value Normalization:
4319
 * Before the value of an attribute is passed to the application or
4320
 * checked for validity, the XML processor must normalize it as follows:
4321
 * - a character reference is processed by appending the referenced
4322
 *   character to the attribute value
4323
 * - an entity reference is processed by recursively processing the
4324
 *   replacement text of the entity
4325
 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
4326
 *   appending #x20 to the normalized value, except that only a single
4327
 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
4328
 *   parsed entity or the literal entity value of an internal parsed entity
4329
 * - other characters are processed by appending them to the normalized value
4330
 * If the declared value is not CDATA, then the XML processor must further
4331
 * process the normalized attribute value by discarding any leading and
4332
 * trailing space (#x20) characters, and by replacing sequences of space
4333
 * (#x20) characters by a single space (#x20) character.
4334
 * All attributes for which no declaration has been read should be treated
4335
 * by a non-validating parser as if declared CDATA.
4336
 *
4337
 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
4338
 */
4339
4340
4341
xmlChar *
4342
0
xmlParseAttValue(xmlParserCtxtPtr ctxt) {
4343
0
    if ((ctxt == NULL) || (ctxt->input == NULL)) return(NULL);
4344
0
    return(xmlParseAttValueInternal(ctxt, NULL, NULL, 0));
4345
0
}
4346
4347
/**
4348
 * xmlParseSystemLiteral:
4349
 * @ctxt:  an XML parser context
4350
 *
4351
 * DEPRECATED: Internal function, don't use.
4352
 *
4353
 * parse an XML Literal
4354
 *
4355
 * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
4356
 *
4357
 * Returns the SystemLiteral parsed or NULL
4358
 */
4359
4360
xmlChar *
4361
0
xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
4362
0
    xmlChar *buf = NULL;
4363
0
    int len = 0;
4364
0
    int size = XML_PARSER_BUFFER_SIZE;
4365
0
    int cur, l;
4366
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4367
0
                    XML_MAX_TEXT_LENGTH :
4368
0
                    XML_MAX_NAME_LENGTH;
4369
0
    xmlChar stop;
4370
0
    int state = ctxt->instate;
4371
4372
0
    if (RAW == '"') {
4373
0
        NEXT;
4374
0
  stop = '"';
4375
0
    } else if (RAW == '\'') {
4376
0
        NEXT;
4377
0
  stop = '\'';
4378
0
    } else {
4379
0
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
4380
0
  return(NULL);
4381
0
    }
4382
4383
0
    buf = (xmlChar *) xmlMallocAtomic(size);
4384
0
    if (buf == NULL) {
4385
0
        xmlErrMemory(ctxt, NULL);
4386
0
  return(NULL);
4387
0
    }
4388
0
    ctxt->instate = XML_PARSER_SYSTEM_LITERAL;
4389
0
    cur = CUR_CHAR(l);
4390
0
    while ((IS_CHAR(cur)) && (cur != stop)) { /* checked */
4391
0
  if (len + 5 >= size) {
4392
0
      xmlChar *tmp;
4393
4394
0
      size *= 2;
4395
0
      tmp = (xmlChar *) xmlRealloc(buf, size);
4396
0
      if (tmp == NULL) {
4397
0
          xmlFree(buf);
4398
0
    xmlErrMemory(ctxt, NULL);
4399
0
    ctxt->instate = (xmlParserInputState) state;
4400
0
    return(NULL);
4401
0
      }
4402
0
      buf = tmp;
4403
0
  }
4404
0
  COPY_BUF(buf, len, cur);
4405
0
        if (len > maxLength) {
4406
0
            xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral");
4407
0
            xmlFree(buf);
4408
0
            ctxt->instate = (xmlParserInputState) state;
4409
0
            return(NULL);
4410
0
        }
4411
0
  NEXTL(l);
4412
0
  cur = CUR_CHAR(l);
4413
0
    }
4414
0
    buf[len] = 0;
4415
0
    if (ctxt->instate == XML_PARSER_EOF) {
4416
0
        xmlFree(buf);
4417
0
        return(NULL);
4418
0
    }
4419
0
    ctxt->instate = (xmlParserInputState) state;
4420
0
    if (!IS_CHAR(cur)) {
4421
0
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
4422
0
    } else {
4423
0
  NEXT;
4424
0
    }
4425
0
    return(buf);
4426
0
}
4427
4428
/**
4429
 * xmlParsePubidLiteral:
4430
 * @ctxt:  an XML parser context
4431
 *
4432
 * DEPRECATED: Internal function, don't use.
4433
 *
4434
 * parse an XML public literal
4435
 *
4436
 * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
4437
 *
4438
 * Returns the PubidLiteral parsed or NULL.
4439
 */
4440
4441
xmlChar *
4442
0
xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
4443
0
    xmlChar *buf = NULL;
4444
0
    int len = 0;
4445
0
    int size = XML_PARSER_BUFFER_SIZE;
4446
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4447
0
                    XML_MAX_TEXT_LENGTH :
4448
0
                    XML_MAX_NAME_LENGTH;
4449
0
    xmlChar cur;
4450
0
    xmlChar stop;
4451
0
    xmlParserInputState oldstate = ctxt->instate;
4452
4453
0
    if (RAW == '"') {
4454
0
        NEXT;
4455
0
  stop = '"';
4456
0
    } else if (RAW == '\'') {
4457
0
        NEXT;
4458
0
  stop = '\'';
4459
0
    } else {
4460
0
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
4461
0
  return(NULL);
4462
0
    }
4463
0
    buf = (xmlChar *) xmlMallocAtomic(size);
4464
0
    if (buf == NULL) {
4465
0
  xmlErrMemory(ctxt, NULL);
4466
0
  return(NULL);
4467
0
    }
4468
0
    ctxt->instate = XML_PARSER_PUBLIC_LITERAL;
4469
0
    cur = CUR;
4470
0
    while ((IS_PUBIDCHAR_CH(cur)) && (cur != stop)) { /* checked */
4471
0
  if (len + 1 >= size) {
4472
0
      xmlChar *tmp;
4473
4474
0
      size *= 2;
4475
0
      tmp = (xmlChar *) xmlRealloc(buf, size);
4476
0
      if (tmp == NULL) {
4477
0
    xmlErrMemory(ctxt, NULL);
4478
0
    xmlFree(buf);
4479
0
    return(NULL);
4480
0
      }
4481
0
      buf = tmp;
4482
0
  }
4483
0
  buf[len++] = cur;
4484
0
        if (len > maxLength) {
4485
0
            xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Public ID");
4486
0
            xmlFree(buf);
4487
0
            return(NULL);
4488
0
        }
4489
0
  NEXT;
4490
0
  cur = CUR;
4491
0
    }
4492
0
    buf[len] = 0;
4493
0
    if (ctxt->instate == XML_PARSER_EOF) {
4494
0
        xmlFree(buf);
4495
0
        return(NULL);
4496
0
    }
4497
0
    if (cur != stop) {
4498
0
  xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
4499
0
    } else {
4500
0
  NEXTL(1);
4501
0
    }
4502
0
    ctxt->instate = oldstate;
4503
0
    return(buf);
4504
0
}
4505
4506
static void xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int partial);
4507
4508
/*
4509
 * used for the test in the inner loop of the char data testing
4510
 */
4511
static const unsigned char test_char_data[256] = {
4512
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4513
    0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9, CR/LF separated */
4514
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4515
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4516
    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x00, 0x27, /* & */
4517
    0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
4518
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
4519
    0x38, 0x39, 0x3A, 0x3B, 0x00, 0x3D, 0x3E, 0x3F, /* < */
4520
    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
4521
    0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
4522
    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
4523
    0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x00, 0x5E, 0x5F, /* ] */
4524
    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
4525
    0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
4526
    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
4527
    0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
4528
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* non-ascii */
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
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4542
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4543
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4544
};
4545
4546
/**
4547
 * xmlParseCharDataInternal:
4548
 * @ctxt:  an XML parser context
4549
 * @partial:  buffer may contain partial UTF-8 sequences
4550
 *
4551
 * Parse character data. Always makes progress if the first char isn't
4552
 * '<' or '&'.
4553
 *
4554
 * The right angle bracket (>) may be represented using the string "&gt;",
4555
 * and must, for compatibility, be escaped using "&gt;" or a character
4556
 * reference when it appears in the string "]]>" in content, when that
4557
 * string is not marking the end of a CDATA section.
4558
 *
4559
 * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
4560
 */
4561
static void
4562
0
xmlParseCharDataInternal(xmlParserCtxtPtr ctxt, int partial) {
4563
0
    const xmlChar *in;
4564
0
    int nbchar = 0;
4565
0
    int line = ctxt->input->line;
4566
0
    int col = ctxt->input->col;
4567
0
    int ccol;
4568
4569
0
    GROW;
4570
    /*
4571
     * Accelerated common case where input don't need to be
4572
     * modified before passing it to the handler.
4573
     */
4574
0
    in = ctxt->input->cur;
4575
0
    do {
4576
0
get_more_space:
4577
0
        while (*in == 0x20) { in++; ctxt->input->col++; }
4578
0
        if (*in == 0xA) {
4579
0
            do {
4580
0
                ctxt->input->line++; ctxt->input->col = 1;
4581
0
                in++;
4582
0
            } while (*in == 0xA);
4583
0
            goto get_more_space;
4584
0
        }
4585
0
        if (*in == '<') {
4586
0
            nbchar = in - ctxt->input->cur;
4587
0
            if (nbchar > 0) {
4588
0
                const xmlChar *tmp = ctxt->input->cur;
4589
0
                ctxt->input->cur = in;
4590
4591
0
                if ((ctxt->sax != NULL) &&
4592
0
                    (ctxt->disableSAX == 0) &&
4593
0
                    (ctxt->sax->ignorableWhitespace !=
4594
0
                     ctxt->sax->characters)) {
4595
0
                    if (areBlanks(ctxt, tmp, nbchar, 1)) {
4596
0
                        if (ctxt->sax->ignorableWhitespace != NULL)
4597
0
                            ctxt->sax->ignorableWhitespace(ctxt->userData,
4598
0
                                                   tmp, nbchar);
4599
0
                    } else {
4600
0
                        if (ctxt->sax->characters != NULL)
4601
0
                            ctxt->sax->characters(ctxt->userData,
4602
0
                                                  tmp, nbchar);
4603
0
                        if (*ctxt->space == -1)
4604
0
                            *ctxt->space = -2;
4605
0
                    }
4606
0
                } else if ((ctxt->sax != NULL) &&
4607
0
                           (ctxt->disableSAX == 0) &&
4608
0
                           (ctxt->sax->characters != NULL)) {
4609
0
                    ctxt->sax->characters(ctxt->userData,
4610
0
                                          tmp, nbchar);
4611
0
                }
4612
0
            }
4613
0
            return;
4614
0
        }
4615
4616
0
get_more:
4617
0
        ccol = ctxt->input->col;
4618
0
        while (test_char_data[*in]) {
4619
0
            in++;
4620
0
            ccol++;
4621
0
        }
4622
0
        ctxt->input->col = ccol;
4623
0
        if (*in == 0xA) {
4624
0
            do {
4625
0
                ctxt->input->line++; ctxt->input->col = 1;
4626
0
                in++;
4627
0
            } while (*in == 0xA);
4628
0
            goto get_more;
4629
0
        }
4630
0
        if (*in == ']') {
4631
0
            if ((in[1] == ']') && (in[2] == '>')) {
4632
0
                xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
4633
0
                if (ctxt->instate != XML_PARSER_EOF)
4634
0
                    ctxt->input->cur = in + 1;
4635
0
                return;
4636
0
            }
4637
0
            in++;
4638
0
            ctxt->input->col++;
4639
0
            goto get_more;
4640
0
        }
4641
0
        nbchar = in - ctxt->input->cur;
4642
0
        if (nbchar > 0) {
4643
0
            if ((ctxt->sax != NULL) &&
4644
0
                (ctxt->disableSAX == 0) &&
4645
0
                (ctxt->sax->ignorableWhitespace !=
4646
0
                 ctxt->sax->characters) &&
4647
0
                (IS_BLANK_CH(*ctxt->input->cur))) {
4648
0
                const xmlChar *tmp = ctxt->input->cur;
4649
0
                ctxt->input->cur = in;
4650
4651
0
                if (areBlanks(ctxt, tmp, nbchar, 0)) {
4652
0
                    if (ctxt->sax->ignorableWhitespace != NULL)
4653
0
                        ctxt->sax->ignorableWhitespace(ctxt->userData,
4654
0
                                                       tmp, nbchar);
4655
0
                } else {
4656
0
                    if (ctxt->sax->characters != NULL)
4657
0
                        ctxt->sax->characters(ctxt->userData,
4658
0
                                              tmp, nbchar);
4659
0
                    if (*ctxt->space == -1)
4660
0
                        *ctxt->space = -2;
4661
0
                }
4662
0
                line = ctxt->input->line;
4663
0
                col = ctxt->input->col;
4664
0
            } else if ((ctxt->sax != NULL) &&
4665
0
                       (ctxt->disableSAX == 0)) {
4666
0
                if (ctxt->sax->characters != NULL)
4667
0
                    ctxt->sax->characters(ctxt->userData,
4668
0
                                          ctxt->input->cur, nbchar);
4669
0
                line = ctxt->input->line;
4670
0
                col = ctxt->input->col;
4671
0
            }
4672
0
            if (ctxt->instate == XML_PARSER_EOF)
4673
0
                return;
4674
0
        }
4675
0
        ctxt->input->cur = in;
4676
0
        if (*in == 0xD) {
4677
0
            in++;
4678
0
            if (*in == 0xA) {
4679
0
                ctxt->input->cur = in;
4680
0
                in++;
4681
0
                ctxt->input->line++; ctxt->input->col = 1;
4682
0
                continue; /* while */
4683
0
            }
4684
0
            in--;
4685
0
        }
4686
0
        if (*in == '<') {
4687
0
            return;
4688
0
        }
4689
0
        if (*in == '&') {
4690
0
            return;
4691
0
        }
4692
0
        SHRINK;
4693
0
        GROW;
4694
0
        if (ctxt->instate == XML_PARSER_EOF)
4695
0
            return;
4696
0
        in = ctxt->input->cur;
4697
0
    } while (((*in >= 0x20) && (*in <= 0x7F)) ||
4698
0
             (*in == 0x09) || (*in == 0x0a));
4699
0
    ctxt->input->line = line;
4700
0
    ctxt->input->col = col;
4701
0
    xmlParseCharDataComplex(ctxt, partial);
4702
0
}
4703
4704
/**
4705
 * xmlParseCharDataComplex:
4706
 * @ctxt:  an XML parser context
4707
 * @cdata:  int indicating whether we are within a CDATA section
4708
 *
4709
 * Always makes progress if the first char isn't '<' or '&'.
4710
 *
4711
 * parse a CharData section.this is the fallback function
4712
 * of xmlParseCharData() when the parsing requires handling
4713
 * of non-ASCII characters.
4714
 */
4715
static void
4716
0
xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int partial) {
4717
0
    xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE + 5];
4718
0
    int nbchar = 0;
4719
0
    int cur, l;
4720
4721
0
    cur = CUR_CHAR(l);
4722
0
    while ((cur != '<') && /* checked */
4723
0
           (cur != '&') &&
4724
0
     (IS_CHAR(cur))) {
4725
0
  if ((cur == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
4726
0
      xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
4727
0
  }
4728
0
  COPY_BUF(buf, nbchar, cur);
4729
  /* move current position before possible calling of ctxt->sax->characters */
4730
0
  NEXTL(l);
4731
0
  if (nbchar >= XML_PARSER_BIG_BUFFER_SIZE) {
4732
0
      buf[nbchar] = 0;
4733
4734
      /*
4735
       * OK the segment is to be consumed as chars.
4736
       */
4737
0
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
4738
0
    if (areBlanks(ctxt, buf, nbchar, 0)) {
4739
0
        if (ctxt->sax->ignorableWhitespace != NULL)
4740
0
      ctxt->sax->ignorableWhitespace(ctxt->userData,
4741
0
                                     buf, nbchar);
4742
0
    } else {
4743
0
        if (ctxt->sax->characters != NULL)
4744
0
      ctxt->sax->characters(ctxt->userData, buf, nbchar);
4745
0
        if ((ctxt->sax->characters !=
4746
0
             ctxt->sax->ignorableWhitespace) &&
4747
0
      (*ctxt->space == -1))
4748
0
      *ctxt->space = -2;
4749
0
    }
4750
0
      }
4751
0
      nbchar = 0;
4752
            /* something really bad happened in the SAX callback */
4753
0
            if (ctxt->instate != XML_PARSER_CONTENT)
4754
0
                return;
4755
0
            SHRINK;
4756
0
  }
4757
0
  cur = CUR_CHAR(l);
4758
0
    }
4759
0
    if (ctxt->instate == XML_PARSER_EOF)
4760
0
        return;
4761
0
    if (nbchar != 0) {
4762
0
        buf[nbchar] = 0;
4763
  /*
4764
   * OK the segment is to be consumed as chars.
4765
   */
4766
0
  if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
4767
0
      if (areBlanks(ctxt, buf, nbchar, 0)) {
4768
0
    if (ctxt->sax->ignorableWhitespace != NULL)
4769
0
        ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
4770
0
      } else {
4771
0
    if (ctxt->sax->characters != NULL)
4772
0
        ctxt->sax->characters(ctxt->userData, buf, nbchar);
4773
0
    if ((ctxt->sax->characters != ctxt->sax->ignorableWhitespace) &&
4774
0
        (*ctxt->space == -1))
4775
0
        *ctxt->space = -2;
4776
0
      }
4777
0
  }
4778
0
    }
4779
    /*
4780
     * cur == 0 can mean
4781
     *
4782
     * - XML_PARSER_EOF or memory error. This is checked above.
4783
     * - An actual 0 character.
4784
     * - End of buffer.
4785
     * - An incomplete UTF-8 sequence. This is allowed if partial is set.
4786
     */
4787
0
    if (ctxt->input->cur < ctxt->input->end) {
4788
0
        if ((cur == 0) && (CUR != 0)) {
4789
0
            if (partial == 0) {
4790
0
                xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4791
0
                        "Incomplete UTF-8 sequence starting with %02X\n", CUR);
4792
0
                NEXTL(1);
4793
0
            }
4794
0
        } else if ((cur != '<') && (cur != '&')) {
4795
            /* Generate the error and skip the offending character */
4796
0
            xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4797
0
                              "PCDATA invalid Char value %d\n", cur);
4798
0
            NEXTL(l);
4799
0
        }
4800
0
    }
4801
0
}
4802
4803
/**
4804
 * xmlParseCharData:
4805
 * @ctxt:  an XML parser context
4806
 * @cdata:  unused
4807
 *
4808
 * DEPRECATED: Internal function, don't use.
4809
 */
4810
void
4811
0
xmlParseCharData(xmlParserCtxtPtr ctxt, ATTRIBUTE_UNUSED int cdata) {
4812
0
    xmlParseCharDataInternal(ctxt, 0);
4813
0
}
4814
4815
/**
4816
 * xmlParseExternalID:
4817
 * @ctxt:  an XML parser context
4818
 * @publicID:  a xmlChar** receiving PubidLiteral
4819
 * @strict: indicate whether we should restrict parsing to only
4820
 *          production [75], see NOTE below
4821
 *
4822
 * DEPRECATED: Internal function, don't use.
4823
 *
4824
 * Parse an External ID or a Public ID
4825
 *
4826
 * NOTE: Productions [75] and [83] interact badly since [75] can generate
4827
 *       'PUBLIC' S PubidLiteral S SystemLiteral
4828
 *
4829
 * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
4830
 *                   | 'PUBLIC' S PubidLiteral S SystemLiteral
4831
 *
4832
 * [83] PublicID ::= 'PUBLIC' S PubidLiteral
4833
 *
4834
 * Returns the function returns SystemLiteral and in the second
4835
 *                case publicID receives PubidLiteral, is strict is off
4836
 *                it is possible to return NULL and have publicID set.
4837
 */
4838
4839
xmlChar *
4840
0
xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
4841
0
    xmlChar *URI = NULL;
4842
4843
0
    *publicID = NULL;
4844
0
    if (CMP6(CUR_PTR, 'S', 'Y', 'S', 'T', 'E', 'M')) {
4845
0
        SKIP(6);
4846
0
  if (SKIP_BLANKS == 0) {
4847
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4848
0
                     "Space required after 'SYSTEM'\n");
4849
0
  }
4850
0
  URI = xmlParseSystemLiteral(ctxt);
4851
0
  if (URI == NULL) {
4852
0
      xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
4853
0
        }
4854
0
    } else if (CMP6(CUR_PTR, 'P', 'U', 'B', 'L', 'I', 'C')) {
4855
0
        SKIP(6);
4856
0
  if (SKIP_BLANKS == 0) {
4857
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4858
0
        "Space required after 'PUBLIC'\n");
4859
0
  }
4860
0
  *publicID = xmlParsePubidLiteral(ctxt);
4861
0
  if (*publicID == NULL) {
4862
0
      xmlFatalErr(ctxt, XML_ERR_PUBID_REQUIRED, NULL);
4863
0
  }
4864
0
  if (strict) {
4865
      /*
4866
       * We don't handle [83] so "S SystemLiteral" is required.
4867
       */
4868
0
      if (SKIP_BLANKS == 0) {
4869
0
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4870
0
      "Space required after the Public Identifier\n");
4871
0
      }
4872
0
  } else {
4873
      /*
4874
       * We handle [83] so we return immediately, if
4875
       * "S SystemLiteral" is not detected. We skip blanks if no
4876
             * system literal was found, but this is harmless since we must
4877
             * be at the end of a NotationDecl.
4878
       */
4879
0
      if (SKIP_BLANKS == 0) return(NULL);
4880
0
      if ((CUR != '\'') && (CUR != '"')) return(NULL);
4881
0
  }
4882
0
  URI = xmlParseSystemLiteral(ctxt);
4883
0
  if (URI == NULL) {
4884
0
      xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
4885
0
        }
4886
0
    }
4887
0
    return(URI);
4888
0
}
4889
4890
/**
4891
 * xmlParseCommentComplex:
4892
 * @ctxt:  an XML parser context
4893
 * @buf:  the already parsed part of the buffer
4894
 * @len:  number of bytes in the buffer
4895
 * @size:  allocated size of the buffer
4896
 *
4897
 * Skip an XML (SGML) comment <!-- .... -->
4898
 *  The spec says that "For compatibility, the string "--" (double-hyphen)
4899
 *  must not occur within comments. "
4900
 * This is the slow routine in case the accelerator for ascii didn't work
4901
 *
4902
 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
4903
 */
4904
static void
4905
xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
4906
0
                       size_t len, size_t size) {
4907
0
    int q, ql;
4908
0
    int r, rl;
4909
0
    int cur, l;
4910
0
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
4911
0
                       XML_MAX_HUGE_LENGTH :
4912
0
                       XML_MAX_TEXT_LENGTH;
4913
0
    int inputid;
4914
4915
0
    inputid = ctxt->input->id;
4916
4917
0
    if (buf == NULL) {
4918
0
        len = 0;
4919
0
  size = XML_PARSER_BUFFER_SIZE;
4920
0
  buf = (xmlChar *) xmlMallocAtomic(size);
4921
0
  if (buf == NULL) {
4922
0
      xmlErrMemory(ctxt, NULL);
4923
0
      return;
4924
0
  }
4925
0
    }
4926
0
    q = CUR_CHAR(ql);
4927
0
    if (q == 0)
4928
0
        goto not_terminated;
4929
0
    if (!IS_CHAR(q)) {
4930
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4931
0
                          "xmlParseComment: invalid xmlChar value %d\n",
4932
0
                    q);
4933
0
  xmlFree (buf);
4934
0
  return;
4935
0
    }
4936
0
    NEXTL(ql);
4937
0
    r = CUR_CHAR(rl);
4938
0
    if (r == 0)
4939
0
        goto not_terminated;
4940
0
    if (!IS_CHAR(r)) {
4941
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4942
0
                          "xmlParseComment: invalid xmlChar value %d\n",
4943
0
                    r);
4944
0
  xmlFree (buf);
4945
0
  return;
4946
0
    }
4947
0
    NEXTL(rl);
4948
0
    cur = CUR_CHAR(l);
4949
0
    if (cur == 0)
4950
0
        goto not_terminated;
4951
0
    while (IS_CHAR(cur) && /* checked */
4952
0
           ((cur != '>') ||
4953
0
      (r != '-') || (q != '-'))) {
4954
0
  if ((r == '-') && (q == '-')) {
4955
0
      xmlFatalErr(ctxt, XML_ERR_HYPHEN_IN_COMMENT, NULL);
4956
0
  }
4957
0
  if (len + 5 >= size) {
4958
0
      xmlChar *new_buf;
4959
0
            size_t new_size;
4960
4961
0
      new_size = size * 2;
4962
0
      new_buf = (xmlChar *) xmlRealloc(buf, new_size);
4963
0
      if (new_buf == NULL) {
4964
0
    xmlFree (buf);
4965
0
    xmlErrMemory(ctxt, NULL);
4966
0
    return;
4967
0
      }
4968
0
      buf = new_buf;
4969
0
            size = new_size;
4970
0
  }
4971
0
  COPY_BUF(buf, len, q);
4972
0
        if (len > maxLength) {
4973
0
            xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4974
0
                         "Comment too big found", NULL);
4975
0
            xmlFree (buf);
4976
0
            return;
4977
0
        }
4978
4979
0
  q = r;
4980
0
  ql = rl;
4981
0
  r = cur;
4982
0
  rl = l;
4983
4984
0
  NEXTL(l);
4985
0
  cur = CUR_CHAR(l);
4986
4987
0
    }
4988
0
    buf[len] = 0;
4989
0
    if (ctxt->instate == XML_PARSER_EOF) {
4990
0
        xmlFree(buf);
4991
0
        return;
4992
0
    }
4993
0
    if (cur == 0) {
4994
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4995
0
                       "Comment not terminated \n<!--%.50s\n", buf);
4996
0
    } else if (!IS_CHAR(cur)) {
4997
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4998
0
                          "xmlParseComment: invalid xmlChar value %d\n",
4999
0
                    cur);
5000
0
    } else {
5001
0
  if (inputid != ctxt->input->id) {
5002
0
      xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5003
0
               "Comment doesn't start and stop in the same"
5004
0
                           " entity\n");
5005
0
  }
5006
0
        NEXT;
5007
0
  if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
5008
0
      (!ctxt->disableSAX))
5009
0
      ctxt->sax->comment(ctxt->userData, buf);
5010
0
    }
5011
0
    xmlFree(buf);
5012
0
    return;
5013
0
not_terminated:
5014
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
5015
0
       "Comment not terminated\n", NULL);
5016
0
    xmlFree(buf);
5017
0
    return;
5018
0
}
5019
5020
/**
5021
 * xmlParseComment:
5022
 * @ctxt:  an XML parser context
5023
 *
5024
 * DEPRECATED: Internal function, don't use.
5025
 *
5026
 * Parse an XML (SGML) comment. Always consumes '<!'.
5027
 *
5028
 *  The spec says that "For compatibility, the string "--" (double-hyphen)
5029
 *  must not occur within comments. "
5030
 *
5031
 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
5032
 */
5033
void
5034
0
xmlParseComment(xmlParserCtxtPtr ctxt) {
5035
0
    xmlChar *buf = NULL;
5036
0
    size_t size = XML_PARSER_BUFFER_SIZE;
5037
0
    size_t len = 0;
5038
0
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
5039
0
                       XML_MAX_HUGE_LENGTH :
5040
0
                       XML_MAX_TEXT_LENGTH;
5041
0
    xmlParserInputState state;
5042
0
    const xmlChar *in;
5043
0
    size_t nbchar = 0;
5044
0
    int ccol;
5045
0
    int inputid;
5046
5047
    /*
5048
     * Check that there is a comment right here.
5049
     */
5050
0
    if ((RAW != '<') || (NXT(1) != '!'))
5051
0
        return;
5052
0
    SKIP(2);
5053
0
    if ((RAW != '-') || (NXT(1) != '-'))
5054
0
        return;
5055
0
    state = ctxt->instate;
5056
0
    ctxt->instate = XML_PARSER_COMMENT;
5057
0
    inputid = ctxt->input->id;
5058
0
    SKIP(2);
5059
0
    GROW;
5060
5061
    /*
5062
     * Accelerated common case where input don't need to be
5063
     * modified before passing it to the handler.
5064
     */
5065
0
    in = ctxt->input->cur;
5066
0
    do {
5067
0
  if (*in == 0xA) {
5068
0
      do {
5069
0
    ctxt->input->line++; ctxt->input->col = 1;
5070
0
    in++;
5071
0
      } while (*in == 0xA);
5072
0
  }
5073
0
get_more:
5074
0
        ccol = ctxt->input->col;
5075
0
  while (((*in > '-') && (*in <= 0x7F)) ||
5076
0
         ((*in >= 0x20) && (*in < '-')) ||
5077
0
         (*in == 0x09)) {
5078
0
        in++;
5079
0
        ccol++;
5080
0
  }
5081
0
  ctxt->input->col = ccol;
5082
0
  if (*in == 0xA) {
5083
0
      do {
5084
0
    ctxt->input->line++; ctxt->input->col = 1;
5085
0
    in++;
5086
0
      } while (*in == 0xA);
5087
0
      goto get_more;
5088
0
  }
5089
0
  nbchar = in - ctxt->input->cur;
5090
  /*
5091
   * save current set of data
5092
   */
5093
0
  if (nbchar > 0) {
5094
0
            if (buf == NULL) {
5095
0
                if ((*in == '-') && (in[1] == '-'))
5096
0
                    size = nbchar + 1;
5097
0
                else
5098
0
                    size = XML_PARSER_BUFFER_SIZE + nbchar;
5099
0
                buf = (xmlChar *) xmlMallocAtomic(size);
5100
0
                if (buf == NULL) {
5101
0
                    xmlErrMemory(ctxt, NULL);
5102
0
                    ctxt->instate = state;
5103
0
                    return;
5104
0
                }
5105
0
                len = 0;
5106
0
            } else if (len + nbchar + 1 >= size) {
5107
0
                xmlChar *new_buf;
5108
0
                size  += len + nbchar + XML_PARSER_BUFFER_SIZE;
5109
0
                new_buf = (xmlChar *) xmlRealloc(buf, size);
5110
0
                if (new_buf == NULL) {
5111
0
                    xmlFree (buf);
5112
0
                    xmlErrMemory(ctxt, NULL);
5113
0
                    ctxt->instate = state;
5114
0
                    return;
5115
0
                }
5116
0
                buf = new_buf;
5117
0
            }
5118
0
            memcpy(&buf[len], ctxt->input->cur, nbchar);
5119
0
            len += nbchar;
5120
0
            buf[len] = 0;
5121
0
  }
5122
0
        if (len > maxLength) {
5123
0
            xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
5124
0
                         "Comment too big found", NULL);
5125
0
            xmlFree (buf);
5126
0
            return;
5127
0
        }
5128
0
  ctxt->input->cur = in;
5129
0
  if (*in == 0xA) {
5130
0
      in++;
5131
0
      ctxt->input->line++; ctxt->input->col = 1;
5132
0
  }
5133
0
  if (*in == 0xD) {
5134
0
      in++;
5135
0
      if (*in == 0xA) {
5136
0
    ctxt->input->cur = in;
5137
0
    in++;
5138
0
    ctxt->input->line++; ctxt->input->col = 1;
5139
0
    goto get_more;
5140
0
      }
5141
0
      in--;
5142
0
  }
5143
0
  SHRINK;
5144
0
  GROW;
5145
0
        if (ctxt->instate == XML_PARSER_EOF) {
5146
0
            xmlFree(buf);
5147
0
            return;
5148
0
        }
5149
0
  in = ctxt->input->cur;
5150
0
  if (*in == '-') {
5151
0
      if (in[1] == '-') {
5152
0
          if (in[2] == '>') {
5153
0
        if (ctxt->input->id != inputid) {
5154
0
      xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5155
0
                     "comment doesn't start and stop in the"
5156
0
                                       " same entity\n");
5157
0
        }
5158
0
        SKIP(3);
5159
0
        if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
5160
0
            (!ctxt->disableSAX)) {
5161
0
      if (buf != NULL)
5162
0
          ctxt->sax->comment(ctxt->userData, buf);
5163
0
      else
5164
0
          ctxt->sax->comment(ctxt->userData, BAD_CAST "");
5165
0
        }
5166
0
        if (buf != NULL)
5167
0
            xmlFree(buf);
5168
0
        if (ctxt->instate != XML_PARSER_EOF)
5169
0
      ctxt->instate = state;
5170
0
        return;
5171
0
    }
5172
0
    if (buf != NULL) {
5173
0
        xmlFatalErrMsgStr(ctxt, XML_ERR_HYPHEN_IN_COMMENT,
5174
0
                          "Double hyphen within comment: "
5175
0
                                      "<!--%.50s\n",
5176
0
              buf);
5177
0
    } else
5178
0
        xmlFatalErrMsgStr(ctxt, XML_ERR_HYPHEN_IN_COMMENT,
5179
0
                          "Double hyphen within comment\n", NULL);
5180
0
                if (ctxt->instate == XML_PARSER_EOF) {
5181
0
                    xmlFree(buf);
5182
0
                    return;
5183
0
                }
5184
0
    in++;
5185
0
    ctxt->input->col++;
5186
0
      }
5187
0
      in++;
5188
0
      ctxt->input->col++;
5189
0
      goto get_more;
5190
0
  }
5191
0
    } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09) || (*in == 0x0a));
5192
0
    xmlParseCommentComplex(ctxt, buf, len, size);
5193
0
    ctxt->instate = state;
5194
0
    return;
5195
0
}
5196
5197
5198
/**
5199
 * xmlParsePITarget:
5200
 * @ctxt:  an XML parser context
5201
 *
5202
 * DEPRECATED: Internal function, don't use.
5203
 *
5204
 * parse the name of a PI
5205
 *
5206
 * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
5207
 *
5208
 * Returns the PITarget name or NULL
5209
 */
5210
5211
const xmlChar *
5212
0
xmlParsePITarget(xmlParserCtxtPtr ctxt) {
5213
0
    const xmlChar *name;
5214
5215
0
    name = xmlParseName(ctxt);
5216
0
    if ((name != NULL) &&
5217
0
        ((name[0] == 'x') || (name[0] == 'X')) &&
5218
0
        ((name[1] == 'm') || (name[1] == 'M')) &&
5219
0
        ((name[2] == 'l') || (name[2] == 'L'))) {
5220
0
  int i;
5221
0
  if ((name[0] == 'x') && (name[1] == 'm') &&
5222
0
      (name[2] == 'l') && (name[3] == 0)) {
5223
0
      xmlFatalErrMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
5224
0
     "XML declaration allowed only at the start of the document\n");
5225
0
      return(name);
5226
0
  } else if (name[3] == 0) {
5227
0
      xmlFatalErr(ctxt, XML_ERR_RESERVED_XML_NAME, NULL);
5228
0
      return(name);
5229
0
  }
5230
0
  for (i = 0;;i++) {
5231
0
      if (xmlW3CPIs[i] == NULL) break;
5232
0
      if (xmlStrEqual(name, (const xmlChar *)xmlW3CPIs[i]))
5233
0
          return(name);
5234
0
  }
5235
0
  xmlWarningMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
5236
0
          "xmlParsePITarget: invalid name prefix 'xml'\n",
5237
0
          NULL, NULL);
5238
0
    }
5239
0
    if ((name != NULL) && (xmlStrchr(name, ':') != NULL)) {
5240
0
  xmlNsErr(ctxt, XML_NS_ERR_COLON,
5241
0
     "colons are forbidden from PI names '%s'\n", name, NULL, NULL);
5242
0
    }
5243
0
    return(name);
5244
0
}
5245
5246
#ifdef LIBXML_CATALOG_ENABLED
5247
/**
5248
 * xmlParseCatalogPI:
5249
 * @ctxt:  an XML parser context
5250
 * @catalog:  the PI value string
5251
 *
5252
 * parse an XML Catalog Processing Instruction.
5253
 *
5254
 * <?oasis-xml-catalog catalog="http://example.com/catalog.xml"?>
5255
 *
5256
 * Occurs only if allowed by the user and if happening in the Misc
5257
 * part of the document before any doctype information
5258
 * This will add the given catalog to the parsing context in order
5259
 * to be used if there is a resolution need further down in the document
5260
 */
5261
5262
static void
5263
0
xmlParseCatalogPI(xmlParserCtxtPtr ctxt, const xmlChar *catalog) {
5264
0
    xmlChar *URL = NULL;
5265
0
    const xmlChar *tmp, *base;
5266
0
    xmlChar marker;
5267
5268
0
    tmp = catalog;
5269
0
    while (IS_BLANK_CH(*tmp)) tmp++;
5270
0
    if (xmlStrncmp(tmp, BAD_CAST"catalog", 7))
5271
0
  goto error;
5272
0
    tmp += 7;
5273
0
    while (IS_BLANK_CH(*tmp)) tmp++;
5274
0
    if (*tmp != '=') {
5275
0
  return;
5276
0
    }
5277
0
    tmp++;
5278
0
    while (IS_BLANK_CH(*tmp)) tmp++;
5279
0
    marker = *tmp;
5280
0
    if ((marker != '\'') && (marker != '"'))
5281
0
  goto error;
5282
0
    tmp++;
5283
0
    base = tmp;
5284
0
    while ((*tmp != 0) && (*tmp != marker)) tmp++;
5285
0
    if (*tmp == 0)
5286
0
  goto error;
5287
0
    URL = xmlStrndup(base, tmp - base);
5288
0
    tmp++;
5289
0
    while (IS_BLANK_CH(*tmp)) tmp++;
5290
0
    if (*tmp != 0)
5291
0
  goto error;
5292
5293
0
    if (URL != NULL) {
5294
0
  ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
5295
0
  xmlFree(URL);
5296
0
    }
5297
0
    return;
5298
5299
0
error:
5300
0
    xmlWarningMsg(ctxt, XML_WAR_CATALOG_PI,
5301
0
            "Catalog PI syntax error: %s\n",
5302
0
      catalog, NULL);
5303
0
    if (URL != NULL)
5304
0
  xmlFree(URL);
5305
0
}
5306
#endif
5307
5308
/**
5309
 * xmlParsePI:
5310
 * @ctxt:  an XML parser context
5311
 *
5312
 * DEPRECATED: Internal function, don't use.
5313
 *
5314
 * parse an XML Processing Instruction.
5315
 *
5316
 * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
5317
 *
5318
 * The processing is transferred to SAX once parsed.
5319
 */
5320
5321
void
5322
0
xmlParsePI(xmlParserCtxtPtr ctxt) {
5323
0
    xmlChar *buf = NULL;
5324
0
    size_t len = 0;
5325
0
    size_t size = XML_PARSER_BUFFER_SIZE;
5326
0
    size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
5327
0
                       XML_MAX_HUGE_LENGTH :
5328
0
                       XML_MAX_TEXT_LENGTH;
5329
0
    int cur, l;
5330
0
    const xmlChar *target;
5331
0
    xmlParserInputState state;
5332
5333
0
    if ((RAW == '<') && (NXT(1) == '?')) {
5334
0
  int inputid = ctxt->input->id;
5335
0
  state = ctxt->instate;
5336
0
        ctxt->instate = XML_PARSER_PI;
5337
  /*
5338
   * this is a Processing Instruction.
5339
   */
5340
0
  SKIP(2);
5341
5342
  /*
5343
   * Parse the target name and check for special support like
5344
   * namespace.
5345
   */
5346
0
        target = xmlParsePITarget(ctxt);
5347
0
  if (target != NULL) {
5348
0
      if ((RAW == '?') && (NXT(1) == '>')) {
5349
0
    if (inputid != ctxt->input->id) {
5350
0
        xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5351
0
                             "PI declaration doesn't start and stop in"
5352
0
                                   " the same entity\n");
5353
0
    }
5354
0
    SKIP(2);
5355
5356
    /*
5357
     * SAX: PI detected.
5358
     */
5359
0
    if ((ctxt->sax) && (!ctxt->disableSAX) &&
5360
0
        (ctxt->sax->processingInstruction != NULL))
5361
0
        ctxt->sax->processingInstruction(ctxt->userData,
5362
0
                                         target, NULL);
5363
0
    if (ctxt->instate != XML_PARSER_EOF)
5364
0
        ctxt->instate = state;
5365
0
    return;
5366
0
      }
5367
0
      buf = (xmlChar *) xmlMallocAtomic(size);
5368
0
      if (buf == NULL) {
5369
0
    xmlErrMemory(ctxt, NULL);
5370
0
    ctxt->instate = state;
5371
0
    return;
5372
0
      }
5373
0
      if (SKIP_BLANKS == 0) {
5374
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_SPACE_REQUIRED,
5375
0
        "ParsePI: PI %s space expected\n", target);
5376
0
      }
5377
0
      cur = CUR_CHAR(l);
5378
0
      while (IS_CHAR(cur) && /* checked */
5379
0
       ((cur != '?') || (NXT(1) != '>'))) {
5380
0
    if (len + 5 >= size) {
5381
0
        xmlChar *tmp;
5382
0
                    size_t new_size = size * 2;
5383
0
        tmp = (xmlChar *) xmlRealloc(buf, new_size);
5384
0
        if (tmp == NULL) {
5385
0
      xmlErrMemory(ctxt, NULL);
5386
0
      xmlFree(buf);
5387
0
      ctxt->instate = state;
5388
0
      return;
5389
0
        }
5390
0
        buf = tmp;
5391
0
                    size = new_size;
5392
0
    }
5393
0
    COPY_BUF(buf, len, cur);
5394
0
                if (len > maxLength) {
5395
0
                    xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
5396
0
                                      "PI %s too big found", target);
5397
0
                    xmlFree(buf);
5398
0
                    ctxt->instate = state;
5399
0
                    return;
5400
0
                }
5401
0
    NEXTL(l);
5402
0
    cur = CUR_CHAR(l);
5403
0
      }
5404
0
      buf[len] = 0;
5405
0
            if (ctxt->instate == XML_PARSER_EOF) {
5406
0
                xmlFree(buf);
5407
0
                return;
5408
0
            }
5409
0
      if (cur != '?') {
5410
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
5411
0
          "ParsePI: PI %s never end ...\n", target);
5412
0
      } else {
5413
0
    if (inputid != ctxt->input->id) {
5414
0
        xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5415
0
                             "PI declaration doesn't start and stop in"
5416
0
                                   " the same entity\n");
5417
0
    }
5418
0
    SKIP(2);
5419
5420
0
#ifdef LIBXML_CATALOG_ENABLED
5421
0
    if (((state == XML_PARSER_MISC) ||
5422
0
               (state == XML_PARSER_START)) &&
5423
0
        (xmlStrEqual(target, XML_CATALOG_PI))) {
5424
0
        xmlCatalogAllow allow = xmlCatalogGetDefaults();
5425
0
        if ((allow == XML_CATA_ALLOW_DOCUMENT) ||
5426
0
      (allow == XML_CATA_ALLOW_ALL))
5427
0
      xmlParseCatalogPI(ctxt, buf);
5428
0
    }
5429
0
#endif
5430
5431
5432
    /*
5433
     * SAX: PI detected.
5434
     */
5435
0
    if ((ctxt->sax) && (!ctxt->disableSAX) &&
5436
0
        (ctxt->sax->processingInstruction != NULL))
5437
0
        ctxt->sax->processingInstruction(ctxt->userData,
5438
0
                                         target, buf);
5439
0
      }
5440
0
      xmlFree(buf);
5441
0
  } else {
5442
0
      xmlFatalErr(ctxt, XML_ERR_PI_NOT_STARTED, NULL);
5443
0
  }
5444
0
  if (ctxt->instate != XML_PARSER_EOF)
5445
0
      ctxt->instate = state;
5446
0
    }
5447
0
}
5448
5449
/**
5450
 * xmlParseNotationDecl:
5451
 * @ctxt:  an XML parser context
5452
 *
5453
 * DEPRECATED: Internal function, don't use.
5454
 *
5455
 * Parse a notation declaration. Always consumes '<!'.
5456
 *
5457
 * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID |  PublicID) S? '>'
5458
 *
5459
 * Hence there is actually 3 choices:
5460
 *     'PUBLIC' S PubidLiteral
5461
 *     'PUBLIC' S PubidLiteral S SystemLiteral
5462
 * and 'SYSTEM' S SystemLiteral
5463
 *
5464
 * See the NOTE on xmlParseExternalID().
5465
 */
5466
5467
void
5468
0
xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
5469
0
    const xmlChar *name;
5470
0
    xmlChar *Pubid;
5471
0
    xmlChar *Systemid;
5472
5473
0
    if ((CUR != '<') || (NXT(1) != '!'))
5474
0
        return;
5475
0
    SKIP(2);
5476
5477
0
    if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
5478
0
  int inputid = ctxt->input->id;
5479
0
  SKIP(8);
5480
0
  if (SKIP_BLANKS == 0) {
5481
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5482
0
         "Space required after '<!NOTATION'\n");
5483
0
      return;
5484
0
  }
5485
5486
0
        name = xmlParseName(ctxt);
5487
0
  if (name == NULL) {
5488
0
      xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
5489
0
      return;
5490
0
  }
5491
0
  if (xmlStrchr(name, ':') != NULL) {
5492
0
      xmlNsErr(ctxt, XML_NS_ERR_COLON,
5493
0
         "colons are forbidden from notation names '%s'\n",
5494
0
         name, NULL, NULL);
5495
0
  }
5496
0
  if (SKIP_BLANKS == 0) {
5497
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5498
0
         "Space required after the NOTATION name'\n");
5499
0
      return;
5500
0
  }
5501
5502
  /*
5503
   * Parse the IDs.
5504
   */
5505
0
  Systemid = xmlParseExternalID(ctxt, &Pubid, 0);
5506
0
  SKIP_BLANKS;
5507
5508
0
  if (RAW == '>') {
5509
0
      if (inputid != ctxt->input->id) {
5510
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5511
0
                         "Notation declaration doesn't start and stop"
5512
0
                               " in the same entity\n");
5513
0
      }
5514
0
      NEXT;
5515
0
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
5516
0
    (ctxt->sax->notationDecl != NULL))
5517
0
    ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
5518
0
  } else {
5519
0
      xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
5520
0
  }
5521
0
  if (Systemid != NULL) xmlFree(Systemid);
5522
0
  if (Pubid != NULL) xmlFree(Pubid);
5523
0
    }
5524
0
}
5525
5526
/**
5527
 * xmlParseEntityDecl:
5528
 * @ctxt:  an XML parser context
5529
 *
5530
 * DEPRECATED: Internal function, don't use.
5531
 *
5532
 * Parse an entity declaration. Always consumes '<!'.
5533
 *
5534
 * [70] EntityDecl ::= GEDecl | PEDecl
5535
 *
5536
 * [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
5537
 *
5538
 * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
5539
 *
5540
 * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
5541
 *
5542
 * [74] PEDef ::= EntityValue | ExternalID
5543
 *
5544
 * [76] NDataDecl ::= S 'NDATA' S Name
5545
 *
5546
 * [ VC: Notation Declared ]
5547
 * The Name must match the declared name of a notation.
5548
 */
5549
5550
void
5551
0
xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
5552
0
    const xmlChar *name = NULL;
5553
0
    xmlChar *value = NULL;
5554
0
    xmlChar *URI = NULL, *literal = NULL;
5555
0
    const xmlChar *ndata = NULL;
5556
0
    int isParameter = 0;
5557
0
    xmlChar *orig = NULL;
5558
5559
0
    if ((CUR != '<') || (NXT(1) != '!'))
5560
0
        return;
5561
0
    SKIP(2);
5562
5563
    /* GROW; done in the caller */
5564
0
    if (CMP6(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'Y')) {
5565
0
  int inputid = ctxt->input->id;
5566
0
  SKIP(6);
5567
0
  if (SKIP_BLANKS == 0) {
5568
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5569
0
         "Space required after '<!ENTITY'\n");
5570
0
  }
5571
5572
0
  if (RAW == '%') {
5573
0
      NEXT;
5574
0
      if (SKIP_BLANKS == 0) {
5575
0
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5576
0
             "Space required after '%%'\n");
5577
0
      }
5578
0
      isParameter = 1;
5579
0
  }
5580
5581
0
        name = xmlParseName(ctxt);
5582
0
  if (name == NULL) {
5583
0
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
5584
0
                     "xmlParseEntityDecl: no name\n");
5585
0
            return;
5586
0
  }
5587
0
  if (xmlStrchr(name, ':') != NULL) {
5588
0
      xmlNsErr(ctxt, XML_NS_ERR_COLON,
5589
0
         "colons are forbidden from entities names '%s'\n",
5590
0
         name, NULL, NULL);
5591
0
  }
5592
0
  if (SKIP_BLANKS == 0) {
5593
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5594
0
         "Space required after the entity name\n");
5595
0
  }
5596
5597
0
  ctxt->instate = XML_PARSER_ENTITY_DECL;
5598
  /*
5599
   * handle the various case of definitions...
5600
   */
5601
0
  if (isParameter) {
5602
0
      if ((RAW == '"') || (RAW == '\'')) {
5603
0
          value = xmlParseEntityValue(ctxt, &orig);
5604
0
    if (value) {
5605
0
        if ((ctxt->sax != NULL) &&
5606
0
      (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5607
0
      ctxt->sax->entityDecl(ctxt->userData, name,
5608
0
                        XML_INTERNAL_PARAMETER_ENTITY,
5609
0
            NULL, NULL, value);
5610
0
    }
5611
0
      } else {
5612
0
          URI = xmlParseExternalID(ctxt, &literal, 1);
5613
0
    if ((URI == NULL) && (literal == NULL)) {
5614
0
        xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
5615
0
    }
5616
0
    if (URI) {
5617
0
        xmlURIPtr uri;
5618
5619
0
        uri = xmlParseURI((const char *) URI);
5620
0
        if (uri == NULL) {
5621
0
            xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
5622
0
             "Invalid URI: %s\n", URI);
5623
      /*
5624
       * This really ought to be a well formedness error
5625
       * but the XML Core WG decided otherwise c.f. issue
5626
       * E26 of the XML erratas.
5627
       */
5628
0
        } else {
5629
0
      if (uri->fragment != NULL) {
5630
          /*
5631
           * Okay this is foolish to block those but not
5632
           * invalid URIs.
5633
           */
5634
0
          xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
5635
0
      } else {
5636
0
          if ((ctxt->sax != NULL) &&
5637
0
        (!ctxt->disableSAX) &&
5638
0
        (ctxt->sax->entityDecl != NULL))
5639
0
        ctxt->sax->entityDecl(ctxt->userData, name,
5640
0
              XML_EXTERNAL_PARAMETER_ENTITY,
5641
0
              literal, URI, NULL);
5642
0
      }
5643
0
      xmlFreeURI(uri);
5644
0
        }
5645
0
    }
5646
0
      }
5647
0
  } else {
5648
0
      if ((RAW == '"') || (RAW == '\'')) {
5649
0
          value = xmlParseEntityValue(ctxt, &orig);
5650
0
    if ((ctxt->sax != NULL) &&
5651
0
        (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5652
0
        ctxt->sax->entityDecl(ctxt->userData, name,
5653
0
        XML_INTERNAL_GENERAL_ENTITY,
5654
0
        NULL, NULL, value);
5655
    /*
5656
     * For expat compatibility in SAX mode.
5657
     */
5658
0
    if ((ctxt->myDoc == NULL) ||
5659
0
        (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
5660
0
        if (ctxt->myDoc == NULL) {
5661
0
      ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
5662
0
      if (ctxt->myDoc == NULL) {
5663
0
          xmlErrMemory(ctxt, "New Doc failed");
5664
0
          goto done;
5665
0
      }
5666
0
      ctxt->myDoc->properties = XML_DOC_INTERNAL;
5667
0
        }
5668
0
        if (ctxt->myDoc->intSubset == NULL)
5669
0
      ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
5670
0
              BAD_CAST "fake", NULL, NULL);
5671
5672
0
        xmlSAX2EntityDecl(ctxt, name, XML_INTERNAL_GENERAL_ENTITY,
5673
0
                    NULL, NULL, value);
5674
0
    }
5675
0
      } else {
5676
0
          URI = xmlParseExternalID(ctxt, &literal, 1);
5677
0
    if ((URI == NULL) && (literal == NULL)) {
5678
0
        xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
5679
0
    }
5680
0
    if (URI) {
5681
0
        xmlURIPtr uri;
5682
5683
0
        uri = xmlParseURI((const char *)URI);
5684
0
        if (uri == NULL) {
5685
0
            xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
5686
0
             "Invalid URI: %s\n", URI);
5687
      /*
5688
       * This really ought to be a well formedness error
5689
       * but the XML Core WG decided otherwise c.f. issue
5690
       * E26 of the XML erratas.
5691
       */
5692
0
        } else {
5693
0
      if (uri->fragment != NULL) {
5694
          /*
5695
           * Okay this is foolish to block those but not
5696
           * invalid URIs.
5697
           */
5698
0
          xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
5699
0
      }
5700
0
      xmlFreeURI(uri);
5701
0
        }
5702
0
    }
5703
0
    if ((RAW != '>') && (SKIP_BLANKS == 0)) {
5704
0
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5705
0
           "Space required before 'NDATA'\n");
5706
0
    }
5707
0
    if (CMP5(CUR_PTR, 'N', 'D', 'A', 'T', 'A')) {
5708
0
        SKIP(5);
5709
0
        if (SKIP_BLANKS == 0) {
5710
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5711
0
               "Space required after 'NDATA'\n");
5712
0
        }
5713
0
        ndata = xmlParseName(ctxt);
5714
0
        if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
5715
0
            (ctxt->sax->unparsedEntityDecl != NULL))
5716
0
      ctxt->sax->unparsedEntityDecl(ctxt->userData, name,
5717
0
            literal, URI, ndata);
5718
0
    } else {
5719
0
        if ((ctxt->sax != NULL) &&
5720
0
            (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5721
0
      ctxt->sax->entityDecl(ctxt->userData, name,
5722
0
            XML_EXTERNAL_GENERAL_PARSED_ENTITY,
5723
0
            literal, URI, NULL);
5724
        /*
5725
         * For expat compatibility in SAX mode.
5726
         * assuming the entity replacement was asked for
5727
         */
5728
0
        if ((ctxt->replaceEntities != 0) &&
5729
0
      ((ctxt->myDoc == NULL) ||
5730
0
      (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE)))) {
5731
0
      if (ctxt->myDoc == NULL) {
5732
0
          ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
5733
0
          if (ctxt->myDoc == NULL) {
5734
0
              xmlErrMemory(ctxt, "New Doc failed");
5735
0
        goto done;
5736
0
          }
5737
0
          ctxt->myDoc->properties = XML_DOC_INTERNAL;
5738
0
      }
5739
5740
0
      if (ctxt->myDoc->intSubset == NULL)
5741
0
          ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
5742
0
            BAD_CAST "fake", NULL, NULL);
5743
0
      xmlSAX2EntityDecl(ctxt, name,
5744
0
                  XML_EXTERNAL_GENERAL_PARSED_ENTITY,
5745
0
                  literal, URI, NULL);
5746
0
        }
5747
0
    }
5748
0
      }
5749
0
  }
5750
0
  if (ctxt->instate == XML_PARSER_EOF)
5751
0
      goto done;
5752
0
  SKIP_BLANKS;
5753
0
  if (RAW != '>') {
5754
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
5755
0
              "xmlParseEntityDecl: entity %s not terminated\n", name);
5756
0
      xmlHaltParser(ctxt);
5757
0
  } else {
5758
0
      if (inputid != ctxt->input->id) {
5759
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5760
0
                         "Entity declaration doesn't start and stop in"
5761
0
                               " the same entity\n");
5762
0
      }
5763
0
      NEXT;
5764
0
  }
5765
0
  if (orig != NULL) {
5766
      /*
5767
       * Ugly mechanism to save the raw entity value.
5768
       */
5769
0
      xmlEntityPtr cur = NULL;
5770
5771
0
      if (isParameter) {
5772
0
          if ((ctxt->sax != NULL) &&
5773
0
        (ctxt->sax->getParameterEntity != NULL))
5774
0
        cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
5775
0
      } else {
5776
0
          if ((ctxt->sax != NULL) &&
5777
0
        (ctxt->sax->getEntity != NULL))
5778
0
        cur = ctxt->sax->getEntity(ctxt->userData, name);
5779
0
    if ((cur == NULL) && (ctxt->userData==ctxt)) {
5780
0
        cur = xmlSAX2GetEntity(ctxt, name);
5781
0
    }
5782
0
      }
5783
0
            if ((cur != NULL) && (cur->orig == NULL)) {
5784
0
    cur->orig = orig;
5785
0
                orig = NULL;
5786
0
      }
5787
0
  }
5788
5789
0
done:
5790
0
  if (value != NULL) xmlFree(value);
5791
0
  if (URI != NULL) xmlFree(URI);
5792
0
  if (literal != NULL) xmlFree(literal);
5793
0
        if (orig != NULL) xmlFree(orig);
5794
0
    }
5795
0
}
5796
5797
/**
5798
 * xmlParseDefaultDecl:
5799
 * @ctxt:  an XML parser context
5800
 * @value:  Receive a possible fixed default value for the attribute
5801
 *
5802
 * DEPRECATED: Internal function, don't use.
5803
 *
5804
 * Parse an attribute default declaration
5805
 *
5806
 * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
5807
 *
5808
 * [ VC: Required Attribute ]
5809
 * if the default declaration is the keyword #REQUIRED, then the
5810
 * attribute must be specified for all elements of the type in the
5811
 * attribute-list declaration.
5812
 *
5813
 * [ VC: Attribute Default Legal ]
5814
 * The declared default value must meet the lexical constraints of
5815
 * the declared attribute type c.f. xmlValidateAttributeDecl()
5816
 *
5817
 * [ VC: Fixed Attribute Default ]
5818
 * if an attribute has a default value declared with the #FIXED
5819
 * keyword, instances of that attribute must match the default value.
5820
 *
5821
 * [ WFC: No < in Attribute Values ]
5822
 * handled in xmlParseAttValue()
5823
 *
5824
 * returns: XML_ATTRIBUTE_NONE, XML_ATTRIBUTE_REQUIRED, XML_ATTRIBUTE_IMPLIED
5825
 *          or XML_ATTRIBUTE_FIXED.
5826
 */
5827
5828
int
5829
0
xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
5830
0
    int val;
5831
0
    xmlChar *ret;
5832
5833
0
    *value = NULL;
5834
0
    if (CMP9(CUR_PTR, '#', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D')) {
5835
0
  SKIP(9);
5836
0
  return(XML_ATTRIBUTE_REQUIRED);
5837
0
    }
5838
0
    if (CMP8(CUR_PTR, '#', 'I', 'M', 'P', 'L', 'I', 'E', 'D')) {
5839
0
  SKIP(8);
5840
0
  return(XML_ATTRIBUTE_IMPLIED);
5841
0
    }
5842
0
    val = XML_ATTRIBUTE_NONE;
5843
0
    if (CMP6(CUR_PTR, '#', 'F', 'I', 'X', 'E', 'D')) {
5844
0
  SKIP(6);
5845
0
  val = XML_ATTRIBUTE_FIXED;
5846
0
  if (SKIP_BLANKS == 0) {
5847
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5848
0
         "Space required after '#FIXED'\n");
5849
0
  }
5850
0
    }
5851
0
    ret = xmlParseAttValue(ctxt);
5852
0
    ctxt->instate = XML_PARSER_DTD;
5853
0
    if (ret == NULL) {
5854
0
  xmlFatalErrMsg(ctxt, (xmlParserErrors)ctxt->errNo,
5855
0
           "Attribute default value declaration error\n");
5856
0
    } else
5857
0
        *value = ret;
5858
0
    return(val);
5859
0
}
5860
5861
/**
5862
 * xmlParseNotationType:
5863
 * @ctxt:  an XML parser context
5864
 *
5865
 * DEPRECATED: Internal function, don't use.
5866
 *
5867
 * parse an Notation attribute type.
5868
 *
5869
 * Note: the leading 'NOTATION' S part has already being parsed...
5870
 *
5871
 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
5872
 *
5873
 * [ VC: Notation Attributes ]
5874
 * Values of this type must match one of the notation names included
5875
 * in the declaration; all notation names in the declaration must be declared.
5876
 *
5877
 * Returns: the notation attribute tree built while parsing
5878
 */
5879
5880
xmlEnumerationPtr
5881
0
xmlParseNotationType(xmlParserCtxtPtr ctxt) {
5882
0
    const xmlChar *name;
5883
0
    xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
5884
5885
0
    if (RAW != '(') {
5886
0
  xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
5887
0
  return(NULL);
5888
0
    }
5889
0
    do {
5890
0
        NEXT;
5891
0
  SKIP_BLANKS;
5892
0
        name = xmlParseName(ctxt);
5893
0
  if (name == NULL) {
5894
0
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
5895
0
         "Name expected in NOTATION declaration\n");
5896
0
            xmlFreeEnumeration(ret);
5897
0
      return(NULL);
5898
0
  }
5899
0
  tmp = ret;
5900
0
  while (tmp != NULL) {
5901
0
      if (xmlStrEqual(name, tmp->name)) {
5902
0
    xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
5903
0
    "standalone: attribute notation value token %s duplicated\n",
5904
0
         name, NULL);
5905
0
    if (!xmlDictOwns(ctxt->dict, name))
5906
0
        xmlFree((xmlChar *) name);
5907
0
    break;
5908
0
      }
5909
0
      tmp = tmp->next;
5910
0
  }
5911
0
  if (tmp == NULL) {
5912
0
      cur = xmlCreateEnumeration(name);
5913
0
      if (cur == NULL) {
5914
0
                xmlFreeEnumeration(ret);
5915
0
                return(NULL);
5916
0
            }
5917
0
      if (last == NULL) ret = last = cur;
5918
0
      else {
5919
0
    last->next = cur;
5920
0
    last = cur;
5921
0
      }
5922
0
  }
5923
0
  SKIP_BLANKS;
5924
0
    } while (RAW == '|');
5925
0
    if (RAW != ')') {
5926
0
  xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
5927
0
        xmlFreeEnumeration(ret);
5928
0
  return(NULL);
5929
0
    }
5930
0
    NEXT;
5931
0
    return(ret);
5932
0
}
5933
5934
/**
5935
 * xmlParseEnumerationType:
5936
 * @ctxt:  an XML parser context
5937
 *
5938
 * DEPRECATED: Internal function, don't use.
5939
 *
5940
 * parse an Enumeration attribute type.
5941
 *
5942
 * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
5943
 *
5944
 * [ VC: Enumeration ]
5945
 * Values of this type must match one of the Nmtoken tokens in
5946
 * the declaration
5947
 *
5948
 * Returns: the enumeration attribute tree built while parsing
5949
 */
5950
5951
xmlEnumerationPtr
5952
0
xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
5953
0
    xmlChar *name;
5954
0
    xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
5955
5956
0
    if (RAW != '(') {
5957
0
  xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_STARTED, NULL);
5958
0
  return(NULL);
5959
0
    }
5960
0
    do {
5961
0
        NEXT;
5962
0
  SKIP_BLANKS;
5963
0
        name = xmlParseNmtoken(ctxt);
5964
0
  if (name == NULL) {
5965
0
      xmlFatalErr(ctxt, XML_ERR_NMTOKEN_REQUIRED, NULL);
5966
0
      return(ret);
5967
0
  }
5968
0
  tmp = ret;
5969
0
  while (tmp != NULL) {
5970
0
      if (xmlStrEqual(name, tmp->name)) {
5971
0
    xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
5972
0
    "standalone: attribute enumeration value token %s duplicated\n",
5973
0
         name, NULL);
5974
0
    if (!xmlDictOwns(ctxt->dict, name))
5975
0
        xmlFree(name);
5976
0
    break;
5977
0
      }
5978
0
      tmp = tmp->next;
5979
0
  }
5980
0
  if (tmp == NULL) {
5981
0
      cur = xmlCreateEnumeration(name);
5982
0
      if (!xmlDictOwns(ctxt->dict, name))
5983
0
    xmlFree(name);
5984
0
      if (cur == NULL) {
5985
0
                xmlFreeEnumeration(ret);
5986
0
                return(NULL);
5987
0
            }
5988
0
      if (last == NULL) ret = last = cur;
5989
0
      else {
5990
0
    last->next = cur;
5991
0
    last = cur;
5992
0
      }
5993
0
  }
5994
0
  SKIP_BLANKS;
5995
0
    } while (RAW == '|');
5996
0
    if (RAW != ')') {
5997
0
  xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_FINISHED, NULL);
5998
0
  return(ret);
5999
0
    }
6000
0
    NEXT;
6001
0
    return(ret);
6002
0
}
6003
6004
/**
6005
 * xmlParseEnumeratedType:
6006
 * @ctxt:  an XML parser context
6007
 * @tree:  the enumeration tree built while parsing
6008
 *
6009
 * DEPRECATED: Internal function, don't use.
6010
 *
6011
 * parse an Enumerated attribute type.
6012
 *
6013
 * [57] EnumeratedType ::= NotationType | Enumeration
6014
 *
6015
 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
6016
 *
6017
 *
6018
 * Returns: XML_ATTRIBUTE_ENUMERATION or XML_ATTRIBUTE_NOTATION
6019
 */
6020
6021
int
6022
0
xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
6023
0
    if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
6024
0
  SKIP(8);
6025
0
  if (SKIP_BLANKS == 0) {
6026
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6027
0
         "Space required after 'NOTATION'\n");
6028
0
      return(0);
6029
0
  }
6030
0
  *tree = xmlParseNotationType(ctxt);
6031
0
  if (*tree == NULL) return(0);
6032
0
  return(XML_ATTRIBUTE_NOTATION);
6033
0
    }
6034
0
    *tree = xmlParseEnumerationType(ctxt);
6035
0
    if (*tree == NULL) return(0);
6036
0
    return(XML_ATTRIBUTE_ENUMERATION);
6037
0
}
6038
6039
/**
6040
 * xmlParseAttributeType:
6041
 * @ctxt:  an XML parser context
6042
 * @tree:  the enumeration tree built while parsing
6043
 *
6044
 * DEPRECATED: Internal function, don't use.
6045
 *
6046
 * parse the Attribute list def for an element
6047
 *
6048
 * [54] AttType ::= StringType | TokenizedType | EnumeratedType
6049
 *
6050
 * [55] StringType ::= 'CDATA'
6051
 *
6052
 * [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' |
6053
 *                        'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
6054
 *
6055
 * Validity constraints for attribute values syntax are checked in
6056
 * xmlValidateAttributeValue()
6057
 *
6058
 * [ VC: ID ]
6059
 * Values of type ID must match the Name production. A name must not
6060
 * appear more than once in an XML document as a value of this type;
6061
 * i.e., ID values must uniquely identify the elements which bear them.
6062
 *
6063
 * [ VC: One ID per Element Type ]
6064
 * No element type may have more than one ID attribute specified.
6065
 *
6066
 * [ VC: ID Attribute Default ]
6067
 * An ID attribute must have a declared default of #IMPLIED or #REQUIRED.
6068
 *
6069
 * [ VC: IDREF ]
6070
 * Values of type IDREF must match the Name production, and values
6071
 * of type IDREFS must match Names; each IDREF Name must match the value
6072
 * of an ID attribute on some element in the XML document; i.e. IDREF
6073
 * values must match the value of some ID attribute.
6074
 *
6075
 * [ VC: Entity Name ]
6076
 * Values of type ENTITY must match the Name production, values
6077
 * of type ENTITIES must match Names; each Entity Name must match the
6078
 * name of an unparsed entity declared in the DTD.
6079
 *
6080
 * [ VC: Name Token ]
6081
 * Values of type NMTOKEN must match the Nmtoken production; values
6082
 * of type NMTOKENS must match Nmtokens.
6083
 *
6084
 * Returns the attribute type
6085
 */
6086
int
6087
0
xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
6088
0
    if (CMP5(CUR_PTR, 'C', 'D', 'A', 'T', 'A')) {
6089
0
  SKIP(5);
6090
0
  return(XML_ATTRIBUTE_CDATA);
6091
0
     } else if (CMP6(CUR_PTR, 'I', 'D', 'R', 'E', 'F', 'S')) {
6092
0
  SKIP(6);
6093
0
  return(XML_ATTRIBUTE_IDREFS);
6094
0
     } else if (CMP5(CUR_PTR, 'I', 'D', 'R', 'E', 'F')) {
6095
0
  SKIP(5);
6096
0
  return(XML_ATTRIBUTE_IDREF);
6097
0
     } else if ((RAW == 'I') && (NXT(1) == 'D')) {
6098
0
        SKIP(2);
6099
0
  return(XML_ATTRIBUTE_ID);
6100
0
     } else if (CMP6(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'Y')) {
6101
0
  SKIP(6);
6102
0
  return(XML_ATTRIBUTE_ENTITY);
6103
0
     } else if (CMP8(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S')) {
6104
0
  SKIP(8);
6105
0
  return(XML_ATTRIBUTE_ENTITIES);
6106
0
     } else if (CMP8(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S')) {
6107
0
  SKIP(8);
6108
0
  return(XML_ATTRIBUTE_NMTOKENS);
6109
0
     } else if (CMP7(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N')) {
6110
0
  SKIP(7);
6111
0
  return(XML_ATTRIBUTE_NMTOKEN);
6112
0
     }
6113
0
     return(xmlParseEnumeratedType(ctxt, tree));
6114
0
}
6115
6116
/**
6117
 * xmlParseAttributeListDecl:
6118
 * @ctxt:  an XML parser context
6119
 *
6120
 * DEPRECATED: Internal function, don't use.
6121
 *
6122
 * Parse an attribute list declaration for an element. Always consumes '<!'.
6123
 *
6124
 * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
6125
 *
6126
 * [53] AttDef ::= S Name S AttType S DefaultDecl
6127
 *
6128
 */
6129
void
6130
0
xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
6131
0
    const xmlChar *elemName;
6132
0
    const xmlChar *attrName;
6133
0
    xmlEnumerationPtr tree;
6134
6135
0
    if ((CUR != '<') || (NXT(1) != '!'))
6136
0
        return;
6137
0
    SKIP(2);
6138
6139
0
    if (CMP7(CUR_PTR, 'A', 'T', 'T', 'L', 'I', 'S', 'T')) {
6140
0
  int inputid = ctxt->input->id;
6141
6142
0
  SKIP(7);
6143
0
  if (SKIP_BLANKS == 0) {
6144
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6145
0
                     "Space required after '<!ATTLIST'\n");
6146
0
  }
6147
0
        elemName = xmlParseName(ctxt);
6148
0
  if (elemName == NULL) {
6149
0
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6150
0
         "ATTLIST: no name for Element\n");
6151
0
      return;
6152
0
  }
6153
0
  SKIP_BLANKS;
6154
0
  GROW;
6155
0
  while ((RAW != '>') && (ctxt->instate != XML_PARSER_EOF)) {
6156
0
      int type;
6157
0
      int def;
6158
0
      xmlChar *defaultValue = NULL;
6159
6160
0
      GROW;
6161
0
            tree = NULL;
6162
0
      attrName = xmlParseName(ctxt);
6163
0
      if (attrName == NULL) {
6164
0
    xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6165
0
             "ATTLIST: no name for Attribute\n");
6166
0
    break;
6167
0
      }
6168
0
      GROW;
6169
0
      if (SKIP_BLANKS == 0) {
6170
0
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6171
0
            "Space required after the attribute name\n");
6172
0
    break;
6173
0
      }
6174
6175
0
      type = xmlParseAttributeType(ctxt, &tree);
6176
0
      if (type <= 0) {
6177
0
          break;
6178
0
      }
6179
6180
0
      GROW;
6181
0
      if (SKIP_BLANKS == 0) {
6182
0
    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6183
0
             "Space required after the attribute type\n");
6184
0
          if (tree != NULL)
6185
0
        xmlFreeEnumeration(tree);
6186
0
    break;
6187
0
      }
6188
6189
0
      def = xmlParseDefaultDecl(ctxt, &defaultValue);
6190
0
      if (def <= 0) {
6191
0
                if (defaultValue != NULL)
6192
0
        xmlFree(defaultValue);
6193
0
          if (tree != NULL)
6194
0
        xmlFreeEnumeration(tree);
6195
0
          break;
6196
0
      }
6197
0
      if ((type != XML_ATTRIBUTE_CDATA) && (defaultValue != NULL))
6198
0
          xmlAttrNormalizeSpace(defaultValue, defaultValue);
6199
6200
0
      GROW;
6201
0
            if (RAW != '>') {
6202
0
    if (SKIP_BLANKS == 0) {
6203
0
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6204
0
      "Space required after the attribute default value\n");
6205
0
        if (defaultValue != NULL)
6206
0
      xmlFree(defaultValue);
6207
0
        if (tree != NULL)
6208
0
      xmlFreeEnumeration(tree);
6209
0
        break;
6210
0
    }
6211
0
      }
6212
0
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
6213
0
    (ctxt->sax->attributeDecl != NULL))
6214
0
    ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
6215
0
                          type, def, defaultValue, tree);
6216
0
      else if (tree != NULL)
6217
0
    xmlFreeEnumeration(tree);
6218
6219
0
      if ((ctxt->sax2) && (defaultValue != NULL) &&
6220
0
          (def != XML_ATTRIBUTE_IMPLIED) &&
6221
0
    (def != XML_ATTRIBUTE_REQUIRED)) {
6222
0
    xmlAddDefAttrs(ctxt, elemName, attrName, defaultValue);
6223
0
      }
6224
0
      if (ctxt->sax2) {
6225
0
    xmlAddSpecialAttr(ctxt, elemName, attrName, type);
6226
0
      }
6227
0
      if (defaultValue != NULL)
6228
0
          xmlFree(defaultValue);
6229
0
      GROW;
6230
0
  }
6231
0
  if (RAW == '>') {
6232
0
      if (inputid != ctxt->input->id) {
6233
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6234
0
                               "Attribute list declaration doesn't start and"
6235
0
                               " stop in the same entity\n");
6236
0
      }
6237
0
      NEXT;
6238
0
  }
6239
0
    }
6240
0
}
6241
6242
/**
6243
 * xmlParseElementMixedContentDecl:
6244
 * @ctxt:  an XML parser context
6245
 * @inputchk:  the input used for the current entity, needed for boundary checks
6246
 *
6247
 * DEPRECATED: Internal function, don't use.
6248
 *
6249
 * parse the declaration for a Mixed Element content
6250
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6251
 *
6252
 * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' |
6253
 *                '(' S? '#PCDATA' S? ')'
6254
 *
6255
 * [ VC: Proper Group/PE Nesting ] applies to [51] too (see [49])
6256
 *
6257
 * [ VC: No Duplicate Types ]
6258
 * The same name must not appear more than once in a single
6259
 * mixed-content declaration.
6260
 *
6261
 * returns: the list of the xmlElementContentPtr describing the element choices
6262
 */
6263
xmlElementContentPtr
6264
0
xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
6265
0
    xmlElementContentPtr ret = NULL, cur = NULL, n;
6266
0
    const xmlChar *elem = NULL;
6267
6268
0
    GROW;
6269
0
    if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
6270
0
  SKIP(7);
6271
0
  SKIP_BLANKS;
6272
0
  if (RAW == ')') {
6273
0
      if (ctxt->input->id != inputchk) {
6274
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6275
0
                               "Element content declaration doesn't start and"
6276
0
                               " stop in the same entity\n");
6277
0
      }
6278
0
      NEXT;
6279
0
      ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
6280
0
      if (ret == NULL)
6281
0
          return(NULL);
6282
0
      if (RAW == '*') {
6283
0
    ret->ocur = XML_ELEMENT_CONTENT_MULT;
6284
0
    NEXT;
6285
0
      }
6286
0
      return(ret);
6287
0
  }
6288
0
  if ((RAW == '(') || (RAW == '|')) {
6289
0
      ret = cur = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
6290
0
      if (ret == NULL) return(NULL);
6291
0
  }
6292
0
  while ((RAW == '|') && (ctxt->instate != XML_PARSER_EOF)) {
6293
0
      NEXT;
6294
0
      if (elem == NULL) {
6295
0
          ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6296
0
    if (ret == NULL) {
6297
0
        xmlFreeDocElementContent(ctxt->myDoc, cur);
6298
0
                    return(NULL);
6299
0
                }
6300
0
    ret->c1 = cur;
6301
0
    if (cur != NULL)
6302
0
        cur->parent = ret;
6303
0
    cur = ret;
6304
0
      } else {
6305
0
          n = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6306
0
    if (n == NULL) {
6307
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6308
0
                    return(NULL);
6309
0
                }
6310
0
    n->c1 = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6311
0
    if (n->c1 != NULL)
6312
0
        n->c1->parent = n;
6313
0
          cur->c2 = n;
6314
0
    if (n != NULL)
6315
0
        n->parent = cur;
6316
0
    cur = n;
6317
0
      }
6318
0
      SKIP_BLANKS;
6319
0
      elem = xmlParseName(ctxt);
6320
0
      if (elem == NULL) {
6321
0
    xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6322
0
      "xmlParseElementMixedContentDecl : Name expected\n");
6323
0
    xmlFreeDocElementContent(ctxt->myDoc, ret);
6324
0
    return(NULL);
6325
0
      }
6326
0
      SKIP_BLANKS;
6327
0
      GROW;
6328
0
  }
6329
0
  if ((RAW == ')') && (NXT(1) == '*')) {
6330
0
      if (elem != NULL) {
6331
0
    cur->c2 = xmlNewDocElementContent(ctxt->myDoc, elem,
6332
0
                                   XML_ELEMENT_CONTENT_ELEMENT);
6333
0
    if (cur->c2 != NULL)
6334
0
        cur->c2->parent = cur;
6335
0
            }
6336
0
            if (ret != NULL)
6337
0
                ret->ocur = XML_ELEMENT_CONTENT_MULT;
6338
0
      if (ctxt->input->id != inputchk) {
6339
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6340
0
                               "Element content declaration doesn't start and"
6341
0
                               " stop in the same entity\n");
6342
0
      }
6343
0
      SKIP(2);
6344
0
  } else {
6345
0
      xmlFreeDocElementContent(ctxt->myDoc, ret);
6346
0
      xmlFatalErr(ctxt, XML_ERR_MIXED_NOT_STARTED, NULL);
6347
0
      return(NULL);
6348
0
  }
6349
6350
0
    } else {
6351
0
  xmlFatalErr(ctxt, XML_ERR_PCDATA_REQUIRED, NULL);
6352
0
    }
6353
0
    return(ret);
6354
0
}
6355
6356
/**
6357
 * xmlParseElementChildrenContentDeclPriv:
6358
 * @ctxt:  an XML parser context
6359
 * @inputchk:  the input used for the current entity, needed for boundary checks
6360
 * @depth: the level of recursion
6361
 *
6362
 * parse the declaration for a Mixed Element content
6363
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6364
 *
6365
 *
6366
 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
6367
 *
6368
 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
6369
 *
6370
 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
6371
 *
6372
 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
6373
 *
6374
 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
6375
 * TODO Parameter-entity replacement text must be properly nested
6376
 *  with parenthesized groups. That is to say, if either of the
6377
 *  opening or closing parentheses in a choice, seq, or Mixed
6378
 *  construct is contained in the replacement text for a parameter
6379
 *  entity, both must be contained in the same replacement text. For
6380
 *  interoperability, if a parameter-entity reference appears in a
6381
 *  choice, seq, or Mixed construct, its replacement text should not
6382
 *  be empty, and neither the first nor last non-blank character of
6383
 *  the replacement text should be a connector (| or ,).
6384
 *
6385
 * Returns the tree of xmlElementContentPtr describing the element
6386
 *          hierarchy.
6387
 */
6388
static xmlElementContentPtr
6389
xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
6390
0
                                       int depth) {
6391
0
    xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
6392
0
    const xmlChar *elem;
6393
0
    xmlChar type = 0;
6394
6395
0
    if (((depth > 128) && ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
6396
0
        (depth >  2048)) {
6397
0
        xmlFatalErrMsgInt(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED,
6398
0
"xmlParseElementChildrenContentDecl : depth %d too deep, use XML_PARSE_HUGE\n",
6399
0
                          depth);
6400
0
  return(NULL);
6401
0
    }
6402
0
    SKIP_BLANKS;
6403
0
    GROW;
6404
0
    if (RAW == '(') {
6405
0
  int inputid = ctxt->input->id;
6406
6407
        /* Recurse on first child */
6408
0
  NEXT;
6409
0
  SKIP_BLANKS;
6410
0
        cur = ret = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
6411
0
                                                           depth + 1);
6412
0
        if (cur == NULL)
6413
0
            return(NULL);
6414
0
  SKIP_BLANKS;
6415
0
  GROW;
6416
0
    } else {
6417
0
  elem = xmlParseName(ctxt);
6418
0
  if (elem == NULL) {
6419
0
      xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
6420
0
      return(NULL);
6421
0
  }
6422
0
        cur = ret = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6423
0
  if (cur == NULL) {
6424
0
      xmlErrMemory(ctxt, NULL);
6425
0
      return(NULL);
6426
0
  }
6427
0
  GROW;
6428
0
  if (RAW == '?') {
6429
0
      cur->ocur = XML_ELEMENT_CONTENT_OPT;
6430
0
      NEXT;
6431
0
  } else if (RAW == '*') {
6432
0
      cur->ocur = XML_ELEMENT_CONTENT_MULT;
6433
0
      NEXT;
6434
0
  } else if (RAW == '+') {
6435
0
      cur->ocur = XML_ELEMENT_CONTENT_PLUS;
6436
0
      NEXT;
6437
0
  } else {
6438
0
      cur->ocur = XML_ELEMENT_CONTENT_ONCE;
6439
0
  }
6440
0
  GROW;
6441
0
    }
6442
0
    SKIP_BLANKS;
6443
0
    while ((RAW != ')') && (ctxt->instate != XML_PARSER_EOF)) {
6444
        /*
6445
   * Each loop we parse one separator and one element.
6446
   */
6447
0
        if (RAW == ',') {
6448
0
      if (type == 0) type = CUR;
6449
6450
      /*
6451
       * Detect "Name | Name , Name" error
6452
       */
6453
0
      else if (type != CUR) {
6454
0
    xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
6455
0
        "xmlParseElementChildrenContentDecl : '%c' expected\n",
6456
0
                      type);
6457
0
    if ((last != NULL) && (last != ret))
6458
0
        xmlFreeDocElementContent(ctxt->myDoc, last);
6459
0
    if (ret != NULL)
6460
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6461
0
    return(NULL);
6462
0
      }
6463
0
      NEXT;
6464
6465
0
      op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_SEQ);
6466
0
      if (op == NULL) {
6467
0
    if ((last != NULL) && (last != ret))
6468
0
        xmlFreeDocElementContent(ctxt->myDoc, last);
6469
0
          xmlFreeDocElementContent(ctxt->myDoc, ret);
6470
0
    return(NULL);
6471
0
      }
6472
0
      if (last == NULL) {
6473
0
    op->c1 = ret;
6474
0
    if (ret != NULL)
6475
0
        ret->parent = op;
6476
0
    ret = cur = op;
6477
0
      } else {
6478
0
          cur->c2 = op;
6479
0
    if (op != NULL)
6480
0
        op->parent = cur;
6481
0
    op->c1 = last;
6482
0
    if (last != NULL)
6483
0
        last->parent = op;
6484
0
    cur =op;
6485
0
    last = NULL;
6486
0
      }
6487
0
  } else if (RAW == '|') {
6488
0
      if (type == 0) type = CUR;
6489
6490
      /*
6491
       * Detect "Name , Name | Name" error
6492
       */
6493
0
      else if (type != CUR) {
6494
0
    xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
6495
0
        "xmlParseElementChildrenContentDecl : '%c' expected\n",
6496
0
          type);
6497
0
    if ((last != NULL) && (last != ret))
6498
0
        xmlFreeDocElementContent(ctxt->myDoc, last);
6499
0
    if (ret != NULL)
6500
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6501
0
    return(NULL);
6502
0
      }
6503
0
      NEXT;
6504
6505
0
      op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6506
0
      if (op == NULL) {
6507
0
    if ((last != NULL) && (last != ret))
6508
0
        xmlFreeDocElementContent(ctxt->myDoc, last);
6509
0
    if (ret != NULL)
6510
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6511
0
    return(NULL);
6512
0
      }
6513
0
      if (last == NULL) {
6514
0
    op->c1 = ret;
6515
0
    if (ret != NULL)
6516
0
        ret->parent = op;
6517
0
    ret = cur = op;
6518
0
      } else {
6519
0
          cur->c2 = op;
6520
0
    if (op != NULL)
6521
0
        op->parent = cur;
6522
0
    op->c1 = last;
6523
0
    if (last != NULL)
6524
0
        last->parent = op;
6525
0
    cur =op;
6526
0
    last = NULL;
6527
0
      }
6528
0
  } else {
6529
0
      xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED, NULL);
6530
0
      if ((last != NULL) && (last != ret))
6531
0
          xmlFreeDocElementContent(ctxt->myDoc, last);
6532
0
      if (ret != NULL)
6533
0
    xmlFreeDocElementContent(ctxt->myDoc, ret);
6534
0
      return(NULL);
6535
0
  }
6536
0
  GROW;
6537
0
  SKIP_BLANKS;
6538
0
  GROW;
6539
0
  if (RAW == '(') {
6540
0
      int inputid = ctxt->input->id;
6541
      /* Recurse on second child */
6542
0
      NEXT;
6543
0
      SKIP_BLANKS;
6544
0
      last = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
6545
0
                                                          depth + 1);
6546
0
            if (last == NULL) {
6547
0
    if (ret != NULL)
6548
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6549
0
    return(NULL);
6550
0
            }
6551
0
      SKIP_BLANKS;
6552
0
  } else {
6553
0
      elem = xmlParseName(ctxt);
6554
0
      if (elem == NULL) {
6555
0
    xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
6556
0
    if (ret != NULL)
6557
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6558
0
    return(NULL);
6559
0
      }
6560
0
      last = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6561
0
      if (last == NULL) {
6562
0
    if (ret != NULL)
6563
0
        xmlFreeDocElementContent(ctxt->myDoc, ret);
6564
0
    return(NULL);
6565
0
      }
6566
0
      if (RAW == '?') {
6567
0
    last->ocur = XML_ELEMENT_CONTENT_OPT;
6568
0
    NEXT;
6569
0
      } else if (RAW == '*') {
6570
0
    last->ocur = XML_ELEMENT_CONTENT_MULT;
6571
0
    NEXT;
6572
0
      } else if (RAW == '+') {
6573
0
    last->ocur = XML_ELEMENT_CONTENT_PLUS;
6574
0
    NEXT;
6575
0
      } else {
6576
0
    last->ocur = XML_ELEMENT_CONTENT_ONCE;
6577
0
      }
6578
0
  }
6579
0
  SKIP_BLANKS;
6580
0
  GROW;
6581
0
    }
6582
0
    if ((cur != NULL) && (last != NULL)) {
6583
0
        cur->c2 = last;
6584
0
  if (last != NULL)
6585
0
      last->parent = cur;
6586
0
    }
6587
0
    if (ctxt->input->id != inputchk) {
6588
0
  xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6589
0
                       "Element content declaration doesn't start and stop in"
6590
0
                       " the same entity\n");
6591
0
    }
6592
0
    NEXT;
6593
0
    if (RAW == '?') {
6594
0
  if (ret != NULL) {
6595
0
      if ((ret->ocur == XML_ELEMENT_CONTENT_PLUS) ||
6596
0
          (ret->ocur == XML_ELEMENT_CONTENT_MULT))
6597
0
          ret->ocur = XML_ELEMENT_CONTENT_MULT;
6598
0
      else
6599
0
          ret->ocur = XML_ELEMENT_CONTENT_OPT;
6600
0
  }
6601
0
  NEXT;
6602
0
    } else if (RAW == '*') {
6603
0
  if (ret != NULL) {
6604
0
      ret->ocur = XML_ELEMENT_CONTENT_MULT;
6605
0
      cur = ret;
6606
      /*
6607
       * Some normalization:
6608
       * (a | b* | c?)* == (a | b | c)*
6609
       */
6610
0
      while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
6611
0
    if ((cur->c1 != NULL) &&
6612
0
              ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
6613
0
         (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT)))
6614
0
        cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
6615
0
    if ((cur->c2 != NULL) &&
6616
0
              ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
6617
0
         (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT)))
6618
0
        cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
6619
0
    cur = cur->c2;
6620
0
      }
6621
0
  }
6622
0
  NEXT;
6623
0
    } else if (RAW == '+') {
6624
0
  if (ret != NULL) {
6625
0
      int found = 0;
6626
6627
0
      if ((ret->ocur == XML_ELEMENT_CONTENT_OPT) ||
6628
0
          (ret->ocur == XML_ELEMENT_CONTENT_MULT))
6629
0
          ret->ocur = XML_ELEMENT_CONTENT_MULT;
6630
0
      else
6631
0
          ret->ocur = XML_ELEMENT_CONTENT_PLUS;
6632
      /*
6633
       * Some normalization:
6634
       * (a | b*)+ == (a | b)*
6635
       * (a | b?)+ == (a | b)*
6636
       */
6637
0
      while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
6638
0
    if ((cur->c1 != NULL) &&
6639
0
              ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
6640
0
         (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT))) {
6641
0
        cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
6642
0
        found = 1;
6643
0
    }
6644
0
    if ((cur->c2 != NULL) &&
6645
0
              ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
6646
0
         (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT))) {
6647
0
        cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
6648
0
        found = 1;
6649
0
    }
6650
0
    cur = cur->c2;
6651
0
      }
6652
0
      if (found)
6653
0
    ret->ocur = XML_ELEMENT_CONTENT_MULT;
6654
0
  }
6655
0
  NEXT;
6656
0
    }
6657
0
    return(ret);
6658
0
}
6659
6660
/**
6661
 * xmlParseElementChildrenContentDecl:
6662
 * @ctxt:  an XML parser context
6663
 * @inputchk:  the input used for the current entity, needed for boundary checks
6664
 *
6665
 * DEPRECATED: Internal function, don't use.
6666
 *
6667
 * parse the declaration for a Mixed Element content
6668
 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6669
 *
6670
 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
6671
 *
6672
 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
6673
 *
6674
 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
6675
 *
6676
 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
6677
 *
6678
 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
6679
 * TODO Parameter-entity replacement text must be properly nested
6680
 *  with parenthesized groups. That is to say, if either of the
6681
 *  opening or closing parentheses in a choice, seq, or Mixed
6682
 *  construct is contained in the replacement text for a parameter
6683
 *  entity, both must be contained in the same replacement text. For
6684
 *  interoperability, if a parameter-entity reference appears in a
6685
 *  choice, seq, or Mixed construct, its replacement text should not
6686
 *  be empty, and neither the first nor last non-blank character of
6687
 *  the replacement text should be a connector (| or ,).
6688
 *
6689
 * Returns the tree of xmlElementContentPtr describing the element
6690
 *          hierarchy.
6691
 */
6692
xmlElementContentPtr
6693
0
xmlParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
6694
    /* stub left for API/ABI compat */
6695
0
    return(xmlParseElementChildrenContentDeclPriv(ctxt, inputchk, 1));
6696
0
}
6697
6698
/**
6699
 * xmlParseElementContentDecl:
6700
 * @ctxt:  an XML parser context
6701
 * @name:  the name of the element being defined.
6702
 * @result:  the Element Content pointer will be stored here if any
6703
 *
6704
 * DEPRECATED: Internal function, don't use.
6705
 *
6706
 * parse the declaration for an Element content either Mixed or Children,
6707
 * the cases EMPTY and ANY are handled directly in xmlParseElementDecl
6708
 *
6709
 * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
6710
 *
6711
 * returns: the type of element content XML_ELEMENT_TYPE_xxx
6712
 */
6713
6714
int
6715
xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, const xmlChar *name,
6716
0
                           xmlElementContentPtr *result) {
6717
6718
0
    xmlElementContentPtr tree = NULL;
6719
0
    int inputid = ctxt->input->id;
6720
0
    int res;
6721
6722
0
    *result = NULL;
6723
6724
0
    if (RAW != '(') {
6725
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
6726
0
    "xmlParseElementContentDecl : %s '(' expected\n", name);
6727
0
  return(-1);
6728
0
    }
6729
0
    NEXT;
6730
0
    GROW;
6731
0
    if (ctxt->instate == XML_PARSER_EOF)
6732
0
        return(-1);
6733
0
    SKIP_BLANKS;
6734
0
    if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
6735
0
        tree = xmlParseElementMixedContentDecl(ctxt, inputid);
6736
0
  res = XML_ELEMENT_TYPE_MIXED;
6737
0
    } else {
6738
0
        tree = xmlParseElementChildrenContentDeclPriv(ctxt, inputid, 1);
6739
0
  res = XML_ELEMENT_TYPE_ELEMENT;
6740
0
    }
6741
0
    SKIP_BLANKS;
6742
0
    *result = tree;
6743
0
    return(res);
6744
0
}
6745
6746
/**
6747
 * xmlParseElementDecl:
6748
 * @ctxt:  an XML parser context
6749
 *
6750
 * DEPRECATED: Internal function, don't use.
6751
 *
6752
 * Parse an element declaration. Always consumes '<!'.
6753
 *
6754
 * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
6755
 *
6756
 * [ VC: Unique Element Type Declaration ]
6757
 * No element type may be declared more than once
6758
 *
6759
 * Returns the type of the element, or -1 in case of error
6760
 */
6761
int
6762
0
xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
6763
0
    const xmlChar *name;
6764
0
    int ret = -1;
6765
0
    xmlElementContentPtr content  = NULL;
6766
6767
0
    if ((CUR != '<') || (NXT(1) != '!'))
6768
0
        return(ret);
6769
0
    SKIP(2);
6770
6771
    /* GROW; done in the caller */
6772
0
    if (CMP7(CUR_PTR, 'E', 'L', 'E', 'M', 'E', 'N', 'T')) {
6773
0
  int inputid = ctxt->input->id;
6774
6775
0
  SKIP(7);
6776
0
  if (SKIP_BLANKS == 0) {
6777
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6778
0
               "Space required after 'ELEMENT'\n");
6779
0
      return(-1);
6780
0
  }
6781
0
        name = xmlParseName(ctxt);
6782
0
  if (name == NULL) {
6783
0
      xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6784
0
         "xmlParseElementDecl: no name for Element\n");
6785
0
      return(-1);
6786
0
  }
6787
0
  if (SKIP_BLANKS == 0) {
6788
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6789
0
         "Space required after the element name\n");
6790
0
  }
6791
0
  if (CMP5(CUR_PTR, 'E', 'M', 'P', 'T', 'Y')) {
6792
0
      SKIP(5);
6793
      /*
6794
       * Element must always be empty.
6795
       */
6796
0
      ret = XML_ELEMENT_TYPE_EMPTY;
6797
0
  } else if ((RAW == 'A') && (NXT(1) == 'N') &&
6798
0
             (NXT(2) == 'Y')) {
6799
0
      SKIP(3);
6800
      /*
6801
       * Element is a generic container.
6802
       */
6803
0
      ret = XML_ELEMENT_TYPE_ANY;
6804
0
  } else if (RAW == '(') {
6805
0
      ret = xmlParseElementContentDecl(ctxt, name, &content);
6806
0
  } else {
6807
      /*
6808
       * [ WFC: PEs in Internal Subset ] error handling.
6809
       */
6810
0
      if ((RAW == '%') && (ctxt->external == 0) &&
6811
0
          (ctxt->inputNr == 1)) {
6812
0
    xmlFatalErrMsg(ctxt, XML_ERR_PEREF_IN_INT_SUBSET,
6813
0
    "PEReference: forbidden within markup decl in internal subset\n");
6814
0
      } else {
6815
0
    xmlFatalErrMsg(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
6816
0
          "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
6817
0
            }
6818
0
      return(-1);
6819
0
  }
6820
6821
0
  SKIP_BLANKS;
6822
6823
0
  if (RAW != '>') {
6824
0
      xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
6825
0
      if (content != NULL) {
6826
0
    xmlFreeDocElementContent(ctxt->myDoc, content);
6827
0
      }
6828
0
  } else {
6829
0
      if (inputid != ctxt->input->id) {
6830
0
    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6831
0
                               "Element declaration doesn't start and stop in"
6832
0
                               " the same entity\n");
6833
0
      }
6834
6835
0
      NEXT;
6836
0
      if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
6837
0
    (ctxt->sax->elementDecl != NULL)) {
6838
0
    if (content != NULL)
6839
0
        content->parent = NULL;
6840
0
          ctxt->sax->elementDecl(ctxt->userData, name, ret,
6841
0
                           content);
6842
0
    if ((content != NULL) && (content->parent == NULL)) {
6843
        /*
6844
         * this is a trick: if xmlAddElementDecl is called,
6845
         * instead of copying the full tree it is plugged directly
6846
         * if called from the parser. Avoid duplicating the
6847
         * interfaces or change the API/ABI
6848
         */
6849
0
        xmlFreeDocElementContent(ctxt->myDoc, content);
6850
0
    }
6851
0
      } else if (content != NULL) {
6852
0
    xmlFreeDocElementContent(ctxt->myDoc, content);
6853
0
      }
6854
0
  }
6855
0
    }
6856
0
    return(ret);
6857
0
}
6858
6859
/**
6860
 * xmlParseConditionalSections
6861
 * @ctxt:  an XML parser context
6862
 *
6863
 * Parse a conditional section. Always consumes '<!['.
6864
 *
6865
 * [61] conditionalSect ::= includeSect | ignoreSect
6866
 * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
6867
 * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
6868
 * [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
6869
 * [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
6870
 */
6871
6872
static void
6873
0
xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
6874
0
    int *inputIds = NULL;
6875
0
    size_t inputIdsSize = 0;
6876
0
    size_t depth = 0;
6877
6878
0
    while (ctxt->instate != XML_PARSER_EOF) {
6879
0
        if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
6880
0
            int id = ctxt->input->id;
6881
6882
0
            SKIP(3);
6883
0
            SKIP_BLANKS;
6884
6885
0
            if (CMP7(CUR_PTR, 'I', 'N', 'C', 'L', 'U', 'D', 'E')) {
6886
0
                SKIP(7);
6887
0
                SKIP_BLANKS;
6888
0
                if (RAW != '[') {
6889
0
                    xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
6890
0
                    xmlHaltParser(ctxt);
6891
0
                    goto error;
6892
0
                }
6893
0
                if (ctxt->input->id != id) {
6894
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6895
0
                                   "All markup of the conditional section is"
6896
0
                                   " not in the same entity\n");
6897
0
                }
6898
0
                NEXT;
6899
6900
0
                if (inputIdsSize <= depth) {
6901
0
                    int *tmp;
6902
6903
0
                    inputIdsSize = (inputIdsSize == 0 ? 4 : inputIdsSize * 2);
6904
0
                    tmp = (int *) xmlRealloc(inputIds,
6905
0
                            inputIdsSize * sizeof(int));
6906
0
                    if (tmp == NULL) {
6907
0
                        xmlErrMemory(ctxt, NULL);
6908
0
                        goto error;
6909
0
                    }
6910
0
                    inputIds = tmp;
6911
0
                }
6912
0
                inputIds[depth] = id;
6913
0
                depth++;
6914
0
            } else if (CMP6(CUR_PTR, 'I', 'G', 'N', 'O', 'R', 'E')) {
6915
0
                size_t ignoreDepth = 0;
6916
6917
0
                SKIP(6);
6918
0
                SKIP_BLANKS;
6919
0
                if (RAW != '[') {
6920
0
                    xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
6921
0
                    xmlHaltParser(ctxt);
6922
0
                    goto error;
6923
0
                }
6924
0
                if (ctxt->input->id != id) {
6925
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6926
0
                                   "All markup of the conditional section is"
6927
0
                                   " not in the same entity\n");
6928
0
                }
6929
0
                NEXT;
6930
6931
0
                while (RAW != 0) {
6932
0
                    if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
6933
0
                        SKIP(3);
6934
0
                        ignoreDepth++;
6935
                        /* Check for integer overflow */
6936
0
                        if (ignoreDepth == 0) {
6937
0
                            xmlErrMemory(ctxt, NULL);
6938
0
                            goto error;
6939
0
                        }
6940
0
                    } else if ((RAW == ']') && (NXT(1) == ']') &&
6941
0
                               (NXT(2) == '>')) {
6942
0
                        if (ignoreDepth == 0)
6943
0
                            break;
6944
0
                        SKIP(3);
6945
0
                        ignoreDepth--;
6946
0
                    } else {
6947
0
                        NEXT;
6948
0
                    }
6949
0
                }
6950
6951
0
    if (RAW == 0) {
6952
0
        xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
6953
0
                    goto error;
6954
0
    }
6955
0
                if (ctxt->input->id != id) {
6956
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6957
0
                                   "All markup of the conditional section is"
6958
0
                                   " not in the same entity\n");
6959
0
                }
6960
0
                SKIP(3);
6961
0
            } else {
6962
0
                xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
6963
0
                xmlHaltParser(ctxt);
6964
0
                goto error;
6965
0
            }
6966
0
        } else if ((depth > 0) &&
6967
0
                   (RAW == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
6968
0
            depth--;
6969
0
            if (ctxt->input->id != inputIds[depth]) {
6970
0
                xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6971
0
                               "All markup of the conditional section is not"
6972
0
                               " in the same entity\n");
6973
0
            }
6974
0
            SKIP(3);
6975
0
        } else if ((RAW == '<') && ((NXT(1) == '!') || (NXT(1) == '?'))) {
6976
0
            xmlParseMarkupDecl(ctxt);
6977
0
        } else {
6978
0
            xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
6979
0
            xmlHaltParser(ctxt);
6980
0
            goto error;
6981
0
        }
6982
6983
0
        if (depth == 0)
6984
0
            break;
6985
6986
0
        SKIP_BLANKS;
6987
0
        SHRINK;
6988
0
        GROW;
6989
0
    }
6990
6991
0
error:
6992
0
    xmlFree(inputIds);
6993
0
}
6994
6995
/**
6996
 * xmlParseMarkupDecl:
6997
 * @ctxt:  an XML parser context
6998
 *
6999
 * DEPRECATED: Internal function, don't use.
7000
 *
7001
 * Parse markup declarations. Always consumes '<!' or '<?'.
7002
 *
7003
 * [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
7004
 *                     NotationDecl | PI | Comment
7005
 *
7006
 * [ VC: Proper Declaration/PE Nesting ]
7007
 * Parameter-entity replacement text must be properly nested with
7008
 * markup declarations. That is to say, if either the first character
7009
 * or the last character of a markup declaration (markupdecl above) is
7010
 * contained in the replacement text for a parameter-entity reference,
7011
 * both must be contained in the same replacement text.
7012
 *
7013
 * [ WFC: PEs in Internal Subset ]
7014
 * In the internal DTD subset, parameter-entity references can occur
7015
 * only where markup declarations can occur, not within markup declarations.
7016
 * (This does not apply to references that occur in external parameter
7017
 * entities or to the external subset.)
7018
 */
7019
void
7020
0
xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
7021
0
    GROW;
7022
0
    if (CUR == '<') {
7023
0
        if (NXT(1) == '!') {
7024
0
      switch (NXT(2)) {
7025
0
          case 'E':
7026
0
        if (NXT(3) == 'L')
7027
0
      xmlParseElementDecl(ctxt);
7028
0
        else if (NXT(3) == 'N')
7029
0
      xmlParseEntityDecl(ctxt);
7030
0
                    else
7031
0
                        SKIP(2);
7032
0
        break;
7033
0
          case 'A':
7034
0
        xmlParseAttributeListDecl(ctxt);
7035
0
        break;
7036
0
          case 'N':
7037
0
        xmlParseNotationDecl(ctxt);
7038
0
        break;
7039
0
          case '-':
7040
0
        xmlParseComment(ctxt);
7041
0
        break;
7042
0
    default:
7043
        /* there is an error but it will be detected later */
7044
0
                    SKIP(2);
7045
0
        break;
7046
0
      }
7047
0
  } else if (NXT(1) == '?') {
7048
0
      xmlParsePI(ctxt);
7049
0
  }
7050
0
    }
7051
7052
    /*
7053
     * detect requirement to exit there and act accordingly
7054
     * and avoid having instate overridden later on
7055
     */
7056
0
    if (ctxt->instate == XML_PARSER_EOF)
7057
0
        return;
7058
7059
0
    ctxt->instate = XML_PARSER_DTD;
7060
0
}
7061
7062
/**
7063
 * xmlParseTextDecl:
7064
 * @ctxt:  an XML parser context
7065
 *
7066
 * DEPRECATED: Internal function, don't use.
7067
 *
7068
 * parse an XML declaration header for external entities
7069
 *
7070
 * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
7071
 */
7072
7073
void
7074
0
xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
7075
0
    xmlChar *version;
7076
0
    int oldstate;
7077
7078
    /*
7079
     * We know that '<?xml' is here.
7080
     */
7081
0
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
7082
0
  SKIP(5);
7083
0
    } else {
7084
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_STARTED, NULL);
7085
0
  return;
7086
0
    }
7087
7088
    /* Avoid expansion of parameter entities when skipping blanks. */
7089
0
    oldstate = ctxt->instate;
7090
0
    ctxt->instate = XML_PARSER_START;
7091
7092
0
    if (SKIP_BLANKS == 0) {
7093
0
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
7094
0
           "Space needed after '<?xml'\n");
7095
0
    }
7096
7097
    /*
7098
     * We may have the VersionInfo here.
7099
     */
7100
0
    version = xmlParseVersionInfo(ctxt);
7101
0
    if (version == NULL)
7102
0
  version = xmlCharStrdup(XML_DEFAULT_VERSION);
7103
0
    else {
7104
0
  if (SKIP_BLANKS == 0) {
7105
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
7106
0
               "Space needed here\n");
7107
0
  }
7108
0
    }
7109
0
    ctxt->input->version = version;
7110
7111
    /*
7112
     * We must have the encoding declaration
7113
     */
7114
0
    xmlParseEncodingDecl(ctxt);
7115
0
    if (ctxt->instate == XML_PARSER_EOF)
7116
0
        return;
7117
0
    if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
7118
  /*
7119
   * The XML REC instructs us to stop parsing right here
7120
   */
7121
0
        ctxt->instate = oldstate;
7122
0
        return;
7123
0
    }
7124
7125
0
    SKIP_BLANKS;
7126
0
    if ((RAW == '?') && (NXT(1) == '>')) {
7127
0
        SKIP(2);
7128
0
    } else if (RAW == '>') {
7129
        /* Deprecated old WD ... */
7130
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
7131
0
  NEXT;
7132
0
    } else {
7133
0
        int c;
7134
7135
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
7136
0
        while ((c = CUR) != 0) {
7137
0
            NEXT;
7138
0
            if (c == '>')
7139
0
                break;
7140
0
        }
7141
0
    }
7142
7143
0
    if (ctxt->instate != XML_PARSER_EOF)
7144
0
        ctxt->instate = oldstate;
7145
0
}
7146
7147
/**
7148
 * xmlParseExternalSubset:
7149
 * @ctxt:  an XML parser context
7150
 * @ExternalID: the external identifier
7151
 * @SystemID: the system identifier (or URL)
7152
 *
7153
 * parse Markup declarations from an external subset
7154
 *
7155
 * [30] extSubset ::= textDecl? extSubsetDecl
7156
 *
7157
 * [31] extSubsetDecl ::= (markupdecl | conditionalSect | PEReference | S) *
7158
 */
7159
void
7160
xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
7161
0
                       const xmlChar *SystemID) {
7162
0
    xmlDetectSAX2(ctxt);
7163
7164
0
    xmlDetectEncoding(ctxt);
7165
7166
0
    if (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) {
7167
0
  xmlParseTextDecl(ctxt);
7168
0
  if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
7169
      /*
7170
       * The XML REC instructs us to stop parsing right here
7171
       */
7172
0
      xmlHaltParser(ctxt);
7173
0
      return;
7174
0
  }
7175
0
    }
7176
0
    if (ctxt->myDoc == NULL) {
7177
0
        ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
7178
0
  if (ctxt->myDoc == NULL) {
7179
0
      xmlErrMemory(ctxt, "New Doc failed");
7180
0
      return;
7181
0
  }
7182
0
  ctxt->myDoc->properties = XML_DOC_INTERNAL;
7183
0
    }
7184
0
    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
7185
0
        xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
7186
7187
0
    ctxt->instate = XML_PARSER_DTD;
7188
0
    ctxt->external = 1;
7189
0
    SKIP_BLANKS;
7190
0
    while ((ctxt->instate != XML_PARSER_EOF) && (RAW != 0)) {
7191
0
  GROW;
7192
0
        if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
7193
0
            xmlParseConditionalSections(ctxt);
7194
0
        } else if ((RAW == '<') && ((NXT(1) == '!') || (NXT(1) == '?'))) {
7195
0
            xmlParseMarkupDecl(ctxt);
7196
0
        } else {
7197
0
            xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
7198
0
            xmlHaltParser(ctxt);
7199
0
            return;
7200
0
        }
7201
0
        SKIP_BLANKS;
7202
0
        SHRINK;
7203
0
    }
7204
7205
0
    if (RAW != 0) {
7206
0
  xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
7207
0
    }
7208
7209
0
}
7210
7211
/**
7212
 * xmlParseReference:
7213
 * @ctxt:  an XML parser context
7214
 *
7215
 * DEPRECATED: Internal function, don't use.
7216
 *
7217
 * parse and handle entity references in content, depending on the SAX
7218
 * interface, this may end-up in a call to character() if this is a
7219
 * CharRef, a predefined entity, if there is no reference() callback.
7220
 * or if the parser was asked to switch to that mode.
7221
 *
7222
 * Always consumes '&'.
7223
 *
7224
 * [67] Reference ::= EntityRef | CharRef
7225
 */
7226
void
7227
0
xmlParseReference(xmlParserCtxtPtr ctxt) {
7228
0
    xmlEntityPtr ent;
7229
0
    xmlChar *val;
7230
0
    int was_checked;
7231
0
    xmlNodePtr list = NULL;
7232
0
    xmlParserErrors ret = XML_ERR_OK;
7233
7234
7235
0
    if (RAW != '&')
7236
0
        return;
7237
7238
    /*
7239
     * Simple case of a CharRef
7240
     */
7241
0
    if (NXT(1) == '#') {
7242
0
  int i = 0;
7243
0
  xmlChar out[16];
7244
0
  int value = xmlParseCharRef(ctxt);
7245
7246
0
  if (value == 0)
7247
0
      return;
7248
7249
        /*
7250
         * Just encode the value in UTF-8
7251
         */
7252
0
        COPY_BUF(out, i, value);
7253
0
        out[i] = 0;
7254
0
        if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
7255
0
            (!ctxt->disableSAX))
7256
0
            ctxt->sax->characters(ctxt->userData, out, i);
7257
0
  return;
7258
0
    }
7259
7260
    /*
7261
     * We are seeing an entity reference
7262
     */
7263
0
    ent = xmlParseEntityRef(ctxt);
7264
0
    if (ent == NULL) return;
7265
0
    if (!ctxt->wellFormed)
7266
0
  return;
7267
0
    was_checked = ent->flags & XML_ENT_PARSED;
7268
7269
    /* special case of predefined entities */
7270
0
    if ((ent->name == NULL) ||
7271
0
        (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
7272
0
  val = ent->content;
7273
0
  if (val == NULL) return;
7274
  /*
7275
   * inline the entity.
7276
   */
7277
0
  if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
7278
0
      (!ctxt->disableSAX))
7279
0
      ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
7280
0
  return;
7281
0
    }
7282
7283
    /*
7284
     * Some users try to parse entities on their own and used to set
7285
     * the renamed "checked" member. Fix the flags to cover this
7286
     * case.
7287
     */
7288
0
    if (((ent->flags & XML_ENT_PARSED) == 0) && (ent->children != NULL))
7289
0
        ent->flags |= XML_ENT_PARSED;
7290
7291
    /*
7292
     * The first reference to the entity trigger a parsing phase
7293
     * where the ent->children is filled with the result from
7294
     * the parsing.
7295
     * Note: external parsed entities will not be loaded, it is not
7296
     * required for a non-validating parser, unless the parsing option
7297
     * of validating, or substituting entities were given. Doing so is
7298
     * far more secure as the parser will only process data coming from
7299
     * the document entity by default.
7300
     *
7301
     * FIXME: This doesn't work correctly since entities can be
7302
     * expanded with different namespace declarations in scope.
7303
     * For example:
7304
     *
7305
     * <!DOCTYPE doc [
7306
     *   <!ENTITY ent "<ns:elem/>">
7307
     * ]>
7308
     * <doc>
7309
     *   <decl1 xmlns:ns="urn:ns1">
7310
     *     &ent;
7311
     *   </decl1>
7312
     *   <decl2 xmlns:ns="urn:ns2">
7313
     *     &ent;
7314
     *   </decl2>
7315
     * </doc>
7316
     *
7317
     * Proposed fix:
7318
     *
7319
     * - Remove the ent->owner optimization which tries to avoid the
7320
     *   initial copy of the entity. Always make entities own the
7321
     *   subtree.
7322
     * - Ignore current namespace declarations when parsing the
7323
     *   entity. If a prefix can't be resolved, don't report an error
7324
     *   but mark it as unresolved.
7325
     * - Try to resolve these prefixes when expanding the entity.
7326
     *   This will require a specialized version of xmlStaticCopyNode
7327
     *   which can also make use of the namespace hash table to avoid
7328
     *   quadratic behavior.
7329
     *
7330
     * Alternatively, we could simply reparse the entity on each
7331
     * expansion like we already do with custom SAX callbacks.
7332
     * External entity content should be cached in this case.
7333
     */
7334
0
    if (((ent->flags & XML_ENT_PARSED) == 0) &&
7335
0
        ((ent->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY) ||
7336
0
         (ctxt->options & (XML_PARSE_NOENT | XML_PARSE_DTDVALID)))) {
7337
0
  unsigned long oldsizeentcopy = ctxt->sizeentcopy;
7338
7339
  /*
7340
   * This is a bit hackish but this seems the best
7341
   * way to make sure both SAX and DOM entity support
7342
   * behaves okay.
7343
   */
7344
0
  void *user_data;
7345
0
  if (ctxt->userData == ctxt)
7346
0
      user_data = NULL;
7347
0
  else
7348
0
      user_data = ctxt->userData;
7349
7350
        /* Avoid overflow as much as possible */
7351
0
        ctxt->sizeentcopy = 0;
7352
7353
0
        if (ent->flags & XML_ENT_EXPANDING) {
7354
0
            xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
7355
0
            xmlHaltParser(ctxt);
7356
0
            return;
7357
0
        }
7358
7359
0
        ent->flags |= XML_ENT_EXPANDING;
7360
7361
  /*
7362
   * Check that this entity is well formed
7363
   * 4.3.2: An internal general parsed entity is well-formed
7364
   * if its replacement text matches the production labeled
7365
   * content.
7366
   */
7367
0
  if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
7368
0
      ctxt->depth++;
7369
0
      ret = xmlParseBalancedChunkMemoryInternal(ctxt, ent->content,
7370
0
                                                user_data, &list);
7371
0
      ctxt->depth--;
7372
7373
0
  } else if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
7374
0
      ctxt->depth++;
7375
0
      ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt, ctxt->sax,
7376
0
                                     user_data, ctxt->depth, ent->URI,
7377
0
             ent->ExternalID, &list);
7378
0
      ctxt->depth--;
7379
0
  } else {
7380
0
      ret = XML_ERR_ENTITY_PE_INTERNAL;
7381
0
      xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
7382
0
       "invalid entity type found\n", NULL);
7383
0
  }
7384
7385
0
        ent->flags &= ~XML_ENT_EXPANDING;
7386
0
        ent->flags |= XML_ENT_PARSED | XML_ENT_CHECKED;
7387
0
        ent->expandedSize = ctxt->sizeentcopy;
7388
0
  if (ret == XML_ERR_ENTITY_LOOP) {
7389
0
            xmlHaltParser(ctxt);
7390
0
      xmlFreeNodeList(list);
7391
0
      return;
7392
0
  }
7393
0
  if (xmlParserEntityCheck(ctxt, oldsizeentcopy)) {
7394
0
      xmlFreeNodeList(list);
7395
0
      return;
7396
0
  }
7397
7398
0
  if ((ret == XML_ERR_OK) && (list != NULL)) {
7399
0
            ent->children = list;
7400
            /*
7401
             * Prune it directly in the generated document
7402
             * except for single text nodes.
7403
             */
7404
0
            if ((ctxt->replaceEntities == 0) ||
7405
0
                (ctxt->parseMode == XML_PARSE_READER) ||
7406
0
                ((list->type == XML_TEXT_NODE) &&
7407
0
                 (list->next == NULL))) {
7408
0
                ent->owner = 1;
7409
0
                while (list != NULL) {
7410
0
                    list->parent = (xmlNodePtr) ent;
7411
0
                    if (list->doc != ent->doc)
7412
0
                        xmlSetTreeDoc(list, ent->doc);
7413
0
                    if (list->next == NULL)
7414
0
                        ent->last = list;
7415
0
                    list = list->next;
7416
0
                }
7417
0
                list = NULL;
7418
0
            } else {
7419
0
                ent->owner = 0;
7420
0
                while (list != NULL) {
7421
0
                    list->parent = (xmlNodePtr) ctxt->node;
7422
0
                    list->doc = ctxt->myDoc;
7423
0
                    if (list->next == NULL)
7424
0
                        ent->last = list;
7425
0
                    list = list->next;
7426
0
                }
7427
0
                list = ent->children;
7428
#ifdef LIBXML_LEGACY_ENABLED
7429
                if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7430
                    xmlAddEntityReference(ent, list, NULL);
7431
#endif /* LIBXML_LEGACY_ENABLED */
7432
0
            }
7433
0
  } else if ((ret != XML_ERR_OK) &&
7434
0
       (ret != XML_WAR_UNDECLARED_ENTITY)) {
7435
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7436
0
         "Entity '%s' failed to parse\n", ent->name);
7437
0
            if (ent->content != NULL)
7438
0
                ent->content[0] = 0;
7439
0
  } else if (list != NULL) {
7440
0
      xmlFreeNodeList(list);
7441
0
      list = NULL;
7442
0
  }
7443
7444
        /* Prevent entity from being parsed and expanded twice (Bug 760367). */
7445
0
        was_checked = 0;
7446
0
    }
7447
7448
    /*
7449
     * Now that the entity content has been gathered
7450
     * provide it to the application, this can take different forms based
7451
     * on the parsing modes.
7452
     */
7453
0
    if (ent->children == NULL) {
7454
  /*
7455
   * Probably running in SAX mode and the callbacks don't
7456
   * build the entity content. So unless we already went
7457
   * though parsing for first checking go though the entity
7458
   * content to generate callbacks associated to the entity
7459
   */
7460
0
  if (was_checked != 0) {
7461
0
      void *user_data;
7462
      /*
7463
       * This is a bit hackish but this seems the best
7464
       * way to make sure both SAX and DOM entity support
7465
       * behaves okay.
7466
       */
7467
0
      if (ctxt->userData == ctxt)
7468
0
    user_data = NULL;
7469
0
      else
7470
0
    user_data = ctxt->userData;
7471
7472
0
      if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
7473
0
    ctxt->depth++;
7474
0
    ret = xmlParseBalancedChunkMemoryInternal(ctxt,
7475
0
           ent->content, user_data, NULL);
7476
0
    ctxt->depth--;
7477
0
      } else if (ent->etype ==
7478
0
           XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
7479
0
          unsigned long oldsizeentities = ctxt->sizeentities;
7480
7481
0
    ctxt->depth++;
7482
0
    ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt,
7483
0
         ctxt->sax, user_data, ctxt->depth,
7484
0
         ent->URI, ent->ExternalID, NULL);
7485
0
    ctxt->depth--;
7486
7487
                /* Undo the change to sizeentities */
7488
0
                ctxt->sizeentities = oldsizeentities;
7489
0
      } else {
7490
0
    ret = XML_ERR_ENTITY_PE_INTERNAL;
7491
0
    xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
7492
0
           "invalid entity type found\n", NULL);
7493
0
      }
7494
0
      if (ret == XML_ERR_ENTITY_LOOP) {
7495
0
    xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
7496
0
    return;
7497
0
      }
7498
0
            if (xmlParserEntityCheck(ctxt, 0))
7499
0
                return;
7500
0
  }
7501
0
  if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
7502
0
      (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
7503
      /*
7504
       * Entity reference callback comes second, it's somewhat
7505
       * superfluous but a compatibility to historical behaviour
7506
       */
7507
0
      ctxt->sax->reference(ctxt->userData, ent->name);
7508
0
  }
7509
0
  return;
7510
0
    }
7511
7512
    /*
7513
     * We also check for amplification if entities aren't substituted.
7514
     * They might be expanded later.
7515
     */
7516
0
    if ((was_checked != 0) &&
7517
0
        (xmlParserEntityCheck(ctxt, ent->expandedSize)))
7518
0
        return;
7519
7520
    /*
7521
     * If we didn't get any children for the entity being built
7522
     */
7523
0
    if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
7524
0
  (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
7525
  /*
7526
   * Create a node.
7527
   */
7528
0
  ctxt->sax->reference(ctxt->userData, ent->name);
7529
0
  return;
7530
0
    }
7531
7532
0
    if (ctxt->replaceEntities)  {
7533
  /*
7534
   * There is a problem on the handling of _private for entities
7535
   * (bug 155816): Should we copy the content of the field from
7536
   * the entity (possibly overwriting some value set by the user
7537
   * when a copy is created), should we leave it alone, or should
7538
   * we try to take care of different situations?  The problem
7539
   * is exacerbated by the usage of this field by the xmlReader.
7540
   * To fix this bug, we look at _private on the created node
7541
   * and, if it's NULL, we copy in whatever was in the entity.
7542
   * If it's not NULL we leave it alone.  This is somewhat of a
7543
   * hack - maybe we should have further tests to determine
7544
   * what to do.
7545
   */
7546
0
  if (ctxt->node != NULL) {
7547
      /*
7548
       * Seems we are generating the DOM content, do
7549
       * a simple tree copy for all references except the first
7550
       * In the first occurrence list contains the replacement.
7551
       */
7552
0
      if (((list == NULL) && (ent->owner == 0)) ||
7553
0
    (ctxt->parseMode == XML_PARSE_READER)) {
7554
0
    xmlNodePtr nw = NULL, cur, firstChild = NULL;
7555
7556
    /*
7557
     * when operating on a reader, the entities definitions
7558
     * are always owning the entities subtree.
7559
    if (ctxt->parseMode == XML_PARSE_READER)
7560
        ent->owner = 1;
7561
     */
7562
7563
0
    cur = ent->children;
7564
0
    while (cur != NULL) {
7565
0
        nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
7566
0
        if (nw != NULL) {
7567
0
      if (nw->_private == NULL)
7568
0
          nw->_private = cur->_private;
7569
0
      if (firstChild == NULL){
7570
0
          firstChild = nw;
7571
0
      }
7572
0
      nw = xmlAddChild(ctxt->node, nw);
7573
0
        }
7574
0
        if (cur == ent->last) {
7575
      /*
7576
       * needed to detect some strange empty
7577
       * node cases in the reader tests
7578
       */
7579
0
      if ((ctxt->parseMode == XML_PARSE_READER) &&
7580
0
          (nw != NULL) &&
7581
0
          (nw->type == XML_ELEMENT_NODE) &&
7582
0
          (nw->children == NULL))
7583
0
          nw->extra = 1;
7584
7585
0
      break;
7586
0
        }
7587
0
        cur = cur->next;
7588
0
    }
7589
#ifdef LIBXML_LEGACY_ENABLED
7590
    if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7591
      xmlAddEntityReference(ent, firstChild, nw);
7592
#endif /* LIBXML_LEGACY_ENABLED */
7593
0
      } else if ((list == NULL) || (ctxt->inputNr > 0)) {
7594
0
    xmlNodePtr nw = NULL, cur, next, last,
7595
0
         firstChild = NULL;
7596
7597
    /*
7598
     * Copy the entity child list and make it the new
7599
     * entity child list. The goal is to make sure any
7600
     * ID or REF referenced will be the one from the
7601
     * document content and not the entity copy.
7602
     */
7603
0
    cur = ent->children;
7604
0
    ent->children = NULL;
7605
0
    last = ent->last;
7606
0
    ent->last = NULL;
7607
0
    while (cur != NULL) {
7608
0
        next = cur->next;
7609
0
        cur->next = NULL;
7610
0
        cur->parent = NULL;
7611
0
        nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
7612
0
        if (nw != NULL) {
7613
0
      if (nw->_private == NULL)
7614
0
          nw->_private = cur->_private;
7615
0
      if (firstChild == NULL){
7616
0
          firstChild = cur;
7617
0
      }
7618
0
      xmlAddChild((xmlNodePtr) ent, nw);
7619
0
        }
7620
0
        xmlAddChild(ctxt->node, cur);
7621
0
        if (cur == last)
7622
0
      break;
7623
0
        cur = next;
7624
0
    }
7625
0
    if (ent->owner == 0)
7626
0
        ent->owner = 1;
7627
#ifdef LIBXML_LEGACY_ENABLED
7628
    if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7629
      xmlAddEntityReference(ent, firstChild, nw);
7630
#endif /* LIBXML_LEGACY_ENABLED */
7631
0
      } else {
7632
0
    const xmlChar *nbktext;
7633
7634
    /*
7635
     * the name change is to avoid coalescing of the
7636
     * node with a possible previous text one which
7637
     * would make ent->children a dangling pointer
7638
     */
7639
0
    nbktext = xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
7640
0
          -1);
7641
0
    if (ent->children->type == XML_TEXT_NODE)
7642
0
        ent->children->name = nbktext;
7643
0
    if ((ent->last != ent->children) &&
7644
0
        (ent->last->type == XML_TEXT_NODE))
7645
0
        ent->last->name = nbktext;
7646
0
    xmlAddChildList(ctxt->node, ent->children);
7647
0
      }
7648
7649
      /*
7650
       * This is to avoid a nasty side effect, see
7651
       * characters() in SAX.c
7652
       */
7653
0
      ctxt->nodemem = 0;
7654
0
      ctxt->nodelen = 0;
7655
0
      return;
7656
0
  }
7657
0
    }
7658
0
}
7659
7660
/**
7661
 * xmlParseEntityRef:
7662
 * @ctxt:  an XML parser context
7663
 *
7664
 * DEPRECATED: Internal function, don't use.
7665
 *
7666
 * Parse an entitiy reference. Always consumes '&'.
7667
 *
7668
 * [68] EntityRef ::= '&' Name ';'
7669
 *
7670
 * [ WFC: Entity Declared ]
7671
 * In a document without any DTD, a document with only an internal DTD
7672
 * subset which contains no parameter entity references, or a document
7673
 * with "standalone='yes'", the Name given in the entity reference
7674
 * must match that in an entity declaration, except that well-formed
7675
 * documents need not declare any of the following entities: amp, lt,
7676
 * gt, apos, quot.  The declaration of a parameter entity must precede
7677
 * any reference to it.  Similarly, the declaration of a general entity
7678
 * must precede any reference to it which appears in a default value in an
7679
 * attribute-list declaration. Note that if entities are declared in the
7680
 * external subset or in external parameter entities, a non-validating
7681
 * processor is not obligated to read and process their declarations;
7682
 * for such documents, the rule that an entity must be declared is a
7683
 * well-formedness constraint only if standalone='yes'.
7684
 *
7685
 * [ WFC: Parsed Entity ]
7686
 * An entity reference must not contain the name of an unparsed entity
7687
 *
7688
 * Returns the xmlEntityPtr if found, or NULL otherwise.
7689
 */
7690
xmlEntityPtr
7691
0
xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
7692
0
    const xmlChar *name;
7693
0
    xmlEntityPtr ent = NULL;
7694
7695
0
    GROW;
7696
0
    if (ctxt->instate == XML_PARSER_EOF)
7697
0
        return(NULL);
7698
7699
0
    if (RAW != '&')
7700
0
        return(NULL);
7701
0
    NEXT;
7702
0
    name = xmlParseName(ctxt);
7703
0
    if (name == NULL) {
7704
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7705
0
           "xmlParseEntityRef: no name\n");
7706
0
        return(NULL);
7707
0
    }
7708
0
    if (RAW != ';') {
7709
0
  xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
7710
0
  return(NULL);
7711
0
    }
7712
0
    NEXT;
7713
7714
    /*
7715
     * Predefined entities override any extra definition
7716
     */
7717
0
    if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
7718
0
        ent = xmlGetPredefinedEntity(name);
7719
0
        if (ent != NULL)
7720
0
            return(ent);
7721
0
    }
7722
7723
    /*
7724
     * Ask first SAX for entity resolution, otherwise try the
7725
     * entities which may have stored in the parser context.
7726
     */
7727
0
    if (ctxt->sax != NULL) {
7728
0
  if (ctxt->sax->getEntity != NULL)
7729
0
      ent = ctxt->sax->getEntity(ctxt->userData, name);
7730
0
  if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
7731
0
      (ctxt->options & XML_PARSE_OLDSAX))
7732
0
      ent = xmlGetPredefinedEntity(name);
7733
0
  if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
7734
0
      (ctxt->userData==ctxt)) {
7735
0
      ent = xmlSAX2GetEntity(ctxt, name);
7736
0
  }
7737
0
    }
7738
0
    if (ctxt->instate == XML_PARSER_EOF)
7739
0
  return(NULL);
7740
    /*
7741
     * [ WFC: Entity Declared ]
7742
     * In a document without any DTD, a document with only an
7743
     * internal DTD subset which contains no parameter entity
7744
     * references, or a document with "standalone='yes'", the
7745
     * Name given in the entity reference must match that in an
7746
     * entity declaration, except that well-formed documents
7747
     * need not declare any of the following entities: amp, lt,
7748
     * gt, apos, quot.
7749
     * The declaration of a parameter entity must precede any
7750
     * reference to it.
7751
     * Similarly, the declaration of a general entity must
7752
     * precede any reference to it which appears in a default
7753
     * value in an attribute-list declaration. Note that if
7754
     * entities are declared in the external subset or in
7755
     * external parameter entities, a non-validating processor
7756
     * is not obligated to read and process their declarations;
7757
     * for such documents, the rule that an entity must be
7758
     * declared is a well-formedness constraint only if
7759
     * standalone='yes'.
7760
     */
7761
0
    if (ent == NULL) {
7762
0
  if ((ctxt->standalone == 1) ||
7763
0
      ((ctxt->hasExternalSubset == 0) &&
7764
0
       (ctxt->hasPErefs == 0))) {
7765
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7766
0
         "Entity '%s' not defined\n", name);
7767
0
  } else {
7768
0
      xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
7769
0
         "Entity '%s' not defined\n", name);
7770
0
      if ((ctxt->inSubset == 0) &&
7771
0
    (ctxt->sax != NULL) &&
7772
0
                (ctxt->disableSAX == 0) &&
7773
0
    (ctxt->sax->reference != NULL)) {
7774
0
    ctxt->sax->reference(ctxt->userData, name);
7775
0
      }
7776
0
  }
7777
0
  ctxt->valid = 0;
7778
0
    }
7779
7780
    /*
7781
     * [ WFC: Parsed Entity ]
7782
     * An entity reference must not contain the name of an
7783
     * unparsed entity
7784
     */
7785
0
    else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
7786
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
7787
0
     "Entity reference to unparsed entity %s\n", name);
7788
0
    }
7789
7790
    /*
7791
     * [ WFC: No External Entity References ]
7792
     * Attribute values cannot contain direct or indirect
7793
     * entity references to external entities.
7794
     */
7795
0
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7796
0
       (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
7797
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
7798
0
       "Attribute references external entity '%s'\n", name);
7799
0
    }
7800
    /*
7801
     * [ WFC: No < in Attribute Values ]
7802
     * The replacement text of any entity referred to directly or
7803
     * indirectly in an attribute value (other than "&lt;") must
7804
     * not contain a <.
7805
     */
7806
0
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7807
0
       (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
7808
0
  if ((ent->flags & XML_ENT_CHECKED_LT) == 0) {
7809
0
            if ((ent->content != NULL) && (xmlStrchr(ent->content, '<')))
7810
0
                ent->flags |= XML_ENT_CONTAINS_LT;
7811
0
            ent->flags |= XML_ENT_CHECKED_LT;
7812
0
        }
7813
0
        if (ent->flags & XML_ENT_CONTAINS_LT)
7814
0
            xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
7815
0
                    "'<' in entity '%s' is not allowed in attributes "
7816
0
                    "values\n", name);
7817
0
    }
7818
7819
    /*
7820
     * Internal check, no parameter entities here ...
7821
     */
7822
0
    else {
7823
0
  switch (ent->etype) {
7824
0
      case XML_INTERNAL_PARAMETER_ENTITY:
7825
0
      case XML_EXTERNAL_PARAMETER_ENTITY:
7826
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
7827
0
       "Attempt to reference the parameter entity '%s'\n",
7828
0
            name);
7829
0
      break;
7830
0
      default:
7831
0
      break;
7832
0
  }
7833
0
    }
7834
7835
    /*
7836
     * [ WFC: No Recursion ]
7837
     * A parsed entity must not contain a recursive reference
7838
     * to itself, either directly or indirectly.
7839
     * Done somewhere else
7840
     */
7841
0
    return(ent);
7842
0
}
7843
7844
/**
7845
 * xmlParseStringEntityRef:
7846
 * @ctxt:  an XML parser context
7847
 * @str:  a pointer to an index in the string
7848
 *
7849
 * parse ENTITY references declarations, but this version parses it from
7850
 * a string value.
7851
 *
7852
 * [68] EntityRef ::= '&' Name ';'
7853
 *
7854
 * [ WFC: Entity Declared ]
7855
 * In a document without any DTD, a document with only an internal DTD
7856
 * subset which contains no parameter entity references, or a document
7857
 * with "standalone='yes'", the Name given in the entity reference
7858
 * must match that in an entity declaration, except that well-formed
7859
 * documents need not declare any of the following entities: amp, lt,
7860
 * gt, apos, quot.  The declaration of a parameter entity must precede
7861
 * any reference to it.  Similarly, the declaration of a general entity
7862
 * must precede any reference to it which appears in a default value in an
7863
 * attribute-list declaration. Note that if entities are declared in the
7864
 * external subset or in external parameter entities, a non-validating
7865
 * processor is not obligated to read and process their declarations;
7866
 * for such documents, the rule that an entity must be declared is a
7867
 * well-formedness constraint only if standalone='yes'.
7868
 *
7869
 * [ WFC: Parsed Entity ]
7870
 * An entity reference must not contain the name of an unparsed entity
7871
 *
7872
 * Returns the xmlEntityPtr if found, or NULL otherwise. The str pointer
7873
 * is updated to the current location in the string.
7874
 */
7875
static xmlEntityPtr
7876
0
xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
7877
0
    xmlChar *name;
7878
0
    const xmlChar *ptr;
7879
0
    xmlChar cur;
7880
0
    xmlEntityPtr ent = NULL;
7881
7882
0
    if ((str == NULL) || (*str == NULL))
7883
0
        return(NULL);
7884
0
    ptr = *str;
7885
0
    cur = *ptr;
7886
0
    if (cur != '&')
7887
0
  return(NULL);
7888
7889
0
    ptr++;
7890
0
    name = xmlParseStringName(ctxt, &ptr);
7891
0
    if (name == NULL) {
7892
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7893
0
           "xmlParseStringEntityRef: no name\n");
7894
0
  *str = ptr;
7895
0
  return(NULL);
7896
0
    }
7897
0
    if (*ptr != ';') {
7898
0
  xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
7899
0
        xmlFree(name);
7900
0
  *str = ptr;
7901
0
  return(NULL);
7902
0
    }
7903
0
    ptr++;
7904
7905
7906
    /*
7907
     * Predefined entities override any extra definition
7908
     */
7909
0
    if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
7910
0
        ent = xmlGetPredefinedEntity(name);
7911
0
        if (ent != NULL) {
7912
0
            xmlFree(name);
7913
0
            *str = ptr;
7914
0
            return(ent);
7915
0
        }
7916
0
    }
7917
7918
    /*
7919
     * Ask first SAX for entity resolution, otherwise try the
7920
     * entities which may have stored in the parser context.
7921
     */
7922
0
    if (ctxt->sax != NULL) {
7923
0
  if (ctxt->sax->getEntity != NULL)
7924
0
      ent = ctxt->sax->getEntity(ctxt->userData, name);
7925
0
  if ((ent == NULL) && (ctxt->options & XML_PARSE_OLDSAX))
7926
0
      ent = xmlGetPredefinedEntity(name);
7927
0
  if ((ent == NULL) && (ctxt->userData==ctxt)) {
7928
0
      ent = xmlSAX2GetEntity(ctxt, name);
7929
0
  }
7930
0
    }
7931
0
    if (ctxt->instate == XML_PARSER_EOF) {
7932
0
  xmlFree(name);
7933
0
  return(NULL);
7934
0
    }
7935
7936
    /*
7937
     * [ WFC: Entity Declared ]
7938
     * In a document without any DTD, a document with only an
7939
     * internal DTD subset which contains no parameter entity
7940
     * references, or a document with "standalone='yes'", the
7941
     * Name given in the entity reference must match that in an
7942
     * entity declaration, except that well-formed documents
7943
     * need not declare any of the following entities: amp, lt,
7944
     * gt, apos, quot.
7945
     * The declaration of a parameter entity must precede any
7946
     * reference to it.
7947
     * Similarly, the declaration of a general entity must
7948
     * precede any reference to it which appears in a default
7949
     * value in an attribute-list declaration. Note that if
7950
     * entities are declared in the external subset or in
7951
     * external parameter entities, a non-validating processor
7952
     * is not obligated to read and process their declarations;
7953
     * for such documents, the rule that an entity must be
7954
     * declared is a well-formedness constraint only if
7955
     * standalone='yes'.
7956
     */
7957
0
    if (ent == NULL) {
7958
0
  if ((ctxt->standalone == 1) ||
7959
0
      ((ctxt->hasExternalSubset == 0) &&
7960
0
       (ctxt->hasPErefs == 0))) {
7961
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7962
0
         "Entity '%s' not defined\n", name);
7963
0
  } else {
7964
0
      xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
7965
0
        "Entity '%s' not defined\n",
7966
0
        name);
7967
0
  }
7968
  /* TODO ? check regressions ctxt->valid = 0; */
7969
0
    }
7970
7971
    /*
7972
     * [ WFC: Parsed Entity ]
7973
     * An entity reference must not contain the name of an
7974
     * unparsed entity
7975
     */
7976
0
    else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
7977
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
7978
0
     "Entity reference to unparsed entity %s\n", name);
7979
0
    }
7980
7981
    /*
7982
     * [ WFC: No External Entity References ]
7983
     * Attribute values cannot contain direct or indirect
7984
     * entity references to external entities.
7985
     */
7986
0
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7987
0
       (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
7988
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
7989
0
   "Attribute references external entity '%s'\n", name);
7990
0
    }
7991
    /*
7992
     * [ WFC: No < in Attribute Values ]
7993
     * The replacement text of any entity referred to directly or
7994
     * indirectly in an attribute value (other than "&lt;") must
7995
     * not contain a <.
7996
     */
7997
0
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7998
0
       (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
7999
0
  if ((ent->flags & XML_ENT_CHECKED_LT) == 0) {
8000
0
            if ((ent->content != NULL) && (xmlStrchr(ent->content, '<')))
8001
0
                ent->flags |= XML_ENT_CONTAINS_LT;
8002
0
            ent->flags |= XML_ENT_CHECKED_LT;
8003
0
        }
8004
0
        if (ent->flags & XML_ENT_CONTAINS_LT)
8005
0
            xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
8006
0
                    "'<' in entity '%s' is not allowed in attributes "
8007
0
                    "values\n", name);
8008
0
    }
8009
8010
    /*
8011
     * Internal check, no parameter entities here ...
8012
     */
8013
0
    else {
8014
0
  switch (ent->etype) {
8015
0
      case XML_INTERNAL_PARAMETER_ENTITY:
8016
0
      case XML_EXTERNAL_PARAMETER_ENTITY:
8017
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
8018
0
       "Attempt to reference the parameter entity '%s'\n",
8019
0
          name);
8020
0
      break;
8021
0
      default:
8022
0
      break;
8023
0
  }
8024
0
    }
8025
8026
    /*
8027
     * [ WFC: No Recursion ]
8028
     * A parsed entity must not contain a recursive reference
8029
     * to itself, either directly or indirectly.
8030
     * Done somewhere else
8031
     */
8032
8033
0
    xmlFree(name);
8034
0
    *str = ptr;
8035
0
    return(ent);
8036
0
}
8037
8038
/**
8039
 * xmlParsePEReference:
8040
 * @ctxt:  an XML parser context
8041
 *
8042
 * DEPRECATED: Internal function, don't use.
8043
 *
8044
 * Parse a parameter entity reference. Always consumes '%'.
8045
 *
8046
 * The entity content is handled directly by pushing it's content as
8047
 * a new input stream.
8048
 *
8049
 * [69] PEReference ::= '%' Name ';'
8050
 *
8051
 * [ WFC: No Recursion ]
8052
 * A parsed entity must not contain a recursive
8053
 * reference to itself, either directly or indirectly.
8054
 *
8055
 * [ WFC: Entity Declared ]
8056
 * In a document without any DTD, a document with only an internal DTD
8057
 * subset which contains no parameter entity references, or a document
8058
 * with "standalone='yes'", ...  ... The declaration of a parameter
8059
 * entity must precede any reference to it...
8060
 *
8061
 * [ VC: Entity Declared ]
8062
 * In a document with an external subset or external parameter entities
8063
 * with "standalone='no'", ...  ... The declaration of a parameter entity
8064
 * must precede any reference to it...
8065
 *
8066
 * [ WFC: In DTD ]
8067
 * Parameter-entity references may only appear in the DTD.
8068
 * NOTE: misleading but this is handled.
8069
 */
8070
void
8071
xmlParsePEReference(xmlParserCtxtPtr ctxt)
8072
0
{
8073
0
    const xmlChar *name;
8074
0
    xmlEntityPtr entity = NULL;
8075
0
    xmlParserInputPtr input;
8076
8077
0
    if (RAW != '%')
8078
0
        return;
8079
0
    NEXT;
8080
0
    name = xmlParseName(ctxt);
8081
0
    if (name == NULL) {
8082
0
  xmlFatalErrMsg(ctxt, XML_ERR_PEREF_NO_NAME, "PEReference: no name\n");
8083
0
  return;
8084
0
    }
8085
0
    if (xmlParserDebugEntities)
8086
0
  xmlGenericError(xmlGenericErrorContext,
8087
0
    "PEReference: %s\n", name);
8088
0
    if (RAW != ';') {
8089
0
  xmlFatalErr(ctxt, XML_ERR_PEREF_SEMICOL_MISSING, NULL);
8090
0
        return;
8091
0
    }
8092
8093
0
    NEXT;
8094
8095
    /*
8096
     * Request the entity from SAX
8097
     */
8098
0
    if ((ctxt->sax != NULL) &&
8099
0
  (ctxt->sax->getParameterEntity != NULL))
8100
0
  entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
8101
0
    if (ctxt->instate == XML_PARSER_EOF)
8102
0
  return;
8103
0
    if (entity == NULL) {
8104
  /*
8105
   * [ WFC: Entity Declared ]
8106
   * In a document without any DTD, a document with only an
8107
   * internal DTD subset which contains no parameter entity
8108
   * references, or a document with "standalone='yes'", ...
8109
   * ... The declaration of a parameter entity must precede
8110
   * any reference to it...
8111
   */
8112
0
  if ((ctxt->standalone == 1) ||
8113
0
      ((ctxt->hasExternalSubset == 0) &&
8114
0
       (ctxt->hasPErefs == 0))) {
8115
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
8116
0
            "PEReference: %%%s; not found\n",
8117
0
            name);
8118
0
  } else {
8119
      /*
8120
       * [ VC: Entity Declared ]
8121
       * In a document with an external subset or external
8122
       * parameter entities with "standalone='no'", ...
8123
       * ... The declaration of a parameter entity must
8124
       * precede any reference to it...
8125
       */
8126
0
            if ((ctxt->validate) && (ctxt->vctxt.error != NULL)) {
8127
0
                xmlValidityError(ctxt, XML_WAR_UNDECLARED_ENTITY,
8128
0
                                 "PEReference: %%%s; not found\n",
8129
0
                                 name, NULL);
8130
0
            } else
8131
0
                xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8132
0
                              "PEReference: %%%s; not found\n",
8133
0
                              name, NULL);
8134
0
            ctxt->valid = 0;
8135
0
  }
8136
0
    } else {
8137
  /*
8138
   * Internal checking in case the entity quest barfed
8139
   */
8140
0
  if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
8141
0
      (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
8142
0
      xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8143
0
      "Internal: %%%s; is not a parameter entity\n",
8144
0
        name, NULL);
8145
0
  } else {
8146
0
            unsigned long parentConsumed;
8147
0
            xmlEntityPtr oldEnt;
8148
8149
0
      if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
8150
0
          ((ctxt->options & XML_PARSE_NOENT) == 0) &&
8151
0
    ((ctxt->options & XML_PARSE_DTDVALID) == 0) &&
8152
0
    ((ctxt->options & XML_PARSE_DTDLOAD) == 0) &&
8153
0
    ((ctxt->options & XML_PARSE_DTDATTR) == 0) &&
8154
0
    (ctxt->replaceEntities == 0) &&
8155
0
    (ctxt->validate == 0))
8156
0
    return;
8157
8158
0
            if (entity->flags & XML_ENT_EXPANDING) {
8159
0
                xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
8160
0
                xmlHaltParser(ctxt);
8161
0
                return;
8162
0
            }
8163
8164
            /* Must be computed from old input before pushing new input. */
8165
0
            parentConsumed = ctxt->input->parentConsumed;
8166
0
            oldEnt = ctxt->input->entity;
8167
0
            if ((oldEnt == NULL) ||
8168
0
                ((oldEnt->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
8169
0
                 ((oldEnt->flags & XML_ENT_PARSED) == 0))) {
8170
0
                xmlSaturatedAdd(&parentConsumed, ctxt->input->consumed);
8171
0
                xmlSaturatedAddSizeT(&parentConsumed,
8172
0
                                     ctxt->input->cur - ctxt->input->base);
8173
0
            }
8174
8175
0
      input = xmlNewEntityInputStream(ctxt, entity);
8176
0
      if (xmlPushInput(ctxt, input) < 0) {
8177
0
                xmlFreeInputStream(input);
8178
0
    return;
8179
0
            }
8180
8181
0
            entity->flags |= XML_ENT_EXPANDING;
8182
8183
0
            input->parentConsumed = parentConsumed;
8184
8185
0
      if (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) {
8186
0
                xmlDetectEncoding(ctxt);
8187
8188
0
                if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) &&
8189
0
                    (IS_BLANK_CH(NXT(5)))) {
8190
0
                    xmlParseTextDecl(ctxt);
8191
0
                }
8192
0
            }
8193
0
  }
8194
0
    }
8195
0
    ctxt->hasPErefs = 1;
8196
0
}
8197
8198
/**
8199
 * xmlLoadEntityContent:
8200
 * @ctxt:  an XML parser context
8201
 * @entity: an unloaded system entity
8202
 *
8203
 * Load the original content of the given system entity from the
8204
 * ExternalID/SystemID given. This is to be used for Included in Literal
8205
 * http://www.w3.org/TR/REC-xml/#inliteral processing of entities references
8206
 *
8207
 * Returns 0 in case of success and -1 in case of failure
8208
 */
8209
static int
8210
0
xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
8211
0
    xmlParserInputPtr oldinput, input = NULL;
8212
0
    xmlParserInputPtr *oldinputTab;
8213
0
    const xmlChar *oldencoding;
8214
0
    xmlChar *content = NULL;
8215
0
    size_t length, i;
8216
0
    int oldinputNr, oldinputMax, oldprogressive;
8217
0
    int ret = -1;
8218
0
    int res;
8219
8220
0
    if ((ctxt == NULL) || (entity == NULL) ||
8221
0
        ((entity->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
8222
0
   (entity->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY)) ||
8223
0
  (entity->content != NULL)) {
8224
0
  xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8225
0
              "xmlLoadEntityContent parameter error");
8226
0
        return(-1);
8227
0
    }
8228
8229
0
    if (xmlParserDebugEntities)
8230
0
  xmlGenericError(xmlGenericErrorContext,
8231
0
    "Reading %s entity content input\n", entity->name);
8232
8233
0
    input = xmlLoadExternalEntity((char *) entity->URI,
8234
0
           (char *) entity->ExternalID, ctxt);
8235
0
    if (input == NULL) {
8236
0
  xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8237
0
              "xmlLoadEntityContent input error");
8238
0
        return(-1);
8239
0
    }
8240
8241
0
    oldinput = ctxt->input;
8242
0
    oldinputNr = ctxt->inputNr;
8243
0
    oldinputMax = ctxt->inputMax;
8244
0
    oldinputTab = ctxt->inputTab;
8245
0
    oldencoding = ctxt->encoding;
8246
0
    oldprogressive = ctxt->progressive;
8247
8248
0
    ctxt->input = NULL;
8249
0
    ctxt->inputNr = 0;
8250
0
    ctxt->inputMax = 1;
8251
0
    ctxt->encoding = NULL;
8252
0
    ctxt->progressive = 0;
8253
0
    ctxt->inputTab = xmlMalloc(sizeof(xmlParserInputPtr));
8254
0
    if (ctxt->inputTab == NULL) {
8255
0
        xmlErrMemory(ctxt, NULL);
8256
0
        xmlFreeInputStream(input);
8257
0
        goto error;
8258
0
    }
8259
8260
0
    xmlBufResetInput(input->buf->buffer, input);
8261
8262
0
    inputPush(ctxt, input);
8263
8264
0
    xmlDetectEncoding(ctxt);
8265
8266
    /*
8267
     * Parse a possible text declaration first
8268
     */
8269
0
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
8270
0
  xmlParseTextDecl(ctxt);
8271
        /*
8272
         * An XML-1.0 document can't reference an entity not XML-1.0
8273
         */
8274
0
        if ((xmlStrEqual(ctxt->version, BAD_CAST "1.0")) &&
8275
0
            (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) {
8276
0
            xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH,
8277
0
                           "Version mismatch between document and entity\n");
8278
0
        }
8279
0
    }
8280
8281
0
    if (ctxt->instate == XML_PARSER_EOF)
8282
0
        goto error;
8283
8284
0
    length = input->cur - input->base;
8285
0
    xmlBufShrink(input->buf->buffer, length);
8286
0
    xmlSaturatedAdd(&ctxt->sizeentities, length);
8287
8288
0
    while ((res = xmlParserInputBufferGrow(input->buf, 4096)) > 0)
8289
0
        ;
8290
8291
0
    xmlBufResetInput(input->buf->buffer, input);
8292
8293
0
    if (res < 0) {
8294
0
        xmlFatalErr(ctxt, input->buf->error, NULL);
8295
0
        goto error;
8296
0
    }
8297
8298
0
    length = xmlBufUse(input->buf->buffer);
8299
0
    content = xmlBufDetach(input->buf->buffer);
8300
8301
0
    if (length > INT_MAX) {
8302
0
        xmlErrMemory(ctxt, NULL);
8303
0
        goto error;
8304
0
    }
8305
8306
0
    for (i = 0; i < length; ) {
8307
0
        int clen = length - i;
8308
0
        int c = xmlGetUTF8Char(content + i, &clen);
8309
8310
0
        if ((c < 0) || (!IS_CHAR(c))) {
8311
0
            xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
8312
0
                              "xmlLoadEntityContent: invalid char value %d\n",
8313
0
                              content[i]);
8314
0
            goto error;
8315
0
        }
8316
0
        i += clen;
8317
0
    }
8318
8319
0
    xmlSaturatedAdd(&ctxt->sizeentities, length);
8320
0
    entity->content = content;
8321
0
    entity->length = length;
8322
0
    content = NULL;
8323
0
    ret = 0;
8324
8325
0
error:
8326
0
    while (ctxt->inputNr > 0)
8327
0
        xmlFreeInputStream(inputPop(ctxt));
8328
0
    xmlFree(ctxt->inputTab);
8329
0
    xmlFree((xmlChar *) ctxt->encoding);
8330
8331
0
    ctxt->input = oldinput;
8332
0
    ctxt->inputNr = oldinputNr;
8333
0
    ctxt->inputMax = oldinputMax;
8334
0
    ctxt->inputTab = oldinputTab;
8335
0
    ctxt->encoding = oldencoding;
8336
0
    ctxt->progressive = oldprogressive;
8337
8338
0
    xmlFree(content);
8339
8340
0
    return(ret);
8341
0
}
8342
8343
/**
8344
 * xmlParseStringPEReference:
8345
 * @ctxt:  an XML parser context
8346
 * @str:  a pointer to an index in the string
8347
 *
8348
 * parse PEReference declarations
8349
 *
8350
 * [69] PEReference ::= '%' Name ';'
8351
 *
8352
 * [ WFC: No Recursion ]
8353
 * A parsed entity must not contain a recursive
8354
 * reference to itself, either directly or indirectly.
8355
 *
8356
 * [ WFC: Entity Declared ]
8357
 * In a document without any DTD, a document with only an internal DTD
8358
 * subset which contains no parameter entity references, or a document
8359
 * with "standalone='yes'", ...  ... The declaration of a parameter
8360
 * entity must precede any reference to it...
8361
 *
8362
 * [ VC: Entity Declared ]
8363
 * In a document with an external subset or external parameter entities
8364
 * with "standalone='no'", ...  ... The declaration of a parameter entity
8365
 * must precede any reference to it...
8366
 *
8367
 * [ WFC: In DTD ]
8368
 * Parameter-entity references may only appear in the DTD.
8369
 * NOTE: misleading but this is handled.
8370
 *
8371
 * Returns the string of the entity content.
8372
 *         str is updated to the current value of the index
8373
 */
8374
static xmlEntityPtr
8375
0
xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
8376
0
    const xmlChar *ptr;
8377
0
    xmlChar cur;
8378
0
    xmlChar *name;
8379
0
    xmlEntityPtr entity = NULL;
8380
8381
0
    if ((str == NULL) || (*str == NULL)) return(NULL);
8382
0
    ptr = *str;
8383
0
    cur = *ptr;
8384
0
    if (cur != '%')
8385
0
        return(NULL);
8386
0
    ptr++;
8387
0
    name = xmlParseStringName(ctxt, &ptr);
8388
0
    if (name == NULL) {
8389
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8390
0
           "xmlParseStringPEReference: no name\n");
8391
0
  *str = ptr;
8392
0
  return(NULL);
8393
0
    }
8394
0
    cur = *ptr;
8395
0
    if (cur != ';') {
8396
0
  xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
8397
0
  xmlFree(name);
8398
0
  *str = ptr;
8399
0
  return(NULL);
8400
0
    }
8401
0
    ptr++;
8402
8403
    /*
8404
     * Request the entity from SAX
8405
     */
8406
0
    if ((ctxt->sax != NULL) &&
8407
0
  (ctxt->sax->getParameterEntity != NULL))
8408
0
  entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
8409
0
    if (ctxt->instate == XML_PARSER_EOF) {
8410
0
  xmlFree(name);
8411
0
  *str = ptr;
8412
0
  return(NULL);
8413
0
    }
8414
0
    if (entity == NULL) {
8415
  /*
8416
   * [ WFC: Entity Declared ]
8417
   * In a document without any DTD, a document with only an
8418
   * internal DTD subset which contains no parameter entity
8419
   * references, or a document with "standalone='yes'", ...
8420
   * ... The declaration of a parameter entity must precede
8421
   * any reference to it...
8422
   */
8423
0
  if ((ctxt->standalone == 1) ||
8424
0
      ((ctxt->hasExternalSubset == 0) && (ctxt->hasPErefs == 0))) {
8425
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
8426
0
     "PEReference: %%%s; not found\n", name);
8427
0
  } else {
8428
      /*
8429
       * [ VC: Entity Declared ]
8430
       * In a document with an external subset or external
8431
       * parameter entities with "standalone='no'", ...
8432
       * ... The declaration of a parameter entity must
8433
       * precede any reference to it...
8434
       */
8435
0
      xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8436
0
        "PEReference: %%%s; not found\n",
8437
0
        name, NULL);
8438
0
      ctxt->valid = 0;
8439
0
  }
8440
0
    } else {
8441
  /*
8442
   * Internal checking in case the entity quest barfed
8443
   */
8444
0
  if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
8445
0
      (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
8446
0
      xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8447
0
        "%%%s; is not a parameter entity\n",
8448
0
        name, NULL);
8449
0
  }
8450
0
    }
8451
0
    ctxt->hasPErefs = 1;
8452
0
    xmlFree(name);
8453
0
    *str = ptr;
8454
0
    return(entity);
8455
0
}
8456
8457
/**
8458
 * xmlParseDocTypeDecl:
8459
 * @ctxt:  an XML parser context
8460
 *
8461
 * DEPRECATED: Internal function, don't use.
8462
 *
8463
 * parse a DOCTYPE declaration
8464
 *
8465
 * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
8466
 *                      ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
8467
 *
8468
 * [ VC: Root Element Type ]
8469
 * The Name in the document type declaration must match the element
8470
 * type of the root element.
8471
 */
8472
8473
void
8474
0
xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
8475
0
    const xmlChar *name = NULL;
8476
0
    xmlChar *ExternalID = NULL;
8477
0
    xmlChar *URI = NULL;
8478
8479
    /*
8480
     * We know that '<!DOCTYPE' has been detected.
8481
     */
8482
0
    SKIP(9);
8483
8484
0
    SKIP_BLANKS;
8485
8486
    /*
8487
     * Parse the DOCTYPE name.
8488
     */
8489
0
    name = xmlParseName(ctxt);
8490
0
    if (name == NULL) {
8491
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8492
0
           "xmlParseDocTypeDecl : no DOCTYPE name !\n");
8493
0
    }
8494
0
    ctxt->intSubName = name;
8495
8496
0
    SKIP_BLANKS;
8497
8498
    /*
8499
     * Check for SystemID and ExternalID
8500
     */
8501
0
    URI = xmlParseExternalID(ctxt, &ExternalID, 1);
8502
8503
0
    if ((URI != NULL) || (ExternalID != NULL)) {
8504
0
        ctxt->hasExternalSubset = 1;
8505
0
    }
8506
0
    ctxt->extSubURI = URI;
8507
0
    ctxt->extSubSystem = ExternalID;
8508
8509
0
    SKIP_BLANKS;
8510
8511
    /*
8512
     * Create and update the internal subset.
8513
     */
8514
0
    if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL) &&
8515
0
  (!ctxt->disableSAX))
8516
0
  ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
8517
0
    if (ctxt->instate == XML_PARSER_EOF)
8518
0
  return;
8519
8520
    /*
8521
     * Is there any internal subset declarations ?
8522
     * they are handled separately in xmlParseInternalSubset()
8523
     */
8524
0
    if (RAW == '[')
8525
0
  return;
8526
8527
    /*
8528
     * We should be at the end of the DOCTYPE declaration.
8529
     */
8530
0
    if (RAW != '>') {
8531
0
  xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
8532
0
    }
8533
0
    NEXT;
8534
0
}
8535
8536
/**
8537
 * xmlParseInternalSubset:
8538
 * @ctxt:  an XML parser context
8539
 *
8540
 * parse the internal subset declaration
8541
 *
8542
 * [28 end] ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
8543
 */
8544
8545
static void
8546
0
xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
8547
    /*
8548
     * Is there any DTD definition ?
8549
     */
8550
0
    if (RAW == '[') {
8551
0
        int baseInputNr = ctxt->inputNr;
8552
0
        ctxt->instate = XML_PARSER_DTD;
8553
0
        NEXT;
8554
  /*
8555
   * Parse the succession of Markup declarations and
8556
   * PEReferences.
8557
   * Subsequence (markupdecl | PEReference | S)*
8558
   */
8559
0
  SKIP_BLANKS;
8560
0
  while (((RAW != ']') || (ctxt->inputNr > baseInputNr)) &&
8561
0
               (ctxt->instate != XML_PARSER_EOF)) {
8562
8563
            /*
8564
             * Conditional sections are allowed from external entities included
8565
             * by PE References in the internal subset.
8566
             */
8567
0
            if ((ctxt->inputNr > 1) && (ctxt->input->filename != NULL) &&
8568
0
                (RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
8569
0
                xmlParseConditionalSections(ctxt);
8570
0
            } else if ((RAW == '<') && ((NXT(1) == '!') || (NXT(1) == '?'))) {
8571
0
          xmlParseMarkupDecl(ctxt);
8572
0
            } else if (RAW == '%') {
8573
0
          xmlParsePEReference(ctxt);
8574
0
            } else {
8575
0
    xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8576
0
                        "xmlParseInternalSubset: error detected in"
8577
0
                        " Markup declaration\n");
8578
0
                xmlHaltParser(ctxt);
8579
0
                return;
8580
0
            }
8581
0
      SKIP_BLANKS;
8582
0
            SHRINK;
8583
0
            GROW;
8584
0
  }
8585
0
  if (RAW == ']') {
8586
0
      NEXT;
8587
0
      SKIP_BLANKS;
8588
0
  }
8589
0
    }
8590
8591
    /*
8592
     * We should be at the end of the DOCTYPE declaration.
8593
     */
8594
0
    if (RAW != '>') {
8595
0
  xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
8596
0
  return;
8597
0
    }
8598
0
    NEXT;
8599
0
}
8600
8601
#ifdef LIBXML_SAX1_ENABLED
8602
/**
8603
 * xmlParseAttribute:
8604
 * @ctxt:  an XML parser context
8605
 * @value:  a xmlChar ** used to store the value of the attribute
8606
 *
8607
 * DEPRECATED: Internal function, don't use.
8608
 *
8609
 * parse an attribute
8610
 *
8611
 * [41] Attribute ::= Name Eq AttValue
8612
 *
8613
 * [ WFC: No External Entity References ]
8614
 * Attribute values cannot contain direct or indirect entity references
8615
 * to external entities.
8616
 *
8617
 * [ WFC: No < in Attribute Values ]
8618
 * The replacement text of any entity referred to directly or indirectly in
8619
 * an attribute value (other than "&lt;") must not contain a <.
8620
 *
8621
 * [ VC: Attribute Value Type ]
8622
 * The attribute must have been declared; the value must be of the type
8623
 * declared for it.
8624
 *
8625
 * [25] Eq ::= S? '=' S?
8626
 *
8627
 * With namespace:
8628
 *
8629
 * [NS 11] Attribute ::= QName Eq AttValue
8630
 *
8631
 * Also the case QName == xmlns:??? is handled independently as a namespace
8632
 * definition.
8633
 *
8634
 * Returns the attribute name, and the value in *value.
8635
 */
8636
8637
const xmlChar *
8638
0
xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
8639
0
    const xmlChar *name;
8640
0
    xmlChar *val;
8641
8642
0
    *value = NULL;
8643
0
    GROW;
8644
0
    name = xmlParseName(ctxt);
8645
0
    if (name == NULL) {
8646
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8647
0
                 "error parsing attribute name\n");
8648
0
        return(NULL);
8649
0
    }
8650
8651
    /*
8652
     * read the value
8653
     */
8654
0
    SKIP_BLANKS;
8655
0
    if (RAW == '=') {
8656
0
        NEXT;
8657
0
  SKIP_BLANKS;
8658
0
  val = xmlParseAttValue(ctxt);
8659
0
  ctxt->instate = XML_PARSER_CONTENT;
8660
0
    } else {
8661
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
8662
0
         "Specification mandates value for attribute %s\n", name);
8663
0
  return(name);
8664
0
    }
8665
8666
    /*
8667
     * Check that xml:lang conforms to the specification
8668
     * No more registered as an error, just generate a warning now
8669
     * since this was deprecated in XML second edition
8670
     */
8671
0
    if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "xml:lang"))) {
8672
0
  if (!xmlCheckLanguageID(val)) {
8673
0
      xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
8674
0
              "Malformed value for xml:lang : %s\n",
8675
0
        val, NULL);
8676
0
  }
8677
0
    }
8678
8679
    /*
8680
     * Check that xml:space conforms to the specification
8681
     */
8682
0
    if (xmlStrEqual(name, BAD_CAST "xml:space")) {
8683
0
  if (xmlStrEqual(val, BAD_CAST "default"))
8684
0
      *(ctxt->space) = 0;
8685
0
  else if (xmlStrEqual(val, BAD_CAST "preserve"))
8686
0
      *(ctxt->space) = 1;
8687
0
  else {
8688
0
    xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
8689
0
"Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
8690
0
                                 val, NULL);
8691
0
  }
8692
0
    }
8693
8694
0
    *value = val;
8695
0
    return(name);
8696
0
}
8697
8698
/**
8699
 * xmlParseStartTag:
8700
 * @ctxt:  an XML parser context
8701
 *
8702
 * DEPRECATED: Internal function, don't use.
8703
 *
8704
 * Parse a start tag. Always consumes '<'.
8705
 *
8706
 * [40] STag ::= '<' Name (S Attribute)* S? '>'
8707
 *
8708
 * [ WFC: Unique Att Spec ]
8709
 * No attribute name may appear more than once in the same start-tag or
8710
 * empty-element tag.
8711
 *
8712
 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
8713
 *
8714
 * [ WFC: Unique Att Spec ]
8715
 * No attribute name may appear more than once in the same start-tag or
8716
 * empty-element tag.
8717
 *
8718
 * With namespace:
8719
 *
8720
 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
8721
 *
8722
 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
8723
 *
8724
 * Returns the element name parsed
8725
 */
8726
8727
const xmlChar *
8728
0
xmlParseStartTag(xmlParserCtxtPtr ctxt) {
8729
0
    const xmlChar *name;
8730
0
    const xmlChar *attname;
8731
0
    xmlChar *attvalue;
8732
0
    const xmlChar **atts = ctxt->atts;
8733
0
    int nbatts = 0;
8734
0
    int maxatts = ctxt->maxatts;
8735
0
    int i;
8736
8737
0
    if (RAW != '<') return(NULL);
8738
0
    NEXT1;
8739
8740
0
    name = xmlParseName(ctxt);
8741
0
    if (name == NULL) {
8742
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8743
0
       "xmlParseStartTag: invalid element name\n");
8744
0
        return(NULL);
8745
0
    }
8746
8747
    /*
8748
     * Now parse the attributes, it ends up with the ending
8749
     *
8750
     * (S Attribute)* S?
8751
     */
8752
0
    SKIP_BLANKS;
8753
0
    GROW;
8754
8755
0
    while (((RAW != '>') &&
8756
0
     ((RAW != '/') || (NXT(1) != '>')) &&
8757
0
     (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) {
8758
0
  attname = xmlParseAttribute(ctxt, &attvalue);
8759
0
        if (attname == NULL) {
8760
0
      xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
8761
0
         "xmlParseStartTag: problem parsing attributes\n");
8762
0
      break;
8763
0
  }
8764
0
        if (attvalue != NULL) {
8765
      /*
8766
       * [ WFC: Unique Att Spec ]
8767
       * No attribute name may appear more than once in the same
8768
       * start-tag or empty-element tag.
8769
       */
8770
0
      for (i = 0; i < nbatts;i += 2) {
8771
0
          if (xmlStrEqual(atts[i], attname)) {
8772
0
        xmlErrAttributeDup(ctxt, NULL, attname);
8773
0
        xmlFree(attvalue);
8774
0
        goto failed;
8775
0
    }
8776
0
      }
8777
      /*
8778
       * Add the pair to atts
8779
       */
8780
0
      if (atts == NULL) {
8781
0
          maxatts = 22; /* allow for 10 attrs by default */
8782
0
          atts = (const xmlChar **)
8783
0
           xmlMalloc(maxatts * sizeof(xmlChar *));
8784
0
    if (atts == NULL) {
8785
0
        xmlErrMemory(ctxt, NULL);
8786
0
        if (attvalue != NULL)
8787
0
      xmlFree(attvalue);
8788
0
        goto failed;
8789
0
    }
8790
0
    ctxt->atts = atts;
8791
0
    ctxt->maxatts = maxatts;
8792
0
      } else if (nbatts + 4 > maxatts) {
8793
0
          const xmlChar **n;
8794
8795
0
          maxatts *= 2;
8796
0
          n = (const xmlChar **) xmlRealloc((void *) atts,
8797
0
               maxatts * sizeof(const xmlChar *));
8798
0
    if (n == NULL) {
8799
0
        xmlErrMemory(ctxt, NULL);
8800
0
        if (attvalue != NULL)
8801
0
      xmlFree(attvalue);
8802
0
        goto failed;
8803
0
    }
8804
0
    atts = n;
8805
0
    ctxt->atts = atts;
8806
0
    ctxt->maxatts = maxatts;
8807
0
      }
8808
0
      atts[nbatts++] = attname;
8809
0
      atts[nbatts++] = attvalue;
8810
0
      atts[nbatts] = NULL;
8811
0
      atts[nbatts + 1] = NULL;
8812
0
  } else {
8813
0
      if (attvalue != NULL)
8814
0
    xmlFree(attvalue);
8815
0
  }
8816
8817
0
failed:
8818
8819
0
  GROW
8820
0
  if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
8821
0
      break;
8822
0
  if (SKIP_BLANKS == 0) {
8823
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
8824
0
         "attributes construct error\n");
8825
0
  }
8826
0
  SHRINK;
8827
0
        GROW;
8828
0
    }
8829
8830
    /*
8831
     * SAX: Start of Element !
8832
     */
8833
0
    if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL) &&
8834
0
  (!ctxt->disableSAX)) {
8835
0
  if (nbatts > 0)
8836
0
      ctxt->sax->startElement(ctxt->userData, name, atts);
8837
0
  else
8838
0
      ctxt->sax->startElement(ctxt->userData, name, NULL);
8839
0
    }
8840
8841
0
    if (atts != NULL) {
8842
        /* Free only the content strings */
8843
0
        for (i = 1;i < nbatts;i+=2)
8844
0
      if (atts[i] != NULL)
8845
0
         xmlFree((xmlChar *) atts[i]);
8846
0
    }
8847
0
    return(name);
8848
0
}
8849
8850
/**
8851
 * xmlParseEndTag1:
8852
 * @ctxt:  an XML parser context
8853
 * @line:  line of the start tag
8854
 * @nsNr:  number of namespaces on the start tag
8855
 *
8856
 * Parse an end tag. Always consumes '</'.
8857
 *
8858
 * [42] ETag ::= '</' Name S? '>'
8859
 *
8860
 * With namespace
8861
 *
8862
 * [NS 9] ETag ::= '</' QName S? '>'
8863
 */
8864
8865
static void
8866
0
xmlParseEndTag1(xmlParserCtxtPtr ctxt, int line) {
8867
0
    const xmlChar *name;
8868
8869
0
    GROW;
8870
0
    if ((RAW != '<') || (NXT(1) != '/')) {
8871
0
  xmlFatalErrMsg(ctxt, XML_ERR_LTSLASH_REQUIRED,
8872
0
           "xmlParseEndTag: '</' not found\n");
8873
0
  return;
8874
0
    }
8875
0
    SKIP(2);
8876
8877
0
    name = xmlParseNameAndCompare(ctxt,ctxt->name);
8878
8879
    /*
8880
     * We should definitely be at the ending "S? '>'" part
8881
     */
8882
0
    GROW;
8883
0
    SKIP_BLANKS;
8884
0
    if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
8885
0
  xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
8886
0
    } else
8887
0
  NEXT1;
8888
8889
    /*
8890
     * [ WFC: Element Type Match ]
8891
     * The Name in an element's end-tag must match the element type in the
8892
     * start-tag.
8893
     *
8894
     */
8895
0
    if (name != (xmlChar*)1) {
8896
0
        if (name == NULL) name = BAD_CAST "unparsable";
8897
0
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
8898
0
         "Opening and ending tag mismatch: %s line %d and %s\n",
8899
0
                    ctxt->name, line, name);
8900
0
    }
8901
8902
    /*
8903
     * SAX: End of Tag
8904
     */
8905
0
    if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
8906
0
  (!ctxt->disableSAX))
8907
0
        ctxt->sax->endElement(ctxt->userData, ctxt->name);
8908
8909
0
    namePop(ctxt);
8910
0
    spacePop(ctxt);
8911
0
    return;
8912
0
}
8913
8914
/**
8915
 * xmlParseEndTag:
8916
 * @ctxt:  an XML parser context
8917
 *
8918
 * DEPRECATED: Internal function, don't use.
8919
 *
8920
 * parse an end of tag
8921
 *
8922
 * [42] ETag ::= '</' Name S? '>'
8923
 *
8924
 * With namespace
8925
 *
8926
 * [NS 9] ETag ::= '</' QName S? '>'
8927
 */
8928
8929
void
8930
0
xmlParseEndTag(xmlParserCtxtPtr ctxt) {
8931
0
    xmlParseEndTag1(ctxt, 0);
8932
0
}
8933
#endif /* LIBXML_SAX1_ENABLED */
8934
8935
/************************************************************************
8936
 *                  *
8937
 *          SAX 2 specific operations       *
8938
 *                  *
8939
 ************************************************************************/
8940
8941
/**
8942
 * xmlParseQNameHashed:
8943
 * @ctxt:  an XML parser context
8944
 * @prefix:  pointer to store the prefix part
8945
 *
8946
 * parse an XML Namespace QName
8947
 *
8948
 * [6]  QName  ::= (Prefix ':')? LocalPart
8949
 * [7]  Prefix  ::= NCName
8950
 * [8]  LocalPart  ::= NCName
8951
 *
8952
 * Returns the Name parsed or NULL
8953
 */
8954
8955
static xmlHashedString
8956
0
xmlParseQNameHashed(xmlParserCtxtPtr ctxt, xmlHashedString *prefix) {
8957
0
    xmlHashedString l, p;
8958
0
    int start, isNCName = 0;
8959
8960
0
    l.name = NULL;
8961
0
    p.name = NULL;
8962
8963
0
    GROW;
8964
0
    if (ctxt->instate == XML_PARSER_EOF)
8965
0
        return(l);
8966
0
    start = CUR_PTR - BASE_PTR;
8967
8968
0
    l = xmlParseNCName(ctxt);
8969
0
    if (l.name != NULL) {
8970
0
        isNCName = 1;
8971
0
        if (CUR == ':') {
8972
0
            NEXT;
8973
0
            p = l;
8974
0
            l = xmlParseNCName(ctxt);
8975
0
        }
8976
0
    }
8977
0
    if ((l.name == NULL) || (CUR == ':')) {
8978
0
        xmlChar *tmp;
8979
8980
0
        l.name = NULL;
8981
0
        p.name = NULL;
8982
0
        if (ctxt->instate == XML_PARSER_EOF)
8983
0
            return(l);
8984
0
        if ((isNCName == 0) && (CUR != ':'))
8985
0
            return(l);
8986
0
        tmp = xmlParseNmtoken(ctxt);
8987
0
        if (tmp != NULL)
8988
0
            xmlFree(tmp);
8989
0
        if (ctxt->instate == XML_PARSER_EOF)
8990
0
            return(l);
8991
0
        l = xmlDictLookupHashed(ctxt->dict, BASE_PTR + start,
8992
0
                                CUR_PTR - (BASE_PTR + start));
8993
0
        xmlNsErr(ctxt, XML_NS_ERR_QNAME,
8994
0
                 "Failed to parse QName '%s'\n", l.name, NULL, NULL);
8995
0
    }
8996
8997
0
    *prefix = p;
8998
0
    return(l);
8999
0
}
9000
9001
/**
9002
 * xmlParseQName:
9003
 * @ctxt:  an XML parser context
9004
 * @prefix:  pointer to store the prefix part
9005
 *
9006
 * parse an XML Namespace QName
9007
 *
9008
 * [6]  QName  ::= (Prefix ':')? LocalPart
9009
 * [7]  Prefix  ::= NCName
9010
 * [8]  LocalPart  ::= NCName
9011
 *
9012
 * Returns the Name parsed or NULL
9013
 */
9014
9015
static const xmlChar *
9016
0
xmlParseQName(xmlParserCtxtPtr ctxt, const xmlChar **prefix) {
9017
0
    xmlHashedString n, p;
9018
9019
0
    n = xmlParseQNameHashed(ctxt, &p);
9020
0
    if (n.name == NULL)
9021
0
        return(NULL);
9022
0
    *prefix = p.name;
9023
0
    return(n.name);
9024
0
}
9025
9026
/**
9027
 * xmlParseQNameAndCompare:
9028
 * @ctxt:  an XML parser context
9029
 * @name:  the localname
9030
 * @prefix:  the prefix, if any.
9031
 *
9032
 * parse an XML name and compares for match
9033
 * (specialized for endtag parsing)
9034
 *
9035
 * Returns NULL for an illegal name, (xmlChar*) 1 for success
9036
 * and the name for mismatch
9037
 */
9038
9039
static const xmlChar *
9040
xmlParseQNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *name,
9041
0
                        xmlChar const *prefix) {
9042
0
    const xmlChar *cmp;
9043
0
    const xmlChar *in;
9044
0
    const xmlChar *ret;
9045
0
    const xmlChar *prefix2;
9046
9047
0
    if (prefix == NULL) return(xmlParseNameAndCompare(ctxt, name));
9048
9049
0
    GROW;
9050
0
    in = ctxt->input->cur;
9051
9052
0
    cmp = prefix;
9053
0
    while (*in != 0 && *in == *cmp) {
9054
0
  ++in;
9055
0
  ++cmp;
9056
0
    }
9057
0
    if ((*cmp == 0) && (*in == ':')) {
9058
0
        in++;
9059
0
  cmp = name;
9060
0
  while (*in != 0 && *in == *cmp) {
9061
0
      ++in;
9062
0
      ++cmp;
9063
0
  }
9064
0
  if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
9065
      /* success */
9066
0
            ctxt->input->col += in - ctxt->input->cur;
9067
0
      ctxt->input->cur = in;
9068
0
      return((const xmlChar*) 1);
9069
0
  }
9070
0
    }
9071
    /*
9072
     * all strings coms from the dictionary, equality can be done directly
9073
     */
9074
0
    ret = xmlParseQName (ctxt, &prefix2);
9075
0
    if (ret == NULL)
9076
0
        return(NULL);
9077
0
    if ((ret == name) && (prefix == prefix2))
9078
0
  return((const xmlChar*) 1);
9079
0
    return ret;
9080
0
}
9081
9082
/**
9083
 * xmlParseAttValueInternal:
9084
 * @ctxt:  an XML parser context
9085
 * @len:  attribute len result
9086
 * @alloc:  whether the attribute was reallocated as a new string
9087
 * @normalize:  if 1 then further non-CDATA normalization must be done
9088
 *
9089
 * parse a value for an attribute.
9090
 * NOTE: if no normalization is needed, the routine will return pointers
9091
 *       directly from the data buffer.
9092
 *
9093
 * 3.3.3 Attribute-Value Normalization:
9094
 * Before the value of an attribute is passed to the application or
9095
 * checked for validity, the XML processor must normalize it as follows:
9096
 * - a character reference is processed by appending the referenced
9097
 *   character to the attribute value
9098
 * - an entity reference is processed by recursively processing the
9099
 *   replacement text of the entity
9100
 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
9101
 *   appending #x20 to the normalized value, except that only a single
9102
 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
9103
 *   parsed entity or the literal entity value of an internal parsed entity
9104
 * - other characters are processed by appending them to the normalized value
9105
 * If the declared value is not CDATA, then the XML processor must further
9106
 * process the normalized attribute value by discarding any leading and
9107
 * trailing space (#x20) characters, and by replacing sequences of space
9108
 * (#x20) characters by a single space (#x20) character.
9109
 * All attributes for which no declaration has been read should be treated
9110
 * by a non-validating parser as if declared CDATA.
9111
 *
9112
 * Returns the AttValue parsed or NULL. The value has to be freed by the
9113
 *     caller if it was copied, this can be detected by val[*len] == 0.
9114
 */
9115
9116
#define GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end) \
9117
0
    const xmlChar *oldbase = ctxt->input->base;\
9118
0
    GROW;\
9119
0
    if (ctxt->instate == XML_PARSER_EOF)\
9120
0
        return(NULL);\
9121
0
    if (oldbase != ctxt->input->base) {\
9122
0
        ptrdiff_t delta = ctxt->input->base - oldbase;\
9123
0
        start = start + delta;\
9124
0
        in = in + delta;\
9125
0
    }\
9126
0
    end = ctxt->input->end;
9127
9128
static xmlChar *
9129
xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
9130
                         int normalize)
9131
0
{
9132
0
    xmlChar limit = 0;
9133
0
    const xmlChar *in = NULL, *start, *end, *last;
9134
0
    xmlChar *ret = NULL;
9135
0
    int line, col;
9136
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
9137
0
                    XML_MAX_HUGE_LENGTH :
9138
0
                    XML_MAX_TEXT_LENGTH;
9139
9140
0
    GROW;
9141
0
    in = (xmlChar *) CUR_PTR;
9142
0
    line = ctxt->input->line;
9143
0
    col = ctxt->input->col;
9144
0
    if (*in != '"' && *in != '\'') {
9145
0
        xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
9146
0
        return (NULL);
9147
0
    }
9148
0
    ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
9149
9150
    /*
9151
     * try to handle in this routine the most common case where no
9152
     * allocation of a new string is required and where content is
9153
     * pure ASCII.
9154
     */
9155
0
    limit = *in++;
9156
0
    col++;
9157
0
    end = ctxt->input->end;
9158
0
    start = in;
9159
0
    if (in >= end) {
9160
0
        GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
9161
0
    }
9162
0
    if (normalize) {
9163
        /*
9164
   * Skip any leading spaces
9165
   */
9166
0
  while ((in < end) && (*in != limit) &&
9167
0
         ((*in == 0x20) || (*in == 0x9) ||
9168
0
          (*in == 0xA) || (*in == 0xD))) {
9169
0
      if (*in == 0xA) {
9170
0
          line++; col = 1;
9171
0
      } else {
9172
0
          col++;
9173
0
      }
9174
0
      in++;
9175
0
      start = in;
9176
0
      if (in >= end) {
9177
0
                GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
9178
0
                if ((in - start) > maxLength) {
9179
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9180
0
                                   "AttValue length too long\n");
9181
0
                    return(NULL);
9182
0
                }
9183
0
      }
9184
0
  }
9185
0
  while ((in < end) && (*in != limit) && (*in >= 0x20) &&
9186
0
         (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
9187
0
      col++;
9188
0
      if ((*in++ == 0x20) && (*in == 0x20)) break;
9189
0
      if (in >= end) {
9190
0
                GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
9191
0
                if ((in - start) > maxLength) {
9192
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9193
0
                                   "AttValue length too long\n");
9194
0
                    return(NULL);
9195
0
                }
9196
0
      }
9197
0
  }
9198
0
  last = in;
9199
  /*
9200
   * skip the trailing blanks
9201
   */
9202
0
  while ((last[-1] == 0x20) && (last > start)) last--;
9203
0
  while ((in < end) && (*in != limit) &&
9204
0
         ((*in == 0x20) || (*in == 0x9) ||
9205
0
          (*in == 0xA) || (*in == 0xD))) {
9206
0
      if (*in == 0xA) {
9207
0
          line++, col = 1;
9208
0
      } else {
9209
0
          col++;
9210
0
      }
9211
0
      in++;
9212
0
      if (in >= end) {
9213
0
    const xmlChar *oldbase = ctxt->input->base;
9214
0
    GROW;
9215
0
                if (ctxt->instate == XML_PARSER_EOF)
9216
0
                    return(NULL);
9217
0
    if (oldbase != ctxt->input->base) {
9218
0
        ptrdiff_t delta = ctxt->input->base - oldbase;
9219
0
        start = start + delta;
9220
0
        in = in + delta;
9221
0
        last = last + delta;
9222
0
    }
9223
0
    end = ctxt->input->end;
9224
0
                if ((in - start) > maxLength) {
9225
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9226
0
                                   "AttValue length too long\n");
9227
0
                    return(NULL);
9228
0
                }
9229
0
      }
9230
0
  }
9231
0
        if ((in - start) > maxLength) {
9232
0
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9233
0
                           "AttValue length too long\n");
9234
0
            return(NULL);
9235
0
        }
9236
0
  if (*in != limit) goto need_complex;
9237
0
    } else {
9238
0
  while ((in < end) && (*in != limit) && (*in >= 0x20) &&
9239
0
         (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
9240
0
      in++;
9241
0
      col++;
9242
0
      if (in >= end) {
9243
0
                GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
9244
0
                if ((in - start) > maxLength) {
9245
0
                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9246
0
                                   "AttValue length too long\n");
9247
0
                    return(NULL);
9248
0
                }
9249
0
      }
9250
0
  }
9251
0
  last = in;
9252
0
        if ((in - start) > maxLength) {
9253
0
            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9254
0
                           "AttValue length too long\n");
9255
0
            return(NULL);
9256
0
        }
9257
0
  if (*in != limit) goto need_complex;
9258
0
    }
9259
0
    in++;
9260
0
    col++;
9261
0
    if (len != NULL) {
9262
0
        if (alloc) *alloc = 0;
9263
0
        *len = last - start;
9264
0
        ret = (xmlChar *) start;
9265
0
    } else {
9266
0
        if (alloc) *alloc = 1;
9267
0
        ret = xmlStrndup(start, last - start);
9268
0
    }
9269
0
    CUR_PTR = in;
9270
0
    ctxt->input->line = line;
9271
0
    ctxt->input->col = col;
9272
0
    return ret;
9273
0
need_complex:
9274
0
    if (alloc) *alloc = 1;
9275
0
    return xmlParseAttValueComplex(ctxt, len, normalize);
9276
0
}
9277
9278
/**
9279
 * xmlParseAttribute2:
9280
 * @ctxt:  an XML parser context
9281
 * @pref:  the element prefix
9282
 * @elem:  the element name
9283
 * @prefix:  a xmlChar ** used to store the value of the attribute prefix
9284
 * @value:  a xmlChar ** used to store the value of the attribute
9285
 * @len:  an int * to save the length of the attribute
9286
 * @alloc:  an int * to indicate if the attribute was allocated
9287
 *
9288
 * parse an attribute in the new SAX2 framework.
9289
 *
9290
 * Returns the attribute name, and the value in *value, .
9291
 */
9292
9293
static xmlHashedString
9294
xmlParseAttribute2(xmlParserCtxtPtr ctxt,
9295
                   const xmlChar * pref, const xmlChar * elem,
9296
                   xmlHashedString * hprefix, xmlChar ** value,
9297
                   int *len, int *alloc)
9298
0
{
9299
0
    xmlHashedString hname;
9300
0
    const xmlChar *prefix, *name;
9301
0
    xmlChar *val, *internal_val = NULL;
9302
0
    int normalize = 0;
9303
9304
0
    *value = NULL;
9305
0
    GROW;
9306
0
    hname = xmlParseQNameHashed(ctxt, hprefix);
9307
0
    if (hname.name == NULL) {
9308
0
        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
9309
0
                       "error parsing attribute name\n");
9310
0
        return(hname);
9311
0
    }
9312
0
    name = hname.name;
9313
0
    if (hprefix->name != NULL)
9314
0
        prefix = hprefix->name;
9315
0
    else
9316
0
        prefix = NULL;
9317
9318
    /*
9319
     * get the type if needed
9320
     */
9321
0
    if (ctxt->attsSpecial != NULL) {
9322
0
        int type;
9323
9324
0
        type = (int) (ptrdiff_t) xmlHashQLookup2(ctxt->attsSpecial,
9325
0
                                                 pref, elem,
9326
0
                                                 prefix, name);
9327
0
        if (type != 0)
9328
0
            normalize = 1;
9329
0
    }
9330
9331
    /*
9332
     * read the value
9333
     */
9334
0
    SKIP_BLANKS;
9335
0
    if (RAW == '=') {
9336
0
        NEXT;
9337
0
        SKIP_BLANKS;
9338
0
        val = xmlParseAttValueInternal(ctxt, len, alloc, normalize);
9339
0
        if (val == NULL) {
9340
0
            hname.name = NULL;
9341
0
            return(hname);
9342
0
        }
9343
0
  if (normalize) {
9344
      /*
9345
       * Sometimes a second normalisation pass for spaces is needed
9346
       * but that only happens if charrefs or entities references
9347
       * have been used in the attribute value, i.e. the attribute
9348
       * value have been extracted in an allocated string already.
9349
       */
9350
0
      if (*alloc) {
9351
0
          const xmlChar *val2;
9352
9353
0
          val2 = xmlAttrNormalizeSpace2(ctxt, val, len);
9354
0
    if ((val2 != NULL) && (val2 != val)) {
9355
0
        xmlFree(val);
9356
0
        val = (xmlChar *) val2;
9357
0
    }
9358
0
      }
9359
0
  }
9360
0
        ctxt->instate = XML_PARSER_CONTENT;
9361
0
    } else {
9362
0
        xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
9363
0
                          "Specification mandates value for attribute %s\n",
9364
0
                          name);
9365
0
        return(hname);
9366
0
    }
9367
9368
0
    if (prefix == ctxt->str_xml) {
9369
        /*
9370
         * Check that xml:lang conforms to the specification
9371
         * No more registered as an error, just generate a warning now
9372
         * since this was deprecated in XML second edition
9373
         */
9374
0
        if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "lang"))) {
9375
0
            internal_val = xmlStrndup(val, *len);
9376
0
            if (!xmlCheckLanguageID(internal_val)) {
9377
0
                xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
9378
0
                              "Malformed value for xml:lang : %s\n",
9379
0
                              internal_val, NULL);
9380
0
            }
9381
0
        }
9382
9383
        /*
9384
         * Check that xml:space conforms to the specification
9385
         */
9386
0
        if (xmlStrEqual(name, BAD_CAST "space")) {
9387
0
            internal_val = xmlStrndup(val, *len);
9388
0
            if (xmlStrEqual(internal_val, BAD_CAST "default"))
9389
0
                *(ctxt->space) = 0;
9390
0
            else if (xmlStrEqual(internal_val, BAD_CAST "preserve"))
9391
0
                *(ctxt->space) = 1;
9392
0
            else {
9393
0
                xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
9394
0
                              "Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
9395
0
                              internal_val, NULL);
9396
0
            }
9397
0
        }
9398
0
        if (internal_val) {
9399
0
            xmlFree(internal_val);
9400
0
        }
9401
0
    }
9402
9403
0
    *value = val;
9404
0
    return (hname);
9405
0
}
9406
9407
/**
9408
 * xmlAttrHashInsert:
9409
 * @ctxt: parser context
9410
 * @size: size of the hash table
9411
 * @name: attribute name
9412
 * @uri: namespace uri
9413
 * @hashValue: combined hash value of name and uri
9414
 * @aindex: attribute index (this is a multiple of 5)
9415
 *
9416
 * Inserts a new attribute into the hash table.
9417
 *
9418
 * Returns INT_MAX if no existing attribute was found, the attribute
9419
 * index if an attribute was found, -1 if a memory allocation failed.
9420
 */
9421
static int
9422
xmlAttrHashInsert(xmlParserCtxtPtr ctxt, unsigned size, const xmlChar *name,
9423
0
                  const xmlChar *uri, unsigned hashValue, int aindex) {
9424
0
    xmlAttrHashBucket *table = ctxt->attrHash;
9425
0
    xmlAttrHashBucket *bucket;
9426
0
    unsigned hindex;
9427
9428
0
    hindex = hashValue & (size - 1);
9429
0
    bucket = &table[hindex];
9430
9431
0
    while (bucket->index >= 0) {
9432
0
        const xmlChar **atts = &ctxt->atts[bucket->index];
9433
9434
0
        if (name == atts[0]) {
9435
0
            int nsIndex = (int) (ptrdiff_t) atts[2];
9436
9437
0
            if ((nsIndex == NS_INDEX_EMPTY) ? (uri == NULL) :
9438
0
                (nsIndex == NS_INDEX_XML) ? (uri == ctxt->str_xml_ns) :
9439
0
                (uri == ctxt->nsTab[nsIndex * 2 + 1]))
9440
0
                return(bucket->index);
9441
0
        }
9442
9443
0
        hindex++;
9444
0
        bucket++;
9445
0
        if (hindex >= size) {
9446
0
            hindex = 0;
9447
0
            bucket = table;
9448
0
        }
9449
0
    }
9450
9451
0
    bucket->index = aindex;
9452
9453
0
    return(INT_MAX);
9454
0
}
9455
9456
static int
9457
xmlAttrHashInsertQName(xmlParserCtxtPtr ctxt, unsigned size,
9458
                       const xmlChar *name, const xmlChar *prefix,
9459
0
                       unsigned hashValue, int aindex) {
9460
0
    xmlAttrHashBucket *table = ctxt->attrHash;
9461
0
    xmlAttrHashBucket *bucket;
9462
0
    unsigned hindex;
9463
9464
0
    hindex = hashValue & (size - 1);
9465
0
    bucket = &table[hindex];
9466
9467
0
    while (bucket->index >= 0) {
9468
0
        const xmlChar **atts = &ctxt->atts[bucket->index];
9469
9470
0
        if ((name == atts[0]) && (prefix == atts[1]))
9471
0
            return(bucket->index);
9472
9473
0
        hindex++;
9474
0
        bucket++;
9475
0
        if (hindex >= size) {
9476
0
            hindex = 0;
9477
0
            bucket = table;
9478
0
        }
9479
0
    }
9480
9481
0
    bucket->index = aindex;
9482
9483
0
    return(INT_MAX);
9484
0
}
9485
/**
9486
 * xmlParseStartTag2:
9487
 * @ctxt:  an XML parser context
9488
 *
9489
 * Parse a start tag. Always consumes '<'.
9490
 *
9491
 * This routine is called when running SAX2 parsing
9492
 *
9493
 * [40] STag ::= '<' Name (S Attribute)* S? '>'
9494
 *
9495
 * [ WFC: Unique Att Spec ]
9496
 * No attribute name may appear more than once in the same start-tag or
9497
 * empty-element tag.
9498
 *
9499
 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
9500
 *
9501
 * [ WFC: Unique Att Spec ]
9502
 * No attribute name may appear more than once in the same start-tag or
9503
 * empty-element tag.
9504
 *
9505
 * With namespace:
9506
 *
9507
 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
9508
 *
9509
 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
9510
 *
9511
 * Returns the element name parsed
9512
 */
9513
9514
static const xmlChar *
9515
xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
9516
0
                  const xmlChar **URI, int *nbNsPtr) {
9517
0
    xmlHashedString hlocalname;
9518
0
    xmlHashedString hprefix;
9519
0
    xmlHashedString hattname;
9520
0
    xmlHashedString haprefix;
9521
0
    const xmlChar *localname;
9522
0
    const xmlChar *prefix;
9523
0
    const xmlChar *attname;
9524
0
    const xmlChar *aprefix;
9525
0
    const xmlChar *uri;
9526
0
    xmlChar *attvalue = NULL;
9527
0
    const xmlChar **atts = ctxt->atts;
9528
0
    unsigned attrHashSize = 0;
9529
0
    int maxatts = ctxt->maxatts;
9530
0
    int nratts, nbatts, nbdef, inputid;
9531
0
    int i, j, nbNs, nbTotalDef, attval, nsIndex, maxAtts;
9532
0
    int alloc = 0;
9533
0
    int numNsErr = 0;
9534
0
    int numDupErr = 0;
9535
9536
0
    if (RAW != '<') return(NULL);
9537
0
    NEXT1;
9538
9539
0
    inputid = ctxt->input->id;
9540
0
    nbatts = 0;
9541
0
    nratts = 0;
9542
0
    nbdef = 0;
9543
0
    nbNs = 0;
9544
0
    nbTotalDef = 0;
9545
0
    attval = 0;
9546
9547
0
    if (xmlParserNsStartElement(ctxt->nsdb) < 0) {
9548
0
        xmlErrMemory(ctxt, NULL);
9549
0
        return(NULL);
9550
0
    }
9551
9552
0
    hlocalname = xmlParseQNameHashed(ctxt, &hprefix);
9553
0
    if (hlocalname.name == NULL) {
9554
0
  xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
9555
0
           "StartTag: invalid element name\n");
9556
0
        return(NULL);
9557
0
    }
9558
0
    localname = hlocalname.name;
9559
0
    prefix = hprefix.name;
9560
9561
    /*
9562
     * Now parse the attributes, it ends up with the ending
9563
     *
9564
     * (S Attribute)* S?
9565
     */
9566
0
    SKIP_BLANKS;
9567
0
    GROW;
9568
9569
    /*
9570
     * The ctxt->atts array will be ultimately passed to the SAX callback
9571
     * containing five xmlChar pointers for each attribute:
9572
     *
9573
     * [0] attribute name
9574
     * [1] attribute prefix
9575
     * [2] namespace URI
9576
     * [3] attribute value
9577
     * [4] end of attribute value
9578
     *
9579
     * To save memory, we reuse this array temporarily and store integers
9580
     * in these pointer variables.
9581
     *
9582
     * [0] attribute name
9583
     * [1] attribute prefix
9584
     * [2] hash value of attribute prefix, and later namespace index
9585
     * [3] for non-allocated values: ptrdiff_t offset into input buffer
9586
     * [4] for non-allocated values: ptrdiff_t offset into input buffer
9587
     *
9588
     * The ctxt->attallocs array contains an additional unsigned int for
9589
     * each attribute, containing the hash value of the attribute name
9590
     * and the alloc flag in bit 31.
9591
     */
9592
9593
0
    while (((RAW != '>') &&
9594
0
     ((RAW != '/') || (NXT(1) != '>')) &&
9595
0
     (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) {
9596
0
  int len = -1;
9597
9598
0
  hattname = xmlParseAttribute2(ctxt, prefix, localname,
9599
0
                                          &haprefix, &attvalue, &len,
9600
0
                                          &alloc);
9601
0
        if (hattname.name == NULL) {
9602
0
      xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
9603
0
           "xmlParseStartTag: problem parsing attributes\n");
9604
0
      break;
9605
0
  }
9606
0
        if (attvalue == NULL)
9607
0
            goto next_attr;
9608
0
        attname = hattname.name;
9609
0
        aprefix = haprefix.name;
9610
0
  if (len < 0) len = xmlStrlen(attvalue);
9611
9612
0
        if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
9613
0
            xmlHashedString huri;
9614
0
            xmlURIPtr parsedUri;
9615
9616
0
            huri = xmlDictLookupHashed(ctxt->dict, attvalue, len);
9617
0
            uri = huri.name;
9618
0
            if (uri == NULL) {
9619
0
                xmlErrMemory(ctxt, NULL);
9620
0
                goto next_attr;
9621
0
            }
9622
0
            if (*uri != 0) {
9623
0
                parsedUri = xmlParseURI((const char *) uri);
9624
0
                if (parsedUri == NULL) {
9625
0
                    xmlNsErr(ctxt, XML_WAR_NS_URI,
9626
0
                             "xmlns: '%s' is not a valid URI\n",
9627
0
                                       uri, NULL, NULL);
9628
0
                } else {
9629
0
                    if (parsedUri->scheme == NULL) {
9630
0
                        xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
9631
0
                                  "xmlns: URI %s is not absolute\n",
9632
0
                                  uri, NULL, NULL);
9633
0
                    }
9634
0
                    xmlFreeURI(parsedUri);
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 cannot be the default namespace\n",
9640
0
                                 NULL, NULL, NULL);
9641
0
                    }
9642
0
                    goto next_attr;
9643
0
                }
9644
0
                if ((len == 29) &&
9645
0
                    (xmlStrEqual(uri,
9646
0
                             BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
9647
0
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9648
0
                         "reuse of the xmlns namespace name is forbidden\n",
9649
0
                             NULL, NULL, NULL);
9650
0
                    goto next_attr;
9651
0
                }
9652
0
            }
9653
9654
0
            if (xmlParserNsPush(ctxt, NULL, &huri, NULL, 0) > 0)
9655
0
                nbNs++;
9656
0
        } else if (aprefix == ctxt->str_xmlns) {
9657
0
            xmlHashedString huri;
9658
0
            xmlURIPtr parsedUri;
9659
9660
0
            huri = xmlDictLookupHashed(ctxt->dict, attvalue, len);
9661
0
            uri = huri.name;
9662
0
            if (uri == NULL) {
9663
0
                xmlErrMemory(ctxt, NULL);
9664
0
                goto next_attr;
9665
0
            }
9666
9667
0
            if (attname == ctxt->str_xml) {
9668
0
                if (uri != ctxt->str_xml_ns) {
9669
0
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9670
0
                             "xml namespace prefix mapped to wrong URI\n",
9671
0
                             NULL, NULL, NULL);
9672
0
                }
9673
                /*
9674
                 * Do not keep a namespace definition node
9675
                 */
9676
0
                goto next_attr;
9677
0
            }
9678
0
            if (uri == ctxt->str_xml_ns) {
9679
0
                if (attname != ctxt->str_xml) {
9680
0
                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9681
0
                             "xml namespace URI mapped to wrong prefix\n",
9682
0
                             NULL, NULL, NULL);
9683
0
                }
9684
0
                goto next_attr;
9685
0
            }
9686
0
            if (attname == ctxt->str_xmlns) {
9687
0
                xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9688
0
                         "redefinition of the xmlns prefix is forbidden\n",
9689
0
                         NULL, NULL, NULL);
9690
0
                goto next_attr;
9691
0
            }
9692
0
            if ((len == 29) &&
9693
0
                (xmlStrEqual(uri,
9694
0
                             BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
9695
0
                xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9696
0
                         "reuse of the xmlns namespace name is forbidden\n",
9697
0
                         NULL, NULL, NULL);
9698
0
                goto next_attr;
9699
0
            }
9700
0
            if ((uri == NULL) || (uri[0] == 0)) {
9701
0
                xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9702
0
                         "xmlns:%s: Empty XML namespace is not allowed\n",
9703
0
                              attname, NULL, NULL);
9704
0
                goto next_attr;
9705
0
            } else {
9706
0
                parsedUri = xmlParseURI((const char *) uri);
9707
0
                if (parsedUri == NULL) {
9708
0
                    xmlNsErr(ctxt, XML_WAR_NS_URI,
9709
0
                         "xmlns:%s: '%s' is not a valid URI\n",
9710
0
                                       attname, uri, NULL);
9711
0
                } else {
9712
0
                    if ((ctxt->pedantic) && (parsedUri->scheme == NULL)) {
9713
0
                        xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
9714
0
                                  "xmlns:%s: URI %s is not absolute\n",
9715
0
                                  attname, uri, NULL);
9716
0
                    }
9717
0
                    xmlFreeURI(parsedUri);
9718
0
                }
9719
0
            }
9720
9721
0
            if (xmlParserNsPush(ctxt, &hattname, &huri, NULL, 0) > 0)
9722
0
                nbNs++;
9723
0
        } else {
9724
            /*
9725
             * Populate attributes array, see above for repurposing
9726
             * of xmlChar pointers.
9727
             */
9728
0
            if ((atts == NULL) || (nbatts + 5 > maxatts)) {
9729
0
                if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
9730
0
                    goto next_attr;
9731
0
                }
9732
0
                maxatts = ctxt->maxatts;
9733
0
                atts = ctxt->atts;
9734
0
            }
9735
0
            ctxt->attallocs[nratts++] = (hattname.hashValue & 0x7FFFFFFF) |
9736
0
                                        ((unsigned) alloc << 31);
9737
0
            atts[nbatts++] = attname;
9738
0
            atts[nbatts++] = aprefix;
9739
0
            atts[nbatts++] = (const xmlChar *) (size_t) haprefix.hashValue;
9740
0
            if (alloc) {
9741
0
                atts[nbatts++] = attvalue;
9742
0
                attvalue += len;
9743
0
                atts[nbatts++] = attvalue;
9744
0
            } else {
9745
                /*
9746
                 * attvalue points into the input buffer which can be
9747
                 * reallocated. Store differences to input->base instead.
9748
                 * The pointers will be reconstructed later.
9749
                 */
9750
0
                atts[nbatts++] = (void *) (attvalue - BASE_PTR);
9751
0
                attvalue += len;
9752
0
                atts[nbatts++] = (void *) (attvalue - BASE_PTR);
9753
0
            }
9754
            /*
9755
             * tag if some deallocation is needed
9756
             */
9757
0
            if (alloc != 0) attval = 1;
9758
0
            attvalue = NULL; /* moved into atts */
9759
0
        }
9760
9761
0
next_attr:
9762
0
        if ((attvalue != NULL) && (alloc != 0)) {
9763
0
            xmlFree(attvalue);
9764
0
            attvalue = NULL;
9765
0
        }
9766
9767
0
  GROW
9768
0
        if (ctxt->instate == XML_PARSER_EOF)
9769
0
            break;
9770
0
  if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
9771
0
      break;
9772
0
  if (SKIP_BLANKS == 0) {
9773
0
      xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
9774
0
         "attributes construct error\n");
9775
0
      break;
9776
0
  }
9777
0
        GROW;
9778
0
    }
9779
9780
0
    if (ctxt->input->id != inputid) {
9781
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
9782
0
                    "Unexpected change of input\n");
9783
0
        localname = NULL;
9784
0
        goto done;
9785
0
    }
9786
9787
    /*
9788
     * Namespaces from default attributes
9789
     */
9790
0
    if (ctxt->attsDefault != NULL) {
9791
0
        xmlDefAttrsPtr defaults;
9792
9793
0
  defaults = xmlHashLookup2(ctxt->attsDefault, localname, prefix);
9794
0
  if (defaults != NULL) {
9795
0
      for (i = 0; i < defaults->nbAttrs; i++) {
9796
0
                xmlDefAttr *attr = &defaults->attrs[i];
9797
9798
0
          attname = attr->name.name;
9799
0
    aprefix = attr->prefix.name;
9800
9801
0
    if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
9802
0
                    xmlParserEntityCheck(ctxt, attr->expandedSize);
9803
9804
0
                    if (xmlParserNsPush(ctxt, NULL, &attr->value, NULL, 1) > 0)
9805
0
                        nbNs++;
9806
0
    } else if (aprefix == ctxt->str_xmlns) {
9807
0
                    xmlParserEntityCheck(ctxt, attr->expandedSize);
9808
9809
0
                    if (xmlParserNsPush(ctxt, &attr->name, &attr->value,
9810
0
                                      NULL, 1) > 0)
9811
0
                        nbNs++;
9812
0
    } else {
9813
0
                    nbTotalDef += 1;
9814
0
                }
9815
0
      }
9816
0
  }
9817
0
    }
9818
9819
    /*
9820
     * Resolve attribute namespaces
9821
     */
9822
0
    for (i = 0; i < nbatts; i += 5) {
9823
0
        attname = atts[i];
9824
0
        aprefix = atts[i+1];
9825
9826
        /*
9827
  * The default namespace does not apply to attribute names.
9828
  */
9829
0
  if (aprefix == NULL) {
9830
0
            nsIndex = NS_INDEX_EMPTY;
9831
0
        } else if (aprefix == ctxt->str_xml) {
9832
0
            nsIndex = NS_INDEX_XML;
9833
0
        } else {
9834
0
            haprefix.name = aprefix;
9835
0
            haprefix.hashValue = (size_t) atts[i+2];
9836
0
            nsIndex = xmlParserNsLookup(ctxt, &haprefix, NULL);
9837
0
      if (nsIndex == INT_MAX) {
9838
0
                xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
9839
0
        "Namespace prefix %s for %s on %s is not defined\n",
9840
0
        aprefix, attname, localname);
9841
0
                nsIndex = NS_INDEX_EMPTY;
9842
0
            }
9843
0
        }
9844
9845
0
        atts[i+2] = (const xmlChar *) (ptrdiff_t) nsIndex;
9846
0
    }
9847
9848
    /*
9849
     * Maximum number of attributes including default attributes.
9850
     */
9851
0
    maxAtts = nratts + nbTotalDef;
9852
9853
    /*
9854
     * Verify that attribute names are unique.
9855
     */
9856
0
    if (maxAtts > 1) {
9857
0
        attrHashSize = 4;
9858
0
        while (attrHashSize / 2 < (unsigned) maxAtts)
9859
0
            attrHashSize *= 2;
9860
9861
0
        if (attrHashSize > ctxt->attrHashMax) {
9862
0
            xmlAttrHashBucket *tmp;
9863
9864
0
            tmp = xmlRealloc(ctxt->attrHash, attrHashSize * sizeof(tmp[0]));
9865
0
            if (tmp == NULL) {
9866
0
                xmlErrMemory(ctxt, NULL);
9867
0
                goto done;
9868
0
            }
9869
9870
0
            ctxt->attrHash = tmp;
9871
0
            ctxt->attrHashMax = attrHashSize;
9872
0
        }
9873
9874
0
        memset(ctxt->attrHash, -1, attrHashSize * sizeof(ctxt->attrHash[0]));
9875
9876
0
        for (i = 0, j = 0; j < nratts; i += 5, j++) {
9877
0
            const xmlChar *nsuri;
9878
0
            unsigned hashValue, nameHashValue, uriHashValue;
9879
0
            int res;
9880
9881
0
            attname = atts[i];
9882
0
            aprefix = atts[i+1];
9883
0
            nsIndex = (ptrdiff_t) atts[i+2];
9884
            /* Hash values always have bit 31 set, see dict.c */
9885
0
            nameHashValue = ctxt->attallocs[j] | 0x80000000;
9886
9887
0
            if (nsIndex == NS_INDEX_EMPTY) {
9888
0
                nsuri = NULL;
9889
0
                uriHashValue = URI_HASH_EMPTY;
9890
0
            } else if (nsIndex == NS_INDEX_XML) {
9891
0
                nsuri = ctxt->str_xml_ns;
9892
0
                uriHashValue = URI_HASH_XML;
9893
0
            } else {
9894
0
                nsuri = ctxt->nsTab[nsIndex * 2 + 1];
9895
0
                uriHashValue = ctxt->nsdb->extra[nsIndex].uriHashValue;
9896
0
            }
9897
9898
0
            hashValue = xmlDictCombineHash(nameHashValue, uriHashValue);
9899
0
            res = xmlAttrHashInsert(ctxt, attrHashSize, attname, nsuri,
9900
0
                                    hashValue, i);
9901
0
            if (res < 0)
9902
0
                continue;
9903
9904
            /*
9905
             * [ WFC: Unique Att Spec ]
9906
             * No attribute name may appear more than once in the same
9907
             * start-tag or empty-element tag.
9908
             * As extended by the Namespace in XML REC.
9909
             */
9910
0
            if (res < INT_MAX) {
9911
0
                if (aprefix == atts[res+1]) {
9912
0
                    xmlErrAttributeDup(ctxt, aprefix, attname);
9913
0
                    numDupErr += 1;
9914
0
                } else {
9915
0
                    xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED,
9916
0
                             "Namespaced Attribute %s in '%s' redefined\n",
9917
0
                             attname, nsuri, NULL);
9918
0
                    numNsErr += 1;
9919
0
                }
9920
0
            }
9921
0
        }
9922
0
    }
9923
9924
    /*
9925
     * Default attributes
9926
     */
9927
0
    if (ctxt->attsDefault != NULL) {
9928
0
        xmlDefAttrsPtr defaults;
9929
9930
0
  defaults = xmlHashLookup2(ctxt->attsDefault, localname, prefix);
9931
0
  if (defaults != NULL) {
9932
0
      for (i = 0; i < defaults->nbAttrs; i++) {
9933
0
                xmlDefAttr *attr = &defaults->attrs[i];
9934
0
                const xmlChar *nsuri;
9935
0
                unsigned hashValue, uriHashValue;
9936
0
                int res;
9937
9938
0
          attname = attr->name.name;
9939
0
    aprefix = attr->prefix.name;
9940
9941
0
    if ((attname == ctxt->str_xmlns) && (aprefix == NULL))
9942
0
                    continue;
9943
0
    if (aprefix == ctxt->str_xmlns)
9944
0
                    continue;
9945
9946
0
                if (aprefix == NULL) {
9947
0
                    nsIndex = NS_INDEX_EMPTY;
9948
0
                    nsuri = NULL;
9949
0
                    uriHashValue = URI_HASH_EMPTY;
9950
0
                } if (aprefix == ctxt->str_xml) {
9951
0
                    nsIndex = NS_INDEX_XML;
9952
0
                    nsuri = ctxt->str_xml_ns;
9953
0
                    uriHashValue = URI_HASH_XML;
9954
0
                } else if (aprefix != NULL) {
9955
0
                    nsIndex = xmlParserNsLookup(ctxt, &attr->prefix, NULL);
9956
0
                    if (nsIndex == INT_MAX) {
9957
0
                        xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
9958
0
                                 "Namespace prefix %s for %s on %s is not "
9959
0
                                 "defined\n",
9960
0
                                 aprefix, attname, localname);
9961
0
                        nsIndex = NS_INDEX_EMPTY;
9962
0
                        nsuri = NULL;
9963
0
                        uriHashValue = URI_HASH_EMPTY;
9964
0
                    } else {
9965
0
                        nsuri = ctxt->nsTab[nsIndex * 2 + 1];
9966
0
                        uriHashValue = ctxt->nsdb->extra[nsIndex].uriHashValue;
9967
0
                    }
9968
0
                }
9969
9970
                /*
9971
                 * Check whether the attribute exists
9972
                 */
9973
0
                if (maxAtts > 1) {
9974
0
                    hashValue = xmlDictCombineHash(attr->name.hashValue,
9975
0
                                                   uriHashValue);
9976
0
                    res = xmlAttrHashInsert(ctxt, attrHashSize, attname, nsuri,
9977
0
                                            hashValue, nbatts);
9978
0
                    if (res < 0)
9979
0
                        continue;
9980
0
                    if (res < INT_MAX) {
9981
0
                        if (aprefix == atts[res+1])
9982
0
                            continue;
9983
0
                        xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED,
9984
0
                                 "Namespaced Attribute %s in '%s' redefined\n",
9985
0
                                 attname, nsuri, NULL);
9986
0
                    }
9987
0
                }
9988
9989
0
                xmlParserEntityCheck(ctxt, attr->expandedSize);
9990
9991
0
                if ((atts == NULL) || (nbatts + 5 > maxatts)) {
9992
0
                    if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
9993
0
                        localname = NULL;
9994
0
                        goto done;
9995
0
                    }
9996
0
                    maxatts = ctxt->maxatts;
9997
0
                    atts = ctxt->atts;
9998
0
                }
9999
10000
0
                atts[nbatts++] = attname;
10001
0
                atts[nbatts++] = aprefix;
10002
0
                atts[nbatts++] = (const xmlChar *) (ptrdiff_t) nsIndex;
10003
0
                atts[nbatts++] = attr->value.name;
10004
0
                atts[nbatts++] = attr->valueEnd;
10005
0
                if ((ctxt->standalone == 1) && (attr->external != 0)) {
10006
0
                    xmlValidityError(ctxt, XML_DTD_STANDALONE_DEFAULTED,
10007
0
                            "standalone: attribute %s on %s defaulted "
10008
0
                            "from external subset\n",
10009
0
                            attname, localname);
10010
0
                }
10011
0
                nbdef++;
10012
0
      }
10013
0
  }
10014
0
    }
10015
10016
    /*
10017
     * Using a single hash table for nsUri/localName pairs cannot
10018
     * detect duplicate QNames reliably. The following example will
10019
     * only result in two namespace errors.
10020
     *
10021
     * <doc xmlns:a="a" xmlns:b="a">
10022
     *   <elem a:a="" b:a="" b:a=""/>
10023
     * </doc>
10024
     *
10025
     * If we saw more than one namespace error but no duplicate QNames
10026
     * were found, we have to scan for duplicate QNames.
10027
     */
10028
0
    if ((numDupErr == 0) && (numNsErr > 1)) {
10029
0
        memset(ctxt->attrHash, -1,
10030
0
               attrHashSize * sizeof(ctxt->attrHash[0]));
10031
10032
0
        for (i = 0, j = 0; j < nratts; i += 5, j++) {
10033
0
            unsigned hashValue, nameHashValue, prefixHashValue;
10034
0
            int res;
10035
10036
0
            aprefix = atts[i+1];
10037
0
            if (aprefix == NULL)
10038
0
                continue;
10039
10040
0
            attname = atts[i];
10041
            /* Hash values always have bit 31 set, see dict.c */
10042
0
            nameHashValue = ctxt->attallocs[j] | 0x80000000;
10043
0
            prefixHashValue = xmlDictComputeHash(ctxt->dict, aprefix);
10044
10045
0
            hashValue = xmlDictCombineHash(nameHashValue, prefixHashValue);
10046
0
            res = xmlAttrHashInsertQName(ctxt, attrHashSize, attname,
10047
0
                                         aprefix, hashValue, i);
10048
0
            if (res < INT_MAX)
10049
0
                xmlErrAttributeDup(ctxt, aprefix, attname);
10050
0
        }
10051
0
    }
10052
10053
    /*
10054
     * Reconstruct attribute pointers
10055
     */
10056
0
    for (i = 0, j = 0; i < nbatts; i += 5, j++) {
10057
        /* namespace URI */
10058
0
        nsIndex = (ptrdiff_t) atts[i+2];
10059
0
        if (nsIndex == INT_MAX)
10060
0
            atts[i+2] = NULL;
10061
0
        else if (nsIndex == INT_MAX - 1)
10062
0
            atts[i+2] = ctxt->str_xml_ns;
10063
0
        else
10064
0
            atts[i+2] = ctxt->nsTab[nsIndex * 2 + 1];
10065
10066
0
        if ((j < nratts) && (ctxt->attallocs[j] & 0x80000000) == 0) {
10067
0
            atts[i+3] = BASE_PTR + (ptrdiff_t) atts[i+3];  /* value */
10068
0
            atts[i+4] = BASE_PTR + (ptrdiff_t) atts[i+4];  /* valuend */
10069
0
        }
10070
0
    }
10071
10072
0
    uri = xmlParserNsLookupUri(ctxt, &hprefix);
10073
0
    if ((prefix != NULL) && (uri == NULL)) {
10074
0
  xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
10075
0
           "Namespace prefix %s on %s is not defined\n",
10076
0
     prefix, localname, NULL);
10077
0
    }
10078
0
    *pref = prefix;
10079
0
    *URI = uri;
10080
10081
    /*
10082
     * SAX callback
10083
     */
10084
0
    if ((ctxt->sax != NULL) && (ctxt->sax->startElementNs != NULL) &&
10085
0
  (!ctxt->disableSAX)) {
10086
0
  if (nbNs > 0)
10087
0
      ctxt->sax->startElementNs(ctxt->userData, localname, prefix, uri,
10088
0
                          nbNs, ctxt->nsTab + 2 * (ctxt->nsNr - nbNs),
10089
0
        nbatts / 5, nbdef, atts);
10090
0
  else
10091
0
      ctxt->sax->startElementNs(ctxt->userData, localname, prefix, uri,
10092
0
                          0, NULL, nbatts / 5, nbdef, atts);
10093
0
    }
10094
10095
0
done:
10096
    /*
10097
     * Free allocated attribute values
10098
     */
10099
0
    if (attval != 0) {
10100
0
  for (i = 0, j = 0; j < nratts; i += 5, j++)
10101
0
      if (ctxt->attallocs[j] & 0x80000000)
10102
0
          xmlFree((xmlChar *) atts[i+3]);
10103
0
    }
10104
10105
0
    *nbNsPtr = nbNs;
10106
0
    return(localname);
10107
0
}
10108
10109
/**
10110
 * xmlParseEndTag2:
10111
 * @ctxt:  an XML parser context
10112
 * @line:  line of the start tag
10113
 * @nsNr:  number of namespaces on the start tag
10114
 *
10115
 * Parse an end tag. Always consumes '</'.
10116
 *
10117
 * [42] ETag ::= '</' Name S? '>'
10118
 *
10119
 * With namespace
10120
 *
10121
 * [NS 9] ETag ::= '</' QName S? '>'
10122
 */
10123
10124
static void
10125
0
xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlStartTag *tag) {
10126
0
    const xmlChar *name;
10127
10128
0
    GROW;
10129
0
    if ((RAW != '<') || (NXT(1) != '/')) {
10130
0
  xmlFatalErr(ctxt, XML_ERR_LTSLASH_REQUIRED, NULL);
10131
0
  return;
10132
0
    }
10133
0
    SKIP(2);
10134
10135
0
    if (tag->prefix == NULL)
10136
0
        name = xmlParseNameAndCompare(ctxt, ctxt->name);
10137
0
    else
10138
0
        name = xmlParseQNameAndCompare(ctxt, ctxt->name, tag->prefix);
10139
10140
    /*
10141
     * We should definitely be at the ending "S? '>'" part
10142
     */
10143
0
    GROW;
10144
0
    if (ctxt->instate == XML_PARSER_EOF)
10145
0
        return;
10146
0
    SKIP_BLANKS;
10147
0
    if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
10148
0
  xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
10149
0
    } else
10150
0
  NEXT1;
10151
10152
    /*
10153
     * [ WFC: Element Type Match ]
10154
     * The Name in an element's end-tag must match the element type in the
10155
     * start-tag.
10156
     *
10157
     */
10158
0
    if (name != (xmlChar*)1) {
10159
0
        if (name == NULL) name = BAD_CAST "unparsable";
10160
0
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
10161
0
         "Opening and ending tag mismatch: %s line %d and %s\n",
10162
0
                    ctxt->name, tag->line, name);
10163
0
    }
10164
10165
    /*
10166
     * SAX: End of Tag
10167
     */
10168
0
    if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
10169
0
  (!ctxt->disableSAX))
10170
0
  ctxt->sax->endElementNs(ctxt->userData, ctxt->name, tag->prefix,
10171
0
                                tag->URI);
10172
10173
0
    spacePop(ctxt);
10174
0
    if (tag->nsNr != 0)
10175
0
  xmlParserNsPop(ctxt, tag->nsNr);
10176
0
}
10177
10178
/**
10179
 * xmlParseCDSect:
10180
 * @ctxt:  an XML parser context
10181
 *
10182
 * DEPRECATED: Internal function, don't use.
10183
 *
10184
 * Parse escaped pure raw content. Always consumes '<!['.
10185
 *
10186
 * [18] CDSect ::= CDStart CData CDEnd
10187
 *
10188
 * [19] CDStart ::= '<![CDATA['
10189
 *
10190
 * [20] Data ::= (Char* - (Char* ']]>' Char*))
10191
 *
10192
 * [21] CDEnd ::= ']]>'
10193
 */
10194
void
10195
0
xmlParseCDSect(xmlParserCtxtPtr ctxt) {
10196
0
    xmlChar *buf = NULL;
10197
0
    int len = 0;
10198
0
    int size = XML_PARSER_BUFFER_SIZE;
10199
0
    int r, rl;
10200
0
    int s, sl;
10201
0
    int cur, l;
10202
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
10203
0
                    XML_MAX_HUGE_LENGTH :
10204
0
                    XML_MAX_TEXT_LENGTH;
10205
10206
0
    if ((CUR != '<') || (NXT(1) != '!') || (NXT(2) != '['))
10207
0
        return;
10208
0
    SKIP(3);
10209
10210
0
    if (!CMP6(CUR_PTR, 'C', 'D', 'A', 'T', 'A', '['))
10211
0
        return;
10212
0
    SKIP(6);
10213
10214
0
    ctxt->instate = XML_PARSER_CDATA_SECTION;
10215
0
    r = CUR_CHAR(rl);
10216
0
    if (!IS_CHAR(r)) {
10217
0
  xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
10218
0
        goto out;
10219
0
    }
10220
0
    NEXTL(rl);
10221
0
    s = CUR_CHAR(sl);
10222
0
    if (!IS_CHAR(s)) {
10223
0
  xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
10224
0
        goto out;
10225
0
    }
10226
0
    NEXTL(sl);
10227
0
    cur = CUR_CHAR(l);
10228
0
    buf = (xmlChar *) xmlMallocAtomic(size);
10229
0
    if (buf == NULL) {
10230
0
  xmlErrMemory(ctxt, NULL);
10231
0
        goto out;
10232
0
    }
10233
0
    while (IS_CHAR(cur) &&
10234
0
           ((r != ']') || (s != ']') || (cur != '>'))) {
10235
0
  if (len + 5 >= size) {
10236
0
      xmlChar *tmp;
10237
10238
0
      tmp = (xmlChar *) xmlRealloc(buf, size * 2);
10239
0
      if (tmp == NULL) {
10240
0
    xmlErrMemory(ctxt, NULL);
10241
0
                goto out;
10242
0
      }
10243
0
      buf = tmp;
10244
0
      size *= 2;
10245
0
  }
10246
0
  COPY_BUF(buf, len, r);
10247
0
        if (len > maxLength) {
10248
0
            xmlFatalErrMsg(ctxt, XML_ERR_CDATA_NOT_FINISHED,
10249
0
                           "CData section too big found\n");
10250
0
            goto out;
10251
0
        }
10252
0
  r = s;
10253
0
  rl = sl;
10254
0
  s = cur;
10255
0
  sl = l;
10256
0
  NEXTL(l);
10257
0
  cur = CUR_CHAR(l);
10258
0
    }
10259
0
    buf[len] = 0;
10260
0
    if (ctxt->instate == XML_PARSER_EOF) {
10261
0
        xmlFree(buf);
10262
0
        return;
10263
0
    }
10264
0
    if (cur != '>') {
10265
0
  xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED,
10266
0
                       "CData section not finished\n%.50s\n", buf);
10267
0
        goto out;
10268
0
    }
10269
0
    NEXTL(l);
10270
10271
    /*
10272
     * OK the buffer is to be consumed as cdata.
10273
     */
10274
0
    if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
10275
0
  if (ctxt->sax->cdataBlock != NULL)
10276
0
      ctxt->sax->cdataBlock(ctxt->userData, buf, len);
10277
0
  else if (ctxt->sax->characters != NULL)
10278
0
      ctxt->sax->characters(ctxt->userData, buf, len);
10279
0
    }
10280
10281
0
out:
10282
0
    if (ctxt->instate != XML_PARSER_EOF)
10283
0
        ctxt->instate = XML_PARSER_CONTENT;
10284
0
    xmlFree(buf);
10285
0
}
10286
10287
/**
10288
 * xmlParseContentInternal:
10289
 * @ctxt:  an XML parser context
10290
 *
10291
 * Parse a content sequence. Stops at EOF or '</'. Leaves checking of
10292
 * unexpected EOF to the caller.
10293
 */
10294
10295
static void
10296
0
xmlParseContentInternal(xmlParserCtxtPtr ctxt) {
10297
0
    int nameNr = ctxt->nameNr;
10298
10299
0
    GROW;
10300
0
    while ((ctxt->input->cur < ctxt->input->end) &&
10301
0
     (ctxt->instate != XML_PARSER_EOF)) {
10302
0
  const xmlChar *cur = ctxt->input->cur;
10303
10304
  /*
10305
   * First case : a Processing Instruction.
10306
   */
10307
0
  if ((*cur == '<') && (cur[1] == '?')) {
10308
0
      xmlParsePI(ctxt);
10309
0
  }
10310
10311
  /*
10312
   * Second case : a CDSection
10313
   */
10314
  /* 2.6.0 test was *cur not RAW */
10315
0
  else if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
10316
0
      xmlParseCDSect(ctxt);
10317
0
  }
10318
10319
  /*
10320
   * Third case :  a comment
10321
   */
10322
0
  else if ((*cur == '<') && (NXT(1) == '!') &&
10323
0
     (NXT(2) == '-') && (NXT(3) == '-')) {
10324
0
      xmlParseComment(ctxt);
10325
0
      ctxt->instate = XML_PARSER_CONTENT;
10326
0
  }
10327
10328
  /*
10329
   * Fourth case :  a sub-element.
10330
   */
10331
0
  else if (*cur == '<') {
10332
0
            if (NXT(1) == '/') {
10333
0
                if (ctxt->nameNr <= nameNr)
10334
0
                    break;
10335
0
          xmlParseElementEnd(ctxt);
10336
0
            } else {
10337
0
          xmlParseElementStart(ctxt);
10338
0
            }
10339
0
  }
10340
10341
  /*
10342
   * Fifth case : a reference. If if has not been resolved,
10343
   *    parsing returns it's Name, create the node
10344
   */
10345
10346
0
  else if (*cur == '&') {
10347
0
      xmlParseReference(ctxt);
10348
0
  }
10349
10350
  /*
10351
   * Last case, text. Note that References are handled directly.
10352
   */
10353
0
  else {
10354
0
      xmlParseCharDataInternal(ctxt, 0);
10355
0
  }
10356
10357
0
  SHRINK;
10358
0
  GROW;
10359
0
    }
10360
0
}
10361
10362
/**
10363
 * xmlParseContent:
10364
 * @ctxt:  an XML parser context
10365
 *
10366
 * Parse a content sequence. Stops at EOF or '</'.
10367
 *
10368
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
10369
 */
10370
10371
void
10372
0
xmlParseContent(xmlParserCtxtPtr ctxt) {
10373
0
    int nameNr = ctxt->nameNr;
10374
10375
0
    xmlParseContentInternal(ctxt);
10376
10377
0
    if ((ctxt->instate != XML_PARSER_EOF) &&
10378
0
        (ctxt->errNo == XML_ERR_OK) &&
10379
0
        (ctxt->nameNr > nameNr)) {
10380
0
        const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
10381
0
        int line = ctxt->pushTab[ctxt->nameNr - 1].line;
10382
0
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
10383
0
                "Premature end of data in tag %s line %d\n",
10384
0
    name, line, NULL);
10385
0
    }
10386
0
}
10387
10388
/**
10389
 * xmlParseElement:
10390
 * @ctxt:  an XML parser context
10391
 *
10392
 * DEPRECATED: Internal function, don't use.
10393
 *
10394
 * parse an XML element
10395
 *
10396
 * [39] element ::= EmptyElemTag | STag content ETag
10397
 *
10398
 * [ WFC: Element Type Match ]
10399
 * The Name in an element's end-tag must match the element type in the
10400
 * start-tag.
10401
 *
10402
 */
10403
10404
void
10405
0
xmlParseElement(xmlParserCtxtPtr ctxt) {
10406
0
    if (xmlParseElementStart(ctxt) != 0)
10407
0
        return;
10408
10409
0
    xmlParseContentInternal(ctxt);
10410
0
    if (ctxt->instate == XML_PARSER_EOF)
10411
0
  return;
10412
10413
0
    if (ctxt->input->cur >= ctxt->input->end) {
10414
0
        if (ctxt->errNo == XML_ERR_OK) {
10415
0
            const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
10416
0
            int line = ctxt->pushTab[ctxt->nameNr - 1].line;
10417
0
            xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
10418
0
                    "Premature end of data in tag %s line %d\n",
10419
0
                    name, line, NULL);
10420
0
        }
10421
0
        return;
10422
0
    }
10423
10424
0
    xmlParseElementEnd(ctxt);
10425
0
}
10426
10427
/**
10428
 * xmlParseElementStart:
10429
 * @ctxt:  an XML parser context
10430
 *
10431
 * Parse the start of an XML element. Returns -1 in case of error, 0 if an
10432
 * opening tag was parsed, 1 if an empty element was parsed.
10433
 *
10434
 * Always consumes '<'.
10435
 */
10436
static int
10437
0
xmlParseElementStart(xmlParserCtxtPtr ctxt) {
10438
0
    const xmlChar *name;
10439
0
    const xmlChar *prefix = NULL;
10440
0
    const xmlChar *URI = NULL;
10441
0
    xmlParserNodeInfo node_info;
10442
0
    int line;
10443
0
    xmlNodePtr cur;
10444
0
    int nbNs = 0;
10445
10446
0
    if (((unsigned int) ctxt->nameNr > xmlParserMaxDepth) &&
10447
0
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
10448
0
  xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
10449
0
     "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
10450
0
        xmlParserMaxDepth);
10451
0
  xmlHaltParser(ctxt);
10452
0
  return(-1);
10453
0
    }
10454
10455
    /* Capture start position */
10456
0
    if (ctxt->record_info) {
10457
0
        node_info.begin_pos = ctxt->input->consumed +
10458
0
                          (CUR_PTR - ctxt->input->base);
10459
0
  node_info.begin_line = ctxt->input->line;
10460
0
    }
10461
10462
0
    if (ctxt->spaceNr == 0)
10463
0
  spacePush(ctxt, -1);
10464
0
    else if (*ctxt->space == -2)
10465
0
  spacePush(ctxt, -1);
10466
0
    else
10467
0
  spacePush(ctxt, *ctxt->space);
10468
10469
0
    line = ctxt->input->line;
10470
0
#ifdef LIBXML_SAX1_ENABLED
10471
0
    if (ctxt->sax2)
10472
0
#endif /* LIBXML_SAX1_ENABLED */
10473
0
        name = xmlParseStartTag2(ctxt, &prefix, &URI, &nbNs);
10474
0
#ifdef LIBXML_SAX1_ENABLED
10475
0
    else
10476
0
  name = xmlParseStartTag(ctxt);
10477
0
#endif /* LIBXML_SAX1_ENABLED */
10478
0
    if (ctxt->instate == XML_PARSER_EOF)
10479
0
  return(-1);
10480
0
    if (name == NULL) {
10481
0
  spacePop(ctxt);
10482
0
        return(-1);
10483
0
    }
10484
0
    nameNsPush(ctxt, name, prefix, URI, line, nbNs);
10485
0
    cur = ctxt->node;
10486
10487
0
#ifdef LIBXML_VALID_ENABLED
10488
    /*
10489
     * [ VC: Root Element Type ]
10490
     * The Name in the document type declaration must match the element
10491
     * type of the root element.
10492
     */
10493
0
    if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
10494
0
        ctxt->node && (ctxt->node == ctxt->myDoc->children))
10495
0
        ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
10496
0
#endif /* LIBXML_VALID_ENABLED */
10497
10498
    /*
10499
     * Check for an Empty Element.
10500
     */
10501
0
    if ((RAW == '/') && (NXT(1) == '>')) {
10502
0
        SKIP(2);
10503
0
  if (ctxt->sax2) {
10504
0
      if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
10505
0
    (!ctxt->disableSAX))
10506
0
    ctxt->sax->endElementNs(ctxt->userData, name, prefix, URI);
10507
0
#ifdef LIBXML_SAX1_ENABLED
10508
0
  } else {
10509
0
      if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
10510
0
    (!ctxt->disableSAX))
10511
0
    ctxt->sax->endElement(ctxt->userData, name);
10512
0
#endif /* LIBXML_SAX1_ENABLED */
10513
0
  }
10514
0
  namePop(ctxt);
10515
0
  spacePop(ctxt);
10516
0
  if (nbNs > 0)
10517
0
      xmlParserNsPop(ctxt, nbNs);
10518
0
  if (cur != NULL && ctxt->record_info) {
10519
0
            node_info.node = cur;
10520
0
            node_info.end_pos = ctxt->input->consumed +
10521
0
                                (CUR_PTR - ctxt->input->base);
10522
0
            node_info.end_line = ctxt->input->line;
10523
0
            xmlParserAddNodeInfo(ctxt, &node_info);
10524
0
  }
10525
0
  return(1);
10526
0
    }
10527
0
    if (RAW == '>') {
10528
0
        NEXT1;
10529
0
        if (cur != NULL && ctxt->record_info) {
10530
0
            node_info.node = cur;
10531
0
            node_info.end_pos = 0;
10532
0
            node_info.end_line = 0;
10533
0
            xmlParserAddNodeInfo(ctxt, &node_info);
10534
0
        }
10535
0
    } else {
10536
0
        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_GT_REQUIRED,
10537
0
         "Couldn't find end of Start Tag %s line %d\n",
10538
0
                    name, line, NULL);
10539
10540
  /*
10541
   * end of parsing of this node.
10542
   */
10543
0
  nodePop(ctxt);
10544
0
  namePop(ctxt);
10545
0
  spacePop(ctxt);
10546
0
  if (nbNs > 0)
10547
0
      xmlParserNsPop(ctxt, nbNs);
10548
0
  return(-1);
10549
0
    }
10550
10551
0
    return(0);
10552
0
}
10553
10554
/**
10555
 * xmlParseElementEnd:
10556
 * @ctxt:  an XML parser context
10557
 *
10558
 * Parse the end of an XML element. Always consumes '</'.
10559
 */
10560
static void
10561
0
xmlParseElementEnd(xmlParserCtxtPtr ctxt) {
10562
0
    xmlNodePtr cur = ctxt->node;
10563
10564
0
    if (ctxt->nameNr <= 0) {
10565
0
        if ((RAW == '<') && (NXT(1) == '/'))
10566
0
            SKIP(2);
10567
0
        return;
10568
0
    }
10569
10570
    /*
10571
     * parse the end of tag: '</' should be here.
10572
     */
10573
0
    if (ctxt->sax2) {
10574
0
  xmlParseEndTag2(ctxt, &ctxt->pushTab[ctxt->nameNr - 1]);
10575
0
  namePop(ctxt);
10576
0
    }
10577
0
#ifdef LIBXML_SAX1_ENABLED
10578
0
    else
10579
0
  xmlParseEndTag1(ctxt, 0);
10580
0
#endif /* LIBXML_SAX1_ENABLED */
10581
10582
    /*
10583
     * Capture end position
10584
     */
10585
0
    if (cur != NULL && ctxt->record_info) {
10586
0
        xmlParserNodeInfoPtr node_info;
10587
10588
0
        node_info = (xmlParserNodeInfoPtr) xmlParserFindNodeInfo(ctxt, cur);
10589
0
        if (node_info != NULL) {
10590
0
            node_info->end_pos = ctxt->input->consumed +
10591
0
                                 (CUR_PTR - ctxt->input->base);
10592
0
            node_info->end_line = ctxt->input->line;
10593
0
        }
10594
0
    }
10595
0
}
10596
10597
/**
10598
 * xmlParseVersionNum:
10599
 * @ctxt:  an XML parser context
10600
 *
10601
 * DEPRECATED: Internal function, don't use.
10602
 *
10603
 * parse the XML version value.
10604
 *
10605
 * [26] VersionNum ::= '1.' [0-9]+
10606
 *
10607
 * In practice allow [0-9].[0-9]+ at that level
10608
 *
10609
 * Returns the string giving the XML version number, or NULL
10610
 */
10611
xmlChar *
10612
0
xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
10613
0
    xmlChar *buf = NULL;
10614
0
    int len = 0;
10615
0
    int size = 10;
10616
0
    xmlChar cur;
10617
10618
0
    buf = (xmlChar *) xmlMallocAtomic(size);
10619
0
    if (buf == NULL) {
10620
0
  xmlErrMemory(ctxt, NULL);
10621
0
  return(NULL);
10622
0
    }
10623
0
    cur = CUR;
10624
0
    if (!((cur >= '0') && (cur <= '9'))) {
10625
0
  xmlFree(buf);
10626
0
  return(NULL);
10627
0
    }
10628
0
    buf[len++] = cur;
10629
0
    NEXT;
10630
0
    cur=CUR;
10631
0
    if (cur != '.') {
10632
0
  xmlFree(buf);
10633
0
  return(NULL);
10634
0
    }
10635
0
    buf[len++] = cur;
10636
0
    NEXT;
10637
0
    cur=CUR;
10638
0
    while ((cur >= '0') && (cur <= '9')) {
10639
0
  if (len + 1 >= size) {
10640
0
      xmlChar *tmp;
10641
10642
0
      size *= 2;
10643
0
      tmp = (xmlChar *) xmlRealloc(buf, size);
10644
0
      if (tmp == NULL) {
10645
0
          xmlFree(buf);
10646
0
    xmlErrMemory(ctxt, NULL);
10647
0
    return(NULL);
10648
0
      }
10649
0
      buf = tmp;
10650
0
  }
10651
0
  buf[len++] = cur;
10652
0
  NEXT;
10653
0
  cur=CUR;
10654
0
    }
10655
0
    buf[len] = 0;
10656
0
    return(buf);
10657
0
}
10658
10659
/**
10660
 * xmlParseVersionInfo:
10661
 * @ctxt:  an XML parser context
10662
 *
10663
 * DEPRECATED: Internal function, don't use.
10664
 *
10665
 * parse the XML version.
10666
 *
10667
 * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
10668
 *
10669
 * [25] Eq ::= S? '=' S?
10670
 *
10671
 * Returns the version string, e.g. "1.0"
10672
 */
10673
10674
xmlChar *
10675
0
xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
10676
0
    xmlChar *version = NULL;
10677
10678
0
    if (CMP7(CUR_PTR, 'v', 'e', 'r', 's', 'i', 'o', 'n')) {
10679
0
  SKIP(7);
10680
0
  SKIP_BLANKS;
10681
0
  if (RAW != '=') {
10682
0
      xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10683
0
      return(NULL);
10684
0
        }
10685
0
  NEXT;
10686
0
  SKIP_BLANKS;
10687
0
  if (RAW == '"') {
10688
0
      NEXT;
10689
0
      version = xmlParseVersionNum(ctxt);
10690
0
      if (RAW != '"') {
10691
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10692
0
      } else
10693
0
          NEXT;
10694
0
  } else if (RAW == '\''){
10695
0
      NEXT;
10696
0
      version = xmlParseVersionNum(ctxt);
10697
0
      if (RAW != '\'') {
10698
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10699
0
      } else
10700
0
          NEXT;
10701
0
  } else {
10702
0
      xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10703
0
  }
10704
0
    }
10705
0
    return(version);
10706
0
}
10707
10708
/**
10709
 * xmlParseEncName:
10710
 * @ctxt:  an XML parser context
10711
 *
10712
 * DEPRECATED: Internal function, don't use.
10713
 *
10714
 * parse the XML encoding name
10715
 *
10716
 * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
10717
 *
10718
 * Returns the encoding name value or NULL
10719
 */
10720
xmlChar *
10721
0
xmlParseEncName(xmlParserCtxtPtr ctxt) {
10722
0
    xmlChar *buf = NULL;
10723
0
    int len = 0;
10724
0
    int size = 10;
10725
0
    int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
10726
0
                    XML_MAX_TEXT_LENGTH :
10727
0
                    XML_MAX_NAME_LENGTH;
10728
0
    xmlChar cur;
10729
10730
0
    cur = CUR;
10731
0
    if (((cur >= 'a') && (cur <= 'z')) ||
10732
0
        ((cur >= 'A') && (cur <= 'Z'))) {
10733
0
  buf = (xmlChar *) xmlMallocAtomic(size);
10734
0
  if (buf == NULL) {
10735
0
      xmlErrMemory(ctxt, NULL);
10736
0
      return(NULL);
10737
0
  }
10738
10739
0
  buf[len++] = cur;
10740
0
  NEXT;
10741
0
  cur = CUR;
10742
0
  while (((cur >= 'a') && (cur <= 'z')) ||
10743
0
         ((cur >= 'A') && (cur <= 'Z')) ||
10744
0
         ((cur >= '0') && (cur <= '9')) ||
10745
0
         (cur == '.') || (cur == '_') ||
10746
0
         (cur == '-')) {
10747
0
      if (len + 1 >= size) {
10748
0
          xmlChar *tmp;
10749
10750
0
    size *= 2;
10751
0
    tmp = (xmlChar *) xmlRealloc(buf, size);
10752
0
    if (tmp == NULL) {
10753
0
        xmlErrMemory(ctxt, NULL);
10754
0
        xmlFree(buf);
10755
0
        return(NULL);
10756
0
    }
10757
0
    buf = tmp;
10758
0
      }
10759
0
      buf[len++] = cur;
10760
0
            if (len > maxLength) {
10761
0
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "EncName");
10762
0
                xmlFree(buf);
10763
0
                return(NULL);
10764
0
            }
10765
0
      NEXT;
10766
0
      cur = CUR;
10767
0
        }
10768
0
  buf[len] = 0;
10769
0
    } else {
10770
0
  xmlFatalErr(ctxt, XML_ERR_ENCODING_NAME, NULL);
10771
0
    }
10772
0
    return(buf);
10773
0
}
10774
10775
/**
10776
 * xmlParseEncodingDecl:
10777
 * @ctxt:  an XML parser context
10778
 *
10779
 * DEPRECATED: Internal function, don't use.
10780
 *
10781
 * parse the XML encoding declaration
10782
 *
10783
 * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' |  "'" EncName "'")
10784
 *
10785
 * this setups the conversion filters.
10786
 *
10787
 * Returns the encoding value or NULL
10788
 */
10789
10790
const xmlChar *
10791
0
xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
10792
0
    xmlChar *encoding = NULL;
10793
10794
0
    SKIP_BLANKS;
10795
0
    if (CMP8(CUR_PTR, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g') == 0)
10796
0
        return(NULL);
10797
10798
0
    SKIP(8);
10799
0
    SKIP_BLANKS;
10800
0
    if (RAW != '=') {
10801
0
        xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10802
0
        return(NULL);
10803
0
    }
10804
0
    NEXT;
10805
0
    SKIP_BLANKS;
10806
0
    if (RAW == '"') {
10807
0
        NEXT;
10808
0
        encoding = xmlParseEncName(ctxt);
10809
0
        if (RAW != '"') {
10810
0
            xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10811
0
            xmlFree((xmlChar *) encoding);
10812
0
            return(NULL);
10813
0
        } else
10814
0
            NEXT;
10815
0
    } else if (RAW == '\''){
10816
0
        NEXT;
10817
0
        encoding = xmlParseEncName(ctxt);
10818
0
        if (RAW != '\'') {
10819
0
            xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10820
0
            xmlFree((xmlChar *) encoding);
10821
0
            return(NULL);
10822
0
        } else
10823
0
            NEXT;
10824
0
    } else {
10825
0
        xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10826
0
    }
10827
10828
0
    if (encoding == NULL)
10829
0
        return(NULL);
10830
10831
0
    xmlSetDeclaredEncoding(ctxt, encoding);
10832
10833
0
    return(ctxt->encoding);
10834
0
}
10835
10836
/**
10837
 * xmlParseSDDecl:
10838
 * @ctxt:  an XML parser context
10839
 *
10840
 * DEPRECATED: Internal function, don't use.
10841
 *
10842
 * parse the XML standalone declaration
10843
 *
10844
 * [32] SDDecl ::= S 'standalone' Eq
10845
 *                 (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no')'"'))
10846
 *
10847
 * [ VC: Standalone Document Declaration ]
10848
 * TODO The standalone document declaration must have the value "no"
10849
 * if any external markup declarations contain declarations of:
10850
 *  - attributes with default values, if elements to which these
10851
 *    attributes apply appear in the document without specifications
10852
 *    of values for these attributes, or
10853
 *  - entities (other than amp, lt, gt, apos, quot), if references
10854
 *    to those entities appear in the document, or
10855
 *  - attributes with values subject to normalization, where the
10856
 *    attribute appears in the document with a value which will change
10857
 *    as a result of normalization, or
10858
 *  - element types with element content, if white space occurs directly
10859
 *    within any instance of those types.
10860
 *
10861
 * Returns:
10862
 *   1 if standalone="yes"
10863
 *   0 if standalone="no"
10864
 *  -2 if standalone attribute is missing or invalid
10865
 *    (A standalone value of -2 means that the XML declaration was found,
10866
 *     but no value was specified for the standalone attribute).
10867
 */
10868
10869
int
10870
0
xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
10871
0
    int standalone = -2;
10872
10873
0
    SKIP_BLANKS;
10874
0
    if (CMP10(CUR_PTR, 's', 't', 'a', 'n', 'd', 'a', 'l', 'o', 'n', 'e')) {
10875
0
  SKIP(10);
10876
0
        SKIP_BLANKS;
10877
0
  if (RAW != '=') {
10878
0
      xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10879
0
      return(standalone);
10880
0
        }
10881
0
  NEXT;
10882
0
  SKIP_BLANKS;
10883
0
        if (RAW == '\''){
10884
0
      NEXT;
10885
0
      if ((RAW == 'n') && (NXT(1) == 'o')) {
10886
0
          standalone = 0;
10887
0
                SKIP(2);
10888
0
      } else if ((RAW == 'y') && (NXT(1) == 'e') &&
10889
0
                 (NXT(2) == 's')) {
10890
0
          standalone = 1;
10891
0
    SKIP(3);
10892
0
            } else {
10893
0
    xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
10894
0
      }
10895
0
      if (RAW != '\'') {
10896
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10897
0
      } else
10898
0
          NEXT;
10899
0
  } else if (RAW == '"'){
10900
0
      NEXT;
10901
0
      if ((RAW == 'n') && (NXT(1) == 'o')) {
10902
0
          standalone = 0;
10903
0
    SKIP(2);
10904
0
      } else if ((RAW == 'y') && (NXT(1) == 'e') &&
10905
0
                 (NXT(2) == 's')) {
10906
0
          standalone = 1;
10907
0
                SKIP(3);
10908
0
            } else {
10909
0
    xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
10910
0
      }
10911
0
      if (RAW != '"') {
10912
0
    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10913
0
      } else
10914
0
          NEXT;
10915
0
  } else {
10916
0
      xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10917
0
        }
10918
0
    }
10919
0
    return(standalone);
10920
0
}
10921
10922
/**
10923
 * xmlParseXMLDecl:
10924
 * @ctxt:  an XML parser context
10925
 *
10926
 * DEPRECATED: Internal function, don't use.
10927
 *
10928
 * parse an XML declaration header
10929
 *
10930
 * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
10931
 */
10932
10933
void
10934
0
xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
10935
0
    xmlChar *version;
10936
10937
    /*
10938
     * This value for standalone indicates that the document has an
10939
     * XML declaration but it does not have a standalone attribute.
10940
     * It will be overwritten later if a standalone attribute is found.
10941
     */
10942
10943
0
    ctxt->standalone = -2;
10944
10945
    /*
10946
     * We know that '<?xml' is here.
10947
     */
10948
0
    SKIP(5);
10949
10950
0
    if (!IS_BLANK_CH(RAW)) {
10951
0
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
10952
0
                 "Blank needed after '<?xml'\n");
10953
0
    }
10954
0
    SKIP_BLANKS;
10955
10956
    /*
10957
     * We must have the VersionInfo here.
10958
     */
10959
0
    version = xmlParseVersionInfo(ctxt);
10960
0
    if (version == NULL) {
10961
0
  xmlFatalErr(ctxt, XML_ERR_VERSION_MISSING, NULL);
10962
0
    } else {
10963
0
  if (!xmlStrEqual(version, (const xmlChar *) XML_DEFAULT_VERSION)) {
10964
      /*
10965
       * Changed here for XML-1.0 5th edition
10966
       */
10967
0
      if (ctxt->options & XML_PARSE_OLD10) {
10968
0
    xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
10969
0
                "Unsupported version '%s'\n",
10970
0
                version);
10971
0
      } else {
10972
0
          if ((version[0] == '1') && ((version[1] == '.'))) {
10973
0
        xmlWarningMsg(ctxt, XML_WAR_UNKNOWN_VERSION,
10974
0
                      "Unsupported version '%s'\n",
10975
0
          version, NULL);
10976
0
    } else {
10977
0
        xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
10978
0
              "Unsupported version '%s'\n",
10979
0
              version);
10980
0
    }
10981
0
      }
10982
0
  }
10983
0
  if (ctxt->version != NULL)
10984
0
      xmlFree((void *) ctxt->version);
10985
0
  ctxt->version = version;
10986
0
    }
10987
10988
    /*
10989
     * We may have the encoding declaration
10990
     */
10991
0
    if (!IS_BLANK_CH(RAW)) {
10992
0
        if ((RAW == '?') && (NXT(1) == '>')) {
10993
0
      SKIP(2);
10994
0
      return;
10995
0
  }
10996
0
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
10997
0
    }
10998
0
    xmlParseEncodingDecl(ctxt);
10999
0
    if ((ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) ||
11000
0
         (ctxt->instate == XML_PARSER_EOF)) {
11001
  /*
11002
   * The XML REC instructs us to stop parsing right here
11003
   */
11004
0
        return;
11005
0
    }
11006
11007
    /*
11008
     * We may have the standalone status.
11009
     */
11010
0
    if ((ctxt->encoding != NULL) && (!IS_BLANK_CH(RAW))) {
11011
0
        if ((RAW == '?') && (NXT(1) == '>')) {
11012
0
      SKIP(2);
11013
0
      return;
11014
0
  }
11015
0
  xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
11016
0
    }
11017
11018
    /*
11019
     * We can grow the input buffer freely at that point
11020
     */
11021
0
    GROW;
11022
11023
0
    SKIP_BLANKS;
11024
0
    ctxt->standalone = xmlParseSDDecl(ctxt);
11025
11026
0
    SKIP_BLANKS;
11027
0
    if ((RAW == '?') && (NXT(1) == '>')) {
11028
0
        SKIP(2);
11029
0
    } else if (RAW == '>') {
11030
        /* Deprecated old WD ... */
11031
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
11032
0
  NEXT;
11033
0
    } else {
11034
0
        int c;
11035
11036
0
  xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
11037
0
        while ((c = CUR) != 0) {
11038
0
            NEXT;
11039
0
            if (c == '>')
11040
0
                break;
11041
0
        }
11042
0
    }
11043
0
}
11044
11045
/**
11046
 * xmlParseMisc:
11047
 * @ctxt:  an XML parser context
11048
 *
11049
 * DEPRECATED: Internal function, don't use.
11050
 *
11051
 * parse an XML Misc* optional field.
11052
 *
11053
 * [27] Misc ::= Comment | PI |  S
11054
 */
11055
11056
void
11057
0
xmlParseMisc(xmlParserCtxtPtr ctxt) {
11058
0
    while (ctxt->instate != XML_PARSER_EOF) {
11059
0
        SKIP_BLANKS;
11060
0
        GROW;
11061
0
        if ((RAW == '<') && (NXT(1) == '?')) {
11062
0
      xmlParsePI(ctxt);
11063
0
        } else if (CMP4(CUR_PTR, '<', '!', '-', '-')) {
11064
0
      xmlParseComment(ctxt);
11065
0
        } else {
11066
0
            break;
11067
0
        }
11068
0
    }
11069
0
}
11070
11071
/**
11072
 * xmlParseDocument:
11073
 * @ctxt:  an XML parser context
11074
 *
11075
 * parse an XML document (and build a tree if using the standard SAX
11076
 * interface).
11077
 *
11078
 * [1] document ::= prolog element Misc*
11079
 *
11080
 * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
11081
 *
11082
 * Returns 0, -1 in case of error. the parser context is augmented
11083
 *                as a result of the parsing.
11084
 */
11085
11086
int
11087
0
xmlParseDocument(xmlParserCtxtPtr ctxt) {
11088
0
    xmlInitParser();
11089
11090
0
    if ((ctxt == NULL) || (ctxt->input == NULL))
11091
0
        return(-1);
11092
11093
0
    GROW;
11094
11095
    /*
11096
     * SAX: detecting the level.
11097
     */
11098
0
    xmlDetectSAX2(ctxt);
11099
11100
    /*
11101
     * SAX: beginning of the document processing.
11102
     */
11103
0
    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
11104
0
        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
11105
0
    if (ctxt->instate == XML_PARSER_EOF)
11106
0
  return(-1);
11107
11108
0
    xmlDetectEncoding(ctxt);
11109
11110
0
    if (CUR == 0) {
11111
0
  xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
11112
0
  return(-1);
11113
0
    }
11114
11115
0
    GROW;
11116
0
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
11117
11118
  /*
11119
   * Note that we will switch encoding on the fly.
11120
   */
11121
0
  xmlParseXMLDecl(ctxt);
11122
0
  if ((ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) ||
11123
0
      (ctxt->instate == XML_PARSER_EOF)) {
11124
      /*
11125
       * The XML REC instructs us to stop parsing right here
11126
       */
11127
0
      return(-1);
11128
0
  }
11129
0
  SKIP_BLANKS;
11130
0
    } else {
11131
0
  ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11132
0
    }
11133
0
    if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
11134
0
        ctxt->sax->startDocument(ctxt->userData);
11135
0
    if (ctxt->instate == XML_PARSER_EOF)
11136
0
  return(-1);
11137
0
    if ((ctxt->myDoc != NULL) && (ctxt->input != NULL) &&
11138
0
        (ctxt->input->buf != NULL) && (ctxt->input->buf->compressed >= 0)) {
11139
0
  ctxt->myDoc->compression = ctxt->input->buf->compressed;
11140
0
    }
11141
11142
    /*
11143
     * The Misc part of the Prolog
11144
     */
11145
0
    xmlParseMisc(ctxt);
11146
11147
    /*
11148
     * Then possibly doc type declaration(s) and more Misc
11149
     * (doctypedecl Misc*)?
11150
     */
11151
0
    GROW;
11152
0
    if (CMP9(CUR_PTR, '<', '!', 'D', 'O', 'C', 'T', 'Y', 'P', 'E')) {
11153
11154
0
  ctxt->inSubset = 1;
11155
0
  xmlParseDocTypeDecl(ctxt);
11156
0
  if (RAW == '[') {
11157
0
      ctxt->instate = XML_PARSER_DTD;
11158
0
      xmlParseInternalSubset(ctxt);
11159
0
      if (ctxt->instate == XML_PARSER_EOF)
11160
0
    return(-1);
11161
0
  }
11162
11163
  /*
11164
   * Create and update the external subset.
11165
   */
11166
0
  ctxt->inSubset = 2;
11167
0
  if ((ctxt->sax != NULL) && (ctxt->sax->externalSubset != NULL) &&
11168
0
      (!ctxt->disableSAX))
11169
0
      ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
11170
0
                                ctxt->extSubSystem, ctxt->extSubURI);
11171
0
  if (ctxt->instate == XML_PARSER_EOF)
11172
0
      return(-1);
11173
0
  ctxt->inSubset = 0;
11174
11175
0
        xmlCleanSpecialAttr(ctxt);
11176
11177
0
  ctxt->instate = XML_PARSER_PROLOG;
11178
0
  xmlParseMisc(ctxt);
11179
0
    }
11180
11181
    /*
11182
     * Time to start parsing the tree itself
11183
     */
11184
0
    GROW;
11185
0
    if (RAW != '<') {
11186
0
  xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
11187
0
           "Start tag expected, '<' not found\n");
11188
0
    } else {
11189
0
  ctxt->instate = XML_PARSER_CONTENT;
11190
0
  xmlParseElement(ctxt);
11191
0
  ctxt->instate = XML_PARSER_EPILOG;
11192
11193
11194
  /*
11195
   * The Misc part at the end
11196
   */
11197
0
  xmlParseMisc(ctxt);
11198
11199
0
        if (ctxt->input->cur < ctxt->input->end) {
11200
0
            if (ctxt->errNo == XML_ERR_OK)
11201
0
          xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
11202
0
        } else if ((ctxt->input->buf != NULL) &&
11203
0
                   (ctxt->input->buf->encoder != NULL) &&
11204
0
                   (!xmlBufIsEmpty(ctxt->input->buf->raw))) {
11205
0
            xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
11206
0
                           "Truncated multi-byte sequence at EOF\n");
11207
0
        }
11208
0
  ctxt->instate = XML_PARSER_EOF;
11209
0
    }
11210
11211
    /*
11212
     * SAX: end of the document processing.
11213
     */
11214
0
    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11215
0
        ctxt->sax->endDocument(ctxt->userData);
11216
11217
    /*
11218
     * Remove locally kept entity definitions if the tree was not built
11219
     */
11220
0
    if ((ctxt->myDoc != NULL) &&
11221
0
  (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
11222
0
  xmlFreeDoc(ctxt->myDoc);
11223
0
  ctxt->myDoc = NULL;
11224
0
    }
11225
11226
0
    if ((ctxt->wellFormed) && (ctxt->myDoc != NULL)) {
11227
0
        ctxt->myDoc->properties |= XML_DOC_WELLFORMED;
11228
0
  if (ctxt->valid)
11229
0
      ctxt->myDoc->properties |= XML_DOC_DTDVALID;
11230
0
  if (ctxt->nsWellFormed)
11231
0
      ctxt->myDoc->properties |= XML_DOC_NSVALID;
11232
0
  if (ctxt->options & XML_PARSE_OLD10)
11233
0
      ctxt->myDoc->properties |= XML_DOC_OLD10;
11234
0
    }
11235
0
    if (! ctxt->wellFormed) {
11236
0
  ctxt->valid = 0;
11237
0
  return(-1);
11238
0
    }
11239
0
    return(0);
11240
0
}
11241
11242
/**
11243
 * xmlParseExtParsedEnt:
11244
 * @ctxt:  an XML parser context
11245
 *
11246
 * parse a general parsed entity
11247
 * An external general parsed entity is well-formed if it matches the
11248
 * production labeled extParsedEnt.
11249
 *
11250
 * [78] extParsedEnt ::= TextDecl? content
11251
 *
11252
 * Returns 0, -1 in case of error. the parser context is augmented
11253
 *                as a result of the parsing.
11254
 */
11255
11256
int
11257
0
xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) {
11258
0
    if ((ctxt == NULL) || (ctxt->input == NULL))
11259
0
        return(-1);
11260
11261
0
    xmlDetectSAX2(ctxt);
11262
11263
    /*
11264
     * SAX: beginning of the document processing.
11265
     */
11266
0
    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
11267
0
        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
11268
11269
0
    xmlDetectEncoding(ctxt);
11270
11271
0
    if (CUR == 0) {
11272
0
  xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
11273
0
    }
11274
11275
    /*
11276
     * Check for the XMLDecl in the Prolog.
11277
     */
11278
0
    GROW;
11279
0
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
11280
11281
  /*
11282
   * Note that we will switch encoding on the fly.
11283
   */
11284
0
  xmlParseXMLDecl(ctxt);
11285
0
  if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
11286
      /*
11287
       * The XML REC instructs us to stop parsing right here
11288
       */
11289
0
      return(-1);
11290
0
  }
11291
0
  SKIP_BLANKS;
11292
0
    } else {
11293
0
  ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11294
0
    }
11295
0
    if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
11296
0
        ctxt->sax->startDocument(ctxt->userData);
11297
0
    if (ctxt->instate == XML_PARSER_EOF)
11298
0
  return(-1);
11299
11300
    /*
11301
     * Doing validity checking on chunk doesn't make sense
11302
     */
11303
0
    ctxt->instate = XML_PARSER_CONTENT;
11304
0
    ctxt->validate = 0;
11305
0
    ctxt->loadsubset = 0;
11306
0
    ctxt->depth = 0;
11307
11308
0
    xmlParseContent(ctxt);
11309
0
    if (ctxt->instate == XML_PARSER_EOF)
11310
0
  return(-1);
11311
11312
0
    if ((RAW == '<') && (NXT(1) == '/')) {
11313
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
11314
0
    } else if (RAW != 0) {
11315
0
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
11316
0
    }
11317
11318
    /*
11319
     * SAX: end of the document processing.
11320
     */
11321
0
    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11322
0
        ctxt->sax->endDocument(ctxt->userData);
11323
11324
0
    if (! ctxt->wellFormed) return(-1);
11325
0
    return(0);
11326
0
}
11327
11328
#ifdef LIBXML_PUSH_ENABLED
11329
/************************************************************************
11330
 *                  *
11331
 *    Progressive parsing interfaces        *
11332
 *                  *
11333
 ************************************************************************/
11334
11335
/**
11336
 * xmlParseLookupChar:
11337
 * @ctxt:  an XML parser context
11338
 * @c:  character
11339
 *
11340
 * Check whether the input buffer contains a character.
11341
 */
11342
static int
11343
0
xmlParseLookupChar(xmlParserCtxtPtr ctxt, int c) {
11344
0
    const xmlChar *cur;
11345
11346
0
    if (ctxt->checkIndex == 0) {
11347
0
        cur = ctxt->input->cur + 1;
11348
0
    } else {
11349
0
        cur = ctxt->input->cur + ctxt->checkIndex;
11350
0
    }
11351
11352
0
    if (memchr(cur, c, ctxt->input->end - cur) == NULL) {
11353
0
        size_t index = ctxt->input->end - ctxt->input->cur;
11354
11355
0
        if (index > LONG_MAX) {
11356
0
            ctxt->checkIndex = 0;
11357
0
            return(1);
11358
0
        }
11359
0
        ctxt->checkIndex = index;
11360
0
        return(0);
11361
0
    } else {
11362
0
        ctxt->checkIndex = 0;
11363
0
        return(1);
11364
0
    }
11365
0
}
11366
11367
/**
11368
 * xmlParseLookupString:
11369
 * @ctxt:  an XML parser context
11370
 * @startDelta: delta to apply at the start
11371
 * @str:  string
11372
 * @strLen:  length of string
11373
 *
11374
 * Check whether the input buffer contains a string.
11375
 */
11376
static const xmlChar *
11377
xmlParseLookupString(xmlParserCtxtPtr ctxt, size_t startDelta,
11378
0
                     const char *str, size_t strLen) {
11379
0
    const xmlChar *cur, *term;
11380
11381
0
    if (ctxt->checkIndex == 0) {
11382
0
        cur = ctxt->input->cur + startDelta;
11383
0
    } else {
11384
0
        cur = ctxt->input->cur + ctxt->checkIndex;
11385
0
    }
11386
11387
0
    term = BAD_CAST strstr((const char *) cur, str);
11388
0
    if (term == NULL) {
11389
0
        const xmlChar *end = ctxt->input->end;
11390
0
        size_t index;
11391
11392
        /* Rescan (strLen - 1) characters. */
11393
0
        if ((size_t) (end - cur) < strLen)
11394
0
            end = cur;
11395
0
        else
11396
0
            end -= strLen - 1;
11397
0
        index = end - ctxt->input->cur;
11398
0
        if (index > LONG_MAX) {
11399
0
            ctxt->checkIndex = 0;
11400
0
            return(ctxt->input->end - strLen);
11401
0
        }
11402
0
        ctxt->checkIndex = index;
11403
0
    } else {
11404
0
        ctxt->checkIndex = 0;
11405
0
    }
11406
11407
0
    return(term);
11408
0
}
11409
11410
/**
11411
 * xmlParseLookupCharData:
11412
 * @ctxt:  an XML parser context
11413
 *
11414
 * Check whether the input buffer contains terminated char data.
11415
 */
11416
static int
11417
0
xmlParseLookupCharData(xmlParserCtxtPtr ctxt) {
11418
0
    const xmlChar *cur = ctxt->input->cur + ctxt->checkIndex;
11419
0
    const xmlChar *end = ctxt->input->end;
11420
0
    size_t index;
11421
11422
0
    while (cur < end) {
11423
0
        if ((*cur == '<') || (*cur == '&')) {
11424
0
            ctxt->checkIndex = 0;
11425
0
            return(1);
11426
0
        }
11427
0
        cur++;
11428
0
    }
11429
11430
0
    index = cur - ctxt->input->cur;
11431
0
    if (index > LONG_MAX) {
11432
0
        ctxt->checkIndex = 0;
11433
0
        return(1);
11434
0
    }
11435
0
    ctxt->checkIndex = index;
11436
0
    return(0);
11437
0
}
11438
11439
/**
11440
 * xmlParseLookupGt:
11441
 * @ctxt:  an XML parser context
11442
 *
11443
 * Check whether there's enough data in the input buffer to finish parsing
11444
 * a start tag. This has to take quotes into account.
11445
 */
11446
static int
11447
0
xmlParseLookupGt(xmlParserCtxtPtr ctxt) {
11448
0
    const xmlChar *cur;
11449
0
    const xmlChar *end = ctxt->input->end;
11450
0
    int state = ctxt->endCheckState;
11451
0
    size_t index;
11452
11453
0
    if (ctxt->checkIndex == 0)
11454
0
        cur = ctxt->input->cur + 1;
11455
0
    else
11456
0
        cur = ctxt->input->cur + ctxt->checkIndex;
11457
11458
0
    while (cur < end) {
11459
0
        if (state) {
11460
0
            if (*cur == state)
11461
0
                state = 0;
11462
0
        } else if (*cur == '\'' || *cur == '"') {
11463
0
            state = *cur;
11464
0
        } else if (*cur == '>') {
11465
0
            ctxt->checkIndex = 0;
11466
0
            ctxt->endCheckState = 0;
11467
0
            return(1);
11468
0
        }
11469
0
        cur++;
11470
0
    }
11471
11472
0
    index = cur - ctxt->input->cur;
11473
0
    if (index > LONG_MAX) {
11474
0
        ctxt->checkIndex = 0;
11475
0
        ctxt->endCheckState = 0;
11476
0
        return(1);
11477
0
    }
11478
0
    ctxt->checkIndex = index;
11479
0
    ctxt->endCheckState = state;
11480
0
    return(0);
11481
0
}
11482
11483
/**
11484
 * xmlParseLookupInternalSubset:
11485
 * @ctxt:  an XML parser context
11486
 *
11487
 * Check whether there's enough data in the input buffer to finish parsing
11488
 * the internal subset.
11489
 */
11490
static int
11491
0
xmlParseLookupInternalSubset(xmlParserCtxtPtr ctxt) {
11492
    /*
11493
     * Sorry, but progressive parsing of the internal subset is not
11494
     * supported. We first check that the full content of the internal
11495
     * subset is available and parsing is launched only at that point.
11496
     * Internal subset ends with "']' S? '>'" in an unescaped section and
11497
     * not in a ']]>' sequence which are conditional sections.
11498
     */
11499
0
    const xmlChar *cur, *start;
11500
0
    const xmlChar *end = ctxt->input->end;
11501
0
    int state = ctxt->endCheckState;
11502
0
    size_t index;
11503
11504
0
    if (ctxt->checkIndex == 0) {
11505
0
        cur = ctxt->input->cur + 1;
11506
0
    } else {
11507
0
        cur = ctxt->input->cur + ctxt->checkIndex;
11508
0
    }
11509
0
    start = cur;
11510
11511
0
    while (cur < end) {
11512
0
        if (state == '-') {
11513
0
            if ((*cur == '-') &&
11514
0
                (cur[1] == '-') &&
11515
0
                (cur[2] == '>')) {
11516
0
                state = 0;
11517
0
                cur += 3;
11518
0
                start = cur;
11519
0
                continue;
11520
0
            }
11521
0
        }
11522
0
        else if (state == ']') {
11523
0
            if (*cur == '>') {
11524
0
                ctxt->checkIndex = 0;
11525
0
                ctxt->endCheckState = 0;
11526
0
                return(1);
11527
0
            }
11528
0
            if (IS_BLANK_CH(*cur)) {
11529
0
                state = ' ';
11530
0
            } else if (*cur != ']') {
11531
0
                state = 0;
11532
0
                start = cur;
11533
0
                continue;
11534
0
            }
11535
0
        }
11536
0
        else if (state == ' ') {
11537
0
            if (*cur == '>') {
11538
0
                ctxt->checkIndex = 0;
11539
0
                ctxt->endCheckState = 0;
11540
0
                return(1);
11541
0
            }
11542
0
            if (!IS_BLANK_CH(*cur)) {
11543
0
                state = 0;
11544
0
                start = cur;
11545
0
                continue;
11546
0
            }
11547
0
        }
11548
0
        else if (state != 0) {
11549
0
            if (*cur == state) {
11550
0
                state = 0;
11551
0
                start = cur + 1;
11552
0
            }
11553
0
        }
11554
0
        else if (*cur == '<') {
11555
0
            if ((cur[1] == '!') &&
11556
0
                (cur[2] == '-') &&
11557
0
                (cur[3] == '-')) {
11558
0
                state = '-';
11559
0
                cur += 4;
11560
                /* Don't treat <!--> as comment */
11561
0
                start = cur;
11562
0
                continue;
11563
0
            }
11564
0
        }
11565
0
        else if ((*cur == '"') || (*cur == '\'') || (*cur == ']')) {
11566
0
            state = *cur;
11567
0
        }
11568
11569
0
        cur++;
11570
0
    }
11571
11572
    /*
11573
     * Rescan the three last characters to detect "<!--" and "-->"
11574
     * split across chunks.
11575
     */
11576
0
    if ((state == 0) || (state == '-')) {
11577
0
        if (cur - start < 3)
11578
0
            cur = start;
11579
0
        else
11580
0
            cur -= 3;
11581
0
    }
11582
0
    index = cur - ctxt->input->cur;
11583
0
    if (index > LONG_MAX) {
11584
0
        ctxt->checkIndex = 0;
11585
0
        ctxt->endCheckState = 0;
11586
0
        return(1);
11587
0
    }
11588
0
    ctxt->checkIndex = index;
11589
0
    ctxt->endCheckState = state;
11590
0
    return(0);
11591
0
}
11592
11593
/**
11594
 * xmlCheckCdataPush:
11595
 * @cur: pointer to the block of characters
11596
 * @len: length of the block in bytes
11597
 * @complete: 1 if complete CDATA block is passed in, 0 if partial block
11598
 *
11599
 * Check that the block of characters is okay as SCdata content [20]
11600
 *
11601
 * Returns the number of bytes to pass if okay, a negative index where an
11602
 *         UTF-8 error occurred otherwise
11603
 */
11604
static int
11605
0
xmlCheckCdataPush(const xmlChar *utf, int len, int complete) {
11606
0
    int ix;
11607
0
    unsigned char c;
11608
0
    int codepoint;
11609
11610
0
    if ((utf == NULL) || (len <= 0))
11611
0
        return(0);
11612
11613
0
    for (ix = 0; ix < len;) {      /* string is 0-terminated */
11614
0
        c = utf[ix];
11615
0
        if ((c & 0x80) == 0x00) { /* 1-byte code, starts with 10 */
11616
0
      if (c >= 0x20)
11617
0
    ix++;
11618
0
      else if ((c == 0xA) || (c == 0xD) || (c == 0x9))
11619
0
          ix++;
11620
0
      else
11621
0
          return(-ix);
11622
0
  } else if ((c & 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */
11623
0
      if (ix + 2 > len) return(complete ? -ix : ix);
11624
0
      if ((utf[ix+1] & 0xc0 ) != 0x80)
11625
0
          return(-ix);
11626
0
      codepoint = (utf[ix] & 0x1f) << 6;
11627
0
      codepoint |= utf[ix+1] & 0x3f;
11628
0
      if (!xmlIsCharQ(codepoint))
11629
0
          return(-ix);
11630
0
      ix += 2;
11631
0
  } else if ((c & 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */
11632
0
      if (ix + 3 > len) return(complete ? -ix : ix);
11633
0
      if (((utf[ix+1] & 0xc0) != 0x80) ||
11634
0
          ((utf[ix+2] & 0xc0) != 0x80))
11635
0
        return(-ix);
11636
0
      codepoint = (utf[ix] & 0xf) << 12;
11637
0
      codepoint |= (utf[ix+1] & 0x3f) << 6;
11638
0
      codepoint |= utf[ix+2] & 0x3f;
11639
0
      if (!xmlIsCharQ(codepoint))
11640
0
          return(-ix);
11641
0
      ix += 3;
11642
0
  } else if ((c & 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */
11643
0
      if (ix + 4 > len) return(complete ? -ix : ix);
11644
0
      if (((utf[ix+1] & 0xc0) != 0x80) ||
11645
0
          ((utf[ix+2] & 0xc0) != 0x80) ||
11646
0
    ((utf[ix+3] & 0xc0) != 0x80))
11647
0
        return(-ix);
11648
0
      codepoint = (utf[ix] & 0x7) << 18;
11649
0
      codepoint |= (utf[ix+1] & 0x3f) << 12;
11650
0
      codepoint |= (utf[ix+2] & 0x3f) << 6;
11651
0
      codepoint |= utf[ix+3] & 0x3f;
11652
0
      if (!xmlIsCharQ(codepoint))
11653
0
          return(-ix);
11654
0
      ix += 4;
11655
0
  } else       /* unknown encoding */
11656
0
      return(-ix);
11657
0
      }
11658
0
      return(ix);
11659
0
}
11660
11661
/**
11662
 * xmlParseTryOrFinish:
11663
 * @ctxt:  an XML parser context
11664
 * @terminate:  last chunk indicator
11665
 *
11666
 * Try to progress on parsing
11667
 *
11668
 * Returns zero if no parsing was possible
11669
 */
11670
static int
11671
0
xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
11672
0
    int ret = 0;
11673
0
    size_t avail;
11674
0
    xmlChar cur, next;
11675
11676
0
    if (ctxt->input == NULL)
11677
0
        return(0);
11678
11679
0
    if ((ctxt->input != NULL) &&
11680
0
        (ctxt->input->cur - ctxt->input->base > 4096)) {
11681
0
        xmlParserShrink(ctxt);
11682
0
    }
11683
11684
0
    while (ctxt->instate != XML_PARSER_EOF) {
11685
0
  if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
11686
0
      return(0);
11687
11688
0
        avail = ctxt->input->end - ctxt->input->cur;
11689
0
        if (avail < 1)
11690
0
      goto done;
11691
0
        switch (ctxt->instate) {
11692
0
            case XML_PARSER_EOF:
11693
          /*
11694
     * Document parsing is done !
11695
     */
11696
0
          goto done;
11697
0
            case XML_PARSER_START:
11698
                /*
11699
                 * Very first chars read from the document flow.
11700
                 */
11701
0
                if ((!terminate) && (avail < 4))
11702
0
                    goto done;
11703
11704
                /*
11705
                 * We need more bytes to detect EBCDIC code pages.
11706
                 * See xmlDetectEBCDIC.
11707
                 */
11708
0
                if ((CMP4(CUR_PTR, 0x4C, 0x6F, 0xA7, 0x94)) &&
11709
0
                    (!terminate) && (avail < 200))
11710
0
                    goto done;
11711
11712
0
                xmlDetectEncoding(ctxt);
11713
0
                if (ctxt->instate == XML_PARSER_EOF)
11714
0
                    goto done;
11715
0
                ctxt->instate = XML_PARSER_XML_DECL;
11716
0
    break;
11717
11718
0
            case XML_PARSER_XML_DECL:
11719
0
    if ((!terminate) && (avail < 2))
11720
0
        goto done;
11721
0
    cur = ctxt->input->cur[0];
11722
0
    next = ctxt->input->cur[1];
11723
0
          if ((cur == '<') && (next == '?')) {
11724
        /* PI or XML decl */
11725
0
        if ((!terminate) &&
11726
0
                        (!xmlParseLookupString(ctxt, 2, "?>", 2)))
11727
0
      goto done;
11728
0
        if ((ctxt->input->cur[2] == 'x') &&
11729
0
      (ctxt->input->cur[3] == 'm') &&
11730
0
      (ctxt->input->cur[4] == 'l') &&
11731
0
      (IS_BLANK_CH(ctxt->input->cur[5]))) {
11732
0
      ret += 5;
11733
0
      xmlParseXMLDecl(ctxt);
11734
0
      if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
11735
          /*
11736
           * The XML REC instructs us to stop parsing right
11737
           * here
11738
           */
11739
0
          xmlHaltParser(ctxt);
11740
0
          return(0);
11741
0
      }
11742
0
        } else {
11743
0
      ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11744
0
        }
11745
0
    } else {
11746
0
        ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11747
0
        if (ctxt->version == NULL) {
11748
0
            xmlErrMemory(ctxt, NULL);
11749
0
      break;
11750
0
        }
11751
0
    }
11752
0
                if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
11753
0
                    ctxt->sax->setDocumentLocator(ctxt->userData,
11754
0
                                                  &xmlDefaultSAXLocator);
11755
0
                if ((ctxt->sax) && (ctxt->sax->startDocument) &&
11756
0
                    (!ctxt->disableSAX))
11757
0
                    ctxt->sax->startDocument(ctxt->userData);
11758
0
                if (ctxt->instate == XML_PARSER_EOF)
11759
0
                    goto done;
11760
0
                ctxt->instate = XML_PARSER_MISC;
11761
0
    break;
11762
0
            case XML_PARSER_START_TAG: {
11763
0
          const xmlChar *name;
11764
0
    const xmlChar *prefix = NULL;
11765
0
    const xmlChar *URI = NULL;
11766
0
                int line = ctxt->input->line;
11767
0
    int nbNs = 0;
11768
11769
0
    if ((!terminate) && (avail < 2))
11770
0
        goto done;
11771
0
    cur = ctxt->input->cur[0];
11772
0
          if (cur != '<') {
11773
0
        xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
11774
0
                                   "Start tag expected, '<' not found");
11775
0
        xmlHaltParser(ctxt);
11776
0
        if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11777
0
      ctxt->sax->endDocument(ctxt->userData);
11778
0
        goto done;
11779
0
    }
11780
0
    if ((!terminate) && (!xmlParseLookupGt(ctxt)))
11781
0
                    goto done;
11782
0
    if (ctxt->spaceNr == 0)
11783
0
        spacePush(ctxt, -1);
11784
0
    else if (*ctxt->space == -2)
11785
0
        spacePush(ctxt, -1);
11786
0
    else
11787
0
        spacePush(ctxt, *ctxt->space);
11788
0
#ifdef LIBXML_SAX1_ENABLED
11789
0
    if (ctxt->sax2)
11790
0
#endif /* LIBXML_SAX1_ENABLED */
11791
0
        name = xmlParseStartTag2(ctxt, &prefix, &URI, &nbNs);
11792
0
#ifdef LIBXML_SAX1_ENABLED
11793
0
    else
11794
0
        name = xmlParseStartTag(ctxt);
11795
0
#endif /* LIBXML_SAX1_ENABLED */
11796
0
    if (ctxt->instate == XML_PARSER_EOF)
11797
0
        goto done;
11798
0
    if (name == NULL) {
11799
0
        spacePop(ctxt);
11800
0
        xmlHaltParser(ctxt);
11801
0
        if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11802
0
      ctxt->sax->endDocument(ctxt->userData);
11803
0
        goto done;
11804
0
    }
11805
0
#ifdef LIBXML_VALID_ENABLED
11806
    /*
11807
     * [ VC: Root Element Type ]
11808
     * The Name in the document type declaration must match
11809
     * the element type of the root element.
11810
     */
11811
0
    if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
11812
0
        ctxt->node && (ctxt->node == ctxt->myDoc->children))
11813
0
        ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
11814
0
#endif /* LIBXML_VALID_ENABLED */
11815
11816
    /*
11817
     * Check for an Empty Element.
11818
     */
11819
0
    if ((RAW == '/') && (NXT(1) == '>')) {
11820
0
        SKIP(2);
11821
11822
0
        if (ctxt->sax2) {
11823
0
      if ((ctxt->sax != NULL) &&
11824
0
          (ctxt->sax->endElementNs != NULL) &&
11825
0
          (!ctxt->disableSAX))
11826
0
          ctxt->sax->endElementNs(ctxt->userData, name,
11827
0
                                  prefix, URI);
11828
0
      if (nbNs > 0)
11829
0
          xmlParserNsPop(ctxt, nbNs);
11830
0
#ifdef LIBXML_SAX1_ENABLED
11831
0
        } else {
11832
0
      if ((ctxt->sax != NULL) &&
11833
0
          (ctxt->sax->endElement != NULL) &&
11834
0
          (!ctxt->disableSAX))
11835
0
          ctxt->sax->endElement(ctxt->userData, name);
11836
0
#endif /* LIBXML_SAX1_ENABLED */
11837
0
        }
11838
0
        spacePop(ctxt);
11839
0
    } else if (RAW == '>') {
11840
0
        NEXT;
11841
0
                    nameNsPush(ctxt, name, prefix, URI, line, nbNs);
11842
0
    } else {
11843
0
        xmlFatalErrMsgStr(ctxt, XML_ERR_GT_REQUIRED,
11844
0
           "Couldn't find end of Start Tag %s\n",
11845
0
           name);
11846
0
        nodePop(ctxt);
11847
0
        spacePop(ctxt);
11848
0
                    if (nbNs > 0)
11849
0
                        xmlParserNsPop(ctxt, nbNs);
11850
0
    }
11851
11852
0
                if (ctxt->instate == XML_PARSER_EOF)
11853
0
                    goto done;
11854
0
                if (ctxt->nameNr == 0)
11855
0
                    ctxt->instate = XML_PARSER_EPILOG;
11856
0
                else
11857
0
                    ctxt->instate = XML_PARSER_CONTENT;
11858
0
                break;
11859
0
      }
11860
0
            case XML_PARSER_CONTENT: {
11861
0
    cur = ctxt->input->cur[0];
11862
11863
0
    if (cur == '<') {
11864
0
                    if ((!terminate) && (avail < 2))
11865
0
                        goto done;
11866
0
        next = ctxt->input->cur[1];
11867
11868
0
                    if (next == '/') {
11869
0
                        ctxt->instate = XML_PARSER_END_TAG;
11870
0
                        break;
11871
0
                    } else if (next == '?') {
11872
0
                        if ((!terminate) &&
11873
0
                            (!xmlParseLookupString(ctxt, 2, "?>", 2)))
11874
0
                            goto done;
11875
0
                        xmlParsePI(ctxt);
11876
0
                        if (ctxt->instate == XML_PARSER_EOF)
11877
0
                            goto done;
11878
0
                        ctxt->instate = XML_PARSER_CONTENT;
11879
0
                        break;
11880
0
                    } else if (next == '!') {
11881
0
                        if ((!terminate) && (avail < 3))
11882
0
                            goto done;
11883
0
                        next = ctxt->input->cur[2];
11884
11885
0
                        if (next == '-') {
11886
0
                            if ((!terminate) && (avail < 4))
11887
0
                                goto done;
11888
0
                            if (ctxt->input->cur[3] == '-') {
11889
0
                                if ((!terminate) &&
11890
0
                                    (!xmlParseLookupString(ctxt, 4, "-->", 3)))
11891
0
                                    goto done;
11892
0
                                xmlParseComment(ctxt);
11893
0
                                if (ctxt->instate == XML_PARSER_EOF)
11894
0
                                    goto done;
11895
0
                                ctxt->instate = XML_PARSER_CONTENT;
11896
0
                                break;
11897
0
                            }
11898
0
                        } else if (next == '[') {
11899
0
                            if ((!terminate) && (avail < 9))
11900
0
                                goto done;
11901
0
                            if ((ctxt->input->cur[2] == '[') &&
11902
0
                                (ctxt->input->cur[3] == 'C') &&
11903
0
                                (ctxt->input->cur[4] == 'D') &&
11904
0
                                (ctxt->input->cur[5] == 'A') &&
11905
0
                                (ctxt->input->cur[6] == 'T') &&
11906
0
                                (ctxt->input->cur[7] == 'A') &&
11907
0
                                (ctxt->input->cur[8] == '[')) {
11908
0
                                SKIP(9);
11909
0
                                ctxt->instate = XML_PARSER_CDATA_SECTION;
11910
0
                                break;
11911
0
                            }
11912
0
                        }
11913
0
                    }
11914
0
    } else if (cur == '&') {
11915
0
        if ((!terminate) && (!xmlParseLookupChar(ctxt, ';')))
11916
0
      goto done;
11917
0
        xmlParseReference(ctxt);
11918
0
                    break;
11919
0
    } else {
11920
        /* TODO Avoid the extra copy, handle directly !!! */
11921
        /*
11922
         * Goal of the following test is:
11923
         *  - minimize calls to the SAX 'character' callback
11924
         *    when they are mergeable
11925
         *  - handle an problem for isBlank when we only parse
11926
         *    a sequence of blank chars and the next one is
11927
         *    not available to check against '<' presence.
11928
         *  - tries to homogenize the differences in SAX
11929
         *    callbacks between the push and pull versions
11930
         *    of the parser.
11931
         */
11932
0
        if (avail < XML_PARSER_BIG_BUFFER_SIZE) {
11933
0
      if ((!terminate) && (!xmlParseLookupCharData(ctxt)))
11934
0
          goto done;
11935
0
                    }
11936
0
                    ctxt->checkIndex = 0;
11937
0
        xmlParseCharDataInternal(ctxt, !terminate);
11938
0
                    break;
11939
0
    }
11940
11941
0
                ctxt->instate = XML_PARSER_START_TAG;
11942
0
    break;
11943
0
      }
11944
0
            case XML_PARSER_END_TAG:
11945
0
    if ((!terminate) && (!xmlParseLookupChar(ctxt, '>')))
11946
0
        goto done;
11947
0
    if (ctxt->sax2) {
11948
0
              xmlParseEndTag2(ctxt, &ctxt->pushTab[ctxt->nameNr - 1]);
11949
0
        nameNsPop(ctxt);
11950
0
    }
11951
0
#ifdef LIBXML_SAX1_ENABLED
11952
0
      else
11953
0
        xmlParseEndTag1(ctxt, 0);
11954
0
#endif /* LIBXML_SAX1_ENABLED */
11955
0
                if (ctxt->instate == XML_PARSER_EOF)
11956
0
                    goto done;
11957
0
    if (ctxt->nameNr == 0) {
11958
0
        ctxt->instate = XML_PARSER_EPILOG;
11959
0
    } else {
11960
0
        ctxt->instate = XML_PARSER_CONTENT;
11961
0
    }
11962
0
    break;
11963
0
            case XML_PARSER_CDATA_SECTION: {
11964
          /*
11965
     * The Push mode need to have the SAX callback for
11966
     * cdataBlock merge back contiguous callbacks.
11967
     */
11968
0
    const xmlChar *term;
11969
11970
0
                if (terminate) {
11971
                    /*
11972
                     * Don't call xmlParseLookupString. If 'terminate'
11973
                     * is set, checkIndex is invalid.
11974
                     */
11975
0
                    term = BAD_CAST strstr((const char *) ctxt->input->cur,
11976
0
                                           "]]>");
11977
0
                } else {
11978
0
        term = xmlParseLookupString(ctxt, 0, "]]>", 3);
11979
0
                }
11980
11981
0
    if (term == NULL) {
11982
0
        int tmp, size;
11983
11984
0
                    if (terminate) {
11985
                        /* Unfinished CDATA section */
11986
0
                        size = ctxt->input->end - ctxt->input->cur;
11987
0
                    } else {
11988
0
                        if (avail < XML_PARSER_BIG_BUFFER_SIZE + 2)
11989
0
                            goto done;
11990
0
                        ctxt->checkIndex = 0;
11991
                        /* XXX: Why don't we pass the full buffer? */
11992
0
                        size = XML_PARSER_BIG_BUFFER_SIZE;
11993
0
                    }
11994
0
                    tmp = xmlCheckCdataPush(ctxt->input->cur, size, 0);
11995
0
                    if (tmp <= 0) {
11996
0
                        tmp = -tmp;
11997
0
                        ctxt->input->cur += tmp;
11998
0
                        goto encoding_error;
11999
0
                    }
12000
0
                    if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
12001
0
                        if (ctxt->sax->cdataBlock != NULL)
12002
0
                            ctxt->sax->cdataBlock(ctxt->userData,
12003
0
                                                  ctxt->input->cur, tmp);
12004
0
                        else if (ctxt->sax->characters != NULL)
12005
0
                            ctxt->sax->characters(ctxt->userData,
12006
0
                                                  ctxt->input->cur, tmp);
12007
0
                    }
12008
0
                    if (ctxt->instate == XML_PARSER_EOF)
12009
0
                        goto done;
12010
0
                    SKIPL(tmp);
12011
0
    } else {
12012
0
                    int base = term - CUR_PTR;
12013
0
        int tmp;
12014
12015
0
        tmp = xmlCheckCdataPush(ctxt->input->cur, base, 1);
12016
0
        if ((tmp < 0) || (tmp != base)) {
12017
0
      tmp = -tmp;
12018
0
      ctxt->input->cur += tmp;
12019
0
      goto encoding_error;
12020
0
        }
12021
0
        if ((ctxt->sax != NULL) && (base == 0) &&
12022
0
            (ctxt->sax->cdataBlock != NULL) &&
12023
0
            (!ctxt->disableSAX)) {
12024
      /*
12025
       * Special case to provide identical behaviour
12026
       * between pull and push parsers on enpty CDATA
12027
       * sections
12028
       */
12029
0
       if ((ctxt->input->cur - ctxt->input->base >= 9) &&
12030
0
           (!strncmp((const char *)&ctxt->input->cur[-9],
12031
0
                     "<![CDATA[", 9)))
12032
0
           ctxt->sax->cdataBlock(ctxt->userData,
12033
0
                                 BAD_CAST "", 0);
12034
0
        } else if ((ctxt->sax != NULL) && (base > 0) &&
12035
0
      (!ctxt->disableSAX)) {
12036
0
      if (ctxt->sax->cdataBlock != NULL)
12037
0
          ctxt->sax->cdataBlock(ctxt->userData,
12038
0
              ctxt->input->cur, base);
12039
0
      else if (ctxt->sax->characters != NULL)
12040
0
          ctxt->sax->characters(ctxt->userData,
12041
0
              ctxt->input->cur, base);
12042
0
        }
12043
0
        if (ctxt->instate == XML_PARSER_EOF)
12044
0
      goto done;
12045
0
        SKIPL(base + 3);
12046
0
        ctxt->instate = XML_PARSER_CONTENT;
12047
0
    }
12048
0
    break;
12049
0
      }
12050
0
            case XML_PARSER_MISC:
12051
0
            case XML_PARSER_PROLOG:
12052
0
            case XML_PARSER_EPILOG:
12053
0
    SKIP_BLANKS;
12054
0
                avail = ctxt->input->end - ctxt->input->cur;
12055
0
    if (avail < 1)
12056
0
        goto done;
12057
0
    if (ctxt->input->cur[0] == '<') {
12058
0
                    if ((!terminate) && (avail < 2))
12059
0
                        goto done;
12060
0
                    next = ctxt->input->cur[1];
12061
0
                    if (next == '?') {
12062
0
                        if ((!terminate) &&
12063
0
                            (!xmlParseLookupString(ctxt, 2, "?>", 2)))
12064
0
                            goto done;
12065
0
                        xmlParsePI(ctxt);
12066
0
                        if (ctxt->instate == XML_PARSER_EOF)
12067
0
                            goto done;
12068
0
                        break;
12069
0
                    } else if (next == '!') {
12070
0
                        if ((!terminate) && (avail < 3))
12071
0
                            goto done;
12072
12073
0
                        if (ctxt->input->cur[2] == '-') {
12074
0
                            if ((!terminate) && (avail < 4))
12075
0
                                goto done;
12076
0
                            if (ctxt->input->cur[3] == '-') {
12077
0
                                if ((!terminate) &&
12078
0
                                    (!xmlParseLookupString(ctxt, 4, "-->", 3)))
12079
0
                                    goto done;
12080
0
                                xmlParseComment(ctxt);
12081
0
                                if (ctxt->instate == XML_PARSER_EOF)
12082
0
                                    goto done;
12083
0
                                break;
12084
0
                            }
12085
0
                        } else if (ctxt->instate == XML_PARSER_MISC) {
12086
0
                            if ((!terminate) && (avail < 9))
12087
0
                                goto done;
12088
0
                            if ((ctxt->input->cur[2] == 'D') &&
12089
0
                                (ctxt->input->cur[3] == 'O') &&
12090
0
                                (ctxt->input->cur[4] == 'C') &&
12091
0
                                (ctxt->input->cur[5] == 'T') &&
12092
0
                                (ctxt->input->cur[6] == 'Y') &&
12093
0
                                (ctxt->input->cur[7] == 'P') &&
12094
0
                                (ctxt->input->cur[8] == 'E')) {
12095
0
                                if ((!terminate) && (!xmlParseLookupGt(ctxt)))
12096
0
                                    goto done;
12097
0
                                ctxt->inSubset = 1;
12098
0
                                xmlParseDocTypeDecl(ctxt);
12099
0
                                if (ctxt->instate == XML_PARSER_EOF)
12100
0
                                    goto done;
12101
0
                                if (RAW == '[') {
12102
0
                                    ctxt->instate = XML_PARSER_DTD;
12103
0
                                } else {
12104
                                    /*
12105
                                     * Create and update the external subset.
12106
                                     */
12107
0
                                    ctxt->inSubset = 2;
12108
0
                                    if ((ctxt->sax != NULL) &&
12109
0
                                        (!ctxt->disableSAX) &&
12110
0
                                        (ctxt->sax->externalSubset != NULL))
12111
0
                                        ctxt->sax->externalSubset(
12112
0
                                                ctxt->userData,
12113
0
                                                ctxt->intSubName,
12114
0
                                                ctxt->extSubSystem,
12115
0
                                                ctxt->extSubURI);
12116
0
                                    ctxt->inSubset = 0;
12117
0
                                    xmlCleanSpecialAttr(ctxt);
12118
0
                                    if (ctxt->instate == XML_PARSER_EOF)
12119
0
                                        goto done;
12120
0
                                    ctxt->instate = XML_PARSER_PROLOG;
12121
0
                                }
12122
0
                                break;
12123
0
                            }
12124
0
                        }
12125
0
                    }
12126
0
                }
12127
12128
0
                if (ctxt->instate == XML_PARSER_EPILOG) {
12129
0
                    if (ctxt->errNo == XML_ERR_OK)
12130
0
                        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
12131
0
        ctxt->instate = XML_PARSER_EOF;
12132
0
                    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
12133
0
                        ctxt->sax->endDocument(ctxt->userData);
12134
0
                } else {
12135
0
        ctxt->instate = XML_PARSER_START_TAG;
12136
0
    }
12137
0
    break;
12138
0
            case XML_PARSER_DTD: {
12139
0
                if ((!terminate) && (!xmlParseLookupInternalSubset(ctxt)))
12140
0
                    goto done;
12141
0
    xmlParseInternalSubset(ctxt);
12142
0
    if (ctxt->instate == XML_PARSER_EOF)
12143
0
        goto done;
12144
0
    ctxt->inSubset = 2;
12145
0
    if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
12146
0
        (ctxt->sax->externalSubset != NULL))
12147
0
        ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
12148
0
          ctxt->extSubSystem, ctxt->extSubURI);
12149
0
    ctxt->inSubset = 0;
12150
0
    xmlCleanSpecialAttr(ctxt);
12151
0
    if (ctxt->instate == XML_PARSER_EOF)
12152
0
        goto done;
12153
0
    ctxt->instate = XML_PARSER_PROLOG;
12154
0
                break;
12155
0
      }
12156
0
            default:
12157
0
    xmlGenericError(xmlGenericErrorContext,
12158
0
      "PP: internal error\n");
12159
0
    ctxt->instate = XML_PARSER_EOF;
12160
0
    break;
12161
0
  }
12162
0
    }
12163
0
done:
12164
0
    return(ret);
12165
0
encoding_error:
12166
0
    if (ctxt->input->end - ctxt->input->cur < 4) {
12167
0
  __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
12168
0
         "Input is not proper UTF-8, indicate encoding !\n",
12169
0
         NULL, NULL);
12170
0
    } else {
12171
0
        char buffer[150];
12172
12173
0
  snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
12174
0
      ctxt->input->cur[0], ctxt->input->cur[1],
12175
0
      ctxt->input->cur[2], ctxt->input->cur[3]);
12176
0
  __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
12177
0
         "Input is not proper UTF-8, indicate encoding !\n%s",
12178
0
         BAD_CAST buffer, NULL);
12179
0
    }
12180
0
    return(0);
12181
0
}
12182
12183
/**
12184
 * xmlParseChunk:
12185
 * @ctxt:  an XML parser context
12186
 * @chunk:  an char array
12187
 * @size:  the size in byte of the chunk
12188
 * @terminate:  last chunk indicator
12189
 *
12190
 * Parse a Chunk of memory
12191
 *
12192
 * Returns zero if no error, the xmlParserErrors otherwise.
12193
 */
12194
int
12195
xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
12196
0
              int terminate) {
12197
0
    int end_in_lf = 0;
12198
12199
0
    if (ctxt == NULL)
12200
0
        return(XML_ERR_INTERNAL_ERROR);
12201
0
    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
12202
0
        return(ctxt->errNo);
12203
0
    if (ctxt->instate == XML_PARSER_EOF)
12204
0
        return(-1);
12205
0
    if (ctxt->input == NULL)
12206
0
        return(-1);
12207
12208
0
    ctxt->progressive = 1;
12209
0
    if (ctxt->instate == XML_PARSER_START)
12210
0
        xmlDetectSAX2(ctxt);
12211
0
    if ((size > 0) && (chunk != NULL) && (!terminate) &&
12212
0
        (chunk[size - 1] == '\r')) {
12213
0
  end_in_lf = 1;
12214
0
  size--;
12215
0
    }
12216
12217
0
    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
12218
0
        (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF))  {
12219
0
  size_t pos = ctxt->input->cur - ctxt->input->base;
12220
0
  int res;
12221
12222
0
  res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
12223
0
        xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos);
12224
0
  if (res < 0) {
12225
0
            xmlFatalErr(ctxt, ctxt->input->buf->error, NULL);
12226
0
      xmlHaltParser(ctxt);
12227
0
      return(ctxt->errNo);
12228
0
  }
12229
0
    }
12230
12231
0
    xmlParseTryOrFinish(ctxt, terminate);
12232
0
    if (ctxt->instate == XML_PARSER_EOF)
12233
0
        return(ctxt->errNo);
12234
12235
0
    if ((ctxt->input != NULL) &&
12236
0
         (((ctxt->input->end - ctxt->input->cur) > XML_MAX_LOOKUP_LIMIT) ||
12237
0
         ((ctxt->input->cur - ctxt->input->base) > XML_MAX_LOOKUP_LIMIT)) &&
12238
0
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
12239
0
        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
12240
0
        xmlHaltParser(ctxt);
12241
0
    }
12242
0
    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
12243
0
        return(ctxt->errNo);
12244
12245
0
    if ((end_in_lf == 1) && (ctxt->input != NULL) &&
12246
0
        (ctxt->input->buf != NULL)) {
12247
0
  size_t pos = ctxt->input->cur - ctxt->input->base;
12248
0
        int res;
12249
12250
0
  res = xmlParserInputBufferPush(ctxt->input->buf, 1, "\r");
12251
0
  xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos);
12252
0
        if (res < 0) {
12253
0
            xmlFatalErr(ctxt, ctxt->input->buf->error, NULL);
12254
0
            xmlHaltParser(ctxt);
12255
0
            return(ctxt->errNo);
12256
0
        }
12257
0
    }
12258
0
    if (terminate) {
12259
  /*
12260
   * Check for termination
12261
   */
12262
0
        if ((ctxt->instate != XML_PARSER_EOF) &&
12263
0
            (ctxt->instate != XML_PARSER_EPILOG)) {
12264
0
            if (ctxt->nameNr > 0) {
12265
0
                const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
12266
0
                int line = ctxt->pushTab[ctxt->nameNr - 1].line;
12267
0
                xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
12268
0
                        "Premature end of data in tag %s line %d\n",
12269
0
                        name, line, NULL);
12270
0
            } else if (ctxt->instate == XML_PARSER_START) {
12271
0
                xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
12272
0
            } else {
12273
0
                xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
12274
0
                               "Start tag expected, '<' not found\n");
12275
0
            }
12276
0
        } else if ((ctxt->input->buf != NULL) &&
12277
0
                   (ctxt->input->buf->encoder != NULL) &&
12278
0
                   (!xmlBufIsEmpty(ctxt->input->buf->raw))) {
12279
0
            xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
12280
0
                           "Truncated multi-byte sequence at EOF\n");
12281
0
        }
12282
0
  if (ctxt->instate != XML_PARSER_EOF) {
12283
0
      if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
12284
0
    ctxt->sax->endDocument(ctxt->userData);
12285
0
  }
12286
0
  ctxt->instate = XML_PARSER_EOF;
12287
0
    }
12288
0
    if (ctxt->wellFormed == 0)
12289
0
  return((xmlParserErrors) ctxt->errNo);
12290
0
    else
12291
0
        return(0);
12292
0
}
12293
12294
/************************************************************************
12295
 *                  *
12296
 *    I/O front end functions to the parser     *
12297
 *                  *
12298
 ************************************************************************/
12299
12300
/**
12301
 * xmlCreatePushParserCtxt:
12302
 * @sax:  a SAX handler
12303
 * @user_data:  The user data returned on SAX callbacks
12304
 * @chunk:  a pointer to an array of chars
12305
 * @size:  number of chars in the array
12306
 * @filename:  an optional file name or URI
12307
 *
12308
 * Create a parser context for using the XML parser in push mode.
12309
 * If @buffer and @size are non-NULL, the data is used to detect
12310
 * the encoding.  The remaining characters will be parsed so they
12311
 * don't need to be fed in again through xmlParseChunk.
12312
 * To allow content encoding detection, @size should be >= 4
12313
 * The value of @filename is used for fetching external entities
12314
 * and error/warning reports.
12315
 *
12316
 * Returns the new parser context or NULL
12317
 */
12318
12319
xmlParserCtxtPtr
12320
xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
12321
0
                        const char *chunk, int size, const char *filename) {
12322
0
    xmlParserCtxtPtr ctxt;
12323
0
    xmlParserInputPtr inputStream;
12324
0
    xmlParserInputBufferPtr buf;
12325
12326
0
    buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE);
12327
0
    if (buf == NULL) return(NULL);
12328
12329
0
    ctxt = xmlNewSAXParserCtxt(sax, user_data);
12330
0
    if (ctxt == NULL) {
12331
0
        xmlErrMemory(NULL, "creating parser: out of memory\n");
12332
0
  xmlFreeParserInputBuffer(buf);
12333
0
  return(NULL);
12334
0
    }
12335
0
    ctxt->dictNames = 1;
12336
0
    if (filename == NULL) {
12337
0
  ctxt->directory = NULL;
12338
0
    } else {
12339
0
        ctxt->directory = xmlParserGetDirectory(filename);
12340
0
    }
12341
12342
0
    inputStream = xmlNewInputStream(ctxt);
12343
0
    if (inputStream == NULL) {
12344
0
  xmlFreeParserCtxt(ctxt);
12345
0
  xmlFreeParserInputBuffer(buf);
12346
0
  return(NULL);
12347
0
    }
12348
12349
0
    if (filename == NULL)
12350
0
  inputStream->filename = NULL;
12351
0
    else {
12352
0
  inputStream->filename = (char *)
12353
0
      xmlCanonicPath((const xmlChar *) filename);
12354
0
  if (inputStream->filename == NULL) {
12355
0
            xmlFreeInputStream(inputStream);
12356
0
      xmlFreeParserCtxt(ctxt);
12357
0
      xmlFreeParserInputBuffer(buf);
12358
0
      return(NULL);
12359
0
  }
12360
0
    }
12361
0
    inputStream->buf = buf;
12362
0
    xmlBufResetInput(inputStream->buf->buffer, inputStream);
12363
0
    inputPush(ctxt, inputStream);
12364
12365
0
    if ((size != 0) && (chunk != NULL) &&
12366
0
        (ctxt->input != NULL) && (ctxt->input->buf != NULL)) {
12367
0
  size_t pos = ctxt->input->cur - ctxt->input->base;
12368
0
        int res;
12369
12370
0
  res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
12371
0
        xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos);
12372
0
        if (res < 0) {
12373
0
            xmlFatalErr(ctxt, ctxt->input->buf->error, NULL);
12374
0
            xmlHaltParser(ctxt);
12375
0
        }
12376
0
    }
12377
12378
0
    return(ctxt);
12379
0
}
12380
#endif /* LIBXML_PUSH_ENABLED */
12381
12382
/**
12383
 * xmlStopParser:
12384
 * @ctxt:  an XML parser context
12385
 *
12386
 * Blocks further parser processing
12387
 */
12388
void
12389
0
xmlStopParser(xmlParserCtxtPtr ctxt) {
12390
0
    if (ctxt == NULL)
12391
0
        return;
12392
0
    xmlHaltParser(ctxt);
12393
0
    ctxt->errNo = XML_ERR_USER_STOP;
12394
0
}
12395
12396
/**
12397
 * xmlCreateIOParserCtxt:
12398
 * @sax:  a SAX handler
12399
 * @user_data:  The user data returned on SAX callbacks
12400
 * @ioread:  an I/O read function
12401
 * @ioclose:  an I/O close function
12402
 * @ioctx:  an I/O handler
12403
 * @enc:  the charset encoding if known
12404
 *
12405
 * Create a parser context for using the XML parser with an existing
12406
 * I/O stream
12407
 *
12408
 * Returns the new parser context or NULL
12409
 */
12410
xmlParserCtxtPtr
12411
xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
12412
  xmlInputReadCallback   ioread, xmlInputCloseCallback  ioclose,
12413
0
  void *ioctx, xmlCharEncoding enc) {
12414
0
    xmlParserCtxtPtr ctxt;
12415
0
    xmlParserInputPtr inputStream;
12416
0
    xmlParserInputBufferPtr buf;
12417
12418
0
    if (ioread == NULL) return(NULL);
12419
12420
0
    buf = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, enc);
12421
0
    if (buf == NULL) {
12422
0
        if (ioclose != NULL)
12423
0
            ioclose(ioctx);
12424
0
        return (NULL);
12425
0
    }
12426
12427
0
    ctxt = xmlNewSAXParserCtxt(sax, user_data);
12428
0
    if (ctxt == NULL) {
12429
0
  xmlFreeParserInputBuffer(buf);
12430
0
  return(NULL);
12431
0
    }
12432
12433
0
    inputStream = xmlNewIOInputStream(ctxt, buf, enc);
12434
0
    if (inputStream == NULL) {
12435
0
  xmlFreeParserCtxt(ctxt);
12436
0
  return(NULL);
12437
0
    }
12438
0
    inputPush(ctxt, inputStream);
12439
12440
0
    return(ctxt);
12441
0
}
12442
12443
#ifdef LIBXML_VALID_ENABLED
12444
/************************************************************************
12445
 *                  *
12446
 *    Front ends when parsing a DTD       *
12447
 *                  *
12448
 ************************************************************************/
12449
12450
/**
12451
 * xmlIOParseDTD:
12452
 * @sax:  the SAX handler block or NULL
12453
 * @input:  an Input Buffer
12454
 * @enc:  the charset encoding if known
12455
 *
12456
 * Load and parse a DTD
12457
 *
12458
 * Returns the resulting xmlDtdPtr or NULL in case of error.
12459
 * @input will be freed by the function in any case.
12460
 */
12461
12462
xmlDtdPtr
12463
xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
12464
0
        xmlCharEncoding enc) {
12465
0
    xmlDtdPtr ret = NULL;
12466
0
    xmlParserCtxtPtr ctxt;
12467
0
    xmlParserInputPtr pinput = NULL;
12468
12469
0
    if (input == NULL)
12470
0
  return(NULL);
12471
12472
0
    ctxt = xmlNewSAXParserCtxt(sax, NULL);
12473
0
    if (ctxt == NULL) {
12474
0
        xmlFreeParserInputBuffer(input);
12475
0
  return(NULL);
12476
0
    }
12477
12478
    /* We are loading a DTD */
12479
0
    ctxt->options |= XML_PARSE_DTDLOAD;
12480
12481
0
    xmlDetectSAX2(ctxt);
12482
12483
    /*
12484
     * generate a parser input from the I/O handler
12485
     */
12486
12487
0
    pinput = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
12488
0
    if (pinput == NULL) {
12489
0
        xmlFreeParserInputBuffer(input);
12490
0
  xmlFreeParserCtxt(ctxt);
12491
0
  return(NULL);
12492
0
    }
12493
12494
    /*
12495
     * plug some encoding conversion routines here.
12496
     */
12497
0
    if (xmlPushInput(ctxt, pinput) < 0) {
12498
0
  xmlFreeParserCtxt(ctxt);
12499
0
  return(NULL);
12500
0
    }
12501
0
    if (enc != XML_CHAR_ENCODING_NONE) {
12502
0
        xmlSwitchEncoding(ctxt, enc);
12503
0
    }
12504
12505
    /*
12506
     * let's parse that entity knowing it's an external subset.
12507
     */
12508
0
    ctxt->inSubset = 2;
12509
0
    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
12510
0
    if (ctxt->myDoc == NULL) {
12511
0
  xmlErrMemory(ctxt, "New Doc failed");
12512
0
  return(NULL);
12513
0
    }
12514
0
    ctxt->myDoc->properties = XML_DOC_INTERNAL;
12515
0
    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
12516
0
                                 BAD_CAST "none", BAD_CAST "none");
12517
12518
0
    xmlDetectEncoding(ctxt);
12519
12520
0
    xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none");
12521
12522
0
    if (ctxt->myDoc != NULL) {
12523
0
  if (ctxt->wellFormed) {
12524
0
      ret = ctxt->myDoc->extSubset;
12525
0
      ctxt->myDoc->extSubset = NULL;
12526
0
      if (ret != NULL) {
12527
0
    xmlNodePtr tmp;
12528
12529
0
    ret->doc = NULL;
12530
0
    tmp = ret->children;
12531
0
    while (tmp != NULL) {
12532
0
        tmp->doc = NULL;
12533
0
        tmp = tmp->next;
12534
0
    }
12535
0
      }
12536
0
  } else {
12537
0
      ret = NULL;
12538
0
  }
12539
0
        xmlFreeDoc(ctxt->myDoc);
12540
0
        ctxt->myDoc = NULL;
12541
0
    }
12542
0
    xmlFreeParserCtxt(ctxt);
12543
12544
0
    return(ret);
12545
0
}
12546
12547
/**
12548
 * xmlSAXParseDTD:
12549
 * @sax:  the SAX handler block
12550
 * @ExternalID:  a NAME* containing the External ID of the DTD
12551
 * @SystemID:  a NAME* containing the URL to the DTD
12552
 *
12553
 * DEPRECATED: Don't use.
12554
 *
12555
 * Load and parse an external subset.
12556
 *
12557
 * Returns the resulting xmlDtdPtr or NULL in case of error.
12558
 */
12559
12560
xmlDtdPtr
12561
xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
12562
0
                          const xmlChar *SystemID) {
12563
0
    xmlDtdPtr ret = NULL;
12564
0
    xmlParserCtxtPtr ctxt;
12565
0
    xmlParserInputPtr input = NULL;
12566
0
    xmlChar* systemIdCanonic;
12567
12568
0
    if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
12569
12570
0
    ctxt = xmlNewSAXParserCtxt(sax, NULL);
12571
0
    if (ctxt == NULL) {
12572
0
  return(NULL);
12573
0
    }
12574
12575
    /* We are loading a DTD */
12576
0
    ctxt->options |= XML_PARSE_DTDLOAD;
12577
12578
    /*
12579
     * Canonicalise the system ID
12580
     */
12581
0
    systemIdCanonic = xmlCanonicPath(SystemID);
12582
0
    if ((SystemID != NULL) && (systemIdCanonic == NULL)) {
12583
0
  xmlFreeParserCtxt(ctxt);
12584
0
  return(NULL);
12585
0
    }
12586
12587
    /*
12588
     * Ask the Entity resolver to load the damn thing
12589
     */
12590
12591
0
    if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
12592
0
  input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
12593
0
                                   systemIdCanonic);
12594
0
    if (input == NULL) {
12595
0
  xmlFreeParserCtxt(ctxt);
12596
0
  if (systemIdCanonic != NULL)
12597
0
      xmlFree(systemIdCanonic);
12598
0
  return(NULL);
12599
0
    }
12600
12601
    /*
12602
     * plug some encoding conversion routines here.
12603
     */
12604
0
    if (xmlPushInput(ctxt, input) < 0) {
12605
0
  xmlFreeParserCtxt(ctxt);
12606
0
  if (systemIdCanonic != NULL)
12607
0
      xmlFree(systemIdCanonic);
12608
0
  return(NULL);
12609
0
    }
12610
12611
0
    xmlDetectEncoding(ctxt);
12612
12613
0
    if (input->filename == NULL)
12614
0
  input->filename = (char *) systemIdCanonic;
12615
0
    else
12616
0
  xmlFree(systemIdCanonic);
12617
12618
    /*
12619
     * let's parse that entity knowing it's an external subset.
12620
     */
12621
0
    ctxt->inSubset = 2;
12622
0
    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
12623
0
    if (ctxt->myDoc == NULL) {
12624
0
  xmlErrMemory(ctxt, "New Doc failed");
12625
0
  xmlFreeParserCtxt(ctxt);
12626
0
  return(NULL);
12627
0
    }
12628
0
    ctxt->myDoc->properties = XML_DOC_INTERNAL;
12629
0
    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
12630
0
                                 ExternalID, SystemID);
12631
0
    xmlParseExternalSubset(ctxt, ExternalID, SystemID);
12632
12633
0
    if (ctxt->myDoc != NULL) {
12634
0
  if (ctxt->wellFormed) {
12635
0
      ret = ctxt->myDoc->extSubset;
12636
0
      ctxt->myDoc->extSubset = NULL;
12637
0
      if (ret != NULL) {
12638
0
    xmlNodePtr tmp;
12639
12640
0
    ret->doc = NULL;
12641
0
    tmp = ret->children;
12642
0
    while (tmp != NULL) {
12643
0
        tmp->doc = NULL;
12644
0
        tmp = tmp->next;
12645
0
    }
12646
0
      }
12647
0
  } else {
12648
0
      ret = NULL;
12649
0
  }
12650
0
        xmlFreeDoc(ctxt->myDoc);
12651
0
        ctxt->myDoc = NULL;
12652
0
    }
12653
0
    xmlFreeParserCtxt(ctxt);
12654
12655
0
    return(ret);
12656
0
}
12657
12658
12659
/**
12660
 * xmlParseDTD:
12661
 * @ExternalID:  a NAME* containing the External ID of the DTD
12662
 * @SystemID:  a NAME* containing the URL to the DTD
12663
 *
12664
 * Load and parse an external subset.
12665
 *
12666
 * Returns the resulting xmlDtdPtr or NULL in case of error.
12667
 */
12668
12669
xmlDtdPtr
12670
0
xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
12671
0
    return(xmlSAXParseDTD(NULL, ExternalID, SystemID));
12672
0
}
12673
#endif /* LIBXML_VALID_ENABLED */
12674
12675
/************************************************************************
12676
 *                  *
12677
 *    Front ends when parsing an Entity     *
12678
 *                  *
12679
 ************************************************************************/
12680
12681
/**
12682
 * xmlParseCtxtExternalEntity:
12683
 * @ctx:  the existing parsing context
12684
 * @URL:  the URL for the entity to load
12685
 * @ID:  the System ID for the entity to load
12686
 * @lst:  the return value for the set of parsed nodes
12687
 *
12688
 * Parse an external general entity within an existing parsing context
12689
 * An external general parsed entity is well-formed if it matches the
12690
 * production labeled extParsedEnt.
12691
 *
12692
 * [78] extParsedEnt ::= TextDecl? content
12693
 *
12694
 * Returns 0 if the entity is well formed, -1 in case of args problem and
12695
 *    the parser error code otherwise
12696
 */
12697
12698
int
12699
xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
12700
0
                 const xmlChar *ID, xmlNodePtr *lst) {
12701
0
    void *userData;
12702
12703
0
    if (ctx == NULL) return(-1);
12704
    /*
12705
     * If the user provided their own SAX callbacks, then reuse the
12706
     * userData callback field, otherwise the expected setup in a
12707
     * DOM builder is to have userData == ctxt
12708
     */
12709
0
    if (ctx->userData == ctx)
12710
0
        userData = NULL;
12711
0
    else
12712
0
        userData = ctx->userData;
12713
0
    return xmlParseExternalEntityPrivate(ctx->myDoc, ctx, ctx->sax,
12714
0
                                         userData, ctx->depth + 1,
12715
0
                                         URL, ID, lst);
12716
0
}
12717
12718
/**
12719
 * xmlParseExternalEntityPrivate:
12720
 * @doc:  the document the chunk pertains to
12721
 * @oldctxt:  the previous parser context if available
12722
 * @sax:  the SAX handler block (possibly NULL)
12723
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
12724
 * @depth:  Used for loop detection, use 0
12725
 * @URL:  the URL for the entity to load
12726
 * @ID:  the System ID for the entity to load
12727
 * @list:  the return value for the set of parsed nodes
12728
 *
12729
 * Private version of xmlParseExternalEntity()
12730
 *
12731
 * Returns 0 if the entity is well formed, -1 in case of args problem and
12732
 *    the parser error code otherwise
12733
 */
12734
12735
static xmlParserErrors
12736
xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
12737
                xmlSAXHandlerPtr sax,
12738
          void *user_data, int depth, const xmlChar *URL,
12739
0
          const xmlChar *ID, xmlNodePtr *list) {
12740
0
    xmlParserCtxtPtr ctxt;
12741
0
    xmlDocPtr newDoc;
12742
0
    xmlNodePtr newRoot;
12743
0
    xmlParserErrors ret = XML_ERR_OK;
12744
12745
0
    if (((depth > 40) &&
12746
0
  ((oldctxt == NULL) || (oldctxt->options & XML_PARSE_HUGE) == 0)) ||
12747
0
  (depth > 100)) {
12748
0
  xmlFatalErrMsg(oldctxt, XML_ERR_ENTITY_LOOP,
12749
0
                       "Maximum entity nesting depth exceeded");
12750
0
        return(XML_ERR_ENTITY_LOOP);
12751
0
    }
12752
12753
0
    if (list != NULL)
12754
0
        *list = NULL;
12755
0
    if ((URL == NULL) && (ID == NULL))
12756
0
  return(XML_ERR_INTERNAL_ERROR);
12757
0
    if (doc == NULL)
12758
0
  return(XML_ERR_INTERNAL_ERROR);
12759
12760
0
    ctxt = xmlCreateEntityParserCtxtInternal(sax, user_data, URL, ID, NULL,
12761
0
                                             oldctxt);
12762
0
    if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
12763
0
    if (oldctxt != NULL) {
12764
0
        ctxt->nbErrors = oldctxt->nbErrors;
12765
0
        ctxt->nbWarnings = oldctxt->nbWarnings;
12766
0
    }
12767
0
    xmlDetectSAX2(ctxt);
12768
12769
0
    newDoc = xmlNewDoc(BAD_CAST "1.0");
12770
0
    if (newDoc == NULL) {
12771
0
  xmlFreeParserCtxt(ctxt);
12772
0
  return(XML_ERR_INTERNAL_ERROR);
12773
0
    }
12774
0
    newDoc->properties = XML_DOC_INTERNAL;
12775
0
    if (doc) {
12776
0
        newDoc->intSubset = doc->intSubset;
12777
0
        newDoc->extSubset = doc->extSubset;
12778
0
        if (doc->dict) {
12779
0
            newDoc->dict = doc->dict;
12780
0
            xmlDictReference(newDoc->dict);
12781
0
        }
12782
0
        if (doc->URL != NULL) {
12783
0
            newDoc->URL = xmlStrdup(doc->URL);
12784
0
        }
12785
0
    }
12786
0
    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
12787
0
    if (newRoot == NULL) {
12788
0
  if (sax != NULL)
12789
0
  xmlFreeParserCtxt(ctxt);
12790
0
  newDoc->intSubset = NULL;
12791
0
  newDoc->extSubset = NULL;
12792
0
        xmlFreeDoc(newDoc);
12793
0
  return(XML_ERR_INTERNAL_ERROR);
12794
0
    }
12795
0
    xmlAddChild((xmlNodePtr) newDoc, newRoot);
12796
0
    nodePush(ctxt, newDoc->children);
12797
0
    if (doc == NULL) {
12798
0
        ctxt->myDoc = newDoc;
12799
0
    } else {
12800
0
        ctxt->myDoc = doc;
12801
0
        newRoot->doc = doc;
12802
0
    }
12803
12804
0
    xmlDetectEncoding(ctxt);
12805
12806
    /*
12807
     * Parse a possible text declaration first
12808
     */
12809
0
    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
12810
0
  xmlParseTextDecl(ctxt);
12811
        /*
12812
         * An XML-1.0 document can't reference an entity not XML-1.0
12813
         */
12814
0
        if ((xmlStrEqual(oldctxt->version, BAD_CAST "1.0")) &&
12815
0
            (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) {
12816
0
            xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH,
12817
0
                           "Version mismatch between document and entity\n");
12818
0
        }
12819
0
    }
12820
12821
0
    ctxt->instate = XML_PARSER_CONTENT;
12822
0
    ctxt->depth = depth;
12823
0
    if (oldctxt != NULL) {
12824
0
  ctxt->_private = oldctxt->_private;
12825
0
  ctxt->loadsubset = oldctxt->loadsubset;
12826
0
  ctxt->validate = oldctxt->validate;
12827
0
  ctxt->valid = oldctxt->valid;
12828
0
  ctxt->replaceEntities = oldctxt->replaceEntities;
12829
0
        if (oldctxt->validate) {
12830
0
            ctxt->vctxt.error = oldctxt->vctxt.error;
12831
0
            ctxt->vctxt.warning = oldctxt->vctxt.warning;
12832
0
            ctxt->vctxt.userData = oldctxt->vctxt.userData;
12833
0
            ctxt->vctxt.flags = oldctxt->vctxt.flags;
12834
0
        }
12835
0
  ctxt->external = oldctxt->external;
12836
0
        if (ctxt->dict) xmlDictFree(ctxt->dict);
12837
0
        ctxt->dict = oldctxt->dict;
12838
0
        ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
12839
0
        ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
12840
0
        ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
12841
0
        ctxt->dictNames = oldctxt->dictNames;
12842
0
        ctxt->attsDefault = oldctxt->attsDefault;
12843
0
        ctxt->attsSpecial = oldctxt->attsSpecial;
12844
0
        ctxt->linenumbers = oldctxt->linenumbers;
12845
0
  ctxt->record_info = oldctxt->record_info;
12846
0
  ctxt->node_seq.maximum = oldctxt->node_seq.maximum;
12847
0
  ctxt->node_seq.length = oldctxt->node_seq.length;
12848
0
  ctxt->node_seq.buffer = oldctxt->node_seq.buffer;
12849
0
    } else {
12850
  /*
12851
   * Doing validity checking on chunk without context
12852
   * doesn't make sense
12853
   */
12854
0
  ctxt->_private = NULL;
12855
0
  ctxt->validate = 0;
12856
0
  ctxt->external = 2;
12857
0
  ctxt->loadsubset = 0;
12858
0
    }
12859
12860
0
    xmlParseContent(ctxt);
12861
12862
0
    if ((RAW == '<') && (NXT(1) == '/')) {
12863
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
12864
0
    } else if (RAW != 0) {
12865
0
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
12866
0
    }
12867
0
    if (ctxt->node != newDoc->children) {
12868
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
12869
0
    }
12870
12871
0
    if (!ctxt->wellFormed) {
12872
0
  ret = (xmlParserErrors)ctxt->errNo;
12873
0
        if (oldctxt != NULL) {
12874
0
            oldctxt->errNo = ctxt->errNo;
12875
0
            oldctxt->wellFormed = 0;
12876
0
            xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
12877
0
        }
12878
0
    } else {
12879
0
  if (list != NULL) {
12880
0
      xmlNodePtr cur;
12881
12882
      /*
12883
       * Return the newly created nodeset after unlinking it from
12884
       * they pseudo parent.
12885
       */
12886
0
      cur = newDoc->children->children;
12887
0
      *list = cur;
12888
0
      while (cur != NULL) {
12889
0
    cur->parent = NULL;
12890
0
    cur = cur->next;
12891
0
      }
12892
0
            newDoc->children->children = NULL;
12893
0
  }
12894
0
  ret = XML_ERR_OK;
12895
0
    }
12896
12897
    /*
12898
     * Also record the size of the entity parsed
12899
     */
12900
0
    if (ctxt->input != NULL && oldctxt != NULL) {
12901
0
        unsigned long consumed = ctxt->input->consumed;
12902
12903
0
        xmlSaturatedAddSizeT(&consumed, ctxt->input->cur - ctxt->input->base);
12904
12905
0
        xmlSaturatedAdd(&oldctxt->sizeentities, consumed);
12906
0
        xmlSaturatedAdd(&oldctxt->sizeentities, ctxt->sizeentities);
12907
12908
0
        xmlSaturatedAdd(&oldctxt->sizeentcopy, consumed);
12909
0
        xmlSaturatedAdd(&oldctxt->sizeentcopy, ctxt->sizeentcopy);
12910
0
    }
12911
12912
0
    if (oldctxt != NULL) {
12913
0
        ctxt->dict = NULL;
12914
0
        ctxt->attsDefault = NULL;
12915
0
        ctxt->attsSpecial = NULL;
12916
0
        oldctxt->nbErrors = ctxt->nbErrors;
12917
0
        oldctxt->nbWarnings = ctxt->nbWarnings;
12918
0
        oldctxt->validate = ctxt->validate;
12919
0
        oldctxt->valid = ctxt->valid;
12920
0
        oldctxt->node_seq.maximum = ctxt->node_seq.maximum;
12921
0
        oldctxt->node_seq.length = ctxt->node_seq.length;
12922
0
        oldctxt->node_seq.buffer = ctxt->node_seq.buffer;
12923
0
    }
12924
0
    ctxt->node_seq.maximum = 0;
12925
0
    ctxt->node_seq.length = 0;
12926
0
    ctxt->node_seq.buffer = NULL;
12927
0
    xmlFreeParserCtxt(ctxt);
12928
0
    newDoc->intSubset = NULL;
12929
0
    newDoc->extSubset = NULL;
12930
0
    xmlFreeDoc(newDoc);
12931
12932
0
    return(ret);
12933
0
}
12934
12935
#ifdef LIBXML_SAX1_ENABLED
12936
/**
12937
 * xmlParseExternalEntity:
12938
 * @doc:  the document the chunk pertains to
12939
 * @sax:  the SAX handler block (possibly NULL)
12940
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
12941
 * @depth:  Used for loop detection, use 0
12942
 * @URL:  the URL for the entity to load
12943
 * @ID:  the System ID for the entity to load
12944
 * @lst:  the return value for the set of parsed nodes
12945
 *
12946
 * Parse an external general entity
12947
 * An external general parsed entity is well-formed if it matches the
12948
 * production labeled extParsedEnt.
12949
 *
12950
 * [78] extParsedEnt ::= TextDecl? content
12951
 *
12952
 * Returns 0 if the entity is well formed, -1 in case of args problem and
12953
 *    the parser error code otherwise
12954
 */
12955
12956
int
12957
xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data,
12958
0
    int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *lst) {
12959
0
    return(xmlParseExternalEntityPrivate(doc, NULL, sax, user_data, depth, URL,
12960
0
                           ID, lst));
12961
0
}
12962
12963
/**
12964
 * xmlParseBalancedChunkMemory:
12965
 * @doc:  the document the chunk pertains to (must not be NULL)
12966
 * @sax:  the SAX handler block (possibly NULL)
12967
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
12968
 * @depth:  Used for loop detection, use 0
12969
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
12970
 * @lst:  the return value for the set of parsed nodes
12971
 *
12972
 * Parse a well-balanced chunk of an XML document
12973
 * called by the parser
12974
 * The allowed sequence for the Well Balanced Chunk is the one defined by
12975
 * the content production in the XML grammar:
12976
 *
12977
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
12978
 *
12979
 * Returns 0 if the chunk is well balanced, -1 in case of args problem and
12980
 *    the parser error code otherwise
12981
 */
12982
12983
int
12984
xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax,
12985
0
     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst) {
12986
0
    return xmlParseBalancedChunkMemoryRecover( doc, sax, user_data,
12987
0
                                                depth, string, lst, 0 );
12988
0
}
12989
#endif /* LIBXML_SAX1_ENABLED */
12990
12991
/**
12992
 * xmlParseBalancedChunkMemoryInternal:
12993
 * @oldctxt:  the existing parsing context
12994
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
12995
 * @user_data:  the user data field for the parser context
12996
 * @lst:  the return value for the set of parsed nodes
12997
 *
12998
 *
12999
 * Parse a well-balanced chunk of an XML document
13000
 * called by the parser
13001
 * The allowed sequence for the Well Balanced Chunk is the one defined by
13002
 * the content production in the XML grammar:
13003
 *
13004
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13005
 *
13006
 * Returns XML_ERR_OK if the chunk is well balanced, and the parser
13007
 * error code otherwise
13008
 *
13009
 * In case recover is set to 1, the nodelist will not be empty even if
13010
 * the parsed chunk is not well balanced.
13011
 */
13012
static xmlParserErrors
13013
xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
13014
0
  const xmlChar *string, void *user_data, xmlNodePtr *lst) {
13015
0
    xmlParserCtxtPtr ctxt;
13016
0
    xmlDocPtr newDoc = NULL;
13017
0
    xmlNodePtr newRoot;
13018
0
    xmlSAXHandlerPtr oldsax = NULL;
13019
0
    xmlNodePtr content = NULL;
13020
0
    xmlNodePtr last = NULL;
13021
0
    xmlParserErrors ret = XML_ERR_OK;
13022
0
    xmlHashedString hprefix, huri;
13023
0
    unsigned i;
13024
13025
0
    if (((oldctxt->depth > 40) && ((oldctxt->options & XML_PARSE_HUGE) == 0)) ||
13026
0
        (oldctxt->depth >  100)) {
13027
0
  xmlFatalErrMsg(oldctxt, XML_ERR_ENTITY_LOOP,
13028
0
                       "Maximum entity nesting depth exceeded");
13029
0
  return(XML_ERR_ENTITY_LOOP);
13030
0
    }
13031
13032
13033
0
    if (lst != NULL)
13034
0
        *lst = NULL;
13035
0
    if (string == NULL)
13036
0
        return(XML_ERR_INTERNAL_ERROR);
13037
13038
0
    ctxt = xmlCreateDocParserCtxt(string);
13039
0
    if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
13040
0
    ctxt->nbErrors = oldctxt->nbErrors;
13041
0
    ctxt->nbWarnings = oldctxt->nbWarnings;
13042
0
    if (user_data != NULL)
13043
0
  ctxt->userData = user_data;
13044
0
    else
13045
0
  ctxt->userData = ctxt;
13046
0
    if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
13047
0
    ctxt->dict = oldctxt->dict;
13048
0
    ctxt->input_id = oldctxt->input_id;
13049
0
    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
13050
0
    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
13051
0
    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
13052
13053
    /*
13054
     * Propagate namespaces down the entity
13055
     *
13056
     * Making entities and namespaces work correctly requires additional
13057
     * changes, see xmlParseReference.
13058
     */
13059
13060
    /* Default namespace */
13061
0
    hprefix.name = NULL;
13062
0
    hprefix.hashValue = 0;
13063
0
    huri.name = xmlParserNsLookupUri(oldctxt, &hprefix);
13064
0
    huri.hashValue = 0;
13065
0
    if (huri.name != NULL)
13066
0
        xmlParserNsPush(ctxt, NULL, &huri, NULL, 0);
13067
13068
0
    for (i = 0; i < oldctxt->nsdb->hashSize; i++) {
13069
0
        xmlParserNsBucket *bucket = &oldctxt->nsdb->hash[i];
13070
0
        const xmlChar **ns;
13071
0
        xmlParserNsExtra *extra;
13072
0
        unsigned nsIndex;
13073
13074
0
        if ((bucket->hashValue != 0) &&
13075
0
            (bucket->index != INT_MAX)) {
13076
0
            nsIndex = bucket->index;
13077
0
            ns = &oldctxt->nsTab[nsIndex * 2];
13078
0
            extra = &oldctxt->nsdb->extra[nsIndex];
13079
13080
0
            hprefix.name = ns[0];
13081
0
            hprefix.hashValue = bucket->hashValue;
13082
0
            huri.name = ns[1];
13083
0
            huri.hashValue = extra->uriHashValue;
13084
            /*
13085
             * Don't copy SAX data to avoid a use-after-free with XML reader.
13086
             * This matches the pre-2.12 behavior.
13087
             */
13088
0
            xmlParserNsPush(ctxt, &hprefix, &huri, NULL, 0);
13089
0
        }
13090
0
    }
13091
13092
0
    oldsax = ctxt->sax;
13093
0
    ctxt->sax = oldctxt->sax;
13094
0
    xmlDetectSAX2(ctxt);
13095
0
    ctxt->replaceEntities = oldctxt->replaceEntities;
13096
0
    ctxt->options = oldctxt->options;
13097
13098
0
    ctxt->_private = oldctxt->_private;
13099
0
    if (oldctxt->myDoc == NULL) {
13100
0
  newDoc = xmlNewDoc(BAD_CAST "1.0");
13101
0
  if (newDoc == NULL) {
13102
0
            ret = XML_ERR_INTERNAL_ERROR;
13103
0
            goto error;
13104
0
  }
13105
0
  newDoc->properties = XML_DOC_INTERNAL;
13106
0
  newDoc->dict = ctxt->dict;
13107
0
  xmlDictReference(newDoc->dict);
13108
0
  ctxt->myDoc = newDoc;
13109
0
    } else {
13110
0
  ctxt->myDoc = oldctxt->myDoc;
13111
0
        content = ctxt->myDoc->children;
13112
0
  last = ctxt->myDoc->last;
13113
0
    }
13114
0
    newRoot = xmlNewDocNode(ctxt->myDoc, NULL, BAD_CAST "pseudoroot", NULL);
13115
0
    if (newRoot == NULL) {
13116
0
        ret = XML_ERR_INTERNAL_ERROR;
13117
0
        goto error;
13118
0
    }
13119
0
    ctxt->myDoc->children = NULL;
13120
0
    ctxt->myDoc->last = NULL;
13121
0
    xmlAddChild((xmlNodePtr) ctxt->myDoc, newRoot);
13122
0
    nodePush(ctxt, ctxt->myDoc->children);
13123
0
    ctxt->instate = XML_PARSER_CONTENT;
13124
0
    ctxt->depth = oldctxt->depth;
13125
13126
0
    ctxt->validate = 0;
13127
0
    ctxt->loadsubset = oldctxt->loadsubset;
13128
0
    if ((oldctxt->validate) || (oldctxt->replaceEntities != 0)) {
13129
  /*
13130
   * ID/IDREF registration will be done in xmlValidateElement below
13131
   */
13132
0
  ctxt->loadsubset |= XML_SKIP_IDS;
13133
0
    }
13134
0
    ctxt->dictNames = oldctxt->dictNames;
13135
0
    ctxt->attsDefault = oldctxt->attsDefault;
13136
0
    ctxt->attsSpecial = oldctxt->attsSpecial;
13137
13138
0
    xmlParseContent(ctxt);
13139
0
    if ((RAW == '<') && (NXT(1) == '/')) {
13140
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13141
0
    } else if (RAW != 0) {
13142
0
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13143
0
    }
13144
0
    if (ctxt->node != ctxt->myDoc->children) {
13145
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13146
0
    }
13147
13148
0
    if (!ctxt->wellFormed) {
13149
0
  ret = (xmlParserErrors)ctxt->errNo;
13150
0
        oldctxt->errNo = ctxt->errNo;
13151
0
        oldctxt->wellFormed = 0;
13152
0
        xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
13153
0
    } else {
13154
0
        ret = XML_ERR_OK;
13155
0
    }
13156
13157
0
    if ((lst != NULL) && (ret == XML_ERR_OK)) {
13158
0
  xmlNodePtr cur;
13159
13160
  /*
13161
   * Return the newly created nodeset after unlinking it from
13162
   * they pseudo parent.
13163
   */
13164
0
  cur = ctxt->myDoc->children->children;
13165
0
  *lst = cur;
13166
0
  while (cur != NULL) {
13167
0
#ifdef LIBXML_VALID_ENABLED
13168
0
      if ((oldctxt->validate) && (oldctxt->wellFormed) &&
13169
0
    (oldctxt->myDoc) && (oldctxt->myDoc->intSubset) &&
13170
0
    (cur->type == XML_ELEMENT_NODE)) {
13171
0
    oldctxt->valid &= xmlValidateElement(&oldctxt->vctxt,
13172
0
      oldctxt->myDoc, cur);
13173
0
      }
13174
0
#endif /* LIBXML_VALID_ENABLED */
13175
0
      cur->parent = NULL;
13176
0
      cur = cur->next;
13177
0
  }
13178
0
  ctxt->myDoc->children->children = NULL;
13179
0
    }
13180
0
    if (ctxt->myDoc != NULL) {
13181
0
  xmlFreeNode(ctxt->myDoc->children);
13182
0
        ctxt->myDoc->children = content;
13183
0
        ctxt->myDoc->last = last;
13184
0
    }
13185
13186
    /*
13187
     * Also record the size of the entity parsed
13188
     */
13189
0
    if (ctxt->input != NULL && oldctxt != NULL) {
13190
0
        unsigned long consumed = ctxt->input->consumed;
13191
13192
0
        xmlSaturatedAddSizeT(&consumed, ctxt->input->cur - ctxt->input->base);
13193
13194
0
        xmlSaturatedAdd(&oldctxt->sizeentcopy, consumed);
13195
0
        xmlSaturatedAdd(&oldctxt->sizeentcopy, ctxt->sizeentcopy);
13196
0
    }
13197
13198
0
    oldctxt->nbErrors = ctxt->nbErrors;
13199
0
    oldctxt->nbWarnings = ctxt->nbWarnings;
13200
13201
0
error:
13202
0
    ctxt->sax = oldsax;
13203
0
    ctxt->dict = NULL;
13204
0
    ctxt->attsDefault = NULL;
13205
0
    ctxt->attsSpecial = NULL;
13206
0
    xmlFreeParserCtxt(ctxt);
13207
0
    if (newDoc != NULL) {
13208
0
  xmlFreeDoc(newDoc);
13209
0
    }
13210
13211
0
    return(ret);
13212
0
}
13213
13214
/**
13215
 * xmlParseInNodeContext:
13216
 * @node:  the context node
13217
 * @data:  the input string
13218
 * @datalen:  the input string length in bytes
13219
 * @options:  a combination of xmlParserOption
13220
 * @lst:  the return value for the set of parsed nodes
13221
 *
13222
 * Parse a well-balanced chunk of an XML document
13223
 * within the context (DTD, namespaces, etc ...) of the given node.
13224
 *
13225
 * The allowed sequence for the data is a Well Balanced Chunk defined by
13226
 * the content production in the XML grammar:
13227
 *
13228
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13229
 *
13230
 * Returns XML_ERR_OK if the chunk is well balanced, and the parser
13231
 * error code otherwise
13232
 */
13233
xmlParserErrors
13234
xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
13235
0
                      int options, xmlNodePtr *lst) {
13236
0
    xmlParserCtxtPtr ctxt;
13237
0
    xmlDocPtr doc = NULL;
13238
0
    xmlNodePtr fake, cur;
13239
0
    int nsnr = 0;
13240
13241
0
    xmlParserErrors ret = XML_ERR_OK;
13242
13243
    /*
13244
     * check all input parameters, grab the document
13245
     */
13246
0
    if ((lst == NULL) || (node == NULL) || (data == NULL) || (datalen < 0))
13247
0
        return(XML_ERR_INTERNAL_ERROR);
13248
0
    switch (node->type) {
13249
0
        case XML_ELEMENT_NODE:
13250
0
        case XML_ATTRIBUTE_NODE:
13251
0
        case XML_TEXT_NODE:
13252
0
        case XML_CDATA_SECTION_NODE:
13253
0
        case XML_ENTITY_REF_NODE:
13254
0
        case XML_PI_NODE:
13255
0
        case XML_COMMENT_NODE:
13256
0
        case XML_DOCUMENT_NODE:
13257
0
        case XML_HTML_DOCUMENT_NODE:
13258
0
      break;
13259
0
  default:
13260
0
      return(XML_ERR_INTERNAL_ERROR);
13261
13262
0
    }
13263
0
    while ((node != NULL) && (node->type != XML_ELEMENT_NODE) &&
13264
0
           (node->type != XML_DOCUMENT_NODE) &&
13265
0
     (node->type != XML_HTML_DOCUMENT_NODE))
13266
0
  node = node->parent;
13267
0
    if (node == NULL)
13268
0
  return(XML_ERR_INTERNAL_ERROR);
13269
0
    if (node->type == XML_ELEMENT_NODE)
13270
0
  doc = node->doc;
13271
0
    else
13272
0
        doc = (xmlDocPtr) node;
13273
0
    if (doc == NULL)
13274
0
  return(XML_ERR_INTERNAL_ERROR);
13275
13276
    /*
13277
     * allocate a context and set-up everything not related to the
13278
     * node position in the tree
13279
     */
13280
0
    if (doc->type == XML_DOCUMENT_NODE)
13281
0
  ctxt = xmlCreateMemoryParserCtxt((char *) data, datalen);
13282
0
#ifdef LIBXML_HTML_ENABLED
13283
0
    else if (doc->type == XML_HTML_DOCUMENT_NODE) {
13284
0
  ctxt = htmlCreateMemoryParserCtxt((char *) data, datalen);
13285
        /*
13286
         * When parsing in context, it makes no sense to add implied
13287
         * elements like html/body/etc...
13288
         */
13289
0
        options |= HTML_PARSE_NOIMPLIED;
13290
0
    }
13291
0
#endif
13292
0
    else
13293
0
        return(XML_ERR_INTERNAL_ERROR);
13294
13295
0
    if (ctxt == NULL)
13296
0
        return(XML_ERR_NO_MEMORY);
13297
13298
    /*
13299
     * Use input doc's dict if present, else assure XML_PARSE_NODICT is set.
13300
     * We need a dictionary for xmlDetectSAX2, so if there's no doc dict
13301
     * we must wait until the last moment to free the original one.
13302
     */
13303
0
    if (doc->dict != NULL) {
13304
0
        if (ctxt->dict != NULL)
13305
0
      xmlDictFree(ctxt->dict);
13306
0
  ctxt->dict = doc->dict;
13307
0
    } else
13308
0
        options |= XML_PARSE_NODICT;
13309
13310
0
    if (doc->encoding != NULL) {
13311
0
        xmlCharEncodingHandlerPtr hdlr;
13312
13313
0
        hdlr = xmlFindCharEncodingHandler((const char *) doc->encoding);
13314
0
        if (hdlr != NULL) {
13315
0
            xmlSwitchToEncoding(ctxt, hdlr);
13316
0
  } else {
13317
0
            return(XML_ERR_UNSUPPORTED_ENCODING);
13318
0
        }
13319
0
    }
13320
13321
0
    xmlCtxtUseOptionsInternal(ctxt, options);
13322
0
    xmlDetectSAX2(ctxt);
13323
0
    ctxt->myDoc = doc;
13324
    /* parsing in context, i.e. as within existing content */
13325
0
    ctxt->input_id = 2;
13326
0
    ctxt->instate = XML_PARSER_CONTENT;
13327
13328
0
    fake = xmlNewDocComment(node->doc, NULL);
13329
0
    if (fake == NULL) {
13330
0
        xmlFreeParserCtxt(ctxt);
13331
0
  return(XML_ERR_NO_MEMORY);
13332
0
    }
13333
0
    xmlAddChild(node, fake);
13334
13335
0
    if (node->type == XML_ELEMENT_NODE)
13336
0
  nodePush(ctxt, node);
13337
13338
0
    if ((ctxt->html == 0) && (node->type == XML_ELEMENT_NODE)) {
13339
  /*
13340
   * initialize the SAX2 namespaces stack
13341
   */
13342
0
  cur = node;
13343
0
  while ((cur != NULL) && (cur->type == XML_ELEMENT_NODE)) {
13344
0
      xmlNsPtr ns = cur->nsDef;
13345
0
            xmlHashedString hprefix, huri;
13346
13347
0
      while (ns != NULL) {
13348
0
                hprefix = xmlDictLookupHashed(ctxt->dict, ns->prefix, -1);
13349
0
                huri = xmlDictLookupHashed(ctxt->dict, ns->href, -1);
13350
0
                if (xmlParserNsPush(ctxt, &hprefix, &huri, ns, 1) > 0)
13351
0
                    nsnr++;
13352
0
    ns = ns->next;
13353
0
      }
13354
0
      cur = cur->parent;
13355
0
  }
13356
0
    }
13357
13358
0
    if ((ctxt->validate) || (ctxt->replaceEntities != 0)) {
13359
  /*
13360
   * ID/IDREF registration will be done in xmlValidateElement below
13361
   */
13362
0
  ctxt->loadsubset |= XML_SKIP_IDS;
13363
0
    }
13364
13365
0
#ifdef LIBXML_HTML_ENABLED
13366
0
    if (doc->type == XML_HTML_DOCUMENT_NODE)
13367
0
        __htmlParseContent(ctxt);
13368
0
    else
13369
0
#endif
13370
0
  xmlParseContent(ctxt);
13371
13372
0
    xmlParserNsPop(ctxt, nsnr);
13373
0
    if ((RAW == '<') && (NXT(1) == '/')) {
13374
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13375
0
    } else if (RAW != 0) {
13376
0
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13377
0
    }
13378
0
    if ((ctxt->node != NULL) && (ctxt->node != node)) {
13379
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13380
0
  ctxt->wellFormed = 0;
13381
0
    }
13382
13383
0
    if (!ctxt->wellFormed) {
13384
0
        if (ctxt->errNo == 0)
13385
0
      ret = XML_ERR_INTERNAL_ERROR;
13386
0
  else
13387
0
      ret = (xmlParserErrors)ctxt->errNo;
13388
0
    } else {
13389
0
        ret = XML_ERR_OK;
13390
0
    }
13391
13392
    /*
13393
     * Return the newly created nodeset after unlinking it from
13394
     * the pseudo sibling.
13395
     */
13396
13397
0
    cur = fake->next;
13398
0
    fake->next = NULL;
13399
0
    node->last = fake;
13400
13401
0
    if (cur != NULL) {
13402
0
  cur->prev = NULL;
13403
0
    }
13404
13405
0
    *lst = cur;
13406
13407
0
    while (cur != NULL) {
13408
0
  cur->parent = NULL;
13409
0
  cur = cur->next;
13410
0
    }
13411
13412
0
    xmlUnlinkNode(fake);
13413
0
    xmlFreeNode(fake);
13414
13415
13416
0
    if (ret != XML_ERR_OK) {
13417
0
        xmlFreeNodeList(*lst);
13418
0
  *lst = NULL;
13419
0
    }
13420
13421
0
    if (doc->dict != NULL)
13422
0
        ctxt->dict = NULL;
13423
0
    xmlFreeParserCtxt(ctxt);
13424
13425
0
    return(ret);
13426
0
}
13427
13428
#ifdef LIBXML_SAX1_ENABLED
13429
/**
13430
 * xmlParseBalancedChunkMemoryRecover:
13431
 * @doc:  the document the chunk pertains to (must not be NULL)
13432
 * @sax:  the SAX handler block (possibly NULL)
13433
 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
13434
 * @depth:  Used for loop detection, use 0
13435
 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
13436
 * @lst:  the return value for the set of parsed nodes
13437
 * @recover: return nodes even if the data is broken (use 0)
13438
 *
13439
 *
13440
 * Parse a well-balanced chunk of an XML document
13441
 * called by the parser
13442
 * The allowed sequence for the Well Balanced Chunk is the one defined by
13443
 * the content production in the XML grammar:
13444
 *
13445
 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13446
 *
13447
 * Returns 0 if the chunk is well balanced, -1 in case of args problem and
13448
 *    the parser error code otherwise
13449
 *
13450
 * In case recover is set to 1, the nodelist will not be empty even if
13451
 * the parsed chunk is not well balanced, assuming the parsing succeeded to
13452
 * some extent.
13453
 */
13454
int
13455
xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
13456
     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst,
13457
0
     int recover) {
13458
0
    xmlParserCtxtPtr ctxt;
13459
0
    xmlDocPtr newDoc;
13460
0
    xmlSAXHandlerPtr oldsax = NULL;
13461
0
    xmlNodePtr content, newRoot;
13462
0
    int ret = 0;
13463
13464
0
    if (depth > 40) {
13465
0
  return(XML_ERR_ENTITY_LOOP);
13466
0
    }
13467
13468
13469
0
    if (lst != NULL)
13470
0
        *lst = NULL;
13471
0
    if (string == NULL)
13472
0
        return(-1);
13473
13474
0
    ctxt = xmlCreateDocParserCtxt(string);
13475
0
    if (ctxt == NULL) return(-1);
13476
0
    ctxt->userData = ctxt;
13477
0
    if (sax != NULL) {
13478
0
  oldsax = ctxt->sax;
13479
0
        ctxt->sax = sax;
13480
0
  if (user_data != NULL)
13481
0
      ctxt->userData = user_data;
13482
0
    }
13483
0
    newDoc = xmlNewDoc(BAD_CAST "1.0");
13484
0
    if (newDoc == NULL) {
13485
0
  xmlFreeParserCtxt(ctxt);
13486
0
  return(-1);
13487
0
    }
13488
0
    newDoc->properties = XML_DOC_INTERNAL;
13489
0
    if ((doc != NULL) && (doc->dict != NULL)) {
13490
0
        xmlDictFree(ctxt->dict);
13491
0
  ctxt->dict = doc->dict;
13492
0
  xmlDictReference(ctxt->dict);
13493
0
  ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
13494
0
  ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
13495
0
  ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
13496
0
  ctxt->dictNames = 1;
13497
0
        newDoc->dict = ctxt->dict;
13498
0
        xmlDictReference(newDoc->dict);
13499
0
    } else {
13500
0
  xmlCtxtUseOptionsInternal(ctxt, XML_PARSE_NODICT);
13501
0
    }
13502
    /* doc == NULL is only supported for historic reasons */
13503
0
    if (doc != NULL) {
13504
0
  newDoc->intSubset = doc->intSubset;
13505
0
  newDoc->extSubset = doc->extSubset;
13506
0
    }
13507
0
    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
13508
0
    if (newRoot == NULL) {
13509
0
  if (sax != NULL)
13510
0
      ctxt->sax = oldsax;
13511
0
  xmlFreeParserCtxt(ctxt);
13512
0
  newDoc->intSubset = NULL;
13513
0
  newDoc->extSubset = NULL;
13514
0
        xmlFreeDoc(newDoc);
13515
0
  return(-1);
13516
0
    }
13517
0
    xmlAddChild((xmlNodePtr) newDoc, newRoot);
13518
0
    nodePush(ctxt, newRoot);
13519
    /* doc == NULL is only supported for historic reasons */
13520
0
    if (doc == NULL) {
13521
0
  ctxt->myDoc = newDoc;
13522
0
    } else {
13523
0
  ctxt->myDoc = newDoc;
13524
  /* Ensure that doc has XML spec namespace */
13525
0
  xmlSearchNsByHref(doc, (xmlNodePtr)doc, XML_XML_NAMESPACE);
13526
0
  newDoc->oldNs = doc->oldNs;
13527
0
    }
13528
0
    ctxt->instate = XML_PARSER_CONTENT;
13529
0
    ctxt->input_id = 2;
13530
0
    ctxt->depth = depth;
13531
13532
    /*
13533
     * Doing validity checking on chunk doesn't make sense
13534
     */
13535
0
    ctxt->validate = 0;
13536
0
    ctxt->loadsubset = 0;
13537
0
    xmlDetectSAX2(ctxt);
13538
13539
0
    if ( doc != NULL ){
13540
0
        content = doc->children;
13541
0
        doc->children = NULL;
13542
0
        xmlParseContent(ctxt);
13543
0
        doc->children = content;
13544
0
    }
13545
0
    else {
13546
0
        xmlParseContent(ctxt);
13547
0
    }
13548
0
    if ((RAW == '<') && (NXT(1) == '/')) {
13549
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13550
0
    } else if (RAW != 0) {
13551
0
  xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13552
0
    }
13553
0
    if (ctxt->node != newDoc->children) {
13554
0
  xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13555
0
    }
13556
13557
0
    if (!ctxt->wellFormed) {
13558
0
        if (ctxt->errNo == 0)
13559
0
      ret = 1;
13560
0
  else
13561
0
      ret = ctxt->errNo;
13562
0
    } else {
13563
0
      ret = 0;
13564
0
    }
13565
13566
0
    if ((lst != NULL) && ((ret == 0) || (recover == 1))) {
13567
0
  xmlNodePtr cur;
13568
13569
  /*
13570
   * Return the newly created nodeset after unlinking it from
13571
   * they pseudo parent.
13572
   */
13573
0
  cur = newDoc->children->children;
13574
0
  *lst = cur;
13575
0
  while (cur != NULL) {
13576
0
      xmlSetTreeDoc(cur, doc);
13577
0
      cur->parent = NULL;
13578
0
      cur = cur->next;
13579
0
  }
13580
0
  newDoc->children->children = NULL;
13581
0
    }
13582
13583
0
    if (sax != NULL)
13584
0
  ctxt->sax = oldsax;
13585
0
    xmlFreeParserCtxt(ctxt);
13586
0
    newDoc->intSubset = NULL;
13587
0
    newDoc->extSubset = NULL;
13588
    /* This leaks the namespace list if doc == NULL */
13589
0
    newDoc->oldNs = NULL;
13590
0
    xmlFreeDoc(newDoc);
13591
13592
0
    return(ret);
13593
0
}
13594
13595
/**
13596
 * xmlSAXParseEntity:
13597
 * @sax:  the SAX handler block
13598
 * @filename:  the filename
13599
 *
13600
 * DEPRECATED: Don't use.
13601
 *
13602
 * parse an XML external entity out of context and build a tree.
13603
 * It use the given SAX function block to handle the parsing callback.
13604
 * If sax is NULL, fallback to the default DOM tree building routines.
13605
 *
13606
 * [78] extParsedEnt ::= TextDecl? content
13607
 *
13608
 * This correspond to a "Well Balanced" chunk
13609
 *
13610
 * Returns the resulting document tree
13611
 */
13612
13613
xmlDocPtr
13614
0
xmlSAXParseEntity(xmlSAXHandlerPtr sax, const char *filename) {
13615
0
    xmlDocPtr ret;
13616
0
    xmlParserCtxtPtr ctxt;
13617
13618
0
    ctxt = xmlCreateFileParserCtxt(filename);
13619
0
    if (ctxt == NULL) {
13620
0
  return(NULL);
13621
0
    }
13622
0
    if (sax != NULL) {
13623
0
  if (ctxt->sax != NULL)
13624
0
      xmlFree(ctxt->sax);
13625
0
        ctxt->sax = sax;
13626
0
        ctxt->userData = NULL;
13627
0
    }
13628
13629
0
    xmlParseExtParsedEnt(ctxt);
13630
13631
0
    if (ctxt->wellFormed)
13632
0
  ret = ctxt->myDoc;
13633
0
    else {
13634
0
        ret = NULL;
13635
0
        xmlFreeDoc(ctxt->myDoc);
13636
0
        ctxt->myDoc = NULL;
13637
0
    }
13638
0
    if (sax != NULL)
13639
0
        ctxt->sax = NULL;
13640
0
    xmlFreeParserCtxt(ctxt);
13641
13642
0
    return(ret);
13643
0
}
13644
13645
/**
13646
 * xmlParseEntity:
13647
 * @filename:  the filename
13648
 *
13649
 * parse an XML external entity out of context and build a tree.
13650
 *
13651
 * [78] extParsedEnt ::= TextDecl? content
13652
 *
13653
 * This correspond to a "Well Balanced" chunk
13654
 *
13655
 * Returns the resulting document tree
13656
 */
13657
13658
xmlDocPtr
13659
0
xmlParseEntity(const char *filename) {
13660
0
    return(xmlSAXParseEntity(NULL, filename));
13661
0
}
13662
#endif /* LIBXML_SAX1_ENABLED */
13663
13664
/**
13665
 * xmlCreateEntityParserCtxtInternal:
13666
 * @URL:  the entity URL
13667
 * @ID:  the entity PUBLIC ID
13668
 * @base:  a possible base for the target URI
13669
 * @pctx:  parser context used to set options on new context
13670
 *
13671
 * Create a parser context for an external entity
13672
 * Automatic support for ZLIB/Compress compressed document is provided
13673
 * by default if found at compile-time.
13674
 *
13675
 * Returns the new parser context or NULL
13676
 */
13677
static xmlParserCtxtPtr
13678
xmlCreateEntityParserCtxtInternal(xmlSAXHandlerPtr sax, void *userData,
13679
        const xmlChar *URL, const xmlChar *ID, const xmlChar *base,
13680
0
        xmlParserCtxtPtr pctx) {
13681
0
    xmlParserCtxtPtr ctxt;
13682
0
    xmlParserInputPtr inputStream;
13683
0
    char *directory = NULL;
13684
0
    xmlChar *uri;
13685
13686
0
    ctxt = xmlNewSAXParserCtxt(sax, userData);
13687
0
    if (ctxt == NULL) {
13688
0
  return(NULL);
13689
0
    }
13690
13691
0
    if (pctx != NULL) {
13692
0
        ctxt->options = pctx->options;
13693
0
        ctxt->_private = pctx->_private;
13694
0
  ctxt->input_id = pctx->input_id;
13695
0
    }
13696
13697
    /* Don't read from stdin. */
13698
0
    if (xmlStrcmp(URL, BAD_CAST "-") == 0)
13699
0
        URL = BAD_CAST "./-";
13700
13701
0
    uri = xmlBuildURI(URL, base);
13702
13703
0
    if (uri == NULL) {
13704
0
  inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
13705
0
  if (inputStream == NULL) {
13706
0
      xmlFreeParserCtxt(ctxt);
13707
0
      return(NULL);
13708
0
  }
13709
13710
0
  inputPush(ctxt, inputStream);
13711
13712
0
  if ((ctxt->directory == NULL) && (directory == NULL))
13713
0
      directory = xmlParserGetDirectory((char *)URL);
13714
0
  if ((ctxt->directory == NULL) && (directory != NULL))
13715
0
      ctxt->directory = directory;
13716
0
    } else {
13717
0
  inputStream = xmlLoadExternalEntity((char *)uri, (char *)ID, ctxt);
13718
0
  if (inputStream == NULL) {
13719
0
      xmlFree(uri);
13720
0
      xmlFreeParserCtxt(ctxt);
13721
0
      return(NULL);
13722
0
  }
13723
13724
0
  inputPush(ctxt, inputStream);
13725
13726
0
  if ((ctxt->directory == NULL) && (directory == NULL))
13727
0
      directory = xmlParserGetDirectory((char *)uri);
13728
0
  if ((ctxt->directory == NULL) && (directory != NULL))
13729
0
      ctxt->directory = directory;
13730
0
  xmlFree(uri);
13731
0
    }
13732
0
    return(ctxt);
13733
0
}
13734
13735
/**
13736
 * xmlCreateEntityParserCtxt:
13737
 * @URL:  the entity URL
13738
 * @ID:  the entity PUBLIC ID
13739
 * @base:  a possible base for the target URI
13740
 *
13741
 * Create a parser context for an external entity
13742
 * Automatic support for ZLIB/Compress compressed document is provided
13743
 * by default if found at compile-time.
13744
 *
13745
 * Returns the new parser context or NULL
13746
 */
13747
xmlParserCtxtPtr
13748
xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID,
13749
0
                    const xmlChar *base) {
13750
0
    return xmlCreateEntityParserCtxtInternal(NULL, NULL, URL, ID, base, NULL);
13751
13752
0
}
13753
13754
/************************************************************************
13755
 *                  *
13756
 *    Front ends when parsing from a file     *
13757
 *                  *
13758
 ************************************************************************/
13759
13760
/**
13761
 * xmlCreateURLParserCtxt:
13762
 * @filename:  the filename or URL
13763
 * @options:  a combination of xmlParserOption
13764
 *
13765
 * Create a parser context for a file or URL content.
13766
 * Automatic support for ZLIB/Compress compressed document is provided
13767
 * by default if found at compile-time and for file accesses
13768
 *
13769
 * Returns the new parser context or NULL
13770
 */
13771
xmlParserCtxtPtr
13772
xmlCreateURLParserCtxt(const char *filename, int options)
13773
0
{
13774
0
    xmlParserCtxtPtr ctxt;
13775
0
    xmlParserInputPtr inputStream;
13776
0
    char *directory = NULL;
13777
13778
0
    ctxt = xmlNewParserCtxt();
13779
0
    if (ctxt == NULL) {
13780
0
  xmlErrMemory(NULL, "cannot allocate parser context");
13781
0
  return(NULL);
13782
0
    }
13783
13784
0
    if (options)
13785
0
  xmlCtxtUseOptionsInternal(ctxt, options);
13786
0
    ctxt->linenumbers = 1;
13787
13788
0
    inputStream = xmlLoadExternalEntity(filename, NULL, ctxt);
13789
0
    if (inputStream == NULL) {
13790
0
  xmlFreeParserCtxt(ctxt);
13791
0
  return(NULL);
13792
0
    }
13793
13794
0
    inputPush(ctxt, inputStream);
13795
0
    if ((ctxt->directory == NULL) && (directory == NULL))
13796
0
        directory = xmlParserGetDirectory(filename);
13797
0
    if ((ctxt->directory == NULL) && (directory != NULL))
13798
0
        ctxt->directory = directory;
13799
13800
0
    return(ctxt);
13801
0
}
13802
13803
/**
13804
 * xmlCreateFileParserCtxt:
13805
 * @filename:  the filename
13806
 *
13807
 * Create a parser context for a file content.
13808
 * Automatic support for ZLIB/Compress compressed document is provided
13809
 * by default if found at compile-time.
13810
 *
13811
 * Returns the new parser context or NULL
13812
 */
13813
xmlParserCtxtPtr
13814
xmlCreateFileParserCtxt(const char *filename)
13815
0
{
13816
0
    return(xmlCreateURLParserCtxt(filename, 0));
13817
0
}
13818
13819
#ifdef LIBXML_SAX1_ENABLED
13820
/**
13821
 * xmlSAXParseFileWithData:
13822
 * @sax:  the SAX handler block
13823
 * @filename:  the filename
13824
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
13825
 *             documents
13826
 * @data:  the userdata
13827
 *
13828
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadFile.
13829
 *
13830
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
13831
 * compressed document is provided by default if found at compile-time.
13832
 * It use the given SAX function block to handle the parsing callback.
13833
 * If sax is NULL, fallback to the default DOM tree building routines.
13834
 *
13835
 * User data (void *) is stored within the parser context in the
13836
 * context's _private member, so it is available nearly everywhere in libxml
13837
 *
13838
 * Returns the resulting document tree
13839
 */
13840
13841
xmlDocPtr
13842
xmlSAXParseFileWithData(xmlSAXHandlerPtr sax, const char *filename,
13843
0
                        int recovery, void *data) {
13844
0
    xmlDocPtr ret;
13845
0
    xmlParserCtxtPtr ctxt;
13846
13847
0
    xmlInitParser();
13848
13849
0
    ctxt = xmlCreateFileParserCtxt(filename);
13850
0
    if (ctxt == NULL) {
13851
0
  return(NULL);
13852
0
    }
13853
0
    if (sax != NULL) {
13854
0
  if (ctxt->sax != NULL)
13855
0
      xmlFree(ctxt->sax);
13856
0
        ctxt->sax = sax;
13857
0
    }
13858
0
    xmlDetectSAX2(ctxt);
13859
0
    if (data!=NULL) {
13860
0
  ctxt->_private = data;
13861
0
    }
13862
13863
0
    if (ctxt->directory == NULL)
13864
0
        ctxt->directory = xmlParserGetDirectory(filename);
13865
13866
0
    ctxt->recovery = recovery;
13867
13868
0
    xmlParseDocument(ctxt);
13869
13870
0
    if ((ctxt->wellFormed) || recovery) {
13871
0
        ret = ctxt->myDoc;
13872
0
  if ((ret != NULL) && (ctxt->input->buf != NULL)) {
13873
0
      if (ctxt->input->buf->compressed > 0)
13874
0
    ret->compression = 9;
13875
0
      else
13876
0
    ret->compression = ctxt->input->buf->compressed;
13877
0
  }
13878
0
    }
13879
0
    else {
13880
0
       ret = NULL;
13881
0
       xmlFreeDoc(ctxt->myDoc);
13882
0
       ctxt->myDoc = NULL;
13883
0
    }
13884
0
    if (sax != NULL)
13885
0
        ctxt->sax = NULL;
13886
0
    xmlFreeParserCtxt(ctxt);
13887
13888
0
    return(ret);
13889
0
}
13890
13891
/**
13892
 * xmlSAXParseFile:
13893
 * @sax:  the SAX handler block
13894
 * @filename:  the filename
13895
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
13896
 *             documents
13897
 *
13898
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadFile.
13899
 *
13900
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
13901
 * compressed document is provided by default if found at compile-time.
13902
 * It use the given SAX function block to handle the parsing callback.
13903
 * If sax is NULL, fallback to the default DOM tree building routines.
13904
 *
13905
 * Returns the resulting document tree
13906
 */
13907
13908
xmlDocPtr
13909
xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
13910
0
                          int recovery) {
13911
0
    return(xmlSAXParseFileWithData(sax,filename,recovery,NULL));
13912
0
}
13913
13914
/**
13915
 * xmlRecoverDoc:
13916
 * @cur:  a pointer to an array of xmlChar
13917
 *
13918
 * DEPRECATED: Use xmlReadDoc with XML_PARSE_RECOVER.
13919
 *
13920
 * parse an XML in-memory document and build a tree.
13921
 * In the case the document is not Well Formed, a attempt to build a
13922
 * tree is tried anyway
13923
 *
13924
 * Returns the resulting document tree or NULL in case of failure
13925
 */
13926
13927
xmlDocPtr
13928
0
xmlRecoverDoc(const xmlChar *cur) {
13929
0
    return(xmlSAXParseDoc(NULL, cur, 1));
13930
0
}
13931
13932
/**
13933
 * xmlParseFile:
13934
 * @filename:  the filename
13935
 *
13936
 * DEPRECATED: Use xmlReadFile.
13937
 *
13938
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
13939
 * compressed document is provided by default if found at compile-time.
13940
 *
13941
 * Returns the resulting document tree if the file was wellformed,
13942
 * NULL otherwise.
13943
 */
13944
13945
xmlDocPtr
13946
0
xmlParseFile(const char *filename) {
13947
0
    return(xmlSAXParseFile(NULL, filename, 0));
13948
0
}
13949
13950
/**
13951
 * xmlRecoverFile:
13952
 * @filename:  the filename
13953
 *
13954
 * DEPRECATED: Use xmlReadFile with XML_PARSE_RECOVER.
13955
 *
13956
 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
13957
 * compressed document is provided by default if found at compile-time.
13958
 * In the case the document is not Well Formed, it attempts to build
13959
 * a tree anyway
13960
 *
13961
 * Returns the resulting document tree or NULL in case of failure
13962
 */
13963
13964
xmlDocPtr
13965
0
xmlRecoverFile(const char *filename) {
13966
0
    return(xmlSAXParseFile(NULL, filename, 1));
13967
0
}
13968
13969
13970
/**
13971
 * xmlSetupParserForBuffer:
13972
 * @ctxt:  an XML parser context
13973
 * @buffer:  a xmlChar * buffer
13974
 * @filename:  a file name
13975
 *
13976
 * DEPRECATED: Don't use.
13977
 *
13978
 * Setup the parser context to parse a new buffer; Clears any prior
13979
 * contents from the parser context. The buffer parameter must not be
13980
 * NULL, but the filename parameter can be
13981
 */
13982
void
13983
xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
13984
                             const char* filename)
13985
0
{
13986
0
    xmlParserInputPtr input;
13987
13988
0
    if ((ctxt == NULL) || (buffer == NULL))
13989
0
        return;
13990
13991
0
    input = xmlNewInputStream(ctxt);
13992
0
    if (input == NULL) {
13993
0
        xmlErrMemory(NULL, "parsing new buffer: out of memory\n");
13994
0
        xmlClearParserCtxt(ctxt);
13995
0
        return;
13996
0
    }
13997
13998
0
    xmlClearParserCtxt(ctxt);
13999
0
    if (filename != NULL)
14000
0
        input->filename = (char *) xmlCanonicPath((const xmlChar *)filename);
14001
0
    input->base = buffer;
14002
0
    input->cur = buffer;
14003
0
    input->end = &buffer[xmlStrlen(buffer)];
14004
0
    inputPush(ctxt, input);
14005
0
}
14006
14007
/**
14008
 * xmlSAXUserParseFile:
14009
 * @sax:  a SAX handler
14010
 * @user_data:  The user data returned on SAX callbacks
14011
 * @filename:  a file name
14012
 *
14013
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadFile.
14014
 *
14015
 * parse an XML file and call the given SAX handler routines.
14016
 * Automatic support for ZLIB/Compress compressed document is provided
14017
 *
14018
 * Returns 0 in case of success or a error number otherwise
14019
 */
14020
int
14021
xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
14022
0
                    const char *filename) {
14023
0
    int ret = 0;
14024
0
    xmlParserCtxtPtr ctxt;
14025
14026
0
    ctxt = xmlCreateFileParserCtxt(filename);
14027
0
    if (ctxt == NULL) return -1;
14028
0
    if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
14029
0
  xmlFree(ctxt->sax);
14030
0
    ctxt->sax = sax;
14031
0
    xmlDetectSAX2(ctxt);
14032
14033
0
    if (user_data != NULL)
14034
0
  ctxt->userData = user_data;
14035
14036
0
    xmlParseDocument(ctxt);
14037
14038
0
    if (ctxt->wellFormed)
14039
0
  ret = 0;
14040
0
    else {
14041
0
        if (ctxt->errNo != 0)
14042
0
      ret = ctxt->errNo;
14043
0
  else
14044
0
      ret = -1;
14045
0
    }
14046
0
    if (sax != NULL)
14047
0
  ctxt->sax = NULL;
14048
0
    if (ctxt->myDoc != NULL) {
14049
0
        xmlFreeDoc(ctxt->myDoc);
14050
0
  ctxt->myDoc = NULL;
14051
0
    }
14052
0
    xmlFreeParserCtxt(ctxt);
14053
14054
0
    return ret;
14055
0
}
14056
#endif /* LIBXML_SAX1_ENABLED */
14057
14058
/************************************************************************
14059
 *                  *
14060
 *    Front ends when parsing from memory     *
14061
 *                  *
14062
 ************************************************************************/
14063
14064
/**
14065
 * xmlCreateMemoryParserCtxt:
14066
 * @buffer:  a pointer to a char array
14067
 * @size:  the size of the array
14068
 *
14069
 * Create a parser context for an XML in-memory document.
14070
 *
14071
 * Returns the new parser context or NULL
14072
 */
14073
xmlParserCtxtPtr
14074
0
xmlCreateMemoryParserCtxt(const char *buffer, int size) {
14075
0
    xmlParserCtxtPtr ctxt;
14076
0
    xmlParserInputPtr input;
14077
0
    xmlParserInputBufferPtr buf;
14078
14079
0
    if (buffer == NULL)
14080
0
  return(NULL);
14081
0
    if (size <= 0)
14082
0
  return(NULL);
14083
14084
0
    ctxt = xmlNewParserCtxt();
14085
0
    if (ctxt == NULL)
14086
0
  return(NULL);
14087
14088
0
    buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
14089
0
    if (buf == NULL) {
14090
0
  xmlFreeParserCtxt(ctxt);
14091
0
  return(NULL);
14092
0
    }
14093
14094
0
    input = xmlNewInputStream(ctxt);
14095
0
    if (input == NULL) {
14096
0
  xmlFreeParserInputBuffer(buf);
14097
0
  xmlFreeParserCtxt(ctxt);
14098
0
  return(NULL);
14099
0
    }
14100
14101
0
    input->filename = NULL;
14102
0
    input->buf = buf;
14103
0
    xmlBufResetInput(input->buf->buffer, input);
14104
14105
0
    inputPush(ctxt, input);
14106
0
    return(ctxt);
14107
0
}
14108
14109
#ifdef LIBXML_SAX1_ENABLED
14110
/**
14111
 * xmlSAXParseMemoryWithData:
14112
 * @sax:  the SAX handler block
14113
 * @buffer:  an pointer to a char array
14114
 * @size:  the size of the array
14115
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14116
 *             documents
14117
 * @data:  the userdata
14118
 *
14119
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadMemory.
14120
 *
14121
 * parse an XML in-memory block and use the given SAX function block
14122
 * to handle the parsing callback. If sax is NULL, fallback to the default
14123
 * DOM tree building routines.
14124
 *
14125
 * User data (void *) is stored within the parser context in the
14126
 * context's _private member, so it is available nearly everywhere in libxml
14127
 *
14128
 * Returns the resulting document tree
14129
 */
14130
14131
xmlDocPtr
14132
xmlSAXParseMemoryWithData(xmlSAXHandlerPtr sax, const char *buffer,
14133
0
            int size, int recovery, void *data) {
14134
0
    xmlDocPtr ret;
14135
0
    xmlParserCtxtPtr ctxt;
14136
14137
0
    xmlInitParser();
14138
14139
0
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
14140
0
    if (ctxt == NULL) return(NULL);
14141
0
    if (sax != NULL) {
14142
0
  if (ctxt->sax != NULL)
14143
0
      xmlFree(ctxt->sax);
14144
0
        ctxt->sax = sax;
14145
0
    }
14146
0
    xmlDetectSAX2(ctxt);
14147
0
    if (data!=NULL) {
14148
0
  ctxt->_private=data;
14149
0
    }
14150
14151
0
    ctxt->recovery = recovery;
14152
14153
0
    xmlParseDocument(ctxt);
14154
14155
0
    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
14156
0
    else {
14157
0
       ret = NULL;
14158
0
       xmlFreeDoc(ctxt->myDoc);
14159
0
       ctxt->myDoc = NULL;
14160
0
    }
14161
0
    if (sax != NULL)
14162
0
  ctxt->sax = NULL;
14163
0
    xmlFreeParserCtxt(ctxt);
14164
14165
0
    return(ret);
14166
0
}
14167
14168
/**
14169
 * xmlSAXParseMemory:
14170
 * @sax:  the SAX handler block
14171
 * @buffer:  an pointer to a char array
14172
 * @size:  the size of the array
14173
 * @recovery:  work in recovery mode, i.e. tries to read not Well Formed
14174
 *             documents
14175
 *
14176
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadMemory.
14177
 *
14178
 * parse an XML in-memory block and use the given SAX function block
14179
 * to handle the parsing callback. If sax is NULL, fallback to the default
14180
 * DOM tree building routines.
14181
 *
14182
 * Returns the resulting document tree
14183
 */
14184
xmlDocPtr
14185
xmlSAXParseMemory(xmlSAXHandlerPtr sax, const char *buffer,
14186
0
            int size, int recovery) {
14187
0
    return xmlSAXParseMemoryWithData(sax, buffer, size, recovery, NULL);
14188
0
}
14189
14190
/**
14191
 * xmlParseMemory:
14192
 * @buffer:  an pointer to a char array
14193
 * @size:  the size of the array
14194
 *
14195
 * DEPRECATED: Use xmlReadMemory.
14196
 *
14197
 * parse an XML in-memory block and build a tree.
14198
 *
14199
 * Returns the resulting document tree
14200
 */
14201
14202
0
xmlDocPtr xmlParseMemory(const char *buffer, int size) {
14203
0
   return(xmlSAXParseMemory(NULL, buffer, size, 0));
14204
0
}
14205
14206
/**
14207
 * xmlRecoverMemory:
14208
 * @buffer:  an pointer to a char array
14209
 * @size:  the size of the array
14210
 *
14211
 * DEPRECATED: Use xmlReadMemory with XML_PARSE_RECOVER.
14212
 *
14213
 * parse an XML in-memory block and build a tree.
14214
 * In the case the document is not Well Formed, an attempt to
14215
 * build a tree is tried anyway
14216
 *
14217
 * Returns the resulting document tree or NULL in case of error
14218
 */
14219
14220
0
xmlDocPtr xmlRecoverMemory(const char *buffer, int size) {
14221
0
   return(xmlSAXParseMemory(NULL, buffer, size, 1));
14222
0
}
14223
14224
/**
14225
 * xmlSAXUserParseMemory:
14226
 * @sax:  a SAX handler
14227
 * @user_data:  The user data returned on SAX callbacks
14228
 * @buffer:  an in-memory XML document input
14229
 * @size:  the length of the XML document in bytes
14230
 *
14231
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadMemory.
14232
 *
14233
 * parse an XML in-memory buffer and call the given SAX handler routines.
14234
 *
14235
 * Returns 0 in case of success or a error number otherwise
14236
 */
14237
int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
14238
0
        const char *buffer, int size) {
14239
0
    int ret = 0;
14240
0
    xmlParserCtxtPtr ctxt;
14241
14242
0
    xmlInitParser();
14243
14244
0
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
14245
0
    if (ctxt == NULL) return -1;
14246
0
    if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
14247
0
        xmlFree(ctxt->sax);
14248
0
    ctxt->sax = sax;
14249
0
    xmlDetectSAX2(ctxt);
14250
14251
0
    if (user_data != NULL)
14252
0
  ctxt->userData = user_data;
14253
14254
0
    xmlParseDocument(ctxt);
14255
14256
0
    if (ctxt->wellFormed)
14257
0
  ret = 0;
14258
0
    else {
14259
0
        if (ctxt->errNo != 0)
14260
0
      ret = ctxt->errNo;
14261
0
  else
14262
0
      ret = -1;
14263
0
    }
14264
0
    if (sax != NULL)
14265
0
        ctxt->sax = NULL;
14266
0
    if (ctxt->myDoc != NULL) {
14267
0
        xmlFreeDoc(ctxt->myDoc);
14268
0
  ctxt->myDoc = NULL;
14269
0
    }
14270
0
    xmlFreeParserCtxt(ctxt);
14271
14272
0
    return ret;
14273
0
}
14274
#endif /* LIBXML_SAX1_ENABLED */
14275
14276
/**
14277
 * xmlCreateDocParserCtxt:
14278
 * @str:  a pointer to an array of xmlChar
14279
 *
14280
 * Creates a parser context for an XML in-memory document.
14281
 *
14282
 * Returns the new parser context or NULL
14283
 */
14284
xmlParserCtxtPtr
14285
0
xmlCreateDocParserCtxt(const xmlChar *str) {
14286
0
    xmlParserCtxtPtr ctxt;
14287
0
    xmlParserInputPtr input;
14288
0
    xmlParserInputBufferPtr buf;
14289
14290
0
    if (str == NULL)
14291
0
  return(NULL);
14292
14293
0
    ctxt = xmlNewParserCtxt();
14294
0
    if (ctxt == NULL)
14295
0
  return(NULL);
14296
14297
0
    buf = xmlParserInputBufferCreateString(str);
14298
0
    if (buf == NULL) {
14299
0
  xmlFreeParserCtxt(ctxt);
14300
0
  return(NULL);
14301
0
    }
14302
14303
0
    input = xmlNewInputStream(ctxt);
14304
0
    if (input == NULL) {
14305
0
  xmlFreeParserInputBuffer(buf);
14306
0
  xmlFreeParserCtxt(ctxt);
14307
0
  return(NULL);
14308
0
    }
14309
14310
0
    input->filename = NULL;
14311
0
    input->buf = buf;
14312
0
    xmlBufResetInput(input->buf->buffer, input);
14313
14314
0
    inputPush(ctxt, input);
14315
0
    return(ctxt);
14316
0
}
14317
14318
#ifdef LIBXML_SAX1_ENABLED
14319
/**
14320
 * xmlSAXParseDoc:
14321
 * @sax:  the SAX handler block
14322
 * @cur:  a pointer to an array of xmlChar
14323
 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14324
 *             documents
14325
 *
14326
 * DEPRECATED: Use xmlNewSAXParserCtxt and xmlCtxtReadDoc.
14327
 *
14328
 * parse an XML in-memory document and build a tree.
14329
 * It use the given SAX function block to handle the parsing callback.
14330
 * If sax is NULL, fallback to the default DOM tree building routines.
14331
 *
14332
 * Returns the resulting document tree
14333
 */
14334
14335
xmlDocPtr
14336
0
xmlSAXParseDoc(xmlSAXHandlerPtr sax, const xmlChar *cur, int recovery) {
14337
0
    xmlDocPtr ret;
14338
0
    xmlParserCtxtPtr ctxt;
14339
0
    xmlSAXHandlerPtr oldsax = NULL;
14340
14341
0
    if (cur == NULL) return(NULL);
14342
14343
14344
0
    ctxt = xmlCreateDocParserCtxt(cur);
14345
0
    if (ctxt == NULL) return(NULL);
14346
0
    if (sax != NULL) {
14347
0
        oldsax = ctxt->sax;
14348
0
        ctxt->sax = sax;
14349
0
        ctxt->userData = NULL;
14350
0
    }
14351
0
    xmlDetectSAX2(ctxt);
14352
14353
0
    xmlParseDocument(ctxt);
14354
0
    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
14355
0
    else {
14356
0
       ret = NULL;
14357
0
       xmlFreeDoc(ctxt->myDoc);
14358
0
       ctxt->myDoc = NULL;
14359
0
    }
14360
0
    if (sax != NULL)
14361
0
  ctxt->sax = oldsax;
14362
0
    xmlFreeParserCtxt(ctxt);
14363
14364
0
    return(ret);
14365
0
}
14366
14367
/**
14368
 * xmlParseDoc:
14369
 * @cur:  a pointer to an array of xmlChar
14370
 *
14371
 * DEPRECATED: Use xmlReadDoc.
14372
 *
14373
 * parse an XML in-memory document and build a tree.
14374
 *
14375
 * Returns the resulting document tree
14376
 */
14377
14378
xmlDocPtr
14379
0
xmlParseDoc(const xmlChar *cur) {
14380
0
    return(xmlSAXParseDoc(NULL, cur, 0));
14381
0
}
14382
#endif /* LIBXML_SAX1_ENABLED */
14383
14384
#ifdef LIBXML_LEGACY_ENABLED
14385
/************************************************************************
14386
 *                  *
14387
 *  Specific function to keep track of entities references    *
14388
 *  and used by the XSLT debugger         *
14389
 *                  *
14390
 ************************************************************************/
14391
14392
static xmlEntityReferenceFunc xmlEntityRefFunc = NULL;
14393
14394
/**
14395
 * xmlAddEntityReference:
14396
 * @ent : A valid entity
14397
 * @firstNode : A valid first node for children of entity
14398
 * @lastNode : A valid last node of children entity
14399
 *
14400
 * Notify of a reference to an entity of type XML_EXTERNAL_GENERAL_PARSED_ENTITY
14401
 */
14402
static void
14403
xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
14404
                      xmlNodePtr lastNode)
14405
{
14406
    if (xmlEntityRefFunc != NULL) {
14407
        (*xmlEntityRefFunc) (ent, firstNode, lastNode);
14408
    }
14409
}
14410
14411
14412
/**
14413
 * xmlSetEntityReferenceFunc:
14414
 * @func: A valid function
14415
 *
14416
 * Set the function to call call back when a xml reference has been made
14417
 */
14418
void
14419
xmlSetEntityReferenceFunc(xmlEntityReferenceFunc func)
14420
{
14421
    xmlEntityRefFunc = func;
14422
}
14423
#endif /* LIBXML_LEGACY_ENABLED */
14424
14425
/************************************************************************
14426
 *                  *
14427
 *  New set (2.6.0) of simpler and more flexible APIs   *
14428
 *                  *
14429
 ************************************************************************/
14430
14431
/**
14432
 * DICT_FREE:
14433
 * @str:  a string
14434
 *
14435
 * Free a string if it is not owned by the "dict" dictionary in the
14436
 * current scope
14437
 */
14438
#define DICT_FREE(str)            \
14439
0
  if ((str) && ((!dict) ||       \
14440
0
      (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))  \
14441
0
      xmlFree((char *)(str));
14442
14443
/**
14444
 * xmlCtxtReset:
14445
 * @ctxt: an XML parser context
14446
 *
14447
 * Reset a parser context
14448
 */
14449
void
14450
xmlCtxtReset(xmlParserCtxtPtr ctxt)
14451
0
{
14452
0
    xmlParserInputPtr input;
14453
0
    xmlDictPtr dict;
14454
14455
0
    if (ctxt == NULL)
14456
0
        return;
14457
14458
0
    dict = ctxt->dict;
14459
14460
0
    while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
14461
0
        xmlFreeInputStream(input);
14462
0
    }
14463
0
    ctxt->inputNr = 0;
14464
0
    ctxt->input = NULL;
14465
14466
0
    ctxt->spaceNr = 0;
14467
0
    if (ctxt->spaceTab != NULL) {
14468
0
  ctxt->spaceTab[0] = -1;
14469
0
  ctxt->space = &ctxt->spaceTab[0];
14470
0
    } else {
14471
0
        ctxt->space = NULL;
14472
0
    }
14473
14474
14475
0
    ctxt->nodeNr = 0;
14476
0
    ctxt->node = NULL;
14477
14478
0
    ctxt->nameNr = 0;
14479
0
    ctxt->name = NULL;
14480
14481
0
    ctxt->nsNr = 0;
14482
0
    xmlParserNsReset(ctxt->nsdb);
14483
14484
0
    DICT_FREE(ctxt->version);
14485
0
    ctxt->version = NULL;
14486
0
    DICT_FREE(ctxt->encoding);
14487
0
    ctxt->encoding = NULL;
14488
0
    DICT_FREE(ctxt->directory);
14489
0
    ctxt->directory = NULL;
14490
0
    DICT_FREE(ctxt->extSubURI);
14491
0
    ctxt->extSubURI = NULL;
14492
0
    DICT_FREE(ctxt->extSubSystem);
14493
0
    ctxt->extSubSystem = NULL;
14494
0
    if (ctxt->myDoc != NULL)
14495
0
        xmlFreeDoc(ctxt->myDoc);
14496
0
    ctxt->myDoc = NULL;
14497
14498
0
    ctxt->standalone = -1;
14499
0
    ctxt->hasExternalSubset = 0;
14500
0
    ctxt->hasPErefs = 0;
14501
0
    ctxt->html = 0;
14502
0
    ctxt->external = 0;
14503
0
    ctxt->instate = XML_PARSER_START;
14504
0
    ctxt->token = 0;
14505
14506
0
    ctxt->wellFormed = 1;
14507
0
    ctxt->nsWellFormed = 1;
14508
0
    ctxt->disableSAX = 0;
14509
0
    ctxt->valid = 1;
14510
#if 0
14511
    ctxt->vctxt.userData = ctxt;
14512
    ctxt->vctxt.error = xmlParserValidityError;
14513
    ctxt->vctxt.warning = xmlParserValidityWarning;
14514
#endif
14515
0
    ctxt->record_info = 0;
14516
0
    ctxt->checkIndex = 0;
14517
0
    ctxt->endCheckState = 0;
14518
0
    ctxt->inSubset = 0;
14519
0
    ctxt->errNo = XML_ERR_OK;
14520
0
    ctxt->depth = 0;
14521
0
    ctxt->catalogs = NULL;
14522
0
    ctxt->sizeentities = 0;
14523
0
    ctxt->sizeentcopy = 0;
14524
0
    xmlInitNodeInfoSeq(&ctxt->node_seq);
14525
14526
0
    if (ctxt->attsDefault != NULL) {
14527
0
        xmlHashFree(ctxt->attsDefault, xmlHashDefaultDeallocator);
14528
0
        ctxt->attsDefault = NULL;
14529
0
    }
14530
0
    if (ctxt->attsSpecial != NULL) {
14531
0
        xmlHashFree(ctxt->attsSpecial, NULL);
14532
0
        ctxt->attsSpecial = NULL;
14533
0
    }
14534
14535
0
#ifdef LIBXML_CATALOG_ENABLED
14536
0
    if (ctxt->catalogs != NULL)
14537
0
  xmlCatalogFreeLocal(ctxt->catalogs);
14538
0
#endif
14539
0
    ctxt->nbErrors = 0;
14540
0
    ctxt->nbWarnings = 0;
14541
0
    if (ctxt->lastError.code != XML_ERR_OK)
14542
0
        xmlResetError(&ctxt->lastError);
14543
0
}
14544
14545
/**
14546
 * xmlCtxtResetPush:
14547
 * @ctxt: an XML parser context
14548
 * @chunk:  a pointer to an array of chars
14549
 * @size:  number of chars in the array
14550
 * @filename:  an optional file name or URI
14551
 * @encoding:  the document encoding, or NULL
14552
 *
14553
 * Reset a push parser context
14554
 *
14555
 * Returns 0 in case of success and 1 in case of error
14556
 */
14557
int
14558
xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk,
14559
                 int size, const char *filename, const char *encoding)
14560
0
{
14561
0
    xmlParserInputPtr inputStream;
14562
0
    xmlParserInputBufferPtr buf;
14563
14564
0
    if (ctxt == NULL)
14565
0
        return(1);
14566
14567
0
    buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE);
14568
0
    if (buf == NULL)
14569
0
        return(1);
14570
14571
0
    if (ctxt == NULL) {
14572
0
        xmlFreeParserInputBuffer(buf);
14573
0
        return(1);
14574
0
    }
14575
14576
0
    xmlCtxtReset(ctxt);
14577
14578
0
    if (filename == NULL) {
14579
0
        ctxt->directory = NULL;
14580
0
    } else {
14581
0
        ctxt->directory = xmlParserGetDirectory(filename);
14582
0
    }
14583
14584
0
    inputStream = xmlNewInputStream(ctxt);
14585
0
    if (inputStream == NULL) {
14586
0
        xmlFreeParserInputBuffer(buf);
14587
0
        return(1);
14588
0
    }
14589
14590
0
    if (filename == NULL)
14591
0
        inputStream->filename = NULL;
14592
0
    else
14593
0
        inputStream->filename = (char *)
14594
0
            xmlCanonicPath((const xmlChar *) filename);
14595
0
    inputStream->buf = buf;
14596
0
    xmlBufResetInput(buf->buffer, inputStream);
14597
14598
0
    inputPush(ctxt, inputStream);
14599
14600
0
    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
14601
0
        (ctxt->input->buf != NULL)) {
14602
0
        size_t pos = ctxt->input->cur - ctxt->input->base;
14603
0
        int res;
14604
14605
0
        res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
14606
0
        xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos);
14607
0
        if (res < 0) {
14608
0
            xmlFatalErr(ctxt, ctxt->input->buf->error, NULL);
14609
0
            xmlHaltParser(ctxt);
14610
0
            return(1);
14611
0
        }
14612
0
    }
14613
14614
0
    if (encoding != NULL) {
14615
0
        xmlCharEncodingHandlerPtr hdlr;
14616
14617
0
        hdlr = xmlFindCharEncodingHandler(encoding);
14618
0
        if (hdlr != NULL) {
14619
0
            xmlSwitchToEncoding(ctxt, hdlr);
14620
0
  } else {
14621
0
      xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
14622
0
            "Unsupported encoding %s\n", BAD_CAST encoding);
14623
0
        }
14624
0
    }
14625
14626
0
    return(0);
14627
0
}
14628
14629
14630
/**
14631
 * xmlCtxtUseOptionsInternal:
14632
 * @ctxt: an XML parser context
14633
 * @options:  a combination of xmlParserOption
14634
 * @encoding:  the user provided encoding to use
14635
 *
14636
 * Applies the options to the parser context
14637
 *
14638
 * Returns 0 in case of success, the set of unknown or unimplemented options
14639
 *         in case of error.
14640
 */
14641
static int
14642
xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options)
14643
0
{
14644
0
    if (ctxt == NULL)
14645
0
        return(-1);
14646
0
    if (options & XML_PARSE_RECOVER) {
14647
0
        ctxt->recovery = 1;
14648
0
        options -= XML_PARSE_RECOVER;
14649
0
  ctxt->options |= XML_PARSE_RECOVER;
14650
0
    } else
14651
0
        ctxt->recovery = 0;
14652
0
    if (options & XML_PARSE_DTDLOAD) {
14653
0
        ctxt->loadsubset = XML_DETECT_IDS;
14654
0
        options -= XML_PARSE_DTDLOAD;
14655
0
  ctxt->options |= XML_PARSE_DTDLOAD;
14656
0
    } else
14657
0
        ctxt->loadsubset = 0;
14658
0
    if (options & XML_PARSE_DTDATTR) {
14659
0
        ctxt->loadsubset |= XML_COMPLETE_ATTRS;
14660
0
        options -= XML_PARSE_DTDATTR;
14661
0
  ctxt->options |= XML_PARSE_DTDATTR;
14662
0
    }
14663
0
    if (options & XML_PARSE_NOENT) {
14664
0
        ctxt->replaceEntities = 1;
14665
        /* ctxt->loadsubset |= XML_DETECT_IDS; */
14666
0
        options -= XML_PARSE_NOENT;
14667
0
  ctxt->options |= XML_PARSE_NOENT;
14668
0
    } else
14669
0
        ctxt->replaceEntities = 0;
14670
0
    if (options & XML_PARSE_PEDANTIC) {
14671
0
        ctxt->pedantic = 1;
14672
0
        options -= XML_PARSE_PEDANTIC;
14673
0
  ctxt->options |= XML_PARSE_PEDANTIC;
14674
0
    } else
14675
0
        ctxt->pedantic = 0;
14676
0
    if (options & XML_PARSE_NOBLANKS) {
14677
0
        ctxt->keepBlanks = 0;
14678
0
        ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
14679
0
        options -= XML_PARSE_NOBLANKS;
14680
0
  ctxt->options |= XML_PARSE_NOBLANKS;
14681
0
    } else
14682
0
        ctxt->keepBlanks = 1;
14683
0
    if (options & XML_PARSE_DTDVALID) {
14684
0
        ctxt->validate = 1;
14685
0
        if (options & XML_PARSE_NOWARNING)
14686
0
            ctxt->vctxt.warning = NULL;
14687
0
        if (options & XML_PARSE_NOERROR)
14688
0
            ctxt->vctxt.error = NULL;
14689
0
        options -= XML_PARSE_DTDVALID;
14690
0
  ctxt->options |= XML_PARSE_DTDVALID;
14691
0
    } else
14692
0
        ctxt->validate = 0;
14693
0
    if (options & XML_PARSE_NOWARNING) {
14694
0
        ctxt->sax->warning = NULL;
14695
0
        options -= XML_PARSE_NOWARNING;
14696
0
    }
14697
0
    if (options & XML_PARSE_NOERROR) {
14698
0
        ctxt->sax->error = NULL;
14699
0
        ctxt->sax->fatalError = NULL;
14700
0
        options -= XML_PARSE_NOERROR;
14701
0
    }
14702
0
#ifdef LIBXML_SAX1_ENABLED
14703
0
    if (options & XML_PARSE_SAX1) {
14704
0
        ctxt->sax->startElementNs = NULL;
14705
0
        ctxt->sax->endElementNs = NULL;
14706
0
        ctxt->sax->initialized = 1;
14707
0
        options -= XML_PARSE_SAX1;
14708
0
  ctxt->options |= XML_PARSE_SAX1;
14709
0
    }
14710
0
#endif /* LIBXML_SAX1_ENABLED */
14711
0
    if (options & XML_PARSE_NODICT) {
14712
0
        ctxt->dictNames = 0;
14713
0
        options -= XML_PARSE_NODICT;
14714
0
  ctxt->options |= XML_PARSE_NODICT;
14715
0
    } else {
14716
0
        ctxt->dictNames = 1;
14717
0
    }
14718
0
    if (options & XML_PARSE_NOCDATA) {
14719
0
        ctxt->sax->cdataBlock = NULL;
14720
0
        options -= XML_PARSE_NOCDATA;
14721
0
  ctxt->options |= XML_PARSE_NOCDATA;
14722
0
    }
14723
0
    if (options & XML_PARSE_NSCLEAN) {
14724
0
  ctxt->options |= XML_PARSE_NSCLEAN;
14725
0
        options -= XML_PARSE_NSCLEAN;
14726
0
    }
14727
0
    if (options & XML_PARSE_NONET) {
14728
0
  ctxt->options |= XML_PARSE_NONET;
14729
0
        options -= XML_PARSE_NONET;
14730
0
    }
14731
0
    if (options & XML_PARSE_COMPACT) {
14732
0
  ctxt->options |= XML_PARSE_COMPACT;
14733
0
        options -= XML_PARSE_COMPACT;
14734
0
    }
14735
0
    if (options & XML_PARSE_OLD10) {
14736
0
  ctxt->options |= XML_PARSE_OLD10;
14737
0
        options -= XML_PARSE_OLD10;
14738
0
    }
14739
0
    if (options & XML_PARSE_NOBASEFIX) {
14740
0
  ctxt->options |= XML_PARSE_NOBASEFIX;
14741
0
        options -= XML_PARSE_NOBASEFIX;
14742
0
    }
14743
0
    if (options & XML_PARSE_HUGE) {
14744
0
  ctxt->options |= XML_PARSE_HUGE;
14745
0
        options -= XML_PARSE_HUGE;
14746
0
        if (ctxt->dict != NULL)
14747
0
            xmlDictSetLimit(ctxt->dict, 0);
14748
0
    }
14749
0
    if (options & XML_PARSE_OLDSAX) {
14750
0
  ctxt->options |= XML_PARSE_OLDSAX;
14751
0
        options -= XML_PARSE_OLDSAX;
14752
0
    }
14753
0
    if (options & XML_PARSE_IGNORE_ENC) {
14754
0
  ctxt->options |= XML_PARSE_IGNORE_ENC;
14755
0
        options -= XML_PARSE_IGNORE_ENC;
14756
0
    }
14757
0
    if (options & XML_PARSE_BIG_LINES) {
14758
0
  ctxt->options |= XML_PARSE_BIG_LINES;
14759
0
        options -= XML_PARSE_BIG_LINES;
14760
0
    }
14761
0
    ctxt->linenumbers = 1;
14762
0
    return (options);
14763
0
}
14764
14765
/**
14766
 * xmlCtxtUseOptions:
14767
 * @ctxt: an XML parser context
14768
 * @options:  a combination of xmlParserOption
14769
 *
14770
 * Applies the options to the parser context
14771
 *
14772
 * Returns 0 in case of success, the set of unknown or unimplemented options
14773
 *         in case of error.
14774
 */
14775
int
14776
xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options)
14777
0
{
14778
0
   return(xmlCtxtUseOptionsInternal(ctxt, options));
14779
0
}
14780
14781
/**
14782
 * xmlCtxtSetMaxAmplification:
14783
 * @ctxt: an XML parser context
14784
 * @maxAmpl:  maximum amplification factor
14785
 *
14786
 * To protect against exponential entity expansion ("billion laughs"), the
14787
 * size of serialized output is (roughly) limited to the input size
14788
 * multiplied by this factor. The default value is 5.
14789
 *
14790
 * When working with documents making heavy use of entity expansion, it can
14791
 * be necessary to increase the value. For security reasons, this should only
14792
 * be considered when processing trusted input.
14793
 */
14794
void
14795
xmlCtxtSetMaxAmplification(xmlParserCtxtPtr ctxt, unsigned maxAmpl)
14796
0
{
14797
0
    ctxt->maxAmpl = maxAmpl;
14798
0
}
14799
14800
/**
14801
 * xmlDoRead:
14802
 * @ctxt:  an XML parser context
14803
 * @URL:  the base URL to use for the document
14804
 * @encoding:  the document encoding, or NULL
14805
 * @options:  a combination of xmlParserOption
14806
 * @reuse:  keep the context for reuse
14807
 *
14808
 * Common front-end for the xmlRead functions
14809
 *
14810
 * Returns the resulting document tree or NULL
14811
 */
14812
static xmlDocPtr
14813
xmlDoRead(xmlParserCtxtPtr ctxt, const char *URL, const char *encoding,
14814
          int options, int reuse)
14815
0
{
14816
0
    xmlDocPtr ret;
14817
14818
0
    xmlCtxtUseOptionsInternal(ctxt, options);
14819
0
    if (encoding != NULL) {
14820
0
        xmlCharEncodingHandlerPtr hdlr;
14821
14822
        /*
14823
         * TODO: We should consider to set XML_PARSE_IGNORE_ENC if the
14824
         * caller provided an encoding. Otherwise, we might switch to
14825
         * the encoding from the XML declaration which is likely to
14826
         * break things. Also see xmlSwitchInputEncoding.
14827
         */
14828
0
  hdlr = xmlFindCharEncodingHandler(encoding);
14829
0
  if (hdlr != NULL)
14830
0
      xmlSwitchToEncoding(ctxt, hdlr);
14831
0
    }
14832
0
    if ((URL != NULL) && (ctxt->input != NULL) &&
14833
0
        (ctxt->input->filename == NULL))
14834
0
        ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL);
14835
0
    xmlParseDocument(ctxt);
14836
0
    if ((ctxt->wellFormed) || ctxt->recovery)
14837
0
        ret = ctxt->myDoc;
14838
0
    else {
14839
0
        ret = NULL;
14840
0
  if (ctxt->myDoc != NULL) {
14841
0
      xmlFreeDoc(ctxt->myDoc);
14842
0
  }
14843
0
    }
14844
0
    ctxt->myDoc = NULL;
14845
0
    if (!reuse) {
14846
0
  xmlFreeParserCtxt(ctxt);
14847
0
    }
14848
14849
0
    return (ret);
14850
0
}
14851
14852
/**
14853
 * xmlReadDoc:
14854
 * @cur:  a pointer to a zero terminated string
14855
 * @URL:  the base URL to use for the document
14856
 * @encoding:  the document encoding, or NULL
14857
 * @options:  a combination of xmlParserOption
14858
 *
14859
 * parse an XML in-memory document and build a tree.
14860
 *
14861
 * Returns the resulting document tree
14862
 */
14863
xmlDocPtr
14864
xmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int options)
14865
0
{
14866
0
    xmlParserCtxtPtr ctxt;
14867
14868
0
    if (cur == NULL)
14869
0
        return (NULL);
14870
0
    xmlInitParser();
14871
14872
0
    ctxt = xmlCreateDocParserCtxt(cur);
14873
0
    if (ctxt == NULL)
14874
0
        return (NULL);
14875
0
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
14876
0
}
14877
14878
/**
14879
 * xmlReadFile:
14880
 * @filename:  a file or URL
14881
 * @encoding:  the document encoding, or NULL
14882
 * @options:  a combination of xmlParserOption
14883
 *
14884
 * parse an XML file from the filesystem or the network.
14885
 *
14886
 * Returns the resulting document tree
14887
 */
14888
xmlDocPtr
14889
xmlReadFile(const char *filename, const char *encoding, int options)
14890
0
{
14891
0
    xmlParserCtxtPtr ctxt;
14892
14893
0
    xmlInitParser();
14894
0
    ctxt = xmlCreateURLParserCtxt(filename, options);
14895
0
    if (ctxt == NULL)
14896
0
        return (NULL);
14897
0
    return (xmlDoRead(ctxt, NULL, encoding, options, 0));
14898
0
}
14899
14900
/**
14901
 * xmlReadMemory:
14902
 * @buffer:  a pointer to a char array
14903
 * @size:  the size of the array
14904
 * @URL:  the base URL to use for the document
14905
 * @encoding:  the document encoding, or NULL
14906
 * @options:  a combination of xmlParserOption
14907
 *
14908
 * parse an XML in-memory document and build a tree.
14909
 *
14910
 * Returns the resulting document tree
14911
 */
14912
xmlDocPtr
14913
xmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options)
14914
0
{
14915
0
    xmlParserCtxtPtr ctxt;
14916
14917
0
    xmlInitParser();
14918
0
    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
14919
0
    if (ctxt == NULL)
14920
0
        return (NULL);
14921
0
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
14922
0
}
14923
14924
/**
14925
 * xmlReadFd:
14926
 * @fd:  an open file descriptor
14927
 * @URL:  the base URL to use for the document
14928
 * @encoding:  the document encoding, or NULL
14929
 * @options:  a combination of xmlParserOption
14930
 *
14931
 * parse an XML from a file descriptor and build a tree.
14932
 * NOTE that the file descriptor will not be closed when the
14933
 *      reader is closed or reset.
14934
 *
14935
 * Returns the resulting document tree
14936
 */
14937
xmlDocPtr
14938
xmlReadFd(int fd, const char *URL, const char *encoding, int options)
14939
0
{
14940
0
    xmlParserCtxtPtr ctxt;
14941
0
    xmlParserInputBufferPtr input;
14942
0
    xmlParserInputPtr stream;
14943
14944
0
    if (fd < 0)
14945
0
        return (NULL);
14946
0
    xmlInitParser();
14947
14948
0
    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
14949
0
    if (input == NULL)
14950
0
        return (NULL);
14951
0
    input->closecallback = NULL;
14952
0
    ctxt = xmlNewParserCtxt();
14953
0
    if (ctxt == NULL) {
14954
0
        xmlFreeParserInputBuffer(input);
14955
0
        return (NULL);
14956
0
    }
14957
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
14958
0
    if (stream == NULL) {
14959
0
        xmlFreeParserInputBuffer(input);
14960
0
  xmlFreeParserCtxt(ctxt);
14961
0
        return (NULL);
14962
0
    }
14963
0
    inputPush(ctxt, stream);
14964
0
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
14965
0
}
14966
14967
/**
14968
 * xmlReadIO:
14969
 * @ioread:  an I/O read function
14970
 * @ioclose:  an I/O close function
14971
 * @ioctx:  an I/O handler
14972
 * @URL:  the base URL to use for the document
14973
 * @encoding:  the document encoding, or NULL
14974
 * @options:  a combination of xmlParserOption
14975
 *
14976
 * parse an XML document from I/O functions and source and build a tree.
14977
 *
14978
 * Returns the resulting document tree
14979
 */
14980
xmlDocPtr
14981
xmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
14982
          void *ioctx, const char *URL, const char *encoding, int options)
14983
0
{
14984
0
    xmlParserCtxtPtr ctxt;
14985
0
    xmlParserInputBufferPtr input;
14986
0
    xmlParserInputPtr stream;
14987
14988
0
    if (ioread == NULL)
14989
0
        return (NULL);
14990
0
    xmlInitParser();
14991
14992
0
    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
14993
0
                                         XML_CHAR_ENCODING_NONE);
14994
0
    if (input == NULL) {
14995
0
        if (ioclose != NULL)
14996
0
            ioclose(ioctx);
14997
0
        return (NULL);
14998
0
    }
14999
0
    ctxt = xmlNewParserCtxt();
15000
0
    if (ctxt == NULL) {
15001
0
        xmlFreeParserInputBuffer(input);
15002
0
        return (NULL);
15003
0
    }
15004
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15005
0
    if (stream == NULL) {
15006
0
        xmlFreeParserInputBuffer(input);
15007
0
  xmlFreeParserCtxt(ctxt);
15008
0
        return (NULL);
15009
0
    }
15010
0
    inputPush(ctxt, stream);
15011
0
    return (xmlDoRead(ctxt, URL, encoding, options, 0));
15012
0
}
15013
15014
/**
15015
 * xmlCtxtReadDoc:
15016
 * @ctxt:  an XML parser context
15017
 * @str:  a pointer to a zero terminated string
15018
 * @URL:  the base URL to use for the document
15019
 * @encoding:  the document encoding, or NULL
15020
 * @options:  a combination of xmlParserOption
15021
 *
15022
 * parse an XML in-memory document and build a tree.
15023
 * This reuses the existing @ctxt parser context
15024
 *
15025
 * Returns the resulting document tree
15026
 */
15027
xmlDocPtr
15028
xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar *str,
15029
               const char *URL, const char *encoding, int options)
15030
0
{
15031
0
    xmlParserInputBufferPtr input;
15032
0
    xmlParserInputPtr stream;
15033
15034
0
    if (ctxt == NULL)
15035
0
        return (NULL);
15036
0
    if (str == NULL)
15037
0
        return (NULL);
15038
0
    xmlInitParser();
15039
15040
0
    xmlCtxtReset(ctxt);
15041
15042
0
    input = xmlParserInputBufferCreateString(str);
15043
0
    if (input == NULL) {
15044
0
  return(NULL);
15045
0
    }
15046
15047
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15048
0
    if (stream == NULL) {
15049
0
  xmlFreeParserInputBuffer(input);
15050
0
  return(NULL);
15051
0
    }
15052
15053
0
    inputPush(ctxt, stream);
15054
0
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15055
0
}
15056
15057
/**
15058
 * xmlCtxtReadFile:
15059
 * @ctxt:  an XML parser context
15060
 * @filename:  a file or URL
15061
 * @encoding:  the document encoding, or NULL
15062
 * @options:  a combination of xmlParserOption
15063
 *
15064
 * parse an XML file from the filesystem or the network.
15065
 * This reuses the existing @ctxt parser context
15066
 *
15067
 * Returns the resulting document tree
15068
 */
15069
xmlDocPtr
15070
xmlCtxtReadFile(xmlParserCtxtPtr ctxt, const char *filename,
15071
                const char *encoding, int options)
15072
0
{
15073
0
    xmlParserInputPtr stream;
15074
15075
0
    if (filename == NULL)
15076
0
        return (NULL);
15077
0
    if (ctxt == NULL)
15078
0
        return (NULL);
15079
0
    xmlInitParser();
15080
15081
0
    xmlCtxtReset(ctxt);
15082
15083
0
    stream = xmlLoadExternalEntity(filename, NULL, ctxt);
15084
0
    if (stream == NULL) {
15085
0
        return (NULL);
15086
0
    }
15087
0
    inputPush(ctxt, stream);
15088
0
    return (xmlDoRead(ctxt, NULL, encoding, options, 1));
15089
0
}
15090
15091
/**
15092
 * xmlCtxtReadMemory:
15093
 * @ctxt:  an XML parser context
15094
 * @buffer:  a pointer to a char array
15095
 * @size:  the size of the array
15096
 * @URL:  the base URL to use for the document
15097
 * @encoding:  the document encoding, or NULL
15098
 * @options:  a combination of xmlParserOption
15099
 *
15100
 * parse an XML in-memory document and build a tree.
15101
 * This reuses the existing @ctxt parser context
15102
 *
15103
 * Returns the resulting document tree
15104
 */
15105
xmlDocPtr
15106
xmlCtxtReadMemory(xmlParserCtxtPtr ctxt, const char *buffer, int size,
15107
                  const char *URL, const char *encoding, int options)
15108
0
{
15109
0
    xmlParserInputBufferPtr input;
15110
0
    xmlParserInputPtr stream;
15111
15112
0
    if (ctxt == NULL)
15113
0
        return (NULL);
15114
0
    if (buffer == NULL)
15115
0
        return (NULL);
15116
0
    xmlInitParser();
15117
15118
0
    xmlCtxtReset(ctxt);
15119
15120
0
    input = xmlParserInputBufferCreateStatic(buffer, size,
15121
0
                                             XML_CHAR_ENCODING_NONE);
15122
0
    if (input == NULL) {
15123
0
  return(NULL);
15124
0
    }
15125
15126
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15127
0
    if (stream == NULL) {
15128
0
  xmlFreeParserInputBuffer(input);
15129
0
  return(NULL);
15130
0
    }
15131
15132
0
    inputPush(ctxt, stream);
15133
0
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15134
0
}
15135
15136
/**
15137
 * xmlCtxtReadFd:
15138
 * @ctxt:  an XML parser context
15139
 * @fd:  an open file descriptor
15140
 * @URL:  the base URL to use for the document
15141
 * @encoding:  the document encoding, or NULL
15142
 * @options:  a combination of xmlParserOption
15143
 *
15144
 * parse an XML from a file descriptor and build a tree.
15145
 * This reuses the existing @ctxt parser context
15146
 * NOTE that the file descriptor will not be closed when the
15147
 *      reader is closed or reset.
15148
 *
15149
 * Returns the resulting document tree
15150
 */
15151
xmlDocPtr
15152
xmlCtxtReadFd(xmlParserCtxtPtr ctxt, int fd,
15153
              const char *URL, const char *encoding, int options)
15154
0
{
15155
0
    xmlParserInputBufferPtr input;
15156
0
    xmlParserInputPtr stream;
15157
15158
0
    if (fd < 0)
15159
0
        return (NULL);
15160
0
    if (ctxt == NULL)
15161
0
        return (NULL);
15162
0
    xmlInitParser();
15163
15164
0
    xmlCtxtReset(ctxt);
15165
15166
15167
0
    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
15168
0
    if (input == NULL)
15169
0
        return (NULL);
15170
0
    input->closecallback = NULL;
15171
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15172
0
    if (stream == NULL) {
15173
0
        xmlFreeParserInputBuffer(input);
15174
0
        return (NULL);
15175
0
    }
15176
0
    inputPush(ctxt, stream);
15177
0
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15178
0
}
15179
15180
/**
15181
 * xmlCtxtReadIO:
15182
 * @ctxt:  an XML parser context
15183
 * @ioread:  an I/O read function
15184
 * @ioclose:  an I/O close function
15185
 * @ioctx:  an I/O handler
15186
 * @URL:  the base URL to use for the document
15187
 * @encoding:  the document encoding, or NULL
15188
 * @options:  a combination of xmlParserOption
15189
 *
15190
 * parse an XML document from I/O functions and source and build a tree.
15191
 * This reuses the existing @ctxt parser context
15192
 *
15193
 * Returns the resulting document tree
15194
 */
15195
xmlDocPtr
15196
xmlCtxtReadIO(xmlParserCtxtPtr ctxt, xmlInputReadCallback ioread,
15197
              xmlInputCloseCallback ioclose, void *ioctx,
15198
        const char *URL,
15199
              const char *encoding, int options)
15200
0
{
15201
0
    xmlParserInputBufferPtr input;
15202
0
    xmlParserInputPtr stream;
15203
15204
0
    if (ioread == NULL)
15205
0
        return (NULL);
15206
0
    if (ctxt == NULL)
15207
0
        return (NULL);
15208
0
    xmlInitParser();
15209
15210
0
    xmlCtxtReset(ctxt);
15211
15212
0
    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
15213
0
                                         XML_CHAR_ENCODING_NONE);
15214
0
    if (input == NULL) {
15215
0
        if (ioclose != NULL)
15216
0
            ioclose(ioctx);
15217
0
        return (NULL);
15218
0
    }
15219
0
    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15220
0
    if (stream == NULL) {
15221
0
        xmlFreeParserInputBuffer(input);
15222
0
        return (NULL);
15223
0
    }
15224
0
    inputPush(ctxt, stream);
15225
0
    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15226
0
}
15227