imports.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. /*
  2. * imports.c: Implementation of the XSLT imports
  3. *
  4. * Reference:
  5. * http://www.w3.org/TR/1999/REC-xslt-19991116
  6. *
  7. * See Copyright for the status of this software.
  8. *
  9. * daniel@veillard.com
  10. */
  11. #define IN_LIBXSLT
  12. #include "libxslt.h"
  13. #include <string.h>
  14. #ifdef HAVE_SYS_TYPES_H
  15. #include <sys/types.h>
  16. #endif
  17. #ifdef HAVE_MATH_H
  18. #include <math.h>
  19. #endif
  20. #ifdef HAVE_FLOAT_H
  21. #include <float.h>
  22. #endif
  23. #ifdef HAVE_IEEEFP_H
  24. #include <ieeefp.h>
  25. #endif
  26. #ifdef HAVE_NAN_H
  27. #include <nan.h>
  28. #endif
  29. #ifdef HAVE_CTYPE_H
  30. #include <ctype.h>
  31. #endif
  32. #include <libxml/xmlmemory.h>
  33. #include <libxml/tree.h>
  34. #include <libxml/hash.h>
  35. #include <libxml/xmlerror.h>
  36. #include <libxml/uri.h>
  37. #include "xslt.h"
  38. #include "xsltInternals.h"
  39. #include "xsltutils.h"
  40. #include "preproc.h"
  41. #include "imports.h"
  42. #include "documents.h"
  43. #include "security.h"
  44. #include "pattern.h"
  45. /************************************************************************
  46. * *
  47. * Module interfaces *
  48. * *
  49. ************************************************************************/
  50. /**
  51. * xsltFixImportedCompSteps:
  52. * @master: the "master" stylesheet
  53. * @style: the stylesheet being imported by the master
  54. *
  55. * normalize the comp steps for the stylesheet being imported
  56. * by the master, together with any imports within that.
  57. *
  58. */
  59. static void xsltFixImportedCompSteps(xsltStylesheetPtr master,
  60. xsltStylesheetPtr style) {
  61. xsltStylesheetPtr res;
  62. xmlHashScan(style->templatesHash, xsltNormalizeCompSteps, master);
  63. master->extrasNr += style->extrasNr;
  64. for (res = style->imports; res != NULL; res = res->next) {
  65. xsltFixImportedCompSteps(master, res);
  66. }
  67. }
  68. /**
  69. * xsltParseStylesheetImport:
  70. * @style: the XSLT stylesheet
  71. * @cur: the import element
  72. *
  73. * parse an XSLT stylesheet import element
  74. *
  75. * Returns 0 in case of success -1 in case of failure.
  76. */
  77. int
  78. xsltParseStylesheetImport(xsltStylesheetPtr style, xmlNodePtr cur) {
  79. int ret = -1;
  80. xmlDocPtr import = NULL;
  81. xmlChar *base = NULL;
  82. xmlChar *uriRef = NULL;
  83. xmlChar *URI = NULL;
  84. xsltStylesheetPtr res;
  85. xsltSecurityPrefsPtr sec;
  86. if ((cur == NULL) || (style == NULL))
  87. return (ret);
  88. uriRef = xmlGetNsProp(cur, (const xmlChar *)"href", NULL);
  89. if (uriRef == NULL) {
  90. xsltTransformError(NULL, style, cur,
  91. "xsl:import : missing href attribute\n");
  92. goto error;
  93. }
  94. base = xmlNodeGetBase(style->doc, cur);
  95. URI = xmlBuildURI(uriRef, base);
  96. if (URI == NULL) {
  97. xsltTransformError(NULL, style, cur,
  98. "xsl:import : invalid URI reference %s\n", uriRef);
  99. goto error;
  100. }
  101. res = style;
  102. while (res != NULL) {
  103. if (res->doc == NULL)
  104. break;
  105. if (xmlStrEqual(res->doc->URL, URI)) {
  106. xsltTransformError(NULL, style, cur,
  107. "xsl:import : recursion detected on imported URL %s\n", URI);
  108. goto error;
  109. }
  110. res = res->parent;
  111. }
  112. /*
  113. * Security framework check
  114. */
  115. sec = xsltGetDefaultSecurityPrefs();
  116. if (sec != NULL) {
  117. int secres;
  118. secres = xsltCheckRead(sec, NULL, URI);
  119. if (secres <= 0) {
  120. if (secres == 0)
  121. xsltTransformError(NULL, NULL, NULL,
  122. "xsl:import: read rights for %s denied\n",
  123. URI);
  124. goto error;
  125. }
  126. }
  127. import = xsltDocDefaultLoader(URI, style->dict, XSLT_PARSE_OPTIONS,
  128. (void *) style, XSLT_LOAD_STYLESHEET);
  129. if (import == NULL) {
  130. xsltTransformError(NULL, style, cur,
  131. "xsl:import : unable to load %s\n", URI);
  132. goto error;
  133. }
  134. res = xsltParseStylesheetImportedDoc(import, style);
  135. if (res != NULL) {
  136. res->next = style->imports;
  137. style->imports = res;
  138. if (style->parent == NULL) {
  139. xsltFixImportedCompSteps(style, res);
  140. }
  141. ret = 0;
  142. } else {
  143. xmlFreeDoc(import);
  144. }
  145. error:
  146. if (uriRef != NULL)
  147. xmlFree(uriRef);
  148. if (base != NULL)
  149. xmlFree(base);
  150. if (URI != NULL)
  151. xmlFree(URI);
  152. return (ret);
  153. }
  154. /**
  155. * xsltParseStylesheetInclude:
  156. * @style: the XSLT stylesheet
  157. * @cur: the include node
  158. *
  159. * parse an XSLT stylesheet include element
  160. *
  161. * Returns 0 in case of success -1 in case of failure
  162. */
  163. int
  164. xsltParseStylesheetInclude(xsltStylesheetPtr style, xmlNodePtr cur) {
  165. int ret = -1;
  166. xmlDocPtr oldDoc;
  167. xmlChar *base = NULL;
  168. xmlChar *uriRef = NULL;
  169. xmlChar *URI = NULL;
  170. xsltStylesheetPtr result;
  171. xsltDocumentPtr include;
  172. xsltDocumentPtr docptr;
  173. int oldNopreproc;
  174. if ((cur == NULL) || (style == NULL))
  175. return (ret);
  176. uriRef = xmlGetNsProp(cur, (const xmlChar *)"href", NULL);
  177. if (uriRef == NULL) {
  178. xsltTransformError(NULL, style, cur,
  179. "xsl:include : missing href attribute\n");
  180. goto error;
  181. }
  182. base = xmlNodeGetBase(style->doc, cur);
  183. URI = xmlBuildURI(uriRef, base);
  184. if (URI == NULL) {
  185. xsltTransformError(NULL, style, cur,
  186. "xsl:include : invalid URI reference %s\n", uriRef);
  187. goto error;
  188. }
  189. /*
  190. * in order to detect recursion, we check all previously included
  191. * stylesheets.
  192. */
  193. docptr = style->includes;
  194. while (docptr != NULL) {
  195. if (xmlStrEqual(docptr->doc->URL, URI)) {
  196. xsltTransformError(NULL, style, cur,
  197. "xsl:include : recursion detected on included URL %s\n", URI);
  198. goto error;
  199. }
  200. docptr = docptr->includes;
  201. }
  202. include = xsltLoadStyleDocument(style, URI);
  203. if (include == NULL) {
  204. xsltTransformError(NULL, style, cur,
  205. "xsl:include : unable to load %s\n", URI);
  206. goto error;
  207. }
  208. #ifdef XSLT_REFACTORED
  209. if (IS_XSLT_ELEM_FAST(cur) && (cur->psvi != NULL)) {
  210. ((xsltStyleItemIncludePtr) cur->psvi)->include = include;
  211. } else {
  212. xsltTransformError(NULL, style, cur,
  213. "Internal error: (xsltParseStylesheetInclude) "
  214. "The xsl:include element was not compiled.\n", URI);
  215. style->errors++;
  216. }
  217. #endif
  218. oldDoc = style->doc;
  219. style->doc = include->doc;
  220. /* chain to stylesheet for recursion checking */
  221. include->includes = style->includes;
  222. style->includes = include;
  223. oldNopreproc = style->nopreproc;
  224. style->nopreproc = include->preproc;
  225. /*
  226. * TODO: This will change some values of the
  227. * including stylesheet with every included module
  228. * (e.g. excluded-result-prefixes)
  229. * We need to strictly seperate such stylesheet-owned values.
  230. */
  231. result = xsltParseStylesheetProcess(style, include->doc);
  232. style->nopreproc = oldNopreproc;
  233. include->preproc = 1;
  234. style->includes = include->includes;
  235. style->doc = oldDoc;
  236. if (result == NULL) {
  237. ret = -1;
  238. goto error;
  239. }
  240. ret = 0;
  241. error:
  242. if (uriRef != NULL)
  243. xmlFree(uriRef);
  244. if (base != NULL)
  245. xmlFree(base);
  246. if (URI != NULL)
  247. xmlFree(URI);
  248. return (ret);
  249. }
  250. /**
  251. * xsltNextImport:
  252. * @cur: the current XSLT stylesheet
  253. *
  254. * Find the next stylesheet in import precedence.
  255. *
  256. * Returns the next stylesheet or NULL if it was the last one
  257. */
  258. xsltStylesheetPtr
  259. xsltNextImport(xsltStylesheetPtr cur) {
  260. if (cur == NULL)
  261. return(NULL);
  262. if (cur->imports != NULL)
  263. return(cur->imports);
  264. if (cur->next != NULL)
  265. return(cur->next) ;
  266. do {
  267. cur = cur->parent;
  268. if (cur == NULL) break;
  269. if (cur->next != NULL) return(cur->next);
  270. } while (cur != NULL);
  271. return(cur);
  272. }
  273. /**
  274. * xsltNeedElemSpaceHandling:
  275. * @ctxt: an XSLT transformation context
  276. *
  277. * Checks whether that stylesheet requires white-space stripping
  278. *
  279. * Returns 1 if space should be stripped, 0 if not
  280. */
  281. int
  282. xsltNeedElemSpaceHandling(xsltTransformContextPtr ctxt) {
  283. xsltStylesheetPtr style;
  284. if (ctxt == NULL)
  285. return(0);
  286. style = ctxt->style;
  287. while (style != NULL) {
  288. if (style->stripSpaces != NULL)
  289. return(1);
  290. style = xsltNextImport(style);
  291. }
  292. return(0);
  293. }
  294. /**
  295. * xsltFindElemSpaceHandling:
  296. * @ctxt: an XSLT transformation context
  297. * @node: an XML node
  298. *
  299. * Find strip-space or preserve-space information for an element
  300. * respect the import precedence or the wildcards
  301. *
  302. * Returns 1 if space should be stripped, 0 if not, and 2 if everything
  303. * should be CDTATA wrapped.
  304. */
  305. int
  306. xsltFindElemSpaceHandling(xsltTransformContextPtr ctxt, xmlNodePtr node) {
  307. xsltStylesheetPtr style;
  308. const xmlChar *val;
  309. if ((ctxt == NULL) || (node == NULL))
  310. return(0);
  311. style = ctxt->style;
  312. while (style != NULL) {
  313. if (node->ns != NULL) {
  314. val = (const xmlChar *)
  315. xmlHashLookup2(style->stripSpaces, node->name, node->ns->href);
  316. if (val == NULL) {
  317. val = (const xmlChar *)
  318. xmlHashLookup2(style->stripSpaces, BAD_CAST "*",
  319. node->ns->href);
  320. }
  321. } else {
  322. val = (const xmlChar *)
  323. xmlHashLookup2(style->stripSpaces, node->name, NULL);
  324. }
  325. if (val != NULL) {
  326. if (xmlStrEqual(val, (xmlChar *) "strip"))
  327. return(1);
  328. if (xmlStrEqual(val, (xmlChar *) "preserve"))
  329. return(0);
  330. }
  331. if (style->stripAll == 1)
  332. return(1);
  333. if (style->stripAll == -1)
  334. return(0);
  335. style = xsltNextImport(style);
  336. }
  337. return(0);
  338. }
  339. /**
  340. * xsltFindTemplate:
  341. * @ctxt: an XSLT transformation context
  342. * @name: the template name
  343. * @nameURI: the template name URI
  344. *
  345. * Finds the named template, apply import precedence rule.
  346. * REVISIT TODO: We'll change the nameURI fields of
  347. * templates to be in the string dict, so if the
  348. * specified @nameURI is in the same dict, then use pointer
  349. * comparison. Check if this can be done in a sane way.
  350. * Maybe this function is not needed internally at
  351. * transformation-time if we hard-wire the called templates
  352. * to the caller.
  353. *
  354. * Returns the xsltTemplatePtr or NULL if not found
  355. */
  356. xsltTemplatePtr
  357. xsltFindTemplate(xsltTransformContextPtr ctxt, const xmlChar *name,
  358. const xmlChar *nameURI) {
  359. xsltTemplatePtr cur;
  360. xsltStylesheetPtr style;
  361. if ((ctxt == NULL) || (name == NULL))
  362. return(NULL);
  363. style = ctxt->style;
  364. while (style != NULL) {
  365. if (style->namedTemplates != NULL) {
  366. cur = (xsltTemplatePtr)
  367. xmlHashLookup2(style->namedTemplates, name, nameURI);
  368. if (cur != NULL)
  369. return(cur);
  370. }
  371. style = xsltNextImport(style);
  372. }
  373. return(NULL);
  374. }