Coverage Report

Created: 2023-09-29 17:40

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