Coverage Report

Created: 2025-07-23 08:13

/src/fontconfig/subprojects/libxml2-2.12.6/error.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * error.c: module displaying/handling XML parser errors
3
 *
4
 * See Copyright for the status of this software.
5
 *
6
 * Daniel Veillard <daniel@veillard.com>
7
 */
8
9
#define IN_LIBXML
10
#include "libxml.h"
11
12
#include <string.h>
13
#include <stdarg.h>
14
#include <libxml/parser.h>
15
#include <libxml/xmlerror.h>
16
#include <libxml/xmlmemory.h>
17
18
#include "private/error.h"
19
20
0
#define XML_MAX_ERRORS 100
21
22
0
#define XML_GET_VAR_STR(msg, str) {       \
23
0
    int       size, prev_size = -1;       \
24
0
    int       chars;            \
25
0
    char      *larger;            \
26
0
    va_list   ap;           \
27
0
                \
28
0
    str = (char *) xmlMalloc(150);        \
29
0
    if (str != NULL) {           \
30
0
                \
31
0
    size = 150;             \
32
0
                \
33
0
    while (size < 64000) {         \
34
0
  va_start(ap, msg);          \
35
0
  chars = vsnprintf(str, size, msg, ap);      \
36
0
  va_end(ap);           \
37
0
  if ((chars > -1) && (chars < size)) {     \
38
0
      if (prev_size == chars) {       \
39
0
    break;            \
40
0
      } else {           \
41
0
    prev_size = chars;        \
42
0
      }              \
43
0
  }             \
44
0
  if (chars > -1)           \
45
0
      size += chars + 1;         \
46
0
  else              \
47
0
      size += 100;         \
48
0
  if ((larger = (char *) xmlRealloc(str, size)) == NULL) {\
49
0
      break;            \
50
0
  }              \
51
0
  str = larger;           \
52
0
    }}               \
53
0
}
54
55
/************************************************************************
56
 *                  *
57
 *      Handling of out of context errors   *
58
 *                  *
59
 ************************************************************************/
60
61
/**
62
 * xmlGenericErrorDefaultFunc:
63
 * @ctx:  an error context
64
 * @msg:  the message to display/transmit
65
 * @...:  extra parameters for the message display
66
 *
67
 * Default handler for out of context error messages.
68
 */
69
void
70
0
xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
71
0
    va_list args;
72
73
0
    if (xmlGenericErrorContext == NULL)
74
0
  xmlGenericErrorContext = (void *) stderr;
75
76
0
    va_start(args, msg);
77
0
    vfprintf((FILE *)xmlGenericErrorContext, msg, args);
78
0
    va_end(args);
79
0
}
80
81
/**
82
 * initGenericErrorDefaultFunc:
83
 * @handler:  the handler
84
 *
85
 * DEPRECATED: Use xmlSetGenericErrorFunc.
86
 *
87
 * Set or reset (if NULL) the default handler for generic errors
88
 * to the builtin error function.
89
 */
90
void
91
initGenericErrorDefaultFunc(xmlGenericErrorFunc * handler)
92
0
{
93
0
    if (handler == NULL)
94
0
        xmlGenericError = xmlGenericErrorDefaultFunc;
95
0
    else
96
0
        xmlGenericError = (*handler);
97
0
}
98
99
/**
100
 * xmlSetGenericErrorFunc:
101
 * @ctx:  the new error handling context
102
 * @handler:  the new handler function
103
 *
104
 * Function to reset the handler and the error context for out of
105
 * context error messages.
106
 * This simply means that @handler will be called for subsequent
107
 * error messages while not parsing nor validating. And @ctx will
108
 * be passed as first argument to @handler
109
 * One can simply force messages to be emitted to another FILE * than
110
 * stderr by setting @ctx to this file handle and @handler to NULL.
111
 * For multi-threaded applications, this must be set separately for each thread.
112
 */
113
void
114
0
xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
115
0
    xmlGenericErrorContext = ctx;
116
0
    if (handler != NULL)
117
0
  xmlGenericError = handler;
118
0
    else
119
0
  xmlGenericError = xmlGenericErrorDefaultFunc;
120
0
}
121
122
/**
123
 * xmlSetStructuredErrorFunc:
124
 * @ctx:  the new error handling context
125
 * @handler:  the new handler function
126
 *
127
 * Function to reset the handler and the error context for out of
128
 * context structured error messages.
129
 * This simply means that @handler will be called for subsequent
130
 * error messages while not parsing nor validating. And @ctx will
131
 * be passed as first argument to @handler
132
 * For multi-threaded applications, this must be set separately for each thread.
133
 */
