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 	char *errmsg = NULL;
207 
208 	if (sqlite3_exec(H->db, ZSTR_VAL(sql), NULL, NULL, &errmsg) != SQLITE_OK) {
209 		pdo_sqlite_error(dbh);
210 		if (errmsg)
211 			sqlite3_free(errmsg);
212 
213 		return -1;
214 	} else {
215 		return sqlite3_changes(H->db);
216 	}
217 }
218 
pdo_sqlite_last_insert_id(pdo_dbh_t * dbh,const zend_string * name)219 static zend_string *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const zend_string *name)
220 {
221 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
222 
223 	return zend_i64_to_str(sqlite3_last_insert_rowid(H->db));
224 }
225 
226 /* 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)227 static zend_string* sqlite_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype)
228 {
229 	char *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 	char *errmsg = NULL;
241 
242 	if (sqlite3_exec(H->db, "BEGIN", NULL, NULL, &errmsg) != SQLITE_OK) {
243 		pdo_sqlite_error(dbh);
244 		if (errmsg)
245 			sqlite3_free(errmsg);
246 		return false;
247 	}
248 	return true;
249 }
250 
sqlite_handle_commit(pdo_dbh_t * dbh)251 static bool sqlite_handle_commit(pdo_dbh_t *dbh)
252 {
253 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
254 	char *errmsg = NULL;
255 
256 	if (sqlite3_exec(H->db, "COMMIT", NULL, NULL, &errmsg) != SQLITE_OK) {
257 		pdo_sqlite_error(dbh);
258 		if (errmsg)
259 			sqlite3_free(errmsg);
260 		return false;
261 	}
262 	return true;
263 }
264 
sqlite_handle_rollback(pdo_dbh_t * dbh)265 static bool sqlite_handle_rollback(pdo_dbh_t *dbh)
266 {
267 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
268 	char *errmsg = NULL;
269 
270 	if (sqlite3_exec(H->db, "ROLLBACK", NULL, NULL, &errmsg) != SQLITE_OK) {
271 		pdo_sqlite_error(dbh);
272 		if (errmsg)
273 			sqlite3_free(errmsg);
274 		return false;
275 	}
276 	return true;
277 }
278 
pdo_sqlite_get_attribute(pdo_dbh_t * dbh,zend_long attr,zval * return_value)279 static int pdo_sqlite_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_value)
280 {
281 	switch (attr) {
282 		case PDO_ATTR_CLIENT_VERSION:
283 		case PDO_ATTR_SERVER_VERSION:
284 			ZVAL_STRING(return_value, (char *)sqlite3_libversion());
285 			break;
286 
287 		default:
288 			return 0;
289 	}
290 
291 	return 1;
292 }
293 
pdo_sqlite_set_attr(pdo_dbh_t * dbh,zend_long attr,zval * val)294 static bool pdo_sqlite_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
295 {
296 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
297 	zend_long lval;
298 
299 	switch (attr) {
300 		case PDO_ATTR_TIMEOUT:
301 			if (!pdo_get_long_param(&lval, val)) {
302 				return false;
303 			}
304 			sqlite3_busy_timeout(H->db, lval * 1000);
305 			return true;
306 		case PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES:
307 			if (!pdo_get_long_param(&lval, val)) {
308 				return false;
309 			}
310 			sqlite3_extended_result_codes(H->db, lval);
311 			return true;
312 	}
313 	return false;
314 }
315 
316 typedef struct {
317 	zval val;
318 	zend_long row;
319 } aggregate_context;
320 
do_callback(struct pdo_sqlite_fci * fc,zval * cb,int argc,sqlite3_value ** argv,sqlite3_context * context,int is_agg)321 static int do_callback(struct pdo_sqlite_fci *fc, zval *cb,
322 		int argc, sqlite3_value **argv, sqlite3_context *context,
323 		int is_agg)
324 {
325 	zval *zargs = NULL;
326 	zval retval;
327 	int i;
328 	int ret;
329 	int fake_argc;
330 	aggregate_context *agg_context = NULL;
331 
332 	if (is_agg) {
333 		is_agg = 2;
334 	}
335 
336 	fake_argc = argc + is_agg;
337 
338 	fc->fci.size = sizeof(fc->fci);
339 	ZVAL_COPY_VALUE(&fc->fci.function_name, cb);
340 	fc->fci.object = NULL;
341 	fc->fci.retval = &retval;
342 	fc->fci.param_count = fake_argc;
343 
344 	/* build up the params */
345 
346 	if (fake_argc) {
347 		zargs = safe_emalloc(fake_argc, sizeof(zval), 0);
348 	}
349 
350 	if (is_agg) {
351 		agg_context = sqlite3_aggregate_context(context, sizeof(aggregate_context));
352 		if (!agg_context) {
353 			efree(zargs);
354 			return FAILURE;
355 		}
356 		if (Z_ISUNDEF(agg_context->val)) {
357 			ZVAL_NEW_REF(&agg_context->val, &EG(uninitialized_zval));
358 		}
359 		ZVAL_COPY_VALUE(&zargs[0], &agg_context->val);
360 		ZVAL_LONG(&zargs[1], ++agg_context->row);
361 	}
362 
363 	for (i = 0; i < argc; i++) {
364 		/* get the value */
365 		switch (sqlite3_value_type(argv[i])) {
366 			case SQLITE_INTEGER:
367 				ZVAL_LONG(&zargs[i + is_agg], sqlite3_value_int(argv[i]));
368 				break;
369 
370 			case SQLITE_FLOAT:
371 				ZVAL_DOUBLE(&zargs[i + is_agg], sqlite3_value_double(argv[i]));
372 				break;
373 
374 			case SQLITE_NULL:
375 				ZVAL_NULL(&zargs[i + is_agg]);
376 				break;
377 
378 			case SQLITE_BLOB:
379 			case SQLITE3_TEXT:
380 			default:
381 				ZVAL_STRINGL(&zargs[i + is_agg], (char*)sqlite3_value_text(argv[i]), sqlite3_value_bytes(argv[i]));
382 				break;
383 		}
384 	}
385 
386 	fc->fci.params = zargs;
387 
388 	if ((ret = zend_call_function(&fc->fci, &fc->fcc)) == FAILURE) {
389 		php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
390 	}
391 
392 	/* clean up the params */
393 	if (zargs) {
394 		for (i = is_agg; i < fake_argc; i++) {
395 			zval_ptr_dtor(&zargs[i]);
396 		}
397 		if (is_agg) {
398 			zval_ptr_dtor(&zargs[1]);
399 		}
400 		efree(zargs);
401 	}
402 
403 	if (!is_agg || !argv) {
404 		/* only set the sqlite return value if we are a scalar function,
405 		 * or if we are finalizing an aggregate */
406 		if (!Z_ISUNDEF(retval)) {
407 			switch (Z_TYPE(retval)) {
408 				case IS_LONG:
409 					sqlite3_result_int(context, Z_LVAL(retval));
410 					break;
411 
412 				case IS_NULL:
413 					sqlite3_result_null(context);
414 					break;
415 
416 				case IS_DOUBLE:
417 					sqlite3_result_double(context, Z_DVAL(retval));
418 					break;
419 
420 				default:
421 					if (!try_convert_to_string(&retval)) {
422 						ret = FAILURE;
423 						break;
424 					}
425 					sqlite3_result_text(context, Z_STRVAL(retval), Z_STRLEN(retval), SQLITE_TRANSIENT);
426 					break;
427 			}
428 		} else {
429 			sqlite3_result_error(context, "failed to invoke callback", 0);
430 		}
431 
432 		if (agg_context) {
433 			zval_ptr_dtor(&agg_context->val);
434 		}
435 	} else {
436 		/* we're stepping in an aggregate; the return value goes into
437 		 * the context */
438 		if (agg_context) {
439 			if (Z_ISUNDEF(retval)) {
440 				zval_ptr_dtor(&agg_context->val);
441 				return FAILURE;
442 			}
443 			zval_ptr_dtor(Z_REFVAL(agg_context->val));
444 			ZVAL_COPY_VALUE(Z_REFVAL(agg_context->val), &retval);
445 			ZVAL_UNDEF(&retval);
446 		}
447 	}
448 
449 	if (!Z_ISUNDEF(retval)) {
450 		zval_ptr_dtor(&retval);
451 	}
452 
453 	return ret;
454 }
455 
php_sqlite3_func_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)456 static void php_sqlite3_func_callback(sqlite3_context *context, int argc,
457 	sqlite3_value **argv)
458 {
459 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
460 
461 	do_callback(&func->afunc, &func->func, argc, argv, context, 0);
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 
469 	do_callback(&func->astep, &func->step, argc, argv, context, 1);
470 }
471 
php_sqlite3_func_final_callback(sqlite3_context * context)472 static void php_sqlite3_func_final_callback(sqlite3_context *context)
473 {
474 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
475 
476 	do_callback(&func->afini, &func->fini, 0, NULL, context, 1);
477 }
478 
php_sqlite3_collation_callback(void * context,int string1_len,const void * string1,int string2_len,const void * string2)479 static int php_sqlite3_collation_callback(void *context,
480 	int string1_len, const void *string1,
481 	int string2_len, const void *string2)
482 {
483 	int ret;
484 	zval zargs[2];
485 	zval retval;
486 	struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context;
487 
488 	collation->fc.fci.size = sizeof(collation->fc.fci);
489 	ZVAL_COPY_VALUE(&collation->fc.fci.function_name, &collation->callback);
490 	collation->fc.fci.object = NULL;
491 	collation->fc.fci.retval = &retval;
492 
493 	// Prepare the arguments.
494 	ZVAL_STRINGL(&zargs[0], (char *) string1, string1_len);
495 	ZVAL_STRINGL(&zargs[1], (char *) string2, string2_len);
496 	collation->fc.fci.param_count = 2;
497 	collation->fc.fci.params = zargs;
498 
499 	if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc)) == FAILURE) {
500 		php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
501 	} else if (!Z_ISUNDEF(retval)) {
502 		if (Z_TYPE(retval) != IS_LONG) {
503 			convert_to_long(&retval);
504 		}
505 		ret = 0;
506 		if (Z_LVAL(retval) > 0) {
507 			ret = 1;
508 		} else if (Z_LVAL(retval) < 0) {
509 			ret = -1;
510 		}
511 		zval_ptr_dtor(&retval);
512 	}
513 
514 	zval_ptr_dtor(&zargs[0]);
515 	zval_ptr_dtor(&zargs[1]);
516 
517 	return ret;
518 }
519 
520 /* {{{ bool SQLite::sqliteCreateFunction(string name, callable callback [, int argcount, int flags])
521    Registers a UDF with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateFunction)522 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateFunction)
523 {
524 	struct pdo_sqlite_func *func;
525 	zend_fcall_info fci;
526 	zend_fcall_info_cache fcc;
527 	char *func_name;
528 	size_t func_name_len;
529 	zend_long argc = -1;
530 	zend_long flags = 0;
531 	pdo_dbh_t *dbh;
532 	pdo_sqlite_db_handle *H;
533 	int ret;
534 
535 	ZEND_PARSE_PARAMETERS_START(2, 4)
536 		Z_PARAM_STRING(func_name, func_name_len)
537 		Z_PARAM_FUNC(fci, fcc)
538 		Z_PARAM_OPTIONAL
539 		Z_PARAM_LONG(argc)
540 		Z_PARAM_LONG(flags)
541 	ZEND_PARSE_PARAMETERS_END();
542 
543 	dbh = Z_PDO_DBH_P(ZEND_THIS);
544 	PDO_CONSTRUCT_CHECK;
545 
546 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
547 
548 	func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
549 
550 	ret = sqlite3_create_function(H->db, func_name, argc, flags | SQLITE_UTF8,
551 			func, php_sqlite3_func_callback, NULL, NULL);
552 	if (ret == SQLITE_OK) {
553 		func->funcname = estrdup(func_name);
554 
555 		ZVAL_COPY(&func->func, &fci.function_name);
556 
557 		func->argc = argc;
558 
559 		func->next = H->funcs;
560 		H->funcs = func;
561 
562 		RETURN_TRUE;
563 	}
564 
565 	efree(func);
566 	RETURN_FALSE;
567 }
568 /* }}} */
569 
570 /* {{{ bool SQLite::sqliteCreateAggregate(string name, callable step, callable fini [, int argcount])
571    Registers a UDF with the sqlite db handle */
572 
573 /* The step function should have the prototype:
574    mixed step(mixed $context, int $rownumber, $value [, $value2 [, ...]])
575 
576    $context will be null for the first row; on subsequent rows it will have
577    the value that was previously returned from the step function; you should
578    use this to maintain state for the aggregate.
579 
580    The fini function should have the prototype:
581    mixed fini(mixed $context, int $rownumber)
582 
583    $context will hold the return value from the very last call to the step function.
584    rownumber will hold the number of rows over which the aggregate was performed.
585    The return value of this function will be used as the return value for this
586    aggregate UDF.
587 */
588 
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateAggregate)589 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateAggregate)
590 {
591 	struct pdo_sqlite_func *func;
592 	zend_fcall_info step_fci, fini_fci;
593 	zend_fcall_info_cache step_fcc, fini_fcc;
594 	char *func_name;
595 	size_t func_name_len;
596 	zend_long argc = -1;
597 	pdo_dbh_t *dbh;
598 	pdo_sqlite_db_handle *H;
599 	int ret;
600 
601 	ZEND_PARSE_PARAMETERS_START(3, 4)
602 		Z_PARAM_STRING(func_name, func_name_len)
603 		Z_PARAM_FUNC(step_fci, step_fcc)
604 		Z_PARAM_FUNC(fini_fci, fini_fcc)
605 		Z_PARAM_OPTIONAL
606 		Z_PARAM_LONG(argc)
607 	ZEND_PARSE_PARAMETERS_END();
608 
609 	dbh = Z_PDO_DBH_P(ZEND_THIS);
610 	PDO_CONSTRUCT_CHECK;
611 
612 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
613 
614 	func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
615 
616 	ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
617 			func, NULL, php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
618 	if (ret == SQLITE_OK) {
619 		func->funcname = estrdup(func_name);
620 
621 		ZVAL_COPY(&func->step, &step_fci.function_name);
622 
623 		ZVAL_COPY(&func->fini, &fini_fci.function_name);
624 
625 		func->argc = argc;
626 
627 		func->next = H->funcs;
628 		H->funcs = func;
629 
630 		RETURN_TRUE;
631 	}
632 
633 	efree(func);
634 	RETURN_FALSE;
635 }
636 /* }}} */
637 
638 /* {{{ bool SQLite::sqliteCreateCollation(string name, callable callback)
639    Registers a collation with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateCollation)640 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateCollation)
641 {
642 	struct pdo_sqlite_collation *collation;
643 	zend_fcall_info fci;
644 	zend_fcall_info_cache fcc;
645 	char *collation_name;
646 	size_t collation_name_len;
647 	pdo_dbh_t *dbh;
648 	pdo_sqlite_db_handle *H;
649 	int ret;
650 
651 	ZEND_PARSE_PARAMETERS_START(2, 2)
652 		Z_PARAM_STRING(collation_name, collation_name_len)
653 		Z_PARAM_FUNC(fci, fcc)
654 	ZEND_PARSE_PARAMETERS_END();
655 
656 	dbh = Z_PDO_DBH_P(ZEND_THIS);
657 	PDO_CONSTRUCT_CHECK;
658 
659 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
660 
661 	collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));
662 
663 	ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_collation_callback);
664 	if (ret == SQLITE_OK) {
665 		collation->name = estrdup(collation_name);
666 
667 		ZVAL_COPY(&collation->callback, &fci.function_name);
668 
669 		collation->next = H->collations;
670 		H->collations = collation;
671 
672 		RETURN_TRUE;
673 	}
674 
675 	efree(collation);
676 	RETURN_FALSE;
677 }
678 /* }}} */
679 
get_driver_methods(pdo_dbh_t * dbh,int kind)680 static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind)
681 {
682 	switch (kind) {
683 		case PDO_DBH_DRIVER_METHOD_KIND_DBH:
684 			return class_PDO_SQLite_Ext_methods;
685 
686 		default:
687 			return NULL;
688 	}
689 }
690 
pdo_sqlite_request_shutdown(pdo_dbh_t * dbh)691 static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh)
692 {
693 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
694 	/* unregister functions, so that they don't linger for the next
695 	 * request */
696 	if (H) {
697 		pdo_sqlite_cleanup_callbacks(H);
698 	}
699 }
700 
pdo_sqlite_get_gc(pdo_dbh_t * dbh,zend_get_gc_buffer * gc_buffer)701 static void pdo_sqlite_get_gc(pdo_dbh_t *dbh, zend_get_gc_buffer *gc_buffer)
702 {
703 	pdo_sqlite_db_handle *H = dbh->driver_data;
704 
705 	struct pdo_sqlite_func *func = H->funcs;
706 	while (func) {
707 		zend_get_gc_buffer_add_zval(gc_buffer, &func->func);
708 		zend_get_gc_buffer_add_zval(gc_buffer, &func->step);
709 		zend_get_gc_buffer_add_zval(gc_buffer, &func->fini);
710 		func = func->next;
711 	}
712 
713 	struct pdo_sqlite_collation *collation = H->collations;
714 	while (collation) {
715 		zend_get_gc_buffer_add_zval(gc_buffer, &collation->callback);
716 		collation = collation->next;
717 	}
718 }
719 
720 static const 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 	NULL, /* in transaction, use PDO's internal tracking mechanism */
736 	pdo_sqlite_get_gc
737 };
738 
make_filename_safe(const char * filename)739 static char *make_filename_safe(const char *filename)
740 {
741 	if (*filename && strncasecmp(filename, "file:", 5) == 0) {
742 		if (PG(open_basedir) && *PG(open_basedir)) {
743 			return NULL;
744 		}
745 		return estrdup(filename);
746 	}
747 	if (*filename && memcmp(filename, ":memory:", sizeof(":memory:"))) {
748 		char *fullpath = expand_filepath(filename, NULL);
749 
750 		if (!fullpath) {
751 			return NULL;
752 		}
753 
754 		if (php_check_open_basedir(fullpath)) {
755 			efree(fullpath);
756 			return NULL;
757 		}
758 		return fullpath;
759 	}
760 	return estrdup(filename);
761 }
762 
authorizer(void * autharg,int access_type,const char * arg3,const char * arg4,const char * arg5,const char * arg6)763 static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
764 		const char *arg5, const char *arg6)
765 {
766 	char *filename;
767 	switch (access_type) {
768 		case SQLITE_COPY: {
769 					filename = make_filename_safe(arg4);
770 			if (!filename) {
771 				return SQLITE_DENY;
772 			}
773 			efree(filename);
774 			return SQLITE_OK;
775 		}
776 
777 		case SQLITE_ATTACH: {
778 					filename = make_filename_safe(arg3);
779 			if (!filename) {
780 				return SQLITE_DENY;
781 			}
782 			efree(filename);
783 			return SQLITE_OK;
784 		}
785 
786 		default:
787 			/* access allowed */
788 			return SQLITE_OK;
789 	}
790 }
791 
pdo_sqlite_handle_factory(pdo_dbh_t * dbh,zval * driver_options)792 static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
793 {
794 	pdo_sqlite_db_handle *H;
795 	int i, ret = 0;
796 	zend_long timeout = 60, flags;
797 	char *filename;
798 
799 	H = pecalloc(1, sizeof(pdo_sqlite_db_handle), dbh->is_persistent);
800 
801 	H->einfo.errcode = 0;
802 	H->einfo.errmsg = NULL;
803 	dbh->driver_data = H;
804 
805 	/* skip all but this one param event */
806 	dbh->skip_param_evt = 0x7F ^ (1 << PDO_PARAM_EVT_EXEC_PRE);
807 
808 	filename = make_filename_safe(dbh->data_source);
809 
810 	if (!filename) {
811 		zend_throw_exception_ex(php_pdo_get_exception(), 0,
812 			"open_basedir prohibits opening %s",
813 			dbh->data_source);
814 		goto cleanup;
815 	}
816 
817 	flags = pdo_attr_lval(driver_options, PDO_SQLITE_ATTR_OPEN_FLAGS, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
818 
819 	if (!(PG(open_basedir) && *PG(open_basedir))) {
820 		flags |= SQLITE_OPEN_URI;
821 	}
822 	i = sqlite3_open_v2(filename, &H->db, flags, NULL);
823 
824 	efree(filename);
825 
826 	if (i != SQLITE_OK) {
827 		pdo_sqlite_error(dbh);
828 		goto cleanup;
829 	}
830 
831 	if (PG(open_basedir) && *PG(open_basedir)) {
832 		sqlite3_set_authorizer(H->db, authorizer, NULL);
833 	}
834 
835 	if (driver_options) {
836 		timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout);
837 	}
838 	sqlite3_busy_timeout(H->db, timeout * 1000);
839 
840 	dbh->alloc_own_columns = 1;
841 	dbh->max_escaped_char_length = 2;
842 
843 	ret = 1;
844 
845 cleanup:
846 	dbh->methods = &sqlite_methods;
847 
848 	return ret;
849 }
850 /* }}} */
851 
852 const pdo_driver_t pdo_sqlite_driver = {
853 	PDO_DRIVER_HEADER(sqlite),
854 	pdo_sqlite_handle_factory
855 };
856