Coverage Report

Created: 2025-07-11 06:46

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