Coverage Report

Created: 2025-07-18 06:31

/src/libxml2/SAX2.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * SAX2.c : Default SAX2 handler to build a tree.
3
 *
4
 * See Copyright for the status of this software.
5
 *
6
 * Daniel Veillard <daniel@veillard.com>
7
 */
8
9
10
#define IN_LIBXML
11
#include "libxml.h"
12
#include <stdlib.h>
13
#include <string.h>
14
#include <limits.h>
15
#include <stddef.h>
16
#include <libxml/SAX2.h>
17
#include <libxml/xmlmemory.h>
18
#include <libxml/tree.h>
19
#include <libxml/parser.h>
20
#include <libxml/parserInternals.h>
21
#include <libxml/valid.h>
22
#include <libxml/entities.h>
23
#include <libxml/xmlerror.h>
24
#include <libxml/xmlIO.h>
25
#include <libxml/uri.h>
26
#include <libxml/valid.h>
27
#include <libxml/HTMLtree.h>
28
29
#include "private/error.h"
30
#include "private/parser.h"
31
#include "private/tree.h"
32
33
/*
34
 * xmlSAX2ErrMemory:
35
 * @ctxt:  an XML validation parser context
36
 * @msg:   a string to accompany the error message
37
 */
38
static void
39
1.34k
xmlSAX2ErrMemory(xmlParserCtxtPtr ctxt) {
40
1.34k
    xmlCtxtErrMemory(ctxt);
41
1.34k
}
42
43
/**
44
 * xmlValidError:
45
 * @ctxt:  an XML validation parser context
46
 * @error:  the error number
47
 * @msg:  the error message
48
 * @str1:  extra data
49
 * @str2:  extra data
50
 *
51
 * Handle a validation error
52
 */
53
static void LIBXML_ATTR_FORMAT(3,0)
54
xmlErrValid(xmlParserCtxtPtr ctxt, xmlParserErrors error,
55
            const char *msg, const xmlChar *str1, const xmlChar *str2)
56
13.0k
{
57
13.0k
    xmlCtxtErr(ctxt, NULL, XML_FROM_DTD, error, XML_ERR_ERROR,
58
13.0k
               str1, str2, NULL, 0, msg, str1, str2);
59
13.0k
    if (ctxt != NULL)
60
13.0k
  ctxt->valid = 0;
61
13.0k
}
62
63
/**
64
 * xmlFatalErrMsg:
65
 * @ctxt:  an XML parser context
66
 * @error:  the error number
67
 * @msg:  the error message
68
 * @str1:  an error string
69
 * @str2:  an error string
70
 *
71
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
72
 */
73
static void LIBXML_ATTR_FORMAT(3,0)
74
xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
75
               const char *msg, const xmlChar *str1, const xmlChar *str2)
76
1.79k
{
77
1.79k
    xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
78
1.79k
               str1, str2, NULL, 0, msg, str1, str2);
79
1.79k
}
80
81
/**
82
 * xmlWarnMsg:
83
 * @ctxt:  an XML parser context
84
 * @error:  the error number
85
 * @msg:  the error message
86
 * @str1:  an error string
87
 * @str2:  an error string
88
 *
89
 * Handle a parser warning
90
 */
91
static void LIBXML_ATTR_FORMAT(3,0)
92
xmlWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
93
               const char *msg, const xmlChar *str1)
94
6.58k
{
95
6.58k
    xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_WARNING,
96
6.58k
               str1, NULL, NULL, 0, msg, str1);
97
6.58k
}
98
99
/**
100
 * xmlNsWarnMsg:
101
 * @ctxt:  an XML parser context
102
 * @error:  the error number
103
 * @msg:  the error message
104
 * @str1:  an error string
105
 *
106
 * Handle a namespace warning
107
 */
108
static void LIBXML_ATTR_FORMAT(3,0)
109
xmlNsWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
110
             const char *msg, const xmlChar *str1, const xmlChar *str2)
111
0
{
112
0
    xmlCtxtErr(ctxt, NULL, XML_FROM_NAMESPACE, error, XML_ERR_WARNING,
113
0
               str1, str2, NULL, 0, msg, str1, str2);
114
0
}
115
116
/**
117
 * xmlSAX2GetPublicId:
118
 * @ctx: the user data (XML parser context)
119
 *
120
 * Provides the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
121
 *
122
 * Returns a xmlChar *
123
 */
124
const xmlChar *
125
xmlSAX2GetPublicId(void *ctx ATTRIBUTE_UNUSED)
126
0
{
127
    /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
128
0
    return(NULL);
129
0
}
130
131
/**
132
 * xmlSAX2GetSystemId:
133
 * @ctx: the user data (XML parser context)
134
 *
135
 * Provides the system ID, basically URL or filename e.g.
136
 * http://www.sgmlsource.com/dtds/memo.dtd
137
 *
138
 * Returns a xmlChar *
139
 */
140
const xmlChar *
141
xmlSAX2GetSystemId(void *ctx)
142
0
{
143
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
144
0
    if ((ctx == NULL) || (ctxt->input == NULL)) return(NULL);
145
0
    return((const xmlChar *) ctxt->input->filename);
146
0
}
147
148
/**
149
 * xmlSAX2GetLineNumber:
150
 * @ctx: the user data (XML parser context)
151
 *
152
 * Provide the line number of the current parsing point.
153
 *
154
 * Returns an int
155
 */
156
int
157
xmlSAX2GetLineNumber(void *ctx)
158
0
{
159
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
160
0
    if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
161
0
    return(ctxt->input->line);
162
0
}
163
164
/**
165
 * xmlSAX2GetColumnNumber:
166
 * @ctx: the user data (XML parser context)
167
 *
168
 * Provide the column number of the current parsing point.
169
 *
170
 * Returns an int
171
 */
172
int
173
xmlSAX2GetColumnNumber(void *ctx)
174
0
{
175
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
176
0
    if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
177
0
    return(ctxt->input->col);
178
0
}
179
180
/**
181
 * xmlSAX2IsStandalone:
182
 * @ctx: the user data (XML parser context)
183
 *
184
 * Is this document tagged standalone ?
185
 *
186
 * Returns 1 if true
187
 */
188
int
189
xmlSAX2IsStandalone(void *ctx)
190
0
{
191
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
192
0
    if ((ctx == NULL) || (ctxt->myDoc == NULL)) return(0);
193
0
    return(ctxt->myDoc->standalone == 1);
194
0
}
195
196
/**
197
 * xmlSAX2HasInternalSubset:
198
 * @ctx: the user data (XML parser context)
199
 *
200
 * Does this document has an internal subset
201
 *
202
 * Returns 1 if true
203
 */
204
int
205
xmlSAX2HasInternalSubset(void *ctx)
206
0
{
207
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
208
0
    if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
209
0
    return(ctxt->myDoc->intSubset != NULL);
210
0
}
211
212
/**
213
 * xmlSAX2HasExternalSubset:
214
 * @ctx: the user data (XML parser context)
215
 *
216
 * Does this document has an external subset
217
 *
218
 * Returns 1 if true
219
 */
220
int
221
xmlSAX2HasExternalSubset(void *ctx)
222
0
{
223
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
224
0
    if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
225
0
    return(ctxt->myDoc->extSubset != NULL);
226
0
}
227
228
/**
229
 * xmlSAX2InternalSubset:
230
 * @ctx:  the user data (XML parser context)
231
 * @name:  the root element name
232
 * @ExternalID:  the external ID
233
 * @SystemID:  the SYSTEM ID (e.g. filename or URL)
234
 *
235
 * Callback on internal subset declaration.
236
 */
237
void
238
xmlSAX2InternalSubset(void *ctx, const xmlChar *name,
239
         const xmlChar *ExternalID, const xmlChar *SystemID)
240
113k
{
241
113k
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
242
113k
    xmlDtdPtr dtd;
243
113k
    if (ctx == NULL) return;
244
245
113k
    if (ctxt->myDoc == NULL)
246
0
  return;
247
113k
    if ((ctxt->html) && (ctxt->instate != XML_PARSER_MISC))
248
0
        return;
249
113k
    dtd = xmlGetIntSubset(ctxt->myDoc);
250
113k
    if (dtd != NULL) {
251
0
  xmlUnlinkNode((xmlNodePtr) dtd);
252
0
  xmlFreeDtd(dtd);
253
0
  ctxt->myDoc->intSubset = NULL;
254
0
    }
255
113k
    ctxt->myDoc->intSubset =
256
113k
  xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
257
113k
    if (ctxt->myDoc->intSubset == NULL)
258
16
        xmlSAX2ErrMemory(ctxt);
259
113k
}
260
261
/**
262
 * xmlSAX2ExternalSubset:
263
 * @ctx: the user data (XML parser context)
264
 * @name:  the root element name
265
 * @ExternalID:  the external ID
266
 * @SystemID:  the SYSTEM ID (e.g. filename or URL)
267
 *
268
 * Callback on external subset declaration.
269
 */
270
void
271
xmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
272
         const xmlChar *ExternalID, const xmlChar *SystemID)
273
33.7k
{
274
33.7k
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
275
33.7k
    if (ctx == NULL) return;
276
33.7k
    if ((SystemID != NULL) &&
277
33.7k
        ((ctxt->options & XML_PARSE_NO_XXE) == 0) &&
278
33.7k
        (((ctxt->validate) || (ctxt->loadsubset)) &&
279
16.0k
   (ctxt->wellFormed && ctxt->myDoc))) {
280
  /*
281
   * Try to fetch and parse the external subset.
282
   */
283
16.0k
  xmlParserInputPtr oldinput;
284
16.0k
  int oldinputNr;
285
16.0k
  int oldinputMax;
286
16.0k
  xmlParserInputPtr *oldinputTab;
287
16.0k
  xmlParserInputPtr input = NULL;
288
16.0k
  const xmlChar *oldencoding;
289
16.0k
        unsigned long consumed;
290
16.0k
        size_t buffered;
291
16.0k
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
292
16.0k
        int inputMax = 1;
293
#else
294
        int inputMax = 5;
295
#endif
296
297
  /*
298
   * Ask the Entity resolver to load the damn thing
299
   */
300
16.0k
  if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
301
16.0k
      input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
302
16.0k
                                          SystemID);
303
16.0k
  if (input == NULL) {
304
2.49k
      return;
305
2.49k
  }
306
307
13.5k
  if (xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID) == NULL) {
308
6
            xmlSAX2ErrMemory(ctxt);
309
6
            xmlFreeInputStream(input);
310
6
            return;
311
6
        }
312
313
  /*
314
   * make sure we won't destroy the main document context
315
   */
316
13.5k
  oldinput = ctxt->input;
317
13.5k
  oldinputNr = ctxt->inputNr;
318
13.5k
  oldinputMax = ctxt->inputMax;
319
13.5k
  oldinputTab = ctxt->inputTab;
320
13.5k
  oldencoding = ctxt->encoding;
321
13.5k
  ctxt->encoding = NULL;
322
323
13.5k
  ctxt->inputTab = xmlMalloc(inputMax * sizeof(xmlParserInputPtr));
324
13.5k
  if (ctxt->inputTab == NULL) {
325
4
      xmlSAX2ErrMemory(ctxt);
326
4
            goto error;
327
4
  }
328
13.5k
  ctxt->inputNr = 0;
329
13.5k
  ctxt->inputMax = inputMax;
330
13.5k
  ctxt->input = NULL;
331
13.5k
  if (xmlCtxtPushInput(ctxt, input) < 0)
332
0
            goto error;
333
334
13.5k
  if (input->filename == NULL)
335
13.5k
      input->filename = (char *) xmlCanonicPath(SystemID);
336
13.5k
  input->line = 1;
337
13.5k
  input->col = 1;
338
13.5k
  input->base = ctxt->input->cur;
339
13.5k
  input->cur = ctxt->input->cur;
340
13.5k
  input->free = NULL;
341
342
  /*
343
   * let's parse that entity knowing it's an external subset.
344
   */
345
13.5k
  xmlParseExternalSubset(ctxt, ExternalID, SystemID);
346
347
        /*
348
   * Free up the external entities
349
   */
350
351
14.4k
  while (ctxt->inputNr > 1)
352
892
      xmlFreeInputStream(xmlCtxtPopInput(ctxt));
353
354
13.5k
        consumed = ctxt->input->consumed;
355
13.5k
        buffered = ctxt->input->cur - ctxt->input->base;
356
13.5k
        if (buffered > ULONG_MAX - consumed)
357
0
            consumed = ULONG_MAX;
358
13.5k
        else
359
13.5k
            consumed += buffered;
360
13.5k
        if (consumed > ULONG_MAX - ctxt->sizeentities)
361
0
            ctxt->sizeentities = ULONG_MAX;
362
13.5k
        else
363
13.5k
            ctxt->sizeentities += consumed;
364
365
13.5k
error:
366
13.5k
  xmlFreeInputStream(input);
367
13.5k
        xmlFree(ctxt->inputTab);
368
369
  /*
370
   * Restore the parsing context of the main entity
371
   */
372
13.5k
  ctxt->input = oldinput;
373
13.5k
  ctxt->inputNr = oldinputNr;
374
13.5k
  ctxt->inputMax = oldinputMax;
375
13.5k
  ctxt->inputTab = oldinputTab;
376
13.5k
  if ((ctxt->encoding != NULL) &&
377
13.5k
      ((ctxt->dict == NULL) ||
378
4.07k
       (!xmlDictOwns(ctxt->dict, ctxt->encoding))))
379
4.07k
      xmlFree((xmlChar *) ctxt->encoding);
380
13.5k
  ctxt->encoding = oldencoding;
