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 74static int debug = 0; 75static int repeat = 0; 76static int timing = 0; 77static int dumpextensions = 0; 78static int novalid = 0; 79static int nodtdattr = 0; 80static int noout = 0; 81static int nodict = 0; 82#ifdef LIBXML_HTML_ENABLED 83static int html = 0; 84#endif 85static char *encoding = NULL; 86static int load_trace = 0; 87#ifdef LIBXML_XINCLUDE_ENABLED 88static int xinclude = 0; 89static int xincludestyle = 0; 90#endif 91static int profile = 0; 92 93#define MAX_PARAMETERS 64 94#define MAX_PATHS 64 95 96static int options = XSLT_PARSE_OPTIONS; 97static const char *params[MAX_PARAMETERS + 1]; 98static int nbparams = 0; 99static xmlChar *strparams[MAX_PARAMETERS + 1]; 100static int nbstrparams = 0; 101static xmlChar *paths[MAX_PATHS + 1]; 102static int nbpaths = 0; 103static char *output = NULL; 104static int errorno = 0; 105static const char *writesubtree = NULL; 106 107/* 108 * Entity loading control and customization. 109 */ 110static 111void 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 136xmlExternalEntityLoader defaultEntityLoader = NULL; 137 138static xmlParserInputPtr 139xsltprocExternalEntityLoader(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 219int 220my_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) 240static struct timeval begin, endtime; 241/* 242 * startTimer: call where you want to start timing 243 */ 244static 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 */ 253static 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 282clock_t begin, endtime; 283static void startTimer(void) 284{ 285 begin=clock(); 286} 287static 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 */ 307static void startTimer(void) 308{ 309 /* 310 * Do nothing 311 */ 312} 313static 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 */ 336static int 337xsltSubtreeCheck(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 354static void 355xsltProcess(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 499static 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 functions 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", xsltMaxDepth); 515 printf("\t--maxvars val : increase the maximum variables (default %d)\n", xsltMaxVars); 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) pair\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 546int 547main(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 } 891done: 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 905