134
void
135
0
xmlSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) {
136
0
    xmlStructuredErrorContext = ctx;
137
0
    xmlStructuredError = handler;
138
0
}
139
140
/************************************************************************
141
 *                  *
142
 *      Handling of parsing errors      *
143
 *                  *
144
 ************************************************************************/
145
146
/**
147
 * xmlParserPrintFileInfo:
148
 * @input:  an xmlParserInputPtr input
149
 *
150
 * Displays the associated file and line information for the current input
151
 */
152
153
void
154
0
xmlParserPrintFileInfo(xmlParserInputPtr input) {
155
0
    if (input != NULL) {
156
0
  if (input->filename)
157
0
      xmlGenericError(xmlGenericErrorContext,
158
0
        "%s:%d: ", input->filename,
159
0
        input->line);
160
0
  else
161
0
      xmlGenericError(xmlGenericErrorContext,
162
0
        "Entity: line %d: ", input->line);
163
0
    }
164
0
}
165
166
/**
167
 * xmlParserPrintFileContextInternal:
168
 * @input:  an xmlParserInputPtr input
169
 *
170
 * Displays current context within the input content for error tracking
171
 */
172
173
static void
174
xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
175
0
    xmlGenericErrorFunc channel, void *data ) {
176
0
    const xmlChar *cur, *base, *start;
177
0
    unsigned int n, col;  /* GCC warns if signed, because compared with sizeof() */
178
0
    xmlChar  content[81]; /* space for 80 chars + line terminator */
179
0
    xmlChar *ctnt;
180
181
0
    if ((input == NULL) || (input->cur == NULL))
182
0
        return;
183
184
0
    cur = input->cur;
185
0
    base = input->base;
186
    /* skip backwards over any end-of-lines */
187
0
    while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
188
0
  cur--;
189
0
    }
190
0
    n = 0;
191
    /* search backwards for beginning-of-line (to max buff size) */
192
0
    while ((n < sizeof(content) - 1) && (cur > base) &&
193
0
     (*cur != '\n') && (*cur != '\r')) {
194
0
        cur--;
195
0
        n++;
196
0
    }
197
0
    if ((n > 0) && ((*cur == '\n') || (*cur == '\r'))) {
198
0
        cur++;
199
0
    } else {
200
        /* skip over continuation bytes */
201
0
        while ((cur < input->cur) && ((*cur & 0xC0) == 0x80))
202
0
            cur++;
203
0
    }
204
    /* calculate the error position in terms of the current position */
205
0
    col = input->cur - cur;
206
    /* search forward for end-of-line (to max buff size) */
207
0
    n = 0;
208
0
    start = cur;
209
    /* copy selected text to our buffer */
210
0
    while ((*cur != 0) && (*(cur) != '\n') && (*(cur) != '\r')) {
211
0
        int len = input->end - cur;
212
0
        int c = xmlGetUTF8Char(cur, &len);
213
214
0
        if ((c < 0) || (n + len > sizeof(content)-1))
215
0
            break;
216
0
        cur += len;
217
0
  n += len;
218
0
    }
219
0
    memcpy(content, start, n);
220
0
    content[n] = 0;
221
    /* print out the selected text */
222
0
    channel(data ,"%s\n", content);
223
    /* create blank line with problem pointer */
224
0
    n = 0;
225
0
    ctnt = content;
226
    /* (leave buffer space for pointer + line terminator) */
227
0
    while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
228
0
  if (*(ctnt) != '\t')
229
0
      *(ctnt) = ' ';
230
0
  ctnt++;
231
0
    }
232
0
    *ctnt++ = '^';
233
0
    *ctnt = 0;
234
0
    channel(data ,"%s\n", content);
235
0
}
236
237
/**
238
 * xmlParserPrintFileContext:
239
 * @input:  an xmlParserInputPtr input
240
 *
241
 * Displays current context within the input content for error tracking
242
 */
243
void
244
0
xmlParserPrintFileContext(xmlParserInputPtr input) {
245
0
   xmlParserPrintFileContextInternal(input, xmlGenericError,
246
0
                                     xmlGenericErrorContext);
247
0
}
248
249
/**
250
 * xmlReportError:
251
 * @err: the error
252
 * @ctx: the parser context or NULL
253
 * @str: the formatted error message
254
 *
255
 * Report an error with its context, replace the 4 old error/warning
256
 * routines.
257
 */
258
static void
259
xmlReportError(xmlErrorPtr err, xmlParserCtxtPtr ctxt, const char *str,
260
               xmlGenericErrorFunc channel, void *data)
