1<?php 2 3namespace dokuwiki\plugin\filelist\test; 4 5use dokuwiki\plugin\filelist\Path; 6use DokuWikiTest; 7 8/** 9 * Path related tests for the filelist plugin 10 * 11 * @group plugin_filelist 12 * @group plugins 13 */ 14class PathTest extends DokuWikiTest 15{ 16 17 protected $path; 18 19 public function setUp(): void 20 { 21 parent::setUp(); 22 23 $this->path = new Path( 24 <<<EOT 25C:\\xampp\\htdocs\\wiki\\ 26\\\\server\\share\\path\\ 27/linux/file/path/ 28/linux/another/path/../..//another/blargh/../path 29 A> alias 30 W> webfoo 31EOT 32 ); 33 } 34 35 /** 36 * Test the configuration parsing for paths and aliases 37 */ 38 public function testGetPaths() 39 { 40 $expect = [ 41 'C:/xampp/htdocs/wiki/' => [ 42 'root' => 'C:/xampp/htdocs/wiki/', 43 'web' => '/lib/plugins/filelist/file.php?root=C%3A%2Fxampp%2Fhtdocs%2Fwiki%2F&file=', 44 ], 45 '\\\\server/share/path/' => [ 46 'root' => '\\\\server/share/path/', 47 'web' => '/lib/plugins/filelist/file.php?root=%5C%5Cserver%2Fshare%2Fpath%2F&file=', 48 ], 49 '/linux/file/path/' => [ 50 'root' => '/linux/file/path/', 51 'web' => '/lib/plugins/filelist/file.php?root=%2Flinux%2Ffile%2Fpath%2F&file=', 52 ], 53 '/linux/another/path/' => [ 54 'root' => '/linux/another/path/', 55 'alias' => 'alias/', 56 'web' => 'webfoo', 57 ], 58 'alias/' => [ 59 'root' => '/linux/another/path/', 60 'alias' => 'alias/', 61 'web' => 'webfoo', 62 ], 63 ]; 64 65 $this->assertEquals($expect, $this->path->getPaths()); 66 } 67 68 /** 69 * Data provider for testGetPathInfoSuccess 70 */ 71 public function providePathInfoSuccess() 72 { 73 return [ 74 ['/linux/another/path', '/linux/another/path/'], 75 ['/linux/another/path/foo', '/linux/another/path/foo/'], 76 ['alias', '/linux/another/path/'], 77 ['alias/foo', '/linux/another/path/foo/'], 78 ['C:\\xampp\\htdocs\\wiki', 'C:/xampp/htdocs/wiki/'], 79 ['C:\\xampp\\htdocs\\wiki\\foo', 'C:/xampp/htdocs/wiki/foo/'], 80 ['\\\\server\\share\\path\\', '\\\\server/share/path/'], 81 ['\\\\server\\share\\path\\foo', '\\\\server/share/path/foo/'], 82 ]; 83 } 84 85 /** 86 * @dataProvider providePathInfoSuccess 87 */ 88 public function testGetPathInfoSuccess($path, $expect) 89 { 90 $pathInfo = $this->path->getPathInfo($path); 91 $this->assertEquals($expect, $pathInfo['path']); 92 } 93 94 public function providePathInfoFailure() 95 { 96 return [ 97 ['/linux/file/path/../../../etc/'], 98 ['W:\\xampp\\htdocs\\wiki\\foo\\bar'], 99 ['/'], 100 ['./'], 101 ['../'], 102 ]; 103 } 104 105 /** 106 * @dataProvider providePathInfoFailure 107 */ 108 public function testGetPathInfoFailure($path) 109 { 110 $this->expectExceptionMessageMatches('/Path not allowed/'); 111 $this->path->getPathInfo($path); 112 } 113 114 /** 115 * Relative paths have to be resolved to an absolute path so that file access works 116 * regardless of the current working directory (which differs between doku.php and file.php) 117 */ 118 public function testRelativePathIsResolvedToAbsolute() 119 { 120 $path = new Path('relative/root/'); 121 $pathInfo = $path->getPathInfo('relative/root/sub/file.txt', false); 122 123 $this->assertEquals( 124 Path::cleanPath(DOKU_INC, false) . '/relative/root/sub/file.txt', 125 $pathInfo['path'] 126 ); 127 } 128 129 /** 130 * Absolute configured paths must be passed through unchanged 131 */ 132 public function testAbsolutePathIsKept() 133 { 134 $path = new Path('/somewhere/else/'); 135 $pathInfo = $path->getPathInfo('/somewhere/else/file.txt', false); 136 $this->assertEquals('/somewhere/else/file.txt', $pathInfo['path']); 137 } 138 139 /** 140 * The wiki/data directory guard must trigger even for relatively configured roots. 141 * 142 * This is the regression behind issue #50: a relative root like "firmware" never matched 143 * the absolute DOKU_INC, so the guard was silently bypassed and wiki files could be served. 144 */ 145 public function testIsWikiControlled() 146 { 147 global $conf; 148 149 // relative path inside the DokuWiki directory (cwd-independent) 150 $this->assertTrue(Path::isWikiControlled('lib/plugins/filelist')); 151 // absolute path inside the DokuWiki directory (e.g. the password hashes) 152 $this->assertTrue(Path::isWikiControlled(DOKU_INC . 'conf/users.auth.php')); 153 // the configured data directory 154 $this->assertTrue(Path::isWikiControlled($conf['savedir'] . '/pages/wiki/dokuwiki.txt')); 155 // a path completely outside the wiki must be allowed 156 $this->assertFalse(Path::isWikiControlled('/some/other/place/file.txt')); 157 } 158} 159