xref: /PHP-7.3/ext/pdo_sqlite/sqlite_driver.c (revision 44ade0e8)
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 7                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2018 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_NONE));
49 		return 0;
50 	}
51 	switch (einfo->errcode) {
52 		case SQLITE_NOTFOUND:
53 			strncpy(*pdo_err, "42S02", sizeof("42S02"));
54 			break;
55 
56 		case SQLITE_INTERRUPT:
57 			strncpy(*pdo_err, "01002", sizeof("01002"));
58 			break;
59 
60 		case SQLITE_NOLFS:
61 			strncpy(*pdo_err, "HYC00", sizeof("HYC00"));
62 			break;
63 
64 		case SQLITE_TOOBIG:
65 			strncpy(*pdo_err, "22001", sizeof("22001"));
66 			break;
67 
68 		case SQLITE_CONSTRAINT:
69 			strncpy(*pdo_err, "23000", sizeof("23000"));
70 			break;
71 
72 		case SQLITE_ERROR:
73 		default:
74 			strncpy(*pdo_err, "HY000", sizeof("HY000"));
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 	}
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)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)
314 {
315 	zval *zargs = NULL;
316 	zval retval;
317 	int i;
318 	int ret;
319 	int fake_argc;
320 	zend_reference *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 	ZVAL_COPY_VALUE(&fc->fci.function_name, cb);
330 	fc->fci.object = NULL;
331 	fc->fci.retval = &retval;
332 	fc->fci.param_count = fake_argc;
333 
334 	/* build up the params */
335 
336 	if (fake_argc) {
337 		zargs = safe_emalloc(fake_argc, sizeof(zval), 0);
338 	}
339 
340 	if (is_agg) {
341 		agg_context = (zend_reference*)sqlite3_aggregate_context(context, sizeof(zend_reference));
342 		if (!agg_context) {
343 			ZVAL_NULL(&zargs[0]);
344 		} else {
345 			if (Z_ISUNDEF(agg_context->val)) {
346 				GC_SET_REFCOUNT(agg_context, 1);
347 				GC_TYPE_INFO(agg_context) = IS_REFERENCE;
348 				ZVAL_NULL(&agg_context->val);
349 			}
350 			ZVAL_REF(&zargs[0], agg_context);
351 		}
352 		ZVAL_LONG(&zargs[1], sqlite3_aggregate_count(context));
353 	}
354 
355 	for (i = 0; i < argc; i++) {
356 		/* get the value */
357 		switch (sqlite3_value_type(argv[i])) {
358 			case SQLITE_INTEGER:
359 				ZVAL_LONG(&zargs[i + is_agg], sqlite3_value_int(argv[i]));
360 				break;
361 
362 			case SQLITE_FLOAT:
363 				ZVAL_DOUBLE(&zargs[i + is_agg], sqlite3_value_double(argv[i]));
364 				break;
365 
366 			case SQLITE_NULL:
367 				ZVAL_NULL(&zargs[i + is_agg]);
368 				break;
369 
370 			case SQLITE_BLOB:
371 			case SQLITE3_TEXT:
372 			default:
373 				ZVAL_STRINGL(&zargs[i + is_agg], (char*)sqlite3_value_text(argv[i]), sqlite3_value_bytes(argv[i]));
374 				break;
375 		}
376 	}
377 
378 	fc->fci.params = zargs;
379 
380 	if ((ret = zend_call_function(&fc->fci, &fc->fcc)) == FAILURE) {
381 		php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
382 	}
383 
384 	/* clean up the params */
385 	if (zargs) {
386 		for (i = is_agg; i < fake_argc; i++) {
387 			zval_ptr_dtor(&zargs[i]);
388 		}
389 		if (is_agg) {
390 			zval_ptr_dtor(&zargs[1]);
391 		}
392 		efree(zargs);
393 	}
394 
395 	if (!is_agg || !argv) {
396 		/* only set the sqlite return value if we are a scalar function,
397 		 * or if we are finalizing an aggregate */
398 		if (!Z_ISUNDEF(retval)) {
399 			switch (Z_TYPE(retval)) {
400 				case IS_LONG:
401 					sqlite3_result_int(context, Z_LVAL(retval));
402 					break;
403 
404 				case IS_NULL:
405 					sqlite3_result_null(context);
406 					break;
407 
408 				case IS_DOUBLE:
409 					sqlite3_result_double(context, Z_DVAL(retval));
410 					break;
411 
412 				default:
413 					convert_to_string_ex(&retval);
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 			zval_ptr_dtor(&agg_context->val);
429 		}
430 		if (!Z_ISUNDEF(retval)) {
431 			ZVAL_COPY_VALUE(&agg_context->val, &retval);
432 			ZVAL_UNDEF(&retval);
433 		} else {
434 			ZVAL_UNDEF(&agg_context->val);
435 		}
436 	}
437 
438 	if (!Z_ISUNDEF(retval)) {
439 		zval_ptr_dtor(&retval);
440 	}
441 
442 	return ret;
443 }
444 
php_sqlite3_func_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)445 static void php_sqlite3_func_callback(sqlite3_context *context, int argc,
446 	sqlite3_value **argv)
447 {
448 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
449 
450 	do_callback(&func->afunc, &func->func, argc, argv, context, 0);
451 }
452 
php_sqlite3_func_step_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)453 static void php_sqlite3_func_step_callback(sqlite3_context *context, int argc,
454 	sqlite3_value **argv)
455 {
456 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
457 
458 	do_callback(&func->astep, &func->step, argc, argv, context, 1);
459 }
460 
php_sqlite3_func_final_callback(sqlite3_context * context)461 static void php_sqlite3_func_final_callback(sqlite3_context *context)
462 {
463 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
464 
465 	do_callback(&func->afini, &func->fini, 0, NULL, context, 1);
466 }
467 
php_sqlite3_collation_callback(void * context,int string1_len,const void * string1,int string2_len,const void * string2)468 static int php_sqlite3_collation_callback(void *context,
469 	int string1_len, const void *string1,
470 	int string2_len, const void *string2)
471 {
472 	int ret;
473 	zval zargs[2];
474 	zval retval;
475 	struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context;
476 
477 	collation->fc.fci.size = sizeof(collation->fc.fci);
478 	ZVAL_COPY_VALUE(&collation->fc.fci.function_name, &collation->callback);
479 	collation->fc.fci.object = NULL;
480 	collation->fc.fci.retval = &retval;
481 
482 	// Prepare the arguments.
483 	ZVAL_STRINGL(&zargs[0], (char *) string1, string1_len);
484 	ZVAL_STRINGL(&zargs[1], (char *) string2, string2_len);
485 	collation->fc.fci.param_count = 2;
486 	collation->fc.fci.params = zargs;
487 
488 	if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc)) == FAILURE) {
489 		php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
490 	} else if (!Z_ISUNDEF(retval)) {
491 		if (Z_TYPE(retval) != IS_LONG) {
492 			convert_to_long_ex(&retval);
493 		}
494 		ret = 0;
495 		if (Z_LVAL(retval) > 0) {
496 			ret = 1;
497 		} else if (Z_LVAL(retval) < 0) {
498 			ret = -1;
499 		}
500 		zval_ptr_dtor(&retval);
501 	}
502 
503 	zval_ptr_dtor(&zargs[0]);
504 	zval_ptr_dtor(&zargs[1]);
505 
506 	return ret;
507 }
508 
509 /* {{{ bool SQLite::sqliteCreateFunction(string name, mixed callback [, int argcount, int flags])
510    Registers a UDF with the sqlite db handle */
PHP_METHOD(SQLite,sqliteCreateFunction)511 static PHP_METHOD(SQLite, sqliteCreateFunction)
512 {
513 	struct pdo_sqlite_func *func;
514 	zval *callback;
515 	char *func_name;
516 	size_t func_name_len;
517 	zend_long argc = -1;
518 	zend_long flags = 0;
519 	pdo_dbh_t *dbh;
520 	pdo_sqlite_db_handle *H;
521 	int ret;
522 
523 	ZEND_PARSE_PARAMETERS_START(2, 4)
524 		Z_PARAM_STRING(func_name, func_name_len)
525 		Z_PARAM_ZVAL(callback)
526 		Z_PARAM_OPTIONAL
527 		Z_PARAM_LONG(argc)
528 		Z_PARAM_LONG(flags)
529 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
530 
531 	dbh = Z_PDO_DBH_P(getThis());
532 	PDO_CONSTRUCT_CHECK;
533 
534 	if (!zend_is_callable(callback, 0, NULL)) {
535 		zend_string *cbname = zend_get_callable_name(callback);
536 		php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
537 		zend_string_release_ex(cbname, 0);
538 		RETURN_FALSE;
539 	}
540 
541 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
542 
543 	func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
544 
545 	ret = sqlite3_create_function(H->db, func_name, argc, flags | SQLITE_UTF8,
546 			func, php_sqlite3_func_callback, NULL, NULL);
547 	if (ret == SQLITE_OK) {
548 		func->funcname = estrdup(func_name);
549 
550 		ZVAL_COPY(&func->func, callback);
551 
552 		func->argc = argc;
553 
554 		func->next = H->funcs;
555 		H->funcs = func;
556 
557 		RETURN_TRUE;
558 	}
559 
560 	efree(func);
561 	RETURN_FALSE;
562 }
563 /* }}} */
564 
565 /* {{{ bool SQLite::sqliteCreateAggregate(string name, mixed step, mixed fini [, int argcount])
566    Registers a UDF with the sqlite db handle */
567 
568 /* The step function should have the prototype:
569    mixed step(mixed $context, int $rownumber, $value [, $value2 [, ...]])
570 
571    $context will be null for the first row; on subsequent rows it will have
572    the value that was previously returned from the step function; you should
573    use this to maintain state for the aggregate.
574 
575    The fini function should have the prototype:
576    mixed fini(mixed $context, int $rownumber)
577 
578    $context will hold the return value from the very last call to the step function.
579    rownumber will hold the number of rows over which the aggregate was performed.
580    The return value of this function will be used as the return value for this
581    aggregate UDF.
582 */
583 
PHP_METHOD(SQLite,sqliteCreateAggregate)584 static PHP_METHOD(SQLite, sqliteCreateAggregate)
585 {
586 	struct pdo_sqlite_func *func;
587 	zval *step_callback, *fini_callback;
588 	char *func_name;
589 	size_t func_name_len;
590 	zend_long argc = -1;
591 	pdo_dbh_t *dbh;
592 	pdo_sqlite_db_handle *H;
593 	int ret;
594 
595 	ZEND_PARSE_PARAMETERS_START(3, 4)
596 		Z_PARAM_STRING(func_name, func_name_len)
597 		Z_PARAM_ZVAL(step_callback)
598 		Z_PARAM_ZVAL(fini_callback)
599 		Z_PARAM_OPTIONAL
600 		Z_PARAM_LONG(argc)
601 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
602 
603 	dbh = Z_PDO_DBH_P(getThis());
604 	PDO_CONSTRUCT_CHECK;
605 
606 	if (!zend_is_callable(step_callback, 0, NULL)) {
607 		zend_string *cbname = zend_get_callable_name(step_callback);
608 		php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
609 		zend_string_release_ex(cbname, 0);
610 		RETURN_FALSE;
611 	}
612 
613 	if (!zend_is_callable(fini_callback, 0, NULL)) {
614 		zend_string *cbname = zend_get_callable_name(fini_callback);
615 		php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
616 		zend_string_release_ex(cbname, 0);
617 		RETURN_FALSE;
618 	}
619 
620 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
621 
622 	func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
623 
624 	ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
625 			func, NULL, php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
626 	if (ret == SQLITE_OK) {
627 		func->funcname = estrdup(func_name);
628 
629 		ZVAL_COPY(&func->step, step_callback);
630 
631 		ZVAL_COPY(&func->fini, fini_callback);
632 
633 		func->argc = argc;
634 
635 		func->next = H->funcs;
636 		H->funcs = func;
637 
638 		RETURN_TRUE;
639 	}
640 
641 	efree(func);
642 	RETURN_FALSE;
643 }
644 /* }}} */
645 
646 /* {{{ bool SQLite::sqliteCreateCollation(string name, mixed callback)
647    Registers a collation with the sqlite db handle */
PHP_METHOD(SQLite,sqliteCreateCollation)648 static PHP_METHOD(SQLite, sqliteCreateCollation)
649 {
650 	struct pdo_sqlite_collation *collation;
651 	zval *callback;
652 	char *collation_name;
653 	size_t collation_name_len;
654 	pdo_dbh_t *dbh;
655 	pdo_sqlite_db_handle *H;
656 	int ret;
657 
658 	ZEND_PARSE_PARAMETERS_START(2, 2)
659 		Z_PARAM_STRING(collation_name, collation_name_len)
660 		Z_PARAM_ZVAL(callback)
661 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
662 
663 	dbh = Z_PDO_DBH_P(getThis());
664 	PDO_CONSTRUCT_CHECK;
665 
666 	if (!zend_is_callable(callback, 0, NULL)) {
667 		zend_string *cbname = zend_get_callable_name(callback);
668 		php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
669 		zend_string_release_ex(cbname, 0);
670 		RETURN_FALSE;
671 	}
672 
673 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
674 
675 	collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));
676 
677 	ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_collation_callback);
678 	if (ret == SQLITE_OK) {
679 		collation->name = estrdup(collation_name);
680 
681 		ZVAL_COPY(&collation->callback, callback);
682 
683 		collation->next = H->collations;
684 		H->collations = collation;
685 
686 		RETURN_TRUE;
687 	}
688 
689 	efree(collation);
690 	RETURN_FALSE;
691 }
692 /* }}} */
693 
694 static const zend_function_entry dbh_methods[] = {
695 	PHP_ME(SQLite, sqliteCreateFunction, NULL, ZEND_ACC_PUBLIC)
696 	PHP_ME(SQLite, sqliteCreateAggregate, NULL, ZEND_ACC_PUBLIC)
697 	PHP_ME(SQLite, sqliteCreateCollation, NULL, ZEND_ACC_PUBLIC)
698 	PHP_FE_END
699 };
700 
get_driver_methods(pdo_dbh_t * dbh,int kind)701 static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind)
702 {
703 	switch (kind) {
704 		case PDO_DBH_DRIVER_METHOD_KIND_DBH:
705 			return dbh_methods;
706 
707 		default:
708 			return NULL;
709 	}
710 }
711 
pdo_sqlite_request_shutdown(pdo_dbh_t * dbh)712 static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh)
713 {
714 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
715 	/* unregister functions, so that they don't linger for the next
716 	 * request */
717 	if (H) {
718 		pdo_sqlite_cleanup_callbacks(H);
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
738 };
739 
make_filename_safe(const char * filename)740 static char *make_filename_safe(const char *filename)
741 {
742 	if (*filename && memcmp(filename, ":memory:", sizeof(":memory:"))) {
743 		char *fullpath = expand_filepath(filename, NULL);
744 
745 		if (!fullpath) {
746 			return NULL;
747 		}
748 
749 		if (php_check_open_basedir(fullpath)) {
750 			efree(fullpath);
751 			return NULL;
752 		}
753 		return fullpath;
754 	}
755 	return estrdup(filename);
756 }
757 
authorizer(void * autharg,int access_type,const char * arg3,const char * arg4,const char * arg5,const char * arg6)758 static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
759 		const char *arg5, const char *arg6)
760 {
761 	char *filename;
762 	switch (access_type) {
763 		case SQLITE_COPY: {
764 					filename = make_filename_safe(arg4);
765 			if (!filename) {
766 				return SQLITE_DENY;
767 			}
768 			efree(filename);
769 			return SQLITE_OK;
770 		}
771 
772 		case SQLITE_ATTACH: {
773 					filename = make_filename_safe(arg3);
774 			if (!filename) {
775 				return SQLITE_DENY;
776 			}
777 			efree(filename);
778 			return SQLITE_OK;
779 		}
780 
781 		default:
782 			/* access allowed */
783 			return SQLITE_OK;
784 	}
785 }
786 
pdo_sqlite_handle_factory(pdo_dbh_t * dbh,zval * driver_options)787 static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
788 {
789 	pdo_sqlite_db_handle *H;
790 	int i, ret = 0;
791 	zend_long timeout = 60, flags;
792 	char *filename;
793 
794 	H = pecalloc(1, sizeof(pdo_sqlite_db_handle), dbh->is_persistent);
795 
796 	H->einfo.errcode = 0;
797 	H->einfo.errmsg = NULL;
798 	dbh->driver_data = H;
799 
800 	/* skip all but this one param event */
801 	dbh->skip_param_evt = 0x7F ^ (1 << PDO_PARAM_EVT_EXEC_PRE);
802 
803 	filename = make_filename_safe(dbh->data_source);
804 
805 	if (!filename) {
806 		zend_throw_exception_ex(php_pdo_get_exception(), 0,
807 			"open_basedir prohibits opening %s",
808 			dbh->data_source);
809 		goto cleanup;
810 	}
811 
812 	flags = pdo_attr_lval(driver_options, PDO_SQLITE_ATTR_OPEN_FLAGS, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
813 
814 #if SQLITE_VERSION_NUMBER >= 3005000
815 	i = sqlite3_open_v2(filename, &H->db, flags, NULL);
816 #else
817 	i = sqlite3_open(filename, &H->db);
818 #endif
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 
853 /*
854  * Local variables:
855  * tab-width: 4
856  * c-basic-offset: 4
857  * End:
858  * vim600: noet sw=4 ts=4 fdm=marker
859  * vim<600: noet sw=4 ts=4
860  */
861