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