Coverage Report

Created: 2024-09-06 07:53

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