1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 5 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2014 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 TSRMLS_DC)34 int _pdo_sqlite_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int line TSRMLS_DC) /* {{{ */
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 TSRMLS_CC, "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 TSRMLS_DC)89 static int pdo_sqlite_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC)
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, 1);
97 }
98
99 return 1;
100 }
101
pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle * H TSRMLS_DC)102 static void pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle *H TSRMLS_DC)
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 (func->func) {
122 zval_ptr_dtor(&func->func);
123 }
124 if (func->step) {
125 zval_ptr_dtor(&func->step);
126 }
127 if (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 (collation->callback) {
149 zval_ptr_dtor(&collation->callback);
150 }
151 efree(collation);
152 }
153 }
154
sqlite_handle_closer(pdo_dbh_t * dbh TSRMLS_DC)155 static int sqlite_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
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 TSRMLS_CC);
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,long sql_len,pdo_stmt_t * stmt,zval * driver_options TSRMLS_DC)178 static int sqlite_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC)
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 TSRMLS_CC)) {
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,long sql_len TSRMLS_DC)206 static long sqlite_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC)
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,unsigned int * len TSRMLS_DC)222 static char *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const char *name, unsigned int *len TSRMLS_DC)
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) TSRMLS_CC);
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,int unquotedlen,char ** quoted,int * quotedlen,enum pdo_param_type paramtype TSRMLS_DC)233 static int sqlite_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen, enum pdo_param_type paramtype TSRMLS_DC)
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 TSRMLS_DC)241 static int sqlite_handle_begin(pdo_dbh_t *dbh TSRMLS_DC)
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 TSRMLS_DC)255 static int sqlite_handle_commit(pdo_dbh_t *dbh TSRMLS_DC)
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 TSRMLS_DC)269 static int sqlite_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
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,long attr,zval * return_value TSRMLS_DC)283 static int pdo_sqlite_get_attribute(pdo_dbh_t *dbh, long attr, zval *return_value TSRMLS_DC)
284 {
285 switch (attr) {
286 case PDO_ATTR_CLIENT_VERSION:
287 case PDO_ATTR_SERVER_VERSION:
288 ZVAL_STRING(return_value, (char *)sqlite3_libversion(), 1);
289 break;
290
291 default:
292 return 0;
293 }
294
295 return 1;
296 }
297
pdo_sqlite_set_attr(pdo_dbh_t * dbh,long attr,zval * val TSRMLS_DC)298 static int pdo_sqlite_set_attr(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC)
299 {
300 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
301
302 switch (attr) {
303 case PDO_ATTR_TIMEOUT:
304 convert_to_long(val);
305 sqlite3_busy_timeout(H->db, Z_LVAL_P(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 TSRMLS_DC)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 TSRMLS_DC)
314 {
315 zval ***zargs = NULL;
316 zval *retval = NULL;
317 int i;
318 int ret;
319 int fake_argc;
320 zval **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 fc->fci.function_table = EG(function_table);
330 fc->fci.function_name = cb;
331 fc->fci.symbol_table = NULL;
332 fc->fci.object_ptr = NULL;
333 fc->fci.retval_ptr_ptr = &retval;
334 fc->fci.param_count = fake_argc;
335
336 /* build up the params */
337
338 if (fake_argc) {
339 zargs = (zval ***)safe_emalloc(fake_argc, sizeof(zval **), 0);
340 }
341
342 if (is_agg) {
343 /* summon the aggregation context */
344 agg_context = (zval**)sqlite3_aggregate_context(context, sizeof(zval*));
345 if (!*agg_context) {
346 MAKE_STD_ZVAL(*agg_context);
347 ZVAL_NULL(*agg_context);
348 }
349 zargs[0] = agg_context;
350
351 zargs[1] = emalloc(sizeof(zval*));
352 MAKE_STD_ZVAL(*zargs[1]);
353 ZVAL_LONG(*zargs[1], sqlite3_aggregate_count(context));
354 }
355
356 for (i = 0; i < argc; i++) {
357 zargs[i + is_agg] = emalloc(sizeof(zval *));
358 MAKE_STD_ZVAL(*zargs[i + is_agg]);
359
360 /* get the value */
361 switch (sqlite3_value_type(argv[i])) {
362 case SQLITE_INTEGER:
363 ZVAL_LONG(*zargs[i + is_agg], sqlite3_value_int(argv[i]));
364 break;
365
366 case SQLITE_FLOAT:
367 ZVAL_DOUBLE(*zargs[i + is_agg], sqlite3_value_double(argv[i]));
368 break;
369
370 case SQLITE_NULL:
371 ZVAL_NULL(*zargs[i + is_agg]);
372 break;
373
374 case SQLITE_BLOB:
375 case SQLITE3_TEXT:
376 default:
377 ZVAL_STRINGL(*zargs[i + is_agg], (char*)sqlite3_value_text(argv[i]),
378 sqlite3_value_bytes(argv[i]), 1);
379 break;
380 }
381 }
382
383
384 fc->fci.params = zargs;
385
386
387 if ((ret = zend_call_function(&fc->fci, &fc->fcc TSRMLS_CC)) == FAILURE) {
388 php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the callback");
389 }
390
391 /* clean up the params */
392 if (zargs) {
393 for (i = is_agg; i < fake_argc; i++) {
394 zval_ptr_dtor(zargs[i]);
395 efree(zargs[i]);
396 }
397 if (is_agg) {
398 zval_ptr_dtor(zargs[1]);
399 efree(zargs[1]);
400 }
401 efree(zargs);
402 }
403
404 if (!is_agg || !argv) {
405 /* only set the sqlite return value if we are a scalar function,
406 * or if we are finalizing an aggregate */
407 if (retval) {
408 switch (Z_TYPE_P(retval)) {
409 case IS_LONG:
410 sqlite3_result_int(context, Z_LVAL_P(retval));
411 break;
412
413 case IS_NULL:
414 sqlite3_result_null(context);
415 break;
416
417 case IS_DOUBLE:
418 sqlite3_result_double(context, Z_DVAL_P(retval));
419 break;
420
421 default:
422 convert_to_string_ex(&retval);
423 sqlite3_result_text(context, Z_STRVAL_P(retval),
424 Z_STRLEN_P(retval), SQLITE_TRANSIENT);
425 break;
426 }
427 } else {
428 sqlite3_result_error(context, "failed to invoke callback", 0);
429 }
430
431 if (agg_context) {
432 zval_ptr_dtor(agg_context);
433 }
434 } else {
435 /* we're stepping in an aggregate; the return value goes into
436 * the context */
437 if (agg_context) {
438 zval_ptr_dtor(agg_context);
439 }
440 if (retval) {
441 *agg_context = retval;
442 retval = NULL;
443 } else {
444 *agg_context = NULL;
445 }
446 }
447
448 if (retval) {
449 zval_ptr_dtor(&retval);
450 }
451
452 return ret;
453 }
454
php_sqlite3_func_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)455 static void php_sqlite3_func_callback(sqlite3_context *context, int argc,
456 sqlite3_value **argv)
457 {
458 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
459 TSRMLS_FETCH();
460
461 do_callback(&func->afunc, func->func, argc, argv, context, 0 TSRMLS_CC);
462 }
463
php_sqlite3_func_step_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)464 static void php_sqlite3_func_step_callback(sqlite3_context *context, int argc,
465 sqlite3_value **argv)
466 {
467 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
468 TSRMLS_FETCH();
469
470 do_callback(&func->astep, func->step, argc, argv, context, 1 TSRMLS_CC);
471 }
472
php_sqlite3_func_final_callback(sqlite3_context * context)473 static void php_sqlite3_func_final_callback(sqlite3_context *context)
474 {
475 struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
476 TSRMLS_FETCH();
477
478 do_callback(&func->afini, func->fini, 0, NULL, context, 1 TSRMLS_CC);
479 }
480
php_sqlite3_collation_callback(void * context,int string1_len,const void * string1,int string2_len,const void * string2)481 static int php_sqlite3_collation_callback(void *context,
482 int string1_len, const void *string1,
483 int string2_len, const void *string2)
484 {
485 int ret;
486 zval *zstring1, *zstring2;
487 zval **zargs[2];
488 zval *retval = NULL;
489 struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context;
490 TSRMLS_FETCH();
491
492 collation->fc.fci.size = sizeof(collation->fc.fci);
493 collation->fc.fci.function_table = EG(function_table);
494 collation->fc.fci.function_name = collation->callback;
495 collation->fc.fci.symbol_table = NULL;
496 collation->fc.fci.object_ptr = NULL;
497 collation->fc.fci.retval_ptr_ptr = &retval;
498
499 // Prepare the arguments.
500 MAKE_STD_ZVAL(zstring1);
501 ZVAL_STRINGL(zstring1, (char *) string1, string1_len, 1);
502 zargs[0] = &zstring1;
503 MAKE_STD_ZVAL(zstring2);
504 ZVAL_STRINGL(zstring2, (char *) string2, string2_len, 1);
505 zargs[1] = &zstring2;
506 collation->fc.fci.param_count = 2;
507 collation->fc.fci.params = zargs;
508
509 if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc TSRMLS_CC)) == FAILURE) {
510 php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the callback");
511 }
512 else if (retval) {
513 if (Z_TYPE_P(retval) != IS_LONG) {
514 convert_to_long_ex(&retval);
515 }
516 ret = 0;
517 if (Z_LVAL_P(retval) > 0) {
518 ret = 1;
519 }
520 else if (Z_LVAL_P(retval) < 0) {
521 ret = -1;
522 }
523 zval_ptr_dtor(&retval);
524 }
525
526 zval_ptr_dtor(zargs[0]);
527 zval_ptr_dtor(zargs[1]);
528
529 return ret;
530 }
531
532 /* {{{ bool SQLite::sqliteCreateFunction(string name, mixed callback [, int argcount])
533 Registers a UDF with the sqlite db handle */
PHP_METHOD(SQLite,sqliteCreateFunction)534 static PHP_METHOD(SQLite, sqliteCreateFunction)
535 {
536 struct pdo_sqlite_func *func;
537 zval *callback;
538 char *func_name;
539 int func_name_len;
540 long argc = -1;
541 char *cbname = NULL;
542 pdo_dbh_t *dbh;
543 pdo_sqlite_db_handle *H;
544 int ret;
545
546 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l",
547 &func_name, &func_name_len, &callback, &argc)) {
548 RETURN_FALSE;
549 }
550
551 dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
552 PDO_CONSTRUCT_CHECK;
553
554 if (!zend_is_callable(callback, 0, &cbname TSRMLS_CC)) {
555 php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname);
556 efree(cbname);
557 RETURN_FALSE;
558 }
559 efree(cbname);
560
561 H = (pdo_sqlite_db_handle *)dbh->driver_data;
562
563 func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
564
565 ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
566 func, php_sqlite3_func_callback, NULL, NULL);
567 if (ret == SQLITE_OK) {
568 func->funcname = estrdup(func_name);
569
570 MAKE_STD_ZVAL(func->func);
571 MAKE_COPY_ZVAL(&callback, func->func);
572
573 func->argc = argc;
574
575 func->next = H->funcs;
576 H->funcs = func;
577
578 RETURN_TRUE;
579 }
580
581 efree(func);
582 RETURN_FALSE;
583 }
584 /* }}} */
585
586 /* {{{ bool SQLite::sqliteCreateAggregate(string name, mixed step, mixed fini [, int argcount])
587 Registers a UDF with the sqlite db handle */
588
589 /* The step function should have the prototype:
590 mixed step(mixed $context, int $rownumber, $value [, $value2 [, ...]])
591
592 $context will be null for the first row; on subsequent rows it will have
593 the value that was previously returned from the step function; you should
594 use this to maintain state for the aggregate.
595
596 The fini function should have the prototype:
597 mixed fini(mixed $context, int $rownumber)
598
599 $context will hold the return value from the very last call to the step function.
600 rownumber will hold the number of rows over which the aggregate was performed.
601 The return value of this function will be used as the return value for this
602 aggregate UDF.
603 */
604
PHP_METHOD(SQLite,sqliteCreateAggregate)605 static PHP_METHOD(SQLite, sqliteCreateAggregate)
606 {
607 struct pdo_sqlite_func *func;
608 zval *step_callback, *fini_callback;
609 char *func_name;
610 int func_name_len;
611 long argc = -1;
612 char *cbname = NULL;
613 pdo_dbh_t *dbh;
614 pdo_sqlite_db_handle *H;
615 int ret;
616
617 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szz|l",
618 &func_name, &func_name_len, &step_callback, &fini_callback, &argc)) {
619 RETURN_FALSE;
620 }
621
622 dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
623 PDO_CONSTRUCT_CHECK;
624
625 if (!zend_is_callable(step_callback, 0, &cbname TSRMLS_CC)) {
626 php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname);
627 efree(cbname);
628 RETURN_FALSE;
629 }
630 efree(cbname);
631 if (!zend_is_callable(fini_callback, 0, &cbname TSRMLS_CC)) {
632 php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname);
633 efree(cbname);
634 RETURN_FALSE;
635 }
636 efree(cbname);
637
638 H = (pdo_sqlite_db_handle *)dbh->driver_data;
639
640 func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
641
642 ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
643 func, NULL, php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
644 if (ret == SQLITE_OK) {
645 func->funcname = estrdup(func_name);
646
647 MAKE_STD_ZVAL(func->step);
648 MAKE_COPY_ZVAL(&step_callback, func->step);
649
650 MAKE_STD_ZVAL(func->fini);
651 MAKE_COPY_ZVAL(&fini_callback, func->fini);
652
653 func->argc = argc;
654
655 func->next = H->funcs;
656 H->funcs = func;
657
658 RETURN_TRUE;
659 }
660
661 efree(func);
662 RETURN_FALSE;
663 }
664 /* }}} */
665
666 /* {{{ bool SQLite::sqliteCreateCollation(string name, mixed callback)
667 Registers a collation with the sqlite db handle */
PHP_METHOD(SQLite,sqliteCreateCollation)668 static PHP_METHOD(SQLite, sqliteCreateCollation)
669 {
670 struct pdo_sqlite_collation *collation;
671 zval *callback;
672 char *collation_name;
673 int collation_name_len;
674 char *cbname = NULL;
675 pdo_dbh_t *dbh;
676 pdo_sqlite_db_handle *H;
677 int ret;
678
679 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz",
680 &collation_name, &collation_name_len, &callback)) {
681 RETURN_FALSE;
682 }
683
684 dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
685 PDO_CONSTRUCT_CHECK;
686
687 if (!zend_is_callable(callback, 0, &cbname TSRMLS_CC)) {
688 php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname);
689 efree(cbname);
690 RETURN_FALSE;
691 }
692 efree(cbname);
693
694 H = (pdo_sqlite_db_handle *)dbh->driver_data;
695
696 collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));
697
698 ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_collation_callback);
699 if (ret == SQLITE_OK) {
700 collation->name = estrdup(collation_name);
701
702 MAKE_STD_ZVAL(collation->callback);
703 MAKE_COPY_ZVAL(&callback, collation->callback);
704
705 collation->next = H->collations;
706 H->collations = collation;
707
708 RETURN_TRUE;
709 }
710
711 efree(collation);
712 RETURN_FALSE;
713 }
714 /* }}} */
715
716 static const zend_function_entry dbh_methods[] = {
717 PHP_ME(SQLite, sqliteCreateFunction, NULL, ZEND_ACC_PUBLIC)
718 PHP_ME(SQLite, sqliteCreateAggregate, NULL, ZEND_ACC_PUBLIC)
719 PHP_ME(SQLite, sqliteCreateCollation, NULL, ZEND_ACC_PUBLIC)
720 PHP_FE_END
721 };
722
get_driver_methods(pdo_dbh_t * dbh,int kind TSRMLS_DC)723 static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind TSRMLS_DC)
724 {
725 switch (kind) {
726 case PDO_DBH_DRIVER_METHOD_KIND_DBH:
727 return dbh_methods;
728
729 default:
730 return NULL;
731 }
732 }
733
pdo_sqlite_request_shutdown(pdo_dbh_t * dbh TSRMLS_DC)734 static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh TSRMLS_DC)
735 {
736 pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
737 /* unregister functions, so that they don't linger for the next
738 * request */
739 if (H) {
740 pdo_sqlite_cleanup_callbacks(H TSRMLS_CC);
741 }
742 }
743
744 static struct pdo_dbh_methods sqlite_methods = {
745 sqlite_handle_closer,
746 sqlite_handle_preparer,
747 sqlite_handle_doer,
748 sqlite_handle_quoter,
749 sqlite_handle_begin,
750 sqlite_handle_commit,
751 sqlite_handle_rollback,
752 pdo_sqlite_set_attr,
753 pdo_sqlite_last_insert_id,
754 pdo_sqlite_fetch_error_func,
755 pdo_sqlite_get_attribute,
756 NULL, /* check_liveness: not needed */
757 get_driver_methods,
758 pdo_sqlite_request_shutdown
759 };
760
make_filename_safe(const char * filename TSRMLS_DC)761 static char *make_filename_safe(const char *filename TSRMLS_DC)
762 {
763 if (*filename && memcmp(filename, ":memory:", sizeof(":memory:"))) {
764 char *fullpath = expand_filepath(filename, NULL TSRMLS_CC);
765
766 if (!fullpath) {
767 return NULL;
768 }
769
770 if (php_check_open_basedir(fullpath TSRMLS_CC)) {
771 efree(fullpath);
772 return NULL;
773 }
774 return fullpath;
775 }
776 return estrdup(filename);
777 }
778
authorizer(void * autharg,int access_type,const char * arg3,const char * arg4,const char * arg5,const char * arg6)779 static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
780 const char *arg5, const char *arg6)
781 {
782 char *filename;
783 switch (access_type) {
784 case SQLITE_COPY: {
785 TSRMLS_FETCH();
786 filename = make_filename_safe(arg4 TSRMLS_CC);
787 if (!filename) {
788 return SQLITE_DENY;
789 }
790 efree(filename);
791 return SQLITE_OK;
792 }
793
794 case SQLITE_ATTACH: {
795 TSRMLS_FETCH();
796 filename = make_filename_safe(arg3 TSRMLS_CC);
797 if (!filename) {
798 return SQLITE_DENY;
799 }
800 efree(filename);
801 return SQLITE_OK;
802 }
803
804 default:
805 /* access allowed */
806 return SQLITE_OK;
807 }
808 }
809
pdo_sqlite_handle_factory(pdo_dbh_t * dbh,zval * driver_options TSRMLS_DC)810 static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
811 {
812 pdo_sqlite_db_handle *H;
813 int i, ret = 0;
814 long timeout = 60;
815 char *filename;
816
817 H = pecalloc(1, sizeof(pdo_sqlite_db_handle), dbh->is_persistent);
818
819 H->einfo.errcode = 0;
820 H->einfo.errmsg = NULL;
821 dbh->driver_data = H;
822
823 filename = make_filename_safe(dbh->data_source TSRMLS_CC);
824
825 if (!filename) {
826 zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC,
827 "open_basedir prohibits opening %s",
828 dbh->data_source);
829 goto cleanup;
830 }
831
832 i = sqlite3_open(filename, &H->db);
833 efree(filename);
834
835 if (i != SQLITE_OK) {
836 pdo_sqlite_error(dbh);
837 goto cleanup;
838 }
839
840 if (PG(open_basedir) && *PG(open_basedir)) {
841 sqlite3_set_authorizer(H->db, authorizer, NULL);
842 }
843
844 if (driver_options) {
845 timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout TSRMLS_CC);
846 }
847 sqlite3_busy_timeout(H->db, timeout * 1000);
848
849 dbh->alloc_own_columns = 1;
850 dbh->max_escaped_char_length = 2;
851
852 ret = 1;
853
854 cleanup:
855 dbh->methods = &sqlite_methods;
856
857 return ret;
858 }
859 /* }}} */
860
861 pdo_driver_t pdo_sqlite_driver = {
862 PDO_DRIVER_HEADER(sqlite),
863 pdo_sqlite_handle_factory
864 };
865
866 /*
867 * Local variables:
868 * tab-width: 4
869 * c-basic-offset: 4
870 * End:
871 * vim600: noet sw=4 ts=4 fdm=marker
872 * vim<600: noet sw=4 ts=4
873 */
874