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 |