381
  /* ctxt->wellFormed = oldwellFormed; */
382
13.5k
    }
383
33.7k
}
384
385
/**
386
 * xmlSAX2ResolveEntity:
387
 * @ctx: the user data (XML parser context)
388
 * @publicId: The public ID of the entity
389
 * @systemId: The system ID of the entity
390
 *
391
 * This is only used to load DTDs. The preferred way to install
392
 * custom resolvers is xmlCtxtSetResourceLoader.
393
 *
394
 * Returns a parser input.
395
 */
396
xmlParserInputPtr
397
xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId,
398
                     const xmlChar *systemId)
399
16.0k
{
400
16.0k
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
401
16.0k
    xmlParserInputPtr ret = NULL;
402
16.0k
    xmlChar *URI = NULL;
403
404
16.0k
    if (ctx == NULL) return(NULL);
405
406
16.0k
    if (systemId != NULL) {
407
16.0k
        const xmlChar *base = NULL;
408
16.0k
        int res;
409
410
16.0k
        if (ctxt->input != NULL)
411
16.0k
            base = BAD_CAST ctxt->input->filename;
412
413
        /*
414
         * We don't really need the 'directory' struct member, but some
415
         * users set it manually to a base URI for memory streams.
416
         */
417
16.0k
        if (base == NULL)
418
14.7k
            base = BAD_CAST ctxt->directory;
419
420
16.0k
        if ((xmlStrlen(systemId) > XML_MAX_URI_LENGTH) ||
421
16.0k
            (xmlStrlen(base) > XML_MAX_URI_LENGTH)) {
422
114
            xmlFatalErr(ctxt, XML_ERR_RESOURCE_LIMIT, "URI too long");
423
114
            return(NULL);
424
114
        }
425
15.8k
        res = xmlBuildURISafe(systemId, base, &URI);
426
15.8k
        if (URI == NULL) {
427
62
            if (res < 0)
428
4
                xmlSAX2ErrMemory(ctxt);
429
58
            else
430
58
                xmlWarnMsg(ctxt, XML_ERR_INVALID_URI,
431
58
                           "Can't resolve URI: %s\n", systemId);
432
62
            return(NULL);
433
62
        }
434
15.8k
        if (xmlStrlen(URI) > XML_MAX_URI_LENGTH) {
435
2
            xmlFatalErr(ctxt, XML_ERR_RESOURCE_LIMIT, "URI too long");
436
2
            xmlFree(URI);
437
2
            return(NULL);
438
2
        }
439
15.8k
    }
440
441
15.8k
    ret = xmlLoadResource(ctxt, (const char *) URI,
442
15.8k
                          (const char *) publicId, XML_RESOURCE_DTD);
443
444
15.8k
    xmlFree(URI);
445
15.8k
    return(ret);
446
16.0k
}
447
448
/**
449
 * xmlSAX2GetEntity:
450
 * @ctx: the user data (XML parser context)
451
 * @name: The entity name
452
 *
453
 * Get an entity by name
454
 *
455
 * Returns the xmlEntityPtr if found.
456
 */
457
xmlEntityPtr
458
xmlSAX2GetEntity(void *ctx, const xmlChar *name)
459
1.39M
{
460
1.39M
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
461
1.39M
    xmlEntityPtr ret = NULL;
462
463
1.39M
    if (ctx == NULL) return(NULL);
464
465
1.39M
    if (ctxt->inSubset == 0) {
466
1.32M
  ret = xmlGetPredefinedEntity(name);
467
1.32M
  if (ret != NULL)
468
0
      return(ret);
469
1.32M
    }
470
1.39M
    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->standalone == 1)) {
471
38
  if (ctxt->inSubset == 2) {
472
0
      ctxt->myDoc->standalone = 0;
473
0
      ret = xmlGetDocEntity(ctxt->myDoc, name);
474
0
      ctxt->myDoc->standalone = 1;
475
38
  } else {
476
38
      ret = xmlGetDocEntity(ctxt->myDoc, name);
477
38
      if (ret == NULL) {
478
38
    ctxt->myDoc->standalone = 0;
479
38
    ret = xmlGetDocEntity(ctxt->myDoc, name);
480
38
    if (ret != NULL) {
481
0
        xmlFatalErrMsg(ctxt, XML_ERR_NOT_STANDALONE,
482
0
   "Entity(%s) document marked standalone but requires external subset\n",
483
0
           name, NULL);
484
0
    }
485
38
    ctxt->myDoc->standalone = 1;
486
38
      }
487
38
  }
488
1.39M
    } else {
489
1.39M
  ret = xmlGetDocEntity(ctxt->myDoc, name);
490
1.39M
    }
491
1.39M
    return(ret);
492
1.39M
}
493
494
/**
495
 * xmlSAX2GetParameterEntity:
496
 * @ctx: the user data (XML parser context)
497
 * @name: The entity name
498
 *
499
 * Get a parameter entity by name
500
 *
501
 * Returns the xmlEntityPtr if found.
502
 */
503
xmlEntityPtr
504
xmlSAX2GetParameterEntity(void *ctx, const xmlChar *name)
505
136k
{
506
136k
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
507
136k
    xmlEntityPtr ret;
508
509
136k
    if (ctx == NULL) return(NULL);
510
511
136k
    ret = xmlGetParameterEntity(ctxt->myDoc, name);
512
136k
    return(ret);
513
136k
}
514
515
516
/**
517
 * xmlSAX2EntityDecl:
518
 * @ctx: the user data (XML parser context)
519
 * @name:  the entity name
520
 * @type:  the entity type
521
 * @publicId: The public ID of the entity
522
 * @systemId: The system ID of the entity
523
 * @content: the entity value (without processing).
524
 *
525
 * An entity definition has been parsed
526
 */
527
void
528
xmlSAX2EntityDecl(void *ctx, const xmlChar *name, int type,
529
          const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
530
134k
{
531
134k
    xmlEntityPtr ent;
532
134k
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
533
134k
    int extSubset;
534
134k
    int res;
535
536
134k
    if ((ctxt == NULL) || (ctxt->myDoc == NULL))
537
0
        return;
538
539
134k
    extSubset = ctxt->inSubset == 2;
540
134k
    res = xmlAddEntity(ctxt->myDoc, extSubset, name, type, publicId, systemId,
541
134k
                       content, &ent);
542
134k
    switch (res) {
543
125k
        case XML_ERR_OK:
544
125k
            break;
545
30
        case XML_ERR_NO_MEMORY:
546
30
            xmlSAX2ErrMemory(ctxt);
547
30
            return;
548
3.49k
        case XML_WAR_ENTITY_REDEFINED:
549
3.49k
            if (ctxt->pedantic) {
550
0
                if (extSubset)
551
0
                    xmlWarnMsg(ctxt, res, "Entity(%s) already defined in the"
552
0
                               " external subset\n", name);
553
0
                else
554
0
                    xmlWarnMsg(ctxt, res, "Entity(%s) already defined in the"
555
0
                               " internal subset\n", name);
556
0
            }
557
3.49k
            return;
558
5.42k
        case XML_ERR_REDECL_PREDEF_ENTITY:
559
            /*
560
             * Technically an error but it's a common mistake to get double
561
             * escaping according to "4.6 Predefined Entities" wrong.
562
             */
563
5.42k
            xmlWarnMsg(ctxt, res, "Invalid redeclaration of predefined"
564
5.42k
                       " entity '%s'", name);
565
5.42k
            return;
566
0
        default:
567
0
            xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
568
0
                           "Unexpected error code from xmlAddEntity\n",
569
0
                           NULL, NULL);
570
0
            return;
571
134k
    }
572
573
125k
    if ((ent->URI == NULL) && (systemId != NULL)) {
574
55.7k
        xmlChar *URI;
575
55.7k
        const char *base = NULL;
576
55.7k
        int i;
577
578
108k
        for (i = ctxt->inputNr - 1; i >= 0; i--) {
579
55.7k
            if (ctxt->inputTab[i]->filename != NULL) {
580
2.87k
                base = ctxt->inputTab[i]->filename;
581
2.87k
                break;
582
2.87k
            }
583
55.7k
        }
584
585
        /*
586
         * We don't really need the 'directory' struct member, but some
587
         * users set it manually to a base URI for memory streams.
588
         */
589
55.7k
        if (base == NULL)
590
52.8k
            base = ctxt->directory;
591
592
55.7k
        res = xmlBuildURISafe(systemId, (const xmlChar *) base, &URI);
593
594
55.7k
        if (URI == NULL) {
595
1.10k
            if (res < 0) {
596
5
                xmlSAX2ErrMemory(ctxt);
597
1.09k
            } else {
598
1.09k
                xmlWarnMsg(ctxt, XML_ERR_INVALID_URI,
599
1.09k
                           "Can't resolve URI: %s\n", systemId);
600
1.09k
            }
601
54.6k
        } else if (xmlStrlen(URI) > XML_MAX_URI_LENGTH) {
602
231
            xmlFatalErr(ctxt, XML_ERR_RESOURCE_LIMIT, "URI too long");
603
231
            xmlFree(URI);
604
54.4k
        } else {
605
54.4k
            ent->URI = URI;
606
54.4k
        }
607
55.7k
    }
608
125k
}
609
610
/**
611
 * xmlSAX2AttributeDecl:
612
 * @ctx: the user data (XML parser context)
613
 * @elem:  the name of the element
614
 * @fullname:  the attribute name
615
 * @type:  the attribute type
616
 * @def:  the type of default value
617
 * @defaultValue: the attribute default value
618
 * @tree:  the tree of enumerated value set
619
 *
620
 * An attribute definition has been parsed
621
 */
622
void
623
xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
624
              int type, int def, const xmlChar *defaultValue,
625
        xmlEnumerationPtr tree)
626
50.1k
{
627
50.1k
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
628
50.1k
    xmlAttributePtr attr;
629
50.1k
    const xmlChar *name = NULL;
630
50.1k
    xmlChar *prefix = NULL;
631
632
    /* Avoid unused variable warning if features are disabled. */
633
50.1k
    (void) attr;
634
635
50.1k
    if ((ctxt == NULL) || (ctxt->myDoc == NULL))
636
0
        return;
637
638
50.1k
    if ((xmlStrEqual(fullname, BAD_CAST "xml:id")) &&
639
50.1k
        (type != XML_ATTRIBUTE_ID)) {
640
  /*
641
   * Raise the error but keep the validity flag
642
   */
643
111
  int tmp = ctxt->valid;
644
111
  xmlErrValid(ctxt, XML_DTD_XMLID_TYPE,
645
111
        "xml:id : attribute type should be ID\n", NULL, NULL);
646
111
  ctxt->valid = tmp;
647
111
    }
648
50.1k
    name = xmlSplitQName4(fullname, &prefix);
649
50.1k
    if (name == NULL)
650
2
        xmlSAX2ErrMemory(ctxt);
651
50.1k
    ctxt->vctxt.valid = 1;
652
50.1k
    if (ctxt->inSubset == 1)
653
48.9k
  attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
654
48.9k
         name, prefix, (xmlAttributeType) type,
655
48.9k
         (xmlAttributeDefault) def, defaultValue, tree);
656
1.25k
    else if (ctxt->inSubset == 2)
657
1.25k
  attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
658
1.25k
     name, prefix, (xmlAttributeType) type,
659
1.25k
     (xmlAttributeDefault) def, defaultValue, tree);
660
0
    else {
661
0
        xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
662
0
       "SAX.xmlSAX2AttributeDecl(%s) called while not in subset\n",
663
0
                 name, NULL);
664
0
  xmlFree(prefix);
665
0
  xmlFreeEnumeration(tree);
666
0
  return;
667
0
    }
668
#ifdef LIBXML_VALID_ENABLED
669
    if (ctxt->vctxt.valid == 0)
670
  ctxt->valid = 0;
671
    if ((attr != NULL) && (ctxt->validate) && (ctxt->wellFormed) &&
672
        (ctxt->myDoc->intSubset != NULL))
673
  ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
674
                                          attr);
675
#endif /* LIBXML_VALID_ENABLED */
676
50.1k
    if (prefix != NULL)
677
13.0k
  xmlFree(prefix);
678
50.1k
}
679
680
/**
681
 * xmlSAX2ElementDecl:
682
 * @ctx: the user data (XML parser context)
683
 * @name:  the element name
684
 * @type:  the element type
685
 * @content: the element value tree
686
 *
687
 * An element definition has been parsed
688
 */
689
void
690
xmlSAX2ElementDecl(void *ctx, const xmlChar * name, int type,
691
            xmlElementContentPtr content)
692
37.1k
{
693
37.1k
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
694
37.1k
    xmlElementPtr elem = NULL;
695
696
    /* Avoid unused variable warning if features are disabled. */
697
37.1k
    (void) elem;
698
699
37.1k
    if ((ctxt == NULL) || (ctxt->myDoc == NULL))
700
0
        return;
701
702
37.1k
    if (ctxt->inSubset == 1)
703
34.7k
        elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
704
34.7k
                                 name, (xmlElementTypeVal) type, content);
705
2.41k
    else if (ctxt->inSubset == 2)
706
2.41k
        elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
707
2.41k
                                 name, (xmlElementTypeVal) type, content);
708
0
    else {
709
0
        xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
710
0
       "SAX.xmlSAX2ElementDecl(%s) called while not in subset\n",
711
0
                 name, NULL);
712
0
        return;
713
0
    }
714
#ifdef LIBXML_VALID_ENABLED
715
    if (elem == NULL)
716
        ctxt->valid = 0;
717
    if (ctxt->validate && ctxt->wellFormed &&
718
        ctxt->myDoc && ctxt->myDoc->intSubset)
