Back to index

php5  5.3.10
xsltprocessor.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Authors: Christian Stocker <chregu@php.net>                          |
00016    |          Rob Richards <rrichards@php.net>                            |
00017    +----------------------------------------------------------------------+
00018 */
00019 
00020 /* $Id: xsltprocessor.c 321634 2012-01-01 13:15:04Z felipe $ */
00021 
00022 #ifdef HAVE_CONFIG_H
00023 #include "config.h"
00024 #endif
00025 
00026 #include "php.h"
00027 #include "php_xsl.h"
00028 #include "ext/libxml/php_libxml.h"
00029 
00030 /* {{{ arginfo */
00031 ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_import_stylesheet, 0, 0, 1)
00032        ZEND_ARG_INFO(0, doc)
00033 ZEND_END_ARG_INFO();
00034 
00035 ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_transform_to_doc, 0, 0, 1)
00036        ZEND_ARG_INFO(0, doc)
00037 ZEND_END_ARG_INFO();
00038 
00039 ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_transform_to_uri, 0, 0, 2)
00040        ZEND_ARG_INFO(0, doc)
00041        ZEND_ARG_INFO(0, uri)
00042 ZEND_END_ARG_INFO();
00043 
00044 ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_transform_to_xml, 0, 0, 1)
00045        ZEND_ARG_INFO(0, doc)
00046 ZEND_END_ARG_INFO();
00047 
00048 ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_set_parameter, 0, 0, 2)
00049        ZEND_ARG_INFO(0, namespace)
00050        ZEND_ARG_INFO(0, name)
00051        ZEND_ARG_INFO(0, value)
00052 ZEND_END_ARG_INFO();
00053 
00054 ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_get_parameter, 0, 0, 2)
00055        ZEND_ARG_INFO(0, namespace)
00056        ZEND_ARG_INFO(0, name)
00057 ZEND_END_ARG_INFO();
00058 
00059 ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_remove_parameter, 0, 0, 2)
00060        ZEND_ARG_INFO(0, namespace)
00061        ZEND_ARG_INFO(0, name)
00062 ZEND_END_ARG_INFO();
00063 
00064 ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_has_exslt_support, 0, 0, 0)
00065 ZEND_END_ARG_INFO();
00066 
00067 ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_register_php_functions, 0, 0, 0)
00068        ZEND_ARG_INFO(0, restrict)
00069 ZEND_END_ARG_INFO();
00070 
00071 ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_set_profiling, 0, 0, 1)
00072        ZEND_ARG_INFO(0, filename)
00073 ZEND_END_ARG_INFO();
00074 /* }}} */
00075 
00076 /*
00077 * class xsl_xsltprocessor 
00078 *
00079 * URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#
00080 * Since: 
00081 */
00082 
00083 const zend_function_entry php_xsl_xsltprocessor_class_functions[] = {
00084        PHP_FALIAS(importStylesheet, xsl_xsltprocessor_import_stylesheet, arginfo_xsl_xsltprocessor_import_stylesheet)
00085        PHP_FALIAS(transformToDoc, xsl_xsltprocessor_transform_to_doc, arginfo_xsl_xsltprocessor_transform_to_doc)
00086        PHP_FALIAS(transformToUri, xsl_xsltprocessor_transform_to_uri, arginfo_xsl_xsltprocessor_transform_to_uri)
00087        PHP_FALIAS(transformToXml, xsl_xsltprocessor_transform_to_xml, arginfo_xsl_xsltprocessor_transform_to_xml)
00088        PHP_FALIAS(setParameter, xsl_xsltprocessor_set_parameter, arginfo_xsl_xsltprocessor_set_parameter)
00089        PHP_FALIAS(getParameter, xsl_xsltprocessor_get_parameter, arginfo_xsl_xsltprocessor_get_parameter)
00090        PHP_FALIAS(removeParameter, xsl_xsltprocessor_remove_parameter, arginfo_xsl_xsltprocessor_remove_parameter)
00091        PHP_FALIAS(hasExsltSupport, xsl_xsltprocessor_has_exslt_support, arginfo_xsl_xsltprocessor_has_exslt_support)
00092        PHP_FALIAS(registerPHPFunctions, xsl_xsltprocessor_register_php_functions, arginfo_xsl_xsltprocessor_register_php_functions)
00093        PHP_FALIAS(setProfiling, xsl_xsltprocessor_set_profiling, arginfo_xsl_xsltprocessor_set_profiling)
00094        {NULL, NULL, NULL}
00095 };
00096 
00097 /* {{{ php_xsl_xslt_string_to_xpathexpr()
00098    Translates a string to a XPath Expression */
00099 static char *php_xsl_xslt_string_to_xpathexpr(const char *str TSRMLS_DC)
00100 {
00101        const xmlChar *string = (const xmlChar *)str;
00102 
00103        xmlChar *value;
00104        int str_len;
00105        
00106        str_len = xmlStrlen(string) + 3;
00107        
00108        if (xmlStrchr(string, '"')) {
00109               if (xmlStrchr(string, '\'')) {
00110                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create XPath expression (string contains both quote and double-quotes)");
00111                      return NULL;
00112               }
00113               value = (xmlChar*) safe_emalloc (str_len, sizeof(xmlChar), 0);
00114               snprintf(value, str_len, "'%s'", string);
00115        } else {
00116               value = (xmlChar*) safe_emalloc (str_len, sizeof(xmlChar), 0);
00117               snprintf(value, str_len, "\"%s\"", string);
00118        }
00119        return (char *) value;
00120 }
00121 /* }}} */
00122 
00123 /* {{{ php_xsl_xslt_make_params()
00124    Translates a PHP array to a libxslt parameters array */
00125 static char **php_xsl_xslt_make_params(HashTable *parht, int xpath_params TSRMLS_DC)
00126 {
00127        
00128        int parsize;
00129        zval **value;
00130        char *xpath_expr, *string_key = NULL;
00131        ulong num_key;
00132        char **params = NULL;
00133        int i = 0;
00134 
00135        parsize = (2 * zend_hash_num_elements(parht) + 1) * sizeof(char *);
00136        params = (char **)safe_emalloc((2 * zend_hash_num_elements(parht) + 1), sizeof(char *), 0);
00137        memset((char *)params, 0, parsize);
00138 
00139        for (zend_hash_internal_pointer_reset(parht);
00140               zend_hash_get_current_data(parht, (void **)&value) == SUCCESS;
00141               zend_hash_move_forward(parht)) {
00142 
00143               if (zend_hash_get_current_key(parht, &string_key, &num_key, 1) != HASH_KEY_IS_STRING) {
00144                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid argument or parameter array");
00145                      efree(params);
00146                      return NULL;
00147               } else {
00148                      if (Z_TYPE_PP(value) != IS_STRING) {
00149                             SEPARATE_ZVAL(value);
00150                             convert_to_string(*value);
00151                      }
00152                      
00153                      if (!xpath_params) {
00154                             xpath_expr = php_xsl_xslt_string_to_xpathexpr(Z_STRVAL_PP(value) TSRMLS_CC);
00155                      } else {
00156                             xpath_expr = estrndup(Z_STRVAL_PP(value), Z_STRLEN_PP(value));
00157                      }
00158                      if (xpath_expr) {
00159                             params[i++] = string_key;
00160                             params[i++] = xpath_expr;
00161                      } else {
00162                             efree(string_key);
00163                      }
00164               }
00165        }
00166 
00167        params[i++] = NULL;
00168 
00169        return params;
00170 }
00171 /* }}} */
00172 
00173 static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int type) /* {{{ */
00174 {
00175        xsltTransformContextPtr tctxt;
00176        zval **args;
00177        zval *retval;
00178        int result, i, ret;
00179        int error = 0;
00180        zend_fcall_info fci;
00181        zval handler;
00182        xmlXPathObjectPtr obj;
00183        char *str;
00184        char *callable = NULL;
00185        xsl_object *intern;
00186        
00187        TSRMLS_FETCH();
00188 
00189        if (! zend_is_executing(TSRMLS_C)) {
00190               xsltGenericError(xsltGenericErrorContext,
00191               "xsltExtFunctionTest: Function called from outside of PHP\n");
00192               error = 1;
00193        } else {
00194               tctxt = xsltXPathGetTransformContext(ctxt);
00195               if (tctxt == NULL) {
00196                      xsltGenericError(xsltGenericErrorContext,
00197                      "xsltExtFunctionTest: failed to get the transformation context\n");
00198                      error = 1;
00199               } else {
00200                      intern = (xsl_object *) tctxt->_private;
00201                      if (intern == NULL) {
00202                             xsltGenericError(xsltGenericErrorContext,
00203                             "xsltExtFunctionTest: failed to get the internal object\n");
00204                             error = 1;
00205                      }
00206                      else if (intern->registerPhpFunctions == 0) {
00207                             xsltGenericError(xsltGenericErrorContext,
00208                             "xsltExtFunctionTest: PHP Object did not register PHP functions\n");
00209                             error = 1;
00210                      }
00211               }
00212        }
00213        
00214        if (error == 1) {
00215               for (i = nargs - 1; i >= 0; i--) {
00216                      obj = valuePop(ctxt);
00217                      xmlXPathFreeObject(obj);
00218               }
00219               return;
00220        }
00221               
00222        fci.param_count = nargs - 1;
00223        if (fci.param_count > 0) {
00224               fci.params = safe_emalloc(fci.param_count, sizeof(zval**), 0);
00225               args = safe_emalloc(fci.param_count, sizeof(zval *), 0);
00226        }
00227        /* Reverse order to pop values off ctxt stack */
00228        for (i = nargs - 2; i >= 0; i--) {
00229               obj = valuePop(ctxt);
00230               MAKE_STD_ZVAL(args[i]);
00231               switch (obj->type) {
00232                      case XPATH_STRING:
00233                             ZVAL_STRING(args[i],  obj->stringval, 1);
00234                             break;
00235                      case XPATH_BOOLEAN:
00236                             ZVAL_BOOL(args[i],  obj->boolval);
00237                             break;
00238                      case XPATH_NUMBER:
00239                             ZVAL_DOUBLE(args[i], obj->floatval);
00240                             break;
00241                      case XPATH_NODESET:
00242                             if (type == 1) {
00243                                    str = xmlXPathCastToString(obj);
00244                                    ZVAL_STRING(args[i], str, 1);
00245                                    xmlFree(str);
00246                             } else if (type == 2) {
00247                                    int j;
00248                                    dom_object *domintern = (dom_object *)intern->doc;
00249                                    array_init(args[i]);
00250                                    if (obj->nodesetval && obj->nodesetval->nodeNr > 0) {
00251                                           for (j = 0; j < obj->nodesetval->nodeNr; j++) {
00252                                                  xmlNodePtr node = obj->nodesetval->nodeTab[j];
00253                                                  zval *child;
00254                                                  MAKE_STD_ZVAL(child);
00255                                                  /* not sure, if we need this... it's copied from xpath.c */
00256                                                  if (node->type == XML_NAMESPACE_DECL) {
00257                                                         xmlNsPtr curns;
00258                                                         xmlNodePtr nsparent;
00259                                                         
00260                                                         nsparent = node->_private;
00261                                                         curns = xmlNewNs(NULL, node->name, NULL);
00262                                                         if (node->children) {
00263                                                                curns->prefix = xmlStrdup((char *) node->children);
00264                                                         }
00265                                                         if (node->children) {
00266                                                                node = xmlNewDocNode(node->doc, NULL, (char *) node->children, node->name);
00267                                                         } else {
00268                                                                node = xmlNewDocNode(node->doc, NULL, "xmlns", node->name);
00269                                                         }
00270                                                         node->type = XML_NAMESPACE_DECL;
00271                                                         node->parent = nsparent;
00272                                                         node->ns = curns;
00273                                                  }
00274                                                  child = php_dom_create_object(node, &ret, NULL, child, domintern TSRMLS_CC);
00275                                                  add_next_index_zval(args[i], child);
00276                                           }
00277                                    }
00278                             }
00279                             break;
00280                      default:
00281                             str = xmlXPathCastToString(obj);
00282                             ZVAL_STRING(args[i], str, 1);
00283                             xmlFree(str);
00284               }
00285               xmlXPathFreeObject(obj);
00286               fci.params[i] = &args[i];
00287        }
00288        
00289        fci.size = sizeof(fci);
00290        fci.function_table = EG(function_table);
00291        
00292        obj = valuePop(ctxt);
00293        if (obj->stringval == NULL) {
00294               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Handler name must be a string");
00295               xmlXPathFreeObject(obj);
00296               if (fci.param_count > 0) {
00297                      for (i = 0; i < nargs - 1; i++) {
00298                             zval_ptr_dtor(&args[i]);
00299                      }
00300                      efree(args);
00301                      efree(fci.params);
00302               }
00303               return; 
00304        }
00305        INIT_PZVAL(&handler);
00306        ZVAL_STRING(&handler, obj->stringval, 1);
00307        xmlXPathFreeObject(obj);
00308        
00309        fci.function_name = &handler;
00310        fci.symbol_table = NULL;
00311        fci.object_ptr = NULL;
00312        fci.retval_ptr_ptr = &retval;
00313        fci.no_separation = 0;
00314        /*fci.function_handler_cache = &function_ptr;*/
00315        if (!zend_make_callable(&handler, &callable TSRMLS_CC)) {
00316               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call handler %s()", callable);
00317               
00318        } else if ( intern->registerPhpFunctions == 2 && zend_hash_exists(intern->registered_phpfunctions, callable, strlen(callable) + 1) == 0) { 
00319               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not allowed to call handler '%s()'", callable);
00320               /* Push an empty string, so that we at least have an xslt result... */
00321               valuePush(ctxt, xmlXPathNewString(""));
00322        } else {
00323               result = zend_call_function(&fci, NULL TSRMLS_CC);
00324               if (result == FAILURE) {
00325                      if (Z_TYPE(handler) == IS_STRING) {
00326                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call handler %s()", Z_STRVAL_P(&handler));
00327                      }
00328               /* retval is == NULL, when an exception occured, don't report anything, because PHP itself will handle that */
00329               } else if (retval == NULL) {
00330               } else {
00331                      if (retval->type == IS_OBJECT && instanceof_function( Z_OBJCE_P(retval), dom_node_class_entry TSRMLS_CC)) {
00332                             xmlNode *nodep;
00333                             dom_object *obj;
00334                             if (intern->node_list == NULL) {
00335                                    ALLOC_HASHTABLE(intern->node_list);
00336                                    zend_hash_init(intern->node_list, 0, NULL, ZVAL_PTR_DTOR, 0);
00337                             }
00338                             zval_add_ref(&retval);
00339                             zend_hash_next_index_insert(intern->node_list, &retval, sizeof(zval *), NULL);
00340                             obj = (dom_object *)zend_object_store_get_object(retval TSRMLS_CC);
00341                             nodep = dom_object_get_node(obj);
00342                             valuePush(ctxt, xmlXPathNewNodeSet(nodep));
00343                      } else if (retval->type == IS_BOOL) {
00344                             valuePush(ctxt, xmlXPathNewBoolean(retval->value.lval));
00345                      } else if (retval->type == IS_OBJECT) {
00346                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "A PHP Object cannot be converted to a XPath-string");
00347                             valuePush(ctxt, xmlXPathNewString(""));
00348                      } else {
00349                             convert_to_string_ex(&retval);
00350                             valuePush(ctxt, xmlXPathNewString( Z_STRVAL_P(retval)));
00351                      }
00352                      zval_ptr_dtor(&retval);
00353               }
00354        }
00355        efree(callable);
00356        zval_dtor(&handler);
00357        if (fci.param_count > 0) {
00358               for (i = 0; i < nargs - 1; i++) {
00359                      zval_ptr_dtor(&args[i]);
00360               }
00361               efree(args);
00362               efree(fci.params);
00363        }
00364 }
00365 /* }}} */
00366 
00367 void xsl_ext_function_string_php(xmlXPathParserContextPtr ctxt, int nargs) /* {{{ */
00368 {
00369        xsl_ext_function_php(ctxt, nargs, 1);
00370 }
00371 /* }}} */
00372 
00373 void xsl_ext_function_object_php(xmlXPathParserContextPtr ctxt, int nargs) /* {{{ */
00374 {
00375        xsl_ext_function_php(ctxt, nargs, 2);
00376 }
00377 /* }}} */
00378 
00379 /* {{{ proto void xsl_xsltprocessor_import_stylesheet(domdocument doc);
00380 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#
00381 Since: 
00382 */
00383 PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet)
00384 {
00385        zval *id, *docp = NULL;
00386        xmlDoc *doc = NULL, *newdoc = NULL;
00387        xsltStylesheetPtr sheetp, oldsheetp;
00388        xsl_object *intern;
00389        int prevSubstValue, prevExtDtdValue, clone_docu = 0;
00390        xmlNode *nodep = NULL;
00391        zend_object_handlers *std_hnd;
00392        zval *cloneDocu, *member;
00393        
00394        if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oo", &id, xsl_xsltprocessor_class_entry, &docp) == FAILURE) {
00395               RETURN_FALSE;
00396        }
00397 
00398        nodep = php_libxml_import_node(docp TSRMLS_CC);
00399        
00400        if (nodep) {
00401               doc = nodep->doc;
00402        }
00403        if (doc == NULL) {
00404               php_error(E_WARNING, "Invalid Document");
00405               RETURN_FALSE;
00406        }
00407 
00408        /* libxslt uses _private, so we must copy the imported 
00409        stylesheet document otherwise the node proxies will be a mess */
00410        newdoc = xmlCopyDoc(doc, 1);
00411        xmlNodeSetBase((xmlNodePtr) newdoc, (xmlChar *)doc->URL);
00412        prevSubstValue = xmlSubstituteEntitiesDefault(1);
00413        prevExtDtdValue = xmlLoadExtDtdDefaultValue;
00414        xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
00415 
00416        sheetp = xsltParseStylesheetDoc(newdoc);
00417        xmlSubstituteEntitiesDefault(prevSubstValue);
00418        xmlLoadExtDtdDefaultValue = prevExtDtdValue;
00419 
00420        if (!sheetp) {
00421               xmlFreeDoc(newdoc);
00422               RETURN_FALSE;
00423        }
00424 
00425        intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC); 
00426 
00427        std_hnd = zend_get_std_object_handlers();
00428        MAKE_STD_ZVAL(member);
00429        ZVAL_STRING(member, "cloneDocument", 0);
00430        cloneDocu = std_hnd->read_property(id, member, BP_VAR_IS TSRMLS_CC);
00431        if (Z_TYPE_P(cloneDocu) != IS_NULL) {
00432               convert_to_long(cloneDocu);
00433               clone_docu = Z_LVAL_P(cloneDocu);
00434        }
00435        efree(member);
00436        if (clone_docu == 0) {
00437               /* check if the stylesheet is using xsl:key, if yes, we have to clone the document _always_ before a transformation */
00438               nodep = xmlDocGetRootElement(sheetp->doc);
00439               if (nodep && (nodep = nodep->children)) {
00440                      while (nodep) {
00441                             if (nodep->type == XML_ELEMENT_NODE && xmlStrEqual(nodep->name, "key") && xmlStrEqual(nodep->ns->href, XSLT_NAMESPACE)) {
00442                                    intern->hasKeys = 1;
00443                                    break;
00444                             }
00445                             nodep = nodep->next;
00446                      }
00447               }
00448        } else {
00449               intern->hasKeys = clone_docu;
00450        }
00451 
00452        if ((oldsheetp = (xsltStylesheetPtr)intern->ptr)) { 
00453               /* free wrapper */
00454               if (((xsltStylesheetPtr) intern->ptr)->_private != NULL) {
00455                      ((xsltStylesheetPtr) intern->ptr)->_private = NULL;   
00456               }
00457               xsltFreeStylesheet((xsltStylesheetPtr) intern->ptr);
00458               intern->ptr = NULL;
00459        }
00460 
00461        php_xsl_set_object(id, sheetp TSRMLS_CC);
00462        RETVAL_TRUE;
00463 }
00464 /* }}} end xsl_xsltprocessor_import_stylesheet */
00465 
00466 static xmlDocPtr php_xsl_apply_stylesheet(zval *id, xsl_object *intern, xsltStylesheetPtr style, zval *docp TSRMLS_DC) /* {{{ */
00467 {
00468        xmlDocPtr newdocp;
00469        xmlDocPtr doc = NULL;
00470        xmlNodePtr node = NULL;
00471        xsltTransformContextPtr ctxt;
00472        php_libxml_node_object *object;
00473        char **params = NULL;
00474        int clone;
00475        zval *doXInclude, *member;
00476        zend_object_handlers *std_hnd;
00477        FILE *f;
00478        int secPrefsError = 0;
00479        int secPrefsValue;
00480        xsltSecurityPrefsPtr secPrefs = NULL;
00481 
00482        node = php_libxml_import_node(docp TSRMLS_CC);
00483        
00484        if (node) {
00485               doc = node->doc;
00486        }
00487        if (doc == NULL) {
00488               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Document");
00489               return NULL;
00490        }
00491 
00492        if (style == NULL) {
00493               php_error_docref(NULL TSRMLS_CC, E_WARNING, "No stylesheet associated to this object");
00494               return NULL;
00495        }
00496        
00497        if (intern->profiling) {
00498               if (php_check_open_basedir(intern->profiling TSRMLS_CC)) {
00499                      f = NULL;
00500               } else {
00501                      f = VCWD_FOPEN(intern->profiling, "w");
00502               }
00503        } else {
00504               f = NULL;
00505        }
00506        
00507        if (intern->parameter) {
00508               params = php_xsl_xslt_make_params(intern->parameter, 0 TSRMLS_CC);
00509        }
00510 
00511        intern->doc = emalloc(sizeof(php_libxml_node_object));
00512        memset(intern->doc, 0, sizeof(php_libxml_node_object));
00513 
00514        if (intern->hasKeys == 1) {
00515               doc = xmlCopyDoc(doc, 1);
00516        } else {
00517               object = (php_libxml_node_object *)zend_object_store_get_object(docp TSRMLS_CC);
00518               intern->doc->document = object->document;
00519        }
00520 
00521        php_libxml_increment_doc_ref(intern->doc, doc TSRMLS_CC);
00522 
00523        ctxt = xsltNewTransformContext(style, doc);
00524        ctxt->_private = (void *) intern;
00525 
00526        std_hnd = zend_get_std_object_handlers();
00527 
00528        MAKE_STD_ZVAL(member);
00529        ZVAL_STRING(member, "doXInclude", 0);
00530        doXInclude = std_hnd->read_property(id, member, BP_VAR_IS TSRMLS_CC);
00531        if (Z_TYPE_P(doXInclude) != IS_NULL) {
00532               convert_to_long(doXInclude);
00533               ctxt->xinclude = Z_LVAL_P(doXInclude);
00534        }
00535        efree(member);
00536 
00537        
00538        secPrefsValue = INI_INT("xsl.security_prefs");
00539        
00540        /* if securityPrefs is set to NONE, we don't have to do any checks, but otherwise... */
00541        if (secPrefsValue != XSL_SECPREF_NONE) {
00542               secPrefs = xsltNewSecurityPrefs(); 
00543               if (secPrefsValue & XSL_SECPREF_READ_FILE ) { 
00544                      if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid)) { 
00545                             secPrefsError = 1;
00546                      }
00547               }
00548               if (secPrefsValue & XSL_SECPREF_WRITE_FILE ) { 
00549                      if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid)) { 
00550                             secPrefsError = 1;
00551                      }
00552               }
00553               if (secPrefsValue & XSL_SECPREF_CREATE_DIRECTORY ) { 
00554                      if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid)) { 
00555                             secPrefsError = 1;
00556                      }
00557               }
00558               if (secPrefsValue & XSL_SECPREF_READ_NETWORK) { 
00559                      if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid)) { 
00560                             secPrefsError = 1;
00561                      }
00562               }
00563               if (secPrefsValue & XSL_SECPREF_WRITE_NETWORK) { 
00564                      if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid)) { 
00565                             secPrefsError = 1;
00566                      }
00567               }
00568        
00569               if (0 != xsltSetCtxtSecurityPrefs(secPrefs, ctxt)) { 
00570                      secPrefsError = 1;
00571               }
00572        }
00573        
00574        if (secPrefsError == 1) {
00575               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't set libxslt security properties, not doing transformation for security reasons");
00576        } else {
00577               newdocp = xsltApplyStylesheetUser(style, doc, (const char**) params,  NULL, f, ctxt);
00578        }
00579        if (f) {
00580               fclose(f);
00581        }
00582        
00583        xsltFreeTransformContext(ctxt);
00584        if (secPrefs) {
00585               xsltFreeSecurityPrefs(secPrefs);
00586        }
00587 
00588        if (intern->node_list != NULL) {
00589               zend_hash_destroy(intern->node_list);
00590               FREE_HASHTABLE(intern->node_list); 
00591               intern->node_list = NULL;
00592        }
00593 
00594        php_libxml_decrement_doc_ref(intern->doc TSRMLS_CC);
00595        efree(intern->doc);
00596        intern->doc = NULL;
00597 
00598        if (params) {
00599               clone = 0;
00600               while(params[clone]) {
00601                      efree(params[clone++]);
00602               }
00603               efree(params);
00604        }
00605 
00606        return newdocp;
00607 
00608 }
00609 /* }}} */
00610 
00611 /* {{{ proto domdocument xsl_xsltprocessor_transform_to_doc(domnode doc);
00612 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#
00613 Since: 
00614 */
00615 PHP_FUNCTION(xsl_xsltprocessor_transform_to_doc)
00616 {
00617        zval *id, *rv = NULL, *docp = NULL;
00618        xmlDoc *newdocp;
00619        xsltStylesheetPtr sheetp;
00620        int ret, ret_class_len=0;
00621        char *ret_class = NULL;
00622        xsl_object *intern;
00623 
00624        id = getThis();
00625        intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
00626        sheetp = (xsltStylesheetPtr) intern->ptr;
00627 
00628        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o|s!", &docp, &ret_class, &ret_class_len) == FAILURE) {
00629               RETURN_FALSE;
00630        }
00631 
00632        newdocp = php_xsl_apply_stylesheet(id, intern, sheetp, docp TSRMLS_CC);
00633 
00634        if (newdocp) {
00635               if (ret_class) {
00636                      int found;
00637                      char *curclass_name;
00638                      zend_class_entry *curce, **ce;
00639                      php_libxml_node_object *interndoc;
00640 
00641                      curce = Z_OBJCE_P(docp);
00642                      curclass_name = curce->name;
00643                      while (curce->parent != NULL) {
00644                             curce = curce->parent;
00645                      }
00646 
00647                      found = zend_lookup_class(ret_class, ret_class_len, &ce TSRMLS_CC);
00648                      if ((found != SUCCESS) || !instanceof_function(*ce, curce TSRMLS_CC)) {
00649                             xmlFreeDoc(newdocp);
00650                             php_error_docref(NULL TSRMLS_CC, E_WARNING, 
00651                                    "Expecting class compatible with %s, '%s' given", curclass_name, ret_class);
00652                             RETURN_FALSE;
00653                      }
00654 
00655                      object_init_ex(return_value, *ce);
00656               
00657                      interndoc = (php_libxml_node_object *)zend_objects_get_address(return_value TSRMLS_CC);
00658                      php_libxml_increment_doc_ref(interndoc, newdocp TSRMLS_CC);
00659                      php_libxml_increment_node_ptr(interndoc, (xmlNodePtr)newdocp, (void *)interndoc TSRMLS_CC);
00660               } else {
00661                      DOM_RET_OBJ(rv, (xmlNodePtr) newdocp, &ret, NULL);
00662               }
00663        } else {
00664               RETURN_FALSE;
00665        }
00666        
00667 }
00668 /* }}} end xsl_xsltprocessor_transform_to_doc */
00669 
00670 /* {{{ proto int xsl_xsltprocessor_transform_to_uri(domdocument doc, string uri);
00671 */
00672 PHP_FUNCTION(xsl_xsltprocessor_transform_to_uri)
00673 {
00674        zval *id, *docp = NULL;
00675        xmlDoc *newdocp;
00676        xsltStylesheetPtr sheetp;
00677        int ret, uri_len;
00678        char *uri;
00679        xsl_object *intern;
00680        
00681        id = getThis();
00682        intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
00683        sheetp = (xsltStylesheetPtr) intern->ptr;
00684 
00685        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "os", &docp, &uri, &uri_len) == FAILURE) {
00686               RETURN_FALSE;
00687        }
00688 
00689        newdocp = php_xsl_apply_stylesheet(id, intern, sheetp, docp TSRMLS_CC);
00690 
00691        ret = -1;
00692        if (newdocp) {
00693               if (strlen(uri) != uri_len) {
00694                      xmlFreeDoc(newdocp);
00695                      RETURN_FALSE;
00696               }
00697               ret = xsltSaveResultToFilename(uri, newdocp, sheetp, 0);
00698               xmlFreeDoc(newdocp);
00699        }
00700 
00701        RETVAL_LONG(ret);
00702 }
00703 /* }}} end xsl_xsltprocessor_transform_to_uri */
00704 
00705 /* {{{ proto string xsl_xsltprocessor_transform_to_xml(domdocument doc);
00706 */
00707 PHP_FUNCTION(xsl_xsltprocessor_transform_to_xml)
00708 {
00709        zval *id, *docp = NULL;
00710        xmlDoc *newdocp;
00711        xsltStylesheetPtr sheetp;
00712        int ret;
00713        xmlChar *doc_txt_ptr;
00714        int doc_txt_len;
00715        xsl_object *intern;
00716        
00717        id = getThis();
00718        intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
00719        sheetp = (xsltStylesheetPtr) intern->ptr;
00720 
00721        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &docp) == FAILURE) {
00722               RETURN_FALSE;
00723        }
00724 
00725        newdocp = php_xsl_apply_stylesheet(id, intern, sheetp, docp TSRMLS_CC);
00726 
00727        ret = -1;
00728        if (newdocp) {
00729               ret = xsltSaveResultToString(&doc_txt_ptr, &doc_txt_len, newdocp, sheetp);
00730               if (doc_txt_ptr && doc_txt_len) {
00731                      RETVAL_STRINGL(doc_txt_ptr, doc_txt_len, 1);
00732                      xmlFree(doc_txt_ptr);
00733               }
00734               xmlFreeDoc(newdocp);
00735        }
00736 
00737        if (ret < 0) {
00738               RETURN_FALSE;
00739        }
00740 }
00741 /* }}} end xsl_xsltprocessor_transform_to_xml */
00742 
00743 /* {{{ proto bool xsl_xsltprocessor_set_parameter(string namespace, mixed name [, string value]);
00744 */
00745 PHP_FUNCTION(xsl_xsltprocessor_set_parameter)
00746 {
00747  
00748        zval *id;
00749        zval *array_value, **entry, *new_string;
00750        xsl_object *intern;
00751        char *string_key, *name, *value, *namespace;
00752        ulong idx;
00753        int string_key_len, namespace_len, name_len, value_len;
00754        DOM_GET_THIS(id);
00755 
00756        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "sa", &namespace, &namespace_len, &array_value) == SUCCESS) {
00757               intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
00758               zend_hash_internal_pointer_reset(Z_ARRVAL_P(array_value));
00759 
00760               while (zend_hash_get_current_data(Z_ARRVAL_P(array_value), (void **)&entry) == SUCCESS) {
00761                      SEPARATE_ZVAL(entry);
00762                      convert_to_string_ex(entry);
00763                      
00764                      if (zend_hash_get_current_key_ex(Z_ARRVAL_P(array_value), &string_key, &string_key_len, &idx, 0, NULL) != HASH_KEY_IS_STRING) {
00765                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid parameter array");
00766                             RETURN_FALSE;
00767                      }
00768                      
00769                      ALLOC_ZVAL(new_string);
00770                      Z_ADDREF_PP(entry);
00771                      COPY_PZVAL_TO_ZVAL(*new_string, *entry);
00772                      
00773                      zend_hash_update(intern->parameter, string_key, string_key_len, &new_string, sizeof(zval*), NULL);
00774                      zend_hash_move_forward(Z_ARRVAL_P(array_value));
00775               }
00776               RETURN_TRUE;
00777 
00778        } else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "sss", &namespace, &namespace_len, &name, &name_len, &value, &value_len) == SUCCESS) {
00779               
00780               intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
00781               
00782               MAKE_STD_ZVAL(new_string);
00783               ZVAL_STRING(new_string, value, 1);
00784               
00785               zend_hash_update(intern->parameter, name, name_len + 1, &new_string, sizeof(zval*), NULL);
00786               RETURN_TRUE;
00787        } else {
00788               WRONG_PARAM_COUNT;
00789        }
00790        
00791 }
00792 /* }}} end xsl_xsltprocessor_set_parameter */
00793 
00794 /* {{{ proto string xsl_xsltprocessor_get_parameter(string namespace, string name);
00795 */
00796 PHP_FUNCTION(xsl_xsltprocessor_get_parameter)
00797 {
00798        zval *id;
00799        int name_len = 0, namespace_len = 0;
00800        char *name, *namespace;
00801        zval **value;
00802        xsl_object *intern;
00803 
00804        DOM_GET_THIS(id);
00805        
00806        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &namespace, &namespace_len, &name, &name_len) == FAILURE) {
00807               RETURN_FALSE;
00808        }
00809        intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
00810        if ( zend_hash_find(intern->parameter, name, name_len + 1,  (void**) &value) == SUCCESS) {
00811               convert_to_string_ex(value);
00812               RETVAL_STRING(Z_STRVAL_PP(value),1);
00813        } else {
00814               RETURN_FALSE;
00815        }
00816 }
00817 /* }}} end xsl_xsltprocessor_get_parameter */
00818 
00819 /* {{{ proto bool xsl_xsltprocessor_remove_parameter(string namespace, string name);
00820 */
00821 PHP_FUNCTION(xsl_xsltprocessor_remove_parameter)
00822 {
00823        zval *id;
00824        int name_len = 0, namespace_len = 0;
00825        char *name, *namespace;
00826        xsl_object *intern;
00827 
00828        DOM_GET_THIS(id);
00829        
00830        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &namespace, &namespace_len, &name, &name_len) == FAILURE) {
00831               RETURN_FALSE;
00832        }
00833        intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
00834        if ( zend_hash_del(intern->parameter, name, name_len + 1) == SUCCESS) {
00835               RETURN_TRUE;
00836        } else {
00837               RETURN_FALSE;
00838        }
00839 }
00840 /* }}} end xsl_xsltprocessor_remove_parameter */
00841 
00842 /* {{{ proto void xsl_xsltprocessor_register_php_functions([mixed $restrict]);
00843 */
00844 PHP_FUNCTION(xsl_xsltprocessor_register_php_functions)
00845 {
00846        zval *id;
00847        xsl_object *intern;
00848        zval *array_value, **entry, *new_string;
00849        int  name_len = 0;
00850        char *name;
00851 
00852        DOM_GET_THIS(id);
00853        
00854        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "a",  &array_value) == SUCCESS) {
00855               intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
00856               zend_hash_internal_pointer_reset(Z_ARRVAL_P(array_value));
00857 
00858               while (zend_hash_get_current_data(Z_ARRVAL_P(array_value), (void **)&entry) == SUCCESS) {
00859                      SEPARATE_ZVAL(entry);
00860                      convert_to_string_ex(entry);
00861                      
00862                      MAKE_STD_ZVAL(new_string);
00863                      ZVAL_LONG(new_string,1);
00864               
00865                      zend_hash_update(intern->registered_phpfunctions, Z_STRVAL_PP(entry), Z_STRLEN_PP(entry) + 1, &new_string, sizeof(zval*), NULL);
00866                      zend_hash_move_forward(Z_ARRVAL_P(array_value));
00867               }
00868               intern->registerPhpFunctions = 2;
00869 
00870        } else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s",  &name, &name_len) == SUCCESS) {
00871               intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
00872               
00873               MAKE_STD_ZVAL(new_string);
00874               ZVAL_LONG(new_string,1);
00875               zend_hash_update(intern->registered_phpfunctions, name, name_len + 1, &new_string, sizeof(zval*), NULL);
00876               intern->registerPhpFunctions = 2;
00877               
00878        } else {
00879               intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
00880               intern->registerPhpFunctions = 1;
00881        }
00882        
00883 }
00884 /* }}} end xsl_xsltprocessor_register_php_functions(); */
00885 
00886 /* {{{ proto bool xsl_xsltprocessor_set_profiling(string filename) */
00887 PHP_FUNCTION(xsl_xsltprocessor_set_profiling)
00888 {
00889        zval *id;
00890        xsl_object *intern;
00891        char *filename = NULL;
00892        int filename_len;
00893        DOM_GET_THIS(id);
00894 
00895        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s!", &filename, &filename_len) == SUCCESS) {
00896               intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
00897               if (intern->profiling) {
00898                      efree(intern->profiling);
00899               }
00900               if (filename != NULL && strlen(filename) == filename_len) {
00901                      intern->profiling = estrndup(filename,filename_len);
00902               } else {
00903                      intern->profiling = NULL;
00904               }
00905               RETURN_TRUE;
00906        } else {
00907               WRONG_PARAM_COUNT;
00908        }
00909 }
00910 /* }}} end xsl_xsltprocessor_set_profiling */
00911 
00912 /* {{{ proto bool xsl_xsltprocessor_has_exslt_support();
00913 */
00914 PHP_FUNCTION(xsl_xsltprocessor_has_exslt_support)
00915 {
00916 #if HAVE_XSL_EXSLT
00917        RETURN_TRUE;
00918 #else
00919        RETURN_FALSE;
00920 #endif
00921 }
00922 /* }}} end xsl_xsltprocessor_has_exslt_support(); */
00923 
00924 /*
00925  * Local variables:
00926  * tab-width: 4
00927  * c-basic-offset: 4
00928  * End:
00929  * vim600: sw=4 ts=4 fdm=marker
00930  * vim<600: sw=4 ts=4
00931  */