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 "ext/pdo/php_pdo.h"
25 #include "ext/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 (ZEND_FCC_INITIALIZED(func->func)) {
116 zend_fcc_dtor(&func->func);
117 }
118 if (ZEND_FCC_INITIALIZED(func->step)) {
119 zend_fcc_dtor(&func->step);
120 }
121 if (ZEND_FCC_INITIALIZED(func->fini)) {
122 zend_fcc_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 (ZEND_FCC_INITIALIZED(collation->callback)) {
143 zend_fcc_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_in_transaction(pdo_dbh_t * dbh)285 static bool pdo_sqlite_in_transaction(pdo_dbh_t *dbh)
286 {
287 pdo_sqlite_db_handle* H = (pdo_sqlite_db_handle*) dbh->driver_data;
288 /* It's not possible in sqlite3 to explicitly turn autocommit off other
289 * than manually starting a transaction. Manual transactions always are
290 * the mode of operation when autocommit is off. */
291 return H->db && sqlite3_get_autocommit(H->db) == 0;
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(zend_fcall_info_cache * fcc,int argc,sqlite3_value ** argv,sqlite3_context * context,int is_agg)321 static int do_callback(zend_fcall_info_cache *fcc, int argc, sqlite3_value **argv, sqlite3_context *context, int is_agg)
322 {
323 zval *zargs = NULL;
324 zval retval;
325 int i;
326 int ret = SUCCESS;
327 int fake_argc;
328 aggregate_context *agg_context = NULL;
329
330 if (is_agg) {
331 is_agg = 2;
332 }
333
334 fake_argc = argc + is_agg;
335
336 /* build up the params */
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 zend_call_known_fcc(fcc, &retval, fake_argc, zargs, /* named_params */ NULL);
378
379 /* clean up the params */
380 if (zargs) {
381 for (i = is_agg; i < fake_argc; i++) {
382 zval_ptr_dtor(&zargs[i]);
383 }
384 if (is_agg) {
385 zval_ptr_dtor(&zargs[1]);
386 }
387 efree(zargs);
388 }
389
390 if (!is_agg || !argv) {
391 /* only set the sqlite return value if we are a scalar function,
392 * or if we are finalizing an aggregate */
393 if (!Z_ISUNDEF(retval)) {
394 switch (Z_TYPE(retval)) {
395 case IS_LONG:
396 sqlite3_result_int(context, Z_LVAL(retval));
397 break;
398
399 case IS_NULL:
400 sqlite3_result_null(context);
401 break;
402
403 case IS_DOUBLE:
404 sqlite3_result_double(context, Z_DVAL(retval));
405 break;
406
407 default:
408 if (!try_convert_to_string(&retval)) {
409 ret = FAILURE;
410 break;
411 }
412 sqlite3_result_text(context, Z_STRVAL(retval), Z_STRLEN(retval), SQLITE_TRANSIENT);
413 break;
414 }
415 } else {
416 sqlite3_result_error(context, "failed to invoke callback", 0);
417 }
418
419 if (agg_context) {
420 zval_ptr_dtor(&agg_context->val);
421 }
422 } else {
423 /* we're stepping in an aggregate; the return value goes into
424 * the context */
425 if (agg_context) {
426 if (Z_ISUNDEF(retval)) {
427 return FAILURE;
428 }
429 zval_ptr_dtor(Z_REFVAL(agg_context->val));
430 ZVAL_COPY_VALUE(Z_REFVAL(agg_context->val), &retval);
431 ZVAL_UNDEF(&retval);
432 }
433 }
434
435 if (!Z_ISUNDEF(retval)) {
436 zval_ptr_dtor(&retval);
437 }
438
439 return ret;
440 }
441
php_sqlite3_func_step_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)442 static void php_sqlite3_func_step_callback(sqlite3_context *context, int argc, sqlite3_value **argv)
443 {
444 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
445
446 do_callback(&func->step, argc, argv, context, 1);
447 }
448
php_sqlite3_func_final_callback(sqlite3_context * context)449 static void php_sqlite3_func_final_callback(sqlite3_context *context)
450 {
451 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
452
453 do_callback(&func->fini, 0, NULL, context, 1);
454 }
455
php_sqlite3_collation_callback(void * context,int string1_len,const void * string1,int string2_len,const void * string2)456 static int php_sqlite3_collation_callback(void *context, int string1_len, const void *string1, int string2_len, const void *string2)
457 {
458 int ret = 0;
459 zval zargs[2];
460 zval retval;
461 struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context;
462
463 /* Prepare the arguments. */
464 ZVAL_STRINGL(&zargs[0], (char *) string1, string1_len);
465 ZVAL_STRINGL(&zargs[1], (char *) string2, string2_len);
466
467 zend_call_known_fcc(&collation->callback, &retval, /* argc */ 2, zargs, /* named_params */ NULL);
468
469 if (!Z_ISUNDEF(retval)) {
470 if (Z_TYPE(retval) != IS_LONG) {
471 convert_to_long(&retval);
472 }
473 if (Z_LVAL(retval) > 0) {
474 ret = 1;
475 } else if (Z_LVAL(retval) < 0) {
476 ret = -1;
477 }
478 zval_ptr_dtor(&retval);
479 }
480
481 zval_ptr_dtor(&zargs[0]);
482 zval_ptr_dtor(&zargs[1]);
483
484 return ret;
485 }
486
php_sqlite3_func_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)487 static void php_sqlite3_func_callback(sqlite3_context *context, int argc, sqlite3_value **argv)
488 {
489 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
490
491 do_callback(&func->func, argc, argv, context, 0);
492 }
493
pdo_sqlite_create_function_internal(INTERNAL_FUNCTION_PARAMETERS)494 void pdo_sqlite_create_function_internal(INTERNAL_FUNCTION_PARAMETERS)
495 {
496 struct pdo_sqlite_func *func;
497 zend_fcall_info fci = empty_fcall_info;
498 zend_fcall_info_cache fcc = empty_fcall_info_cache;
499 char *func_name;
500 size_t func_name_len;
501 zend_long argc = -1;
502 zend_long flags = 0;
503 pdo_dbh_t *dbh;
504 pdo_sqlite_db_handle *H;
505 int ret;
506
507 ZEND_PARSE_PARAMETERS_START(2, 4)
508 Z_PARAM_STRING(func_name, func_name_len)
509 Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(fci, fcc)
510 Z_PARAM_OPTIONAL
511 Z_PARAM_LONG(argc)
512 Z_PARAM_LONG(flags)
513 ZEND_PARSE_PARAMETERS_END_EX(goto error;);
514
515 dbh = Z_PDO_DBH_P(ZEND_THIS);
516 PDO_CONSTRUCT_CHECK;
517
518 H = (pdo_sqlite_db_handle *)dbh->driver_data;
519
520 func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
521
522 ret = sqlite3_create_function(H->db, func_name, argc, flags | SQLITE_UTF8, func, php_sqlite3_func_callback, NULL, NULL);
523 if (ret == SQLITE_OK) {
524 func->funcname = estrdup(func_name);
525
526 zend_fcc_dup(&func->func, &fcc);
527
528 func->argc = argc;
529
530 func->next = H->funcs;
531 H->funcs = func;
532
533 RETURN_TRUE;
534 }
535
536 efree(func);
537
538 error:
539 zend_release_fcall_info_cache(&fcc);
540 RETURN_FALSE;
541 }
542
543 /* {{{ bool SQLite::sqliteCreateFunction(string name, callable callback [, int argcount, int flags])
544 Registers a UDF with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateFunction)545 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateFunction)
546 {
547 pdo_sqlite_create_function_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU);
548 }
549 /* }}} */
550
pdo_sqlite_create_aggregate_internal(INTERNAL_FUNCTION_PARAMETERS)551 void pdo_sqlite_create_aggregate_internal(INTERNAL_FUNCTION_PARAMETERS)
552 {
553 struct pdo_sqlite_func *func;
554 zend_fcall_info step_fci = empty_fcall_info;
555 zend_fcall_info fini_fci = empty_fcall_info;
556 zend_fcall_info_cache step_fcc = empty_fcall_info_cache;
557 zend_fcall_info_cache fini_fcc = empty_fcall_info_cache;
558 char *func_name;
559 size_t func_name_len;
560 zend_long argc = -1;
561 pdo_dbh_t *dbh;
562 pdo_sqlite_db_handle *H;
563 int ret;
564
565 ZEND_PARSE_PARAMETERS_START(3, 4)
566 Z_PARAM_STRING(func_name, func_name_len)
567 Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(step_fci, step_fcc)
568 Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(fini_fci, fini_fcc)
569 Z_PARAM_OPTIONAL
570 Z_PARAM_LONG(argc)
571 ZEND_PARSE_PARAMETERS_END_EX(goto error;);
572
573 dbh = Z_PDO_DBH_P(ZEND_THIS);
574 PDO_CONSTRUCT_CHECK;
575
576 H = (pdo_sqlite_db_handle *)dbh->driver_data;
577
578 func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
579
580 ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8, func, NULL,
581 php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
582 if (ret == SQLITE_OK) {
583 func->funcname = estrdup(func_name);
584
585 zend_fcc_dup(&func->step, &step_fcc);
586 zend_fcc_dup(&func->fini, &fini_fcc);
587
588 func->argc = argc;
589
590 func->next = H->funcs;
591 H->funcs = func;
592
593 RETURN_TRUE;
594 }
595
596 efree(func);
597
598 error:
599 zend_release_fcall_info_cache(&step_fcc);
600 zend_release_fcall_info_cache(&fini_fcc);
601 RETURN_FALSE;
602 }
603
604 /* {{{ bool SQLite::sqliteCreateAggregate(string name, callable step, callable fini [, int argcount])
605 Registers a UDF with the sqlite db handle */
606
607 /* The step function should have the prototype:
608 mixed step(mixed $context, int $rownumber, $value [, $value2 [, ...]])
609
610 $context will be null for the first row; on subsequent rows it will have
611 the value that was previously returned from the step function; you should
612 use this to maintain state for the aggregate.
613
614 The fini function should have the prototype:
615 mixed fini(mixed $context, int $rownumber)
616
617 $context will hold the return value from the very last call to the step function.
618 rownumber will hold the number of rows over which the aggregate was performed.
619 The return value of this function will be used as the return value for this
620 aggregate UDF.
621 */
622
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateAggregate)623 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateAggregate)
624 {
625 pdo_sqlite_create_aggregate_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU);
626 }
627 /* }}} */
628
pdo_sqlite_create_collation_internal(INTERNAL_FUNCTION_PARAMETERS,pdo_sqlite_create_collation_callback callback)629 void pdo_sqlite_create_collation_internal(INTERNAL_FUNCTION_PARAMETERS, pdo_sqlite_create_collation_callback callback)
630 {
631 struct pdo_sqlite_collation *collation;
632 zend_fcall_info fci = empty_fcall_info;
633 zend_fcall_info_cache fcc = empty_fcall_info_cache;
634 char *collation_name;
635 size_t collation_name_len;
636 pdo_dbh_t *dbh;
637 pdo_sqlite_db_handle *H;
638 int ret;
639
640 ZEND_PARSE_PARAMETERS_START(2, 2)
641 Z_PARAM_STRING(collation_name, collation_name_len)
642 Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(fci, fcc)
643 ZEND_PARSE_PARAMETERS_END();
644
645 dbh = Z_PDO_DBH_P(ZEND_THIS);
646 PDO_CONSTRUCT_CHECK;
647
648 H = (pdo_sqlite_db_handle *)dbh->driver_data;
649
650 collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));
651
652 ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, callback);
653 if (ret == SQLITE_OK) {
654 collation->name = estrdup(collation_name);
655
656 zend_fcc_dup(&collation->callback, &fcc);
657
658 collation->next = H->collations;
659 H->collations = collation;
660
661 RETURN_TRUE;
662 }
663
664 zend_release_fcall_info_cache(&fcc);
665
666 if (UNEXPECTED(EG(exception))) {
667 RETURN_THROWS();
668 }
669
670 efree(collation);
671 RETURN_FALSE;
672 }
673
674 /* {{{ bool SQLite::sqliteCreateCollation(string name, callable callback)
675 Registers a collation with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateCollation)676 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateCollation)
677 {
678 pdo_sqlite_create_collation_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_sqlite3_collation_callback);
679 }
680 /* }}} */
681
get_driver_methods(pdo_dbh_t * dbh,int kind)682 static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind)
683 {
684 switch (kind) {
685 case PDO_DBH_DRIVER_METHOD_KIND_DBH:
686 return class_PDO_SQLite_Ext_methods;
687
688 default:
689 return NULL;
690 }
691 }
692
pdo_sqlite_request_shutdown(pdo_dbh_t * dbh)693 static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh)
694 {
695 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
696 /* unregister functions, so that they don't linger for the next
697 * request */
698 if (H) {
699 pdo_sqlite_cleanup_callbacks(H);
700 }
701 }
702
pdo_sqlite_get_gc(pdo_dbh_t * dbh,zend_get_gc_buffer * gc_buffer)703 static void pdo_sqlite_get_gc(pdo_dbh_t *dbh, zend_get_gc_buffer *gc_buffer)
704 {
705 pdo_sqlite_db_handle *H = dbh->driver_data;
706
707 struct pdo_sqlite_func *func = H->funcs;
708 while (func) {
709 if (ZEND_FCC_INITIALIZED(func->func)) {
710 zend_get_gc_buffer_add_fcc(gc_buffer, &func->func);
711 }
712 if (ZEND_FCC_INITIALIZED(func->step)) {
713 zend_get_gc_buffer_add_fcc(gc_buffer, &func->step);
714 }
715 if (ZEND_FCC_INITIALIZED(func->fini)) {
716 zend_get_gc_buffer_add_fcc(gc_buffer, &func->fini);
717 }
718 func = func->next;
719 }
720
721 struct pdo_sqlite_collation *collation = H->collations;
722 while (collation) {
723 if (ZEND_FCC_INITIALIZED(collation->callback)) {
724 zend_get_gc_buffer_add_fcc(gc_buffer, &collation->callback);
725 }
726 collation = collation->next;
727 }
728 }
729
730 static const struct pdo_dbh_methods sqlite_methods = {
731 sqlite_handle_closer,
732 sqlite_handle_preparer,
733 sqlite_handle_doer,
734 sqlite_handle_quoter,
735 sqlite_handle_begin,
736 sqlite_handle_commit,
737 sqlite_handle_rollback,
738 pdo_sqlite_set_attr,
739 pdo_sqlite_last_insert_id,
740 pdo_sqlite_fetch_error_func,
741 pdo_sqlite_get_attribute,
742 NULL, /* check_liveness: not needed */
743 get_driver_methods,
744 pdo_sqlite_request_shutdown,
745 pdo_sqlite_in_transaction,
746 pdo_sqlite_get_gc,
747 pdo_sqlite_scanner
748 };
749
make_filename_safe(const char * filename)750 static char *make_filename_safe(const char *filename)
751 {
752 if (!filename) {
753 return NULL;
754 }
755 if (*filename && strncasecmp(filename, "file:", 5) == 0) {
756 if (PG(open_basedir) && *PG(open_basedir)) {
757 return NULL;
758 }
759 return estrdup(filename);
760 }
761 if (*filename && strcmp(filename, ":memory:")) {
762 char *fullpath = expand_filepath(filename, NULL);
763
764 if (!fullpath) {
765 return NULL;
766 }
767
768 if (php_check_open_basedir(fullpath)) {
769 efree(fullpath);
770 return NULL;
771 }
772 return fullpath;
773 }
774 return estrdup(filename);
775 }
776
authorizer(void * autharg,int access_type,const char * arg3,const char * arg4,const char * arg5,const char * arg6)777 static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
778 const char *arg5, const char *arg6)
779 {
780 char *filename;
781 switch (access_type) {
782 case SQLITE_ATTACH: {
783 filename = make_filename_safe(arg3);
784 if (!filename) {
785 return SQLITE_DENY;
786 }
787 efree(filename);
788 return SQLITE_OK;
789 }
790
791 default:
792 /* access allowed */
793 return SQLITE_OK;
794 }
795 }
796
pdo_sqlite_handle_factory(pdo_dbh_t * dbh,zval * driver_options)797 static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
798 {
799 pdo_sqlite_db_handle *H;
800 int i, ret = 0;
801 zend_long timeout = 60, flags;
802 char *filename;
803
804 H = pecalloc(1, sizeof(pdo_sqlite_db_handle), dbh->is_persistent);
805
806 H->einfo.errcode = 0;
807 H->einfo.errmsg = NULL;
808 dbh->driver_data = H;
809
810 /* skip all but this one param event */
811 dbh->skip_param_evt = 0x7F ^ (1 << PDO_PARAM_EVT_EXEC_PRE);
812
813 filename = make_filename_safe(dbh->data_source);
814
815 if (!filename) {
816 zend_throw_exception_ex(php_pdo_get_exception(), 0,
817 "open_basedir prohibits opening %s",
818 dbh->data_source);
819 goto cleanup;
820 }
821
822 flags = pdo_attr_lval(driver_options, PDO_SQLITE_ATTR_OPEN_FLAGS, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
823
824 if (!(PG(open_basedir) && *PG(open_basedir))) {
825 flags |= SQLITE_OPEN_URI;
826 }
827 i = sqlite3_open_v2(filename, &H->db, flags, NULL);
828
829 efree(filename);
830
831 if (i != SQLITE_OK) {
832 pdo_sqlite_error(dbh);
833 goto cleanup;
834 }
835
836 if (PG(open_basedir) && *PG(open_basedir)) {
837 sqlite3_set_authorizer(H->db, authorizer, NULL);
838 }
839
840 if (driver_options) {
841 timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout);
842 }
843 sqlite3_busy_timeout(H->db, timeout * 1000);
844
845 dbh->alloc_own_columns = 1;
846 dbh->max_escaped_char_length = 2;
847
848 ret = 1;
849
850 cleanup:
851 dbh->methods = &sqlite_methods;
852
853 return ret;
854 }
855 /* }}} */
856
857 const pdo_driver_t pdo_sqlite_driver = {
858 PDO_DRIVER_HEADER(sqlite),
859 pdo_sqlite_handle_factory
860 };
861