719
        ctxt->valid &=
720
            xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
721
#endif /* LIBXML_VALID_ENABLED */
722
37.1k
}
723
724
/**
725
 * xmlSAX2NotationDecl:
726
 * @ctx: the user data (XML parser context)
727
 * @name: The name of the notation
728
 * @publicId: The public ID of the entity
729
 * @systemId: The system ID of the entity
730
 *
731
 * What to do when a notation declaration has been parsed.
732
 */
733
void
734
xmlSAX2NotationDecl(void *ctx, const xmlChar *name,
735
       const xmlChar *publicId, const xmlChar *systemId)
736
7.87k
{
737
7.87k
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
738
7.87k
    xmlNotationPtr nota = NULL;
739
740
    /* Avoid unused variable warning if features are disabled. */
741
7.87k
    (void) nota;
742
743
7.87k
    if ((ctxt == NULL) || (ctxt->myDoc == NULL))
744
0
        return;
745
746
7.87k
    if ((publicId == NULL) && (systemId == NULL)) {
747
1.79k
  xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
748
1.79k
       "SAX.xmlSAX2NotationDecl(%s) externalID or PublicID missing\n",
749
1.79k
                 name, NULL);
750
1.79k
  return;
751
6.07k
    } else if (ctxt->inSubset == 1)
752
6.07k
  nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
753
6.07k
                              publicId, systemId);
754
0
    else if (ctxt->inSubset == 2)
755
0
  nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name,
756
0
                              publicId, systemId);
757
0
    else {
758
0
  xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
759
0
       "SAX.xmlSAX2NotationDecl(%s) called while not in subset\n",
760
0
                 name, NULL);
761
0
  return;
762
0
    }
763
#ifdef LIBXML_VALID_ENABLED
764
    if (nota == NULL) ctxt->valid = 0;
765
    if ((ctxt->validate) && (ctxt->wellFormed) &&
766
        (ctxt->myDoc->intSubset != NULL))
767
  ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
768
                                         nota);
769
#endif /* LIBXML_VALID_ENABLED */
770
7.87k
}
771
772
/**
773
 * xmlSAX2UnparsedEntityDecl:
774
 * @ctx: the user data (XML parser context)
775
 * @name: The name of the entity
776
 * @publicId: The public ID of the entity
777
 * @systemId: The system ID of the entity
778
 * @notationName: the name of the notation
779
 *
780
 * What to do when an unparsed entity declaration is parsed
781
 */
782
void
783
xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name,
784
       const xmlChar *publicId, const xmlChar *systemId,
785
       const xmlChar *notationName)
786
306
{
787
306
    xmlSAX2EntityDecl(ctx, name, XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
788
306
                      publicId, systemId, (xmlChar *) notationName);
789
306
}
790
791
/**
792
 * xmlSAX2SetDocumentLocator:
793
 * @ctx: the user data (XML parser context)
794
 * @loc: A SAX Locator
795
 *
796
 * Receive the document locator at startup, actually xmlDefaultSAXLocator
797
 * Everything is available on the context, so this is useless in our case.
798
 */
799
void
800
xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
801
858k
{
802
858k
}
803
804
/**
805
 * xmlSAX2StartDocument:
806
 * @ctx: the user data (XML parser context)
807
 *
808
 * called when the document start being processed.
809
 */
810
void
811
xmlSAX2StartDocument(void *ctx)
812
798k
{
813
798k
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
814
798k
    xmlDocPtr doc;
815
816
798k
    if (ctx == NULL) return;
817
818
798k
#ifdef LIBXML_HTML_ENABLED
819
798k
    if (ctxt->html) {
820
0
  if (ctxt->myDoc == NULL)
821
0
      ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
822
0
  if (ctxt->myDoc == NULL) {
823
0
      xmlSAX2ErrMemory(ctxt);
824
0
      return;
825
0
  }
826
0
  ctxt->myDoc->properties = XML_DOC_HTML;
827
0
  ctxt->myDoc->parseFlags = ctxt->options;
828
0
    } else
829
798k
#endif
830
798k
    {
831
798k
  doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
832
798k
  if (doc != NULL) {
833
798k
      doc->properties = 0;
834
798k
      if (ctxt->options & XML_PARSE_OLD10)
835
0
          doc->properties |= XML_DOC_OLD10;
836
798k
      doc->parseFlags = ctxt->options;
837
798k
      doc->standalone = ctxt->standalone;
838
798k
  } else {
839
90
      xmlSAX2ErrMemory(ctxt);
840
90
      return;
841
90
  }
842
798k
  if ((ctxt->dictNames) && (doc != NULL)) {
843
798k
      doc->dict = ctxt->dict;
844
798k
      xmlDictReference(doc->dict);
845
798k
  }
846
798k
    }
847
798k
    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
848
798k
  (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
849
63.5k
  ctxt->myDoc->URL = xmlPathToURI((const xmlChar *)ctxt->input->filename);
850
63.5k
  if (ctxt->myDoc->URL == NULL)
851
0
      xmlSAX2ErrMemory(ctxt);
852
63.5k
    }
853
798k
}
854
855
/**
856
 * xmlSAX2EndDocument:
857
 * @ctx: the user data (XML parser context)
858
 *
859
 * called when the document end has been detected.
860
 */
861
void
862
xmlSAX2EndDocument(void *ctx)
863
856k
{
864
856k
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
865
856k
    xmlDocPtr doc;
866
867
856k
    if (ctx == NULL) return;
868
#ifdef LIBXML_VALID_ENABLED
869
    if (ctxt->validate && ctxt->wellFormed &&
870
        ctxt->myDoc && ctxt->myDoc->intSubset)
871
  ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
872
#endif /* LIBXML_VALID_ENABLED */
873
874
856k
    doc = ctxt->myDoc;
875
856k
    if ((doc != NULL) && (doc->encoding == NULL)) {
876
814k
        const xmlChar *encoding = xmlGetActualEncoding(ctxt);
877
878
814k
        if (encoding != NULL) {
879
105k
            doc->encoding = xmlStrdup(encoding);
880
105k
            if (doc->encoding == NULL)
881
310
                xmlSAX2ErrMemory(ctxt);
882
105k
        }
883
814k
    }
884
856k
}
885
886
static void
887
6.93M
xmlSAX2AppendChild(xmlParserCtxtPtr ctxt, xmlNodePtr node) {
888
6.93M
    xmlNodePtr parent;
889
6.93M
    xmlNodePtr last;
890
891
6.93M
    if (ctxt->inSubset == 1) {
892
19.6k
  parent = (xmlNodePtr) ctxt->myDoc->intSubset;
893
6.91M
    } else if (ctxt->inSubset == 2) {
894
5.95k
  parent = (xmlNodePtr) ctxt->myDoc->extSubset;
895
6.90M
    } else {
896
6.90M
        parent = ctxt->node;
897
6.90M
        if (parent == NULL)
898
733k
            parent = (xmlNodePtr) ctxt->myDoc;
899
6.90M
    }
900
901
6.93M
    last = parent->last;
902
6.93M
    if (last == NULL) {
903
965k
        parent->children = node;
904
5.96M
    } else {
905
5.96M
        last->next = node;
906
5.96M
        node->prev = last;
907
5.96M
    }
908
909
6.93M
    parent->last = node;
910
6.93M
    node->parent = parent;
911
912
6.93M
    if ((node->type != XML_TEXT_NODE) &&
913
6.93M
        (ctxt->linenumbers) &&
914
6.93M
  (ctxt->input != NULL)) {
915
4.10M
        if ((unsigned) ctxt->input->line < (unsigned) USHRT_MAX)
916
4.10M
            node->line = ctxt->input->line;
917
5.18k
        else
918
5.18k
            node->line = USHRT_MAX;
919
4.10M
    }
920
6.93M
}
921
922
#if defined(LIBXML_SAX1_ENABLED)
923
/**
924
 * xmlNsErrMsg:
925
 * @ctxt:  an XML parser context
926
 * @error:  the error number
927
 * @msg:  the error message
928
 * @str1:  an error string
929
 * @str2:  an error string
930
 *
931
 * Handle a namespace error
932
 */
933
static void LIBXML_ATTR_FORMAT(3,0)
934
xmlNsErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
935
            const char *msg, const xmlChar *str1, const xmlChar *str2)
936
{
937
    xmlCtxtErr(ctxt, NULL, XML_FROM_NAMESPACE, error, XML_ERR_ERROR,
938
               str1, str2, NULL, 0, msg, str1, str2);
939
}
940
941
/**
942
 * xmlSAX1Attribute:
943
 * @ctx: the user data (XML parser context)
944
 * @fullname:  The attribute name, including namespace prefix
945
 * @value:  The attribute value
946
 *
947
 * Handle an attribute that has been read by the parser.
948
 *
949
 * Deprecated SAX1 interface.
950
 */
951
static void
952
xmlSAX1Attribute(xmlParserCtxtPtr ctxt, const xmlChar *fullname,
953
                 const xmlChar *value, const xmlChar *prefix)
954
{
955
    xmlAttrPtr ret;
956
    const xmlChar *name;
957
    xmlChar *ns;
958
    xmlNsPtr namespace;
959
960
    /*
961
     * Split the full name into a namespace prefix and the tag name
962
     */
963
    name = xmlSplitQName4(fullname, &ns);
964
    if (name == NULL) {
965
        xmlSAX2ErrMemory(ctxt);
966
        return;
967
    }
968
969
    /*
970
     * Check whether it's a namespace definition
971
     */
972
    if ((ns == NULL) &&
973
        (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
974
        (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
975
  xmlNsPtr nsret;
976
  xmlChar *val;
977
978
        /* Avoid unused variable warning if features are disabled. */
979
        (void) nsret;
980
981
        if (!ctxt->replaceEntities) {
982
            /* TODO: normalize if needed */
983
      val = xmlExpandEntitiesInAttValue(ctxt, value, /* normalize */ 0);
984
      if (val == NULL) {
985
          xmlSAX2ErrMemory(ctxt);
986
    return;
987
      }
988
  } else {
989
      val = (xmlChar *) value;
990
  }
991
992
  if (val[0] != 0) {
993
      xmlURIPtr uri;
994
995
      if (xmlParseURISafe((const char *)val, &uri) < 0)
996
                xmlSAX2ErrMemory(ctxt);
997
      if (uri == NULL) {
998
                xmlNsWarnMsg(ctxt, XML_WAR_NS_URI,
999
                             "xmlns:%s: %s not a valid URI\n", name, value);
1000
      } else {
1001
    if (uri->scheme == NULL) {
1002
                    xmlNsWarnMsg(ctxt, XML_WAR_NS_URI_RELATIVE,
1003
                                 "xmlns:%s: URI %s is not absolute\n",
1004
                                 name, value);
1005
    }
1006
    xmlFreeURI(uri);
1007
      }
1008
  }
1009
1010
  /* a default namespace definition */
1011
  nsret = xmlNewNs(ctxt->node, val, NULL);
1012
        if (nsret == NULL) {
1013
            xmlSAX2ErrMemory(ctxt);
1014
        }
1015
#ifdef LIBXML_VALID_ENABLED
1016
  /*
1017
   * Validate also for namespace decls, they are attributes from
1018
   * an XML-1.0 perspective
1019
   */
1020
        else if (ctxt->validate && ctxt->wellFormed &&
1021
                 ctxt->myDoc && ctxt->myDoc->intSubset) {
1022
      ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1023
             ctxt->node, prefix, nsret, val);
1024
        }
1025
#endif /* LIBXML_VALID_ENABLED */
1026
  if (val != value)
1027
      xmlFree(val);
1028
  return;
1029
    }
1030
    if ((ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
1031
        (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
1032
  xmlNsPtr nsret;
1033
  xmlChar *val;
1034
1035
        /* Avoid unused variable warning if features are disabled. */
1036
        (void) nsret;
1037
1038
        if (!ctxt->replaceEntities) {
1039
            /* TODO: normalize if needed */
1040
      val = xmlExpandEntitiesInAttValue(ctxt, value, /* normalize */ 0);
1041
      if (val == NULL) {
1042
          xmlSAX2ErrMemory(ctxt);
1043
          xmlFree(ns);
1044
    return;
1045
      }
1046
  } else {
1047
      val = (xmlChar *) value;
1048
  }
1049
1050
  if (val[0] == 0) {
1051
      xmlNsErrMsg(ctxt, XML_NS_ERR_EMPTY,
1052
            "Empty namespace name for prefix %s\n", name, NULL);
1053
  }
1054
  if ((ctxt->pedantic != 0) && (val[0] != 0)) {
1055
      xmlURIPtr uri;
1056
1057
      if (xmlParseURISafe((const char *)val, &uri) < 0)
1058
                xmlSAX2ErrMemory(ctxt);
1059
      if (uri == NULL) {
1060
          xmlNsWarnMsg(ctxt, XML_WAR_NS_URI,
1061
       "xmlns:%s: %s not a valid URI\n", name, value);
1062
      } else {
1063
    if (uri->scheme == NULL) {
1064
        xmlNsWarnMsg(ctxt, XML_WAR_NS_URI_RELATIVE,
1065
         "xmlns:%s: URI %s is not absolute\n", name, value);
1066
    }
1067
    xmlFreeURI(uri);
1068
      }
1069
  }
1070
1071
  /* a standard namespace definition */
1072
  nsret = xmlNewNs(ctxt->node, val, name);
1073
  xmlFree(ns);
1074
1075
        if (nsret == NULL) {
1076
            xmlSAX2ErrMemory(ctxt);
1077
        }
1078
#ifdef LIBXML_VALID_ENABLED
1079
  /*
1080
   * Validate also for namespace decls, they are attributes from
1081
   * an XML-1.0 perspective
1082
   */
1083
        else if (ctxt->validate && ctxt->wellFormed &&
1084
           ctxt->myDoc && ctxt->myDoc->intSubset) {
1085
      ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1086
             ctxt->node, prefix, nsret, value);
1087
        }
1088
#endif /* LIBXML_VALID_ENABLED */
1089
  if (val != value)
1090
      xmlFree(val);
1091
  return;
1092
    }
1093
1094
    if (ns != NULL) {
1095
        int res;
1096
1097
  res = xmlSearchNsSafe(ctxt->node, ns, &namespace);
1098
        if (res < 0)
1099
            xmlSAX2ErrMemory(ctxt);
1100
1101
  if (namespace == NULL) {
1102
      xmlNsErrMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
1103
        "Namespace prefix %s of attribute %s is not defined\n",
1104
                 ns, name);
1105
  } else {
1106
            xmlAttrPtr prop;
1107
1108
            prop = ctxt->node->properties;
1109
            while (prop != NULL) {
1110
                if (prop->ns != NULL) {
1111
                    if ((xmlStrEqual(name, prop->name)) &&
1112
                        ((namespace == prop->ns) ||
1113
                         (xmlStrEqual(namespace->href, prop->ns->href)))) {
1114
                        xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER,
1115
                                   XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL,
1116
                                   name, NULL, NULL, 0,
1117
                                   "Attribute %s in %s redefined\n",
1118
                                   name, namespace->href);
1119
                        goto error;
1120
                    }
1121
                }
1122
                prop = prop->next;
1123
            }
1124
        }
1125
    } else {
1126
  namespace = NULL;
1127
    }
1128
1129
    /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
1130
    ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
1131
    if (ret == NULL) {
1132
        xmlSAX2ErrMemory(ctxt);
1133
        goto error;
1134
    }
1135
1136
    if (ctxt->replaceEntities == 0) {
1137
        if (xmlNodeParseContent((xmlNodePtr) ret, value, INT_MAX) < 0)
1138
            xmlSAX2ErrMemory(ctxt);
1139
    } else if (value != NULL) {
1140
        ret->children = xmlNewDocText(ctxt->myDoc, value);
1141
        if (ret->children == NULL) {
1142
            xmlSAX2ErrMemory(ctxt);
1143
        } else {
1144
            ret->last = ret->children;
1145
            ret->children->parent = (xmlNodePtr) ret;
1146
        }
1147
    }
1148
1149
#ifdef LIBXML_VALID_ENABLED
1150
    if (ctxt->validate && ctxt->wellFormed &&
1151
        ctxt->myDoc && ctxt->myDoc->intSubset) {
1152
1153
  /*
1154
   * If we don't substitute entities, the validation should be
1155
   * done on a value with replaced entities anyway.
1156
   */
1157
        if (!ctxt->replaceEntities) {
1158
      xmlChar *val;
1159
1160
            /* TODO: normalize if needed */
1161
      val = xmlExpandEntitiesInAttValue(ctxt, value, /* normalize */ 0);
1162
1163
      if (val == NULL)
1164
    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1165
        ctxt->myDoc, ctxt->node, ret, value);
1166
      else {
1167
    xmlChar *nvalnorm;
1168
1169
    /*
1170
     * Do the last stage of the attribute normalization
1171
     * It need to be done twice ... it's an extra burden related
1172
     * to the ability to keep xmlSAX2References in attributes
1173
     */
1174
                nvalnorm = xmlValidCtxtNormalizeAttributeValue(
1175
                                 &ctxt->vctxt, ctxt->myDoc,
1176
                                 ctxt->node, fullname, val);
1177
    if (nvalnorm != NULL) {
1178
        xmlFree(val);
1179
        val = nvalnorm;
1180
    }
1181
1182
    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1183
              ctxt->myDoc, ctxt->node, ret, val);
1184
                xmlFree(val);
1185
      }
1186
  } else {
1187
      ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
1188
                 ctxt->node, ret, value);
