helly           Thu May 29 10:16:25 2003 EDT

  Added files:                 (Branch: PHP_4_3)
    /php4/ext/dba       dba_inifile.c php_inifile.h 
    /php4/ext/dba/libinifile    .cvsignore inifile.c inifile.h 
    /php4/ext/dba/tests dba_inifile.phpt 

  Modified files:              
    /php4/ext/dba       config.m4 dba.c 
  Log:
  MFH: ini file support
  
  
Index: php4/ext/dba/config.m4
diff -u php4/ext/dba/config.m4:1.29.2.19 php4/ext/dba/config.m4:1.29.2.20
--- php4/ext/dba/config.m4:1.29.2.19    Tue May 20 20:35:29 2003
+++ php4/ext/dba/config.m4      Thu May 29 10:16:25 2003
@@ -1,5 +1,5 @@
 dnl
-dnl $Id: config.m4,v 1.29.2.19 2003/05/21 00:35:29 helly Exp $
+dnl $Id: config.m4,v 1.29.2.20 2003/05/29 14:16:25 helly Exp $
 dnl
 
 dnl Suppose we need FlatFile if no support or only CDB is used.
@@ -390,6 +390,24 @@
 ])
 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 @@
 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: php4/ext/dba/dba.c
diff -u php4/ext/dba/dba.c:1.61.2.15 php4/ext/dba/dba.c:1.61.2.16
--- php4/ext/dba/dba.c:1.61.2.15        Mon May 19 18:53:35 2003
+++ php4/ext/dba/dba.c  Thu May 29 10:16:25 2003
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: dba.c,v 1.61.2.15 2003/05/19 22:53:35 helly Exp $ */
+/* $Id: dba.c,v 1.61.2.16 2003/05/29 14:16:25 helly Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -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 @@
                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 @@
        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 @@
 #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 @@
 #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 @@
 }
 /* }}} */
 
+/* {{{ 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_MSHUTDOWN_FUNCTION(dba)
 {
+       UNREGISTER_INI_ENTRIES();
        return SUCCESS;
 }
 /* }}} */
@@ -302,17 +454,9 @@
  */
 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 @@
                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 @@
        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 @@
                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 @@
                }
        }
        
-       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 @@
 /* }}} */
 #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 @@
 }
 /* }}} */
 
-/* {{{ 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 @@
 {
        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 @@
        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 @@
 /* }}} */
 
 /* {{{ 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 @@
 /* }}} */
 
 /* {{{ 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: php4/ext/dba/dba_inifile.c
+++ php4/ext/dba/dba_inifile.c
/*
   +----------------------------------------------------------------------+
   | PHP Version 4                                                        |
   +----------------------------------------------------------------------+
   | Copyright (c) 1997-2003 The PHP Group                                |
   +----------------------------------------------------------------------+
   | This source file is subject to version 2.02 of the PHP license,      |
   | that is bundled with this package in the file LICENSE, and is        |
   | available at through the world-wide-web at                           |
   | http://www.php.net/license/2_02.txt.                                 |
   | If you did not receive a copy of the PHP license and are unable to   |
   | obtain it through the world-wide-web, please send a note to          |
   | [EMAIL PROTECTED] so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
   | Author: Marcus Boerger <[EMAIL PROTECTED]>                               |
   +----------------------------------------------------------------------+
 */

/* $Id: dba_inifile.c,v 1.1 2003/02/22 17:20:05 helly Exp $ */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"

#if DBA_INIFILE
#include "php_inifile.h"

#include "libinifile/inifile.h"

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define INIFILE_DATA \
        inifile *dba = info->dbf

#define INIFILE_GKEY \
        key_type ini_key = inifile_key_split((char*)key) /* keylen not needed here */

#define INIFILE_DONE \
        inifile_key_free(&ini_key)

DBA_OPEN_FUNC(inifile)
{
        info->dbf = inifile_alloc(info->fp, info->mode == DBA_READER, 
info->flags&DBA_PERSISTENT TSRMLS_CC);

        return info->dbf ? SUCCESS : FAILURE;
}

