From 9fb3a40c2f1fa2ead34ab0fe9523ff592922c94c Mon Sep 17 00:00:00 2001 From: e-ht <1045813+e-ht@users.noreply.github> Date: Fri, 16 Dec 2022 22:05:01 -0800 Subject: [PATCH 1/9] - replaced functions-plugins.php/yourls_activate_plugin_sandbox() with functions.php/yourls_activate_file_sandbox() - updated calls to functions --- includes/Config/Init.php | 4 ++-- includes/Database/YDB.php | 2 +- includes/functions-html.php | 2 +- includes/functions-plugins.php | 22 +++------------------- includes/functions.php | 20 ++++++++++++++++++-- tests/tests/plugins/files.php | 2 +- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/includes/Config/Init.php b/includes/Config/Init.php index a0c50f213..c6f41da90 100644 --- a/includes/Config/Init.php +++ b/includes/Config/Init.php @@ -147,7 +147,7 @@ public function redirect_ssl_if_needed() { public function include_db_files() { // Allow drop-in replacement for the DB engine if (file_exists(YOURLS_USERDIR.'/db.php')) { - require_once YOURLS_USERDIR.'/db.php'; + yourls_activate_file_sandbox( YOURLS_USERDIR.'/db.php' ); } else { require_once YOURLS_INC.'/class-mysql.php'; yourls_db_connect(); @@ -160,7 +160,7 @@ public function include_db_files() { */ public function include_cache_files() { if (file_exists(YOURLS_USERDIR.'/cache.php')) { - require_once YOURLS_USERDIR.'/cache.php'; + yourls_activate_file_sandbox( YOURLS_USERDIR.'/cache.php' ); } } diff --git a/includes/Database/YDB.php b/includes/Database/YDB.php index 091cb8a2d..b734fe70b 100644 --- a/includes/Database/YDB.php +++ b/includes/Database/YDB.php @@ -158,7 +158,7 @@ public function connect_to_DB() { public function dead_or_error(\Exception $exception) { // Use any /user/db_error.php file if( file_exists( YOURLS_USERDIR . '/db_error.php' ) ) { - include_once( YOURLS_USERDIR . '/db_error.php' ); + yourls_activate_file_sandbox( YOURLS_USERDIR . '/db_error.php' ); die(); } diff --git a/includes/functions-html.php b/includes/functions-html.php index 427e28eb8..2d92cd302 100644 --- a/includes/functions-html.php +++ b/includes/functions-html.php @@ -906,7 +906,7 @@ function yourls_page( $page ) { } yourls_do_action( 'pre_page', $page ); - include_once( YOURLS_PAGEDIR . "/$page.php" ); + yourls_activate_file_sandbox( YOURLS_PAGEDIR . "/$page.php" ); yourls_do_action( 'post_page', $page ); } diff --git a/includes/functions-plugins.php b/includes/functions-plugins.php index dab4f9679..67e1977ba 100644 --- a/includes/functions-plugins.php +++ b/includes/functions-plugins.php @@ -595,7 +595,7 @@ function yourls_load_plugins() { $plugins = []; foreach ( $active_plugins as $key => $plugin ) { $file = YOURLS_PLUGINDIR . '/' . $plugin; - if ( yourls_is_a_plugin_file($file) && yourls_activate_plugin_sandbox( $file ) === true ) { + if ( yourls_is_a_plugin_file($file) && yourls_activate_file_sandbox( $file ) === true ) { $plugins[] = $plugin; unset( $active_plugins[ $key ] ); } @@ -659,7 +659,7 @@ function yourls_activate_plugin( $plugin ) { } // attempt activation. - $attempt = yourls_activate_plugin_sandbox( $plugindir.'/'.$plugin ); + $attempt = yourls_activate_file_sandbox( $plugindir.'/'.$plugin ); if( $attempt !== true ) { return yourls_s( 'Plugin generated unexpected output. Error was:
%s
', $attempt ); } @@ -673,22 +673,6 @@ function yourls_activate_plugin( $plugin ) { return true; } -/** - * Plugin activation sandbox - * - * @since 1.8.3 - * @param string $pluginfile Plugin filename (full path) - * @return string|true string if error or true if success - */ -function yourls_activate_plugin_sandbox( $pluginfile ) { - try { - include_once $pluginfile; - return true; - } catch ( \Throwable $e ) { - return $e->getMessage(); - } -} - /** * Deactivate a plugin * @@ -708,7 +692,7 @@ function yourls_deactivate_plugin( $plugin ) { $uninst_file = YOURLS_PLUGINDIR . '/' . dirname($plugin) . '/uninstall.php'; if ( file_exists($uninst_file) ) { define('YOURLS_UNINSTALL_PLUGIN', true); - $attempt = yourls_activate_plugin_sandbox( $uninst_file ); + $attempt = yourls_activate_file_sandbox( $uninst_file ); if( $attempt !== true ) { return yourls_s( 'Plugin generated unexpected output. Error was:
%s
', $attempt ); } diff --git a/includes/functions.php b/includes/functions.php index ec9f9febe..a19942ed2 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -1072,7 +1072,7 @@ function yourls_check_maintenance_mode() { } global $maintenance_start; - include_once( $file ); + yourls_activate_file_sandbox( $file ); // If the $maintenance_start timestamp is older than 10 minutes, don't die. if ( ( time() - $maintenance_start ) >= 600 ) { return; @@ -1080,7 +1080,7 @@ function yourls_check_maintenance_mode() { // Use any /user/maintenance.php file if( file_exists( YOURLS_USERDIR.'/maintenance.php' ) ) { - include_once( YOURLS_USERDIR.'/maintenance.php' ); + yourls_activate_file_sandbox( YOURLS_USERDIR.'/maintenance.php' ); die(); } @@ -1271,3 +1271,19 @@ function yourls_tell_if_new_version() { yourls_debug_log( 'Check for new version: '.( yourls_maybe_check_core_version() ? 'yes' : 'no' ) ); yourls_new_core_version_notice(YOURLS_VERSION); } + +/** + * File activation sandbox + * + * @since TODO + * @param string $file filename (full path) + * @return string|true string if error or true if success + */ +function yourls_activate_file_sandbox( $file ) { + try { + include_once $file; + return true; + } catch ( \Throwable $e ) { + return $e->getMessage(); + } +} diff --git a/tests/tests/plugins/files.php b/tests/tests/plugins/files.php index 6062c7626..d029a03c0 100644 --- a/tests/tests/plugins/files.php +++ b/tests/tests/plugins/files.php @@ -193,7 +193,7 @@ public function test_invalid_plugin_deactivate() { * @dataProvider get_invalid_code_plugins */ public function test_invalid_plugin_does_not_activate($plugin) { - $this->assertNotTrue( yourls_activate_plugin_sandbox( $plugin ) ); + $this->assertNotTrue( yourls_activate_file_sandbox( $plugin ) ); $this->assertNotTrue( yourls_activate_plugin( $plugin ) ); $this->assertNotTrue( yourls_is_active_plugin( $plugin ) ); } From b433f3cdaf6b88dae91696d111882c46981fbac1 Mon Sep 17 00:00:00 2001 From: e-ht <1045813+e-ht@users.noreply.github> Date: Sat, 17 Dec 2022 18:28:21 -0800 Subject: [PATCH 2/9] fix typo-- missing 's' --- tests/data/config/yourls-tests-config-sample.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/data/config/yourls-tests-config-sample.php b/tests/data/config/yourls-tests-config-sample.php index 3d391a3ab..6ec26b433 100644 --- a/tests/data/config/yourls-tests-config-sample.php +++ b/tests/data/config/yourls-tests-config-sample.php @@ -1,6 +1,6 @@ Date: Sat, 17 Dec 2022 19:27:37 -0800 Subject: [PATCH 3/9] deprecate function yourls_activate_plugin_sandbox() --- includes/functions-deprecated.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/includes/functions-deprecated.php b/includes/functions-deprecated.php index bbc4f3c06..76fa6c941 100644 --- a/includes/functions-deprecated.php +++ b/includes/functions-deprecated.php @@ -17,6 +17,24 @@ // @codeCoverageIgnoreStart +/** + * Plugin activation sandbox + * + * @since 1.8.3 + * @deprecated 1.9.1 + * @param string $pluginfile Plugin filename (full path) + * @return string|true string if error or true if success + */ +function yourls_activate_plugin_sandbox( $pluginfile ) { + yourls_deprecated_function( __FUNCTION__, '1.9.1', 'yourls_activate_file_sandbox'); + try { + include_once $pluginfile; + return true; + } catch ( \Throwable $e ) { + return $e->getMessage(); + } +} + /** * Return current admin page, or null if not an admin page. Was not used anywhere. * From 9c801209e137831d743f9bb090c0a62e8d1c2062 Mon Sep 17 00:00:00 2001 From: e-ht <1045813+e-ht@users.noreply.github> Date: Sat, 17 Dec 2022 22:05:49 -0800 Subject: [PATCH 4/9] add unit tests for yourls_activate_file_sandbox() --- .../tests/functions/activate_file_sandbox.php | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 tests/tests/functions/activate_file_sandbox.php diff --git a/tests/tests/functions/activate_file_sandbox.php b/tests/tests/functions/activate_file_sandbox.php new file mode 100644 index 000000000..9181968d6 --- /dev/null +++ b/tests/tests/functions/activate_file_sandbox.php @@ -0,0 +1,22 @@ +assertTrue( yourls_activate_file_sandbox( $file ) ); + unlink("$file"); + } else { + $this->markTestSkipped( "Cannot create test '$file"); + } + } + +} From 084ecc97bc748ebbca7b49c01bf514a8210fe181 Mon Sep 17 00:00:00 2001 From: e-ht <1045813+e-ht@users.noreply.github> Date: Thu, 5 Jan 2023 01:22:16 -0800 Subject: [PATCH 5/9] - added `is_readable()` to `yourls_activate_file_sandbox()` to ensure we get a true or catch - added checks for displaying errors where appropriate --- includes/Config/Init.php | 27 +++++++++++++++++------ includes/Database/YDB.php | 19 +++++++++++----- includes/functions-plugins.php | 14 +++++++----- includes/functions.php | 40 +++++++++++++++++++++------------- 4 files changed, 68 insertions(+), 32 deletions(-) diff --git a/includes/Config/Init.php b/includes/Config/Init.php index c6f41da90..9b8b95fc3 100644 --- a/includes/Config/Init.php +++ b/includes/Config/Init.php @@ -145,11 +145,19 @@ public function redirect_ssl_if_needed() { * @return void */ public function include_db_files() { - // Allow drop-in replacement for the DB engine - if (file_exists(YOURLS_USERDIR.'/db.php')) { - yourls_activate_file_sandbox( YOURLS_USERDIR.'/db.php' ); - } else { - require_once YOURLS_INC.'/class-mysql.php'; + // Attempt to open drop-in replacement for the DB engine else default to core engine + $file = YOURLS_USERDIR . '/db.php'; + $attempt = yourls_activate_file_sandbox( $file ); + + // Check if we have an error to display + if ( is_string( $attempt ) ) { + $message = yourls_s( 'Loading %s generated unexpected output. Error was:
%s
', $file, $attempt ); + yourls_add_notice( $message ); + } + + // Fallback to core DB engine + if ( $attempt !== true ) { + require_once YOURLS_INC . '/class-mysql.php'; yourls_db_connect(); } } @@ -159,8 +167,13 @@ public function include_db_files() { * @return void */ public function include_cache_files() { - if (file_exists(YOURLS_USERDIR.'/cache.php')) { - yourls_activate_file_sandbox( YOURLS_USERDIR.'/cache.php' ); + $file = YOURLS_USERDIR . '/cache.php'; + $attempt = yourls_activate_file_sandbox( $file ); + + // Check if we have an error to display + if ( is_string( $attempt ) ) { + $message = yourls_s( 'Loading %s generated unexpected output. Error was:
%s
', $file, $attempt ); + yourls_add_notice( $message ); } } diff --git a/includes/Database/YDB.php b/includes/Database/YDB.php index b734fe70b..4a4574e0b 100644 --- a/includes/Database/YDB.php +++ b/includes/Database/YDB.php @@ -157,15 +157,24 @@ public function connect_to_DB() { */ public function dead_or_error(\Exception $exception) { // Use any /user/db_error.php file - if( file_exists( YOURLS_USERDIR . '/db_error.php' ) ) { - yourls_activate_file_sandbox( YOURLS_USERDIR . '/db_error.php' ); + $file = YOURLS_USERDIR . '/db_error.php'; + $attempt = yourls_activate_file_sandbox( $file ); + + // Check if we have an error to display + if ( is_string( $attempt ) ) { + $message = yourls_s( 'Loading %s generated unexpected output. Error was:
%s
', $file, $attempt ); + yourls_die( yourls__( $message ), yourls__( 'Fatal error' ), 503 ); die(); } - $message = yourls__( 'Incorrect DB config, or could not connect to DB' ); - $message .= '
' . get_class($exception) .': ' . $exception->getMessage(); + if ( $attempt !== true ) { + $message = yourls__( 'Incorrect DB config, or could not connect to DB' ); + $message .= '
' . get_class($exception) .': ' . $exception->getMessage(); + + yourls_die( yourls__( $message ), yourls__( 'Fatal error' ), 503 ); + die(); + } - yourls_die( yourls__( $message ), yourls__( 'Fatal error' ), 503 ); die(); } diff --git a/includes/functions-plugins.php b/includes/functions-plugins.php index 67e1977ba..4ef8720a1 100644 --- a/includes/functions-plugins.php +++ b/includes/functions-plugins.php @@ -690,12 +690,16 @@ function yourls_deactivate_plugin( $plugin ) { // Check if we have an uninstall file - load if so $uninst_file = YOURLS_PLUGINDIR . '/' . dirname($plugin) . '/uninstall.php'; - if ( file_exists($uninst_file) ) { + $attempt = yourls_activate_file_sandbox( $uninst_file ); + + // Check if we have an error to display + if ( is_string( $attempt ) ) { + $message = yourls_s( 'Loading %s generated unexpected output. Error was:
%s
', $uninst_file, $attempt ); + return( $message ); + } + + if ( $attempt === true ) { define('YOURLS_UNINSTALL_PLUGIN', true); - $attempt = yourls_activate_file_sandbox( $uninst_file ); - if( $attempt !== true ) { - return yourls_s( 'Plugin generated unexpected output. Error was:
%s
', $attempt ); - } } // Deactivate the plugin diff --git a/includes/functions.php b/includes/functions.php index a19942ed2..799314b15 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -1065,30 +1065,38 @@ function yourls_fix_request_uri() { * @return void */ function yourls_check_maintenance_mode() { - $file = YOURLS_ABSPATH . '/.maintenance' ; + $dot_file = YOURLS_ABSPATH . '/.maintenance' ; - if ( !file_exists( $file ) || yourls_is_upgrading() || yourls_is_installing() ) { + if ( !file_exists( $dot_file ) || yourls_is_upgrading() || yourls_is_installing() ) { return; } global $maintenance_start; - yourls_activate_file_sandbox( $file ); + yourls_activate_file_sandbox( $dot_file ); // If the $maintenance_start timestamp is older than 10 minutes, don't die. if ( ( time() - $maintenance_start ) >= 600 ) { return; } // Use any /user/maintenance.php file - if( file_exists( YOURLS_USERDIR.'/maintenance.php' ) ) { - yourls_activate_file_sandbox( YOURLS_USERDIR.'/maintenance.php' ); - die(); - } + $file = YOURLS_USERDIR . '/maintenance.php'; + $attempt = yourls_activate_file_sandbox( $file ); + + // Check if we have an error to display + if ( is_string( $attempt ) ) { + $message = yourls_s( 'Loading %s generated unexpected output. Error was:
%s
', $file, $attempt ); + yourls_die( yourls__( $message ), yourls__( 'Fatal error' ), 503 ); + } - // Or use the default messages - $title = yourls__( 'Service temporarily unavailable' ); - $message = yourls__( 'Our service is currently undergoing scheduled maintenance.' ) . "

\n

" . - yourls__( 'Things should not last very long, thank you for your patience and please excuse the inconvenience' ); - yourls_die( $message, $title , 503 ); + if ( $attempt !== true ) { + // Or use the default messages + $title = yourls__('Service temporarily unavailable'); + $message = yourls__('Our service is currently undergoing scheduled maintenance.') . "

\n

" . + yourls__('Things should not last very long, thank you for your patience and please excuse the inconvenience'); + yourls_die( $message, $title, 503 ); + } + + die(); } /** @@ -1277,12 +1285,14 @@ function yourls_tell_if_new_version() { * * @since TODO * @param string $file filename (full path) - * @return string|true string if error or true if success + * @return string|bool string if error, true if success, false if no file exists */ function yourls_activate_file_sandbox( $file ) { try { - include_once $file; - return true; + if (is_readable( $file )) { + include_once $file; + return true; + } } catch ( \Throwable $e ) { return $e->getMessage(); } From e450881ef2fa1e9d96866326093c1b58858d3122 Mon Sep 17 00:00:00 2001 From: e-ht <1045813+e-ht@users.noreply.github.com> Date: Thu, 5 Jan 2023 11:23:41 -0800 Subject: [PATCH 6/9] update function description ...to remove return type typo --- includes/functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/functions.php b/includes/functions.php index 799314b15..79c25184a 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -1285,7 +1285,7 @@ function yourls_tell_if_new_version() { * * @since TODO * @param string $file filename (full path) - * @return string|bool string if error, true if success, false if no file exists + * @return string|bool string if error, true if success */ function yourls_activate_file_sandbox( $file ) { try { From c7dc42dfc834ee4177763a33e1d46c9dc3013639 Mon Sep 17 00:00:00 2001 From: Ozh Date: Sun, 12 Feb 2023 11:54:54 +0100 Subject: [PATCH 7/9] Tweaks - rename sandbox function - move tests - fix deprecated function --- includes/Config/Init.php | 4 ++-- includes/Database/YDB.php | 2 +- includes/functions-deprecated.php | 11 +++-------- includes/functions-html.php | 2 +- includes/functions-plugins.php | 6 +++--- includes/functions.php | 12 +++++++----- .../include_file_sandbox.php} | 11 +++++++++-- 7 files changed, 26 insertions(+), 22 deletions(-) rename tests/tests/{functions/activate_file_sandbox.php => utilities/include_file_sandbox.php} (55%) diff --git a/includes/Config/Init.php b/includes/Config/Init.php index 9b8b95fc3..f46345f9d 100644 --- a/includes/Config/Init.php +++ b/includes/Config/Init.php @@ -147,7 +147,7 @@ public function redirect_ssl_if_needed() { public function include_db_files() { // Attempt to open drop-in replacement for the DB engine else default to core engine $file = YOURLS_USERDIR . '/db.php'; - $attempt = yourls_activate_file_sandbox( $file ); + $attempt = yourls_include_file_sandbox( $file ); // Check if we have an error to display if ( is_string( $attempt ) ) { @@ -168,7 +168,7 @@ public function include_db_files() { */ public function include_cache_files() { $file = YOURLS_USERDIR . '/cache.php'; - $attempt = yourls_activate_file_sandbox( $file ); + $attempt = yourls_include_file_sandbox( $file ); // Check if we have an error to display if ( is_string( $attempt ) ) { diff --git a/includes/Database/YDB.php b/includes/Database/YDB.php index 4a4574e0b..c2edbb86d 100644 --- a/includes/Database/YDB.php +++ b/includes/Database/YDB.php @@ -158,7 +158,7 @@ public function connect_to_DB() { public function dead_or_error(\Exception $exception) { // Use any /user/db_error.php file $file = YOURLS_USERDIR . '/db_error.php'; - $attempt = yourls_activate_file_sandbox( $file ); + $attempt = yourls_include_file_sandbox( $file ); // Check if we have an error to display if ( is_string( $attempt ) ) { diff --git a/includes/functions-deprecated.php b/includes/functions-deprecated.php index 76fa6c941..3154c174f 100644 --- a/includes/functions-deprecated.php +++ b/includes/functions-deprecated.php @@ -21,18 +21,13 @@ * Plugin activation sandbox * * @since 1.8.3 - * @deprecated 1.9.1 + * @deprecated 1.9.2 * @param string $pluginfile Plugin filename (full path) * @return string|true string if error or true if success */ function yourls_activate_plugin_sandbox( $pluginfile ) { - yourls_deprecated_function( __FUNCTION__, '1.9.1', 'yourls_activate_file_sandbox'); - try { - include_once $pluginfile; - return true; - } catch ( \Throwable $e ) { - return $e->getMessage(); - } + yourls_deprecated_function( __FUNCTION__, '1.9.1', 'yourls_include_file_sandbox'); + return yourls_include_file_sandbox($pluginfile); } /** diff --git a/includes/functions-html.php b/includes/functions-html.php index 2d92cd302..f37cf9381 100644 --- a/includes/functions-html.php +++ b/includes/functions-html.php @@ -906,7 +906,7 @@ function yourls_page( $page ) { } yourls_do_action( 'pre_page', $page ); - yourls_activate_file_sandbox( YOURLS_PAGEDIR . "/$page.php" ); + yourls_include_file_sandbox( YOURLS_PAGEDIR . "/$page.php" ); yourls_do_action( 'post_page', $page ); } diff --git a/includes/functions-plugins.php b/includes/functions-plugins.php index 4ef8720a1..5bf35613d 100644 --- a/includes/functions-plugins.php +++ b/includes/functions-plugins.php @@ -595,7 +595,7 @@ function yourls_load_plugins() { $plugins = []; foreach ( $active_plugins as $key => $plugin ) { $file = YOURLS_PLUGINDIR . '/' . $plugin; - if ( yourls_is_a_plugin_file($file) && yourls_activate_file_sandbox( $file ) === true ) { + if ( yourls_is_a_plugin_file($file) && yourls_include_file_sandbox( $file ) === true ) { $plugins[] = $plugin; unset( $active_plugins[ $key ] ); } @@ -659,7 +659,7 @@ function yourls_activate_plugin( $plugin ) { } // attempt activation. - $attempt = yourls_activate_file_sandbox( $plugindir.'/'.$plugin ); + $attempt = yourls_include_file_sandbox( $plugindir.'/'.$plugin ); if( $attempt !== true ) { return yourls_s( 'Plugin generated unexpected output. Error was:

%s
', $attempt ); } @@ -690,7 +690,7 @@ function yourls_deactivate_plugin( $plugin ) { // Check if we have an uninstall file - load if so $uninst_file = YOURLS_PLUGINDIR . '/' . dirname($plugin) . '/uninstall.php'; - $attempt = yourls_activate_file_sandbox( $uninst_file ); + $attempt = yourls_include_file_sandbox( $uninst_file ); // Check if we have an error to display if ( is_string( $attempt ) ) { diff --git a/includes/functions.php b/includes/functions.php index 79c25184a..575e3b0ca 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -1072,7 +1072,7 @@ function yourls_check_maintenance_mode() { } global $maintenance_start; - yourls_activate_file_sandbox( $dot_file ); + yourls_include_file_sandbox( $dot_file ); // If the $maintenance_start timestamp is older than 10 minutes, don't die. if ( ( time() - $maintenance_start ) >= 600 ) { return; @@ -1080,7 +1080,7 @@ function yourls_check_maintenance_mode() { // Use any /user/maintenance.php file $file = YOURLS_USERDIR . '/maintenance.php'; - $attempt = yourls_activate_file_sandbox( $file ); + $attempt = yourls_include_file_sandbox( $file ); // Check if we have an error to display if ( is_string( $attempt ) ) { @@ -1281,13 +1281,15 @@ function yourls_tell_if_new_version() { } /** - * File activation sandbox + * File include sandbox * - * @since TODO + * Attempt to include a PHP file, fail with an error message if the file isn't valid PHP code + * + * @since 1.9.2 * @param string $file filename (full path) * @return string|bool string if error, true if success */ -function yourls_activate_file_sandbox( $file ) { +function yourls_include_file_sandbox($file) { try { if (is_readable( $file )) { include_once $file; diff --git a/tests/tests/functions/activate_file_sandbox.php b/tests/tests/utilities/include_file_sandbox.php similarity index 55% rename from tests/tests/functions/activate_file_sandbox.php rename to tests/tests/utilities/include_file_sandbox.php index 9181968d6..c6c953297 100644 --- a/tests/tests/functions/activate_file_sandbox.php +++ b/tests/tests/utilities/include_file_sandbox.php @@ -9,14 +9,21 @@ class FileLoader_Test extends PHPUnit\Framework\TestCase { + /** + * Load empty file + */ public function test_load_file() { - $file = YOURLS_USERDIR . "/" . rand_str() . ".php"; + $file = YOURLS_TESTDATA_DIR . "/" . rand_str() . ".php"; if( touch("$file") ) { - $this->assertTrue( yourls_activate_file_sandbox( $file ) ); + $this->assertTrue( yourls_include_file_sandbox( $file ) ); unlink("$file"); } else { $this->markTestSkipped( "Cannot create test '$file"); } } + /** + * For tests to load valid and broken PHP code: see in tests/plugins/files.php + */ + } From 4bdce03bf162e4a59e080d80bd5ab00894cfca0c Mon Sep 17 00:00:00 2001 From: Ozh Date: Sun, 12 Feb 2023 13:25:52 +0100 Subject: [PATCH 8/9] Tweaks : - do not try to include a file if it doesn't exist - do not introduce new untranslated strings - do not expose sensitive info (path) on public pages when loading custom DB, cache or maintenance file - log loaded files - tweak yourls_debug_log to allow early uses --- includes/Config/Init.php | 26 +++++++++------- includes/Database/YDB.php | 23 +++++--------- includes/functions-debug.php | 7 +++-- includes/functions-html.php | 5 ++- includes/functions.php | 31 +++++++++---------- tests/tests/plugins/files.php | 2 +- .../tests/utilities/include_file_sandbox.php | 11 +++++-- 7 files changed, 55 insertions(+), 50 deletions(-) diff --git a/includes/Config/Init.php b/includes/Config/Init.php index f46345f9d..84b0da496 100644 --- a/includes/Config/Init.php +++ b/includes/Config/Init.php @@ -147,12 +147,13 @@ public function redirect_ssl_if_needed() { public function include_db_files() { // Attempt to open drop-in replacement for the DB engine else default to core engine $file = YOURLS_USERDIR . '/db.php'; - $attempt = yourls_include_file_sandbox( $file ); - - // Check if we have an error to display - if ( is_string( $attempt ) ) { - $message = yourls_s( 'Loading %s generated unexpected output. Error was:
%s
', $file, $attempt ); - yourls_add_notice( $message ); + $attempt = false; + if(file_exists($file)) { + $attempt = yourls_include_file_sandbox( $file ); + // Check if we have an error to display + if ( is_string( $attempt ) ) { + yourls_add_notice( $attempt ); + } } // Fallback to core DB engine @@ -168,12 +169,13 @@ public function include_db_files() { */ public function include_cache_files() { $file = YOURLS_USERDIR . '/cache.php'; - $attempt = yourls_include_file_sandbox( $file ); - - // Check if we have an error to display - if ( is_string( $attempt ) ) { - $message = yourls_s( 'Loading %s generated unexpected output. Error was:
%s
', $file, $attempt ); - yourls_add_notice( $message ); + $attempt = false; + if(file_exists($file)) { + $attempt = yourls_include_file_sandbox($file); + // Check if we have an error to display + if (is_string($attempt)) { + yourls_add_notice($attempt); + } } } diff --git a/includes/Database/YDB.php b/includes/Database/YDB.php index c2edbb86d..f13e145d1 100644 --- a/includes/Database/YDB.php +++ b/includes/Database/YDB.php @@ -158,24 +158,17 @@ public function connect_to_DB() { public function dead_or_error(\Exception $exception) { // Use any /user/db_error.php file $file = YOURLS_USERDIR . '/db_error.php'; - $attempt = yourls_include_file_sandbox( $file ); - - // Check if we have an error to display - if ( is_string( $attempt ) ) { - $message = yourls_s( 'Loading %s generated unexpected output. Error was:
%s
', $file, $attempt ); - yourls_die( yourls__( $message ), yourls__( 'Fatal error' ), 503 ); - die(); - } - - if ( $attempt !== true ) { - $message = yourls__( 'Incorrect DB config, or could not connect to DB' ); - $message .= '
' . get_class($exception) .': ' . $exception->getMessage(); - - yourls_die( yourls__( $message ), yourls__( 'Fatal error' ), 503 ); - die(); + if(file_exists($file)) { + if(yourls_include_file_sandbox( $file ) === true) { + die(); + } } + $message = yourls__( 'Incorrect DB config, or could not connect to DB' ); + $message .= '
' . get_class($exception) .': ' . $exception->getMessage(); + yourls_die( yourls__( $message ), yourls__( 'Fatal error' ), 503 ); die(); + } /** diff --git a/includes/functions-debug.php b/includes/functions-debug.php index 1aeee6588..4e5a5572b 100644 --- a/includes/functions-debug.php +++ b/includes/functions-debug.php @@ -7,7 +7,7 @@ * Add a message to the debug log * * When in debug mode ( YOURLS_DEBUG == true ) the debug log is echoed in yourls_html_footer() - * Log messages are appended to $ydb->debug_log array, which is instanciated within class ezSQLcore_YOURLS + * Log messages are appended to $ydb->debug_log array, which is instanciated within class Database\YDB * * @since 1.7 * @param string $msg Message to add to the debug log @@ -17,7 +17,10 @@ function yourls_debug_log( $msg ) { yourls_do_action( 'debug_log', $msg ); // Get the DB object ($ydb), get its profiler (\Aura\Sql\Profiler\Profiler), its logger (\Aura\Sql\Profiler\MemoryLogger) and // pass it a unused argument (loglevel) and the message - yourls_get_db()->getProfiler()->getLogger()->log( 'debug', $msg); + // Check if function exists to allow usage of the function in very early stages + if(function_exists('yourls_debug_log')) { + yourls_get_db()->getProfiler()->getLogger()->log( 'debug', $msg); + } return $msg; } diff --git a/includes/functions-html.php b/includes/functions-html.php index f37cf9381..5f37305fd 100644 --- a/includes/functions-html.php +++ b/includes/functions-html.php @@ -906,7 +906,10 @@ function yourls_page( $page ) { } yourls_do_action( 'pre_page', $page ); - yourls_include_file_sandbox( YOURLS_PAGEDIR . "/$page.php" ); + $load = yourls_include_file_sandbox(YOURLS_PAGEDIR . "/$page.php"); + if (is_string($load)) { + yourls_die( $load, yourls__('Not found'), 404 ); + } yourls_do_action( 'post_page', $page ); } diff --git a/includes/functions.php b/includes/functions.php index 575e3b0ca..acf3fbfe7 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -1080,23 +1080,17 @@ function yourls_check_maintenance_mode() { // Use any /user/maintenance.php file $file = YOURLS_USERDIR . '/maintenance.php'; - $attempt = yourls_include_file_sandbox( $file ); - - // Check if we have an error to display - if ( is_string( $attempt ) ) { - $message = yourls_s( 'Loading %s generated unexpected output. Error was:
%s
', $file, $attempt ); - yourls_die( yourls__( $message ), yourls__( 'Fatal error' ), 503 ); - } - - if ( $attempt !== true ) { - // Or use the default messages - $title = yourls__('Service temporarily unavailable'); - $message = yourls__('Our service is currently undergoing scheduled maintenance.') . "

\n

" . - yourls__('Things should not last very long, thank you for your patience and please excuse the inconvenience'); - yourls_die( $message, $title, 503 ); + if(file_exists($file)) { + if(yourls_include_file_sandbox( $file ) == true) { + die(); + } } - die(); + // Or use the default messages + $title = yourls__('Service temporarily unavailable'); + $message = yourls__('Our service is currently undergoing scheduled maintenance.') . "

\n

" . + yourls__('Things should not last very long, thank you for your patience and please excuse the inconvenience'); + yourls_die( $message, $title, 503 ); } /** @@ -1283,7 +1277,8 @@ function yourls_tell_if_new_version() { /** * File include sandbox * - * Attempt to include a PHP file, fail with an error message if the file isn't valid PHP code + * Attempt to include a PHP file, fail with an error message if the file isn't valid PHP code. + * This function does not check first if the file exists : depending on use case, you may check first. * * @since 1.9.2 * @param string $file filename (full path) @@ -1293,9 +1288,11 @@ function yourls_include_file_sandbox($file) { try { if (is_readable( $file )) { include_once $file; + yourls_debug_log("loaded $file"); return true; } } catch ( \Throwable $e ) { - return $e->getMessage(); + yourls_debug_log("could not load $file"); + return sprintf("%s (%s : %s)", $e->getMessage() , $e->getFile() , $e->getLine() ); } } diff --git a/tests/tests/plugins/files.php b/tests/tests/plugins/files.php index d029a03c0..632df5553 100644 --- a/tests/tests/plugins/files.php +++ b/tests/tests/plugins/files.php @@ -193,7 +193,7 @@ public function test_invalid_plugin_deactivate() { * @dataProvider get_invalid_code_plugins */ public function test_invalid_plugin_does_not_activate($plugin) { - $this->assertNotTrue( yourls_activate_file_sandbox( $plugin ) ); + $this->assertNotTrue( yourls_include_file_sandbox( $plugin ) ); $this->assertNotTrue( yourls_activate_plugin( $plugin ) ); $this->assertNotTrue( yourls_is_active_plugin( $plugin ) ); } diff --git a/tests/tests/utilities/include_file_sandbox.php b/tests/tests/utilities/include_file_sandbox.php index c6c953297..f4e9c2749 100644 --- a/tests/tests/utilities/include_file_sandbox.php +++ b/tests/tests/utilities/include_file_sandbox.php @@ -10,9 +10,9 @@ class FileLoader_Test extends PHPUnit\Framework\TestCase { /** - * Load empty file + * Load valid file = true */ - public function test_load_file() { + public function test_load_file_exists() { $file = YOURLS_TESTDATA_DIR . "/" . rand_str() . ".php"; if( touch("$file") ) { $this->assertTrue( yourls_include_file_sandbox( $file ) ); @@ -22,6 +22,13 @@ public function test_load_file() { } } + /** + * Load missing file = string + */ + public function test_load_file_exists() { + $this->assertIsString( yourls_include_file_sandbox( YOURLS_TESTDATA_DIR . "/" . rand_str() . ".php" ) ); + } + /** * For tests to load valid and broken PHP code: see in tests/plugins/files.php */ From 92b65d3dc598d87845d8b3fb6b7e820d2df73d71 Mon Sep 17 00:00:00 2001 From: Ozh Date: Sun, 12 Feb 2023 13:27:48 +0100 Subject: [PATCH 9/9] Bleh, wrong test name --- tests/tests/utilities/include_file_sandbox.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tests/utilities/include_file_sandbox.php b/tests/tests/utilities/include_file_sandbox.php index f4e9c2749..09e0ab33e 100644 --- a/tests/tests/utilities/include_file_sandbox.php +++ b/tests/tests/utilities/include_file_sandbox.php @@ -25,7 +25,7 @@ public function test_load_file_exists() { /** * Load missing file = string */ - public function test_load_file_exists() { + public function test_load_file_not_exists() { $this->assertIsString( yourls_include_file_sandbox( YOURLS_TESTDATA_DIR . "/" . rand_str() . ".php" ) ); }