261
0
{
262
0
    char *file = NULL;
263
0
    int line = 0;
264
0
    int code = -1;
265
0
    int domain;
266
0
    const xmlChar *name = NULL;
267
0
    xmlNodePtr node;
268
0
    xmlErrorLevel level;
269
0
    xmlParserInputPtr input = NULL;
270
0
    xmlParserInputPtr cur = NULL;
271
272
0
    if (err == NULL)
273
0
        return;
274
275
0
    if (channel == NULL) {
276
0
  channel = xmlGenericError;
277
0
  data = xmlGenericErrorContext;
278
0
    }
279
0
    file = err->file;
280
0
    line = err->line;
281
0
    code = err->code;
282
0
    domain = err->domain;
283
0
    level = err->level;
284
0
    node = err->node;
285
286
0
    if (code == XML_ERR_OK)
287
0
        return;
288
289
0
    if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
290
0
        name = node->name;
291
292
    /*
293
     * Maintain the compatibility with the legacy error handling
294
     */
295
0
    if (ctxt != NULL) {
296
0
        input = ctxt->input;
297
0
        if ((input != NULL) && (input->filename == NULL) &&
298
0
            (ctxt->inputNr > 1)) {
299
0
            cur = input;
300
0
            input = ctxt->inputTab[ctxt->inputNr - 2];
301
0
        }
302
0
        if (input != NULL) {
303
0
            if (input->filename)
304
0
                channel(data, "%s:%d: ", input->filename, input->line);
305
0
            else if ((line != 0) && (domain == XML_FROM_PARSER))
306
0
                channel(data, "Entity: line %d: ", input->line);
307
0
        }
308
0
    } else {
309
0
        if (file != NULL)
310
0
            channel(data, "%s:%d: ", file, line);
311
0
        else if ((line != 0) &&
312
0
           ((domain == XML_FROM_PARSER) || (domain == XML_FROM_SCHEMASV)||
313
0
      (domain == XML_FROM_SCHEMASP)||(domain == XML_FROM_DTD) ||
314
0
      (domain == XML_FROM_RELAXNGP)||(domain == XML_FROM_RELAXNGV)))
315
0
            channel(data, "Entity: line %d: ", line);
316
0
    }
317
0
    if (name != NULL) {
318
0
        channel(data, "element %s: ", name);
319
0
    }
320
0
    switch (domain) {
321
0
        case XML_FROM_PARSER:
322
0
            channel(data, "parser ");
323
0
            break;
324
0
        case XML_FROM_NAMESPACE:
325
0
            channel(data, "namespace ");
326
0
            break;
327
0
        case XML_FROM_DTD:
328
0
        case XML_FROM_VALID:
329
0
            channel(data, "validity ");
330
0
            break;
331
0
        case XML_FROM_HTML:
332
0
            channel(data, "HTML parser ");
333
0
            break;
334
0
        case XML_FROM_MEMORY:
335
0
            channel(data, "memory ");
336
0
            break;
337
0
        case XML_FROM_OUTPUT:
338
0
            channel(data, "output ");
339
0
            break;
340
0
        case XML_FROM_IO:
341
0
            channel(data, "I/O ");
342
0
            break;
343
0
        case XML_FROM_XINCLUDE:
344
0
            channel(data, "XInclude ");
345
0
            break;
346
0
        case XML_FROM_XPATH:
347
0
            channel(data, "XPath ");
348
0
            break;
349
0
        case XML_FROM_XPOINTER:
350
0
            channel(data, "parser ");
351
0
            break;
352
0
        case XML_FROM_REGEXP:
353
0
            channel(data, "regexp ");
354
0
            break;
355
0
        case XML_FROM_MODULE:
356
0
            channel(data, "module ");
357
0
            break;
358
0
        case XML_FROM_SCHEMASV:
359
0
            channel(data, "Schemas validity ");
360
0
            break;
361
0
        case XML_FROM_SCHEMASP:
362
0
            channel(data, "Schemas parser ");
363
0
            break;
364
0
        case XML_FROM_RELAXNGP:
365
0
            channel(data, "Relax-NG parser ");
366
0
            break;
367
0
        case XML_FROM_RELAXNGV:
368
0
            channel(data, "Relax-NG validity ");
369
0
            break;
370
0
        case XML_FROM_CATALOG:
371
0
            channel(data, "Catalog ");
372
0
            break;
373
0
        case XML_FROM_C14N:
374
0
            channel(data, "C14N ");
375
0
            break;
376
0
        case XML_FROM_XSLT:
377
0
            channel(data, "XSLT ");
378
0
            break;
379
0
        case XML_FROM_I18N:
380
0
            channel(data, "encoding ");
381
0
            break;
382
0
        case XML_FROM_SCHEMATRONV:
383
0
            channel(data, "schematron ");
384
0
            break;
385
0
        case XML_FROM_BUFFER:
386
0
            channel(data, "internal buffer ");
387
0
            break;
388
0
        case XML_FROM_URI:
389
0
            channel(data, "URI ");
390
0
            break;
391
0
        default:
392
0
            break;
393
0
    }
394
0
    switch (level) {
395
0
        case XML_ERR_NONE:
396
0
            channel(data, ": ");
397
0
            break;
398
0
        case XML_ERR_WARNING:
399
0
            channel(data, "warning : ");
400
0
            break;
401
0
        case XML_ERR_ERROR:
402
0
            channel(data, "error : ");
403
0
            break;
404
0
        case XML_ERR_FATAL:
405
0
            channel(data, "error : ");
406
0
            break;
407
0
    }
408
0
    if (str != NULL) {
409
0
        int len;
410
0
  len = xmlStrlen((const xmlChar *)str);
411
0
  if ((len > 0) && (str[len - 1] != '\n'))
412
0
      channel(data, "%s\n", str);
413
0
  else
414
0
      channel(data, "%s", str);
415
0
    } else {
416
0
        channel(data, "%s\n", "out of memory error");
417
0
    }
418
419
0
    if (ctxt != NULL) {
420
0
        xmlParserPrintFileContextInternal(input, channel, data);
421
0
        if (cur != NULL) {
422
0
            if (cur->filename)
423
0
                channel(data, "%s:%d: \n", cur->filename, cur->line);
424
0
            else if ((line != 0) && (domain == XML_FROM_PARSER))
425
0
                channel(data, "Entity: line %d: \n", cur->line);
426
0
            xmlParserPrintFileContextInternal(cur, channel, data);
427
0
        }
428
0
    }
429
0
    if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
430
0
        (err->int1 < 100) &&
431
0
  (err->int1 < xmlStrlen((const xmlChar *)err->str1))) {
432
0
  xmlChar buf[150];
433
0
  int i;
434
435
0
  channel(data, "%s\n", err->str1);
436
0
  for (i=0;i < err->int1;i++)
437
0
       buf[i] = ' ';
438
0
  buf[i++] = '^';
439
0
  buf[i] = 0;
440
0
  channel(data, "%s\n", buf);
441
0
    }