DBA_CLOSE_FUNC(inifile)
{
        INIFILE_DATA;

        inifile_free(dba, info->flags&DBA_PERSISTENT);
}

DBA_FETCH_FUNC(inifile)
{
        val_type ini_val;

        INIFILE_DATA;
        INIFILE_GKEY;

        ini_val = inifile_fetch(dba, &ini_key, skip TSRMLS_CC);
        *newlen = ini_val.value ? strlen(ini_val.value) : 0;
        INIFILE_DONE;
        return ini_val.value;
}

DBA_UPDATE_FUNC(inifile)
{
        val_type ini_val;
        int res;

        INIFILE_DATA;
        INIFILE_GKEY;
        
        ini_val.value = val;
        
        if (mode == 1) {
                res = inifile_append(dba, &ini_key, &ini_val TSRMLS_CC);
        } else {
                res = inifile_replace(dba, &ini_key, &ini_val TSRMLS_CC);
        }
        INIFILE_DONE;
        switch(res) {
        case -1:
                php_error_docref1(NULL TSRMLS_CC, key, E_WARNING, "Operation not 
possible");
                return FAILURE;
        default:
        case 0:
                return SUCCESS;
        case 1:
                php_error_docref1(NULL TSRMLS_CC, key, E_WARNING, "Key already 
exists");
                return SUCCESS;
        }
}

DBA_EXISTS_FUNC(inifile)
{
        val_type ini_val;

        INIFILE_DATA;
        INIFILE_GKEY;
        
        ini_val = inifile_fetch(dba, &ini_key, 0 TSRMLS_CC);
        INIFILE_DONE;
        if (ini_val.value) {
                inifile_val_free(&ini_val);
                return SUCCESS;
        }
        return FAILURE;
}

DBA_DELETE_FUNC(inifile)
{
        INIFILE_DATA;
        INIFILE_GKEY;
        int res =  inifile_delete(dba, &ini_key TSRMLS_CC);

        INIFILE_DONE;
        return (res == -1 ? FAILURE : SUCCESS);
}

DBA_FIRSTKEY_FUNC(inifile)
{
        INIFILE_DATA;

        if (inifile_firstkey(dba TSRMLS_CC)) {
                char *result = inifile_key_string(&dba->curr.key);
                *newlen = strlen(result);
                return result;
        } else {
                return NULL;
        }
}

DBA_NEXTKEY_FUNC(inifile)
{
        INIFILE_DATA;
        
        if (!dba->curr.key.group && !dba->curr.key.name) {
                return NULL;
        }

        if (inifile_nextkey(dba TSRMLS_CC)) {
                char *result = inifile_key_string(&dba->curr.key);
                *newlen = strlen(result);
                return result;
        } else {
                return NULL;
        }
}

DBA_OPTIMIZE_FUNC(inifile)
{
        /* dummy */
        return SUCCESS;
}

DBA_SYNC_FUNC(inifile)
{
        /* dummy */
        return SUCCESS;
}

DBA_INFO_FUNC(inifile)
{
        return estrdup(inifile_version());
}

#endif

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: sw=4 ts=4 fdm=marker
 * vim<600: sw=4 ts=4
 */

Index: php4/ext/dba/php_inifile.h
+++ php4/ext/dba/php_inifile.h
#ifndef PHP_INIFILE_H
#define PHP_INIFILE_H

#if DBA_INIFILE

#include "php_dba.h"

DBA_FUNCS(inifile);

#endif

#endif

Index: php4/ext/dba/libinifile/.cvsignore
+++ php4/ext/dba/libinifile/.cvsignore
*.lo
*.la
deps
*.plg
*.opt
*.ncb
Release
Release_inline
Debug
Release_TS
Release_TSDbg
Release_TS_inline
Debug_TS

Index: php4/ext/dba/libinifile/inifile.c
+++ php4/ext/dba/libinifile/inifile.c
/*
   +----------------------------------------------------------------------+
   | PHP Version 4                                                        |
   +----------------------------------------------------------------------+
   | Copyright (c) 1997-2003 The PHP Group                                |
   +----------------------------------------------------------------------+
   | This source file is subject to version 2.02 of the PHP license,      |
   | that is bundled with this package in the file LICENSE, and is        |
   | available at through the world-wide-web at                           |
   | http://www.php.net/license/2_02.txt.                                 |
   | If you did not receive a copy of the PHP license and are unable to   |
   | obtain it through the world-wide-web, please send a note to          |
   | [EMAIL PROTECTED] so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
   | Author: Marcus Boerger <[EMAIL PROTECTED]>                               |
   +----------------------------------------------------------------------+
 */

/* $Id: inifile.c,v 1.1 2003/02/22 17:20:05 helly Exp $ */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_globals.h"
#include "safe_mode.h"
#include "php_network.h"

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif

#include "inifile.h"

/* ret = -1 means that database was opened for read-only
 * ret = 0  success
 * ret = 1  key already exists - nothing done
 */

/* {{{ inifile_version */
char *inifile_version() 
{
        return "1.0, $Revision: 1.1 $";
}
/* }}} */ 

/* {{{ inifile_free_key */
void inifile_key_free(key_type *key)
{
        if (key->group) {
                efree(key->group);
        }
        if (key->name) {
                efree(key->name);
        }
        memset(key, 0, sizeof(key_type));
}
/* }}} */

/* {{{ inifile_free_val */
void inifile_val_free(val_type *val)
{
        if (val->value) {
                efree(val->value);
        }
        memset(val, 0, sizeof(val_type));
}
/* }}} */

/* {{{ inifile_free_val */
void inifile_line_free(line_type *ln)
{
        inifile_key_free(&ln->key);
        inifile_val_free(&ln->val);
        ln->pos = 0;
}
/* }}} */

/* {{{ inifile_alloc */
inifile * inifile_alloc(php_stream *fp, int readonly, int persistent TSRMLS_DC)
{
        inifile *dba;
        int fd = 0;

        if (!readonly) {
                if (php_stream_is(fp, PHP_STREAM_IS_SOCKET)) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't truncate 
sockets");
                        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;
                }
        }
        dba = pemalloc(sizeof(inifile), persistent);
        memset(dba, 0, sizeof(inifile));
        dba->fp = fp;
        dba->fd = fd;
        dba->readonly = readonly;
        return dba;
}
/* }}} */

/* {{{ inifile_free */
void inifile_free(inifile *dba, int persistent)
{
        if (dba) {
                inifile_line_free(&dba->curr);
                inifile_line_free(&dba->next);
                pefree(dba, persistent);
        }
}
/* }}} */

/* {{{ inifile_key_split */
key_type inifile_key_split(const char *group_name)
{
        key_type key;
        char *name;
        
        if (group_name[0] == '[' && (name = strchr(group_name, ']')) != NULL) {
                key.group = estrndup(group_name+1, name - (group_name + 1));
                key.name = estrdup(name+1);
        } else {
                key.group = estrdup("");
                key.name = estrdup(group_name);
        }
        return key;
}
/* }}} */

/* {{{ inifile_key_string */
char * inifile_key_string(const key_type *key)
{
        if (key->group && *key->group) {
                char *result;
                spprintf(&result, 0, "[%s]%s", key->group, key->name ? key->name : "");
                return result;
        } else if (key->name) {
                return estrdup(key->name);
        } else {
                return NULL;
        }
}
/* }}} */

/* {{{ etrim */
static char *etrim(const char *str)
{
        char *val;
        size_t l;
        
        if (!str) {
                return NULL;
        }
        val = (char*)str;
        while (strchr(" \t\r\n", *val)) {
                val++;
        }
        l = strlen(val);
        while (l && (strchr(" \t\r\n", val[l-1]))) {
                l--;
        }
        return estrndup(val, l);
}
/* }}} */

/* {{{ inifile_findkey
 */
static int inifile_read(inifile *dba, line_type *ln TSRMLS_DC) {
        char *fline;
        char *pos;

        inifile_val_free(&ln->val);
        while ((fline = php_stream_gets(dba->fp, NULL, 0)) != NULL) {
                if (fline) {
                        if (fline[0] == '[') {
                                /* A value name cannot start with '['
                                 * So either we find a ']' or we found an error
                                 */
                                pos = strchr(fline+1, ']');
                                if (pos) {
                                        *pos = '\0';
                                        inifile_key_free(&ln->key);
                                        ln->key.group = etrim(fline+1);
                                        ln->key.name = estrdup("");
                                        ln->pos = php_stream_tell(dba->fp);
                                        efree(fline);
                                        return 1;
                                } else {
                                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, 
"The following group was started with '[' but not ended with ']': '%s'", fline+1);
                                        efree(fline);
                                        continue;
                                }
                        } else {
                                pos = strchr(fline, '=');
                                if (pos) {
                                        *pos = '\0';
                                        /* keep group or make empty if not existent */
                                        if (!ln->key.group) {
                                                ln->key.group = estrdup("");
                                        }
                                        if (ln->key.name) {
                                                efree(ln->key.name);
                                        }
                                        ln->key.name = etrim(fline);
                                        ln->val.value = etrim(pos+1);
                                        ln->pos = php_stream_tell(dba->fp);
                                        efree(fline);
                                        return 1;
                                } else {
                                        /* simply ignore lines without '='
                                         * those should be comments
                                         */
                                         efree(fline);
                                         continue;
                                }
                        }
                }
        }
        inifile_line_free(ln);
        return 0;
}
/* }}} */

