Coverage Report

Created: 2025-07-23 08:13

/src/fontconfig/subprojects/libxml2-2.12.6/parserInternals.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * parserInternals.c : Internal routines (and obsolete ones) needed for the
3
 *                     XML and HTML parsers.
4
 *
5
 * See Copyright for the status of this software.
6
 *
7
 * daniel@veillard.com
8
 */
9
10
#define IN_LIBXML
11
#include "libxml.h"
12
13
#if defined(_WIN32)
14
#define XML_DIR_SEP '\\'
15
#else
16
#define XML_DIR_SEP '/'
17
#endif
18
19
#include <string.h>
20
#include <ctype.h>
21
#include <stdlib.h>
22
23
#include <libxml/xmlmemory.h>
24
#include <libxml/tree.h>
25
#include <libxml/parser.h>
26
#include <libxml/parserInternals.h>
27
#include <libxml/entities.h>
28
#include <libxml/xmlerror.h>
29
#include <libxml/encoding.h>
30
#include <libxml/xmlIO.h>
31
#include <libxml/uri.h>
32
#include <libxml/dict.h>
33
#include <libxml/xmlsave.h>
34
#ifdef LIBXML_CATALOG_ENABLED
35
#include <libxml/catalog.h>
36
#endif
37
#include <libxml/chvalid.h>
38
39
#define CUR(ctxt) ctxt->input->cur
40
#define END(ctxt) ctxt->input->end
41
42
#include "private/buf.h"
43
#include "private/enc.h"
44
#include "private/error.h"
45
#include "private/io.h"
46
#include "private/parser.h"
47
48
/*
49
 * XML_MAX_AMPLIFICATION_DEFAULT is the default maximum allowed amplification
50
 * factor of serialized output after entity expansion.
51
 */
52
11
#define XML_MAX_AMPLIFICATION_DEFAULT 5
53
54
/*
55
 * Various global defaults for parsing
56
 */
57
58
/**
59
 * xmlCheckVersion:
60
 * @version: the include version number
61
 *
62
 * check the compiled lib version against the include one.
63
 * This can warn or immediately kill the application
64
 */
65
void
66
0
xmlCheckVersion(int version) {
67
0
    int myversion = LIBXML_VERSION;
68
69
0
    xmlInitParser();
70
71
0
    if ((myversion / 10000) != (version / 10000)) {
72
0
  xmlGenericError(xmlGenericErrorContext,
73
0
    "Fatal: program compiled against libxml %d using libxml %d\n",
74
0
    (version / 10000), (myversion / 10000));
75
0
  fprintf(stderr,
76
0
    "Fatal: program compiled against libxml %d using libxml %d\n",
77
0
    (version / 10000), (myversion / 10000));
78
0
    }
79
0
    if ((myversion / 100) < (version / 100)) {
80
0
  xmlGenericError(xmlGenericErrorContext,
81
0
    "Warning: program compiled against libxml %d using older %d\n",
82
0
    (version / 100), (myversion / 100));
83
0
    }
84
0
}
85
86
87
/************************************************************************
88
 *                  *
89
 *    Some factorized error routines        *
90
 *                  *
91
 ************************************************************************/
92
93
94
/**
95
 * xmlErrMemory:
96
 * @ctxt:  an XML parser context
97
 * @extra:  extra information
98
 *
99
 * Handle a redefinition of attribute error
100
 */
101
void
102
xmlErrMemory(xmlParserCtxtPtr ctxt, const char *extra)
103
0
{
104
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
105
0
        (ctxt->instate == XML_PARSER_EOF))
106
0
  return;
107
0
    if (ctxt != NULL) {
108
0
        ctxt->errNo = XML_ERR_NO_MEMORY;
109
0
        ctxt->instate = XML_PARSER_EOF;
110
0
        ctxt->disableSAX = 1;
111
0
    }
112
0
    if (extra)
113
0
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
114
0
                        XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
115
0
                        NULL, NULL, 0, 0,
116
0
                        "Memory allocation failed : %s\n", extra);
117
0
    else
118
0
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
119
0
                        XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,
120
0
                        NULL, NULL, 0, 0, "Memory allocation failed\n");
121
0
}
122
123
/**
124
 * __xmlErrEncoding:
125
 * @ctxt:  an XML parser context
126
 * @xmlerr:  the error number
127
 * @msg:  the error message
128
 * @str1:  an string info
129
 * @str2:  an string info
130
 *
131
 * Handle an encoding error
132
 */
133
void
134
__xmlErrEncoding(xmlParserCtxtPtr ctxt, xmlParserErrors xmlerr,
135
                 const char *msg, const xmlChar * str1, const xmlChar * str2)
136
0
{
137
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
138
0
        (ctxt->instate == XML_PARSER_EOF))
139
0
  return;
140
0
    if (ctxt != NULL)
141
0
        ctxt->errNo = xmlerr;
142
0
    __xmlRaiseError(NULL, NULL, NULL,
143
0
                    ctxt, NULL, XML_FROM_PARSER, xmlerr, XML_ERR_FATAL,
144
0
                    NULL, 0, (const char *) str1, (const char *) str2,
145
0
                    NULL, 0, 0, msg, str1, str2);
146
0
    if (ctxt != NULL) {
147
0
        ctxt->wellFormed = 0;
148
0
        if (ctxt->recovery == 0)
149
0
            ctxt->disableSAX = 1;
150
0
    }
151
0
}
152
153
/**
154
 * xmlErrInternal:
155
 * @ctxt:  an XML parser context
156
 * @msg:  the error message
157
 * @str:  error information
158
 *
159
 * Handle an internal error
160
 */
161
static void LIBXML_ATTR_FORMAT(2,0)
162
xmlErrInternal(xmlParserCtxtPtr ctxt, const char *msg, const xmlChar * str)
163
0
{
164
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
165
0
        (ctxt->instate == XML_PARSER_EOF))
166
0
  return;
167
0
    if (ctxt != NULL)
168
0
        ctxt->errNo = XML_ERR_INTERNAL_ERROR;
169
0
    __xmlRaiseError(NULL, NULL, NULL,
170
0
                    ctxt, NULL, XML_FROM_PARSER, XML_ERR_INTERNAL_ERROR,
171
0
                    XML_ERR_FATAL, NULL, 0, (const char *) str, NULL, NULL,
172
0
                    0, 0, msg, str);
173
0
    if (ctxt != NULL) {
174
0
        ctxt->wellFormed = 0;
175
0
        if (ctxt->recovery == 0)
176
0
            ctxt->disableSAX = 1;
177
0
    }
178
0
}
179
180
/**
181
 * xmlFatalErr:
182
 * @ctxt:  an XML parser context
183
 * @error:  the error number
184
 * @info:  extra information string
185
 *
186
 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
187
 */
188
void
189
xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
190
0
{
191
0
    const char *errmsg;
192
193
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
194
0
        (ctxt->instate == XML_PARSER_EOF))
195
0
  return;
196
0
    switch (error) {
197
0
        case XML_ERR_INVALID_HEX_CHARREF:
198
0
            errmsg = "CharRef: invalid hexadecimal value";
199
0
            break;
200
0
        case XML_ERR_INVALID_DEC_CHARREF:
201
0
            errmsg = "CharRef: invalid decimal value";
202
0
            break;
203
0
        case XML_ERR_INVALID_CHARREF:
204
0
            errmsg = "CharRef: invalid value";
205
0
            break;
206
0
        case XML_ERR_INTERNAL_ERROR:
207
0
            errmsg = "internal error";
208
0
            break;
209
0
        case XML_ERR_PEREF_AT_EOF:
210
0
            errmsg = "PEReference at end of document";
211
0
            break;
212
0
        case XML_ERR_PEREF_IN_PROLOG:
213
0
            errmsg = "PEReference in prolog";
214
0
            break;
215
0
        case XML_ERR_PEREF_IN_EPILOG:
216
0
            errmsg = "PEReference in epilog";
217
0
            break;
218
0
        case XML_ERR_PEREF_NO_NAME:
219
0
            errmsg = "PEReference: no name";
220
0
            break;
221
0
        case XML_ERR_PEREF_SEMICOL_MISSING:
222
0
            errmsg = "PEReference: expecting ';'";
223
0
            break;
224
0
        case XML_ERR_ENTITY_LOOP:
225
0
            errmsg = "Detected an entity reference loop";
226
0
            break;
227
0
        case XML_ERR_ENTITY_NOT_STARTED:
228
0
            errmsg = "EntityValue: \" or ' expected";
229
0
            break;
230
0
        case XML_ERR_ENTITY_PE_INTERNAL:
231
0
            errmsg = "PEReferences forbidden in internal subset";
232
0
            break;
233
0
        case XML_ERR_ENTITY_NOT_FINISHED:
234
0
            errmsg = "EntityValue: \" or ' expected";
235
0
            break;
236
0
        case XML_ERR_ATTRIBUTE_NOT_STARTED:
237
0
            errmsg = "AttValue: \" or ' expected";
238
0
            break;
239
0
        case XML_ERR_LT_IN_ATTRIBUTE:
240
0
            errmsg = "Unescaped '<' not allowed in attributes values";
241
0
            break;
242
0
        case XML_ERR_LITERAL_NOT_STARTED:
243
0
            errmsg = "SystemLiteral \" or ' expected";
244
0
            break;
245
0
        case XML_ERR_LITERAL_NOT_FINISHED:
246
0
            errmsg = "Unfinished System or Public ID \" or ' expected";
247
0
            break;
248
0
        case XML_ERR_MISPLACED_CDATA_END:
249
0
            errmsg = "Sequence ']]>' not allowed in content";
250
0
            break;
251
0
        case XML_ERR_URI_REQUIRED:
252
0
            errmsg = "SYSTEM or PUBLIC, the URI is missing";
253
0
            break;
254
0
        case XML_ERR_PUBID_REQUIRED:
255
0
            errmsg = "PUBLIC, the Public Identifier is missing";
256
0
            break;
257
0
        case XML_ERR_HYPHEN_IN_COMMENT:
258
0
            errmsg = "Comment must not contain '--' (double-hyphen)";
259
0
            break;
260
0
        case XML_ERR_PI_NOT_STARTED:
261
0
            errmsg = "xmlParsePI : no target name";
262
0
            break;
263
0
        case XML_ERR_RESERVED_XML_NAME:
264
0
            errmsg = "Invalid PI name";
265
0
            break;
266
0
        case XML_ERR_NOTATION_NOT_STARTED:
267
0
            errmsg = "NOTATION: Name expected here";
268
0
            break;
269
0
        case XML_ERR_NOTATION_NOT_FINISHED:
270
0
            errmsg = "'>' required to close NOTATION declaration";
271
0
            break;
272
0
        case XML_ERR_VALUE_REQUIRED:
273
0
            errmsg = "Entity value required";
274
0
            break;
275
0
        case XML_ERR_URI_FRAGMENT:
276
0
            errmsg = "Fragment not allowed";
277
0
            break;
278
0
        case XML_ERR_ATTLIST_NOT_STARTED:
279
0
            errmsg = "'(' required to start ATTLIST enumeration";
280
0
            break;
281
0
        case XML_ERR_NMTOKEN_REQUIRED:
282
0
            errmsg = "NmToken expected in ATTLIST enumeration";
283
0
            break;
284
0
        case XML_ERR_ATTLIST_NOT_FINISHED:
285
0
            errmsg = "')' required to finish ATTLIST enumeration";
286
0
            break;
287
0
        case XML_ERR_MIXED_NOT_STARTED:
288
0
            errmsg = "MixedContentDecl : '|' or ')*' expected";
289
0
            break;
290
0
        case XML_ERR_PCDATA_REQUIRED:
291
0
            errmsg = "MixedContentDecl : '#PCDATA' expected";
292
0
            break;
293
0
        case XML_ERR_ELEMCONTENT_NOT_STARTED:
294
0
            errmsg = "ContentDecl : Name or '(' expected";
295
0
            break;
296
0
        case XML_ERR_ELEMCONTENT_NOT_FINISHED:
297
0
            errmsg = "ContentDecl : ',' '|' or ')' expected";
298
0
            break;
299
0
        case XML_ERR_PEREF_IN_INT_SUBSET:
300
0
            errmsg =
301
0
                "PEReference: forbidden within markup decl in internal subset";
302
0
            break;
303
0
        case XML_ERR_GT_REQUIRED:
304
0
            errmsg = "expected '>'";
305
0
            break;
306
0
        case XML_ERR_CONDSEC_INVALID:
307
0
            errmsg = "XML conditional section '[' expected";
308
0
            break;
309
0
        case XML_ERR_EXT_SUBSET_NOT_FINISHED:
310
0
            errmsg = "Content error in the external subset";
311
0
            break;
312
0
        case XML_ERR_CONDSEC_INVALID_KEYWORD:
313
0
            errmsg =
314
0
                "conditional section INCLUDE or IGNORE keyword expected";
315
0
            break;
316
0
        case XML_ERR_CONDSEC_NOT_FINISHED:
317
0
            errmsg = "XML conditional section not closed";
318
0
            break;
319
0
        case XML_ERR_XMLDECL_NOT_STARTED:
320
0
            errmsg = "Text declaration '<?xml' required";
321
0
            break;
322
0
        case XML_ERR_XMLDECL_NOT_FINISHED:
323
0
            errmsg = "parsing XML declaration: '?>' expected";
324
0
            break;
325
0
        case XML_ERR_EXT_ENTITY_STANDALONE:
326
0
            errmsg = "external parsed entities cannot be standalone";
327
0
            break;
328
0
        case XML_ERR_ENTITYREF_SEMICOL_MISSING:
329
0
            errmsg = "EntityRef: expecting ';'";
330
0
            break;
331
0
        case XML_ERR_DOCTYPE_NOT_FINISHED:
332
0
            errmsg = "DOCTYPE improperly terminated";
333
0
            break;
334
0
        case XML_ERR_LTSLASH_REQUIRED:
335
0
            errmsg = "EndTag: '</' not found";
336
0
            break;
337
0
        case XML_ERR_EQUAL_REQUIRED:
338
0
            errmsg = "expected '='";
339
0
            break;
340
0
        case XML_ERR_STRING_NOT_CLOSED:
341
0
            errmsg = "String not closed expecting \" or '";
342
0
            break;
343
0
        case XML_ERR_STRING_NOT_STARTED:
344
0
            errmsg = "String not started expecting ' or \"";
345
0
            break;
346
0
        case XML_ERR_ENCODING_NAME:
347
0
            errmsg = "Invalid XML encoding name";
348
0
            break;
349
0
        case XML_ERR_STANDALONE_VALUE:
350
0
            errmsg = "standalone accepts only 'yes' or 'no'";
351
0
            break;
352
0
        case XML_ERR_DOCUMENT_EMPTY:
353
0
            errmsg = "Document is empty";
354
0
            break;
355
0
        case XML_ERR_DOCUMENT_END:
356
0
            errmsg = "Extra content at the end of the document";
357
0
            break;
358
0
        case XML_ERR_NOT_WELL_BALANCED:
359
0
            errmsg = "chunk is not well balanced";
360
0
            break;
361
0
        case XML_ERR_EXTRA_CONTENT:
362
0
            errmsg = "extra content at the end of well balanced chunk";
363
0
            break;
364
0
        case XML_ERR_VERSION_MISSING:
365
0
            errmsg = "Malformed declaration expecting version";
366
0
            break;
367
0
        case XML_ERR_NAME_TOO_LONG:
368
0
            errmsg = "Name too long";
369
0
            break;
370
0
        case XML_ERR_INVALID_ENCODING:
371
0
            errmsg = "Invalid bytes in character encoding";
372
0
            break;
373
0
        case XML_IO_UNKNOWN:
374
0
            errmsg = "I/O error";
375
0
            break;
376
#if 0
377
        case:
378
            errmsg = "";
379
            break;
380
#endif
381
0
        default:
382
0
            errmsg = "Unregistered error message";
383
0
    }
