libxslt_processor.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  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. void clearMessages(){messages.clear();}
  340. public:
  341. Owned<IProperties> xslParameters;
  342. Owned<CLibXsltSource> xslSrc;
  343. Owned<CLibXmlSource> xmlSrc;
  344. Owned<CLibXsltResultTarget> target;
  345. Owned<IIncludeHandler> includeHandler;
  346. Owned<IXslFunction> msgfn;
  347. MapStringToMyClass<IXslFunction> functions;
  348. Owned<IMultiException> exceptions;
  349. StringBuffer messages;
  350. void *userData;
  351. };
  352. CLibXslTransform::CLibXslTransform()
  353. {
  354. userData = NULL;
  355. msgfn.setown(createExternalFunction("message", libxsltCustomMessageHandler));
  356. setExternalFunction(SEISINT_XSLTEXT_NAMESPACE, msgfn, true);
  357. }
  358. CLibXslTransform::~CLibXslTransform()
  359. {
  360. }
  361. void CLibXslTransform::copyParameters(IProperties *params)
  362. {
  363. if (params)
  364. {
  365. Owned<IPropertyIterator> it = params->getIterator();
  366. ForEach(*it.get())
  367. {
  368. const char *name = it->getPropKey();
  369. const char *value = params->queryProp(name);
  370. setParameter(name, value);
  371. }
  372. }
  373. }
  374. int CLibXslTransform::setExternalFunction(const char* ns, IXslFunction* xfn, bool set)
  375. {
  376. if (!xfn)
  377. return 0;
  378. CLibXslFunction *cfn = dynamic_cast<CLibXslFunction*>(xfn);
  379. if (!cfn)
  380. throw MakeStringException(XSLERR_ExternalFunctionIncompatible, "External Funciton not created for LIBXSLT");
  381. cfn->setURI(ns);
  382. if (set)
  383. {
  384. StringBuffer s(ns);
  385. s.append(':').append(xfn->getName());
  386. if (!functions.getValue(s.str()))
  387. functions.setValue(s.str(), xfn);
  388. }
  389. return 0;
  390. }
  391. bool CLibXslTransform::checkSanity()
  392. {
  393. return (xslSrc.get() != NULL && xmlSrc.get() != NULL);
  394. }
  395. CLibXslTransform *getXsltTransformObject(xsltTransformContextPtr x)
  396. {
  397. if (!x)
  398. return NULL;
  399. if (!x->_private)
  400. return NULL;
  401. return static_cast<CLibXslTransform *>(x->_private);
  402. }
  403. void globalLibXsltExtensionHandler(xmlXPathParserContextPtr ctxt, int nargs);
  404. static void libxsltErrorMsgHandler(void *ctx, const char *format, ...) __attribute__((format(printf,2,3)));
  405. static void libxsltErrorMsgHandler(void *ctx, const char *format, ...)
  406. {
  407. if (!ctx)
  408. return;
  409. if (format && *format == '\n')
  410. return;
  411. CLibXslTransform *ctrans = (CLibXslTransform*)ctx;//getXsltTransformObject((xsltTransformContextPtr)ctx);
  412. if (!ctrans)
  413. return;
  414. va_list args;
  415. va_start(args, format);
  416. ctrans->ensureExceptions()->append(*MakeStringExceptionVA(XSLERR_TransformError, format, args));
  417. va_end(args);
  418. }
  419. int CLibXslTransform::transform(xmlChar **xmlbuff, int &len)
  420. {
  421. clearExceptions();
  422. clearMessages();
  423. xsltSetGenericErrorFunc(this, libxsltErrorMsgHandler);
  424. if (!xmlSrc)
  425. throw MakeStringException(XSLERR_MissingXml, "XSLT Transform missing XML");
  426. else if (!xslSrc)
  427. throw MakeStringException(XSLERR_MissingSource, "XSL source not set");
  428. StringArray params;
  429. if (xslParameters)
  430. {
  431. Owned<IPropertyIterator> it = xslParameters->getIterator();
  432. ForEach(*it)
  433. {
  434. const char *name = it->getPropKey();
  435. if (!name || !*name)
  436. continue;
  437. const char *val = xslParameters->queryProp(name);
  438. if (!val || !*val)
  439. continue;
  440. params.append(name);
  441. params.append(val);
  442. }
  443. }
  444. xmlDocPtr xmldoc = xmlSrc->getParsedXml();
  445. xslSrc->setIncludeHandler(includeHandler.get());
  446. xsltStylesheetPtr xsldoc = xslSrc->getCompiledXslt();
  447. xsltTransformContextPtr ctxt = xsltNewTransformContext(xsldoc, xmldoc);
  448. if (!ctxt)
  449. throw MakeStringException(XSLERR_CouldNotCreateTransform, "Failed creating libxslt Transform Context");
  450. ctxt->_private = this;
  451. HashIterator h(functions);
  452. ForEach (h)
  453. {
  454. IXslFunction *fn = functions.mapToValue(&h.query());
  455. CLibXslFunction *cfn = dynamic_cast<CLibXslFunction*>(fn);
  456. if (cfn && cfn->name.length())
  457. xsltRegisterExtFunction(ctxt, (const xmlChar *) cfn->name.get(), (const xmlChar *) cfn->uri.str(), globalLibXsltExtensionHandler);
  458. }
  459. xsltSetCtxtParseOptions(ctxt, XSLT_PARSE_OPTIONS);
  460. MemoryBuffer mp;
  461. if (params.length())
  462. mp.append(sizeof(const char *) * params.length(), params.getArray()).append((unsigned __int64)0);
  463. xmlDocPtr res = xsltApplyStylesheetUser(xsldoc, xmldoc, (mp.length()) ? (const char**)mp.toByteArray() : NULL, NULL, NULL, ctxt);
  464. if (!res)
  465. {
  466. if (exceptions && exceptions->ordinality())
  467. throw exceptions.getClear();
  468. throw MakeStringException(XSLERR_TransformFailed, "Failed running xlst using libxslt.");
  469. }
  470. xsltTransformState stateAfterTransform = ctxt->state;
  471. try
  472. {
  473. xsltFreeTransformContext(ctxt);
  474. xsltSaveResultToString(xmlbuff, &len, res, xsldoc);
  475. }
  476. catch(...)
  477. {
  478. xmlFreeDoc(res);
  479. xmlFree(xmlbuff);
  480. throw MakeStringException(XSLERR_TransformFailed, "Failed processing libxslt transform output");
  481. }
  482. xmlFreeDoc(res);
  483. if (exceptions && exceptions->ordinality())
  484. {
  485. if (stateAfterTransform != XSLT_STATE_OK)
  486. {
  487. throw exceptions.getClear();
  488. }
  489. else
  490. {
  491. StringBuffer strErrMsg;
  492. exceptions.get()->errorMessage(strErrMsg);
  493. messages.set(strErrMsg.str());
  494. }
  495. }
  496. return 0;
  497. }
  498. int CLibXslTransform::transform(StringBuffer &s)
  499. {
  500. int len = 0;
  501. xmlChar *xmlbuff = NULL;
  502. transform(&xmlbuff, len);
  503. if (len && xmlbuff)
  504. {
  505. s.append(len, (char *) xmlbuff);
  506. xmlFree(xmlbuff);
  507. }
  508. return 0;
  509. }
  510. int CLibXslTransform::transform()
  511. {
  512. int len = 0;
  513. xmlChar *xmlbuff = NULL;
  514. transform(&xmlbuff, len);
  515. if (len && xmlbuff)
  516. {
  517. target->process((const char *) xmlbuff, len);
  518. xmlFree(xmlbuff);
  519. }
  520. return 0;
  521. }
  522. int CLibXslTransform::transform(ISocket* targetSocket)
  523. {
  524. int len = 0;
  525. xmlChar *xmlbuff = NULL;
  526. transform(&xmlbuff, len);
  527. if (len && xmlbuff)
  528. {
  529. targetSocket->write((const void *) xmlbuff, (size32_t) len);
  530. xmlFree(xmlbuff);
  531. }
  532. return 0;
  533. }
  534. int CLibXslTransform::setXmlSource(const char *pszFileName)
  535. {
  536. xmlSrc.setown(new CLibXmlSource(pszFileName));
  537. return 0;
  538. }
  539. int CLibXslTransform::setXmlSource(const char *pszBuffer, unsigned int nSize)
  540. {
  541. xmlSrc.setown(new CLibXmlSource(pszBuffer, nSize));
  542. return 0;
  543. }
  544. int CLibXslTransform::setXslSource(const char *pszBuffer, unsigned int nSize, const char *cacheId, const char *rootpath)
  545. {
  546. xslSrc.setown(new CLibXsltSource(pszBuffer, nSize, cacheId));
  547. return 0;
  548. }
  549. int CLibXslTransform::loadXslFromEmbedded(const char *path, const char *cacheId)
  550. {
  551. xslSrc.setown(new CLibXsltSource(includeHandler.get(), path, cacheId));
  552. return 0;
  553. }
  554. int CLibXslTransform::setXslNoCache(const char *pszBuffer, unsigned int nSize, const char *rootpath)
  555. {
  556. xslSrc.setown(new CLibXsltSource(pszBuffer, nSize, NULL));
  557. return 0;
  558. }
  559. int CLibXslTransform::loadXslFromFile(const char *pszFileName, const char *altCacheId)
  560. {
  561. xslSrc.setown(new CLibXsltSource(pszFileName));
  562. return 0;
  563. }
  564. int CLibXslTransform::setResultTarget(const char *pszFileName)
  565. {
  566. target.setown(new CLibXsltResultTarget(pszFileName));
  567. return 0;
  568. }
  569. int CLibXslTransform::setResultTarget(char *pszBuffer, unsigned int nSize)
  570. {
  571. target.setown(new CLibXsltResultTarget(pszBuffer, nSize));
  572. return 0;
  573. }
  574. int CLibXslTransform::closeResultTarget()
  575. {
  576. return 0;
  577. }
  578. int CLibXslTransform::setParameter(const char *pszName, const char *pszExpression)
  579. {
  580. if (pszName && *pszName)
  581. ensureParameters()->setProp(pszName, pszExpression);
  582. return 0;
  583. }
  584. int CLibXslTransform::setStringParameter(const char *pszName, const char* pszString)
  585. {
  586. if (pszName && *pszName)
  587. ensureParameters()->setProp(pszName, StringBuffer("'").append(pszString).append("'").str());
  588. return 0;
  589. }
  590. class CLibXslProcessor : public CInterface, implements IXslProcessor
  591. {
  592. public:
  593. IMPLEMENT_IINTERFACE;
  594. CLibXslProcessor();
  595. ~CLibXslProcessor();
  596. virtual IXslTransform *createXslTransform();
  597. virtual int execute(IXslTransform *pITransform);
  598. virtual int setDefIncludeHandler(IIncludeHandler* handler){includeHandler.set(handler); return 0;}
  599. IIncludeHandler* queryDefIncludeHandler(){return includeHandler.get();}
  600. virtual void setCacheTimeout(int timeout);
  601. virtual int getCacheTimeout();
  602. public:
  603. Owned<IIncludeHandler> includeHandler;
  604. int m_cachetimeout;
  605. };
  606. CLibXslProcessor::CLibXslProcessor()
  607. {
  608. m_cachetimeout = XSLT_DEFAULT_CACHETIMEOUT;
  609. xmlInitMemory();
  610. xmlInitParser();
  611. xmlSubstituteEntitiesDefault(1);
  612. xmlThrDefSaveNoEmptyTags(1);
  613. xmlLoadExtDtdDefaultValue = 1;
  614. xsltMaxDepth = 20000;
  615. xsltSetLoaderFunc(NULL);
  616. originalLibXsltIncludeHandler = xsltDocDefaultLoader;
  617. xsltSetLoaderFunc(globalLibXsltIncludeHandler);
  618. exsltRegisterAll();
  619. xsltSetGenericErrorFunc(NULL, libxsltErrorMsgHandler);
  620. }
  621. CLibXslProcessor::~CLibXslProcessor()
  622. {
  623. xsltCleanupGlobals();
  624. xmlCleanupParser();
  625. xmlCleanupMemory();
  626. }
  627. static CLibXslProcessor xslProcessor;
  628. extern IXslProcessor* getXslProcessor()
  629. {
  630. return LINK(&xslProcessor);
  631. }
  632. IXslTransform *CLibXslProcessor::createXslTransform()
  633. {
  634. return new CLibXslTransform();
  635. }
  636. int CLibXslProcessor::execute(IXslTransform *pITransform)
  637. {
  638. return ((CLibXslTransform*)pITransform)->transform();
  639. }
  640. void CLibXslProcessor::setCacheTimeout(int timeout)
  641. {
  642. m_cachetimeout = timeout;
  643. IXslCache* xslcache = getXslCache2();
  644. if (xslcache)
  645. xslcache->setCacheTimeout(timeout);
  646. }
  647. int CLibXslProcessor::getCacheTimeout()
  648. {
  649. return m_cachetimeout;
  650. }
  651. CLibXsltSource *getXsltStylesheetSourceObject(xsltStylesheetPtr x)
  652. {
  653. if (!x)
  654. return NULL;
  655. if (x->_private)
  656. return static_cast<CLibXsltSource *>(x->_private);
  657. if (!x->doc || !x->doc->_private)
  658. return NULL;
  659. x->_private = x->doc->_private; //initialy stored in root xstl xml document
  660. return static_cast<CLibXsltSource *>(x->_private);
  661. }
  662. xmlDocPtr libXsltIncludeHandler(const xmlChar * URI, xmlDictPtr dict, int options, IIncludeHandler* handler, xsltLoadType type)
  663. {
  664. bool mbContainsPath=false;
  665. MemoryBuffer mb;
  666. StringBuffer decodedURI;
  667. appendDecodedURL(decodedURI, (const char *)URI);
  668. if (strchr(decodedURI.str(), '%')) //libxstl seems to double encode
  669. {
  670. StringBuffer s;
  671. appendDecodedURL(s, decodedURI.str());
  672. decodedURI.swapWith(s);
  673. }
  674. if (!handler->getInclude(decodedURI, mb, mbContainsPath))
  675. return originalLibXsltIncludeHandler(URI, dict, options, NULL, type);
  676. if (mbContainsPath)
  677. return originalLibXsltIncludeHandler((const xmlChar *)mb.append((char)0).toByteArray(), dict, options, NULL, type);
  678. if (mb.length())
  679. return xmlReadMemory(mb.toByteArray(), mb.length(), (const char *)URI, NULL, 0);
  680. return NULL;
  681. }
  682. IIncludeHandler* getXsltStylesheetIncludeHandler(xsltStylesheetPtr x, IIncludeHandler *def)
  683. {
  684. CLibXsltSource *src = getXsltStylesheetSourceObject(x);
  685. return (src && src->includeHandler) ? src->includeHandler.get() : def;
  686. }
  687. xmlDocPtr globalLibXsltIncludeHandler(const xmlChar * URI, xmlDictPtr dict, int options, void *ctx, xsltLoadType type)
  688. {
  689. xsltStylesheetPtr x = (xsltStylesheetPtr)ctx;
  690. if (type == XSLT_LOAD_DOCUMENT)
  691. x = ((xsltTransformContextPtr)ctx)->style;
  692. IIncludeHandler* handler = getXsltStylesheetIncludeHandler(x, xslProcessor.queryDefIncludeHandler());
  693. if (handler)
  694. return libXsltIncludeHandler(URI, dict, options, handler, type);
  695. return originalLibXsltIncludeHandler(URI, dict, options, ctx, type);
  696. }
  697. void libxsltCustomMessageHandler(StringBuffer& out, const char* in, IXslTransform* trans)
  698. {
  699. CLibXslTransform *ctrans = dynamic_cast<CLibXslTransform *>(trans);
  700. if (!ctrans)
  701. return;
  702. ctrans->messages.append(in).append(';');
  703. out.append(in);
  704. }
  705. void globalLibXsltExtensionHandler(xmlXPathParserContextPtr ctxt, int nargs)
  706. {
  707. const xmlChar *uri = ctxt->context->functionURI;
  708. const xmlChar *name = ctxt->context->function;
  709. xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);
  710. if (!tctxt)
  711. {
  712. xsltGenericError(xsltGenericErrorContext, "failed to get the transformation context\n");
  713. return;
  714. }
  715. if (nargs!=1)
  716. {
  717. VStringBuffer msg("Extension %s:%s - called", uri, name);
  718. if (!nargs)
  719. msg.append(" without any arguments\n");
  720. else
  721. msg.append(" with too many arguments\n");
  722. xsltGenericError(xsltGenericErrorContext, "%s", msg.str());
  723. ctxt->error = XPATH_INVALID_ARITY;
  724. return;
  725. }
  726. xmlChar *text =xmlXPathPopString(ctxt);
  727. CLibXslTransform *trns = getXsltTransformObject(tctxt);
  728. if (!trns)
  729. {
  730. xsltGenericError(xsltGenericErrorContext, "{%s}%s: IXslTransform not found\n", uri, name);
  731. return;
  732. }
  733. StringBuffer out;
  734. IXslFunction *xslfn = trns->queryExternalFunction((const char *)uri, (const char *)name);
  735. if (!xslfn)
  736. {
  737. xsltGenericError(xsltGenericErrorContext, "{%s}%s: IXslFuntionTransform not found\n", uri, name);
  738. return;
  739. }
  740. CLibXslFunction *cfn = dynamic_cast<CLibXslFunction *>(xslfn);
  741. cfn->fn(out, (const char *)text, trns);
  742. valuePush(ctxt, xmlXPathNewCString(out.str()));
  743. }