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

Reply via email to