@@ -240,6 +240,7 @@ public function db_connect( $allow_bail = true ) {
240240 require_once __DIR__ . '/../../wp-includes/sqlite-ast/class-wp-sqlite-driver.php ' ;
241241 require_once __DIR__ . '/../../wp-includes/sqlite-ast/class-wp-sqlite-driver-exception.php ' ;
242242 require_once __DIR__ . '/../../wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php ' ;
243+ $ this ->ensure_database_directory ( FQDB );
243244 $ this ->dbh = new WP_SQLite_Driver (
244245 array (
245246 'connection ' => $ pdo ,
@@ -442,4 +443,51 @@ public function db_version() {
442443 public function db_server_info () {
443444 return $ this ->dbh ->get_sqlite_version ();
444445 }
446+
447+ /**
448+ * Make sure the SQLite database directory exists and is writable.
449+ * Create .htaccess and index.php files to prevent direct access.
450+ *
451+ * @param string $database_path The path to the SQLite database file.
452+ */
453+ private function ensure_database_directory ( string $ database_path ) {
454+ $ dir = dirname ( $ database_path );
455+
456+ // Set the umask to 0000 to apply permissions exactly as specified.
457+ // A non-zero umask affects new file and directory permissions.
458+ $ umask = umask ( 0 );
459+
460+ // Ensure database directory.
461+ if ( ! is_dir ( $ dir ) ) {
462+ if ( ! @mkdir ( $ dir , 0700 , true ) ) {
463+ wp_die ( sprintf ( 'Failed to create database directory: %s ' , $ dir ), 'Error! ' );
464+ }
465+ }
466+ if ( ! is_writable ( $ dir ) ) {
467+ wp_die ( sprintf ( 'Database directory is not writable: %s ' , $ dir ), 'Error! ' );
468+ }
469+
470+ // Ensure .htaccess file to prevent direct access.
471+ $ path = $ dir . DIRECTORY_SEPARATOR . '.htaccess ' ;
472+ if ( ! is_file ( $ path ) ) {
473+ $ result = file_put_contents ( $ path , 'DENY FROM ALL ' , LOCK_EX );
474+ if ( false === $ result ) {
475+ wp_die ( sprintf ( 'Failed to create file: %s ' , $ path ), 'Error! ' );
476+ }
477+ chmod ( $ path , 0600 );
478+ }
479+
480+ // Ensure index.php file to prevent direct access.
481+ $ path = $ dir . DIRECTORY_SEPARATOR . 'index.php ' ;
482+ if ( ! is_file ( $ path ) ) {
483+ $ result = file_put_contents ( $ path , '<?php // Silence is gold. ?> ' , LOCK_EX );
484+ if ( false === $ result ) {
485+ wp_die ( sprintf ( 'Failed to create file: %s ' , $ path ), 'Error! ' );
486+ }
487+ chmod ( $ path , 0600 );
488+ }
489+
490+ // Restore the original umask value.
491+ umask ( $ umask );
492+ }
445493}
0 commit comments