static xmlDocPtr php_xsl_apply_stylesheet(zval *id, xsl_object *intern, xsltStylesheetPtr style, zval *docp) /* {{{ */ { xmlDocPtr newdocp = NULL; xmlDocPtr doc = NULL; xmlNodePtr node = NULL; xsltTransformContextPtr ctxt; php_libxml_node_object *object; char **params = NULL; int clone; zval *doXInclude, member, rv; zend_object_handlers *std_hnd; FILE *f; int secPrefsError = 0; int secPrefsValue; xsltSecurityPrefsPtr secPrefs = NULL; node = php_libxml_import_node(docp); if (node) { doc = node->doc; } if (doc == NULL) { php_error_docref(NULL, E_WARNING, "Invalid Document"); return NULL; } if (style == NULL) { php_error_docref(NULL, E_WARNING, "No stylesheet associated to this object"); return NULL; } if (intern->profiling) { if (php_check_open_basedir(intern->profiling)) { f = NULL; } else { f = VCWD_FOPEN(intern->profiling, "w"); } } else { f = NULL; } if (intern->parameter) { params = php_xsl_xslt_make_params(intern->parameter, 0); } intern->doc = emalloc(sizeof(php_libxml_node_object)); memset(intern->doc, 0, sizeof(php_libxml_node_object)); if (intern->hasKeys == 1) { doc = xmlCopyDoc(doc, 1); } else { object = Z_LIBXML_NODE_P(docp); intern->doc->document = object->document; } php_libxml_increment_doc_ref(intern->doc, doc); ctxt = xsltNewTransformContext(style, doc); ctxt->_private = (void *) intern; std_hnd = zend_get_std_object_handlers(); ZVAL_STRING(&member, "doXInclude"); doXInclude = std_hnd->read_property(id, &member, BP_VAR_IS, NULL, &rv); if (Z_TYPE_P(doXInclude) != IS_NULL) { convert_to_long(doXInclude); ctxt->xinclude = Z_LVAL_P(doXInclude); } zval_ptr_dtor(&member); secPrefsValue = intern->securityPrefs; /* if securityPrefs is set to NONE, we don't have to do any checks, but otherwise... */ if (secPrefsValue != XSL_SECPREF_NONE) { secPrefs = xsltNewSecurityPrefs(); if (secPrefsValue & XSL_SECPREF_READ_FILE ) { if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid)) { secPrefsError = 1; } } if (secPrefsValue & XSL_SECPREF_WRITE_FILE ) { if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid)) { secPrefsError = 1; } } if (secPrefsValue & XSL_SECPREF_CREATE_DIRECTORY ) { if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid)) { secPrefsError = 1; } } if (secPrefsValue & XSL_SECPREF_READ_NETWORK) { if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid)) { secPrefsError = 1; } } if (secPrefsValue & XSL_SECPREF_WRITE_NETWORK) { if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid)) { secPrefsError = 1; } } if (0 != xsltSetCtxtSecurityPrefs(secPrefs, ctxt)) { secPrefsError = 1; } } if (secPrefsError == 1) { php_error_docref(NULL, E_WARNING, "Can't set libxslt security properties, not doing transformation for security reasons"); } else { newdocp = xsltApplyStylesheetUser(style, doc, (const char**) params, NULL, f, ctxt); } if (f) { fclose(f); } xsltFreeTransformContext(ctxt); if (secPrefs) { xsltFreeSecurityPrefs(secPrefs); } if (intern->node_list != NULL) { zend_hash_destroy(intern->node_list); FREE_HASHTABLE(intern->node_list); intern->node_list = NULL; } php_libxml_decrement_doc_ref(intern->doc); efree(intern->doc); intern->doc = NULL; if (params) { clone = 0; while(params[clone]) { efree(params[clone++]); } efree(params); } return newdocp; }
bool XSLTProcessor::transformToString(Node* sourceNode, String& mimeType, String& resultString, String& resultEncoding) { RefPtr<Document> ownerDocument = sourceNode->document(); setXSLTLoadCallBack(docLoaderFunc, this, ownerDocument->cachedResourceLoader()); xsltStylesheetPtr sheet = xsltStylesheetPointer(m_stylesheet, m_stylesheetRootNode.get()); if (!sheet) { setXSLTLoadCallBack(0, 0, 0); m_stylesheet = 0; return false; } m_stylesheet->clearDocuments(); xmlChar* origMethod = sheet->method; if (!origMethod && mimeType == "text/html") sheet->method = (xmlChar*)"html"; bool success = false; bool shouldFreeSourceDoc = false; if (xmlDocPtr sourceDoc = xmlDocPtrFromNode(sourceNode, shouldFreeSourceDoc)) { // The XML declaration would prevent parsing the result as a fragment, and it's not needed even for documents, // as the result of this function is always immediately parsed. sheet->omitXmlDeclaration = true; xsltTransformContextPtr transformContext = xsltNewTransformContext(sheet, sourceDoc); registerXSLTExtensions(transformContext); xsltSecurityPrefsPtr securityPrefs = xsltNewSecurityPrefs(); // Read permissions are checked by docLoaderFunc. if (0 != xsltSetSecurityPrefs(securityPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid)) CRASH(); if (0 != xsltSetSecurityPrefs(securityPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid)) CRASH(); if (0 != xsltSetSecurityPrefs(securityPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid)) CRASH(); if (0 != xsltSetCtxtSecurityPrefs(securityPrefs, transformContext)) CRASH(); // <http://bugs.webkit.org/show_bug.cgi?id=16077>: XSLT processor <xsl:sort> algorithm only compares by code point. xsltSetCtxtSortFunc(transformContext, xsltUnicodeSortFunction); // This is a workaround for a bug in libxslt. // The bug has been fixed in version 1.1.13, so once we ship that this can be removed. if (!transformContext->globalVars) transformContext->globalVars = xmlHashCreate(20); const char** params = xsltParamArrayFromParameterMap(m_parameters); xsltQuoteUserParams(transformContext, params); xmlDocPtr resultDoc = xsltApplyStylesheetUser(sheet, sourceDoc, 0, 0, 0, transformContext); xsltFreeTransformContext(transformContext); xsltFreeSecurityPrefs(securityPrefs); freeXsltParamArray(params); if (shouldFreeSourceDoc) xmlFreeDoc(sourceDoc); if ((success = saveResultToString(resultDoc, sheet, resultString))) { mimeType = resultMIMEType(resultDoc, sheet); resultEncoding = (char*)resultDoc->encoding; } xmlFreeDoc(resultDoc); } sheet->method = origMethod; setXSLTLoadCallBack(0, 0, 0); xsltFreeStylesheet(sheet); m_stylesheet = 0; return success; }
xmlDocPtr c_XSLTProcessor::apply_stylesheet() { SYNC_VM_REGS_SCOPED(); if (m_stylesheet == nullptr || m_doc == nullptr) { raise_error("Unable to apply stylesheet"); return nullptr; } xsltTransformContextPtr ctxt = xsltNewTransformContext (m_stylesheet, m_doc); if (ctxt == nullptr) { raise_error("Unable to apply stylesheet"); return nullptr; } ctxt->_private = this; xsltSecurityPrefsPtr prefs = nullptr; if (m_secprefs != k_XSL_SECPREF_NONE) { prefs = xsltNewSecurityPrefs(); int error = 0; if (m_secprefs & k_XSL_SECPREF_READ_FILE) { if (xsltSetSecurityPrefs(prefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid) != 0) { error = 1; } } if (m_secprefs & k_XSL_SECPREF_WRITE_FILE) { if (xsltSetSecurityPrefs(prefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid) != 0) { error = 1; } } if (m_secprefs & k_XSL_SECPREF_CREATE_DIRECTORY) { if (xsltSetSecurityPrefs(prefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid) != 0) { error = 1; } } if (m_secprefs & k_XSL_SECPREF_READ_NETWORK) { if (xsltSetSecurityPrefs(prefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid) != 0) { error = 1; } } if (m_secprefs & k_XSL_SECPREF_WRITE_NETWORK) { if (xsltSetSecurityPrefs(prefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid) != 0) { error = 1; } } if (xsltSetCtxtSecurityPrefs(prefs, ctxt) != 0) { error = 1; } if (error == 1) { raise_error("Can't set libxslt security properties, not doing " "transformation for security reasons"); return nullptr; } } xsltRegisterExtFunction(ctxt, (const xmlChar*) "functionString", (const xmlChar*) "http://php.net/xsl", xslt_ext_function_string_php ); xsltRegisterExtFunction(ctxt, (const xmlChar*) "function", (const xmlChar*) "http://php.net/xsl", xslt_ext_function_object_php ); for (ArrayIter iter(m_params); iter; ++iter) { assert(iter.first().isString()); assert(iter.second().isString()); xmlChar *value = xslt_string_to_xpathexpr(iter.second().toString().c_str()); if (value) { xsltEvalOneUserParam(ctxt, (const xmlChar*)iter.first().toString().c_str(), (const xmlChar*)value ); xmlFree(value); } } FILE *profile = nullptr; if (m_profile) { profile = fopen(m_profile.data(), "w"); } xmlDocPtr res = xsltApplyStylesheetUser(m_stylesheet, m_doc, nullptr, nullptr, profile, ctxt); if (profile) { fclose(profile); } xsltFreeTransformContext(ctxt); if (prefs) { xsltFreeSecurityPrefs(prefs); } return res; }