Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions features/db-sqlite-path.feature
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,78 @@ Feature: Select the configured SQLite database for file operations
| | selected.sqlite | | | |
| | | | selected.sqlite | / |

Scenario: Resolve the recorded secret path from db-path.php
Given a WP install
When I run `wp eval 'mkdir( "recorded" ); copy( defined( "DB_PATH" ) ? DB_PATH : FQDB, "recorded/selected.sqlite" ); copy( "recorded/selected.sqlite", ".ht.sqlite" ); file_put_contents( "recorded/db-path.php", "<?php return " . var_export( getcwd() . "/recorded/selected.sqlite", true ) . ";" );'`
And I run `sqlite3 recorded/selected.sqlite "CREATE TABLE path_marker (value TEXT); INSERT INTO path_marker VALUES ('selected');"`
And I run `sqlite3 .ht.sqlite "CREATE TABLE path_marker (value TEXT); INSERT INTO path_marker VALUES ('other');"`

Given a paths.php file:
"""
<?php
define( 'FQDBDIR', __DIR__ . '/recorded/' );
"""
When I run `wp config set path_constants "require __DIR__ . '/paths.php'" --type=variable --raw`
And I try `wp eval 'echo "ready";'`
Then the return code should be 0

When I run `wp eval 'echo md5_file( ".ht.sqlite" );' --skip-wordpress`
Then save STDOUT as {OTHER_HASH}

When I try `wp db export selected.sql`
Then the return code should be 0
And the selected.sql file should contain:
"""
INSERT INTO path_marker VALUES('selected');
"""
And the selected.sql file should not contain:
"""
INSERT INTO path_marker VALUES('other');
"""

When I try `wp db drop --yes`
Then the return code should be 0
And the recorded/selected.sqlite file should not exist

When I run `wp eval 'echo md5_file( ".ht.sqlite" );' --skip-wordpress`
Then STDOUT should be:
"""
{OTHER_HASH}
"""

@require-sqlite
Scenario: Resolve the recorded secret path without loading the drop-in
Given a WP install
When I run `wp eval 'mkdir( "recorded" ); copy( defined( "DB_PATH" ) ? DB_PATH : FQDB, "recorded/selected.sqlite" ); copy( "recorded/selected.sqlite", ".ht.sqlite" ); file_put_contents( "recorded/db-path.php", "<?php return " . var_export( getcwd() . "/recorded/selected.sqlite", true ) . ";" );'`
And I run `sqlite3 recorded/selected.sqlite "CREATE TABLE path_marker (value TEXT); INSERT INTO path_marker VALUES ('selected');"`
And I run `sqlite3 .ht.sqlite "CREATE TABLE path_marker (value TEXT); INSERT INTO path_marker VALUES ('other');"`

Given a paths.php file:
"""
<?php
define( 'DB_ENGINE', 'sqlite' );
define( 'FQDBDIR', __DIR__ . '/recorded/' );
"""
When I run `wp config set path_constants "require __DIR__ . '/paths.php'" --type=variable --raw`
And I try `wp eval 'echo "ready";'`
Then the return code should be 0

# Remove the drop-in so no DB_PATH or FQDB constant can be defined
# before get_sqlite_db_path() runs. Only the recorded-path branch can
# resolve this database.
When I run `rm wp-content/db.php`

And I try `wp db export selected.sql`
Then the return code should be 0
And the selected.sql file should contain:
"""
INSERT INTO path_marker VALUES('selected');
"""
And the selected.sql file should not contain:
"""
INSERT INTO path_marker VALUES('other');
"""

Scenario Outline: Reject file operations on an in-memory SQLite database
Given a WP install
And an input.sql file:
Expand Down
24 changes: 21 additions & 3 deletions src/DB_Command_SQLite.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,28 @@ protected function get_sqlite_db_path() {
$wp_content_dir = defined( 'WP_CONTENT_DIR' ) ? WP_CONTENT_DIR : ABSPATH . 'wp-content';

// Check for FQDBDIR and construct path.
$db_dir = defined( 'FQDBDIR' ) ? FQDBDIR : $wp_content_dir . '/database';
$db_file = defined( 'DB_FILE' ) ? DB_FILE : '.ht.sqlite';
$db_dir = defined( 'FQDBDIR' ) ? FQDBDIR : $wp_content_dir . '/database';

$db_path = rtrim( $db_dir, '/' ) . '/' . ltrim( $db_file, '/' );
// DB_FILE selects a file inside FQDBDIR (sqlite-database-integration 3.1+).
if ( defined( 'DB_FILE' ) ) {
return rtrim( $db_dir, '/' ) . '/' . ltrim( DB_FILE, '/' );
}

// Check for the recorded secret path (sqlite-database-integration 3.1+).
$path_file = rtrim( $db_dir, '/\\' ) . '/db-path.php';
if ( file_exists( $path_file ) ) {
// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- Failure is checked below.
$recorded_path = @include $path_file;
if ( is_string( $recorded_path ) && '' !== $recorded_path ) {
if ( ':memory:' === $recorded_path ) {
WP_CLI::error( 'This command does not support in-memory SQLite databases.' );
}

return $recorded_path;
}
}

$db_path = rtrim( $db_dir, '/' ) . '/.ht.sqlite';

// If the file exists, return it.
if ( file_exists( $db_path ) ) {
Expand Down
Loading