1189
  }
1190
    } else
1191
#endif /* LIBXML_VALID_ENABLED */
1192
           if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
1193
               (ctxt->input->entity == NULL) &&
1194
               /* Don't create IDs containing entity references */
1195
               (ret->children != NULL) &&
1196
               (ret->children->type == XML_TEXT_NODE) &&
1197
               (ret->children->next == NULL)) {
1198
        xmlChar *content = ret->children->content;
1199
        /*
1200
   * when validating, the ID registration is done at the attribute
1201
   * validation level. Otherwise we have to do specific handling here.
1202
   */
1203
  if (xmlStrEqual(fullname, BAD_CAST "xml:id")) {
1204
      /*
1205
       * Add the xml:id value
1206
       *
1207
       * Open issue: normalization of the value.
1208
       */
1209
      if (xmlValidateNCName(content, 1) != 0) {
1210
          xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
1211
                "xml:id : attribute value %s is not an NCName\n",
1212
                content, NULL);
1213
      }
1214
      xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret);
1215
  } else {
1216
            int res = xmlIsID(ctxt->myDoc, ctxt->node, ret);
1217
1218
            if (res < 0)
1219
                xmlCtxtErrMemory(ctxt);
1220
            else if (res > 0)
1221
                xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret);
1222
            else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
1223
                xmlAddRef(&ctxt->vctxt, ctxt->myDoc, content, ret);
1224
        }
1225
    }
1226
1227
error:
1228
    if (ns != NULL)
1229
  xmlFree(ns);
1230
}
1231
1232
/*
1233
 * xmlCheckDefaultedAttributes:
1234
 *
1235
 * Check defaulted attributes from the DTD
1236
 *
1237
 * Deprecated SAX1 interface.
1238
 */
1239
static void
1240
xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name,
1241
  const xmlChar *prefix, const xmlChar **atts) {
1242
    xmlElementPtr elemDecl;
1243
    const xmlChar *att;
1244
    int internal = 1;
1245
    int i;
1246
1247
    elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix);
1248
    if (elemDecl == NULL) {
1249
  elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix);
1250
  internal = 0;
1251
    }
1252
1253
process_external_subset:
1254
1255
    if (elemDecl != NULL) {
1256
  xmlAttributePtr attr = elemDecl->attributes;
1257
  /*
1258
   * Check against defaulted attributes from the external subset
1259
   * if the document is stamped as standalone
1260
   */
1261
  if ((ctxt->myDoc->standalone == 1) &&
1262
      (ctxt->myDoc->extSubset != NULL) &&
1263
      (ctxt->validate)) {
1264
      while (attr != NULL) {
1265
    if ((attr->defaultValue != NULL) &&
1266
        (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset,
1267
          attr->elem, attr->name,
1268
          attr->prefix) == attr) &&
1269
        (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1270
          attr->elem, attr->name,
1271
          attr->prefix) == NULL)) {
1272
        xmlChar *fulln;
1273
1274
        if (attr->prefix != NULL) {
1275
      fulln = xmlStrdup(attr->prefix);
1276
                        if (fulln != NULL)
1277
          fulln = xmlStrcat(fulln, BAD_CAST ":");
1278
                        if (fulln != NULL)
1279
          fulln = xmlStrcat(fulln, attr->name);
1280
        } else {
1281
      fulln = xmlStrdup(attr->name);
1282
        }
1283
                    if (fulln == NULL) {
1284
                        xmlSAX2ErrMemory(ctxt);
1285
                        break;
1286
                    }
1287
1288
        /*
1289
         * Check that the attribute is not declared in the
1290
         * serialization
1291
         */
1292
        att = NULL;
1293
        if (atts != NULL) {
1294
      i = 0;
1295
      att = atts[i];
1296
      while (att != NULL) {
1297
          if (xmlStrEqual(att, fulln))
1298
        break;
1299
          i += 2;
1300
          att = atts[i];
1301
      }
1302
        }
1303
        if (att == NULL) {
1304
            xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED,
1305
      "standalone: attribute %s on %s defaulted from external subset\n",
1306
            fulln,
1307
            attr->elem);
1308
        }
1309
                    xmlFree(fulln);
1310
    }
1311
    attr = attr->nexth;
1312
      }
1313
  }
1314
1315
  /*
1316
   * Actually insert defaulted values when needed
1317
   */
1318
  attr = elemDecl->attributes;
1319
  while (attr != NULL) {
1320
      /*
1321
       * Make sure that attributes redefinition occurring in the
1322
       * internal subset are not overridden by definitions in the
1323
       * external subset.
1324
       */
1325
      if (attr->defaultValue != NULL) {
1326
    /*
1327
     * the element should be instantiated in the tree if:
1328
     *  - this is a namespace prefix
1329
     *  - the user required for completion in the tree
1330
     *    like XSLT
1331
     *  - there isn't already an attribute definition
1332
     *    in the internal subset overriding it.
1333
     */
1334
    if (((attr->prefix != NULL) &&
1335
         (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
1336
        ((attr->prefix == NULL) &&
1337
         (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
1338
        (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
1339
        xmlAttributePtr tst;
1340
1341
        tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1342
               attr->elem, attr->name,
1343
               attr->prefix);
1344
        if ((tst == attr) || (tst == NULL)) {
1345
            xmlChar fn[50];
1346
      xmlChar *fulln;
1347
1348
                        fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
1349
      if (fulln == NULL) {
1350
          xmlSAX2ErrMemory(ctxt);
1351
          return;
1352
      }
1353
1354
      /*
1355
       * Check that the attribute is not declared in the
1356
       * serialization
1357
       */
1358
      att = NULL;
1359
      if (atts != NULL) {
1360
          i = 0;
1361
          att = atts[i];
1362
          while (att != NULL) {
1363
        if (xmlStrEqual(att, fulln))
1364
            break;
1365
        i += 2;
1366
        att = atts[i];
1367
          }
1368
      }
1369
      if (att == NULL) {
1370
          xmlSAX1Attribute(ctxt, fulln,
1371
               attr->defaultValue, prefix);
1372
      }
1373
      if ((fulln != fn) && (fulln != attr->name))
1374
          xmlFree(fulln);
1375
        }
1376
    }
1377
      }
1378
      attr = attr->nexth;
1379
  }
1380
  if (internal == 1) {
1381
      elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
1382
                                 name, prefix);
1383
      internal = 0;
1384
      goto process_external_subset;
1385
  }
1386
    }
1387
}
1388
1389
/**
1390
 * xmlSAX1StartElement:
1391
 * @ctx: the user data (XML parser context)
1392
 * @fullname:  The element name, including namespace prefix
1393
 * @atts:  An array of name/value attributes pairs, NULL terminated
1394
 *
1395
 * called when an opening tag has been processed.
1396
 *
1397
 * Deprecated SAX1 interface.
1398
 */
1399
static void
1400
xmlSAX1StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
1401
{
1402
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1403
    xmlNodePtr ret;
1404
    xmlNodePtr parent;
1405
    xmlNsPtr ns;
1406
    const xmlChar *name;
1407
    xmlChar *prefix;
1408
    const xmlChar *att;
1409
    const xmlChar *value;
1410
    int i, res;
1411
1412
    if ((ctx == NULL) || (fullname == NULL) || (ctxt->myDoc == NULL)) return;
1413
1414
    /*
1415
     * First check on validity:
1416
     */
1417
    if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
1418
        ((ctxt->myDoc->intSubset == NULL) ||
1419
   ((ctxt->myDoc->intSubset->notations == NULL) &&
1420
    (ctxt->myDoc->intSubset->elements == NULL) &&
1421
    (ctxt->myDoc->intSubset->attributes == NULL) &&
1422
    (ctxt->myDoc->intSubset->entities == NULL)))) {
1423
  xmlErrValid(ctxt, XML_ERR_NO_DTD,
1424
    "Validation failed: no DTD found !", NULL, NULL);
1425
  ctxt->validate = 0;
1426
    }
1427
1428
    /*
1429
     * Split the full name into a namespace prefix and the tag name
1430
     */
1431
    name = xmlSplitQName4(fullname, &prefix);
1432
    if (name == NULL) {
1433
        xmlSAX2ErrMemory(ctxt);
1434
        return;
1435
    }
1436
1437
    /*
1438
     * Note : the namespace resolution is deferred until the end of the
1439
     *        attributes parsing, since local namespace can be defined as
1440
     *        an attribute at this level.
1441
     */
1442
    ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
1443
    if (ret == NULL) {
1444
  xmlFree(prefix);
1445
  xmlSAX2ErrMemory(ctxt);
1446
        return;
1447
    }
1448
    ctxt->nodemem = -1;
1449
1450
    /* Initialize parent before pushing node */
1451
    parent = ctxt->node;
1452
    if (parent == NULL)
1453
        parent = (xmlNodePtr) ctxt->myDoc;
1454
1455
    /*
1456
     * Link the child element
1457
     */
1458
    xmlSAX2AppendChild(ctxt, ret);
1459
1460
    /*
1461
     * We are parsing a new node.
1462
     */
1463
    if (nodePush(ctxt, ret) < 0) {
1464
        xmlUnlinkNode(ret);
1465
        xmlFreeNode(ret);
1466
        if (prefix != NULL)
1467
            xmlFree(prefix);
1468
        return;
1469
    }
1470
1471
    /*
1472
     * Insert all the defaulted attributes from the DTD especially
1473
     * namespaces
1474
     */
1475
    if ((ctxt->myDoc->intSubset != NULL) ||
1476
        (ctxt->myDoc->extSubset != NULL)) {
1477
        xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
1478
    }
1479
1480
    /*
1481
     * process all the attributes whose name start with "xmlns"
1482
     */
1483
    if (atts != NULL) {
1484
        i = 0;
1485
        att = atts[i++];
1486
        value = atts[i++];
1487
        while ((att != NULL) && (value != NULL)) {
1488
            if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
1489
                (att[3] == 'n') && (att[4] == 's'))
1490
                xmlSAX1Attribute(ctxt, att, value, prefix);
1491
1492
            att = atts[i++];
1493
            value = atts[i++];
1494
        }
1495
    }
