aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--phpBB/phpbb/path_helper.php119
1 files changed, 82 insertions, 37 deletions
diff --git a/phpBB/phpbb/path_helper.php b/phpBB/phpbb/path_helper.php
index b157c5930a..8552dbeb3a 100644
--- a/phpBB/phpbb/path_helper.php
+++ b/phpBB/phpbb/path_helper.php
@@ -24,7 +24,7 @@ class path_helper
/** @var \phpbb\filesystem */
protected $filesystem;
- /** @var \phpbb\request\request */
+ /** @var \phpbb\request\request_interface */
protected $request;
/** @var \phpbb\config\config */
@@ -181,46 +181,32 @@ class path_helper
}
/*
- * Check AJAX request
+ * 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/
*/
- if ($this->request->is_ajax())
+ if ($this->request->is_ajax() && $this->request->header('Referer'))
{
- // Check referer
- $referer = strtolower($this->request->header('Referer'));
-
- // Count chars
- $chars = strlen($this->config['server_name'] . $this->config['script_path']) - 1;
-
- /*
- * Return string without server name and script path
- * e.g. 'http://localhost/phpBB/app.php', where server name is 'localhost'
- * and script path is '/phpBB', will be cut to '/app.php'
- */
- $ref = substr(strstr($referer, strtolower($this->config['server_name'] . $this->config['script_path'])), $chars);
-
- // How many slashes does the referer used?
- $count_slashes = substr_count($ref, '/');
-
- /*
- * If the shorten referer has only 1 slash,
- * return default path
- */
- if ($count_slashes == 1)
- {
- return $this->web_root_path = $this->phpbb_root_path;
- }
- /*
- * Otherwise we are on routed page so we must correct the relative path
- * for web URLs. We must append ../ to the end of the root path
- * as many times as / exists in shorten referer less one time
- */
- else
- {
- return $this->web_root_path = $this->phpbb_root_path . str_repeat('../', $count_slashes - 1);
- }
+ $referer_web_root_path = $this->get_web_root_path_from_ajax_referer(
+ $this->request->header('Referer'),
+ $this->symfony_request->getUriForPath('')
+ );
+ return $this->web_root_path = $this->phpbb_root_path . $referer_web_root_path;
}
- // How many corrections might we need?
+ // How many corrections might we need?
$corrections = substr_count($path_info, '/');
/*
@@ -241,6 +227,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