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