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, int argc, sqlite3_value **argv, sqlite3_context *context, int is_agg)
313 {
314 zval *zargs = NULL;
315 zval retval;
316 int i;
317 int ret;
318 int fake_argc;
319 aggregate_context *agg_context = NULL;
320
321 if (is_agg) {
322 is_agg = 2;
323 }
324
325 fake_argc = argc + is_agg;
326
327 fc->fci.size = sizeof(fc->fci);
328 ZVAL_COPY_VALUE(&fc->fci.function_name, cb);
329 fc->fci.object = NULL;
330 fc->fci.retval = &retval;
331 fc->fci.param_count = fake_argc;
332
333 /* build up the params */
334
335 if (fake_argc) {
336 zargs = safe_emalloc(fake_argc, sizeof(zval), 0);
337 }
338
339 if (is_agg) {
340 agg_context = sqlite3_aggregate_context(context, sizeof(aggregate_context));
341 if (!agg_context) {
342 efree(zargs);
343 return FAILURE;
344 }
345 if (Z_ISUNDEF(agg_context->val)) {
346 ZVAL_NEW_REF(&agg_context->val, &EG(uninitialized_zval));
347 }
348 ZVAL_COPY_VALUE(&zargs[0], &agg_context->val);
349 ZVAL_LONG(&zargs[1], ++agg_context->row);
350 }
351
352 for (i = 0; i < argc; i++) {
353 /* get the value */
354 switch (sqlite3_value_type(argv[i])) {
355 case SQLITE_INTEGER:
356 ZVAL_LONG(&zargs[i + is_agg], sqlite3_value_int(argv[i]));
357 break;
358
359 case SQLITE_FLOAT:
360 ZVAL_DOUBLE(&zargs[i + is_agg], sqlite3_value_double(argv[i]));
361 break;
362
363 case SQLITE_NULL:
364 ZVAL_NULL(&zargs[i + is_agg]);
365 break;
366
367 case SQLITE_BLOB:
368 case SQLITE3_TEXT:
369 default:
370 ZVAL_STRINGL(&zargs[i + is_agg], (char*)sqlite3_value_text(argv[i]), sqlite3_value_bytes(argv[i]));
371 break;
372 }
373 }
374
375 fc->fci.params = zargs;
376
377 if ((ret = zend_call_function(&fc->fci, &fc->fcc)) == FAILURE) {
378 php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
379 }
380
381 /* clean up the params */
382 if (zargs) {
383 for (i = is_agg; i < fake_argc; i++) {
384 zval_ptr_dtor(&zargs[i]);
385 }
386 if (is_agg) {
387 zval_ptr_dtor(&zargs[1]);
388 }
389 efree(zargs);
390 }
391
392 if (!is_agg || !argv) {
393 /* only set the sqlite return value if we are a scalar function,
394 * or if we are finalizing an aggregate */
395 if (!Z_ISUNDEF(retval)) {
396 switch (Z_TYPE(retval)) {
397 case IS_LONG:
398 sqlite3_result_int(context, Z_LVAL(retval));
399 break;
400
401 case IS_NULL:
402 sqlite3_result_null(context);
403 break;
404
405 case IS_DOUBLE:
406 sqlite3_result_double(context, Z_DVAL(retval));
407 break;
408
409 default:
410 if (!try_convert_to_string(&retval)) {
411 ret = FAILURE;
412 break;
413 }
414 sqlite3_result_text(context, Z_STRVAL(retval), Z_STRLEN(retval), SQLITE_TRANSIENT);
415 break;
416 }
417 } else {
418 sqlite3_result_error(context, "failed to invoke callback", 0);
419 }
420
421 if (agg_context) {
422 zval_ptr_dtor(&agg_context->val);
423 }
424 } else {
425 /* we're stepping in an aggregate; the return value goes into
426 * the context */
427 if (agg_context) {
428 if (Z_ISUNDEF(retval)) {
429 zval_ptr_dtor(&agg_context->val);
430 return FAILURE;
431 }
432 zval_ptr_dtor(Z_REFVAL(agg_context->val));
433 ZVAL_COPY_VALUE(Z_REFVAL(agg_context->val), &retval);
434 ZVAL_UNDEF(&retval);
435 }
436 }
437
438 if (!Z_ISUNDEF(retval)) {
439 zval_ptr_dtor(&retval);
440 }
441
442 return ret;
443 }
444
php_sqlite3_func_step_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)445 static void php_sqlite3_func_step_callback(sqlite3_context *context, int argc, sqlite3_value **argv)
446 {
447 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
448
449 do_callback(&func->astep, &func->step, argc, argv, context, 1);
450 }
451
php_sqlite3_func_final_callback(sqlite3_context * context)452 static void php_sqlite3_func_final_callback(sqlite3_context *context)
453 {
454 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
455
456 do_callback(&func->afini, &func->fini, 0, NULL, context, 1);
457 }
458
php_sqlite3_collation_callback(void * context,int string1_len,const void * string1,int string2_len,const void * string2)459 static int php_sqlite3_collation_callback(void *context, int string1_len, const void *string1, int string2_len, const void *string2)
460 {
461 int ret;
462 zval zargs[2];
463 zval retval;
464 struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context;
465
466 collation->fc.fci.size = sizeof(collation->fc.fci);
467 ZVAL_COPY_VALUE(&collation->fc.fci.function_name, &collation->callback);
468 collation->fc.fci.object = NULL;
469 collation->fc.fci.retval = &retval;
470
471 /* Prepare the arguments. */
472 ZVAL_STRINGL(&zargs[0], (char *) string1, string1_len);
473 ZVAL_STRINGL(&zargs[1], (char *) string2, string2_len);
474 collation->fc.fci.param_count = 2;
475 collation->fc.fci.params = zargs;
476
477 if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc)) == FAILURE) {
478 php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
479 } else if (!Z_ISUNDEF(retval)) {
480 if (Z_TYPE(retval) != IS_LONG) {
481 convert_to_long(&retval);
482 }
483 ret = 0;
484 if (Z_LVAL(retval) > 0) {
485 ret = 1;
486 } else if (Z_LVAL(retval) < 0) {
487 ret = -1;
488 }
489 zval_ptr_dtor(&retval);
490 }
491
492 zval_ptr_dtor(&zargs[0]);
493 zval_ptr_dtor(&zargs[1]);
494
495 return ret;
496 }
497
php_sqlite3_func_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)498 static void php_sqlite3_func_callback(sqlite3_context *context, int argc, sqlite3_value **argv)
499 {
500 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
501
502 do_callback(&func->afunc, &func->func, argc, argv, context, 0);
503 }
504
pdo_sqlite_create_function_internal(INTERNAL_FUNCTION_PARAMETERS)505 void pdo_sqlite_create_function_internal(INTERNAL_FUNCTION_PARAMETERS)
506 {
507 struct pdo_sqlite_func *func;
508 zend_fcall_info fci;
509 zend_fcall_info_cache fcc;
510 char *func_name;
511 size_t func_name_len;
512 zend_long argc = -1;
513 zend_long flags = 0;
514 pdo_dbh_t *dbh;
515 pdo_sqlite_db_handle *H;
516 int ret;
517
518 ZEND_PARSE_PARAMETERS_START(2, 4)
519 Z_PARAM_STRING(func_name, func_name_len)
520 Z_PARAM_FUNC(fci, fcc)
521 Z_PARAM_OPTIONAL
522 Z_PARAM_LONG(argc)
523 Z_PARAM_LONG(flags)
524 ZEND_PARSE_PARAMETERS_END();
525
526 dbh = Z_PDO_DBH_P(ZEND_THIS);
527 PDO_CONSTRUCT_CHECK;
528
529 H = (pdo_sqlite_db_handle *)dbh->driver_data;
530
531 func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
532
533 ret = sqlite3_create_function(H->db, func_name, argc, flags | SQLITE_UTF8, func, php_sqlite3_func_callback, NULL, NULL);
534 if (ret == SQLITE_OK) {
535 func->funcname = estrdup(func_name);
536
537 ZVAL_COPY(&func->func, &fci.function_name);
538
539 func->argc = argc;
540
541 func->next = H->funcs;
542 H->funcs = func;
543
544 RETURN_TRUE;
545 }
546
547 efree(func);
548 RETURN_FALSE;
549 }
550
551 /* {{{ bool SQLite::sqliteCreateFunction(string name, callable callback [, int argcount, int flags])
552 Registers a UDF with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateFunction)553 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateFunction)
554 {
555 pdo_sqlite_create_function_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU);
556 }
557 /* }}} */
558
pdo_sqlite_create_aggregate_internal(INTERNAL_FUNCTION_PARAMETERS)559 void pdo_sqlite_create_aggregate_internal(INTERNAL_FUNCTION_PARAMETERS)
560 {
561 struct pdo_sqlite_func *func;
562 zend_fcall_info step_fci, fini_fci;
563 zend_fcall_info_cache step_fcc, fini_fcc;
564 char *func_name;
565 size_t func_name_len;
566 zend_long argc = -1;
567 pdo_dbh_t *dbh;
568 pdo_sqlite_db_handle *H;
569 int ret;
570
571 ZEND_PARSE_PARAMETERS_START(3, 4)
572 Z_PARAM_STRING(func_name, func_name_len)
573 Z_PARAM_FUNC(step_fci, step_fcc)
574 Z_PARAM_FUNC(fini_fci, fini_fcc)
575 Z_PARAM_OPTIONAL
576 Z_PARAM_LONG(argc)
577 ZEND_PARSE_PARAMETERS_END();
578
579 dbh = Z_PDO_DBH_P(ZEND_THIS);
580 PDO_CONSTRUCT_CHECK;
581
582 H = (pdo_sqlite_db_handle *)dbh->driver_data;
583
584 func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
585
586 ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8, func, NULL,
587 php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
588 if (ret == SQLITE_OK) {
589 func->funcname = estrdup(func_name);
590
591 ZVAL_COPY(&func->step, &step_fci.function_name);
592
593 ZVAL_COPY(&func->fini, &fini_fci.function_name);
594
595 func->argc = argc;
596
597 func->next = H->funcs;
598 H->funcs = func;
599
600 RETURN_TRUE;
601 }
602
603 efree(func);
604 RETURN_FALSE;
605 }
606
607 /* {{{ bool SQLite::sqliteCreateAggregate(string name, callable step, callable fini [, int argcount])
608 Registers a UDF with the sqlite db handle */
609
610 /* The step function should have the prototype:
611 mixed step(mixed $context, int $rownumber, $value [, $value2 [, ...]])
612
613 $context will be null for the first row; on subsequent rows it will have
614 the value that was previously returned from the step function; you should
615 use this to maintain state for the aggregate.
616
617 The fini function should have the prototype:
618 mixed fini(mixed $context, int $rownumber)
619
620 $context will hold the return value from the very last call to the step function.
621 rownumber will hold the number of rows over which the aggregate was performed.
622 The return value of this function will be used as the return value for this
623 aggregate UDF.
624 */
625
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateAggregate)626 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateAggregate)
627 {
628 pdo_sqlite_create_aggregate_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU);
629 }
630 /* }}} */
631
pdo_sqlite_create_collation_internal(INTERNAL_FUNCTION_PARAMETERS,pdo_sqlite_create_collation_callback callback)632 void pdo_sqlite_create_collation_internal(INTERNAL_FUNCTION_PARAMETERS, pdo_sqlite_create_collation_callback callback)
633 {
634 struct pdo_sqlite_collation *collation;
635 zend_fcall_info fci;
636 zend_fcall_info_cache fcc;
637 char *collation_name;
638 size_t collation_name_len;
639 pdo_dbh_t *dbh;
640 pdo_sqlite_db_handle *H;
641 int ret;
642
643 ZEND_PARSE_PARAMETERS_START(2, 2)
644 Z_PARAM_STRING(collation_name, collation_name_len)
645 Z_PARAM_FUNC(fci, fcc)
646 ZEND_PARSE_PARAMETERS_END();
647
648 dbh = Z_PDO_DBH_P(ZEND_THIS);
649 PDO_CONSTRUCT_CHECK;
650
651 H = (pdo_sqlite_db_handle *)dbh->driver_data;
652
653 collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));
654
655 ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, callback);
656 if (ret == SQLITE_OK) {
657 collation->name = estrdup(collation_name);
658
659 ZVAL_COPY(&collation->callback, &fci.function_name);
660
661 collation->next = H->collations;
662 H->collations = collation;
663
664 RETURN_TRUE;
665 }
666
667 if (UNEXPECTED(EG(exception))) {
668 RETURN_THROWS();
669 }
670
671 efree(collation);
672 RETURN_FALSE;
673 }
674
675 /* {{{ bool SQLite::sqliteCreateCollation(string name, callable callback)
676 Registers a collation with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateCollation)677 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateCollation)
678 {
679 pdo_sqlite_create_collation_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_sqlite3_collation_callback);
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 && memcmp(filename, ":memory:", sizeof(":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