/* {{{ inifile_key_cmp */
/* 0 = EQUAL
 * 1 = GROUP-EQUAL,NAME-DIFFERENT
 * 2 = DIFFERENT
 */
static int inifile_key_cmp(const key_type *k1, const key_type *k2 TSRMLS_DC)
{
        assert(k1->group && k1->name && k2->group && k2->name);
        
        if (!strcmp(k1->group, k2->group)) {
                if (!strcmp(k1->name, k2->name)) {
                        return 0;
                } else {
                        return 1;
                }
        } else {
                return 2;
        }
}
/* }}} */

/* {{{ inifile_fetch
 */
val_type inifile_fetch(inifile *dba, const key_type *key, int skip TSRMLS_DC) {
        line_type ln = {{NULL,NULL},{NULL}};
        val_type val;
        int res, grp_eq = 0;

        if (skip == -1) {
                if (dba->next.key.group && dba->next.key.name && 
!inifile_key_cmp(&dba->next.key, key TSRMLS_CC)) {
                        /* we got it already from last fetch */
                        val.value = estrdup(dba->next.val.value ? dba->next.val.value 
: "");
                        /* allow faster access by automatically getting next key */
                        php_stream_seek(dba->fp, dba->next.pos, SEEK_SET);
                        ln.key.group = estrdup(dba->next.key.group ? 
dba->next.key.group : "");
                        inifile_read(dba, &ln TSRMLS_CC);
                        inifile_line_free(&dba->next);
                        dba->next = ln;
                        return val;
                } else if (dba->curr.key.group && dba->curr.key.name && 
!inifile_key_cmp(&dba->curr.key, key TSRMLS_CC)) {
                        /* we got it already from firstkey/lastkey */
                        /* 
                         * this optimisation does not work when firstkey/nextkey found
                         * any instance other than the one instance wanted.
                         */
                        val.value = estrdup(dba->curr.val.value ? dba->curr.val.value 
: "");
                        /* allow faster access by automatically getting next key 
                         * we must use the line pointer 'next' since we cannot change 
the 
                         * line pointer of firstkey/nextkey
                         */
                        php_stream_seek(dba->fp, dba->curr.pos, SEEK_SET);
                        ln.key.group = estrdup(dba->curr.key.group ? 
dba->curr.key.group : "");
                        inifile_read(dba, &ln TSRMLS_CC);
                        inifile_line_free(&dba->next);
                        dba->next = ln;
                        return val;
                }
        }

        /* the slow way: restart and seacrch */
        if (skip != -1 || !dba->next.key.group || !dba->next.key.name || 
inifile_key_cmp(&dba->next.key, key TSRMLS_CC)) {
                /* specific instance or not same key -> restart search */
                php_stream_rewind(dba->fp);
        }
        inifile_line_free(&dba->next);
        if (skip == -1) {
                skip = 0;
        }
        while(inifile_read(dba, &ln TSRMLS_CC)) {
                if (!(res=inifile_key_cmp(&ln.key, key TSRMLS_CC))) {
                        if (!skip) {
                                val.value = estrdup(ln.val.value ? ln.val.value : "");
                                /* allow faster access by automatically getting next 
key */
                                inifile_read(dba, &ln TSRMLS_CC);
                                inifile_line_free(&dba->next);
                                dba->next = ln;
                                return val;
                        }
                        skip--;
                } else if (res == 1) {
                        grp_eq = 1;
                } else if (grp_eq) {
                        /* we are leaving group now: that means we cannot find the key 
*/
                        break;
                }
        }
        inifile_line_free(&ln);
        inifile_line_free(&dba->next);
        return ln.val;
}
/* }}} */

