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