diff options
Diffstat (limited to 'phpBB/phpbb/path_helper.php')
| -rw-r--r-- | phpBB/phpbb/path_helper.php | 103 | 
1 files changed, 101 insertions, 2 deletions
| diff --git a/phpBB/phpbb/path_helper.php b/phpBB/phpbb/path_helper.php index b592cc4460..a8592eac6c 100644 --- a/phpBB/phpbb/path_helper.php +++ b/phpBB/phpbb/path_helper.php @@ -24,6 +24,9 @@ class path_helper  	/** @var \phpbb\filesystem */  	protected $filesystem; +	/** @var \phpbb\request\request_interface */ +	protected $request; +  	/** @var string */  	protected $phpbb_root_path; @@ -41,13 +44,16 @@ class path_helper  	*  	* @param \phpbb\symfony_request $symfony_request  	* @param \phpbb\filesystem $filesystem +	* @param \phpbb\request\request_interface $request  	* @param string $phpbb_root_path Relative path to phpBB root  	* @param string $php_ext PHP extension (php) +	* @param mixed $adm_relative_path Relative path admin path to adm/ root  	*/ -	public function __construct(\phpbb\symfony_request $symfony_request, \phpbb\filesystem $filesystem, $phpbb_root_path, $php_ext, $adm_relative_path = null) +	public function __construct(\phpbb\symfony_request $symfony_request, \phpbb\filesystem $filesystem, \phpbb\request\request_interface $request, $phpbb_root_path, $php_ext, $adm_relative_path = null)  	{  		$this->symfony_request = $symfony_request;  		$this->filesystem = $filesystem; +		$this->request = $request;  		$this->phpbb_root_path = $phpbb_root_path;  		$this->php_ext = $php_ext;  		$this->adm_relative_path = $adm_relative_path; @@ -98,7 +104,13 @@ class path_helper  		{  			$path = substr($path, strlen($this->phpbb_root_path)); -			return $this->filesystem->clean_path($this->get_web_root_path() . $path); +			$web_root_path = $this->get_web_root_path(); +			if (substr($web_root_path, -8) === 'app.php/' && substr($path, 0, 7) === 'app.php') +			{ +				$path = substr($path, 8); +			} + +			return $this->filesystem->clean_path($web_root_path . $path);  		}  		return $path; @@ -170,6 +182,34 @@ class path_helper  			return $this->web_root_path = $this->phpbb_root_path;  		} +		/* +		* Check AJAX request: +		* If the current request is a AJAX we need to fix the paths. +		* We need to get the root path based on the Referer, so we can use +		* the generated URLs in the template of the Referer. If we do not +		* generate the relative path based on the Referer, but based on the +		* currently requested URL, the generated URLs will not point to the +		* intended locations: +		*	Referer				desired URL			desired relative root path +		*	memberlist.php		faq.php				./ +		*	memberlist.php		app.php/foo/bar		./ +		*	app.php/foo			memberlist.php		../ +		*	app.php/foo			app.php/fox			../ +		*	app.php/foo/bar		memberlist.php		../../ +		*	../page.php			memberlist.php		./phpBB/ +		*	../sub/page.php		memberlist.php		./../phpBB/ +		* +		* The referer must be specified as a parameter in the query. +		*/ +		if ($this->request->is_ajax() && $this->symfony_request->get('_referer')) +		{ +			$referer_web_root_path = $this->get_web_root_path_from_ajax_referer( +				$this->symfony_request->get('_referer'), +				$this->symfony_request->getSchemeAndHttpHost() . $this->symfony_request->getBasePath() +			); +			return $this->web_root_path = $this->phpbb_root_path . $referer_web_root_path; +		} +  		// How many corrections might we need?  		$corrections = substr_count($path_info, '/'); @@ -191,6 +231,65 @@ class path_helper  	}  	/** +	* Get the web root path of the referer form an ajax request +	* +	* @param string $absolute_referer_url +	* @param string $absolute_board_url +	* @return string +	*/ +	public function get_web_root_path_from_ajax_referer($absolute_referer_url, $absolute_board_url) +	{ +		// If the board URL is in the beginning of the referer, this means +		// we the referer is in the board URL or a subdirectory of it. +		// So we just need to count the / (slashes) in the left over part of +		// the referer and prepend ../ the the current root_path, to get the +		// web root path of the referer. +		if (strpos($absolute_referer_url, $absolute_board_url) === 0) +		{ +			$relative_referer_path = substr($absolute_referer_url, strlen($absolute_board_url)); +			$has_params = strpos($relative_referer_path, '?'); +			if ($has_params !== false) +			{ +				$relative_referer_path = substr($relative_referer_path, 0, $has_params); +			} +			$corrections = substr_count($relative_referer_path, '/'); +			return $this->phpbb_root_path . str_repeat('../', $corrections - 1); +		} + +		// If not, it's a bit more complicated. We go to the parent directory +		// of the referer until we find the remaining referer in the board URL. +		// Foreach directory we need to add a ../ to the fixed root_path. +		// When we finally found it, we need to remove the remaining referer +		// from the board URL, to get the boards root path. +		// If the then append these two strings, we get our fixed web root path. +		$fixed_root_path = ''; +		$referer_dir = $absolute_referer_url; +		$has_params = strpos($referer_dir, '?'); +		if ($has_params !== false) +		{ +			$referer_dir = substr($referer_dir, 0, $has_params); +		} + +		// If we do not find a slash at the end of the referer, we come +		// from a file. So the first dirname() does not need a traversal +		// path correction. +		if (substr($referer_dir, -1) !== '/') +		{ +			$referer_dir = dirname($referer_dir); +		} + +		while (strpos($absolute_board_url, $referer_dir) !== 0) +		{ +			$fixed_root_path .= '../'; +			$referer_dir = dirname($referer_dir); +		} + +		$fixed_root_path .= substr($absolute_board_url, strlen($referer_dir) + 1); +		// Add trailing slash +		return $this->phpbb_root_path . $fixed_root_path . '/'; +	} + +	/**  	* Eliminates useless . and .. components from specified URL  	*  	* @param string $url URL to clean | 