384
0
    if (ctxt != NULL)
385
0
  ctxt->errNo = error;
386
0
    if (info == NULL) {
387
0
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
388
0
                        XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s\n",
389
0
                        errmsg);
390
0
    } else {
391
0
        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
392
0
                        XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s: %s\n",
393
0
                        errmsg, info);
394
0
    }
395
0
    if (ctxt != NULL) {
396
0
  ctxt->wellFormed = 0;
397
0
  if (ctxt->recovery == 0)
398
0
      ctxt->disableSAX = 1;
399
0
    }
400
0
}
401
402
/**
403
 * xmlErrEncodingInt:
404
 * @ctxt:  an XML parser context
405
 * @error:  the error number
406
 * @msg:  the error message
407
 * @val:  an integer value
408
 *
409
 * n encoding error
410
 */
411
static void LIBXML_ATTR_FORMAT(3,0)
412
xmlErrEncodingInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
413
                  const char *msg, int val)
414
0
{
415
0
    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
416
0
        (ctxt->instate == XML_PARSER_EOF))
417
0
  return;
418
0
    if (ctxt != NULL)
419
0
        ctxt->errNo = error;
420
0
    __xmlRaiseError(NULL, NULL, NULL,
421
0
                    ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
422
0
                    NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
423
0
    if (ctxt != NULL) {
424
0
        ctxt->wellFormed = 0;
425
0
        if (ctxt->recovery == 0)
426
0
            ctxt->disableSAX = 1;
427
0
    }
428
0
}
429
430
/**
431
 * xmlIsLetter:
432
 * @c:  an unicode character (int)
433
 *
434
 * Check whether the character is allowed by the production
435
 * [84] Letter ::= BaseChar | Ideographic
436
 *
437
 * Returns 0 if not, non-zero otherwise
438
 */
439
int
440
0
xmlIsLetter(int c) {
441
0
    return(IS_BASECHAR(c) || IS_IDEOGRAPHIC(c));
442
0
}
443
444
/************************************************************************
445
 *                  *
446
 *    Input handling functions for progressive parsing  *
447
 *                  *
448
 ************************************************************************/
449
450
/* we need to keep enough input to show errors in context */
451
0
#define LINE_LEN        80
452
453
/**
454
 * xmlHaltParser:
455
 * @ctxt:  an XML parser context
456
 *
457
 * Blocks further parser processing don't override error
458
 * for internal use
459
 */
460
void
461
0
xmlHaltParser(xmlParserCtxtPtr ctxt) {
462
0
    if (ctxt == NULL)
463
0
        return;
464
0
    ctxt->instate = XML_PARSER_EOF;
465
0
    ctxt->disableSAX = 1;
466
0
    while (ctxt->inputNr > 1)
467
0
        xmlFreeInputStream(inputPop(ctxt));
468
0
    if (ctxt->input != NULL) {
469
        /*
470
   * in case there was a specific allocation deallocate before
471
   * overriding base
472
   */
473
0
        if (ctxt->input->free != NULL) {
474
0
      ctxt->input->free((xmlChar *) ctxt->input->base);
475
0
      ctxt->input->free = NULL;
476
0
  }
477
0
        if (ctxt->input->buf != NULL) {
478
0
            xmlFreeParserInputBuffer(ctxt->input->buf);
479
0
            ctxt->input->buf = NULL;
480
0
        }
481
0
  ctxt->input->cur = BAD_CAST"";
482
0
        ctxt->input->length = 0;
483
0
  ctxt->input->base = ctxt->input->cur;
484
0
        ctxt->input->end = ctxt->input->cur;
485
0
    }
486
0
}
487
488
/**
489
 * xmlParserInputRead:
490
 * @in:  an XML parser input
491
 * @len:  an indicative size for the lookahead
492
 *
493
 * DEPRECATED: This function was internal and is deprecated.
494
 *
495
 * Returns -1 as this is an error to use it.
496
 */
497
int
498
0
xmlParserInputRead(xmlParserInputPtr in ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED) {
499
0
    return(-1);
500
0
}
501
502
/**
503
 * xmlParserGrow:
504
 * @ctxt:  an XML parser context
505
 *
506
 * Grow the input buffer.
507
 *
508
 * Returns the number of bytes read or -1 in case of error.
509
 */
510
int
511
649
xmlParserGrow(xmlParserCtxtPtr ctxt) {
512
649
    xmlParserInputPtr in = ctxt->input;
513
649
    xmlParserInputBufferPtr buf = in->buf;
514
649
    ptrdiff_t curEnd = in->end - in->cur;
515
649
    ptrdiff_t curBase = in->cur - in->base;
516
649
    int ret;
517
518
649
    if (buf == NULL)
519
0
        return(0);
520
    /* Don't grow push parser buffer. */
521
649
    if ((ctxt->progressive) && (ctxt->inputNr <= 1))
522
649
        return(0);
523
    /* Don't grow memory buffers. */
524
0
    if ((buf->encoder == NULL) && (buf->readcallback == NULL))
525
0
        return(0);
526
0
    if (buf->error != 0)
527
0
        return(-1);
528
529
0
    if (((curEnd > XML_MAX_LOOKUP_LIMIT) ||
530
0
         (curBase > XML_MAX_LOOKUP_LIMIT)) &&
531
0
        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
532
0
        xmlErrMemory(ctxt, "Huge input lookup");
533
0
        xmlHaltParser(ctxt);
534
0
  return(-1);
535
0
    }
536
537
0
    if (curEnd >= INPUT_CHUNK)
538
0
        return(0);
539
540
0
    ret = xmlParserInputBufferGrow(buf, INPUT_CHUNK);
541
0
    xmlBufUpdateInput(buf->buffer, in, curBase);
542
543
0
    if (ret < 0) {
544
0
        xmlFatalErr(ctxt, buf->error, NULL);
545
        /* Buffer contents may be lost in case of memory errors. */
546
0
        if (buf->error == XML_ERR_NO_MEMORY)
547
0
            xmlHaltParser(ctxt);
548
0
    }
549
550
0
    return(ret);
551
0
}
552
553
/**
554
 * xmlParserInputGrow:
555
 * @in:  an XML parser input
556
 * @len:  an indicative size for the lookahead
557
 *
558
 * DEPRECATED: Don't use.
559
 *
560
 * This function increase the input for the parser. It tries to
561
 * preserve pointers to the input buffer, and keep already read data
562
 *
563
 * Returns the amount of char read, or -1 in case of error, 0 indicate the
564
 * end of this entity
565
 */
566
int
567
0
xmlParserInputGrow(xmlParserInputPtr in, int len) {
568
0
    int ret;
569
0
    size_t indx;
570
571
0
    if ((in == NULL) || (len < 0)) return(-1);
572
0
    if (in->buf == NULL) return(-1);
573
0
    if (in->base == NULL) return(-1);
574
0
    if (in->cur == NULL) return(-1);
575
0
    if (in->buf->buffer == NULL) return(-1);
576
577
    /* Don't grow memory buffers. */
578
0
    if ((in->buf->encoder == NULL) && (in->buf->readcallback == NULL))
579
0
        return(0);
580
581
0
    indx = in->cur - in->base;
582
0
    if (xmlBufUse(in->buf->buffer) > (unsigned int) indx + INPUT_CHUNK) {
583
0
        return(0);
584
0
    }
585
0
    ret = xmlParserInputBufferGrow(in->buf, len);
586
587
0
    in->base = xmlBufContent(in->buf->buffer);
588
0
    if (in->base == NULL) {
589
0
        in->base = BAD_CAST "";
590
0
        in->cur = in->base;
591
0
        in->end = in->base;
592
0
        return(-1);
593
0
    }
594
0
    in->cur = in->base + indx;
595
0
    in->end = xmlBufEnd(in->buf->buffer);
596
597
0
    return(ret);
598
0
}
599
600
/**
601
 * xmlParserShrink:
602
 * @ctxt:  an XML parser context
603
 *
604
 * Shrink the input buffer.
605
 */
606
void
607
0
xmlParserShrink(xmlParserCtxtPtr ctxt) {
608
0
    xmlParserInputPtr in = ctxt->input;
609
0
    xmlParserInputBufferPtr buf = in->buf;
610
0
    size_t used;
611
612
0
    if (buf == NULL)
613
0
        return;
614
    /* Don't shrink pull parser memory buffers. */
615
0
    if (((ctxt->progressive == 0) || (ctxt->inputNr > 1)) &&
616
0
        (buf->encoder == NULL) &&
617
0
        (buf->readcallback == NULL))
618
0
        return;
619
620
0
    used = in->cur - in->base;
621
    /*
622
     * Do not shrink on large buffers whose only a tiny fraction
623
     * was consumed
624
     */
625
0
    if (used > INPUT_CHUNK) {
626
0
  size_t res = xmlBufShrink(buf->buffer, used - LINE_LEN);
627
628
0
  if (res > 0) {
629
0
            used -= res;
630
0
            if ((res > ULONG_MAX) ||
631
0
                (in->consumed > ULONG_MAX - (unsigned long)res))
632
0
                in->consumed = ULONG_MAX;
633
0
            else
634
0
                in->consumed += res;
635
0
  }
636
0
    }
637
638
0
    xmlBufUpdateInput(buf->buffer, in, used);
639
0
}
640
641
/**
642
 * xmlParserInputShrink:
643
 * @in:  an XML parser input
644
 *
645
 * DEPRECATED: Don't use.
646
 *
647
 * This function removes used input for the parser.
648
 */
