Coverage Report

Created: 2024-08-17 06:44

/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
36.6M
#define XML_MAX_ERRORS 100
22
23
487k
#define XML_GET_VAR_STR(msg, str) {       \
24
487k
    int       size, prev_size = -1;       \
25
487k
    int       chars;            \
26
487k
    char      *larger;            \
27
487k
    va_list   ap;           \
28
487k
                \
29
487k
    str = (char *) xmlMalloc(150);        \
30
487k
    if (str != NULL) {           \
31
487k
                \
32
487k
    size = 150;             \
33
487k
                \
34
975k
    while (size < 64000) {         \
35
975k
  va_start(ap, msg);          \
36
975k
  chars = vsnprintf(str, size, msg, ap);      \
37
975k
  va_end(ap);           \
38
975k
  if ((chars > -1) && (chars < size)) {     \
39
975k
      if (prev_size == chars) {       \
40
487k
    break;            \
41
487k
      } else {           \
42
487k
    prev_size = chars;        \
43
487k
      }              \
44
975k
  }              \
45
975k
  if (chars > -1)           \
46
488k
      size += chars + 1;         \
47
488k
  else              \
48
488k
      size += 100;         \
49
488k
  if ((larger = (char *) xmlRealloc(str, size)) == NULL) {\
50
0
      break;            \
51
0
  }              \
52
488k
  str = larger;           \
53
488k
    }}               \
54
487k
}
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
12
xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
116
12
    xmlGenericErrorContext = ctx;
117
12
    if (handler != NULL)
118
12
  xmlGenericError = handler;
119
0
    else
120
0
  xmlGenericError = xmlGenericErrorDefaultFunc;
121
12
}
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
12
xmlParserPrintFileInfo(xmlParserInputPtr input) {
156
12
    if (input != NULL) {
157
12
  if (input->filename)
158
8
      xmlGenericError(xmlGenericErrorContext,
159
8
        "%s:%d: ", input->filename,
160
8
        input->line);
161
4
  else
162
4
      xmlGenericError(xmlGenericErrorContext,
163
4
        "Entity: line %d: ", input->line);
164
12
    }
165
12
}
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
58.1k
    xmlGenericErrorFunc channel, void *data ) {
177
58.1k
    const xmlChar *cur, *base, *start;
178
58.1k
    unsigned int n, col;  /* GCC warns if signed, because compared with sizeof() */
179
58.1k
    xmlChar  content[81]; /* space for 80 chars + line terminator */
180
58.1k
    xmlChar *ctnt;
181
182
58.1k
    if ((input == NULL) || (input->cur == NULL))
183
0
        return;
184
185
58.1k
    cur = input->cur;
186
58.1k
    base = input->base;
187
    /* skip backwards over any end-of-lines */
188
62.2k
    while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
189
4.14k
  cur--;
190
4.14k
    }
191
58.1k
    n = 0;
192
    /* search backwards for beginning-of-line (to max buff size) */
193
2.18M
    while ((n < sizeof(content) - 1) && (cur > base) &&
194
2.18M
     (*cur != '\n') && (*cur != '\r')) {
195
2.12M
        cur--;
196
2.12M
        n++;
197
2.12M
    }
198
58.1k
    if ((n > 0) && ((*cur == '\n') || (*cur == '\r'))) {
199
39.5k
        cur++;
200
39.5k
    } else {
201
        /* skip over continuation bytes */
202
35.4k
        while ((cur < input->cur) && ((*cur & 0xC0) == 0x80))
203
16.9k
            cur++;
204
18.5k
    }
205
    /* calculate the error position in terms of the current position */
206
58.1k
    col = input->cur - cur;
207
    /* search forward for end-of-line (to max buff size) */
208
58.1k
    n = 0;
209
58.1k
    start = cur;
210
    /* copy selected text to our buffer */
211
2.22M
    while ((*cur != 0) && (*(cur) != '\n') && (*(cur) != '\r')) {
212
2.18M
        int len = input->end - cur;
213
2.18M
        int c = xmlGetUTF8Char(cur, &len);
214
215
2.18M
        if ((c < 0) || (n + len > sizeof(content)-1))
216
17.7k
            break;
217
2.16M
        cur += len;
218
2.16M
  n += len;
219
2.16M
    }
