--- 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-16 13:38:33.985989144 +0100 @@ -31,6 +31,8 @@ #include "php_pdo_sqlite_int.h" #include "zend_exceptions.h" +static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4, + const char *arg5, const char *arg6); int _pdo_sqlite_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int line TSRMLS_DC) /* {{{ */ { pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data; @@ -593,9 +595,59 @@ RETURN_FALSE; } /* }}} */ + +/* {{{ bool SQLite::sqliteSetAuthorizer(string name, mixed callback [, int argcount]) + Registers a UDF with the sqlite db handle */ +static PHP_METHOD(SQLite, sqliteSetAuthorizer) +{ + static 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 || callback->type == IS_STRING && ! strcmp(callback->value.str.val,"") ){ + if (user_authorizer!=NULL){ + FREE_ZVAL(user_authorizer); + sqlite3_set_authorizer(H->db, 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 (user_authorizer!=NULL){ + FREE_ZVAL(user_authorizer); + } + + MAKE_STD_ZVAL(user_authorizer); + ZVAL_STRING(user_authorizer, callback->value.str.val, 1); + sqlite3_set_authorizer(H->db, 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} }; @@ -663,32 +715,147 @@ static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4, const char *arg5, const char *arg6) { + 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) { + retval=SQLITE_DENY; + }else{ + efree(filename); + retval=SQLITE_OK; + } } - efree(filename); - return SQLITE_OK; - } - case SQLITE_ATTACH: { - TSRMLS_FETCH(); - filename = make_filename_safe(arg3 TSRMLS_CC); - if (!filename) { - return SQLITE_DENY; + case SQLITE_ATTACH: { + TSRMLS_FETCH(); + filename = make_filename_safe(arg3 TSRMLS_CC); + if (!filename) { + retval=SQLITE_DENY; + }else{ + efree(filename); + retval=SQLITE_OK; + } } - efree(filename); - return SQLITE_OK; - } - default: - /* access allowed */ - return SQLITE_OK; + default: + /* access allowed */ + retval=SQLITE_OK; + } + } + if( retval==SQLITE_OK && autharg!=NULL ){ + callback=(zval*)autharg; + zval **args[5]; + zend_fcall_info_cache fci_cache = empty_fcall_info_cache; + zval *result = NULL; + zend_fcall_info fci; + char* zCode; + switch( access_type ){ + case SQLITE_COPY : zCode="SQLITE_COPY"; break; + case SQLITE_CREATE_INDEX : zCode="SQLITE_CREATE_INDEX"; break; + case SQLITE_CREATE_TABLE : zCode="SQLITE_CREATE_TABLE"; break; + case SQLITE_CREATE_TEMP_INDEX : zCode="SQLITE_CREATE_TEMP_INDEX"; break; + case SQLITE_CREATE_TEMP_TABLE : zCode="SQLITE_CREATE_TEMP_TABLE"; break; + case SQLITE_CREATE_TEMP_TRIGGER: zCode="SQLITE_CREATE_TEMP_TRIGGER"; break; + case SQLITE_CREATE_TEMP_VIEW : zCode="SQLITE_CREATE_TEMP_VIEW"; break; + case SQLITE_CREATE_TRIGGER : zCode="SQLITE_CREATE_TRIGGER"; break; + case SQLITE_CREATE_VIEW : zCode="SQLITE_CREATE_VIEW"; break; + case SQLITE_DELETE : zCode="SQLITE_DELETE"; break; + case SQLITE_DROP_INDEX : zCode="SQLITE_DROP_INDEX"; break; + case SQLITE_DROP_TABLE : zCode="SQLITE_DROP_TABLE"; break; + case SQLITE_DROP_TEMP_INDEX : zCode="SQLITE_DROP_TEMP_INDEX"; break; + case SQLITE_DROP_TEMP_TABLE : zCode="SQLITE_DROP_TEMP_TABLE"; break; + case SQLITE_DROP_TEMP_TRIGGER : zCode="SQLITE_DROP_TEMP_TRIGGER"; break; + case SQLITE_DROP_TEMP_VIEW : zCode="SQLITE_DROP_TEMP_VIEW"; break; + case SQLITE_DROP_TRIGGER : zCode="SQLITE_DROP_TRIGGER"; break; + case SQLITE_DROP_VIEW : zCode="SQLITE_DROP_VIEW"; break; + case SQLITE_INSERT : zCode="SQLITE_INSERT"; break; + case SQLITE_PRAGMA : zCode="SQLITE_PRAGMA"; break; + case SQLITE_READ : zCode="SQLITE_READ"; break; + case SQLITE_SELECT : zCode="SQLITE_SELECT"; break; + case SQLITE_TRANSACTION : zCode="SQLITE_TRANSACTION"; break; + case SQLITE_UPDATE : zCode="SQLITE_UPDATE"; break; + case SQLITE_ATTACH : zCode="SQLITE_ATTACH"; break; + case SQLITE_DETACH : zCode="SQLITE_DETACH"; break; + case SQLITE_ALTER_TABLE : zCode="SQLITE_ALTER_TABLE"; break; + case SQLITE_REINDEX : zCode="SQLITE_REINDEX"; break; + case SQLITE_ANALYZE : zCode="SQLITE_ANALYZE"; break; + case SQLITE_CREATE_VTABLE : zCode="SQLITE_CREATE_VTABLE"; break; + case SQLITE_DROP_VTABLE : zCode="SQLITE_DROP_VTABLE"; break; + default : zCode="????"; break; + } + MAKE_STD_ZVAL(zaccess_type); + ZVAL_STRING(zaccess_type,zCode, 1); + args[0]=&zaccess_type; + + MAKE_STD_ZVAL(zarg3); + if( arg3!=NULL ){ + ZVAL_STRING(zarg3,(char*)arg3, 1); + }else{ + ZVAL_STRING(zarg3,"", 1); + } + args[1]=&zarg3; + + MAKE_STD_ZVAL(zarg4); + if( arg4!=NULL ){ + ZVAL_STRING(zarg4,(char*)arg4, 1); + }else{ + ZVAL_STRING(zarg4,"", 1); + } + args[2]=&zarg4; + + MAKE_STD_ZVAL(zarg5); + if( arg5!=NULL ){ + ZVAL_STRING(zarg5,(char*)arg5, 1); + }else{ + ZVAL_STRING(zarg5,"", 1); + } + args[3]=&zarg5; + + MAKE_STD_ZVAL(zarg6); + if( arg6!=NULL ){ + ZVAL_STRING(zarg6,(char*)arg6, 1); + }else{ + ZVAL_STRING(zarg6,"", 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; + } + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the reduction callback"); + retval=SQLITE_DENY; + } + + 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) /* {{{ */ @@ -721,9 +888,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, NULL); if (driver_options) { timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout TSRMLS_CC);