From: Marcus Boerger Date: Thu, 29 May 2003 14:16:25 +0000 (+0000) Subject: MFH: ini file support X-Git-Tag: BEFORE_FD_REAPPLY~35 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ee11982bcbc1ebe617b8f6252af76e1d64e75de2;p=php MFH: ini file support --- diff --git a/ext/dba/config.m4 b/ext/dba/config.m4 index 2c08053599..4fbd297346 100644 --- a/ext/dba/config.m4 +++ b/ext/dba/config.m4 @@ -390,6 +390,24 @@ AC_ARG_WITH(cdb, ]) AC_DBA_STD_RESULT(cdb) +AC_DEFUN(PHP_DBA_BUILTIN_INI,[ + AC_DEFINE(DBA_INIFILE, 1, [ ]) + ini_sources="libinifile/inifile.c" + THIS_RESULT="builtin" +]) + +AC_ARG_WITH(inifile, +[ --with-inifile DBA: Include INI support],[ + if test "$withval" != "no"; then + PHP_DBA_BUILTIN_INI + fi +],[ + if test "$PHP_DBA" != "no" -o "$HAVE_DBA" = "1"; then + PHP_DBA_BUILTIN_INI + fi +]) +AC_DBA_STD_RESULT(inifile,INI File) + AC_DEFUN(PHP_DBA_BUILTIN_FLATFILE,[ AC_DEFINE(DBA_FLATFILE, 1, [ ]) flat_sources="libflatfile/flatfile.c" @@ -415,7 +433,8 @@ AC_MSG_CHECKING(whether to enable DBA interface) if test "$HAVE_DBA" = "1"; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_DBA, 1, [ ]) - PHP_NEW_EXTENSION(dba, dba.c dba_cdb.c dba_db2.c dba_dbm.c dba_gdbm.c dba_ndbm.c dba_db3.c dba_db4.c dba_flatfile.c $cdb_sources $flat_sources, $ext_shared) + PHP_NEW_EXTENSION(dba, dba.c dba_cdb.c dba_db2.c dba_dbm.c dba_gdbm.c dba_ndbm.c dba_db3.c dba_db4.c dba_flatfile.c dba_inifile.c $cdb_sources $flat_sources $ini_sources, $ext_shared) + PHP_ADD_BUILD_DIR($ext_builddir/libinifile) PHP_ADD_BUILD_DIR($ext_builddir/libcdb) PHP_ADD_BUILD_DIR($ext_builddir/libflatfile) PHP_SUBST(DBA_SHARED_LIBADD) diff --git a/ext/dba/dba.c b/ext/dba/dba.c index bcc97f167d..c23a18029c 100644 --- a/ext/dba/dba.c +++ b/ext/dba/dba.c @@ -28,6 +28,7 @@ #if HAVE_DBA #include "ext/standard/flock_compat.h" +#include "php_ini.h" #include #include #ifdef HAVE_SYS_FILE_H @@ -46,6 +47,7 @@ #include "php_db3.h" #include "php_db4.h" #include "php_flatfile.h" +#include "php_inifile.h" /* {{{ dba_functions[] */ @@ -105,15 +107,56 @@ ZEND_GET_MODULE(dba) WRONG_PARAM_COUNT; \ } +/* {{{ php_dba_myke_key */ +static size_t php_dba_make_key(zval **key, char **key_str, char **key_free TSRMLS_DC) +{ + if (Z_TYPE_PP(key) == IS_ARRAY) { + zval **group, **name; + HashPosition pos; + size_t len; + + if (zend_hash_num_elements(Z_ARRVAL_PP(key)) != 2) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Key does not have exactly two elements: (key, name)"); + return -1; + } + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(key), &pos); + zend_hash_get_current_data_ex(Z_ARRVAL_PP(key), (void **) &group, &pos); + zend_hash_move_forward_ex(Z_ARRVAL_PP(key), &pos); + zend_hash_get_current_data_ex(Z_ARRVAL_PP(key), (void **) &name, &pos); + convert_to_string_ex(group); + convert_to_string_ex(name); + if (Z_STRLEN_PP(group) == 0) { + *key_str = Z_STRVAL_PP(name); + *key_free = NULL; + return Z_STRLEN_PP(name); + } + len = spprintf(key_str, 0, "[%s]%s", Z_STRVAL_PP(group), Z_STRVAL_PP(name)); + *key_free = *key_str; + return len; + } else { + convert_to_string_ex(key); + *key_str = Z_STRVAL_PP(key); + *key_free = NULL; + return Z_STRLEN_PP(key); + } +} +/* }}} */ + #define DBA_GET2 \ zval **key; \ + char *key_str, *key_free; \ + size_t key_len; \ if(ac != 2 || zend_get_parameters_ex(ac, &key, &id) != SUCCESS) { \ WRONG_PARAM_COUNT; \ } \ - convert_to_string_ex(key) + if ((key_len = php_dba_make_key(key, &key_str, &key_free TSRMLS_CC)) == 0) {\ + RETURN_FALSE; \ + } #define DBA_GET2_3 \ zval **key; \ + char *key_str, *key_free; \ + size_t key_len; \ zval **tmp; \ int skip = 0; \ switch(ac) { \ @@ -132,7 +175,21 @@ ZEND_GET_MODULE(dba) default: \ WRONG_PARAM_COUNT; \ } \ - convert_to_string_ex(key) + if ((key_len = php_dba_make_key(key, &key_str, &key_free TSRMLS_CC)) == 0) {\ + RETURN_FALSE; \ + } + +#define DBA_GET3 \ + zval **key, **val; \ + char *key_str, *key_free; \ + size_t key_len; \ + if(ac != 3 || zend_get_parameters_ex(ac, &key, &val, &id) != SUCCESS) { \ + WRONG_PARAM_COUNT; \ + } \ + convert_to_string_ex(val); \ + if ((key_len = php_dba_make_key(key, &key_str, &key_free TSRMLS_CC)) == 0) {\ + RETURN_FALSE; \ + } #define DBA_ID_GET \ ZEND_FETCH_RESOURCE2(info, dba_info *, id, -1, "DBA identifier", le_db, le_pdb); @@ -140,7 +197,10 @@ ZEND_GET_MODULE(dba) #define DBA_ID_GET1 DBA_ID_PARS; DBA_GET1; DBA_ID_GET #define DBA_ID_GET2 DBA_ID_PARS; DBA_GET2; DBA_ID_GET #define DBA_ID_GET2_3 DBA_ID_PARS; DBA_GET2_3; DBA_ID_GET +#define DBA_ID_GET3 DBA_ID_PARS; DBA_GET3; DBA_ID_GET +#define DBA_ID_DONE \ + if (key_free) efree(key_free) /* a DBA handler must have specific routines */ #define DBA_NAMED_HND(alias, name, flags) \ @@ -188,14 +248,68 @@ static dba_handler handler[] = { #if DBA_DB4 DBA_HND(db4, DBA_LOCK_ALL) /* No lock in lib */ #endif +#if DBA_INIFILE + DBA_HND(inifile, DBA_STREAM_OPEN|DBA_LOCK_ALL) /* No lock in lib */ +#endif #if DBA_FLATFILE DBA_HND(flatfile, DBA_STREAM_OPEN|DBA_LOCK_ALL) /* No lock in lib */ #endif { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } }; +#if DBA_FLATFILE +#define DBA_DEFAULT "flatfile" +#elif DBA_DB4 +#define DBA_DEFAULT "db4" +#elif DBA_DB3 +#define DBA_DEFAULT "db3" +#elif DBA_DB2 +#define DBA_DEFAULT "db2" +#elif DBA_GDBM +#define DBA_DEFAULT "gdbm" +#elif DBA_NBBM +#define DBA_DEFAULT "ndbm" +#elif DBA_DBM +#define DBA_DEFAULT "dbm" +#else +#define DBA_DEFAULT "" +#endif +/* cdb/cdb_make and ini are no option here */ + +ZEND_BEGIN_MODULE_GLOBALS(dba) + char *default_handler; + dba_handler *default_hptr; +ZEND_END_MODULE_GLOBALS(dba) + +ZEND_DECLARE_MODULE_GLOBALS(dba) + +#ifdef ZTS +#define DBA_G(v) TSRMG(dba_globals_id, zend_dba_globals *, v) +#else +#define DBA_G(v) (dba_globals.v) +#endif + static int le_db; static int le_pdb; + +/* {{{ dba_fetch_resource +PHPAPI void dba_fetch_resource(dba_info **pinfo, zval **id TSRMLS_DC) +{ + dba_info *info; + DBA_ID_FETCH + *pinfo = info; +} +*/ +/* }}} */ + +/* {{{ dba_get_handler +PHPAPI dba_handler *dba_get_handler(const char* handler_name) +{ + dba_handler *hptr; + for (hptr = handler; hptr->name && strcasecmp(hptr->name, handler_name); hptr++); + return hptr; +} +*/ /* }}} */ /* {{{ dba_close @@ -253,10 +367,47 @@ static void dba_close_pe_rsrc(zend_rsrc_list_entry *rsrc TSRMLS_DC) } /* }}} */ +/* {{{ PHP_INI + */ +ZEND_API ZEND_INI_MH(OnUpdateDefaultHandler) +{ + dba_handler *hptr; + + if (!strlen(new_value)) { + DBA_G(default_hptr) = NULL; + return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); + } + + for (hptr = handler; hptr->name && strcasecmp(hptr->name, new_value); hptr++); + + if (!hptr->name) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such handler: %s", new_value); + return FAILURE; + } + DBA_G(default_hptr) = hptr; + return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); +} + +PHP_INI_BEGIN() + STD_PHP_INI_ENTRY("dba.default_handler", DBA_DEFAULT, PHP_INI_ALL, OnUpdateDefaultHandler, default_handler, zend_dba_globals, dba_globals) +PHP_INI_END() +/* }}} */ + +/* {{{ php_dba_init_globals + */ +static void php_dba_init_globals(zend_dba_globals *dba_globals) +{ + dba_globals->default_handler = ""; + dba_globals->default_hptr = NULL; +} +/* }}} */ + /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(dba) { + ZEND_INIT_MODULE_GLOBALS(dba, php_dba_init_globals, NULL); + REGISTER_INI_ENTRIES(); le_db = zend_register_list_destructors_ex(dba_close_rsrc, NULL, "dba", module_number); le_pdb = zend_register_list_destructors_ex(dba_close_pe_rsrc, dba_close_rsrc, "dba persistent", module_number); return SUCCESS; @@ -267,6 +418,7 @@ PHP_MINIT_FUNCTION(dba) */ PHP_MSHUTDOWN_FUNCTION(dba) { + UNREGISTER_INI_ENTRIES(); return SUCCESS; } /* }}} */ @@ -302,17 +454,9 @@ PHP_MINFO_FUNCTION(dba) */ static void php_dba_update(INTERNAL_FUNCTION_PARAMETERS, int mode) { - DBA_ID_PARS; - zval **val, **key; char *v; int len; - - if(ac != 3 || zend_get_parameters_ex(ac, &key, &val, &id) != SUCCESS) { - WRONG_PARAM_COUNT; - } - convert_to_string_ex(key); - convert_to_string_ex(val); - DBA_ID_GET; + DBA_ID_GET3; DBA_WRITE_CHECK; @@ -320,15 +464,20 @@ static void php_dba_update(INTERNAL_FUNCTION_PARAMETERS, int mode) len = Z_STRLEN_PP(val); v = estrndup(Z_STRVAL_PP(val), len); php_stripslashes(v, &len TSRMLS_CC); - if(info->hnd->update(info, VALLEN(key), v, len, mode TSRMLS_CC) == SUCCESS) { + if(info->hnd->update(info, key_str, key_len, v, len, mode TSRMLS_CC) == SUCCESS) { efree(v); + DBA_ID_DONE; RETURN_TRUE; } efree(v); } else { - if(info->hnd->update(info, VALLEN(key), VALLEN(val), mode TSRMLS_CC) == SUCCESS) + if(info->hnd->update(info, key_str, key_len, VALLEN(val), mode TSRMLS_CC) == SUCCESS) + { + DBA_ID_DONE; RETURN_TRUE; + } } + DBA_ID_DONE; RETURN_FALSE; } /* }}} */ @@ -377,7 +526,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent) char mode[4], *pmode, *lock_file_mode = NULL; int persistent_flag = persistent ? STREAM_OPEN_PERSISTENT : 0; - if(ac < 3) { + if(ac < 2) { WRONG_PARAM_COUNT; } @@ -398,7 +547,8 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent) list_entry *le; /* calculate hash */ - key = emalloc(keylen); + key = safe_emalloc(keylen, 1, 1); + key[keylen] = '\0'; keylen = 0; for(i = 0; i < ac; i++) { @@ -421,7 +571,16 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent) } } - for (hptr = handler; hptr->name && strcasecmp(hptr->name, Z_STRVAL_PP(args[2])); hptr++); + if (ac==2) { + hptr = DBA_G(default_hptr); + if (!hptr) { + php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "No default handler selected"); + FREENOW; + RETURN_FALSE; + } + } else { + for (hptr = handler; hptr->name && strcasecmp(hptr->name, Z_STRVAL_PP(args[2])); hptr++); + } if (!hptr->name) { php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "No such handler: %s", Z_STRVAL_PP(args[2])); @@ -633,7 +792,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent) /* }}} */ #undef FREENOW -/* {{{ proto int dba_popen(string path, string mode, string handlername [, string ...]) +/* {{{ proto int dba_popen(string path, string mode [, string handlername, string ...]) Opens path using the specified handler in mode persistently */ PHP_FUNCTION(dba_popen) { @@ -641,7 +800,7 @@ PHP_FUNCTION(dba_popen) } /* }}} */ -/* {{{ proto int dba_open(string path, string mode, string handlername [, string ...]) +/* {{{ proto int dba_open(string path, string mode [, string handlername, string ...]) Opens path using the specified handler in mode*/ PHP_FUNCTION(dba_open) { @@ -665,9 +824,11 @@ PHP_FUNCTION(dba_exists) { DBA_ID_GET2; - if(info->hnd->exists(info, VALLEN(key) TSRMLS_CC) == SUCCESS) { + if(info->hnd->exists(info, key_str, key_len TSRMLS_CC) == SUCCESS) { + DBA_ID_DONE; RETURN_TRUE; } + DBA_ID_DONE; RETURN_FALSE; } /* }}} */ @@ -680,15 +841,38 @@ PHP_FUNCTION(dba_fetch) int len = 0; DBA_ID_GET2_3; - if (ac==3 && strcmp(info->hnd->name, "cdb")) { - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Handler %s does not support optional skip parameter", info->hnd->name); + if (ac==3) { + if (!strcmp(info->hnd->name, "cdb")) { + if (skip < 0) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Handler %s accepts only skip values greater than or equal to zero, using skip=0", info->hnd->name); + skip = 0; + } + } else if (!strcmp(info->hnd->name, "inifile")) { + /* "-1" is compareable to 0 but allows a non restrictive + * access which is fater. For example 'inifile' uses this + * to allow faster access when the key was already found + * using firstkey/nextkey. However explicitly setting the + * value to 0 ensures the first value. + */ + if (skip < -1) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Handler %s accepts only skip value -1 and greater, using skip=0", info->hnd->name); + skip = 0; + } + } else { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Handler %s does not support optional skip parameter, the value will be ignored", info->hnd->name); + skip = 0; + } + } else { + skip = 0; } - if((val = info->hnd->fetch(info, VALLEN(key), skip, &len TSRMLS_CC)) != NULL) { + if((val = info->hnd->fetch(info, key_str, key_len, skip, &len TSRMLS_CC)) != NULL) { if (val && PG(magic_quotes_runtime)) { val = php_addslashes(val, len, &len, 1 TSRMLS_CC); } + DBA_ID_DONE; RETURN_STRINGL(val, len, 0); } + DBA_ID_DONE; RETURN_FALSE; } /* }}} */ @@ -724,21 +908,27 @@ PHP_FUNCTION(dba_nextkey) /* }}} */ /* {{{ proto bool dba_delete(string key, int handle) - Deletes the entry associated with key */ + Deletes the entry associated with key + If inifile: remove all other key lines */ PHP_FUNCTION(dba_delete) { DBA_ID_GET2; DBA_WRITE_CHECK; - if(info->hnd->delete(info, VALLEN(key) TSRMLS_CC) == SUCCESS) + if(info->hnd->delete(info, key_str, key_len TSRMLS_CC) == SUCCESS) + { + DBA_ID_DONE; RETURN_TRUE; + } + DBA_ID_DONE; RETURN_FALSE; } /* }}} */ /* {{{ proto bool dba_insert(string key, string value, int handle) - Inserts value as key, returns false, if key exists already */ + If not inifile: Insert value as key, return false, if key exists already + If inifile: Add vakue as key (next instance of key) */ PHP_FUNCTION(dba_insert) { php_dba_update(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); @@ -746,7 +936,8 @@ PHP_FUNCTION(dba_insert) /* }}} */ /* {{{ proto bool dba_replace(string key, string value, int handle) - Inserts value as key, replaces key, if key exists already */ + Inserts value as key, replaces key, if key exists already + If inifile: remove all other key lines */ PHP_FUNCTION(dba_replace) { php_dba_update(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); diff --git a/ext/dba/libinifile/inifile.c b/ext/dba/libinifile/inifile.c index 6e3d94dc4a..e9941244af 100644 --- a/ext/dba/libinifile/inifile.c +++ b/ext/dba/libinifile/inifile.c @@ -87,10 +87,6 @@ inifile * inifile_alloc(php_stream *fp, int readonly, int persistent TSRMLS_DC) int fd = 0; if (!readonly) { - if (!php_stream_truncate_supported(fp)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't truncate this stream"); - return NULL; - } if (SUCCESS != php_stream_cast(fp, PHP_STREAM_AS_FD, (void*)&fd, 1)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not cast stream"); return NULL; @@ -320,7 +316,8 @@ static int inifile_truncate(inifile *dba, size_t size TSRMLS_DC) { int res; - if ((res=php_stream_truncate_set_size(dba->fp, size)) != 0) { + php_stream_flush(dba->fp); + if ((res=ftruncate(dba->fd, size)) != 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error in ftruncate: %d", res); return FAILURE; }