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