649
void
650
0
xmlParserInputShrink(xmlParserInputPtr in) {
651
0
    size_t used;
652
0
    size_t ret;
653
654
0
    if (in == NULL) return;
655
0
    if (in->buf == NULL) return;
656
0
    if (in->base == NULL) return;
657
0
    if (in->cur == NULL) return;
658
0
    if (in->buf->buffer == NULL) return;
659
660
0
    used = in->cur - in->base;
661
    /*
662
     * Do not shrink on large buffers whose only a tiny fraction
663
     * was consumed
664
     */
665
0
    if (used > INPUT_CHUNK) {
666
0
  ret = xmlBufShrink(in->buf->buffer, used - LINE_LEN);
667
0
  if (ret > 0) {
668
0
            used -= ret;
669
0
            if ((ret > ULONG_MAX) ||
670
0
                (in->consumed > ULONG_MAX - (unsigned long)ret))
671
0
                in->consumed = ULONG_MAX;
672
0
            else
673
0
                in->consumed += ret;
674
0
  }
675
0
    }
676
677
0
    if (xmlBufUse(in->buf->buffer) <= INPUT_CHUNK) {
678
0
        xmlParserInputBufferRead(in->buf, 2 * INPUT_CHUNK);
679
0
    }
680
681
0
    in->base = xmlBufContent(in->buf->buffer);
682
0
    if (in->base == NULL) {
683
        /* TODO: raise error */
684
0
        in->base = BAD_CAST "";
685
0
        in->cur = in->base;
686
0
        in->end = in->base;
687
0
        return;
688
0
    }
689
0
    in->cur = in->base + used;
690
0
    in->end = xmlBufEnd(in->buf->buffer);
691
0
}
692
693
/************************************************************************
694
 *                  *
695
 *    UTF8 character input and related functions    *
696
 *                  *
697
 ************************************************************************/
698
699
/**
700
 * xmlNextChar:
701
 * @ctxt:  the XML parser context
702
 *
703
 * DEPRECATED: Internal function, do not use.
704
 *
705
 * Skip to the next char input char.
706
 */
707
708
void
709
xmlNextChar(xmlParserCtxtPtr ctxt)
710
176
{
711
176
    const unsigned char *cur;
712
176
    size_t avail;
713
176
    int c;
714
715
176
    if ((ctxt == NULL) || (ctxt->instate == XML_PARSER_EOF) ||
716
176
        (ctxt->input == NULL))
717
0
        return;
718
719
176
    avail = ctxt->input->end - ctxt->input->cur;
720
721
176
    if (avail < INPUT_CHUNK) {
722
88
        xmlParserGrow(ctxt);
723
88
        if ((ctxt->instate == XML_PARSER_EOF) ||
724
88
            (ctxt->input->cur >= ctxt->input->end))
725
0
            return;
726
88
        avail = ctxt->input->end - ctxt->input->cur;
727
88
    }
728
729
176
    cur = ctxt->input->cur;
730
176
    c = *cur;
731
732
176
    if (c < 0x80) {
733
176
        if (c == '\n') {
734
0
            ctxt->input->cur++;
735
0
            ctxt->input->line++;
736
0
            ctxt->input->col = 1;
737
176
        } else if (c == '\r') {
738
            /*
739
             *   2.11 End-of-Line Handling
740
             *   the literal two-character sequence "#xD#xA" or a standalone
741
             *   literal #xD, an XML processor must pass to the application
742
             *   the single character #xA.
743
             */
744
0
            ctxt->input->cur += ((cur[1] == '\n') ? 2 : 1);
745
0
            ctxt->input->line++;
746
0
            ctxt->input->col = 1;
747
0
            return;
748
176
        } else {
749
176
            ctxt->input->cur++;
750
176
            ctxt->input->col++;
751
176
        }
752
176
    } else {
753
0
        ctxt->input->col++;
754
755
0
        if ((avail < 2) || (cur[1] & 0xc0) != 0x80)
756
0
            goto encoding_error;
757
758
0
        if (c < 0xe0) {
759
            /* 2-byte code */
760
0
            if (c < 0xc2)
761
0
                goto encoding_error;
762
0
            ctxt->input->cur += 2;
763
0
        } else {
764
0
            unsigned int val = (c << 8) | cur[1];
765
766
0
            if ((avail < 3) || (cur[2] & 0xc0) != 0x80)
767
0
                goto encoding_error;
768
769
0
            if (c < 0xf0) {
770
                /* 3-byte code */
771
0
                if ((val < 0xe0a0) || ((val >= 0xeda0) && (val < 0xee00)))
772
0
                    goto encoding_error;
773
0
                ctxt->input->cur += 3;
774
0
            } else {
775
0
                if ((avail < 4) || ((cur[3] & 0xc0) != 0x80))
776
0
                    goto encoding_error;
777
778
                /* 4-byte code */
779
0
                if ((val < 0xf090) || (val >= 0xf490))
780
0
                    goto encoding_error;
781
0
                ctxt->input->cur += 4;
782
0
            }
783
0
        }
784
0
    }
785
786
176
    return;
787
788
176
encoding_error:
789
    /* Only report the first error */
790
0
    if ((ctxt->input->flags & XML_INPUT_ENCODING_ERROR) == 0) {
791
0
        if ((ctxt == NULL) || (ctxt->input == NULL) ||
792
0
            (ctxt->input->end - ctxt->input->cur < 4)) {
793
0
            __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
794
0
                         "Input is not proper UTF-8, indicate encoding !\n",
795
0
                         NULL, NULL);
796
0
        } else {
797
0
            char buffer[150];
798
799
0
            snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
800
0
                            ctxt->input->cur[0], ctxt->input->cur[1],
801
0
                            ctxt->input->cur[2], ctxt->input->cur[3]);
802
0
            __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
803
0
                         "Input is not proper UTF-8, indicate encoding !\n%s",
804
0
                         BAD_CAST buffer, NULL);
805
0
        }
806
0
        ctxt->input->flags |= XML_INPUT_ENCODING_ERROR;
807
0
    }
808
0
    ctxt->input->cur++;
809
0
    return;
810
176
}
811
812
/**
813
 * xmlCurrentChar:
814
 * @ctxt:  the XML parser context
815
 * @len:  pointer to the length of the char read
816
 *
817
 * DEPRECATED: Internal function, do not use.
818
 *
819
 * The current char value, if using UTF-8 this may actually span multiple
820
 * bytes in the input buffer. Implement the end of line normalization:
821
 * 2.11 End-of-Line Handling
822
 * Wherever an external parsed entity or the literal entity value
823
 * of an internal parsed entity contains either the literal two-character
824
 * sequence "#xD#xA" or a standalone literal #xD, an XML processor
825
 * must pass to the application the single character #xA.
826
 * This behavior can conveniently be produced by normalizing all
827
 * line breaks to #xA on input, before parsing.)
828
 *
829
 * Returns the current char value and its length
830
 */
831
832
int
833
0
xmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
834
0
    const unsigned char *cur;
835
0
    size_t avail;
836
0
    int c;
837
838
0
    if ((ctxt == NULL) || (len == NULL) || (ctxt->input == NULL)) return(0);
839
0
    if (ctxt->instate == XML_PARSER_EOF)
840
0
  return(0);
841
842
0
    avail = ctxt->input->end - ctxt->input->cur;
843
844
0
    if (avail < INPUT_CHUNK) {
845
0
        xmlParserGrow(ctxt);
846
0
        if (ctxt->instate == XML_PARSER_EOF)
847
0
            return(0);
848
0
        avail = ctxt->input->end - ctxt->input->cur;
849
0
    }
850
851
0
    cur = ctxt->input->cur;
852
0
    c = *cur;
853
854
0
    if (c < 0x80) {
855
  /* 1-byte code */
856
0
        if (c < 0x20) {
857
            /*
858
             *   2.11 End-of-Line Handling
859
             *   the literal two-character sequence "#xD#xA" or a standalone
860
             *   literal #xD, an XML processor must pass to the application
861
             *   the single character #xA.
862
             */
863
0
            if (c == '\r') {
864
                /*
865
                 * TODO: This function shouldn't change the 'cur' pointer
866
                 * as side effect, but the NEXTL macro in parser.c relies
867
                 * on this behavior when incrementing line numbers.
868
                 */
869
0
                if (cur[1] == '\n')
870
0
                    ctxt->input->cur++;
871
0
                *len = 1;
872
0
                c = '\n';
873
0
            } else if (c == 0) {
874
0
                if (ctxt->input->cur >= ctxt->input->end) {
875
0
                    *len = 0;
876
0
                } else {
877
0
                    *len = 1;
878
                    /*
879
                     * TODO: Null bytes should be handled by callers,
880
                     * but this can be tricky.
881
                     */
882
0
                    xmlErrEncodingInt(ctxt, XML_ERR_INVALID_CHAR,
883
0
                            "Char 0x0 out of allowed range\n", c);
884
0
                }
885
0
            } else {
886
0
                *len = 1;
887
0
            }
888
0
        } else {
889
0
            *len = 1;
890
0
        }
891
892
0
        return(c);
893
0
    } else {
894
0
        int val;
895
896
0
        if (avail < 2)
897
0
            goto incomplete_sequence;
898
0
        if ((cur[1] & 0xc0) != 0x80)
899
0
            goto encoding_error;
900
901
0
        if (c < 0xe0) {
902
            /* 2-byte code */
903
0
            if (c < 0xc2)
904
0
                goto encoding_error;
905
0
            val = (c & 0x1f) << 6;
906
0
            val |= cur[1] & 0x3f;
907
0
            *len = 2;
908
0
        } else {
909
0
            if (avail < 3)
910
0
                goto incomplete_sequence;
911
0
            if ((cur[2] & 0xc0) != 0x80)
912
0
                goto encoding_error;
913
914
0
            if (c < 0xf0) {
915
                /* 3-byte code */
916
0
                val = (c & 0xf) << 12;
917
0
                val |= (cur[1] & 0x3f) << 6;
918
0
                val |= cur[2] & 0x3f;
919
0
                if ((val < 0x800) || ((val >= 0xd800) && (val < 0xe000)))
920
0
                    goto encoding_error;
921
0
                *len = 3;
922
0
            } else {
923
0
                if (avail < 4)
924
0
                    goto incomplete_sequence;
925
0
                if ((cur[3] & 0xc0) != 0x80)
926
0
                    goto encoding_error;
927
928
                /* 4-byte code */
929
0
                val = (c & 0x0f) << 18;
930
0
                val |= (cur[1] & 0x3f) << 12;
931
0
                val |= (cur[2] & 0x3f) << 6;
932
0
                val |= cur[3] & 0x3f;
933
0
                if ((val < 0x10000) || (val >= 0x110000))
934
0
                    goto encoding_error;
935
0
                *len = 4;
936
0
            }
937
0
        }
938
939
0
        return(val);
940
0
    }
941
942
0
encoding_error:
943
    /* Only report the first error */
944
0
    if ((ctxt->input->flags & XML_INPUT_ENCODING_ERROR) == 0) {
945
0
        if (ctxt->input->end - ctxt->input->cur < 4) {
946
0
            __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
947
0
                         "Input is not proper UTF-8, indicate encoding !\n",
948
0
                         NULL, NULL);
949
0
        } else {
950
0
            char buffer[150];
951
952
0
            snprintf(&buffer[0], 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
953
0
                            ctxt->input->cur[0], ctxt->input->cur[1],
954
0
                            ctxt->input->cur[2], ctxt->input->cur[3]);
955
0
            __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
956
0
                         "Input is not proper UTF-8, indicate encoding !\n%s",
957
0
                         BAD_CAST buffer, NULL);
958
0
        }
959
0
        ctxt->input->flags |= XML_INPUT_ENCODING_ERROR;
