Coverage Report

Created: 2025-07-23 08:13

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