2006/11/16, Mario Wolff <[EMAIL PROTECTED]>:
2006/11/16, Wez Furlong <[EMAIL PROTECTED]>:
> I suggest that you adjust your patch to cache the function callback
> information in the pdo_dbh_t to reduce some of that overhead, and run
> some benchmarks for a simple authorizer function in PHP that always
> returns true vs the same script with no authorizer, so that we get a
> feel for what kind of impact that has for various common queries.
Is the pdo_sqlite_db_handle not the better place to store? I'm not so
deep in the architecture to decide!
New patches attached! static-stuff removed. user_authorizer cleanup done.
> --Wez.
--- 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 16:22:36.605683512 +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;
--- 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 16:42:57.660055032 +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,60 @@
RETURN_FALSE;
}
/* }}} */
+
+/* {{{ bool SQLite::sqliteSetAuthorizer(string name, mixed callback [, int argcount])
+ Registers a UDF 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 || callback->type == IS_STRING && ! strcmp(callback->value.str.val,"") ){
+ if (H->user_authorizer!=NULL){
+ FREE_ZVAL(H->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 (H->user_authorizer!=NULL){
+ FREE_ZVAL(H->user_authorizer);
+ }
+
+ MAKE_STD_ZVAL(user_authorizer);
+ ZVAL_STRING(user_authorizer, callback->value.str.val, 1);
+ sqlite3_set_authorizer(H->db, authorizer, user_authorizer);
+ 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 +670,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 +720,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) /* {{{ */
@@ -702,6 +874,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 +894,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);
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php