960
0
    }
961
0
    *len = 1;
962
0
    return(0xFFFD); /* U+FFFD Replacement Character */
963
964
0
incomplete_sequence:
965
    /*
966
     * An encoding problem may arise from a truncated input buffer
967
     * splitting a character in the middle. In that case do not raise
968
     * an error but return 0. This should only happen when push parsing
969
     * char data.
970
     */
971
0
    *len = 0;
972
0
    return(0);
973
0
}
974
975
/**
976
 * xmlStringCurrentChar:
977
 * @ctxt:  the XML parser context
978
 * @cur:  pointer to the beginning of the char
979
 * @len:  pointer to the length of the char read
980
 *
981
 * DEPRECATED: Internal function, do not use.
982
 *
983
 * The current char value, if using UTF-8 this may actually span multiple
984
 * bytes in the input buffer.
985
 *
986
 * Returns the current char value and its length
987
 */
988
989
int
990
xmlStringCurrentChar(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
991
0
                     const xmlChar *cur, int *len) {
992
0
    int c;
993
994
0
    if ((cur == NULL) || (len == NULL))
995
0
        return(0);
996
997
    /* cur is zero-terminated, so we can lie about its length. */
998
0
    *len = 4;
999
0
    c = xmlGetUTF8Char(cur, len);
1000
1001
0
    return((c < 0) ? 0 : c);
1002
0
}
1003
1004
/**
1005
 * xmlCopyCharMultiByte:
1006
 * @out:  pointer to an array of xmlChar
1007
 * @val:  the char value
1008
 *
1009
 * append the char value in the array
1010
 *
1011
 * Returns the number of xmlChar written
1012
 */
1013
int
1014
0
xmlCopyCharMultiByte(xmlChar *out, int val) {
1015
0
    if ((out == NULL) || (val < 0)) return(0);
1016
    /*
1017
     * We are supposed to handle UTF8, check it's valid
1018
     * From rfc2044: encoding of the Unicode values on UTF-8:
1019
     *
1020
     * UCS-4 range (hex.)           UTF-8 octet sequence (binary)
1021
     * 0000 0000-0000 007F   0xxxxxxx
1022
     * 0000 0080-0000 07FF   110xxxxx 10xxxxxx
1023
     * 0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx
1024
     */
1025
0
    if  (val >= 0x80) {
1026
0
  xmlChar *savedout = out;
1027
0
  int bits;
1028
0
  if (val <   0x800) { *out++= (val >>  6) | 0xC0;  bits=  0; }
1029
0
  else if (val < 0x10000) { *out++= (val >> 12) | 0xE0;  bits=  6;}
1030
0
  else if (val < 0x110000)  { *out++= (val >> 18) | 0xF0;  bits=  12; }
1031
0
  else {
1032
0
      xmlErrEncodingInt(NULL, XML_ERR_INVALID_CHAR,
1033
0
        "Internal error, xmlCopyCharMultiByte 0x%X out of bound\n",
1034
0
            val);
1035
0
      return(0);
1036
0
  }
1037
0
  for ( ; bits >= 0; bits-= 6)
1038
0
      *out++= ((val >> bits) & 0x3F) | 0x80 ;
1039
0
  return (out - savedout);
1040
0
    }
1041
0
    *out = val;
1042
0
    return 1;
1043
0
}
1044
1045
/**
1046
 * xmlCopyChar:
1047
 * @len:  Ignored, compatibility
1048
 * @out:  pointer to an array of xmlChar
1049
 * @val:  the char value
1050
 *
1051
 * append the char value in the array
1052
 *
1053
 * Returns the number of xmlChar written
1054
 */
1055
1056
int
1057
0
xmlCopyChar(int len ATTRIBUTE_UNUSED, xmlChar *out, int val) {
1058
0
    if ((out == NULL) || (val < 0)) return(0);
1059
    /* the len parameter is ignored */
1060
0
    if  (val >= 0x80) {
1061
0
  return(xmlCopyCharMultiByte (out, val));
1062
0
    }
1063
0
    *out = val;
1064
0
    return 1;
1065
0
}
1066
1067
/************************************************************************
1068
 *                  *
1069
 *    Commodity functions to switch encodings     *
1070
 *                  *
1071
 ************************************************************************/
1072
1073
static xmlCharEncodingHandlerPtr
1074
0
xmlDetectEBCDIC(xmlParserInputPtr input) {
1075
0
    xmlChar out[200];
1076
0
    xmlCharEncodingHandlerPtr handler;
1077
0
    int inlen, outlen, res, i;
1078
1079
    /*
1080
     * To detect the EBCDIC code page, we convert the first 200 bytes
1081
     * to EBCDIC-US and try to find the encoding declaration.
1082
     */
1083
0
    handler = xmlGetCharEncodingHandler(XML_CHAR_ENCODING_EBCDIC);
1084
0
    if (handler == NULL)
1085
0
        return(NULL);
1086
0
    outlen = sizeof(out) - 1;
1087
0
    inlen = input->end - input->cur;
1088
0
    res = xmlEncInputChunk(handler, out, &outlen, input->cur, &inlen);
1089
0
    if (res < 0)
1090
0
        return(handler);
1091
0
    out[outlen] = 0;
1092
1093
0
    for (i = 0; i < outlen; i++) {
1094
0
        if (out[i] == '>')
1095
0
            break;
1096
0
        if ((out[i] == 'e') &&
1097
0
            (xmlStrncmp(out + i, BAD_CAST "encoding", 8) == 0)) {
1098
0
            int start, cur, quote;
1099
1100
0
            i += 8;
1101
0
            while (IS_BLANK_CH(out[i]))
1102
0
                i += 1;
1103
0
            if (out[i++] != '=')
1104
0
                break;
1105
0
            while (IS_BLANK_CH(out[i]))
1106
0
                i += 1;
1107
0
            quote = out[i++];
1108
0
            if ((quote != '\'') && (quote != '"'))
1109
0
                break;
1110
0
            start = i;
1111
0
            cur = out[i];
1112
0
            while (((cur >= 'a') && (cur <= 'z')) ||
1113
0
                   ((cur >= 'A') && (cur <= 'Z')) ||
1114
0
                   ((cur >= '0') && (cur <= '9')) ||
1115
0
                   (cur == '.') || (cur == '_') ||
1116
0
                   (cur == '-'))
1117
0
                cur = out[++i];
1118
0
            if (cur != quote)
1119
0
                break;
1120
0
            out[i] = 0;
1121
0
            xmlCharEncCloseFunc(handler);
1122
0
            return(xmlFindCharEncodingHandler((char *) out + start));
1123
0
        }
1124
0
    }
1125
1126
    /*
1127
     * ICU handlers are stateful, so we have to recreate them.
1128
     */
1129
0
    xmlCharEncCloseFunc(handler);
1130
0
    return(xmlGetCharEncodingHandler(XML_CHAR_ENCODING_EBCDIC));
1131
0
}
1132
1133
/**
1134
 * xmlSwitchEncoding:
1135
 * @ctxt:  the parser context
1136
 * @enc:  the encoding value (number)
1137
 *
1138
 * Use encoding specified by enum to decode input data.
1139
 *
1140
 * This function can be used to enforce the encoding of chunks passed
1141
 * to xmlParseChunk.
1142
 *
1143
 * Returns 0 in case of success, -1 otherwise
1144
 */
1145
int
1146
xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc)
1147
0
{
1148
0
    xmlCharEncodingHandlerPtr handler = NULL;
1149
0
    int check = 1;
1150
0
    int ret;
1151
1152
0
    if ((ctxt == NULL) || (ctxt->input == NULL))
1153
0
        return(-1);
1154
1155
0
    switch (enc) {
1156
0
  case XML_CHAR_ENCODING_NONE:
1157
0
  case XML_CHAR_ENCODING_UTF8:
1158
0
        case XML_CHAR_ENCODING_ASCII:
1159
0
            check = 0;
1160
0
            break;
1161
0
        case XML_CHAR_ENCODING_EBCDIC:
1162
0
            handler = xmlDetectEBCDIC(ctxt->input);
1163
0
            break;
1164
0
        default:
1165
0
            handler = xmlGetCharEncodingHandler(enc);
1166
0
            break;
1167
0
    }
1168
1169
0
    if ((check) && (handler == NULL)) {
1170
0
        const char *name = xmlGetCharEncodingName(enc);
1171
1172
0
        __xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
1173
0
                "encoding not supported: %s\n",
1174
0
                BAD_CAST (name ? name : "<null>"), NULL);
1175
        /*
1176
         * TODO: We could recover from errors in external entities
1177
         * if we didn't stop the parser. But most callers of this
1178
         * function don't check the return value.
1179
         */
1180
0
        xmlStopParser(ctxt);
1181
0
        return(-1);
1182
0
    }
1183
1184
0
    ret = xmlSwitchInputEncoding(ctxt, ctxt->input, handler);
1185
1186
0
    if ((ret >= 0) && (enc == XML_CHAR_ENCODING_NONE)) {
1187
0
        ctxt->input->flags &= ~XML_INPUT_HAS_ENCODING;
1188
0
    }
1189
1190
0
    return(ret);
1191
0
}
1192
1193
/**
1194
 * xmlSwitchInputEncoding:
1195
 * @ctxt:  the parser context
1196
 * @input:  the input stream
1197
 * @handler:  the encoding handler
1198
 *
1199
 * DEPRECATED: Internal function, don't use.
1200
 *
1201
 * Use encoding handler to decode input data.
1202
 *
1203
 * Returns 0 in case of success, -1 otherwise
1204
 */
1205
int
1206
xmlSwitchInputEncoding(xmlParserCtxtPtr ctxt, xmlParserInputPtr input,
1207
                       xmlCharEncodingHandlerPtr handler)
1208
0
{
1209
0
    int nbchars;
1210
0
    xmlParserInputBufferPtr in;
1211
1212
0
    if ((input == NULL) || (input->buf == NULL)) {
1213
0
        xmlCharEncCloseFunc(handler);
1214
0
  return (-1);
1215
0
    }
1216
0
    in = input->buf;
1217
1218
0
    input->flags |= XML_INPUT_HAS_ENCODING;
1219
1220
    /*
1221
     * UTF-8 requires no encoding handler.
1222
     */
1223
0
    if ((handler != NULL) &&
1224
0
        (xmlStrcasecmp(BAD_CAST handler->name, BAD_CAST "UTF-8") == 0)) {
1225
0
        xmlCharEncCloseFunc(handler);
1226
0
        handler = NULL;
1227
0
    }
1228
1229
0
    if (in->encoder == handler)
1230
0
        return (0);
1231
1232
0
    if (in->encoder != NULL) {
1233
        /*
1234
         * Switching encodings during parsing is a really bad idea,
1235
         * but Chromium can switch between ISO-8859-1 and UTF-16 before
1236
         * separate calls to xmlParseChunk.
1237
         *
1238
         * TODO: We should check whether the "raw" input buffer is empty and
1239
         * convert the old content using the old encoder.
1240
         */
1241
1242
0
        xmlCharEncCloseFunc(in->encoder);
1243
0
        in->encoder = handler;
1244
0
        return (0);
1245
0
    }
1246
1247
0
    in->encoder = handler;
1248
1249
    /*
1250
     * Is there already some content down the pipe to convert ?
1251
     */
1252
0
    if (xmlBufIsEmpty(in->buffer) == 0) {
1253
0
        size_t processed;
1254
1255
        /*
1256
         * Shrink the current input buffer.
1257
         * Move it as the raw buffer and create a new input buffer
1258
         */
1259
0
        processed = input->cur - input->base;
1260
0
        xmlBufShrink(in->buffer, processed);
1261
0
        input->consumed += processed;
1262
0
        in->raw = in->buffer;
1263
0
        in->buffer = xmlBufCreate();
1264
0
        in->rawconsumed = processed;
1265
1266
0
        nbchars = xmlCharEncInput(in);
1267
0
        xmlBufResetInput(in->buffer, input);
1268
0
        if (nbchars < 0) {
1269
            /* TODO: This could be an out of memory or an encoding error. */
1270
0
            xmlErrInternal(ctxt,
1271
0
                           "switching encoding: encoder error\n",
1272
0
                           NULL);
1273
0
            xmlHaltParser(ctxt);
1274
0
            return (-1);
1275
0
        }
1276
0
    }
1277
0
    return (0);
1278
0
}
1279
1280
/**
1281
 * xmlSwitchToEncoding:
1282
 * @ctxt:  the parser context
1283
 * @handler:  the encoding handler
1284
 *
1285
 * Use encoding handler to decode input data.
1286
 *
1287
 * This function can be used to enforce the encoding of chunks passed
1288
 * to xmlParseChunk.
1289
 *
1290
 * Returns 0 in case of success, -1 otherwise
1291
 */
