1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2018 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Author: Wez Furlong <wez@php.net> |
16 +----------------------------------------------------------------------+
17 */
18
19 /* $Id$ */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "php.h"
26 #include "php_ini.h"
27 #include "ext/standard/info.h"
28 #include "pdo/php_pdo.h"
29 #include "pdo/php_pdo_driver.h"
30 #include "php_pdo_sqlite.h"
31 #include "php_pdo_sqlite_int.h"
32 #include "zend_exceptions.h"
33
_pdo_sqlite_error(pdo_dbh_t * dbh,pdo_stmt_t * stmt,const char * file,int line)34 int _pdo_sqlite_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int line) /* {{{ */
35 {
36 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
37 pdo_error_type *pdo_err = stmt ? &stmt->error_code : &dbh->error_code;
38 pdo_sqlite_error_info *einfo = &H->einfo;
39
40 einfo->errcode = sqlite3_errcode(H->db);
41 einfo->file = file;
42 einfo->line = line;
43
44 if (einfo->errcode != SQLITE_OK) {
45 if (einfo->errmsg) {
46 pefree(einfo->errmsg, dbh->is_persistent);
47 }
48 einfo->errmsg = pestrdup((char*)sqlite3_errmsg(H->db), dbh->is_persistent);
49 } else { /* no error */
50 strncpy(*pdo_err, PDO_ERR_NONE, sizeof(PDO_ERR_NONE));
51 return 0;
52 }
53 switch (einfo->errcode) {
54 case SQLITE_NOTFOUND:
55 strncpy(*pdo_err, "42S02", sizeof("42S02"));
56 break;
57
58 case SQLITE_INTERRUPT:
59 strncpy(*pdo_err, "01002", sizeof("01002"));
60 break;
61
62 case SQLITE_NOLFS:
63 strncpy(*pdo_err, "HYC00", sizeof("HYC00"));
64 break;
65
66 case SQLITE_TOOBIG:
67 strncpy(*pdo_err, "22001", sizeof("22001"));
68 break;
69
70 case SQLITE_CONSTRAINT:
71 strncpy(*pdo_err, "23000", sizeof("23000"));
72 break;
73
74 case SQLITE_ERROR:
75 default:
76 strncpy(*pdo_err, "HY000", sizeof("HY000"));
77 break;
78 }
79
80 if (!dbh->methods) {
81 zend_throw_exception_ex(php_pdo_get_exception(), einfo->errcode, "SQLSTATE[%s] [%d] %s",
82 *pdo_err, einfo->errcode, einfo->errmsg);
83 }
84
85 return einfo->errcode;
86 }
87 /* }}} */
88
pdo_sqlite_fetch_error_func(pdo_dbh_t * dbh,pdo_stmt_t * stmt,zval * info)89 static int pdo_sqlite_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info)
90 {
91 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
92 pdo_sqlite_error_info *einfo = &H->einfo;
93
94 if (einfo->errcode) {
95 add_next_index_long(info, einfo->errcode);
96 add_next_index_string(info, einfo->errmsg);
97 }
98
99 return 1;
100 }
101
pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle * H)102 static void pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle *H)
103 {
104 struct pdo_sqlite_func *func;
105
106 while (H->funcs) {
107 func = H->funcs;
108 H->funcs = func->next;
109
110 if (H->db) {
111 /* delete the function from the handle */
112 sqlite3_create_function(H->db,
113 func->funcname,
114 func->argc,
115 SQLITE_UTF8,
116 func,
117 NULL, NULL, NULL);
118 }
119
120 efree((char*)func->funcname);
121 if (!Z_ISUNDEF(func->func)) {
122 zval_ptr_dtor(&func->func);
123 }
124 if (!Z_ISUNDEF(func->step)) {
125 zval_ptr_dtor(&func->step);
126 }
127 if (!Z_ISUNDEF(func->fini)) {
128 zval_ptr_dtor(&func->fini);
129 }
130 efree(func);
131 }
132
133 while (H->collations) {
134 struct pdo_sqlite_collation *collation;
135 collation = H->collations;
136 H->collations = collation->next;
137
138 if (H->db) {
139 /* delete the collation from the handle */
140 sqlite3_create_collation(H->db,
141 collation->name,
142 SQLITE_UTF8,
143 collation,
144 NULL);
145 }
146
147 efree((char*)collation->name);
148 if (!Z_ISUNDEF(collation->callback)) {
149 zval_ptr_dtor(&collation->callback);
150 }
151 efree(collation);
152 }
153 }
154
sqlite_handle_closer(pdo_dbh_t * dbh)155 static int sqlite_handle_closer(pdo_dbh_t *dbh) /* {{{ */
156 {
157 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
158
159 if (H) {
160 pdo_sqlite_error_info *einfo = &H->einfo;
161
162 pdo_sqlite_cleanup_callbacks(H);
163 if (H->db) {
164 #ifdef HAVE_SQLITE3_CLOSE_V2
165 sqlite3_close_v2(H->db);
166 #else
167 sqlite3_close(H->db);
168 #endif
169 H->db = NULL;
170 }
171 if (einfo->errmsg) {
172 pefree(einfo->errmsg, dbh->is_persistent);
173 einfo->errmsg = NULL;
174 }
175 pefree(H, dbh->is_persistent);
176 dbh->driver_data = NULL;
177 }
178 return 0;
179 }
180 /* }}} */
181
sqlite_handle_preparer(pdo_dbh_t * dbh,const char * sql,size_t sql_len,pdo_stmt_t * stmt,zval * driver_options)182 static int sqlite_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len, pdo_stmt_t *stmt, zval *driver_options)
183 {
184 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
185 pdo_sqlite_stmt *S = ecalloc(1, sizeof(pdo_sqlite_stmt));
186 int i;
187 const char *tail;
188
189 S->H = H;
190 stmt->driver_data = S;
191 stmt->methods = &sqlite_stmt_methods;
192 stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL|PDO_PLACEHOLDER_NAMED;
193
194 if (PDO_CURSOR_FWDONLY != pdo_attr_lval(driver_options, PDO_ATTR_CURSOR, PDO_CURSOR_FWDONLY)) {
195 H->einfo.errcode = SQLITE_ERROR;
196 pdo_sqlite_error(dbh);
197 return 0;
198 }
199
200 i = sqlite3_prepare_v2(H->db, sql, sql_len, &S->stmt, &tail);
201 if (i == SQLITE_OK) {
202 return 1;
203 }
204
205 pdo_sqlite_error(dbh);
206
207 return 0;
208 }
209
sqlite_handle_doer(pdo_dbh_t * dbh,const char * sql,size_t sql_len)210 static zend_long sqlite_handle_doer(pdo_dbh_t *dbh, const char *sql, size_t sql_len)
211 {
212 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
213 char *errmsg = NULL;
214
215 if (sqlite3_exec(H->db, sql, NULL, NULL, &errmsg) != SQLITE_OK) {
216 pdo_sqlite_error(dbh);
217 if (errmsg)
218 sqlite3_free(errmsg);
219
220 return -1;
221 } else {
222 return sqlite3_changes(H->db);
223 }
224 }
225
pdo_sqlite_last_insert_id(pdo_dbh_t * dbh,const char * name,size_t * len)226 static char *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const char *name, size_t *len)
227 {
228 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
229 char *id;
230
231 id = php_pdo_int64_to_str(sqlite3_last_insert_rowid(H->db));
232 *len = strlen(id);
233 return id;
234 }
235
236 /* NB: doesn't handle binary strings... use prepared stmts for that */
sqlite_handle_quoter(pdo_dbh_t * dbh,const char * unquoted,size_t unquotedlen,char ** quoted,size_t * quotedlen,enum pdo_param_type paramtype)237 static int sqlite_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, char **quoted, size_t *quotedlen, enum pdo_param_type paramtype )
238 {
239 *quoted = safe_emalloc(2, unquotedlen, 3);
240 sqlite3_snprintf(2*unquotedlen + 3, *quoted, "'%q'", unquoted);
241 *quotedlen = strlen(*quoted);
242 return 1;
243 }
244
sqlite_handle_begin(pdo_dbh_t * dbh)245 static int sqlite_handle_begin(pdo_dbh_t *dbh)
246 {
247 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
248 char *errmsg = NULL;
249
250 if (sqlite3_exec(H->db, "BEGIN", NULL, NULL, &errmsg) != SQLITE_OK) {
251 pdo_sqlite_error(dbh);
252 if (errmsg)
253 sqlite3_free(errmsg);
254 return 0;
255 }
256 return 1;
257 }
258
sqlite_handle_commit(pdo_dbh_t * dbh)259 static int sqlite_handle_commit(pdo_dbh_t *dbh)
260 {
261 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
262 char *errmsg = NULL;
263
264 if (sqlite3_exec(H->db, "COMMIT", NULL, NULL, &errmsg) != SQLITE_OK) {
265 pdo_sqlite_error(dbh);
266 if (errmsg)
267 sqlite3_free(errmsg);
268 return 0;
269 }
270 return 1;
271 }
272
sqlite_handle_rollback(pdo_dbh_t * dbh)273 static int sqlite_handle_rollback(pdo_dbh_t *dbh)
274 {
275 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
276 char *errmsg = NULL;
277
278 if (sqlite3_exec(H->db, "ROLLBACK", NULL, NULL, &errmsg) != SQLITE_OK) {
279 pdo_sqlite_error(dbh);
280 if (errmsg)
281 sqlite3_free(errmsg);
282 return 0;
283 }
284 return 1;
285 }
286
pdo_sqlite_get_attribute(pdo_dbh_t * dbh,zend_long attr,zval * return_value)287 static int pdo_sqlite_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_value)
288 {
289 switch (attr) {
290 case PDO_ATTR_CLIENT_VERSION:
291 case PDO_ATTR_SERVER_VERSION:
292 ZVAL_STRING(return_value, (char *)sqlite3_libversion());
293 break;
294
295 default:
296 return 0;
297 }
298
299 return 1;
300 }
301
pdo_sqlite_set_attr(pdo_dbh_t * dbh,zend_long attr,zval * val)302 static int pdo_sqlite_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
303 {
304 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
305
306 switch (attr) {
307 case PDO_ATTR_TIMEOUT:
308 sqlite3_busy_timeout(H->db, zval_get_long(val) * 1000);
309 return 1;
310 }
311 return 0;
312 }
313
do_callback(struct pdo_sqlite_fci * fc,zval * cb,int argc,sqlite3_value ** argv,sqlite3_context * context,int is_agg)314 static int do_callback(struct pdo_sqlite_fci *fc, zval *cb,
315 int argc, sqlite3_value **argv, sqlite3_context *context,
316 int is_agg)
317 {
318 zval *zargs = NULL;
319 zval retval;
320 int i;
321 int ret;
322 int fake_argc;
323 zend_reference *agg_context = NULL;
324
325 if (is_agg) {
326 is_agg = 2;
327 }
328
329 fake_argc = argc + is_agg;
330
331 fc->fci.size = sizeof(fc->fci);
332 ZVAL_COPY_VALUE(&fc->fci.function_name, cb);
333 fc->fci.object = NULL;
334 fc->fci.retval = &retval;
335 fc->fci.param_count = fake_argc;
336
337 /* build up the params */
338
339 if (fake_argc) {
340 zargs = safe_emalloc(fake_argc, sizeof(zval), 0);
341 }
342
343 if (is_agg) {
344 agg_context = (zend_reference*)sqlite3_aggregate_context(context, sizeof(zend_reference));
345 if (!agg_context) {
346 ZVAL_NULL(&zargs[0]);
347 } else {
348 if (Z_ISUNDEF(agg_context->val)) {
349 GC_REFCOUNT(agg_context) = 1;
350 GC_TYPE_INFO(agg_context) = IS_REFERENCE;
351 ZVAL_NULL(&agg_context->val);
352 }
353 ZVAL_REF(&zargs[0], agg_context);
354 }
355 ZVAL_LONG(&zargs[1], sqlite3_aggregate_count(context));
356 }
357
358 for (i = 0; i < argc; i++) {
359 /* get the value */
360 switch (sqlite3_value_type(argv[i])) {
361 case SQLITE_INTEGER:
362 ZVAL_LONG(&zargs[i + is_agg], sqlite3_value_int(argv[i]));
363 break;
364
365 case SQLITE_FLOAT:
366 ZVAL_DOUBLE(&zargs[i + is_agg], sqlite3_value_double(argv[i]));
367 break;
368
369 case SQLITE_NULL:
370 ZVAL_NULL(&zargs[i + is_agg]);
371 break;
372
373 case SQLITE_BLOB:
374 case SQLITE3_TEXT:
375 default:
376 ZVAL_STRINGL(&zargs[i + is_agg], (char*)sqlite3_value_text(argv[i]), sqlite3_value_bytes(argv[i]));
377 break;
378 }
379 }
380
381 fc->fci.params = zargs;
382
383 if ((ret = zend_call_function(&fc->fci, &fc->fcc)) == FAILURE) {
384 php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
385 }
386
387 /* clean up the params */
388 if (zargs) {
389 for (i = is_agg; i < fake_argc; i++) {
390 zval_ptr_dtor(&zargs[i]);
391 }
392 if (is_agg) {
393 zval_ptr_dtor(&zargs[1]);
394 }
395 efree(zargs);
396 }
397
398 if (!is_agg || !argv) {
399 /* only set the sqlite return value if we are a scalar function,
400 * or if we are finalizing an aggregate */
401 if (!Z_ISUNDEF(retval)) {
402 switch (Z_TYPE(retval)) {
403 case IS_LONG:
404 sqlite3_result_int(context, Z_LVAL(retval));
405 break;
406
407 case IS_NULL:
408 sqlite3_result_null(context);
409 break;
410
411 case IS_DOUBLE:
412 sqlite3_result_double(context, Z_DVAL(retval));
413 break;
414
415 default:
416 convert_to_string_ex(&retval);
417 sqlite3_result_text(context, Z_STRVAL(retval), Z_STRLEN(retval), SQLITE_TRANSIENT);
418 break;
419 }
420 } else {
421 sqlite3_result_error(context, "failed to invoke callback", 0);
422 }
423
424 if (agg_context) {
425 zval_ptr_dtor(&agg_context->val);
426 }
427 } else {
428 /* we're stepping in an aggregate; the return value goes into
429 * the context */
430 if (agg_context) {
431 zval_ptr_dtor(&agg_context->val);
432 }
433 if (!Z_ISUNDEF(retval)) {
434 ZVAL_COPY_VALUE(&agg_context->val, &retval);
435 ZVAL_UNDEF(&retval);
436 } else {
437 ZVAL_UNDEF(&agg_context->val);
438 }
439 }
440
441 if (!Z_ISUNDEF(retval)) {
442 zval_ptr_dtor(&retval);
443 }
444
445 return ret;
446 }
447
php_sqlite3_func_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)448 static void php_sqlite3_func_callback(sqlite3_context *context, int argc,
449 sqlite3_value **argv)
450 {
451 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
452
453 do_callback(&func->afunc, &func->func, argc, argv, context, 0);
454 }
455
php_sqlite3_func_step_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)456 static void php_sqlite3_func_step_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->astep, &func->step, argc, argv, context, 1);
462 }
463
php_sqlite3_func_final_callback(sqlite3_context * context)464 static void php_sqlite3_func_final_callback(sqlite3_context *context)
465 {
466 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
467
468 do_callback(&func->afini, &func->fini, 0, NULL, context, 1);
469 }
470
php_sqlite3_collation_callback(void * context,int string1_len,const void * string1,int string2_len,const void * string2)471 static int php_sqlite3_collation_callback(void *context,
472 int string1_len, const void *string1,
473 int string2_len, const void *string2)
474 {
475 int ret;
476 zval zargs[2];
477 zval retval;
478 struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context;
479
480 collation->fc.fci.size = sizeof(collation->fc.fci);
481 ZVAL_COPY_VALUE(&collation->fc.fci.function_name, &collation->callback);
482 collation->fc.fci.object = NULL;
483 collation->fc.fci.retval = &retval;
484
485 // Prepare the arguments.
486 ZVAL_STRINGL(&zargs[0], (char *) string1, string1_len);
487 ZVAL_STRINGL(&zargs[1], (char *) string2, string2_len);
488 collation->fc.fci.param_count = 2;
489 collation->fc.fci.params = zargs;
490
491 if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc)) == FAILURE) {
492 php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
493 } else if (!Z_ISUNDEF(retval)) {
494 if (Z_TYPE(retval) != IS_LONG) {
495 convert_to_long_ex(&retval);
496 }
497 ret = 0;
498 if (Z_LVAL(retval) > 0) {
499 ret = 1;
500 } else if (Z_LVAL(retval) < 0) {
501 ret = -1;
502 }
503 zval_ptr_dtor(&retval);
504 }
505
506 zval_ptr_dtor(&zargs[0]);
507 zval_ptr_dtor(&zargs[1]);
508
509 return ret;
510 }
511
512 /* {{{ bool SQLite::sqliteCreateFunction(string name, mixed callback [, int argcount, int flags])
513 Registers a UDF with the sqlite db handle */
PHP_METHOD(SQLite,sqliteCreateFunction)514 static PHP_METHOD(SQLite, sqliteCreateFunction)
515 {
516 struct pdo_sqlite_func *func;
517 zval *callback;
518 char *func_name;
519 size_t func_name_len;
520 zend_long argc = -1;
521 zend_long flags = 0;
522 pdo_dbh_t *dbh;
523 pdo_sqlite_db_handle *H;
524 int ret;
525
526 ZEND_PARSE_PARAMETERS_START(2, 4)
527 Z_PARAM_STRING(func_name, func_name_len)
528 Z_PARAM_ZVAL(callback)
529 Z_PARAM_OPTIONAL
530 Z_PARAM_LONG(argc)
531 Z_PARAM_LONG(flags)
532 ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
533
534 dbh = Z_PDO_DBH_P(getThis());
535 PDO_CONSTRUCT_CHECK;
536
537 if (!zend_is_callable(callback, 0, NULL)) {
538 zend_string *cbname = zend_get_callable_name(callback);
539 php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
540 zend_string_release(cbname);
541 RETURN_FALSE;
542 }
543
544 H = (pdo_sqlite_db_handle *)dbh->driver_data;
545
546 func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
547
548 ret = sqlite3_create_function(H->db, func_name, argc, flags | SQLITE_UTF8,
549 func, php_sqlite3_func_callback, NULL, NULL);
550 if (ret == SQLITE_OK) {
551 func->funcname = estrdup(func_name);
552
553 ZVAL_COPY(&func->func, callback);
554
555 func->argc = argc;
556
557 func->next = H->funcs;
558 H->funcs = func;
559
560 RETURN_TRUE;
561 }
562
563 efree(func);
564 RETURN_FALSE;
565 }
566 /* }}} */
567
568 /* {{{ bool SQLite::sqliteCreateAggregate(string name, mixed step, mixed fini [, int argcount])
569 Registers a UDF with the sqlite db handle */
570
571 /* The step function should have the prototype:
572 mixed step(mixed $context, int $rownumber, $value [, $value2 [, ...]])
573
574 $context will be null for the first row; on subsequent rows it will have
575 the value that was previously returned from the step function; you should
576 use this to maintain state for the aggregate.
577
578 The fini function should have the prototype:
579 mixed fini(mixed $context, int $rownumber)
580
581 $context will hold the return value from the very last call to the step function.
582 rownumber will hold the number of rows over which the aggregate was performed.
583 The return value of this function will be used as the return value for this
584 aggregate UDF.
585 */
586
PHP_METHOD(SQLite,sqliteCreateAggregate)587 static PHP_METHOD(SQLite, sqliteCreateAggregate)
588 {
589 struct pdo_sqlite_func *func;
590 zval *step_callback, *fini_callback;
591 char *func_name;
592 size_t func_name_len;
593 zend_long argc = -1;
594 pdo_dbh_t *dbh;
595 pdo_sqlite_db_handle *H;
596 int ret;
597
598 ZEND_PARSE_PARAMETERS_START(3, 4)
599 Z_PARAM_STRING(func_name, func_name_len)
600 Z_PARAM_ZVAL(step_callback)
601 Z_PARAM_ZVAL(fini_callback)
602 Z_PARAM_OPTIONAL
603 Z_PARAM_LONG(argc)
604 ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
605
606 dbh = Z_PDO_DBH_P(getThis());
607 PDO_CONSTRUCT_CHECK;
608
609 if (!zend_is_callable(step_callback, 0, NULL)) {
610 zend_string *cbname = zend_get_callable_name(step_callback);
611 php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
612 zend_string_release(cbname);
613 RETURN_FALSE;
614 }
615
616 if (!zend_is_callable(fini_callback, 0, NULL)) {
617 zend_string *cbname = zend_get_callable_name(fini_callback);
618 php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
619 zend_string_release(cbname);
620 RETURN_FALSE;
621 }
622
623 H = (pdo_sqlite_db_handle *)dbh->driver_data;
624
625 func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
626
627 ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
628 func, NULL, php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
629 if (ret == SQLITE_OK) {
630 func->funcname = estrdup(func_name);
631
632 ZVAL_COPY(&func->step, step_callback);
633
634 ZVAL_COPY(&func->fini, fini_callback);
635
636 func->argc = argc;
637
638 func->next = H->funcs;
639 H->funcs = func;
640
641 RETURN_TRUE;
642 }
643
644 efree(func);
645 RETURN_FALSE;
646 }
647 /* }}} */
648
649 /* {{{ bool SQLite::sqliteCreateCollation(string name, mixed callback)
650 Registers a collation with the sqlite db handle */
PHP_METHOD(SQLite,sqliteCreateCollation)651 static PHP_METHOD(SQLite, sqliteCreateCollation)
652 {
653 struct pdo_sqlite_collation *collation;
654 zval *callback;
655 char *collation_name;
656 size_t collation_name_len;
657 pdo_dbh_t *dbh;
658 pdo_sqlite_db_handle *H;
659 int ret;
660
661 ZEND_PARSE_PARAMETERS_START(2, 2)
662 Z_PARAM_STRING(collation_name, collation_name_len)
663 Z_PARAM_ZVAL(callback)
664 ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
665
666 dbh = Z_PDO_DBH_P(getThis());
667 PDO_CONSTRUCT_CHECK;
668
669 if (!zend_is_callable(callback, 0, NULL)) {
670 zend_string *cbname = zend_get_callable_name(callback);
671 php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
672 zend_string_release(cbname);
673 RETURN_FALSE;
674 }
675
676 H = (pdo_sqlite_db_handle *)dbh->driver_data;
677
678 collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));
679
680 ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_collation_callback);
681 if (ret == SQLITE_OK) {
682 collation->name = estrdup(collation_name);
683
684 ZVAL_COPY(&collation->callback, callback);
685
686 collation->next = H->collations;
687 H->collations = collation;
688
689 RETURN_TRUE;
690 }
691
692 efree(collation);
693 RETURN_FALSE;
694 }
695 /* }}} */
696
697 static const zend_function_entry dbh_methods[] = {
698 PHP_ME(SQLite, sqliteCreateFunction, NULL, ZEND_ACC_PUBLIC)
699 PHP_ME(SQLite, sqliteCreateAggregate, NULL, ZEND_ACC_PUBLIC)
700 PHP_ME(SQLite, sqliteCreateCollation, NULL, ZEND_ACC_PUBLIC)
701 PHP_FE_END
702 };
703
get_driver_methods(pdo_dbh_t * dbh,int kind)704 static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind)
705 {
706 switch (kind) {
707 case PDO_DBH_DRIVER_METHOD_KIND_DBH:
708 return dbh_methods;
709
710 default:
711 return NULL;
712 }
713 }
714
pdo_sqlite_request_shutdown(pdo_dbh_t * dbh)715 static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh)
716 {
717 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
718 /* unregister functions, so that they don't linger for the next
719 * request */
720 if (H) {
721 pdo_sqlite_cleanup_callbacks(H);
722 }
723 }
724
725 static struct pdo_dbh_methods sqlite_methods = {
726 sqlite_handle_closer,
727 sqlite_handle_preparer,
728 sqlite_handle_doer,
729 sqlite_handle_quoter,
730 sqlite_handle_begin,
731 sqlite_handle_commit,
732 sqlite_handle_rollback,
733 pdo_sqlite_set_attr,
734 pdo_sqlite_last_insert_id,
735 pdo_sqlite_fetch_error_func,
736 pdo_sqlite_get_attribute,
737 NULL, /* check_liveness: not needed */
738 get_driver_methods,
739 pdo_sqlite_request_shutdown,
740 NULL
741 };
742
make_filename_safe(const char * filename)743 static char *make_filename_safe(const char *filename)
744 {
745 if (*filename && memcmp(filename, ":memory:", sizeof(":memory:"))) {
746 char *fullpath = expand_filepath(filename, NULL);
747
748 if (!fullpath) {
749 return NULL;
750 }
751
752 if (php_check_open_basedir(fullpath)) {
753 efree(fullpath);
754 return NULL;
755 }
756 return fullpath;
757 }
758 return estrdup(filename);
759 }
760
authorizer(void * autharg,int access_type,const char * arg3,const char * arg4,const char * arg5,const char * arg6)761 static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
762 const char *arg5, const char *arg6)
763 {
764 char *filename;
765 switch (access_type) {
766 case SQLITE_COPY: {
767 filename = make_filename_safe(arg4);
768 if (!filename) {
769 return SQLITE_DENY;
770 }
771 efree(filename);
772 return SQLITE_OK;
773 }
774
775 case SQLITE_ATTACH: {
776 filename = make_filename_safe(arg3);
777 if (!filename) {
778 return SQLITE_DENY;
779 }
780 efree(filename);
781 return SQLITE_OK;
782 }
783
784 default:
785 /* access allowed */
786 return SQLITE_OK;
787 }
788 }
789
pdo_sqlite_handle_factory(pdo_dbh_t * dbh,zval * driver_options)790 static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
791 {
792 pdo_sqlite_db_handle *H;
793 int i, ret = 0;
794 zend_long timeout = 60;
795 char *filename;
796
797 H = pecalloc(1, sizeof(pdo_sqlite_db_handle), dbh->is_persistent);
798
799 H->einfo.errcode = 0;
800 H->einfo.errmsg = NULL;
801 dbh->driver_data = H;
802
803 filename = make_filename_safe(dbh->data_source);
804
805 if (!filename) {
806 zend_throw_exception_ex(php_pdo_get_exception(), 0,
807 "open_basedir prohibits opening %s",
808 dbh->data_source);
809 goto cleanup;
810 }
811
812 i = sqlite3_open(filename, &H->db);
813 efree(filename);
814
815 if (i != SQLITE_OK) {
816 pdo_sqlite_error(dbh);
817 goto cleanup;
818 }
819
820 if (PG(open_basedir) && *PG(open_basedir)) {
821 sqlite3_set_authorizer(H->db, authorizer, NULL);
822 }
823
824 if (driver_options) {
825 timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout);
826 }
827 sqlite3_busy_timeout(H->db, timeout * 1000);
828
829 dbh->alloc_own_columns = 1;
830 dbh->max_escaped_char_length = 2;
831
832 ret = 1;
833
834 cleanup:
835 dbh->methods = &sqlite_methods;
836
837 return ret;
838 }
839 /* }}} */
840
841 pdo_driver_t pdo_sqlite_driver = {
842 PDO_DRIVER_HEADER(sqlite),
843 pdo_sqlite_handle_factory
844 };
845
846 /*
847 * Local variables:
848 * tab-width: 4
849 * c-basic-offset: 4
850 * End:
851 * vim600: noet sw=4 ts=4 fdm=marker
852 * vim<600: noet sw=4 ts=4
853 */
854