1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 6 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 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 280739 2009-05-18 20:21:39Z scottmac $ */
21 :
22 : #ifdef HAVE_CONFIG_H
23 : #include "config.h"
24 : #endif
25 :
26 : #include "php.h"
27 :
28 : #if HAVE_DBA
29 :
30 : #include "php_ini.h"
31 : #include <stdio.h>
32 : #include <fcntl.h>
33 : #ifdef HAVE_SYS_FILE_H
34 : #include <sys/file.h>
35 : #endif
36 :
37 : #include "php_dba.h"
38 : #include "ext/standard/info.h"
39 : #include "ext/standard/php_string.h"
40 : #include "ext/standard/flock_compat.h"
41 :
42 : #include "php_gdbm.h"
43 : #include "php_ndbm.h"
44 : #include "php_dbm.h"
45 : #include "php_cdb.h"
46 : #include "php_db1.h"
47 : #include "php_db2.h"
48 : #include "php_db3.h"
49 : #include "php_db4.h"
50 : #include "php_flatfile.h"
51 : #include "php_inifile.h"
52 : #include "php_qdbm.h"
53 : #include "php_tcadb.h"
54 :
55 : /* {{{ arginfo */
56 : ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_popen, 0, 0, 2)
57 : ZEND_ARG_INFO(0, path)
58 : ZEND_ARG_INFO(0, mode)
59 : ZEND_ARG_INFO(0, handlername)
60 : ZEND_ARG_INFO(0, ...)
61 : ZEND_END_ARG_INFO()
62 :
63 : ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_open, 0, 0, 2)
64 : ZEND_ARG_INFO(0, path)
65 : ZEND_ARG_INFO(0, mode)
66 : ZEND_ARG_INFO(0, handlername)
67 : ZEND_ARG_INFO(0, ...)
68 : ZEND_END_ARG_INFO()
69 :
70 : ZEND_BEGIN_ARG_INFO(arginfo_dba_close, 0)
71 : ZEND_ARG_INFO(0, handle)
72 : ZEND_END_ARG_INFO()
73 :
74 : ZEND_BEGIN_ARG_INFO(arginfo_dba_exists, 0)
75 : ZEND_ARG_INFO(0, key)
76 : ZEND_ARG_INFO(0, handle)
77 : ZEND_END_ARG_INFO()
78 :
79 : ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_fetch, 0, 0, 2)
80 : ZEND_ARG_INFO(0, key)
81 : ZEND_ARG_INFO(0, skip)
82 : ZEND_ARG_INFO(0, handle)
83 : ZEND_END_ARG_INFO()
84 :
85 : ZEND_BEGIN_ARG_INFO(arginfo_dba_key_split, 0)
86 : ZEND_ARG_INFO(0, key)
87 : ZEND_END_ARG_INFO()
88 :
89 : ZEND_BEGIN_ARG_INFO(arginfo_dba_firstkey, 0)
90 : ZEND_ARG_INFO(0, handle)
91 : ZEND_END_ARG_INFO()
92 :
93 : ZEND_BEGIN_ARG_INFO(arginfo_dba_nextkey, 0)
94 : ZEND_ARG_INFO(0, handle)
95 : ZEND_END_ARG_INFO()
96 :
97 : ZEND_BEGIN_ARG_INFO(arginfo_dba_delete, 0)
98 : ZEND_ARG_INFO(0, key)
99 : ZEND_ARG_INFO(0, handle)
100 : ZEND_END_ARG_INFO()
101 :
102 : ZEND_BEGIN_ARG_INFO(arginfo_dba_insert, 0)
103 : ZEND_ARG_INFO(0, key)
104 : ZEND_ARG_INFO(0, value)
105 : ZEND_ARG_INFO(0, handle)
106 : ZEND_END_ARG_INFO()
107 :
108 : ZEND_BEGIN_ARG_INFO(arginfo_dba_replace, 0)
109 : ZEND_ARG_INFO(0, key)
110 : ZEND_ARG_INFO(0, value)
111 : ZEND_ARG_INFO(0, handle)
112 : ZEND_END_ARG_INFO()
113 :
114 : ZEND_BEGIN_ARG_INFO(arginfo_dba_optimize, 0)
115 : ZEND_ARG_INFO(0, handle)
116 : ZEND_END_ARG_INFO()
117 :
118 : ZEND_BEGIN_ARG_INFO(arginfo_dba_sync, 0)
119 : ZEND_ARG_INFO(0, handle)
120 : ZEND_END_ARG_INFO()
121 :
122 : ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_handlers, 0, 0, 0)
123 : ZEND_ARG_INFO(0, full_info)
124 : ZEND_END_ARG_INFO()
125 :
126 : ZEND_BEGIN_ARG_INFO(arginfo_dba_list, 0)
127 : ZEND_END_ARG_INFO()
128 :
129 : /* }}} */
130 :
131 : /* {{{ dba_functions[]
132 : */
133 : const zend_function_entry dba_functions[] = {
134 : PHP_FE(dba_open, arginfo_dba_open)
135 : PHP_FE(dba_popen, arginfo_dba_popen)
136 : PHP_FE(dba_close, arginfo_dba_close)
137 : PHP_FE(dba_delete, arginfo_dba_delete)
138 : PHP_FE(dba_exists, arginfo_dba_exists)
139 : PHP_FE(dba_fetch, arginfo_dba_fetch)
140 : PHP_FE(dba_insert, arginfo_dba_insert)
141 : PHP_FE(dba_replace, arginfo_dba_replace)
142 : PHP_FE(dba_firstkey, arginfo_dba_firstkey)
143 : PHP_FE(dba_nextkey, arginfo_dba_nextkey)
144 : PHP_FE(dba_optimize, arginfo_dba_optimize)
145 : PHP_FE(dba_sync, arginfo_dba_sync)
146 : PHP_FE(dba_handlers, arginfo_dba_handlers)
147 : PHP_FE(dba_list, arginfo_dba_list)
148 : PHP_FE(dba_key_split, arginfo_dba_key_split)
149 : {NULL, NULL, NULL}
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 330 : {
205 330 : if (Z_TYPE_P(key) == IS_ARRAY) {
206 : zval **group, **name;
207 : HashPosition pos;
208 : size_t len;
209 :
210 0 : if (zend_hash_num_elements(Z_ARRVAL_P(key)) != 2) {
211 0 : php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Key does not have exactly two elements: (key, name)");
212 0 : return -1;
213 : }
214 0 : zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(key), &pos);
215 0 : zend_hash_get_current_data_ex(Z_ARRVAL_P(key), (void **) &group, &pos);
216 0 : zend_hash_move_forward_ex(Z_ARRVAL_P(key), &pos);
217 0 : zend_hash_get_current_data_ex(Z_ARRVAL_P(key), (void **) &name, &pos);
218 0 : convert_to_string_ex(group);
219 0 : convert_to_string_ex(name);
220 0 : if (Z_STRLEN_PP(group) == 0) {
221 0 : *key_str = Z_STRVAL_PP(name);
222 0 : *key_free = NULL;
223 0 : return Z_STRLEN_PP(name);
224 : }
225 0 : len = spprintf(key_str, 0, "[%s]%s", Z_STRVAL_PP(group), Z_STRVAL_PP(name));
226 0 : *key_free = *key_str;
227 0 : return len;
228 : } else {
229 330 : *key_free = NULL;
230 :
231 330 : convert_to_string(key);
232 330 : *key_str = Z_STRVAL_P(key);
233 :
234 330 : 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 : int 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
341 : #if DBA_TCADB
342 : DBA_HND(tcadb, DBA_LOCK_ALL)
343 : #endif
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"
365 : #elif DBA_TCADB
366 : #define DBA_DEFAULT "tcadb"
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 70 : {
400 70 : if (info->hnd) {
401 61 : info->hnd->close(info TSRMLS_CC);
402 : }
403 70 : if (info->path) {
404 70 : pefree(info->path, info->flags&DBA_PERSISTENT);
405 : }
406 70 : if (info->fp && info->fp!=info->lock.fp) {
407 16 : if(info->flags&DBA_PERSISTENT) {
408 4 : php_stream_pclose(info->fp);
409 : } else {
410 12 : php_stream_close(info->fp);
411 : }
412 : }
413 70 : if (info->lock.fp) {
414 52 : if(info->flags&DBA_PERSISTENT) {
415 9 : php_stream_pclose(info->lock.fp);
416 : } else {
417 43 : php_stream_close(info->lock.fp);
418 : }
419 : }
420 70 : if (info->lock.name) {
421 52 : pefree(info->lock.name, info->flags&DBA_PERSISTENT);
422 : }
423 70 : pefree(info, info->flags&DBA_PERSISTENT);
424 70 : }
425 : /* }}} */
426 :
427 : /* {{{ dba_close_rsrc
428 : */
429 : static void dba_close_rsrc(zend_rsrc_list_entry *rsrc TSRMLS_DC)
430 61 : {
431 61 : dba_info *info = (dba_info *)rsrc->ptr;
432 :
433 61 : dba_close(info TSRMLS_CC);
434 61 : }
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 28 : {
440 28 : 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 15 : {
447 15 : dba_info *info = (dba_info *)rsrc->ptr;
448 :
449 : /* closes the resource by calling dba_close_rsrc() */
450 15 : zend_hash_apply_with_argument(&EG(persistent_list), (apply_func_arg_t) dba_close_pe_rsrc_deleter, info TSRMLS_CC);
451 15 : }
452 : /* }}} */
453 :
454 : /* {{{ PHP_INI
455 : */
456 : ZEND_INI_MH(OnUpdateDefaultHandler)
457 17007 : {
458 : dba_handler *hptr;
459 :
460 17007 : if (!strlen(new_value)) {
461 0 : DBA_G(default_hptr) = NULL;
462 0 : return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
463 : }
464 :
465 17007 : for (hptr = handler; hptr->name && strcasecmp(hptr->name, new_value); hptr++);
466 :
467 17007 : if (!hptr->name) {
468 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such handler: %s", new_value);
469 0 : return FAILURE;
470 : }
471 17007 : DBA_G(default_hptr) = hptr;
472 17007 : 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 17007 : {
484 17007 : dba_globals->default_handler = "";
485 17007 : dba_globals->default_hptr = NULL;
486 17007 : }
487 : /* }}} */
488 :
489 : /* {{{ PHP_MINIT_FUNCTION
490 : */
491 : PHP_MINIT_FUNCTION(dba)
492 17007 : {
493 17007 : REGISTER_INI_ENTRIES();
494 17007 : le_db = zend_register_list_destructors_ex(dba_close_rsrc, NULL, "dba", module_number);
495 17007 : le_pdb = zend_register_list_destructors_ex(dba_close_pe_rsrc, dba_close_rsrc, "dba persistent", module_number);
496 17007 : return SUCCESS;
497 : }
498 : /* }}} */
499 :
500 : /* {{{ PHP_MSHUTDOWN_FUNCTION
501 : */
502 : PHP_MSHUTDOWN_FUNCTION(dba)
503 17039 : {
504 17039 : UNREGISTER_INI_ENTRIES();
505 17039 : 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 43 : {
515 : dba_handler *hptr;
516 43 : smart_str handlers = {0};
517 :
518 301 : for(hptr = handler; hptr->name; hptr++) {
519 258 : smart_str_appends(&handlers, hptr->name);
520 258 : smart_str_appendc(&handlers, ' ');
521 : }
522 :
523 43 : php_info_print_table_start();
524 43 : php_info_print_table_row(2, "DBA support", "enabled");
525 43 : if (handlers.c) {
526 43 : smart_str_0(&handlers);
527 43 : php_info_print_table_row(2, "Supported handlers", handlers.c);
528 43 : smart_str_free(&handlers);
529 : } else {
530 0 : php_info_print_table_row(2, "Supported handlers", "none");
531 : }
532 43 : php_info_print_table_end();
533 43 : DISPLAY_INI_ENTRIES();
534 43 : }
535 : /* }}} */
536 :
537 : /* {{{ php_dba_update
538 : */
539 : static void php_dba_update(INTERNAL_FUNCTION_PARAMETERS, int mode)
540 122 : {
541 : int val_len;
542 : zval *id;
543 122 : dba_info *info = NULL;
544 122 : int ac = ZEND_NUM_ARGS();
545 : zval *key;
546 : char *val;
547 : char *key_str, *key_free;
548 : size_t key_len;
549 :
550 122 : if (zend_parse_parameters(ac TSRMLS_CC, "zsr", &key, &val, &val_len, &id) == FAILURE) {
551 0 : return;
552 : }
553 :
554 122 : if ((key_len = php_dba_make_key(key, &key_str, &key_free TSRMLS_CC)) == 0) {
555 0 : RETURN_FALSE;
556 : }
557 :
558 122 : DBA_FETCH_RESOURCE(info, &id);
559 :
560 122 : DBA_WRITE_CHECK;
561 :
562 122 : if(info->hnd->update(info, key_str, key_len, val, val_len, mode TSRMLS_CC) == SUCCESS)
563 : {
564 119 : DBA_ID_DONE;
565 119 : RETURN_TRUE;
566 : }
567 3 : DBA_ID_DONE;
568 3 : RETURN_FALSE;
569 : }
570 : /* }}} */
571 :
572 : #define FREENOW if(args) efree(args); if(key) efree(key)
573 :
574 : /* {{{ php_find_dbm
575 : */
576 : dba_info *php_dba_find(const char* path TSRMLS_DC)
577 65 : {
578 : zend_rsrc_list_entry *le;
579 : dba_info *info;
580 : int numitems, i;
581 :
582 65 : numitems = zend_hash_next_free_element(&EG(regular_list));
583 1333 : for (i=1; i<numitems; i++) {
584 1281 : if (zend_hash_index_find(&EG(regular_list), i, (void **) &le)==FAILURE) {
585 989 : continue;
586 : }
587 292 : if (Z_TYPE_P(le) == le_db || Z_TYPE_P(le) == le_pdb) {
588 16 : info = (dba_info *)(le->ptr);
589 16 : if (!strcmp(info->path, path)) {
590 13 : return (dba_info *)(le->ptr);
591 : }
592 : }
593 : }
594 :
595 52 : return NULL;
596 : }
597 : /* }}} */
598 :
599 : /* {{{ php_dba_open
600 : */
601 : static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
602 70 : {
603 70 : zval ***args = (zval ***) NULL;
604 70 : int ac = ZEND_NUM_ARGS();
605 : dba_mode_t modenr;
606 : dba_info *info, *other;
607 : dba_handler *hptr;
608 70 : char *key = NULL, *error = NULL;
609 70 : int keylen = 0;
610 : int i;
611 70 : int lock_mode, lock_flag, lock_dbf = 0;
612 : char *file_mode;
613 70 : char mode[4], *pmode, *lock_file_mode = NULL;
614 70 : int persistent_flag = persistent ? STREAM_OPEN_PERSISTENT : 0;
615 : char *opened_path, *lock_name;
616 :
617 70 : if(ac < 2) {
618 0 : WRONG_PARAM_COUNT;
619 : }
620 :
621 : /* we pass additional args to the respective handler */
622 70 : args = safe_emalloc(ac, sizeof(zval *), 0);
623 70 : if (zend_get_parameters_array_ex(ac, args) != SUCCESS) {
624 0 : FREENOW;
625 0 : WRONG_PARAM_COUNT;
626 : }
627 :
628 : /* we only take string arguments */
629 280 : for (i = 0; i < ac; i++) {
630 210 : convert_to_string_ex(args[i]);
631 210 : keylen += Z_STRLEN_PP(args[i]);
632 : }
633 :
634 70 : if (persistent) {
635 : zend_rsrc_list_entry *le;
636 :
637 : /* calculate hash */
638 15 : key = safe_emalloc(keylen, 1, 1);
639 15 : key[keylen] = '\0';
640 15 : keylen = 0;
641 :
642 60 : for(i = 0; i < ac; i++) {
643 45 : memcpy(key+keylen, Z_STRVAL_PP(args[i]), Z_STRLEN_PP(args[i]));
644 45 : keylen += Z_STRLEN_PP(args[i]);
645 : }
646 :
647 : /* try to find if we already have this link in our persistent list */
648 15 : if (zend_hash_find(&EG(persistent_list), key, keylen+1, (void **) &le) == SUCCESS) {
649 0 : FREENOW;
650 :
651 0 : if (Z_TYPE_P(le) != le_pdb) {
652 0 : RETURN_FALSE;
653 : }
654 :
655 0 : info = (dba_info *)le->ptr;
656 :
657 0 : ZEND_REGISTER_RESOURCE(return_value, info, le_pdb);
658 0 : return;
659 : }
660 : }
661 :
662 70 : if (ac==2) {
663 0 : hptr = DBA_G(default_hptr);
664 0 : if (!hptr) {
665 0 : php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "No default handler selected");
666 0 : FREENOW;
667 0 : RETURN_FALSE;
668 : }
669 : } else {
670 70 : for (hptr = handler; hptr->name && strcasecmp(hptr->name, Z_STRVAL_PP(args[2])); hptr++);
671 : }
672 :
673 70 : if (!hptr->name) {
674 0 : php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "No such handler: %s", Z_STRVAL_PP(args[2]));
675 0 : FREENOW;
676 0 : RETURN_FALSE;
677 : }
678 :
679 : /* Check mode: [rwnc][fl]?t?
680 : * r: Read
681 : * w: Write
682 : * n: Create/Truncate
683 : * c: Create
684 : *
685 : * d: force lock on database file
686 : * l: force lock on lck file
687 : * -: ignore locking
688 : *
689 : * t: test open database, warning if locked
690 : */
691 70 : strlcpy(mode, Z_STRVAL_PP(args[1]), sizeof(mode));
692 70 : pmode = &mode[0];
693 94 : if (pmode[0] && (pmode[1]=='d' || pmode[1]=='l' || pmode[1]=='-')) { /* force lock on db file or lck file or disable locking */
694 24 : switch (pmode[1]) {
695 : case 'd':
696 0 : lock_dbf = 1;
697 0 : if ((hptr->flags & DBA_LOCK_ALL) == 0) {
698 0 : lock_flag = (hptr->flags & DBA_LOCK_ALL);
699 0 : break;
700 : }
701 : /* no break */
702 : case 'l':
703 19 : lock_flag = DBA_LOCK_ALL;
704 19 : if ((hptr->flags & DBA_LOCK_ALL) == 0) {
705 0 : php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_NOTICE, "Handler %s does locking internally", hptr->name);
706 : }
707 19 : break;
708 : default:
709 : case '-':
710 5 : if ((hptr->flags & DBA_LOCK_ALL) == 0) {
711 0 : php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Locking cannot be disabled for handler %s", hptr->name);
712 0 : FREENOW;
713 0 : RETURN_FALSE;
714 : }
715 5 : lock_flag = 0;
716 : break;
717 : }
718 : } else {
719 46 : lock_flag = (hptr->flags&DBA_LOCK_ALL);
720 46 : lock_dbf = 1;
721 : }
722 70 : switch (*pmode++) {
723 : case 'r':
724 34 : modenr = DBA_READER;
725 34 : lock_mode = (lock_flag & DBA_LOCK_READER) ? LOCK_SH : 0;
726 34 : file_mode = "r";
727 34 : break;
728 : case 'w':
729 0 : modenr = DBA_WRITER;
730 0 : lock_mode = (lock_flag & DBA_LOCK_WRITER) ? LOCK_EX : 0;
731 0 : file_mode = "r+b";
732 0 : break;
733 : case 'c':
734 12 : modenr = DBA_CREAT;
735 12 : lock_mode = (lock_flag & DBA_LOCK_CREAT) ? LOCK_EX : 0;
736 12 : if (lock_mode) {
737 11 : if (lock_dbf) {
738 : /* the create/append check will be done on the lock
739 : * when the lib opens the file it is already created
740 : */
741 7 : file_mode = "r+b"; /* read & write, seek 0 */
742 7 : lock_file_mode = "a+b"; /* append */
743 : } else {
744 4 : file_mode = "a+b"; /* append */
745 4 : lock_file_mode = "w+b"; /* create/truncate */
746 : }
747 : } else {
748 1 : file_mode = "a+b";
749 : }
750 : /* In case of the 'a+b' append mode, the handler is responsible
751 : * to handle any rewind problems (see flatfile handler).
752 : */
753 12 : break;
754 : case 'n':
755 24 : modenr = DBA_TRUNC;
756 24 : lock_mode = (lock_flag & DBA_LOCK_TRUNC) ? LOCK_EX : 0;
757 24 : file_mode = "w+b";
758 24 : break;
759 : default:
760 0 : php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Illegal DBA mode");
761 0 : FREENOW;
762 0 : RETURN_FALSE;
763 : }
764 70 : if (!lock_file_mode) {
765 59 : lock_file_mode = file_mode;
766 : }
767 70 : if (*pmode=='d' || *pmode=='l' || *pmode=='-') {
768 24 : pmode++; /* done already - skip here */
769 : }
770 70 : if (*pmode=='t') {
771 4 : pmode++;
772 4 : if (!lock_flag) {
773 0 : php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "You cannot combine modifiers - (no lock) and t (test lock)");
774 0 : FREENOW;
775 0 : RETURN_FALSE;
776 : }
777 4 : if (!lock_mode) {
778 0 : if ((hptr->flags & DBA_LOCK_ALL) == 0) {
779 0 : php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Handler %s uses its own locking which doesn't support mode modifier t (test lock)", hptr->name);
780 0 : FREENOW;
781 0 : RETURN_FALSE;
782 : } else {
783 0 : php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Handler %s doesn't uses locking for this mode which makes modifier t (test lock) obsolete", hptr->name);
784 0 : FREENOW;
785 0 : RETURN_FALSE;
786 : }
787 : } else {
788 4 : lock_mode |= LOCK_NB; /* test =: non blocking */
789 : }
790 : }
791 70 : if (*pmode) {
792 0 : php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Illegal DBA mode");
793 0 : FREENOW;
794 0 : RETURN_FALSE;
795 : }
796 :
797 70 : info = pemalloc(sizeof(dba_info), persistent);
798 70 : memset(info, 0, sizeof(dba_info));
799 70 : info->path = pestrdup(Z_STRVAL_PP(args[0]), persistent);
800 70 : info->mode = modenr;
801 70 : info->argc = ac - 3;
802 70 : info->argv = args + 3;
803 70 : info->flags = (hptr->flags & ~DBA_LOCK_ALL) | (lock_flag & DBA_LOCK_ALL) | (persistent ? DBA_PERSISTENT : 0);
804 70 : info->lock.mode = lock_mode;
805 :
806 : /* if any open call is a locking call:
807 : * check if we already habe a locking call open that should block this call
808 : * the problem is some systems would allow read during write
809 : */
810 70 : if (hptr->flags & DBA_LOCK_ALL) {
811 65 : if ((other = php_dba_find(info->path TSRMLS_CC)) != NULL) {
812 13 : if ( ( (lock_mode&LOCK_EX) && (other->lock.mode&(LOCK_EX|LOCK_SH)) )
813 : || ( (other->lock.mode&LOCK_EX) && (lock_mode&(LOCK_EX|LOCK_SH)) )
814 : ) {
815 8 : error = "Unable to establish lock (database file already open)"; /* force failure exit */
816 : }
817 : }
818 : }
819 :
820 70 : if (!error && lock_mode) {
821 52 : if (lock_dbf) {
822 37 : lock_name = Z_STRVAL_PP(args[0]);
823 : } else {
824 15 : spprintf(&lock_name, 0, "%s.lck", info->path);
825 15 : if (!strcmp(file_mode, "r")) {
826 : /* when in read only mode try to use existing .lck file first */
827 : /* do not log errors for .lck file while in read ony mode on .lck file */
828 6 : lock_file_mode = "rb";
829 6 : info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|IGNORE_PATH|persistent_flag, &opened_path);
830 : }
831 15 : if (!info->lock.fp) {
832 : /* when not in read mode or failed to open .lck file read only. now try again in create(write) mode and log errors */
833 9 : lock_file_mode = "a+b";
834 : } else {
835 6 : if (!persistent) {
836 6 : info->lock.name = opened_path;
837 : } else {
838 0 : info->lock.name = pestrdup(opened_path, persistent);
839 0 : efree(opened_path);
840 : }
841 : }
842 : }
843 52 : if (!info->lock.fp) {
844 46 : info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, &opened_path);
845 46 : if (info->lock.fp) {
846 46 : if (lock_dbf) {
847 : /* replace the path info with the real path of the opened file */
848 37 : pefree(info->path, persistent);
849 37 : info->path = pestrdup(opened_path, persistent);
850 : }
851 : /* now store the name of the lock */
852 46 : if (!persistent) {
853 37 : info->lock.name = opened_path;
854 : } else {
855 9 : info->lock.name = pestrdup(opened_path, persistent);
856 9 : efree(opened_path);
857 : }
858 : }
859 : }
860 52 : if (!lock_dbf) {
861 15 : efree(lock_name);
862 : }
863 52 : if (!info->lock.fp) {
864 0 : dba_close(info TSRMLS_CC);
865 : /* stream operation already wrote an error message */
866 0 : FREENOW;
867 0 : RETURN_FALSE;
868 : }
869 52 : if (!php_stream_supports_lock(info->lock.fp)) {
870 0 : error = "Stream does not support locking";
871 : }
872 52 : if (php_stream_lock(info->lock.fp, lock_mode)) {
873 0 : error = "Unable to establish lock"; /* force failure exit */
874 : }
875 : }
876 :
877 : /* centralised open stream for builtin */
878 70 : if (!error && (hptr->flags&DBA_STREAM_OPEN)==DBA_STREAM_OPEN) {
879 76 : if (info->lock.fp && lock_dbf) {
880 30 : info->fp = info->lock.fp; /* use the same stream for locking and database access */
881 : } else {
882 16 : info->fp = php_stream_open_wrapper(info->path, file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, NULL);
883 : }
884 46 : if (!info->fp) {
885 0 : dba_close(info TSRMLS_CC);
886 : /* stream operation already wrote an error message */
887 0 : FREENOW;
888 0 : RETURN_FALSE;
889 : }
890 46 : if (hptr->flags & (DBA_NO_APPEND|DBA_CAST_AS_FD)) {
891 : /* Needed becasue some systems do not allow to write to the original
892 : * file contents with O_APPEND being set.
893 : */
894 46 : if (SUCCESS != php_stream_cast(info->fp, PHP_STREAM_AS_FD, (void*)&info->fd, 1)) {
895 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not cast stream");
896 0 : dba_close(info TSRMLS_CC);
897 0 : FREENOW;
898 0 : RETURN_FALSE;
899 : #ifdef F_SETFL
900 46 : } else if (modenr == DBA_CREAT) {
901 6 : int flags = fcntl(info->fd, F_SETFL);
902 6 : fcntl(info->fd, F_SETFL, flags & ~O_APPEND);
903 : #endif
904 : }
905 :
906 : }
907 : }
908 :
909 70 : if (error || hptr->open(info, &error TSRMLS_CC) != SUCCESS) {
910 9 : dba_close(info TSRMLS_CC);
911 9 : php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Driver initialization failed for handler: %s%s%s", hptr->name, error?": ":"", error?error:"");
912 9 : FREENOW;
913 9 : RETURN_FALSE;
914 : }
915 :
916 61 : info->hnd = hptr;
917 61 : info->argc = 0;
918 61 : info->argv = NULL;
919 :
920 61 : if (persistent) {
921 : zend_rsrc_list_entry new_le;
922 :
923 15 : Z_TYPE(new_le) = le_pdb;
924 15 : new_le.ptr = info;
925 15 : if (zend_hash_update(&EG(persistent_list), key, keylen+1, &new_le, sizeof(zend_rsrc_list_entry), NULL) == FAILURE) {
926 0 : dba_close(info TSRMLS_CC);
927 0 : php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Could not register persistent resource");
928 0 : FREENOW;
929 0 : RETURN_FALSE;
930 : }
931 : }
932 :
933 61 : ZEND_REGISTER_RESOURCE(return_value, info, (persistent ? le_pdb : le_db));
934 61 : FREENOW;
935 : }
936 : /* }}} */
937 : #undef FREENOW
938 :
939 : /* {{{ proto resource dba_popen(string path, string mode [, string handlername, string ...])
940 : Opens path using the specified handler in mode persistently */
941 : PHP_FUNCTION(dba_popen)
942 15 : {
943 15 : php_dba_open(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
944 15 : }
945 : /* }}} */
946 :
947 : /* {{{ proto resource dba_open(string path, string mode [, string handlername, string ...])
948 : Opens path using the specified handler in mode*/
949 : PHP_FUNCTION(dba_open)
950 55 : {
951 55 : php_dba_open(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
952 55 : }
953 : /* }}} */
954 :
955 : /* {{{ proto void dba_close(resource handle)
956 : Closes database */
957 : PHP_FUNCTION(dba_close)
958 47 : {
959 : zval *id;
960 47 : dba_info *info = NULL;
961 :
962 47 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
963 0 : return;
964 : }
965 :
966 47 : DBA_FETCH_RESOURCE(info, &id);
967 :
968 47 : zend_list_delete(Z_RESVAL_P(id));
969 : }
970 : /* }}} */
971 :
972 : /* {{{ proto bool dba_exists(string key, resource handle)
973 : Checks, if the specified key exists */
974 : PHP_FUNCTION(dba_exists)
975 73 : {
976 73 : DBA_ID_GET2;
977 :
978 73 : if(info->hnd->exists(info, key_str, key_len TSRMLS_CC) == SUCCESS) {
979 50 : DBA_ID_DONE;
980 50 : RETURN_TRUE;
981 : }
982 23 : DBA_ID_DONE;
983 23 : RETURN_FALSE;
984 : }
985 : /* }}} */
986 :
987 : /* {{{ proto string dba_fetch(string key, [int skip ,] resource handle)
988 : Fetches the data associated with key */
989 : PHP_FUNCTION(dba_fetch)
990 106 : {
991 : char *val;
992 106 : int len = 0;
993 106 : DBA_ID_GET2_3;
994 :
995 106 : if (ac==3) {
996 7 : if (!strcmp(info->hnd->name, "cdb")) {
997 7 : if (skip < 0) {
998 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Handler %s accepts only skip values greater than or equal to zero, using skip=0", info->hnd->name);
999 0 : skip = 0;
1000 : }
1001 0 : } else if (!strcmp(info->hnd->name, "inifile")) {
1002 : /* "-1" is compareable to 0 but allows a non restrictive
1003 : * access which is fater. For example 'inifile' uses this
1004 : * to allow faster access when the key was already found
1005 : * using firstkey/nextkey. However explicitly setting the
1006 : * value to 0 ensures the first value.
1007 : */
1008 0 : if (skip < -1) {
1009 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Handler %s accepts only skip value -1 and greater, using skip=0", info->hnd->name);
1010 0 : skip = 0;
1011 : }
1012 : } else {
1013 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Handler %s does not support optional skip parameter, the value will be ignored", info->hnd->name);
1014 0 : skip = 0;
1015 : }
1016 : } else {
1017 99 : skip = 0;
1018 : }
1019 106 : if((val = info->hnd->fetch(info, key_str, key_len, skip, &len TSRMLS_CC)) != NULL) {
1020 106 : DBA_ID_DONE;
1021 106 : RETURN_STRINGL(val, len, 0);
1022 : }
1023 0 : DBA_ID_DONE;
1024 0 : RETURN_FALSE;
1025 : }
1026 : /* }}} */
1027 :
1028 : /* {{{ proto array|false dba_key_split(string key)
1029 : Splits an inifile key into an array of the form array(0=>group,1=>value_name) but returns false if input is false or null */
1030 : PHP_FUNCTION(dba_key_split)
1031 0 : {
1032 : zval *zkey;
1033 : char *key, *name;
1034 : int key_len;
1035 :
1036 0 : if (ZEND_NUM_ARGS() != 1) {
1037 0 : WRONG_PARAM_COUNT;
1038 : }
1039 0 : if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &zkey) == SUCCESS) {
1040 0 : if (Z_TYPE_P(zkey) == IS_NULL || (Z_TYPE_P(zkey) == IS_BOOL && !Z_LVAL_P(zkey))) {
1041 0 : RETURN_BOOL(0);
1042 : }
1043 : }
1044 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) {
1045 0 : RETURN_BOOL(0);
1046 : }
1047 0 : array_init(return_value);
1048 0 : if (key[0] == '[' && (name = strchr(key, ']')) != NULL) {
1049 0 : add_next_index_stringl(return_value, key+1, name - (key + 1), 1);
1050 0 : add_next_index_stringl(return_value, name+1, key_len - (name - key + 1), 1);
1051 : } else {
1052 0 : add_next_index_stringl(return_value, "", 0, 1);
1053 0 : add_next_index_stringl(return_value, key, key_len, 1);
1054 : }
1055 : }
1056 : /* }}} */
1057 :
1058 : /* {{{ proto string dba_firstkey(resource handle)
1059 : Resets the internal key pointer and returns the first key */
1060 : PHP_FUNCTION(dba_firstkey)
1061 26 : {
1062 : char *fkey;
1063 : int len;
1064 : zval *id;
1065 26 : dba_info *info = NULL;
1066 :
1067 26 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
1068 0 : return;
1069 : }
1070 :
1071 26 : DBA_FETCH_RESOURCE(info, &id);
1072 :
1073 26 : fkey = info->hnd->firstkey(info, &len TSRMLS_CC);
1074 :
1075 26 : if (fkey)
1076 26 : RETURN_STRINGL(fkey, len, 0);
1077 :
1078 0 : RETURN_FALSE;
1079 : }
1080 : /* }}} */
1081 :
1082 : /* {{{ proto string dba_nextkey(resource handle)
1083 : Returns the next key */
1084 : PHP_FUNCTION(dba_nextkey)
1085 93 : {
1086 : char *nkey;
1087 : int len;
1088 : zval *id;
1089 93 : dba_info *info = NULL;
1090 :
1091 93 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
1092 0 : return;
1093 : }
1094 :
1095 93 : DBA_FETCH_RESOURCE(info, &id);
1096 :
1097 93 : nkey = info->hnd->nextkey(info, &len TSRMLS_CC);
1098 :
1099 93 : if (nkey)
1100 67 : RETURN_STRINGL(nkey, len, 0);
1101 :
1102 26 : RETURN_FALSE;
1103 : }
1104 : /* }}} */
1105 :
1106 : /* {{{ proto bool dba_delete(string key, resource handle)
1107 : Deletes the entry associated with key
1108 : If inifile: remove all other key lines */
1109 : PHP_FUNCTION(dba_delete)
1110 29 : {
1111 29 : DBA_ID_GET2;
1112 :
1113 29 : DBA_WRITE_CHECK;
1114 :
1115 29 : if(info->hnd->delete(info, key_str, key_len TSRMLS_CC) == SUCCESS)
1116 : {
1117 29 : DBA_ID_DONE;
1118 29 : RETURN_TRUE;
1119 : }
1120 0 : DBA_ID_DONE;
1121 0 : RETURN_FALSE;
1122 : }
1123 : /* }}} */
1124 :
1125 : /* {{{ proto bool dba_insert(string key, string value, resource handle)
1126 : If not inifile: Insert value as key, return false, if key exists already
1127 : If inifile: Add vakue as key (next instance of key) */
1128 : PHP_FUNCTION(dba_insert)
1129 103 : {
1130 103 : php_dba_update(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1131 103 : }
1132 : /* }}} */
1133 :
1134 : /* {{{ proto bool dba_replace(string key, string value, resource handle)
1135 : Inserts value as key, replaces key, if key exists already
1136 : If inifile: remove all other key lines */
1137 : PHP_FUNCTION(dba_replace)
1138 19 : {
1139 19 : php_dba_update(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1140 19 : }
1141 : /* }}} */
1142 :
1143 : /* {{{ proto bool dba_optimize(resource handle)
1144 : Optimizes (e.g. clean up, vacuum) database */
1145 : PHP_FUNCTION(dba_optimize)
1146 0 : {
1147 : zval *id;
1148 0 : dba_info *info = NULL;
1149 :
1150 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
1151 0 : return;
1152 : }
1153 :
1154 0 : DBA_FETCH_RESOURCE(info, &id);
1155 :
1156 0 : DBA_WRITE_CHECK;
1157 :
1158 0 : if (info->hnd->optimize(info TSRMLS_CC) == SUCCESS) {
1159 0 : RETURN_TRUE;
1160 : }
1161 :
1162 0 : RETURN_FALSE;
1163 : }
1164 : /* }}} */
1165 :
1166 : /* {{{ proto bool dba_sync(resource handle)
1167 : Synchronizes database */
1168 : PHP_FUNCTION(dba_sync)
1169 0 : {
1170 : zval *id;
1171 0 : dba_info *info = NULL;
1172 :
1173 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
1174 0 : return;
1175 : }
1176 :
1177 0 : DBA_FETCH_RESOURCE(info, &id);
1178 :
1179 0 : if (info->hnd->sync(info TSRMLS_CC) == SUCCESS) {
1180 0 : RETURN_TRUE;
1181 : }
1182 :
1183 0 : RETURN_FALSE;
1184 : }
1185 : /* }}} */
1186 :
1187 : /* {{{ proto array dba_handlers([bool full_info])
1188 : List configured database handlers */
1189 : PHP_FUNCTION(dba_handlers)
1190 88 : {
1191 : dba_handler *hptr;
1192 88 : zend_bool full_info = 0;
1193 :
1194 88 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &full_info) == FAILURE) {
1195 0 : RETURN_FALSE;
1196 : }
1197 :
1198 88 : array_init(return_value);
1199 :
1200 616 : for(hptr = handler; hptr->name; hptr++) {
1201 528 : if (full_info) {
1202 0 : add_assoc_string(return_value, hptr->name, hptr->info(hptr, NULL TSRMLS_CC), 0);
1203 : } else {
1204 528 : add_next_index_string(return_value, hptr->name, 1);
1205 : }
1206 : }
1207 : }
1208 : /* }}} */
1209 :
1210 : /* {{{ proto array dba_list()
1211 : List opened databases */
1212 : PHP_FUNCTION(dba_list)
1213 1 : {
1214 : ulong numitems, i;
1215 : zend_rsrc_list_entry *le;
1216 : dba_info *info;
1217 :
1218 1 : if (ZEND_NUM_ARGS()!=0) {
1219 0 : ZEND_WRONG_PARAM_COUNT();
1220 : RETURN_FALSE;
1221 : }
1222 :
1223 1 : array_init(return_value);
1224 :
1225 1 : numitems = zend_hash_next_free_element(&EG(regular_list));
1226 13 : for (i=1; i<numitems; i++) {
1227 12 : if (zend_hash_index_find(&EG(regular_list), i, (void **) &le)==FAILURE) {
1228 2 : continue;
1229 : }
1230 10 : if (Z_TYPE_P(le) == le_db || Z_TYPE_P(le) == le_pdb) {
1231 3 : info = (dba_info *)(le->ptr);
1232 3 : 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 : */
|