Coverage Report

Created: 2025-06-22 06:55

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