442
0
}
443
444
/**
445
 * __xmlRaiseError:
446
 * @schannel: the structured callback channel
447
 * @channel: the old callback channel
448
 * @data: the callback data
449
 * @ctx: the parser context or NULL
450
 * @ctx: the parser context or NULL
451
 * @domain: the domain for the error
452
 * @code: the code for the error
453
 * @level: the xmlErrorLevel for the error
454
 * @file: the file source of the error (or NULL)
455
 * @line: the line of the error or 0 if N/A
456
 * @str1: extra string info
457
 * @str2: extra string info
458
 * @str3: extra string info
459
 * @int1: extra int info
460
 * @col: column number of the error or 0 if N/A
461
 * @msg:  the message to display/transmit
462
 * @...:  extra parameters for the message display
463
 *
464
 * Update the appropriate global or contextual error structure,
465
 * then forward the error message down the parser or generic
466
 * error callback handler
467
 */
468
void
469
__xmlRaiseError(xmlStructuredErrorFunc schannel,
470
              xmlGenericErrorFunc channel, void *data, void *ctx,
471
              void *nod, int domain, int code, xmlErrorLevel level,
472
              const char *file, int line, const char *str1,
473
              const char *str2, const char *str3, int int1, int col,
474
        const char *msg, ...)
475
0
{
476
0
    xmlParserCtxtPtr ctxt = NULL;
477
0
    xmlNodePtr node = (xmlNodePtr) nod;
478
0
    char *str = NULL;
479
0
    xmlParserInputPtr input = NULL;
480
0
    xmlErrorPtr to = &xmlLastError;
481
0
    xmlNodePtr baseptr = NULL;
482
483
0
    if (code == XML_ERR_OK)
484
0
        return;
485
0
    if ((xmlGetWarningsDefaultValue == 0) && (level == XML_ERR_WARNING))
486
0
        return;
487
0
    if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
488
0
        (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
489
0
  (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
490
0
  ctxt = (xmlParserCtxtPtr) ctx;
491
492
0
        if (ctxt != NULL) {
493
0
            if (level == XML_ERR_WARNING) {
494
0
                if (ctxt->nbWarnings >= XML_MAX_ERRORS)
495
0
                    return;
496
0
                ctxt->nbWarnings += 1;
497
0
            } else {
498
0
                if (ctxt->nbErrors >= XML_MAX_ERRORS)
499
0
                    return;
500
0
                ctxt->nbErrors += 1;
501
0
            }
502
503
0
            if ((schannel == NULL) && (ctxt->sax != NULL) &&
504
0
                (ctxt->sax->initialized == XML_SAX2_MAGIC) &&
505
0
                (ctxt->sax->serror != NULL)) {
506
0
                schannel = ctxt->sax->serror;
507
0
                data = ctxt->userData;
508
0
            }
509
0
        }
510
0
    }
511
    /*
512
     * Check if structured error handler set
513
     */
514
0
    if (schannel == NULL) {
515
0
  schannel = xmlStructuredError;
516
  /*
517
   * if user has defined handler, change data ptr to user's choice
518
   */
519
0
  if (schannel != NULL)
520
0
      data = xmlStructuredErrorContext;
521
0
    }
522
    /*
523
     * Formatting the message
524
     */
525
0
    if (msg == NULL) {
526
0
        str = (char *) xmlStrdup(BAD_CAST "No error message provided");
527
0
    } else {
528
0
        XML_GET_VAR_STR(msg, str);
529
0
    }
530
531
    /*
532
     * specific processing if a parser context is provided
533
     */
534
0
    if (ctxt != NULL) {
535
0
        if (file == NULL) {
536
0
            input = ctxt->input;
537
0
            if ((input != NULL) && (input->filename == NULL) &&
538
0
                (ctxt->inputNr > 1)) {
539
0
                input = ctxt->inputTab[ctxt->inputNr - 2];
540
0
            }
541
0
            if (input != NULL) {
542
0
                file = input->filename;
543
0
                line = input->line;
544
0
                col = input->col;
545
0
            }
546
0
        }
547
0
        to = &ctxt->lastError;
548
0
    } else if ((node != NULL) && (file == NULL)) {
549
0
  int i;
550
551
0
  if ((node->doc != NULL) && (node->doc->URL != NULL)) {
552
0
      baseptr = node;
553
/*      file = (const char *) node->doc->URL; */
554
0
  }
555
0
  for (i = 0;
556
0
       ((i < 10) && (node != NULL) && (node->type != XML_ELEMENT_NODE));
557
0
       i++)
558
0
       node = node->parent;
559
0
        if ((baseptr == NULL) && (node != NULL) &&
560
0
      (node->doc != NULL) && (node->doc->URL != NULL))
561
0
      baseptr = node;
562
563
0
  if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
564
0
      line = node->line;
565
0
  if ((line == 0) || (line == 65535))
566
0
      line = xmlGetLineNo(node);
567
0
    }
568
569
    /*
570
     * Save the information about the error
571
     */
572
0
    xmlResetError(to);
573
0
    to->domain = domain;
574
0
    to->code = code;
575
0
    to->message = str;
576
0
    to->level = level;
577
0
    if (file != NULL)
578
0
        to->file = (char *) xmlStrdup((const xmlChar *) file);
579
0
    else if (baseptr != NULL) {
580
0
#ifdef LIBXML_XINCLUDE_ENABLED
581
  /*
582
   * We check if the error is within an XInclude section and,
583
   * if so, attempt to print out the href of the XInclude instead
584
   * of the usual "base" (doc->URL) for the node (bug 152623).
585
   */
586
0
        xmlNodePtr prev = baseptr;
587
0
        char *href = NULL;
588
0
  int inclcount = 0;
589
0
  while (prev != NULL) {
590
0
      if (prev->prev == NULL)
591
0
          prev = prev->parent;
592
0
      else {
593
0
          prev = prev->prev;
594
0
    if (prev->type == XML_XINCLUDE_START) {
595
0
        if (inclcount > 0) {
596
0
                        --inclcount;
597
0
                    } else {
598
0
                        href = (char *) xmlGetProp(prev, BAD_CAST "href");
599
0
                        if (href != NULL)
600
0
                break;
601
0
                    }
602
0
    } else if (prev->type == XML_XINCLUDE_END)
603
0
        inclcount++;
604
0
      }
605
0
  }
606
0
        if (href != NULL)
607
0
            to->file = href;
608
0
  else
609
0
#endif
610
0
      to->file = (char *) xmlStrdup(baseptr->doc->URL);
611
0
  if ((to->file == NULL) && (node != NULL) && (node->doc != NULL)) {
612
0
      to->file = (char *) xmlStrdup(node->doc->URL);
613
0
  }
614
0
    }
615
0
    to->line = line;
616
0
    if (str1 != NULL)
617
0
        to->str1 = (char *) xmlStrdup((const xmlChar *) str1);
618
0
    if (str2 != NULL)
619
0
        to->str2 = (char *) xmlStrdup((const xmlChar *) str2);
620
0
    if (str3 != NULL)
621
0
        to->str3 = (char *) xmlStrdup((const xmlChar *) str3);
622
0
    to->int1 = int1;
623
0
    to->int2 = col;
624
0
    to->node = node;
625
0
    to->ctxt = ctx;
626
627
0
    if (to != &xmlLastError)
628
0
        xmlCopyError(to,&xmlLastError);
629
630
0
    if (schannel != NULL) {
631
0
  schannel(data, to);
632
0
  return;
633
0
    }
634
635
    /*
636
     * Find the callback channel if channel param is NULL
637
     */
638
0
    if ((ctxt != NULL) && (channel == NULL) &&
639
0
        (xmlStructuredError == NULL) && (ctxt->sax != NULL)) {
640
0
        if (level == XML_ERR_WARNING)
641
0
      channel = ctxt->sax->warning;
642
0
        else
643
0
      channel = ctxt->sax->error;
644
0
  data = ctxt->userData;
645
0
    } else if (channel == NULL) {
646
0
  channel = xmlGenericError;
647
0
  if (ctxt != NULL) {
648
0
      data = ctxt;
649
0
  } else {
650
0
      data = xmlGenericErrorContext;
651
0
  }
652
0
    }
653
0
    if (channel == NULL)
654
0
        return;
655
656
0
    if ((channel == xmlParserError) ||
657
0
        (channel == xmlParserWarning) ||
658
0
  (channel == xmlParserValidityError) ||
659
0
  (channel == xmlParserValidityWarning))
660
0
  xmlReportError(to, ctxt, str, NULL, NULL);
661
0
    else if (((void(*)(void)) channel == (void(*)(void)) fprintf) ||
662
0
             (channel == xmlGenericErrorDefaultFunc))
663
0
  xmlReportError(to, ctxt, str, channel, data);
664
0
    else
665
0
  channel(data, "%s", str);
666
0
}
667
668
/**
669
 * __xmlSimpleError:
670
 * @domain: where the error comes from
671
 * @code: the error code
672
 * @node: the context node
673
 * @extra:  extra information
674
 *
675
 * Handle an out of memory condition
676
 */
677
void
678
__xmlSimpleError(int domain, int code, xmlNodePtr node,
679
                 const char *msg, const char *extra)
680
0
{
681
682
0
    if (code == XML_ERR_NO_MEMORY) {
683
0
  if (extra)
684
0
      __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain,
685
0
          XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
686
0
          NULL, NULL, 0, 0,
687
0
          "Memory allocation failed : %s\n", extra);
688
0
  else
689
0
      __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain,
690
0
          XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,
691
0
          NULL, NULL, 0, 0, "Memory allocation failed\n");
692
0
    } else {
693
0
  __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain,
694
0
      code, XML_ERR_ERROR, NULL, 0, extra,
695
0
      NULL, NULL, 0, 0, msg, extra);
