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