diff --git a/dir2cast.php b/dir2cast.php index 4ff8af7..e2f298c 100644 --- a/dir2cast.php +++ b/dir2cast.php @@ -617,7 +617,7 @@ protected function stripBasePath($filename) { if(strlen(RSS_File_Item::$FILES_DIR) && strpos($filename, RSS_File_Item::$FILES_DIR) === 0) { - return ltrim(substr($filename, strlen(RSS_File_Item::$FILES_DIR)), '/'); + $filename = ltrim(substr($filename, strlen(RSS_File_Item::$FILES_DIR)), '/'); } return $filename; } @@ -1583,7 +1583,7 @@ public static function display($message, $errfile, $errline) { if(self::$errors) { - if(!defined('CLI_ONLY') || !CLI_ONLY) + if(!defined('CLI_ONLY')) { if(!http_response_code()) { @@ -1591,12 +1591,12 @@ public static function display($message, $errfile, $errline) } } - if((!defined('CLI_ONLY') || !CLI_ONLY) && !ini_get('html_errors')) + if((!defined('CLI_ONLY')) && !ini_get('html_errors')) { header("Content-type: text/plain"); // reset the content-type } - if((!defined('CLI_ONLY') || !CLI_ONLY ) && ini_get('html_errors')) + if((!defined('CLI_ONLY')) && ini_get('html_errors')) { header("Content-type: text/html"); // reset the content-type @@ -1650,7 +1650,7 @@ public static function display($message, $errfile, $errline) public static function display404($message) { - if(defined('CLI_ONLY') && CLI_ONLY) + if(defined('CLI_ONLY')) { http_response_code(404); header("Content-type: text/plain"); @@ -1692,18 +1692,18 @@ public static function bootstrap(array $SERVER, array $GET, array $argv) define('CLI_ONLY', true); } - if(defined('CLI_ONLY') && CLI_ONLY) { - define('DIR2CAST_BASE', realpath(dirname($argv[0]))); + if(defined('CLI_ONLY')) { + define('DIR2CAST_BASE', slashdir(realpath(dirname($argv[0])))); } else { - define('DIR2CAST_BASE', dirname(__FILE__)); + define('DIR2CAST_BASE', slashdir(dirname(__FILE__))); } // If an installation-wide config file exists, load it now. // Installation-wide config can contain TMP_DIR, MP3_DIR and MIN_CACHE_TIME. // Anything else it contains will be used as a fall-back if no dir-specific dir2cast.ini exists - if(file_exists( DIR2CAST_BASE . '/dir2cast.ini' )) + if(file_exists( DIR2CAST_BASE . 'dir2cast.ini' )) { - $ini_file_name = DIR2CAST_BASE . '/dir2cast.ini'; + $ini_file_name = DIR2CAST_BASE . 'dir2cast.ini'; self::load_from_ini( $ini_file_name ); self::finalize(array('TMP_DIR', 'MP3_BASE', 'MP3_DIR', 'MIN_CACHE_TIME', 'FORCE_PASSWORD')); define('INI_FILE', $ini_file_name); @@ -1725,11 +1725,12 @@ public static function bootstrap(array $SERVER, array $GET, array $argv) } if(!defined('MP3_DIR') && !empty($cli_options['media-dir'])) { - define('MP3_DIR', realpath($cli_options['media-dir'])); - if(!is_dir(MP3_DIR) or !is_readable(MP3_DIR)) + + if(!is_dir($cli_options['media-dir']) or !is_readable($cli_options['media-dir'])) { ErrorHandler::display404($cli_options['media-dir']); } + define('MP3_DIR', slashdir(realpath($cli_options['media-dir']))); } if(!defined('MP3_URL') && !empty($cli_options['media-url'])) { @@ -1768,13 +1769,13 @@ public static function bootstrap(array $SERVER, array $GET, array $argv) define('FORCE_PASSWORD', ''); if(!defined('TMP_DIR')) { - define('TMP_DIR', DIR2CAST_BASE . '/temp'); + define('TMP_DIR', DIR2CAST_BASE . 'temp'); } if(!defined('MP3_BASE')) { if(!empty($SERVER['HTTP_HOST'])) - define('MP3_BASE', dirname($SERVER['SCRIPT_FILENAME'])); + define('MP3_BASE', slashdir(dirname($SERVER['SCRIPT_FILENAME']))); else define('MP3_BASE', DIR2CAST_BASE); } @@ -1783,14 +1784,14 @@ public static function bootstrap(array $SERVER, array $GET, array $argv) { if(!empty($GET['dir'])) { - define('MP3_DIR', MP3_BASE . '/' . safe_path(magic_stripslashes($GET['dir']))); + define('MP3_DIR', slashdir(slashdir(MP3_BASE) . safe_path(magic_stripslashes($GET['dir'])))); if(!is_dir(MP3_DIR) or !is_readable(MP3_DIR)) { ErrorHandler::display404($GET['dir']); } } else - define('MP3_DIR', MP3_BASE); + define('MP3_DIR', slashdir(MP3_BASE)); } } @@ -1801,15 +1802,14 @@ public static function defaults(array $SERVER) { // if an MP3_DIR specific config file exists, load it now, as long as it's not the same file as the global one! if( - file_exists( MP3_DIR . '/dir2cast.ini' ) and - realpath(DIR2CAST_BASE . '/dir2cast.ini') != realpath( MP3_DIR . '/dir2cast.ini' ) + file_exists( MP3_DIR . 'dir2cast.ini' ) and + realpath(DIR2CAST_BASE . 'dir2cast.ini') != realpath( MP3_DIR . 'dir2cast.ini' ) ) { - self::load_from_ini( MP3_DIR . '/dir2cast.ini' ); + self::load_from_ini( MP3_DIR . 'dir2cast.ini' ); } self::finalize(); - if(!defined('MP3_URL')) { # This works on the principle that MP3_DIR must be under DOCUMENT_ROOT (otherwise how will you serve the MP3s?) @@ -1818,9 +1818,9 @@ public static function defaults(array $SERVER) if(!empty($SERVER['HTTP_HOST'])) { - $path_part = substr(MP3_DIR, strlen($SERVER['DOCUMENT_ROOT'])); + $path_part = substr(slashdir(MP3_DIR), strlen(slashdir($SERVER['DOCUMENT_ROOT']))); define('MP3_URL', - 'http' . (!empty($SERVER['HTTPS']) ? 's' : '') . '://' . $SERVER['HTTP_HOST'] . '/' . ltrim( rtrim( $path_part, '/' ) . '/', '/' )); + 'http' . (!empty($SERVER['HTTPS']) ? 's' : '') . '://' . $SERVER['HTTP_HOST'] . '/' . ltrim( slashdir( $path_part ), '/' )); } else define('MP3_URL', 'file://' . MP3_DIR ); @@ -1852,10 +1852,10 @@ public static function defaults(array $SERVER) if(!defined('DESCRIPTION')) { - if(file_exists(MP3_DIR . '/description.txt')) - define('DESCRIPTION', file_get_contents(MP3_DIR . '/description.txt')); - elseif(file_exists(DIR2CAST_BASE . '/description.txt')) - define('DESCRIPTION', file_get_contents(DIR2CAST_BASE . '/description.txt')); + if(file_exists(MP3_DIR . 'description.txt')) + define('DESCRIPTION', file_get_contents(MP3_DIR . 'description.txt')); + elseif(file_exists(DIR2CAST_BASE . 'description.txt')) + define('DESCRIPTION', file_get_contents(DIR2CAST_BASE . 'description.txt')); else define('DESCRIPTION', 'Podcast'); } @@ -1877,20 +1877,20 @@ public static function defaults(array $SERVER) if(!defined('ITUNES_SUBTITLE')) { - if(file_exists(MP3_DIR . '/itunes_subtitle.txt')) - define('ITUNES_SUBTITLE', file_get_contents(MP3_DIR . '/itunes_subtitle.txt')); - elseif(file_exists(DIR2CAST_BASE . '/itunes_subtitle.txt')) - define('ITUNES_SUBTITLE', file_get_contents(DIR2CAST_BASE . '/itunes_subtitle.txt')); + if(file_exists(MP3_DIR . 'itunes_subtitle.txt')) + define('ITUNES_SUBTITLE', file_get_contents(MP3_DIR . 'itunes_subtitle.txt')); + elseif(file_exists(DIR2CAST_BASE . 'itunes_subtitle.txt')) + define('ITUNES_SUBTITLE', file_get_contents(DIR2CAST_BASE . 'itunes_subtitle.txt')); else define('ITUNES_SUBTITLE', DESCRIPTION); } if(!defined('ITUNES_SUMMARY')) { - if(file_exists(MP3_DIR . '/itunes_summary.txt')) - define('ITUNES_SUMMARY', file_get_contents(MP3_DIR . '/itunes_summary.txt')); - elseif(file_exists(DIR2CAST_BASE . '/itunes_summary.txt')) - define('ITUNES_SUMMARY', file_get_contents(DIR2CAST_BASE . '/itunes_summary.txt')); + if(file_exists(MP3_DIR . 'itunes_summary.txt')) + define('ITUNES_SUMMARY', file_get_contents(MP3_DIR . 'itunes_summary.txt')); + elseif(file_exists(DIR2CAST_BASE . 'itunes_summary.txt')) + define('ITUNES_SUMMARY', file_get_contents(DIR2CAST_BASE . 'itunes_summary.txt')); else define('ITUNES_SUMMARY', DESCRIPTION); } @@ -1901,9 +1901,9 @@ public static function defaults(array $SERVER) define('IMAGE', rtrim(MP3_URL, '/') . '/image.jpg'); elseif(file_exists(rtrim(MP3_DIR, '/') . '/image.png')) define('IMAGE', rtrim(MP3_URL, '/') . '/image.png'); - elseif(file_exists(DIR2CAST_BASE . '/image.jpg')) + elseif(file_exists(DIR2CAST_BASE . 'image.jpg')) define('IMAGE', rtrim(MP3_URL, '/') . '/image.jpg'); - elseif(file_exists(DIR2CAST_BASE . '/image.png')) + elseif(file_exists(DIR2CAST_BASE . 'image.png')) define('IMAGE', rtrim(MP3_URL, '/') . '/image.png'); else define('IMAGE', ''); @@ -1915,9 +1915,9 @@ public static function defaults(array $SERVER) define('ITUNES_IMAGE', rtrim(MP3_URL, '/') . '/itunes_image.jpg'); elseif(file_exists(rtrim(MP3_DIR, '/') . '/itunes_image.png')) define('ITUNES_IMAGE', rtrim(MP3_URL, '/') . '/itunes_image.png'); - elseif(file_exists(DIR2CAST_BASE . '/itunes_image.jpg')) + elseif(file_exists(DIR2CAST_BASE . 'itunes_image.jpg')) define('ITUNES_IMAGE', rtrim(MP3_URL, '/') . '/itunes_image.jpg'); - elseif(file_exists(DIR2CAST_BASE . '/itunes_image.png')) + elseif(file_exists(DIR2CAST_BASE . 'itunes_image.png')) define('ITUNES_IMAGE', rtrim(MP3_URL, '/') . '/itunes_image.png'); else define('ITUNES_IMAGE', ''); @@ -1974,7 +1974,7 @@ public static function defaults(array $SERVER) define('CLOCK_OFFSET', 0); // Set up factory settings for Podcast subclasses - Dir_Podcast::$EMPTY_PODCAST_IS_ERROR = !defined('CLI_ONLY') || !CLI_ONLY; + Dir_Podcast::$EMPTY_PODCAST_IS_ERROR = !defined('CLI_ONLY'); Dir_Podcast::$RECURSIVE_DIRECTORY_ITERATOR = RECURSIVE_DIRECTORY_ITERATOR; Dir_Podcast::$ITEM_COUNT = ITEM_COUNT; Dir_Podcast::$MIN_FILE_AGE = MIN_FILE_AGE; @@ -2070,7 +2070,7 @@ public function update_mtime_if_metadata_files_modified() $filepath = rtrim(MP3_DIR, '/') . '/' . $file; if(!file_exists($filepath)) { - $filepath = DIR2CAST_BASE . '/' . $file; + $filepath = DIR2CAST_BASE . $file; } if(!file_exists($filepath)) { @@ -2125,7 +2125,7 @@ public function output() if(!defined('OUTPUT_FILE')) { $output = $podcast->generate(); - if(!defined('CLI_ONLY') || !CLI_ONLY) + if(!defined('CLI_ONLY')) { $podcast->http_headers(strlen($output)); } @@ -2195,6 +2195,11 @@ function utf8_for_xml($s) return preg_replace('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', '', $s); } +function slashdir($dir) +{ + return rtrim($dir, '/') . '/'; +} + /* DISPATCH *********************************************/ function main($args) diff --git a/docker-compose/nginx/default.conf b/docker-compose/nginx/default.conf index a918f54..f2ab099 100644 --- a/docker-compose/nginx/default.conf +++ b/docker-compose/nginx/default.conf @@ -8,7 +8,7 @@ server { # Don't allow downloading of dir2cast.ini, as it may contain sensitive # info such as the refresh password. Also, don't allow downloading of # dir2cast.php, for security and privacy reasons. - location ~ /dir2cast\.(ini|php)$ { + location ~ \.(ini|php)$ { return 404; } diff --git a/test/FourOhFourTest.php b/test/FourOhFourTest.php index 6b36221..3f2214d 100644 --- a/test/FourOhFourTest.php +++ b/test/FourOhFourTest.php @@ -11,8 +11,8 @@ public static function setUpBeforeClass(): void public function test_non_existent_dir_prints_bare_error_CLI_case(): void { - exec('php dir2cast.php --output=out.xml --media-dir=imaginary-dir', $output, $returncode); - $this->assertEquals("Not Found: imaginary-dir", implode("\n", $output)); + exec('php dir2cast.php --media-dir=dir2cast.ini', $output, $returncode); + $this->assertEquals("Not Found: dir2cast.ini", implode("\n", $output)); $this->assertEquals(254, $returncode); // 254 is -2 } diff --git a/test/SettingsHandlerTest.php b/test/SettingsHandlerTest.php index 51da4e1..401f1d1 100644 --- a/test/SettingsHandlerTest.php +++ b/test/SettingsHandlerTest.php @@ -137,7 +137,7 @@ public function test_default_defines_set() // should not be defined as $argv was empty $this->assertFalse(defined('CLI_ONLY')); - $this->assertEquals(DIR2CAST_BASE, realpath('..')); // from bootstrap.php + $this->assertEquals(DIR2CAST_BASE, slashdir(realpath('..'))); // from bootstrap.php } /** @@ -172,7 +172,7 @@ public function test_defines_CLI_ONLY_if_argv0() $this->assertFalse(defined('CLI_ONLY')); SettingsHandler::bootstrap(array(), array(), array('dir2cast.php')); $this->assertTrue(defined('CLI_ONLY')); - $this->assertEquals(DIR2CAST_BASE, getcwd()); // from fake $argv + $this->assertEquals(DIR2CAST_BASE, slashdir(getcwd())); // from fake $argv } /** @@ -187,7 +187,7 @@ public function test_bootstrap_sets_sensible_global_defaults_for_entire_installa SettingsHandler::bootstrap(array(), array(), array($argv0, $argv1)); $this->assertEquals(MIN_CACHE_TIME, 5); $this->assertEquals(FORCE_PASSWORD, ''); - $this->assertEquals(TMP_DIR, DIR2CAST_BASE . '/temp'); + $this->assertEquals(TMP_DIR, DIR2CAST_BASE . 'temp'); $this->assertEquals(MP3_BASE, DIR2CAST_BASE); $this->assertEquals(MP3_DIR, DIR2CAST_BASE); } @@ -207,8 +207,8 @@ public function test_when_SERVER_HTTP_HOST_then_MP3_BASE_defaults_to_same_dir() /* $GET */ array(), /* $argv */ array() ); - $this->assertEquals(MP3_BASE, '/var/www'); - $this->assertEquals(MP3_DIR, '/var/www'); + $this->assertEquals(MP3_BASE, '/var/www/'); + $this->assertEquals(MP3_DIR, '/var/www/'); } /** @@ -322,8 +322,8 @@ public function test_cli_media_dir_a_ok() mkdir($this->temp_file); SettingsHandler::bootstrap(array(), array(), array("dir2cast.php", "--media-dir={$this->temp_file}")); - $this->assertEquals(MP3_BASE, realpath('.')); - $this->assertEquals(MP3_DIR, realpath($this->temp_file)); + $this->assertEquals(MP3_BASE, slashdir(realpath('.'))); + $this->assertEquals(MP3_DIR, slashdir(realpath($this->temp_file))); $this->assertFalse(http_response_code()); } @@ -338,8 +338,8 @@ public function test_GET_media_dir_a_ok() mkdir('../' . $this->temp_file); SettingsHandler::bootstrap(array(), array("dir" => $this->temp_file), array()); - $this->assertEquals(MP3_BASE, realpath('..')); // due to bootstrap.php chdir - $this->assertEquals(MP3_DIR, realpath('../' . $this->temp_file)); + $this->assertEquals(MP3_BASE, slashdir(realpath('..'))); // due to bootstrap.php chdir + $this->assertEquals(MP3_DIR, slashdir(realpath('../' . $this->temp_file))); $this->assertFalse(http_response_code()); } @@ -355,8 +355,8 @@ public function test_GET_media_dir_safe_dot_dot_1() chdir('deep/root'); SettingsHandler::bootstrap(array(), array("dir" => ".."), array()); - $this->assertEquals(MP3_BASE, realpath("{$this->starting_dir}/..")); // due to bootstrap.php chdir - $this->assertEquals(slashdir(MP3_DIR), slashdir(MP3_BASE)); + $this->assertEquals(MP3_BASE, slashdir(realpath("{$this->starting_dir}/.."))); // due to bootstrap.php chdir + $this->assertEquals(MP3_DIR, slashdir(MP3_BASE)); $this->assertFalse(http_response_code()); } @@ -372,8 +372,8 @@ public function test_GET_media_dir_safe_dot_dot_2() chdir('deep/root'); SettingsHandler::bootstrap(array(), array("dir" => "../../.."), array()); - $this->assertEquals(MP3_BASE, realpath("{$this->starting_dir}/..")); // due to bootstrap.php chdir - $this->assertEquals(slashdir(MP3_DIR), slashdir(MP3_BASE)); + $this->assertEquals(MP3_BASE, slashdir(realpath("{$this->starting_dir}/.."))); // due to bootstrap.php chdir + $this->assertEquals(MP3_DIR, slashdir(MP3_BASE)); $this->assertFalse(http_response_code()); } @@ -425,7 +425,7 @@ public function test_GET_media_dir_safe_dir_with_good_base() SettingsHandler::bootstrap(array(), array("dir" => "root"), array()); $this->assertEquals(MP3_BASE, realpath("..")); - $this->assertEquals(MP3_DIR, realpath('.')); + $this->assertEquals(MP3_DIR, realpath('.') . '/'); $this->assertFalse(http_response_code()); } @@ -528,7 +528,7 @@ public function test_CLI_ONLY_sensible_defaults() SettingsHandler::bootstrap(array(), array(), array('dir2cast.php')); SettingsHandler::defaults(array()); - $this->assertEquals(MP3_URL, 'file://' . getcwd()); + $this->assertEquals(MP3_URL, 'file://' . getcwd() . '/'); $this->assertEquals(LINK, 'http://www.example.com/'); $this->assertEquals(RSS_LINK, 'http://www.example.com/rss'); $this->assertEquals(TITLE, 'test'); // name of this folder diff --git a/test/bootstrap.php b/test/bootstrap.php index c2a1b9b..9fe6f3e 100644 --- a/test/bootstrap.php +++ b/test/bootstrap.php @@ -124,11 +124,6 @@ function fake_getopt($argv_in, $short_options, $long_options) return array(); } -function slashdir($dir) -{ - return rtrim($dir, '/') . '/'; -} - define('NO_DISPATCHER', true); require_once('../dir2cast.php');