/* {{{ inifile_firstkey
 */
int inifile_firstkey(inifile *dba TSRMLS_DC) {
        inifile_line_free(&dba->curr);
        dba->curr.pos = 0;
        return inifile_nextkey(dba TSRMLS_CC);
}
/* }}} */

/* {{{ inifile_nextkey
 */
int inifile_nextkey(inifile *dba TSRMLS_DC) {
        line_type ln = {{NULL,NULL},{NULL}};

        /*inifile_line_free(&dba->next); ??? */
        php_stream_seek(dba->fp, dba->curr.pos, SEEK_SET);
        ln.key.group = estrdup(dba->curr.key.group ? dba->curr.key.group : "");
        inifile_read(dba, &ln TSRMLS_CC);
        inifile_line_free(&dba->curr);
        dba->curr = ln;
        return ln.key.group || ln.key.name;
}       
/* }}} */

/* {{{ inifile_truncate
 */
static int inifile_truncate(inifile *dba, size_t size TSRMLS_DC)
{
        int res;

        if ((res=ftruncate(dba->fd, size)) != 0) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error in ftruncate: %d", 
res);
                return FAILURE;
        }
        php_stream_seek(dba->fp, size, SEEK_SET);
        return SUCCESS;
}
/* }}} */

/* {{{ inifile_find_group
 * if found pos_grp_start points to "[group_name]"
 */