1496
1497
    /*
1498
     * Search the namespace, note that since the attributes have been
1499
     * processed, the local namespaces are available.
1500
     */
1501
    res = xmlSearchNsSafe(ret, prefix, &ns);
1502
    if (res < 0)
1503
        xmlSAX2ErrMemory(ctxt);
1504
    if ((ns == NULL) && (parent != NULL)) {
1505
        res = xmlSearchNsSafe(parent, prefix, &ns);
1506
        if (res < 0)
1507
            xmlSAX2ErrMemory(ctxt);
1508
    }
1509
    if ((prefix != NULL) && (ns == NULL)) {
1510
        xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
1511
                     "Namespace prefix %s is not defined\n",
1512
                     prefix, NULL);
1513
        ns = xmlNewNs(ret, NULL, prefix);
1514
        if (ns == NULL)
1515
            xmlSAX2ErrMemory(ctxt);
1516
    }
1517
1518
    /*
1519
     * set the namespace node, making sure that if the default namespace
1520
     * is unbound on a parent we simply keep it NULL
1521
     */
1522
    if ((ns != NULL) && (ns->href != NULL) &&
1523
        ((ns->href[0] != 0) || (ns->prefix != NULL)))
1524
        xmlSetNs(ret, ns);
1525
1526
    /*
1527
     * process all the other attributes
1528
     */
1529
    if (atts != NULL) {
1530
        i = 0;
1531
  att = atts[i++];
1532
  value = atts[i++];
1533
        while ((att != NULL) && (value != NULL)) {
1534
            if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') ||
1535
                (att[3] != 'n') || (att[4] != 's'))
1536
                xmlSAX1Attribute(ctxt, att, value, NULL);
1537
1538
            /*
1539
             * Next ones
1540
             */
1541
            att = atts[i++];
1542
            value = atts[i++];
1543
        }
1544
    }
1545
1546
#ifdef LIBXML_VALID_ENABLED
1547
    /*
1548
     * If it's the Document root, finish the DTD validation and
1549
     * check the document root element for validity
1550
     */
1551
    if ((ctxt->validate) &&
1552
        ((ctxt->vctxt.flags & XML_VCTXT_DTD_VALIDATED) == 0)) {
1553
  int chk;
1554
1555
  chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1556
  if (chk <= 0)
1557
      ctxt->valid = 0;
1558
  if (chk < 0)
1559
      ctxt->wellFormed = 0;
1560
  ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
1561
  ctxt->vctxt.flags |= XML_VCTXT_DTD_VALIDATED;
1562
    }
1563
#endif /* LIBXML_VALID_ENABLED */
1564
1565
    if (prefix != NULL)
1566
  xmlFree(prefix);
1567
1568
}
1569
#endif /* LIBXML_SAX1_ENABLED */
1570
1571
#ifdef LIBXML_HTML_ENABLED
1572
static void
1573
xmlSAX2HtmlAttribute(xmlParserCtxtPtr ctxt, const xmlChar *fullname,
1574
0
                     const xmlChar *value) {
1575
0
    xmlAttrPtr ret;
1576
0
    xmlChar *nval = NULL;
1577
1578
0
    ret = xmlNewNsProp(ctxt->node, NULL, fullname, NULL);
1579
0
    if (ret == NULL) {
1580
0
        xmlSAX2ErrMemory(ctxt);
1581
0
        return;
1582
0
    }
1583
1584
0
    if ((value == NULL) && (htmlIsBooleanAttr(fullname))) {
1585
0
        nval = xmlStrdup(fullname);
1586
0
        if (nval == NULL) {
1587
0
            xmlSAX2ErrMemory(ctxt);
1588
0
            return;
1589
0
        }
1590
0
        value = nval;
1591
0
    }
1592
1593
0
    if (value != NULL) {
1594
0
        ret->children = xmlNewDocText(ctxt->myDoc, value);
1595
0
        if (ret->children == NULL) {
1596
0
            xmlSAX2ErrMemory(ctxt);
1597
0
        } else {
1598
0
            ret->last = ret->children;
1599
0
            ret->children->parent = (xmlNodePtr) ret;
1600
0
        }
1601
0
    }
1602
1603
0
    if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
1604
        /*
1605
         * Don't create IDs containing entity references (should
1606
         * be always the case with HTML)
1607
         */
1608
0
        (ret->children != NULL) &&
1609
0
        (ret->children->type == XML_TEXT_NODE) &&
1610
0
        (ret->children->next == NULL)) {
1611
0
        int res = xmlIsID(ctxt->myDoc, ctxt->node, ret);
1612
1613
0
        if (res < 0)
1614
0
            xmlCtxtErrMemory(ctxt);
1615
0
        else if (res > 0)
1616
0
            xmlAddID(&ctxt->vctxt, ctxt->myDoc, ret->children->content, ret);
1617
0
    }
1618
1619
0
    if (nval != NULL)
1620
0
        xmlFree(nval);
1621
0
}
1622
1623
/**
1624
 * xmlSAX2StartHtmlElement:
1625
 * @ctxt:  parser context
1626
 * @fullname:  The element name, including namespace prefix
1627
 * @atts:  An array of name/value attributes pairs, NULL terminated
1628
 *
1629
 * Called when an opening tag has been processed.
1630
 */
1631
static void
1632
xmlSAX2StartHtmlElement(xmlParserCtxtPtr ctxt, const xmlChar *fullname,
1633
0
                        const xmlChar **atts) {
1634
0
    xmlNodePtr ret;
1635
0
    xmlNodePtr parent;
1636
0
    const xmlChar *att;
1637
0
    const xmlChar *value;
1638
0
    int i;
1639
1640
0
    ret = xmlNewDocNode(ctxt->myDoc, NULL, fullname, NULL);
1641
0
    if (ret == NULL) {
1642
0
  xmlSAX2ErrMemory(ctxt);
1643
0
        return;
1644
0
    }
1645
0
    ctxt->nodemem = -1;
1646
1647
    /* Initialize parent before pushing node */
1648
0
    parent = ctxt->node;
1649
0
    if (parent == NULL)
1650
0
        parent = (xmlNodePtr) ctxt->myDoc;
1651
1652
    /*
1653
     * Link the child element
1654
     */
1655
0
    xmlSAX2AppendChild(ctxt, ret);
1656
1657
    /*
1658
     * We are parsing a new node.
1659
     */
1660
0
    if (nodePush(ctxt, ret) < 0) {
1661
0
        xmlUnlinkNode(ret);
1662
0
        xmlFreeNode(ret);
1663
0
        return;
1664
0
    }
1665
1666
0
    if (atts != NULL) {
1667
0
        i = 0;
1668
0
  att = atts[i++];
1669
0
  value = atts[i++];
1670
0
        while (att != NULL) {
1671
0
            xmlSAX2HtmlAttribute(ctxt, att, value);
1672
0
            att = atts[i++];
1673
0
            value = atts[i++];
1674
0
        }
1675
0
    }
1676
0
}
1677
#endif /* LIBXML_HTML_ENABLED */
1678
1679
/**
1680
 * xmlSAX2StartElement:
1681
 * @ctx: the user data (XML parser context)
1682
 * @fullname:  The element name, including namespace prefix
1683
 * @atts:  An array of name/value attributes pairs, NULL terminated
1684
 *
1685
 * DEPRECATED: Don't call this function directly.
1686
 *
1687
 * Called when an opening tag has been processed.
1688
 *
1689
 * Used for HTML and SAX1.
1690
 */
1691
void
1692
0
xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts) {
1693
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1694
1695
0
    (void) atts;
1696
1697
0
    if ((ctxt == NULL) || (fullname == NULL) || (ctxt->myDoc == NULL))
1698
0
        return;
1699
1700
#ifdef LIBXML_SAX1_ENABLED
1701
    if (!ctxt->html) {
1702
        xmlSAX1StartElement(ctxt, fullname, atts);
1703
        return;
1704
    }
1705
#endif
1706
1707
0
#ifdef LIBXML_HTML_ENABLED
1708
0
    if (ctxt->html) {
1709
0
        xmlSAX2StartHtmlElement(ctxt, fullname, atts);
1710
0
        return;
1711
0
    }
1712
0
#endif
1713
0
}
1714
1715
/**
1716
 * xmlSAX2EndElement:
1717
 * @ctx: the user data (XML parser context)
1718
 * @name:  The element name
1719
 *
1720
 * DEPRECATED: Don't call this function directly.
1721
 *
1722
 * called when the end of an element has been detected.
1723
 *
1724
 * Used for HTML and SAX1.
1725
 */
1726
void
1727
xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
1728
0
{
1729
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1730
1731
0
    if (ctxt == NULL)
1732
0
        return;
1733
1734
#if defined(LIBXML_SAX1_ENABLED) && defined(LIBXML_VALID_ENABLED)
1735
    if (!ctxt->html && ctxt->validate && ctxt->wellFormed &&
1736
        ctxt->myDoc && ctxt->myDoc->intSubset)
1737
        ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1738
               ctxt->node);
1739
#endif /* LIBXML_VALID_ENABLED */
1740
1741
0
#if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED)
1742
0
    ctxt->nodemem = -1;
1743
1744
    /*
1745
     * end of parsing of this node.
1746
     */
1747
0
    nodePop(ctxt);
1748
0
#endif
1749
0
}
1750
1751
/*
1752
 * xmlSAX2TextNode:
1753
 * @ctxt:  the parser context
1754
 * @str:  the input string
1755
 * @len: the string length
1756
 *
1757
 * Callback for a text node
1758
 *
1759
 * Returns the newly allocated string or NULL if not needed or error
1760
 */
1761
static xmlNodePtr
1762
7.61M
xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
1763
7.61M
    xmlNodePtr ret;
1764
7.61M
    const xmlChar *intern = NULL;
1765
1766
    /*
1767
     * Allocate
1768
     */
1769
7.61M
    if (ctxt->freeElems != NULL) {
1770
0
  ret = ctxt->freeElems;
1771
0
  ctxt->freeElems = ret->next;
1772
0
  ctxt->freeElemsNr--;
1773
7.61M
    } else {
1774
7.61M
  ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1775
7.61M
    }
1776
7.61M
    if (ret == NULL) {
1777
233
        xmlCtxtErrMemory(ctxt);
1778
233
  return(NULL);
1779
233
    }
1780
7.61M
    memset(ret, 0, sizeof(xmlNode));
1781
    /*
1782
     * intern the formatting blanks found between tags, or the
1783
     * very short strings
1784
     */
1785
7.61M
    if ((!ctxt->html) && (ctxt->dictNames)) {
1786
7.61M
        xmlChar cur = str[len];
1787
1788
7.61M
  if ((len < (int) (2 * sizeof(void *))) &&
1789
7.61M
      (ctxt->options & XML_PARSE_COMPACT)) {
1790
      /* store the string in the node overriding properties and nsDef */
1791
0
      xmlChar *tmp = (xmlChar *) &(ret->properties);
1792
0
      memcpy(tmp, str, len);
1793
0
      tmp[len] = 0;
1794
0
      intern = tmp;
1795
7.61M
  } else if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
1796
3.42M
      ((cur == '<') && (str[len + 1] != '!')))) {
1797
3.17M
      intern = xmlDictLookup(ctxt->dict, str, len);
1798
3.17M
            if (intern == NULL) {
1799
1
                xmlSAX2ErrMemory(ctxt);
1800
1
                xmlFree(ret);
1801
1
                return(NULL);
1802
1
            }
1803
4.43M
  } else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') &&
1804
4.43M
             (str[len + 1] != '!')) {
1805
499k
      int i;
1806
1807
2.05M
      for (i = 1;i < len;i++) {
1808
1.80M
    if (!IS_BLANK_CH(str[i])) goto skip;
1809
1.80M
      }
1810
256k
      intern = xmlDictLookup(ctxt->dict, str, len);
1811
256k
            if (intern == NULL) {
1812
1
                xmlSAX2ErrMemory(ctxt);
1813
1
                xmlFree(ret);
1814
1
                return(NULL);
1815
1
            }
1816
256k
  }
1817
7.61M
    }
1818
7.61M
skip:
1819
7.61M
    ret->type = XML_TEXT_NODE;
1820
1821
7.61M
    ret->name = xmlStringText;
1822
7.61M
    if (intern == NULL) {
1823
4.18M
  ret->content = xmlStrndup(str, len);
1824
4.18M
  if (ret->content == NULL) {
1825
120
      xmlSAX2ErrMemory(ctxt);
1826
120
      xmlFree(ret);
1827
120
      return(NULL);
1828
120
  }
1829
4.18M
    } else
1830
3.43M
  ret->content = (xmlChar *) intern;
