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:
@@ -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;
|
||||
|
Reference in New Issue
Block a user