Coverage Report

Created: 2025-08-11 08:01

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