1831
1832
7.61M
    if ((xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1833
0
  xmlRegisterNodeDefaultValue(ret);
1834
7.61M
    return(ret);
1835
7.61M
}
1836
1837
#ifdef LIBXML_VALID_ENABLED
1838
/*
1839
 * xmlSAX2DecodeAttrEntities:
1840
 * @ctxt:  the parser context
1841
 * @str:  the input string
1842
 * @len: the string length
1843
 *
1844
 * Remove the entities from an attribute value
1845
 *
1846
 * Returns the newly allocated string or NULL if not needed or error
1847
 */
1848
static xmlChar *
1849
xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
1850
                          const xmlChar *end) {
1851
    const xmlChar *in;
1852
1853
    in = str;
1854
    while (in < end)
1855
        if (*in++ == '&')
1856
      goto decode;
1857
    return(NULL);
1858
decode:
1859
    /*
1860
     * If the value contains '&', we can be sure it was allocated and is
1861
     * zero-terminated.
1862
     */
1863
    /* TODO: normalize if needed */
1864
    return(xmlExpandEntitiesInAttValue(ctxt, str, /* normalize */ 0));
1865
}
1866
#endif /* LIBXML_VALID_ENABLED */
1867
1868
/**
1869
 * xmlSAX2AttributeNs:
1870
 * @ctx: the user data (XML parser context)
1871
 * @localname:  the local name of the attribute
1872
 * @prefix:  the attribute namespace prefix if available
1873
 * @URI:  the attribute namespace name if available
1874
 * @value:  Start of the attribute value
1875
 * @valueend: end of the attribute value
1876
 *
1877
 * Handle an attribute that has been read by the parser.
1878
 * The default handling is to convert the attribute into an
1879
 * DOM subtree and past it in a new xmlAttr element added to
1880
 * the element.
1881
 *
1882
 * Returns the new attribute or NULL in case of error.
1883
 */
1884
static xmlAttrPtr
1885
xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
1886
                   const xmlChar * localname,
1887
                   const xmlChar * prefix,
1888
       const xmlChar * value,
1889
       const xmlChar * valueend)
1890
3.73M
{
1891
3.73M
    xmlAttrPtr ret;
1892
3.73M
    xmlNsPtr namespace = NULL;
1893
3.73M
    xmlChar *dup = NULL;
1894
1895
    /*
1896
     * Note: if prefix == NULL, the attribute is not in the default namespace
1897
     */
1898
3.73M
    if (prefix != NULL) {
1899
110k
  namespace = xmlParserNsLookupSax(ctxt, prefix);
1900
110k
  if ((namespace == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) {
1901
101k
            int res;
1902
1903
101k
      res = xmlSearchNsSafe(ctxt->node, prefix, &namespace);
1904
101k
            if (res < 0)
1905
13
                xmlSAX2ErrMemory(ctxt);
1906
101k
  }
1907
110k
    }
1908
1909
    /*
1910
     * allocate the node
1911
     */
1912
3.73M
    if (ctxt->freeAttrs != NULL) {
1913
0
        ret = ctxt->freeAttrs;
1914
0
  ctxt->freeAttrs = ret->next;
1915
0
  ctxt->freeAttrsNr--;
1916
3.73M
    } else {
1917
3.73M
        ret = xmlMalloc(sizeof(*ret));
1918
3.73M
        if (ret == NULL) {
1919
263
            xmlSAX2ErrMemory(ctxt);
1920
263
            return(NULL);
1921
263
        }
1922
3.73M
    }
1923
1924
3.73M
    memset(ret, 0, sizeof(xmlAttr));
1925
3.73M
    ret->type = XML_ATTRIBUTE_NODE;
1926
1927
    /*
1928
     * xmlParseBalancedChunkMemoryRecover had a bug that could result in
1929
     * a mismatch between ctxt->node->doc and ctxt->myDoc. We use
1930
     * ctxt->node->doc here, but we should somehow make sure that the
1931
     * document pointers match.
1932
     */
1933
1934
    /* assert(ctxt->node->doc == ctxt->myDoc); */
1935
1936
3.73M
    ret->parent = ctxt->node;
1937
3.73M
    ret->doc = ctxt->node->doc;
1938
3.73M
    ret->ns = namespace;
1939
1940
3.73M
    if (ctxt->dictNames) {
1941
3.73M
        ret->name = localname;
1942
3.73M
    } else {
1943
0
        ret->name = xmlStrdup(localname);
1944
0
        if (ret->name == NULL)
1945
0
            xmlSAX2ErrMemory(ctxt);
1946
0
    }
1947
1948
3.73M
    if ((xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1949
0
        xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
1950
1951
3.73M
    if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1952
0
  xmlNodePtr tmp;
1953
1954
  /*
1955
   * We know that if there is an entity reference, then
1956
   * the string has been dup'ed and terminates with 0
1957
   * otherwise with ' or "
1958
   */
1959
0
  if (*valueend != 0) {
1960
0
      tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1961
0
      ret->children = tmp;
1962
0
      ret->last = tmp;
1963
0
      if (tmp != NULL) {
1964
0
    tmp->doc = ret->doc;
1965
0
    tmp->parent = (xmlNodePtr) ret;
1966
0
      }
1967
0
  } else if (valueend > value) {
1968
0
            if (xmlNodeParseContent((xmlNodePtr) ret, value,
1969
0
                                    valueend - value) < 0)
1970
0
                xmlSAX2ErrMemory(ctxt);
1971
0
  }
1972
3.73M
    } else if (value != NULL) {
1973
3.73M
  xmlNodePtr tmp;
1974
1975
3.73M
  tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1976
3.73M
  ret->children = tmp;
1977
3.73M
  ret->last = tmp;
1978
3.73M
  if (tmp != NULL) {
1979
3.73M
      tmp->doc = ret->doc;
1980
3.73M
      tmp->parent = (xmlNodePtr) ret;
1981
3.73M
  }
1982
3.73M
    }
1983
1984
#ifdef LIBXML_VALID_ENABLED
1985
    if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1986
        ctxt->myDoc && ctxt->myDoc->intSubset) {
1987
  /*
1988
   * If we don't substitute entities, the validation should be
1989
   * done on a value with replaced entities anyway.
1990
   */
1991
        if (!ctxt->replaceEntities) {
1992
      dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend);
1993
      if (dup == NULL) {
1994
          if (*valueend == 0) {
1995
        ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1996
            ctxt->myDoc, ctxt->node, ret, value);
1997
    } else {
1998
        /*
1999
         * That should already be normalized.
2000
         * cheaper to finally allocate here than duplicate
2001
         * entry points in the full validation code
2002
         */
2003
        dup = xmlStrndup(value, valueend - value);
2004
                    if (dup == NULL)
2005
                        xmlSAX2ErrMemory(ctxt);
2006
2007
        ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2008
            ctxt->myDoc, ctxt->node, ret, dup);
2009
    }
2010
      } else {
2011
          /*
2012
     * dup now contains a string of the flattened attribute
2013
     * content with entities substituted. Check if we need to
2014
     * apply an extra layer of normalization.
2015
     * It need to be done twice ... it's an extra burden related
2016
     * to the ability to keep references in attributes
2017
     */
2018
    if (ctxt->attsSpecial != NULL) {
2019
        xmlChar *nvalnorm;
2020
        xmlChar fn[50];
2021
        xmlChar *fullname;
2022
2023
        fullname = xmlBuildQName(localname, prefix, fn, 50);
2024
                    if (fullname == NULL) {
2025
                        xmlSAX2ErrMemory(ctxt);
2026
                    } else {
2027
      ctxt->vctxt.valid = 1;
2028
            nvalnorm = xmlValidCtxtNormalizeAttributeValue(
2029
                       &ctxt->vctxt, ctxt->myDoc,
2030
           ctxt->node, fullname, dup);
2031
      if (ctxt->vctxt.valid != 1)
2032
          ctxt->valid = 0;
2033
2034
      if ((fullname != fn) && (fullname != localname))
2035
          xmlFree(fullname);
2036
      if (nvalnorm != NULL) {
2037
          xmlFree(dup);
2038
          dup = nvalnorm;
2039
      }
2040
        }
2041
    }
2042
2043
    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2044
              ctxt->myDoc, ctxt->node, ret, dup);
2045
      }
2046
  } else {
2047
      /*
2048
       * if entities already have been substituted, then
2049
       * the attribute as passed is already normalized
2050
       */
2051
      dup = xmlStrndup(value, valueend - value);
2052
            if (dup == NULL)
2053
                xmlSAX2ErrMemory(ctxt);
2054
2055
      ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2056
                               ctxt->myDoc, ctxt->node, ret, dup);
2057
  }
2058
    } else
2059
#endif /* LIBXML_VALID_ENABLED */
2060
3.73M
           if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
2061
3.73M
               (ctxt->input->entity == NULL) &&
2062
               /* Don't create IDs containing entity references */
2063
3.73M
               (ret->children != NULL) &&
2064
3.73M
               (ret->children->type == XML_TEXT_NODE) &&
2065
3.73M
               (ret->children->next == NULL)) {
2066
3.72M
        xmlChar *content = ret->children->content;
2067
        /*
2068
   * when validating, the ID registration is done at the attribute
2069
   * validation level. Otherwise we have to do specific handling here.
2070
   */
2071
3.72M
        if ((prefix == ctxt->str_xml) &&
2072
3.72M
             (localname[0] == 'i') && (localname[1] == 'd') &&
2073
3.72M
       (localname[2] == 0)) {
2074
      /*
2075
       * Add the xml:id value
2076
       *
2077
       * Open issue: normalization of the value.
2078
       */
2079
13.1k
      if (xmlValidateNCName(content, 1) != 0) {
2080
12.9k
          xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
2081
12.9k
                            "xml:id : attribute value %s is not an NCName\n",
2082
12.9k
                            content, NULL);
2083
12.9k
      }
2084
13.1k
      xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret);
2085
3.71M
  } else {
2086
3.71M
            int res = xmlIsID(ctxt->myDoc, ctxt->node, ret);
2087
2088
3.71M
            if (res < 0)
2089
1
                xmlCtxtErrMemory(ctxt);
2090
3.71M
            else if (res > 0)
2091
24.6k
                xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret);
2092
3.68M
            else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
2093
1.38k
                xmlAddRef(&ctxt->vctxt, ctxt->myDoc, content, ret);
2094
3.71M
  }
2095
3.72M
    }
2096
3.73M
    if (dup != NULL)
2097
0
  xmlFree(dup);
2098
2099
3.73M
    return(ret);
2100
3.73M
}
2101
2102
/**
2103
 * xmlSAX2StartElementNs:
2104
 * @ctx:  the user data (XML parser context)
2105
 * @localname:  the local name of the element
2106
 * @prefix:  the element namespace prefix if available
2107
 * @URI:  the element namespace name if available
2108
 * @nb_namespaces:  number of namespace definitions on that node
2109
 * @namespaces:  pointer to the array of prefix/URI pairs namespace definitions
2110
 * @nb_attributes:  the number of attributes on that node
2111
 * @nb_defaulted:  the number of defaulted attributes.
2112
 * @attributes:  pointer to the array of (localname/prefix/URI/value/end)
2113
 *               attribute values.
2114
 *
2115
 * SAX2 callback when an element start has been detected by the parser.
2116
 * It provides the namespace information for the element, as well as
2117
 * the new namespace declarations on the element.
2118
 */
2119
void
2120
xmlSAX2StartElementNs(void *ctx,
2121
                      const xmlChar *localname,
2122
          const xmlChar *prefix,
2123
          const xmlChar *URI,
2124
          int nb_namespaces,
2125
          const xmlChar **namespaces,
2126
          int nb_attributes,
2127
          int nb_defaulted,
2128
          const xmlChar **attributes)
2129
3.93M
{
2130
3.93M
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2131
3.93M
    xmlNodePtr ret;
2132
3.93M
    xmlNsPtr last = NULL, ns;
2133
3.93M
    const xmlChar *uri, *pref;
2134
3.93M
    xmlChar *lname = NULL;
2135
3.93M
    int i, j;
2136
2137
3.93M
    if (ctx == NULL) return;
2138
    /*
2139
     * First check on validity:
2140
     */
2141
3.93M
    if (ctxt->validate &&
2142
3.93M
        ((ctxt->myDoc == NULL) ||
2143
0
         ((ctxt->myDoc->extSubset == NULL) &&
2144
0
          ((ctxt->myDoc->intSubset == NULL) ||
2145
0
     ((ctxt->myDoc->intSubset->notations == NULL) &&
2146
0
      (ctxt->myDoc->intSubset->elements == NULL) &&
2147
0
      (ctxt->myDoc->intSubset->attributes == NULL) &&
2148
0
      (ctxt->myDoc->intSubset->entities == NULL)))))) {
2149
0
  xmlErrValid(ctxt, XML_DTD_NO_DTD,
2150
0
    "Validation failed: no DTD found !", NULL, NULL);
2151
0
  ctxt->validate = 0;
2152
0
    }
2153
2154
    /*
2155
     * Take care of the rare case of an undefined namespace prefix
2156
     */
2157
3.93M
    if ((prefix != NULL) && (URI == NULL)) {
2158
163k
        if (ctxt->dictNames) {
2159
163k
      const xmlChar *fullname;
2160
2161
163k
      fullname = xmlDictQLookup(ctxt->dict, prefix, localname);
2162
163k
      if (fullname == NULL) {
2163
1
                xmlSAX2ErrMemory(ctxt);
2164
1
                return;
2165
1
            }
2166
163k
      localname = fullname;
2167
163k
  } else {
2168
0
      lname = xmlBuildQName(localname, prefix, NULL, 0);
2169
0
            if (lname == NULL) {
2170
0
                xmlSAX2ErrMemory(ctxt);
2171
0
                return;
2172
0
            }
2173
0
  }
2174
163k
    }
2175
    /*
2176
     * allocate the node
2177
     */
2178
3.93M
    if (ctxt->freeElems != NULL) {
2179
0
        ret = ctxt->freeElems;
2180
0
  ctxt->freeElems = ret->next;
2181
0
  ctxt->freeElemsNr--;
2182
0
  memset(ret, 0, sizeof(xmlNode));
2183
0
        ret->doc = ctxt->myDoc;
2184
0
  ret->type = XML_ELEMENT_NODE;
2185
2186
0
  if (ctxt->dictNames)
2187
0
      ret->name = localname;
2188
0
  else {
2189
0
      if (lname == NULL)
2190
0
    ret->name = xmlStrdup(localname);
2191
0
      else
2192
0
          ret->name = lname;
2193
0
      if (ret->name == NULL) {
2194
0
          xmlSAX2ErrMemory(ctxt);
2195
0
                xmlFree(ret);
2196
0
    return;
2197
0
      }
2198
0
  }
2199
0
  if ((xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2200
0
      xmlRegisterNodeDefaultValue(ret);
2201
3.93M
    } else {
2202
3.93M
  if (ctxt->dictNames)
2203
3.93M
      ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
2204
3.93M
                                 (xmlChar *) localname, NULL);
2205
0
  else if (lname == NULL)
2206
0
      ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL);
2207
0
  else
2208
0
      ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, lname, NULL);
2209
3.93M
  if (ret == NULL) {
2210
102
      xmlSAX2ErrMemory(ctxt);
2211
102
      return;
2212
102
  }
2213
3.93M
    }