1292
int
1293
xmlSwitchToEncoding(xmlParserCtxtPtr ctxt, xmlCharEncodingHandlerPtr handler)
1294
0
{
1295
0
    if (ctxt == NULL)
1296
0
        return(-1);
1297
0
    return(xmlSwitchInputEncoding(ctxt, ctxt->input, handler));
1298
0
}
1299
1300
/**
1301
 * xmlDetectEncoding:
1302
 * @ctxt:  the parser context
1303
 *
1304
 * Handle optional BOM, detect and switch to encoding.
1305
 *
1306
 * Assumes that there are at least four bytes in the input buffer.
1307
 */
1308
void
1309
11
xmlDetectEncoding(xmlParserCtxtPtr ctxt) {
1310
11
    const xmlChar *in;
1311
11
    xmlCharEncoding enc;
1312
11
    int bomSize;
1313
11
    int autoFlag = 0;
1314
1315
11
    if (xmlParserGrow(ctxt) < 0)
1316
0
        return;
1317
11
    in = ctxt->input->cur;
1318
11
    if (ctxt->input->end - in < 4)
1319
0
        return;
1320
1321
11
    if (ctxt->input->flags & XML_INPUT_HAS_ENCODING) {
1322
        /*
1323
         * If the encoding was already set, only skip the BOM which was
1324
         * possibly decoded to UTF-8.
1325
         */
1326
0
        if ((in[0] == 0xEF) && (in[1] == 0xBB) && (in[2] == 0xBF)) {
1327
0
            ctxt->input->cur += 3;
1328
0
        }
1329
1330
0
        return;
1331
0
    }
1332
1333
11
    enc = XML_CHAR_ENCODING_NONE;
1334
11
    bomSize = 0;
1335
1336
11
    switch (in[0]) {
1337
0
        case 0x00:
1338
0
            if ((in[1] == 0x00) && (in[2] == 0x00) && (in[3] == 0x3C)) {
1339
0
                enc = XML_CHAR_ENCODING_UCS4BE;
1340
0
                autoFlag = XML_INPUT_AUTO_OTHER;
1341
0
            } else if ((in[1] == 0x3C) && (in[2] == 0x00) && (in[3] == 0x3F)) {
1342
0
                enc = XML_CHAR_ENCODING_UTF16BE;
1343
0
                autoFlag = XML_INPUT_AUTO_UTF16BE;
1344
0
            }
1345
0
            break;
1346
1347
11
        case 0x3C:
1348
11
            if (in[1] == 0x00) {
1349
0
                if ((in[2] == 0x00) && (in[3] == 0x00)) {
1350
0
                    enc = XML_CHAR_ENCODING_UCS4LE;
1351
0
                    autoFlag = XML_INPUT_AUTO_OTHER;
1352
0
                } else if ((in[2] == 0x3F) && (in[3] == 0x00)) {
1353
0
                    enc = XML_CHAR_ENCODING_UTF16LE;
1354
0
                    autoFlag = XML_INPUT_AUTO_UTF16LE;
1355
0
                }
1356
0
            }
1357
11
            break;
1358
1359
0
        case 0x4C:
1360
0
      if ((in[1] == 0x6F) && (in[2] == 0xA7) && (in[3] == 0x94)) {
1361
0
          enc = XML_CHAR_ENCODING_EBCDIC;
1362
0
                autoFlag = XML_INPUT_AUTO_OTHER;
1363
0
            }
1364
0
            break;
1365
1366
0
        case 0xEF:
1367
0
            if ((in[1] == 0xBB) && (in[2] == 0xBF)) {
1368
0
                enc = XML_CHAR_ENCODING_UTF8;
1369
0
                autoFlag = XML_INPUT_AUTO_UTF8;
1370
0
                bomSize = 3;
1371
0
            }
1372
0
            break;
1373
1374
0
        case 0xFE:
1375
0
            if (in[1] == 0xFF) {
1376
0
                enc = XML_CHAR_ENCODING_UTF16BE;
1377
0
                autoFlag = XML_INPUT_AUTO_UTF16BE;
1378
0
                bomSize = 2;
1379
0
            }
1380
0
            break;
1381
1382
0
        case 0xFF:
1383
0
            if (in[1] == 0xFE) {
1384
0
                enc = XML_CHAR_ENCODING_UTF16LE;
1385
0
                autoFlag = XML_INPUT_AUTO_UTF16LE;
1386
0
                bomSize = 2;
1387
0
            }
1388
0
            break;
1389
11
    }
1390
1391
11
    if (bomSize > 0) {
1392
0
        ctxt->input->cur += bomSize;
1393
0
    }
1394
1395
11
    if (enc != XML_CHAR_ENCODING_NONE) {
1396
0
        ctxt->input->flags |= autoFlag;
1397
0
        xmlSwitchEncoding(ctxt, enc);
1398
0
    }
1399
11
}
1400
1401
/**
1402
 * xmlSetDeclaredEncoding:
1403
 * @ctxt:  the parser context
1404
 * @encoding:  declared encoding
1405
 *
1406
 * Set the encoding from a declaration in the document.
1407
 *
1408
 * If no encoding was set yet, switch the encoding. Otherwise, only warn
1409
 * about encoding mismatches.
1410
 *
1411
 * Takes ownership of 'encoding'.
1412
 */
1413
void
1414
0
xmlSetDeclaredEncoding(xmlParserCtxtPtr ctxt, xmlChar *encoding) {
1415
0
    if (ctxt->encoding != NULL)
1416
0
        xmlFree((xmlChar *) ctxt->encoding);
1417
0
    ctxt->encoding = encoding;
1418
1419
0
    if (((ctxt->input->flags & XML_INPUT_HAS_ENCODING) == 0) &&
1420
0
        ((ctxt->options & XML_PARSE_IGNORE_ENC) == 0)) {
1421
0
        xmlCharEncodingHandlerPtr handler;
1422
1423
0
        handler = xmlFindCharEncodingHandler((const char *) encoding);
1424
0
        if (handler == NULL) {
1425
0
            __xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
1426
0
                             "Unsupported encoding: %s\n",
1427
0
                             encoding, NULL);
1428
0
            return;
1429
0
        }
1430
1431
0
        xmlSwitchToEncoding(ctxt, handler);
1432
0
        ctxt->input->flags |= XML_INPUT_USES_ENC_DECL;
1433
0
    } else if (ctxt->input->flags & XML_INPUT_AUTO_ENCODING) {
1434
0
        static const char *allowedUTF8[] = {
1435
0
            "UTF-8", "UTF8", NULL
1436
0
        };
1437
0
        static const char *allowedUTF16LE[] = {
1438
0
            "UTF-16", "UTF-16LE", "UTF16", NULL
1439
0
        };
1440
0
        static const char *allowedUTF16BE[] = {
1441
0
            "UTF-16", "UTF-16BE", "UTF16", NULL
1442
0
        };
1443
0
        const char **allowed = NULL;
1444
0
        const char *autoEnc = NULL;
1445
1446
0
        switch (ctxt->input->flags & XML_INPUT_AUTO_ENCODING) {
1447
0
            case XML_INPUT_AUTO_UTF8:
1448
0
                allowed = allowedUTF8;
1449
0
                autoEnc = "UTF-8";
1450
0
                break;
1451
0
            case XML_INPUT_AUTO_UTF16LE:
1452
0
                allowed = allowedUTF16LE;
1453
0
                autoEnc = "UTF-16LE";
1454
0
                break;
1455
0
            case XML_INPUT_AUTO_UTF16BE:
1456
0
                allowed = allowedUTF16BE;
1457
0
                autoEnc = "UTF-16BE";
1458
0
                break;
1459
0
        }
1460
1461
0
        if (allowed != NULL) {
1462
0
            const char **p;
1463
0
            int match = 0;
1464
1465
0
            for (p = allowed; *p != NULL; p++) {
1466
0
                if (xmlStrcasecmp(encoding, BAD_CAST *p) == 0) {
1467
0
                    match = 1;
1468
0
                    break;
1469
0
                }
1470
0
            }
1471
1472
0
            if (match == 0) {
1473
0
                xmlWarningMsg(ctxt, XML_WAR_ENCODING_MISMATCH,
1474
0
                              "Encoding '%s' doesn't match "
1475
0
                              "auto-detected '%s'\n",
1476
0
                              encoding, BAD_CAST autoEnc);
1477
0
            }
1478
0
        }
1479
0
    }
1480
0
}
1481
1482
/**
1483
 * xmlGetActualEncoding:
1484
 * @ctxt:  the parser context
1485
 *
1486
 * Returns the actual used to parse the document. This can differ from
1487
 * the declared encoding.
1488
 */
1489
const xmlChar *
1490
0
xmlGetActualEncoding(xmlParserCtxtPtr ctxt) {
1491
0
    const xmlChar *encoding = NULL;
1492
1493
0
    if ((ctxt->input->flags & XML_INPUT_USES_ENC_DECL) ||
1494
0
        (ctxt->input->flags & XML_INPUT_AUTO_ENCODING)) {
1495
        /* Preserve encoding exactly */
1496
0
        encoding = ctxt->encoding;
1497
0
    } else if ((ctxt->input->buf) && (ctxt->input->buf->encoder)) {
1498
0
        encoding = BAD_CAST ctxt->input->buf->encoder->name;
1499
0
    } else if (ctxt->input->flags & XML_INPUT_HAS_ENCODING) {
1500
0
        encoding = BAD_CAST "UTF-8";
1501
0
    }
1502
1503
0
    return(encoding);
1504
0
}
1505
1506
/************************************************************************
1507
 *                  *
1508
 *  Commodity functions to handle entities processing   *
1509
 *                  *
1510
 ************************************************************************/
1511
1512
/**
1513
 * xmlFreeInputStream:
1514
 * @input:  an xmlParserInputPtr
1515
 *
1516
 * Free up an input stream.
1517
 */
1518
void
1519
11
xmlFreeInputStream(xmlParserInputPtr input) {
1520
11
    if (input == NULL) return;
1521
1522
11
    if (input->filename != NULL) xmlFree((char *) input->filename);
1523
11
    if (input->directory != NULL) xmlFree((char *) input->directory);
1524
11
    if (input->version != NULL) xmlFree((char *) input->version);
1525
11
    if ((input->free != NULL) && (input->base != NULL))
1526
0
        input->free((xmlChar *) input->base);
1527
11
    if (input->buf != NULL)
1528
11
        xmlFreeParserInputBuffer(input->buf);
1529
11
    xmlFree(input);
1530
11
}
1531
1532
/**
1533
 * xmlNewInputStream:
1534
 * @ctxt:  an XML parser context
1535
 *
1536
 * Create a new input stream structure.
1537
 *
1538
 * Returns the new input stream or NULL
1539
 */
1540
xmlParserInputPtr
1541
11
xmlNewInputStream(xmlParserCtxtPtr ctxt) {
1542
11
    xmlParserInputPtr input;
1543
1544
11
    input = (xmlParserInputPtr) xmlMalloc(sizeof(xmlParserInput));
1545
11
    if (input == NULL) {
1546
0
        xmlErrMemory(ctxt,  "couldn't allocate a new input stream\n");
1547
0
  return(NULL);
1548
0
    }
1549
11
    memset(input, 0, sizeof(xmlParserInput));
1550
11
    input->line = 1;
1551
11
    input->col = 1;
1552
1553
    /*
1554
     * If the context is NULL the id cannot be initialized, but that
1555
     * should not happen while parsing which is the situation where
1556
     * the id is actually needed.
1557
     */
1558
11
    if (ctxt != NULL) {
1559
11
        if (input->id >= INT_MAX) {
1560
0
            xmlErrMemory(ctxt, "Input ID overflow\n");
1561
0
            return(NULL);
1562
0
        }
1563
11
        input->id = ctxt->input_id++;
1564
11
    }
1565
1566
11
    return(input);
1567
11
}
1568
1569
/**
1570
 * xmlNewIOInputStream:
1571
 * @ctxt:  an XML parser context
1572
 * @input:  an I/O Input
1573
 * @enc:  the charset encoding if known
1574
 *
1575
 * Create a new input stream structure encapsulating the @input into
1576
 * a stream suitable for the parser.
1577
 *
1578
 * Returns the new input stream or NULL
1579
 */
