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

Reply via email to