2214
2215
    /*
2216
     * Build the namespace list
2217
     */
2218
4.66M
    for (i = 0,j = 0;j < nb_namespaces;j++) {
2219
726k
        pref = namespaces[i++];
2220
726k
  uri = namespaces[i++];
2221
726k
  ns = xmlNewNs(NULL, uri, pref);
2222
726k
  if (ns != NULL) {
2223
725k
      if (last == NULL) {
2224
629k
          ret->nsDef = last = ns;
2225
629k
      } else {
2226
96.1k
          last->next = ns;
2227
96.1k
    last = ns;
2228
96.1k
      }
2229
725k
      if ((URI != NULL) && (prefix == pref))
2230
621k
    ret->ns = ns;
2231
725k
  } else {
2232
115
            xmlSAX2ErrMemory(ctxt);
2233
115
      continue;
2234
115
  }
2235
2236
725k
        xmlParserNsUpdateSax(ctxt, pref, ns);
2237
2238
#ifdef LIBXML_VALID_ENABLED
2239
  if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2240
      ctxt->myDoc && ctxt->myDoc->intSubset) {
2241
      ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
2242
                                             ret, prefix, ns, uri);
2243
  }
2244
#endif /* LIBXML_VALID_ENABLED */
2245
725k
    }
2246
3.93M
    ctxt->nodemem = -1;
2247
2248
    /*
2249
     * Link the child element
2250
     */
2251
3.93M
    xmlSAX2AppendChild(ctxt, ret);
2252
2253
    /*
2254
     * We are parsing a new node.
2255
     */
2256
3.93M
    if (nodePush(ctxt, ret) < 0) {
2257
335
        xmlUnlinkNode(ret);
2258
335
        xmlFreeNode(ret);
2259
335
        return;
2260
335
    }
2261
2262
    /*
2263
     * Insert the defaulted attributes from the DTD only if requested:
2264
     */
2265
3.93M
    if ((nb_defaulted != 0) &&
2266
3.93M
        ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0))
2267
0
  nb_attributes -= nb_defaulted;
2268
2269
    /*
2270
     * Search the namespace if it wasn't already found
2271
     * Note that, if prefix is NULL, this searches for the default Ns
2272
     */
2273
3.93M
    if ((URI != NULL) && (ret->ns == NULL)) {
2274
2.50M
        ret->ns = xmlParserNsLookupSax(ctxt, prefix);
2275
2.50M
  if ((ret->ns == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) {
2276
10.5k
            int res;
2277
2278
10.5k
      res = xmlSearchNsSafe(ret, prefix, &ret->ns);
2279
10.5k
            if (res < 0)
2280
1
                xmlSAX2ErrMemory(ctxt);
2281
10.5k
  }
2282
2.50M
  if (ret->ns == NULL) {
2283
79
      ns = xmlNewNs(ret, NULL, prefix);
2284
79
      if (ns == NULL) {
2285
2286
79
          xmlSAX2ErrMemory(ctxt);
2287
79
    return;
2288
79
      }
2289
0
            if (prefix != NULL)
2290
0
                xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
2291
0
                             "Namespace prefix %s was not found\n",
2292
0
                             prefix, NULL);
2293
0
            else
2294
0
                xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
2295
0
                             "Namespace default prefix was not found\n",
2296
0
                             NULL, NULL);
2297
0
  }
2298
2.50M
    }
2299
2300
    /*
2301
     * process all the other attributes
2302
     */
2303
3.93M
    if (nb_attributes > 0) {
2304
3.24M
        xmlAttrPtr prev = NULL;
2305
2306
6.97M
        for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
2307
3.73M
            xmlAttrPtr attr = NULL;
2308
2309
      /*
2310
       * Handle the rare case of an undefined attribute prefix
2311
       */
2312
3.73M
      if ((attributes[j+1] != NULL) && (attributes[j+2] == NULL)) {
2313
28.6k
    if (ctxt->dictNames) {
2314
28.6k
        const xmlChar *fullname;
2315
2316
28.6k
        fullname = xmlDictQLookup(ctxt->dict, attributes[j+1],
2317
28.6k
                                  attributes[j]);
2318
28.6k
        if (fullname == NULL) {
2319
1
                        xmlSAX2ErrMemory(ctxt);
2320
1
                        return;
2321
1
                    }
2322
28.6k
                    attr = xmlSAX2AttributeNs(ctxt, fullname, NULL,
2323
28.6k
                                              attributes[j+3],
2324
28.6k
                                              attributes[j+4]);
2325
28.6k
                    goto have_attr;
2326
28.6k
    } else {
2327
0
        lname = xmlBuildQName(attributes[j], attributes[j+1],
2328
0
                              NULL, 0);
2329
0
        if (lname == NULL) {
2330
0
                        xmlSAX2ErrMemory(ctxt);
2331
0
                        return;
2332
0
                    }
2333
0
                    attr = xmlSAX2AttributeNs(ctxt, lname, NULL,
2334
0
                                              attributes[j+3],
2335
0
                                              attributes[j+4]);
2336
0
                    xmlFree(lname);
2337
0
                    goto have_attr;
2338
0
    }
2339
28.6k
      }
2340
3.70M
            attr = xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
2341
3.70M
                                      attributes[j+3], attributes[j+4]);
2342
3.73M
have_attr:
2343
3.73M
            if (attr == NULL)
2344
263
                continue;
2345
2346
            /* link at the end to preserve order */
2347
3.73M
            if (prev == NULL) {
2348
3.24M
                ctxt->node->properties = attr;
2349
3.24M
            } else {
2350
489k
                prev->next = attr;
2351
489k
                attr->prev = prev;
2352
489k
            }
2353
2354
3.73M
            prev = attr;
2355
3.73M
  }
2356
3.24M
    }
2357
2358
#ifdef LIBXML_VALID_ENABLED
2359
    /*
2360
     * If it's the Document root, finish the DTD validation and
2361
     * check the document root element for validity
2362
     */
2363
    if ((ctxt->validate) &&
2364
        ((ctxt->vctxt.flags & XML_VCTXT_DTD_VALIDATED) == 0)) {
2365
  int chk;
2366
2367
  chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
2368
  if (chk <= 0)
2369
      ctxt->valid = 0;
2370
  if (chk < 0)
2371
      ctxt->wellFormed = 0;
2372
  ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
2373
  ctxt->vctxt.flags |= XML_VCTXT_DTD_VALIDATED;
2374
    }
2375
#endif /* LIBXML_VALID_ENABLED */
2376
3.93M
}
2377
2378
/**
2379
 * xmlSAX2EndElementNs:
2380
 * @ctx:  the user data (XML parser context)
2381
 * @localname:  the local name of the element
2382
 * @prefix:  the element namespace prefix if available
2383
 * @URI:  the element namespace name if available
2384
 *
2385
 * SAX2 callback when an element end has been detected by the parser.
2386
 * It provides the namespace information for the element.
2387
 */
2388
void
2389
xmlSAX2EndElementNs(void *ctx,
2390
                    const xmlChar * localname ATTRIBUTE_UNUSED,
2391
                    const xmlChar * prefix ATTRIBUTE_UNUSED,
2392
        const xmlChar * URI ATTRIBUTE_UNUSED)
2393
3.68M
{
2394
3.68M
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2395
2396
3.68M
    if (ctx == NULL) return;
2397
3.68M
    ctxt->nodemem = -1;
2398
2399
#ifdef LIBXML_VALID_ENABLED
2400
    if (ctxt->validate && ctxt->wellFormed &&
2401
        ctxt->myDoc && ctxt->myDoc->intSubset)
2402
        ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
2403
                                             ctxt->node);
2404
#endif /* LIBXML_VALID_ENABLED */
2405
2406
    /*
2407
     * end of parsing of this node.
2408
     */
2409
3.68M
    nodePop(ctxt);
2410
3.68M
}
2411
2412
/**
2413
 * xmlSAX2Reference:
2414
 * @ctx: the user data (XML parser context)
2415
 * @name:  The entity name
2416
 *
2417
 * called when an entity xmlSAX2Reference is detected.
2418
 */
2419
void
2420
xmlSAX2Reference(void *ctx, const xmlChar *name)
2421
0
{
2422
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2423
0
    xmlNodePtr ret;
2424
2425
0
    if (ctx == NULL) return;
2426
0
    ret = xmlNewReference(ctxt->myDoc, name);
2427
0
    if (ret == NULL) {
2428
0
        xmlSAX2ErrMemory(ctxt);
2429
0
        return;
2430
0
    }
2431
2432
0
    xmlSAX2AppendChild(ctxt, ret);
2433
0
}
2434
2435
/**
2436
 * xmlSAX2Text:
2437
 * @ctx: the user data (XML parser context)
2438
 * @ch:  a xmlChar string
2439
 * @len: the number of xmlChar
2440
 * @type: text or cdata
2441
 *
2442
 * Append characters.
2443
 */
2444
static void
2445
xmlSAX2Text(xmlParserCtxtPtr ctxt, const xmlChar *ch, int len,
2446
            xmlElementType type)
