Allow specifying sqlite3 DSN (file:/) in PDO SQLite

Closes GH-6610.
This commit is contained in:
tzmfreedom 2021-01-17 14:13:19 +09:00 committed by Nikita Popov
parent cc3e03c512
commit a8dd009f23
4 changed files with 84 additions and 0 deletions

View File

@ -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.

View File

@ -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);

View File

@ -0,0 +1,31 @@
--TEST--
PDO SQLite open_basedir check
--SKIPIF--
<?php if (!extension_loaded('pdo_sqlite')) print 'skip not loaded'; ?>
--INI--
open_basedir=.
--FILE--
<?php
chdir(__DIR__);
try {
$db = new PDO('sqlite:../not_in_open_basedir.sqlite');
} catch (Exception $e) {
echo $e->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

View File

@ -0,0 +1,37 @@
--TEST--
PDO_sqlite: Testing filename uri
--SKIPIF--
<?php if (!extension_loaded('pdo_sqlite')) print 'skip not loaded'; ?>
--FILE--
<?php
// create with default read-write|create mode
$filename = "file:" . __DIR__ . DIRECTORY_SEPARATOR . "pdo_sqlite_filename_uri.db";
$db = new PDO('sqlite:' . $filename);
var_dump($db->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--
<?php
$filename = __DIR__ . DIRECTORY_SEPARATOR . "pdo_sqlite_filename_uri.db";
if (file_exists($filename)) {
unlink($filename);
}
?>
--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