Annotation of embedaddon/php/ext/xsl/xsltprocessor.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
                      5:    | Copyright (c) 1997-2012 The PHP Group                                |
                      6:    +----------------------------------------------------------------------+
                      7:    | This source file is subject to version 3.01 of the PHP license,      |
                      8:    | that is bundled with this package in the file LICENSE, and is        |
                      9:    | available through the world-wide-web at the following url:           |
                     10:    | http://www.php.net/license/3_01.txt                                  |
                     11:    | If you did not receive a copy of the PHP license and are unable to   |
                     12:    | obtain it through the world-wide-web, please send a note to          |
                     13:    | license@php.net so we can mail you a copy immediately.               |
                     14:    +----------------------------------------------------------------------+
                     15:    | Authors: Christian Stocker <chregu@php.net>                          |
                     16:    |          Rob Richards <rrichards@php.net>                            |
                     17:    +----------------------------------------------------------------------+
                     18: */
                     19: 
                     20: /* $Id: xsltprocessor.c 321634 2012-01-01 13:15:04Z felipe $ */
                     21: 
                     22: #ifdef HAVE_CONFIG_H
                     23: #include "config.h"
                     24: #endif
                     25: 
                     26: #include "php.h"
                     27: #include "php_xsl.h"
                     28: #include "ext/libxml/php_libxml.h"
                     29: 
                     30: /* {{{ arginfo */
                     31: ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_import_stylesheet, 0, 0, 1)
                     32:        ZEND_ARG_INFO(0, doc)
                     33: ZEND_END_ARG_INFO();
                     34: 
                     35: ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_transform_to_doc, 0, 0, 1)
                     36:        ZEND_ARG_INFO(0, doc)
                     37: ZEND_END_ARG_INFO();
                     38: 
                     39: ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_transform_to_uri, 0, 0, 2)
                     40:        ZEND_ARG_INFO(0, doc)
                     41:        ZEND_ARG_INFO(0, uri)
                     42: ZEND_END_ARG_INFO();
                     43: 
                     44: ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_transform_to_xml, 0, 0, 1)
                     45:        ZEND_ARG_INFO(0, doc)
                     46: ZEND_END_ARG_INFO();
                     47: 
                     48: ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_set_parameter, 0, 0, 2)
                     49:        ZEND_ARG_INFO(0, namespace)
                     50:        ZEND_ARG_INFO(0, name)
                     51:        ZEND_ARG_INFO(0, value)
                     52: ZEND_END_ARG_INFO();
                     53: 
                     54: ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_get_parameter, 0, 0, 2)
                     55:        ZEND_ARG_INFO(0, namespace)
                     56:        ZEND_ARG_INFO(0, name)
                     57: ZEND_END_ARG_INFO();
                     58: 
                     59: ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_remove_parameter, 0, 0, 2)
                     60:        ZEND_ARG_INFO(0, namespace)
                     61:        ZEND_ARG_INFO(0, name)
                     62: ZEND_END_ARG_INFO();
                     63: 
                     64: ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_has_exslt_support, 0, 0, 0)
                     65: ZEND_END_ARG_INFO();
                     66: 
                     67: ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_register_php_functions, 0, 0, 0)
                     68:        ZEND_ARG_INFO(0, restrict)
                     69: ZEND_END_ARG_INFO();
                     70: 
                     71: ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_set_profiling, 0, 0, 1)
                     72:        ZEND_ARG_INFO(0, filename)
                     73: ZEND_END_ARG_INFO();
                     74: /* }}} */
                     75: 
                     76: /*
                     77: * class xsl_xsltprocessor 
                     78: *
                     79: * URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#
                     80: * Since: 
                     81: */
                     82: 
                     83: const zend_function_entry php_xsl_xsltprocessor_class_functions[] = {
                     84:        PHP_FALIAS(importStylesheet, xsl_xsltprocessor_import_stylesheet, arginfo_xsl_xsltprocessor_import_stylesheet)
                     85:        PHP_FALIAS(transformToDoc, xsl_xsltprocessor_transform_to_doc, arginfo_xsl_xsltprocessor_transform_to_doc)
                     86:        PHP_FALIAS(transformToUri, xsl_xsltprocessor_transform_to_uri, arginfo_xsl_xsltprocessor_transform_to_uri)
                     87:        PHP_FALIAS(transformToXml, xsl_xsltprocessor_transform_to_xml, arginfo_xsl_xsltprocessor_transform_to_xml)
                     88:        PHP_FALIAS(setParameter, xsl_xsltprocessor_set_parameter, arginfo_xsl_xsltprocessor_set_parameter)
                     89:        PHP_FALIAS(getParameter, xsl_xsltprocessor_get_parameter, arginfo_xsl_xsltprocessor_get_parameter)
                     90:        PHP_FALIAS(removeParameter, xsl_xsltprocessor_remove_parameter, arginfo_xsl_xsltprocessor_remove_parameter)
                     91:        PHP_FALIAS(hasExsltSupport, xsl_xsltprocessor_has_exslt_support, arginfo_xsl_xsltprocessor_has_exslt_support)
                     92:        PHP_FALIAS(registerPHPFunctions, xsl_xsltprocessor_register_php_functions, arginfo_xsl_xsltprocessor_register_php_functions)
                     93:        PHP_FALIAS(setProfiling, xsl_xsltprocessor_set_profiling, arginfo_xsl_xsltprocessor_set_profiling)
                     94:        {NULL, NULL, NULL}
                     95: };
                     96: 
                     97: /* {{{ php_xsl_xslt_string_to_xpathexpr()
                     98:    Translates a string to a XPath Expression */
                     99: static char *php_xsl_xslt_string_to_xpathexpr(const char *str TSRMLS_DC)
                    100: {
                    101:        const xmlChar *string = (const xmlChar *)str;
                    102: 
                    103:        xmlChar *value;
                    104:        int str_len;
                    105:        
                    106:        str_len = xmlStrlen(string) + 3;
                    107:        
                    108:        if (xmlStrchr(string, '"')) {
                    109:                if (xmlStrchr(string, '\'')) {
                    110:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create XPath expression (string contains both quote and double-quotes)");
                    111:                        return NULL;
                    112:                }
                    113:                value = (xmlChar*) safe_emalloc (str_len, sizeof(xmlChar), 0);
                    114:                snprintf(value, str_len, "'%s'", string);
                    115:        } else {
                    116:                value = (xmlChar*) safe_emalloc (str_len, sizeof(xmlChar), 0);
                    117:                snprintf(value, str_len, "\"%s\"", string);
                    118:        }
                    119:        return (char *) value;
                    120: }
                    121: /* }}} */
                    122: 
                    123: /* {{{ php_xsl_xslt_make_params()
                    124:    Translates a PHP array to a libxslt parameters array */
                    125: static char **php_xsl_xslt_make_params(HashTable *parht, int xpath_params TSRMLS_DC)
                    126: {
                    127:        
                    128:        int parsize;
                    129:        zval **value;
                    130:        char *xpath_expr, *string_key = NULL;
                    131:        ulong num_key;
                    132:        char **params = NULL;
                    133:        int i = 0;
                    134: 
                    135:        parsize = (2 * zend_hash_num_elements(parht) + 1) * sizeof(char *);
                    136:        params = (char **)safe_emalloc((2 * zend_hash_num_elements(parht) + 1), sizeof(char *), 0);
                    137:        memset((char *)params, 0, parsize);
                    138: 
                    139:        for (zend_hash_internal_pointer_reset(parht);
                    140:                zend_hash_get_current_data(parht, (void **)&value) == SUCCESS;
                    141:                zend_hash_move_forward(parht)) {
                    142: 
                    143:                if (zend_hash_get_current_key(parht, &string_key, &num_key, 1) != HASH_KEY_IS_STRING) {
                    144:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid argument or parameter array");
                    145:                        efree(params);
                    146:                        return NULL;
                    147:                } else {
                    148:                        if (Z_TYPE_PP(value) != IS_STRING) {
                    149:                                SEPARATE_ZVAL(value);
                    150:                                convert_to_string(*value);
                    151:                        }
                    152:                        
                    153:                        if (!xpath_params) {
                    154:                                xpath_expr = php_xsl_xslt_string_to_xpathexpr(Z_STRVAL_PP(value) TSRMLS_CC);
                    155:                        } else {
                    156:                                xpath_expr = estrndup(Z_STRVAL_PP(value), Z_STRLEN_PP(value));
                    157:                        }
                    158:                        if (xpath_expr) {
                    159:                                params[i++] = string_key;
                    160:                                params[i++] = xpath_expr;
                    161:                        } else {
                    162:                                efree(string_key);
                    163:                        }
                    164:                }
                    165:        }
                    166: 
                    167:        params[i++] = NULL;
                    168: 
                    169:        return params;
                    170: }
                    171: /* }}} */
                    172: 
                    173: static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int type) /* {{{ */
                    174: {
                    175:        xsltTransformContextPtr tctxt;
                    176:        zval **args;
                    177:        zval *retval;
                    178:        int result, i, ret;
                    179:        int error = 0;
                    180:        zend_fcall_info fci;
                    181:        zval handler;
                    182:        xmlXPathObjectPtr obj;
                    183:        char *str;
                    184:        char *callable = NULL;
                    185:        xsl_object *intern;
                    186:        
                    187:        TSRMLS_FETCH();
                    188: 
                    189:        if (! zend_is_executing(TSRMLS_C)) {
                    190:                xsltGenericError(xsltGenericErrorContext,
                    191:                "xsltExtFunctionTest: Function called from outside of PHP\n");
                    192:                error = 1;
                    193:        } else {
                    194:                tctxt = xsltXPathGetTransformContext(ctxt);
                    195:                if (tctxt == NULL) {
                    196:                        xsltGenericError(xsltGenericErrorContext,
                    197:                        "xsltExtFunctionTest: failed to get the transformation context\n");
                    198:                        error = 1;
                    199:                } else {
                    200:                        intern = (xsl_object *) tctxt->_private;
                    201:                        if (intern == NULL) {
                    202:                                xsltGenericError(xsltGenericErrorContext,
                    203:                                "xsltExtFunctionTest: failed to get the internal object\n");
                    204:                                error = 1;
                    205:                        }
                    206:                        else if (intern->registerPhpFunctions == 0) {
                    207:                                xsltGenericError(xsltGenericErrorContext,
                    208:                                "xsltExtFunctionTest: PHP Object did not register PHP functions\n");
                    209:                                error = 1;
                    210:                        }
                    211:                }
                    212:        }
                    213:        
                    214:        if (error == 1) {
                    215:                for (i = nargs - 1; i >= 0; i--) {
                    216:                        obj = valuePop(ctxt);
                    217:                        xmlXPathFreeObject(obj);
                    218:                }
                    219:                return;
                    220:        }
                    221:                
                    222:        fci.param_count = nargs - 1;
                    223:        if (fci.param_count > 0) {
                    224:                fci.params = safe_emalloc(fci.param_count, sizeof(zval**), 0);
                    225:                args = safe_emalloc(fci.param_count, sizeof(zval *), 0);
                    226:        }
                    227:        /* Reverse order to pop values off ctxt stack */
                    228:        for (i = nargs - 2; i >= 0; i--) {
                    229:                obj = valuePop(ctxt);
                    230:                MAKE_STD_ZVAL(args[i]);
                    231:                switch (obj->type) {
                    232:                        case XPATH_STRING:
                    233:                                ZVAL_STRING(args[i],  obj->stringval, 1);
                    234:                                break;
                    235:                        case XPATH_BOOLEAN:
                    236:                                ZVAL_BOOL(args[i],  obj->boolval);
                    237:                                break;
                    238:                        case XPATH_NUMBER:
                    239:                                ZVAL_DOUBLE(args[i], obj->floatval);
                    240:                                break;
                    241:                        case XPATH_NODESET:
                    242:                                if (type == 1) {
                    243:                                        str = xmlXPathCastToString(obj);
                    244:                                        ZVAL_STRING(args[i], str, 1);
                    245:                                        xmlFree(str);
                    246:                                } else if (type == 2) {
                    247:                                        int j;
                    248:                                        dom_object *domintern = (dom_object *)intern->doc;
                    249:                                        array_init(args[i]);
                    250:                                        if (obj->nodesetval && obj->nodesetval->nodeNr > 0) {
                    251:                                                for (j = 0; j < obj->nodesetval->nodeNr; j++) {
                    252:                                                        xmlNodePtr node = obj->nodesetval->nodeTab[j];
                    253:                                                        zval *child;
                    254:                                                        MAKE_STD_ZVAL(child);
                    255:                                                        /* not sure, if we need this... it's copied from xpath.c */
                    256:                                                        if (node->type == XML_NAMESPACE_DECL) {
                    257:                                                                xmlNsPtr curns;
                    258:                                                                xmlNodePtr nsparent;
                    259:                                                                
                    260:                                                                nsparent = node->_private;
                    261:                                                                curns = xmlNewNs(NULL, node->name, NULL);
                    262:                                                                if (node->children) {
                    263:                                                                        curns->prefix = xmlStrdup((char *) node->children);
                    264:                                                                }
                    265:                                                                if (node->children) {
                    266:                                                                        node = xmlNewDocNode(node->doc, NULL, (char *) node->children, node->name);
                    267:                                                                } else {
                    268:                                                                        node = xmlNewDocNode(node->doc, NULL, "xmlns", node->name);
                    269:                                                                }
                    270:                                                                node->type = XML_NAMESPACE_DECL;
                    271:                                                                node->parent = nsparent;
                    272:                                                                node->ns = curns;
                    273:                                                        }
                    274:                                                        child = php_dom_create_object(node, &ret, NULL, child, domintern TSRMLS_CC);
                    275:                                                        add_next_index_zval(args[i], child);
                    276:                                                }
                    277:                                        }
                    278:                                }
                    279:                                break;
                    280:                        default:
                    281:                                str = xmlXPathCastToString(obj);
                    282:                                ZVAL_STRING(args[i], str, 1);
                    283:                                xmlFree(str);
                    284:                }
                    285:                xmlXPathFreeObject(obj);
                    286:                fci.params[i] = &args[i];
                    287:        }
                    288:        
                    289:        fci.size = sizeof(fci);
                    290:        fci.function_table = EG(function_table);
                    291:        
                    292:        obj = valuePop(ctxt);
                    293:        if (obj->stringval == NULL) {
                    294:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Handler name must be a string");
                    295:                xmlXPathFreeObject(obj);
                    296:                if (fci.param_count > 0) {
                    297:                        for (i = 0; i < nargs - 1; i++) {
                    298:                                zval_ptr_dtor(&args[i]);
                    299:                        }
                    300:                        efree(args);
                    301:                        efree(fci.params);
                    302:                }
                    303:                return; 
                    304:        }
                    305:        INIT_PZVAL(&handler);
                    306:        ZVAL_STRING(&handler, obj->stringval, 1);
                    307:        xmlXPathFreeObject(obj);
                    308:        
                    309:        fci.function_name = &handler;
                    310:        fci.symbol_table = NULL;
                    311:        fci.object_ptr = NULL;
                    312:        fci.retval_ptr_ptr = &retval;
                    313:        fci.no_separation = 0;
                    314:        /*fci.function_handler_cache = &function_ptr;*/
                    315:        if (!zend_make_callable(&handler, &callable TSRMLS_CC)) {
                    316:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call handler %s()", callable);
                    317:                
                    318:        } else if ( intern->registerPhpFunctions == 2 && zend_hash_exists(intern->registered_phpfunctions, callable, strlen(callable) + 1) == 0) { 
                    319:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not allowed to call handler '%s()'", callable);
                    320:                /* Push an empty string, so that we at least have an xslt result... */
                    321:                valuePush(ctxt, xmlXPathNewString(""));
                    322:        } else {
                    323:                result = zend_call_function(&fci, NULL TSRMLS_CC);
                    324:                if (result == FAILURE) {
                    325:                        if (Z_TYPE(handler) == IS_STRING) {
                    326:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call handler %s()", Z_STRVAL_P(&handler));
                    327:                        }
                    328:                /* retval is == NULL, when an exception occured, don't report anything, because PHP itself will handle that */
                    329:                } else if (retval == NULL) {
                    330:                } else {
                    331:                        if (retval->type == IS_OBJECT && instanceof_function( Z_OBJCE_P(retval), dom_node_class_entry TSRMLS_CC)) {
                    332:                                xmlNode *nodep;
                    333:                                dom_object *obj;
                    334:                                if (intern->node_list == NULL) {
                    335:                                        ALLOC_HASHTABLE(intern->node_list);
                    336:                                        zend_hash_init(intern->node_list, 0, NULL, ZVAL_PTR_DTOR, 0);
                    337:                                }
                    338:                                zval_add_ref(&retval);
                    339:                                zend_hash_next_index_insert(intern->node_list, &retval, sizeof(zval *), NULL);
                    340:                                obj = (dom_object *)zend_object_store_get_object(retval TSRMLS_CC);
                    341:                                nodep = dom_object_get_node(obj);
                    342:                                valuePush(ctxt, xmlXPathNewNodeSet(nodep));
                    343:                        } else if (retval->type == IS_BOOL) {
                    344:                                valuePush(ctxt, xmlXPathNewBoolean(retval->value.lval));
                    345:                        } else if (retval->type == IS_OBJECT) {
                    346:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "A PHP Object cannot be converted to a XPath-string");
                    347:                                valuePush(ctxt, xmlXPathNewString(""));
                    348:                        } else {
                    349:                                convert_to_string_ex(&retval);
                    350:                                valuePush(ctxt, xmlXPathNewString( Z_STRVAL_P(retval)));
                    351:                        }
                    352:                        zval_ptr_dtor(&retval);
                    353:                }
                    354:        }
                    355:        efree(callable);
                    356:        zval_dtor(&handler);
                    357:        if (fci.param_count > 0) {
                    358:                for (i = 0; i < nargs - 1; i++) {
                    359:                        zval_ptr_dtor(&args[i]);
                    360:                }
                    361:                efree(args);
                    362:                efree(fci.params);
                    363:        }
                    364: }
                    365: /* }}} */
                    366: 
                    367: void xsl_ext_function_string_php(xmlXPathParserContextPtr ctxt, int nargs) /* {{{ */
                    368: {
                    369:        xsl_ext_function_php(ctxt, nargs, 1);
                    370: }
                    371: /* }}} */
                    372: 
                    373: void xsl_ext_function_object_php(xmlXPathParserContextPtr ctxt, int nargs) /* {{{ */
                    374: {
                    375:        xsl_ext_function_php(ctxt, nargs, 2);
                    376: }
                    377: /* }}} */
                    378: 
                    379: /* {{{ proto void xsl_xsltprocessor_import_stylesheet(domdocument doc);
                    380: URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#
                    381: Since: 
                    382: */
                    383: PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet)
                    384: {
                    385:        zval *id, *docp = NULL;
                    386:        xmlDoc *doc = NULL, *newdoc = NULL;
                    387:        xsltStylesheetPtr sheetp, oldsheetp;
                    388:        xsl_object *intern;
                    389:        int prevSubstValue, prevExtDtdValue, clone_docu = 0;
                    390:        xmlNode *nodep = NULL;
                    391:        zend_object_handlers *std_hnd;
                    392:        zval *cloneDocu, *member;
                    393:        
                    394:        if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oo", &id, xsl_xsltprocessor_class_entry, &docp) == FAILURE) {
                    395:                RETURN_FALSE;
                    396:        }
                    397: 
                    398:        nodep = php_libxml_import_node(docp TSRMLS_CC);
                    399:        
                    400:        if (nodep) {
                    401:                doc = nodep->doc;
                    402:        }
                    403:        if (doc == NULL) {
                    404:                php_error(E_WARNING, "Invalid Document");
                    405:                RETURN_FALSE;
                    406:        }
                    407: 
                    408:        /* libxslt uses _private, so we must copy the imported 
                    409:        stylesheet document otherwise the node proxies will be a mess */
                    410:        newdoc = xmlCopyDoc(doc, 1);
                    411:        xmlNodeSetBase((xmlNodePtr) newdoc, (xmlChar *)doc->URL);
                    412:        prevSubstValue = xmlSubstituteEntitiesDefault(1);
                    413:        prevExtDtdValue = xmlLoadExtDtdDefaultValue;
                    414:        xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
                    415: 
                    416:        sheetp = xsltParseStylesheetDoc(newdoc);
                    417:        xmlSubstituteEntitiesDefault(prevSubstValue);
                    418:        xmlLoadExtDtdDefaultValue = prevExtDtdValue;
                    419: 
                    420:        if (!sheetp) {
                    421:                xmlFreeDoc(newdoc);
                    422:                RETURN_FALSE;
                    423:        }
                    424: 
                    425:        intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC); 
                    426: 
                    427:        std_hnd = zend_get_std_object_handlers();
                    428:        MAKE_STD_ZVAL(member);
                    429:        ZVAL_STRING(member, "cloneDocument", 0);
                    430:        cloneDocu = std_hnd->read_property(id, member, BP_VAR_IS TSRMLS_CC);
                    431:        if (Z_TYPE_P(cloneDocu) != IS_NULL) {
                    432:                convert_to_long(cloneDocu);
                    433:                clone_docu = Z_LVAL_P(cloneDocu);
                    434:        }
                    435:        efree(member);
                    436:        if (clone_docu == 0) {
                    437:                /* check if the stylesheet is using xsl:key, if yes, we have to clone the document _always_ before a transformation */
                    438:                nodep = xmlDocGetRootElement(sheetp->doc);
                    439:                if (nodep && (nodep = nodep->children)) {
                    440:                        while (nodep) {
                    441:                                if (nodep->type == XML_ELEMENT_NODE && xmlStrEqual(nodep->name, "key") && xmlStrEqual(nodep->ns->href, XSLT_NAMESPACE)) {
                    442:                                        intern->hasKeys = 1;
                    443:                                        break;
                    444:                                }
                    445:                                nodep = nodep->next;
                    446:                        }
                    447:                }
                    448:        } else {
                    449:                intern->hasKeys = clone_docu;
                    450:        }
                    451: 
                    452:        if ((oldsheetp = (xsltStylesheetPtr)intern->ptr)) { 
                    453:                /* free wrapper */
                    454:                if (((xsltStylesheetPtr) intern->ptr)->_private != NULL) {
                    455:                        ((xsltStylesheetPtr) intern->ptr)->_private = NULL;   
                    456:                }
                    457:                xsltFreeStylesheet((xsltStylesheetPtr) intern->ptr);
                    458:                intern->ptr = NULL;
                    459:        }
                    460: 
                    461:        php_xsl_set_object(id, sheetp TSRMLS_CC);
                    462:        RETVAL_TRUE;
                    463: }
                    464: /* }}} end xsl_xsltprocessor_import_stylesheet */
                    465: 
                    466: static xmlDocPtr php_xsl_apply_stylesheet(zval *id, xsl_object *intern, xsltStylesheetPtr style, zval *docp TSRMLS_DC) /* {{{ */
                    467: {
                    468:        xmlDocPtr newdocp;
                    469:        xmlDocPtr doc = NULL;
                    470:        xmlNodePtr node = NULL;
                    471:        xsltTransformContextPtr ctxt;
                    472:        php_libxml_node_object *object;
                    473:        char **params = NULL;
                    474:        int clone;
                    475:        zval *doXInclude, *member;
                    476:        zend_object_handlers *std_hnd;
                    477:        FILE *f;
                    478:        int secPrefsError = 0;
                    479:        int secPrefsValue;
                    480:        xsltSecurityPrefsPtr secPrefs = NULL;
                    481: 
                    482:        node = php_libxml_import_node(docp TSRMLS_CC);
                    483:        
                    484:        if (node) {
                    485:                doc = node->doc;
                    486:        }
                    487:        if (doc == NULL) {
                    488:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Document");
                    489:                return NULL;
                    490:        }
                    491: 
                    492:        if (style == NULL) {
                    493:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "No stylesheet associated to this object");
                    494:                return NULL;
                    495:        }
                    496:        
                    497:        if (intern->profiling) {
                    498:                if (php_check_open_basedir(intern->profiling TSRMLS_CC)) {
                    499:                        f = NULL;
                    500:                } else {
                    501:                        f = VCWD_FOPEN(intern->profiling, "w");
                    502:                }
                    503:        } else {
                    504:                f = NULL;
                    505:        }
                    506:        
                    507:        if (intern->parameter) {
                    508:                params = php_xsl_xslt_make_params(intern->parameter, 0 TSRMLS_CC);
                    509:        }
                    510: 
                    511:        intern->doc = emalloc(sizeof(php_libxml_node_object));
                    512:        memset(intern->doc, 0, sizeof(php_libxml_node_object));
                    513: 
                    514:        if (intern->hasKeys == 1) {
                    515:                doc = xmlCopyDoc(doc, 1);
                    516:        } else {
                    517:                object = (php_libxml_node_object *)zend_object_store_get_object(docp TSRMLS_CC);
                    518:                intern->doc->document = object->document;
                    519:        }
                    520: 
                    521:        php_libxml_increment_doc_ref(intern->doc, doc TSRMLS_CC);
                    522: 
                    523:        ctxt = xsltNewTransformContext(style, doc);
                    524:        ctxt->_private = (void *) intern;
                    525: 
                    526:        std_hnd = zend_get_std_object_handlers();
                    527: 
                    528:        MAKE_STD_ZVAL(member);
                    529:        ZVAL_STRING(member, "doXInclude", 0);
                    530:        doXInclude = std_hnd->read_property(id, member, BP_VAR_IS TSRMLS_CC);
                    531:        if (Z_TYPE_P(doXInclude) != IS_NULL) {
                    532:                convert_to_long(doXInclude);
                    533:                ctxt->xinclude = Z_LVAL_P(doXInclude);
                    534:        }
                    535:        efree(member);
                    536: 
                    537:        
                    538:        secPrefsValue = INI_INT("xsl.security_prefs");
                    539:        
                    540:        /* if securityPrefs is set to NONE, we don't have to do any checks, but otherwise... */
                    541:        if (secPrefsValue != XSL_SECPREF_NONE) {
                    542:                secPrefs = xsltNewSecurityPrefs(); 
                    543:                if (secPrefsValue & XSL_SECPREF_READ_FILE ) { 
                    544:                        if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid)) { 
                    545:                                secPrefsError = 1;
                    546:                        }
                    547:                }
                    548:                if (secPrefsValue & XSL_SECPREF_WRITE_FILE ) { 
                    549:                        if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid)) { 
                    550:                                secPrefsError = 1;
                    551:                        }
                    552:                }
                    553:                if (secPrefsValue & XSL_SECPREF_CREATE_DIRECTORY ) { 
                    554:                        if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid)) { 
                    555:                                secPrefsError = 1;
                    556:                        }
                    557:                }
                    558:                if (secPrefsValue & XSL_SECPREF_READ_NETWORK) { 
                    559:                        if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid)) { 
                    560:                                secPrefsError = 1;
                    561:                        }
                    562:                }
                    563:                if (secPrefsValue & XSL_SECPREF_WRITE_NETWORK) { 
                    564:                        if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid)) { 
                    565:                                secPrefsError = 1;
                    566:                        }
                    567:                }
                    568:        
                    569:                if (0 != xsltSetCtxtSecurityPrefs(secPrefs, ctxt)) { 
                    570:                        secPrefsError = 1;
                    571:                }
                    572:        }
                    573:        
                    574:        if (secPrefsError == 1) {
                    575:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't set libxslt security properties, not doing transformation for security reasons");
                    576:        } else {
                    577:                newdocp = xsltApplyStylesheetUser(style, doc, (const char**) params,  NULL, f, ctxt);
                    578:        }
                    579:        if (f) {
                    580:                fclose(f);
                    581:        }
                    582:        
                    583:        xsltFreeTransformContext(ctxt);
                    584:        if (secPrefs) {
                    585:                xsltFreeSecurityPrefs(secPrefs);
                    586:        }
                    587: 
                    588:        if (intern->node_list != NULL) {
                    589:                zend_hash_destroy(intern->node_list);
                    590:                FREE_HASHTABLE(intern->node_list);      
                    591:                intern->node_list = NULL;
                    592:        }
                    593: 
                    594:        php_libxml_decrement_doc_ref(intern->doc TSRMLS_CC);
                    595:        efree(intern->doc);
                    596:        intern->doc = NULL;
                    597: 
                    598:        if (params) {
                    599:                clone = 0;
                    600:                while(params[clone]) {
                    601:                        efree(params[clone++]);
                    602:                }
                    603:                efree(params);
                    604:        }
                    605: 
                    606:        return newdocp;
                    607: 
                    608: }
                    609: /* }}} */
                    610: 
                    611: /* {{{ proto domdocument xsl_xsltprocessor_transform_to_doc(domnode doc);
                    612: URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#
                    613: Since: 
                    614: */
                    615: PHP_FUNCTION(xsl_xsltprocessor_transform_to_doc)
                    616: {
                    617:        zval *id, *rv = NULL, *docp = NULL;
                    618:        xmlDoc *newdocp;
                    619:        xsltStylesheetPtr sheetp;
                    620:        int ret, ret_class_len=0;
                    621:        char *ret_class = NULL;
                    622:        xsl_object *intern;
                    623: 
                    624:        id = getThis();
                    625:        intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
                    626:        sheetp = (xsltStylesheetPtr) intern->ptr;
                    627: 
                    628:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o|s!", &docp, &ret_class, &ret_class_len) == FAILURE) {
                    629:                RETURN_FALSE;
                    630:        }
                    631: 
                    632:        newdocp = php_xsl_apply_stylesheet(id, intern, sheetp, docp TSRMLS_CC);
                    633: 
                    634:        if (newdocp) {
                    635:                if (ret_class) {
                    636:                        int found;
                    637:                        char *curclass_name;
                    638:                        zend_class_entry *curce, **ce;
                    639:                        php_libxml_node_object *interndoc;
                    640: 
                    641:                        curce = Z_OBJCE_P(docp);
                    642:                        curclass_name = curce->name;
                    643:                        while (curce->parent != NULL) {
                    644:                                curce = curce->parent;
                    645:                        }
                    646: 
                    647:                        found = zend_lookup_class(ret_class, ret_class_len, &ce TSRMLS_CC);
                    648:                        if ((found != SUCCESS) || !instanceof_function(*ce, curce TSRMLS_CC)) {
                    649:                                xmlFreeDoc(newdocp);
                    650:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, 
                    651:                                        "Expecting class compatible with %s, '%s' given", curclass_name, ret_class);
                    652:                                RETURN_FALSE;
                    653:                        }
                    654: 
                    655:                        object_init_ex(return_value, *ce);
                    656:                
                    657:                        interndoc = (php_libxml_node_object *)zend_objects_get_address(return_value TSRMLS_CC);
                    658:                        php_libxml_increment_doc_ref(interndoc, newdocp TSRMLS_CC);
                    659:                        php_libxml_increment_node_ptr(interndoc, (xmlNodePtr)newdocp, (void *)interndoc TSRMLS_CC);
                    660:                } else {
                    661:                        DOM_RET_OBJ(rv, (xmlNodePtr) newdocp, &ret, NULL);
                    662:                }
                    663:        } else {
                    664:                RETURN_FALSE;
                    665:        }
                    666:        
                    667: }
                    668: /* }}} end xsl_xsltprocessor_transform_to_doc */
                    669: 
                    670: /* {{{ proto int xsl_xsltprocessor_transform_to_uri(domdocument doc, string uri);
                    671: */
                    672: PHP_FUNCTION(xsl_xsltprocessor_transform_to_uri)
                    673: {
                    674:        zval *id, *docp = NULL;
                    675:        xmlDoc *newdocp;
                    676:        xsltStylesheetPtr sheetp;
                    677:        int ret, uri_len;
                    678:        char *uri;
                    679:        xsl_object *intern;
                    680:        
                    681:        id = getThis();
                    682:        intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
                    683:        sheetp = (xsltStylesheetPtr) intern->ptr;
                    684: 
                    685:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "os", &docp, &uri, &uri_len) == FAILURE) {
                    686:                RETURN_FALSE;
                    687:        }
                    688: 
                    689:        newdocp = php_xsl_apply_stylesheet(id, intern, sheetp, docp TSRMLS_CC);
                    690: 
                    691:        ret = -1;
                    692:        if (newdocp) {
                    693:                if (strlen(uri) != uri_len) {
                    694:                        xmlFreeDoc(newdocp);
                    695:                        RETURN_FALSE;
                    696:                }
                    697:                ret = xsltSaveResultToFilename(uri, newdocp, sheetp, 0);
                    698:                xmlFreeDoc(newdocp);
                    699:        }
                    700: 
                    701:        RETVAL_LONG(ret);
                    702: }
                    703: /* }}} end xsl_xsltprocessor_transform_to_uri */
                    704: 
                    705: /* {{{ proto string xsl_xsltprocessor_transform_to_xml(domdocument doc);
                    706: */
                    707: PHP_FUNCTION(xsl_xsltprocessor_transform_to_xml)
                    708: {
                    709:        zval *id, *docp = NULL;
                    710:        xmlDoc *newdocp;
                    711:        xsltStylesheetPtr sheetp;
                    712:        int ret;
                    713:        xmlChar *doc_txt_ptr;
                    714:        int doc_txt_len;
                    715:        xsl_object *intern;
                    716:        
                    717:        id = getThis();
                    718:        intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
                    719:        sheetp = (xsltStylesheetPtr) intern->ptr;
                    720: 
                    721:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &docp) == FAILURE) {
                    722:                RETURN_FALSE;
                    723:        }
                    724: 
                    725:        newdocp = php_xsl_apply_stylesheet(id, intern, sheetp, docp TSRMLS_CC);
                    726: 
                    727:        ret = -1;
                    728:        if (newdocp) {
                    729:                ret = xsltSaveResultToString(&doc_txt_ptr, &doc_txt_len, newdocp, sheetp);
                    730:                if (doc_txt_ptr && doc_txt_len) {
                    731:                        RETVAL_STRINGL(doc_txt_ptr, doc_txt_len, 1);
                    732:                        xmlFree(doc_txt_ptr);
                    733:                }
                    734:                xmlFreeDoc(newdocp);
                    735:        }
                    736: 
                    737:        if (ret < 0) {
                    738:                RETURN_FALSE;
                    739:        }
                    740: }
                    741: /* }}} end xsl_xsltprocessor_transform_to_xml */
                    742: 
                    743: /* {{{ proto bool xsl_xsltprocessor_set_parameter(string namespace, mixed name [, string value]);
                    744: */
                    745: PHP_FUNCTION(xsl_xsltprocessor_set_parameter)
                    746: {
                    747:  
                    748:        zval *id;
                    749:        zval *array_value, **entry, *new_string;
                    750:        xsl_object *intern;
                    751:        char *string_key, *name, *value, *namespace;
                    752:        ulong idx;
                    753:        int string_key_len, namespace_len, name_len, value_len;
                    754:        DOM_GET_THIS(id);
                    755: 
                    756:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "sa", &namespace, &namespace_len, &array_value) == SUCCESS) {
                    757:                intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
                    758:                zend_hash_internal_pointer_reset(Z_ARRVAL_P(array_value));
                    759: 
                    760:                while (zend_hash_get_current_data(Z_ARRVAL_P(array_value), (void **)&entry) == SUCCESS) {
                    761:                        SEPARATE_ZVAL(entry);
                    762:                        convert_to_string_ex(entry);
                    763:                        
                    764:                        if (zend_hash_get_current_key_ex(Z_ARRVAL_P(array_value), &string_key, &string_key_len, &idx, 0, NULL) != HASH_KEY_IS_STRING) {
                    765:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid parameter array");
                    766:                                RETURN_FALSE;
                    767:                        }
                    768:                        
                    769:                        ALLOC_ZVAL(new_string);
                    770:                        Z_ADDREF_PP(entry);
                    771:                        COPY_PZVAL_TO_ZVAL(*new_string, *entry);
                    772:                        
                    773:                        zend_hash_update(intern->parameter, string_key, string_key_len, &new_string, sizeof(zval*), NULL);
                    774:                        zend_hash_move_forward(Z_ARRVAL_P(array_value));
                    775:                }
                    776:                RETURN_TRUE;
                    777: 
                    778:        } 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) {
                    779:                
                    780:                intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
                    781:                
                    782:                MAKE_STD_ZVAL(new_string);
                    783:                ZVAL_STRING(new_string, value, 1);
                    784:                
                    785:                zend_hash_update(intern->parameter, name, name_len + 1, &new_string, sizeof(zval*), NULL);
                    786:                RETURN_TRUE;
                    787:        } else {
                    788:                WRONG_PARAM_COUNT;
                    789:        }
                    790:        
                    791: }
                    792: /* }}} end xsl_xsltprocessor_set_parameter */
                    793: 
                    794: /* {{{ proto string xsl_xsltprocessor_get_parameter(string namespace, string name);
                    795: */
                    796: PHP_FUNCTION(xsl_xsltprocessor_get_parameter)
                    797: {
                    798:        zval *id;
                    799:        int name_len = 0, namespace_len = 0;
                    800:        char *name, *namespace;
                    801:        zval **value;
                    802:        xsl_object *intern;
                    803: 
                    804:        DOM_GET_THIS(id);
                    805:        
                    806:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &namespace, &namespace_len, &name, &name_len) == FAILURE) {
                    807:                RETURN_FALSE;
                    808:        }
                    809:        intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
                    810:        if ( zend_hash_find(intern->parameter, name, name_len + 1,  (void**) &value) == SUCCESS) {
                    811:                convert_to_string_ex(value);
                    812:                RETVAL_STRING(Z_STRVAL_PP(value),1);
                    813:        } else {
                    814:                RETURN_FALSE;
                    815:        }
                    816: }
                    817: /* }}} end xsl_xsltprocessor_get_parameter */
                    818: 
                    819: /* {{{ proto bool xsl_xsltprocessor_remove_parameter(string namespace, string name);
                    820: */
                    821: PHP_FUNCTION(xsl_xsltprocessor_remove_parameter)
                    822: {
                    823:        zval *id;
                    824:        int name_len = 0, namespace_len = 0;
                    825:        char *name, *namespace;
                    826:        xsl_object *intern;
                    827: 
                    828:        DOM_GET_THIS(id);
                    829:        
                    830:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &namespace, &namespace_len, &name, &name_len) == FAILURE) {
                    831:                RETURN_FALSE;
                    832:        }
                    833:        intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
                    834:        if ( zend_hash_del(intern->parameter, name, name_len + 1) == SUCCESS) {
                    835:                RETURN_TRUE;
                    836:        } else {
                    837:                RETURN_FALSE;
                    838:        }
                    839: }
                    840: /* }}} end xsl_xsltprocessor_remove_parameter */
                    841: 
                    842: /* {{{ proto void xsl_xsltprocessor_register_php_functions([mixed $restrict]);
                    843: */
                    844: PHP_FUNCTION(xsl_xsltprocessor_register_php_functions)
                    845: {
                    846:        zval *id;
                    847:        xsl_object *intern;
                    848:        zval *array_value, **entry, *new_string;
                    849:        int  name_len = 0;
                    850:        char *name;
                    851: 
                    852:        DOM_GET_THIS(id);
                    853:        
                    854:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "a",  &array_value) == SUCCESS) {
                    855:                intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
                    856:                zend_hash_internal_pointer_reset(Z_ARRVAL_P(array_value));
                    857: 
                    858:                while (zend_hash_get_current_data(Z_ARRVAL_P(array_value), (void **)&entry) == SUCCESS) {
                    859:                        SEPARATE_ZVAL(entry);
                    860:                        convert_to_string_ex(entry);
                    861:                        
                    862:                        MAKE_STD_ZVAL(new_string);
                    863:                        ZVAL_LONG(new_string,1);
                    864:                
                    865:                        zend_hash_update(intern->registered_phpfunctions, Z_STRVAL_PP(entry), Z_STRLEN_PP(entry) + 1, &new_string, sizeof(zval*), NULL);
                    866:                        zend_hash_move_forward(Z_ARRVAL_P(array_value));
                    867:                }
                    868:                intern->registerPhpFunctions = 2;
                    869: 
                    870:        } else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s",  &name, &name_len) == SUCCESS) {
                    871:                intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
                    872:                
                    873:                MAKE_STD_ZVAL(new_string);
                    874:                ZVAL_LONG(new_string,1);
                    875:                zend_hash_update(intern->registered_phpfunctions, name, name_len + 1, &new_string, sizeof(zval*), NULL);
                    876:                intern->registerPhpFunctions = 2;
                    877:                
                    878:        } else {
                    879:                intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
                    880:                intern->registerPhpFunctions = 1;
                    881:        }
                    882:        
                    883: }
                    884: /* }}} end xsl_xsltprocessor_register_php_functions(); */
                    885: 
                    886: /* {{{ proto bool xsl_xsltprocessor_set_profiling(string filename) */
                    887: PHP_FUNCTION(xsl_xsltprocessor_set_profiling)
                    888: {
                    889:        zval *id;
                    890:        xsl_object *intern;
                    891:        char *filename = NULL;
                    892:        int filename_len;
                    893:        DOM_GET_THIS(id);
                    894: 
                    895:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s!", &filename, &filename_len) == SUCCESS) {
                    896:                intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
                    897:                if (intern->profiling) {
                    898:                        efree(intern->profiling);
                    899:                }
                    900:                if (filename != NULL && strlen(filename) == filename_len) {
                    901:                        intern->profiling = estrndup(filename,filename_len);
                    902:                } else {
                    903:                        intern->profiling = NULL;
                    904:                }
                    905:                RETURN_TRUE;
                    906:        } else {
                    907:                WRONG_PARAM_COUNT;
                    908:        }
                    909: }
                    910: /* }}} end xsl_xsltprocessor_set_profiling */
                    911: 
                    912: /* {{{ proto bool xsl_xsltprocessor_has_exslt_support();
                    913: */
                    914: PHP_FUNCTION(xsl_xsltprocessor_has_exslt_support)
                    915: {
                    916: #if HAVE_XSL_EXSLT
                    917:        RETURN_TRUE;
                    918: #else
                    919:        RETURN_FALSE;
                    920: #endif
                    921: }
                    922: /* }}} end xsl_xsltprocessor_has_exslt_support(); */
                    923: 
                    924: /*
                    925:  * Local variables:
                    926:  * tab-width: 4
                    927:  * c-basic-offset: 4
                    928:  * End:
                    929:  * vim600: sw=4 ts=4 fdm=marker
                    930:  * vim<600: sw=4 ts=4
                    931:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>