1580
xmlParserInputPtr
1581
xmlNewIOInputStream(xmlParserCtxtPtr ctxt, xmlParserInputBufferPtr input,
1582
0
              xmlCharEncoding enc) {
1583
0
    xmlParserInputPtr inputStream;
1584
1585
0
    if (input == NULL) return(NULL);
1586
0
    if (xmlParserDebugEntities)
1587
0
  xmlGenericError(xmlGenericErrorContext, "new input from I/O\n");
1588
0
    inputStream = xmlNewInputStream(ctxt);
1589
0
    if (inputStream == NULL) {
1590
0
  return(NULL);
1591
0
    }
1592
0
    inputStream->filename = NULL;
1593
0
    inputStream->buf = input;
1594
0
    xmlBufResetInput(inputStream->buf->buffer, inputStream);
1595
1596
0
    if (enc != XML_CHAR_ENCODING_NONE) {
1597
0
        xmlSwitchEncoding(ctxt, enc);
1598
0
    }
1599
1600
0
    return(inputStream);
1601
0
}
1602
1603
/**
1604
 * xmlNewEntityInputStream:
1605
 * @ctxt:  an XML parser context
1606
 * @entity:  an Entity pointer
1607
 *
1608
 * DEPRECATED: Internal function, do not use.
1609
 *
1610
 * Create a new input stream based on an xmlEntityPtr
1611
 *
1612
 * Returns the new input stream or NULL
1613
 */
1614
xmlParserInputPtr
1615
0
xmlNewEntityInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
1616
0
    xmlParserInputPtr input;
1617
1618
0
    if (entity == NULL) {
1619
0
        xmlErrInternal(ctxt, "xmlNewEntityInputStream entity = NULL\n",
1620
0
                 NULL);
1621
0
  return(NULL);
1622
0
    }
1623
0
    if (xmlParserDebugEntities)
1624
0
  xmlGenericError(xmlGenericErrorContext,
1625
0
    "new input from entity: %s\n", entity->name);
1626
0
    if (entity->content == NULL) {
1627
0
  switch (entity->etype) {
1628
0
            case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1629
0
          xmlErrInternal(ctxt, "Cannot parse entity %s\n",
1630
0
                   entity->name);
1631
0
                break;
1632
0
            case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1633
0
            case XML_EXTERNAL_PARAMETER_ENTITY:
1634
0
    input = xmlLoadExternalEntity((char *) entity->URI,
1635
0
           (char *) entity->ExternalID, ctxt);
1636
0
                if (input != NULL)
1637
0
                    input->entity = entity;
1638
0
                return(input);
1639
0
            case XML_INTERNAL_GENERAL_ENTITY:
1640
0
          xmlErrInternal(ctxt,
1641
0
          "Internal entity %s without content !\n",
1642
0
                   entity->name);
1643
0
                break;
1644
0
            case XML_INTERNAL_PARAMETER_ENTITY:
1645
0
          xmlErrInternal(ctxt,
1646
0
          "Internal parameter entity %s without content !\n",
1647
0
                   entity->name);
1648
0
                break;
1649
0
            case XML_INTERNAL_PREDEFINED_ENTITY:
1650
0
          xmlErrInternal(ctxt,
1651
0
          "Predefined entity %s without content !\n",
1652
0
                   entity->name);
1653
0
                break;
1654
0
  }
1655
0
  return(NULL);
1656
0
    }
1657
0
    input = xmlNewInputStream(ctxt);
1658
0
    if (input == NULL) {
1659
0
  return(NULL);
1660
0
    }
1661
0
    if (entity->URI != NULL)
1662
0
  input->filename = (char *) xmlStrdup((xmlChar *) entity->URI);
1663
0
    input->base = entity->content;
1664
0
    if (entity->length == 0)
1665
0
        entity->length = xmlStrlen(entity->content);
1666
0
    input->cur = entity->content;
1667
0
    input->length = entity->length;
1668
0
    input->end = &entity->content[input->length];
1669
0
    input->entity = entity;
1670
0
    return(input);
1671
0
}
1672
1673
/**
1674
 * xmlNewStringInputStream:
1675
 * @ctxt:  an XML parser context
1676
 * @buffer:  an memory buffer
1677
 *
1678
 * Create a new input stream based on a memory buffer.
1679
 * Returns the new input stream
1680
 */
1681
xmlParserInputPtr
1682
0
xmlNewStringInputStream(xmlParserCtxtPtr ctxt, const xmlChar *buffer) {
1683
0
    xmlParserInputPtr input;
1684
0
    xmlParserInputBufferPtr buf;
1685
1686
0
    if (buffer == NULL) {
1687
0
        xmlErrInternal(ctxt, "xmlNewStringInputStream string = NULL\n",
1688
0
                 NULL);
1689
0
  return(NULL);
1690
0
    }
1691
0
    if (xmlParserDebugEntities)
1692
0
  xmlGenericError(xmlGenericErrorContext,
1693
0
    "new fixed input: %.30s\n", buffer);
1694
0
    buf = xmlParserInputBufferCreateString(buffer);
1695
0
    if (buf == NULL) {
1696
0
  xmlErrMemory(ctxt, NULL);
1697
0
        return(NULL);
1698
0
    }
1699
0
    input = xmlNewInputStream(ctxt);
1700
0
    if (input == NULL) {
1701
0
        xmlErrMemory(ctxt,  "couldn't allocate a new input stream\n");
1702
0
  xmlFreeParserInputBuffer(buf);
1703
0
  return(NULL);
1704
0
    }
1705
0
    input->buf = buf;
1706
0
    xmlBufResetInput(input->buf->buffer, input);
1707
0
    return(input);
1708
0
}
1709
1710
/**
1711
 * xmlNewInputFromFile:
1712
 * @ctxt:  an XML parser context
1713
 * @filename:  the filename to use as entity
1714
 *
1715
 * Create a new input stream based on a file or an URL.
1716
 *
1717
 * Returns the new input stream or NULL in case of error
1718
 */
1719
xmlParserInputPtr
1720
0
xmlNewInputFromFile(xmlParserCtxtPtr ctxt, const char *filename) {
1721
0
    xmlParserInputBufferPtr buf;
1722
0
    xmlParserInputPtr inputStream;
1723
0
    char *directory = NULL;
1724
0
    xmlChar *URI = NULL;
1725
1726
0
    if (xmlParserDebugEntities)
1727
0
  xmlGenericError(xmlGenericErrorContext,
1728
0
    "new input from file: %s\n", filename);
1729
0
    if (ctxt == NULL) return(NULL);
1730
0
    buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
1731
0
    if (buf == NULL) {
1732
0
  if (filename == NULL)
1733
0
      __xmlLoaderErr(ctxt,
1734
0
                     "failed to load external entity: NULL filename \n",
1735
0
         NULL);
1736
0
  else
1737
0
      __xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n",
1738
0
         (const char *) filename);
1739
0
  return(NULL);
1740
0
    }
1741
1742
0
    inputStream = xmlNewInputStream(ctxt);
1743
0
    if (inputStream == NULL) {
1744
0
  xmlFreeParserInputBuffer(buf);
1745
0
  return(NULL);
1746
0
    }
1747
1748
0
    inputStream->buf = buf;
1749
0
    inputStream = xmlCheckHTTPInput(ctxt, inputStream);
1750
0
    if (inputStream == NULL)
1751
0
        return(NULL);
1752
1753
0
    if (inputStream->filename == NULL)
1754
0
  URI = xmlStrdup((xmlChar *) filename);
1755
0
    else
1756
0
  URI = xmlStrdup((xmlChar *) inputStream->filename);
1757
0
    directory = xmlParserGetDirectory((const char *) URI);
1758
0
    if (inputStream->filename != NULL) xmlFree((char *)inputStream->filename);
1759
0
    inputStream->filename = (char *) xmlCanonicPath((const xmlChar *) URI);
1760
0
    if (URI != NULL) xmlFree((char *) URI);
1761
0
    inputStream->directory = directory;
1762
1763
0
    xmlBufResetInput(inputStream->buf->buffer, inputStream);
1764
0
    if ((ctxt->directory == NULL) && (directory != NULL))
1765
0
        ctxt->directory = (char *) xmlStrdup((const xmlChar *) directory);
1766
0
    return(inputStream);
1767
0
}
1768
1769
/************************************************************************
1770
 *                  *
1771
 *    Commodity functions to handle parser contexts   *
1772
 *                  *
1773
 ************************************************************************/
1774
1775
/**
1776
 * xmlInitSAXParserCtxt:
1777
 * @ctxt:  XML parser context
1778
 * @sax:  SAX handlert
1779
 * @userData:  user data
1780
 *
1781
 * Initialize a SAX parser context
1782
 *
1783
 * Returns 0 in case of success and -1 in case of error
1784
 */
1785
1786
static int
1787
xmlInitSAXParserCtxt(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax,
1788
                     void *userData)
1789
11
{
1790
11
    xmlParserInputPtr input;
1791
1792
11
    if(ctxt==NULL) {
1793
0
        xmlErrInternal(NULL, "Got NULL parser context\n", NULL);
1794
0
        return(-1);
1795
0
    }
1796
1797
11
    xmlInitParser();
1798
1799
11
    if (ctxt->dict == NULL)
1800
11
  ctxt->dict = xmlDictCreate();
1801
11
    if (ctxt->dict == NULL) {
1802
0
        xmlErrMemory(NULL, "cannot initialize parser context\n");
1803
0
  return(-1);
1804
0
    }
1805
11
    xmlDictSetLimit(ctxt->dict, XML_MAX_DICTIONARY_LIMIT);
1806
1807
11
    if (ctxt->sax == NULL)
1808
11
  ctxt->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
1809
11
    if (ctxt->sax == NULL) {
1810
0
        xmlErrMemory(NULL, "cannot initialize parser context\n");
1811
0
  return(-1);
1812
0
    }
1813
11
    if (sax == NULL) {
1814
0
  memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
1815
0
        xmlSAXVersion(ctxt->sax, 2);
1816
0
        ctxt->userData = ctxt;
1817
11
    } else {
1818
11
  if (sax->initialized == XML_SAX2_MAGIC) {
1819
0
      memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
1820
11
        } else {
1821
11
      memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
1822
11
      memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
1823
11
        }
1824
11
        ctxt->userData = userData ? userData : ctxt;
1825
11
    }
1826
1827
11
    ctxt->maxatts = 0;
1828
11
    ctxt->atts = NULL;
1829
    /* Allocate the Input stack */
1830
11
    if (ctxt->inputTab == NULL) {
1831
11
  ctxt->inputTab = (xmlParserInputPtr *)
1832
11
        xmlMalloc(5 * sizeof(xmlParserInputPtr));
1833
11
  ctxt->inputMax = 5;
1834
11
    }
1835
11
    if (ctxt->inputTab == NULL) {
1836
0
        xmlErrMemory(NULL, "cannot initialize parser context\n");
1837
0
  ctxt->inputNr = 0;
1838
0
  ctxt->inputMax = 0;
1839
0
  ctxt->input = NULL;
1840
0
  return(-1);
1841
0
    }
1842
11
    while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
1843
0
        xmlFreeInputStream(input);
1844
0
    }
1845
11
    ctxt->inputNr = 0;
1846
11
    ctxt->input = NULL;
1847
1848
11
    ctxt->version = NULL;
1849
11
    ctxt->encoding = NULL;
1850
11
    ctxt->standalone = -1;
1851
11
    ctxt->hasExternalSubset = 0;
1852
11
    ctxt->hasPErefs = 0;
1853
11
    ctxt->html = 0;
1854
11
    ctxt->external = 0;
1855
11
    ctxt->instate = XML_PARSER_START;
1856
11
    ctxt->token = 0;
1857
11
    ctxt->directory = NULL;
1858
1859
    /* Allocate the Node stack */
1860
11
    if (ctxt->nodeTab == NULL) {
1861
11
  ctxt->nodeTab = (xmlNodePtr *) xmlMalloc(10 * sizeof(xmlNodePtr));
1862
11
  ctxt->nodeMax = 10;
1863
11
    }
