Annotation of embedaddon/php/ext/dba/dba.c, revision 1.1.1.4

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
1.1.1.3   misho       5:    | Copyright (c) 1997-2013 The PHP Group                                |
1.1       misho       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: 
1.1.1.2   misho      20: /* $Id$ */
1.1       misho      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"
1.1.1.2   misho      53: #include "php_tcadb.h"
1.1       misho      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:                *key_free = NULL;
                    230: 
                    231:                convert_to_string(key);
                    232:                *key_str = Z_STRVAL_P(key);
                    233: 
                    234:                return Z_STRLEN_P(key);
                    235:        }
                    236: }
                    237: /* }}} */
                    238: 
                    239: #define DBA_GET2                                                                                               \
                    240:        zval *key;                                                                                                      \
                    241:        char *key_str, *key_free;                                                                       \
                    242:        size_t key_len;                                                                                         \
                    243:        if (zend_parse_parameters(ac TSRMLS_CC, "zr", &key, &id) == FAILURE) {  \
                    244:                return;                                                                                                 \
                    245:        }                                                                                                                       \
                    246:        if ((key_len = php_dba_make_key(key, &key_str, &key_free TSRMLS_CC)) == 0) {\
                    247:                RETURN_FALSE;                                                                                   \
                    248:        }
                    249: 
                    250: #define DBA_GET2_3                                                                                             \
                    251:        zval *key;                                                                                                      \
                    252:        char *key_str, *key_free;                                                                       \
                    253:        size_t key_len;                                                                                         \
                    254:        long skip = 0;                                                                                          \
                    255:        switch(ac) {                                                                                            \
                    256:        case 2:                                                                                                         \
                    257:                if (zend_parse_parameters(ac TSRMLS_CC, "zr", &key, &id) == FAILURE) { \
                    258:                        return;                                                                                         \
                    259:                }                                                                                                               \
                    260:                break;                                                                                                  \
                    261:        case 3:                                                                                                         \
                    262:                if (zend_parse_parameters(ac TSRMLS_CC, "zlr", &key, &skip, &id) == FAILURE) { \
                    263:                        return;                                                                                         \
                    264:                }                                                                                                               \
                    265:                break;                                                                                                  \
                    266:        default:                                                                                                        \
                    267:                WRONG_PARAM_COUNT;                                                                              \
                    268:        }                                                                                                                       \
                    269:        if ((key_len = php_dba_make_key(key, &key_str, &key_free TSRMLS_CC)) == 0) {\
                    270:                RETURN_FALSE;                                                                                   \
                    271:        }
                    272: 
                    273: 
                    274: #define DBA_FETCH_RESOURCE(info, id)   \
                    275:        ZEND_FETCH_RESOURCE2(info, dba_info *, id, -1, "DBA identifier", le_db, le_pdb);
                    276: 
                    277: #define DBA_ID_GET2   DBA_ID_PARS; DBA_GET2;   DBA_FETCH_RESOURCE(info, &id)
                    278: #define DBA_ID_GET2_3 DBA_ID_PARS; DBA_GET2_3; DBA_FETCH_RESOURCE(info, &id)
                    279: 
                    280: #define DBA_ID_DONE                                                                                            \
                    281:        if (key_free) efree(key_free)
                    282: /* a DBA handler must have specific routines */
                    283: 
                    284: #define DBA_NAMED_HND(alias, name, flags) \
                    285: {\
                    286:        #alias, flags, dba_open_##name, dba_close_##name, dba_fetch_##name, dba_update_##name, \
                    287:        dba_exists_##name, dba_delete_##name, dba_firstkey_##name, dba_nextkey_##name, \
                    288:        dba_optimize_##name, dba_sync_##name, dba_info_##name \
                    289: },
                    290: 
                    291: #define DBA_HND(name, flags) DBA_NAMED_HND(name, name, flags)
                    292: 
                    293: /* check whether the user has write access */
                    294: #define DBA_WRITE_CHECK \
                    295:        if(info->mode != DBA_WRITER && info->mode != DBA_TRUNC && info->mode != DBA_CREAT) { \
                    296:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "You cannot perform a modification to a database without proper access"); \
                    297:                RETURN_FALSE; \
                    298:        }
                    299: 
                    300: /* }}} */
                    301: 
                    302: /* {{{ globals */
                    303: 
                    304: static dba_handler handler[] = {
                    305: #if DBA_GDBM
                    306:        DBA_HND(gdbm, DBA_LOCK_EXT) /* Locking done in library if set */
                    307: #endif
                    308: #if DBA_DBM
                    309:        DBA_HND(dbm, DBA_LOCK_ALL) /* No lock in lib */
                    310: #endif
                    311: #if DBA_NDBM
                    312:        DBA_HND(ndbm, DBA_LOCK_ALL) /* Could be done in library: filemode = 0644 + S_ENFMT */
                    313: #endif
                    314: #if DBA_CDB
                    315:        DBA_HND(cdb, DBA_STREAM_OPEN|DBA_LOCK_ALL) /* No lock in lib */
                    316: #endif
                    317: #if DBA_CDB_BUILTIN
                    318:     DBA_NAMED_HND(cdb_make, cdb, DBA_STREAM_OPEN|DBA_LOCK_ALL) /* No lock in lib */
                    319: #endif
                    320: #if DBA_DB1
                    321:        DBA_HND(db1, DBA_LOCK_ALL) /* No lock in lib */
                    322: #endif
                    323: #if DBA_DB2
                    324:        DBA_HND(db2, DBA_LOCK_ALL) /* No lock in lib */
                    325: #endif
                    326: #if DBA_DB3
                    327:        DBA_HND(db3, DBA_LOCK_ALL) /* No lock in lib */
                    328: #endif
                    329: #if DBA_DB4
                    330:        DBA_HND(db4, DBA_LOCK_ALL) /* No lock in lib */
                    331: #endif
                    332: #if DBA_INIFILE
                    333:        DBA_HND(inifile, DBA_STREAM_OPEN|DBA_LOCK_ALL|DBA_CAST_AS_FD) /* No lock in lib */
                    334: #endif
                    335: #if DBA_FLATFILE
                    336:        DBA_HND(flatfile, DBA_STREAM_OPEN|DBA_LOCK_ALL|DBA_NO_APPEND) /* No lock in lib */
                    337: #endif
                    338: #if DBA_QDBM
                    339:        DBA_HND(qdbm, DBA_LOCK_EXT)
                    340: #endif
1.1.1.2   misho     341: #if DBA_TCADB
                    342:        DBA_HND(tcadb, DBA_LOCK_ALL)
                    343: #endif
1.1       misho     344:        { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
                    345: };
                    346: 
                    347: #if DBA_FLATFILE
                    348: #define DBA_DEFAULT "flatfile"
                    349: #elif DBA_DB4
                    350: #define DBA_DEFAULT "db4"
                    351: #elif DBA_DB3
                    352: #define DBA_DEFAULT "db3"
                    353: #elif DBA_DB2
                    354: #define DBA_DEFAULT "db2"
                    355: #elif DBA_DB1
                    356: #define DBA_DEFAULT "db1"
                    357: #elif DBA_GDBM
                    358: #define DBA_DEFAULT "gdbm"
                    359: #elif DBA_NBBM
                    360: #define DBA_DEFAULT "ndbm"
                    361: #elif DBA_DBM
                    362: #define DBA_DEFAULT "dbm"
                    363: #elif DBA_QDBM
                    364: #define DBA_DEFAULT "qdbm"
1.1.1.2   misho     365: #elif DBA_TCADB
                    366: #define DBA_DEFAULT "tcadb"
1.1       misho     367: #else
                    368: #define DBA_DEFAULT ""
                    369: #endif
                    370: /* cdb/cdb_make and ini are no option here */
                    371: 
                    372: static int le_db;
                    373: static int le_pdb;
                    374: /* }}} */
                    375: 
                    376: /* {{{ dba_fetch_resource
                    377: PHPAPI void dba_fetch_resource(dba_info **pinfo, zval **id TSRMLS_DC)
                    378: {
                    379:        dba_info *info;
                    380:        DBA_ID_FETCH
                    381:        *pinfo = info;
                    382: }
                    383: */
                    384: /* }}} */
                    385: 
                    386: /* {{{ dba_get_handler
                    387: PHPAPI dba_handler *dba_get_handler(const char* handler_name)
                    388: {
                    389:        dba_handler *hptr;
                    390:        for (hptr = handler; hptr->name && strcasecmp(hptr->name, handler_name); hptr++);
                    391:        return hptr;
                    392: }
                    393: */
                    394: /* }}} */
                    395: 
                    396: /* {{{ dba_close 
                    397:  */ 
                    398: static void dba_close(dba_info *info TSRMLS_DC)
                    399: {
                    400:        if (info->hnd) {
                    401:                info->hnd->close(info TSRMLS_CC);
                    402:        }
                    403:        if (info->path) {
                    404:                pefree(info->path, info->flags&DBA_PERSISTENT);
                    405:        }
                    406:        if (info->fp && info->fp!=info->lock.fp) {
                    407:                if(info->flags&DBA_PERSISTENT) {
                    408:                        php_stream_pclose(info->fp);
                    409:                } else {
                    410:                        php_stream_close(info->fp);
                    411:                }
                    412:        }
                    413:        if (info->lock.fp) {
                    414:                if(info->flags&DBA_PERSISTENT) {
                    415:                        php_stream_pclose(info->lock.fp);
                    416:                } else {
                    417:                        php_stream_close(info->lock.fp);
                    418:                }
                    419:        }
                    420:        if (info->lock.name) {
                    421:                pefree(info->lock.name, info->flags&DBA_PERSISTENT);
                    422:        }
                    423:        pefree(info, info->flags&DBA_PERSISTENT);
                    424: }
                    425: /* }}} */
                    426: 
                    427: /* {{{ dba_close_rsrc
                    428:  */
                    429: static void dba_close_rsrc(zend_rsrc_list_entry *rsrc TSRMLS_DC)
                    430: {
                    431:        dba_info *info = (dba_info *)rsrc->ptr; 
                    432: 
                    433:        dba_close(info TSRMLS_CC);
                    434: }
                    435: /* }}} */
                    436: 
                    437: /* {{{ dba_close_pe_rsrc_deleter */
                    438: int dba_close_pe_rsrc_deleter(zend_rsrc_list_entry *le, void *pDba TSRMLS_DC)
                    439: {
                    440:        return le->ptr == pDba;
                    441: }
                    442: /* }}} */
                    443: 
                    444: /* {{{ dba_close_pe_rsrc */
                    445: static void dba_close_pe_rsrc(zend_rsrc_list_entry *rsrc TSRMLS_DC)
                    446: {
                    447:        dba_info *info = (dba_info *)rsrc->ptr; 
                    448: 
                    449:        /* closes the resource by calling dba_close_rsrc() */
                    450:        zend_hash_apply_with_argument(&EG(persistent_list), (apply_func_arg_t) dba_close_pe_rsrc_deleter, info TSRMLS_CC);
                    451: }
                    452: /* }}} */
                    453: 
                    454: /* {{{ PHP_INI
                    455:  */
                    456: ZEND_INI_MH(OnUpdateDefaultHandler)
                    457: {
                    458:        dba_handler *hptr;
                    459: 
                    460:        if (!strlen(new_value)) {
                    461:                DBA_G(default_hptr) = NULL;
                    462:                return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
                    463:        }
                    464: 
                    465:        for (hptr = handler; hptr->name && strcasecmp(hptr->name, new_value); hptr++);
                    466: 
                    467:        if (!hptr->name) {
                    468:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such handler: %s", new_value);
                    469:                return FAILURE;
                    470:        }
                    471:        DBA_G(default_hptr) = hptr;
                    472:        return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
                    473: }
                    474: 
                    475: PHP_INI_BEGIN()
                    476:     STD_PHP_INI_ENTRY("dba.default_handler", DBA_DEFAULT, PHP_INI_ALL, OnUpdateDefaultHandler, default_handler,    zend_dba_globals, dba_globals)
                    477: PHP_INI_END()
                    478: /* }}} */
                    479:  
                    480: /* {{{ PHP_GINIT_FUNCTION
                    481:  */
                    482: static PHP_GINIT_FUNCTION(dba)
                    483: {
                    484:        dba_globals->default_handler = "";
                    485:        dba_globals->default_hptr    = NULL;
                    486: }
                    487: /* }}} */
                    488: 
                    489: /* {{{ PHP_MINIT_FUNCTION
                    490:  */
                    491: PHP_MINIT_FUNCTION(dba)
                    492: {
                    493:        REGISTER_INI_ENTRIES();
                    494:        le_db = zend_register_list_destructors_ex(dba_close_rsrc, NULL, "dba", module_number);
                    495:        le_pdb = zend_register_list_destructors_ex(dba_close_pe_rsrc, dba_close_rsrc, "dba persistent", module_number);
                    496:        return SUCCESS;
                    497: }
                    498: /* }}} */
                    499: 
                    500: /* {{{ PHP_MSHUTDOWN_FUNCTION
                    501:  */
                    502: PHP_MSHUTDOWN_FUNCTION(dba)
                    503: {
                    504:        UNREGISTER_INI_ENTRIES();
                    505:        return SUCCESS;
                    506: }
                    507: /* }}} */
                    508: 
                    509: #include "ext/standard/php_smart_str.h"
                    510: 
                    511: /* {{{ PHP_MINFO_FUNCTION
                    512:  */
                    513: PHP_MINFO_FUNCTION(dba)
                    514: {
                    515:        dba_handler *hptr;
                    516:        smart_str handlers = {0};
                    517: 
                    518:        for(hptr = handler; hptr->name; hptr++) {
                    519:                smart_str_appends(&handlers, hptr->name);
                    520:                smart_str_appendc(&handlers, ' ');
                    521:        }
                    522: 
                    523:        php_info_print_table_start();
                    524:        php_info_print_table_row(2, "DBA support", "enabled");
                    525:        if (handlers.c) {
                    526:                smart_str_0(&handlers);
                    527:                php_info_print_table_row(2, "Supported handlers", handlers.c);
                    528:                smart_str_free(&handlers);
                    529:        } else {
                    530:                php_info_print_table_row(2, "Supported handlers", "none");
                    531:        }
                    532:        php_info_print_table_end();
                    533:        DISPLAY_INI_ENTRIES();
                    534: }
                    535: /* }}} */
                    536: 
                    537: /* {{{ php_dba_update
                    538:  */
                    539: static void php_dba_update(INTERNAL_FUNCTION_PARAMETERS, int mode)
                    540: {
                    541:        int val_len;
                    542:        zval *id;
                    543:        dba_info *info = NULL;
                    544:        int ac = ZEND_NUM_ARGS();
                    545:        zval *key;
                    546:        char *val;
                    547:        char *key_str, *key_free;
                    548:        size_t key_len;
                    549: 
                    550:        if (zend_parse_parameters(ac TSRMLS_CC, "zsr", &key, &val, &val_len, &id) == FAILURE) {
                    551:                return;
                    552:        }
                    553: 
                    554:        if ((key_len = php_dba_make_key(key, &key_str, &key_free TSRMLS_CC)) == 0) {
                    555:                RETURN_FALSE;
                    556:        }
                    557: 
                    558:        DBA_FETCH_RESOURCE(info, &id);
                    559: 
                    560:        DBA_WRITE_CHECK;
                    561: 
1.1.1.2   misho     562:        if (info->hnd->update(info, key_str, key_len, val, val_len, mode TSRMLS_CC) == SUCCESS) {
                    563:                DBA_ID_DONE;
                    564:                RETURN_TRUE;
1.1       misho     565:        }
                    566: 
                    567:        DBA_ID_DONE;
                    568:        RETURN_FALSE;
                    569: }
                    570: /* }}} */
                    571: 
                    572: #define FREENOW if(args) efree(args); if(key) efree(key)
                    573: 
                    574: /* {{{ php_find_dbm
                    575:  */
                    576: dba_info *php_dba_find(const char* path TSRMLS_DC)
                    577: {
                    578:        zend_rsrc_list_entry *le;
                    579:        dba_info *info;
                    580:        int numitems, i;
                    581: 
                    582:        numitems = zend_hash_next_free_element(&EG(regular_list));
                    583:        for (i=1; i<numitems; i++) {
                    584:                if (zend_hash_index_find(&EG(regular_list), i, (void **) &le)==FAILURE) {
                    585:                        continue;
                    586:                }
                    587:                if (Z_TYPE_P(le) == le_db || Z_TYPE_P(le) == le_pdb) {
                    588:                        info = (dba_info *)(le->ptr);
                    589:                        if (!strcmp(info->path, path)) {
                    590:                                return (dba_info *)(le->ptr);
                    591:                        }
                    592:                }
                    593:        }
                    594: 
                    595:        return NULL;
                    596: }
                    597: /* }}} */
                    598: 
                    599: /* {{{ php_dba_open
                    600:  */
                    601: static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
                    602: {
                    603:        zval ***args = (zval ***) NULL;
                    604:        int ac = ZEND_NUM_ARGS();
                    605:        dba_mode_t modenr;
                    606:        dba_info *info, *other;
                    607:        dba_handler *hptr;
                    608:        char *key = NULL, *error = NULL;
                    609:        int keylen = 0;
                    610:        int i;
                    611:        int lock_mode, lock_flag, lock_dbf = 0;
                    612:        char *file_mode;
                    613:        char mode[4], *pmode, *lock_file_mode = NULL;
                    614:        int persistent_flag = persistent ? STREAM_OPEN_PERSISTENT : 0;
                    615:        char *opened_path, *lock_name;
                    616:        
                    617:        if(ac < 2) {
                    618:                WRONG_PARAM_COUNT;
                    619:        }
                    620:        
                    621:        /* we pass additional args to the respective handler */
                    622:        args = safe_emalloc(ac, sizeof(zval *), 0);
                    623:        if (zend_get_parameters_array_ex(ac, args) != SUCCESS) {
                    624:                FREENOW;
                    625:                WRONG_PARAM_COUNT;
                    626:        }
                    627:                
                    628:        /* we only take string arguments */
                    629:        for (i = 0; i < ac; i++) {
                    630:                convert_to_string_ex(args[i]);
                    631:                keylen += Z_STRLEN_PP(args[i]);
                    632:        }
                    633: 
                    634:        if (persistent) {
                    635:                zend_rsrc_list_entry *le;
                    636:                
                    637:                /* calculate hash */
                    638:                key = safe_emalloc(keylen, 1, 1);
                    639:                key[keylen] = '\0';
                    640:                keylen = 0;
                    641:                
                    642:                for(i = 0; i < ac; i++) {
                    643:                        memcpy(key+keylen, Z_STRVAL_PP(args[i]), Z_STRLEN_PP(args[i]));
                    644:                        keylen += Z_STRLEN_PP(args[i]);
                    645:                }
                    646: 
                    647:                /* try to find if we already have this link in our persistent list */
                    648:                if (zend_hash_find(&EG(persistent_list), key, keylen+1, (void **) &le) == SUCCESS) {
                    649:                        FREENOW;
                    650:                        
                    651:                        if (Z_TYPE_P(le) != le_pdb) {
                    652:                                RETURN_FALSE;
                    653:                        }
                    654:                
                    655:                        info = (dba_info *)le->ptr;
                    656: 
                    657:                        ZEND_REGISTER_RESOURCE(return_value, info, le_pdb);
                    658:                        return;
                    659:                }
                    660:        }
                    661:        
                    662:        if (ac==2) {
                    663:                hptr = DBA_G(default_hptr);
                    664:                if (!hptr) {
                    665:                        php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "No default handler selected");
                    666:                        FREENOW;
                    667:                        RETURN_FALSE;
                    668:                }
                    669:        } else {
                    670:                for (hptr = handler; hptr->name && strcasecmp(hptr->name, Z_STRVAL_PP(args[2])); hptr++);
                    671:        }
                    672: 
                    673:        if (!hptr->name) {
                    674:                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]));
                    675:                FREENOW;
                    676:                RETURN_FALSE;
                    677:        }
                    678: 
                    679:        /* Check mode: [rwnc][fl]?t?
                    680:         * r: Read
                    681:         * w: Write
                    682:         * n: Create/Truncate
                    683:         * c: Create
                    684:         *
                    685:         * d: force lock on database file
                    686:         * l: force lock on lck file
                    687:         * -: ignore locking
                    688:         *
                    689:         * t: test open database, warning if locked
                    690:         */
                    691:        strlcpy(mode, Z_STRVAL_PP(args[1]), sizeof(mode));
                    692:        pmode = &mode[0];
                    693:        if (pmode[0] && (pmode[1]=='d' || pmode[1]=='l' || pmode[1]=='-')) { /* force lock on db file or lck file or disable locking */
                    694:                switch (pmode[1]) {
                    695:                case 'd':
                    696:                        lock_dbf = 1;
                    697:                        if ((hptr->flags & DBA_LOCK_ALL) == 0) {
                    698:                                lock_flag = (hptr->flags & DBA_LOCK_ALL);
                    699:                                break;
                    700:                        }
                    701:                        /* no break */
                    702:                case 'l':
                    703:                        lock_flag = DBA_LOCK_ALL;
                    704:                        if ((hptr->flags & DBA_LOCK_ALL) == 0) {
                    705:                                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);
                    706:                        }
                    707:                        break;
                    708:                default:
                    709:                case '-':
                    710:                        if ((hptr->flags & DBA_LOCK_ALL) == 0) {
                    711:                                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);
                    712:                                FREENOW;
                    713:                                RETURN_FALSE;
                    714:                        }
                    715:                        lock_flag = 0;
                    716:                        break;
                    717:                }
                    718:        } else {
                    719:                lock_flag = (hptr->flags&DBA_LOCK_ALL);
                    720:                lock_dbf = 1;
                    721:        }
                    722:        switch (*pmode++) {
                    723:                case 'r': 
                    724:                        modenr = DBA_READER; 
                    725:                        lock_mode = (lock_flag & DBA_LOCK_READER) ? LOCK_SH : 0;
                    726:                        file_mode = "r";
                    727:                        break;
                    728:                case 'w': 
                    729:                        modenr = DBA_WRITER; 
                    730:                        lock_mode = (lock_flag & DBA_LOCK_WRITER) ? LOCK_EX : 0;
                    731:                        file_mode = "r+b";
                    732:                        break;
                    733:                case 'c': 
                    734:                        modenr = DBA_CREAT; 
                    735:                        lock_mode = (lock_flag & DBA_LOCK_CREAT) ? LOCK_EX : 0;
                    736:                        if (lock_mode) {
                    737:                                if (lock_dbf) {
                    738:                                        /* the create/append check will be done on the lock
                    739:                                         * when the lib opens the file it is already created
                    740:                                         */
                    741:                                        file_mode = "r+b";       /* read & write, seek 0 */
                    742:                                        lock_file_mode = "a+b";  /* append */
                    743:                                } else {
                    744:                                        file_mode = "a+b";       /* append */
                    745:                                        lock_file_mode = "w+b";  /* create/truncate */
                    746:                                }
                    747:                        } else {
                    748:                                file_mode = "a+b";
                    749:                        }
                    750:                        /* In case of the 'a+b' append mode, the handler is responsible 
                    751:                         * to handle any rewind problems (see flatfile handler).
                    752:                         */
                    753:                        break;
                    754:                case 'n':
                    755:                        modenr = DBA_TRUNC;
                    756:                        lock_mode = (lock_flag & DBA_LOCK_TRUNC) ? LOCK_EX : 0;
                    757:                        file_mode = "w+b";
                    758:                        break;
                    759:                default:
                    760:                        php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Illegal DBA mode");
                    761:                        FREENOW;
                    762:                        RETURN_FALSE;
                    763:        }
                    764:        if (!lock_file_mode) {
                    765:                lock_file_mode = file_mode;
                    766:        }
                    767:        if (*pmode=='d' || *pmode=='l' || *pmode=='-') {
                    768:                pmode++; /* done already - skip here */
                    769:        }
                    770:        if (*pmode=='t') {
                    771:                pmode++;
                    772:                if (!lock_flag) {
                    773:                        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)");
                    774:                        FREENOW;
                    775:                        RETURN_FALSE;
                    776:                }
                    777:                if (!lock_mode) {
                    778:                        if ((hptr->flags & DBA_LOCK_ALL) == 0) {
                    779:                                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);
                    780:                                FREENOW;
                    781:                                RETURN_FALSE;
                    782:                        } else {
                    783:                                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);
                    784:                                FREENOW;
                    785:                                RETURN_FALSE;
                    786:                        }
                    787:                } else {
                    788:                        lock_mode |= LOCK_NB; /* test =: non blocking */
                    789:                }
                    790:        }
                    791:        if (*pmode) {
                    792:                php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Illegal DBA mode");
                    793:                FREENOW;
                    794:                RETURN_FALSE;
                    795:        }
                    796:                        
                    797:        info = pemalloc(sizeof(dba_info), persistent);
                    798:        memset(info, 0, sizeof(dba_info));
                    799:        info->path = pestrdup(Z_STRVAL_PP(args[0]), persistent);
                    800:        info->mode = modenr;
                    801:        info->argc = ac - 3;
                    802:        info->argv = args + 3;
                    803:        info->flags = (hptr->flags & ~DBA_LOCK_ALL) | (lock_flag & DBA_LOCK_ALL) | (persistent ? DBA_PERSISTENT : 0);
                    804:        info->lock.mode = lock_mode;
                    805: 
                    806:        /* if any open call is a locking call:
                    807:         * check if we already habe a locking call open that should block this call
                    808:         * the problem is some systems would allow read during write
                    809:         */
                    810:        if (hptr->flags & DBA_LOCK_ALL) {
                    811:                if ((other = php_dba_find(info->path TSRMLS_CC)) != NULL) {
                    812:                        if (   ( (lock_mode&LOCK_EX)        && (other->lock.mode&(LOCK_EX|LOCK_SH)) )
                    813:                            || ( (other->lock.mode&LOCK_EX) && (lock_mode&(LOCK_EX|LOCK_SH))        )
                    814:                           ) {
                    815:                                error = "Unable to establish lock (database file already open)"; /* force failure exit */
                    816:                        }
                    817:                }
                    818:        }
                    819: 
                    820:        if (!error && lock_mode) {
                    821:                if (lock_dbf) {
                    822:                        lock_name = Z_STRVAL_PP(args[0]);
                    823:                } else {
                    824:                        spprintf(&lock_name, 0, "%s.lck", info->path);
                    825:                        if (!strcmp(file_mode, "r")) {
                    826:                                /* when in read only mode try to use existing .lck file first */
                    827:                                /* do not log errors for .lck file while in read ony mode on .lck file */
                    828:                                lock_file_mode = "rb";
1.1.1.2   misho     829:                                info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|IGNORE_PATH|persistent_flag, &opened_path);
1.1       misho     830:                        }
                    831:                        if (!info->lock.fp) {
                    832:                                /* when not in read mode or failed to open .lck file read only. now try again in create(write) mode and log errors */
                    833:                                lock_file_mode = "a+b";
                    834:                        } else {
                    835:                                if (!persistent) {
                    836:                                        info->lock.name = opened_path;
                    837:                                } else {
                    838:                                        info->lock.name = pestrdup(opened_path, persistent);
                    839:                                        efree(opened_path);
                    840:                                }
                    841:                        }
                    842:                }
                    843:                if (!info->lock.fp) {
1.1.1.2   misho     844:                        info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, &opened_path);
1.1       misho     845:                        if (info->lock.fp) {
                    846:                                if (lock_dbf) {
                    847:                                        /* replace the path info with the real path of the opened file */
                    848:                                        pefree(info->path, persistent);
                    849:                                        info->path = pestrdup(opened_path, persistent);
                    850:                                }
                    851:                                /* now store the name of the lock */
                    852:                                if (!persistent) {
                    853:                                        info->lock.name = opened_path;
                    854:                                } else {
                    855:                                        info->lock.name = pestrdup(opened_path, persistent);
                    856:                                        efree(opened_path);
                    857:                                }
                    858:                        }
                    859:                }
                    860:                if (!lock_dbf) {
                    861:                        efree(lock_name);
                    862:                }
                    863:                if (!info->lock.fp) {
                    864:                        dba_close(info TSRMLS_CC);
                    865:                        /* stream operation already wrote an error message */
                    866:                        FREENOW;
                    867:                        RETURN_FALSE;
                    868:                }
                    869:                if (!php_stream_supports_lock(info->lock.fp)) {
                    870:                        error = "Stream does not support locking";
                    871:                }
                    872:                if (php_stream_lock(info->lock.fp, lock_mode)) {
                    873:                        error = "Unable to establish lock"; /* force failure exit */
                    874:                }
                    875:        }
                    876: 
                    877:        /* centralised open stream for builtin */
                    878:        if (!error && (hptr->flags&DBA_STREAM_OPEN)==DBA_STREAM_OPEN) {
                    879:                if (info->lock.fp && lock_dbf) {
                    880:                        info->fp = info->lock.fp; /* use the same stream for locking and database access */
                    881:                } else {
1.1.1.2   misho     882:                        info->fp = php_stream_open_wrapper(info->path, file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, NULL);
1.1       misho     883:                }
                    884:                if (!info->fp) {
                    885:                        dba_close(info TSRMLS_CC);
                    886:                        /* stream operation already wrote an error message */
                    887:                        FREENOW;
                    888:                        RETURN_FALSE;
                    889:                }
                    890:                if (hptr->flags & (DBA_NO_APPEND|DBA_CAST_AS_FD)) {
1.1.1.4 ! misho     891:                        /* Needed because some systems do not allow to write to the original 
1.1       misho     892:                         * file contents with O_APPEND being set.
                    893:                         */
                    894:                        if (SUCCESS != php_stream_cast(info->fp, PHP_STREAM_AS_FD, (void*)&info->fd, 1)) {
                    895:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not cast stream");
                    896:                                dba_close(info TSRMLS_CC);
                    897:                                FREENOW;
                    898:                                RETURN_FALSE;
                    899: #ifdef F_SETFL
                    900:                        } else if (modenr == DBA_CREAT) {
                    901:                                int flags = fcntl(info->fd, F_SETFL);
                    902:                                fcntl(info->fd, F_SETFL, flags & ~O_APPEND);
                    903: #endif
                    904:                        }
                    905:                                
                    906:                }
                    907:        }
                    908: 
                    909:        if (error || hptr->open(info, &error TSRMLS_CC) != SUCCESS) {
                    910:                dba_close(info TSRMLS_CC);
                    911:                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:"");
                    912:                FREENOW;
                    913:                RETURN_FALSE;
                    914:        }
                    915: 
                    916:        info->hnd = hptr;
                    917:        info->argc = 0;
                    918:        info->argv = NULL;
                    919: 
                    920:        if (persistent) {
                    921:                zend_rsrc_list_entry new_le;
                    922: 
                    923:                Z_TYPE(new_le) = le_pdb;
                    924:                new_le.ptr = info;
                    925:                if (zend_hash_update(&EG(persistent_list), key, keylen+1, &new_le, sizeof(zend_rsrc_list_entry), NULL) == FAILURE) {
                    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, "Could not register persistent resource");
                    928:                        FREENOW;
                    929:                        RETURN_FALSE;
                    930:                }
                    931:        }
                    932: 
                    933:        ZEND_REGISTER_RESOURCE(return_value, info, (persistent ? le_pdb : le_db));
                    934:        FREENOW;
                    935: }
                    936: /* }}} */
                    937: #undef FREENOW
                    938: 
                    939: /* {{{ proto resource dba_popen(string path, string mode [, string handlername, string ...])
                    940:    Opens path using the specified handler in mode persistently */
                    941: PHP_FUNCTION(dba_popen)
                    942: {
                    943:        php_dba_open(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
                    944: }
                    945: /* }}} */
                    946: 
                    947: /* {{{ proto resource dba_open(string path, string mode [, string handlername, string ...])
                    948:    Opens path using the specified handler in mode*/
                    949: PHP_FUNCTION(dba_open)
                    950: {
                    951:        php_dba_open(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
                    952: }
                    953: /* }}} */
                    954: 
                    955: /* {{{ proto void dba_close(resource handle)
                    956:    Closes database */
                    957: PHP_FUNCTION(dba_close)
                    958: {
                    959:        zval *id;
                    960:        dba_info *info = NULL;
                    961: 
                    962:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
                    963:                return;
                    964:        }
                    965: 
                    966:        DBA_FETCH_RESOURCE(info, &id);
                    967: 
                    968:        zend_list_delete(Z_RESVAL_P(id));
                    969: }
                    970: /* }}} */
                    971: 
                    972: /* {{{ proto bool dba_exists(string key, resource handle)
                    973:    Checks, if the specified key exists */
                    974: PHP_FUNCTION(dba_exists)
                    975: {
                    976:        DBA_ID_GET2;
                    977: 
                    978:        if(info->hnd->exists(info, key_str, key_len TSRMLS_CC) == SUCCESS) {
                    979:                DBA_ID_DONE;
                    980:                RETURN_TRUE;
                    981:        }
                    982:        DBA_ID_DONE;
                    983:        RETURN_FALSE;
                    984: }
                    985: /* }}} */
                    986: 
                    987: /* {{{ proto string dba_fetch(string key, [int skip ,] resource handle)
                    988:    Fetches the data associated with key */
                    989: PHP_FUNCTION(dba_fetch)
                    990: {
                    991:        char *val;
                    992:        int len = 0;
                    993:        DBA_ID_GET2_3;
                    994: 
                    995:        if (ac==3) {
                    996:                if (!strcmp(info->hnd->name, "cdb")) {
                    997:                        if (skip < 0) {
                    998:                                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);
                    999:                                skip = 0;
                   1000:                        }
                   1001:                } else if (!strcmp(info->hnd->name, "inifile")) {
                   1002:                        /* "-1" is compareable to 0 but allows a non restrictive 
                   1003:                         * access which is fater. For example 'inifile' uses this
                   1004:                         * to allow faster access when the key was already found
                   1005:                         * using firstkey/nextkey. However explicitly setting the
                   1006:                         * value to 0 ensures the first value. 
                   1007:                         */
                   1008:                        if (skip < -1) {
                   1009:                                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Handler %s accepts only skip value -1 and greater, using skip=0", info->hnd->name);
                   1010:                                skip = 0;
                   1011:                        }
                   1012:                } else {
                   1013:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Handler %s does not support optional skip parameter, the value will be ignored", info->hnd->name);
                   1014:                        skip = 0;                       
                   1015:                }
                   1016:        } else {
                   1017:                skip = 0; 
                   1018:        }
                   1019:        if((val = info->hnd->fetch(info, key_str, key_len, skip, &len TSRMLS_CC)) != NULL) {
                   1020:                DBA_ID_DONE;
                   1021:                RETURN_STRINGL(val, len, 0);
                   1022:        } 
                   1023:        DBA_ID_DONE;
                   1024:        RETURN_FALSE;
                   1025: }
                   1026: /* }}} */
                   1027: 
                   1028: /* {{{ proto array|false dba_key_split(string key)
                   1029:    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 */
                   1030: PHP_FUNCTION(dba_key_split)
                   1031: {
                   1032:        zval *zkey;
                   1033:        char *key, *name;
                   1034:        int key_len;
                   1035: 
                   1036:        if (ZEND_NUM_ARGS() != 1) {
                   1037:                WRONG_PARAM_COUNT;
                   1038:        }
                   1039:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &zkey) == SUCCESS) {
                   1040:                if (Z_TYPE_P(zkey) == IS_NULL || (Z_TYPE_P(zkey) == IS_BOOL && !Z_LVAL_P(zkey))) {
                   1041:                        RETURN_BOOL(0);
                   1042:                }
                   1043:        }
                   1044:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) {
                   1045:                RETURN_BOOL(0);
                   1046:        }
                   1047:        array_init(return_value);
                   1048:        if (key[0] == '[' && (name = strchr(key, ']')) != NULL) {
                   1049:                add_next_index_stringl(return_value, key+1, name - (key + 1), 1);
                   1050:                add_next_index_stringl(return_value, name+1, key_len - (name - key + 1), 1);
                   1051:        } else {
                   1052:                add_next_index_stringl(return_value, "", 0, 1);
                   1053:                add_next_index_stringl(return_value, key, key_len, 1);
                   1054:        }
                   1055: }
                   1056: /* }}} */
                   1057: 
                   1058: /* {{{ proto string dba_firstkey(resource handle)
                   1059:    Resets the internal key pointer and returns the first key */
                   1060: PHP_FUNCTION(dba_firstkey)
                   1061: {
                   1062:        char *fkey;
                   1063:        int len;
                   1064:        zval *id;
                   1065:        dba_info *info = NULL;
                   1066: 
                   1067:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
                   1068:                return;
                   1069:        }
                   1070: 
                   1071:        DBA_FETCH_RESOURCE(info, &id);
                   1072: 
                   1073:        fkey = info->hnd->firstkey(info, &len TSRMLS_CC);
                   1074: 
                   1075:        if (fkey)
                   1076:                RETURN_STRINGL(fkey, len, 0);
                   1077: 
                   1078:        RETURN_FALSE;
                   1079: }
                   1080: /* }}} */
                   1081: 
                   1082: /* {{{ proto string dba_nextkey(resource handle)
                   1083:    Returns the next key */
                   1084: PHP_FUNCTION(dba_nextkey)
                   1085: {
                   1086:        char *nkey;
                   1087:        int len;
                   1088:        zval *id;
                   1089:        dba_info *info = NULL;
                   1090: 
                   1091:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
                   1092:                return;
                   1093:        }
                   1094: 
                   1095:        DBA_FETCH_RESOURCE(info, &id);
                   1096: 
                   1097:        nkey = info->hnd->nextkey(info, &len TSRMLS_CC);
                   1098: 
                   1099:        if (nkey)
                   1100:                RETURN_STRINGL(nkey, len, 0);
                   1101: 
                   1102:        RETURN_FALSE;
                   1103: }
                   1104: /* }}} */
                   1105: 
                   1106: /* {{{ proto bool dba_delete(string key, resource handle)
                   1107:    Deletes the entry associated with key
                   1108:    If inifile: remove all other key lines */
                   1109: PHP_FUNCTION(dba_delete)
                   1110: {
                   1111:        DBA_ID_GET2;
                   1112:        
                   1113:        DBA_WRITE_CHECK;
                   1114:        
                   1115:        if(info->hnd->delete(info, key_str, key_len TSRMLS_CC) == SUCCESS)
                   1116:        {
                   1117:                DBA_ID_DONE;
                   1118:                RETURN_TRUE;
                   1119:        }
                   1120:        DBA_ID_DONE;
                   1121:        RETURN_FALSE;
                   1122: }
                   1123: /* }}} */
                   1124: 
                   1125: /* {{{ proto bool dba_insert(string key, string value, resource handle)
                   1126:    If not inifile: Insert value as key, return false, if key exists already 
                   1127:    If inifile: Add vakue as key (next instance of key) */
                   1128: PHP_FUNCTION(dba_insert)
                   1129: {
                   1130:        php_dba_update(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
                   1131: }
                   1132: /* }}} */
                   1133: 
                   1134: /* {{{ proto bool dba_replace(string key, string value, resource handle)
                   1135:    Inserts value as key, replaces key, if key exists already
                   1136:    If inifile: remove all other key lines */
                   1137: PHP_FUNCTION(dba_replace)
                   1138: {
                   1139:        php_dba_update(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
                   1140: }
                   1141: /* }}} */
                   1142: 
                   1143: /* {{{ proto bool dba_optimize(resource handle)
                   1144:    Optimizes (e.g. clean up, vacuum) database */
                   1145: PHP_FUNCTION(dba_optimize)
                   1146: {
                   1147:        zval *id;
                   1148:        dba_info *info = NULL;
                   1149: 
                   1150:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
                   1151:                return;
                   1152:        }
                   1153: 
                   1154:        DBA_FETCH_RESOURCE(info, &id);
                   1155: 
                   1156:        DBA_WRITE_CHECK;
                   1157: 
                   1158:        if (info->hnd->optimize(info TSRMLS_CC) == SUCCESS) {
                   1159:                RETURN_TRUE;
                   1160:        }
                   1161: 
                   1162:        RETURN_FALSE;
                   1163: }
                   1164: /* }}} */
                   1165: 
                   1166: /* {{{ proto bool dba_sync(resource handle)
                   1167:    Synchronizes database */
                   1168: PHP_FUNCTION(dba_sync)
                   1169: {
                   1170:        zval *id;
                   1171:        dba_info *info = NULL;
                   1172: 
                   1173:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
                   1174:                return;
                   1175:        }
                   1176: 
                   1177:        DBA_FETCH_RESOURCE(info, &id);
                   1178: 
                   1179:        if (info->hnd->sync(info TSRMLS_CC) == SUCCESS) {
                   1180:                RETURN_TRUE;
                   1181:        }
                   1182: 
                   1183:        RETURN_FALSE;
                   1184: }
                   1185: /* }}} */
                   1186: 
                   1187: /* {{{ proto array dba_handlers([bool full_info])
                   1188:    List configured database handlers */
                   1189: PHP_FUNCTION(dba_handlers)
                   1190: {
                   1191:        dba_handler *hptr;
                   1192:        zend_bool full_info = 0;
                   1193: 
                   1194:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &full_info) == FAILURE) {
                   1195:                RETURN_FALSE;
                   1196:        }
                   1197: 
                   1198:        array_init(return_value);
                   1199: 
                   1200:        for(hptr = handler; hptr->name; hptr++) {
                   1201:                if (full_info) {
                   1202:                        add_assoc_string(return_value, hptr->name, hptr->info(hptr, NULL TSRMLS_CC), 0);
                   1203:                } else {
                   1204:                        add_next_index_string(return_value, hptr->name, 1);
                   1205:                }
                   1206:        }
                   1207: }
                   1208: /* }}} */
                   1209: 
                   1210: /* {{{ proto array dba_list()
                   1211:    List opened databases */
                   1212: PHP_FUNCTION(dba_list)
                   1213: {
                   1214:        ulong numitems, i;
                   1215:        zend_rsrc_list_entry *le;
                   1216:        dba_info *info;
                   1217: 
                   1218:        if (zend_parse_parameters_none() == FAILURE) {
                   1219:                RETURN_FALSE;
                   1220:        }
                   1221: 
                   1222:        array_init(return_value);
                   1223: 
                   1224:        numitems = zend_hash_next_free_element(&EG(regular_list));
                   1225:        for (i=1; i<numitems; i++) {
                   1226:                if (zend_hash_index_find(&EG(regular_list), i, (void **) &le)==FAILURE) {
                   1227:                        continue;
                   1228:                }
                   1229:                if (Z_TYPE_P(le) == le_db || Z_TYPE_P(le) == le_pdb) {
                   1230:                        info = (dba_info *)(le->ptr);
                   1231:                        add_index_string(return_value, i, info->path, 1);
                   1232:                }
                   1233:        }
                   1234: }
                   1235: /* }}} */
                   1236: 
                   1237: #endif /* HAVE_DBA */
                   1238: 
                   1239: /*
                   1240:  * Local variables:
                   1241:  * tab-width: 4
                   1242:  * c-basic-offset: 4
                   1243:  * End:
                   1244:  * vim600: sw=4 ts=4 fdm=marker
                   1245:  * vim<600: sw=4 ts=4
                   1246:  */

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