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