696
0
    }
697
0
}
698
/**
699
 * xmlParserError:
700
 * @ctx:  an XML parser context
701
 * @msg:  the message to display/transmit
702
 * @...:  extra parameters for the message display
703
 *
704
 * Display and format an error messages, gives file, line, position and
705
 * extra parameters.
706
 */
707
void
708
xmlParserError(void *ctx, const char *msg, ...)
709
0
{
710
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
711
0
    xmlParserInputPtr input = NULL;
712
0
    xmlParserInputPtr cur = NULL;
713
0
    char * str;
714
715
0
    if (ctxt != NULL) {
716
0
  input = ctxt->input;
717
0
  if ((input != NULL) && (input->filename == NULL) &&
718
0
      (ctxt->inputNr > 1)) {
719
0
      cur = input;
720
0
      input = ctxt->inputTab[ctxt->inputNr - 2];
721
0
  }
722
0
  xmlParserPrintFileInfo(input);
723
0
    }
724
725
0
    xmlGenericError(xmlGenericErrorContext, "error: ");
726
0
    XML_GET_VAR_STR(msg, str);
727
0
    xmlGenericError(xmlGenericErrorContext, "%s", str);
728
0
    if (str != NULL)
729
0
  xmlFree(str);
730
731
0
    if (ctxt != NULL) {
732
0
  xmlParserPrintFileContext(input);
733
0
  if (cur != NULL) {
734
0
      xmlParserPrintFileInfo(cur);
735
0
      xmlGenericError(xmlGenericErrorContext, "\n");
736
0
      xmlParserPrintFileContext(cur);
737
0
  }
738
0
    }
739
0
}
740
741
/**
742
 * xmlParserWarning:
743
 * @ctx:  an XML parser context
744
 * @msg:  the message to display/transmit
745
 * @...:  extra parameters for the message display
746
 *
747
 * Display and format a warning messages, gives file, line, position and
748
 * extra parameters.
749
 */