1864
11
    if (ctxt->nodeTab == NULL) {
1865
0
        xmlErrMemory(NULL, "cannot initialize parser context\n");
1866
0
  ctxt->nodeNr = 0;
1867
0
  ctxt->nodeMax = 0;
1868
0
  ctxt->node = NULL;
1869
0
  ctxt->inputNr = 0;
1870
0
  ctxt->inputMax = 0;
1871
0
  ctxt->input = NULL;
1872
0
  return(-1);
1873
0
    }
1874
11
    ctxt->nodeNr = 0;
1875
11
    ctxt->node = NULL;
1876
1877
    /* Allocate the Name stack */
1878
11
    if (ctxt->nameTab == NULL) {
1879
11
  ctxt->nameTab = (const xmlChar **) xmlMalloc(10 * sizeof(xmlChar *));
1880
11
  ctxt->nameMax = 10;
1881
11
    }
1882
11
    if (ctxt->nameTab == NULL) {
1883
0
        xmlErrMemory(NULL, "cannot initialize parser context\n");
1884
0
  ctxt->nodeNr = 0;
1885
0
  ctxt->nodeMax = 0;
1886
0
  ctxt->node = NULL;
1887
0
  ctxt->inputNr = 0;
1888
0
  ctxt->inputMax = 0;
1889
0
  ctxt->input = NULL;
1890
0
  ctxt->nameNr = 0;
1891
0
  ctxt->nameMax = 0;
1892
0
  ctxt->name = NULL;
1893
0
  return(-1);
1894
0
    }
1895
11
    ctxt->nameNr = 0;
1896
11
    ctxt->name = NULL;
1897
1898
    /* Allocate the space stack */
1899
11
    if (ctxt->spaceTab == NULL) {
1900
11
  ctxt->spaceTab = (int *) xmlMalloc(10 * sizeof(int));
1901
11
  ctxt->spaceMax = 10;
1902
11
    }
1903
11
    if (ctxt->spaceTab == NULL) {
1904
0
        xmlErrMemory(NULL, "cannot initialize parser context\n");
1905
0
  ctxt->nodeNr = 0;
1906
0
  ctxt->nodeMax = 0;
1907
0
  ctxt->node = NULL;
1908
0
  ctxt->inputNr = 0;
1909
0
  ctxt->inputMax = 0;
1910
0
  ctxt->input = NULL;
1911
0
  ctxt->nameNr = 0;
1912
0
  ctxt->nameMax = 0;
1913
0
  ctxt->name = NULL;
1914
0
  ctxt->spaceNr = 0;
1915
0
  ctxt->spaceMax = 0;
1916
0
  ctxt->space = NULL;
1917
0
  return(-1);
1918
0
    }
1919
11
    ctxt->spaceNr = 1;
1920
11
    ctxt->spaceMax = 10;
1921
11
    ctxt->spaceTab[0] = -1;
1922
11
    ctxt->space = &ctxt->spaceTab[0];
1923
11
    ctxt->myDoc = NULL;
1924
11
    ctxt->wellFormed = 1;
1925
11
    ctxt->nsWellFormed = 1;
1926
11
    ctxt->valid = 1;
1927
11
    ctxt->loadsubset = xmlLoadExtDtdDefaultValue;
1928
11
    if (ctxt->loadsubset) {
1929
0
        ctxt->options |= XML_PARSE_DTDLOAD;
1930
0
    }
1931
11
    ctxt->validate = xmlDoValidityCheckingDefaultValue;
1932
11
    ctxt->pedantic = xmlPedanticParserDefaultValue;
1933
11
    if (ctxt->pedantic) {
1934
0
        ctxt->options |= XML_PARSE_PEDANTIC;
1935
0
    }
1936
11
    ctxt->linenumbers = xmlLineNumbersDefaultValue;
1937
11
    ctxt->keepBlanks = xmlKeepBlanksDefaultValue;
1938
11
    if (ctxt->keepBlanks == 0) {
1939
0
  ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
1940
0
  ctxt->options |= XML_PARSE_NOBLANKS;
1941
0
    }
1942
1943
11
    ctxt->vctxt.flags = XML_VCTXT_USE_PCTXT;
1944
11
    ctxt->vctxt.userData = ctxt;
1945
11
    ctxt->vctxt.error = xmlParserValidityError;
1946
11
    ctxt->vctxt.warning = xmlParserValidityWarning;
1947
11
    if (ctxt->validate) {
1948
0
  if (xmlGetWarningsDefaultValue == 0)
1949
0
      ctxt->vctxt.warning = NULL;
1950
0
  else
1951
0
      ctxt->vctxt.warning = xmlParserValidityWarning;
1952
0
  ctxt->vctxt.nodeMax = 0;
1953
0
        ctxt->options |= XML_PARSE_DTDVALID;
1954
0
    }
1955
11
    ctxt->replaceEntities = xmlSubstituteEntitiesDefaultValue;
1956
11
    if (ctxt->replaceEntities) {
1957
0
        ctxt->options |= XML_PARSE_NOENT;
1958
0
    }
1959
11
    ctxt->record_info = 0;
1960
11
    ctxt->checkIndex = 0;
1961
11
    ctxt->inSubset = 0;
1962
11
    ctxt->errNo = XML_ERR_OK;
1963
11
    ctxt->depth = 0;
1964
11
    ctxt->catalogs = NULL;
1965
11
    ctxt->sizeentities = 0;
1966
11
    ctxt->sizeentcopy = 0;
1967
11
    ctxt->input_id = 1;
1968
11
    ctxt->maxAmpl = XML_MAX_AMPLIFICATION_DEFAULT;
1969
11
    xmlInitNodeInfoSeq(&ctxt->node_seq);
1970
1971
11
    if (ctxt->nsdb == NULL) {
1972
11
        ctxt->nsdb = xmlParserNsCreate();
1973
11
        if (ctxt->nsdb == NULL) {
1974
0
            xmlErrMemory(ctxt, NULL);
1975
0
            return(-1);
1976
0
        }
1977
11
    }
1978
1979
11
    return(0);
1980
11
}
1981
1982
/**
1983
 * xmlInitParserCtxt:
1984
 * @ctxt:  an XML parser context
1985
 *
1986
 * DEPRECATED: Internal function which will be made private in a future
1987
 * version.
1988
 *
1989
 * Initialize a parser context
1990
 *
1991
 * Returns 0 in case of success and -1 in case of error
1992
 */
1993
1994
int
1995
xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
1996
0
{
1997
0
    return(xmlInitSAXParserCtxt(ctxt, NULL, NULL));
1998
0
}
1999
2000
/**
2001
 * xmlFreeParserCtxt:
2002
 * @ctxt:  an XML parser context
2003
 *
2004
 * Free all the memory used by a parser context. However the parsed
2005
 * document in ctxt->myDoc is not freed.
2006
 */
2007
2008
void
2009
xmlFreeParserCtxt(xmlParserCtxtPtr ctxt)
2010
11
{
2011
11
    xmlParserInputPtr input;
2012
2013
11
    if (ctxt == NULL) return;
2014
2015
22
    while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
2016
11
        xmlFreeInputStream(input);
2017
11
    }
2018
11
    if (ctxt->spaceTab != NULL) xmlFree(ctxt->spaceTab);
2019
11
    if (ctxt->nameTab != NULL) xmlFree((xmlChar * *)ctxt->nameTab);
2020
11
    if (ctxt->nodeTab != NULL) xmlFree(ctxt->nodeTab);
2021
11
    if (ctxt->nodeInfoTab != NULL) xmlFree(ctxt->nodeInfoTab);
2022
11
    if (ctxt->inputTab != NULL) xmlFree(ctxt->inputTab);
2023
11
    if (ctxt->version != NULL) xmlFree((char *) ctxt->version);
2024
11
    if (ctxt->encoding != NULL) xmlFree((char *) ctxt->encoding);
2025
11
    if (ctxt->extSubURI != NULL) xmlFree((char *) ctxt->extSubURI);
2026
11
    if (ctxt->extSubSystem != NULL) xmlFree((char *) ctxt->extSubSystem);
2027
11
#ifdef LIBXML_SAX1_ENABLED
2028
11
    if ((ctxt->sax != NULL) &&
2029
11
        (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler))
2030
#else
2031
    if (ctxt->sax != NULL)
2032
#endif /* LIBXML_SAX1_ENABLED */
2033
11
        xmlFree(ctxt->sax);
2034
11
    if (ctxt->directory != NULL) xmlFree((char *) ctxt->directory);
2035
11
    if (ctxt->vctxt.nodeTab != NULL) xmlFree(ctxt->vctxt.nodeTab);
2036
11
    if (ctxt->atts != NULL) xmlFree((xmlChar * *)ctxt->atts);
2037
11
    if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
2038
11
    if (ctxt->nsTab != NULL) xmlFree(ctxt->nsTab);
2039
11
    if (ctxt->nsdb != NULL) xmlParserNsFree(ctxt->nsdb);
2040
11
    if (ctxt->attrHash != NULL) xmlFree(ctxt->attrHash);
2041
11
    if (ctxt->pushTab != NULL) xmlFree(ctxt->pushTab);
2042
11
    if (ctxt->attallocs != NULL) xmlFree(ctxt->attallocs);
2043
11
    if (ctxt->attsDefault != NULL)
2044
0
        xmlHashFree(ctxt->attsDefault, xmlHashDefaultDeallocator);
2045
11
    if (ctxt->attsSpecial != NULL)
2046
0
        xmlHashFree(ctxt->attsSpecial, NULL);
2047
11
    if (ctxt->freeElems != NULL) {
2048
0
        xmlNodePtr cur, next;
2049
2050
0
  cur = ctxt->freeElems;
2051
0
  while (cur != NULL) {
2052
0
      next = cur->next;
2053
0
      xmlFree(cur);
2054
0
      cur = next;
2055
0
  }
2056
0
    }
2057
11
    if (ctxt->freeAttrs != NULL) {
2058
0
        xmlAttrPtr cur, next;
2059
2060
0
  cur = ctxt->freeAttrs;
2061
0
  while (cur != NULL) {
2062
0
      next = cur->next;
2063
0
      xmlFree(cur);
2064
0
      cur = next;
2065
0
  }
2066
0
    }
2067
    /*
2068
     * cleanup the error strings
2069
     */
2070
11
    if (ctxt->lastError.message != NULL)
2071
0
        xmlFree(ctxt->lastError.message);
2072
11
    if (ctxt->lastError.file != NULL)
2073
0
        xmlFree(ctxt->lastError.file);
2074
11
    if (ctxt->lastError.str1 != NULL)
2075
0
        xmlFree(ctxt->lastError.str1);
2076
11
    if (ctxt->lastError.str2 != NULL)
2077
0
        xmlFree(ctxt->lastError.str2);
2078
11
    if (ctxt->lastError.str3 != NULL)
2079
0
        xmlFree(ctxt->lastError.str3);
2080
2081
11
#ifdef LIBXML_CATALOG_ENABLED
2082
11
    if (ctxt->catalogs != NULL)
2083
0
  xmlCatalogFreeLocal(ctxt->catalogs);
2084
11
#endif
2085
11
    xmlFree(ctxt);
2086
11
}
2087
2088
/**
2089
 * xmlNewParserCtxt:
2090
 *
2091
 * Allocate and initialize a new parser context.
2092
 *
2093
 * Returns the xmlParserCtxtPtr or NULL
2094
 */
2095
2096
xmlParserCtxtPtr
2097
xmlNewParserCtxt(void)
2098
0
{
2099
0
    return(xmlNewSAXParserCtxt(NULL, NULL));
2100
0
}
2101
2102
/**
2103
 * xmlNewSAXParserCtxt:
2104
 * @sax:  SAX handler
2105
 * @userData:  user data
2106
 *
2107
 * Allocate and initialize a new SAX parser context. If userData is NULL,
2108
 * the parser context will be passed as user data.
2109
 *
2110
 * Returns the xmlParserCtxtPtr or NULL if memory allocation failed.
2111
 */