static int inifile_find_group(inifile *dba, const key_type *key, size_t *pos_grp_start 
TSRMLS_DC) 
{
        int ret = FAILURE;

        php_stream_flush(dba->fp);
        php_stream_seek(dba->fp, 0, SEEK_SET);
        inifile_line_free(&dba->curr);
        inifile_line_free(&dba->next);

        if (key->group && strlen(key->group)) {
                int res;
                line_type ln = {{NULL,NULL},{NULL}};

                res = 1;
                while(inifile_read(dba, &ln TSRMLS_CC)) {
                        if ((res=inifile_key_cmp(&ln.key, key TSRMLS_CC)) < 2) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found group: %d", *pos_grp_start);
                                ret = SUCCESS;
                                break;
                        }
                        *pos_grp_start = php_stream_tell(dba->fp);
                }
                inifile_line_free(&ln);
        } else {
                *pos_grp_start = 0;
                ret = SUCCESS;
        }
        if (ret == FAILURE) {
                *pos_grp_start = php_stream_tell(dba->fp);
        }
        return ret;
}
/* }}} */

/* {{{ inifile_next_group
 * only valid after a call to inifile_find_group
 * if any next group is found pos_grp_start points to "[group_name]" or whitespace 
before that
 */
static int inifile_next_group(inifile *dba, const key_type *key, size_t *pos_grp_start 
TSRMLS_DC) 
{
        int ret = FAILURE;
        line_type ln = {{NULL,NULL},{NULL}};

        *pos_grp_start = php_stream_tell(dba->fp);
        ln.key.group = estrdup(key->group);
        while(inifile_read(dba, &ln TSRMLS_CC)) {
                if (inifile_key_cmp(&ln.key, key TSRMLS_CC) == 2) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found next group: %d", *pos_grp_start);
                        ret = SUCCESS;
                        break;
                }
                *pos_grp_start = php_stream_tell(dba->fp);
        }
        inifile_line_free(&ln);
        return ret;
}
/* }}} */

