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