Coverage Report

Created: 2025-07-12 06:33

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