1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2017 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 fc->fci.function_table = EG(function_table);
329 ZVAL_COPY_VALUE(&fc->fci.function_name, cb);
330 fc->fci.symbol_table = NULL;
331 fc->fci.object = NULL;
332 fc->fci.retval = &retval;
333 fc->fci.param_count = fake_argc;
334
335 /* build up the params */
336
337 if (fake_argc) {
338 zargs = safe_emalloc(fake_argc, sizeof(zval), 0);
339 }
340
341 if (is_agg) {
342 agg_context = (zend_reference*)sqlite3_aggregate_context(context, sizeof(zend_reference));
343 if (!agg_context) {
344 ZVAL_NULL(&zargs[0]);
345 } else {
346 if (Z_ISUNDEF(agg_context->val)) {
347 GC_REFCOUNT(agg_context) = 1;
348 GC_TYPE_INFO(agg_context) = IS_REFERENCE;
349 ZVAL_NULL(&agg_context->val);
350 }
351 ZVAL_REF(&zargs[0], agg_context);
352 }
353 ZVAL_LONG(&zargs[1], sqlite3_aggregate_count(context));
354 }
355
356 for (i = 0; i < argc; i++) {
357 /* get the value */
358 switch (sqlite3_value_type(argv[i])) {
359 case SQLITE_INTEGER:
360 ZVAL_LONG(&zargs[i + is_agg], sqlite3_value_int(argv[i]));
361 break;
362
363 case SQLITE_FLOAT:
364 ZVAL_DOUBLE(&zargs[i + is_agg], sqlite3_value_double(argv[i]));
365 break;
366
367 case SQLITE_NULL:
368 ZVAL_NULL(&zargs[i + is_agg]);
369 break;
370
371 case SQLITE_BLOB:
372 case SQLITE3_TEXT:
373 default:
374 ZVAL_STRINGL(&zargs[i + is_agg], (char*)sqlite3_value_text(argv[i]), sqlite3_value_bytes(argv[i]));
375 break;
376 }
377 }
378
379 fc->fci.params = zargs;
380
381 if ((ret = zend_call_function(&fc->fci, &fc->fcc)) == FAILURE) {
382 php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
383 }
384
385 /* clean up the params */
386 if (zargs) {
387 for (i = is_agg; i < fake_argc; i++) {
388 zval_ptr_dtor(&zargs[i]);
389 }
390 if (is_agg) {
391 zval_ptr_dtor(&zargs[1]);
392 }
393 efree(zargs);
394 }
395
396 if (!is_agg || !argv) {
397 /* only set the sqlite return value if we are a scalar function,
398 * or if we are finalizing an aggregate */
399 if (!Z_ISUNDEF(retval)) {
400 switch (Z_TYPE(retval)) {
401 case IS_LONG:
402 sqlite3_result_int(context, Z_LVAL(retval));
403 break;
404
405 case IS_NULL:
406 sqlite3_result_null(context);
407 break;
408
409 case IS_DOUBLE:
410 sqlite3_result_double(context, Z_DVAL(retval));
411 break;
412
413 default:
414 convert_to_string_ex(&retval);
415 sqlite3_result_text(context, Z_STRVAL(retval), Z_STRLEN(retval), SQLITE_TRANSIENT);
416 break;
417 }
418 } else {
419 sqlite3_result_error(context, "failed to invoke callback", 0);
420 }
421
422 if (agg_context) {
423 zval_ptr_dtor(&agg_context->val);
424 }
425 } else {
426 /* we're stepping in an aggregate; the return value goes into
427 * the context */
428 if (agg_context) {
429 zval_ptr_dtor(&agg_context->val);
430 }
431 if (!Z_ISUNDEF(retval)) {
432 ZVAL_COPY_VALUE(&agg_context->val, &retval);
433 ZVAL_UNDEF(&retval);
434 } else {
435 ZVAL_UNDEF(&agg_context->val);
436 }
437 }
438
439 if (!Z_ISUNDEF(retval)) {
440 zval_ptr_dtor(&retval);
441 }
442
443 return ret;
444 }
445
php_sqlite3_func_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)446 static void php_sqlite3_func_callback(sqlite3_context *context, int argc,
447 sqlite3_value **argv)
448 {
449 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
450
451 do_callback(&func->afunc, &func->func, argc, argv, context, 0);
452 }
453
php_sqlite3_func_step_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)454 static void php_sqlite3_func_step_callback(sqlite3_context *context, int argc,
455 sqlite3_value **argv)
456 {
457 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
458
459 do_callback(&func->astep, &func->step, argc, argv, context, 1);
460 }
461
php_sqlite3_func_final_callback(sqlite3_context * context)462 static void php_sqlite3_func_final_callback(sqlite3_context *context)
463 {
464 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
465
466 do_callback(&func->afini, &func->fini, 0, NULL, context, 1);
467 }
468
php_sqlite3_collation_callback(void * context,int string1_len,const void * string1,int string2_len,const void * string2)469 static int php_sqlite3_collation_callback(void *context,
470 int string1_len, const void *string1,
471 int string2_len, const void *string2)
472 {
473 int ret;
474 zval zargs[2];
475 zval retval;
476 struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context;
477
478 collation->fc.fci.size = sizeof(collation->fc.fci);
479 collation->fc.fci.function_table = EG(function_table);
480 ZVAL_COPY_VALUE(&collation->fc.fci.function_name, &collation->callback);
481 collation->fc.fci.symbol_table = NULL;
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])
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_string *cbname = NULL;
522 pdo_dbh_t *dbh;
523 pdo_sqlite_db_handle *H;
524 int ret;
525
526 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "sz|l",
527 &func_name, &func_name_len, &callback, &argc)) {
528 RETURN_FALSE;
529 }
530
531 dbh = Z_PDO_DBH_P(getThis());
532 PDO_CONSTRUCT_CHECK;
533
534 if (!zend_is_callable(callback, 0, &cbname)) {
535 php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
536 zend_string_release(cbname);
537 RETURN_FALSE;
538 }
539 zend_string_release(cbname);
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, 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 zend_string *cbname = NULL;
592 pdo_dbh_t *dbh;
593 pdo_sqlite_db_handle *H;
594 int ret;
595
596 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "szz|l",
597 &func_name, &func_name_len, &step_callback, &fini_callback, &argc)) {
598 RETURN_FALSE;
599 }
600
601 dbh = Z_PDO_DBH_P(getThis());
602 PDO_CONSTRUCT_CHECK;
603
604 if (!zend_is_callable(step_callback, 0, &cbname)) {
605 php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
606 zend_string_release(cbname);
607 RETURN_FALSE;
608 }
609 zend_string_release(cbname);
610 if (!zend_is_callable(fini_callback, 0, &cbname)) {
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 zend_string_release(cbname);
616
617 H = (pdo_sqlite_db_handle *)dbh->driver_data;
618
619 func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
620
621 ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
622 func, NULL, php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
623 if (ret == SQLITE_OK) {
624 func->funcname = estrdup(func_name);
625
626 ZVAL_COPY(&func->step, step_callback);
627
628 ZVAL_COPY(&func->fini, fini_callback);
629
630 func->argc = argc;
631
632 func->next = H->funcs;
633 H->funcs = func;
634
635 RETURN_TRUE;
636 }
637
638 efree(func);
639 RETURN_FALSE;
640 }
641 /* }}} */
642
643 /* {{{ bool SQLite::sqliteCreateCollation(string name, mixed callback)
644 Registers a collation with the sqlite db handle */
PHP_METHOD(SQLite,sqliteCreateCollation)645 static PHP_METHOD(SQLite, sqliteCreateCollation)
646 {
647 struct pdo_sqlite_collation *collation;
648 zval *callback;
649 char *collation_name;
650 size_t collation_name_len;
651 zend_string *cbname = NULL;
652 pdo_dbh_t *dbh;
653 pdo_sqlite_db_handle *H;
654 int ret;
655
656 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "sz",
657 &collation_name, &collation_name_len, &callback)) {
658 RETURN_FALSE;
659 }
660
661 dbh = Z_PDO_DBH_P(getThis());
662 PDO_CONSTRUCT_CHECK;
663
664 if (!zend_is_callable(callback, 0, &cbname)) {
665 php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
666 zend_string_release(cbname);
667 RETURN_FALSE;
668 }
669 zend_string_release(cbname);
670
671 H = (pdo_sqlite_db_handle *)dbh->driver_data;
672
673 collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));
674
675 ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_collation_callback);
676 if (ret == SQLITE_OK) {
677 collation->name = estrdup(collation_name);
678
679 ZVAL_COPY(&collation->callback, callback);
680
681 collation->next = H->collations;
682 H->collations = collation;
683
684 RETURN_TRUE;
685 }
686
687 efree(collation);
688 RETURN_FALSE;
689 }
690 /* }}} */
691
692 static const zend_function_entry dbh_methods[] = {
693 PHP_ME(SQLite, sqliteCreateFunction, NULL, ZEND_ACC_PUBLIC)
694 PHP_ME(SQLite, sqliteCreateAggregate, NULL, ZEND_ACC_PUBLIC)
695 PHP_ME(SQLite, sqliteCreateCollation, NULL, ZEND_ACC_PUBLIC)
696 PHP_FE_END
697 };
698
get_driver_methods(pdo_dbh_t * dbh,int kind)699 static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind)
700 {
701 switch (kind) {
702 case PDO_DBH_DRIVER_METHOD_KIND_DBH:
703 return dbh_methods;
704
705 default:
706 return NULL;
707 }
708 }
709
pdo_sqlite_request_shutdown(pdo_dbh_t * dbh)710 static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh)
711 {
712 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
713 /* unregister functions, so that they don't linger for the next
714 * request */
715 if (H) {
716 pdo_sqlite_cleanup_callbacks(H);
717 }
718 }
719
720 static struct pdo_dbh_methods sqlite_methods = {
721 sqlite_handle_closer,
722 sqlite_handle_preparer,
723 sqlite_handle_doer,
724 sqlite_handle_quoter,
725 sqlite_handle_begin,
726 sqlite_handle_commit,
727 sqlite_handle_rollback,
728 pdo_sqlite_set_attr,
729 pdo_sqlite_last_insert_id,
730 pdo_sqlite_fetch_error_func,
731 pdo_sqlite_get_attribute,
732 NULL, /* check_liveness: not needed */
733 get_driver_methods,
734 pdo_sqlite_request_shutdown
735 };
736
make_filename_safe(const char * filename)737 static char *make_filename_safe(const char *filename)
738 {
739 if (*filename && memcmp(filename, ":memory:", sizeof(":memory:"))) {
740 char *fullpath = expand_filepath(filename, NULL);
741
742 if (!fullpath) {
743 return NULL;
744 }
745
746 if (php_check_open_basedir(fullpath)) {
747 efree(fullpath);
748 return NULL;
749 }
750 return fullpath;
751 }
752 return estrdup(filename);
753 }
754
authorizer(void * autharg,int access_type,const char * arg3,const char * arg4,const char * arg5,const char * arg6)755 static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
756 const char *arg5, const char *arg6)
757 {
758 char *filename;
759 switch (access_type) {
760 case SQLITE_COPY: {
761 filename = make_filename_safe(arg4);
762 if (!filename) {
763 return SQLITE_DENY;
764 }
765 efree(filename);
766 return SQLITE_OK;
767 }
768
769 case SQLITE_ATTACH: {
770 filename = make_filename_safe(arg3);
771 if (!filename) {
772 return SQLITE_DENY;
773 }
774 efree(filename);
775 return SQLITE_OK;
776 }
777
778 default:
779 /* access allowed */
780 return SQLITE_OK;
781 }
782 }
783
pdo_sqlite_handle_factory(pdo_dbh_t * dbh,zval * driver_options)784 static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
785 {
786 pdo_sqlite_db_handle *H;
787 int i, ret = 0;
788 zend_long timeout = 60;
789 char *filename;
790
791 H = pecalloc(1, sizeof(pdo_sqlite_db_handle), dbh->is_persistent);
792
793 H->einfo.errcode = 0;
794 H->einfo.errmsg = NULL;
795 dbh->driver_data = H;
796
797 filename = make_filename_safe(dbh->data_source);
798
799 if (!filename) {
800 zend_throw_exception_ex(php_pdo_get_exception(), 0,
801 "open_basedir prohibits opening %s",
802 dbh->data_source);
803 goto cleanup;
804 }
805
806 i = sqlite3_open(filename, &H->db);
807 efree(filename);
808
809 if (i != SQLITE_OK) {
810 pdo_sqlite_error(dbh);
811 goto cleanup;
812 }
813
814 if (PG(open_basedir) && *PG(open_basedir)) {
815 sqlite3_set_authorizer(H->db, authorizer, NULL);
816 }
817
818 if (driver_options) {
819 timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout);
820 }
821 sqlite3_busy_timeout(H->db, timeout * 1000);
822
823 dbh->alloc_own_columns = 1;
824 dbh->max_escaped_char_length = 2;
825
826 ret = 1;
827
828 cleanup:
829 dbh->methods = &sqlite_methods;
830
831 return ret;
832 }
833 /* }}} */
834
835 pdo_driver_t pdo_sqlite_driver = {
836 PDO_DRIVER_HEADER(sqlite),
837 pdo_sqlite_handle_factory
838 };
839
840 /*
841 * Local variables:
842 * tab-width: 4
843 * c-basic-offset: 4
844 * End:
845 * vim600: noet sw=4 ts=4 fdm=marker
846 * vim<600: noet sw=4 ts=4
847 */
848