From: tzmfreedom Date: Sun, 17 Jan 2021 05:13:19 +0000 (+0900) Subject: Allow specifying sqlite3 DSN (file:/) in PDO SQLite X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a8dd009f23ab9ccd6b63f58a203d49fd0513a50d;p=php Allow specifying sqlite3 DSN (file:/) in PDO SQLite Closes GH-6610. --- diff --git a/UPGRADING b/UPGRADING index facdf30377..29701c3714 100644 --- a/UPGRADING +++ b/UPGRADING @@ -126,6 +126,13 @@ PHP 8.1 UPGRADE NOTES echo $h, "\n"; ``` +- PDO SQLite: + . SQLite's "file:" DSN syntax is now supported, which allows specifying + additional flags. This feature is not available if open_basedir is set. + Example: + + new PDO('sqlite:file:path/to/sqlite.db?mode=ro') + - Posix: . Added POSIX_RLIMIT_KQUEUES and POSIX_RLIMIT_NPTS. These rlimits are only available on FreeBSD. diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c index a48c77f9e8..217833f6ad 100644 --- a/ext/pdo_sqlite/sqlite_driver.c +++ b/ext/pdo_sqlite/sqlite_driver.c @@ -731,6 +731,12 @@ static const struct pdo_dbh_methods sqlite_methods = { static char *make_filename_safe(const char *filename) { + if (*filename && strncasecmp(filename, "file:", 5) == 0) { + if (PG(open_basedir) && *PG(open_basedir)) { + return NULL; + } + return estrdup(filename); + } if (*filename && memcmp(filename, ":memory:", sizeof(":memory:"))) { char *fullpath = expand_filepath(filename, NULL); @@ -803,6 +809,9 @@ static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{ flags = pdo_attr_lval(driver_options, PDO_SQLITE_ATTR_OPEN_FLAGS, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); + if (!(PG(open_basedir) && *PG(open_basedir))) { + flags |= SQLITE_OPEN_URI; + } i = sqlite3_open_v2(filename, &H->db, flags, NULL); efree(filename); diff --git a/ext/pdo_sqlite/tests/open_basedir.phpt b/ext/pdo_sqlite/tests/open_basedir.phpt new file mode 100644 index 0000000000..8041b47407 --- /dev/null +++ b/ext/pdo_sqlite/tests/open_basedir.phpt @@ -0,0 +1,31 @@ +--TEST-- +PDO SQLite open_basedir check +--SKIPIF-- + +--INI-- +open_basedir=. +--FILE-- +getMessage() . "\n"; +} +try { + $db = new PDO('sqlite:file:../not_in_open_basedir.sqlite'); +} catch (Exception $e) { + echo $e->getMessage() . "\n"; +} +try { + $db = new PDO('sqlite:file:../not_in_open_basedir.sqlite?mode=ro'); +} catch (Exception $e) { + echo $e->getMessage() . "\n"; +} + +?> +--EXPECT-- +open_basedir prohibits opening ../not_in_open_basedir.sqlite +open_basedir prohibits opening file:../not_in_open_basedir.sqlite +open_basedir prohibits opening file:../not_in_open_basedir.sqlite?mode=ro diff --git a/ext/pdo_sqlite/tests/pdo_sqlite_filename_uri.phpt b/ext/pdo_sqlite/tests/pdo_sqlite_filename_uri.phpt new file mode 100644 index 0000000000..7eec264ae2 --- /dev/null +++ b/ext/pdo_sqlite/tests/pdo_sqlite_filename_uri.phpt @@ -0,0 +1,37 @@ +--TEST-- +PDO_sqlite: Testing filename uri +--SKIPIF-- + +--FILE-- +exec('CREATE TABLE test1 (id INT);')); + +// create with readonly mode +$filename = "file:" . __DIR__ . DIRECTORY_SEPARATOR . "pdo_sqlite_filename_uri.db?mode=ro"; + +$db = new PDO('sqlite:' . $filename); + +var_dump($db->exec('CREATE TABLE test2 (id INT);')); + +?> +--CLEAN-- + +--EXPECTF-- +int(0) + +Fatal error: Uncaught PDOException: SQLSTATE[HY000]: General error: 8 attempt to write a readonly database in %s +Stack trace: +%s +#1 {main} + thrown in %s