Hello list,
i've extended sqlite_driver to get access to the authorizer-feature of
sqlite. This is my first contact with the Zend-API and my last c skill
is more than a bit outdated.
Could someone review/cleanup my code to get it merged to the
distribution? Hint and comment welcome!
Thanks,
Mario Wolff

PS: Patch applys against 5.2.0!
*** php-5.2.0/ext/pdo_sqlite/sqlite_driver.c	Sat Sep 16 20:30:03 2006
--- php-5.2.0-new/ext/pdo_sqlite/sqlite_driver.c	Thu Nov 16 13:38:33 2006
***************
*** 31,36 ****
--- 31,38 ----
  #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,601 ****
--- 595,653 ----
  	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,694 ****
  static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
  		const char *arg5, const char *arg6)
  {
  	char *filename;
! 	switch (access_type) {
! 		case SQLITE_COPY: {
! 			TSRMLS_FETCH();
! 			filename = make_filename_safe(arg4 TSRMLS_CC);
! 			if (!filename) {
! 				return SQLITE_DENY;
  			}
- 			efree(filename);
- 			return SQLITE_OK;
- 		}
  
! 		case SQLITE_ATTACH: {
! 			TSRMLS_FETCH();
! 			filename = make_filename_safe(arg3 TSRMLS_CC);
! 			if (!filename) {
! 				return SQLITE_DENY;
  			}
- 			efree(filename);
- 			return SQLITE_OK;
- 		}
  
! 		default:
! 			/* access allowed */
! 			return SQLITE_OK;
  	}
  }
  
  static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
--- 715,861 ----
  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;
! 	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;
! 				}
  			}
  
! 			case SQLITE_ATTACH: {
! 				TSRMLS_FETCH();
! 				filename = make_filename_safe(arg3 TSRMLS_CC);
! 				if (!filename) {
! 					retval=SQLITE_DENY;
! 				}else{
! 					efree(filename);
! 					retval=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,729 ****
  		goto cleanup;
  	}
  
! 	if (PG(safe_mode) || (PG(open_basedir) && *PG(open_basedir))) {
! 		sqlite3_set_authorizer(H->db, authorizer, NULL);
! 	}
  
  	if (driver_options) {
  		timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout TSRMLS_CC);
--- 888,894 ----
  		goto cleanup;
  	}
  
! 	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