220
58.1k
    memcpy(content, start, n);
221
58.1k
    content[n] = 0;
222
    /* print out the selected text */
223
58.1k
    channel(data ,"%s\n", content);
224
    /* create blank line with problem pointer */
225
58.1k
    n = 0;
226
58.1k
    ctnt = content;
227
    /* (leave buffer space for pointer + line terminator) */
228
1.85M
    while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
229
1.79M
  if (*(ctnt) != '\t')
230
1.78M
      *(ctnt) = ' ';
231
1.79M
  ctnt++;
232
1.79M
    }
233
58.1k
    *ctnt++ = '^';
234
58.1k
    *ctnt = 0;
235
58.1k
    channel(data ,"%s\n", content);
236
58.1k
}
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
12
xmlParserPrintFileContext(xmlParserInputPtr input) {
246
12
   xmlParserPrintFileContextInternal(input, xmlGenericError,
247
12
                                     xmlGenericErrorContext);
248
12
}
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
56.6k
{
263
56.6k
    char *file = NULL;
264
56.6k
    int line = 0;
265
56.6k
    int code = -1;
266
56.6k
    int domain;
267
56.6k
    const xmlChar *name = NULL;
268
56.6k
    xmlNodePtr node;
269
56.6k
    xmlErrorLevel level;
270
56.6k
    xmlParserInputPtr input = NULL;
271
56.6k
    xmlParserInputPtr cur = NULL;
272
273
56.6k
    if (err == NULL)
274
0
        return;
275
276
56.6k
    if (channel == NULL) {
277
56.6k
  channel = xmlGenericError;
278
56.6k
  data = xmlGenericErrorContext;
279
56.6k
    }
280
56.6k
    file = err->file;
281
56.6k
    line = err->line;
282
56.6k
    code = err->code;
283
56.6k
    domain = err->domain;
284
56.6k
    level = err->level;
285
56.6k
    node = err->node;
286
287
56.6k
    if (code == XML_ERR_OK)
288
0
        return;
289
290
56.6k
    if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
291
195
        name = node->name;
292
293
    /*
294
     * Maintain the compatibility with the legacy error handling
295
     */
296
56.6k
    if (ctxt != NULL) {
297
56.6k
        input = ctxt->input;
298
56.6k
        if ((input != NULL) && (input->filename == NULL) &&
299
56.6k
            (ctxt->inputNr > 1)) {
300
1.45k
            cur = input;
301
1.45k
            input = ctxt->inputTab[ctxt->inputNr - 2];
302
1.45k
        }
303
56.6k
        if (input != NULL) {
304
56.6k
            if (input->filename)
305
44.9k
                channel(data, "%s:%d: ", input->filename, input->line);
306
11.6k
            else if ((line != 0) && (domain == XML_FROM_PARSER))
307
11.2k
                channel(data, "Entity: line %d: ", input->line);
308
56.6k
        }
309
56.6k
    } 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
56.6k
    if (name != NULL) {
319
195
        channel(data, "element %s: ", name);
320
195
    }
321
56.6k
    switch (domain) {
322
55.4k
        case XML_FROM_PARSER:
323
55.4k
            channel(data, "parser ");
324
55.4k
            break;
325
740
        case XML_FROM_NAMESPACE:
326
740
            channel(data, "namespace ");
327
740
            break;
328
90
        case XML_FROM_DTD:
329
399
        case XML_FROM_VALID:
330
399
            channel(data, "validity ");
331
399
            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
56.6k
    }
395
56.6k
    switch (level) {
396
0
        case XML_ERR_NONE:
397
0
            channel(data, ": ");
398
0
            break;
399
10.7k
        case XML_ERR_WARNING:
400
10.7k
            channel(data, "warning : ");
401
10.7k
            break;
402
2.65k
        case XML_ERR_ERROR:
403
2.65k
            channel(data, "error : ");
404
2.65k
            break;
405
43.2k
        case XML_ERR_FATAL:
406
43.2k
            channel(data, "error : ");
407
43.2k
            break;
408
56.6k
    }
409
56.6k
    if (str != NULL) {
410
56.6k
        int len;
411
56.6k
  len = xmlStrlen((const xmlChar *)str);
412
56.6k
  if ((len > 0) && (str[len - 1] != '\n'))
413
186
      channel(data, "%s\n", str);
414
56.4k
  else
415
56.4k
      channel(data, "%s", str);
416
56.6k
    } else {
417
0
        channel(data, "%s\n", "out of memory error");
418
0
    }
419
420
56.6k
    if (ctxt != NULL) {
421
56.6k
        xmlParserPrintFileContextInternal(input, channel, data);
422
56.6k
        if (cur != NULL) {
423
1.45k
            if (cur->filename)
424
0
                channel(data, "%s:%d: \n", cur->filename, cur->line);
425
1.45k
            else if ((line != 0) && (domain == XML_FROM_PARSER))
426
1.45k
                channel(data, "Entity: line %d: \n", cur->line);
427
1.45k
            xmlParserPrintFileContextInternal(cur, channel, data);
428
1.45k
        }
429
56.6k
    }
430
56.6k
    if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
431
56.6k
        (err->int1 < 100) &&
432
56.6k
  (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
56.6k
}
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
37.0M
{
477
37.0M
    xmlParserCtxtPtr ctxt = NULL;
478
37.0M
    xmlNodePtr node = (xmlNodePtr) nod;
479
37.0M
    char *str = NULL;
480
37.0M
    xmlParserInputPtr input = NULL;
481
37.0M
    xmlErrorPtr to = &xmlLastError;
482
37.0M
    xmlNodePtr baseptr = NULL;
483
484
37.0M
    if (code == XML_ERR_OK)
485
0
        return;
486
37.0M
    if ((xmlGetWarningsDefaultValue == 0) && (level == XML_ERR_WARNING))
487
0
        return;
488
37.0M
    if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
489
37.0M
        (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
490
37.0M
  (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
491
36.6M
  ctxt = (xmlParserCtxtPtr) ctx;
492
493
36.6M
        if (ctxt != NULL) {
494
36.6M
            if (level == XML_ERR_WARNING) {
495
15.1k
                if (ctxt->nbWarnings >= XML_MAX_ERRORS)
496
471
                    return;
497
14.6k
                ctxt->nbWarnings += 1;
498
36.6M
            } else {
499
36.6M
                if (ctxt->nbErrors >= XML_MAX_ERRORS)
500
36.5M
                    return;
501
122k
                ctxt->nbErrors += 1;
502
122k
            }
503
504
136k
            if ((schannel == NULL) && (ctxt->sax != NULL) &&
505
136k
                (ctxt->sax->initialized == XML_SAX2_MAGIC) &&
506
136k
                (ctxt->sax->serror != NULL)) {
507
0
                schannel = ctxt->sax->serror;
508
0
                data = ctxt->userData;
509
0
            }
510
136k
        }
511
36.6M
    }
512
    /*
513
     * Check if structured error handler set
514
     */
515
487k
    if (schannel == NULL) {
516
487k
  schannel = xmlStructuredError;
517
  /*
518
   * if user has defined handler, change data ptr to user's choice
519
   */
520
487k
  if (schannel != NULL)
521
0
      data = xmlStructuredErrorContext;
522
487k
    }
523
    /*
524
     * Formatting the message
525
     */
526
487k
    if (msg == NULL) {
527
0
        str = (char *) xmlStrdup(BAD_CAST "No error message provided");
528
487k
    } else {
529
487k
        XML_GET_VAR_STR(msg, str);
530
487k
    }
531
532
    /*
533
     * specific processing if a parser context is provided
534
     */
535
487k
    if (ctxt != NULL) {
536
136k
        if (file == NULL) {
537
136k
            input = ctxt->input;
538
136k
            if ((input != NULL) && (input->filename == NULL) &&
539
136k
                (ctxt->inputNr > 1)) {
540
1.45k
                input = ctxt->inputTab[ctxt->inputNr - 2];
541
1.45k
            }
542
136k
            if (input != NULL) {
543
136k
                file = input->filename;
544
136k
                line = input->line;
545
136k
                col = input->col;
546
136k
            }
547
136k
        }
548
136k
        to = &ctxt->lastError;
549
350k
    } else if ((node != NULL) && (file == NULL)) {
550
350k
  int i;
551
552
350k
  if ((node->doc != NULL) && (node->doc->URL != NULL)) {
553
350k
      baseptr = node;
554
/*      file = (const char *) node->doc->URL; */
555
350k
  }
556
350k
  for (i = 0;
557
700k
       ((i < 10) && (node != NULL) && (node->type != XML_ELEMENT_NODE));
558
350k
       i++)
559
350k
       node = node->parent;
560
350k
        if ((baseptr == NULL) && (node != NULL) &&
561
350k
      (node->doc != NULL) && (node->doc->URL != NULL))
562
0
      baseptr = node;
563
564
350k
  if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
565
350k
      line = node->line;
566
350k
  if ((line == 0) || (line == 65535))
567
0
      line = xmlGetLineNo(node);
568
350k
    }
569
570
    /*
571
     * Save the information about the error
572
     */
573
487k
    xmlResetError(to);
574
487k
    to->domain = domain;
575
487k
    to->code = code;
576
487k
    to->message = str;
577
487k
    to->level = level;
578
487k
    if (file != NULL)
579
112k
        to->file = (char *) xmlStrdup((const xmlChar *) file);
580
375k
    else if (baseptr != NULL) {
581
350k
#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
350k
        xmlNodePtr prev = baseptr;
588
350k
        char *href = NULL;
589
350k
  int inclcount = 0;
590
5.44M
  while (prev != NULL) {
591
5.09M
      if (prev->prev == NULL)
592
2.09M
          prev = prev->parent;
593
2.99M
      else {
594
2.99M
          prev = prev->prev;
595
2.99M
    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
2.99M
    } else if (prev->type == XML_XINCLUDE_END)
604
0
        inclcount++;
605
2.99M
      }
606
5.09M
  }
607
350k
        if (href != NULL)
608
0
            to->file = href;
609
350k
  else
610
350k
#endif
611
350k
      to->file = (char *) xmlStrdup(baseptr->doc->URL);
612
350k
  if ((to->file == NULL) && (node != NULL) && (node->doc != NULL)) {
613
0
      to->file = (char *) xmlStrdup(node->doc->URL);
614
0
  }
615
350k
    }
616
487k
    to->line = line;
617
487k
    if (str1 != NULL)
618
43.0k
        to->str1 = (char *) xmlStrdup((const xmlChar *) str1);
619
487k
    if (str2 != NULL)
620
4.96k
        to->str2 = (char *) xmlStrdup((const xmlChar *) str2);
621
487k
    if (str3 != NULL)
622
130
        to->str3 = (char *) xmlStrdup((const xmlChar *) str3);
623
487k
    to->int1 = int1;
624
487k
    to->int2 = col;
625
487k
    to->node = node;
626
487k
    to->ctxt = ctx;
627
628
487k
    if (to != &xmlLastError)
629
136k
        xmlCopyError(to,&xmlLastError);
630
631
487k
    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
487k
    if ((ctxt != NULL) && (channel == NULL) &&
640
487k
        (xmlStructuredError == NULL) && (ctxt->sax != NULL)) {
641
125k
        if (level == XML_ERR_WARNING)
642
4.00k
      channel = ctxt->sax->warning;
643
121k
        else
644
121k
      channel = ctxt->sax->error;
645
125k
  data = ctxt->userData;
646
361k
    } else if (channel == NULL) {
647
350k
  channel = xmlGenericError;
648
350k
  if (ctxt != NULL) {
649
0
      data = ctxt;
650
350k
  } else {
651
350k
      data = xmlGenericErrorContext;
652
350k
  }
653
350k
    }
654
487k
    if (channel == NULL)
655
80.2k
        return;
656
657
407k
    if ((channel == xmlParserError) ||
658
407k
        (channel == xmlParserWarning) ||
659
407k
  (channel == xmlParserValidityError) ||
660
407k
  (channel == xmlParserValidityWarning))
661
56.6k
  xmlReportError(to, ctxt, str, NULL, NULL);
662
350k
    else if (((void(*)(void)) channel == (void(*)(void)) fprintf) ||
663
350k
             (channel == xmlGenericErrorDefaultFunc))
664
0
  xmlReportError(to, ctxt, str, channel, data);
665
350k
    else
666
350k
  channel(data, "%s", str);
667
407k
}
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
350k
{
682
683
350k
    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
350k
    } else {
694
350k
  __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain,
695
350k
      code, XML_ERR_ERROR, NULL, 0, extra,
696
350k
      NULL, NULL, 0, 0, msg, extra);
697
350k
    }
