root/ext/dba/dba.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. php_dba_make_key
  2. dba_close
  3. dba_close_rsrc
  4. dba_close_pe_rsrc_deleter
  5. dba_close_pe_rsrc
  6. ZEND_INI_MH
  7. PHP_INI_BEGIN
  8. PHP_MINIT_FUNCTION
  9. PHP_MSHUTDOWN_FUNCTION
  10. PHP_MINFO_FUNCTION
  11. php_dba_update
  12. php_dba_find
  13. php_dba_open
  14. PHP_FUNCTION
  15. PHP_FUNCTION
  16. PHP_FUNCTION
  17. PHP_FUNCTION
  18. PHP_FUNCTION
  19. PHP_FUNCTION
  20. PHP_FUNCTION
  21. PHP_FUNCTION
  22. PHP_FUNCTION
  23. PHP_FUNCTION
  24. PHP_FUNCTION
  25. PHP_FUNCTION
  26. PHP_FUNCTION
  27. PHP_FUNCTION
  28. PHP_FUNCTION

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 5                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP license,      |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Authors: Sascha Schumann <sascha@schumann.cx>                        |
  16    |          Marcus Boerger <helly@php.net>                              |
  17    +----------------------------------------------------------------------+
  18  */
  19 
  20 /* $Id$ */
  21 
  22 #ifdef HAVE_CONFIG_H
  23 #include "config.h"
  24 #endif
  25 
  26 #include "php.h"
  27 
  28 #if HAVE_DBA
  29 
  30 #include "php_ini.h"
  31 #include <stdio.h> 
  32 #include <fcntl.h>
  33 #ifdef HAVE_SYS_FILE_H
  34 #include <sys/file.h>
  35 #endif
  36  
  37 #include "php_dba.h"
  38 #include "ext/standard/info.h"
  39 #include "ext/standard/php_string.h"
  40 #include "ext/standard/flock_compat.h"
  41 
  42 #include "php_gdbm.h"
  43 #include "php_ndbm.h"
  44 #include "php_dbm.h"
  45 #include "php_cdb.h"
  46 #include "php_db1.h"
  47 #include "php_db2.h"
  48 #include "php_db3.h"
  49 #include "php_db4.h"
  50 #include "php_flatfile.h"
  51 #include "php_inifile.h"
  52 #include "php_qdbm.h"
  53 #include "php_tcadb.h"
  54 
  55 /* {{{ arginfo */
  56 ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_popen, 0, 0, 2)
  57         ZEND_ARG_INFO(0, path)
  58         ZEND_ARG_INFO(0, mode)
  59         ZEND_ARG_INFO(0, handlername)
  60         ZEND_ARG_VARIADIC_INFO(0, handler_parameters)
  61 ZEND_END_ARG_INFO()
  62 
  63 ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_open, 0, 0, 2)
  64         ZEND_ARG_INFO(0, path)
  65         ZEND_ARG_INFO(0, mode)
  66         ZEND_ARG_INFO(0, handlername)
  67         ZEND_ARG_VARIADIC_INFO(0, handler_parameters)
  68 ZEND_END_ARG_INFO()
  69 
  70 ZEND_BEGIN_ARG_INFO(arginfo_dba_close, 0)
  71         ZEND_ARG_INFO(0, handle)
  72 ZEND_END_ARG_INFO()
  73 
  74 ZEND_BEGIN_ARG_INFO(arginfo_dba_exists, 0)
  75         ZEND_ARG_INFO(0, key)
  76         ZEND_ARG_INFO(0, handle)
  77 ZEND_END_ARG_INFO()
  78 
  79 ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_fetch, 0, 0, 2)
  80         ZEND_ARG_INFO(0, key)
  81         ZEND_ARG_INFO(0, skip)
  82         ZEND_ARG_INFO(0, handle)
  83 ZEND_END_ARG_INFO()
  84 
  85 ZEND_BEGIN_ARG_INFO(arginfo_dba_key_split, 0)
  86         ZEND_ARG_INFO(0, key)
  87 ZEND_END_ARG_INFO()
  88 
  89 ZEND_BEGIN_ARG_INFO(arginfo_dba_firstkey, 0)
  90         ZEND_ARG_INFO(0, handle)
  91 ZEND_END_ARG_INFO()
  92 
  93 ZEND_BEGIN_ARG_INFO(arginfo_dba_nextkey, 0)
  94         ZEND_ARG_INFO(0, handle)
  95 ZEND_END_ARG_INFO()
  96 
  97 ZEND_BEGIN_ARG_INFO(arginfo_dba_delete, 0)
  98         ZEND_ARG_INFO(0, key)
  99         ZEND_ARG_INFO(0, handle)
 100 ZEND_END_ARG_INFO()
 101 
 102 ZEND_BEGIN_ARG_INFO(arginfo_dba_insert, 0)
 103         ZEND_ARG_INFO(0, key)
 104         ZEND_ARG_INFO(0, value)
 105         ZEND_ARG_INFO(0, handle)
 106 ZEND_END_ARG_INFO()
 107 
 108 ZEND_BEGIN_ARG_INFO(arginfo_dba_replace, 0)
 109         ZEND_ARG_INFO(0, key)
 110         ZEND_ARG_INFO(0, value)
 111         ZEND_ARG_INFO(0, handle)
 112 ZEND_END_ARG_INFO()
 113 
 114 ZEND_BEGIN_ARG_INFO(arginfo_dba_optimize, 0)
 115         ZEND_ARG_INFO(0, handle)
 116 ZEND_END_ARG_INFO()
 117 
 118 ZEND_BEGIN_ARG_INFO(arginfo_dba_sync, 0)
 119         ZEND_ARG_INFO(0, handle)
 120 ZEND_END_ARG_INFO()
 121 
 122 ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_handlers, 0, 0, 0)
 123         ZEND_ARG_INFO(0, full_info)
 124 ZEND_END_ARG_INFO()
 125 
 126 ZEND_BEGIN_ARG_INFO(arginfo_dba_list, 0)
 127 ZEND_END_ARG_INFO()
 128 
 129 /* }}} */
 130 
 131 /* {{{ dba_functions[]
 132  */
 133 const zend_function_entry dba_functions[] = {
 134         PHP_FE(dba_open, arginfo_dba_open)
 135         PHP_FE(dba_popen, arginfo_dba_popen)
 136         PHP_FE(dba_close, arginfo_dba_close)
 137         PHP_FE(dba_delete, arginfo_dba_delete)
 138         PHP_FE(dba_exists, arginfo_dba_exists)
 139         PHP_FE(dba_fetch, arginfo_dba_fetch)
 140         PHP_FE(dba_insert, arginfo_dba_insert)
 141         PHP_FE(dba_replace, arginfo_dba_replace)
 142         PHP_FE(dba_firstkey, arginfo_dba_firstkey)
 143         PHP_FE(dba_nextkey, arginfo_dba_nextkey)
 144         PHP_FE(dba_optimize, arginfo_dba_optimize)
 145         PHP_FE(dba_sync, arginfo_dba_sync)
 146         PHP_FE(dba_handlers, arginfo_dba_handlers)
 147         PHP_FE(dba_list, arginfo_dba_list)
 148         PHP_FE(dba_key_split, arginfo_dba_key_split)
 149         PHP_FE_END
 150 };
 151 /* }}} */
 152 
 153 PHP_MINIT_FUNCTION(dba);
 154 PHP_MSHUTDOWN_FUNCTION(dba);
 155 PHP_MINFO_FUNCTION(dba);
 156 
 157 ZEND_BEGIN_MODULE_GLOBALS(dba)
 158         char *default_handler;
 159         dba_handler *default_hptr;
 160 ZEND_END_MODULE_GLOBALS(dba) 
 161 
 162 ZEND_DECLARE_MODULE_GLOBALS(dba)
 163 
 164 #ifdef ZTS
 165 #define DBA_G(v) TSRMG(dba_globals_id, zend_dba_globals *, v)
 166 #else
 167 #define DBA_G(v) (dba_globals.v)
 168 #endif 
 169 
 170 static PHP_GINIT_FUNCTION(dba);
 171 
 172 zend_module_entry dba_module_entry = {
 173         STANDARD_MODULE_HEADER,
 174         "dba",
 175         dba_functions, 
 176         PHP_MINIT(dba), 
 177         PHP_MSHUTDOWN(dba),
 178         NULL,
 179         NULL,
 180         PHP_MINFO(dba),
 181         NO_VERSION_YET,
 182         PHP_MODULE_GLOBALS(dba),
 183         PHP_GINIT(dba),
 184         NULL,
 185         NULL,
 186         STANDARD_MODULE_PROPERTIES_EX
 187 };
 188 
 189 #ifdef COMPILE_DL_DBA
 190 ZEND_GET_MODULE(dba)
 191 #endif
 192 
 193 /* {{{ macromania */
 194 
 195 #define DBA_ID_PARS                                                                                     \
 196         zval *id;                                                                                                       \
 197         dba_info *info = NULL;                                                                          \
 198         int ac = ZEND_NUM_ARGS()
 199 
 200 /* these are used to get the standard arguments */
 201 
 202 /* {{{ php_dba_myke_key */
 203 static size_t php_dba_make_key(zval *key, char **key_str, char **key_free TSRMLS_DC)
 204 {
 205         if (Z_TYPE_P(key) == IS_ARRAY) {
 206                 zval **group, **name;
 207                 HashPosition pos;
 208                 size_t len;
 209         
 210                 if (zend_hash_num_elements(Z_ARRVAL_P(key)) != 2) {
 211                         php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Key does not have exactly two elements: (key, name)");
 212                         return -1;
 213                 }
 214                 zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(key), &pos);
 215                 zend_hash_get_current_data_ex(Z_ARRVAL_P(key), (void **) &group, &pos);
 216                 zend_hash_move_forward_ex(Z_ARRVAL_P(key), &pos);
 217                 zend_hash_get_current_data_ex(Z_ARRVAL_P(key), (void **) &name, &pos);
 218                 convert_to_string_ex(group);
 219                 convert_to_string_ex(name);
 220                 if (Z_STRLEN_PP(group) == 0) {
 221                         *key_str = Z_STRVAL_PP(name);
 222                         *key_free = NULL;
 223                         return Z_STRLEN_PP(name);
 224                 }
 225                 len = spprintf(key_str, 0, "[%s]%s", Z_STRVAL_PP(group), Z_STRVAL_PP(name));
 226                 *key_free = *key_str;
 227                 return len;
 228         } else {
 229                 zval tmp = *key;
 230                 int len;
 231 
 232                 zval_copy_ctor(&tmp);
 233                 convert_to_string(&tmp);
 234 
 235                 *key_free = *key_str = estrndup(Z_STRVAL(tmp), Z_STRLEN(tmp));
 236                 len = Z_STRLEN(tmp);
 237 
 238                 zval_dtor(&tmp);
 239                 return len;
 240         }
 241 }
 242 /* }}} */
 243 
 244 #define DBA_GET2                                                                                                \
 245         zval *key;                                                                                                      \
 246         char *key_str, *key_free;                                                                       \
 247         size_t key_len;                                                                                         \
 248         if (zend_parse_parameters(ac TSRMLS_CC, "zr", &key, &id) == FAILURE) {  \
 249                 return;                                                                                                 \
 250         }                                                                                                                       \
 251         if ((key_len = php_dba_make_key(key, &key_str, &key_free TSRMLS_CC)) == 0) {\
 252                 RETURN_FALSE;                                                                                   \
 253         }
 254 
 255 #define DBA_GET2_3                                                                                              \
 256         zval *key;                                                                                                      \
 257         char *key_str, *key_free;                                                                       \
 258         size_t key_len;                                                                                         \
 259         long skip = 0;                                                                                          \
 260         switch(ac) {                                                                                            \
 261         case 2:                                                                                                         \
 262                 if (zend_parse_parameters(ac TSRMLS_CC, "zr", &key, &id) == FAILURE) { \
 263                         return;                                                                                         \
 264                 }                                                                                                               \
 265                 break;                                                                                                  \
 266         case 3:                                                                                                         \
 267                 if (zend_parse_parameters(ac TSRMLS_CC, "zlr", &key, &skip, &id) == FAILURE) { \
 268                         return;                                                                                         \
 269                 }                                                                                                               \
 270                 break;                                                                                                  \
 271         default:                                                                                                        \
 272                 WRONG_PARAM_COUNT;                                                                              \
 273         }                                                                                                                       \
 274         if ((key_len = php_dba_make_key(key, &key_str, &key_free TSRMLS_CC)) == 0) {\
 275                 RETURN_FALSE;                                                                                   \
 276         }
 277 
 278 
 279 #define DBA_FETCH_RESOURCE(info, id)    \
 280         ZEND_FETCH_RESOURCE2(info, dba_info *, id, -1, "DBA identifier", le_db, le_pdb);
 281 
 282 #define DBA_ID_GET2   DBA_ID_PARS; DBA_GET2;   DBA_FETCH_RESOURCE(info, &id)
 283 #define DBA_ID_GET2_3 DBA_ID_PARS; DBA_GET2_3; DBA_FETCH_RESOURCE(info, &id)
 284 
 285 #define DBA_ID_DONE                                                                                             \
 286         if (key_free) efree(key_free)
 287 /* a DBA handler must have specific routines */
 288 
 289 #define DBA_NAMED_HND(alias, name, flags) \
 290 {\
 291         #alias, flags, dba_open_##name, dba_close_##name, dba_fetch_##name, dba_update_##name, \
 292         dba_exists_##name, dba_delete_##name, dba_firstkey_##name, dba_nextkey_##name, \
 293         dba_optimize_##name, dba_sync_##name, dba_info_##name \
 294 },
 295 
 296 #define DBA_HND(name, flags) DBA_NAMED_HND(name, name, flags)
 297 
 298 /* check whether the user has write access */
 299 #define DBA_WRITE_CHECK \
 300         if(info->mode != DBA_WRITER && info->mode != DBA_TRUNC && info->mode != DBA_CREAT) { \
 301                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "You cannot perform a modification to a database without proper access"); \
 302                 RETURN_FALSE; \
 303         }
 304 
 305 /* the same check, but with a call to DBA_ID_DONE before returning */
 306 #define DBA_WRITE_CHECK_WITH_ID \
 307         if(info->mode != DBA_WRITER && info->mode != DBA_TRUNC && info->mode != DBA_CREAT) { \
 308                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "You cannot perform a modification to a database without proper access"); \
 309                 DBA_ID_DONE; \
 310                 RETURN_FALSE; \
 311         }
 312 
 313 /* }}} */
 314 
 315 /* {{{ globals */
 316 
 317 static dba_handler handler[] = {
 318 #if DBA_GDBM
 319         DBA_HND(gdbm, DBA_LOCK_EXT) /* Locking done in library if set */
 320 #endif
 321 #if DBA_DBM
 322         DBA_HND(dbm, DBA_LOCK_ALL) /* No lock in lib */
 323 #endif
 324 #if DBA_NDBM
 325         DBA_HND(ndbm, DBA_LOCK_ALL) /* Could be done in library: filemode = 0644 + S_ENFMT */
 326 #endif
 327 #if DBA_CDB
 328         DBA_HND(cdb, DBA_STREAM_OPEN|DBA_LOCK_ALL) /* No lock in lib */
 329 #endif
 330 #if DBA_CDB_BUILTIN
 331     DBA_NAMED_HND(cdb_make, cdb, DBA_STREAM_OPEN|DBA_LOCK_ALL) /* No lock in lib */
 332 #endif
 333 #if DBA_DB1
 334         DBA_HND(db1, DBA_LOCK_ALL) /* No lock in lib */
 335 #endif
 336 #if DBA_DB2
 337         DBA_HND(db2, DBA_LOCK_ALL) /* No lock in lib */
 338 #endif
 339 #if DBA_DB3
 340         DBA_HND(db3, DBA_LOCK_ALL) /* No lock in lib */
 341 #endif
 342 #if DBA_DB4
 343         DBA_HND(db4, DBA_LOCK_ALL) /* No lock in lib */
 344 #endif
 345 #if DBA_INIFILE
 346         DBA_HND(inifile, DBA_STREAM_OPEN|DBA_LOCK_ALL|DBA_CAST_AS_FD) /* No lock in lib */
 347 #endif
 348 #if DBA_FLATFILE
 349         DBA_HND(flatfile, DBA_STREAM_OPEN|DBA_LOCK_ALL|DBA_NO_APPEND) /* No lock in lib */
 350 #endif
 351 #if DBA_QDBM
 352         DBA_HND(qdbm, DBA_LOCK_EXT)
 353 #endif
 354 #if DBA_TCADB
 355         DBA_HND(tcadb, DBA_LOCK_ALL)
 356 #endif
 357         { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
 358 };
 359 
 360 #if DBA_FLATFILE
 361 #define DBA_DEFAULT "flatfile"
 362 #elif DBA_DB4
 363 #define DBA_DEFAULT "db4"
 364 #elif DBA_DB3
 365 #define DBA_DEFAULT "db3"
 366 #elif DBA_DB2
 367 #define DBA_DEFAULT "db2"
 368 #elif DBA_DB1
 369 #define DBA_DEFAULT "db1"
 370 #elif DBA_GDBM
 371 #define DBA_DEFAULT "gdbm"
 372 #elif DBA_NBBM
 373 #define DBA_DEFAULT "ndbm"
 374 #elif DBA_DBM
 375 #define DBA_DEFAULT "dbm"
 376 #elif DBA_QDBM
 377 #define DBA_DEFAULT "qdbm"
 378 #elif DBA_TCADB
 379 #define DBA_DEFAULT "tcadb"
 380 #else
 381 #define DBA_DEFAULT ""
 382 #endif
 383 /* cdb/cdb_make and ini are no option here */
 384 
 385 static int le_db;
 386 static int le_pdb;
 387 /* }}} */
 388 
 389 /* {{{ dba_fetch_resource
 390 PHPAPI void dba_fetch_resource(dba_info **pinfo, zval **id TSRMLS_DC)
 391 {
 392         dba_info *info;
 393         DBA_ID_FETCH
 394         *pinfo = info;
 395 }
 396 */
 397 /* }}} */
 398 
 399 /* {{{ dba_get_handler
 400 PHPAPI dba_handler *dba_get_handler(const char* handler_name)
 401 {
 402         dba_handler *hptr;
 403         for (hptr = handler; hptr->name && strcasecmp(hptr->name, handler_name); hptr++);
 404         return hptr;
 405 }
 406 */
 407 /* }}} */
 408 
 409 /* {{{ dba_close 
 410  */ 
 411 static void dba_close(dba_info *info TSRMLS_DC)
 412 {
 413         if (info->hnd) {
 414                 info->hnd->close(info TSRMLS_CC);
 415         }
 416         if (info->path) {
 417                 pefree(info->path, info->flags&DBA_PERSISTENT);
 418         }
 419         if (info->fp && info->fp!=info->lock.fp) {
 420                 if(info->flags&DBA_PERSISTENT) {
 421                         php_stream_pclose(info->fp);
 422                 } else {
 423                         php_stream_close(info->fp);
 424                 }
 425         }
 426         if (info->lock.fp) {
 427                 if(info->flags&DBA_PERSISTENT) {
 428                         php_stream_pclose(info->lock.fp);
 429                 } else {
 430                         php_stream_close(info->lock.fp);
 431                 }
 432         }
 433         if (info->lock.name) {
 434                 pefree(info->lock.name, info->flags&DBA_PERSISTENT);
 435         }
 436         pefree(info, info->flags&DBA_PERSISTENT);
 437 }
 438 /* }}} */
 439 
 440 /* {{{ dba_close_rsrc
 441  */
 442 static void dba_close_rsrc(zend_rsrc_list_entry *rsrc TSRMLS_DC)
 443 {
 444         dba_info *info = (dba_info *)rsrc->ptr; 
 445 
 446         dba_close(info TSRMLS_CC);
 447 }
 448 /* }}} */
 449 
 450 /* {{{ dba_close_pe_rsrc_deleter */
 451 int dba_close_pe_rsrc_deleter(zend_rsrc_list_entry *le, void *pDba TSRMLS_DC)
 452 {
 453         return le->ptr == pDba;
 454 }
 455 /* }}} */
 456 
 457 /* {{{ dba_close_pe_rsrc */
 458 static void dba_close_pe_rsrc(zend_rsrc_list_entry *rsrc TSRMLS_DC)
 459 {
 460         dba_info *info = (dba_info *)rsrc->ptr; 
 461 
 462         /* closes the resource by calling dba_close_rsrc() */
 463         zend_hash_apply_with_argument(&EG(persistent_list), (apply_func_arg_t) dba_close_pe_rsrc_deleter, info TSRMLS_CC);
 464 }
 465 /* }}} */
 466 
 467 /* {{{ PHP_INI
 468  */
 469 ZEND_INI_MH(OnUpdateDefaultHandler)
 470 {
 471         dba_handler *hptr;
 472 
 473         if (!strlen(new_value)) {
 474                 DBA_G(default_hptr) = NULL;
 475                 return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
 476         }
 477 
 478         for (hptr = handler; hptr->name && strcasecmp(hptr->name, new_value); hptr++);
 479 
 480         if (!hptr->name) {
 481                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such handler: %s", new_value);
 482                 return FAILURE;
 483         }
 484         DBA_G(default_hptr) = hptr;
 485         return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
 486 }
 487 
 488 PHP_INI_BEGIN()
 489     STD_PHP_INI_ENTRY("dba.default_handler", DBA_DEFAULT, PHP_INI_ALL, OnUpdateDefaultHandler, default_handler,    zend_dba_globals, dba_globals)
 490 PHP_INI_END()
 491 /* }}} */
 492  
 493 /* {{{ PHP_GINIT_FUNCTION
 494  */
 495 static PHP_GINIT_FUNCTION(dba)
 496 {
 497         dba_globals->default_handler = "";
 498         dba_globals->default_hptr    = NULL;
 499 }
 500 /* }}} */
 501 
 502 /* {{{ PHP_MINIT_FUNCTION
 503  */
 504 PHP_MINIT_FUNCTION(dba)
 505 {
 506         REGISTER_INI_ENTRIES();
 507         le_db = zend_register_list_destructors_ex(dba_close_rsrc, NULL, "dba", module_number);
 508         le_pdb = zend_register_list_destructors_ex(dba_close_pe_rsrc, dba_close_rsrc, "dba persistent", module_number);
 509         return SUCCESS;
 510 }
 511 /* }}} */
 512 
 513 /* {{{ PHP_MSHUTDOWN_FUNCTION
 514  */
 515 PHP_MSHUTDOWN_FUNCTION(dba)
 516 {
 517         UNREGISTER_INI_ENTRIES();
 518         return SUCCESS;
 519 }
 520 /* }}} */
 521 
 522 #include "ext/standard/php_smart_str.h"
 523 
 524 /* {{{ PHP_MINFO_FUNCTION
 525  */
 526 PHP_MINFO_FUNCTION(dba)
 527 {
 528         dba_handler *hptr;
 529         smart_str handlers = {0};
 530 
 531         for(hptr = handler; hptr->name; hptr++) {
 532                 smart_str_appends(&handlers, hptr->name);
 533                 smart_str_appendc(&handlers, ' ');
 534         }
 535 
 536         php_info_print_table_start();
 537         php_info_print_table_row(2, "DBA support", "enabled");
 538         if (handlers.c) {
 539                 smart_str_0(&handlers);
 540                 php_info_print_table_row(2, "Supported handlers", handlers.c);
 541                 smart_str_free(&handlers);
 542         } else {
 543                 php_info_print_table_row(2, "Supported handlers", "none");
 544         }
 545         php_info_print_table_end();
 546         DISPLAY_INI_ENTRIES();
 547 }
 548 /* }}} */
 549 
 550 /* {{{ php_dba_update
 551  */
 552 static void php_dba_update(INTERNAL_FUNCTION_PARAMETERS, int mode)
 553 {
 554         int val_len;
 555         zval *id;
 556         dba_info *info = NULL;
 557         int ac = ZEND_NUM_ARGS();
 558         zval *key;
 559         char *val;
 560         char *key_str, *key_free;
 561         size_t key_len;
 562 
 563         if (zend_parse_parameters(ac TSRMLS_CC, "zsr", &key, &val, &val_len, &id) == FAILURE) {
 564                 return;
 565         }
 566 
 567         if ((key_len = php_dba_make_key(key, &key_str, &key_free TSRMLS_CC)) == 0) {
 568                 RETURN_FALSE;
 569         }
 570 
 571         DBA_FETCH_RESOURCE(info, &id);
 572 
 573         DBA_WRITE_CHECK_WITH_ID;
 574 
 575         if (info->hnd->update(info, key_str, key_len, val, val_len, mode TSRMLS_CC) == SUCCESS) {
 576                 DBA_ID_DONE;
 577                 RETURN_TRUE;
 578         }
 579 
 580         DBA_ID_DONE;
 581         RETURN_FALSE;
 582 }
 583 /* }}} */
 584 
 585 #define FREENOW if(args) efree(args); if(key) efree(key)
 586 
 587 /* {{{ php_find_dbm
 588  */
 589 dba_info *php_dba_find(const char* path TSRMLS_DC)
 590 {
 591         zend_rsrc_list_entry *le;
 592         dba_info *info;
 593         int numitems, i;
 594 
 595         numitems = zend_hash_next_free_element(&EG(regular_list));
 596         for (i=1; i<numitems; i++) {
 597                 if (zend_hash_index_find(&EG(regular_list), i, (void **) &le)==FAILURE) {
 598                         continue;
 599                 }
 600                 if (Z_TYPE_P(le) == le_db || Z_TYPE_P(le) == le_pdb) {
 601                         info = (dba_info *)(le->ptr);
 602                         if (!strcmp(info->path, path)) {
 603                                 return (dba_info *)(le->ptr);
 604                         }
 605                 }
 606         }
 607 
 608         return NULL;
 609 }
 610 /* }}} */
 611 
 612 /* {{{ php_dba_open
 613  */
 614 static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
 615 {
 616         zval ***args = (zval ***) NULL;
 617         int ac = ZEND_NUM_ARGS();
 618         dba_mode_t modenr;
 619         dba_info *info, *other;
 620         dba_handler *hptr;
 621         char *key = NULL, *error = NULL;
 622         int keylen = 0;
 623         int i;
 624         int lock_mode, lock_flag, lock_dbf = 0;
 625         char *file_mode;
 626         char mode[4], *pmode, *lock_file_mode = NULL;
 627         int persistent_flag = persistent ? STREAM_OPEN_PERSISTENT : 0;
 628         char *opened_path = NULL;
 629         char *lock_name;
 630         
 631         if(ac < 2) {
 632                 WRONG_PARAM_COUNT;
 633         }
 634         
 635         /* we pass additional args to the respective handler */
 636         args = safe_emalloc(ac, sizeof(zval *), 0);
 637         if (zend_get_parameters_array_ex(ac, args) != SUCCESS) {
 638                 FREENOW;
 639                 WRONG_PARAM_COUNT;
 640         }
 641                 
 642         /* we only take string arguments */
 643         for (i = 0; i < ac; i++) {
 644                 convert_to_string_ex(args[i]);
 645                 keylen += Z_STRLEN_PP(args[i]);
 646         }
 647 
 648         if (persistent) {
 649                 zend_rsrc_list_entry *le;
 650                 
 651                 /* calculate hash */
 652                 key = safe_emalloc(keylen, 1, 1);
 653                 key[keylen] = '\0';
 654                 keylen = 0;
 655                 
 656                 for(i = 0; i < ac; i++) {
 657                         memcpy(key+keylen, Z_STRVAL_PP(args[i]), Z_STRLEN_PP(args[i]));
 658                         keylen += Z_STRLEN_PP(args[i]);
 659                 }
 660 
 661                 /* try to find if we already have this link in our persistent list */
 662                 if (zend_hash_find(&EG(persistent_list), key, keylen+1, (void **) &le) == SUCCESS) {
 663                         FREENOW;
 664                         
 665                         if (Z_TYPE_P(le) != le_pdb) {
 666                                 RETURN_FALSE;
 667                         }
 668                 
 669                         info = (dba_info *)le->ptr;
 670 
 671                         ZEND_REGISTER_RESOURCE(return_value, info, le_pdb);
 672                         return;
 673                 }
 674         }
 675         
 676         if (ac==2) {
 677                 hptr = DBA_G(default_hptr);
 678                 if (!hptr) {
 679                         php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "No default handler selected");
 680                         FREENOW;
 681                         RETURN_FALSE;
 682                 }
 683         } else {
 684                 for (hptr = handler; hptr->name && strcasecmp(hptr->name, Z_STRVAL_PP(args[2])); hptr++);
 685         }
 686 
 687         if (!hptr->name) {
 688                 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]));
 689                 FREENOW;
 690                 RETURN_FALSE;
 691         }
 692 
 693         /* Check mode: [rwnc][fl]?t?
 694          * r: Read
 695          * w: Write
 696          * n: Create/Truncate
 697          * c: Create
 698          *
 699          * d: force lock on database file
 700          * l: force lock on lck file
 701          * -: ignore locking
 702          *
 703          * t: test open database, warning if locked
 704          */
 705         strlcpy(mode, Z_STRVAL_PP(args[1]), sizeof(mode));
 706         pmode = &mode[0];
 707         if (pmode[0] && (pmode[1]=='d' || pmode[1]=='l' || pmode[1]=='-')) { /* force lock on db file or lck file or disable locking */
 708                 switch (pmode[1]) {
 709                 case 'd':
 710                         lock_dbf = 1;
 711                         if ((hptr->flags & DBA_LOCK_ALL) == 0) {
 712                                 lock_flag = (hptr->flags & DBA_LOCK_ALL);
 713                                 break;
 714                         }
 715                         /* no break */
 716                 case 'l':
 717                         lock_flag = DBA_LOCK_ALL;
 718                         if ((hptr->flags & DBA_LOCK_ALL) == 0) {
 719                                 php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_NOTICE, "Handler %s does locking internally", hptr->name);
 720                         }
 721                         break;
 722                 default:
 723                 case '-':
 724                         if ((hptr->flags & DBA_LOCK_ALL) == 0) {
 725                                 php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Locking cannot be disabled for handler %s", hptr->name);
 726                                 FREENOW;
 727                                 RETURN_FALSE;
 728                         }
 729                         lock_flag = 0;
 730                         break;
 731                 }
 732         } else {
 733                 lock_flag = (hptr->flags&DBA_LOCK_ALL);
 734                 lock_dbf = 1;
 735         }
 736         switch (*pmode++) {
 737                 case 'r': 
 738                         modenr = DBA_READER; 
 739                         lock_mode = (lock_flag & DBA_LOCK_READER) ? LOCK_SH : 0;
 740                         file_mode = "r";
 741                         break;
 742                 case 'w': 
 743                         modenr = DBA_WRITER; 
 744                         lock_mode = (lock_flag & DBA_LOCK_WRITER) ? LOCK_EX : 0;
 745                         file_mode = "r+b";
 746                         break;
 747                 case 'c': 
 748                         modenr = DBA_CREAT; 
 749                         lock_mode = (lock_flag & DBA_LOCK_CREAT) ? LOCK_EX : 0;
 750                         if (lock_mode) {
 751                                 if (lock_dbf) {
 752                                         /* the create/append check will be done on the lock
 753                                          * when the lib opens the file it is already created
 754                                          */
 755                                         file_mode = "r+b";       /* read & write, seek 0 */
 756                                         lock_file_mode = "a+b";  /* append */
 757                                 } else {
 758                                         file_mode = "a+b";       /* append */
 759                                         lock_file_mode = "w+b";  /* create/truncate */
 760                                 }
 761                         } else {
 762                                 file_mode = "a+b";
 763                         }
 764                         /* In case of the 'a+b' append mode, the handler is responsible 
 765                          * to handle any rewind problems (see flatfile handler).
 766                          */
 767                         break;
 768                 case 'n':
 769                         modenr = DBA_TRUNC;
 770                         lock_mode = (lock_flag & DBA_LOCK_TRUNC) ? LOCK_EX : 0;
 771                         file_mode = "w+b";
 772                         break;
 773                 default:
 774                         php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Illegal DBA mode");
 775                         FREENOW;
 776                         RETURN_FALSE;
 777         }
 778         if (!lock_file_mode) {
 779                 lock_file_mode = file_mode;
 780         }
 781         if (*pmode=='d' || *pmode=='l' || *pmode=='-') {
 782                 pmode++; /* done already - skip here */
 783         }
 784         if (*pmode=='t') {
 785                 pmode++;
 786                 if (!lock_flag) {
 787                         php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "You cannot combine modifiers - (no lock) and t (test lock)");
 788                         FREENOW;
 789                         RETURN_FALSE;
 790                 }
 791                 if (!lock_mode) {
 792                         if ((hptr->flags & DBA_LOCK_ALL) == 0) {
 793                                 php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Handler %s uses its own locking which doesn't support mode modifier t (test lock)", hptr->name);
 794                                 FREENOW;
 795                                 RETURN_FALSE;
 796                         } else {
 797                                 php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Handler %s doesn't uses locking for this mode which makes modifier t (test lock) obsolete", hptr->name);
 798                                 FREENOW;
 799                                 RETURN_FALSE;
 800                         }
 801                 } else {
 802                         lock_mode |= LOCK_NB; /* test =: non blocking */
 803                 }
 804         }
 805         if (*pmode) {
 806                 php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Illegal DBA mode");
 807                 FREENOW;
 808                 RETURN_FALSE;
 809         }
 810                         
 811         info = pemalloc(sizeof(dba_info), persistent);
 812         memset(info, 0, sizeof(dba_info));
 813         info->path = pestrdup(Z_STRVAL_PP(args[0]), persistent);
 814         info->mode = modenr;
 815         info->argc = ac - 3;
 816         info->argv = args + 3;
 817         info->flags = (hptr->flags & ~DBA_LOCK_ALL) | (lock_flag & DBA_LOCK_ALL) | (persistent ? DBA_PERSISTENT : 0);
 818         info->lock.mode = lock_mode;
 819 
 820         /* if any open call is a locking call:
 821          * check if we already habe a locking call open that should block this call
 822          * the problem is some systems would allow read during write
 823          */
 824         if (hptr->flags & DBA_LOCK_ALL) {
 825                 if ((other = php_dba_find(info->path TSRMLS_CC)) != NULL) {
 826                         if (   ( (lock_mode&LOCK_EX)        && (other->lock.mode&(LOCK_EX|LOCK_SH)) )
 827                             || ( (other->lock.mode&LOCK_EX) && (lock_mode&(LOCK_EX|LOCK_SH))        )
 828                            ) {
 829                                 error = "Unable to establish lock (database file already open)"; /* force failure exit */
 830                         }
 831                 }
 832         }
 833 
 834         if (!error && lock_mode) {
 835                 if (lock_dbf) {
 836                         lock_name = Z_STRVAL_PP(args[0]);
 837                 } else {
 838                         spprintf(&lock_name, 0, "%s.lck", info->path);
 839                         if (!strcmp(file_mode, "r")) {
 840                                 /* when in read only mode try to use existing .lck file first */
 841                                 /* do not log errors for .lck file while in read ony mode on .lck file */
 842                                 lock_file_mode = "rb";
 843                                 info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|IGNORE_PATH|persistent_flag, &opened_path);
 844                         }
 845                         if (!info->lock.fp) {
 846                                 /* when not in read mode or failed to open .lck file read only. now try again in create(write) mode and log errors */
 847                                 lock_file_mode = "a+b";
 848                         } else {
 849                                 if (!persistent) {
 850                                         info->lock.name = opened_path;
 851                                 } else {
 852                                         if (opened_path) {
 853                                                 info->lock.name = pestrdup(opened_path, persistent);
 854                                                 efree(opened_path);
 855                                         }
 856                                 }
 857                         }
 858                 }
 859                 if (!info->lock.fp) {
 860                         info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, &opened_path);
 861                         if (info->lock.fp) {
 862                                 if (lock_dbf) {
 863                                         /* replace the path info with the real path of the opened file */
 864                                         pefree(info->path, persistent);
 865                                         info->path = pestrdup(opened_path, persistent);
 866                                 }
 867                                 /* now store the name of the lock */
 868                                 if (!persistent) {
 869                                         info->lock.name = opened_path;
 870                                 } else {
 871                                         info->lock.name = pestrdup(opened_path, persistent);
 872                                         efree(opened_path);
 873                                 }
 874                         }
 875                 }
 876                 if (!lock_dbf) {
 877                         efree(lock_name);
 878                 }
 879                 if (!info->lock.fp) {
 880                         dba_close(info TSRMLS_CC);
 881                         /* stream operation already wrote an error message */
 882                         FREENOW;
 883                         RETURN_FALSE;
 884                 }
 885                 if (!php_stream_supports_lock(info->lock.fp)) {
 886                         error = "Stream does not support locking";
 887                 }
 888                 if (php_stream_lock(info->lock.fp, lock_mode)) {
 889                         error = "Unable to establish lock"; /* force failure exit */
 890                 }
 891         }
 892 
 893         /* centralised open stream for builtin */
 894         if (!error && (hptr->flags&DBA_STREAM_OPEN)==DBA_STREAM_OPEN) {
 895                 if (info->lock.fp && lock_dbf) {
 896                         info->fp = info->lock.fp; /* use the same stream for locking and database access */
 897                 } else {
 898                         info->fp = php_stream_open_wrapper(info->path, file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, NULL);
 899                 }
 900                 if (!info->fp) {
 901                         dba_close(info TSRMLS_CC);
 902                         /* stream operation already wrote an error message */
 903                         FREENOW;
 904                         RETURN_FALSE;
 905                 }
 906                 if (hptr->flags & (DBA_NO_APPEND|DBA_CAST_AS_FD)) {
 907                         /* Needed because some systems do not allow to write to the original 
 908                          * file contents with O_APPEND being set.
 909                          */
 910                         if (SUCCESS != php_stream_cast(info->fp, PHP_STREAM_AS_FD, (void*)&info->fd, 1)) {
 911                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not cast stream");
 912                                 dba_close(info TSRMLS_CC);
 913                                 FREENOW;
 914                                 RETURN_FALSE;
 915 #ifdef F_SETFL
 916                         } else if (modenr == DBA_CREAT) {
 917                                 int flags = fcntl(info->fd, F_GETFL);
 918                                 fcntl(info->fd, F_SETFL, flags & ~O_APPEND);
 919 #endif
 920                         }
 921                                 
 922                 }
 923         }
 924 
 925         if (error || hptr->open(info, &error TSRMLS_CC) != SUCCESS) {
 926                 dba_close(info TSRMLS_CC);
 927                 php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Driver initialization failed for handler: %s%s%s", hptr->name, error?": ":"", error?error:"");
 928                 FREENOW;
 929                 RETURN_FALSE;
 930         }
 931 
 932         info->hnd = hptr;
 933         info->argc = 0;
 934         info->argv = NULL;
 935 
 936         if (persistent) {
 937                 zend_rsrc_list_entry new_le;
 938 
 939                 Z_TYPE(new_le) = le_pdb;
 940                 new_le.ptr = info;
 941                 if (zend_hash_update(&EG(persistent_list), key, keylen+1, &new_le, sizeof(zend_rsrc_list_entry), NULL) == FAILURE) {
 942                         dba_close(info TSRMLS_CC);
 943                         php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Could not register persistent resource");
 944                         FREENOW;
 945                         RETURN_FALSE;
 946                 }
 947         }
 948 
 949         ZEND_REGISTER_RESOURCE(return_value, info, (persistent ? le_pdb : le_db));
 950         FREENOW;
 951 }
 952 /* }}} */
 953 #undef FREENOW
 954 
 955 /* {{{ proto resource dba_popen(string path, string mode [, string handlername, string ...])
 956    Opens path using the specified handler in mode persistently */
 957 PHP_FUNCTION(dba_popen)
 958 {
 959         php_dba_open(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
 960 }
 961 /* }}} */
 962 
 963 /* {{{ proto resource dba_open(string path, string mode [, string handlername, string ...])
 964    Opens path using the specified handler in mode*/
 965 PHP_FUNCTION(dba_open)
 966 {
 967         php_dba_open(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
 968 }
 969 /* }}} */
 970 
 971 /* {{{ proto void dba_close(resource handle)
 972    Closes database */
 973 PHP_FUNCTION(dba_close)
 974 {
 975         zval *id;
 976         dba_info *info = NULL;
 977 
 978         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
 979                 return;
 980         }
 981 
 982         DBA_FETCH_RESOURCE(info, &id);
 983 
 984         zend_list_delete(Z_RESVAL_P(id));
 985 }
 986 /* }}} */
 987 
 988 /* {{{ proto bool dba_exists(string key, resource handle)
 989    Checks, if the specified key exists */
 990 PHP_FUNCTION(dba_exists)
 991 {
 992         DBA_ID_GET2;
 993 
 994         if(info->hnd->exists(info, key_str, key_len TSRMLS_CC) == SUCCESS) {
 995                 DBA_ID_DONE;
 996                 RETURN_TRUE;
 997         }
 998         DBA_ID_DONE;
 999         RETURN_FALSE;
1000 }
1001 /* }}} */
1002 
1003 /* {{{ proto string dba_fetch(string key, [int skip ,] resource handle)
1004    Fetches the data associated with key */
1005 PHP_FUNCTION(dba_fetch)
1006 {
1007         char *val;
1008         int len = 0;
1009         DBA_ID_GET2_3;
1010 
1011         if (ac==3) {
1012                 if (!strcmp(info->hnd->name, "cdb")) {
1013                         if (skip < 0) {
1014                                 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);
1015                                 skip = 0;
1016                         }
1017                 } else if (!strcmp(info->hnd->name, "inifile")) {
1018                         /* "-1" is compareable to 0 but allows a non restrictive 
1019                          * access which is fater. For example 'inifile' uses this
1020                          * to allow faster access when the key was already found
1021                          * using firstkey/nextkey. However explicitly setting the
1022                          * value to 0 ensures the first value. 
1023                          */
1024                         if (skip < -1) {
1025                                 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Handler %s accepts only skip value -1 and greater, using skip=0", info->hnd->name);
1026                                 skip = 0;
1027                         }
1028                 } else {
1029                         php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Handler %s does not support optional skip parameter, the value will be ignored", info->hnd->name);
1030                         skip = 0;                       
1031                 }
1032         } else {
1033                 skip = 0; 
1034         }
1035         if((val = info->hnd->fetch(info, key_str, key_len, skip, &len TSRMLS_CC)) != NULL) {
1036                 DBA_ID_DONE;
1037                 RETURN_STRINGL(val, len, 0);
1038         } 
1039         DBA_ID_DONE;
1040         RETURN_FALSE;
1041 }
1042 /* }}} */
1043 
1044 /* {{{ proto array|false dba_key_split(string key)
1045    Splits an inifile key into an array of the form array(0=>group,1=>value_name) but returns false if input is false or null */
1046 PHP_FUNCTION(dba_key_split)
1047 {
1048         zval *zkey;
1049         char *key, *name;
1050         int key_len;
1051 
1052         if (ZEND_NUM_ARGS() != 1) {
1053                 WRONG_PARAM_COUNT;
1054         }
1055         if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &zkey) == SUCCESS) {
1056                 if (Z_TYPE_P(zkey) == IS_NULL || (Z_TYPE_P(zkey) == IS_BOOL && !Z_LVAL_P(zkey))) {
1057                         RETURN_BOOL(0);
1058                 }
1059         }
1060         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) {
1061                 RETURN_BOOL(0);
1062         }
1063         array_init(return_value);
1064         if (key[0] == '[' && (name = strchr(key, ']')) != NULL) {
1065                 add_next_index_stringl(return_value, key+1, name - (key + 1), 1);
1066                 add_next_index_stringl(return_value, name+1, key_len - (name - key + 1), 1);
1067         } else {
1068                 add_next_index_stringl(return_value, "", 0, 1);
1069                 add_next_index_stringl(return_value, key, key_len, 1);
1070         }
1071 }
1072 /* }}} */
1073 
1074 /* {{{ proto string dba_firstkey(resource handle)
1075    Resets the internal key pointer and returns the first key */
1076 PHP_FUNCTION(dba_firstkey)
1077 {
1078         char *fkey;
1079         int len;
1080         zval *id;
1081         dba_info *info = NULL;
1082 
1083         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
1084                 return;
1085         }
1086 
1087         DBA_FETCH_RESOURCE(info, &id);
1088 
1089         fkey = info->hnd->firstkey(info, &len TSRMLS_CC);
1090 
1091         if (fkey)
1092                 RETURN_STRINGL(fkey, len, 0);
1093 
1094         RETURN_FALSE;
1095 }
1096 /* }}} */
1097 
1098 /* {{{ proto string dba_nextkey(resource handle)
1099    Returns the next key */
1100 PHP_FUNCTION(dba_nextkey)
1101 {
1102         char *nkey;
1103         int len;
1104         zval *id;
1105         dba_info *info = NULL;
1106 
1107         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
1108                 return;
1109         }
1110 
1111         DBA_FETCH_RESOURCE(info, &id);
1112 
1113         nkey = info->hnd->nextkey(info, &len TSRMLS_CC);
1114 
1115         if (nkey)
1116                 RETURN_STRINGL(nkey, len, 0);
1117 
1118         RETURN_FALSE;
1119 }
1120 /* }}} */
1121 
1122 /* {{{ proto bool dba_delete(string key, resource handle)
1123    Deletes the entry associated with key
1124    If inifile: remove all other key lines */
1125 PHP_FUNCTION(dba_delete)
1126 {
1127         DBA_ID_GET2;
1128         
1129         DBA_WRITE_CHECK_WITH_ID;
1130         
1131         if(info->hnd->delete(info, key_str, key_len TSRMLS_CC) == SUCCESS)
1132         {
1133                 DBA_ID_DONE;
1134                 RETURN_TRUE;
1135         }
1136         DBA_ID_DONE;
1137         RETURN_FALSE;
1138 }
1139 /* }}} */
1140 
1141 /* {{{ proto bool dba_insert(string key, string value, resource handle)
1142    If not inifile: Insert value as key, return false, if key exists already 
1143    If inifile: Add vakue as key (next instance of key) */
1144 PHP_FUNCTION(dba_insert)
1145 {
1146         php_dba_update(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1147 }
1148 /* }}} */
1149 
1150 /* {{{ proto bool dba_replace(string key, string value, resource handle)
1151    Inserts value as key, replaces key, if key exists already
1152    If inifile: remove all other key lines */
1153 PHP_FUNCTION(dba_replace)
1154 {
1155         php_dba_update(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1156 }
1157 /* }}} */
1158 
1159 /* {{{ proto bool dba_optimize(resource handle)
1160    Optimizes (e.g. clean up, vacuum) database */
1161 PHP_FUNCTION(dba_optimize)
1162 {
1163         zval *id;
1164         dba_info *info = NULL;
1165 
1166         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
1167                 return;
1168         }
1169 
1170         DBA_FETCH_RESOURCE(info, &id);
1171 
1172         DBA_WRITE_CHECK;
1173 
1174         if (info->hnd->optimize(info TSRMLS_CC) == SUCCESS) {
1175                 RETURN_TRUE;
1176         }
1177 
1178         RETURN_FALSE;
1179 }
1180 /* }}} */
1181 
1182 /* {{{ proto bool dba_sync(resource handle)
1183    Synchronizes database */
1184 PHP_FUNCTION(dba_sync)
1185 {
1186         zval *id;
1187         dba_info *info = NULL;
1188 
1189         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
1190                 return;
1191         }
1192 
1193         DBA_FETCH_RESOURCE(info, &id);
1194 
1195         if (info->hnd->sync(info TSRMLS_CC) == SUCCESS) {
1196                 RETURN_TRUE;
1197         }
1198 
1199         RETURN_FALSE;
1200 }
1201 /* }}} */
1202 
1203 /* {{{ proto array dba_handlers([bool full_info])
1204    List configured database handlers */
1205 PHP_FUNCTION(dba_handlers)
1206 {
1207         dba_handler *hptr;
1208         zend_bool full_info = 0;
1209 
1210         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &full_info) == FAILURE) {
1211                 RETURN_FALSE;
1212         }
1213 
1214         array_init(return_value);
1215 
1216         for(hptr = handler; hptr->name; hptr++) {
1217                 if (full_info) {
1218                         add_assoc_string(return_value, hptr->name, hptr->info(hptr, NULL TSRMLS_CC), 0);
1219                 } else {
1220                         add_next_index_string(return_value, hptr->name, 1);
1221                 }
1222         }
1223 }
1224 /* }}} */
1225 
1226 /* {{{ proto array dba_list()
1227    List opened databases */
1228 PHP_FUNCTION(dba_list)
1229 {
1230         ulong numitems, i;
1231         zend_rsrc_list_entry *le;
1232         dba_info *info;
1233 
1234         if (zend_parse_parameters_none() == FAILURE) {
1235                 RETURN_FALSE;
1236         }
1237 
1238         array_init(return_value);
1239 
1240         numitems = zend_hash_next_free_element(&EG(regular_list));
1241         for (i=1; i<numitems; i++) {
1242                 if (zend_hash_index_find(&EG(regular_list), i, (void **) &le)==FAILURE) {
1243                         continue;
1244                 }
1245                 if (Z_TYPE_P(le) == le_db || Z_TYPE_P(le) == le_pdb) {
1246                         info = (dba_info *)(le->ptr);
1247                         add_index_string(return_value, i, info->path, 1);
1248                 }
1249         }
1250 }
1251 /* }}} */
1252 
1253 #endif /* HAVE_DBA */
1254 
1255 /*
1256  * Local variables:
1257  * tab-width: 4
1258  * c-basic-offset: 4
1259  * End:
1260  * vim600: sw=4 ts=4 fdm=marker
1261  * vim<600: sw=4 ts=4
1262  */

/* [<][>][^][v][top][bottom][index][help] */