1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-10 16:54:44 +02:00

Some updates to ProcessPageView and additions for processwire/processwire-issues#366 to better handle URLs with unrecognized characters

This commit is contained in:
Ryan Cramer
2017-09-21 11:37:46 -04:00
parent 8bcb31359f
commit f822292eb3

View File

@@ -115,7 +115,7 @@ class ProcessPageView extends Process {
// check if there is an 'it' GET variable present in the request URL query string, which we don't want here
if(isset($_GET['it']) && strpos($this->dirtyURL, '?it=') !== false || strpos($this->dirtyURL, '&it=')) {
// force to use path in request url rather than contents of 'it' var
list($it, $x) = explode('?', $this->dirtyURL);
list($it,) = explode('?', $this->dirtyURL);
$rootURL = $this->wire('config')->urls->root;
if(strlen($rootURL) > 1 && strpos($it, $rootURL) === 0) $it = substr($it, strlen($rootURL)-1);
$it = str_replace('index.php', '', $it);
@@ -214,12 +214,13 @@ class ProcessPageView extends Process {
return $this->pageNotFound(new NullPage(), $this->requestURL, true, 'requested page resolved to NullPage');
}
return '';
}
/**
* Method executed when externally bootstrapped
*
* @return blank string
* @return string blank string
*
*/
public function ___executeExternal() {
@@ -257,9 +258,12 @@ class ProcessPageView extends Process {
* Hook called when the pageview failed to finish due to an exception.
*
* Sends a copy of the exception that occurred.
*
* @param \Exception $e
*
*/
public function ___failed(\Exception $e) {
if($e) {}
$this->wire()->setStatus(ProcessWire::statusFailed);
}
@@ -270,21 +274,70 @@ class ProcessPageView extends Process {
*
*/
protected function getPage() {
/** @var Config $config */
$config = $this->wire('config');
$shit = isset($_GET['it']) ? trim($_GET['it']) : "/"; // dirty
$it = preg_replace('{[^-_./a-zA-Z0-9]}', '', $shit); // clean
// force redirect to actual page URL? (if different from request URL)
$forceRedirect = false;
// did URL end with index.php|htm|html? If so we might redirect if a page matches without it.
$indexRedirect = false;
/** @var string $shit Dirty URL */
/** @var string $it Clean URL */
if(isset($_GET['it'])) {
// normal request
$shit = trim($_GET['it']);
} else if(isset($_SERVER['REQUEST_URI'])) {
// abnormal request, something about request URL made .htaccess skip it, or index.php called directly
$shit = trim($_SERVER['REQUEST_URI']);
if(strpos($shit, '?') !== false) list($shit,) = explode('?', $shit);
if($config->urls->root != '/') {
if(strpos($shit, $config->urls->root) === 0) {
// remove root URL from request
$shit = substr($shit, strlen($config->urls->root) - 1);
} else {
// request URL outside of our root directory
return null;
}
}
} else {
$shit = '/';
}
if($shit === '/') {
$it = '/';
} else {
$it = preg_replace('{[^-_./a-zA-Z0-9]}', '', $shit); // clean
}
unset($_GET['it']);
if($shit !== $it && $config->pageNameCharset == 'UTF8') {
$it = $this->wire('sanitizer')->pagePathNameUTF8($shit);
if($shit !== $it) {
// sanitized URL does not match requested URL
if($config->pageNameCharset == 'UTF8') {
// test for extended page name URL
$it = $this->wire('sanitizer')->pagePathNameUTF8($shit);
}
if($shit !== $it) {
// if still does not match then fail
return null;
}
}
if(!isset($it[0]) || $it[0] != '/') $it = "/$it";
if(strpos($it, '//') !== false) return null;
// if request contains index.php and the $it string does not, make it redirect to correct version
$forceRedirect = strpos($this->dirtyURL, 'index.php') !== false && strpos($it, 'index.php') === false;
if(strpos($it, '/index.') !== false && preg_match('{/index\.(php|html?)$}', $it, $matches)) {
// if request is to index.php|htm|html, make note of it to determine if we can redirect later
$indexRedirect = true;
} else if(strpos($this->dirtyURL, 'index.php') !== false && strpos($it, 'index.php') === false) {
// if request contains index.php and the $it string does not, make it redirect to correct version
$forceRedirect = true;
}
$numParts = substr_count($it, '/');
if($numParts > $config->maxUrlDepth) return null;
@@ -351,7 +404,14 @@ class ProcessPageView extends Process {
if(!$page || !$page->id) return null;
// if URL segments and/or page numbers are present and not allowed then abort
if(!$this->checkUrlSegments($urlSegments, $page)) return null;
if(!$this->checkUrlSegments($urlSegments, $page)) {
if($indexRedirect && $cnt === 1) {
// index.php|htm|html segments if not used by page can redirect to URL without it
$forceRedirect = true;
} else {
return null;
}
}
if($forceRedirect && !$this->redirectURL) $this->redirectURL = $page->url;
@@ -429,7 +489,7 @@ class ProcessPageView extends Process {
if(!$maxPageNum) $maxPageNum = 999;
if($pageNum > $maxPageNum) return false;
}
$page->pageNum = $pageNum; // backwards compatibility
$page->setQuietly('pageNum', $pageNum); // backwards compatibility
$this->input->setPageNum($pageNum);
array_pop($urlSegments);
}
@@ -536,7 +596,7 @@ class ProcessPageView extends Process {
*
* If the user doesn't have access, then a login Page or NULL (for 404) is returned instead.
*
* @param $page
* @param Page $page
* @return Page|null
*
*/
@@ -589,7 +649,7 @@ class ProcessPageView extends Process {
* if a similar check is needed somewhere else in the core.
*
* @param Page $page
* @return Page|null
* @return Page|null|bool
*
*/
protected function checkAccessDelegated(Page $page) {
@@ -685,6 +745,10 @@ class ProcessPageView extends Process {
* Passthru a file for a non-public page
*
* If the page is public, then it just does a 301 redirect to the file.
*
* @param Page $page
* @param string $basename
* @throws Wire404Exception
*
*/
protected function ___sendFile($page, $basename) {
@@ -721,6 +785,7 @@ class ProcessPageView extends Process {
* @return string
*/
protected function ___pageNotFound($page, $url, $triggerReady = false, $reason = '') {
if($page || $url || $reason) {} // variables provided for hooks only
$this->responseType = self::responseTypeError;
$config = $this->config;