1 /*
2 * xmllint.c : a small tester program for XML input.
3 *
4 * See Copyright for the status of this software.
5 *
6 * daniel@veillard.com
7 */
8
9 #include "libxml.h"
10
11 #include <string.h>
12 #include <stdarg.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <errno.h>
16 #include <limits.h>
17 #include <fcntl.h>
18
19 #ifdef _WIN32
20 #include <io.h>
21 #include <sys/timeb.h>
22 #else
23 #include <sys/time.h>
24 #include <unistd.h>
25 #endif
26
27 #if HAVE_DECL_MMAP
28 #include <sys/mman.h>
29 #include <sys/stat.h>
30 /* seems needed for Solaris */
31 #ifndef MAP_FAILED
32 #define MAP_FAILED ((void *) -1)
33 #endif
34 #endif
35
36 #include <libxml/xmlmemory.h>
37 #include <libxml/parser.h>
38 #include <libxml/parserInternals.h>
39 #include <libxml/HTMLparser.h>
40 #include <libxml/HTMLtree.h>
41 #include <libxml/tree.h>
42 #include <libxml/xpath.h>
43 #include <libxml/xpathInternals.h>
44 #include <libxml/debugXML.h>
45 #include <libxml/xmlerror.h>
46 #ifdef LIBXML_XINCLUDE_ENABLED
47 #include <libxml/xinclude.h>
48 #endif
49 #ifdef LIBXML_CATALOG_ENABLED
50 #include <libxml/catalog.h>
51 #endif
52 #include <libxml/xmlreader.h>
53 #ifdef LIBXML_SCHEMATRON_ENABLED
54 #include <libxml/schematron.h>
55 #endif
56 #ifdef LIBXML_SCHEMAS_ENABLED
57 #include <libxml/relaxng.h>
58 #include <libxml/xmlschemas.h>
59 #endif
60 #ifdef LIBXML_PATTERN_ENABLED
61 #include <libxml/pattern.h>
62 #endif
63 #ifdef LIBXML_C14N_ENABLED
64 #include <libxml/c14n.h>
65 #endif
66 #ifdef LIBXML_OUTPUT_ENABLED
67 #include <libxml/xmlsave.h>
68 #endif
69
70 #include "private/lint.h"
71
72 #ifndef STDIN_FILENO
73 #define STDIN_FILENO 0
74 #endif
75 #ifndef STDOUT_FILENO
76 #define STDOUT_FILENO 1
77 #endif
78
79 #define MAX_PATHS 64
80
81 #ifdef _WIN32
82 #define PATH_SEPARATOR ';'
83 #else
84 #define PATH_SEPARATOR ':'
85 #endif
86
87 #define HTML_BUF_SIZE 50000
88
89 /* Internal parser option */
90 #define XML_PARSE_UNZIP (1 << 24)
91
92 typedef enum {
93 XMLLINT_RETURN_OK = 0, /* No error */
94 XMLLINT_ERR_UNCLASS = 1, /* Unclassified */
95 XMLLINT_ERR_DTD = 2, /* Error in DTD */
96 XMLLINT_ERR_VALID = 3, /* Validation error */
97 XMLLINT_ERR_RDFILE = 4, /* CtxtReadFile error */
98 XMLLINT_ERR_SCHEMACOMP = 5, /* Schema compilation */
99 XMLLINT_ERR_OUT = 6, /* Error writing output */
100 XMLLINT_ERR_SCHEMAPAT = 7, /* Error in schema pattern */
101 /*XMLLINT_ERR_RDREGIS = 8,*/
102 XMLLINT_ERR_MEM = 9, /* Out of memory error */
103 XMLLINT_ERR_XPATH = 10, /* XPath evaluation error */
104 XMLLINT_ERR_XPATH_EMPTY = 11 /* XPath result is empty */
105 } xmllintReturnCode;
106
107 #ifdef _WIN32
108 typedef __time64_t xmlSeconds;
109 #else
110 typedef time_t xmlSeconds;
111 #endif
112
113 typedef struct {
114 xmlSeconds sec;
115 int usec;
116 } xmlTime;
117
118 typedef struct {
119 FILE *errStream;
120 xmlParserCtxtPtr ctxt;
121 xmlResourceLoader defaultResourceLoader;
122
123 int version;
124 int maxmem;
125 int nowrap;
126 int sax;
127 int callbacks;
128 int shell;
129 #ifdef LIBXML_DEBUG_ENABLED
130 int debugent;
131 #endif
132 int debug;
133 int copy;
134 int noout;
135 #ifdef LIBXML_OUTPUT_ENABLED
136 const char *output;
137 int format;
138 const char *encoding;
139 int compress;
140 #endif /* LIBXML_OUTPUT_ENABLED */
141 #ifdef LIBXML_VALID_ENABLED
142 int postvalid;
143 const char *dtdvalid;
144 const char *dtdvalidfpi;
145 int insert;
146 #endif
147 #ifdef LIBXML_SCHEMAS_ENABLED
148 const char *relaxng;
149 xmlRelaxNGPtr relaxngschemas;
150 const char *schema;
151 xmlSchemaPtr wxschemas;
152 #endif
153 #ifdef LIBXML_SCHEMATRON_ENABLED
154 const char *schematron;
155 xmlSchematronPtr wxschematron;
156 #endif
157 int repeat;
158 #if defined(LIBXML_HTML_ENABLED)
159 int html;
160 int xmlout;
161 #endif
162 int htmlout;
163 #ifdef LIBXML_PUSH_ENABLED
164 int push;
165 #endif /* LIBXML_PUSH_ENABLED */
166 #if HAVE_DECL_MMAP
167 int memory;
168 char *memoryData;
169 size_t memorySize;
170 #endif
171 int testIO;
172 #ifdef LIBXML_XINCLUDE_ENABLED
173 int xinclude;
174 #endif
175 xmllintReturnCode progresult;
176 int quiet;
177 int timing;
178 int generate;
179 int dropdtd;
180 #ifdef LIBXML_C14N_ENABLED
181 int canonical;
182 int canonical_11;
183 int exc_canonical;
184 #endif
185 #ifdef LIBXML_READER_ENABLED
186 int stream;
187 int walker;
188 #ifdef LIBXML_PATTERN_ENABLED
189 const char *pattern;
190 xmlPatternPtr patternc;
191 xmlStreamCtxtPtr patstream;
192 #endif
193 #endif /* LIBXML_READER_ENABLED */
194 #ifdef LIBXML_XPATH_ENABLED
195 const char *xpathquery;
196 #endif
197 #ifdef LIBXML_CATALOG_ENABLED
198 int catalogs;
199 int nocatalogs;
200 #endif
201 int options;
202 unsigned maxAmpl;
203
204 xmlChar *paths[MAX_PATHS + 1];
205 int nbpaths;
206 int load_trace;
207
208 char *htmlBuf;
209 int htmlBufLen;
210
211 xmlTime begin, end;
212 } xmllintState;
213
214 static int xmllintMaxmem;
215 static int xmllintMaxmemReached;
216 static int xmllintOom;
217
218 /************************************************************************
219 * *
220 * Entity loading control and customization. *
221 * *
222 ************************************************************************/
223
224 static void
parsePath(xmllintState * lint,const xmlChar * path)225 parsePath(xmllintState *lint, const xmlChar *path) {
226 const xmlChar *cur;
227
228 if (path == NULL)
229 return;
230 while (*path != 0) {
231 if (lint->nbpaths >= MAX_PATHS) {
232 fprintf(lint->errStream, "MAX_PATHS reached: too many paths\n");
233 lint->progresult = XMLLINT_ERR_UNCLASS;
234 return;
235 }
236 cur = path;
237 while ((*cur == ' ') || (*cur == PATH_SEPARATOR))
238 cur++;
239 path = cur;
240 while ((*cur != 0) && (*cur != ' ') && (*cur != PATH_SEPARATOR))
241 cur++;
242 if (cur != path) {
243 lint->paths[lint->nbpaths] = xmlStrndup(path, cur - path);
244 if (lint->paths[lint->nbpaths] != NULL)
245 lint->nbpaths++;
246 path = cur;
247 }
248 }
249 }
250
251 static int
xmllintResourceLoader(void * ctxt,const char * URL,const char * ID,xmlResourceType type,int flags,xmlParserInputPtr * out)252 xmllintResourceLoader(void *ctxt, const char *URL,
253 const char *ID, xmlResourceType type, int flags,
254 xmlParserInputPtr *out) {
255 xmllintState *lint = ctxt;
256 int code;
257 int i;
258 const char *lastsegment = URL;
259 const char *iter = URL;
260
261 if ((lint->nbpaths > 0) && (iter != NULL)) {
262 while (*iter != 0) {
263 if (*iter == '/')
264 lastsegment = iter + 1;
265 iter++;
266 }
267 }
268
269 if (lint->defaultResourceLoader != NULL)
270 code = lint->defaultResourceLoader(NULL, URL, ID, type, flags, out);
271 else
272 code = xmlNewInputFromUrl(URL, flags, out);
273 if (code != XML_IO_ENOENT) {
274 if ((lint->load_trace) && (code == XML_ERR_OK)) {
275 fprintf(lint->errStream, "Loaded URL=\"%s\" ID=\"%s\"\n",
276 URL, ID ? ID : "(null)");
277 }
278 return(code);
279 }
280
281 for (i = 0; i < lint->nbpaths; i++) {
282 xmlChar *newURL;
283
284 newURL = xmlStrdup((const xmlChar *) lint->paths[i]);
285 newURL = xmlStrcat(newURL, (const xmlChar *) "/");
286 newURL = xmlStrcat(newURL, (const xmlChar *) lastsegment);
287 if (newURL != NULL) {
288 if (lint->defaultResourceLoader != NULL)
289 code = lint->defaultResourceLoader(NULL, (const char *) newURL,
290 ID, type, flags, out);
291 else
292 code = xmlNewInputFromUrl((const char *) newURL, flags, out);
293 if (code != XML_IO_ENOENT) {
294 if ((lint->load_trace) && (code == XML_ERR_OK)) {
295 fprintf(lint->errStream, "Loaded URL=\"%s\" ID=\"%s\"\n",
296 newURL, ID ? ID : "(null)");
297 }
298 xmlFree(newURL);
299 return(code);
300 }
301 xmlFree(newURL);
302 }
303 }
304
305 return(XML_IO_ENOENT);
306 }
307
308 /************************************************************************
309 * *
310 * Core parsing functions *
311 * *
312 ************************************************************************/
313
314 static int
myRead(void * f,char * buf,int len)315 myRead(void *f, char *buf, int len) {
316 return(fread(buf, 1, len, (FILE *) f));
317 }
318
319 static int
myClose(void * context)320 myClose(void *context) {
321 FILE *f = (FILE *) context;
322 if (f == stdin)
323 return(0);
324 return(fclose(f));
325 }
326
327 static xmlDocPtr
parseXml(xmllintState * lint,const char * filename)328 parseXml(xmllintState *lint, const char *filename) {
329 xmlParserCtxtPtr ctxt = lint->ctxt;
330 xmlDocPtr doc;
331
332 #ifdef LIBXML_PUSH_ENABLED
333 if (lint->push) {
334 FILE *f;
335 int res;
336 char chars[4096];
337
338 if ((filename[0] == '-') && (filename[1] == 0)) {
339 f = stdin;
340 } else {
341 f = fopen(filename, "rb");
342 if (f == NULL) {
343 fprintf(lint->errStream, "Can't open %s\n", filename);
344 lint->progresult = XMLLINT_ERR_RDFILE;
345 return(NULL);
346 }
347 }
348
349 while ((res = fread(chars, 1, 4096, f)) > 0) {
350 xmlParseChunk(ctxt, chars, res, 0);
351 }
352 xmlParseChunk(ctxt, chars, 0, 1);
353
354 doc = ctxt->myDoc;
355 ctxt->myDoc = NULL;
356 if (f != stdin)
357 fclose(f);
358
359 /*
360 * The push parser leaves non-wellformed documents
361 * in ctxt->myDoc.
362 */
363 if (!ctxt->wellFormed) {
364 xmlFreeDoc(doc);
365 doc = NULL;
366 }
367
368 return(doc);
369 }
370 #endif /* LIBXML_PUSH_ENABLED */
371
372 #if HAVE_DECL_MMAP
373 if (lint->memory) {
374 xmlParserInputPtr input;
375
376 input = xmlNewInputFromMemory(filename,
377 lint->memoryData, lint->memorySize,
378 XML_INPUT_BUF_STATIC |
379 XML_INPUT_BUF_ZERO_TERMINATED);
380 if (input == NULL) {
381 lint->progresult = XMLLINT_ERR_MEM;
382 return(NULL);
383 }
384 doc = xmlCtxtParseDocument(ctxt, input);
385 return(doc);
386 }
387 #endif
388
389 if (lint->testIO) {
390 FILE *f;
391
392 if ((filename[0] == '-') && (filename[1] == 0)) {
393 f = stdin;
394 } else {
395 f = fopen(filename, "rb");
396 if (f == NULL) {
397 fprintf(lint->errStream, "Can't open %s\n", filename);
398 lint->progresult = XMLLINT_ERR_RDFILE;
399 return(NULL);
400 }
401 }
402
403 doc = xmlCtxtReadIO(ctxt, myRead, myClose, f, filename, NULL,
404 lint->options);
405 } else {
406 if (strcmp(filename, "-") == 0)
407 doc = xmlCtxtReadFd(ctxt, STDIN_FILENO, "-", NULL,
408 lint->options | XML_PARSE_UNZIP);
409 else
410 doc = xmlCtxtReadFile(ctxt, filename, NULL,
411 lint->options | XML_PARSE_UNZIP);
412 }
413
414 return(doc);
415 }
416
417 #ifdef LIBXML_HTML_ENABLED
418 static xmlDocPtr
parseHtml(xmllintState * lint,const char * filename)419 parseHtml(xmllintState *lint, const char *filename) {
420 xmlParserCtxtPtr ctxt = lint->ctxt;
421 xmlDocPtr doc;
422
423 #ifdef LIBXML_PUSH_ENABLED
424 if (lint->push) {
425 FILE *f;
426 int res;
427 char chars[4096];
428
429 if ((filename[0] == '-') && (filename[1] == 0)) {
430 f = stdin;
431 } else {
432 f = fopen(filename, "rb");
433 if (f == NULL) {
434 fprintf(lint->errStream, "Can't open %s\n", filename);
435 lint->progresult = XMLLINT_ERR_RDFILE;
436 return(NULL);
437 }
438 }
439
440 while ((res = fread(chars, 1, 4096, f)) > 0) {
441 htmlParseChunk(ctxt, chars, res, 0);
442 }
443 htmlParseChunk(ctxt, chars, 0, 1);
444 doc = ctxt->myDoc;
445 ctxt->myDoc = NULL;
446 if (f != stdin)
447 fclose(f);
448
449 return(doc);
450 }
451 #endif /* LIBXML_PUSH_ENABLED */
452
453 #if HAVE_DECL_MMAP
454 if (lint->memory) {
455 xmlParserInputPtr input;
456
457 input = xmlNewInputFromMemory(filename,
458 lint->memoryData, lint->memorySize,
459 XML_INPUT_BUF_STATIC |
460 XML_INPUT_BUF_ZERO_TERMINATED);
461 if (input == NULL) {
462 lint->progresult = XMLLINT_ERR_MEM;
463 return(NULL);
464 }
465 doc = htmlCtxtParseDocument(ctxt, input);
466 return(doc);
467 }
468 #endif
469
470 if (strcmp(filename, "-") == 0)
471 doc = htmlCtxtReadFd(ctxt, STDIN_FILENO, "-", NULL,
472 lint->options);
473 else
474 doc = htmlCtxtReadFile(ctxt, filename, NULL, lint->options);
475
476 return(doc);
477 }
478 #endif /* LIBXML_HTML_ENABLED */
479
480 /************************************************************************
481 * *
482 * Memory allocation consumption debugging *
483 * *
484 ************************************************************************/
485
486 #define XMLLINT_ABORT_ON_FAILURE 0
487
488 static void
myFreeFunc(void * mem)489 myFreeFunc(void *mem) {
490 xmlMemFree(mem);
491 }
492
493 static void *
myMallocFunc(size_t size)494 myMallocFunc(size_t size) {
495 void *ret;
496
497 if (xmlMemUsed() + size > (size_t) xmllintMaxmem) {
498 #if XMLLINT_ABORT_ON_FAILURE
499 abort();
500 #endif
501 xmllintMaxmemReached = 1;
502 xmllintOom = 1;
503 return(NULL);
504 }
505
506 ret = xmlMemMalloc(size);
507 if (ret == NULL)
508 xmllintOom = 1;
509
510 return(ret);
511 }
512
513 static void *
myReallocFunc(void * mem,size_t size)514 myReallocFunc(void *mem, size_t size) {
515 void *ret;
516 size_t oldsize = xmlMemSize(mem);
517
518 if (xmlMemUsed() + size - oldsize > (size_t) xmllintMaxmem) {
519 #if XMLLINT_ABORT_ON_FAILURE
520 abort();
521 #endif
522 xmllintMaxmemReached = 1;
523 xmllintOom = 1;
524 return(NULL);
525 }
526
527 ret = xmlMemRealloc(mem, size);
528 if (ret == NULL)
529 xmllintOom = 1;
530
531 return(ret);
532 }
533
534 static char *
myStrdupFunc(const char * str)535 myStrdupFunc(const char *str) {
536 size_t size;
537 char *ret;
538
539 if (str == NULL)
540 return(NULL);
541
542 size = strlen(str) + 1;
543 if (xmlMemUsed() + size > (size_t) xmllintMaxmem) {
544 #if XMLLINT_ABORT_ON_FAILURE
545 abort();
546 #endif
547 xmllintMaxmemReached = 1;
548 xmllintOom = 1;
549 return(NULL);
550 }
551
552 ret = xmlMemMalloc(size);
553 if (ret == NULL) {
554 xmllintOom = 1;
555 return(NULL);
556 }
557
558 memcpy(ret, str, size);
559
560 return(ret);
561 }
562
563 /************************************************************************
564 * *
565 * Internal timing routines to remove the necessity to have *
566 * unix-specific function calls. *
567 * *
568 ************************************************************************/
569
570 static void
getTime(xmlTime * time)571 getTime(xmlTime *time) {
572 #ifdef _WIN32
573 struct __timeb64 timebuffer;
574
575 _ftime64(&timebuffer);
576 time->sec = timebuffer.time;
577 time->usec = timebuffer.millitm * 1000;
578 #else /* _WIN32 */
579 struct timeval tv;
580
581 gettimeofday(&tv, NULL);
582 time->sec = tv.tv_sec;
583 time->usec = tv.tv_usec;
584 #endif /* _WIN32 */
585 }
586
587 /*
588 * startTimer: call where you want to start timing
589 */
590 static void
startTimer(xmllintState * lint)591 startTimer(xmllintState *lint)
592 {
593 getTime(&lint->begin);
594 }
595
596 /*
597 * endTimer: call where you want to stop timing and to print out a
598 * message about the timing performed; format is a printf
599 * type argument
600 */
601 static void LIBXML_ATTR_FORMAT(2,3)
endTimer(xmllintState * lint,const char * fmt,...)602 endTimer(xmllintState *lint, const char *fmt, ...)
603 {
604 xmlSeconds msec;
605 va_list ap;
606
607 getTime(&lint->end);
608 msec = lint->end.sec - lint->begin.sec;
609 msec *= 1000;
610 msec += (lint->end.usec - lint->begin.usec) / 1000;
611
612 va_start(ap, fmt);
613 vfprintf(lint->errStream, fmt, ap);
614 va_end(ap);
615
616 fprintf(lint->errStream, " took %ld ms\n", (long) msec);
617 }
618
619 /************************************************************************
620 * *
621 * HTML output *
622 * *
623 ************************************************************************/
624
625 static void
xmlHTMLEncodeSend(xmllintState * lint)626 xmlHTMLEncodeSend(xmllintState *lint) {
627 char *result;
628
629 /*
630 * xmlEncodeEntitiesReentrant assumes valid UTF-8, but the buffer might
631 * end with a truncated UTF-8 sequence. This is a hack to at least avoid
632 * an out-of-bounds read.
633 */
634 memset(&lint->htmlBuf[HTML_BUF_SIZE - 4], 0, 4);
635 result = (char *) xmlEncodeEntitiesReentrant(NULL, BAD_CAST lint->htmlBuf);
636 if (result) {
637 fprintf(lint->errStream, "%s", result);
638 xmlFree(result);
639 }
640
641 lint->htmlBufLen = 0;
642 }
643
644 static void
xmlHTMLBufCat(void * data,const char * fmt,...)645 xmlHTMLBufCat(void *data, const char *fmt, ...) {
646 xmllintState *lint = data;
647 va_list ap;
648 int res;
649
650 va_start(ap, fmt);
651 res = vsnprintf(&lint->htmlBuf[lint->htmlBufLen],
652 HTML_BUF_SIZE - lint->htmlBufLen, fmt, ap);
653 va_end(ap);
654
655 if (res > 0) {
656 if (res > HTML_BUF_SIZE - lint->htmlBufLen - 1)
657 lint->htmlBufLen = HTML_BUF_SIZE - 1;
658 else
659 lint->htmlBufLen += res;
660 }
661 }
662
663 /**
664 * xmlHTMLError:
665 * @ctx: an XML parser context
666 * @msg: the message to display/transmit
667 * @...: extra parameters for the message display
668 *
669 * Display and format an error messages, gives file, line, position and
670 * extra parameters.
671 */
672 static void
xmlHTMLError(void * vctxt,const xmlError * error)673 xmlHTMLError(void *vctxt, const xmlError *error)
674 {
675 xmlParserCtxtPtr ctxt = vctxt;
676 xmllintState *lint = ctxt->_private;
677 xmlParserInputPtr input;
678 xmlGenericErrorFunc oldError;
679 void *oldErrorCtxt;
680
681 input = ctxt->input;
682 if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
683 input = ctxt->inputTab[ctxt->inputNr - 2];
684 }
685
686 oldError = xmlGenericError;
687 oldErrorCtxt = xmlGenericErrorContext;
688 xmlSetGenericErrorFunc(lint, xmlHTMLBufCat);
689
690 fprintf(lint->errStream, "<p>");
691
692 xmlParserPrintFileInfo(input);
693 xmlHTMLEncodeSend(lint);
694
695 fprintf(lint->errStream, "<b>%s%s</b>: ",
696 (error->domain == XML_FROM_VALID) ||
697 (error->domain == XML_FROM_DTD) ? "validity " : "",
698 error->level == XML_ERR_WARNING ? "warning" : "error");
699
700 snprintf(lint->htmlBuf, HTML_BUF_SIZE, "%s", error->message);
701 xmlHTMLEncodeSend(lint);
702
703 fprintf(lint->errStream, "</p>\n");
704
705 if (input != NULL) {
706 fprintf(lint->errStream, "<pre>\n");
707
708 xmlParserPrintFileContext(input);
709 xmlHTMLEncodeSend(lint);
710
711 fprintf(lint->errStream, "</pre>");
712 }
713
714 xmlSetGenericErrorFunc(oldErrorCtxt, oldError);
715 }
716
717 /************************************************************************
718 * *
719 * SAX based tests *
720 * *
721 ************************************************************************/
722
723 /*
724 * empty SAX block
725 */
726 static const xmlSAXHandler emptySAXHandler = {
727 NULL, /* internalSubset */
728 NULL, /* isStandalone */
729 NULL, /* hasInternalSubset */
730 NULL, /* hasExternalSubset */
731 NULL, /* resolveEntity */
732 NULL, /* getEntity */
733 NULL, /* entityDecl */
734 NULL, /* notationDecl */
735 NULL, /* attributeDecl */
736 NULL, /* elementDecl */
737 NULL, /* unparsedEntityDecl */
738 NULL, /* setDocumentLocator */
739 NULL, /* startDocument */
740 NULL, /* endDocument */
741 NULL, /* startElement */
742 NULL, /* endElement */
743 NULL, /* reference */
744 NULL, /* characters */
745 NULL, /* ignorableWhitespace */
746 NULL, /* processingInstruction */
747 NULL, /* comment */
748 NULL, /* xmlParserWarning */
749 NULL, /* xmlParserError */
750 NULL, /* xmlParserError */
751 NULL, /* getParameterEntity */
752 NULL, /* cdataBlock; */
753 NULL, /* externalSubset; */
754 XML_SAX2_MAGIC,
755 NULL,
756 NULL, /* startElementNs */
757 NULL, /* endElementNs */
758 NULL /* xmlStructuredErrorFunc */
759 };
760
761 /**
762 * isStandaloneDebug:
763 * @ctxt: An XML parser context
764 *
765 * Is this document tagged standalone ?
766 *
767 * Returns 1 if true
768 */
769 static int
isStandaloneDebug(void * ctx)770 isStandaloneDebug(void *ctx)
771 {
772 xmllintState *lint = ctx;
773
774 lint->callbacks++;
775 if (lint->noout)
776 return(0);
777 fprintf(stdout, "SAX.isStandalone()\n");
778 return(0);
779 }
780
781 /**
782 * hasInternalSubsetDebug:
783 * @ctxt: An XML parser context
784 *
785 * Does this document has an internal subset
786 *
787 * Returns 1 if true
788 */
789 static int
hasInternalSubsetDebug(void * ctx)790 hasInternalSubsetDebug(void *ctx)
791 {
792 xmllintState *lint = ctx;
793
794 lint->callbacks++;
795 if (lint->noout)
796 return(0);
797 fprintf(stdout, "SAX.hasInternalSubset()\n");
798 return(0);
799 }
800
801 /**
802 * hasExternalSubsetDebug:
803 * @ctxt: An XML parser context
804 *
805 * Does this document has an external subset
806 *
807 * Returns 1 if true
808 */
809 static int
hasExternalSubsetDebug(void * ctx)810 hasExternalSubsetDebug(void *ctx)
811 {
812 xmllintState *lint = ctx;
813
814 lint->callbacks++;
815 if (lint->noout)
816 return(0);
817 fprintf(stdout, "SAX.hasExternalSubset()\n");
818 return(0);
819 }
820
821 /**
822 * internalSubsetDebug:
823 * @ctxt: An XML parser context
824 *
825 * Does this document has an internal subset
826 */
827 static void
internalSubsetDebug(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)828 internalSubsetDebug(void *ctx, const xmlChar *name,
829 const xmlChar *ExternalID, const xmlChar *SystemID)
830 {
831 xmllintState *lint = ctx;
832
833 lint->callbacks++;
834 if (lint->noout)
835 return;
836 fprintf(stdout, "SAX.internalSubset(%s,", name);
837 if (ExternalID == NULL)
838 fprintf(stdout, " ,");
839 else
840 fprintf(stdout, " %s,", ExternalID);
841 if (SystemID == NULL)
842 fprintf(stdout, " )\n");
843 else
844 fprintf(stdout, " %s)\n", SystemID);
845 }
846
847 /**
848 * externalSubsetDebug:
849 * @ctxt: An XML parser context
850 *
851 * Does this document has an external subset
852 */
853 static void
externalSubsetDebug(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)854 externalSubsetDebug(void *ctx, const xmlChar *name,
855 const xmlChar *ExternalID, const xmlChar *SystemID)
856 {
857 xmllintState *lint = ctx;
858
859 lint->callbacks++;
860 if (lint->noout)
861 return;
862 fprintf(stdout, "SAX.externalSubset(%s,", name);
863 if (ExternalID == NULL)
864 fprintf(stdout, " ,");
865 else
866 fprintf(stdout, " %s,", ExternalID);
867 if (SystemID == NULL)
868 fprintf(stdout, " )\n");
869 else
870 fprintf(stdout, " %s)\n", SystemID);
871 }
872
873 /**
874 * resolveEntityDebug:
875 * @ctxt: An XML parser context
876 * @publicId: The public ID of the entity
877 * @systemId: The system ID of the entity
878 *
879 * Special entity resolver, better left to the parser, it has
880 * more context than the application layer.
881 * The default behaviour is to NOT resolve the entities, in that case
882 * the ENTITY_REF nodes are built in the structure (and the parameter
883 * values).
884 *
885 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
886 */
887 static xmlParserInputPtr
resolveEntityDebug(void * ctx,const xmlChar * publicId,const xmlChar * systemId)888 resolveEntityDebug(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
889 {
890 xmllintState *lint = ctx;
891
892 lint->callbacks++;
893 if (lint->noout)
894 return(NULL);
895 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
896
897
898 fprintf(stdout, "SAX.resolveEntity(");
899 if (publicId != NULL)
900 fprintf(stdout, "%s", (char *)publicId);
901 else
902 fprintf(stdout, " ");
903 if (systemId != NULL)
904 fprintf(stdout, ", %s)\n", (char *)systemId);
905 else
906 fprintf(stdout, ", )\n");
907 return(NULL);
908 }
909
910 /**
911 * getEntityDebug:
912 * @ctxt: An XML parser context
913 * @name: The entity name
914 *
915 * Get an entity by name
916 *
917 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
918 */
919 static xmlEntityPtr
getEntityDebug(void * ctx,const xmlChar * name)920 getEntityDebug(void *ctx, const xmlChar *name)
921 {
922 xmllintState *lint = ctx;
923
924 lint->callbacks++;
925 if (lint->noout)
926 return(NULL);
927 fprintf(stdout, "SAX.getEntity(%s)\n", name);
928 return(NULL);
929 }
930
931 /**
932 * getParameterEntityDebug:
933 * @ctxt: An XML parser context
934 * @name: The entity name
935 *
936 * Get a parameter entity by name
937 *
938 * Returns the xmlParserInputPtr
939 */
940 static xmlEntityPtr
getParameterEntityDebug(void * ctx,const xmlChar * name)941 getParameterEntityDebug(void *ctx, const xmlChar *name)
942 {
943 xmllintState *lint = ctx;
944
945 lint->callbacks++;
946 if (lint->noout)
947 return(NULL);
948 fprintf(stdout, "SAX.getParameterEntity(%s)\n", name);
949 return(NULL);
950 }
951
952
953 /**
954 * entityDeclDebug:
955 * @ctxt: An XML parser context
956 * @name: the entity name
957 * @type: the entity type
958 * @publicId: The public ID of the entity
959 * @systemId: The system ID of the entity
960 * @content: the entity value (without processing).
961 *
962 * An entity definition has been parsed
963 */
964 static void
entityDeclDebug(void * ctx,const xmlChar * name,int type,const xmlChar * publicId,const xmlChar * systemId,xmlChar * content)965 entityDeclDebug(void *ctx, const xmlChar *name, int type,
966 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
967 {
968 xmllintState *lint = ctx;
969 const xmlChar *nullstr = BAD_CAST "(null)";
970
971 /* not all libraries handle printing null pointers nicely */
972 if (publicId == NULL)
973 publicId = nullstr;
974 if (systemId == NULL)
975 systemId = nullstr;
976 if (content == NULL)
977 content = (xmlChar *)nullstr;
978 lint->callbacks++;
979 if (lint->noout)
980 return;
981 fprintf(stdout, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
982 name, type, publicId, systemId, content);
983 }
984
985 /**
986 * attributeDeclDebug:
987 * @ctxt: An XML parser context
988 * @name: the attribute name
989 * @type: the attribute type
990 *
991 * An attribute definition has been parsed
992 */
993 static void
attributeDeclDebug(void * ctx,const xmlChar * elem,const xmlChar * name,int type,int def,const xmlChar * defaultValue,xmlEnumerationPtr tree)994 attributeDeclDebug(void *ctx, const xmlChar * elem,
995 const xmlChar * name, int type, int def,
996 const xmlChar * defaultValue, xmlEnumerationPtr tree)
997 {
998 xmllintState *lint = ctx;
999
1000 lint->callbacks++;
1001 if (lint->noout)
1002 return;
1003 if (defaultValue == NULL)
1004 fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
1005 elem, name, type, def);
1006 else
1007 fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
1008 elem, name, type, def, defaultValue);
1009 xmlFreeEnumeration(tree);
1010 }
1011
1012 /**
1013 * elementDeclDebug:
1014 * @ctxt: An XML parser context
1015 * @name: the element name
1016 * @type: the element type
1017 * @content: the element value (without processing).
1018 *
1019 * An element definition has been parsed
1020 */
1021 static void
elementDeclDebug(void * ctx,const xmlChar * name,int type,xmlElementContentPtr content ATTRIBUTE_UNUSED)1022 elementDeclDebug(void *ctx, const xmlChar *name, int type,
1023 xmlElementContentPtr content ATTRIBUTE_UNUSED)
1024 {
1025 xmllintState *lint = ctx;
1026
1027 lint->callbacks++;
1028 if (lint->noout)
1029 return;
1030 fprintf(stdout, "SAX.elementDecl(%s, %d, ...)\n",
1031 name, type);
1032 }
1033
1034 /**
1035 * notationDeclDebug:
1036 * @ctxt: An XML parser context
1037 * @name: The name of the notation
1038 * @publicId: The public ID of the entity
1039 * @systemId: The system ID of the entity
1040 *
1041 * What to do when a notation declaration has been parsed.
1042 */
1043 static void
notationDeclDebug(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId)1044 notationDeclDebug(void *ctx, const xmlChar *name,
1045 const xmlChar *publicId, const xmlChar *systemId)
1046 {
1047 xmllintState *lint = ctx;
1048
1049 lint->callbacks++;
1050 if (lint->noout)
1051 return;
1052 fprintf(stdout, "SAX.notationDecl(%s, %s, %s)\n",
1053 (char *) name, (char *) publicId, (char *) systemId);
1054 }
1055
1056 /**
1057 * unparsedEntityDeclDebug:
1058 * @ctxt: An XML parser context
1059 * @name: The name of the entity
1060 * @publicId: The public ID of the entity
1061 * @systemId: The system ID of the entity
1062 * @notationName: the name of the notation
1063 *
1064 * What to do when an unparsed entity declaration is parsed
1065 */
1066 static void
unparsedEntityDeclDebug(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId,const xmlChar * notationName)1067 unparsedEntityDeclDebug(void *ctx, const xmlChar *name,
1068 const xmlChar *publicId, const xmlChar *systemId,
1069 const xmlChar *notationName)
1070 {
1071 xmllintState *lint = ctx;
1072 const xmlChar *nullstr = BAD_CAST "(null)";
1073
1074 if (publicId == NULL)
1075 publicId = nullstr;
1076 if (systemId == NULL)
1077 systemId = nullstr;
1078 if (notationName == NULL)
1079 notationName = nullstr;
1080 lint->callbacks++;
1081 if (lint->noout)
1082 return;
1083 fprintf(stdout, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
1084 (char *) name, (char *) publicId, (char *) systemId,
1085 (char *) notationName);
1086 }
1087
1088 /**
1089 * setDocumentLocatorDebug:
1090 * @ctxt: An XML parser context
1091 * @loc: A SAX Locator
1092 *
1093 * Receive the document locator at startup, actually xmlDefaultSAXLocator
1094 * Everything is available on the context, so this is useless in our case.
1095 */
1096 static void
setDocumentLocatorDebug(void * ctx,xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)1097 setDocumentLocatorDebug(void *ctx, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
1098 {
1099 xmllintState *lint = ctx;
1100
1101 lint->callbacks++;
1102 if (lint->noout)
1103 return;
1104 fprintf(stdout, "SAX.setDocumentLocator()\n");
1105 }
1106
1107 /**
1108 * startDocumentDebug:
1109 * @ctxt: An XML parser context
1110 *
1111 * called when the document start being processed.
1112 */
1113 static void
startDocumentDebug(void * ctx)1114 startDocumentDebug(void *ctx)
1115 {
1116 xmllintState *lint = ctx;
1117
1118 lint->callbacks++;
1119 if (lint->noout)
1120 return;
1121 fprintf(stdout, "SAX.startDocument()\n");
1122 }
1123
1124 /**
1125 * endDocumentDebug:
1126 * @ctxt: An XML parser context
1127 *
1128 * called when the document end has been detected.
1129 */
1130 static void
endDocumentDebug(void * ctx)1131 endDocumentDebug(void *ctx)
1132 {
1133 xmllintState *lint = ctx;
1134
1135 lint->callbacks++;
1136 if (lint->noout)
1137 return;
1138 fprintf(stdout, "SAX.endDocument()\n");
1139 }
1140
1141 #ifdef LIBXML_SAX1_ENABLED
1142 /**
1143 * startElementDebug:
1144 * @ctxt: An XML parser context
1145 * @name: The element name
1146 *
1147 * called when an opening tag has been processed.
1148 */
1149 static void
startElementDebug(void * ctx,const xmlChar * name,const xmlChar ** atts)1150 startElementDebug(void *ctx, const xmlChar *name, const xmlChar **atts)
1151 {
1152 xmllintState *lint = ctx;
1153 int i;
1154
1155 lint->callbacks++;
1156 if (lint->noout)
1157 return;
1158 fprintf(stdout, "SAX.startElement(%s", (char *) name);
1159 if (atts != NULL) {
1160 for (i = 0;(atts[i] != NULL);i++) {
1161 fprintf(stdout, ", %s='", atts[i++]);
1162 if (atts[i] != NULL)
1163 fprintf(stdout, "%s'", atts[i]);
1164 }
1165 }
1166 fprintf(stdout, ")\n");
1167 }
1168
1169 /**
1170 * endElementDebug:
1171 * @ctxt: An XML parser context
1172 * @name: The element name
1173 *
1174 * called when the end of an element has been detected.
1175 */
1176 static void
endElementDebug(void * ctx,const xmlChar * name)1177 endElementDebug(void *ctx, const xmlChar *name)
1178 {
1179 xmllintState *lint = ctx;
1180
1181 lint->callbacks++;
1182 if (lint->noout)
1183 return;
1184 fprintf(stdout, "SAX.endElement(%s)\n", (char *) name);
1185 }
1186 #endif /* LIBXML_SAX1_ENABLED */
1187
1188 /**
1189 * charactersDebug:
1190 * @ctxt: An XML parser context
1191 * @ch: a xmlChar string
1192 * @len: the number of xmlChar
1193 *
1194 * receiving some chars from the parser.
1195 * Question: how much at a time ???
1196 */
1197 static void
charactersDebug(void * ctx,const xmlChar * ch,int len)1198 charactersDebug(void *ctx, const xmlChar *ch, int len)
1199 {
1200 xmllintState *lint = ctx;
1201 char out[40];
1202 int i;
1203
1204 lint->callbacks++;
1205 if (lint->noout)
1206 return;
1207 for (i = 0;(i<len) && (i < 30);i++)
1208 out[i] = (char) ch[i];
1209 out[i] = 0;
1210
1211 fprintf(stdout, "SAX.characters(%s, %d)\n", out, len);
1212 }
1213
1214 /**
1215 * referenceDebug:
1216 * @ctxt: An XML parser context
1217 * @name: The entity name
1218 *
1219 * called when an entity reference is detected.
1220 */
1221 static void
referenceDebug(void * ctx,const xmlChar * name)1222 referenceDebug(void *ctx, const xmlChar *name)
1223 {
1224 xmllintState *lint = ctx;
1225
1226 lint->callbacks++;
1227 if (lint->noout)
1228 return;
1229 fprintf(stdout, "SAX.reference(%s)\n", name);
1230 }
1231
1232 /**
1233 * ignorableWhitespaceDebug:
1234 * @ctxt: An XML parser context
1235 * @ch: a xmlChar string
1236 * @start: the first char in the string
1237 * @len: the number of xmlChar
1238 *
1239 * receiving some ignorable whitespaces from the parser.
1240 * Question: how much at a time ???
1241 */
1242 static void
ignorableWhitespaceDebug(void * ctx,const xmlChar * ch,int len)1243 ignorableWhitespaceDebug(void *ctx, const xmlChar *ch, int len)
1244 {
1245 xmllintState *lint = ctx;
1246 char out[40];
1247 int i;
1248
1249 lint->callbacks++;
1250 if (lint->noout)
1251 return;
1252 for (i = 0;(i<len) && (i < 30);i++)
1253 out[i] = ch[i];
1254 out[i] = 0;
1255 fprintf(stdout, "SAX.ignorableWhitespace(%s, %d)\n", out, len);
1256 }
1257
1258 /**
1259 * processingInstructionDebug:
1260 * @ctxt: An XML parser context
1261 * @target: the target name
1262 * @data: the PI data's
1263 * @len: the number of xmlChar
1264 *
1265 * A processing instruction has been parsed.
1266 */
1267 static void
processingInstructionDebug(void * ctx,const xmlChar * target,const xmlChar * data)1268 processingInstructionDebug(void *ctx, const xmlChar *target,
1269 const xmlChar *data)
1270 {
1271 xmllintState *lint = ctx;
1272
1273 lint->callbacks++;
1274 if (lint->noout)
1275 return;
1276 if (data != NULL)
1277 fprintf(stdout, "SAX.processingInstruction(%s, %s)\n",
1278 (char *) target, (char *) data);
1279 else
1280 fprintf(stdout, "SAX.processingInstruction(%s, NULL)\n",
1281 (char *) target);
1282 }
1283
1284 /**
1285 * cdataBlockDebug:
1286 * @ctx: the user data (XML parser context)
1287 * @value: The pcdata content
1288 * @len: the block length
1289 *
1290 * called when a pcdata block has been parsed
1291 */
1292 static void
cdataBlockDebug(void * ctx,const xmlChar * value,int len)1293 cdataBlockDebug(void *ctx, const xmlChar *value, int len)
1294 {
1295 xmllintState *lint = ctx;
1296
1297 lint->callbacks++;
1298 if (lint->noout)
1299 return;
1300 fprintf(stdout, "SAX.pcdata(%.20s, %d)\n",
1301 (char *) value, len);
1302 }
1303
1304 /**
1305 * commentDebug:
1306 * @ctxt: An XML parser context
1307 * @value: the comment content
1308 *
1309 * A comment has been parsed.
1310 */
1311 static void
commentDebug(void * ctx,const xmlChar * value)1312 commentDebug(void *ctx, const xmlChar *value)
1313 {
1314 xmllintState *lint = ctx;
1315
1316 lint->callbacks++;
1317 if (lint->noout)
1318 return;
1319 fprintf(stdout, "SAX.comment(%s)\n", value);
1320 }
1321
1322 /**
1323 * warningDebug:
1324 * @ctxt: An XML parser context
1325 * @msg: the message to display/transmit
1326 * @...: extra parameters for the message display
1327 *
1328 * Display and format a warning messages, gives file, line, position and
1329 * extra parameters.
1330 */
1331 static void LIBXML_ATTR_FORMAT(2,3)
warningDebug(void * ctx,const char * msg,...)1332 warningDebug(void *ctx, const char *msg, ...)
1333 {
1334 xmllintState *lint = ctx;
1335 va_list args;
1336
1337 lint->callbacks++;
1338 if (lint->noout)
1339 return;
1340 va_start(args, msg);
1341 fprintf(stdout, "SAX.warning: ");
1342 vfprintf(stdout, msg, args);
1343 va_end(args);
1344 }
1345
1346 /**
1347 * errorDebug:
1348 * @ctxt: An XML parser context
1349 * @msg: the message to display/transmit
1350 * @...: extra parameters for the message display
1351 *
1352 * Display and format a error messages, gives file, line, position and
1353 * extra parameters.
1354 */
1355 static void LIBXML_ATTR_FORMAT(2,3)
errorDebug(void * ctx,const char * msg,...)1356 errorDebug(void *ctx, const char *msg, ...)
1357 {
1358 xmllintState *lint = ctx;
1359 va_list args;
1360
1361 lint->callbacks++;
1362 if (lint->noout)
1363 return;
1364 va_start(args, msg);
1365 fprintf(stdout, "SAX.error: ");
1366 vfprintf(stdout, msg, args);
1367 va_end(args);
1368 }
1369
1370 /**
1371 * fatalErrorDebug:
1372 * @ctxt: An XML parser context
1373 * @msg: the message to display/transmit
1374 * @...: extra parameters for the message display
1375 *
1376 * Display and format a fatalError messages, gives file, line, position and
1377 * extra parameters.
1378 */
1379 static void LIBXML_ATTR_FORMAT(2,3)
fatalErrorDebug(void * ctx,const char * msg,...)1380 fatalErrorDebug(void *ctx, const char *msg, ...)
1381 {
1382 xmllintState *lint = ctx;
1383 va_list args;
1384
1385 lint->callbacks++;
1386 if (lint->noout)
1387 return;
1388 va_start(args, msg);
1389 fprintf(stdout, "SAX.fatalError: ");
1390 vfprintf(stdout, msg, args);
1391 va_end(args);
1392 }
1393
1394 #ifdef LIBXML_SAX1_ENABLED
1395 static const xmlSAXHandler debugSAXHandler = {
1396 internalSubsetDebug,
1397 isStandaloneDebug,
1398 hasInternalSubsetDebug,
1399 hasExternalSubsetDebug,
1400 resolveEntityDebug,
1401 getEntityDebug,
1402 entityDeclDebug,
1403 notationDeclDebug,
1404 attributeDeclDebug,
1405 elementDeclDebug,
1406 unparsedEntityDeclDebug,
1407 setDocumentLocatorDebug,
1408 startDocumentDebug,
1409 endDocumentDebug,
1410 startElementDebug,
1411 endElementDebug,
1412 referenceDebug,
1413 charactersDebug,
1414 ignorableWhitespaceDebug,
1415 processingInstructionDebug,
1416 commentDebug,
1417 warningDebug,
1418 errorDebug,
1419 fatalErrorDebug,
1420 getParameterEntityDebug,
1421 cdataBlockDebug,
1422 externalSubsetDebug,
1423 1,
1424 NULL,
1425 NULL,
1426 NULL,
1427 NULL
1428 };
1429 #endif
1430
1431 /*
1432 * SAX2 specific callbacks
1433 */
1434 /**
1435 * startElementNsDebug:
1436 * @ctxt: An XML parser context
1437 * @name: The element name
1438 *
1439 * called when an opening tag has been processed.
1440 */
1441 static void
startElementNsDebug(void * ctx,const xmlChar * localname,const xmlChar * prefix,const xmlChar * URI,int nb_namespaces,const xmlChar ** namespaces,int nb_attributes,int nb_defaulted,const xmlChar ** attributes)1442 startElementNsDebug(void *ctx,
1443 const xmlChar *localname,
1444 const xmlChar *prefix,
1445 const xmlChar *URI,
1446 int nb_namespaces,
1447 const xmlChar **namespaces,
1448 int nb_attributes,
1449 int nb_defaulted,
1450 const xmlChar **attributes)
1451 {
1452 xmllintState *lint = ctx;
1453 int i;
1454
1455 lint->callbacks++;
1456 if (lint->noout)
1457 return;
1458 fprintf(stdout, "SAX.startElementNs(%s", (char *) localname);
1459 if (prefix == NULL)
1460 fprintf(stdout, ", NULL");
1461 else
1462 fprintf(stdout, ", %s", (char *) prefix);
1463 if (URI == NULL)
1464 fprintf(stdout, ", NULL");
1465 else
1466 fprintf(stdout, ", '%s'", (char *) URI);
1467 fprintf(stdout, ", %d", nb_namespaces);
1468
1469 if (namespaces != NULL) {
1470 for (i = 0;i < nb_namespaces * 2;i++) {
1471 fprintf(stdout, ", xmlns");
1472 if (namespaces[i] != NULL)
1473 fprintf(stdout, ":%s", namespaces[i]);
1474 i++;
1475 fprintf(stdout, "='%s'", namespaces[i]);
1476 }
1477 }
1478 fprintf(stdout, ", %d, %d", nb_attributes, nb_defaulted);
1479 if (attributes != NULL) {
1480 for (i = 0;i < nb_attributes * 5;i += 5) {
1481 if (attributes[i + 1] != NULL)
1482 fprintf(stdout, ", %s:%s='", attributes[i + 1], attributes[i]);
1483 else
1484 fprintf(stdout, ", %s='", attributes[i]);
1485 fprintf(stdout, "%.4s...', %d", attributes[i + 3],
1486 (int)(attributes[i + 4] - attributes[i + 3]));
1487 }
1488 }
1489 fprintf(stdout, ")\n");
1490 }
1491
1492 /**
1493 * endElementDebug:
1494 * @ctxt: An XML parser context
1495 * @name: The element name
1496 *
1497 * called when the end of an element has been detected.
1498 */
1499 static void
endElementNsDebug(void * ctx,const xmlChar * localname,const xmlChar * prefix,const xmlChar * URI)1500 endElementNsDebug(void *ctx,
1501 const xmlChar *localname,
1502 const xmlChar *prefix,
1503 const xmlChar *URI)
1504 {
1505 xmllintState *lint = ctx;
1506
1507 lint->callbacks++;
1508 if (lint->noout)
1509 return;
1510 fprintf(stdout, "SAX.endElementNs(%s", (char *) localname);
1511 if (prefix == NULL)
1512 fprintf(stdout, ", NULL");
1513 else
1514 fprintf(stdout, ", %s", (char *) prefix);
1515 if (URI == NULL)
1516 fprintf(stdout, ", NULL)\n");
1517 else
1518 fprintf(stdout, ", '%s')\n", (char *) URI);
1519 }
1520
1521 static const xmlSAXHandler debugSAX2Handler = {
1522 internalSubsetDebug,
1523 isStandaloneDebug,
1524 hasInternalSubsetDebug,
1525 hasExternalSubsetDebug,
1526 resolveEntityDebug,
1527 getEntityDebug,
1528 entityDeclDebug,
1529 notationDeclDebug,
1530 attributeDeclDebug,
1531 elementDeclDebug,
1532 unparsedEntityDeclDebug,
1533 setDocumentLocatorDebug,
1534 startDocumentDebug,
1535 endDocumentDebug,
1536 NULL,
1537 NULL,
1538 referenceDebug,
1539 charactersDebug,
1540 ignorableWhitespaceDebug,
1541 processingInstructionDebug,
1542 commentDebug,
1543 warningDebug,
1544 errorDebug,
1545 fatalErrorDebug,
1546 getParameterEntityDebug,
1547 cdataBlockDebug,
1548 externalSubsetDebug,
1549 XML_SAX2_MAGIC,
1550 NULL,
1551 startElementNsDebug,
1552 endElementNsDebug,
1553 NULL
1554 };
1555
1556 static void
testSAX(xmllintState * lint,const char * filename)1557 testSAX(xmllintState *lint, const char *filename) {
1558 lint->callbacks = 0;
1559
1560 #ifdef LIBXML_SCHEMAS_ENABLED
1561 if (lint->wxschemas != NULL) {
1562 int ret;
1563 xmlSchemaValidCtxtPtr vctxt;
1564 xmlParserInputBufferPtr buf;
1565
1566 if (strcmp(filename, "-") == 0)
1567 buf = xmlParserInputBufferCreateFd(STDIN_FILENO,
1568 XML_CHAR_ENCODING_NONE);
1569 else
1570 buf = xmlParserInputBufferCreateFilename(filename,
1571 XML_CHAR_ENCODING_NONE);
1572 if (buf == NULL)
1573 return;
1574
1575 vctxt = xmlSchemaNewValidCtxt(lint->wxschemas);
1576 if (vctxt == NULL) {
1577 lint->progresult = XMLLINT_ERR_MEM;
1578 xmlFreeParserInputBuffer(buf);
1579 return;
1580 }
1581 xmlSchemaValidateSetFilename(vctxt, filename);
1582
1583 ret = xmlSchemaValidateStream(vctxt, buf, 0, lint->ctxt->sax, lint);
1584 if (lint->repeat == 1) {
1585 if (ret == 0) {
1586 if (!lint->quiet) {
1587 fprintf(lint->errStream, "%s validates\n", filename);
1588 }
1589 } else if (ret > 0) {
1590 fprintf(lint->errStream, "%s fails to validate\n", filename);
1591 lint->progresult = XMLLINT_ERR_VALID;
1592 } else {
1593 fprintf(lint->errStream, "%s validation generated an internal error\n",
1594 filename);
1595 lint->progresult = XMLLINT_ERR_VALID;
1596 }
1597 }
1598 xmlSchemaFreeValidCtxt(vctxt);
1599 } else
1600 #endif
1601 #ifdef LIBXML_HTML_ENABLED
1602 if (lint->html) {
1603 parseHtml(lint, filename);
1604 } else
1605 #endif
1606 {
1607 parseXml(lint, filename);
1608 }
1609 }
1610
1611 /************************************************************************
1612 * *
1613 * Stream Test processing *
1614 * *
1615 ************************************************************************/
1616 #ifdef LIBXML_READER_ENABLED
processNode(xmllintState * lint,xmlTextReaderPtr reader)1617 static void processNode(xmllintState *lint, xmlTextReaderPtr reader) {
1618 const xmlChar *name, *value;
1619 int type, empty;
1620
1621 type = xmlTextReaderNodeType(reader);
1622 empty = xmlTextReaderIsEmptyElement(reader);
1623
1624 if (lint->debug) {
1625 name = xmlTextReaderConstName(reader);
1626 if (name == NULL)
1627 name = BAD_CAST "--";
1628
1629 value = xmlTextReaderConstValue(reader);
1630
1631
1632 printf("%d %d %s %d %d",
1633 xmlTextReaderDepth(reader),
1634 type,
1635 name,
1636 empty,
1637 xmlTextReaderHasValue(reader));
1638 if (value == NULL)
1639 printf("\n");
1640 else {
1641 printf(" %s\n", value);
1642 }
1643 }
1644 #ifdef LIBXML_PATTERN_ENABLED
1645 if (lint->patternc) {
1646 xmlChar *path = NULL;
1647 int match = -1;
1648
1649 if (type == XML_READER_TYPE_ELEMENT) {
1650 /* do the check only on element start */
1651 match = xmlPatternMatch(lint->patternc,
1652 xmlTextReaderCurrentNode(reader));
1653
1654 if (match) {
1655 path = xmlGetNodePath(xmlTextReaderCurrentNode(reader));
1656 printf("Node %s matches pattern %s\n", path, lint->pattern);
1657 }
1658 }
1659 if (lint->patstream != NULL) {
1660 int ret;
1661
1662 if (type == XML_READER_TYPE_ELEMENT) {
1663 ret = xmlStreamPush(lint->patstream,
1664 xmlTextReaderConstLocalName(reader),
1665 xmlTextReaderConstNamespaceUri(reader));
1666 if (ret < 0) {
1667 fprintf(lint->errStream, "xmlStreamPush() failure\n");
1668 xmlFreeStreamCtxt(lint->patstream);
1669 lint->patstream = NULL;
1670 } else if (ret != match) {
1671 if (path == NULL) {
1672 path = xmlGetNodePath(
1673 xmlTextReaderCurrentNode(reader));
1674 }
1675 fprintf(lint->errStream,
1676 "xmlPatternMatch and xmlStreamPush disagree\n");
1677 if (path != NULL)
1678 fprintf(lint->errStream, " pattern %s node %s\n",
1679 lint->pattern, path);
1680 else
1681 fprintf(lint->errStream, " pattern %s node %s\n",
1682 lint->pattern, xmlTextReaderConstName(reader));
1683 }
1684
1685 }
1686 if ((type == XML_READER_TYPE_END_ELEMENT) ||
1687 ((type == XML_READER_TYPE_ELEMENT) && (empty))) {
1688 ret = xmlStreamPop(lint->patstream);
1689 if (ret < 0) {
1690 fprintf(lint->errStream, "xmlStreamPop() failure\n");
1691 xmlFreeStreamCtxt(lint->patstream);
1692 lint->patstream = NULL;
1693 }
1694 }
1695 }
1696 if (path != NULL)
1697 xmlFree(path);
1698 }
1699 #endif
1700 }
1701
streamFile(xmllintState * lint,const char * filename)1702 static void streamFile(xmllintState *lint, const char *filename) {
1703 xmlParserInputBufferPtr input = NULL;
1704 FILE *errStream = lint->errStream;
1705 xmlTextReaderPtr reader;
1706 int ret;
1707
1708 #if HAVE_DECL_MMAP
1709 if (lint->memory) {
1710 reader = xmlReaderForMemory(lint->memoryData, lint->memorySize,
1711 filename, NULL, lint->options);
1712 } else
1713 #endif
1714 {
1715 if (strcmp(filename, "-") == 0) {
1716 reader = xmlReaderForFd(STDIN_FILENO, "-", NULL, lint->options);
1717 }
1718 else {
1719 /*
1720 * There's still no easy way to get a reader for a file with
1721 * adequate error repoting.
1722 */
1723
1724 xmlResetLastError();
1725 input = xmlParserInputBufferCreateFilename(filename,
1726 XML_CHAR_ENCODING_NONE);
1727 if (input == NULL) {
1728 const xmlError *error = xmlGetLastError();
1729
1730 if ((error != NULL) && (error->code == XML_ERR_NO_MEMORY)) {
1731 lint->progresult = XMLLINT_ERR_MEM;
1732 } else {
1733 fprintf(errStream, "Unable to open %s\n", filename);
1734 lint->progresult = XMLLINT_ERR_RDFILE;
1735 }
1736 return;
1737 }
1738
1739 reader = xmlNewTextReader(input, filename);
1740 if (reader == NULL) {
1741 lint->progresult = XMLLINT_ERR_MEM;
1742 xmlFreeParserInputBuffer(input);
1743 return;
1744 }
1745 if (xmlTextReaderSetup(reader, NULL, NULL, NULL,
1746 lint->options) < 0) {
1747 lint->progresult = XMLLINT_ERR_MEM;
1748 xmlFreeParserInputBuffer(input);
1749 return;
1750 }
1751 }
1752 }
1753 if (reader == NULL) {
1754 lint->progresult = XMLLINT_ERR_MEM;
1755 return;
1756 }
1757
1758 #ifdef LIBXML_PATTERN_ENABLED
1759 if (lint->patternc != NULL) {
1760 lint->patstream = xmlPatternGetStreamCtxt(lint->patternc);
1761 if (lint->patstream != NULL) {
1762 ret = xmlStreamPush(lint->patstream, NULL, NULL);
1763 if (ret < 0) {
1764 fprintf(errStream, "xmlStreamPush() failure\n");
1765 xmlFreeStreamCtxt(lint->patstream);
1766 lint->patstream = NULL;
1767 }
1768 }
1769 }
1770 #endif
1771
1772
1773 xmlTextReaderSetResourceLoader(reader, xmllintResourceLoader, lint);
1774 if (lint->maxAmpl > 0)
1775 xmlTextReaderSetMaxAmplification(reader, lint->maxAmpl);
1776
1777 #ifdef LIBXML_SCHEMAS_ENABLED
1778 if (lint->relaxng != NULL) {
1779 if ((lint->timing) && (lint->repeat == 1)) {
1780 startTimer(lint);
1781 }
1782 ret = xmlTextReaderRelaxNGValidate(reader, lint->relaxng);
1783 if (ret < 0) {
1784 fprintf(errStream, "Relax-NG schema %s failed to compile\n",
1785 lint->relaxng);
1786 lint->progresult = XMLLINT_ERR_SCHEMACOMP;
1787 lint->relaxng = NULL;
1788 }
1789 if ((lint->timing) && (lint->repeat == 1)) {
1790 endTimer(lint, "Compiling the schemas");
1791 }
1792 }
1793 if (lint->schema != NULL) {
1794 if ((lint->timing) && (lint->repeat == 1)) {
1795 startTimer(lint);
1796 }
1797 ret = xmlTextReaderSchemaValidate(reader, lint->schema);
1798 if (ret < 0) {
1799 fprintf(errStream, "XSD schema %s failed to compile\n",
1800 lint->schema);
1801 lint->progresult = XMLLINT_ERR_SCHEMACOMP;
1802 lint->schema = NULL;
1803 }
1804 if ((lint->timing) && (lint->repeat == 1)) {
1805 endTimer(lint, "Compiling the schemas");
1806 }
1807 }
1808 #endif
1809
1810 /*
1811 * Process all nodes in sequence
1812 */
1813 if ((lint->timing) && (lint->repeat == 1)) {
1814 startTimer(lint);
1815 }
1816 ret = xmlTextReaderRead(reader);
1817 while (ret == 1) {
1818 if ((lint->debug)
1819 #ifdef LIBXML_PATTERN_ENABLED
1820 || (lint->patternc)
1821 #endif
1822 )
1823 processNode(lint, reader);
1824 ret = xmlTextReaderRead(reader);
1825 }
1826 if ((lint->timing) && (lint->repeat == 1)) {
1827 #ifdef LIBXML_SCHEMAS_ENABLED
1828 if (lint->relaxng != NULL)
1829 endTimer(lint, "Parsing and validating");
1830 else
1831 #endif
1832 #ifdef LIBXML_VALID_ENABLED
1833 if (lint->options & XML_PARSE_DTDVALID)
1834 endTimer(lint, "Parsing and validating");
1835 else
1836 #endif
1837 endTimer(lint, "Parsing");
1838 }
1839
1840 #ifdef LIBXML_VALID_ENABLED
1841 if (lint->options & XML_PARSE_DTDVALID) {
1842 if (xmlTextReaderIsValid(reader) != 1) {
1843 fprintf(errStream,
1844 "Document %s does not validate\n", filename);
1845 lint->progresult = XMLLINT_ERR_VALID;
1846 }
1847 }
1848 #endif /* LIBXML_VALID_ENABLED */
1849 #ifdef LIBXML_SCHEMAS_ENABLED
1850 if ((lint->relaxng != NULL) || (lint->schema != NULL)) {
1851 if (xmlTextReaderIsValid(reader) != 1) {
1852 fprintf(errStream, "%s fails to validate\n", filename);
1853 lint->progresult = XMLLINT_ERR_VALID;
1854 } else {
1855 if (!lint->quiet) {
1856 fprintf(errStream, "%s validates\n", filename);
1857 }
1858 }
1859 }
1860 #endif
1861 /*
1862 * Done, cleanup and status
1863 */
1864 xmlFreeTextReader(reader);
1865 xmlFreeParserInputBuffer(input);
1866 if (ret != 0) {
1867 fprintf(errStream, "%s : failed to parse\n", filename);
1868 lint->progresult = XMLLINT_ERR_UNCLASS;
1869 }
1870 #ifdef LIBXML_PATTERN_ENABLED
1871 if (lint->patstream != NULL) {
1872 xmlFreeStreamCtxt(lint->patstream);
1873 lint->patstream = NULL;
1874 }
1875 #endif
1876 }
1877
walkDoc(xmllintState * lint,xmlDocPtr doc)1878 static void walkDoc(xmllintState *lint, xmlDocPtr doc) {
1879 FILE *errStream = lint->errStream;
1880 xmlTextReaderPtr reader;
1881 int ret;
1882
1883 #ifdef LIBXML_PATTERN_ENABLED
1884 if (lint->pattern != NULL) {
1885 xmlNodePtr root;
1886 const xmlChar *namespaces[22];
1887 int i;
1888 xmlNsPtr ns;
1889
1890 root = xmlDocGetRootElement(doc);
1891 if (root == NULL ) {
1892 fprintf(errStream,
1893 "Document does not have a root element");
1894 lint->progresult = XMLLINT_ERR_UNCLASS;
1895 return;
1896 }
1897 for (ns = root->nsDef, i = 0;ns != NULL && i < 20;ns=ns->next) {
1898 namespaces[i++] = ns->href;
1899 namespaces[i++] = ns->prefix;
1900 }
1901 namespaces[i++] = NULL;
1902 namespaces[i] = NULL;
1903
1904 ret = xmlPatternCompileSafe((const xmlChar *) lint->pattern, doc->dict,
1905 0, &namespaces[0], &lint->patternc);
1906 if (lint->patternc == NULL) {
1907 if (ret < 0) {
1908 lint->progresult = XMLLINT_ERR_MEM;
1909 } else {
1910 fprintf(errStream, "Pattern %s failed to compile\n",
1911 lint->pattern);
1912 lint->progresult = XMLLINT_ERR_SCHEMAPAT;
1913 }
1914 goto error;
1915 }
1916
1917 lint->patstream = xmlPatternGetStreamCtxt(lint->patternc);
1918 if (lint->patstream == NULL) {
1919 lint->progresult = XMLLINT_ERR_MEM;
1920 goto error;
1921 }
1922
1923 ret = xmlStreamPush(lint->patstream, NULL, NULL);
1924 if (ret < 0) {
1925 fprintf(errStream, "xmlStreamPush() failure\n");
1926 lint->progresult = XMLLINT_ERR_MEM;
1927 goto error;
1928 }
1929 }
1930 #endif /* LIBXML_PATTERN_ENABLED */
1931 reader = xmlReaderWalker(doc);
1932 if (reader != NULL) {
1933 if ((lint->timing) && (lint->repeat == 1)) {
1934 startTimer(lint);
1935 }
1936 ret = xmlTextReaderRead(reader);
1937 while (ret == 1) {
1938 if ((lint->debug)
1939 #ifdef LIBXML_PATTERN_ENABLED
1940 || (lint->patternc)
1941 #endif
1942 )
1943 processNode(lint, reader);
1944 ret = xmlTextReaderRead(reader);
1945 }
1946 if ((lint->timing) && (lint->repeat == 1)) {
1947 endTimer(lint, "walking through the doc");
1948 }
1949 xmlFreeTextReader(reader);
1950 if (ret != 0) {
1951 fprintf(errStream, "failed to walk through the doc\n");
1952 lint->progresult = XMLLINT_ERR_UNCLASS;
1953 }
1954 } else {
1955 fprintf(errStream, "Failed to create a reader from the document\n");
1956 lint->progresult = XMLLINT_ERR_UNCLASS;
1957 }
1958
1959 #ifdef LIBXML_PATTERN_ENABLED
1960 error:
1961 if (lint->patternc != NULL) {
1962 xmlFreePattern(lint->patternc);
1963 lint->patternc = NULL;
1964 }
1965 if (lint->patstream != NULL) {
1966 xmlFreeStreamCtxt(lint->patstream);
1967 lint->patstream = NULL;
1968 }
1969 #endif
1970 }
1971 #endif /* LIBXML_READER_ENABLED */
1972
1973 #ifdef LIBXML_XPATH_ENABLED
1974 /************************************************************************
1975 * *
1976 * XPath Query *
1977 * *
1978 ************************************************************************/
1979
1980 static void
doXPathDump(xmllintState * lint,xmlXPathObjectPtr cur)1981 doXPathDump(xmllintState *lint, xmlXPathObjectPtr cur) {
1982 switch(cur->type) {
1983 case XPATH_NODESET: {
1984 #ifdef LIBXML_OUTPUT_ENABLED
1985 xmlOutputBufferPtr buf;
1986 xmlNodePtr node;
1987 int i;
1988
1989 if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr <= 0)) {
1990 lint->progresult = XMLLINT_ERR_XPATH_EMPTY;
1991 if (!lint->quiet) {
1992 fprintf(lint->errStream, "XPath set is empty\n");
1993 }
1994 break;
1995 }
1996 buf = xmlOutputBufferCreateFile(stdout, NULL);
1997 if (buf == NULL) {
1998 lint->progresult = XMLLINT_ERR_MEM;
1999 return;
2000 }
2001 for (i = 0;i < cur->nodesetval->nodeNr;i++) {
2002 node = cur->nodesetval->nodeTab[i];
2003 xmlNodeDumpOutput(buf, NULL, node, 0, 0, NULL);
2004 xmlOutputBufferWrite(buf, 1, "\n");
2005 }
2006 xmlOutputBufferClose(buf);
2007 #else
2008 printf("xpath returned %d nodes\n", cur->nodesetval->nodeNr);
2009 #endif
2010 break;
2011 }
2012 case XPATH_BOOLEAN:
2013 if (cur->boolval) printf("true\n");
2014 else printf("false\n");
2015 break;
2016 case XPATH_NUMBER:
2017 switch (xmlXPathIsInf(cur->floatval)) {
2018 case 1:
2019 printf("Infinity\n");
2020 break;
2021 case -1:
2022 printf("-Infinity\n");
2023 break;
2024 default:
2025 if (xmlXPathIsNaN(cur->floatval)) {
2026 printf("NaN\n");
2027 } else {
2028 printf("%0g\n", cur->floatval);
2029 }
2030 }
2031 break;
2032 case XPATH_STRING:
2033 printf("%s\n", (const char *) cur->stringval);
2034 break;
2035 case XPATH_UNDEFINED:
2036 fprintf(lint->errStream, "XPath Object is uninitialized\n");
2037 lint->progresult = XMLLINT_ERR_XPATH;
2038 break;
2039 default:
2040 fprintf(lint->errStream, "XPath object of unexpected type\n");
2041 lint->progresult = XMLLINT_ERR_XPATH;
2042 break;
2043 }
2044 }
2045
2046 static void
doXPathQuery(xmllintState * lint,xmlDocPtr doc,const char * query)2047 doXPathQuery(xmllintState *lint, xmlDocPtr doc, const char *query) {
2048 xmlXPathContextPtr ctxt = NULL;
2049 xmlXPathCompExprPtr comp = NULL;
2050 xmlXPathObjectPtr res = NULL;
2051
2052 ctxt = xmlXPathNewContext(doc);
2053 if (ctxt == NULL) {
2054 lint->progresult = XMLLINT_ERR_MEM;
2055 goto error;
2056 }
2057
2058 comp = xmlXPathCtxtCompile(ctxt, BAD_CAST query);
2059 if (comp == NULL) {
2060 fprintf(lint->errStream, "XPath compilation failure\n");
2061 lint->progresult = XMLLINT_ERR_XPATH;
2062 goto error;
2063 }
2064
2065 #ifdef LIBXML_DEBUG_ENABLED
2066 if (lint->debug) {
2067 xmlXPathDebugDumpCompExpr(stdout, comp, 0);
2068 printf("\n");
2069 }
2070 #endif
2071
2072 ctxt->node = (xmlNodePtr) doc;
2073 res = xmlXPathCompiledEval(comp, ctxt);
2074 if (res == NULL) {
2075 fprintf(lint->errStream, "XPath evaluation failure\n");
2076 lint->progresult = XMLLINT_ERR_XPATH;
2077 goto error;
2078 }
2079
2080 doXPathDump(lint, res);
2081
2082 error:
2083 xmlXPathFreeObject(res);
2084 xmlXPathFreeCompExpr(comp);
2085 xmlXPathFreeContext(ctxt);
2086 }
2087 #endif /* LIBXML_XPATH_ENABLED */
2088
2089 /************************************************************************
2090 * *
2091 * Tree Test processing *
2092 * *
2093 ************************************************************************/
2094
2095 static xmlDocPtr
parseFile(xmllintState * lint,const char * filename)2096 parseFile(xmllintState *lint, const char *filename) {
2097 xmlDocPtr doc = NULL;
2098
2099 if ((lint->generate) && (filename == NULL)) {
2100 xmlNodePtr n;
2101
2102 doc = xmlNewDoc(BAD_CAST "1.0");
2103 if (doc == NULL) {
2104 lint->progresult = XMLLINT_ERR_MEM;
2105 return(NULL);
2106 }
2107 n = xmlNewDocNode(doc, NULL, BAD_CAST "info", NULL);
2108 if (n == NULL) {
2109 xmlFreeDoc(doc);
2110 lint->progresult = XMLLINT_ERR_MEM;
2111 return(NULL);
2112 }
2113 if (xmlNodeSetContent(n, BAD_CAST "abc") < 0) {
2114 xmlFreeNode(n);
2115 xmlFreeDoc(doc);
2116 lint->progresult = XMLLINT_ERR_MEM;
2117 return(NULL);
2118 }
2119 xmlDocSetRootElement(doc, n);
2120
2121 return(doc);
2122 }
2123
2124 #ifdef LIBXML_HTML_ENABLED
2125 if (lint->html) {
2126 doc = parseHtml(lint, filename);
2127 return(doc);
2128 }
2129 #endif /* LIBXML_HTML_ENABLED */
2130 {
2131 doc = parseXml(lint, filename);
2132 }
2133
2134 if (doc == NULL) {
2135 if (lint->ctxt->errNo == XML_ERR_NO_MEMORY)
2136 lint->progresult = XMLLINT_ERR_MEM;
2137 else
2138 lint->progresult = XMLLINT_ERR_RDFILE;
2139 } else {
2140 #ifdef LIBXML_VALID_ENABLED
2141 if ((lint->options & XML_PARSE_DTDVALID) && (lint->ctxt->valid == 0))
2142 lint->progresult = XMLLINT_ERR_VALID;
2143 #endif /* LIBXML_VALID_ENABLED */
2144 }
2145
2146 return(doc);
2147 }
2148
2149 static void
parseAndPrintFile(xmllintState * lint,const char * filename)2150 parseAndPrintFile(xmllintState *lint, const char *filename) {
2151 FILE *errStream = lint->errStream;
2152 xmlDocPtr doc;
2153
2154 /* Avoid unused variable warning */
2155 (void) errStream;
2156
2157 if ((lint->timing) && (lint->repeat == 1))
2158 startTimer(lint);
2159
2160 doc = parseFile(lint, filename);
2161 if (doc == NULL) {
2162 if (lint->progresult == XMLLINT_RETURN_OK)
2163 lint->progresult = XMLLINT_ERR_UNCLASS;
2164 return;
2165 }
2166
2167 if ((lint->timing) && (lint->repeat == 1)) {
2168 endTimer(lint, "Parsing");
2169 }
2170
2171 if (lint->dropdtd) {
2172 xmlDtdPtr dtd;
2173
2174 dtd = xmlGetIntSubset(doc);
2175 if (dtd != NULL) {
2176 xmlUnlinkNode((xmlNodePtr)dtd);
2177 doc->intSubset = dtd;
2178 }
2179 }
2180
2181 #ifdef LIBXML_XINCLUDE_ENABLED
2182 if (lint->xinclude) {
2183 if ((lint->timing) && (lint->repeat == 1)) {
2184 startTimer(lint);
2185 }
2186 if (xmlXIncludeProcessFlags(doc, lint->options) < 0) {
2187 lint->progresult = XMLLINT_ERR_UNCLASS;
2188 goto done;
2189 }
2190 if ((lint->timing) && (lint->repeat == 1)) {
2191 endTimer(lint, "Xinclude processing");
2192 }
2193 }
2194 #endif
2195
2196 /*
2197 * shell interaction
2198 */
2199 if (lint->shell) {
2200 #ifdef LIBXML_XPATH_ENABLED
2201 xmlXPathOrderDocElems(doc);
2202 #endif
2203 xmllintShell(doc, filename, stdout);
2204 goto done;
2205 }
2206
2207 #ifdef LIBXML_XPATH_ENABLED
2208 if (lint->xpathquery != NULL) {
2209 xmlXPathOrderDocElems(doc);
2210 doXPathQuery(lint, doc, lint->xpathquery);
2211 }
2212 #endif
2213
2214 /*
2215 * test intermediate copy if needed.
2216 */
2217 if (lint->copy) {
2218 xmlDocPtr tmp;
2219
2220 tmp = doc;
2221 if (lint->timing) {
2222 startTimer(lint);
2223 }
2224 doc = xmlCopyDoc(doc, 1);
2225 if (doc == NULL) {
2226 lint->progresult = XMLLINT_ERR_MEM;
2227 xmlFreeDoc(tmp);
2228 return;
2229 }
2230 if (lint->timing) {
2231 endTimer(lint, "Copying");
2232 }
2233 if (lint->timing) {
2234 startTimer(lint);
2235 }
2236 xmlFreeDoc(tmp);
2237 if (lint->timing) {
2238 endTimer(lint, "Freeing original");
2239 }
2240 }
2241
2242 #ifdef LIBXML_VALID_ENABLED
2243 if ((lint->insert)
2244 #ifdef LIBXML_HTML_ENABLED
2245 && (!lint->html)
2246 #endif
2247 ) {
2248 const xmlChar* list[256];
2249 int nb, i;
2250 xmlNodePtr node;
2251
2252 if (doc->children != NULL) {
2253 node = doc->children;
2254 while ((node != NULL) &&
2255 ((node->type != XML_ELEMENT_NODE) ||
2256 (node->last == NULL)))
2257 node = node->next;
2258 if (node != NULL) {
2259 nb = xmlValidGetValidElements(node->last, NULL, list, 256);
2260 if (nb < 0) {
2261 fprintf(errStream, "could not get valid list of elements\n");
2262 } else if (nb == 0) {
2263 fprintf(errStream, "No element can be inserted under root\n");
2264 } else {
2265 fprintf(errStream, "%d element types can be inserted under root:\n",
2266 nb);
2267 for (i = 0;i < nb;i++) {
2268 fprintf(errStream, "%s\n", (char *) list[i]);
2269 }
2270 }
2271 }
2272 }
2273 } else
2274 #endif /* LIBXML_VALID_ENABLED */
2275 #ifdef LIBXML_READER_ENABLED
2276 if (lint->walker) {
2277 walkDoc(lint, doc);
2278 }
2279 #endif /* LIBXML_READER_ENABLED */
2280 #ifdef LIBXML_OUTPUT_ENABLED
2281 if (lint->noout == 0) {
2282 if (lint->compress)
2283 xmlSetDocCompressMode(doc, 9);
2284
2285 /*
2286 * print it.
2287 */
2288 #ifdef LIBXML_DEBUG_ENABLED
2289 if (!lint->debug) {
2290 #endif
2291 if ((lint->timing) && (lint->repeat == 1)) {
2292 startTimer(lint);
2293 }
2294 #ifdef LIBXML_HTML_ENABLED
2295 if ((lint->html) && (!lint->xmlout)) {
2296 if (lint->compress) {
2297 htmlSaveFile(lint->output ? lint->output : "-", doc);
2298 }
2299 else if (lint->encoding != NULL) {
2300 if (lint->format == 1) {
2301 htmlSaveFileFormat(lint->output ? lint->output : "-",
2302 doc, lint->encoding, 1);
2303 }
2304 else {
2305 htmlSaveFileFormat(lint->output ? lint->output : "-",
2306 doc, lint->encoding, 0);
2307 }
2308 }
2309 else if (lint->format == 1) {
2310 htmlSaveFileFormat(lint->output ? lint->output : "-",
2311 doc, NULL, 1);
2312 }
2313 else {
2314 FILE *out;
2315 if (lint->output == NULL)
2316 out = stdout;
2317 else {
2318 out = fopen(lint->output,"wb");
2319 }
2320 if (out != NULL) {
2321 if (htmlDocDump(out, doc) < 0)
2322 lint->progresult = XMLLINT_ERR_OUT;
2323
2324 if (lint->output != NULL)
2325 fclose(out);
2326 } else {
2327 fprintf(errStream, "failed to open %s\n",
2328 lint->output);
2329 lint->progresult = XMLLINT_ERR_OUT;
2330 }
2331 }
2332 if ((lint->timing) && (lint->repeat == 1)) {
2333 endTimer(lint, "Saving");
2334 }
2335 } else
2336 #endif
2337 #ifdef LIBXML_C14N_ENABLED
2338 if (lint->canonical) {
2339 xmlChar *result = NULL;
2340 int size;
2341
2342 size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_1_0, NULL, 1, &result);
2343 if (size >= 0) {
2344 if (write(1, result, size) == -1) {
2345 fprintf(errStream, "Can't write data\n");
2346 }
2347 xmlFree(result);
2348 } else {
2349 fprintf(errStream, "Failed to canonicalize\n");
2350 lint->progresult = XMLLINT_ERR_OUT;
2351 }
2352 } else if (lint->canonical_11) {
2353 xmlChar *result = NULL;
2354 int size;
2355
2356 size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_1_1, NULL, 1, &result);
2357 if (size >= 0) {
2358 if (write(1, result, size) == -1) {
2359 fprintf(errStream, "Can't write data\n");
2360 }
2361 xmlFree(result);
2362 } else {
2363 fprintf(errStream, "Failed to canonicalize\n");
2364 lint->progresult = XMLLINT_ERR_OUT;
2365 }
2366 } else if (lint->exc_canonical) {
2367 xmlChar *result = NULL;
2368 int size;
2369
2370 size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_EXCLUSIVE_1_0, NULL, 1, &result);
2371 if (size >= 0) {
2372 if (write(1, result, size) == -1) {
2373 fprintf(errStream, "Can't write data\n");
2374 }
2375 xmlFree(result);
2376 } else {
2377 fprintf(errStream, "Failed to canonicalize\n");
2378 lint->progresult = XMLLINT_ERR_OUT;
2379 }
2380 } else
2381 #endif
2382 #if HAVE_DECL_MMAP
2383 if (lint->memory) {
2384 xmlChar *result;
2385 int len;
2386
2387 if (lint->encoding != NULL) {
2388 if (lint->format == 1) {
2389 xmlDocDumpFormatMemoryEnc(doc, &result, &len,
2390 lint->encoding, 1);
2391 } else {
2392 xmlDocDumpMemoryEnc(doc, &result, &len,
2393 lint->encoding);
2394 }
2395 } else {
2396 if (lint->format == 1)
2397 xmlDocDumpFormatMemory(doc, &result, &len, 1);
2398 else
2399 xmlDocDumpMemory(doc, &result, &len);
2400 }
2401 if (result == NULL) {
2402 fprintf(errStream, "Failed to save\n");
2403 lint->progresult = XMLLINT_ERR_OUT;
2404 } else {
2405 if (write(1, result, len) == -1) {
2406 fprintf(errStream, "Can't write data\n");
2407 }
2408 xmlFree(result);
2409 }
2410
2411 } else
2412 #endif /* HAVE_DECL_MMAP */
2413 if (lint->compress) {
2414 xmlSaveFile(lint->output ? lint->output : "-", doc);
2415 } else {
2416 xmlSaveCtxtPtr ctxt;
2417 int saveOpts = 0;
2418
2419 if (lint->format == 1)
2420 saveOpts |= XML_SAVE_FORMAT;
2421 else if (lint->format == 2)
2422 saveOpts |= XML_SAVE_WSNONSIG;
2423
2424 #if defined(LIBXML_HTML_ENABLED)
2425 if (lint->xmlout)
2426 saveOpts |= XML_SAVE_AS_XML;
2427 #endif
2428
2429 if (lint->output == NULL)
2430 ctxt = xmlSaveToFd(STDOUT_FILENO, lint->encoding,
2431 saveOpts);
2432 else
2433 ctxt = xmlSaveToFilename(lint->output, lint->encoding,
2434 saveOpts);
2435
2436 if (ctxt != NULL) {
2437 if (xmlSaveDoc(ctxt, doc) < 0) {
2438 fprintf(errStream, "failed save to %s\n",
2439 lint->output ? lint->output : "-");
2440 lint->progresult = XMLLINT_ERR_OUT;
2441 }
2442 xmlSaveClose(ctxt);
2443 } else {
2444 lint->progresult = XMLLINT_ERR_OUT;
2445 }
2446 }
2447 if ((lint->timing) && (lint->repeat == 1)) {
2448 endTimer(lint, "Saving");
2449 }
2450 #ifdef LIBXML_DEBUG_ENABLED
2451 } else {
2452 FILE *out;
2453 if (lint->output == NULL)
2454 out = stdout;
2455 else {
2456 out = fopen(lint->output, "wb");
2457 }
2458 if (out != NULL) {
2459 xmlDebugDumpDocument(out, doc);
2460
2461 if (lint->output != NULL)
2462 fclose(out);
2463 } else {
2464 fprintf(errStream, "failed to open %s\n", lint->output);
2465 lint->progresult = XMLLINT_ERR_OUT;
2466 }
2467 }
2468 #endif
2469 }
2470 #endif /* LIBXML_OUTPUT_ENABLED */
2471
2472 #ifdef LIBXML_VALID_ENABLED
2473 /*
2474 * A posteriori validation test
2475 */
2476 if ((lint->dtdvalid != NULL) || (lint->dtdvalidfpi != NULL)) {
2477 xmlDtdPtr dtd;
2478
2479 if ((lint->timing) && (lint->repeat == 1)) {
2480 startTimer(lint);
2481 }
2482 if (lint->dtdvalid != NULL)
2483 dtd = xmlParseDTD(NULL, BAD_CAST lint->dtdvalid);
2484 else
2485 dtd = xmlParseDTD(BAD_CAST lint->dtdvalidfpi, NULL);
2486 if ((lint->timing) && (lint->repeat == 1)) {
2487 endTimer(lint, "Parsing DTD");
2488 }
2489 if (dtd == NULL) {
2490 if (lint->dtdvalid != NULL)
2491 fprintf(errStream, "Could not parse DTD %s\n",
2492 lint->dtdvalid);
2493 else
2494 fprintf(errStream, "Could not parse DTD %s\n",
2495 lint->dtdvalidfpi);
2496 lint->progresult = XMLLINT_ERR_DTD;
2497 } else {
2498 xmlValidCtxtPtr cvp;
2499
2500 cvp = xmlNewValidCtxt();
2501 if (cvp == NULL) {
2502 lint->progresult = XMLLINT_ERR_MEM;
2503 xmlFreeDtd(dtd);
2504 return;
2505 }
2506
2507 if ((lint->timing) && (lint->repeat == 1)) {
2508 startTimer(lint);
2509 }
2510 if (!xmlValidateDtd(cvp, doc, dtd)) {
2511 if (lint->dtdvalid != NULL)
2512 fprintf(errStream,
2513 "Document %s does not validate against %s\n",
2514 filename, lint->dtdvalid);
2515 else
2516 fprintf(errStream,
2517 "Document %s does not validate against %s\n",
2518 filename, lint->dtdvalidfpi);
2519 lint->progresult = XMLLINT_ERR_VALID;
2520 }
2521 if ((lint->timing) && (lint->repeat == 1)) {
2522 endTimer(lint, "Validating against DTD");
2523 }
2524 xmlFreeValidCtxt(cvp);
2525 xmlFreeDtd(dtd);
2526 }
2527 } else if (lint->postvalid) {
2528 xmlValidCtxtPtr cvp;
2529
2530 cvp = xmlNewValidCtxt();
2531 if (cvp == NULL) {
2532 lint->progresult = XMLLINT_ERR_MEM;
2533 xmlFreeDoc(doc);
2534 return;
2535 }
2536
2537 if ((lint->timing) && (lint->repeat == 1)) {
2538 startTimer(lint);
2539 }
2540 if (!xmlValidateDocument(cvp, doc)) {
2541 fprintf(errStream,
2542 "Document %s does not validate\n", filename);
2543 lint->progresult = XMLLINT_ERR_VALID;
2544 }
2545 if ((lint->timing) && (lint->repeat == 1)) {
2546 endTimer(lint, "Validating");
2547 }
2548 xmlFreeValidCtxt(cvp);
2549 }
2550 #endif /* LIBXML_VALID_ENABLED */
2551 #ifdef LIBXML_SCHEMATRON_ENABLED
2552 if (lint->wxschematron != NULL) {
2553 xmlSchematronValidCtxtPtr ctxt;
2554 int ret;
2555 int flag;
2556
2557 if ((lint->timing) && (lint->repeat == 1)) {
2558 startTimer(lint);
2559 }
2560
2561 if (lint->debug)
2562 flag = XML_SCHEMATRON_OUT_XML;
2563 else
2564 flag = XML_SCHEMATRON_OUT_TEXT;
2565 if (lint->noout)
2566 flag |= XML_SCHEMATRON_OUT_QUIET;
2567 ctxt = xmlSchematronNewValidCtxt(lint->wxschematron, flag);
2568 if (ctxt == NULL) {
2569 lint->progresult = XMLLINT_ERR_MEM;
2570 xmlFreeDoc(doc);
2571 return;
2572 }
2573 ret = xmlSchematronValidateDoc(ctxt, doc);
2574 if (ret == 0) {
2575 if (!lint->quiet) {
2576 fprintf(errStream, "%s validates\n", filename);
2577 }
2578 } else if (ret > 0) {
2579 fprintf(errStream, "%s fails to validate\n", filename);
2580 lint->progresult = XMLLINT_ERR_VALID;
2581 } else {
2582 fprintf(errStream, "%s validation generated an internal error\n",
2583 filename);
2584 lint->progresult = XMLLINT_ERR_VALID;
2585 }
2586 xmlSchematronFreeValidCtxt(ctxt);
2587 if ((lint->timing) && (lint->repeat == 1)) {
2588 endTimer(lint, "Validating");
2589 }
2590 }
2591 #endif
2592 #ifdef LIBXML_SCHEMAS_ENABLED
2593 if (lint->relaxngschemas != NULL) {
2594 xmlRelaxNGValidCtxtPtr ctxt;
2595 int ret;
2596
2597 if ((lint->timing) && (lint->repeat == 1)) {
2598 startTimer(lint);
2599 }
2600
2601 ctxt = xmlRelaxNGNewValidCtxt(lint->relaxngschemas);
2602 if (ctxt == NULL) {
2603 lint->progresult = XMLLINT_ERR_MEM;
2604 xmlFreeDoc(doc);
2605 return;
2606 }
2607 ret = xmlRelaxNGValidateDoc(ctxt, doc);
2608 if (ret == 0) {
2609 if (!lint->quiet) {
2610 fprintf(errStream, "%s validates\n", filename);
2611 }
2612 } else if (ret > 0) {
2613 fprintf(errStream, "%s fails to validate\n", filename);
2614 lint->progresult = XMLLINT_ERR_VALID;
2615 } else {
2616 fprintf(errStream, "%s validation generated an internal error\n",
2617 filename);
2618 lint->progresult = XMLLINT_ERR_VALID;
2619 }
2620 xmlRelaxNGFreeValidCtxt(ctxt);
2621 if ((lint->timing) && (lint->repeat == 1)) {
2622 endTimer(lint, "Validating");
2623 }
2624 } else if (lint->wxschemas != NULL) {
2625 xmlSchemaValidCtxtPtr ctxt;
2626 int ret;
2627
2628 if ((lint->timing) && (lint->repeat == 1)) {
2629 startTimer(lint);
2630 }
2631
2632 ctxt = xmlSchemaNewValidCtxt(lint->wxschemas);
2633 if (ctxt == NULL) {
2634 lint->progresult = XMLLINT_ERR_MEM;
2635 xmlFreeDoc(doc);
2636 return;
2637 }
2638 ret = xmlSchemaValidateDoc(ctxt, doc);
2639 if (ret == 0) {
2640 if (!lint->quiet) {
2641 fprintf(errStream, "%s validates\n", filename);
2642 }
2643 } else if (ret > 0) {
2644 fprintf(errStream, "%s fails to validate\n", filename);
2645 lint->progresult = XMLLINT_ERR_VALID;
2646 } else {
2647 fprintf(errStream, "%s validation generated an internal error\n",
2648 filename);
2649 lint->progresult = XMLLINT_ERR_VALID;
2650 }
2651 xmlSchemaFreeValidCtxt(ctxt);
2652 if ((lint->timing) && (lint->repeat == 1)) {
2653 endTimer(lint, "Validating");
2654 }
2655 }
2656 #endif
2657
2658 #ifdef LIBXML_DEBUG_ENABLED
2659 if ((lint->debugent)
2660 #if defined(LIBXML_HTML_ENABLED)
2661 && (!lint->html)
2662 #endif
2663 )
2664 xmlDebugDumpEntities(errStream, doc);
2665 #endif
2666
2667 /* Avoid unused label warning */
2668 goto done;
2669
2670 done:
2671 /*
2672 * free it.
2673 */
2674 if ((lint->timing) && (lint->repeat == 1)) {
2675 startTimer(lint);
2676 }
2677 xmlFreeDoc(doc);
2678 if ((lint->timing) && (lint->repeat == 1)) {
2679 endTimer(lint, "Freeing");
2680 }
2681 }
2682
2683 /************************************************************************
2684 * *
2685 * Usage and Main *
2686 * *
2687 ************************************************************************/
2688
showVersion(FILE * errStream,const char * name)2689 static void showVersion(FILE *errStream, const char *name) {
2690 fprintf(errStream, "%s: using libxml version %s\n", name, xmlParserVersion);
2691 fprintf(errStream, " compiled with: ");
2692 if (xmlHasFeature(XML_WITH_THREAD)) fprintf(errStream, "Threads ");
2693 if (xmlHasFeature(XML_WITH_TREE)) fprintf(errStream, "Tree ");
2694 if (xmlHasFeature(XML_WITH_OUTPUT)) fprintf(errStream, "Output ");
2695 if (xmlHasFeature(XML_WITH_PUSH)) fprintf(errStream, "Push ");
2696 if (xmlHasFeature(XML_WITH_READER)) fprintf(errStream, "Reader ");
2697 if (xmlHasFeature(XML_WITH_PATTERN)) fprintf(errStream, "Patterns ");
2698 if (xmlHasFeature(XML_WITH_WRITER)) fprintf(errStream, "Writer ");
2699 if (xmlHasFeature(XML_WITH_SAX1)) fprintf(errStream, "SAXv1 ");
2700 if (xmlHasFeature(XML_WITH_HTTP)) fprintf(errStream, "HTTP ");
2701 if (xmlHasFeature(XML_WITH_VALID)) fprintf(errStream, "DTDValid ");
2702 if (xmlHasFeature(XML_WITH_HTML)) fprintf(errStream, "HTML ");
2703 if (xmlHasFeature(XML_WITH_LEGACY)) fprintf(errStream, "Legacy ");
2704 if (xmlHasFeature(XML_WITH_C14N)) fprintf(errStream, "C14N ");
2705 if (xmlHasFeature(XML_WITH_CATALOG)) fprintf(errStream, "Catalog ");
2706 if (xmlHasFeature(XML_WITH_XPATH)) fprintf(errStream, "XPath ");
2707 if (xmlHasFeature(XML_WITH_XPTR)) fprintf(errStream, "XPointer ");
2708 if (xmlHasFeature(XML_WITH_XINCLUDE)) fprintf(errStream, "XInclude ");
2709 if (xmlHasFeature(XML_WITH_ICONV)) fprintf(errStream, "Iconv ");
2710 if (xmlHasFeature(XML_WITH_ICU)) fprintf(errStream, "ICU ");
2711 if (xmlHasFeature(XML_WITH_ISO8859X)) fprintf(errStream, "ISO8859X ");
2712 if (xmlHasFeature(XML_WITH_UNICODE)) fprintf(errStream, "Unicode ");
2713 if (xmlHasFeature(XML_WITH_REGEXP)) fprintf(errStream, "Regexps ");
2714 if (xmlHasFeature(XML_WITH_AUTOMATA)) fprintf(errStream, "Automata ");
2715 if (xmlHasFeature(XML_WITH_EXPR)) fprintf(errStream, "Expr ");
2716 if (xmlHasFeature(XML_WITH_SCHEMAS)) fprintf(errStream, "Schemas ");
2717 if (xmlHasFeature(XML_WITH_SCHEMATRON)) fprintf(errStream, "Schematron ");
2718 if (xmlHasFeature(XML_WITH_MODULES)) fprintf(errStream, "Modules ");
2719 if (xmlHasFeature(XML_WITH_DEBUG)) fprintf(errStream, "Debug ");
2720 if (xmlHasFeature(XML_WITH_ZLIB)) fprintf(errStream, "Zlib ");
2721 if (xmlHasFeature(XML_WITH_LZMA)) fprintf(errStream, "Lzma ");
2722 fprintf(errStream, "\n");
2723 }
2724
usage(FILE * f,const char * name)2725 static void usage(FILE *f, const char *name) {
2726 fprintf(f, "Usage : %s [options] XMLfiles ...\n", name);
2727 #ifdef LIBXML_OUTPUT_ENABLED
2728 fprintf(f, "\tParse the XML files and output the result of the parsing\n");
2729 #else
2730 fprintf(f, "\tParse the XML files\n");
2731 #endif /* LIBXML_OUTPUT_ENABLED */
2732 fprintf(f, "\t--version : display the version of the XML library used\n");
2733 fprintf(f, "\t--shell : run a navigating shell\n");
2734 #ifdef LIBXML_DEBUG_ENABLED
2735 fprintf(f, "\t--debug : dump a debug tree of the in-memory document\n");
2736 fprintf(f, "\t--debugent : debug the entities defined in the document\n");
2737 #else
2738 #ifdef LIBXML_READER_ENABLED
2739 fprintf(f, "\t--debug : dump the nodes content when using --stream\n");
2740 #endif /* LIBXML_READER_ENABLED */
2741 #endif
2742 fprintf(f, "\t--copy : used to test the internal copy implementation\n");
2743 fprintf(f, "\t--recover : output what was parsable on broken XML documents\n");
2744 fprintf(f, "\t--huge : remove any internal arbitrary parser limits\n");
2745 fprintf(f, "\t--noent : substitute entity references by their value\n");
2746 fprintf(f, "\t--noenc : ignore any encoding specified inside the document\n");
2747 fprintf(f, "\t--noout : don't output the result tree\n");
2748 fprintf(f, "\t--path 'paths': provide a set of paths for resources\n");
2749 fprintf(f, "\t--load-trace : print trace of all external entities loaded\n");
2750 fprintf(f, "\t--nonet : refuse to fetch DTDs or entities over network\n");
2751 fprintf(f, "\t--nocompact : do not generate compact text nodes\n");
2752 fprintf(f, "\t--htmlout : output results as HTML\n");
2753 fprintf(f, "\t--nowrap : do not put HTML doc wrapper\n");
2754 #ifdef LIBXML_VALID_ENABLED
2755 fprintf(f, "\t--valid : validate the document in addition to std well-formed check\n");
2756 fprintf(f, "\t--postvalid : do a posteriori validation, i.e after parsing\n");
2757 fprintf(f, "\t--dtdvalid URL : do a posteriori validation against a given DTD\n");
2758 fprintf(f, "\t--dtdvalidfpi FPI : same but name the DTD with a Public Identifier\n");
2759 fprintf(f, "\t--insert : ad-hoc test for valid insertions\n");
2760 #endif /* LIBXML_VALID_ENABLED */
2761 fprintf(f, "\t--quiet : be quiet when succeeded\n");
2762 fprintf(f, "\t--timing : print some timings\n");
2763 fprintf(f, "\t--repeat : repeat 100 times, for timing or profiling\n");
2764 fprintf(f, "\t--dropdtd : remove the DOCTYPE of the input docs\n");
2765 #ifdef LIBXML_HTML_ENABLED
2766 fprintf(f, "\t--html : use the HTML parser\n");
2767 fprintf(f, "\t--xmlout : force to use the XML serializer when using --html\n");
2768 fprintf(f, "\t--nodefdtd : do not default HTML doctype\n");
2769 #endif
2770 #ifdef LIBXML_PUSH_ENABLED
2771 fprintf(f, "\t--push : use the push mode of the parser\n");
2772 #endif /* LIBXML_PUSH_ENABLED */
2773 #if HAVE_DECL_MMAP
2774 fprintf(f, "\t--memory : parse from memory\n");
2775 #endif
2776 fprintf(f, "\t--maxmem nbbytes : limits memory allocation to nbbytes bytes\n");
2777 fprintf(f, "\t--nowarning : do not emit warnings from parser/validator\n");
2778 fprintf(f, "\t--noblanks : drop (ignorable?) blanks spaces\n");
2779 fprintf(f, "\t--nocdata : replace cdata section with text nodes\n");
2780 fprintf(f, "\t--nodict : create document without dictionary\n");
2781 fprintf(f, "\t--pedantic : enable additional warnings\n");
2782 #ifdef LIBXML_OUTPUT_ENABLED
2783 fprintf(f, "\t--output file or -o file: save to a given file\n");
2784 fprintf(f, "\t--format : reformat/reindent the output\n");
2785 fprintf(f, "\t--encode encoding : output in the given encoding\n");
2786 fprintf(f, "\t--pretty STYLE : pretty-print in a particular style\n");
2787 fprintf(f, "\t 0 Do not pretty print\n");
2788 fprintf(f, "\t 1 Format the XML content, as --format\n");
2789 fprintf(f, "\t 2 Add whitespace inside tags, preserving content\n");
2790 #ifdef LIBXML_ZLIB_ENABLED
2791 fprintf(f, "\t--compress : turn on gzip compression of output\n");
2792 #endif
2793 #endif /* LIBXML_OUTPUT_ENABLED */
2794 fprintf(f, "\t--c14n : save in W3C canonical format v1.0 (with comments)\n");
2795 fprintf(f, "\t--c14n11 : save in W3C canonical format v1.1 (with comments)\n");
2796 fprintf(f, "\t--exc-c14n : save in W3C exclusive canonical format (with comments)\n");
2797 #ifdef LIBXML_C14N_ENABLED
2798 #endif /* LIBXML_C14N_ENABLED */
2799 fprintf(f, "\t--nsclean : remove redundant namespace declarations\n");
2800 fprintf(f, "\t--testIO : test user I/O support\n");
2801 #ifdef LIBXML_CATALOG_ENABLED
2802 fprintf(f, "\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
2803 fprintf(f, "\t otherwise XML Catalogs starting from \n");
2804 fprintf(f, "\t file://" XML_SYSCONFDIR "/xml/catalog "
2805 "are activated by default\n");
2806 fprintf(f, "\t--nocatalogs: deactivate all catalogs\n");
2807 #endif
2808 fprintf(f, "\t--auto : generate a small doc on the fly\n");
2809 #ifdef LIBXML_XINCLUDE_ENABLED
2810 fprintf(f, "\t--xinclude : do XInclude processing\n");
2811 fprintf(f, "\t--noxincludenode : same but do not generate XInclude nodes\n");
2812 fprintf(f, "\t--nofixup-base-uris : do not fixup xml:base uris\n");
2813 #endif
2814 fprintf(f, "\t--loaddtd : fetch external DTD\n");
2815 fprintf(f, "\t--dtdattr : loaddtd + populate the tree with inherited attributes \n");
2816 #ifdef LIBXML_READER_ENABLED
2817 fprintf(f, "\t--stream : use the streaming interface to process very large files\n");
2818 fprintf(f, "\t--walker : create a reader and walk though the resulting doc\n");
2819 #ifdef LIBXML_PATTERN_ENABLED
2820 fprintf(f, "\t--pattern pattern_value : test the pattern support\n");
2821 #endif
2822 #endif /* LIBXML_READER_ENABLED */
2823 #ifdef LIBXML_SCHEMAS_ENABLED
2824 fprintf(f, "\t--relaxng schema : do RelaxNG validation against the schema\n");
2825 fprintf(f, "\t--schema schema : do validation against the WXS schema\n");
2826 #endif
2827 #ifdef LIBXML_SCHEMATRON_ENABLED
2828 fprintf(f, "\t--schematron schema : do validation against a schematron\n");
2829 #endif
2830 #ifdef LIBXML_SAX1_ENABLED
2831 fprintf(f, "\t--sax1: use the old SAX1 interfaces for processing\n");
2832 #endif
2833 fprintf(f, "\t--sax: do not build a tree but work just at the SAX level\n");
2834 fprintf(f, "\t--oldxml10: use XML-1.0 parsing rules before the 5th edition\n");
2835 #ifdef LIBXML_XPATH_ENABLED
2836 fprintf(f, "\t--xpath expr: evaluate the XPath expression, imply --noout\n");
2837 #endif
2838 fprintf(f, "\t--max-ampl value: set maximum amplification factor\n");
2839
2840 fprintf(f, "\nLibxml project home page: https://gitlab.gnome.org/GNOME/libxml2\n");
2841 }
2842
2843 static unsigned long
parseInteger(FILE * errStream,const char * ctxt,const char * str,unsigned long min,unsigned long max)2844 parseInteger(FILE *errStream, const char *ctxt, const char *str,
2845 unsigned long min, unsigned long max) {
2846 char *strEnd;
2847 unsigned long val;
2848
2849 errno = 0;
2850 val = strtoul(str, &strEnd, 10);
2851 if (errno == EINVAL || *strEnd != 0) {
2852 fprintf(errStream, "%s: invalid integer: %s\n", ctxt, str);
2853 exit(XMLLINT_ERR_UNCLASS);
2854 }
2855 if (errno != 0 || val < min || val > max) {
2856 fprintf(errStream, "%s: integer out of range: %s\n", ctxt, str);
2857 exit(XMLLINT_ERR_UNCLASS);
2858 }
2859
2860 return(val);
2861 }
2862
2863 static int
skipArgs(const char * arg)2864 skipArgs(const char *arg) {
2865 if ((!strcmp(arg, "-path")) ||
2866 (!strcmp(arg, "--path")) ||
2867 (!strcmp(arg, "-maxmem")) ||
2868 (!strcmp(arg, "--maxmem")) ||
2869 #ifdef LIBXML_OUTPUT_ENABLED
2870 (!strcmp(arg, "-o")) ||
2871 (!strcmp(arg, "-output")) ||
2872 (!strcmp(arg, "--output")) ||
2873 (!strcmp(arg, "-encode")) ||
2874 (!strcmp(arg, "--encode")) ||
2875 (!strcmp(arg, "-pretty")) ||
2876 (!strcmp(arg, "--pretty")) ||
2877 #endif
2878 #ifdef LIBXML_VALID_ENABLED
2879 (!strcmp(arg, "-dtdvalid")) ||
2880 (!strcmp(arg, "--dtdvalid")) ||
2881 (!strcmp(arg, "-dtdvalidfpi")) ||
2882 (!strcmp(arg, "--dtdvalidfpi")) ||
2883 #endif
2884 #ifdef LIBXML_SCHEMAS_ENABLED
2885 (!strcmp(arg, "-relaxng")) ||
2886 (!strcmp(arg, "--relaxng")) ||
2887 (!strcmp(arg, "-schema")) ||
2888 (!strcmp(arg, "--schema")) ||
2889 #endif
2890 #ifdef LIBXML_SCHEMATRON_ENABLED
2891 (!strcmp(arg, "-schematron")) ||
2892 (!strcmp(arg, "--schematron")) ||
2893 #endif
2894 #if defined(LIBXML_READER_ENABLED) && defined(LIBXML_PATTERN_ENABLED)
2895 (!strcmp(arg, "-pattern")) ||
2896 (!strcmp(arg, "--pattern")) ||
2897 #endif
2898 #ifdef LIBXML_XPATH_ENABLED
2899 (!strcmp(arg, "-xpath")) ||
2900 (!strcmp(arg, "--xpath")) ||
2901 #endif
2902 (!strcmp(arg, "-max-ampl")) ||
2903 (!strcmp(arg, "--max-ampl"))
2904 ) {
2905 return(1);
2906 }
2907
2908 return(0);
2909 }
2910
2911 static void
xmllintInit(xmllintState * lint)2912 xmllintInit(xmllintState *lint) {
2913 memset(lint, 0, sizeof(*lint));
2914
2915 lint->repeat = 1;
2916 lint->progresult = XMLLINT_RETURN_OK;
2917 lint->options = XML_PARSE_COMPACT | XML_PARSE_BIG_LINES;
2918 }
2919
2920 static int
xmllintParseOptions(xmllintState * lint,int argc,const char ** argv)2921 xmllintParseOptions(xmllintState *lint, int argc, const char **argv) {
2922 FILE *errStream = lint->errStream;
2923 int i;
2924
2925 if (argc <= 1) {
2926 usage(errStream, argv[0]);
2927 return(XMLLINT_ERR_UNCLASS);
2928 }
2929
2930 for (i = 1; i < argc ; i++) {
2931 if (argv[i][0] != '-' || argv[i][1] == 0)
2932 continue;
2933
2934 if ((!strcmp(argv[i], "-maxmem")) ||
2935 (!strcmp(argv[i], "--maxmem"))) {
2936 i++;
2937 if (i >= argc) {
2938 fprintf(errStream, "maxmem: missing integer value\n");
2939 return(XMLLINT_ERR_UNCLASS);
2940 }
2941 errno = 0;
2942 lint->maxmem = parseInteger(errStream, "maxmem", argv[i],
2943 0, INT_MAX);
2944 } else if ((!strcmp(argv[i], "-debug")) ||
2945 (!strcmp(argv[i], "--debug"))) {
2946 lint->debug = 1;
2947 } else if ((!strcmp(argv[i], "-shell")) ||
2948 (!strcmp(argv[i], "--shell"))) {
2949 lint->shell = 1;
2950 } else if ((!strcmp(argv[i], "-copy")) ||
2951 (!strcmp(argv[i], "--copy"))) {
2952 lint->copy = 1;
2953 } else if ((!strcmp(argv[i], "-recover")) ||
2954 (!strcmp(argv[i], "--recover"))) {
2955 lint->options |= XML_PARSE_RECOVER;
2956 } else if ((!strcmp(argv[i], "-huge")) ||
2957 (!strcmp(argv[i], "--huge"))) {
2958 lint->options |= XML_PARSE_HUGE;
2959 } else if ((!strcmp(argv[i], "-noent")) ||
2960 (!strcmp(argv[i], "--noent"))) {
2961 lint->options |= XML_PARSE_NOENT;
2962 } else if ((!strcmp(argv[i], "-noenc")) ||
2963 (!strcmp(argv[i], "--noenc"))) {
2964 lint->options |= XML_PARSE_IGNORE_ENC;
2965 } else if ((!strcmp(argv[i], "-nsclean")) ||
2966 (!strcmp(argv[i], "--nsclean"))) {
2967 lint->options |= XML_PARSE_NSCLEAN;
2968 } else if ((!strcmp(argv[i], "-nocdata")) ||
2969 (!strcmp(argv[i], "--nocdata"))) {
2970 lint->options |= XML_PARSE_NOCDATA;
2971 } else if ((!strcmp(argv[i], "-nodict")) ||
2972 (!strcmp(argv[i], "--nodict"))) {
2973 lint->options |= XML_PARSE_NODICT;
2974 } else if ((!strcmp(argv[i], "-version")) ||
2975 (!strcmp(argv[i], "--version"))) {
2976 showVersion(errStream, argv[0]);
2977 lint->version = 1;
2978 } else if ((!strcmp(argv[i], "-noout")) ||
2979 (!strcmp(argv[i], "--noout"))) {
2980 lint->noout = 1;
2981 } else if ((!strcmp(argv[i], "-htmlout")) ||
2982 (!strcmp(argv[i], "--htmlout"))) {
2983 lint->htmlout = 1;
2984 } else if ((!strcmp(argv[i], "-nowrap")) ||
2985 (!strcmp(argv[i], "--nowrap"))) {
2986 lint->nowrap = 1;
2987 #ifdef LIBXML_HTML_ENABLED
2988 } else if ((!strcmp(argv[i], "-html")) ||
2989 (!strcmp(argv[i], "--html"))) {
2990 lint->html = 1;
2991 } else if ((!strcmp(argv[i], "-xmlout")) ||
2992 (!strcmp(argv[i], "--xmlout"))) {
2993 lint->xmlout = 1;
2994 } else if ((!strcmp(argv[i], "-nodefdtd")) ||
2995 (!strcmp(argv[i], "--nodefdtd"))) {
2996 lint->options |= HTML_PARSE_NODEFDTD;
2997 #endif /* LIBXML_HTML_ENABLED */
2998 } else if ((!strcmp(argv[i], "-loaddtd")) ||
2999 (!strcmp(argv[i], "--loaddtd"))) {
3000 lint->options |= XML_PARSE_DTDLOAD;
3001 } else if ((!strcmp(argv[i], "-dtdattr")) ||
3002 (!strcmp(argv[i], "--dtdattr"))) {
3003 lint->options |= XML_PARSE_DTDATTR;
3004 #ifdef LIBXML_VALID_ENABLED
3005 } else if ((!strcmp(argv[i], "-valid")) ||
3006 (!strcmp(argv[i], "--valid"))) {
3007 lint->options |= XML_PARSE_DTDVALID;
3008 } else if ((!strcmp(argv[i], "-postvalid")) ||
3009 (!strcmp(argv[i], "--postvalid"))) {
3010 lint->postvalid = 1;
3011 lint->options |= XML_PARSE_DTDLOAD;
3012 } else if ((!strcmp(argv[i], "-dtdvalid")) ||
3013 (!strcmp(argv[i], "--dtdvalid"))) {
3014 i++;
3015 lint->dtdvalid = argv[i];
3016 lint->options |= XML_PARSE_DTDLOAD;
3017 } else if ((!strcmp(argv[i], "-dtdvalidfpi")) ||
3018 (!strcmp(argv[i], "--dtdvalidfpi"))) {
3019 i++;
3020 lint->dtdvalidfpi = argv[i];
3021 lint->options |= XML_PARSE_DTDLOAD;
3022 } else if ((!strcmp(argv[i], "-insert")) ||
3023 (!strcmp(argv[i], "--insert"))) {
3024 lint->insert = 1;
3025 #endif /* LIBXML_VALID_ENABLED */
3026 } else if ((!strcmp(argv[i], "-dropdtd")) ||
3027 (!strcmp(argv[i], "--dropdtd"))) {
3028 lint->dropdtd = 1;
3029 } else if ((!strcmp(argv[i], "-quiet")) ||
3030 (!strcmp(argv[i], "--quiet"))) {
3031 lint->quiet = 1;
3032 } else if ((!strcmp(argv[i], "-timing")) ||
3033 (!strcmp(argv[i], "--timing"))) {
3034 lint->timing = 1;
3035 } else if ((!strcmp(argv[i], "-auto")) ||
3036 (!strcmp(argv[i], "--auto"))) {
3037 lint->generate = 1;
3038 } else if ((!strcmp(argv[i], "-repeat")) ||
3039 (!strcmp(argv[i], "--repeat"))) {
3040 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
3041 lint->repeat = 2;
3042 #else
3043 if (lint->repeat > 1)
3044 lint->repeat *= 10;
3045 else
3046 lint->repeat = 100;
3047 #endif
3048 #ifdef LIBXML_PUSH_ENABLED
3049 } else if ((!strcmp(argv[i], "-push")) ||
3050 (!strcmp(argv[i], "--push"))) {
3051 lint->push = 1;
3052 #endif /* LIBXML_PUSH_ENABLED */
3053 #if HAVE_DECL_MMAP
3054 } else if ((!strcmp(argv[i], "-memory")) ||
3055 (!strcmp(argv[i], "--memory"))) {
3056 lint->memory = 1;
3057 #endif
3058 } else if ((!strcmp(argv[i], "-testIO")) ||
3059 (!strcmp(argv[i], "--testIO"))) {
3060 lint->testIO = 1;
3061 #ifdef LIBXML_XINCLUDE_ENABLED
3062 } else if ((!strcmp(argv[i], "-xinclude")) ||
3063 (!strcmp(argv[i], "--xinclude"))) {
3064 lint->xinclude = 1;
3065 lint->options |= XML_PARSE_XINCLUDE;
3066 } else if ((!strcmp(argv[i], "-noxincludenode")) ||
3067 (!strcmp(argv[i], "--noxincludenode"))) {
3068 lint->xinclude = 1;
3069 lint->options |= XML_PARSE_XINCLUDE;
3070 lint->options |= XML_PARSE_NOXINCNODE;
3071 } else if ((!strcmp(argv[i], "-nofixup-base-uris")) ||
3072 (!strcmp(argv[i], "--nofixup-base-uris"))) {
3073 lint->xinclude = 1;
3074 lint->options |= XML_PARSE_XINCLUDE;
3075 lint->options |= XML_PARSE_NOBASEFIX;
3076 #endif
3077 } else if ((!strcmp(argv[i], "-nowarning")) ||
3078 (!strcmp(argv[i], "--nowarning"))) {
3079 lint->options |= XML_PARSE_NOWARNING;
3080 lint->options &= ~XML_PARSE_PEDANTIC;
3081 } else if ((!strcmp(argv[i], "-pedantic")) ||
3082 (!strcmp(argv[i], "--pedantic"))) {
3083 lint->options |= XML_PARSE_PEDANTIC;
3084 lint->options &= ~XML_PARSE_NOWARNING;
3085 #ifdef LIBXML_DEBUG_ENABLED
3086 } else if ((!strcmp(argv[i], "-debugent")) ||
3087 (!strcmp(argv[i], "--debugent"))) {
3088 lint->debugent = 1;
3089 #endif
3090 #ifdef LIBXML_C14N_ENABLED
3091 } else if ((!strcmp(argv[i], "-c14n")) ||
3092 (!strcmp(argv[i], "--c14n"))) {
3093 lint->canonical = 1;
3094 lint->options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
3095 } else if ((!strcmp(argv[i], "-c14n11")) ||
3096 (!strcmp(argv[i], "--c14n11"))) {
3097 lint->canonical_11 = 1;
3098 lint->options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
3099 } else if ((!strcmp(argv[i], "-exc-c14n")) ||
3100 (!strcmp(argv[i], "--exc-c14n"))) {
3101 lint->exc_canonical = 1;
3102 lint->options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
3103 #endif
3104 #ifdef LIBXML_CATALOG_ENABLED
3105 } else if ((!strcmp(argv[i], "-catalogs")) ||
3106 (!strcmp(argv[i], "--catalogs"))) {
3107 lint->catalogs = 1;
3108 } else if ((!strcmp(argv[i], "-nocatalogs")) ||
3109 (!strcmp(argv[i], "--nocatalogs"))) {
3110 lint->nocatalogs = 1;
3111 #endif
3112 } else if ((!strcmp(argv[i], "-noblanks")) ||
3113 (!strcmp(argv[i], "--noblanks"))) {
3114 lint->options |= XML_PARSE_NOBLANKS;
3115 #ifdef LIBXML_OUTPUT_ENABLED
3116 } else if ((!strcmp(argv[i], "-o")) ||
3117 (!strcmp(argv[i], "-output")) ||
3118 (!strcmp(argv[i], "--output"))) {
3119 i++;
3120 lint->output = argv[i];
3121 } else if ((!strcmp(argv[i], "-format")) ||
3122 (!strcmp(argv[i], "--format"))) {
3123 lint->format = 1;
3124 lint->options |= XML_PARSE_NOBLANKS;
3125 } else if ((!strcmp(argv[i], "-encode")) ||
3126 (!strcmp(argv[i], "--encode"))) {
3127 i++;
3128 lint->encoding = argv[i];
3129 } else if ((!strcmp(argv[i], "-pretty")) ||
3130 (!strcmp(argv[i], "--pretty"))) {
3131 i++;
3132 if (argv[i] != NULL)
3133 lint->format = atoi(argv[i]);
3134 #ifdef LIBXML_ZLIB_ENABLED
3135 } else if ((!strcmp(argv[i], "-compress")) ||
3136 (!strcmp(argv[i], "--compress"))) {
3137 lint->compress = 1;
3138 #endif
3139 #endif /* LIBXML_OUTPUT_ENABLED */
3140 #ifdef LIBXML_READER_ENABLED
3141 } else if ((!strcmp(argv[i], "-stream")) ||
3142 (!strcmp(argv[i], "--stream"))) {
3143 lint->stream = 1;
3144 } else if ((!strcmp(argv[i], "-walker")) ||
3145 (!strcmp(argv[i], "--walker"))) {
3146 lint->walker = 1;
3147 lint->noout = 1;
3148 #ifdef LIBXML_PATTERN_ENABLED
3149 } else if ((!strcmp(argv[i], "-pattern")) ||
3150 (!strcmp(argv[i], "--pattern"))) {
3151 i++;
3152 lint->pattern = argv[i];
3153 #endif
3154 #endif /* LIBXML_READER_ENABLED */
3155 #ifdef LIBXML_SAX1_ENABLED
3156 } else if ((!strcmp(argv[i], "-sax1")) ||
3157 (!strcmp(argv[i], "--sax1"))) {
3158 lint->options |= XML_PARSE_SAX1;
3159 #endif /* LIBXML_SAX1_ENABLED */
3160 } else if ((!strcmp(argv[i], "-sax")) ||
3161 (!strcmp(argv[i], "--sax"))) {
3162 lint->sax = 1;
3163 #ifdef LIBXML_SCHEMAS_ENABLED
3164 } else if ((!strcmp(argv[i], "-relaxng")) ||
3165 (!strcmp(argv[i], "--relaxng"))) {
3166 i++;
3167 lint->relaxng = argv[i];
3168 lint->options |= XML_PARSE_NOENT;
3169 } else if ((!strcmp(argv[i], "-schema")) ||
3170 (!strcmp(argv[i], "--schema"))) {
3171 i++;
3172 lint->schema = argv[i];
3173 lint->options |= XML_PARSE_NOENT;
3174 #endif
3175 #ifdef LIBXML_SCHEMATRON_ENABLED
3176 } else if ((!strcmp(argv[i], "-schematron")) ||
3177 (!strcmp(argv[i], "--schematron"))) {
3178 i++;
3179 lint->schematron = argv[i];
3180 lint->options |= XML_PARSE_NOENT;
3181 #endif
3182 } else if ((!strcmp(argv[i], "-nonet")) ||
3183 (!strcmp(argv[i], "--nonet"))) {
3184 lint->options |= XML_PARSE_NONET;
3185 } else if ((!strcmp(argv[i], "-nocompact")) ||
3186 (!strcmp(argv[i], "--nocompact"))) {
3187 lint->options &= ~XML_PARSE_COMPACT;
3188 } else if ((!strcmp(argv[i], "-load-trace")) ||
3189 (!strcmp(argv[i], "--load-trace"))) {
3190 lint->load_trace = 1;
3191 } else if ((!strcmp(argv[i], "-path")) ||
3192 (!strcmp(argv[i], "--path"))) {
3193 i++;
3194 parsePath(lint, BAD_CAST argv[i]);
3195 #ifdef LIBXML_XPATH_ENABLED
3196 } else if ((!strcmp(argv[i], "-xpath")) ||
3197 (!strcmp(argv[i], "--xpath"))) {
3198 i++;
3199 lint->noout++;
3200 lint->xpathquery = argv[i];
3201 #endif
3202 } else if ((!strcmp(argv[i], "-oldxml10")) ||
3203 (!strcmp(argv[i], "--oldxml10"))) {
3204 lint->options |= XML_PARSE_OLD10;
3205 } else if ((!strcmp(argv[i], "-max-ampl")) ||
3206 (!strcmp(argv[i], "--max-ampl"))) {
3207 i++;
3208 if (i >= argc) {
3209 fprintf(errStream, "max-ampl: missing integer value\n");
3210 return(XMLLINT_ERR_UNCLASS);
3211 }
3212 lint->maxAmpl = parseInteger(errStream, "max-ampl", argv[i],
3213 1, UINT_MAX);
3214 } else {
3215 fprintf(errStream, "Unknown option %s\n", argv[i]);
3216 usage(errStream, argv[0]);
3217 return(XMLLINT_ERR_UNCLASS);
3218 }
3219 }
3220
3221 if (lint->shell)
3222 lint->repeat = 1;
3223
3224 return(XMLLINT_RETURN_OK);
3225 }
3226
3227 int
xmllintMain(int argc,const char ** argv,FILE * errStream,xmlResourceLoader loader)3228 xmllintMain(int argc, const char **argv, FILE *errStream,
3229 xmlResourceLoader loader) {
3230 xmllintState state, *lint;
3231 int i, j, res;
3232 int files = 0;
3233
3234 #ifdef _WIN32
3235 _setmode(_fileno(stdin), _O_BINARY);
3236 _setmode(_fileno(stdout), _O_BINARY);
3237 _setmode(_fileno(stderr), _O_BINARY);
3238 #endif
3239
3240 lint = &state;
3241 xmllintInit(lint);
3242 lint->errStream = errStream;
3243 lint->defaultResourceLoader = loader;
3244
3245 res = xmllintParseOptions(lint, argc, argv);
3246 if (res != XMLLINT_RETURN_OK) {
3247 lint->progresult = res;
3248 goto error;
3249 }
3250
3251 if (lint->maxmem != 0) {
3252 xmllintMaxmem = 0;
3253 xmllintMaxmemReached = 0;
3254 xmllintOom = 0;
3255 xmlMemSetup(myFreeFunc, myMallocFunc, myReallocFunc, myStrdupFunc);
3256 }
3257
3258 LIBXML_TEST_VERSION
3259
3260 #ifdef LIBXML_CATALOG_ENABLED
3261 if (lint->nocatalogs == 0) {
3262 if (lint->catalogs) {
3263 const char *catal;
3264
3265 catal = getenv("SGML_CATALOG_FILES");
3266 if (catal != NULL) {
3267 xmlLoadCatalogs(catal);
3268 } else {
3269 fprintf(errStream, "Variable $SGML_CATALOG_FILES not set\n");
3270 }
3271 }
3272 }
3273 #endif
3274
3275 #ifdef LIBXML_OUTPUT_ENABLED
3276 {
3277 const char *indent = getenv("XMLLINT_INDENT");
3278 if (indent != NULL) {
3279 xmlTreeIndentString = indent;
3280 }
3281 }
3282 #endif
3283
3284 if (lint->htmlout) {
3285 lint->htmlBuf = xmlMalloc(HTML_BUF_SIZE);
3286 if (lint->htmlBuf == NULL) {
3287 lint->progresult = XMLLINT_ERR_MEM;
3288 goto error;
3289 }
3290
3291 if (!lint->nowrap) {
3292 fprintf(errStream,
3293 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n");
3294 fprintf(errStream,
3295 "\t\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n");
3296 fprintf(errStream,
3297 "<html><head><title>%s output</title></head>\n",
3298 argv[0]);
3299 fprintf(errStream,
3300 "<body bgcolor=\"#ffffff\"><h1 align=\"center\">%s output</h1>\n",
3301 argv[0]);
3302 }
3303 }
3304
3305 #ifdef LIBXML_SCHEMATRON_ENABLED
3306 if ((lint->schematron != NULL) && (lint->sax == 0)
3307 #ifdef LIBXML_READER_ENABLED
3308 && (lint->stream == 0)
3309 #endif /* LIBXML_READER_ENABLED */
3310 ) {
3311 xmlSchematronParserCtxtPtr ctxt;
3312
3313 /* forces loading the DTDs */
3314 lint->options |= XML_PARSE_DTDLOAD;
3315 if (lint->timing) {
3316 startTimer(lint);
3317 }
3318 ctxt = xmlSchematronNewParserCtxt(lint->schematron);
3319 if (ctxt == NULL) {
3320 lint->progresult = XMLLINT_ERR_MEM;
3321 goto error;
3322 }
3323 lint->wxschematron = xmlSchematronParse(ctxt);
3324 if (lint->wxschematron == NULL) {
3325 fprintf(errStream, "Schematron schema %s failed to compile\n",
3326 lint->schematron);
3327 lint->progresult = XMLLINT_ERR_SCHEMACOMP;
3328 goto error;
3329 }
3330 xmlSchematronFreeParserCtxt(ctxt);
3331 if (lint->timing) {
3332 endTimer(lint, "Compiling the schemas");
3333 }
3334 }
3335 #endif
3336
3337 #ifdef LIBXML_SCHEMAS_ENABLED
3338 if ((lint->relaxng != NULL) && (lint->sax == 0)
3339 #ifdef LIBXML_READER_ENABLED
3340 && (lint->stream == 0)
3341 #endif /* LIBXML_READER_ENABLED */
3342 ) {
3343 xmlRelaxNGParserCtxtPtr ctxt;
3344
3345 /* forces loading the DTDs */
3346 lint->options |= XML_PARSE_DTDLOAD;
3347 if (lint->timing) {
3348 startTimer(lint);
3349 }
3350 ctxt = xmlRelaxNGNewParserCtxt(lint->relaxng);
3351 if (ctxt == NULL) {
3352 lint->progresult = XMLLINT_ERR_MEM;
3353 goto error;
3354 }
3355 xmlRelaxNGSetResourceLoader(ctxt, xmllintResourceLoader, lint);
3356 lint->relaxngschemas = xmlRelaxNGParse(ctxt);
3357 if (lint->relaxngschemas == NULL) {
3358 fprintf(errStream, "Relax-NG schema %s failed to compile\n",
3359 lint->relaxng);
3360 lint->progresult = XMLLINT_ERR_SCHEMACOMP;
3361 goto error;
3362 }
3363 xmlRelaxNGFreeParserCtxt(ctxt);
3364 if (lint->timing) {
3365 endTimer(lint, "Compiling the schemas");
3366 }
3367 } else if ((lint->schema != NULL)
3368 #ifdef LIBXML_READER_ENABLED
3369 && (lint->stream == 0)
3370 #endif
3371 ) {
3372 xmlSchemaParserCtxtPtr ctxt;
3373
3374 if (lint->timing) {
3375 startTimer(lint);
3376 }
3377 ctxt = xmlSchemaNewParserCtxt(lint->schema);
3378 if (ctxt == NULL) {
3379 lint->progresult = XMLLINT_ERR_MEM;
3380 goto error;
3381 }
3382 xmlSchemaSetResourceLoader(ctxt, xmllintResourceLoader, lint);
3383 lint->wxschemas = xmlSchemaParse(ctxt);
3384 if (lint->wxschemas == NULL) {
3385 fprintf(errStream, "WXS schema %s failed to compile\n",
3386 lint->schema);
3387 lint->progresult = XMLLINT_ERR_SCHEMACOMP;
3388 goto error;
3389 }
3390 xmlSchemaFreeParserCtxt(ctxt);
3391 if (lint->timing) {
3392 endTimer(lint, "Compiling the schemas");
3393 }
3394 }
3395 #endif /* LIBXML_SCHEMAS_ENABLED */
3396
3397 #if defined(LIBXML_READER_ENABLED) && defined(LIBXML_PATTERN_ENABLED)
3398 if ((lint->pattern != NULL) && (lint->walker == 0)) {
3399 res = xmlPatternCompileSafe(BAD_CAST lint->pattern, NULL, 0, NULL,
3400 &lint->patternc);
3401 if (lint->patternc == NULL) {
3402 if (res < 0) {
3403 lint->progresult = XMLLINT_ERR_MEM;
3404 } else {
3405 fprintf(errStream, "Pattern %s failed to compile\n",
3406 lint->pattern);
3407 lint->progresult = XMLLINT_ERR_SCHEMAPAT;
3408 }
3409 goto error;
3410 }
3411 }
3412 #endif /* LIBXML_READER_ENABLED && LIBXML_PATTERN_ENABLED */
3413
3414 /*
3415 * The main loop over input documents
3416 */
3417 for (i = 1; i < argc ; i++) {
3418 const char *filename = argv[i];
3419 #if HAVE_DECL_MMAP
3420 int memoryFd = -1;
3421 #endif
3422
3423 if ((filename[0] == '-') && (strcmp(filename, "-") != 0)) {
3424 i += skipArgs(filename);
3425 continue;
3426 }
3427
3428 #if HAVE_DECL_MMAP
3429 if (lint->memory) {
3430 struct stat info;
3431 if (stat(filename, &info) < 0) {
3432 lint->progresult = XMLLINT_ERR_RDFILE;
3433 break;
3434 }
3435 memoryFd = open(filename, O_RDONLY);
3436 if (memoryFd < 0) {
3437 lint->progresult = XMLLINT_ERR_RDFILE;
3438 break;
3439 }
3440 lint->memoryData = mmap(NULL, info.st_size + 1, PROT_READ,
3441 MAP_SHARED, memoryFd, 0);
3442 if (lint->memoryData == (void *) MAP_FAILED) {
3443 close(memoryFd);
3444 fprintf(errStream, "mmap failure for file %s\n", filename);
3445 lint->progresult = XMLLINT_ERR_RDFILE;
3446 break;
3447 }
3448 lint->memorySize = info.st_size;
3449 }
3450 #endif /* HAVE_DECL_MMAP */
3451
3452 if ((lint->timing) && (lint->repeat > 1))
3453 startTimer(lint);
3454
3455 #ifdef LIBXML_READER_ENABLED
3456 if (lint->stream != 0) {
3457 for (j = 0; j < lint->repeat; j++)
3458 streamFile(lint, filename);
3459 } else
3460 #endif /* LIBXML_READER_ENABLED */
3461 {
3462 xmlParserCtxtPtr ctxt;
3463
3464 #ifdef LIBXML_HTML_ENABLED
3465 if (lint->html) {
3466 #ifdef LIBXML_PUSH_ENABLED
3467 if (lint->push) {
3468 ctxt = htmlCreatePushParserCtxt(NULL, NULL, NULL, 0,
3469 filename,
3470 XML_CHAR_ENCODING_NONE);
3471 htmlCtxtUseOptions(ctxt, lint->options);
3472 } else
3473 #endif /* LIBXML_PUSH_ENABLED */
3474 {
3475 ctxt = htmlNewParserCtxt();
3476 }
3477 } else
3478 #endif /* LIBXML_HTML_ENABLED */
3479 {
3480 #ifdef LIBXML_PUSH_ENABLED
3481 if (lint->push) {
3482 ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0,
3483 filename);
3484 xmlCtxtUseOptions(ctxt, lint->options);
3485 } else
3486 #endif /* LIBXML_PUSH_ENABLED */
3487 {
3488 ctxt = xmlNewParserCtxt();
3489 }
3490 }
3491 if (ctxt == NULL) {
3492 lint->progresult = XMLLINT_ERR_MEM;
3493 goto error;
3494 }
3495
3496 if (lint->sax) {
3497 const xmlSAXHandler *handler;
3498
3499 if (lint->noout) {
3500 handler = &emptySAXHandler;
3501 #ifdef LIBXML_SAX1_ENABLED
3502 } else if (lint->options & XML_PARSE_SAX1) {
3503 handler = &debugSAXHandler;
3504 #endif
3505 } else {
3506 handler = &debugSAX2Handler;
3507 }
3508
3509 *ctxt->sax = *handler;
3510 ctxt->userData = lint;
3511 }
3512
3513 xmlCtxtSetResourceLoader(ctxt, xmllintResourceLoader, lint);
3514 if (lint->maxAmpl > 0)
3515 xmlCtxtSetMaxAmplification(ctxt, lint->maxAmpl);
3516
3517 if (lint->htmlout) {
3518 ctxt->_private = lint;
3519 xmlCtxtSetErrorHandler(ctxt, xmlHTMLError, ctxt);
3520 }
3521
3522 lint->ctxt = ctxt;
3523
3524 for (j = 0; j < lint->repeat; j++) {
3525 #ifdef LIBXML_PUSH_ENABLED
3526 if ((lint->push) && (j > 0))
3527 xmlCtxtResetPush(ctxt, NULL, 0, NULL, NULL);
3528 #endif
3529 if (lint->sax) {
3530 testSAX(lint, filename);
3531 } else {
3532 parseAndPrintFile(lint, filename);
3533 }
3534 }
3535
3536 xmlFreeParserCtxt(ctxt);
3537 }
3538
3539 if ((lint->timing) && (lint->repeat > 1)) {
3540 endTimer(lint, "%d iterations", lint->repeat);
3541 }
3542
3543 files += 1;
3544
3545 #if HAVE_DECL_MMAP
3546 if (lint->memory) {
3547 munmap(lint->memoryData, lint->memorySize);
3548 close(memoryFd);
3549 }
3550 #endif
3551 }
3552
3553 if (lint->generate)
3554 parseAndPrintFile(lint, NULL);
3555
3556 if ((lint->htmlout) && (!lint->nowrap)) {
3557 fprintf(errStream, "</body></html>\n");
3558 }
3559
3560 if ((files == 0) && (!lint->generate) && (lint->version == 0)) {
3561 usage(errStream, argv[0]);
3562 lint->progresult = XMLLINT_ERR_UNCLASS;
3563 }
3564
3565 error:
3566
3567 if (lint->htmlout)
3568 xmlFree(lint->htmlBuf);
3569
3570 #ifdef LIBXML_SCHEMATRON_ENABLED
3571 if (lint->wxschematron != NULL)
3572 xmlSchematronFree(lint->wxschematron);
3573 #endif
3574 #ifdef LIBXML_SCHEMAS_ENABLED
3575 if (lint->relaxngschemas != NULL)
3576 xmlRelaxNGFree(lint->relaxngschemas);
3577 if (lint->wxschemas != NULL)
3578 xmlSchemaFree(lint->wxschemas);
3579 #endif
3580 #if defined(LIBXML_READER_ENABLED) && defined(LIBXML_PATTERN_ENABLED)
3581 if (lint->patternc != NULL)
3582 xmlFreePattern(lint->patternc);
3583 #endif
3584
3585 xmlCleanupParser();
3586
3587 if ((lint->maxmem) && (xmllintMaxmemReached)) {
3588 fprintf(errStream, "Maximum memory exceeded (%d bytes)\n",
3589 xmllintMaxmem);
3590 } else if (lint->progresult == XMLLINT_ERR_MEM) {
3591 fprintf(errStream, "Out-of-memory error reported\n");
3592 }
3593
3594 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
3595 if ((lint->maxmem) &&
3596 (xmllintOom != (lint->progresult == XMLLINT_ERR_MEM))) {
3597 fprintf(stderr, "xmllint: malloc failure %s reported\n",
3598 xmllintOom ? "not" : "erroneously");
3599 abort();
3600 }
3601 #endif
3602
3603 return(lint->progresult);
3604 }
3605
3606