2447
4.58M
{
2448
4.58M
    xmlNodePtr lastChild;
2449
2450
4.58M
    if (ctxt == NULL) return;
2451
    /*
2452
     * Handle the data if any. If there is no child
2453
     * add it as content, otherwise if the last child is text,
2454
     * concatenate it, else create a new node of type text.
2455
     */
2456
2457
4.58M
    if (ctxt->node == NULL) {
2458
0
        return;
2459
0
    }
2460
4.58M
    lastChild = ctxt->node->last;
2461
2462
    /*
2463
     * Here we needed an accelerator mechanism in case of very large
2464
     * elements. Use an attribute in the structure !!!
2465
     */
2466
4.58M
    if (lastChild == NULL) {
2467
1.05M
        if (type == XML_TEXT_NODE)
2468
1.05M
            lastChild = xmlSAX2TextNode(ctxt, ch, len);
2469
0
        else
2470
0
            lastChild = xmlNewCDataBlock(ctxt->myDoc, ch, len);
2471
1.05M
  if (lastChild != NULL) {
2472
1.05M
      ctxt->node->children = lastChild;
2473
1.05M
      ctxt->node->last = lastChild;
2474
1.05M
      lastChild->parent = ctxt->node;
2475
1.05M
      lastChild->doc = ctxt->node->doc;
2476
1.05M
      ctxt->nodelen = len;
2477
1.05M
      ctxt->nodemem = len + 1;
2478
1.05M
  } else {
2479
44
      xmlSAX2ErrMemory(ctxt);
2480
44
      return;
2481
44
  }
2482
3.52M
    } else {
2483
3.52M
  int coalesceText = (lastChild != NULL) &&
2484
3.52M
      (lastChild->type == type) &&
2485
3.52M
      (((ctxt->html) && (type != XML_TEXT_NODE)) ||
2486
700k
             (lastChild->name == xmlStringText));
2487
3.52M
  if ((coalesceText) && (ctxt->nodemem > 0)) {
2488
700k
            int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
2489
0
                            XML_MAX_HUGE_LENGTH :
2490
700k
                            XML_MAX_TEXT_LENGTH;
2491
2492
      /*
2493
       * The whole point of maintaining nodelen and nodemem,
2494
       * xmlTextConcat is too costly, i.e. compute length,
2495
       * reallocate a new buffer, move data, append ch. Here
2496
       * We try to minimize realloc() uses and avoid copying
2497
       * and recomputing length over and over.
2498
       */
2499
700k
      if (lastChild->content == (xmlChar *)&(lastChild->properties)) {
2500
0
    lastChild->content = xmlStrdup(lastChild->content);
2501
0
    lastChild->properties = NULL;
2502
700k
      } else if ((ctxt->nodemem == ctxt->nodelen + 1) &&
2503
700k
                 (xmlDictOwns(ctxt->dict, lastChild->content))) {
2504
0
    lastChild->content = xmlStrdup(lastChild->content);
2505
0
      }
2506
700k
      if (lastChild->content == NULL) {
2507
0
    xmlSAX2ErrMemory(ctxt);
2508
0
    return;
2509
0
      }
2510
700k
            if ((len > maxLength) || (ctxt->nodelen > maxLength - len)) {
2511
0
                xmlFatalErr(ctxt, XML_ERR_RESOURCE_LIMIT,
2512
0
                            "Text node too long, try XML_PARSE_HUGE");
2513
0
                xmlHaltParser(ctxt);
2514
0
                return;
2515
0
            }
2516
700k
      if (ctxt->nodelen + len >= ctxt->nodemem) {
2517
400k
    xmlChar *newbuf;
2518
400k
    int size;
2519
2520
400k
    size = ctxt->nodemem > INT_MAX - len ?
2521
0
                       INT_MAX :
2522
400k
                       ctxt->nodemem + len;
2523
400k
    size = size > INT_MAX / 2 ? INT_MAX : size * 2;
2524
400k
                newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
2525
400k
    if (newbuf == NULL) {
2526
18
        xmlSAX2ErrMemory(ctxt);
2527
18
        return;
2528
18
    }
2529
400k
    ctxt->nodemem = size;
2530
400k
    lastChild->content = newbuf;
2531
400k
      }
2532
700k
      memcpy(&lastChild->content[ctxt->nodelen], ch, len);
2533
700k
      ctxt->nodelen += len;
2534
700k
      lastChild->content[ctxt->nodelen] = 0;
2535
2.82M
  } else if (coalesceText) {
2536
0
      if (xmlTextConcat(lastChild, ch, len)) {
2537
0
    xmlSAX2ErrMemory(ctxt);
2538
0
      }
2539
0
      if (ctxt->node->children != NULL) {
2540
0
    ctxt->nodelen = xmlStrlen(lastChild->content);
2541
0
    ctxt->nodemem = ctxt->nodelen + 1;
2542
0
      }
2543
2.82M
  } else {
2544
      /* Mixed content, first time */
2545
2.82M
            if (type == XML_TEXT_NODE) {
2546
2.82M
                lastChild = xmlSAX2TextNode(ctxt, ch, len);
2547
2.82M
                if (lastChild != NULL)
2548
2.82M
                    lastChild->doc = ctxt->myDoc;
2549
2.82M
            } else
2550
0
                lastChild = xmlNewCDataBlock(ctxt->myDoc, ch, len);
2551
2.82M
      if (lastChild == NULL) {
2552
102
                xmlSAX2ErrMemory(ctxt);
2553
2.82M
            } else {
2554
2.82M
    xmlSAX2AppendChild(ctxt, lastChild);
2555
2.82M
    if (ctxt->node->children != NULL) {
2556
2.82M
        ctxt->nodelen = len;
2557
2.82M
        ctxt->nodemem = len + 1;
2558
2.82M
    }
2559
2.82M
      }
2560
2.82M
  }
2561
3.52M
    }
2562
2563
4.58M
    if ((lastChild != NULL) &&
2564
4.58M
        (type == XML_TEXT_NODE) &&
2565
4.58M
        (ctxt->linenumbers) &&
2566
4.58M
        (ctxt->input != NULL)) {
2567
4.58M
        if ((unsigned) ctxt->input->line < (unsigned) USHRT_MAX)
2568
4.55M
            lastChild->line = ctxt->input->line;
2569
22.6k
        else {
2570
22.6k
            lastChild->line = USHRT_MAX;
2571
22.6k
            if (ctxt->options & XML_PARSE_BIG_LINES)
2572
0
                lastChild->psvi = XML_INT_TO_PTR(ctxt->input->line);
2573
22.6k
        }
2574
4.58M
    }
2575
4.58M
}
2576
2577
/**
2578
 * xmlSAX2Characters:
2579
 * @ctx: the user data (XML parser context)
2580
 * @ch:  a xmlChar string
2581
 * @len: the number of xmlChar
2582
 *
2583
 * receiving some chars from the parser.
2584
 */
2585
void
2586
xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
2587
4.58M
{
2588
4.58M
    xmlSAX2Text((xmlParserCtxtPtr) ctx, ch, len, XML_TEXT_NODE);
2589
4.58M
}
2590
2591
/**
2592
 * xmlSAX2IgnorableWhitespace:
2593
 * @ctx: the user data (XML parser context)
2594
 * @ch:  a xmlChar string
2595
 * @len: the number of xmlChar
2596
 *
2597
 * receiving some ignorable whitespaces from the parser.
2598
 * UNUSED: by default the DOM building will use xmlSAX2Characters
2599
 */
2600
void
2601
xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
2602
0
{
2603
0
}
2604
2605
/**
2606
 * xmlSAX2ProcessingInstruction:
2607
 * @ctx: the user data (XML parser context)
2608
 * @target:  the target name
2609
 * @data: the PI data's
2610
 *
2611
 * A processing instruction has been parsed.
2612
 */
2613
void
2614
xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
2615
                      const xmlChar *data)
2616
85.5k
{
2617
85.5k
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2618
85.5k
    xmlNodePtr ret;
2619
2620
85.5k
    if (ctx == NULL) return;
2621
2622
85.5k
    ret = xmlNewDocPI(ctxt->myDoc, target, data);
2623
85.5k
    if (ret == NULL) {
2624
6
        xmlSAX2ErrMemory(ctxt);
2625
6
        return;
2626
6
    }
2627
2628
85.5k
    xmlSAX2AppendChild(ctxt, ret);
2629
85.5k
}
2630
2631
/**
2632
 * xmlSAX2Comment:
2633
 * @ctx: the user data (XML parser context)
2634
 * @value:  the xmlSAX2Comment content
2635
 *
2636
 * A xmlSAX2Comment has been parsed.
2637
 */
2638
void
2639
xmlSAX2Comment(void *ctx, const xmlChar *value)
2640
86.0k
{
2641
86.0k
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2642
86.0k
    xmlNodePtr ret;
2643
2644
86.0k
    if (ctx == NULL) return;
2645
2646
86.0k
    ret = xmlNewDocComment(ctxt->myDoc, value);
2647
86.0k
    if (ret == NULL) {
2648
7
        xmlSAX2ErrMemory(ctxt);
2649
7
        return;
2650
7
    }
2651
2652
86.0k
    xmlSAX2AppendChild(ctxt, ret);
2653
86.0k
}
2654
2655
/**
2656
 * xmlSAX2CDataBlock:
2657
 * @ctx: the user data (XML parser context)
2658
 * @value:  The pcdata content
2659
 * @len:  the block length
2660
 *
2661
 * called when a pcdata block has been parsed
2662
 */
2663
void
2664
xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
2665
0
{
2666
0
    xmlSAX2Text((xmlParserCtxtPtr) ctx, value, len, XML_CDATA_SECTION_NODE);
2667
0
}
2668
2669
#ifdef LIBXML_SAX1_ENABLED
2670
/**
2671
 * xmlSAXDefaultVersion:
2672
 * @version:  the version, must be 2
2673
 *
2674
 * DEPRECATED: Use parser option XML_PARSE_SAX1.
2675
 *
2676
 * Has no effect.
2677
 *
2678
 * Returns 2 in case of success and -1 in case of error.
2679
 */
2680
int
2681
xmlSAXDefaultVersion(int version)
2682
{
2683
    if (version != 2)
2684
        return(-1);
2685
    return(2);
2686
}
2687
#endif /* LIBXML_SAX1_ENABLED */
2688
2689
/**
2690
 * xmlSAXVersion:
2691
 * @hdlr:  the SAX handler
2692
 * @version:  the version, 1 or 2
2693
 *
2694
 * Initialize the default XML SAX handler according to the version
2695
 *
2696
 * Returns 0 in case of success and -1 in case of error.
2697
 */
2698
int
2699
xmlSAXVersion(xmlSAXHandler *hdlr, int version)
2700
1.02M
{
2701
1.02M
    if (hdlr == NULL) return(-1);
2702
1.02M
    if (version == 2) {
2703
1.02M
  hdlr->startElementNs = xmlSAX2StartElementNs;
2704
1.02M
  hdlr->endElementNs = xmlSAX2EndElementNs;
2705
1.02M
  hdlr->serror = NULL;
2706
1.02M
  hdlr->initialized = XML_SAX2_MAGIC;
2707
#ifdef LIBXML_SAX1_ENABLED
2708
    } else if (version == 1) {
2709
  hdlr->initialized = 1;
2710
#endif /* LIBXML_SAX1_ENABLED */
2711
1.02M
    } else
2712
0
        return(-1);
2713
#ifdef LIBXML_SAX1_ENABLED
2714
    hdlr->startElement = xmlSAX2StartElement;
2715
    hdlr->endElement = xmlSAX2EndElement;
2716
#else
2717
1.02M
    hdlr->startElement = NULL;
2718
1.02M
    hdlr->endElement = NULL;
2719
1.02M
#endif /* LIBXML_SAX1_ENABLED */
2720
1.02M
    hdlr->internalSubset = xmlSAX2InternalSubset;
2721
1.02M
    hdlr->externalSubset = xmlSAX2ExternalSubset;
2722
1.02M
    hdlr->isStandalone = xmlSAX2IsStandalone;
2723
1.02M
    hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2724
1.02M
    hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2725
1.02M
    hdlr->resolveEntity = xmlSAX2ResolveEntity;
2726
1.02M
    hdlr->getEntity = xmlSAX2GetEntity;
2727
1.02M
    hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
2728
1.02M
    hdlr->entityDecl = xmlSAX2EntityDecl;
2729
1.02M
    hdlr->attributeDecl = xmlSAX2AttributeDecl;
2730
1.02M
    hdlr->elementDecl = xmlSAX2ElementDecl;
2731
1.02M
    hdlr->notationDecl = xmlSAX2NotationDecl;
2732
1.02M
    hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
2733
1.02M
    hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2734
1.02M
    hdlr->startDocument = xmlSAX2StartDocument;
2735
1.02M
    hdlr->endDocument = xmlSAX2EndDocument;
2736
1.02M
    hdlr->reference = xmlSAX2Reference;
2737
1.02M
    hdlr->characters = xmlSAX2Characters;
2738
1.02M
    hdlr->cdataBlock = xmlSAX2CDataBlock;
2739
1.02M
    hdlr->ignorableWhitespace = xmlSAX2Characters;
2740
1.02M
    hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2741
1.02M
    hdlr->comment = xmlSAX2Comment;
2742
1.02M
    hdlr->warning = xmlParserWarning;
2743
1.02M
    hdlr->error = xmlParserError;
2744
1.02M
    hdlr->fatalError = xmlParserError;
2745
2746
1.02M
    return(0);
2747
1.02M
}
2748
2749
/**
2750
 * xmlSAX2InitDefaultSAXHandler:
2751
 * @hdlr:  the SAX handler
2752
 * @warning:  flag if non-zero sets the handler warning procedure
2753
 *
2754
 * Initialize the default XML SAX2 handler
2755
 */
2756
void
2757
xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
2758
0
{
2759
0
    if ((hdlr == NULL) || (hdlr->initialized != 0))
2760
0
  return;
2761
2762
0
    xmlSAXVersion(hdlr, 2);
2763
0
    if (warning == 0)
2764
0
  hdlr->warning = NULL;
2765
0
}
2766
2767
/**
2768
 * xmlDefaultSAXHandlerInit:
2769
 *
2770
 * DEPRECATED: This function is a no-op. Call xmlInitParser to
2771
 * initialize the library.
2772
 *
2773
 * Initialize the default SAX2 handler
2774
 */
2775
void
2776
xmlDefaultSAXHandlerInit(void)
2777
0
{
2778
0
}
2779
2780
#ifdef LIBXML_HTML_ENABLED
2781
2782
/**
2783
 * xmlSAX2InitHtmlDefaultSAXHandler:
2784
 * @hdlr:  the SAX handler
2785
 *
2786
 * Initialize the default HTML SAX2 handler
2787
 */
2788
void
2789
xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
2790
0
{
2791
0
    if ((hdlr == NULL) || (hdlr->initialized != 0))
2792
0
  return;
2793
2794
0
    hdlr->internalSubset = xmlSAX2InternalSubset;
2795
0
    hdlr->externalSubset = NULL;
2796
0
    hdlr->isStandalone = NULL;
2797
0
    hdlr->hasInternalSubset = NULL;
2798
0
    hdlr->hasExternalSubset = NULL;
2799
0
    hdlr->resolveEntity = NULL;
2800
0
    hdlr->getEntity = xmlSAX2GetEntity;
2801
0
    hdlr->getParameterEntity = NULL;
2802
0
    hdlr->entityDecl = NULL;
2803
0
    hdlr->attributeDecl = NULL;
2804
0
    hdlr->elementDecl = NULL;
2805
0
    hdlr->notationDecl = NULL;
2806
0
    hdlr->unparsedEntityDecl = NULL;
2807
0
    hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2808
0
    hdlr->startDocument = xmlSAX2StartDocument;
2809
0
    hdlr->endDocument = xmlSAX2EndDocument;
2810
0
    hdlr->startElement = xmlSAX2StartElement;
2811
0
    hdlr->endElement = xmlSAX2EndElement;
2812
0
    hdlr->reference = NULL;
2813
0
    hdlr->characters = xmlSAX2Characters;
2814
0
    hdlr->cdataBlock = xmlSAX2CDataBlock;
2815
0
    hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2816
0
    hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2817
0
    hdlr->comment = xmlSAX2Comment;
2818
0
    hdlr->warning = xmlParserWarning;
2819
0
    hdlr->error = xmlParserError;
2820
0
    hdlr->fatalError = xmlParserError;
2821
2822
0
    hdlr->initialized = 1;
2823
0
}
2824
2825
/**
2826
 * htmlDefaultSAXHandlerInit:
2827
 *
2828
 * DEPRECATED: This function is a no-op. Call xmlInitParser to
2829
 * initialize the library.
2830
 */
2831
void
2832
htmlDefaultSAXHandlerInit(void)
2833
0
{
2834
0
}
2835
2836
#endif /* LIBXML_HTML_ENABLED */