[18214] | 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 | |
---|
| 12 | #define IN_LIBXSLT |
---|
| 13 | #include "libxslt.h" |
---|
| 14 | |
---|
| 15 | #include <string.h> |
---|
| 16 | |
---|
| 17 | #ifdef HAVE_SYS_TYPES_H |
---|
| 18 | #include <sys/types.h> |
---|
| 19 | #endif |
---|
| 20 | #ifdef HAVE_MATH_H |
---|
| 21 | #include <math.h> |
---|
| 22 | #endif |
---|
| 23 | #ifdef HAVE_FLOAT_H |
---|
| 24 | #include <float.h> |
---|
| 25 | #endif |
---|
| 26 | #ifdef HAVE_IEEEFP_H |
---|
| 27 | #include <ieeefp.h> |
---|
| 28 | #endif |
---|
| 29 | #ifdef HAVE_NAN_H |
---|
| 30 | #include <nan.h> |
---|
| 31 | #endif |
---|
| 32 | #ifdef HAVE_CTYPE_H |
---|
| 33 | #include <ctype.h> |
---|
| 34 | #endif |
---|
| 35 | |
---|
| 36 | #include <libxml/xmlmemory.h> |
---|
| 37 | #include <libxml/tree.h> |
---|
| 38 | #include <libxml/hash.h> |
---|
| 39 | #include <libxml/xmlerror.h> |
---|
| 40 | #include <libxml/uri.h> |
---|
| 41 | #include "xslt.h" |
---|
| 42 | #include "xsltInternals.h" |
---|
| 43 | #include "xsltutils.h" |
---|
| 44 | #include "imports.h" |
---|
| 45 | #include "documents.h" |
---|
| 46 | #include "security.h" |
---|
| 47 | |
---|
| 48 | |
---|
| 49 | |
---|
| 50 | /************************************************************************ |
---|
| 51 | * * |
---|
| 52 | * Module interfaces * |
---|
| 53 | * * |
---|
| 54 | ************************************************************************/ |
---|
| 55 | |
---|
| 56 | /** |
---|
| 57 | * xsltParseStylesheetImport: |
---|
| 58 | * @style: the XSLT stylesheet |
---|
[18542] | 59 | * @cur: the import element |
---|
[18214] | 60 | * |
---|
[18542] | 61 | * parse an XSLT stylesheet import element |
---|
| 62 | * |
---|
| 63 | * Returns 0 in case of success -1 in case of failure. |
---|
[18214] | 64 | */ |
---|
| 65 | |
---|
| 66 | int |
---|
| 67 | xsltParseStylesheetImport(xsltStylesheetPtr style, xmlNodePtr cur) { |
---|
| 68 | int ret = -1; |
---|
| 69 | xmlDocPtr import = NULL; |
---|
| 70 | xmlChar *base = NULL; |
---|
| 71 | xmlChar *uriRef = NULL; |
---|
| 72 | xmlChar *URI = NULL; |
---|
| 73 | xsltStylesheetPtr res; |
---|
| 74 | xsltSecurityPrefsPtr sec; |
---|
| 75 | |
---|
| 76 | if ((cur == NULL) || (style == NULL)) |
---|
| 77 | return (ret); |
---|
| 78 | |
---|
| 79 | uriRef = xsltGetNsProp(cur, (const xmlChar *)"href", XSLT_NAMESPACE); |
---|
| 80 | if (uriRef == NULL) { |
---|
| 81 | xsltTransformError(NULL, style, cur, |
---|
| 82 | "xsl:import : missing href attribute\n"); |
---|
| 83 | goto error; |
---|
| 84 | } |
---|
| 85 | |
---|
| 86 | base = xmlNodeGetBase(style->doc, cur); |
---|
| 87 | URI = xmlBuildURI(uriRef, base); |
---|
| 88 | if (URI == NULL) { |
---|
| 89 | xsltTransformError(NULL, style, cur, |
---|
| 90 | "xsl:import : invalid URI reference %s\n", uriRef); |
---|
| 91 | goto error; |
---|
| 92 | } |
---|
| 93 | |
---|
| 94 | /* |
---|
| 95 | * Security framework check |
---|
| 96 | */ |
---|
| 97 | sec = xsltGetDefaultSecurityPrefs(); |
---|
| 98 | if (sec != NULL) { |
---|
| 99 | int secres; |
---|
| 100 | |
---|
| 101 | secres = xsltCheckRead(sec, NULL, URI); |
---|
| 102 | if (secres == 0) { |
---|
| 103 | xsltTransformError(NULL, NULL, NULL, |
---|
| 104 | "xsl:import: read rights for %s denied\n", |
---|
| 105 | URI); |
---|
| 106 | goto error; |
---|
| 107 | } |
---|
| 108 | } |
---|
| 109 | |
---|
| 110 | import = xmlParseFile((const char *)URI); |
---|
| 111 | if (import == NULL) { |
---|
| 112 | xsltTransformError(NULL, style, cur, |
---|
| 113 | "xsl:import : unable to load %s\n", URI); |
---|
| 114 | goto error; |
---|
| 115 | } |
---|
| 116 | |
---|
[18542] | 117 | res = xsltParseStylesheetImportedDoc(import); |
---|
[18214] | 118 | if (res != NULL) { |
---|
| 119 | res->parent = style; |
---|
| 120 | res->next = style->imports; |
---|
| 121 | style->imports = res; |
---|
| 122 | style->extrasNr += res->extrasNr; |
---|
| 123 | ret = 0; |
---|
| 124 | } else { |
---|
| 125 | xmlFreeDoc(import); |
---|
| 126 | } |
---|
| 127 | |
---|
| 128 | error: |
---|
| 129 | if (uriRef != NULL) |
---|
| 130 | xmlFree(uriRef); |
---|
| 131 | if (base != NULL) |
---|
| 132 | xmlFree(base); |
---|
| 133 | if (URI != NULL) |
---|
| 134 | xmlFree(URI); |
---|
| 135 | |
---|
| 136 | return (ret); |
---|
| 137 | } |
---|
| 138 | |
---|
| 139 | /** |
---|
| 140 | * xsltParseStylesheetInclude: |
---|
| 141 | * @style: the XSLT stylesheet |
---|
[18542] | 142 | * @cur: the include node |
---|
[18214] | 143 | * |
---|
[18542] | 144 | * parse an XSLT stylesheet include element |
---|
| 145 | * |
---|
| 146 | * Returns 0 in case of success -1 in case of failure |
---|
[18214] | 147 | */ |
---|
| 148 | |
---|
| 149 | int |
---|
| 150 | xsltParseStylesheetInclude(xsltStylesheetPtr style, xmlNodePtr cur) { |
---|
| 151 | int ret = -1; |
---|
| 152 | xmlDocPtr oldDoc; |
---|
| 153 | xmlChar *base = NULL; |
---|
| 154 | xmlChar *uriRef = NULL; |
---|
| 155 | xmlChar *URI = NULL; |
---|
| 156 | xsltDocumentPtr include; |
---|
| 157 | |
---|
| 158 | if ((cur == NULL) || (style == NULL)) |
---|
| 159 | return (ret); |
---|
| 160 | |
---|
| 161 | uriRef = xsltGetNsProp(cur, (const xmlChar *)"href", XSLT_NAMESPACE); |
---|
| 162 | if (uriRef == NULL) { |
---|
| 163 | xsltTransformError(NULL, style, cur, |
---|
| 164 | "xsl:include : missing href attribute\n"); |
---|
| 165 | goto error; |
---|
| 166 | } |
---|
| 167 | |
---|
| 168 | base = xmlNodeGetBase(style->doc, cur); |
---|
| 169 | URI = xmlBuildURI(uriRef, base); |
---|
| 170 | if (URI == NULL) { |
---|
| 171 | xsltTransformError(NULL, style, cur, |
---|
| 172 | "xsl:include : invalid URI reference %s\n", uriRef); |
---|
| 173 | goto error; |
---|
| 174 | } |
---|
| 175 | |
---|
| 176 | include = xsltLoadStyleDocument(style, URI); |
---|
| 177 | if (include == NULL) { |
---|
| 178 | xsltTransformError(NULL, style, cur, |
---|
| 179 | "xsl:include : unable to load %s\n", URI); |
---|
| 180 | goto error; |
---|
| 181 | } |
---|
| 182 | |
---|
| 183 | oldDoc = style->doc; |
---|
| 184 | style->doc = include->doc; |
---|
| 185 | ret = (int)xsltParseStylesheetProcess(style, include->doc); |
---|
| 186 | style->doc = oldDoc; |
---|
| 187 | if (ret == 0) { |
---|
| 188 | ret = -1; |
---|
| 189 | goto error; |
---|
| 190 | } |
---|
| 191 | ret = 0; |
---|
| 192 | |
---|
| 193 | error: |
---|
| 194 | if (uriRef != NULL) |
---|
| 195 | xmlFree(uriRef); |
---|
| 196 | if (base != NULL) |
---|
| 197 | xmlFree(base); |
---|
| 198 | if (URI != NULL) |
---|
| 199 | xmlFree(URI); |
---|
| 200 | |
---|
| 201 | return (ret); |
---|
| 202 | } |
---|
| 203 | |
---|
| 204 | /** |
---|
| 205 | * xsltNextImport: |
---|
| 206 | * @cur: the current XSLT stylesheet |
---|
| 207 | * |
---|
| 208 | * Find the next stylesheet in import precedence. |
---|
| 209 | * |
---|
| 210 | * Returns the next stylesheet or NULL if it was the last one |
---|
| 211 | */ |
---|
| 212 | |
---|
| 213 | xsltStylesheetPtr |
---|
| 214 | xsltNextImport(xsltStylesheetPtr cur) { |
---|
| 215 | if (cur == NULL) |
---|
| 216 | return(NULL); |
---|
| 217 | if (cur->imports != NULL) |
---|
| 218 | return(cur->imports); |
---|
| 219 | if (cur->next != NULL) |
---|
| 220 | return(cur->next) ; |
---|
| 221 | do { |
---|
| 222 | cur = cur->parent; |
---|
| 223 | if (cur == NULL) return(NULL); |
---|
| 224 | if (cur->next != NULL) return(cur->next); |
---|
| 225 | } while (cur != NULL); |
---|
| 226 | return(cur); |
---|
| 227 | } |
---|
| 228 | |
---|
| 229 | /** |
---|
| 230 | * xsltNeedElemSpaceHandling: |
---|
| 231 | * @ctxt: an XSLT transformation context |
---|
| 232 | * |
---|
[18542] | 233 | * Checks whether that stylesheet requires white-space stripping |
---|
[18214] | 234 | * |
---|
| 235 | * Returns 1 if space should be stripped, 0 if not |
---|
| 236 | */ |
---|
| 237 | |
---|
| 238 | int |
---|
| 239 | xsltNeedElemSpaceHandling(xsltTransformContextPtr ctxt) { |
---|
| 240 | xsltStylesheetPtr style; |
---|
| 241 | |
---|
| 242 | if (ctxt == NULL) |
---|
| 243 | return(0); |
---|
| 244 | style = ctxt->style; |
---|
| 245 | while (style != NULL) { |
---|
| 246 | if (style->stripSpaces != NULL) |
---|
| 247 | return(1); |
---|
| 248 | style = xsltNextImport(style); |
---|
| 249 | } |
---|
| 250 | return(0); |
---|
| 251 | } |
---|
| 252 | |
---|
| 253 | /** |
---|
| 254 | * xsltFindElemSpaceHandling: |
---|
| 255 | * @ctxt: an XSLT transformation context |
---|
| 256 | * @node: an XML node |
---|
| 257 | * |
---|
| 258 | * Find strip-space or preserve-space informations for an element |
---|
| 259 | * respect the import precedence or the wildcards |
---|
| 260 | * |
---|
| 261 | * Returns 1 if space should be stripped, 0 if not, and 2 if everything |
---|
| 262 | * should be CDTATA wrapped. |
---|
| 263 | */ |
---|
| 264 | |
---|
| 265 | int |
---|
| 266 | xsltFindElemSpaceHandling(xsltTransformContextPtr ctxt, xmlNodePtr node) { |
---|
| 267 | xsltStylesheetPtr style; |
---|
| 268 | const xmlChar *val; |
---|
| 269 | |
---|
| 270 | if ((ctxt == NULL) || (node == NULL)) |
---|
| 271 | return(0); |
---|
| 272 | style = ctxt->style; |
---|
| 273 | while (style != NULL) { |
---|
| 274 | if (node->ns != NULL) { |
---|
| 275 | val = (const xmlChar *) |
---|
| 276 | xmlHashLookup2(style->stripSpaces, node->name, node->ns->href); |
---|
| 277 | } else { |
---|
| 278 | val = (const xmlChar *) |
---|
| 279 | xmlHashLookup2(style->stripSpaces, node->name, NULL); |
---|
| 280 | } |
---|
| 281 | if (val != NULL) { |
---|
| 282 | if (xmlStrEqual(val, (xmlChar *) "strip")) |
---|
| 283 | return(1); |
---|
| 284 | if (xmlStrEqual(val, (xmlChar *) "preserve")) |
---|
| 285 | return(0); |
---|
| 286 | } |
---|
[18542] | 287 | if (style->stripAll == 1) |
---|
[18214] | 288 | return(1); |
---|
[18542] | 289 | if (style->stripAll == -1) |
---|
[18214] | 290 | return(0); |
---|
| 291 | |
---|
| 292 | style = xsltNextImport(style); |
---|
| 293 | } |
---|
| 294 | return(0); |
---|
| 295 | } |
---|
| 296 | |
---|
| 297 | /** |
---|
| 298 | * xsltFindTemplate: |
---|
| 299 | * @ctxt: an XSLT transformation context |
---|
| 300 | * @name: the template name |
---|
| 301 | * @nameURI: the template name URI |
---|
| 302 | * |
---|
| 303 | * Finds the named template, apply import precedence rule. |
---|
| 304 | * |
---|
| 305 | * Returns the xsltTemplatePtr or NULL if not found |
---|
| 306 | */ |
---|
| 307 | xsltTemplatePtr |
---|
| 308 | xsltFindTemplate(xsltTransformContextPtr ctxt, const xmlChar *name, |
---|
| 309 | const xmlChar *nameURI) { |
---|
| 310 | xsltTemplatePtr cur; |
---|
| 311 | xsltStylesheetPtr style; |
---|
| 312 | |
---|
| 313 | if ((ctxt == NULL) || (name == NULL)) |
---|
| 314 | return(NULL); |
---|
| 315 | style = ctxt->style; |
---|
| 316 | while (style != NULL) { |
---|
| 317 | cur = style->templates; |
---|
| 318 | while (cur != NULL) { |
---|
| 319 | if (xmlStrEqual(name, cur->name)) { |
---|
| 320 | if (((nameURI == NULL) && (cur->nameURI == NULL)) || |
---|
| 321 | ((nameURI != NULL) && (cur->nameURI != NULL) && |
---|
| 322 | (xmlStrEqual(nameURI, cur->nameURI)))) { |
---|
| 323 | return(cur); |
---|
| 324 | } |
---|
| 325 | } |
---|
| 326 | cur = cur->next; |
---|
| 327 | } |
---|
| 328 | |
---|
| 329 | style = xsltNextImport(style); |
---|
| 330 | } |
---|
| 331 | return(NULL); |
---|
| 332 | } |
---|
| 333 | |
---|