diff options
| -rw-r--r-- | phpBB/phpbb/template/twig/loader.php | 150 | ||||
| -rw-r--r-- | phpBB/phpbb/template/twig/twig.php | 22 | 
2 files changed, 165 insertions, 7 deletions
| diff --git a/phpBB/phpbb/template/twig/loader.php b/phpBB/phpbb/template/twig/loader.php new file mode 100644 index 0000000000..0829e519f7 --- /dev/null +++ b/phpBB/phpbb/template/twig/loader.php @@ -0,0 +1,150 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* Twig Template loader +* @package phpBB3 +*/ +class phpbb_template_twig_loader extends Twig_Loader_Filesystem +{ +	protected $safe_directories = array(); + +	/** +	* Set safe directories +	* +	* @param array $directories Array of directories that are safe (empty to clear) +	* @return Twig_Loader_Filesystem +	*/ +	public function setSafeDirectories($directories = array()) +	{ +		$this->safe_directories = array(); + +		if (!empty($directories)) +		{ +			foreach ($directories as $directory) +			{ +				$this->addSafeDirectory($directory); +			} +		} + +		return $this; +	} + +	/** +	* Add safe directory +	* +	* @param string $directory Directory that should be added +	* @return Twig_Loader_Filesystem +	*/ +	public function addSafeDirectory($directory) +	{ +		$directory = phpbb_realpath($directory); + +		if ($directory !== false) +		{ +			$this->safe_directories[] = $directory; +		} + +		return $this; +	} + +	/** +	* Get current safe directories +	* +	* @return array +	*/ +	public function getSafeDirectories() +	{ +		return $this->safe_directories; +	} + +	/** +	* Override for parent::validateName() +	* +	* This is done because we added support for safe directories, and when Twig +	*	findTemplate() is called, validateName() is called first, which would +	*	always throw an exception if the file is outside of the configured +	*	template directories. +	*/ +	protected function validateName($name) +	{ +		return; +	} + +	/** +	* Find the template +	* +	* Override for Twig_Loader_Filesystem::findTemplate to add support +	*	for loading from safe directories. +	*/ +	protected function findTemplate($name) +	{ +		$name = (string) $name; + +		// normalize name +		$name = preg_replace('#/{2,}#', '/', strtr($name, '\\', '/')); + +		// If this is in the cache we can skip the entire process below +		//	as it should have already been validated +		if (isset($this->cache[$name])) { +			return $this->cache[$name]; +		} + +		// First, find the template name. The override above of validateName +		//	causes the validateName process to be skipped for this call +		$file = parent::findTemplate($name); + +		try +		{ +			// Try validating the name (which may throw an exception) +			parent::validateName($name); +		} +		catch (Twig_Error_Loader $e) +		{ +			if (strpos($e->getRawMessage(), 'Looks like you try to load a template outside configured directories') === 0) +			{ +				// Ok, so outside of the configured template directories, we +				//	can now check if we're within a "safe" directory + +				// Find the real path of the directory the file is in +				$directory = phpbb_realpath(dirname($file)); + +				if ($directory === false) +				{ +					// Some sort of error finding the actual path, must throw the exception +					throw $e; +				} + +				foreach ($this->safe_directories as $safe_directory) +				{ +					if (strpos($directory, $safe_directory) === 0) +					{ +						// The directory being loaded is below a directory +						// that is "safe". We're good to load it! +						return $file; +					} +				} +			} + +			// Not within any safe directories +			throw $e; +		} + +		// No exception from validateName, safe to load. +		return $file; +	} +} diff --git a/phpBB/phpbb/template/twig/twig.php b/phpBB/phpbb/template/twig/twig.php index 1ed89d3ccc..5746cc64a3 100644 --- a/phpBB/phpbb/template/twig/twig.php +++ b/phpBB/phpbb/template/twig/twig.php @@ -91,7 +91,7 @@ class phpbb_template_twig extends phpbb_template_base  		$this->cachepath = $phpbb_root_path . 'cache/twig/';  		// Initiate the loader, __main__ namespace paths will be setup later in set_style_names() -		$loader = new Twig_Loader_Filesystem(''); +		$loader = new phpbb_template_twig_loader('');  		$this->twig = new phpbb_template_twig_environment(  			$this->config, @@ -181,11 +181,15 @@ class phpbb_template_twig extends phpbb_template_base  		{  			foreach ($names as $name)  			{ -				$path = $this->phpbb_root_path . trim($directory, '/') . "/{$name}/template/"; +				$path = $this->phpbb_root_path . trim($directory, '/') . "/{$name}/"; +				$template_path = $path . 'template/'; -				if (is_dir($path)) +				if (is_dir($template_path))  				{ -					$paths[] = $path; +					// Add the base style directory as a safe directory +					$this->twig->getLoader()->addSafeDirectory($path); + +					$paths[] = $template_path;  				}  			}  		} @@ -233,11 +237,15 @@ class phpbb_template_twig extends phpbb_template_base  				foreach ($names as $style_name)  				{ -					$ext_style_path = $ext_path . 'styles/' . $style_name . '/template'; +					$ext_style_path = $ext_path . 'styles/' . $style_name . '/'; +					$ext_style_template_path = $ext_style_path . 'template/'; -					if (is_dir($ext_style_path)) +					if (is_dir($ext_style_template_path))  					{ -						$paths[] = $ext_style_path; +						// Add the base style directory as a safe directory +						$this->twig->getLoader()->addSafeDirectory($ext_style_path); + +						$paths[] = $ext_style_template_path;  					}  				} | 
