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 sqlite3_close(H->db);
165 H->db = NULL;
166 }
167 if (einfo->errmsg) {
168 pefree(einfo->errmsg, dbh->is_persistent);
169 einfo->errmsg = NULL;
170 }
171 pefree(H, dbh->is_persistent);
172 dbh->driver_data = NULL;
173 }
174 return 0;
175 }
176 /* }}} */
177
sqlite_handle_preparer(pdo_dbh_t * dbh,const char * sql,size_t sql_len,pdo_stmt_t * stmt,zval * driver_options)178 static int sqlite_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len, pdo_stmt_t *stmt, zval *driver_options)
179 {
180 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
181 pdo_sqlite_stmt *S = ecalloc(1, sizeof(pdo_sqlite_stmt));
182 int i;
183 const char *tail;
184
185 S->H = H;
186 stmt->driver_data = S;
187 stmt->methods = &sqlite_stmt_methods;
188 stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL|PDO_PLACEHOLDER_NAMED;
189
190 if (PDO_CURSOR_FWDONLY != pdo_attr_lval(driver_options, PDO_ATTR_CURSOR, PDO_CURSOR_FWDONLY)) {
191 H->einfo.errcode = SQLITE_ERROR;
192 pdo_sqlite_error(dbh);
193 return 0;
194 }
195
196 i = sqlite3_prepare(H->db, sql, sql_len, &S->stmt, &tail);
197 if (i == SQLITE_OK) {
198 return 1;
199 }
200
201 pdo_sqlite_error(dbh);
202
203 return 0;
204 }
205
sqlite_handle_doer(pdo_dbh_t * dbh,const char * sql,size_t sql_len)206 static zend_long sqlite_handle_doer(pdo_dbh_t *dbh, const char *sql, size_t sql_len)
207 {
208 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
209 char *errmsg = NULL;
210
211 if (sqlite3_exec(H->db, sql, NULL, NULL, &errmsg) != SQLITE_OK) {
212 pdo_sqlite_error(dbh);
213 if (errmsg)
214 sqlite3_free(errmsg);
215
216 return -1;
217 } else {
218 return sqlite3_changes(H->db);
219 }
220 }
221
pdo_sqlite_last_insert_id(pdo_dbh_t * dbh,const char * name,size_t * len)222 static char *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const char *name, size_t *len)
223 {
224 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
225 char *id;
226
227 id = php_pdo_int64_to_str(sqlite3_last_insert_rowid(H->db));
228 *len = strlen(id);
229 return id;
230 }
231
232 /* 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)233 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 )
234 {
235 *quoted = safe_emalloc(2, unquotedlen, 3);
236 sqlite3_snprintf(2*unquotedlen + 3, *quoted, "'%q'", unquoted);
237 *quotedlen = strlen(*quoted);
238 return 1;
239 }
240
sqlite_handle_begin(pdo_dbh_t * dbh)241 static int sqlite_handle_begin(pdo_dbh_t *dbh)
242 {
243 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
244 char *errmsg = NULL;
245
246 if (sqlite3_exec(H->db, "BEGIN", NULL, NULL, &errmsg) != SQLITE_OK) {
247 pdo_sqlite_error(dbh);
248 if (errmsg)
249 sqlite3_free(errmsg);
250 return 0;
251 }
252 return 1;
253 }
254
sqlite_handle_commit(pdo_dbh_t * dbh)255 static int sqlite_handle_commit(pdo_dbh_t *dbh)
256 {
257 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
258 char *errmsg = NULL;
259
260 if (sqlite3_exec(H->db, "COMMIT", NULL, NULL, &errmsg) != SQLITE_OK) {
261 pdo_sqlite_error(dbh);
262 if (errmsg)
263 sqlite3_free(errmsg);
264 return 0;
265 }
266 return 1;
267 }
268
sqlite_handle_rollback(pdo_dbh_t * dbh)269 static int sqlite_handle_rollback(pdo_dbh_t *dbh)
270 {
271 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
272 char *errmsg = NULL;
273
274 if (sqlite3_exec(H->db, "ROLLBACK", NULL, NULL, &errmsg) != SQLITE_OK) {
275 pdo_sqlite_error(dbh);
276 if (errmsg)
277 sqlite3_free(errmsg);
278 return 0;
279 }
280 return 1;
281 }
282
pdo_sqlite_get_attribute(pdo_dbh_t * dbh,zend_long attr,zval * return_value)283 static int pdo_sqlite_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_value)
284 {
285 switch (attr) {
286 case PDO_ATTR_CLIENT_VERSION:
287 case PDO_ATTR_SERVER_VERSION:
288 ZVAL_STRING(return_value, (char *)sqlite3_libversion());
289 break;
290
291 default:
292 return 0;
293 }
294
295 return 1;
296 }
297
pdo_sqlite_set_attr(pdo_dbh_t * dbh,zend_long attr,zval * val)298 static int pdo_sqlite_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
299 {
300 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
301
302 switch (attr) {
303 case PDO_ATTR_TIMEOUT:
304 sqlite3_busy_timeout(H->db, zval_get_long(val) * 1000);
305 return 1;
306 }
307 return 0;
308 }
309
do_callback(struct pdo_sqlite_fci * fc,zval * cb,int argc,sqlite3_value ** argv,sqlite3_context * context,int is_agg)310 static int do_callback(struct pdo_sqlite_fci *fc, zval *cb,
311 int argc, sqlite3_value **argv, sqlite3_context *context,
312 int is_agg)
313 {
314 zval *zargs = NULL;
315 zval retval;
316 int i;
317 int ret;
318 int fake_argc;
319 zend_reference *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 = (zend_reference*)sqlite3_aggregate_context(context, sizeof(zend_reference));
341 if (!agg_context) {
342 ZVAL_NULL(&zargs[0]);
343 } else {
344 if (Z_ISUNDEF(agg_context->val)) {
345 GC_REFCOUNT(agg_context) = 1;
346 GC_TYPE_INFO(agg_context) = IS_REFERENCE;
347 ZVAL_NULL(&agg_context->val);
348 }
349 ZVAL_REF(&zargs[0], agg_context);
350 }
351 ZVAL_LONG(&zargs[1], sqlite3_aggregate_count(context));
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 fc->fci.params = zargs;
378
379 if ((ret = zend_call_function(&fc->fci, &fc->fcc)) == FAILURE) {
380 php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
381 }
382
383 /* clean up the params */
384 if (zargs) {
385 for (i = is_agg; i < fake_argc; i++) {
386 zval_ptr_dtor(&zargs[i]);
387 }
388 if (is_agg) {
389 zval_ptr_dtor(&zargs[1]);
390 }
391 efree(zargs);
392 }
393
394 if (!is_agg || !argv) {
395 /* only set the sqlite return value if we are a scalar function,
396 * or if we are finalizing an aggregate */
397 if (!Z_ISUNDEF(retval)) {
398 switch (Z_TYPE(retval)) {
399 case IS_LONG:
400 sqlite3_result_int(context, Z_LVAL(retval));
401 break;
402
403 case IS_NULL:
404 sqlite3_result_null(context);
405 break;
406
407 case IS_DOUBLE:
408 sqlite3_result_double(context, Z_DVAL(retval));
409 break;
410
411 default:
412 convert_to_string_ex(&retval);
413 sqlite3_result_text(context, Z_STRVAL(retval), Z_STRLEN(retval), SQLITE_TRANSIENT);
414 break;
415 }
416 } else {
417 sqlite3_result_error(context, "failed to invoke callback", 0);
418 }
419
420 if (agg_context) {
421 zval_ptr_dtor(&agg_context->val);
422 }
423 } else {
424 /* we're stepping in an aggregate; the return value goes into
425 * the context */
426 if (agg_context) {
427 zval_ptr_dtor(&agg_context->val);
428 }
429 if (!Z_ISUNDEF(retval)) {
430 ZVAL_COPY_VALUE(&agg_context->val, &retval);
431 ZVAL_UNDEF(&retval);
432 } else {
433 ZVAL_UNDEF(&agg_context->val);
434 }
435 }
436
437 if (!Z_ISUNDEF(retval)) {
438 zval_ptr_dtor(&retval);
439 }
440
441 return ret;
442 }
443
php_sqlite3_func_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)444 static void php_sqlite3_func_callback(sqlite3_context *context, int argc,
445 sqlite3_value **argv)
446 {
447 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
448
449 do_callback(&func->afunc, &func->func, argc, argv, context, 0);
450 }
451
php_sqlite3_func_step_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)452 static void php_sqlite3_func_step_callback(sqlite3_context *context, int argc,
453 sqlite3_value **argv)
454 {
455 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
456
457 do_callback(&func->astep, &func->step, argc, argv, context, 1);
458 }
459
php_sqlite3_func_final_callback(sqlite3_context * context)460 static void php_sqlite3_func_final_callback(sqlite3_context *context)
461 {
462 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
463
464 do_callback(&func->afini, &func->fini, 0, NULL, context, 1);
465 }
466
php_sqlite3_collation_callback(void * context,int string1_len,const void * string1,int string2_len,const void * string2)467 static int php_sqlite3_collation_callback(void *context,
468 int string1_len, const void *string1,
469 int string2_len, const void *string2)
470 {
471 int ret;
472 zval zargs[2];
473 zval retval;
474 struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context;
475
476 collation->fc.fci.size = sizeof(collation->fc.fci);
477 ZVAL_COPY_VALUE(&collation->fc.fci.function_name, &collation->callback);
478 collation->fc.fci.object = NULL;
479 collation->fc.fci.retval = &retval;
480
481 // Prepare the arguments.
482 ZVAL_STRINGL(&zargs[0], (char *) string1, string1_len);
483 ZVAL_STRINGL(&zargs[1], (char *) string2, string2_len);
484 collation->fc.fci.param_count = 2;
485 collation->fc.fci.params = zargs;
486
487 if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc)) == FAILURE) {
488 php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
489 } else if (!Z_ISUNDEF(retval)) {
490 if (Z_TYPE(retval) != IS_LONG) {
491 convert_to_long_ex(&retval);
492 }
493 ret = 0;
494 if (Z_LVAL(retval) > 0) {
495 ret = 1;
496 } else if (Z_LVAL(retval) < 0) {
497 ret = -1;
498 }
499 zval_ptr_dtor(&retval);
500 }
501
502 zval_ptr_dtor(&zargs[0]);
503 zval_ptr_dtor(&zargs[1]);
504
505 return ret;
506 }
507
508 /* {{{ bool SQLite::sqliteCreateFunction(string name, mixed callback [, int argcount, int flags])
509 Registers a UDF with the sqlite db handle */
PHP_METHOD(SQLite,sqliteCreateFunction)510 static PHP_METHOD(SQLite, sqliteCreateFunction)
511 {
512 struct pdo_sqlite_func *func;
513 zval *callback;
514 char *func_name;
515 size_t func_name_len;
516 zend_long argc = -1;
517 zend_long flags = 0;
518 zend_string *cbname = NULL;
519 pdo_dbh_t *dbh;
520 pdo_sqlite_db_handle *H;
521 int ret;
522
523 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "sz|ll",
524 &func_name, &func_name_len, &callback, &argc, &flags)) {
525 RETURN_FALSE;
526 }
527
528 dbh = Z_PDO_DBH_P(getThis());
529 PDO_CONSTRUCT_CHECK;
530
531 if (!zend_is_callable(callback, 0, &cbname)) {
532 php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
533 zend_string_release(cbname);
534 RETURN_FALSE;
535 }
536 zend_string_release(cbname);
537
538 H = (pdo_sqlite_db_handle *)dbh->driver_data;
539
540 func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
541
542 ret = sqlite3_create_function(H->db, func_name, argc, flags | SQLITE_UTF8,
543 func, php_sqlite3_func_callback, NULL, NULL);
544 if (ret == SQLITE_OK) {
545 func->funcname = estrdup(func_name);
546
547 ZVAL_COPY(&func->func, callback);
548
549 func->argc = argc;
550
551 func->next = H->funcs;
552 H->funcs = func;
553
554 RETURN_TRUE;
555 }
556
557 efree(func);
558 RETURN_FALSE;
559 }
560 /* }}} */
561
562 /* {{{ bool SQLite::sqliteCreateAggregate(string name, mixed step, mixed fini [, int argcount])
563 Registers a UDF with the sqlite db handle */
564
565 /* The step function should have the prototype:
566 mixed step(mixed $context, int $rownumber, $value [, $value2 [, ...]])
567
568 $context will be null for the first row; on subsequent rows it will have
569 the value that was previously returned from the step function; you should
570 use this to maintain state for the aggregate.
571
572 The fini function should have the prototype:
573 mixed fini(mixed $context, int $rownumber)
574
575 $context will hold the return value from the very last call to the step function.
576 rownumber will hold the number of rows over which the aggregate was performed.
577 The return value of this function will be used as the return value for this
578 aggregate UDF.
579 */
580
PHP_METHOD(SQLite,sqliteCreateAggregate)581 static PHP_METHOD(SQLite, sqliteCreateAggregate)
582 {
583 struct pdo_sqlite_func *func;
584 zval *step_callback, *fini_callback;
585 char *func_name;
586 size_t func_name_len;
587 zend_long argc = -1;
588 zend_string *cbname = NULL;
589 pdo_dbh_t *dbh;
590 pdo_sqlite_db_handle *H;
591 int ret;
592
593 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "szz|l",
594 &func_name, &func_name_len, &step_callback, &fini_callback, &argc)) {
595 RETURN_FALSE;
596 }
597
598 dbh = Z_PDO_DBH_P(getThis());
599 PDO_CONSTRUCT_CHECK;
600
601 if (!zend_is_callable(step_callback, 0, &cbname)) {
602 php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
603 zend_string_release(cbname);
604 RETURN_FALSE;
605 }
606 zend_string_release(cbname);
607 if (!zend_is_callable(fini_callback, 0, &cbname)) {
608 php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
609 zend_string_release(cbname);
610 RETURN_FALSE;
611 }
612 zend_string_release(cbname);
613
614 H = (pdo_sqlite_db_handle *)dbh->driver_data;
615
616 func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
617
618 ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
619 func, NULL, php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
620 if (ret == SQLITE_OK) {
621 func->funcname = estrdup(func_name);
622
623 ZVAL_COPY(&func->step, step_callback);
624
625 ZVAL_COPY(&func->fini, fini_callback);
626
627 func->argc = argc;
628
629 func->next = H->funcs;
630 H->funcs = func;
631
632 RETURN_TRUE;
633 }
634
635 efree(func);
636 RETURN_FALSE;
637 }
638 /* }}} */
639
640 /* {{{ bool SQLite::sqliteCreateCollation(string name, mixed callback)
641 Registers a collation with the sqlite db handle */
PHP_METHOD(SQLite,sqliteCreateCollation)642 static PHP_METHOD(SQLite, sqliteCreateCollation)
643 {
644 struct pdo_sqlite_collation *collation;
645 zval *callback;
646 char *collation_name;
647 size_t collation_name_len;
648 zend_string *cbname = NULL;
649 pdo_dbh_t *dbh;
650 pdo_sqlite_db_handle *H;
651 int ret;
652
653 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "sz",
654 &collation_name, &collation_name_len, &callback)) {
655 RETURN_FALSE;
656 }
657
658 dbh = Z_PDO_DBH_P(getThis());
659 PDO_CONSTRUCT_CHECK;
660
661 if (!zend_is_callable(callback, 0, &cbname)) {
662 php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
663 zend_string_release(cbname);
664 RETURN_FALSE;
665 }
666 zend_string_release(cbname);
667
668 H = (pdo_sqlite_db_handle *)dbh->driver_data;
669
670 collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));
671
672 ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_collation_callback);
673 if (ret == SQLITE_OK) {
674 collation->name = estrdup(collation_name);
675
676 ZVAL_COPY(&collation->callback, callback);
677
678 collation->next = H->collations;
679 H->collations = collation;
680
681 RETURN_TRUE;
682 }
683
684 efree(collation);
685 RETURN_FALSE;
686 }
687 /* }}} */
688
689 static const zend_function_entry dbh_methods[] = {
690 PHP_ME(SQLite, sqliteCreateFunction, NULL, ZEND_ACC_PUBLIC)
691 PHP_ME(SQLite, sqliteCreateAggregate, NULL, ZEND_ACC_PUBLIC)
692 PHP_ME(SQLite, sqliteCreateCollation, NULL, ZEND_ACC_PUBLIC)
693 PHP_FE_END
694 };
695
get_driver_methods(pdo_dbh_t * dbh,int kind)696 static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind)
697 {
698 switch (kind) {
699 case PDO_DBH_DRIVER_METHOD_KIND_DBH:
700 return dbh_methods;
701
702 default:
703 return NULL;
704 }
705 }
706
pdo_sqlite_request_shutdown(pdo_dbh_t * dbh)707 static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh)
708 {
709 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
710 /* unregister functions, so that they don't linger for the next
711 * request */
712 if (H) {
713 pdo_sqlite_cleanup_callbacks(H);
714 }
715 }
716
717 static struct pdo_dbh_methods sqlite_methods = {
718 sqlite_handle_closer,
719 sqlite_handle_preparer,
720 sqlite_handle_doer,
721 sqlite_handle_quoter,
722 sqlite_handle_begin,
723 sqlite_handle_commit,
724 sqlite_handle_rollback,
725 pdo_sqlite_set_attr,
726 pdo_sqlite_last_insert_id,
727 pdo_sqlite_fetch_error_func,
728 pdo_sqlite_get_attribute,
729 NULL, /* check_liveness: not needed */
730 get_driver_methods,
731 pdo_sqlite_request_shutdown,
732 NULL
733 };
734
make_filename_safe(const char * filename)735 static char *make_filename_safe(const char *filename)
736 {
737 if (*filename && memcmp(filename, ":memory:", sizeof(":memory:"))) {
738 char *fullpath = expand_filepath(filename, NULL);
739
740 if (!fullpath) {
741 return NULL;
742 }
743
744 if (php_check_open_basedir(fullpath)) {
745 efree(fullpath);
746 return NULL;
747 }
748 return fullpath;
749 }
750 return estrdup(filename);
751 }
752
authorizer(void * autharg,int access_type,const char * arg3,const char * arg4,const char * arg5,const char * arg6)753 static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
754 const char *arg5, const char *arg6)
755 {
756 char *filename;
757 switch (access_type) {
758 case SQLITE_COPY: {
759 filename = make_filename_safe(arg4);
760 if (!filename) {
761 return SQLITE_DENY;
762 }
763 efree(filename);
764 return SQLITE_OK;
765 }
766
767 case SQLITE_ATTACH: {
768 filename = make_filename_safe(arg3);
769 if (!filename) {
770 return SQLITE_DENY;
771 }
772 efree(filename);
773 return SQLITE_OK;
774 }
775
776 default:
777 /* access allowed */
778 return SQLITE_OK;
779 }
780 }
781
pdo_sqlite_handle_factory(pdo_dbh_t * dbh,zval * driver_options)782 static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
783 {
784 pdo_sqlite_db_handle *H;
785 int i, ret = 0;
786 zend_long timeout = 60;
787 char *filename;
788
789 H = pecalloc(1, sizeof(pdo_sqlite_db_handle), dbh->is_persistent);
790
791 H->einfo.errcode = 0;
792 H->einfo.errmsg = NULL;
793 dbh->driver_data = H;
794
795 filename = make_filename_safe(dbh->data_source);
796
797 if (!filename) {
798 zend_throw_exception_ex(php_pdo_get_exception(), 0,
799 "open_basedir prohibits opening %s",
800 dbh->data_source);
801 goto cleanup;
802 }
803
804 i = sqlite3_open(filename, &H->db);
805 efree(filename);
806
807 if (i != SQLITE_OK) {
808 pdo_sqlite_error(dbh);
809 goto cleanup;
810 }
811
812 if (PG(open_basedir) && *PG(open_basedir)) {
813 sqlite3_set_authorizer(H->db, authorizer, NULL);
814 }
815
816 if (driver_options) {
817 timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout);
818 }
819 sqlite3_busy_timeout(H->db, timeout * 1000);
820
821 dbh->alloc_own_columns = 1;
822 dbh->max_escaped_char_length = 2;
823
824 ret = 1;
825
826 cleanup:
827 dbh->methods = &sqlite_methods;
828
829 return ret;
830 }
831 /* }}} */
832
833 pdo_driver_t pdo_sqlite_driver = {
834 PDO_DRIVER_HEADER(sqlite),
835 pdo_sqlite_handle_factory
836 };
837
838 /*
839 * Local variables:
840 * tab-width: 4
841 * c-basic-offset: 4
842 * End:
843 * vim600: noet sw=4 ts=4 fdm=marker
844 * vim<600: noet sw=4 ts=4
845 */
846