/* {{{ inifile_copy_to
 */
static int inifile_copy_to(inifile *dba, size_t pos_start, size_t pos_end, inifile 
**ini_copy TSRMLS_DC)
{
        php_stream *fp;
        
        if (pos_start == pos_end) {
                *ini_copy = NULL;
                return SUCCESS;
        }
        if ((fp = php_stream_temp_create(0, 64 * 1024)) == NULL) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not create 
temporary stream");
                *ini_copy = NULL;
                return FAILURE;
        }

        if ((*ini_copy = inifile_alloc(fp, 1, 0 TSRMLS_CC)) == NULL) {
                /* writes error */
                return FAILURE;
        }
        php_stream_seek(dba->fp, pos_start, SEEK_SET);
        if (!php_stream_copy_to_stream(dba->fp, fp, pos_end - pos_start)) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not copy group [%d 
- %d] to temporary stream", pos_start, pos_end);
                return FAILURE;
        } 
        return SUCCESS;
}
/* }}} */

/* {{{ inifile_filter
 * copy from to dba while ignoring key name (group must equal)
 */
static int inifile_filter(inifile *dba, inifile *from, const key_type *key TSRMLS_DC) 
{
        size_t pos_start = 0, pos_next = 0, pos_curr;
        int ret = SUCCESS;
        line_type ln = {{NULL,NULL},{NULL}};

        php_stream_seek(from->fp, 0, SEEK_SET);
        php_stream_seek(dba->fp, 0, SEEK_END);
        while(inifile_read(from, &ln TSRMLS_CC)) {
                switch(inifile_key_cmp(&ln.key, key TSRMLS_CC)) {
                case 0:
                        pos_curr = php_stream_tell(from->fp);
                        if (pos_start != pos_next) {
                                php_stream_seek(from->fp, pos_start, SEEK_SET);
                                if (!php_stream_copy_to_stream(from->fp, dba->fp, 
pos_next - pos_start)) {
                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, 
"Could not copy [%d - %d] from temporary stream", pos_next, pos_start);
                                        ret = FAILURE;
                                }
                                php_stream_seek(from->fp, pos_curr, SEEK_SET);
                        }
                        pos_next = pos_start = pos_curr;
                        break;
                case 1:
                        pos_next = php_stream_tell(from->fp);
                        break;
                case 2:
                        /* the function is meant to process only entries from same 
group */
                        assert(0);
                        break;
                }
        }
        if (pos_start != pos_next) {
                php_stream_seek(from->fp, pos_start, SEEK_SET);
                if (!php_stream_copy_to_stream(from->fp, dba->fp, pos_next - 
pos_start)) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not copy 
[%d - %d] from temporary stream", pos_next, pos_start);
                        ret = FAILURE;
                }
        }
        inifile_line_free(&ln);
        return SUCCESS;
}
/* }}} */

/* {{{ inifile_delete_replace_append
 */
