--- embedaddon/php/ext/pdo_sqlite/sqlite_driver.c 2012/02/21 23:47:59 1.1 +++ embedaddon/php/ext/pdo_sqlite/sqlite_driver.c 2012/05/29 12:34:41 1.1.1.2 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: sqlite_driver.c,v 1.1 2012/02/21 23:47:59 misho Exp $ */ +/* $Id: sqlite_driver.c,v 1.1.1.2 2012/05/29 12:34:41 misho Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -129,6 +129,27 @@ static void pdo_sqlite_cleanup_callbacks(pdo_sqlite_db } efree(func); } + + while (H->collations) { + struct pdo_sqlite_collation *collation; + collation = H->collations; + H->collations = collation->next; + + if (H->db) { + /* delete the collation from the handle */ + sqlite3_create_collation(H->db, + collation->name, + SQLITE_UTF8, + collation, + NULL); + } + + efree((char*)collation->name); + if (collation->callback) { + zval_ptr_dtor(&collation->callback); + } + efree(collation); + } } static int sqlite_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */ @@ -457,6 +478,57 @@ static void php_sqlite3_func_final_callback(sqlite3_co do_callback(&func->afini, func->fini, 0, NULL, context, 1 TSRMLS_CC); } +static int php_sqlite3_collation_callback(void *context, + int string1_len, const void *string1, + int string2_len, const void *string2) +{ + int ret; + zval *zstring1, *zstring2; + zval **zargs[2]; + zval *retval = NULL; + struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context; + TSRMLS_FETCH(); + + collation->fc.fci.size = sizeof(collation->fc.fci); + collation->fc.fci.function_table = EG(function_table); + collation->fc.fci.function_name = collation->callback; + collation->fc.fci.symbol_table = NULL; + collation->fc.fci.object_ptr = NULL; + collation->fc.fci.retval_ptr_ptr = &retval; + + // Prepare the arguments. + MAKE_STD_ZVAL(zstring1); + ZVAL_STRINGL(zstring1, (char *) string1, string1_len, 1); + zargs[0] = &zstring1; + MAKE_STD_ZVAL(zstring2); + ZVAL_STRINGL(zstring2, (char *) string2, string2_len, 1); + zargs[1] = &zstring2; + collation->fc.fci.param_count = 2; + collation->fc.fci.params = zargs; + + if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc TSRMLS_CC)) == FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the callback"); + } + else if (retval) { + if (Z_TYPE_P(retval) != IS_LONG) { + convert_to_long_ex(&retval); + } + ret = 0; + if (Z_LVAL_P(retval) > 0) { + ret = 1; + } + else if (Z_LVAL_P(retval) < 0) { + ret = -1; + } + zval_ptr_dtor(&retval); + } + + zval_ptr_dtor(zargs[0]); + zval_ptr_dtor(zargs[1]); + + return ret; +} + /* {{{ bool SQLite::sqliteCreateFunction(string name, mixed callback [, int argcount]) Registers a UDF with the sqlite db handle */ static PHP_METHOD(SQLite, sqliteCreateFunction) @@ -590,9 +662,61 @@ static PHP_METHOD(SQLite, sqliteCreateAggregate) RETURN_FALSE; } /* }}} */ + +/* {{{ bool SQLite::sqliteCreateCollation(string name, mixed callback) + Registers a collation with the sqlite db handle */ +static PHP_METHOD(SQLite, sqliteCreateCollation) +{ + struct pdo_sqlite_collation *collation; + zval *callback; + char *collation_name; + int collation_name_len; + char *cbname = NULL; + pdo_dbh_t *dbh; + pdo_sqlite_db_handle *H; + int ret; + + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", + &collation_name, &collation_name_len, &callback)) { + RETURN_FALSE; + } + + dbh = zend_object_store_get_object(getThis() TSRMLS_CC); + PDO_CONSTRUCT_CHECK; + + if (!zend_is_callable(callback, 0, &cbname TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname); + efree(cbname); + RETURN_FALSE; + } + efree(cbname); + + H = (pdo_sqlite_db_handle *)dbh->driver_data; + + collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation)); + + ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_collation_callback); + if (ret == SQLITE_OK) { + collation->name = estrdup(collation_name); + + MAKE_STD_ZVAL(collation->callback); + MAKE_COPY_ZVAL(&callback, collation->callback); + + collation->next = H->collations; + H->collations = collation; + + RETURN_TRUE; + } + + efree(collation); + RETURN_FALSE; +} +/* }}} */ + static const zend_function_entry dbh_methods[] = { PHP_ME(SQLite, sqliteCreateFunction, NULL, ZEND_ACC_PUBLIC) PHP_ME(SQLite, sqliteCreateAggregate, NULL, ZEND_ACC_PUBLIC) + PHP_ME(SQLite, sqliteCreateCollation, NULL, ZEND_ACC_PUBLIC) PHP_FE_END }; @@ -643,11 +767,6 @@ static char *make_filename_safe(const char *filename T return NULL; } - if (PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) { - efree(fullpath); - return NULL; - } - if (php_check_open_basedir(fullpath TSRMLS_CC)) { efree(fullpath); return NULL; @@ -705,7 +824,7 @@ static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, z if (!filename) { zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, - "safe_mode/open_basedir prohibits opening %s", + "open_basedir prohibits opening %s", dbh->data_source); goto cleanup; } @@ -718,7 +837,7 @@ static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, z goto cleanup; } - if (PG(safe_mode) || (PG(open_basedir) && *PG(open_basedir))) { + if (PG(open_basedir) && *PG(open_basedir)) { sqlite3_set_authorizer(H->db, authorizer, NULL); }