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 return FAILURE;
445 }
446 zval_ptr_dtor(Z_REFVAL(agg_context->val));
447 ZVAL_COPY_VALUE(Z_REFVAL(agg_context->val), &retval);
448 ZVAL_UNDEF(&retval);
449 }
450 }
451
452 if (!Z_ISUNDEF(retval)) {
453 zval_ptr_dtor(&retval);
454 }
455
456 return ret;
457 }
458
php_sqlite3_func_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)459 static void php_sqlite3_func_callback(sqlite3_context *context, int argc,
460 sqlite3_value **argv)
461 {
462 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
463
464 do_callback(&func->afunc, &func->func, argc, argv, context, 0);
465 }
466
php_sqlite3_func_step_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)467 static void php_sqlite3_func_step_callback(sqlite3_context *context, int argc,
468 sqlite3_value **argv)
469 {
470 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
471
472 do_callback(&func->astep, &func->step, argc, argv, context, 1);
473 }
474
php_sqlite3_func_final_callback(sqlite3_context * context)475 static void php_sqlite3_func_final_callback(sqlite3_context *context)
476 {
477 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
478
479 do_callback(&func->afini, &func->fini, 0, NULL, context, 1);
480 }
481
php_sqlite3_collation_callback(void * context,int string1_len,const void * string1,int string2_len,const void * string2)482 static int php_sqlite3_collation_callback(void *context,
483 int string1_len, const void *string1,
484 int string2_len, const void *string2)
485 {
486 int ret;
487 zval zargs[2];
488 zval retval;
489 struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context;
490
491 collation->fc.fci.size = sizeof(collation->fc.fci);
492 ZVAL_COPY_VALUE(&collation->fc.fci.function_name, &collation->callback);
493 collation->fc.fci.object = NULL;
494 collation->fc.fci.retval = &retval;
495
496 // Prepare the arguments.
497 ZVAL_STRINGL(&zargs[0], (char *) string1, string1_len);
498 ZVAL_STRINGL(&zargs[1], (char *) string2, string2_len);
499 collation->fc.fci.param_count = 2;
500 collation->fc.fci.params = zargs;
501
502 if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc)) == FAILURE) {
503 php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
504 } else if (!Z_ISUNDEF(retval)) {
505 if (Z_TYPE(retval) != IS_LONG) {
506 convert_to_long(&retval);
507 }
508 ret = 0;
509 if (Z_LVAL(retval) > 0) {
510 ret = 1;
511 } else if (Z_LVAL(retval) < 0) {
512 ret = -1;
513 }
514 zval_ptr_dtor(&retval);
515 }
516
517 zval_ptr_dtor(&zargs[0]);
518 zval_ptr_dtor(&zargs[1]);
519
520 return ret;
521 }
522
523 /* {{{ bool SQLite::sqliteCreateFunction(string name, callable callback [, int argcount, int flags])
524 Registers a UDF with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateFunction)525 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateFunction)
526 {
527 struct pdo_sqlite_func *func;
528 zend_fcall_info fci;
529 zend_fcall_info_cache fcc;
530 char *func_name;
531 size_t func_name_len;
532 zend_long argc = -1;
533 zend_long flags = 0;
534 pdo_dbh_t *dbh;
535 pdo_sqlite_db_handle *H;
536 int ret;
537
538 ZEND_PARSE_PARAMETERS_START(2, 4)
539 Z_PARAM_STRING(func_name, func_name_len)
540 Z_PARAM_FUNC(fci, fcc)
541 Z_PARAM_OPTIONAL
542 Z_PARAM_LONG(argc)
543 Z_PARAM_LONG(flags)
544 ZEND_PARSE_PARAMETERS_END();
545
546 dbh = Z_PDO_DBH_P(ZEND_THIS);
547 PDO_CONSTRUCT_CHECK;
548
549 H = (pdo_sqlite_db_handle *)dbh->driver_data;
550
551 func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
552
553 ret = sqlite3_create_function(H->db, func_name, argc, flags | SQLITE_UTF8,
554 func, php_sqlite3_func_callback, NULL, NULL);
555 if (ret == SQLITE_OK) {
556 func->funcname = estrdup(func_name);
557
558 ZVAL_COPY(&func->func, &fci.function_name);
559
560 func->argc = argc;
561
562 func->next = H->funcs;
563 H->funcs = func;
564
565 RETURN_TRUE;
566 }
567
568 efree(func);
569 RETURN_FALSE;
570 }
571 /* }}} */
572
573 /* {{{ bool SQLite::sqliteCreateAggregate(string name, callable step, callable fini [, int argcount])
574 Registers a UDF with the sqlite db handle */
575
576 /* The step function should have the prototype:
577 mixed step(mixed $context, int $rownumber, $value [, $value2 [, ...]])
578
579 $context will be null for the first row; on subsequent rows it will have
580 the value that was previously returned from the step function; you should
581 use this to maintain state for the aggregate.
582
583 The fini function should have the prototype:
584 mixed fini(mixed $context, int $rownumber)
585
586 $context will hold the return value from the very last call to the step function.
587 rownumber will hold the number of rows over which the aggregate was performed.
588 The return value of this function will be used as the return value for this
589 aggregate UDF.
590 */
591
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateAggregate)592 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateAggregate)
593 {
594 struct pdo_sqlite_func *func;
595 zend_fcall_info step_fci, fini_fci;
596 zend_fcall_info_cache step_fcc, fini_fcc;
597 char *func_name;
598 size_t func_name_len;
599 zend_long argc = -1;
600 pdo_dbh_t *dbh;
601 pdo_sqlite_db_handle *H;
602 int ret;
603
604 ZEND_PARSE_PARAMETERS_START(3, 4)
605 Z_PARAM_STRING(func_name, func_name_len)
606 Z_PARAM_FUNC(step_fci, step_fcc)
607 Z_PARAM_FUNC(fini_fci, fini_fcc)
608 Z_PARAM_OPTIONAL
609 Z_PARAM_LONG(argc)
610 ZEND_PARSE_PARAMETERS_END();
611
612 dbh = Z_PDO_DBH_P(ZEND_THIS);
613 PDO_CONSTRUCT_CHECK;
614
615 H = (pdo_sqlite_db_handle *)dbh->driver_data;
616
617 func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
618
619 ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
620 func, NULL, php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
621 if (ret == SQLITE_OK) {
622 func->funcname = estrdup(func_name);
623
624 ZVAL_COPY(&func->step, &step_fci.function_name);
625
626 ZVAL_COPY(&func->fini, &fini_fci.function_name);
627
628 func->argc = argc;
629
630 func->next = H->funcs;
631 H->funcs = func;
632
633 RETURN_TRUE;
634 }
635
636 efree(func);
637 RETURN_FALSE;
638 }
639 /* }}} */
640
641 /* {{{ bool SQLite::sqliteCreateCollation(string name, callable callback)
642 Registers a collation with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateCollation)643 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateCollation)
644 {
645 struct pdo_sqlite_collation *collation;
646 zend_fcall_info fci;
647 zend_fcall_info_cache fcc;
648 char *collation_name;
649 size_t collation_name_len;
650 pdo_dbh_t *dbh;
651 pdo_sqlite_db_handle *H;
652 int ret;
653
654 ZEND_PARSE_PARAMETERS_START(2, 2)
655 Z_PARAM_STRING(collation_name, collation_name_len)
656 Z_PARAM_FUNC(fci, fcc)
657 ZEND_PARSE_PARAMETERS_END();
658
659 dbh = Z_PDO_DBH_P(ZEND_THIS);
660 PDO_CONSTRUCT_CHECK;
661
662 H = (pdo_sqlite_db_handle *)dbh->driver_data;
663
664 collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));
665
666 ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_collation_callback);
667 if (ret == SQLITE_OK) {
668 collation->name = estrdup(collation_name);
669
670 ZVAL_COPY(&collation->callback, &fci.function_name);
671
672 collation->next = H->collations;
673 H->collations = collation;
674
675 RETURN_TRUE;
676 }
677
678 efree(collation);
679 RETURN_FALSE;
680 }
681 /* }}} */
682
get_driver_methods(pdo_dbh_t * dbh,int kind)683 static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind)
684 {
685 switch (kind) {
686 case PDO_DBH_DRIVER_METHOD_KIND_DBH:
687 return class_PDO_SQLite_Ext_methods;
688
689 default:
690 return NULL;
691 }
692 }
693
pdo_sqlite_request_shutdown(pdo_dbh_t * dbh)694 static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh)
695 {
696 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
697 /* unregister functions, so that they don't linger for the next
698 * request */
699 if (H) {
700 pdo_sqlite_cleanup_callbacks(H);
701 }
702 }
703
pdo_sqlite_get_gc(pdo_dbh_t * dbh,zend_get_gc_buffer * gc_buffer)704 static void pdo_sqlite_get_gc(pdo_dbh_t *dbh, zend_get_gc_buffer *gc_buffer)
705 {
706 pdo_sqlite_db_handle *H = dbh->driver_data;
707
708 struct pdo_sqlite_func *func = H->funcs;
709 while (func) {
710 zend_get_gc_buffer_add_zval(gc_buffer, &func->func);
711 zend_get_gc_buffer_add_zval(gc_buffer, &func->step);
712 zend_get_gc_buffer_add_zval(gc_buffer, &func->fini);
713 func = func->next;
714 }
715
716 struct pdo_sqlite_collation *collation = H->collations;
717 while (collation) {
718 zend_get_gc_buffer_add_zval(gc_buffer, &collation->callback);
719 collation = collation->next;
720 }
721 }
722
723 static const struct pdo_dbh_methods sqlite_methods = {
724 sqlite_handle_closer,
725 sqlite_handle_preparer,
726 sqlite_handle_doer,
727 sqlite_handle_quoter,
728 sqlite_handle_begin,
729 sqlite_handle_commit,
730 sqlite_handle_rollback,
731 pdo_sqlite_set_attr,
732 pdo_sqlite_last_insert_id,
733 pdo_sqlite_fetch_error_func,
734 pdo_sqlite_get_attribute,
735 NULL, /* check_liveness: not needed */
736 get_driver_methods,
737 pdo_sqlite_request_shutdown,
738 NULL, /* in transaction, use PDO's internal tracking mechanism */
739 pdo_sqlite_get_gc
740 };
741
make_filename_safe(const char * filename)742 static char *make_filename_safe(const char *filename)
743 {
744 if (!filename) {
745 return NULL;
746 }
747 if (*filename && strncasecmp(filename, "file:", 5) == 0) {
748 if (PG(open_basedir) && *PG(open_basedir)) {
749 return NULL;
750 }
751 return estrdup(filename);
752 }
753 if (*filename && strcmp(filename, ":memory:")) {
754 char *fullpath = expand_filepath(filename, NULL);
755
756 if (!fullpath) {
757 return NULL;
758 }
759
760 if (php_check_open_basedir(fullpath)) {
761 efree(fullpath);
762 return NULL;
763 }
764 return fullpath;
765 }
766 return estrdup(filename);
767 }
768
authorizer(void * autharg,int access_type,const char * arg3,const char * arg4,const char * arg5,const char * arg6)769 static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
770 const char *arg5, const char *arg6)
771 {
772 char *filename;
773 switch (access_type) {
774 case SQLITE_ATTACH: {
775 filename = make_filename_safe(arg3);
776 if (!filename) {
777 return SQLITE_DENY;
778 }
779 efree(filename);
780 return SQLITE_OK;
781 }
782
783 default:
784 /* access allowed */
785 return SQLITE_OK;
786 }
787 }
788
pdo_sqlite_handle_factory(pdo_dbh_t * dbh,zval * driver_options)789 static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
790 {
791 pdo_sqlite_db_handle *H;
792 int i, ret = 0;
793 zend_long timeout = 60, flags;
794 char *filename;
795
796 H = pecalloc(1, sizeof(pdo_sqlite_db_handle), dbh->is_persistent);
797
798 H->einfo.errcode = 0;
799 H->einfo.errmsg = NULL;
800 dbh->driver_data = H;
801
802 /* skip all but this one param event */
803 dbh->skip_param_evt = 0x7F ^ (1 << PDO_PARAM_EVT_EXEC_PRE);
804
805 filename = make_filename_safe(dbh->data_source);
806
807 if (!filename) {
808 zend_throw_exception_ex(php_pdo_get_exception(), 0,
809 "open_basedir prohibits opening %s",
810 dbh->data_source);
811 goto cleanup;
812 }
813
814 flags = pdo_attr_lval(driver_options, PDO_SQLITE_ATTR_OPEN_FLAGS, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
815
816 if (!(PG(open_basedir) && *PG(open_basedir))) {
817 flags |= SQLITE_OPEN_URI;
818 }
819 i = sqlite3_open_v2(filename, &H->db, flags, NULL);
820
821 efree(filename);
822
823 if (i != SQLITE_OK) {
824 pdo_sqlite_error(dbh);
825 goto cleanup;
826 }
827
828 if (PG(open_basedir) && *PG(open_basedir)) {
829 sqlite3_set_authorizer(H->db, authorizer, NULL);
830 }
831
832 if (driver_options) {
833 timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout);
834 }
835 sqlite3_busy_timeout(H->db, timeout * 1000);
836
837 dbh->alloc_own_columns = 1;
838 dbh->max_escaped_char_length = 2;
839
840 ret = 1;
841
842 cleanup:
843 dbh->methods = &sqlite_methods;
844
845 return ret;
846 }
847 /* }}} */
848
849 const pdo_driver_t pdo_sqlite_driver = {
850 PDO_DRIVER_HEADER(sqlite),
851 pdo_sqlite_handle_factory
852 };
853