2006/11/16, Wez Furlong <[EMAIL PROTECTED]>:
I think it would be better to pass in the pdo_dbh_t as the autharg to the C level callback and then use that to determine if any of the expensive work needs to be done in the callback.
Saves the sqlite_set_authorizer recall in SetAuthorizer, Looks simpler and cleaner. -> done
static int authorizer(....) { pdo_dbh_t *db; /* keep the current safemode / basedir checks "cheap" and fast */ if (existing safe_mode and open_base dir return SQLITE_DENY) { return SQLITE_DENY; } db = (pdo_dbh_t*)autharg; if (db->user_authorizer) { TSRMLS_FETCH();
What is this? I'm not familiar with the hole php-stuff, sorry! Done by: + pdo_dbh_t *dbh; + pdo_sqlite_db_handle *H; ... + dbh=(pdo_dbh_t*)autharg; + PDO_CONSTRUCT_CHECK; + H = (pdo_sqlite_db_handle *)dbh->driver_data; + + if( H->user_authorizer ){ OK?
... free stuff } } You should take a look at how the pdo_sqlite_fci stuff works and adopt that for the authorizer callback, as it will help improve runtime performance there.
Can't find usefull stuff to adopt. Can you hint me further?
It would also be best to register constants for the various SQLITE_XXX codes rather than creating strings and having the PHP code check against strings. This will also improve performance at runtime.
I like talking parameters! But you are right, performance comes first! -> done
> Short test script:
Modified: <?php $data = array( 'one', 'two', 'three', 'four', 'five', 'six'); $db = new PDO( 'sqlite::memory:'); echo "register authorizer\n"; $db->sqliteSetAuthorizer('auth'); $db->exec( "CREATE TABLE strings( a)"); $insert = $db->prepare( 'INSERT INTO strings VALUES ( ?)'); foreach ( $data as $str) { $insert->execute( array( $str)); } $insert = null; if( $delete = $db->prepare( 'DELETE FROM strings where a=?')){ if( $delete->execute(array( "six" ))){ echo "delete done!\n"; } $delete = null; }else{ echo "delete not prepared\n"; } echo "unregister authorizer\n"; $db->sqliteSetAuthorizer(); if( $delete = $db->prepare( 'DELETE FROM strings where a=?')){ if( $delete->execute(array( "six" ))){ echo "delete done!\n"; } $delete = null; }else{ echo "delete not prepared\n"; } function auth($type,$arga,$argb,$argc,$argd ){ echo "$type\t$arga\t$argb\t$argc\t$argd\n"; if( $type==SQLITE_DELETE ){ return SQLITE_DENY; } return SQLITE_OK; } print_r( $db->query( 'SELECT sqlite_version( *);')->fetchAll( )); print_r( $db->query( 'SELECT * from strings;')->fetchAll( )); ?>
> gives:
now: register authorizer 18 sqlite_master main 2 strings main 23 sqlite_master type main 23 sqlite_master name main 23 sqlite_master tbl_name main 23 sqlite_master rootpage main 23 sqlite_master sql main 20 sqlite_master ROWID main 20 sqlite_master name main 20 sqlite_master rootpage main 20 sqlite_master sql main 20 sqlite_master tbl_name main 18 strings main 9 strings main delete not prepared unregister authorizer delete done! Array ( [0] => Array ( [sqlite_version( *)] => 3.3.7 [0] => 3.3.7 ) ) Array ( [0] => Array ( [a] => one [0] => one ) [1] => Array ( [a] => two [0] => two ) [2] => Array ( [a] => three [0] => three ) [3] => Array ( [a] => four [0] => four ) [4] => Array ( [a] => five [0] => five ) ) Regards, Mario
diff -ur php-5.2.0/ext/pdo_sqlite/pdo_sqlite.c php-5.2.0-new/ext/pdo_sqlite/pdo_sqlite.c --- php-5.2.0/ext/pdo_sqlite/pdo_sqlite.c 2006-01-01 13:50:12.000000000 +0100 +++ php-5.2.0-new/ext/pdo_sqlite/pdo_sqlite.c 2006-11-16 21:03:33.000000000 +0100 @@ -77,6 +77,42 @@ /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(pdo_sqlite) { + REGISTER_LONG_CONSTANT("SQLITE_COPY", SQLITE_COPY, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_CREATE_INDEX", SQLITE_CREATE_INDEX, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_CREATE_TABLE", SQLITE_CREATE_TABLE, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_CREATE_TEMP_INDEX", SQLITE_CREATE_TEMP_INDEX, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_CREATE_TEMP_TABLE", SQLITE_CREATE_TEMP_TABLE, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_CREATE_TEMP_TRIGGER", SQLITE_CREATE_TEMP_TRIGGER, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_CREATE_TEMP_VIEW", SQLITE_CREATE_TEMP_VIEW, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_CREATE_TRIGGER", SQLITE_CREATE_TRIGGER, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_CREATE_VIEW", SQLITE_CREATE_VIEW, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_DELETE", SQLITE_DELETE, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_DROP_INDEX", SQLITE_DROP_INDEX, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_DROP_TABLE", SQLITE_DROP_TABLE, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_DROP_TEMP_INDEX", SQLITE_DROP_TEMP_INDEX, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_DROP_TEMP_TABLE", SQLITE_DROP_TEMP_TABLE, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_DROP_TEMP_TRIGGER", SQLITE_DROP_TEMP_TRIGGER, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_DROP_TEMP_VIEW", SQLITE_DROP_TEMP_VIEW, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_DROP_TRIGGER", SQLITE_DROP_TRIGGER, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_DROP_VIEW", SQLITE_DROP_VIEW, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_INSERT", SQLITE_INSERT, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_PRAGMA", SQLITE_PRAGMA, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_READ", SQLITE_READ, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_SELECT", SQLITE_SELECT, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_TRANSACTION", SQLITE_TRANSACTION, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_UPDATE", SQLITE_UPDATE, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_ATTACH", SQLITE_ATTACH, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_DETACH", SQLITE_DETACH, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_ALTER_TABLE", SQLITE_ALTER_TABLE, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_REINDEX", SQLITE_REINDEX, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_ANALYZE", SQLITE_ANALYZE, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_CREATE_VTABLE", SQLITE_CREATE_VTABLE, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_DROP_VTABLE", SQLITE_DROP_VTABLE, CONST_PERSISTENT | CONST_CS); + // REGISTER_LONG_CONSTANT("SQLITE_FUNCTION", SQLITE_FUNCTION, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_OK", SQLITE_OK, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_DENY", SQLITE_DENY, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("SQLITE_IGNORE", SQLITE_IGNORE, CONST_PERSISTENT | CONST_CS); + return php_pdo_register_driver(&pdo_sqlite_driver); } /* }}} */ diff -ur php-5.2.0/ext/pdo_sqlite/php_pdo_sqlite_int.h php-5.2.0-new/ext/pdo_sqlite/php_pdo_sqlite_int.h --- php-5.2.0/ext/pdo_sqlite/php_pdo_sqlite_int.h 2006-01-01 13:50:12.000000000 +0100 +++ php-5.2.0-new/ext/pdo_sqlite/php_pdo_sqlite_int.h 2006-11-16 20:51:42.000000000 +0100 @@ -49,6 +49,7 @@ typedef struct { sqlite3 *db; pdo_sqlite_error_info einfo; + zval *user_authorizer; struct pdo_sqlite_func *funcs; } pdo_sqlite_db_handle; diff -ur php-5.2.0/ext/pdo_sqlite/sqlite_driver.c php-5.2.0-new/ext/pdo_sqlite/sqlite_driver.c --- php-5.2.0/ext/pdo_sqlite/sqlite_driver.c 2006-09-16 20:30:03.000000000 +0200 +++ php-5.2.0-new/ext/pdo_sqlite/sqlite_driver.c 2006-11-17 10:05:30.552613256 +0100 @@ -593,9 +593,59 @@ RETURN_FALSE; } /* }}} */ + +/* {{{ bool SQLite::sqliteSetAuthorizer( mixed callback ) + Registers a callback for authorization with the sqlite db handle */ +static PHP_METHOD(SQLite, sqliteSetAuthorizer) +{ + zval *user_authorizer=NULL; + struct pdo_sqlite_func *func; + zval *callback=NULL; + char *cbname = NULL; + pdo_dbh_t *dbh; + pdo_sqlite_db_handle *H; + int ret; + + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z", + &callback)) { + RETURN_FALSE; + } + + dbh = zend_object_store_get_object(getThis() TSRMLS_CC); + PDO_CONSTRUCT_CHECK; + H = (pdo_sqlite_db_handle *)dbh->driver_data; + + if( callback==NULL ){ + if (H->user_authorizer!=NULL){ + FREE_ZVAL(H->user_authorizer); + H->user_authorizer=NULL; + } + RETURN_TRUE; + } + + if (!zend_is_callable(callback, 0, &cbname)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname); + efree(cbname); + RETURN_FALSE; + } + efree(cbname); + + + if (H->user_authorizer!=NULL){ + FREE_ZVAL(H->user_authorizer); + } + + MAKE_STD_ZVAL(user_authorizer); + ZVAL_STRING(user_authorizer, callback->value.str.val, 1); + H->user_authorizer=user_authorizer; + RETURN_TRUE; +} +/* }}} */ + static zend_function_entry dbh_methods[] = { PHP_ME(SQLite, sqliteCreateFunction, NULL, ZEND_ACC_PUBLIC) PHP_ME(SQLite, sqliteCreateAggregate, NULL, ZEND_ACC_PUBLIC) + PHP_ME(SQLite, sqliteSetAuthorizer, NULL, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} }; @@ -617,6 +667,10 @@ * request */ if (H) { pdo_sqlite_cleanup_callbacks(H TSRMLS_CC); + if( H->user_authorizer!=0 ){ + FREE_ZVAL(H->user_authorizer); + H->user_authorizer=NULL; + } } } @@ -663,32 +717,94 @@ static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4, const char *arg5, const char *arg6) { + pdo_dbh_t *dbh; + pdo_sqlite_db_handle *H; + zval *callback=NULL,*zaccess_type,*zarg3,*zarg4,*zarg5,*zarg6; + int retval=SQLITE_OK; char *filename; - switch (access_type) { - case SQLITE_COPY: { - TSRMLS_FETCH(); - filename = make_filename_safe(arg4 TSRMLS_CC); - if (!filename) { - return SQLITE_DENY; + if (PG(safe_mode) || (PG(open_basedir) && *PG(open_basedir))) { + switch (access_type) { + case SQLITE_COPY: { + TSRMLS_FETCH(); + filename = make_filename_safe(arg4 TSRMLS_CC); + if (!filename) { + return SQLITE_DENY; + } + efree(filename); + } + case SQLITE_ATTACH: { + TSRMLS_FETCH(); + filename = make_filename_safe(arg3 TSRMLS_CC); + if (!filename) { + return SQLITE_DENY; + } + efree(filename); } - efree(filename); - return SQLITE_OK; } - - case SQLITE_ATTACH: { - TSRMLS_FETCH(); - filename = make_filename_safe(arg3 TSRMLS_CC); - if (!filename) { - return SQLITE_DENY; + } + dbh=(pdo_dbh_t*)autharg; + PDO_CONSTRUCT_CHECK; + H = (pdo_sqlite_db_handle *)dbh->driver_data; + + if( H->user_authorizer ){ + callback=(zval*)H->user_authorizer; + zval **args[5]; + zend_fcall_info_cache fci_cache = empty_fcall_info_cache; + zval *result = NULL; + zend_fcall_info fci; + + MAKE_STD_ZVAL(zaccess_type); + ZVAL_LONG(zaccess_type,access_type); + args[0]=&zaccess_type; + + MAKE_STD_ZVAL(zarg3); + ZVAL_STRING(zarg3,arg3?(char*)arg3:"", 1); + args[1]=&zarg3; + + MAKE_STD_ZVAL(zarg4); + ZVAL_STRING(zarg4,arg4?(char*)arg4:"", 1); + args[2]=&zarg4; + + MAKE_STD_ZVAL(zarg5); + ZVAL_STRING(zarg5,arg5?(char*)arg5:"", 1); + args[3]=&zarg5; + + MAKE_STD_ZVAL(zarg6); + ZVAL_STRING(zarg6,arg6?(char*)arg6:"", 1); + args[4]=&zarg6; + + fci.size = sizeof(fci); + fci.function_table = EG(function_table); + fci.function_name = callback; + fci.symbol_table = NULL; + fci.object_pp = NULL; + fci.retval_ptr_ptr = &result; + fci.param_count = 5; + fci.params = args; + fci.no_separation = 0; + + if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && result) { + if( result->type==IS_BOOL ){ + retval=(result->value.lval==0); + }else if( result->type==IS_LONG ){ + retval=result->value.lval; + }else{ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid return from authorizer, need bool or int"); + retval=SQLITE_DENY; } - efree(filename); - return SQLITE_OK; + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the reduction callback"); + retval=SQLITE_DENY; } - - default: - /* access allowed */ - return SQLITE_OK; + + FREE_ZVAL(zaccess_type); + FREE_ZVAL(zarg3); + FREE_ZVAL(zarg4); + FREE_ZVAL(zarg5); + FREE_ZVAL(zarg6); + } + return retval; } static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */ @@ -702,6 +818,7 @@ H->einfo.errcode = 0; H->einfo.errmsg = NULL; + H->user_authorizer = NULL; dbh->driver_data = H; filename = make_filename_safe(dbh->data_source TSRMLS_CC); @@ -721,9 +838,7 @@ goto cleanup; } - if (PG(safe_mode) || (PG(open_basedir) && *PG(open_basedir))) { - sqlite3_set_authorizer(H->db, authorizer, NULL); - } + sqlite3_set_authorizer(H->db, authorizer, dbh); if (driver_options) { timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout TSRMLS_CC);
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php