750
void
751
xmlParserWarning(void *ctx, const char *msg, ...)
752
0
{
753
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
754
0
    xmlParserInputPtr input = NULL;
755
0
    xmlParserInputPtr cur = NULL;
756
0
    char * str;
757
758
0
    if (ctxt != NULL) {
759
0
  input = ctxt->input;
760
0
  if ((input != NULL) && (input->filename == NULL) &&
761
0
      (ctxt->inputNr > 1)) {
762
0
      cur = input;
763
0
      input = ctxt->inputTab[ctxt->inputNr - 2];
764
0
  }
765
0
  xmlParserPrintFileInfo(input);
766
0
    }
767
768
0
    xmlGenericError(xmlGenericErrorContext, "warning: ");
769
0
    XML_GET_VAR_STR(msg, str);
770
0
    xmlGenericError(xmlGenericErrorContext, "%s", str);
771
0
    if (str != NULL)
772
0
  xmlFree(str);
773
774
0
    if (ctxt != NULL) {
775
0
  xmlParserPrintFileContext(input);
776
0
  if (cur != NULL) {
777
0
      xmlParserPrintFileInfo(cur);
778
0
      xmlGenericError(xmlGenericErrorContext, "\n");
779
0
      xmlParserPrintFileContext(cur);
780
0
  }
781
0
    }
782
0
}
783
784
/************************************************************************
785
 *                  *
786
 *      Handling of validation errors     *
787
 *                  *
788
 ************************************************************************/
