• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <stdlib.h>
15 #include <libxml/parser.h>
16 #include <libxml/xmlerror.h>
17 #include <libxml/xmlmemory.h>
18 
19 #include "private/error.h"
20 #include "private/string.h"
21 
22 /************************************************************************
23  *									*
24  *			Error struct					*
25  *									*
26  ************************************************************************/
27 
28 static int
xmlVSetError(xmlError * err,void * ctxt,xmlNodePtr node,int domain,int code,xmlErrorLevel level,const char * file,int line,const char * str1,const char * str2,const char * str3,int int1,int col,const char * fmt,va_list ap)29 xmlVSetError(xmlError *err,
30              void *ctxt, xmlNodePtr node,
31              int domain, int code, xmlErrorLevel level,
32              const char *file, int line,
33              const char *str1, const char *str2, const char *str3,
34              int int1, int col,
35              const char *fmt, va_list ap)
36 {
37     char *message = NULL;
38     char *fileCopy = NULL;
39     char *str1Copy = NULL;
40     char *str2Copy = NULL;
41     char *str3Copy = NULL;
42 
43     if (code == XML_ERR_OK) {
44         xmlResetError(err);
45         return(0);
46     }
47 
48     /*
49      * Formatting the message
50      */
51     if (fmt == NULL) {
52         message = xmlMemStrdup("No error message provided");
53     } else {
54         xmlChar *tmp;
55         int res;
56 
57         res = xmlStrVASPrintf(&tmp, MAX_ERR_MSG_SIZE, fmt, ap);
58         if (res < 0)
59             goto err_memory;
60         message = (char *) tmp;
61     }
62     if (message == NULL)
63         goto err_memory;
64 
65     if (file != NULL) {
66         fileCopy = (char *) xmlStrdup((const xmlChar *) file);
67         if (fileCopy == NULL)
68             goto err_memory;
69     }
70     if (str1 != NULL) {
71         str1Copy = (char *) xmlStrdup((const xmlChar *) str1);
72         if (str1Copy == NULL)
73             goto err_memory;
74     }
75     if (str2 != NULL) {
76         str2Copy = (char *) xmlStrdup((const xmlChar *) str2);
77         if (str2Copy == NULL)
78             goto err_memory;
79     }
80     if (str3 != NULL) {
81         str3Copy = (char *) xmlStrdup((const xmlChar *) str3);
82         if (str3Copy == NULL)
83             goto err_memory;
84     }
85 
86     xmlResetError(err);
87 
88     err->domain = domain;
89     err->code = code;
90     err->message = message;
91     err->level = level;
92     err->file = fileCopy;
93     err->line = line;
94     err->str1 = str1Copy;
95     err->str2 = str2Copy;
96     err->str3 = str3Copy;
97     err->int1 = int1;
98     err->int2 = col;
99     err->node = node;
100     err->ctxt = ctxt;
101 
102     return(0);
103 
104 err_memory:
105     xmlFree(message);
106     xmlFree(fileCopy);
107     xmlFree(str1Copy);
108     xmlFree(str2Copy);
109     xmlFree(str3Copy);
110     return(-1);
111 }
112 
113 static int LIBXML_ATTR_FORMAT(14,15)
xmlSetError(xmlError * err,void * ctxt,xmlNodePtr node,int domain,int code,xmlErrorLevel level,const char * file,int line,const char * str1,const char * str2,const char * str3,int int1,int col,const char * fmt,...)114 xmlSetError(xmlError *err,
115             void *ctxt, xmlNodePtr node,
116             int domain, int code, xmlErrorLevel level,
117             const char *file, int line,
118             const char *str1, const char *str2, const char *str3,
119             int int1, int col,
120             const char *fmt, ...)
121 {
122     va_list ap;
123     int res;
124 
125     va_start(ap, fmt);
126     res = xmlVSetError(err, ctxt, node, domain, code, level, file, line,
127                        str1, str2, str3, int1, col, fmt, ap);
128     va_end(ap);
129 
130     return(res);
131 }
132 
133 static int
xmlVUpdateError(xmlError * err,void * ctxt,xmlNodePtr node,int domain,int code,xmlErrorLevel level,const char * file,int line,const char * str1,const char * str2,const char * str3,int int1,int col,const char * fmt,va_list ap)134 xmlVUpdateError(xmlError *err,
135                 void *ctxt, xmlNodePtr node,
136                 int domain, int code, xmlErrorLevel level,
137                 const char *file, int line,
138                 const char *str1, const char *str2, const char *str3,
139                 int int1, int col,
140                 const char *fmt, va_list ap)
141 {
142     int res;
143 
144     /*
145      * Find first element parent.
146      */
147     if (node != NULL) {
148         int i;
149 
150         for (i = 0; i < 10; i++) {
151             if ((node->type == XML_ELEMENT_NODE) ||
152                 (node->parent == NULL))
153                 break;
154             node = node->parent;
155         }
156     }
157 
158     /*
159      * Get file and line from node.
160      */
161     if (node != NULL) {
162         if ((file == NULL) && (node->doc != NULL))
163             file = (const char *) node->doc->URL;
164 
165         if (line == 0) {
166             if (node->type == XML_ELEMENT_NODE)
167                 line = node->line;
168             if ((line == 0) || (line == 65535))
169                 line = xmlGetLineNo(node);
170         }
171     }
172 
173     res = xmlVSetError(err, ctxt, node, domain, code, level, file, line,
174                        str1, str2, str3, int1, col, fmt, ap);
175 
176     return(res);
177 }
178 
179 /************************************************************************
180  *									*
181  *			Handling of out of context errors		*
182  *									*
183  ************************************************************************/
184 
185 /**
186  * xmlGenericErrorDefaultFunc:
187  * @ctx:  an error context
188  * @msg:  the message to display/transmit
189  * @...:  extra parameters for the message display
190  *
191  * Default handler for out of context error messages.
192  */
193 void
xmlGenericErrorDefaultFunc(void * ctx ATTRIBUTE_UNUSED,const char * msg,...)194 xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
195     va_list args;
196 
197     if (xmlGenericErrorContext == NULL)
198 	xmlGenericErrorContext = (void *) stderr;
199 
200     va_start(args, msg);
201     vfprintf((FILE *)xmlGenericErrorContext, msg, args);
202     va_end(args);
203 }
204 
205 /**
206  * initGenericErrorDefaultFunc:
207  * @handler:  the handler
208  *
209  * DEPRECATED: Use xmlSetGenericErrorFunc.
210  *
211  * Set or reset (if NULL) the default handler for generic errors
212  * to the builtin error function.
213  */
214 void
initGenericErrorDefaultFunc(xmlGenericErrorFunc * handler)215 initGenericErrorDefaultFunc(xmlGenericErrorFunc * handler)
216 {
217     if (handler == NULL)
218         xmlGenericError = xmlGenericErrorDefaultFunc;
219     else
220         xmlGenericError = (*handler);
221 }
222 
223 /**
224  * xmlSetGenericErrorFunc:
225  * @ctx:  the new error handling context
226  * @handler:  the new handler function
227  *
228  * DEPRECATED: See xmlSetStructuredErrorFunc for alternatives.
229  *
230  * Set the global "generic" handler and context for error messages.
231  * The generic error handler will only receive fragments of error
232  * messages which should be concatenated or printed to a stream.
233  *
234  * If handler is NULL, use the built-in default handler which prints
235  * to stderr.
236  *
237  * Since this is a global setting, it's a good idea to reset the
238  * error handler to its default value after collecting the errors
239  * you're interested in.
240  *
241  * For multi-threaded applications, this must be set separately for
242  * each thread.
243  */
244 void
xmlSetGenericErrorFunc(void * ctx,xmlGenericErrorFunc handler)245 xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
246     xmlGenericErrorContext = ctx;
247     if (handler != NULL)
248 	xmlGenericError = handler;
249     else
250 	xmlGenericError = xmlGenericErrorDefaultFunc;
251 }
252 
253 /**
254  * xmlSetStructuredErrorFunc:
255  * @ctx:  the new error handling context
256  * @handler:  the new handler function
257  *
258  * DEPRECATED: Use a per-context error handler.
259  *
260  * It's recommended to use the per-context error handlers instead:
261  *
262  * - xmlCtxtSetErrorHandler (since 2.13.0)
263  * - xmlTextReaderSetStructuredErrorHandler
264  * - xmlXPathSetErrorHandler (since 2.13.0)
265  * - xmlXIncludeSetErrorHandler (since 2.13.0)
266  * - xmlSchemaSetParserStructuredErrors
267  * - xmlSchemaSetValidStructuredErrors
268  * - xmlRelaxNGSetParserStructuredErrors
269  * - xmlRelaxNGSetValidStructuredErrors
270  *
271  * Set the global "structured" handler and context for error messages.
272  * If handler is NULL, the error handler is deactivated.
273  *
274  * The structured error handler takes precedence over "generic"
275  * handlers, even per-context generic handlers.
276  *
277  * Since this is a global setting, it's a good idea to deactivate the
278  * error handler after collecting the errors you're interested in.
279  *
280  * For multi-threaded applications, this must be set separately for
281  * each thread.
282  */
283 void
xmlSetStructuredErrorFunc(void * ctx,xmlStructuredErrorFunc handler)284 xmlSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) {
285     xmlStructuredErrorContext = ctx;
286     xmlStructuredError = handler;
287 }
288 
289 /************************************************************************
290  *									*
291  *			Handling of parsing errors			*
292  *									*
293  ************************************************************************/
294 
295 /**
296  * xmlParserPrintFileInfo:
297  * @input:  an xmlParserInputPtr input
298  *
299  * DEPRECATED: Use xmlFormatError.
300  *
301  * Displays the associated file and line information for the current input
302  */
303 
304 void
xmlParserPrintFileInfo(xmlParserInputPtr input)305 xmlParserPrintFileInfo(xmlParserInputPtr input) {
306     if (input != NULL) {
307 	if (input->filename)
308 	    xmlGenericError(xmlGenericErrorContext,
309 		    "%s:%d: ", input->filename,
310 		    input->line);
311 	else
312 	    xmlGenericError(xmlGenericErrorContext,
313 		    "Entity: line %d: ", input->line);
314     }
315 }
316 
317 /**
318  * xmlParserPrintFileContextInternal:
319  * @input:  an xmlParserInputPtr input
320  *
321  * Displays current context within the input content for error tracking
322  */
323 
324 static void
xmlParserPrintFileContextInternal(xmlParserInputPtr input,xmlGenericErrorFunc channel,void * data)325 xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
326 		xmlGenericErrorFunc channel, void *data ) {
327     const xmlChar *cur, *base, *start;
328     unsigned int n, col;	/* GCC warns if signed, because compared with sizeof() */
329     xmlChar  content[81]; /* space for 80 chars + line terminator */
330     xmlChar *ctnt;
331 
332     if ((input == NULL) || (input->cur == NULL))
333         return;
334 
335     cur = input->cur;
336     base = input->base;
337     /* skip backwards over any end-of-lines */
338     while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
339 	cur--;
340     }
341     n = 0;
342     /* search backwards for beginning-of-line (to max buff size) */
343     while ((n < sizeof(content) - 1) && (cur > base) &&
344 	   (*cur != '\n') && (*cur != '\r')) {
345         cur--;
346         n++;
347     }
348     if ((n > 0) && ((*cur == '\n') || (*cur == '\r'))) {
349         cur++;
350     } else {
351         /* skip over continuation bytes */
352         while ((cur < input->cur) && ((*cur & 0xC0) == 0x80))
353             cur++;
354     }
355     /* calculate the error position in terms of the current position */
356     col = input->cur - cur;
357     /* search forward for end-of-line (to max buff size) */
358     n = 0;
359     start = cur;
360     /* copy selected text to our buffer */
361     while ((*cur != 0) && (*(cur) != '\n') && (*(cur) != '\r')) {
362         int len = input->end - cur;
363         int c = xmlGetUTF8Char(cur, &len);
364 
365         if ((c < 0) || (n + len > sizeof(content)-1))
366             break;
367         cur += len;
368 	n += len;
369     }
370     memcpy(content, start, n);
371     content[n] = 0;
372     /* print out the selected text */
373     channel(data ,"%s\n", content);
374     /* create blank line with problem pointer */
375     n = 0;
376     ctnt = content;
377     /* (leave buffer space for pointer + line terminator) */
378     while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
379 	if (*(ctnt) != '\t')
380 	    *(ctnt) = ' ';
381 	ctnt++;
382     }
383     *ctnt++ = '^';
384     *ctnt = 0;
385     channel(data ,"%s\n", content);
386 }
387 
388 /**
389  * xmlParserPrintFileContext:
390  * @input:  an xmlParserInputPtr input
391  *
392  * DEPRECATED: Use xmlFormatError.
393  *
394  * Displays current context within the input content for error tracking
395  */
396 void
xmlParserPrintFileContext(xmlParserInputPtr input)397 xmlParserPrintFileContext(xmlParserInputPtr input) {
398    xmlParserPrintFileContextInternal(input, xmlGenericError,
399                                      xmlGenericErrorContext);
400 }
401 
402 /**
403  * xmlFormatError:
404  * @err:  the error
405  * @channel:  callback
406  * @data:  user data for callback
407  *
408  * Report a formatted error to a printf-like callback.
409  *
410  * This can result in a verbose multi-line report including additional
411  * information from the parser context.
412  *
413  * Available since 2.13.0.
414  */
415 void
xmlFormatError(const xmlError * err,xmlGenericErrorFunc channel,void * data)416 xmlFormatError(const xmlError *err, xmlGenericErrorFunc channel, void *data)
417 {
418     const char *message;
419     const char *file;
420     int line;
421     int code;
422     int domain;
423     const xmlChar *name = NULL;
424     xmlNodePtr node;
425     xmlErrorLevel level;
426     xmlParserCtxtPtr ctxt = NULL;
427     xmlParserInputPtr input = NULL;
428     xmlParserInputPtr cur = NULL;
429 
430     if ((err == NULL) || (channel == NULL))
431         return;
432 
433     message = err->message;
434     file = err->file;
435     line = err->line;
436     code = err->code;
437     domain = err->domain;
438     level = err->level;
439     node = err->node;
440 
441     if (code == XML_ERR_OK)
442         return;
443 
444     if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
445         (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
446 	(domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
447 	ctxt = err->ctxt;
448     }
449 
450     if ((node != NULL) && (node->type == XML_ELEMENT_NODE) &&
451         (domain != XML_FROM_SCHEMASV))
452         name = node->name;
453 
454     /*
455      * Maintain the compatibility with the legacy error handling
456      */
457     if ((ctxt != NULL) && (ctxt->input != NULL)) {
458         input = ctxt->input;
459         if ((input->filename == NULL) &&
460             (ctxt->inputNr > 1)) {
461             cur = input;
462             input = ctxt->inputTab[ctxt->inputNr - 2];
463         }
464         if (input->filename)
465             channel(data, "%s:%d: ", input->filename, input->line);
466         else if ((line != 0) && (domain == XML_FROM_PARSER))
467             channel(data, "Entity: line %d: ", input->line);
468     } else {
469         if (file != NULL)
470             channel(data, "%s:%d: ", file, line);
471         else if ((line != 0) &&
472 	         ((domain == XML_FROM_PARSER) || (domain == XML_FROM_SCHEMASV)||
473 		  (domain == XML_FROM_SCHEMASP)||(domain == XML_FROM_DTD) ||
474 		  (domain == XML_FROM_RELAXNGP)||(domain == XML_FROM_RELAXNGV)))
475             channel(data, "Entity: line %d: ", line);
476     }
477     if (name != NULL) {
478         channel(data, "element %s: ", name);
479     }
480     switch (domain) {
481         case XML_FROM_PARSER:
482             channel(data, "parser ");
483             break;
484         case XML_FROM_NAMESPACE:
485             channel(data, "namespace ");
486             break;
487         case XML_FROM_DTD:
488         case XML_FROM_VALID:
489             channel(data, "validity ");
490             break;
491         case XML_FROM_HTML:
492             channel(data, "HTML parser ");
493             break;
494         case XML_FROM_MEMORY:
495             channel(data, "memory ");
496             break;
497         case XML_FROM_OUTPUT:
498             channel(data, "output ");
499             break;
500         case XML_FROM_IO:
501             channel(data, "I/O ");
502             break;
503         case XML_FROM_XINCLUDE:
504             channel(data, "XInclude ");
505             break;
506         case XML_FROM_XPATH:
507             channel(data, "XPath ");
508             break;
509         case XML_FROM_XPOINTER:
510             channel(data, "parser ");
511             break;
512         case XML_FROM_REGEXP:
513             channel(data, "regexp ");
514             break;
515         case XML_FROM_MODULE:
516             channel(data, "module ");
517             break;
518         case XML_FROM_SCHEMASV:
519             channel(data, "Schemas validity ");
520             break;
521         case XML_FROM_SCHEMASP:
522             channel(data, "Schemas parser ");
523             break;
524         case XML_FROM_RELAXNGP:
525             channel(data, "Relax-NG parser ");
526             break;
527         case XML_FROM_RELAXNGV:
528             channel(data, "Relax-NG validity ");
529             break;
530         case XML_FROM_CATALOG:
531             channel(data, "Catalog ");
532             break;
533         case XML_FROM_C14N:
534             channel(data, "C14N ");
535             break;
536         case XML_FROM_XSLT:
537             channel(data, "XSLT ");
538             break;
539         case XML_FROM_I18N:
540             channel(data, "encoding ");
541             break;
542         case XML_FROM_SCHEMATRONV:
543             channel(data, "schematron ");
544             break;
545         case XML_FROM_BUFFER:
546             channel(data, "internal buffer ");
547             break;
548         case XML_FROM_URI:
549             channel(data, "URI ");
550             break;
551         default:
552             break;
553     }
554     switch (level) {
555         case XML_ERR_NONE:
556             channel(data, ": ");
557             break;
558         case XML_ERR_WARNING:
559             channel(data, "warning : ");
560             break;
561         case XML_ERR_ERROR:
562             channel(data, "error : ");
563             break;
564         case XML_ERR_FATAL:
565             channel(data, "error : ");
566             break;
567     }
568     if (message != NULL) {
569         int len;
570 	len = xmlStrlen((const xmlChar *) message);
571 	if ((len > 0) && (message[len - 1] != '\n'))
572 	    channel(data, "%s\n", message);
573 	else
574 	    channel(data, "%s", message);
575     } else {
576         channel(data, "%s\n", "No error message provided");
577     }
578 
579     if (ctxt != NULL) {
580         if ((input != NULL) &&
581             ((input->buf == NULL) || (input->buf->encoder == NULL)) &&
582             (code == XML_ERR_INVALID_ENCODING) &&
583             (input->cur < input->end)) {
584             int i;
585 
586             channel(data, "Bytes:");
587             for (i = 0; i < 4; i++) {
588                 if (input->cur + i >= input->end)
589                     break;
590                 channel(data, " 0x%02X", input->cur[i]);
591             }
592             channel(data, "\n");
593         }
594 
595         xmlParserPrintFileContextInternal(input, channel, data);
596 
597         if (cur != NULL) {
598             if (cur->filename)
599                 channel(data, "%s:%d: \n", cur->filename, cur->line);
600             else if ((line != 0) && (domain == XML_FROM_PARSER))
601                 channel(data, "Entity: line %d: \n", cur->line);
602             xmlParserPrintFileContextInternal(cur, channel, data);
603         }
604     }
605     if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
606         (err->int1 < 100) &&
607 	(err->int1 < xmlStrlen((const xmlChar *)err->str1))) {
608 	xmlChar buf[150];
609 	int i;
610 
611 	channel(data, "%s\n", err->str1);
612 	for (i=0;i < err->int1;i++)
613 	     buf[i] = ' ';
614 	buf[i++] = '^';
615 	buf[i] = 0;
616 	channel(data, "%s\n", buf);
617     }
618 }
619 
620 /**
621  * xmlRaiseMemoryError:
622  * @schannel: the structured callback channel
623  * @channel: the old callback channel
624  * @data: the callback data
625  * @domain: the domain for the error
626  * @error: optional error struct to be filled
627  *
628  * Update the global and optional error structure, then forward the
629  * error to an error handler.
630  *
631  * This function doesn't make memory allocations which are likely
632  * to fail after an OOM error.
633  */
634 void
xmlRaiseMemoryError(xmlStructuredErrorFunc schannel,xmlGenericErrorFunc channel,void * data,int domain,xmlError * error)635 xmlRaiseMemoryError(xmlStructuredErrorFunc schannel, xmlGenericErrorFunc channel,
636                     void *data, int domain, xmlError *error)
637 {
638     xmlError *lastError = &xmlLastError;
639 
640     xmlResetLastError();
641     lastError->domain = domain;
642     lastError->code = XML_ERR_NO_MEMORY;
643     lastError->level = XML_ERR_FATAL;
644 
645     if (error != NULL) {
646         xmlResetError(error);
647         error->domain = domain;
648         error->code = XML_ERR_NO_MEMORY;
649         error->level = XML_ERR_FATAL;
650     }
651 
652     if (schannel != NULL) {
653         schannel(data, lastError);
654     } else if (xmlStructuredError != NULL) {
655         xmlStructuredError(xmlStructuredErrorContext, lastError);
656     } else if (channel != NULL) {
657         channel(data, "libxml2: out of memory\n");
658     }
659 }
660 
661 /**
662  * xmlVRaiseError:
663  * @schannel: the structured callback channel
664  * @channel: the old callback channel
665  * @data: the callback data
666  * @ctx: the parser context or NULL
667  * @node: the current node or NULL
668  * @domain: the domain for the error
669  * @code: the code for the error
670  * @level: the xmlErrorLevel for the error
671  * @file: the file source of the error (or NULL)
672  * @line: the line of the error or 0 if N/A
673  * @str1: extra string info
674  * @str2: extra string info
675  * @str3: extra string info
676  * @int1: extra int info
677  * @col: column number of the error or 0 if N/A
678  * @msg:  the message to display/transmit
679  * @ap:  extra parameters for the message display
680  *
681  * Update the appropriate global or contextual error structure,
682  * then forward the error message down the parser or generic
683  * error callback handler
684  *
685  * Returns 0 on success, -1 if a memory allocation failed.
686  */
687 int
xmlVRaiseError(xmlStructuredErrorFunc schannel,xmlGenericErrorFunc channel,void * data,void * ctx,xmlNode * node,int domain,int code,xmlErrorLevel level,const char * file,int line,const char * str1,const char * str2,const char * str3,int int1,int col,const char * msg,va_list ap)688 xmlVRaiseError(xmlStructuredErrorFunc schannel,
689                xmlGenericErrorFunc channel, void *data, void *ctx,
690                xmlNode *node, int domain, int code, xmlErrorLevel level,
691                const char *file, int line, const char *str1,
692                const char *str2, const char *str3, int int1, int col,
693                const char *msg, va_list ap)
694 {
695     xmlParserCtxtPtr ctxt = NULL;
696     /* xmlLastError is a macro retrieving the per-thread global. */
697     xmlErrorPtr lastError = &xmlLastError;
698     xmlErrorPtr to = lastError;
699 
700     if (code == XML_ERR_OK)
701         return(0);
702 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
703     if (code == XML_ERR_INTERNAL_ERROR) {
704         fprintf(stderr, "Unexpected error: %d\n", code);
705         abort();
706     }
707 #endif
708     if ((xmlGetWarningsDefaultValue == 0) && (level == XML_ERR_WARNING))
709         return(0);
710 
711     if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
712         (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
713 	(domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
714 	ctxt = (xmlParserCtxtPtr) ctx;
715 
716         if (ctxt != NULL)
717             to = &ctxt->lastError;
718     }
719 
720     if (xmlVUpdateError(to, ctxt, node, domain, code, level, file, line,
721                         str1, str2, str3, int1, col, msg, ap))
722         return(-1);
723 
724     if (to != lastError) {
725         if (xmlCopyError(to, lastError) < 0)
726             return(-1);
727     }
728 
729     if (schannel != NULL) {
730 	schannel(data, to);
731     } else if (xmlStructuredError != NULL) {
732         xmlStructuredError(xmlStructuredErrorContext, to);
733     } else if (channel != NULL) {
734         /* Don't invoke legacy error handlers */
735         if ((channel == xmlGenericErrorDefaultFunc) ||
736             (channel == xmlParserError) ||
737             (channel == xmlParserWarning) ||
738             (channel == xmlParserValidityError) ||
739             (channel == xmlParserValidityWarning))
740             xmlFormatError(to, xmlGenericError, xmlGenericErrorContext);
741         else
742 	    channel(data, "%s", to->message);
743     }
744 
745     return(0);
746 }
747 
748 /**
749  * __xmlRaiseError:
750  * @schannel: the structured callback channel
751  * @channel: the old callback channel
752  * @data: the callback data
753  * @ctx: the parser context or NULL
754  * @nod: the node or NULL
755  * @domain: the domain for the error
756  * @code: the code for the error
757  * @level: the xmlErrorLevel for the error
758  * @file: the file source of the error (or NULL)
759  * @line: the line of the error or 0 if N/A
760  * @str1: extra string info
761  * @str2: extra string info
762  * @str3: extra string info
763  * @int1: extra int info
764  * @col: column number of the error or 0 if N/A
765  * @msg:  the message to display/transmit
766  * @...:  extra parameters for the message display
767  *
768  * Update the appropriate global or contextual error structure,
769  * then forward the error message down the parser or generic
770  * error callback handler
771  *
772  * Returns 0 on success, -1 if a memory allocation failed.
773  */
774 int
__xmlRaiseError(xmlStructuredErrorFunc schannel,xmlGenericErrorFunc channel,void * data,void * ctx,xmlNode * node,int domain,int code,xmlErrorLevel level,const char * file,int line,const char * str1,const char * str2,const char * str3,int int1,int col,const char * msg,...)775 __xmlRaiseError(xmlStructuredErrorFunc schannel,
776                 xmlGenericErrorFunc channel, void *data, void *ctx,
777                 xmlNode *node, int domain, int code, xmlErrorLevel level,
778                 const char *file, int line, const char *str1,
779                 const char *str2, const char *str3, int int1, int col,
780                 const char *msg, ...)
781 {
782     va_list ap;
783     int res;
784 
785     va_start(ap, msg);
786     res = xmlVRaiseError(schannel, channel, data, ctx, node, domain, code,
787                          level, file, line, str1, str2, str3, int1, col, msg,
788                          ap);
789     va_end(ap);
790 
791     return(res);
792 }
793 
794 static void
xmlVFormatLegacyError(void * ctx,const char * level,const char * fmt,va_list ap)795 xmlVFormatLegacyError(void *ctx, const char *level,
796                       const char *fmt, va_list ap) {
797     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
798     xmlParserInputPtr input = NULL;
799     xmlParserInputPtr cur = NULL;
800     xmlChar *str = NULL;
801 
802     if (ctxt != NULL) {
803 	input = ctxt->input;
804 	if ((input != NULL) && (input->filename == NULL) &&
805 	    (ctxt->inputNr > 1)) {
806 	    cur = input;
807 	    input = ctxt->inputTab[ctxt->inputNr - 2];
808 	}
809 	xmlParserPrintFileInfo(input);
810     }
811 
812     xmlGenericError(xmlGenericErrorContext, "%s: ", level);
813 
814     xmlStrVASPrintf(&str, MAX_ERR_MSG_SIZE, fmt, ap);
815     if (str != NULL) {
816         xmlGenericError(xmlGenericErrorContext, "%s", (char *) str);
817 	xmlFree(str);
818     }
819 
820     if (ctxt != NULL) {
821 	xmlParserPrintFileContext(input);
822 	if (cur != NULL) {
823 	    xmlParserPrintFileInfo(cur);
824 	    xmlGenericError(xmlGenericErrorContext, "\n");
825 	    xmlParserPrintFileContext(cur);
826 	}
827     }
828 }
829 
830 /**
831  * xmlParserError:
832  * @ctx:  an XML parser context
833  * @msg:  the message to display/transmit
834  * @...:  extra parameters for the message display
835  *
836  * Display and format an error messages, gives file, line, position and
837  * extra parameters.
838  */
839 void
xmlParserError(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)840 xmlParserError(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
841 {
842     va_list ap;
843 
844     va_start(ap, msg);
845     xmlVFormatLegacyError(ctx, "error", msg, ap);
846     va_end(ap);
847 }
848 
849 /**
850  * xmlParserWarning:
851  * @ctx:  an XML parser context
852  * @msg:  the message to display/transmit
853  * @...:  extra parameters for the message display
854  *
855  * Display and format a warning messages, gives file, line, position and
856  * extra parameters.
857  */
858 void
xmlParserWarning(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)859 xmlParserWarning(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
860 {
861     va_list ap;
862 
863     va_start(ap, msg);
864     xmlVFormatLegacyError(ctx, "warning", msg, ap);
865     va_end(ap);
866 }
867 
868 /**
869  * xmlParserValidityError:
870  * @ctx:  an XML parser context
871  * @msg:  the message to display/transmit
872  * @...:  extra parameters for the message display
873  *
874  * Display and format an validity error messages, gives file,
875  * line, position and extra parameters.
876  */
877 void
xmlParserValidityError(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)878 xmlParserValidityError(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
879 {
880     va_list ap;
881 
882     va_start(ap, msg);
883     xmlVFormatLegacyError(ctx, "validity error", msg, ap);
884     va_end(ap);
885 }
886 
887 /**
888  * xmlParserValidityWarning:
889  * @ctx:  an XML parser context
890  * @msg:  the message to display/transmit
891  * @...:  extra parameters for the message display
892  *
893  * Display and format a validity warning messages, gives file, line,
894  * position and extra parameters.
895  */
896 void
xmlParserValidityWarning(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)897 xmlParserValidityWarning(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
898 {
899     va_list ap;
900 
901     va_start(ap, msg);
902     xmlVFormatLegacyError(ctx, "validity warning", msg, ap);
903     va_end(ap);
904 }
905 
906 
907 /************************************************************************
908  *									*
909  *			Extended Error Handling				*
910  *									*
911  ************************************************************************/
912 
913 /**
914  * xmlGetLastError:
915  *
916  * Get the last global error registered. This is per thread if compiled
917  * with thread support.
918  *
919  * Returns a pointer to the error
920  */
921 const xmlError *
xmlGetLastError(void)922 xmlGetLastError(void)
923 {
924     if (xmlLastError.code == XML_ERR_OK)
925         return (NULL);
926     return (&xmlLastError);
927 }
928 
929 /**
930  * xmlResetError:
931  * @err: pointer to the error.
932  *
933  * Cleanup the error.
934  */
935 void
xmlResetError(xmlErrorPtr err)936 xmlResetError(xmlErrorPtr err)
937 {
938     if (err == NULL)
939         return;
940     if (err->code == XML_ERR_OK)
941         return;
942     if (err->message != NULL)
943         xmlFree(err->message);
944     if (err->file != NULL)
945         xmlFree(err->file);
946     if (err->str1 != NULL)
947         xmlFree(err->str1);
948     if (err->str2 != NULL)
949         xmlFree(err->str2);
950     if (err->str3 != NULL)
951         xmlFree(err->str3);
952     memset(err, 0, sizeof(xmlError));
953     err->code = XML_ERR_OK;
954 }
955 
956 /**
957  * xmlResetLastError:
958  *
959  * Cleanup the last global error registered. For parsing error
960  * this does not change the well-formedness result.
961  */
962 void
xmlResetLastError(void)963 xmlResetLastError(void)
964 {
965     if (xmlLastError.code == XML_ERR_OK)
966         return;
967     xmlResetError(&xmlLastError);
968 }
969 
970 /**
971  * xmlCtxtGetLastError:
972  * @ctx:  an XML parser context
973  *
974  * Get the last parsing error registered.
975  *
976  * Returns NULL if no error occurred or a pointer to the error
977  */
978 const xmlError *
xmlCtxtGetLastError(void * ctx)979 xmlCtxtGetLastError(void *ctx)
980 {
981     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
982 
983     if (ctxt == NULL)
984         return (NULL);
985     if (ctxt->lastError.code == XML_ERR_OK)
986         return (NULL);
987     return (&ctxt->lastError);
988 }
989 
990 /**
991  * xmlCtxtResetLastError:
992  * @ctx:  an XML parser context
993  *
994  * Cleanup the last global error registered. For parsing error
995  * this does not change the well-formedness result.
996  */
997 void
xmlCtxtResetLastError(void * ctx)998 xmlCtxtResetLastError(void *ctx)
999 {
1000     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1001 
1002     if (ctxt == NULL)
1003         return;
1004     ctxt->errNo = XML_ERR_OK;
1005     if (ctxt->lastError.code == XML_ERR_OK)
1006         return;
1007     xmlResetError(&ctxt->lastError);
1008 }
1009 
1010 /**
1011  * xmlCopyError:
1012  * @from:  a source error
1013  * @to:  a target error
1014  *
1015  * Save the original error to the new place.
1016  *
1017  * Returns 0 in case of success and -1 in case of error.
1018  */
1019 int
xmlCopyError(const xmlError * from,xmlErrorPtr to)1020 xmlCopyError(const xmlError *from, xmlErrorPtr to) {
1021     const char *fmt = NULL;
1022 
1023     if ((from == NULL) || (to == NULL))
1024         return(-1);
1025 
1026     if (from->message != NULL)
1027         fmt = "%s";
1028 
1029     return(xmlSetError(to, from->ctxt, from->node,
1030                        from->domain, from->code, from->level,
1031                        from->file, from->line,
1032                        from->str1, from->str2, from->str3,
1033                        from->int1, from->int2,
1034                        fmt, from->message));
1035 }
1036 
1037 /**
1038  * xmlErrString:
1039  * @code:  an xmlParserErrors code
1040  *
1041  * Returns an error message for a code.
1042  */
1043 const char *
xmlErrString(xmlParserErrors code)1044 xmlErrString(xmlParserErrors code) {
1045     const char *errmsg;
1046 
1047     switch (code) {
1048         case XML_ERR_INVALID_HEX_CHARREF:
1049             errmsg = "CharRef: invalid hexadecimal value";
1050             break;
1051         case XML_ERR_INVALID_DEC_CHARREF:
1052             errmsg = "CharRef: invalid decimal value";
1053             break;
1054         case XML_ERR_INVALID_CHARREF:
1055             errmsg = "CharRef: invalid value";
1056             break;
1057         case XML_ERR_INTERNAL_ERROR:
1058             errmsg = "internal error";
1059             break;
1060         case XML_ERR_PEREF_AT_EOF:
1061             errmsg = "PEReference at end of document";
1062             break;
1063         case XML_ERR_PEREF_IN_PROLOG:
1064             errmsg = "PEReference in prolog";
1065             break;
1066         case XML_ERR_PEREF_IN_EPILOG:
1067             errmsg = "PEReference in epilog";
1068             break;
1069         case XML_ERR_PEREF_NO_NAME:
1070             errmsg = "PEReference: no name";
1071             break;
1072         case XML_ERR_PEREF_SEMICOL_MISSING:
1073             errmsg = "PEReference: expecting ';'";
1074             break;
1075         case XML_ERR_ENTITY_LOOP:
1076             errmsg = "Detected an entity reference loop";
1077             break;
1078         case XML_ERR_ENTITY_NOT_STARTED:
1079             errmsg = "EntityValue: \" or ' expected";
1080             break;
1081         case XML_ERR_ENTITY_PE_INTERNAL:
1082             errmsg = "PEReferences forbidden in internal subset";
1083             break;
1084         case XML_ERR_ENTITY_NOT_FINISHED:
1085             errmsg = "EntityValue: \" or ' expected";
1086             break;
1087         case XML_ERR_ATTRIBUTE_NOT_STARTED:
1088             errmsg = "AttValue: \" or ' expected";
1089             break;
1090         case XML_ERR_LT_IN_ATTRIBUTE:
1091             errmsg = "Unescaped '<' not allowed in attributes values";
1092             break;
1093         case XML_ERR_LITERAL_NOT_STARTED:
1094             errmsg = "SystemLiteral \" or ' expected";
1095             break;
1096         case XML_ERR_LITERAL_NOT_FINISHED:
1097             errmsg = "Unfinished System or Public ID \" or ' expected";
1098             break;
1099         case XML_ERR_MISPLACED_CDATA_END:
1100             errmsg = "Sequence ']]>' not allowed in content";
1101             break;
1102         case XML_ERR_URI_REQUIRED:
1103             errmsg = "SYSTEM or PUBLIC, the URI is missing";
1104             break;
1105         case XML_ERR_PUBID_REQUIRED:
1106             errmsg = "PUBLIC, the Public Identifier is missing";
1107             break;
1108         case XML_ERR_HYPHEN_IN_COMMENT:
1109             errmsg = "Comment must not contain '--' (double-hyphen)";
1110             break;
1111         case XML_ERR_PI_NOT_STARTED:
1112             errmsg = "xmlParsePI : no target name";
1113             break;
1114         case XML_ERR_RESERVED_XML_NAME:
1115             errmsg = "Invalid PI name";
1116             break;
1117         case XML_ERR_NOTATION_NOT_STARTED:
1118             errmsg = "NOTATION: Name expected here";
1119             break;
1120         case XML_ERR_NOTATION_NOT_FINISHED:
1121             errmsg = "'>' required to close NOTATION declaration";
1122             break;
1123         case XML_ERR_VALUE_REQUIRED:
1124             errmsg = "Entity value required";
1125             break;
1126         case XML_ERR_URI_FRAGMENT:
1127             errmsg = "Fragment not allowed";
1128             break;
1129         case XML_ERR_ATTLIST_NOT_STARTED:
1130             errmsg = "'(' required to start ATTLIST enumeration";
1131             break;
1132         case XML_ERR_NMTOKEN_REQUIRED:
1133             errmsg = "NmToken expected in ATTLIST enumeration";
1134             break;
1135         case XML_ERR_ATTLIST_NOT_FINISHED:
1136             errmsg = "')' required to finish ATTLIST enumeration";
1137             break;
1138         case XML_ERR_MIXED_NOT_STARTED:
1139             errmsg = "MixedContentDecl : '|' or ')*' expected";
1140             break;
1141         case XML_ERR_PCDATA_REQUIRED:
1142             errmsg = "MixedContentDecl : '#PCDATA' expected";
1143             break;
1144         case XML_ERR_ELEMCONTENT_NOT_STARTED:
1145             errmsg = "ContentDecl : Name or '(' expected";
1146             break;
1147         case XML_ERR_ELEMCONTENT_NOT_FINISHED:
1148             errmsg = "ContentDecl : ',' '|' or ')' expected";
1149             break;
1150         case XML_ERR_PEREF_IN_INT_SUBSET:
1151             errmsg =
1152                 "PEReference: forbidden within markup decl in internal subset";
1153             break;
1154         case XML_ERR_GT_REQUIRED:
1155             errmsg = "expected '>'";
1156             break;
1157         case XML_ERR_CONDSEC_INVALID:
1158             errmsg = "XML conditional section '[' expected";
1159             break;
1160         case XML_ERR_INT_SUBSET_NOT_FINISHED:
1161             errmsg = "Content error in the internal subset";
1162             break;
1163         case XML_ERR_EXT_SUBSET_NOT_FINISHED:
1164             errmsg = "Content error in the external subset";
1165             break;
1166         case XML_ERR_CONDSEC_INVALID_KEYWORD:
1167             errmsg =
1168                 "conditional section INCLUDE or IGNORE keyword expected";
1169             break;
1170         case XML_ERR_CONDSEC_NOT_FINISHED:
1171             errmsg = "XML conditional section not closed";
1172             break;
1173         case XML_ERR_XMLDECL_NOT_STARTED:
1174             errmsg = "Text declaration '<?xml' required";
1175             break;
1176         case XML_ERR_XMLDECL_NOT_FINISHED:
1177             errmsg = "parsing XML declaration: '?>' expected";
1178             break;
1179         case XML_ERR_EXT_ENTITY_STANDALONE:
1180             errmsg = "external parsed entities cannot be standalone";
1181             break;
1182         case XML_ERR_ENTITYREF_SEMICOL_MISSING:
1183             errmsg = "EntityRef: expecting ';'";
1184             break;
1185         case XML_ERR_DOCTYPE_NOT_FINISHED:
1186             errmsg = "DOCTYPE improperly terminated";
1187             break;
1188         case XML_ERR_LTSLASH_REQUIRED:
1189             errmsg = "EndTag: '</' not found";
1190             break;
1191         case XML_ERR_EQUAL_REQUIRED:
1192             errmsg = "expected '='";
1193             break;
1194         case XML_ERR_STRING_NOT_CLOSED:
1195             errmsg = "String not closed expecting \" or '";
1196             break;
1197         case XML_ERR_STRING_NOT_STARTED:
1198             errmsg = "String not started expecting ' or \"";
1199             break;
1200         case XML_ERR_ENCODING_NAME:
1201             errmsg = "Invalid XML encoding name";
1202             break;
1203         case XML_ERR_STANDALONE_VALUE:
1204             errmsg = "standalone accepts only 'yes' or 'no'";
1205             break;
1206         case XML_ERR_DOCUMENT_EMPTY:
1207             errmsg = "Document is empty";
1208             break;
1209         case XML_ERR_DOCUMENT_END:
1210             errmsg = "Extra content at the end of the document";
1211             break;
1212         case XML_ERR_NOT_WELL_BALANCED:
1213             errmsg = "chunk is not well balanced";
1214             break;
1215         case XML_ERR_EXTRA_CONTENT:
1216             errmsg = "extra content at the end of well balanced chunk";
1217             break;
1218         case XML_ERR_VERSION_MISSING:
1219             errmsg = "Malformed declaration expecting version";
1220             break;
1221         case XML_ERR_NAME_TOO_LONG:
1222             errmsg = "Name too long";
1223             break;
1224         case XML_ERR_INVALID_ENCODING:
1225             errmsg = "Invalid bytes in character encoding";
1226             break;
1227         case XML_ERR_RESOURCE_LIMIT:
1228             errmsg = "Resource limit exceeded";
1229             break;
1230         case XML_ERR_ARGUMENT:
1231             errmsg = "Invalid argument";
1232             break;
1233         case XML_ERR_SYSTEM:
1234             errmsg = "Out of system resources";
1235             break;
1236         case XML_ERR_REDECL_PREDEF_ENTITY:
1237             errmsg = "Invalid redeclaration of predefined entity";
1238             break;
1239         case XML_ERR_UNSUPPORTED_ENCODING:
1240             errmsg = "Unsupported encoding";
1241             break;
1242         case XML_ERR_INVALID_CHAR:
1243             errmsg = "Invalid character";
1244             break;
1245 
1246         case XML_IO_UNKNOWN:
1247             errmsg = "Unknown IO error"; break;
1248         case XML_IO_EACCES:
1249             errmsg = "Permission denied"; break;
1250         case XML_IO_EAGAIN:
1251             errmsg = "Resource temporarily unavailable"; break;
1252         case XML_IO_EBADF:
1253             errmsg = "Bad file descriptor"; break;
1254         case XML_IO_EBADMSG:
1255             errmsg = "Bad message"; break;
1256         case XML_IO_EBUSY:
1257             errmsg = "Resource busy"; break;
1258         case XML_IO_ECANCELED:
1259             errmsg = "Operation canceled"; break;
1260         case XML_IO_ECHILD:
1261             errmsg = "No child processes"; break;
1262         case XML_IO_EDEADLK:
1263             errmsg = "Resource deadlock avoided"; break;
1264         case XML_IO_EDOM:
1265             errmsg = "Domain error"; break;
1266         case XML_IO_EEXIST:
1267             errmsg = "File exists"; break;
1268         case XML_IO_EFAULT:
1269             errmsg = "Bad address"; break;
1270         case XML_IO_EFBIG:
1271             errmsg = "File too large"; break;
1272         case XML_IO_EINPROGRESS:
1273             errmsg = "Operation in progress"; break;
1274         case XML_IO_EINTR:
1275             errmsg = "Interrupted function call"; break;
1276         case XML_IO_EINVAL:
1277             errmsg = "Invalid argument"; break;
1278         case XML_IO_EIO:
1279             errmsg = "Input/output error"; break;
1280         case XML_IO_EISDIR:
1281             errmsg = "Is a directory"; break;
1282         case XML_IO_EMFILE:
1283             errmsg = "Too many open files"; break;
1284         case XML_IO_EMLINK:
1285             errmsg = "Too many links"; break;
1286         case XML_IO_EMSGSIZE:
1287             errmsg = "Inappropriate message buffer length"; break;
1288         case XML_IO_ENAMETOOLONG:
1289             errmsg = "Filename too long"; break;
1290         case XML_IO_ENFILE:
1291             errmsg = "Too many open files in system"; break;
1292         case XML_IO_ENODEV:
1293             errmsg = "No such device"; break;
1294         case XML_IO_ENOENT:
1295             errmsg = "No such file or directory"; break;
1296         case XML_IO_ENOEXEC:
1297             errmsg = "Exec format error"; break;
1298         case XML_IO_ENOLCK:
1299             errmsg = "No locks available"; break;
1300         case XML_IO_ENOMEM:
1301             errmsg = "Not enough space"; break;
1302         case XML_IO_ENOSPC:
1303             errmsg = "No space left on device"; break;
1304         case XML_IO_ENOSYS:
1305             errmsg = "Function not implemented"; break;
1306         case XML_IO_ENOTDIR:
1307             errmsg = "Not a directory"; break;
1308         case XML_IO_ENOTEMPTY:
1309             errmsg = "Directory not empty"; break;
1310         case XML_IO_ENOTSUP:
1311             errmsg = "Not supported"; break;
1312         case XML_IO_ENOTTY:
1313             errmsg = "Inappropriate I/O control operation"; break;
1314         case XML_IO_ENXIO:
1315             errmsg = "No such device or address"; break;
1316         case XML_IO_EPERM:
1317             errmsg = "Operation not permitted"; break;
1318         case XML_IO_EPIPE:
1319             errmsg = "Broken pipe"; break;
1320         case XML_IO_ERANGE:
1321             errmsg = "Result too large"; break;
1322         case XML_IO_EROFS:
1323             errmsg = "Read-only file system"; break;
1324         case XML_IO_ESPIPE:
1325             errmsg = "Invalid seek"; break;
1326         case XML_IO_ESRCH:
1327             errmsg = "No such process"; break;
1328         case XML_IO_ETIMEDOUT:
1329             errmsg = "Operation timed out"; break;
1330         case XML_IO_EXDEV:
1331             errmsg = "Improper link"; break;
1332         case XML_IO_NETWORK_ATTEMPT:
1333             errmsg = "Attempt to load network entity"; break;
1334         case XML_IO_ENCODER:
1335             errmsg = "encoder error"; break;
1336         case XML_IO_FLUSH:
1337             errmsg = "flush error"; break;
1338         case XML_IO_WRITE:
1339             errmsg = "write error"; break;
1340         case XML_IO_NO_INPUT:
1341             errmsg = "no input"; break;
1342         case XML_IO_BUFFER_FULL:
1343             errmsg = "buffer full"; break;
1344         case XML_IO_LOAD_ERROR:
1345             errmsg = "loading error"; break;
1346         case XML_IO_ENOTSOCK:
1347             errmsg = "not a socket"; break;
1348         case XML_IO_EISCONN:
1349             errmsg = "already connected"; break;
1350         case XML_IO_ECONNREFUSED:
1351             errmsg = "connection refused"; break;
1352         case XML_IO_ENETUNREACH:
1353             errmsg = "unreachable network"; break;
1354         case XML_IO_EADDRINUSE:
1355             errmsg = "address in use"; break;
1356         case XML_IO_EALREADY:
1357             errmsg = "already in use"; break;
1358         case XML_IO_EAFNOSUPPORT:
1359             errmsg = "unknown address family"; break;
1360         case XML_IO_UNSUPPORTED_PROTOCOL:
1361             errmsg = "unsupported protocol"; break;
1362 
1363         default:
1364             errmsg = "Unregistered error message";
1365     }
1366 
1367     return(errmsg);
1368 }
1369