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

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

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