789
790
/**
791
 * xmlParserValidityError:
792
 * @ctx:  an XML parser context
793
 * @msg:  the message to display/transmit
794
 * @...:  extra parameters for the message display
795
 *
796
 * Display and format an validity error messages, gives file,
797
 * line, position and extra parameters.
798
 */
799
void
800
xmlParserValidityError(void *ctx, const char *msg, ...)
801
0
{
802
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
803
0
    xmlParserInputPtr input = NULL;
804
0
    char * str;
805
0
    int len = xmlStrlen((const xmlChar *) msg);
806
0
    static int had_info = 0;
807
808
0
    if ((len > 1) && (msg[len - 2] != ':')) {
809
0
  if (ctxt != NULL) {
810
0
      input = ctxt->input;
811
0
      if ((input->filename == NULL) && (ctxt->inputNr > 1))
812
0
    input = ctxt->inputTab[ctxt->inputNr - 2];
813
814
0
      if (had_info == 0) {
815
0
    xmlParserPrintFileInfo(input);
816
0
      }
817
0
  }
818
0
  xmlGenericError(xmlGenericErrorContext, "validity error: ");
819
0
  had_info = 0;
820
0
    } else {
821
0
  had_info = 1;
822
0
    }
823
824
0
    XML_GET_VAR_STR(msg, str);
825
0
    xmlGenericError(xmlGenericErrorContext, "%s", str);
826
0
    if (str != NULL)
827
0
  xmlFree(str);
828
829
0
    if ((ctxt != NULL) && (input != NULL)) {
830
0
  xmlParserPrintFileContext(input);
831
0
    }
832
0
}
833
834
/**
835
 * xmlParserValidityWarning:
836
 * @ctx:  an XML parser context
837
 * @msg:  the message to display/transmit
838
 * @...:  extra parameters for the message display
839
 *
840
 * Display and format a validity warning messages, gives file, line,
841
 * position and extra parameters.
842
 */
843
void
844
xmlParserValidityWarning(void *ctx, const char *msg, ...)
845
0
{
846
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
847
0
    xmlParserInputPtr input = NULL;
848
0
    char * str;
849
0
    int len = xmlStrlen((const xmlChar *) msg);
850
851
0
    if ((ctxt != NULL) && (len != 0) && (msg[len - 1] != ':')) {
852
0
  input = ctxt->input;
853
0
  if ((input->filename == NULL) && (ctxt->inputNr > 1))
854
0
      input = ctxt->inputTab[ctxt->inputNr - 2];
855
856
0
  xmlParserPrintFileInfo(input);
857
0
    }
858
859
0
    xmlGenericError(xmlGenericErrorContext, "validity warning: ");
860
0
    XML_GET_VAR_STR(msg, str);
861
0
    xmlGenericError(xmlGenericErrorContext, "%s", str);
862
0
    if (str != NULL)
863
0
  xmlFree(str);
864
865
0
    if (ctxt != NULL) {
866
0
  xmlParserPrintFileContext(input);
867
0
    }
868
0
}
869
870
871
/************************************************************************
872
 *                  *
873
 *      Extended Error Handling       *
874
 *                  *
875
 ************************************************************************/
876
877
/**
878
 * xmlGetLastError:
879
 *
880
 * Get the last global error registered. This is per thread if compiled
881
 * with thread support.
882
 *
883
 * Returns a pointer to the error
884
 */