2112
2113
xmlParserCtxtPtr
2114
xmlNewSAXParserCtxt(const xmlSAXHandler *sax, void *userData)
2115
11
{
2116
11
    xmlParserCtxtPtr ctxt;
2117
2118
11
    ctxt = (xmlParserCtxtPtr) xmlMalloc(sizeof(xmlParserCtxt));
2119
11
    if (ctxt == NULL) {
2120
0
  xmlErrMemory(NULL, "cannot allocate parser context\n");
2121
0
  return(NULL);
2122
0
    }
2123
11
    memset(ctxt, 0, sizeof(xmlParserCtxt));
2124
11
    if (xmlInitSAXParserCtxt(ctxt, sax, userData) < 0) {
2125
0
        xmlFreeParserCtxt(ctxt);
2126
0
  return(NULL);
2127
0
    }
2128
11
    return(ctxt);
2129
11
}
2130
2131
/************************************************************************
2132
 *                  *
2133
 *    Handling of node information        *
2134
 *                  *
2135
 ************************************************************************/
2136
2137
/**
2138
 * xmlClearParserCtxt:
2139
 * @ctxt:  an XML parser context
2140
 *
2141
 * Clear (release owned resources) and reinitialize a parser context
2142
 */
2143
2144
void
2145
xmlClearParserCtxt(xmlParserCtxtPtr ctxt)
2146
0
{
2147
0
  if (ctxt==NULL)
2148
0
    return;
2149
0
  xmlClearNodeInfoSeq(&ctxt->node_seq);
2150
0
  xmlCtxtReset(ctxt);
2151
0
}
2152
2153
2154
/**
2155
 * xmlParserFindNodeInfo:
2156
 * @ctx:  an XML parser context
2157
 * @node:  an XML node within the tree
2158
 *
2159
 * DEPRECATED: Don't use.
2160
 *
2161
 * Find the parser node info struct for a given node
2162
 *
2163
 * Returns an xmlParserNodeInfo block pointer or NULL
2164
 */
2165
const xmlParserNodeInfo *
2166
xmlParserFindNodeInfo(const xmlParserCtxtPtr ctx, const xmlNodePtr node)
2167
0
{
2168
0
    unsigned long pos;
2169
2170
0
    if ((ctx == NULL) || (node == NULL))
2171
0
        return (NULL);
2172
    /* Find position where node should be at */
2173
0
    pos = xmlParserFindNodeInfoIndex(&ctx->node_seq, node);
2174
0
    if (pos < ctx->node_seq.length
2175
0
        && ctx->node_seq.buffer[pos].node == node)
2176
0
        return &ctx->node_seq.buffer[pos];
2177
0
    else
2178
0
        return NULL;
2179
0
}
2180
2181
2182
/**
2183
 * xmlInitNodeInfoSeq:
2184
 * @seq:  a node info sequence pointer
2185
 *
2186
 * DEPRECATED: Don't use.
2187
 *
2188
 * -- Initialize (set to initial state) node info sequence
2189
 */
2190
void
2191
xmlInitNodeInfoSeq(xmlParserNodeInfoSeqPtr seq)
2192
11
{
2193
11
    if (seq == NULL)
2194
0
        return;
2195
11
    seq->length = 0;
2196
11
    seq->maximum = 0;
2197
11
    seq->buffer = NULL;
2198
11
}
2199
2200
/**
2201
 * xmlClearNodeInfoSeq:
2202
 * @seq:  a node info sequence pointer
2203
 *
2204
 * DEPRECATED: Don't use.
2205
 *
2206
 * -- Clear (release memory and reinitialize) node
2207
 *   info sequence
2208
 */
2209
void
2210
xmlClearNodeInfoSeq(xmlParserNodeInfoSeqPtr seq)
2211
0
{
2212
0
    if (seq == NULL)
2213
0
        return;
2214
0
    if (seq->buffer != NULL)
2215
0
        xmlFree(seq->buffer);
2216
0
    xmlInitNodeInfoSeq(seq);
2217
0
}
2218
2219
/**
2220
 * xmlParserFindNodeInfoIndex:
2221
 * @seq:  a node info sequence pointer
2222
 * @node:  an XML node pointer
2223
 *
2224
 * DEPRECATED: Don't use.
2225
 *
2226
 * xmlParserFindNodeInfoIndex : Find the index that the info record for
2227
 *   the given node is or should be at in a sorted sequence
2228
 *
2229
 * Returns a long indicating the position of the record
2230
 */
2231
unsigned long
2232
xmlParserFindNodeInfoIndex(const xmlParserNodeInfoSeqPtr seq,
2233
                           const xmlNodePtr node)
2234
0
{
2235
0
    unsigned long upper, lower, middle;
2236
0
    int found = 0;
2237
2238
0
    if ((seq == NULL) || (node == NULL))
2239
0
        return ((unsigned long) -1);
2240
2241
    /* Do a binary search for the key */
2242
0
    lower = 1;
2243
0
    upper = seq->length;
2244
0
    middle = 0;
2245
0
    while (lower <= upper && !found) {
2246
0
        middle = lower + (upper - lower) / 2;
2247
0
        if (node == seq->buffer[middle - 1].node)
2248
0
            found = 1;
2249
0
        else if (node < seq->buffer[middle - 1].node)
2250
0
            upper = middle - 1;
2251
0
        else
2252
0
            lower = middle + 1;
2253
0
    }
2254
2255
    /* Return position */
2256
0
    if (middle == 0 || seq->buffer[middle - 1].node < node)
2257
0
        return middle;
2258
0
    else
2259
0
        return middle - 1;
2260
0
}
2261
2262
2263
/**
2264
 * xmlParserAddNodeInfo:
2265
 * @ctxt:  an XML parser context
2266
 * @info:  a node info sequence pointer
2267
 *
2268
 * DEPRECATED: Don't use.
2269
 *
2270
 * Insert node info record into the sorted sequence
2271
 */
2272
void
2273
xmlParserAddNodeInfo(xmlParserCtxtPtr ctxt,
2274
                     const xmlParserNodeInfoPtr info)
2275
0
{
2276
0
    unsigned long pos;
2277
2278
0
    if ((ctxt == NULL) || (info == NULL)) return;
2279
2280
    /* Find pos and check to see if node is already in the sequence */
2281
0
    pos = xmlParserFindNodeInfoIndex(&ctxt->node_seq, (xmlNodePtr)
2282
0
                                     info->node);
2283
2284
0
    if ((pos < ctxt->node_seq.length) &&
2285
0
        (ctxt->node_seq.buffer != NULL) &&
2286
0
        (ctxt->node_seq.buffer[pos].node == info->node)) {
2287
0
        ctxt->node_seq.buffer[pos] = *info;
2288
0
    }
2289
2290
    /* Otherwise, we need to add new node to buffer */
2291
0
    else {
2292
0
        if ((ctxt->node_seq.length + 1 > ctxt->node_seq.maximum) ||
2293
0
      (ctxt->node_seq.buffer == NULL)) {
2294
0
            xmlParserNodeInfo *tmp_buffer;
2295
0
            unsigned int byte_size;
2296
2297
0
            if (ctxt->node_seq.maximum == 0)
2298
0
                ctxt->node_seq.maximum = 2;
2299
0
            byte_size = (sizeof(*ctxt->node_seq.buffer) *
2300
0
      (2 * ctxt->node_seq.maximum));
2301
2302
0
            if (ctxt->node_seq.buffer == NULL)
2303
0
                tmp_buffer = (xmlParserNodeInfo *) xmlMalloc(byte_size);
2304
0
            else
2305
0
                tmp_buffer =
2306
0
                    (xmlParserNodeInfo *) xmlRealloc(ctxt->node_seq.buffer,
2307
0
                                                     byte_size);
2308
2309
0
            if (tmp_buffer == NULL) {
2310
0
    xmlErrMemory(ctxt, "failed to allocate buffer\n");
2311
0
                return;
2312
0
            }
2313
0
            ctxt->node_seq.buffer = tmp_buffer;
2314
0
            ctxt->node_seq.maximum *= 2;
2315
0
        }
2316
2317
        /* If position is not at end, move elements out of the way */
2318
0
        if (pos != ctxt->node_seq.length) {
2319
0
            unsigned long i;
2320
2321
0
            for (i = ctxt->node_seq.length; i > pos; i--)
2322
0
                ctxt->node_seq.buffer[i] = ctxt->node_seq.buffer[i - 1];
2323
0
        }
2324
2325
        /* Copy element and increase length */
2326
0
        ctxt->node_seq.buffer[pos] = *info;
2327
0
        ctxt->node_seq.length++;
2328
0
    }
2329
0
}
2330
2331
/************************************************************************
2332
 *                  *
2333
 *    Defaults settings         *
2334
 *                  *
2335
 ************************************************************************/
2336
/**
2337
 * xmlPedanticParserDefault:
2338
 * @val:  int 0 or 1
2339
 *
2340
 * DEPRECATED: Use the modern options API with XML_PARSE_PEDANTIC.
2341
 *
2342
 * Set and return the previous value for enabling pedantic warnings.
2343
 *
2344
 * Returns the last value for 0 for no substitution, 1 for substitution.
2345
 */
2346
2347
int
2348
0
xmlPedanticParserDefault(int val) {
2349
0
    int old = xmlPedanticParserDefaultValue;
2350
2351
0
    xmlPedanticParserDefaultValue = val;
2352
0
    return(old);
2353
0
}
2354
2355
/**
2356
 * xmlLineNumbersDefault:
2357
 * @val:  int 0 or 1
2358
 *
2359
 * DEPRECATED: The modern options API always enables line numbers.
2360
 *
2361
 * Set and return the previous value for enabling line numbers in elements
2362
 * contents. This may break on old application and is turned off by default.
2363
 *
2364
 * Returns the last value for 0 for no substitution, 1 for substitution.
2365
 */
2366
2367
int
2368
0
xmlLineNumbersDefault(int val) {
2369
0
    int old = xmlLineNumbersDefaultValue;
2370
2371
0
    xmlLineNumbersDefaultValue = val;
2372
0
    return(old);
2373
0
}
2374
2375
/**
2376
 * xmlSubstituteEntitiesDefault:
2377
 * @val:  int 0 or 1
2378
 *
2379
 * DEPRECATED: Use the modern options API with XML_PARSE_NOENT.
2380
 *
2381
 * Set and return the previous value for default entity support.
2382
 * Initially the parser always keep entity references instead of substituting
2383
 * entity values in the output. This function has to be used to change the
2384
 * default parser behavior
2385
 * SAX::substituteEntities() has to be used for changing that on a file by
2386
 * file basis.
2387
 *
2388
 * Returns the last value for 0 for no substitution, 1 for substitution.
2389
 */
2390
2391
int
2392
0
xmlSubstituteEntitiesDefault(int val) {
2393
0
    int old = xmlSubstituteEntitiesDefaultValue;
2394
2395
0
    xmlSubstituteEntitiesDefaultValue = val;
2396
0
    return(old);
2397
0
}
2398
2399
/**
2400
 * xmlKeepBlanksDefault:
2401
 * @val:  int 0 or 1
2402
 *
2403
 * DEPRECATED: Use the modern options API with XML_PARSE_NOBLANKS.
2404
 *
2405
 * Set and return the previous value for default blanks text nodes support.
2406
 * The 1.x version of the parser used an heuristic to try to detect
2407
 * ignorable white spaces. As a result the SAX callback was generating
2408
 * xmlSAX2IgnorableWhitespace() callbacks instead of characters() one, and when
2409
 * using the DOM output text nodes containing those blanks were not generated.
2410
 * The 2.x and later version will switch to the XML standard way and
2411
 * ignorableWhitespace() are only generated when running the parser in
2412
 * validating mode and when the current element doesn't allow CDATA or
2413
 * mixed content.
2414
 * This function is provided as a way to force the standard behavior
2415
 * on 1.X libs and to switch back to the old mode for compatibility when
2416
 * running 1.X client code on 2.X . Upgrade of 1.X code should be done
2417
 * by using xmlIsBlankNode() commodity function to detect the "empty"
2418
 * nodes generated.
2419
 * This value also affect autogeneration of indentation when saving code
2420
 * if blanks sections are kept, indentation is not generated.
2421
 *
2422
 * Returns the last value for 0 for no substitution, 1 for substitution.
2423
 */
2424
2425
int
2426
0
xmlKeepBlanksDefault(int val) {
2427
0
    int old = xmlKeepBlanksDefaultValue;
2428
2429
0
    xmlKeepBlanksDefaultValue = val;
2430
0
#ifdef LIBXML_OUTPUT_ENABLED
2431
0
    if (!val)
2432
0
        xmlIndentTreeOutput = 1;
2433
0
#endif
2434
0
    return(old);
2435
0
}
2436