static int inifile_delete_replace_append(inifile *dba, const key_type *key, const 
val_type *value, int append TSRMLS_DC) 
{
        size_t pos_grp_start, pos_grp_next;
        inifile *ini_tmp = NULL;
        php_stream *fp_tmp = NULL;
        int ret;

        /* 1) Search group start
         * 2) Search next group
         * 3) If not append: Copy group to ini_tmp
         * 4) Open temp_stream and copy remainder
         * 5) Truncate stream
         * 6) If not append AND key.name given: Filtered copy back from ini_tmp 
         *    to stream. Otherwise the user wanted to delete the group.
         * 7) Append value if given
         * 8) Append temporary stream
         */

        assert(!append || (key->name && value)); /* missuse */

        /* 1 - 3 */
        inifile_find_group(dba, key, &pos_grp_start TSRMLS_CC);
        inifile_next_group(dba, key, &pos_grp_next TSRMLS_CC);
        if (append) {
                ret = SUCCESS;
        } else {
                ret = inifile_copy_to(dba, pos_grp_start, pos_grp_next, &ini_tmp 
TSRMLS_CC);
        }

        /* 4 */
        if (ret == SUCCESS) {
                fp_tmp = php_stream_temp_create(0, 64 * 1024);
                if (!fp_tmp) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not create 
temporary stream");
                        ret = FAILURE;
                } else {
                        php_stream_seek(dba->fp, 0, SEEK_END);
                        if (pos_grp_next != php_stream_tell(dba->fp)) {
                                php_stream_seek(dba->fp, pos_grp_next, SEEK_SET);
                                if (!php_stream_copy_to_stream(dba->fp, fp_tmp, 
PHP_STREAM_COPY_ALL)) {
                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, 
"Could not copy remainder to temporary stream");
                                        ret = FAILURE;
                                }
                        }
                }
        }
        
        /* 5 */
        if (ret == SUCCESS) {
                ret = inifile_truncate(dba, append ? pos_grp_next : pos_grp_start 
TSRMLS_CC); /* writes error on fail */
        }

        if (ret == SUCCESS) {
                if (key->name && strlen(key->name)) {
                        /* 6 */
                        if (!append && ini_tmp) {
                                ret = inifile_filter(dba, ini_tmp, key TSRMLS_CC);
                        }

                        /* 7 */
                        /* important: do not query ret==SUCCESS again: inifile_filter 
might fail but
                         * however next operation must be done.
                         */
                        if (value) {
                                if (pos_grp_start == pos_grp_next && key->group && 
strlen(key->group)) {
                                        php_stream_printf(dba->fp TSRMLS_CC, "[%s]\n", 
key->group);
                                }
                                php_stream_printf(dba->fp TSRMLS_CC, "%s=%s\n", 
key->name, value->value ? value->value : "");
                        }
                }
                
                /* 8 */ 
                /* important: do not query ret==SUCCESS again: inifile_filter might 
fail but
                 * however next operation must be done.
                 */
                if (fp_tmp && php_stream_tell(fp_tmp)) {
                        php_stream_seek(fp_tmp, 0, SEEK_SET);
                        php_stream_seek(dba->fp, 0, SEEK_END);
                        if (!php_stream_copy_to_stream(fp_tmp, dba->fp, 
PHP_STREAM_COPY_ALL)) {
                                php_error_docref(NULL TSRMLS_CC, E_ERROR, "Could not 
copy from temporary stream - ini file truncated");
                                ret = FAILURE;
                        }
                }
        }

        if (ini_tmp) {
                php_stream_close(ini_tmp->fp);
                inifile_free(ini_tmp, 0);
        }
        if (fp_tmp) {
                php_stream_close(fp_tmp);
        }
        php_stream_flush(dba->fp);
        php_stream_seek(dba->fp, 0, SEEK_SET);

        return ret;
}
/* }}} */

/* {{{ inifile_delete
 */
int inifile_delete(inifile *dba, const key_type *key TSRMLS_DC) 
{
        return inifile_delete_replace_append(dba, key, NULL, 0 TSRMLS_CC);
}       
/* }}} */

