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

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: 
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:        char *v;
                    542:        int val_len;
                    543:        zval *id;
                    544:        dba_info *info = NULL;
                    545:        int ac = ZEND_NUM_ARGS();
                    546:        zval *key;
                    547:        char *val;
                    548:        char *key_str, *key_free;
                    549:        size_t key_len;
                    550: 
                    551:        if (zend_parse_parameters(ac TSRMLS_CC, "zsr", &key, &val, &val_len, &id) == FAILURE) {
                    552:                return;
                    553:        }
                    554: 
                    555:        if ((key_len = php_dba_make_key(key, &key_str, &key_free TSRMLS_CC)) == 0) {
                    556:                RETURN_FALSE;
                    557:        }
                    558: 
                    559:        DBA_FETCH_RESOURCE(info, &id);
                    560: 
                    561:        DBA_WRITE_CHECK;
                    562: 
1.1.1.2 ! misho     563:        if (info->hnd->update(info, key_str, key_len, val, val_len, mode TSRMLS_CC) == SUCCESS) {
        !           564:                DBA_ID_DONE;
        !           565:                RETURN_TRUE;
1.1       misho     566:        }
                    567: 
                    568:        DBA_ID_DONE;
                    569:        RETURN_FALSE;
                    570: }
                    571: /* }}} */
                    572: 
                    573: #define FREENOW if(args) efree(args); if(key) efree(key)
                    574: 
                    575: /* {{{ php_find_dbm
                    576:  */
                    577: dba_info *php_dba_find(const char* path TSRMLS_DC)
                    578: {
                    579:        zend_rsrc_list_entry *le;
                    580:        dba_info *info;
                    581:        int numitems, i;
                    582: 
                    583:        numitems = zend_hash_next_free_element(&EG(regular_list));
                    584:        for (i=1; i<numitems; i++) {
                    585:                if (zend_hash_index_find(&EG(regular_list), i, (void **) &le)==FAILURE) {
                    586:                        continue;
                    587:                }
                    588:                if (Z_TYPE_P(le) == le_db || Z_TYPE_P(le) == le_pdb) {
                    589:                        info = (dba_info *)(le->ptr);
                    590:                        if (!strcmp(info->path, path)) {
                    591:                                return (dba_info *)(le->ptr);
                    592:                        }
                    593:                }
                    594:        }
                    595: 
                    596:        return NULL;
                    597: }
                    598: /* }}} */
                    599: 
                    600: /* {{{ php_dba_open
                    601:  */
                    602: static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
                    603: {
                    604:        zval ***args = (zval ***) NULL;
                    605:        int ac = ZEND_NUM_ARGS();
                    606:        dba_mode_t modenr;
                    607:        dba_info *info, *other;
                    608:        dba_handler *hptr;
                    609:        char *key = NULL, *error = NULL;
                    610:        int keylen = 0;
                    611:        int i;
                    612:        int lock_mode, lock_flag, lock_dbf = 0;
                    613:        char *file_mode;
                    614:        char mode[4], *pmode, *lock_file_mode = NULL;
                    615:        int persistent_flag = persistent ? STREAM_OPEN_PERSISTENT : 0;
                    616:        char *opened_path, *lock_name;
                    617:        
                    618:        if(ac < 2) {
                    619:                WRONG_PARAM_COUNT;
                    620:        }
                    621:        
                    622:        /* we pass additional args to the respective handler */
                    623:        args = safe_emalloc(ac, sizeof(zval *), 0);
                    624:        if (zend_get_parameters_array_ex(ac, args) != SUCCESS) {
                    625:                FREENOW;
                    626:                WRONG_PARAM_COUNT;
                    627:        }
                    628:                
                    629:        /* we only take string arguments */
                    630:        for (i = 0; i < ac; i++) {
                    631:                convert_to_string_ex(args[i]);
                    632:                keylen += Z_STRLEN_PP(args[i]);
                    633:        }
                    634: 
                    635:        if (persistent) {
                    636:                zend_rsrc_list_entry *le;
                    637:                
                    638:                /* calculate hash */
                    639:                key = safe_emalloc(keylen, 1, 1);
                    640:                key[keylen] = '\0';
                    641:                keylen = 0;
                    642:                
                    643:                for(i = 0; i < ac; i++) {
                    644:                        memcpy(key+keylen, Z_STRVAL_PP(args[i]), Z_STRLEN_PP(args[i]));
                    645:                        keylen += Z_STRLEN_PP(args[i]);
                    646:                }
                    647: 
                    648:                /* try to find if we already have this link in our persistent list */
                    649:                if (zend_hash_find(&EG(persistent_list), key, keylen+1, (void **) &le) == SUCCESS) {
                    650:                        FREENOW;
                    651:                        
                    652:                        if (Z_TYPE_P(le) != le_pdb) {
                    653:                                RETURN_FALSE;
                    654:                        }
                    655:                
                    656:                        info = (dba_info *)le->ptr;
                    657: 
                    658:                        ZEND_REGISTER_RESOURCE(return_value, info, le_pdb);
                    659:                        return;
                    660:                }
                    661:        }
                    662:        
                    663:        if (ac==2) {
                    664:                hptr = DBA_G(default_hptr);
                    665:                if (!hptr) {
                    666:                        php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "No default handler selected");
                    667:                        FREENOW;
                    668:                        RETURN_FALSE;
                    669:                }
                    670:        } else {
                    671:                for (hptr = handler; hptr->name && strcasecmp(hptr->name, Z_STRVAL_PP(args[2])); hptr++);
                    672:        }
                    673: 
                    674:        if (!hptr->name) {
                    675:                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]));
                    676:                FREENOW;
                    677:                RETURN_FALSE;
                    678:        }
                    679: 
                    680:        /* Check mode: [rwnc][fl]?t?
                    681:         * r: Read
                    682:         * w: Write
                    683:         * n: Create/Truncate
                    684:         * c: Create
                    685:         *
                    686:         * d: force lock on database file
                    687:         * l: force lock on lck file
                    688:         * -: ignore locking
                    689:         *
                    690:         * t: test open database, warning if locked
                    691:         */
                    692:        strlcpy(mode, Z_STRVAL_PP(args[1]), sizeof(mode));
                    693:        pmode = &mode[0];
                    694:        if (pmode[0] && (pmode[1]=='d' || pmode[1]=='l' || pmode[1]=='-')) { /* force lock on db file or lck file or disable locking */
                    695:                switch (pmode[1]) {
                    696:                case 'd':
                    697:                        lock_dbf = 1;
                    698:                        if ((hptr->flags & DBA_LOCK_ALL) == 0) {
                    699:                                lock_flag = (hptr->flags & DBA_LOCK_ALL);
                    700:                                break;
                    701:                        }
                    702:                        /* no break */
                    703:                case 'l':
                    704:                        lock_flag = DBA_LOCK_ALL;
                    705:                        if ((hptr->flags & DBA_LOCK_ALL) == 0) {
                    706:                                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);
                    707:                        }
                    708:                        break;
                    709:                default:
                    710:                case '-':
                    711:                        if ((hptr->flags & DBA_LOCK_ALL) == 0) {
                    712:                                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);
                    713:                                FREENOW;
                    714:                                RETURN_FALSE;
                    715:                        }
                    716:                        lock_flag = 0;
                    717:                        break;
                    718:                }
                    719:        } else {
                    720:                lock_flag = (hptr->flags&DBA_LOCK_ALL);
                    721:                lock_dbf = 1;
                    722:        }
                    723:        switch (*pmode++) {
                    724:                case 'r': 
                    725:                        modenr = DBA_READER; 
                    726:                        lock_mode = (lock_flag & DBA_LOCK_READER) ? LOCK_SH : 0;
                    727:                        file_mode = "r";
                    728:                        break;
                    729:                case 'w': 
                    730:                        modenr = DBA_WRITER; 
                    731:                        lock_mode = (lock_flag & DBA_LOCK_WRITER) ? LOCK_EX : 0;
                    732:                        file_mode = "r+b";
                    733:                        break;
                    734:                case 'c': 
                    735:                        modenr = DBA_CREAT; 
                    736:                        lock_mode = (lock_flag & DBA_LOCK_CREAT) ? LOCK_EX : 0;
                    737:                        if (lock_mode) {
                    738:                                if (lock_dbf) {
                    739:                                        /* the create/append check will be done on the lock
                    740:                                         * when the lib opens the file it is already created
                    741:                                         */
                    742:                                        file_mode = "r+b";       /* read & write, seek 0 */
                    743:                                        lock_file_mode = "a+b";  /* append */
                    744:                                } else {
                    745:                                        file_mode = "a+b";       /* append */
                    746:                                        lock_file_mode = "w+b";  /* create/truncate */
                    747:                                }
                    748:                        } else {
                    749:                                file_mode = "a+b";
                    750:                        }
                    751:                        /* In case of the 'a+b' append mode, the handler is responsible 
                    752:                         * to handle any rewind problems (see flatfile handler).
                    753:                         */
                    754:                        break;
                    755:                case 'n':
                    756:                        modenr = DBA_TRUNC;
                    757:                        lock_mode = (lock_flag & DBA_LOCK_TRUNC) ? LOCK_EX : 0;
                    758:                        file_mode = "w+b";
                    759:                        break;
                    760:                default:
                    761:                        php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Illegal DBA mode");
                    762:                        FREENOW;
                    763:                        RETURN_FALSE;
                    764:        }
                    765:        if (!lock_file_mode) {
                    766:                lock_file_mode = file_mode;
                    767:        }
                    768:        if (*pmode=='d' || *pmode=='l' || *pmode=='-') {
                    769:                pmode++; /* done already - skip here */
                    770:        }
                    771:        if (*pmode=='t') {
                    772:                pmode++;
                    773:                if (!lock_flag) {
                    774:                        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)");
                    775:                        FREENOW;
                    776:                        RETURN_FALSE;
                    777:                }
                    778:                if (!lock_mode) {
                    779:                        if ((hptr->flags & DBA_LOCK_ALL) == 0) {
                    780:                                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);
                    781:                                FREENOW;
                    782:                                RETURN_FALSE;
                    783:                        } else {
                    784:                                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);
                    785:                                FREENOW;
                    786:                                RETURN_FALSE;
                    787:                        }
                    788:                } else {
                    789:                        lock_mode |= LOCK_NB; /* test =: non blocking */
                    790:                }
                    791:        }
                    792:        if (*pmode) {
                    793:                php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Illegal DBA mode");
                    794:                FREENOW;
                    795:                RETURN_FALSE;
                    796:        }
                    797:                        
                    798:        info = pemalloc(sizeof(dba_info), persistent);
                    799:        memset(info, 0, sizeof(dba_info));
                    800:        info->path = pestrdup(Z_STRVAL_PP(args[0]), persistent);
                    801:        info->mode = modenr;
                    802:        info->argc = ac - 3;
                    803:        info->argv = args + 3;
                    804:        info->flags = (hptr->flags & ~DBA_LOCK_ALL) | (lock_flag & DBA_LOCK_ALL) | (persistent ? DBA_PERSISTENT : 0);
                    805:        info->lock.mode = lock_mode;
                    806: 
                    807:        /* if any open call is a locking call:
                    808:         * check if we already habe a locking call open that should block this call
                    809:         * the problem is some systems would allow read during write
                    810:         */
                    811:        if (hptr->flags & DBA_LOCK_ALL) {
                    812:                if ((other = php_dba_find(info->path TSRMLS_CC)) != NULL) {
                    813:                        if (   ( (lock_mode&LOCK_EX)        && (other->lock.mode&(LOCK_EX|LOCK_SH)) )
                    814:                            || ( (other->lock.mode&LOCK_EX) && (lock_mode&(LOCK_EX|LOCK_SH))        )
                    815:                           ) {
                    816:                                error = "Unable to establish lock (database file already open)"; /* force failure exit */
                    817:                        }
                    818:                }
                    819:        }
                    820: 
                    821:        if (!error && lock_mode) {
                    822:                if (lock_dbf) {
                    823:                        lock_name = Z_STRVAL_PP(args[0]);
                    824:                } else {
                    825:                        spprintf(&lock_name, 0, "%s.lck", info->path);
                    826:                        if (!strcmp(file_mode, "r")) {
                    827:                                /* when in read only mode try to use existing .lck file first */
                    828:                                /* do not log errors for .lck file while in read ony mode on .lck file */
                    829:                                lock_file_mode = "rb";
1.1.1.2 ! misho     830:                                info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|IGNORE_PATH|persistent_flag, &opened_path);
1.1       misho     831:                        }
                    832:                        if (!info->lock.fp) {
                    833:                                /* when not in read mode or failed to open .lck file read only. now try again in create(write) mode and log errors */
                    834:                                lock_file_mode = "a+b";
                    835:                        } else {
                    836:                                if (!persistent) {
                    837:                                        info->lock.name = opened_path;
                    838:                                } else {
                    839:                                        info->lock.name = pestrdup(opened_path, persistent);
                    840:                                        efree(opened_path);
                    841:                                }
                    842:                        }
                    843:                }
                    844:                if (!info->lock.fp) {
1.1.1.2 ! misho     845:                        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     846:                        if (info->lock.fp) {
                    847:                                if (lock_dbf) {
                    848:                                        /* replace the path info with the real path of the opened file */
                    849:                                        pefree(info->path, persistent);
                    850:                                        info->path = pestrdup(opened_path, persistent);
                    851:                                }
                    852:                                /* now store the name of the lock */
                    853:                                if (!persistent) {
                    854:                                        info->lock.name = opened_path;
                    855:                                } else {
                    856:                                        info->lock.name = pestrdup(opened_path, persistent);
                    857:                                        efree(opened_path);
                    858:                                }
                    859:                        }
                    860:                }
                    861:                if (!lock_dbf) {
                    862:                        efree(lock_name);
                    863:                }
                    864:                if (!info->lock.fp) {
                    865:                        dba_close(info TSRMLS_CC);
                    866:                        /* stream operation already wrote an error message */
                    867:                        FREENOW;
                    868:                        RETURN_FALSE;
                    869:                }
                    870:                if (!php_stream_supports_lock(info->lock.fp)) {
                    871:                        error = "Stream does not support locking";
                    872:                }
                    873:                if (php_stream_lock(info->lock.fp, lock_mode)) {
                    874:                        error = "Unable to establish lock"; /* force failure exit */
                    875:                }
                    876:        }
                    877: 
                    878:        /* centralised open stream for builtin */
                    879:        if (!error && (hptr->flags&DBA_STREAM_OPEN)==DBA_STREAM_OPEN) {
                    880:                if (info->lock.fp && lock_dbf) {
                    881:                        info->fp = info->lock.fp; /* use the same stream for locking and database access */
                    882:                } else {
1.1.1.2 ! misho     883:                        info->fp = php_stream_open_wrapper(info->path, file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, NULL);
1.1       misho     884:                }
                    885:                if (!info->fp) {
                    886:                        dba_close(info TSRMLS_CC);
                    887:                        /* stream operation already wrote an error message */
                    888:                        FREENOW;
                    889:                        RETURN_FALSE;
                    890:                }
                    891:                if (hptr->flags & (DBA_NO_APPEND|DBA_CAST_AS_FD)) {
                    892:                        /* Needed becasue some systems do not allow to write to the original 
                    893:                         * file contents with O_APPEND being set.
                    894:                         */
                    895:                        if (SUCCESS != php_stream_cast(info->fp, PHP_STREAM_AS_FD, (void*)&info->fd, 1)) {
                    896:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not cast stream");
                    897:                                dba_close(info TSRMLS_CC);
                    898:                                FREENOW;
                    899:                                RETURN_FALSE;
                    900: #ifdef F_SETFL
                    901:                        } else if (modenr == DBA_CREAT) {
                    902:                                int flags = fcntl(info->fd, F_SETFL);
                    903:                                fcntl(info->fd, F_SETFL, flags & ~O_APPEND);
                    904: #endif
                    905:                        }
                    906:                                
                    907:                }
                    908:        }
                    909: 
                    910:        if (error || hptr->open(info, &error TSRMLS_CC) != SUCCESS) {
                    911:                dba_close(info TSRMLS_CC);
                    912:                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:"");
                    913:                FREENOW;
                    914:                RETURN_FALSE;
                    915:        }
                    916: 
                    917:        info->hnd = hptr;
                    918:        info->argc = 0;
                    919:        info->argv = NULL;
                    920: 
                    921:        if (persistent) {
                    922:                zend_rsrc_list_entry new_le;
                    923: 
                    924:                Z_TYPE(new_le) = le_pdb;
                    925:                new_le.ptr = info;
                    926:                if (zend_hash_update(&EG(persistent_list), key, keylen+1, &new_le, sizeof(zend_rsrc_list_entry), NULL) == FAILURE) {
                    927:                        dba_close(info TSRMLS_CC);
                    928:                        php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Could not register persistent resource");
                    929:                        FREENOW;
                    930:                        RETURN_FALSE;
                    931:                }
                    932:        }
                    933: 
                    934:        ZEND_REGISTER_RESOURCE(return_value, info, (persistent ? le_pdb : le_db));
                    935:        FREENOW;
                    936: }
                    937: /* }}} */
                    938: #undef FREENOW
                    939: 
                    940: /* {{{ proto resource dba_popen(string path, string mode [, string handlername, string ...])
                    941:    Opens path using the specified handler in mode persistently */
                    942: PHP_FUNCTION(dba_popen)
                    943: {
                    944:        php_dba_open(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
                    945: }
                    946: /* }}} */
                    947: 
                    948: /* {{{ proto resource dba_open(string path, string mode [, string handlername, string ...])
                    949:    Opens path using the specified handler in mode*/
                    950: PHP_FUNCTION(dba_open)
                    951: {
                    952:        php_dba_open(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
                    953: }
                    954: /* }}} */
                    955: 
                    956: /* {{{ proto void dba_close(resource handle)
                    957:    Closes database */
                    958: PHP_FUNCTION(dba_close)
                    959: {
                    960:        zval *id;
                    961:        dba_info *info = NULL;
                    962: 
                    963:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
                    964:                return;
                    965:        }
                    966: 
                    967:        DBA_FETCH_RESOURCE(info, &id);
                    968: 
                    969:        zend_list_delete(Z_RESVAL_P(id));
                    970: }
                    971: /* }}} */
                    972: 
                    973: /* {{{ proto bool dba_exists(string key, resource handle)
                    974:    Checks, if the specified key exists */
                    975: PHP_FUNCTION(dba_exists)
                    976: {
                    977:        DBA_ID_GET2;
                    978: 
                    979:        if(info->hnd->exists(info, key_str, key_len TSRMLS_CC) == SUCCESS) {
                    980:                DBA_ID_DONE;
                    981:                RETURN_TRUE;
                    982:        }
                    983:        DBA_ID_DONE;
                    984:        RETURN_FALSE;
                    985: }
                    986: /* }}} */
                    987: 
                    988: /* {{{ proto string dba_fetch(string key, [int skip ,] resource handle)
                    989:    Fetches the data associated with key */
                    990: PHP_FUNCTION(dba_fetch)
                    991: {
                    992:        char *val;
                    993:        int len = 0;
                    994:        DBA_ID_GET2_3;
                    995: 
                    996:        if (ac==3) {
                    997:                if (!strcmp(info->hnd->name, "cdb")) {
                    998:                        if (skip < 0) {
                    999:                                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);
                   1000:                                skip = 0;
                   1001:                        }
                   1002:                } else if (!strcmp(info->hnd->name, "inifile")) {
                   1003:                        /* "-1" is compareable to 0 but allows a non restrictive 
                   1004:                         * access which is fater. For example 'inifile' uses this
                   1005:                         * to allow faster access when the key was already found
                   1006:                         * using firstkey/nextkey. However explicitly setting the
                   1007:                         * value to 0 ensures the first value. 
                   1008:                         */
                   1009:                        if (skip < -1) {
                   1010:                                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Handler %s accepts only skip value -1 and greater, using skip=0", info->hnd->name);
                   1011:                                skip = 0;
                   1012:                        }
                   1013:                } else {
                   1014:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Handler %s does not support optional skip parameter, the value will be ignored", info->hnd->name);
                   1015:                        skip = 0;                       
                   1016:                }
                   1017:        } else {
                   1018:                skip = 0; 
                   1019:        }
                   1020:        if((val = info->hnd->fetch(info, key_str, key_len, skip, &len TSRMLS_CC)) != NULL) {
                   1021:                DBA_ID_DONE;
                   1022:                RETURN_STRINGL(val, len, 0);
                   1023:        } 
                   1024:        DBA_ID_DONE;
                   1025:        RETURN_FALSE;
                   1026: }
                   1027: /* }}} */
                   1028: 
                   1029: /* {{{ proto array|false dba_key_split(string key)
                   1030:    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 */
                   1031: PHP_FUNCTION(dba_key_split)
                   1032: {
                   1033:        zval *zkey;
                   1034:        char *key, *name;
                   1035:        int key_len;
                   1036: 
                   1037:        if (ZEND_NUM_ARGS() != 1) {
                   1038:                WRONG_PARAM_COUNT;
                   1039:        }
                   1040:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &zkey) == SUCCESS) {
                   1041:                if (Z_TYPE_P(zkey) == IS_NULL || (Z_TYPE_P(zkey) == IS_BOOL && !Z_LVAL_P(zkey))) {
                   1042:                        RETURN_BOOL(0);
                   1043:                }
                   1044:        }
                   1045:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) {
                   1046:                RETURN_BOOL(0);
                   1047:        }
                   1048:        array_init(return_value);
                   1049:        if (key[0] == '[' && (name = strchr(key, ']')) != NULL) {
                   1050:                add_next_index_stringl(return_value, key+1, name - (key + 1), 1);
                   1051:                add_next_index_stringl(return_value, name+1, key_len - (name - key + 1), 1);
                   1052:        } else {
                   1053:                add_next_index_stringl(return_value, "", 0, 1);
                   1054:                add_next_index_stringl(return_value, key, key_len, 1);
                   1055:        }
                   1056: }
                   1057: /* }}} */
                   1058: 
                   1059: /* {{{ proto string dba_firstkey(resource handle)
                   1060:    Resets the internal key pointer and returns the first key */
                   1061: PHP_FUNCTION(dba_firstkey)
                   1062: {
                   1063:        char *fkey;
                   1064:        int len;
                   1065:        zval *id;
                   1066:        dba_info *info = NULL;
                   1067: 
                   1068:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
                   1069:                return;
                   1070:        }
                   1071: 
                   1072:        DBA_FETCH_RESOURCE(info, &id);
                   1073: 
                   1074:        fkey = info->hnd->firstkey(info, &len TSRMLS_CC);
                   1075: 
                   1076:        if (fkey)
                   1077:                RETURN_STRINGL(fkey, len, 0);
                   1078: 
                   1079:        RETURN_FALSE;
                   1080: }
                   1081: /* }}} */
                   1082: 
                   1083: /* {{{ proto string dba_nextkey(resource handle)
                   1084:    Returns the next key */
                   1085: PHP_FUNCTION(dba_nextkey)
                   1086: {
                   1087:        char *nkey;
                   1088:        int len;
                   1089:        zval *id;
                   1090:        dba_info *info = NULL;
                   1091: 
                   1092:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
                   1093:                return;
                   1094:        }
                   1095: 
                   1096:        DBA_FETCH_RESOURCE(info, &id);
                   1097: 
                   1098:        nkey = info->hnd->nextkey(info, &len TSRMLS_CC);
                   1099: 
                   1100:        if (nkey)
                   1101:                RETURN_STRINGL(nkey, len, 0);
                   1102: 
                   1103:        RETURN_FALSE;
                   1104: }
                   1105: /* }}} */
                   1106: 
                   1107: /* {{{ proto bool dba_delete(string key, resource handle)
                   1108:    Deletes the entry associated with key
                   1109:    If inifile: remove all other key lines */
                   1110: PHP_FUNCTION(dba_delete)
                   1111: {
                   1112:        DBA_ID_GET2;
                   1113:        
                   1114:        DBA_WRITE_CHECK;
                   1115:        
                   1116:        if(info->hnd->delete(info, key_str, key_len TSRMLS_CC) == SUCCESS)
                   1117:        {
                   1118:                DBA_ID_DONE;
                   1119:                RETURN_TRUE;
                   1120:        }
                   1121:        DBA_ID_DONE;
                   1122:        RETURN_FALSE;
                   1123: }
                   1124: /* }}} */
                   1125: 
                   1126: /* {{{ proto bool dba_insert(string key, string value, resource handle)
                   1127:    If not inifile: Insert value as key, return false, if key exists already 
                   1128:    If inifile: Add vakue as key (next instance of key) */
                   1129: PHP_FUNCTION(dba_insert)
                   1130: {
                   1131:        php_dba_update(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
                   1132: }
                   1133: /* }}} */
                   1134: 
                   1135: /* {{{ proto bool dba_replace(string key, string value, resource handle)
                   1136:    Inserts value as key, replaces key, if key exists already
                   1137:    If inifile: remove all other key lines */
                   1138: PHP_FUNCTION(dba_replace)
                   1139: {
                   1140:        php_dba_update(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
                   1141: }
                   1142: /* }}} */
                   1143: 
                   1144: /* {{{ proto bool dba_optimize(resource handle)
                   1145:    Optimizes (e.g. clean up, vacuum) database */
                   1146: PHP_FUNCTION(dba_optimize)
                   1147: {
                   1148:        zval *id;
                   1149:        dba_info *info = NULL;
                   1150: 
                   1151:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
                   1152:                return;
                   1153:        }
                   1154: 
                   1155:        DBA_FETCH_RESOURCE(info, &id);
                   1156: 
                   1157:        DBA_WRITE_CHECK;
                   1158: 
                   1159:        if (info->hnd->optimize(info TSRMLS_CC) == SUCCESS) {
                   1160:                RETURN_TRUE;
                   1161:        }
                   1162: 
                   1163:        RETURN_FALSE;
                   1164: }
                   1165: /* }}} */
                   1166: 
                   1167: /* {{{ proto bool dba_sync(resource handle)
                   1168:    Synchronizes database */
                   1169: PHP_FUNCTION(dba_sync)
                   1170: {
                   1171:        zval *id;
                   1172:        dba_info *info = NULL;
                   1173: 
                   1174:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
                   1175:                return;
                   1176:        }
                   1177: 
                   1178:        DBA_FETCH_RESOURCE(info, &id);
                   1179: 
                   1180:        if (info->hnd->sync(info TSRMLS_CC) == SUCCESS) {
                   1181:                RETURN_TRUE;
                   1182:        }
                   1183: 
                   1184:        RETURN_FALSE;
                   1185: }
                   1186: /* }}} */
                   1187: 
                   1188: /* {{{ proto array dba_handlers([bool full_info])
                   1189:    List configured database handlers */
                   1190: PHP_FUNCTION(dba_handlers)
                   1191: {
                   1192:        dba_handler *hptr;
                   1193:        zend_bool full_info = 0;
                   1194: 
                   1195:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &full_info) == FAILURE) {
                   1196:                RETURN_FALSE;
                   1197:        }
                   1198: 
                   1199:        array_init(return_value);
                   1200: 
                   1201:        for(hptr = handler; hptr->name; hptr++) {
                   1202:                if (full_info) {
                   1203:                        add_assoc_string(return_value, hptr->name, hptr->info(hptr, NULL TSRMLS_CC), 0);
                   1204:                } else {
                   1205:                        add_next_index_string(return_value, hptr->name, 1);
                   1206:                }
                   1207:        }
                   1208: }
                   1209: /* }}} */
                   1210: 
                   1211: /* {{{ proto array dba_list()
                   1212:    List opened databases */
                   1213: PHP_FUNCTION(dba_list)
                   1214: {
                   1215:        ulong numitems, i;
                   1216:        zend_rsrc_list_entry *le;
                   1217:        dba_info *info;
                   1218: 
                   1219:        if (zend_parse_parameters_none() == FAILURE) {
                   1220:                RETURN_FALSE;
                   1221:        }
                   1222: 
                   1223:        array_init(return_value);
                   1224: 
                   1225:        numitems = zend_hash_next_free_element(&EG(regular_list));
                   1226:        for (i=1; i<numitems; i++) {
                   1227:                if (zend_hash_index_find(&EG(regular_list), i, (void **) &le)==FAILURE) {
                   1228:                        continue;
                   1229:                }
                   1230:                if (Z_TYPE_P(le) == le_db || Z_TYPE_P(le) == le_pdb) {
                   1231:                        info = (dba_info *)(le->ptr);
                   1232:                        add_index_string(return_value, i, info->path, 1);
                   1233:                }
                   1234:        }
                   1235: }
                   1236: /* }}} */
                   1237: 
                   1238: #endif /* HAVE_DBA */
                   1239: 
                   1240: /*
                   1241:  * Local variables:
                   1242:  * tab-width: 4
                   1243:  * c-basic-offset: 4
                   1244:  * End:
                   1245:  * vim600: sw=4 ts=4 fdm=marker
                   1246:  * vim<600: sw=4 ts=4
                   1247:  */

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