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
207 if (sqlite3_exec(H->db, ZSTR_VAL(sql), NULL, NULL, NULL) != SQLITE_OK) {
208 pdo_sqlite_error(dbh);
209 return -1;
210 } else {
211 return sqlite3_changes(H->db);
212 }
213 }
214
pdo_sqlite_last_insert_id(pdo_dbh_t * dbh,const zend_string * name)215 static zend_string *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const zend_string *name)
216 {
217 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
218
219 return zend_i64_to_str(sqlite3_last_insert_rowid(H->db));
220 }
221
222 /* 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)223 static zend_string* sqlite_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype)
224 {
225 char *quoted;
226 if (ZSTR_LEN(unquoted) > (INT_MAX - 3) / 2) {
227 return NULL;
228 }
229 quoted = safe_emalloc(2, ZSTR_LEN(unquoted), 3);
230 /* TODO use %Q format? */
231 sqlite3_snprintf(2*ZSTR_LEN(unquoted) + 3, quoted, "'%q'", ZSTR_VAL(unquoted));
232 zend_string *quoted_str = zend_string_init(quoted, strlen(quoted), 0);
233 efree(quoted);
234 return quoted_str;
235 }
236
sqlite_handle_begin(pdo_dbh_t * dbh)237 static bool sqlite_handle_begin(pdo_dbh_t *dbh)
238 {
239 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
240
241 if (sqlite3_exec(H->db, "BEGIN", NULL, NULL, NULL) != SQLITE_OK) {
242 pdo_sqlite_error(dbh);
243 return false;
244 }
245 return true;
246 }
247
sqlite_handle_commit(pdo_dbh_t * dbh)248 static bool sqlite_handle_commit(pdo_dbh_t *dbh)
249 {
250 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
251
252 if (sqlite3_exec(H->db, "COMMIT", NULL, NULL, NULL) != SQLITE_OK) {
253 pdo_sqlite_error(dbh);
254 return false;
255 }
256 return true;
257 }
258
sqlite_handle_rollback(pdo_dbh_t * dbh)259 static bool sqlite_handle_rollback(pdo_dbh_t *dbh)
260 {
261 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
262
263 if (sqlite3_exec(H->db, "ROLLBACK", NULL, NULL, NULL) != SQLITE_OK) {
264 pdo_sqlite_error(dbh);
265 return false;
266 }
267 return true;
268 }
269
pdo_sqlite_get_attribute(pdo_dbh_t * dbh,zend_long attr,zval * return_value)270 static int pdo_sqlite_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_value)
271 {
272 switch (attr) {
273 case PDO_ATTR_CLIENT_VERSION:
274 case PDO_ATTR_SERVER_VERSION:
275 ZVAL_STRING(return_value, (char *)sqlite3_libversion());
276 break;
277
278 default:
279 return 0;
280 }
281
282 return 1;
283 }
284
pdo_sqlite_set_attr(pdo_dbh_t * dbh,zend_long attr,zval * val)285 static bool pdo_sqlite_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
286 {
287 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
288 zend_long lval;
289
290 switch (attr) {
291 case PDO_ATTR_TIMEOUT:
292 if (!pdo_get_long_param(&lval, val)) {
293 return false;
294 }
295 sqlite3_busy_timeout(H->db, lval * 1000);
296 return true;
297 case PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES:
298 if (!pdo_get_long_param(&lval, val)) {
299 return false;
300 }
301 sqlite3_extended_result_codes(H->db, lval);
302 return true;
303 }
304 return false;
305 }
306
307 typedef struct {
308 zval val;
309 zend_long row;
310 } aggregate_context;
311
do_callback(struct pdo_sqlite_fci * fc,zval * cb,int argc,sqlite3_value ** argv,sqlite3_context * context,int is_agg)312 static int do_callback(struct pdo_sqlite_fci *fc, zval *cb,
313 int argc, sqlite3_value **argv, sqlite3_context *context,
314 int is_agg)
315 {
316 zval *zargs = NULL;
317 zval retval;
318 int i;
319 int ret;
320 int fake_argc;
321 aggregate_context *agg_context = NULL;
322
323 if (is_agg) {
324 is_agg = 2;
325 }
326
327 fake_argc = argc + is_agg;
328
329 fc->fci.size = sizeof(fc->fci);
330 ZVAL_COPY_VALUE(&fc->fci.function_name, cb);
331 fc->fci.object = NULL;
332 fc->fci.retval = &retval;
333 fc->fci.param_count = fake_argc;
334
335 /* build up the params */
336
337 if (fake_argc) {
338 zargs = safe_emalloc(fake_argc, sizeof(zval), 0);
339 }
340
341 if (is_agg) {
342 agg_context = sqlite3_aggregate_context(context, sizeof(aggregate_context));
343 if (!agg_context) {
344 efree(zargs);
345 return FAILURE;
346 }
347 if (Z_ISUNDEF(agg_context->val)) {
348 ZVAL_NEW_REF(&agg_context->val, &EG(uninitialized_zval));
349 }
350 ZVAL_COPY_VALUE(&zargs[0], &agg_context->val);
351 ZVAL_LONG(&zargs[1], ++agg_context->row);
352 }
353
354 for (i = 0; i < argc; i++) {
355 /* get the value */
356 switch (sqlite3_value_type(argv[i])) {
357 case SQLITE_INTEGER:
358 ZVAL_LONG(&zargs[i + is_agg], sqlite3_value_int(argv[i]));
359 break;
360
361 case SQLITE_FLOAT:
362 ZVAL_DOUBLE(&zargs[i + is_agg], sqlite3_value_double(argv[i]));
363 break;
364
365 case SQLITE_NULL:
366 ZVAL_NULL(&zargs[i + is_agg]);
367 break;
368
369 case SQLITE_BLOB:
370 case SQLITE3_TEXT:
371 default:
372 ZVAL_STRINGL(&zargs[i + is_agg], (char*)sqlite3_value_text(argv[i]), sqlite3_value_bytes(argv[i]));
373 break;
374 }
375 }
376
377 fc->fci.params = zargs;
378
379 if ((ret = zend_call_function(&fc->fci, &fc->fcc)) == FAILURE) {
380 php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
381 }
382
383 /* clean up the params */
384 if (zargs) {
385 for (i = is_agg; i < fake_argc; i++) {
386 zval_ptr_dtor(&zargs[i]);
387 }
388 if (is_agg) {
389 zval_ptr_dtor(&zargs[1]);
390 }
391 efree(zargs);
392 }
393
394 if (!is_agg || !argv) {
395 /* only set the sqlite return value if we are a scalar function,
396 * or if we are finalizing an aggregate */
397 if (!Z_ISUNDEF(retval)) {
398 switch (Z_TYPE(retval)) {
399 case IS_LONG:
400 sqlite3_result_int(context, Z_LVAL(retval));
401 break;
402
403 case IS_NULL:
404 sqlite3_result_null(context);
405 break;
406
407 case IS_DOUBLE:
408 sqlite3_result_double(context, Z_DVAL(retval));
409 break;
410
411 default:
412 if (!try_convert_to_string(&retval)) {
413 ret = FAILURE;
414 break;
415 }
416 sqlite3_result_text(context, Z_STRVAL(retval), Z_STRLEN(retval), SQLITE_TRANSIENT);
417 break;
418 }
419 } else {
420 sqlite3_result_error(context, "failed to invoke callback", 0);
421 }
422
423 if (agg_context) {
424 zval_ptr_dtor(&agg_context->val);
425 }
426 } else {
427 /* we're stepping in an aggregate; the return value goes into
428 * the context */
429 if (agg_context) {
430 if (Z_ISUNDEF(retval)) {
431 return FAILURE;
432 }
433 zval_ptr_dtor(Z_REFVAL(agg_context->val));
434 ZVAL_COPY_VALUE(Z_REFVAL(agg_context->val), &retval);
435 ZVAL_UNDEF(&retval);
436 }
437 }
438
439 if (!Z_ISUNDEF(retval)) {
440 zval_ptr_dtor(&retval);
441 }
442
443 return ret;
444 }
445
php_sqlite3_func_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)446 static void php_sqlite3_func_callback(sqlite3_context *context, int argc,
447 sqlite3_value **argv)
448 {
449 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
450
451 do_callback(&func->afunc, &func->func, argc, argv, context, 0);
452 }
453
php_sqlite3_func_step_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)454 static void php_sqlite3_func_step_callback(sqlite3_context *context, int argc,
455 sqlite3_value **argv)
456 {
457 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
458
459 do_callback(&func->astep, &func->step, argc, argv, context, 1);
460 }
461
php_sqlite3_func_final_callback(sqlite3_context * context)462 static void php_sqlite3_func_final_callback(sqlite3_context *context)
463 {
464 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
465
466 do_callback(&func->afini, &func->fini, 0, NULL, context, 1);
467 }
468
php_sqlite3_collation_callback(void * context,int string1_len,const void * string1,int string2_len,const void * string2)469 static int php_sqlite3_collation_callback(void *context,
470 int string1_len, const void *string1,
471 int string2_len, const void *string2)
472 {
473 int ret;
474 zval zargs[2];
475 zval retval;
476 struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context;
477
478 collation->fc.fci.size = sizeof(collation->fc.fci);
479 ZVAL_COPY_VALUE(&collation->fc.fci.function_name, &collation->callback);
480 collation->fc.fci.object = NULL;
481 collation->fc.fci.retval = &retval;
482
483 // Prepare the arguments.
484 ZVAL_STRINGL(&zargs[0], (char *) string1, string1_len);
485 ZVAL_STRINGL(&zargs[1], (char *) string2, string2_len);
486 collation->fc.fci.param_count = 2;
487 collation->fc.fci.params = zargs;
488
489 if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc)) == FAILURE) {
490 php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
491 } else if (!Z_ISUNDEF(retval)) {
492 if (Z_TYPE(retval) != IS_LONG) {
493 convert_to_long(&retval);
494 }
495 ret = 0;
496 if (Z_LVAL(retval) > 0) {
497 ret = 1;
498 } else if (Z_LVAL(retval) < 0) {
499 ret = -1;
500 }
501 zval_ptr_dtor(&retval);
502 }
503
504 zval_ptr_dtor(&zargs[0]);
505 zval_ptr_dtor(&zargs[1]);
506
507 return ret;
508 }
509
510 /* {{{ bool SQLite::sqliteCreateFunction(string name, callable callback [, int argcount, int flags])
511 Registers a UDF with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateFunction)512 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateFunction)
513 {
514 struct pdo_sqlite_func *func;
515 zend_fcall_info fci;
516 zend_fcall_info_cache fcc;
517 char *func_name;
518 size_t func_name_len;
519 zend_long argc = -1;
520 zend_long flags = 0;
521 pdo_dbh_t *dbh;
522 pdo_sqlite_db_handle *H;
523 int ret;
524
525 ZEND_PARSE_PARAMETERS_START(2, 4)
526 Z_PARAM_STRING(func_name, func_name_len)
527 Z_PARAM_FUNC(fci, fcc)
528 Z_PARAM_OPTIONAL
529 Z_PARAM_LONG(argc)
530 Z_PARAM_LONG(flags)
531 ZEND_PARSE_PARAMETERS_END();
532
533 dbh = Z_PDO_DBH_P(ZEND_THIS);
534 PDO_CONSTRUCT_CHECK;
535
536 H = (pdo_sqlite_db_handle *)dbh->driver_data;
537
538 func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
539
540 ret = sqlite3_create_function(H->db, func_name, argc, flags | SQLITE_UTF8,
541 func, php_sqlite3_func_callback, NULL, NULL);
542 if (ret == SQLITE_OK) {
543 func->funcname = estrdup(func_name);
544
545 ZVAL_COPY(&func->func, &fci.function_name);
546
547 func->argc = argc;
548
549 func->next = H->funcs;
550 H->funcs = func;
551
552 RETURN_TRUE;
553 }
554
555 efree(func);
556 RETURN_FALSE;
557 }
558 /* }}} */
559
560 /* {{{ bool SQLite::sqliteCreateAggregate(string name, callable step, callable fini [, int argcount])
561 Registers a UDF with the sqlite db handle */
562
563 /* The step function should have the prototype:
564 mixed step(mixed $context, int $rownumber, $value [, $value2 [, ...]])
565
566 $context will be null for the first row; on subsequent rows it will have
567 the value that was previously returned from the step function; you should
568 use this to maintain state for the aggregate.
569
570 The fini function should have the prototype:
571 mixed fini(mixed $context, int $rownumber)
572
573 $context will hold the return value from the very last call to the step function.
574 rownumber will hold the number of rows over which the aggregate was performed.
575 The return value of this function will be used as the return value for this
576 aggregate UDF.
577 */
578
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateAggregate)579 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateAggregate)
580 {
581 struct pdo_sqlite_func *func;
582 zend_fcall_info step_fci, fini_fci;
583 zend_fcall_info_cache step_fcc, fini_fcc;
584 char *func_name;
585 size_t func_name_len;
586 zend_long argc = -1;
587 pdo_dbh_t *dbh;
588 pdo_sqlite_db_handle *H;
589 int ret;
590
591 ZEND_PARSE_PARAMETERS_START(3, 4)
592 Z_PARAM_STRING(func_name, func_name_len)
593 Z_PARAM_FUNC(step_fci, step_fcc)
594 Z_PARAM_FUNC(fini_fci, fini_fcc)
595 Z_PARAM_OPTIONAL
596 Z_PARAM_LONG(argc)
597 ZEND_PARSE_PARAMETERS_END();
598
599 dbh = Z_PDO_DBH_P(ZEND_THIS);
600 PDO_CONSTRUCT_CHECK;
601
602 H = (pdo_sqlite_db_handle *)dbh->driver_data;
603
604 func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
605
606 ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
607 func, NULL, php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
608 if (ret == SQLITE_OK) {
609 func->funcname = estrdup(func_name);
610
611 ZVAL_COPY(&func->step, &step_fci.function_name);
612
613 ZVAL_COPY(&func->fini, &fini_fci.function_name);
614
615 func->argc = argc;
616
617 func->next = H->funcs;
618 H->funcs = func;
619
620 RETURN_TRUE;
621 }
622
623 efree(func);
624 RETURN_FALSE;
625 }
626 /* }}} */
627
628 /* {{{ bool SQLite::sqliteCreateCollation(string name, callable callback)
629 Registers a collation with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateCollation)630 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateCollation)
631 {
632 struct pdo_sqlite_collation *collation;
633 zend_fcall_info fci;
634 zend_fcall_info_cache fcc;
635 char *collation_name;
636 size_t collation_name_len;
637 pdo_dbh_t *dbh;
638 pdo_sqlite_db_handle *H;
639 int ret;
640
641 ZEND_PARSE_PARAMETERS_START(2, 2)
642 Z_PARAM_STRING(collation_name, collation_name_len)
643 Z_PARAM_FUNC(fci, fcc)
644 ZEND_PARSE_PARAMETERS_END();
645
646 dbh = Z_PDO_DBH_P(ZEND_THIS);
647 PDO_CONSTRUCT_CHECK;
648
649 H = (pdo_sqlite_db_handle *)dbh->driver_data;
650
651 collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));
652
653 ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_collation_callback);
654 if (ret == SQLITE_OK) {
655 collation->name = estrdup(collation_name);
656
657 ZVAL_COPY(&collation->callback, &fci.function_name);
658
659 collation->next = H->collations;
660 H->collations = collation;
661
662 RETURN_TRUE;
663 }
664
665 efree(collation);
666 RETURN_FALSE;
667 }
668 /* }}} */
669
get_driver_methods(pdo_dbh_t * dbh,int kind)670 static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind)
671 {
672 switch (kind) {
673 case PDO_DBH_DRIVER_METHOD_KIND_DBH:
674 return class_PDO_SQLite_Ext_methods;
675
676 default:
677 return NULL;
678 }
679 }
680
pdo_sqlite_request_shutdown(pdo_dbh_t * dbh)681 static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh)
682 {
683 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
684 /* unregister functions, so that they don't linger for the next
685 * request */
686 if (H) {
687 pdo_sqlite_cleanup_callbacks(H);
688 }
689 }
690
pdo_sqlite_get_gc(pdo_dbh_t * dbh,zend_get_gc_buffer * gc_buffer)691 static void pdo_sqlite_get_gc(pdo_dbh_t *dbh, zend_get_gc_buffer *gc_buffer)
692 {
693 pdo_sqlite_db_handle *H = dbh->driver_data;
694
695 struct pdo_sqlite_func *func = H->funcs;
696 while (func) {
697 zend_get_gc_buffer_add_zval(gc_buffer, &func->func);
698 zend_get_gc_buffer_add_zval(gc_buffer, &func->step);
699 zend_get_gc_buffer_add_zval(gc_buffer, &func->fini);
700 func = func->next;
701 }
702
703 struct pdo_sqlite_collation *collation = H->collations;
704 while (collation) {
705 zend_get_gc_buffer_add_zval(gc_buffer, &collation->callback);
706 collation = collation->next;
707 }
708 }
709
710 static const struct pdo_dbh_methods sqlite_methods = {
711 sqlite_handle_closer,
712 sqlite_handle_preparer,
713 sqlite_handle_doer,
714 sqlite_handle_quoter,
715 sqlite_handle_begin,
716 sqlite_handle_commit,
717 sqlite_handle_rollback,
718 pdo_sqlite_set_attr,
719 pdo_sqlite_last_insert_id,
720 pdo_sqlite_fetch_error_func,
721 pdo_sqlite_get_attribute,
722 NULL, /* check_liveness: not needed */
723 get_driver_methods,
724 pdo_sqlite_request_shutdown,
725 NULL, /* in transaction, use PDO's internal tracking mechanism */
726 pdo_sqlite_get_gc
727 };
728
make_filename_safe(const char * filename)729 static char *make_filename_safe(const char *filename)
730 {
731 if (!filename) {
732 return NULL;
733 }
734 if (*filename && strncasecmp(filename, "file:", 5) == 0) {
735 if (PG(open_basedir) && *PG(open_basedir)) {
736 return NULL;
737 }
738 return estrdup(filename);
739 }
740 if (*filename && strcmp(filename, ":memory:")) {
741 char *fullpath = expand_filepath(filename, NULL);
742
743 if (!fullpath) {
744 return NULL;
745 }
746
747 if (php_check_open_basedir(fullpath)) {
748 efree(fullpath);
749 return NULL;
750 }
751 return fullpath;
752 }
753 return estrdup(filename);
754 }
755
authorizer(void * autharg,int access_type,const char * arg3,const char * arg4,const char * arg5,const char * arg6)756 static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
757 const char *arg5, const char *arg6)
758 {
759 char *filename;
760 switch (access_type) {
761 case SQLITE_ATTACH: {
762 filename = make_filename_safe(arg3);
763 if (!filename) {
764 return SQLITE_DENY;
765 }
766 efree(filename);
767 return SQLITE_OK;
768 }
769
770 default:
771 /* access allowed */
772 return SQLITE_OK;
773 }
774 }
775
pdo_sqlite_handle_factory(pdo_dbh_t * dbh,zval * driver_options)776 static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
777 {
778 pdo_sqlite_db_handle *H;
779 int i, ret = 0;
780 zend_long timeout = 60, flags;
781 char *filename;
782
783 H = pecalloc(1, sizeof(pdo_sqlite_db_handle), dbh->is_persistent);
784
785 H->einfo.errcode = 0;
786 H->einfo.errmsg = NULL;
787 dbh->driver_data = H;
788
789 /* skip all but this one param event */
790 dbh->skip_param_evt = 0x7F ^ (1 << PDO_PARAM_EVT_EXEC_PRE);
791
792 filename = make_filename_safe(dbh->data_source);
793
794 if (!filename) {
795 zend_throw_exception_ex(php_pdo_get_exception(), 0,
796 "open_basedir prohibits opening %s",
797 dbh->data_source);
798 goto cleanup;
799 }
800
801 flags = pdo_attr_lval(driver_options, PDO_SQLITE_ATTR_OPEN_FLAGS, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
802
803 if (!(PG(open_basedir) && *PG(open_basedir))) {
804 flags |= SQLITE_OPEN_URI;
805 }
806 i = sqlite3_open_v2(filename, &H->db, flags, NULL);
807
808 efree(filename);
809
810 if (i != SQLITE_OK) {
811 pdo_sqlite_error(dbh);
812 goto cleanup;
813 }
814
815 if (PG(open_basedir) && *PG(open_basedir)) {
816 sqlite3_set_authorizer(H->db, authorizer, NULL);
817 }
818
819 if (driver_options) {
820 timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout);
821 }
822 sqlite3_busy_timeout(H->db, timeout * 1000);
823
824 dbh->alloc_own_columns = 1;
825 dbh->max_escaped_char_length = 2;
826
827 ret = 1;
828
829 cleanup:
830 dbh->methods = &sqlite_methods;
831
832 return ret;
833 }
834 /* }}} */
835
836 const pdo_driver_t pdo_sqlite_driver = {
837 PDO_DRIVER_HEADER(sqlite),
838 pdo_sqlite_handle_factory
839 };
840