1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Wez Furlong <wez@php.net> |
14 +----------------------------------------------------------------------+
15 */
16
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20
21 #include "php.h"
22 #include "php_ini.h"
23 #include "ext/standard/info.h"
24 #include "pdo/php_pdo.h"
25 #include "pdo/php_pdo_driver.h"
26 #include "php_pdo_sqlite.h"
27 #include "php_pdo_sqlite_int.h"
28 #include "zend_exceptions.h"
29 #include "sqlite_driver_arginfo.h"
30
_pdo_sqlite_error(pdo_dbh_t * dbh,pdo_stmt_t * stmt,const char * file,int line)31 int _pdo_sqlite_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int line) /* {{{ */
32 {
33 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
34 pdo_error_type *pdo_err = stmt ? &stmt->error_code : &dbh->error_code;
35 pdo_sqlite_error_info *einfo = &H->einfo;
36
37 einfo->errcode = sqlite3_errcode(H->db);
38 einfo->file = file;
39 einfo->line = line;
40
41 if (einfo->errcode != SQLITE_OK) {
42 if (einfo->errmsg) {
43 pefree(einfo->errmsg, dbh->is_persistent);
44 }
45 einfo->errmsg = pestrdup((char*)sqlite3_errmsg(H->db), dbh->is_persistent);
46 } else { /* no error */
47 strncpy(*pdo_err, PDO_ERR_NONE, sizeof(*pdo_err));
48 return 0;
49 }
50 switch (einfo->errcode) {
51 case SQLITE_NOTFOUND:
52 strncpy(*pdo_err, "42S02", sizeof(*pdo_err));
53 break;
54
55 case SQLITE_INTERRUPT:
56 strncpy(*pdo_err, "01002", sizeof(*pdo_err));
57 break;
58
59 case SQLITE_NOLFS:
60 strncpy(*pdo_err, "HYC00", sizeof(*pdo_err));
61 break;
62
63 case SQLITE_TOOBIG:
64 strncpy(*pdo_err, "22001", sizeof(*pdo_err));
65 break;
66
67 case SQLITE_CONSTRAINT:
68 strncpy(*pdo_err, "23000", sizeof(*pdo_err));
69 break;
70
71 case SQLITE_ERROR:
72 default:
73 strncpy(*pdo_err, "HY000", sizeof(*pdo_err));
74 break;
75 }
76
77 if (!dbh->methods) {
78 pdo_throw_exception(einfo->errcode, einfo->errmsg, pdo_err);
79 }
80
81 return einfo->errcode;
82 }
83 /* }}} */
84
pdo_sqlite_fetch_error_func(pdo_dbh_t * dbh,pdo_stmt_t * stmt,zval * info)85 static void pdo_sqlite_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info)
86 {
87 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
88 pdo_sqlite_error_info *einfo = &H->einfo;
89
90 if (einfo->errcode) {
91 add_next_index_long(info, einfo->errcode);
92 add_next_index_string(info, einfo->errmsg);
93 }
94 }
95
pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle * H)96 static void pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle *H)
97 {
98 struct pdo_sqlite_func *func;
99
100 while (H->funcs) {
101 func = H->funcs;
102 H->funcs = func->next;
103
104 if (H->db) {
105 /* delete the function from the handle */
106 sqlite3_create_function(H->db,
107 func->funcname,
108 func->argc,
109 SQLITE_UTF8,
110 func,
111 NULL, NULL, NULL);
112 }
113
114 efree((char*)func->funcname);
115 if (!Z_ISUNDEF(func->func)) {
116 zval_ptr_dtor(&func->func);
117 }
118 if (!Z_ISUNDEF(func->step)) {
119 zval_ptr_dtor(&func->step);
120 }
121 if (!Z_ISUNDEF(func->fini)) {
122 zval_ptr_dtor(&func->fini);
123 }
124 efree(func);
125 }
126
127 while (H->collations) {
128 struct pdo_sqlite_collation *collation;
129 collation = H->collations;
130 H->collations = collation->next;
131
132 if (H->db) {
133 /* delete the collation from the handle */
134 sqlite3_create_collation(H->db,
135 collation->name,
136 SQLITE_UTF8,
137 collation,
138 NULL);
139 }
140
141 efree((char*)collation->name);
142 if (!Z_ISUNDEF(collation->callback)) {
143 zval_ptr_dtor(&collation->callback);
144 }
145 efree(collation);
146 }
147 }
148
sqlite_handle_closer(pdo_dbh_t * dbh)149 static void sqlite_handle_closer(pdo_dbh_t *dbh) /* {{{ */
150 {
151 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
152
153 if (H) {
154 pdo_sqlite_error_info *einfo = &H->einfo;
155
156 pdo_sqlite_cleanup_callbacks(H);
157 if (H->db) {
158 #ifdef HAVE_SQLITE3_CLOSE_V2
159 sqlite3_close_v2(H->db);
160 #else
161 sqlite3_close(H->db);
162 #endif
163 H->db = NULL;
164 }
165 if (einfo->errmsg) {
166 pefree(einfo->errmsg, dbh->is_persistent);
167 einfo->errmsg = NULL;
168 }
169 pefree(H, dbh->is_persistent);
170 dbh->driver_data = NULL;
171 }
172 }
173 /* }}} */
174
sqlite_handle_preparer(pdo_dbh_t * dbh,zend_string * sql,pdo_stmt_t * stmt,zval * driver_options)175 static bool sqlite_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, pdo_stmt_t *stmt, zval *driver_options)
176 {
177 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
178 pdo_sqlite_stmt *S = ecalloc(1, sizeof(pdo_sqlite_stmt));
179 int i;
180 const char *tail;
181
182 S->H = H;
183 stmt->driver_data = S;
184 stmt->methods = &sqlite_stmt_methods;
185 stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL|PDO_PLACEHOLDER_NAMED;
186
187 if (PDO_CURSOR_FWDONLY != pdo_attr_lval(driver_options, PDO_ATTR_CURSOR, PDO_CURSOR_FWDONLY)) {
188 H->einfo.errcode = SQLITE_ERROR;
189 pdo_sqlite_error(dbh);
190 return false;
191 }
192
193 i = sqlite3_prepare_v2(H->db, ZSTR_VAL(sql), ZSTR_LEN(sql), &S->stmt, &tail);
194 if (i == SQLITE_OK) {
195 return true;
196 }
197
198 pdo_sqlite_error(dbh);
199
200 return false;
201 }
202
sqlite_handle_doer(pdo_dbh_t * dbh,const zend_string * sql)203 static zend_long sqlite_handle_doer(pdo_dbh_t *dbh, const zend_string *sql)
204 {
205 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
206 char *errmsg = NULL;
207
208 if (sqlite3_exec(H->db, ZSTR_VAL(sql), NULL, NULL, &errmsg) != SQLITE_OK) {
209 pdo_sqlite_error(dbh);
210 if (errmsg)
211 sqlite3_free(errmsg);
212
213 return -1;
214 } else {
215 return sqlite3_changes(H->db);
216 }
217 }
218
pdo_sqlite_last_insert_id(pdo_dbh_t * dbh,const zend_string * name)219 static zend_string *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const zend_string *name)
220 {
221 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
222
223 return zend_i64_to_str(sqlite3_last_insert_rowid(H->db));
224 }
225
226 /* NB: doesn't handle binary strings... use prepared stmts for that */
sqlite_handle_quoter(pdo_dbh_t * dbh,const zend_string * unquoted,enum pdo_param_type paramtype)227 static zend_string* sqlite_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype)
228 {
229 char *quoted;
230 if (ZSTR_LEN(unquoted) > (INT_MAX - 3) / 2) {
231 return NULL;
232 }
233 quoted = safe_emalloc(2, ZSTR_LEN(unquoted), 3);
234 /* TODO use %Q format? */
235 sqlite3_snprintf(2*ZSTR_LEN(unquoted) + 3, quoted, "'%q'", ZSTR_VAL(unquoted));
236 zend_string *quoted_str = zend_string_init(quoted, strlen(quoted), 0);
237 efree(quoted);
238 return quoted_str;
239 }
240
sqlite_handle_begin(pdo_dbh_t * dbh)241 static bool sqlite_handle_begin(pdo_dbh_t *dbh)
242 {
243 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
244 char *errmsg = NULL;
245
246 if (sqlite3_exec(H->db, "BEGIN", NULL, NULL, &errmsg) != SQLITE_OK) {
247 pdo_sqlite_error(dbh);
248 if (errmsg)
249 sqlite3_free(errmsg);
250 return false;
251 }
252 return true;
253 }
254
sqlite_handle_commit(pdo_dbh_t * dbh)255 static bool sqlite_handle_commit(pdo_dbh_t *dbh)
256 {
257 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
258 char *errmsg = NULL;
259
260 if (sqlite3_exec(H->db, "COMMIT", NULL, NULL, &errmsg) != SQLITE_OK) {
261 pdo_sqlite_error(dbh);
262 if (errmsg)
263 sqlite3_free(errmsg);
264 return false;
265 }
266 return true;
267 }
268
sqlite_handle_rollback(pdo_dbh_t * dbh)269 static bool sqlite_handle_rollback(pdo_dbh_t *dbh)
270 {
271 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
272 char *errmsg = NULL;
273
274 if (sqlite3_exec(H->db, "ROLLBACK", NULL, NULL, &errmsg) != SQLITE_OK) {
275 pdo_sqlite_error(dbh);
276 if (errmsg)
277 sqlite3_free(errmsg);
278 return false;
279 }
280 return true;
281 }
282
pdo_sqlite_get_attribute(pdo_dbh_t * dbh,zend_long attr,zval * return_value)283 static int pdo_sqlite_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_value)
284 {
285 switch (attr) {
286 case PDO_ATTR_CLIENT_VERSION:
287 case PDO_ATTR_SERVER_VERSION:
288 ZVAL_STRING(return_value, (char *)sqlite3_libversion());
289 break;
290
291 default:
292 return 0;
293 }
294
295 return 1;
296 }
297
pdo_sqlite_set_attr(pdo_dbh_t * dbh,zend_long attr,zval * val)298 static bool pdo_sqlite_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
299 {
300 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
301 zend_long lval;
302
303 switch (attr) {
304 case PDO_ATTR_TIMEOUT:
305 if (!pdo_get_long_param(&lval, val)) {
306 return false;
307 }
308 sqlite3_busy_timeout(H->db, lval * 1000);
309 return true;
310 case PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES:
311 if (!pdo_get_long_param(&lval, val)) {
312 return false;
313 }
314 sqlite3_extended_result_codes(H->db, lval);
315 return true;
316 }
317 return false;
318 }
319
320 typedef struct {
321 zval val;
322 zend_long row;
323 } aggregate_context;
324
do_callback(struct pdo_sqlite_fci * fc,zval * cb,int argc,sqlite3_value ** argv,sqlite3_context * context,int is_agg)325 static int do_callback(struct pdo_sqlite_fci *fc, zval *cb,
326 int argc, sqlite3_value **argv, sqlite3_context *context,
327 int is_agg)
328 {
329 zval *zargs = NULL;
330 zval retval;
331 int i;
332 int ret;
333 int fake_argc;
334 aggregate_context *agg_context = NULL;
335
336 if (is_agg) {
337 is_agg = 2;
338 }
339
340 fake_argc = argc + is_agg;
341
342 fc->fci.size = sizeof(fc->fci);
343 ZVAL_COPY_VALUE(&fc->fci.function_name, cb);
344 fc->fci.object = NULL;
345 fc->fci.retval = &retval;
346 fc->fci.param_count = fake_argc;
347
348 /* build up the params */
349
350 if (fake_argc) {
351 zargs = safe_emalloc(fake_argc, sizeof(zval), 0);
352 }
353
354 if (is_agg) {
355 agg_context = sqlite3_aggregate_context(context, sizeof(aggregate_context));
356 if (!agg_context) {
357 efree(zargs);
358 return FAILURE;
359 }
360 if (Z_ISUNDEF(agg_context->val)) {
361 ZVAL_NEW_REF(&agg_context->val, &EG(uninitialized_zval));
362 }
363 ZVAL_COPY_VALUE(&zargs[0], &agg_context->val);
364 ZVAL_LONG(&zargs[1], ++agg_context->row);
365 }
366
367 for (i = 0; i < argc; i++) {
368 /* get the value */
369 switch (sqlite3_value_type(argv[i])) {
370 case SQLITE_INTEGER:
371 ZVAL_LONG(&zargs[i + is_agg], sqlite3_value_int(argv[i]));
372 break;
373
374 case SQLITE_FLOAT:
375 ZVAL_DOUBLE(&zargs[i + is_agg], sqlite3_value_double(argv[i]));
376 break;
377
378 case SQLITE_NULL:
379 ZVAL_NULL(&zargs[i + is_agg]);
380 break;
381
382 case SQLITE_BLOB:
383 case SQLITE3_TEXT:
384 default:
385 ZVAL_STRINGL(&zargs[i + is_agg], (char*)sqlite3_value_text(argv[i]), sqlite3_value_bytes(argv[i]));
386 break;
387 }
388 }
389
390 fc->fci.params = zargs;
391
392 if ((ret = zend_call_function(&fc->fci, &fc->fcc)) == FAILURE) {
393 php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
394 }
395
396 /* clean up the params */
397 if (zargs) {
398 for (i = is_agg; i < fake_argc; i++) {
399 zval_ptr_dtor(&zargs[i]);
400 }
401 if (is_agg) {
402 zval_ptr_dtor(&zargs[1]);
403 }
404 efree(zargs);
405 }
406
407 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 if (!Z_ISUNDEF(retval)) {
411 switch (Z_TYPE(retval)) {
412 case IS_LONG:
413 sqlite3_result_int(context, Z_LVAL(retval));
414 break;
415
416 case IS_NULL:
417 sqlite3_result_null(context);
418 break;
419
420 case IS_DOUBLE:
421 sqlite3_result_double(context, Z_DVAL(retval));
422 break;
423
424 default:
425 if (!try_convert_to_string(&retval)) {
426 ret = FAILURE;
427 break;
428 }
429 sqlite3_result_text(context, Z_STRVAL(retval), Z_STRLEN(retval), SQLITE_TRANSIENT);
430 break;
431 }
432 } else {
433 sqlite3_result_error(context, "failed to invoke callback", 0);
434 }
435
436 if (agg_context) {
437 zval_ptr_dtor(&agg_context->val);
438 }
439 } else {
440 /* we're stepping in an aggregate; the return value goes into
441 * the context */
442 if (agg_context) {
443 if (Z_ISUNDEF(retval)) {
444 zval_ptr_dtor(&agg_context->val);
445 return FAILURE;
446 }
447 zval_ptr_dtor(Z_REFVAL(agg_context->val));
448 ZVAL_COPY_VALUE(Z_REFVAL(agg_context->val), &retval);
449 ZVAL_UNDEF(&retval);
450 }
451 }
452
453 if (!Z_ISUNDEF(retval)) {
454 zval_ptr_dtor(&retval);
455 }
456
457 return ret;
458 }
459
php_sqlite3_func_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)460 static void php_sqlite3_func_callback(sqlite3_context *context, int argc,
461 sqlite3_value **argv)
462 {
463 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
464
465 do_callback(&func->afunc, &func->func, argc, argv, context, 0);
466 }
467
php_sqlite3_func_step_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)468 static void php_sqlite3_func_step_callback(sqlite3_context *context, int argc,
469 sqlite3_value **argv)
470 {
471 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
472
473 do_callback(&func->astep, &func->step, argc, argv, context, 1);
474 }
475
php_sqlite3_func_final_callback(sqlite3_context * context)476 static void php_sqlite3_func_final_callback(sqlite3_context *context)
477 {
478 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
479
480 do_callback(&func->afini, &func->fini, 0, NULL, context, 1);
481 }
482
php_sqlite3_collation_callback(void * context,int string1_len,const void * string1,int string2_len,const void * string2)483 static int php_sqlite3_collation_callback(void *context,
484 int string1_len, const void *string1,
485 int string2_len, const void *string2)
486 {
487 int ret;
488 zval zargs[2];
489 zval retval;
490 struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context;
491
492 collation->fc.fci.size = sizeof(collation->fc.fci);
493 ZVAL_COPY_VALUE(&collation->fc.fci.function_name, &collation->callback);
494 collation->fc.fci.object = NULL;
495 collation->fc.fci.retval = &retval;
496
497 // Prepare the arguments.
498 ZVAL_STRINGL(&zargs[0], (char *) string1, string1_len);
499 ZVAL_STRINGL(&zargs[1], (char *) string2, string2_len);
500 collation->fc.fci.param_count = 2;
501 collation->fc.fci.params = zargs;
502
503 if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc)) == FAILURE) {
504 php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
505 } else if (!Z_ISUNDEF(retval)) {
506 if (Z_TYPE(retval) != IS_LONG) {
507 convert_to_long(&retval);
508 }
509 ret = 0;
510 if (Z_LVAL(retval) > 0) {
511 ret = 1;
512 } else if (Z_LVAL(retval) < 0) {
513 ret = -1;
514 }
515 zval_ptr_dtor(&retval);
516 }
517
518 zval_ptr_dtor(&zargs[0]);
519 zval_ptr_dtor(&zargs[1]);
520
521 return ret;
522 }
523
524 /* {{{ bool SQLite::sqliteCreateFunction(string name, callable callback [, int argcount, int flags])
525 Registers a UDF with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateFunction)526 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateFunction)
527 {
528 struct pdo_sqlite_func *func;
529 zend_fcall_info fci;
530 zend_fcall_info_cache fcc;
531 char *func_name;
532 size_t func_name_len;
533 zend_long argc = -1;
534 zend_long flags = 0;
535 pdo_dbh_t *dbh;
536 pdo_sqlite_db_handle *H;
537 int ret;
538
539 ZEND_PARSE_PARAMETERS_START(2, 4)
540 Z_PARAM_STRING(func_name, func_name_len)
541 Z_PARAM_FUNC(fci, fcc)
542 Z_PARAM_OPTIONAL
543 Z_PARAM_LONG(argc)
544 Z_PARAM_LONG(flags)
545 ZEND_PARSE_PARAMETERS_END();
546
547 dbh = Z_PDO_DBH_P(ZEND_THIS);
548 PDO_CONSTRUCT_CHECK;
549
550 H = (pdo_sqlite_db_handle *)dbh->driver_data;
551
552 func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
553
554 ret = sqlite3_create_function(H->db, func_name, argc, flags | SQLITE_UTF8,
555 func, php_sqlite3_func_callback, NULL, NULL);
556 if (ret == SQLITE_OK) {
557 func->funcname = estrdup(func_name);
558
559 ZVAL_COPY(&func->func, &fci.function_name);
560
561 func->argc = argc;
562
563 func->next = H->funcs;
564 H->funcs = func;
565
566 RETURN_TRUE;
567 }
568
569 efree(func);
570 RETURN_FALSE;
571 }
572 /* }}} */
573
574 /* {{{ bool SQLite::sqliteCreateAggregate(string name, callable step, callable fini [, int argcount])
575 Registers a UDF with the sqlite db handle */
576
577 /* The step function should have the prototype:
578 mixed step(mixed $context, int $rownumber, $value [, $value2 [, ...]])
579
580 $context will be null for the first row; on subsequent rows it will have
581 the value that was previously returned from the step function; you should
582 use this to maintain state for the aggregate.
583
584 The fini function should have the prototype:
585 mixed fini(mixed $context, int $rownumber)
586
587 $context will hold the return value from the very last call to the step function.
588 rownumber will hold the number of rows over which the aggregate was performed.
589 The return value of this function will be used as the return value for this
590 aggregate UDF.
591 */
592
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateAggregate)593 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateAggregate)
594 {
595 struct pdo_sqlite_func *func;
596 zend_fcall_info step_fci, fini_fci;
597 zend_fcall_info_cache step_fcc, fini_fcc;
598 char *func_name;
599 size_t func_name_len;
600 zend_long argc = -1;
601 pdo_dbh_t *dbh;
602 pdo_sqlite_db_handle *H;
603 int ret;
604
605 ZEND_PARSE_PARAMETERS_START(3, 4)
606 Z_PARAM_STRING(func_name, func_name_len)
607 Z_PARAM_FUNC(step_fci, step_fcc)
608 Z_PARAM_FUNC(fini_fci, fini_fcc)
609 Z_PARAM_OPTIONAL
610 Z_PARAM_LONG(argc)
611 ZEND_PARSE_PARAMETERS_END();
612
613 dbh = Z_PDO_DBH_P(ZEND_THIS);
614 PDO_CONSTRUCT_CHECK;
615
616 H = (pdo_sqlite_db_handle *)dbh->driver_data;
617
618 func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
619
620 ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
621 func, NULL, php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
622 if (ret == SQLITE_OK) {
623 func->funcname = estrdup(func_name);
624
625 ZVAL_COPY(&func->step, &step_fci.function_name);
626
627 ZVAL_COPY(&func->fini, &fini_fci.function_name);
628
629 func->argc = argc;
630
631 func->next = H->funcs;
632 H->funcs = func;
633
634 RETURN_TRUE;
635 }
636
637 efree(func);
638 RETURN_FALSE;
639 }
640 /* }}} */
641
642 /* {{{ bool SQLite::sqliteCreateCollation(string name, callable callback)
643 Registers a collation with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateCollation)644 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateCollation)
645 {
646 struct pdo_sqlite_collation *collation;
647 zend_fcall_info fci;
648 zend_fcall_info_cache fcc;
649 char *collation_name;
650 size_t collation_name_len;
651 pdo_dbh_t *dbh;
652 pdo_sqlite_db_handle *H;
653 int ret;
654
655 ZEND_PARSE_PARAMETERS_START(2, 2)
656 Z_PARAM_STRING(collation_name, collation_name_len)
657 Z_PARAM_FUNC(fci, fcc)
658 ZEND_PARSE_PARAMETERS_END();
659
660 dbh = Z_PDO_DBH_P(ZEND_THIS);
661 PDO_CONSTRUCT_CHECK;
662
663 H = (pdo_sqlite_db_handle *)dbh->driver_data;
664
665 collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));
666
667 ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_collation_callback);
668 if (ret == SQLITE_OK) {
669 collation->name = estrdup(collation_name);
670
671 ZVAL_COPY(&collation->callback, &fci.function_name);
672
673 collation->next = H->collations;
674 H->collations = collation;
675
676 RETURN_TRUE;
677 }
678
679 efree(collation);
680 RETURN_FALSE;
681 }
682 /* }}} */
683
get_driver_methods(pdo_dbh_t * dbh,int kind)684 static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind)
685 {
686 switch (kind) {
687 case PDO_DBH_DRIVER_METHOD_KIND_DBH:
688 return class_PDO_SQLite_Ext_methods;
689
690 default:
691 return NULL;
692 }
693 }
694
pdo_sqlite_request_shutdown(pdo_dbh_t * dbh)695 static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh)
696 {
697 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
698 /* unregister functions, so that they don't linger for the next
699 * request */
700 if (H) {
701 pdo_sqlite_cleanup_callbacks(H);
702 }
703 }
704
pdo_sqlite_get_gc(pdo_dbh_t * dbh,zend_get_gc_buffer * gc_buffer)705 static void pdo_sqlite_get_gc(pdo_dbh_t *dbh, zend_get_gc_buffer *gc_buffer)
706 {
707 pdo_sqlite_db_handle *H = dbh->driver_data;
708
709 struct pdo_sqlite_func *func = H->funcs;
710 while (func) {
711 zend_get_gc_buffer_add_zval(gc_buffer, &func->func);
712 zend_get_gc_buffer_add_zval(gc_buffer, &func->step);
713 zend_get_gc_buffer_add_zval(gc_buffer, &func->fini);
714 func = func->next;
715 }
716
717 struct pdo_sqlite_collation *collation = H->collations;
718 while (collation) {
719 zend_get_gc_buffer_add_zval(gc_buffer, &collation->callback);
720 collation = collation->next;
721 }
722 }
723
724 static const struct pdo_dbh_methods sqlite_methods = {
725 sqlite_handle_closer,
726 sqlite_handle_preparer,
727 sqlite_handle_doer,
728 sqlite_handle_quoter,
729 sqlite_handle_begin,
730 sqlite_handle_commit,
731 sqlite_handle_rollback,
732 pdo_sqlite_set_attr,
733 pdo_sqlite_last_insert_id,
734 pdo_sqlite_fetch_error_func,
735 pdo_sqlite_get_attribute,
736 NULL, /* check_liveness: not needed */
737 get_driver_methods,
738 pdo_sqlite_request_shutdown,
739 NULL, /* in transaction, use PDO's internal tracking mechanism */
740 pdo_sqlite_get_gc
741 };
742
make_filename_safe(const char * filename)743 static char *make_filename_safe(const char *filename)
744 {
745 if (!filename) {
746 return NULL;
747 }
748 if (*filename && strncasecmp(filename, "file:", 5) == 0) {
749 if (PG(open_basedir) && *PG(open_basedir)) {
750 return NULL;
751 }
752 return estrdup(filename);
753 }
754 if (*filename && memcmp(filename, ":memory:", sizeof(":memory:"))) {
755 char *fullpath = expand_filepath(filename, NULL);
756
757 if (!fullpath) {
758 return NULL;
759 }
760
761 if (php_check_open_basedir(fullpath)) {
762 efree(fullpath);
763 return NULL;
764 }
765 return fullpath;
766 }
767 return estrdup(filename);
768 }
769
authorizer(void * autharg,int access_type,const char * arg3,const char * arg4,const char * arg5,const char * arg6)770 static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
771 const char *arg5, const char *arg6)
772 {
773 char *filename;
774 switch (access_type) {
775 case SQLITE_COPY: {
776 filename = make_filename_safe(arg4);
777 if (!filename) {
778 return SQLITE_DENY;
779 }
780 efree(filename);
781 return SQLITE_OK;
782 }
783
784 case SQLITE_ATTACH: {
785 filename = make_filename_safe(arg3);
786 if (!filename) {
787 return SQLITE_DENY;
788 }
789 efree(filename);
790 return SQLITE_OK;
791 }
792
793 default:
794 /* access allowed */
795 return SQLITE_OK;
796 }
797 }
798
pdo_sqlite_handle_factory(pdo_dbh_t * dbh,zval * driver_options)799 static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
800 {
801 pdo_sqlite_db_handle *H;
802 int i, ret = 0;
803 zend_long timeout = 60, flags;
804 char *filename;
805
806 H = pecalloc(1, sizeof(pdo_sqlite_db_handle), dbh->is_persistent);
807
808 H->einfo.errcode = 0;
809 H->einfo.errmsg = NULL;
810 dbh->driver_data = H;
811
812 /* skip all but this one param event */
813 dbh->skip_param_evt = 0x7F ^ (1 << PDO_PARAM_EVT_EXEC_PRE);
814
815 filename = make_filename_safe(dbh->data_source);
816
817 if (!filename) {
818 zend_throw_exception_ex(php_pdo_get_exception(), 0,
819 "open_basedir prohibits opening %s",
820 dbh->data_source);
821 goto cleanup;
822 }
823
824 flags = pdo_attr_lval(driver_options, PDO_SQLITE_ATTR_OPEN_FLAGS, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
825
826 if (!(PG(open_basedir) && *PG(open_basedir))) {
827 flags |= SQLITE_OPEN_URI;
828 }
829 i = sqlite3_open_v2(filename, &H->db, flags, NULL);
830
831 efree(filename);
832
833 if (i != SQLITE_OK) {
834 pdo_sqlite_error(dbh);
835 goto cleanup;
836 }
837
838 if (PG(open_basedir) && *PG(open_basedir)) {
839 sqlite3_set_authorizer(H->db, authorizer, NULL);
840 }
841
842 if (driver_options) {
843 timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout);
844 }
845 sqlite3_busy_timeout(H->db, timeout * 1000);
846
847 dbh->alloc_own_columns = 1;
848 dbh->max_escaped_char_length = 2;
849
850 ret = 1;
851
852 cleanup:
853 dbh->methods = &sqlite_methods;
854
855 return ret;
856 }
857 /* }}} */
858
859 const pdo_driver_t pdo_sqlite_driver = {
860 PDO_DRIVER_HEADER(sqlite),
861 pdo_sqlite_handle_factory
862 };
863