Coverage Report

Created: 2025-11-16 09:57

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