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 : | Author: Wez Furlong <wez@php.net> |
16 : +----------------------------------------------------------------------+
17 : */
18 :
19 : /* $Id: sqlite_driver.c 276986 2009-03-10 23:40:06Z helly $ */
20 :
21 : #ifdef HAVE_CONFIG_H
22 : #include "config.h"
23 : #endif
24 :
25 : #include "php.h"
26 : #include "php_ini.h"
27 : #include "ext/standard/info.h"
28 : #include "pdo/php_pdo.h"
29 : #include "pdo/php_pdo_driver.h"
30 : #include "php_pdo_sqlite.h"
31 : #include "php_pdo_sqlite_int.h"
32 : #include "zend_exceptions.h"
33 :
34 : int _pdo_sqlite_error_msg(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *sqlstate, const char *msg,
35 : const char *file, int line TSRMLS_DC)
36 0 : {
37 0 : pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
38 0 : pdo_error_type *pdo_err = stmt ? &stmt->error_code : &dbh->error_code;
39 0 : pdo_sqlite_error_info *einfo = &H->einfo;
40 :
41 0 : einfo->errcode = SQLITE_ERROR;
42 0 : einfo->file = file;
43 0 : einfo->line = line;
44 0 : einfo->errmsg = pestrdup(msg, dbh->is_persistent);
45 0 : if (sqlstate) {
46 0 : strcpy(*pdo_err, sqlstate);
47 : } else {
48 0 : strcpy(*pdo_err, "HY000");
49 : }
50 :
51 0 : if (!dbh->methods) {
52 0 : zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "SQLSTATE[%s] [%d] %s",
53 : *pdo_err, einfo->errcode, einfo->errmsg);
54 : }
55 0 : return einfo->errcode;
56 : }
57 :
58 : int _pdo_sqlite_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int line TSRMLS_DC) /* {{{ */
59 288 : {
60 288 : pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
61 288 : pdo_error_type *pdo_err = stmt ? &stmt->error_code : &dbh->error_code;
62 288 : pdo_sqlite_error_info *einfo = &H->einfo;
63 :
64 288 : einfo->errcode = sqlite3_errcode(H->db);
65 288 : einfo->file = file;
66 288 : einfo->line = line;
67 :
68 288 : if (einfo->errcode != SQLITE_OK) {
69 288 : if (einfo->errmsg) {
70 195 : pefree(einfo->errmsg, dbh->is_persistent);
71 : }
72 288 : einfo->errmsg = pestrdup((char*)sqlite3_errmsg(H->db), dbh->is_persistent);
73 : } else { /* no error */
74 0 : strcpy(*pdo_err, PDO_ERR_NONE);
75 0 : return 0;
76 : }
77 288 : switch (einfo->errcode) {
78 : case SQLITE_NOTFOUND:
79 0 : strcpy(*pdo_err, "42S02");
80 0 : break;
81 :
82 : case SQLITE_INTERRUPT:
83 0 : strcpy(*pdo_err, "01002");
84 0 : break;
85 :
86 : case SQLITE_NOLFS:
87 0 : strcpy(*pdo_err, "HYC00");
88 0 : break;
89 :
90 : case SQLITE_TOOBIG:
91 0 : strcpy(*pdo_err, "22001");
92 0 : break;
93 :
94 : case SQLITE_CONSTRAINT:
95 0 : strcpy(*pdo_err, "23000");
96 0 : break;
97 :
98 : case SQLITE_ERROR:
99 : default:
100 288 : strcpy(*pdo_err, "HY000");
101 : break;
102 : }
103 :
104 288 : if (!dbh->methods) {
105 0 : zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "SQLSTATE[%s] [%d] %s",
106 : *pdo_err, einfo->errcode, einfo->errmsg);
107 : }
108 :
109 288 : return einfo->errcode;
110 : }
111 : /* }}} */
112 :
113 : static int pdo_sqlite_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC)
114 22 : {
115 22 : pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
116 22 : pdo_sqlite_error_info *einfo = &H->einfo;
117 :
118 22 : if (einfo->errcode) {
119 21 : add_next_index_long(info, einfo->errcode);
120 21 : add_next_index_string(info, einfo->errmsg, 1);
121 : }
122 :
123 22 : return 1;
124 : }
125 :
126 : static void pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle *H TSRMLS_DC)
127 129 : {
128 : struct pdo_sqlite_func *func;
129 :
130 258 : while (H->funcs) {
131 0 : func = H->funcs;
132 0 : H->funcs = func->next;
133 :
134 0 : if (H->db) {
135 : /* delete the function from the handle */
136 0 : sqlite3_create_function(H->db,
137 : func->funcname,
138 : func->argc,
139 : SQLITE_UTF8,
140 : func,
141 : NULL, NULL, NULL);
142 : }
143 :
144 0 : efree((char*)func->funcname);
145 0 : if (func->func) {
146 0 : zval_ptr_dtor(&func->func);
147 : }
148 0 : if (func->step) {
149 0 : zval_ptr_dtor(&func->step);
150 : }
151 0 : if (func->fini) {
152 0 : zval_ptr_dtor(&func->fini);
153 : }
154 0 : efree(func);
155 : }
156 129 : }
157 :
158 : static int sqlite_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
159 125 : {
160 125 : pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
161 :
162 125 : if (H) {
163 125 : pdo_sqlite_error_info *einfo = &H->einfo;
164 :
165 125 : pdo_sqlite_cleanup_callbacks(H TSRMLS_CC);
166 125 : if (H->db) {
167 125 : sqlite3_close(H->db);
168 125 : H->db = NULL;
169 : }
170 125 : if (einfo->errmsg) {
171 92 : pefree(einfo->errmsg, dbh->is_persistent);
172 92 : einfo->errmsg = NULL;
173 : }
174 125 : pefree(H, dbh->is_persistent);
175 125 : dbh->driver_data = NULL;
176 : }
177 125 : return 0;
178 : }
179 : /* }}} */
180 :
181 : static int sqlite_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC)
182 125 : {
183 125 : pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
184 125 : pdo_sqlite_stmt *S = ecalloc(1, sizeof(pdo_sqlite_stmt));
185 : int i;
186 : const char *tail;
187 :
188 125 : S->H = H;
189 125 : stmt->driver_data = S;
190 125 : stmt->methods = &sqlite_stmt_methods;
191 125 : stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL|PDO_PLACEHOLDER_NAMED;
192 :
193 125 : if (PDO_CURSOR_FWDONLY != pdo_attr_lval(driver_options, PDO_ATTR_CURSOR, PDO_CURSOR_FWDONLY TSRMLS_CC)) {
194 0 : H->einfo.errcode = SQLITE_ERROR;
195 0 : pdo_sqlite_error(dbh);
196 0 : return 0;
197 : }
198 :
199 125 : i = sqlite3_prepare(H->db, sql, sql_len, &S->stmt, &tail);
200 125 : if (i == SQLITE_OK) {
201 124 : return 1;
202 : }
203 :
204 1 : pdo_sqlite_error(dbh);
205 :
206 1 : return 0;
207 : }
208 :
209 : static long sqlite_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC)
210 421 : {
211 421 : pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
212 421 : char *errmsg = NULL;
213 :
214 421 : if (sqlite3_exec(H->db, sql, NULL, NULL, &errmsg) != SQLITE_OK) {
215 277 : pdo_sqlite_error(dbh);
216 277 : if (errmsg)
217 277 : sqlite3_free(errmsg);
218 :
219 277 : return -1;
220 : } else {
221 144 : return sqlite3_changes(H->db);
222 : }
223 : }
224 :
225 : static char *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const char *name, int *len TSRMLS_DC)
226 1 : {
227 1 : pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
228 : char *id;
229 :
230 1 : id = php_pdo_int64_to_str(sqlite3_last_insert_rowid(H->db) TSRMLS_CC);
231 1 : *len = strlen(id);
232 1 : return id;
233 : }
234 :
235 : /* NB: doesn't handle binary strings... use prepared stmts for that */
236 : static int sqlite_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen, enum pdo_param_type paramtype TSRMLS_DC)
237 1 : {
238 1 : *quoted = safe_emalloc(2, unquotedlen, 3);
239 1 : sqlite3_snprintf(2*unquotedlen + 3, *quoted, "'%q'", unquoted);
240 1 : *quotedlen = strlen(*quoted);
241 1 : return 1;
242 : }
243 :
244 : static int sqlite_handle_begin(pdo_dbh_t *dbh TSRMLS_DC)
245 5 : {
246 5 : pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
247 5 : char *errmsg = NULL;
248 :
249 5 : if (sqlite3_exec(H->db, "BEGIN", NULL, NULL, &errmsg) != SQLITE_OK) {
250 0 : pdo_sqlite_error(dbh);
251 0 : if (errmsg)
252 0 : sqlite3_free(errmsg);
253 0 : return 0;
254 : }
255 5 : return 1;
256 : }
257 :
258 : static int sqlite_handle_commit(pdo_dbh_t *dbh TSRMLS_DC)
259 2 : {
260 2 : pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
261 2 : char *errmsg = NULL;
262 :
263 2 : if (sqlite3_exec(H->db, "COMMIT", NULL, NULL, &errmsg) != SQLITE_OK) {
264 0 : pdo_sqlite_error(dbh);
265 0 : if (errmsg)
266 0 : sqlite3_free(errmsg);
267 0 : return 0;
268 : }
269 2 : return 1;
270 : }
271 :
272 : static int sqlite_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
273 3 : {
274 3 : pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
275 3 : char *errmsg = NULL;
276 :
277 3 : if (sqlite3_exec(H->db, "ROLLBACK", NULL, NULL, &errmsg) != SQLITE_OK) {
278 0 : pdo_sqlite_error(dbh);
279 0 : if (errmsg)
280 0 : sqlite3_free(errmsg);
281 0 : return 0;
282 : }
283 3 : return 1;
284 : }
285 :
286 : static int pdo_sqlite_get_attribute(pdo_dbh_t *dbh, long attr, zval *return_value TSRMLS_DC)
287 0 : {
288 0 : switch (attr) {
289 : case PDO_ATTR_CLIENT_VERSION:
290 : case PDO_ATTR_SERVER_VERSION:
291 0 : ZVAL_STRING(return_value, (char *)sqlite3_libversion(), 1);
292 : break;
293 :
294 : default:
295 0 : return 0;
296 : }
297 :
298 0 : return 1;
299 : }
300 :
301 : static int pdo_sqlite_set_attr(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC)
302 4 : {
303 4 : pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
304 :
305 4 : switch (attr) {
306 : case PDO_ATTR_TIMEOUT:
307 0 : convert_to_long(val);
308 0 : sqlite3_busy_timeout(H->db, Z_LVAL_P(val) * 1000);
309 0 : return 1;
310 : }
311 4 : return 0;
312 : }
313 :
314 : static int do_callback(struct pdo_sqlite_fci *fc, zval *cb,
315 : int argc, sqlite3_value **argv, sqlite3_context *context,
316 : int is_agg TSRMLS_DC)
317 0 : {
318 0 : zval ***zargs = NULL;
319 0 : zval *retval = NULL;
320 : int i;
321 : int ret;
322 : int fake_argc;
323 0 : zval **agg_context = NULL;
324 :
325 0 : if (is_agg) {
326 0 : is_agg = 2;
327 : }
328 :
329 0 : fake_argc = argc + is_agg;
330 :
331 0 : fc->fci.size = sizeof(fc->fci);
332 0 : fc->fci.function_table = EG(function_table);
333 0 : fc->fci.function_name = cb;
334 0 : fc->fci.symbol_table = NULL;
335 0 : fc->fci.object_ptr = NULL;
336 0 : fc->fci.retval_ptr_ptr = &retval;
337 0 : fc->fci.param_count = fake_argc;
338 :
339 : /* build up the params */
340 :
341 0 : if (fake_argc) {
342 0 : zargs = (zval ***)safe_emalloc(fake_argc, sizeof(zval **), 0);
343 : }
344 :
345 0 : if (is_agg) {
346 : /* summon the aggregation context */
347 0 : agg_context = (zval**)sqlite3_aggregate_context(context, sizeof(zval*));
348 0 : if (!*agg_context) {
349 0 : MAKE_STD_ZVAL(*agg_context);
350 0 : ZVAL_NULL(*agg_context);
351 : }
352 0 : zargs[0] = agg_context;
353 :
354 0 : zargs[1] = emalloc(sizeof(zval*));
355 0 : MAKE_STD_ZVAL(*zargs[1]);
356 0 : ZVAL_LONG(*zargs[1], sqlite3_aggregate_count(context));
357 : }
358 :
359 0 : for (i = 0; i < argc; i++) {
360 0 : zargs[i + is_agg] = emalloc(sizeof(zval *));
361 0 : MAKE_STD_ZVAL(*zargs[i + is_agg]);
362 :
363 : /* get the value */
364 0 : switch (sqlite3_value_type(argv[i])) {
365 : case SQLITE_INTEGER:
366 0 : ZVAL_LONG(*zargs[i + is_agg], sqlite3_value_int(argv[i]));
367 0 : break;
368 :
369 : case SQLITE_FLOAT:
370 0 : ZVAL_DOUBLE(*zargs[i + is_agg], sqlite3_value_double(argv[i]));
371 0 : break;
372 :
373 : case SQLITE_NULL:
374 0 : ZVAL_NULL(*zargs[i + is_agg]);
375 0 : break;
376 :
377 : case SQLITE_BLOB:
378 : case SQLITE3_TEXT:
379 : default:
380 0 : ZVAL_STRINGL(*zargs[i + is_agg], (char*)sqlite3_value_text(argv[i]),
381 : sqlite3_value_bytes(argv[i]), 1);
382 : break;
383 : }
384 : }
385 :
386 :
387 0 : fc->fci.params = zargs;
388 :
389 :
390 0 : if ((ret = zend_call_function(&fc->fci, &fc->fcc TSRMLS_CC)) == FAILURE) {
391 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the callback");
392 : }
393 :
394 : /* clean up the params */
395 0 : if (zargs) {
396 0 : for (i = is_agg; i < fake_argc; i++) {
397 0 : zval_ptr_dtor(zargs[i]);
398 0 : efree(zargs[i]);
399 : }
400 0 : if (is_agg) {
401 0 : zval_ptr_dtor(zargs[1]);
402 0 : efree(zargs[1]);
403 : }
404 0 : efree(zargs);
405 : }
406 :
407 0 : if (!is_agg || !argv) {
408 : /* only set the sqlite return value if we are a scalar function,
409 : * or if we are finalizing an aggregate */
410 0 : if (retval) {
411 0 : switch (Z_TYPE_P(retval)) {
412 : case IS_LONG:
413 0 : sqlite3_result_int(context, Z_LVAL_P(retval));
414 0 : break;
415 :
416 : case IS_NULL:
417 0 : sqlite3_result_null(context);
418 0 : break;
419 :
420 : case IS_DOUBLE:
421 0 : sqlite3_result_double(context, Z_DVAL_P(retval));
422 0 : break;
423 :
424 : default:
425 0 : convert_to_string_ex(&retval);
426 0 : sqlite3_result_text(context, Z_STRVAL_P(retval),
427 : Z_STRLEN_P(retval), SQLITE_TRANSIENT);
428 : break;
429 : }
430 : } else {
431 0 : sqlite3_result_error(context, "failed to invoke callback", 0);
432 : }
433 :
434 0 : if (agg_context) {
435 0 : zval_ptr_dtor(agg_context);
436 : }
437 : } else {
438 : /* we're stepping in an aggregate; the return value goes into
439 : * the context */
440 0 : if (agg_context) {
441 0 : zval_ptr_dtor(agg_context);
442 : }
443 0 : if (retval) {
444 0 : *agg_context = retval;
445 0 : retval = NULL;
446 : } else {
447 0 : *agg_context = NULL;
448 : }
449 : }
450 :
451 0 : if (retval) {
452 0 : zval_ptr_dtor(&retval);
453 : }
454 :
455 0 : return ret;
456 : }
457 :
458 : static void php_sqlite3_func_callback(sqlite3_context *context, int argc,
459 : sqlite3_value **argv)
460 0 : {
461 0 : struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
462 : TSRMLS_FETCH();
463 :
464 0 : do_callback(&func->afunc, func->func, argc, argv, context, 0 TSRMLS_CC);
465 0 : }
466 :
467 : static void php_sqlite3_func_step_callback(sqlite3_context *context, int argc,
468 : sqlite3_value **argv)
469 0 : {
470 0 : struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
471 : TSRMLS_FETCH();
472 :
473 0 : do_callback(&func->astep, func->step, argc, argv, context, 1 TSRMLS_CC);
474 0 : }
475 :
476 : static void php_sqlite3_func_final_callback(sqlite3_context *context)
477 0 : {
478 0 : struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
479 : TSRMLS_FETCH();
480 :
481 0 : do_callback(&func->afini, func->fini, 0, NULL, context, 1 TSRMLS_CC);
482 0 : }
483 :
484 : /* {{{ bool SQLite::sqliteCreateFunction(string name, mixed callback [, int argcount])
485 : Registers a UDF with the sqlite db handle */
486 : static PHP_METHOD(SQLite, sqliteCreateFunction)
487 0 : {
488 : struct pdo_sqlite_func *func;
489 : zval *callback;
490 : char *func_name;
491 : int func_name_len;
492 0 : long argc = -1;
493 : pdo_dbh_t *dbh;
494 : pdo_sqlite_db_handle *H;
495 : int ret;
496 :
497 0 : if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l",
498 : &func_name, &func_name_len, &callback, &argc)) {
499 0 : RETURN_FALSE;
500 : }
501 :
502 0 : dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
503 0 : PDO_CONSTRUCT_CHECK;
504 :
505 0 : if (!zend_is_callable(callback, 0, NULL TSRMLS_CC)) {
506 0 : pdo_sqlite_errmsg(dbh, NULL, "callback is not callable");
507 0 : RETURN_FALSE;
508 : }
509 :
510 0 : H = (pdo_sqlite_db_handle *)dbh->driver_data;
511 :
512 0 : func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
513 :
514 0 : ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
515 : func, php_sqlite3_func_callback, NULL, NULL);
516 0 : if (ret == SQLITE_OK) {
517 0 : func->funcname = estrdup(func_name);
518 :
519 0 : MAKE_STD_ZVAL(func->func);
520 0 : *(func->func) = *callback;
521 0 : zval_copy_ctor(func->func);
522 0 : INIT_PZVAL(func->func);
523 :
524 0 : func->argc = argc;
525 :
526 0 : func->next = H->funcs;
527 0 : H->funcs = func;
528 :
529 0 : RETURN_TRUE;
530 : }
531 :
532 0 : efree(func);
533 0 : RETURN_FALSE;
534 : }
535 : /* }}} */
536 :
537 : /* {{{ bool SQLite::sqliteCreateAggregate(string name, mixed step, mixed fini [, int argcount])
538 : Registers a UDF with the sqlite db handle */
539 :
540 : /* The step function should have the prototype:
541 : mixed step(mixed $context, int $rownumber, $value [, $value2 [, ...]])
542 :
543 : $context will be null for the first row; on subsequent rows it will have
544 : the value that was previously returned from the step function; you should
545 : use this to maintain state for the aggregate.
546 :
547 : The fini function should have the prototype:
548 : mixed fini(mixed $context, int $rownumber)
549 :
550 : $context will hold the return value from the very last call to the step function.
551 : rownumber will hold the number of rows over which the aggregate was performed.
552 : The return value of this function will be used as the return value for this
553 : aggregate UDF.
554 : */
555 :
556 : static PHP_METHOD(SQLite, sqliteCreateAggregate)
557 0 : {
558 : struct pdo_sqlite_func *func;
559 : zval *step_callback, *fini_callback;
560 : char *func_name;
561 : int func_name_len;
562 0 : long argc = -1;
563 : pdo_dbh_t *dbh;
564 : pdo_sqlite_db_handle *H;
565 : int ret;
566 :
567 0 : if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szz|l",
568 : &func_name, &func_name_len, &step_callback, &fini_callback, &argc)) {
569 0 : RETURN_FALSE;
570 : }
571 :
572 0 : dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
573 0 : PDO_CONSTRUCT_CHECK;
574 :
575 0 : if (!zend_is_callable(step_callback, 0, NULL TSRMLS_CC)) {
576 0 : pdo_sqlite_errmsg(dbh, NULL, "step callback is not callable");
577 0 : RETURN_FALSE;
578 : }
579 0 : if (!zend_is_callable(fini_callback, 0, NULL TSRMLS_CC)) {
580 0 : pdo_sqlite_errmsg(dbh, NULL, "fini callback is not callable");
581 0 : RETURN_FALSE;
582 : }
583 :
584 0 : H = (pdo_sqlite_db_handle *)dbh->driver_data;
585 :
586 0 : func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
587 :
588 0 : ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
589 : func, NULL, php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
590 0 : if (ret == SQLITE_OK) {
591 0 : func->funcname = estrdup(func_name);
592 :
593 0 : MAKE_STD_ZVAL(func->step);
594 0 : *(func->step) = *step_callback;
595 0 : zval_copy_ctor(func->step);
596 0 : INIT_PZVAL(func->step);
597 :
598 0 : MAKE_STD_ZVAL(func->fini);
599 0 : *(func->fini) = *fini_callback;
600 0 : zval_copy_ctor(func->fini);
601 0 : INIT_PZVAL(func->fini);
602 :
603 0 : func->argc = argc;
604 :
605 0 : func->next = H->funcs;
606 0 : H->funcs = func;
607 :
608 0 : RETURN_TRUE;
609 : }
610 :
611 0 : efree(func);
612 0 : RETURN_FALSE;
613 : }
614 : /* }}} */
615 : static const zend_function_entry dbh_methods[] = {
616 : PHP_ME(SQLite, sqliteCreateFunction, NULL, ZEND_ACC_PUBLIC)
617 : PHP_ME(SQLite, sqliteCreateAggregate, NULL, ZEND_ACC_PUBLIC)
618 : {NULL, NULL, NULL}
619 : };
620 :
621 : static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind TSRMLS_DC)
622 2 : {
623 2 : switch (kind) {
624 : case PDO_DBH_DRIVER_METHOD_KIND_DBH:
625 2 : return dbh_methods;
626 :
627 : default:
628 0 : return NULL;
629 : }
630 : }
631 :
632 : static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh TSRMLS_DC)
633 4 : {
634 4 : pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
635 : /* unregister functions, so that they don't linger for the next
636 : * request */
637 4 : if (H) {
638 4 : pdo_sqlite_cleanup_callbacks(H TSRMLS_CC);
639 : }
640 4 : }
641 :
642 : static struct pdo_dbh_methods sqlite_methods = {
643 : sqlite_handle_closer,
644 : sqlite_handle_preparer,
645 : sqlite_handle_doer,
646 : sqlite_handle_quoter,
647 : sqlite_handle_begin,
648 : sqlite_handle_commit,
649 : sqlite_handle_rollback,
650 : pdo_sqlite_set_attr,
651 : pdo_sqlite_last_insert_id,
652 : pdo_sqlite_fetch_error_func,
653 : pdo_sqlite_get_attribute,
654 : NULL, /* check_liveness: not needed */
655 : get_driver_methods,
656 : pdo_sqlite_request_shutdown
657 : };
658 :
659 : static char *make_filename_safe(const char *filename TSRMLS_DC)
660 126 : {
661 126 : if (strncmp(filename, ":memory:", sizeof(":memory:")-1)) {
662 1 : char *fullpath = expand_filepath(filename, NULL TSRMLS_CC);
663 :
664 1 : if (!fullpath) {
665 0 : return NULL;
666 : }
667 :
668 : #if PHP_MAJOR_VERSION < 6
669 : if (PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
670 : efree(fullpath);
671 : return NULL;
672 : }
673 : #endif
674 :
675 1 : if (php_check_open_basedir(fullpath TSRMLS_CC)) {
676 0 : efree(fullpath);
677 0 : return NULL;
678 : }
679 1 : return fullpath;
680 : }
681 125 : return estrdup(filename);
682 : }
683 :
684 : static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
685 : const char *arg5, const char *arg6)
686 0 : {
687 : char *filename;
688 0 : switch (access_type) {
689 : case SQLITE_COPY: {
690 : TSRMLS_FETCH();
691 0 : filename = make_filename_safe(arg4 TSRMLS_CC);
692 0 : if (!filename) {
693 0 : return SQLITE_DENY;
694 : }
695 0 : efree(filename);
696 0 : return SQLITE_OK;
697 : }
698 :
699 : case SQLITE_ATTACH: {
700 : TSRMLS_FETCH();
701 0 : filename = make_filename_safe(arg3 TSRMLS_CC);
702 0 : if (!filename) {
703 0 : return SQLITE_DENY;
704 : }
705 0 : efree(filename);
706 0 : return SQLITE_OK;
707 : }
708 :
709 : default:
710 : /* access allowed */
711 0 : return SQLITE_OK;
712 : }
713 : }
714 :
715 : static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
716 126 : {
717 : pdo_sqlite_db_handle *H;
718 126 : int i, ret = 0;
719 126 : long timeout = 60;
720 : char *filename;
721 :
722 126 : H = pecalloc(1, sizeof(pdo_sqlite_db_handle), dbh->is_persistent);
723 :
724 126 : H->einfo.errcode = 0;
725 126 : H->einfo.errmsg = NULL;
726 126 : dbh->driver_data = H;
727 :
728 126 : filename = make_filename_safe(dbh->data_source TSRMLS_CC);
729 :
730 126 : if (!filename) {
731 0 : zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC,
732 : "safe_mode/open_basedir prohibits opening %s",
733 : dbh->data_source);
734 0 : goto cleanup;
735 : }
736 :
737 126 : i = sqlite3_open(filename, &H->db);
738 126 : efree(filename);
739 :
740 126 : if (i != SQLITE_OK) {
741 0 : pdo_sqlite_error(dbh);
742 0 : goto cleanup;
743 : }
744 :
745 126 : if (
746 : #if PHP_MAJOR_VERSION < 6
747 : PG(safe_mode) ||
748 : #endif
749 : (PG(open_basedir) && *PG(open_basedir))) {
750 0 : sqlite3_set_authorizer(H->db, authorizer, NULL);
751 : }
752 :
753 126 : if (driver_options) {
754 2 : timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout TSRMLS_CC);
755 : }
756 126 : sqlite3_busy_timeout(H->db, timeout * 1000);
757 :
758 126 : dbh->alloc_own_columns = 1;
759 126 : dbh->max_escaped_char_length = 2;
760 :
761 126 : ret = 1;
762 :
763 126 : cleanup:
764 126 : dbh->methods = &sqlite_methods;
765 :
766 126 : return ret;
767 : }
768 : /* }}} */
769 :
770 : pdo_driver_t pdo_sqlite_driver = {
771 : PDO_DRIVER_HEADER(sqlite),
772 : pdo_sqlite_handle_factory
773 : };
774 :
775 : /*
776 : * Local variables:
777 : * tab-width: 4
778 : * c-basic-offset: 4
779 : * End:
780 : * vim600: noet sw=4 ts=4 fdm=marker
781 : * vim<600: noet sw=4 ts=4
782 : */
|