698
350k
}
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
12
{
754
12
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
755
12
    xmlParserInputPtr input = NULL;
756
12
    xmlParserInputPtr cur = NULL;
757
12
    char * str;
758
759
12
    if (ctxt != NULL) {
760
12
  input = ctxt->input;
761
12
  if ((input != NULL) && (input->filename == NULL) &&
762
12
      (ctxt->inputNr > 1)) {
763
0
      cur = input;
764
0
      input = ctxt->inputTab[ctxt->inputNr - 2];
765
0
  }
766
12
  xmlParserPrintFileInfo(input);
767
12
    }
768
769
12
    xmlGenericError(xmlGenericErrorContext, "warning: ");
770
12
    XML_GET_VAR_STR(msg, str);
771
12
    xmlGenericError(xmlGenericErrorContext, "%s", str);
772
12
    if (str != NULL)
773
12
  xmlFree(str);
774
775
12
    if (ctxt != NULL) {
776
12
  xmlParserPrintFileContext(input);
777
12
  if (cur != NULL) {
778
0
      xmlParserPrintFileInfo(cur);
779
0
      xmlGenericError(xmlGenericErrorContext, "\n");
780
0
      xmlParserPrintFileContext(cur);
781
0
  }
782
12
    }
783
12
}
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
491k
{
903
491k
    if (err == NULL)
904
0
        return;
905
491k
    if (err->code == XML_ERR_OK)
906
11.0k
        return;
907
480k
    if (err->message != NULL)
908
480k
        xmlFree(err->message);
909
480k
    if (err->file != NULL)
910
455k
        xmlFree(err->file);
911
480k
    if (err->str1 != NULL)
912
38.8k
        xmlFree(err->str1);
913
480k
    if (err->str2 != NULL)
914
4.69k
        xmlFree(err->str2);
915
480k
    if (err->str3 != NULL)
916
120
        xmlFree(err->str3);
917
480k
    memset(err, 0, sizeof(xmlError));
918
480k
    err->code = XML_ERR_OK;
919
480k
}
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
4.44k
{
930
4.44k
    if (xmlLastError.code == XML_ERR_OK)
931
771
        return;
932
3.67k
    xmlResetError(&xmlLastError);
933
3.67k
}
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
137k
xmlCopyError(xmlErrorPtr from, xmlErrorPtr to) {
986
137k
    char *message, *file, *str1, *str2, *str3;
987
988
137k
    if ((from == NULL) || (to == NULL))
989
0
        return(-1);
990
991
137k
    message = (char *) xmlStrdup((xmlChar *) from->message);
992
137k
    file = (char *) xmlStrdup ((xmlChar *) from->file);
993
137k
    str1 = (char *) xmlStrdup ((xmlChar *) from->str1);
994
137k
    str2 = (char *) xmlStrdup ((xmlChar *) from->str2);
995
137k
    str3 = (char *) xmlStrdup ((xmlChar *) from->str3);
996
997
137k
    if (to->message != NULL)
998
133k
        xmlFree(to->message);
999
137k
    if (to->file != NULL)
1000
111k
        xmlFree(to->file);
1001
137k
    if (to->str1 != NULL)
1002
40.6k
        xmlFree(to->str1);
1003
137k
    if (to->str2 != NULL)
1004
4.75k
        xmlFree(to->str2);
1005
137k
    if (to->str3 != NULL)
1006
126
        xmlFree(to->str3);
1007
137k
    to->domain = from->domain;
1008
137k
    to->code = from->code;
1009
137k
    to->level = from->level;
1010
137k
    to->line = from->line;
1011
137k
    to->node = from->node;
1012
137k
    to->int1 = from->int1;
1013
137k
    to->int2 = from->int2;
1014
137k
    to->node = from->node;
1015
137k
    to->ctxt = from->ctxt;
1016
137k
    to->message = message;
1017
137k
    to->file = file;
1018
137k
    to->str1 = str1;
1019
137k
    to->str2 = str2;
1020
137k
    to->str3 = str3;
1021
1022
137k
    return 0;
1023
137k
}
1024