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