File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / dba / dba.c
Revision 1.1.1.5 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 20:03:42 2014 UTC (10 years, 3 months ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29, HEAD
php 5.4.29

    1: /*
    2:    +----------------------------------------------------------------------+
    3:    | PHP Version 5                                                        |
    4:    +----------------------------------------------------------------------+
    5:    | Copyright (c) 1997-2014 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: dba.c,v 1.1.1.5 2014/06/15 20:03:42 misho Exp $ */
   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_INFO(0, ...)
   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_INFO(0, ...)
   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_SETFL);
  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:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>