]> granicus.if.org Git - php/commitdiff
MFH: ini file support
authorMarcus Boerger <helly@php.net>
Thu, 29 May 2003 14:16:25 +0000 (14:16 +0000)
committerMarcus Boerger <helly@php.net>
Thu, 29 May 2003 14:16:25 +0000 (14:16 +0000)
ext/dba/config.m4
ext/dba/dba.c
ext/dba/libinifile/inifile.c

index 2c0805359910a09140278be8c1f2e825c9adfc85..4fbd29734670e93b52732a6fc5e7d6f6e1f9c0de 100644 (file)
@@ -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)
index bcc97f167d89f8bab11152a6e3d9d95f3b321b03..c23a18029cf373a5b7883325c3748223d8a564b2 100644 (file)
@@ -28,6 +28,7 @@
 #if HAVE_DBA
 
 #include "ext/standard/flock_compat.h" 
+#include "php_ini.h"
 #include <stdio.h> 
 #include <fcntl.h>
 #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);
index 6e3d94dc4a34dc1e53f608b02d144fd2974085f0..e9941244af1a1b8b7eb8437e441404af3a469c90 100644 (file)
@@ -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;
        }