libxslt_processor.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844
  1. #include "jliball.hpp"
  2. #include <string.h>
  3. #include <libxml/xmlmemory.h>
  4. #include <libxml/parserInternals.h>
  5. #include <libxml/debugXML.h>
  6. #include <libxml/HTMLtree.h>
  7. #include <libxml/xmlIO.h>
  8. #include <libxml/xinclude.h>
  9. #include <libxml/catalog.h>
  10. #include <libxml/xpathInternals.h>
  11. #include <libxslt/xslt.h>
  12. #include <libxslt/xsltInternals.h>
  13. #include <libxslt/transform.h>
  14. #include <libxslt/documents.h>
  15. #include <libxslt/xsltutils.h>
  16. #include <libxslt/extensions.h>
  17. #include <libxslt/variables.h>
  18. #include <libexslt/exslt.h>
  19. #ifdef _WIN32
  20. #undef new
  21. #undef delete
  22. #endif
  23. #include "xslprocessor.hpp"
  24. #include "xslcache.hpp"
  25. #include "xmlerror.hpp"
  26. extern int xmlLoadExtDtdDefaultValue;
  27. xsltDocLoaderFunc originalLibXsltIncludeHandler = NULL;
  28. xmlDocPtr libXsltIncludeHandler(const xmlChar * URI, xmlDictPtr dict, int options, IIncludeHandler* handler, xsltLoadType type);
  29. xmlDocPtr globalLibXsltIncludeHandler(const xmlChar * URI, xmlDictPtr dict, int options, void *ctx, xsltLoadType type);
  30. void libxsltCustomMessageHandler(StringBuffer& out, const char* in, IXslTransform* transform);
  31. class CLibXsltSource : public CInterface, implements IXslBuffer
  32. {
  33. public:
  34. IMPLEMENT_IINTERFACE;
  35. CLibXsltSource(const char* fname) : filename(fname), cacheId(fname), compiledXslt(NULL)
  36. {
  37. srcType = IO_TYPE_FILE;
  38. }
  39. CLibXsltSource(IIncludeHandler *handler, const char* rootpath, const char *_cacheId) : cacheId(_cacheId), compiledXslt(NULL), filename(rootpath)
  40. {
  41. srcType = IO_TYPE_BUFFER;
  42. bool pathOnly=false;
  43. MemoryBuffer mb;
  44. if (!handler->getInclude(rootpath, mb, pathOnly) || pathOnly || !mb.length())
  45. throw MakeStringException(XSLERR_InvalidSource, "Failed to load XSLT resource path %s\n", rootpath);
  46. text.set(mb.toByteArray(), mb.length());
  47. StringBuffer s("file://");
  48. if (*rootpath!='/')
  49. s.append('/');
  50. filename.set(s.append(rootpath).str());
  51. }
  52. CLibXsltSource(const char* s, int len, const char *_cacheId) : cacheId(_cacheId), compiledXslt(NULL)
  53. {
  54. srcType = IO_TYPE_BUFFER;
  55. text.set(s, len);
  56. filename.set("buffer.xslt");
  57. }
  58. virtual ~CLibXsltSource()
  59. {
  60. if (compiledXslt)
  61. xsltFreeStylesheet(compiledXslt);
  62. }
  63. virtual void compile();
  64. virtual bool isCompiled() const {return compiledXslt!=NULL;}
  65. virtual IO_Type getType() {return srcType;}
  66. virtual const char* getFileName(){return filename.get();}
  67. virtual char* getBuf(){return (char*)text.get();}
  68. virtual int getLen(){return text.length();}
  69. virtual StringArray& getIncludes(){return includes;}
  70. virtual const char *getCacheId(){return cacheId.get();}
  71. void setIncludeHandler(IIncludeHandler* handler){includeHandler.set(handler);}
  72. xsltStylesheetPtr getCompiledXslt();
  73. xsltStylesheetPtr parseXsltFile();
  74. public:
  75. IO_Type srcType;
  76. StringAttr filename;
  77. StringAttr cacheId;
  78. StringAttr text;
  79. Owned<IIncludeHandler> includeHandler;
  80. StringArray includes;
  81. xsltStylesheetPtr compiledXslt;
  82. };
  83. xsltStylesheetPtr CLibXsltSource::getCompiledXslt()
  84. {
  85. if (compiledXslt)
  86. return compiledXslt;
  87. IXslCache* xslcache = getXslCache();
  88. if (xslcache)
  89. {
  90. IXslBuffer* xslbuffer = xslcache->getCompiledXsl(this, false);
  91. if (xslbuffer)
  92. return ((CLibXsltSource*)xslbuffer)->compiledXslt;
  93. }
  94. compile();
  95. return compiledXslt;
  96. }
  97. xsltStylesheetPtr CLibXsltSource::parseXsltFile()
  98. {
  99. if (filename.isEmpty())
  100. return NULL;
  101. xmlDocPtr doc = xsltDocDefaultLoader((xmlChar *)filename.get(), NULL, XSLT_PARSE_OPTIONS, NULL, XSLT_LOAD_START);
  102. if (!doc)
  103. throw MakeStringException(XSLERR_InvalidSource, "Failed to parse XSLT source\n");
  104. doc->_private = static_cast<void *>(this);
  105. xsltStylesheetPtr style = xsltParseStylesheetDoc(doc);
  106. if (!style)
  107. {
  108. xmlFreeDoc(doc);
  109. throw MakeStringException(XSLERR_InvalidSource, "Failed to parse XSLT source\n");
  110. }
  111. return style;
  112. }
  113. void CLibXsltSource::compile()
  114. {
  115. if (!compiledXslt)
  116. {
  117. if ((srcType == IO_TYPE_FILE && filename.isEmpty()) || (srcType == IO_TYPE_BUFFER && text.isEmpty()))
  118. throw MakeStringException(XSLERR_MissingSource, "xslt source not set");
  119. if (compiledXslt != NULL)
  120. {
  121. xsltFreeStylesheet(compiledXslt);
  122. compiledXslt = NULL;
  123. }
  124. try
  125. {
  126. if (srcType == IO_TYPE_FILE)
  127. compiledXslt = parseXsltFile();
  128. else if (srcType == IO_TYPE_BUFFER)
  129. {
  130. xmlDocPtr xsldoc = xmlReadMemory(text.get(), text.length(), filename.get(), NULL, 0);
  131. if (!xsldoc)
  132. throw MakeStringException(XSLERR_InvalidSource, "XSLT source contains invalid XML\n");
  133. xsldoc->_private=(void*)this;
  134. compiledXslt = xsltParseStylesheetDoc(xsldoc);
  135. if (!compiledXslt)
  136. throw MakeStringException(XSLERR_InvalidSource, "Failed to parse XSLT source\n");
  137. }
  138. if (compiledXslt)
  139. compiledXslt->_private = (void*)this;
  140. }
  141. catch(...)
  142. {
  143. compiledXslt = NULL;
  144. throw;
  145. }
  146. }
  147. }
  148. class CLibXmlSource : public CInterface, implements IInterface
  149. {
  150. public:
  151. IMPLEMENT_IINTERFACE;
  152. CLibXmlSource(const char* fname)
  153. {
  154. filename.set(fname);
  155. srcType = IO_TYPE_FILE;
  156. parsedXml = NULL;
  157. }
  158. CLibXmlSource(const char* buf, int len)
  159. {
  160. text.set(buf, len);
  161. srcType = IO_TYPE_BUFFER;
  162. parsedXml = NULL;
  163. }
  164. virtual ~CLibXmlSource()
  165. {
  166. if (parsedXml)
  167. xmlFreeDoc(parsedXml);
  168. }
  169. xmlDocPtr getParsedXml();
  170. bool isCompiled() const {return parsedXml!=NULL;}
  171. public:
  172. IO_Type srcType;
  173. StringAttr filename;
  174. StringAttr text;
  175. xmlDocPtr parsedXml;
  176. };
  177. xmlDocPtr CLibXmlSource::getParsedXml()
  178. {
  179. if (!parsedXml)
  180. {
  181. if ((srcType == IO_TYPE_FILE && filename.isEmpty()) ||
  182. (srcType == IO_TYPE_BUFFER && text.isEmpty()))
  183. throw MakeStringException(XSLERR_MissingXml, "xml source not set");
  184. if (parsedXml)
  185. {
  186. xmlFreeDoc(parsedXml);
  187. parsedXml = NULL;
  188. }
  189. try
  190. {
  191. if (srcType == IO_TYPE_FILE)
  192. parsedXml = xmlParseFile(filename.get());
  193. else if (srcType == IO_TYPE_BUFFER)
  194. parsedXml = xmlReadMemory(text.get(), text.length(), "source.xml", NULL, 0);
  195. }
  196. catch(...)
  197. {
  198. parsedXml = NULL;
  199. throw;
  200. }
  201. }
  202. return parsedXml;
  203. }
  204. class CLibXsltResultTarget : public CInterface, implements IInterface
  205. {
  206. private:
  207. IO_Type destType;
  208. StringAttr filename;
  209. char* dest;
  210. int maxLen;
  211. public:
  212. IMPLEMENT_IINTERFACE;
  213. CLibXsltResultTarget(const char* _filename) : filename(_filename)
  214. {
  215. destType = IO_TYPE_FILE;
  216. }
  217. CLibXsltResultTarget(char* _buffer, int _len) : dest(_buffer), maxLen(_len)
  218. {
  219. destType = IO_TYPE_BUFFER;
  220. }
  221. void process(const char* content, int contLen)
  222. {
  223. if (destType == IO_TYPE_FILE)
  224. {
  225. Owned<IFile> f = createIFile(filename.get());
  226. Owned<IFileIO> fio = f->open(IFOwrite);
  227. fio->write(0, contLen, content);
  228. }
  229. else
  230. {
  231. if (contLen>maxLen)
  232. throw MakeStringException(XSLERR_TargetBufferToSmall, "XSLT Output greater than target buffer size");
  233. memcpy((void*)dest, content, contLen);
  234. dest[contLen] = '\0';
  235. }
  236. }
  237. };
  238. typedef void TextFunctionType(StringBuffer& out, const char* pszIn, IXslTransform* pTransform);
  239. class CLibXslFunction : public CInterface, implements IXslFunction
  240. {
  241. public:
  242. IMPLEMENT_IINTERFACE;
  243. CLibXslFunction(const char* _name, TextFunctionType* _fn, IXslTransform* trans)
  244. : name(_name), fn(_fn), parent(trans), assigned(false) {}
  245. virtual ~CLibXslFunction(){}
  246. virtual const char* getName() const
  247. {
  248. return name.get();
  249. }
  250. virtual bool isAssigned ()
  251. {
  252. return assigned;
  253. }
  254. virtual void setAssigned(bool bAssigned)
  255. {
  256. assigned = bAssigned;
  257. }
  258. virtual void setURI(const char *_uri)
  259. {
  260. if (uri.isEmpty())
  261. uri.set(_uri);
  262. else if (!streq(uri.get(), _uri))
  263. throw MakeStringException(XSLERR_ExtenrnalFunctionMultipleURIs, "The same function cannot be assigned to multiple URIs");
  264. }
  265. public:
  266. StringAttr name;
  267. StringAttr uri;
  268. TextFunctionType* fn;
  269. bool assigned;
  270. IXslTransform* parent;
  271. };
  272. class CLibXslTransform : public CInterface, implements IXslTransform
  273. {
  274. public:
  275. IMPLEMENT_IINTERFACE;
  276. CLibXslTransform();
  277. ~CLibXslTransform();
  278. virtual int transform();
  279. virtual int transform(StringBuffer &s);
  280. virtual int transform(ISocket* targetSocket);
  281. int transform(xmlChar **xmlbuff, int &len);
  282. virtual int setXmlSource(const char *pszFileName);
  283. virtual int setXmlSource(const char *pszBuffer, unsigned int nSize);
  284. virtual int setXslSource(const char *pszBuffer, unsigned int nSize, const char *cacheId, const char *rootpath);
  285. virtual int setXslNoCache(const char *pszBuffer, unsigned int nSize, const char *rootpath=NULL);
  286. virtual int loadXslFromFile(const char *pszFileName, const char *altCacheId=NULL);
  287. virtual int loadXslFromEmbedded(const char *path, const char *cacheId);
  288. virtual int setResultTarget(char *pszBuffer, unsigned int nSize);
  289. virtual int setResultTarget(const char *pszFileName);
  290. virtual int closeResultTarget();
  291. virtual int setParameter(const char *pszName, const char *pszExpression);
  292. virtual void copyParameters(IProperties *params);
  293. virtual int setStringParameter(const char *pszName, const char* pszString);
  294. bool checkSanity();
  295. virtual int setIncludeHandler(IIncludeHandler* handler)
  296. {
  297. includeHandler.set(handler);
  298. return 0;
  299. }
  300. virtual IXslFunction* createExternalFunction( const char* name, TextFunctionType *fn)
  301. {
  302. return new CLibXslFunction(name, fn, this);
  303. }
  304. virtual int setExternalFunction(const char* ns, IXslFunction* xfn, bool set);
  305. IXslFunction* queryExternalFunction(const char *ns, const char* name)
  306. {
  307. StringBuffer s(ns);
  308. return functions.getValue(s.append(':').append(name).str());
  309. }
  310. virtual const char* getLastError() const
  311. {
  312. return ""; //was xalan specific pass through
  313. }
  314. virtual const char* getMessages() const
  315. {
  316. return messages.str();
  317. }
  318. virtual void setUserData(void* _userData)
  319. {
  320. userData = _userData;
  321. }
  322. virtual void* getUserData() const
  323. {
  324. return userData;
  325. }
  326. IProperties *ensureParameters()
  327. {
  328. if (!xslParameters)
  329. xslParameters.setown(createProperties());
  330. return xslParameters.get();
  331. }
  332. IMultiException *ensureExceptions()
  333. {
  334. if (!exceptions)
  335. exceptions.setown(MakeMultiException());
  336. return exceptions.get();
  337. }
  338. void clearExceptions(){exceptions.clear();}
  339. public:
  340. Owned<IProperties> xslParameters;
  341. Owned<CLibXsltSource> xslSrc;
  342. Owned<CLibXmlSource> xmlSrc;
  343. Owned<CLibXsltResultTarget> target;
  344. Owned<IIncludeHandler> includeHandler;
  345. Owned<IXslFunction> msgfn;
  346. MapStringToMyClass<IXslFunction> functions;
  347. Owned<IMultiException> exceptions;
  348. StringBuffer messages;
  349. void *userData;
  350. };
  351. CLibXslTransform::CLibXslTransform()
  352. {
  353. userData = NULL;
  354. msgfn.setown(createExternalFunction("message", libxsltCustomMessageHandler));
  355. setExternalFunction(SEISINT_XSLTEXT_NAMESPACE, msgfn, true);
  356. }
  357. CLibXslTransform::~CLibXslTransform()
  358. {
  359. }
  360. void CLibXslTransform::copyParameters(IProperties *params)
  361. {
  362. if (params)
  363. {
  364. Owned<IPropertyIterator> it = params->getIterator();
  365. ForEach(*it.get())
  366. {
  367. const char *name = it->getPropKey();
  368. const char *value = params->queryProp(name);
  369. setParameter(name, value);
  370. }
  371. }
  372. }
  373. int CLibXslTransform::setExternalFunction(const char* ns, IXslFunction* xfn, bool set)
  374. {
  375. if (!xfn)
  376. return 0;
  377. CLibXslFunction *cfn = dynamic_cast<CLibXslFunction*>(xfn);
  378. if (!cfn)
  379. throw MakeStringException(XSLERR_ExternalFunctionIncompatible, "External Funciton not created for LIBXSLT");
  380. cfn->setURI(ns);
  381. if (set)
  382. {
  383. StringBuffer s(ns);
  384. s.append(':').append(xfn->getName());
  385. if (!functions.getValue(s.str()))
  386. functions.setValue(s.str(), xfn);
  387. }
  388. return 0;
  389. }
  390. bool CLibXslTransform::checkSanity()
  391. {
  392. return (xslSrc.get() != NULL && xmlSrc.get() != NULL);
  393. }
  394. CLibXslTransform *getXsltTransformObject(xsltTransformContextPtr x)
  395. {
  396. if (!x)
  397. return NULL;
  398. if (!x->_private)
  399. return NULL;
  400. return static_cast<CLibXslTransform *>(x->_private);
  401. }
  402. void globalLibXsltExtensionHandler(xmlXPathParserContextPtr ctxt, int nargs);
  403. static void libxsltErrorMsgHandler(void *ctx, const char *format, ...)
  404. {
  405. if (!ctx)
  406. return;
  407. CLibXslTransform *ctrans = (CLibXslTransform*)ctx;//getXsltTransformObject((xsltTransformContextPtr)ctx);
  408. if (!ctrans)
  409. return;
  410. va_list args;
  411. va_start(args, format);
  412. ctrans->ensureExceptions()->append(*MakeStringExceptionVA(XSLERR_TransformError, format, args));
  413. va_end(args);
  414. }
  415. int CLibXslTransform::transform(xmlChar **xmlbuff, int &len)
  416. {
  417. clearExceptions();
  418. xsltSetGenericErrorFunc(this, libxsltErrorMsgHandler);
  419. if (!xmlSrc)
  420. throw MakeStringException(XSLERR_MissingXml, "XSLT Transform missing XML");
  421. else if (!xslSrc)
  422. throw MakeStringException(XSLERR_MissingSource, "XSL source not set");
  423. StringArray params;
  424. if (xslParameters)
  425. {
  426. Owned<IPropertyIterator> it = xslParameters->getIterator();
  427. ForEach(*it)
  428. {
  429. const char *name = it->getPropKey();
  430. if (!name || !*name)
  431. continue;
  432. const char *val = xslParameters->queryProp(name);
  433. if (!val || !*val)
  434. continue;
  435. params.append(name);
  436. params.append(val);
  437. }
  438. }
  439. xmlDocPtr xmldoc = xmlSrc->getParsedXml();
  440. xslSrc->setIncludeHandler(includeHandler.get());
  441. xsltStylesheetPtr xsldoc = xslSrc->getCompiledXslt();
  442. xsltTransformContextPtr ctxt = xsltNewTransformContext(xsldoc, xmldoc);
  443. if (!ctxt)
  444. throw MakeStringException(XSLERR_CouldNotCreateTransform, "Failed creating libxslt Transform Context");
  445. ctxt->_private = this;
  446. HashIterator h(functions);
  447. ForEach (h)
  448. {
  449. IXslFunction *fn = functions.mapToValue(&h.query());
  450. CLibXslFunction *cfn = dynamic_cast<CLibXslFunction*>(fn);
  451. if (cfn && cfn->name.length())
  452. xsltRegisterExtFunction(ctxt, (const xmlChar *) cfn->name.get(), (const xmlChar *) cfn->uri.sget(), globalLibXsltExtensionHandler);
  453. }
  454. xsltSetCtxtParseOptions(ctxt, XSLT_PARSE_OPTIONS);
  455. MemoryBuffer mp;
  456. if (params.length())
  457. mp.append(sizeof(const char *) * params.length(), params.getArray()).append((unsigned __int64)0);
  458. xmlDocPtr res = xsltApplyStylesheetUser(xsldoc, xmldoc, (mp.length()) ? (const char**)mp.toByteArray() : NULL, NULL, NULL, ctxt);
  459. if (!res)
  460. {
  461. if (exceptions && exceptions->ordinality())
  462. throw exceptions.getClear();
  463. throw MakeStringException(XSLERR_TransformFailed, "Failed running xlst using libxslt.");
  464. }
  465. try
  466. {
  467. xsltFreeTransformContext(ctxt);
  468. xsltSaveResultToString(xmlbuff, &len, res, xsldoc);
  469. }
  470. catch(...)
  471. {
  472. xmlFreeDoc(res);
  473. xmlFree(xmlbuff);
  474. throw MakeStringException(XSLERR_TransformFailed, "Failed processing libxslt transform output");
  475. }
  476. xmlFreeDoc(res);
  477. if (exceptions && exceptions->ordinality())
  478. throw exceptions.getClear();
  479. return 0;
  480. }
  481. int CLibXslTransform::transform(StringBuffer &s)
  482. {
  483. int len = 0;
  484. xmlChar *xmlbuff = NULL;
  485. transform(&xmlbuff, len);
  486. if (len && xmlbuff)
  487. {
  488. s.append(len, (char *) xmlbuff);
  489. xmlFree(xmlbuff);
  490. }
  491. return 0;
  492. }
  493. int CLibXslTransform::transform()
  494. {
  495. int len = 0;
  496. xmlChar *xmlbuff = NULL;
  497. transform(&xmlbuff, len);
  498. if (len && xmlbuff)
  499. {
  500. target->process((const char *) xmlbuff, len);
  501. xmlFree(xmlbuff);
  502. }
  503. return 0;
  504. }
  505. int CLibXslTransform::transform(ISocket* targetSocket)
  506. {
  507. int len = 0;
  508. xmlChar *xmlbuff = NULL;
  509. transform(&xmlbuff, len);
  510. if (len && xmlbuff)
  511. {
  512. targetSocket->write((const void *) xmlbuff, (size32_t) len);
  513. xmlFree(xmlbuff);
  514. }
  515. return 0;
  516. }
  517. int CLibXslTransform::setXmlSource(const char *pszFileName)
  518. {
  519. xmlSrc.setown(new CLibXmlSource(pszFileName));
  520. return 0;
  521. }
  522. int CLibXslTransform::setXmlSource(const char *pszBuffer, unsigned int nSize)
  523. {
  524. xmlSrc.setown(new CLibXmlSource(pszBuffer, nSize));
  525. return 0;
  526. }
  527. int CLibXslTransform::setXslSource(const char *pszBuffer, unsigned int nSize, const char *cacheId, const char *rootpath)
  528. {
  529. xslSrc.setown(new CLibXsltSource(pszBuffer, nSize, cacheId));
  530. return 0;
  531. }
  532. int CLibXslTransform::loadXslFromEmbedded(const char *path, const char *cacheId)
  533. {
  534. xslSrc.setown(new CLibXsltSource(includeHandler.get(), path, cacheId));
  535. return 0;
  536. }
  537. int CLibXslTransform::setXslNoCache(const char *pszBuffer, unsigned int nSize, const char *rootpath)
  538. {
  539. xslSrc.setown(new CLibXsltSource(pszBuffer, nSize, NULL));
  540. return 0;
  541. }
  542. int CLibXslTransform::loadXslFromFile(const char *pszFileName, const char *altCacheId)
  543. {
  544. xslSrc.setown(new CLibXsltSource(pszFileName));
  545. return 0;
  546. }
  547. int CLibXslTransform::setResultTarget(const char *pszFileName)
  548. {
  549. target.setown(new CLibXsltResultTarget(pszFileName));
  550. return 0;
  551. }
  552. int CLibXslTransform::setResultTarget(char *pszBuffer, unsigned int nSize)
  553. {
  554. target.setown(new CLibXsltResultTarget(pszBuffer, nSize));
  555. return 0;
  556. }
  557. int CLibXslTransform::closeResultTarget()
  558. {
  559. return 0;
  560. }
  561. int CLibXslTransform::setParameter(const char *pszName, const char *pszExpression)
  562. {
  563. if (pszName && *pszName)
  564. ensureParameters()->setProp(pszName, pszExpression);
  565. return 0;
  566. }
  567. int CLibXslTransform::setStringParameter(const char *pszName, const char* pszString)
  568. {
  569. if (pszName && *pszName)
  570. ensureParameters()->setProp(pszName, StringBuffer("'").append(pszString).append("'").str());
  571. return 0;
  572. }
  573. class CLibXslProcessor : public CInterface, implements IXslProcessor
  574. {
  575. public:
  576. IMPLEMENT_IINTERFACE;
  577. CLibXslProcessor();
  578. ~CLibXslProcessor();
  579. virtual IXslTransform *createXslTransform();
  580. virtual int execute(IXslTransform *pITransform);
  581. virtual int setDefIncludeHandler(IIncludeHandler* handler){includeHandler.set(handler); return 0;}
  582. IIncludeHandler* queryDefIncludeHandler(){return includeHandler.get();}
  583. virtual void setCacheTimeout(int timeout);
  584. virtual int getCacheTimeout();
  585. public:
  586. Owned<IIncludeHandler> includeHandler;
  587. int m_cachetimeout;
  588. };
  589. CLibXslProcessor::CLibXslProcessor()
  590. {
  591. m_cachetimeout = XSLT_DEFAULT_CACHETIMEOUT;
  592. xmlInitMemory();
  593. xmlInitParser();
  594. xmlSubstituteEntitiesDefault(1);
  595. xmlThrDefSaveNoEmptyTags(1);
  596. xmlLoadExtDtdDefaultValue = 1;
  597. xsltMaxDepth = 20000;
  598. xsltSetLoaderFunc(NULL);
  599. originalLibXsltIncludeHandler = xsltDocDefaultLoader;
  600. xsltSetLoaderFunc(globalLibXsltIncludeHandler);
  601. exsltRegisterAll();
  602. xsltSetGenericErrorFunc(NULL, libxsltErrorMsgHandler);
  603. }
  604. CLibXslProcessor::~CLibXslProcessor()
  605. {
  606. xsltCleanupGlobals();
  607. xmlCleanupParser();
  608. xmlCleanupMemory();
  609. }
  610. static CLibXslProcessor xslProcessor;
  611. extern IXslProcessor* getXslProcessor()
  612. {
  613. return LINK(&xslProcessor);
  614. }
  615. IXslTransform *CLibXslProcessor::createXslTransform()
  616. {
  617. return new CLibXslTransform();
  618. }
  619. int CLibXslProcessor::execute(IXslTransform *pITransform)
  620. {
  621. return ((CLibXslTransform*)pITransform)->transform();
  622. }
  623. void CLibXslProcessor::setCacheTimeout(int timeout)
  624. {
  625. m_cachetimeout = timeout;
  626. IXslCache* xslcache = getXslCache2();
  627. if (xslcache)
  628. xslcache->setCacheTimeout(timeout);
  629. }
  630. int CLibXslProcessor::getCacheTimeout()
  631. {
  632. return m_cachetimeout;
  633. }
  634. CLibXsltSource *getXsltStylesheetSourceObject(xsltStylesheetPtr x)
  635. {
  636. if (!x)
  637. return NULL;
  638. if (x->_private)
  639. return static_cast<CLibXsltSource *>(x->_private);
  640. if (!x->doc || !x->doc->_private)
  641. return NULL;
  642. x->_private = x->doc->_private; //initialy stored in root xstl xml document
  643. return static_cast<CLibXsltSource *>(x->_private);
  644. }
  645. xmlDocPtr libXsltIncludeHandler(const xmlChar * URI, xmlDictPtr dict, int options, IIncludeHandler* handler, xsltLoadType type)
  646. {
  647. bool mbContainsPath=false;
  648. MemoryBuffer mb;
  649. if (!handler->getInclude((const char *)URI, mb, mbContainsPath))
  650. return originalLibXsltIncludeHandler(URI, dict, options, NULL, type);
  651. if (mbContainsPath)
  652. return originalLibXsltIncludeHandler((const xmlChar *)mb.append((char)0).toByteArray(), dict, options, NULL, type);
  653. if (mb.length())
  654. return xmlReadMemory(mb.toByteArray(), mb.length(), (const char *)URI, NULL, 0);
  655. return NULL;
  656. }
  657. IIncludeHandler* getXsltStylesheetIncludeHandler(xsltStylesheetPtr x, IIncludeHandler *def)
  658. {
  659. CLibXsltSource *src = getXsltStylesheetSourceObject(x);
  660. return (src && src->includeHandler) ? src->includeHandler.get() : def;
  661. }
  662. xmlDocPtr globalLibXsltIncludeHandler(const xmlChar * URI, xmlDictPtr dict, int options, void *ctx, xsltLoadType type)
  663. {
  664. xsltStylesheetPtr x = (xsltStylesheetPtr)ctx;
  665. if (type == XSLT_LOAD_DOCUMENT)
  666. x = ((xsltTransformContextPtr)ctx)->style;
  667. IIncludeHandler* handler = getXsltStylesheetIncludeHandler(x, xslProcessor.queryDefIncludeHandler());
  668. if (handler)
  669. return libXsltIncludeHandler(URI, dict, options, handler, type);
  670. return originalLibXsltIncludeHandler(URI, dict, options, ctx, type);
  671. }
  672. void libxsltCustomMessageHandler(StringBuffer& out, const char* in, IXslTransform* trans)
  673. {
  674. CLibXslTransform *ctrans = dynamic_cast<CLibXslTransform *>(trans);
  675. if (!ctrans)
  676. return;
  677. ctrans->messages.append(in).append(';');
  678. out.append(in);
  679. }
  680. void globalLibXsltExtensionHandler(xmlXPathParserContextPtr ctxt, int nargs)
  681. {
  682. const xmlChar *uri = ctxt->context->functionURI;
  683. const xmlChar *name = ctxt->context->function;
  684. xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);
  685. if (!tctxt)
  686. {
  687. xsltGenericError(xsltGenericErrorContext, "failed to get the transformation context\n");
  688. return;
  689. }
  690. if (nargs!=1)
  691. {
  692. VStringBuffer msg("Extension %s:%s - called", uri, name);
  693. if (!nargs)
  694. msg.append(" without any arguments\n");
  695. else
  696. msg.append(" with too many arguments\n");
  697. xsltGenericError(xsltGenericErrorContext, msg.str());
  698. ctxt->error = XPATH_INVALID_ARITY;
  699. return;
  700. }
  701. xmlChar *text =xmlXPathPopString(ctxt);
  702. CLibXslTransform *trns = getXsltTransformObject(tctxt);
  703. if (!trns)
  704. {
  705. xsltGenericError(xsltGenericErrorContext, "{%s}%s: IXslTransform not found\n", uri, name);
  706. return;
  707. }
  708. StringBuffer out;
  709. IXslFunction *xslfn = trns->queryExternalFunction((const char *)uri, (const char *)name);
  710. if (!xslfn)
  711. {
  712. xsltGenericError(xsltGenericErrorContext, "{%s}%s: IXslFuntionTransform not found\n", uri, name);
  713. return;
  714. }
  715. CLibXslFunction *cfn = dynamic_cast<CLibXslFunction *>(xslfn);
  716. cfn->fn(out, (const char *)text, trns);
  717. valuePush(ctxt, xmlXPathNewCString(out.str()));
  718. }