885
const xmlError *
886
xmlGetLastError(void)
887
0
{
888
0
    if (xmlLastError.code == XML_ERR_OK)
889
0
        return (NULL);
890
0
    return (&xmlLastError);
891
0
}
892
893
/**
894
 * xmlResetError:
895
 * @err: pointer to the error.
896
 *
897
 * Cleanup the error.
898
 */
899
void
900
xmlResetError(xmlErrorPtr err)
901
0
{
902
0
    if (err == NULL)
903
0
        return;
904
0
    if (err->code == XML_ERR_OK)
905
0
        return;
906
0
    if (err->message != NULL)
907
0
        xmlFree(err->message);
908
0
    if (err->file != NULL)
909
0
        xmlFree(err->file);
910
0
    if (err->str1 != NULL)
911
0
        xmlFree(err->str1);
912
0
    if (err->str2 != NULL)
913
0
        xmlFree(err->str2);
914
0
    if (err->str3 != NULL)
915
0
        xmlFree(err->str3);
916
0
    memset(err, 0, sizeof(xmlError));
917
0
    err->code = XML_ERR_OK;
918
0
}
919
920
/**
921
 * xmlResetLastError:
922
 *
923
 * Cleanup the last global error registered. For parsing error
924
 * this does not change the well-formedness result.
925
 */
926
void
927
xmlResetLastError(void)
928
0
{
929
0
    if (xmlLastError.code == XML_ERR_OK)
930
0
        return;
931
0
    xmlResetError(&xmlLastError);
932
0
}
933
934
/**
935
 * xmlCtxtGetLastError:
936
 * @ctx:  an XML parser context
937
 *
938
 * Get the last parsing error registered.
939
 *
940
 * Returns NULL if no error occurred or a pointer to the error
941
 */
942
const xmlError *
943
xmlCtxtGetLastError(void *ctx)
944
0
{
945
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
946
947
0
    if (ctxt == NULL)
948
0
        return (NULL);
949
0
    if (ctxt->lastError.code == XML_ERR_OK)
950
0
        return (NULL);
951
0
    return (&ctxt->lastError);
952
0
}
953
954
/**
955
 * xmlCtxtResetLastError:
956
 * @ctx:  an XML parser context
957
 *
958
 * Cleanup the last global error registered. For parsing error
959
 * this does not change the well-formedness result.
960
 */
961
void
962
xmlCtxtResetLastError(void *ctx)
963
0
{
964
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
965
966
0
    if (ctxt == NULL)
967
0
        return;
968
0
    ctxt->errNo = XML_ERR_OK;
969
0
    if (ctxt->lastError.code == XML_ERR_OK)
970
0
        return;
971
0
    xmlResetError(&ctxt->lastError);
972
0
}
973
974
/**
975
 * xmlCopyError:
976
 * @from:  a source error
977
 * @to:  a target error
978
 *
979
 * Save the original error to the new place.
980
 *
981
 * Returns 0 in case of success and -1 in case of error.
982
 */
983
int
984
0
xmlCopyError(const xmlError *from, xmlErrorPtr to) {
985
0
    char *message, *file, *str1, *str2, *str3;
986
987
0
    if ((from == NULL) || (to == NULL))
988
0
        return(-1);
989
990
0
    message = (char *) xmlStrdup((xmlChar *) from->message);
991
0
    file = (char *) xmlStrdup ((xmlChar *) from->file);
992
0
    str1 = (char *) xmlStrdup ((xmlChar *) from->str1);
993
0
    str2 = (char *) xmlStrdup ((xmlChar *) from->str2);
994
0
    str3 = (char *) xmlStrdup ((xmlChar *) from->str3);
995
996
0
    if (to->message != NULL)
997
0
        xmlFree(to->message);
998
0
    if (to->file != NULL)
999
0
        xmlFree(to->file);
1000
0
    if (to->str1 != NULL)
1001
0
        xmlFree(to->str1);
1002
0
    if (to->str2 != NULL)
1003
0
        xmlFree(to->str2);
1004
0
    if (to->str3 != NULL)
1005
0
        xmlFree(to->str3);
1006
0
    to->domain = from->domain;
1007
0
    to->code = from->code;
1008
0
    to->level = from->level;
1009
0
    to->line = from->line;
1010
0
    to->node = from->node;
1011
0
    to->int1 = from->int1;
1012
0
    to->int2 = from->int2;
1013
0
    to->node = from->node;
1014
0
    to->ctxt = from->ctxt;
1015
0
    to->message = message;
1016
0
    to->file = file;
1017
0
    to->str1 = str1;
1018
0
    to->str2 = str2;
1019
0
    to->str3 = str3;
1020
1021
0
    return 0;
1022
0
}
1023