OLD | NEW |
| (Empty) |
1 /* | |
2 * xsltproc.c: user program for the XSL Transformation 1.0 engine | |
3 * | |
4 * See Copyright for the status of this software. | |
5 * | |
6 * daniel@veillard.com | |
7 */ | |
8 | |
9 #include "libxslt/libxslt.h" | |
10 #include "libexslt/exslt.h" | |
11 #include <stdio.h> | |
12 #ifdef HAVE_STRING_H | |
13 #include <string.h> | |
14 #endif | |
15 #ifdef HAVE_SYS_TIME_H | |
16 #include <sys/time.h> | |
17 #endif | |
18 #ifdef HAVE_TIME_H | |
19 #include <time.h> | |
20 #endif | |
21 #ifdef HAVE_SYS_STAT_H | |
22 #include <sys/stat.h> | |
23 #endif | |
24 #ifdef HAVE_UNISTD_H | |
25 #include <unistd.h> | |
26 #endif | |
27 #ifdef HAVE_STDLIB_H | |
28 #include <stdlib.h> | |
29 #endif | |
30 #ifdef HAVE_STDARG_H | |
31 #include <stdarg.h> | |
32 #endif | |
33 #include <libxml/xmlmemory.h> | |
34 #include <libxml/debugXML.h> | |
35 #include <libxml/HTMLtree.h> | |
36 #include <libxml/xmlIO.h> | |
37 #ifdef LIBXML_XINCLUDE_ENABLED | |
38 #include <libxml/xinclude.h> | |
39 #endif | |
40 #ifdef LIBXML_CATALOG_ENABLED | |
41 #include <libxml/catalog.h> | |
42 #endif | |
43 #include <libxml/parser.h> | |
44 #include <libxml/parserInternals.h> | |
45 #include <libxml/uri.h> | |
46 | |
47 #include <libxslt/xslt.h> | |
48 #include <libxslt/xsltInternals.h> | |
49 #include <libxslt/transform.h> | |
50 #include <libxslt/xsltutils.h> | |
51 #include <libxslt/extensions.h> | |
52 #include <libxslt/security.h> | |
53 | |
54 #include <libexslt/exsltconfig.h> | |
55 | |
56 #if defined(WIN32) && !defined (__CYGWIN__) | |
57 #if defined(_MSC_VER) || defined(__MINGW32__) | |
58 #include <winsock2.h> | |
59 #define gettimeofday(p1,p2) | |
60 #define snprintf _snprintf | |
61 #endif /* _MS_VER */ | |
62 #else /* WIN32 */ | |
63 #if defined(HAVE_SYS_TIME_H) | |
64 #include <sys/time.h> | |
65 #elif defined(HAVE_TIME_H) | |
66 #include <time.h> | |
67 #endif | |
68 #endif /* WIN32 */ | |
69 | |
70 #ifdef HAVE_SYS_TIMEB_H | |
71 #include <sys/timeb.h> | |
72 #endif | |
73 | |
74 static int debug = 0; | |
75 static int repeat = 0; | |
76 static int timing = 0; | |
77 static int dumpextensions = 0; | |
78 static int novalid = 0; | |
79 static int nodtdattr = 0; | |
80 static int noout = 0; | |
81 static int nodict = 0; | |
82 #ifdef LIBXML_HTML_ENABLED | |
83 static int html = 0; | |
84 #endif | |
85 static char *encoding = NULL; | |
86 static int load_trace = 0; | |
87 #ifdef LIBXML_XINCLUDE_ENABLED | |
88 static int xinclude = 0; | |
89 static int xincludestyle = 0; | |
90 #endif | |
91 static int profile = 0; | |
92 | |
93 #define MAX_PARAMETERS 64 | |
94 #define MAX_PATHS 64 | |
95 | |
96 static int options = XSLT_PARSE_OPTIONS; | |
97 static const char *params[MAX_PARAMETERS + 1]; | |
98 static int nbparams = 0; | |
99 static xmlChar *strparams[MAX_PARAMETERS + 1]; | |
100 static int nbstrparams = 0; | |
101 static xmlChar *paths[MAX_PATHS + 1]; | |
102 static int nbpaths = 0; | |
103 static char *output = NULL; | |
104 static int errorno = 0; | |
105 static const char *writesubtree = NULL; | |
106 | |
107 /* | |
108 * Entity loading control and customization. | |
109 */ | |
110 static | |
111 void parsePath(const xmlChar *path) { | |
112 const xmlChar *cur; | |
113 | |
114 if (path == NULL) | |
115 return; | |
116 while (*path != 0) { | |
117 if (nbpaths >= MAX_PATHS) { | |
118 fprintf(stderr, "MAX_PATHS reached: too many paths\n"); | |
119 return; | |
120 } | |
121 cur = path; | |
122 while ((*cur == ' ') || (*cur == ':')) | |
123 cur++; | |
124 path = cur; | |
125 while ((*cur != 0) && (*cur != ' ') && (*cur != ':')) | |
126 cur++; | |
127 if (cur != path) { | |
128 paths[nbpaths] = xmlStrndup(path, cur - path); | |
129 if (paths[nbpaths] != NULL) | |
130 nbpaths++; | |
131 path = cur; | |
132 } | |
133 } | |
134 } | |
135 | |
136 xmlExternalEntityLoader defaultEntityLoader = NULL; | |
137 | |
138 static xmlParserInputPtr | |
139 xsltprocExternalEntityLoader(const char *URL, const char *ID, | |
140 xmlParserCtxtPtr ctxt) { | |
141 xmlParserInputPtr ret; | |
142 warningSAXFunc warning = NULL; | |
143 | |
144 int i; | |
145 const char *lastsegment = URL; | |
146 const char *iter = URL; | |
147 | |
148 if (nbpaths > 0) { | |
149 while (*iter != 0) { | |
150 if (*iter == '/') | |
151 lastsegment = iter + 1; | |
152 iter++; | |
153 } | |
154 } | |
155 | |
156 if ((ctxt != NULL) && (ctxt->sax != NULL)) { | |
157 warning = ctxt->sax->warning; | |
158 ctxt->sax->warning = NULL; | |
159 } | |
160 | |
161 if (defaultEntityLoader != NULL) { | |
162 ret = defaultEntityLoader(URL, ID, ctxt); | |
163 if (ret != NULL) { | |
164 if (warning != NULL) | |
165 ctxt->sax->warning = warning; | |
166 if (load_trace) { | |
167 fprintf \ | |
168 (stderr, | |
169 "Loaded URL=\"%s\" ID=\"%s\"\n", | |
170 URL ? URL : "(null)", | |
171 ID ? ID : "(null)"); | |
172 } | |
173 return(ret); | |
174 } | |
175 } | |
176 for (i = 0;i < nbpaths;i++) { | |
177 xmlChar *newURL; | |
178 | |
179 newURL = xmlStrdup((const xmlChar *) paths[i]); | |
180 newURL = xmlStrcat(newURL, (const xmlChar *) "/"); | |
181 newURL = xmlStrcat(newURL, (const xmlChar *) lastsegment); | |
182 if (newURL != NULL) { | |
183 ret = defaultEntityLoader((const char *)newURL, ID, ctxt); | |
184 if (ret != NULL) { | |
185 if (warning != NULL) | |
186 ctxt->sax->warning = warning; | |
187 if (load_trace) { | |
188 fprintf \ | |
189 (stderr, | |
190 "Loaded URL=\"%s\" ID=\"%s\"\n", | |
191 newURL, | |
192 ID ? ID : "(null)"); | |
193 } | |
194 xmlFree(newURL); | |
195 return(ret); | |
196 } | |
197 xmlFree(newURL); | |
198 } | |
199 } | |
200 if (warning != NULL) { | |
201 ctxt->sax->warning = warning; | |
202 if (URL != NULL) | |
203 warning(ctxt, "failed to load external entity \"%s\"\n", URL); | |
204 else if (ID != NULL) | |
205 warning(ctxt, "failed to load external entity \"%s\"\n", ID); | |
206 } | |
207 return(NULL); | |
208 } | |
209 | |
210 /* | |
211 * Internal timing routines to remove the necessity to have unix-specific | |
212 * function calls | |
213 */ | |
214 #ifndef HAVE_GETTIMEOFDAY | |
215 #ifdef HAVE_SYS_TIMEB_H | |
216 #ifdef HAVE_SYS_TIME_H | |
217 #ifdef HAVE_FTIME | |
218 | |
219 int | |
220 my_gettimeofday(struct timeval *tvp, void *tzp) | |
221 { | |
222 struct timeb timebuffer; | |
223 | |
224 ftime(&timebuffer); | |
225 if (tvp) { | |
226 tvp->tv_sec = timebuffer.time; | |
227 tvp->tv_usec = timebuffer.millitm * 1000L; | |
228 } | |
229 return (0); | |
230 } | |
231 #define HAVE_GETTIMEOFDAY 1 | |
232 #define gettimeofday my_gettimeofday | |
233 | |
234 #endif /* HAVE_FTIME */ | |
235 #endif /* HAVE_SYS_TIME_H */ | |
236 #endif /* HAVE_SYS_TIMEB_H */ | |
237 #endif /* !HAVE_GETTIMEOFDAY */ | |
238 | |
239 #if defined(HAVE_GETTIMEOFDAY) | |
240 static struct timeval begin, endtime; | |
241 /* | |
242 * startTimer: call where you want to start timing | |
243 */ | |
244 static void startTimer(void) | |
245 { | |
246 gettimeofday(&begin,NULL); | |
247 } | |
248 /* | |
249 * endTimer: call where you want to stop timing and to print out a | |
250 * message about the timing performed; format is a printf | |
251 * type argument | |
252 */ | |
253 static void endTimer(const char *format, ...) | |
254 { | |
255 long msec; | |
256 va_list ap; | |
257 | |
258 gettimeofday(&endtime, NULL); | |
259 msec = endtime.tv_sec - begin.tv_sec; | |
260 msec *= 1000; | |
261 msec += (endtime.tv_usec - begin.tv_usec) / 1000; | |
262 | |
263 #ifndef HAVE_STDARG_H | |
264 #error "endTimer required stdarg functions" | |
265 #endif | |
266 va_start(ap, format); | |
267 vfprintf(stderr,format,ap); | |
268 va_end(ap); | |
269 | |
270 fprintf(stderr, " took %ld ms\n", msec); | |
271 } | |
272 #elif defined(HAVE_TIME_H) | |
273 /* | |
274 * No gettimeofday function, so we have to make do with calling clock. | |
275 * This is obviously less accurate, but there's little we can do about | |
276 * that. | |
277 */ | |
278 #ifndef CLOCKS_PER_SEC | |
279 #define CLOCKS_PER_SEC 100 | |
280 #endif | |
281 | |
282 clock_t begin, endtime; | |
283 static void startTimer(void) | |
284 { | |
285 begin=clock(); | |
286 } | |
287 static void endTimer(char *format, ...) | |
288 { | |
289 long msec; | |
290 va_list ap; | |
291 | |
292 endtime=clock(); | |
293 msec = ((endtime-begin) * 1000) / CLOCKS_PER_SEC; | |
294 | |
295 #ifndef HAVE_STDARG_H | |
296 #error "endTimer required stdarg functions" | |
297 #endif | |
298 va_start(ap, format); | |
299 vfprintf(stderr,format,ap); | |
300 va_end(ap); | |
301 fprintf(stderr, " took %ld ms\n", msec); | |
302 } | |
303 #else | |
304 /* | |
305 * We don't have a gettimeofday or time.h, so we just don't do timing | |
306 */ | |
307 static void startTimer(void) | |
308 { | |
309 /* | |
310 * Do nothing | |
311 */ | |
312 } | |
313 static void endTimer(char *format, ...) | |
314 { | |
315 /* | |
316 * We cannot do anything because we don't have a timing function | |
317 */ | |
318 #ifdef HAVE_STDARG_H | |
319 va_start(ap, format); | |
320 vfprintf(stderr,format,ap); | |
321 va_end(ap); | |
322 fprintf(stderr, " was not timed\n", msec); | |
323 #else | |
324 /* We don't have gettimeofday, time or stdarg.h, what crazy world is | |
325 * this ?! | |
326 */ | |
327 #endif | |
328 } | |
329 #endif | |
330 | |
331 /* | |
332 * xsltSubtreeCheck: | |
333 * | |
334 * allow writes only on a subtree specified on the command line | |
335 */ | |
336 static int | |
337 xsltSubtreeCheck(xsltSecurityPrefsPtr sec ATTRIBUTE_UNUSED, | |
338 xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED, | |
339 const char *value ATTRIBUTE_UNUSED) { | |
340 int len, ret; | |
341 | |
342 if (writesubtree == NULL) | |
343 return(0); | |
344 if (value == NULL) | |
345 return(-1); | |
346 | |
347 len = xmlStrlen(BAD_CAST writesubtree); | |
348 ret = xmlStrncmp(BAD_CAST writesubtree, BAD_CAST value, len); | |
349 if (ret == 0) | |
350 return(1); | |
351 return(0); | |
352 } | |
353 | |
354 static void | |
355 xsltProcess(xmlDocPtr doc, xsltStylesheetPtr cur, const char *filename) { | |
356 xmlDocPtr res; | |
357 xsltTransformContextPtr ctxt; | |
358 | |
359 | |
360 #ifdef LIBXML_XINCLUDE_ENABLED | |
361 if (xinclude) { | |
362 int ret; | |
363 | |
364 if (timing) | |
365 startTimer(); | |
366 #if LIBXML_VERSION >= 20603 | |
367 ret = xmlXIncludeProcessFlags(doc, XSLT_PARSE_OPTIONS); | |
368 #else | |
369 ret = xmlXIncludeProcess(doc); | |
370 #endif | |
371 if (timing) { | |
372 endTimer("XInclude processing %s", filename); | |
373 } | |
374 | |
375 if (ret < 0) { | |
376 errorno = 6; | |
377 return; | |
378 } | |
379 } | |
380 #endif | |
381 if (timing) | |
382 startTimer(); | |
383 if (output == NULL) { | |
384 if (repeat) { | |
385 int j; | |
386 | |
387 for (j = 1; j < repeat; j++) { | |
388 res = xsltApplyStylesheet(cur, doc, params); | |
389 xmlFreeDoc(res); | |
390 xmlFreeDoc(doc); | |
391 #ifdef LIBXML_HTML_ENABLED | |
392 if (html) | |
393 doc = htmlReadFile(filename, encoding, options); | |
394 else | |
395 #endif | |
396 doc = xmlReadFile(filename, encoding, options); | |
397 } | |
398 } | |
399 ctxt = xsltNewTransformContext(cur, doc); | |
400 if (ctxt == NULL) | |
401 return; | |
402 xsltSetCtxtParseOptions(ctxt, options); | |
403 #ifdef LIBXML_XINCLUDE_ENABLED | |
404 if (xinclude) | |
405 ctxt->xinclude = 1; | |
406 #endif | |
407 if (profile) { | |
408 res = xsltApplyStylesheetUser(cur, doc, params, NULL, | |
409 stderr, ctxt); | |
410 } else { | |
411 res = xsltApplyStylesheetUser(cur, doc, params, NULL, | |
412 NULL, ctxt); | |
413 } | |
414 if (ctxt->state == XSLT_STATE_ERROR) | |
415 errorno = 9; | |
416 else if (ctxt->state == XSLT_STATE_STOPPED) | |
417 errorno = 10; | |
418 xsltFreeTransformContext(ctxt); | |
419 if (timing) { | |
420 if (repeat) | |
421 endTimer("Applying stylesheet %d times", repeat); | |
422 else | |
423 endTimer("Applying stylesheet"); | |
424 } | |
425 xmlFreeDoc(doc); | |
426 if (res == NULL) { | |
427 fprintf(stderr, "no result for %s\n", filename); | |
428 return; | |
429 } | |
430 if (noout) { | |
431 xmlFreeDoc(res); | |
432 return; | |
433 } | |
434 #ifdef LIBXML_DEBUG_ENABLED | |
435 if (debug) | |
436 xmlDebugDumpDocument(stdout, res); | |
437 else { | |
438 #endif | |
439 if (cur->methodURI == NULL) { | |
440 if (timing) | |
441 startTimer(); | |
442 xsltSaveResultToFile(stdout, res, cur); | |
443 if (timing) | |
444 endTimer("Saving result"); | |
445 } else { | |
446 if (xmlStrEqual | |
447 (cur->method, (const xmlChar *) "xhtml")) { | |
448 fprintf(stderr, "non standard output xhtml\n"); | |
449 if (timing) | |
450 startTimer(); | |
451 xsltSaveResultToFile(stdout, res, cur); | |
452 if (timing) | |
453 endTimer("Saving result"); | |
454 } else { | |
455 fprintf(stderr, | |
456 "Unsupported non standard output %s\n", | |
457 cur->method); | |
458 errorno = 7; | |
459 } | |
460 } | |
461 #ifdef LIBXML_DEBUG_ENABLED | |
462 } | |
463 #endif | |
464 | |
465 xmlFreeDoc(res); | |
466 } else { | |
467 int ret; | |
468 ctxt = xsltNewTransformContext(cur, doc); | |
469 if (ctxt == NULL) | |
470 return; | |
471 xsltSetCtxtParseOptions(ctxt, options); | |
472 #ifdef LIBXML_XINCLUDE_ENABLED | |
473 if (xinclude) | |
474 ctxt->xinclude = 1; | |
475 #endif | |
476 ctxt->maxTemplateDepth = xsltMaxDepth; | |
477 ctxt->maxTemplateVars = xsltMaxVars; | |
478 | |
479 if (profile) { | |
480 ret = xsltRunStylesheetUser(cur, doc, params, output, | |
481 NULL, NULL, stderr, ctxt); | |
482 } else { | |
483 ret = xsltRunStylesheetUser(cur, doc, params, output, | |
484 NULL, NULL, NULL, ctxt); | |
485 } | |
486 if (ret == -1) | |
487 errorno = 11; | |
488 else if (ctxt->state == XSLT_STATE_ERROR) | |
489 errorno = 9; | |
490 else if (ctxt->state == XSLT_STATE_STOPPED) | |
491 errorno = 10; | |
492 xsltFreeTransformContext(ctxt); | |
493 if (timing) | |
494 endTimer("Running stylesheet and saving result"); | |
495 xmlFreeDoc(doc); | |
496 } | |
497 } | |
498 | |
499 static void usage(const char *name) { | |
500 printf("Usage: %s [options] stylesheet file [file ...]\n", name); | |
501 printf(" Options:\n"); | |
502 printf("\t--version or -V: show the version of libxml and libxslt used\n"); | |
503 printf("\t--verbose or -v: show logs of what's happening\n"); | |
504 printf("\t--output file or -o file: save to a given file\n"); | |
505 printf("\t--timing: display the time used\n"); | |
506 printf("\t--repeat: run the transformation 20 times\n"); | |
507 #ifdef LIBXML_DEBUG_ENABLED | |
508 printf("\t--debug: dump the tree of the result instead\n"); | |
509 #endif | |
510 printf("\t--dumpextensions: dump the registered extension elements and funct
ions to stdout\n"); | |
511 printf("\t--novalid skip the DTD loading phase\n"); | |
512 printf("\t--nodtdattr do not default attributes from the DTD\n"); | |
513 printf("\t--noout: do not dump the result\n"); | |
514 printf("\t--maxdepth val : increase the maximum depth (default %d)\n", xsltM
axDepth); | |
515 printf("\t--maxvars val : increase the maximum variables (default %d)\n", xs
ltMaxVars); | |
516 printf("\t--maxparserdepth val : increase the maximum parser depth\n"); | |
517 #ifdef LIBXML_HTML_ENABLED | |
518 printf("\t--html: the input document is(are) an HTML file(s)\n"); | |
519 #endif | |
520 printf("\t--encoding: the input document character encoding\n"); | |
521 printf("\t--param name value : pass a (parameter,value) pair\n"); | |
522 printf("\t value is an UTF8 XPath expression.\n"); | |
523 printf("\t string values must be quoted like \"'string'\"\n or"); | |
524 printf("\t use stringparam to avoid it\n"); | |
525 printf("\t--stringparam name value : pass a (parameter, UTF8 string value) p
air\n"); | |
526 printf("\t--path 'paths': provide a set of paths for resources\n"); | |
527 printf("\t--nonet : refuse to fetch DTDs or entities over network\n"); | |
528 printf("\t--nowrite : refuse to write to any file or resource\n"); | |
529 printf("\t--nomkdir : refuse to create directories\n"); | |
530 printf("\t--writesubtree path : allow file write only with the path subtree\
n"); | |
531 #ifdef LIBXML_CATALOG_ENABLED | |
532 printf("\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n"); | |
533 printf("\t otherwise XML Catalogs starting from \n"); | |
534 printf("\t file:///etc/xml/catalog are activated by default\n"); | |
535 #endif | |
536 #ifdef LIBXML_XINCLUDE_ENABLED | |
537 printf("\t--xinclude : do XInclude processing on document input\n"); | |
538 printf("\t--xincludestyle : do XInclude processing on stylesheets\n"); | |
539 #endif | |
540 printf("\t--load-trace : print trace of all external entites loaded\n"); | |
541 printf("\t--profile or --norman : dump profiling informations \n"); | |
542 printf("\nProject libxslt home page: http://xmlsoft.org/XSLT/\n"); | |
543 printf("To report bugs and get help: http://xmlsoft.org/XSLT/bugs.html\n"); | |
544 } | |
545 | |
546 int | |
547 main(int argc, char **argv) | |
548 { | |
549 int i; | |
550 xsltStylesheetPtr cur = NULL; | |
551 xmlDocPtr doc, style; | |
552 xsltSecurityPrefsPtr sec = NULL; | |
553 | |
554 if (argc <= 1) { | |
555 usage(argv[0]); | |
556 return (1); | |
557 } | |
558 | |
559 xmlInitMemory(); | |
560 | |
561 LIBXML_TEST_VERSION | |
562 | |
563 sec = xsltNewSecurityPrefs(); | |
564 xsltSetDefaultSecurityPrefs(sec); | |
565 defaultEntityLoader = xmlGetExternalEntityLoader(); | |
566 xmlSetExternalEntityLoader(xsltprocExternalEntityLoader); | |
567 | |
568 for (i = 1; i < argc; i++) { | |
569 if (!strcmp(argv[i], "-")) | |
570 break; | |
571 | |
572 if (argv[i][0] != '-') | |
573 continue; | |
574 #ifdef LIBXML_DEBUG_ENABLED | |
575 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug"))) { | |
576 debug++; | |
577 } else | |
578 #endif | |
579 if ((!strcmp(argv[i], "-v")) || | |
580 (!strcmp(argv[i], "-verbose")) || | |
581 (!strcmp(argv[i], "--verbose"))) { | |
582 xsltSetGenericDebugFunc(stderr, NULL); | |
583 } else if ((!strcmp(argv[i], "-o")) || | |
584 (!strcmp(argv[i], "-output")) || | |
585 (!strcmp(argv[i], "--output"))) { | |
586 i++; | |
587 #if defined(WIN32) || defined (__CYGWIN__) | |
588 output = xmlCanonicPath(argv[i]); | |
589 if (output == NULL) | |
590 #endif | |
591 output = (char *) xmlStrdup((xmlChar *) argv[i]); | |
592 } else if ((!strcmp(argv[i], "-V")) || | |
593 (!strcmp(argv[i], "-version")) || | |
594 (!strcmp(argv[i], "--version"))) { | |
595 printf("Using libxml %s, libxslt %s and libexslt %s\n", | |
596 xmlParserVersion, xsltEngineVersion, exsltLibraryVersion); | |
597 printf | |
598 ("xsltproc was compiled against libxml %d, libxslt %d and libexslt %d\n", | |
599 LIBXML_VERSION, LIBXSLT_VERSION, LIBEXSLT_VERSION); | |
600 printf("libxslt %d was compiled against libxml %d\n", | |
601 xsltLibxsltVersion, xsltLibxmlVersion); | |
602 printf("libexslt %d was compiled against libxml %d\n", | |
603 exsltLibexsltVersion, exsltLibxmlVersion); | |
604 } else if ((!strcmp(argv[i], "-repeat")) | |
605 || (!strcmp(argv[i], "--repeat"))) { | |
606 if (repeat == 0) | |
607 repeat = 20; | |
608 else | |
609 repeat = 100; | |
610 } else if ((!strcmp(argv[i], "-novalid")) || | |
611 (!strcmp(argv[i], "--novalid"))) { | |
612 novalid++; | |
613 } else if ((!strcmp(argv[i], "-nodtdattr")) || | |
614 (!strcmp(argv[i], "--nodtdattr"))) { | |
615 nodtdattr++; | |
616 } else if ((!strcmp(argv[i], "-noout")) || | |
617 (!strcmp(argv[i], "--noout"))) { | |
618 noout++; | |
619 #ifdef LIBXML_HTML_ENABLED | |
620 } else if ((!strcmp(argv[i], "-html")) || | |
621 (!strcmp(argv[i], "--html"))) { | |
622 html++; | |
623 #endif | |
624 } else if ((!strcmp(argv[i], "-encoding")) || | |
625 (!strcmp(argv[i], "--encoding"))) { | |
626 encoding = argv[++i]; | |
627 } else if ((!strcmp(argv[i], "-timing")) || | |
628 (!strcmp(argv[i], "--timing"))) { | |
629 timing++; | |
630 } else if ((!strcmp(argv[i], "-profile")) || | |
631 (!strcmp(argv[i], "--profile"))) { | |
632 profile++; | |
633 } else if ((!strcmp(argv[i], "-nodict")) || | |
634 (!strcmp(argv[i], "--nodict"))) { | |
635 nodict++; | |
636 } else if ((!strcmp(argv[i], "-norman")) || | |
637 (!strcmp(argv[i], "--norman"))) { | |
638 profile++; | |
639 } else if ((!strcmp(argv[i], "-nonet")) || | |
640 (!strcmp(argv[i], "--nonet"))) { | |
641 defaultEntityLoader = xmlNoNetExternalEntityLoader; | |
642 } else if ((!strcmp(argv[i], "-nowrite")) || | |
643 (!strcmp(argv[i], "--nowrite"))) { | |
644 xsltSetSecurityPrefs(sec, XSLT_SECPREF_WRITE_FILE, | |
645 xsltSecurityForbid); | |
646 xsltSetSecurityPrefs(sec, XSLT_SECPREF_CREATE_DIRECTORY, | |
647 xsltSecurityForbid); | |
648 xsltSetSecurityPrefs(sec, XSLT_SECPREF_WRITE_NETWORK, | |
649 xsltSecurityForbid); | |
650 } else if ((!strcmp(argv[i], "-nomkdir")) || | |
651 (!strcmp(argv[i], "--nomkdir"))) { | |
652 xsltSetSecurityPrefs(sec, XSLT_SECPREF_CREATE_DIRECTORY, | |
653 xsltSecurityForbid); | |
654 } else if ((!strcmp(argv[i], "-writesubtree")) || | |
655 (!strcmp(argv[i], "--writesubtree"))) { | |
656 i++; | |
657 writesubtree = argv[i]; | |
658 xsltSetSecurityPrefs(sec, XSLT_SECPREF_WRITE_FILE, | |
659 xsltSubtreeCheck); | |
660 } else if ((!strcmp(argv[i], "-path")) || | |
661 (!strcmp(argv[i], "--path"))) { | |
662 i++; | |
663 parsePath(BAD_CAST argv[i]); | |
664 #ifdef LIBXML_CATALOG_ENABLED | |
665 } else if ((!strcmp(argv[i], "-catalogs")) || | |
666 (!strcmp(argv[i], "--catalogs"))) { | |
667 const char *catalogs; | |
668 | |
669 catalogs = getenv("SGML_CATALOG_FILES"); | |
670 if (catalogs == NULL) { | |
671 fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n"); | |
672 } else { | |
673 xmlLoadCatalogs(catalogs); | |
674 } | |
675 #endif | |
676 #ifdef LIBXML_XINCLUDE_ENABLED | |
677 } else if ((!strcmp(argv[i], "-xinclude")) || | |
678 (!strcmp(argv[i], "--xinclude"))) { | |
679 xinclude++; | |
680 } else if ((!strcmp(argv[i], "-xincludestyle")) || | |
681 (!strcmp(argv[i], "--xincludestyle"))) { | |
682 xincludestyle++; | |
683 xsltSetXIncludeDefault(1); | |
684 #endif | |
685 } else if ((!strcmp(argv[i], "-load-trace")) || | |
686 (!strcmp(argv[i], "--load-trace"))) { | |
687 load_trace++; | |
688 } else if ((!strcmp(argv[i], "-param")) || | |
689 (!strcmp(argv[i], "--param"))) { | |
690 i++; | |
691 params[nbparams++] = argv[i++]; | |
692 params[nbparams++] = argv[i]; | |
693 if (nbparams >= MAX_PARAMETERS) { | |
694 fprintf(stderr, "too many params increase MAX_PARAMETERS \n"); | |
695 return (2); | |
696 } | |
697 } else if ((!strcmp(argv[i], "-stringparam")) || | |
698 (!strcmp(argv[i], "--stringparam"))) { | |
699 const xmlChar *string; | |
700 xmlChar *value; | |
701 | |
702 i++; | |
703 params[nbparams++] = argv[i++]; | |
704 string = (const xmlChar *) argv[i]; | |
705 if (xmlStrchr(string, '"')) { | |
706 if (xmlStrchr(string, '\'')) { | |
707 fprintf(stderr, | |
708 "stringparam contains both quote and double-quotes !\n"); | |
709 return(8); | |
710 } | |
711 value = xmlStrdup((const xmlChar *)"'"); | |
712 value = xmlStrcat(value, string); | |
713 value = xmlStrcat(value, (const xmlChar *)"'"); | |
714 } else { | |
715 value = xmlStrdup((const xmlChar *)"\""); | |
716 value = xmlStrcat(value, string); | |
717 value = xmlStrcat(value, (const xmlChar *)"\""); | |
718 } | |
719 | |
720 params[nbparams++] = (const char *) value; | |
721 strparams[nbstrparams++] = value; | |
722 if (nbparams >= MAX_PARAMETERS) { | |
723 fprintf(stderr, "too many params increase MAX_PARAMETERS \n"); | |
724 return (2); | |
725 } | |
726 } else if ((!strcmp(argv[i], "-maxdepth")) || | |
727 (!strcmp(argv[i], "--maxdepth"))) { | |
728 int value; | |
729 | |
730 i++; | |
731 if (sscanf(argv[i], "%d", &value) == 1) { | |
732 if (value > 0) | |
733 xsltMaxDepth = value; | |
734 } | |
735 } else if ((!strcmp(argv[i], "-maxvars")) || | |
736 (!strcmp(argv[i], "--maxvars"))) { | |
737 int value; | |
738 | |
739 i++; | |
740 if (sscanf(argv[i], "%d", &value) == 1) { | |
741 if (value > 0) | |
742 xsltMaxVars = value; | |
743 } | |
744 } else if ((!strcmp(argv[i], "-maxparserdepth")) || | |
745 (!strcmp(argv[i], "--maxparserdepth"))) { | |
746 int value; | |
747 | |
748 i++; | |
749 if (sscanf(argv[i], "%d", &value) == 1) { | |
750 if (value > 0) | |
751 xmlParserMaxDepth = value; | |
752 } | |
753 } else if ((!strcmp(argv[i],"-dumpextensions"))|| | |
754 (!strcmp(argv[i],"--dumpextensions"))) { | |
755 dumpextensions++; | |
756 } else { | |
757 fprintf(stderr, "Unknown option %s\n", argv[i]); | |
758 usage(argv[0]); | |
759 return (3); | |
760 } | |
761 } | |
762 params[nbparams] = NULL; | |
763 | |
764 if (novalid != 0) | |
765 options = XML_PARSE_NOENT | XML_PARSE_NOCDATA; | |
766 else if (nodtdattr) | |
767 options = XML_PARSE_NOENT | XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA; | |
768 if (nodict != 0) | |
769 options |= XML_PARSE_NODICT; | |
770 | |
771 /* | |
772 * Register the EXSLT extensions and the test module | |
773 */ | |
774 exsltRegisterAll(); | |
775 xsltRegisterTestModule(); | |
776 | |
777 if (dumpextensions) | |
778 xsltDebugDumpExtensions(NULL); | |
779 | |
780 for (i = 1; i < argc; i++) { | |
781 if ((!strcmp(argv[i], "-maxdepth")) || | |
782 (!strcmp(argv[i], "--maxdepth"))) { | |
783 i++; | |
784 continue; | |
785 } else if ((!strcmp(argv[i], "-maxparserdepth")) || | |
786 (!strcmp(argv[i], "--maxparserdepth"))) { | |
787 i++; | |
788 continue; | |
789 } else if ((!strcmp(argv[i], "-o")) || | |
790 (!strcmp(argv[i], "-output")) || | |
791 (!strcmp(argv[i], "--output"))) { | |
792 i++; | |
793 continue; | |
794 } else if ((!strcmp(argv[i], "-encoding")) || | |
795 (!strcmp(argv[i], "--encoding"))) { | |
796 i++; | |
797 continue; | |
798 } else if ((!strcmp(argv[i], "-writesubtree")) || | |
799 (!strcmp(argv[i], "--writesubtree"))) { | |
800 i++; | |
801 continue; | |
802 } else if ((!strcmp(argv[i], "-path")) || | |
803 (!strcmp(argv[i], "--path"))) { | |
804 i++; | |
805 continue; | |
806 } | |
807 if ((!strcmp(argv[i], "-param")) || (!strcmp(argv[i], "--param"))) { | |
808 i += 2; | |
809 continue; | |
810 } | |
811 if ((!strcmp(argv[i], "-stringparam")) || | |
812 (!strcmp(argv[i], "--stringparam"))) { | |
813 i += 2; | |
814 continue; | |
815 } | |
816 if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) { | |
817 if (timing) | |
818 startTimer(); | |
819 style = xmlReadFile((const char *) argv[i], NULL, options); | |
820 if (timing) | |
821 endTimer("Parsing stylesheet %s", argv[i]); | |
822 #ifdef LIBXML_XINCLUDE_ENABLED | |
823 if (xincludestyle) { | |
824 if (style != NULL) { | |
825 if (timing) | |
826 startTimer(); | |
827 #if LIBXML_VERSION >= 20603 | |
828 xmlXIncludeProcessFlags(style, XSLT_PARSE_OPTIONS); | |
829 #else | |
830 xmlXIncludeProcess(style); | |
831 #endif | |
832 if (timing) { | |
833 endTimer("XInclude processing %s", argv[i]); | |
834 } | |
835 } | |
836 } | |
837 #endif | |
838 if (style == NULL) { | |
839 fprintf(stderr, "cannot parse %s\n", argv[i]); | |
840 cur = NULL; | |
841 errorno = 4; | |
842 } else { | |
843 cur = xsltLoadStylesheetPI(style); | |
844 if (cur != NULL) { | |
845 /* it is an embedded stylesheet */ | |
846 xsltProcess(style, cur, argv[i]); | |
847 xsltFreeStylesheet(cur); | |
848 cur = NULL; | |
849 goto done; | |
850 } | |
851 cur = xsltParseStylesheetDoc(style); | |
852 if (cur != NULL) { | |
853 if (cur->errors != 0) { | |
854 errorno = 5; | |
855 goto done; | |
856 } | |
857 i++; | |
858 } else { | |
859 xmlFreeDoc(style); | |
860 errorno = 5; | |
861 goto done; | |
862 } | |
863 } | |
864 break; | |
865 | |
866 } | |
867 } | |
868 | |
869 | |
870 if ((cur != NULL) && (cur->errors == 0)) { | |
871 for (; i < argc; i++) { | |
872 doc = NULL; | |
873 if (timing) | |
874 startTimer(); | |
875 #ifdef LIBXML_HTML_ENABLED | |
876 if (html) | |
877 doc = htmlReadFile(argv[i], encoding, options); | |
878 else | |
879 #endif | |
880 doc = xmlReadFile(argv[i], encoding, options); | |
881 if (doc == NULL) { | |
882 fprintf(stderr, "unable to parse %s\n", argv[i]); | |
883 errorno = 6; | |
884 continue; | |
885 } | |
886 if (timing) | |
887 endTimer("Parsing document %s", argv[i]); | |
888 xsltProcess(doc, cur, argv[i]); | |
889 } | |
890 } | |
891 done: | |
892 if (cur != NULL) | |
893 xsltFreeStylesheet(cur); | |
894 for (i = 0;i < nbstrparams;i++) | |
895 xmlFree(strparams[i]); | |
896 if (output != NULL) | |
897 xmlFree(output); | |
898 xsltFreeSecurityPrefs(sec); | |
899 xsltCleanupGlobals(); | |
900 xmlCleanupParser(); | |
901 xmlMemoryDump(); | |
902 return(errorno); | |
903 } | |
904 | |
OLD | NEW |