/* {{{ inifile_relace
 */
int inifile_replace(inifile *dba, const key_type *key, const val_type *value 
TSRMLS_DC) 
{
        return inifile_delete_replace_append(dba, key, value, 0 TSRMLS_CC);
}
/* }}} */

/* {{{ inifile_append
 */
int inifile_append(inifile *dba, const key_type *key, const val_type *value TSRMLS_DC) 
{
        return inifile_delete_replace_append(dba, key, value, 1 TSRMLS_CC);
}
/* }}} */

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: sw=4 ts=4 fdm=marker
 * vim<600: sw=4 ts=4
 */

Index: php4/ext/dba/libinifile/inifile.h
+++ php4/ext/dba/libinifile/inifile.h
/*
   +----------------------------------------------------------------------+
   | PHP Version 4                                                        |
   +----------------------------------------------------------------------+
   | Copyright (c) 1997-2003 The PHP Group                                |
   +----------------------------------------------------------------------+
   | This source file is subject to version 2.02 of the PHP license,      |
   | that is bundled with this package in the file LICENSE, and is        |
   | available at through the world-wide-web at                           |
   | http://www.php.net/license/2_02.txt.                                 |
   | If you did not receive a copy of the PHP license and are unable to   |
   | obtain it through the world-wide-web, please send a note to          |
   | [EMAIL PROTECTED] so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
   | Author: Marcus Boerger <[EMAIL PROTECTED]>                               |
   +----------------------------------------------------------------------+
 */

/* $Id: inifile.h,v 1.1 2003/02/22 17:20:05 helly Exp $ */

#ifndef PHP_LIB_INIFILE_H
#define PHP_LIB_INIFILE_H

typedef struct {
        char *group;
        char *name;
} key_type;

typedef struct {
        char *value;
} val_type;

typedef struct {
        key_type key;
        val_type val;
        size_t pos;
} line_type;

typedef struct {
        char *lockfn;
        int lockfd;
        php_stream *fp;
        int fd;
        int readonly;
        line_type curr;
        line_type next;
} inifile;

val_type inifile_fetch(inifile *dba, const key_type *key, int skip TSRMLS_DC);
int inifile_firstkey(inifile *dba TSRMLS_DC);
int inifile_nextkey(inifile *dba TSRMLS_DC);
int inifile_delete(inifile *dba, const key_type *key TSRMLS_DC);
int inifile_replace(inifile *dba, const key_type *key, const val_type *val TSRMLS_DC);
int inifile_append(inifile *dba, const key_type *key, const val_type *val TSRMLS_DC);
char *inifile_version();

key_type inifile_key_split(const char *group_name);
char * inifile_key_string(const key_type *key);

void inifile_key_free(key_type *key);
void inifile_val_free(val_type *val);
void inifile_line_free(line_type *ln);

inifile * inifile_alloc(php_stream *fp, int readonly, int persistent TSRMLS_DC);
void inifile_free(inifile *dba, int persistent);

#endif

Index: php4/ext/dba/tests/dba_inifile.phpt
+++ php4/ext/dba/tests/dba_inifile.phpt
--TEST--
DBA INIFILE handler test
--SKIPIF--
<?php 
        require_once('skipif.inc');
        if (!in_array('inifile', dba_handlers())) die('skip INIFILE handler not 
available');
?>
--FILE--
<?php
        require_once('test.inc');
        $handler = 'inifile';
        require_once('dba_handler.inc');
?>
--EXPECT--
database handler: inifile
3NYNYY
Content String 2
Content 2 replaced
Read during write: not allowed
Content 2 replaced 2nd time
The 6th value
array(3) {
  ["key number 6"]=>
  string(13) "The 6th value"
  ["key2"]=>
  string(27) "Content 2 replaced 2nd time"
  ["key5"]=>
  string(23) "The last content string"
}
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to