Compare commits
23 Commits
Author | SHA1 | Date |
---|---|---|
Abel Hoogeveen | 58e885e35f | |
Abel Hoogeveen | d6863d3f51 | |
Abel Hoogeveen | 22e3ec2fd0 | |
Abel Hoogeveen | d66c244931 | |
Abel Hoogeveen | 0e2eb5ef72 | |
Abel Hoogeveen | 3c7011eddb | |
Abel Hoogeveen | cd331dc39d | |
Abel Hoogeveen | 444f614c48 | |
Abel Hoogeveen | af25072b24 | |
Abel Hoogeveen | d7b2c40c57 | |
Abel Hoogeveen | e3485fa256 | |
Abel Hoogeveen | c09d1a35d5 | |
Abel Hoogeveen | b976dbeae3 | |
Abel Hoogeveen | 1180445dcc | |
Abel Hoogeveen | 74cb630d80 | |
Abel Hoogeveen | 0ba98f8130 | |
Abel Hoogeveen | ddbc787c45 | |
Abel Hoogeveen | 35df988200 | |
Abel Hoogeveen | a04293d8b4 | |
Abel Hoogeveen | cf8315e06b | |
Abel Hoogeveen | fd531b53e2 | |
Abel Hoogeveen | 7c77c339cf | |
Abel Hoogeveen | 612ab3abca |
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2013-2021 TechFuze
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -4,28 +4,23 @@
|
|||
"license": ["MIT"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "TechFuze",
|
||||
"homepage": "https://techfuze.net"
|
||||
},
|
||||
{
|
||||
"name": "FuzeWorks Community",
|
||||
"homepage": "https://techfuze.net/fuzeworks/contributors"
|
||||
"name": "Abel Hoogeveen",
|
||||
"homepage": "https://i15.nl"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.1.0",
|
||||
"fuzeworks/mvcr": "1.2.0-RC3",
|
||||
"fuzeworks/core": "1.2.0-RC3"
|
||||
"php": ">=8.1.0",
|
||||
"fuzeworks/core": "~1.3.0",
|
||||
"fuzeworks/mvcr": "~1.3.0",
|
||||
"fuzeworks/objectstorage": "~1.3.0"
|
||||
},
|
||||
"minimum-stability": "RC",
|
||||
"prefer-stable": true,
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7"
|
||||
"fuzeworks/layout": "~1.3.0",
|
||||
"fuzeworks/tracycomponent": "~1.3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"FuzeWorks\\": "src/FuzeWorks/"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -50,12 +50,12 @@ return [
|
|||
| 'csrf_exclude_uris' = Array of URIs which ignore CSRF checks
|
||||
*/
|
||||
'csrf_protection' => true,
|
||||
'csrf_token_name' => 'fw_csrf_token',
|
||||
'csrf_token_name' => 'csrf_token',
|
||||
'csrf_expire' => 7200,
|
||||
'csrf_exclude_uris' => array(),
|
||||
|
||||
// CSRF Cookie information
|
||||
'csrf_cookie_name' => 'fw_csrf_cookie',
|
||||
'csrf_cookie_name' => 'csrf_cookie',
|
||||
'csrf_cookie_prefix' => '',
|
||||
'csrf_cookie_domain' => '',
|
||||
'csrf_cookie_path' => '/',
|
||||
|
|
|
@ -34,13 +34,35 @@
|
|||
* @version Version 1.2.0
|
||||
*/
|
||||
return [
|
||||
'allow_get_input' => true,
|
||||
'empty_global_arrays' => true,
|
||||
'restore_global_arrays' => true,
|
||||
// General
|
||||
'base_url' => '',
|
||||
'serverName' => 'FuzeWorks',
|
||||
|
||||
// Whether to allow GET parameters
|
||||
'allow_get_input' => true,
|
||||
|
||||
// Clears the global $_GET, $_POST, $_COOKIE and $_SERVER arrays in order to prevent misuse
|
||||
'empty_global_arrays' => true,
|
||||
|
||||
// Whether to restore the $_GET, $_POST, $_COOKIE and $_SERVER arrays when FuzeWorks shuts down
|
||||
'restore_global_arrays' => true,
|
||||
'permitted_uri_chars' => 'a-z 0-9~%.:_\-',
|
||||
'charset' => 'UTF-8',
|
||||
|
||||
// Whether to redirect http traffic to https
|
||||
'redirect_to_https' => false,
|
||||
|
||||
// Whether to gzip the output when the client supports it
|
||||
'compress_output' => false,
|
||||
|
||||
// Global switch for output cache. To use, must be enabled in view as well
|
||||
'cache_output' => true,
|
||||
'xss_clean' => true,
|
||||
|
||||
// Cookie settings
|
||||
'cookie_prefix' => 'FWZ_',
|
||||
'xss_clean' => true
|
||||
'cookie_domain' => '',
|
||||
'cookie_path' => '/',
|
||||
'cookie_secure' => false,
|
||||
'cookie_httponly' => false
|
||||
];
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
/**
|
||||
* FuzeWorks WebComponent.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2019 TechFuze
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2019, TechFuze. (http://techfuze.net)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link http://techfuze.net/fuzeworks
|
||||
* @since Version 1.2.0
|
||||
*
|
||||
* @version Version 1.2.0
|
||||
*/
|
||||
|
||||
namespace FuzeWorks\Event;
|
||||
use FuzeWorks\Event;
|
||||
|
||||
class ResourceServeEvent extends Event
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $resourceName;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $requestURL;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $resourceFilePath;
|
||||
|
||||
public function init(string $resourceName, string $requestURL, string $resourceFilePath)
|
||||
{
|
||||
$this->resourceName = $resourceName;
|
||||
$this->requestURL = $requestURL;
|
||||
$this->resourceFilePath = $resourceFilePath;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
/**
|
||||
* FuzeWorks WebComponent.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2019 TechFuze
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2019, TechFuze. (http://techfuze.net)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link http://techfuze.net/fuzeworks
|
||||
* @since Version 1.2.0
|
||||
*
|
||||
* @version Version 1.2.0
|
||||
*/
|
||||
|
||||
namespace FuzeWorks\Event;
|
||||
use FuzeWorks\Event;
|
||||
|
||||
class RouteWebRequestEvent extends Event
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $uriString;
|
||||
|
||||
public function init(string $uriString)
|
||||
{
|
||||
$this->uriString = $uriString;
|
||||
}
|
||||
|
||||
}
|
|
@ -75,6 +75,9 @@ class Input
|
|||
if (!WebComponent::$willHandleRequest)
|
||||
return;
|
||||
|
||||
// Start session
|
||||
session_start();
|
||||
|
||||
// Sanitize all global arrays
|
||||
$this->sanitizeGlobals();
|
||||
|
||||
|
@ -324,7 +327,6 @@ class Input
|
|||
/**
|
||||
* Fetch the HTTP_USER_AGENT variable from the $_SERVER array
|
||||
*
|
||||
* @param string|array|null $index
|
||||
* @param bool $xssClean
|
||||
* @return mixed
|
||||
*/
|
||||
|
@ -336,7 +338,6 @@ class Input
|
|||
/**
|
||||
* Fetch the REQUEST_METHOD variable from the $_SERVER array
|
||||
*
|
||||
* @param string|array|null $index
|
||||
* @param bool $xssClean
|
||||
* @return mixed
|
||||
*/
|
||||
|
|
|
@ -145,7 +145,7 @@ class Output
|
|||
$output = is_null($output) ? $this->output : $output;
|
||||
|
||||
// Write cache if requested to do so
|
||||
if ($this->cacheTime > 0)
|
||||
if ($this->cacheTime > 0 && !is_null($output))
|
||||
$this->writeCache($output);
|
||||
|
||||
// First send status code
|
||||
|
@ -201,18 +201,22 @@ class Output
|
|||
|
||||
public function getCache(string $selector): bool
|
||||
{
|
||||
// If empty, index page is requested
|
||||
$selector = empty($selector) ? 'index' : $selector;
|
||||
// If output cache is disabled, don't return a cache result
|
||||
if ($this->config->get('cache_output') !== true)
|
||||
return false;
|
||||
|
||||
// Generate the full uri
|
||||
$uri = $this->config->get('base_url') . $selector;
|
||||
$uri = $this->config->get('base_url') . (empty($selector) ? 'index' : $selector);
|
||||
$getParams = $this->input->get();
|
||||
|
||||
// Determine the identifier
|
||||
$identier = md5($uri . '|' . serialize($getParams));
|
||||
|
||||
// Determine the file that holds the cache
|
||||
if ($this->compressOutput)
|
||||
$file = Core::$tempDir . DS . 'OutputCache' . DS . md5($uri) . '_gzip.fwcache';
|
||||
$file = Core::$tempDir . DS . 'OutputCache' . DS . $identier . '_gzip.fwcache';
|
||||
else
|
||||
$file = Core::$tempDir . DS . 'OutputCache' . DS . md5($uri) . '.fwcache';
|
||||
|
||||
$file = Core::$tempDir . DS . 'OutputCache' . DS . $identier . '.fwcache';
|
||||
|
||||
// Determine if file exists
|
||||
if (!file_exists($file))
|
||||
|
@ -259,6 +263,10 @@ class Output
|
|||
|
||||
public function writeCache(string $output)
|
||||
{
|
||||
// If output cache is disabled, don't create a cache entry
|
||||
if ($this->config->get('cache_output') !== true)
|
||||
return false;
|
||||
|
||||
// First create cache directory
|
||||
$cachePath = Core::$tempDir . DS . 'OutputCache';
|
||||
|
||||
|
@ -278,12 +286,16 @@ class Output
|
|||
|
||||
// Generate the full uri
|
||||
$uri = $this->config->get('base_url') . (empty($this->uri->uriString()) ? 'index' : $this->uri->uriString());
|
||||
$getParams = $this->input->get();
|
||||
|
||||
// Determine the identifier
|
||||
$identifier = md5($uri . '|' . serialize($getParams));
|
||||
|
||||
// Determine the file that holds the cache
|
||||
if ($this->compressOutput)
|
||||
$file = $cachePath . DS . md5($uri) . '_gzip.fwcache';
|
||||
$file = $cachePath . DS . $identifier . '_gzip.fwcache';
|
||||
else
|
||||
$file = $cachePath . DS . md5($uri) . '.fwcache';
|
||||
$file = $cachePath . DS . $identifier . '.fwcache';
|
||||
|
||||
|
||||
// If compression is enabled, compress the output
|
||||
|
@ -314,9 +326,6 @@ class Output
|
|||
return false;
|
||||
}
|
||||
|
||||
// Lowering permissions to read only
|
||||
chmod($cachePath, 0640);
|
||||
|
||||
// And report back
|
||||
Logger::logInfo("Output cache has been saved.");
|
||||
|
||||
|
@ -513,4 +522,25 @@ class Output
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the location to redirect the user to.
|
||||
*
|
||||
* @param string $locationUrl Should be prepended with /
|
||||
* @param bool $permanent True for 301, false for 302 redirect.
|
||||
* @return void
|
||||
*/
|
||||
public function setLocation(string $locationUrl, bool $permanent = false)
|
||||
{
|
||||
// Set the status header
|
||||
if ($permanent)
|
||||
$this->setStatusHeader(301);
|
||||
else
|
||||
$this->setStatusHeader(302);
|
||||
|
||||
// And the location itself
|
||||
$header = 'Location: ' . $locationUrl;
|
||||
$this->headers[] = [$header, true];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
<?php
|
||||
/**
|
||||
* FuzeWorks WebComponent.
|
||||
*
|
||||
* The FuzeWorks PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2013-2019 TechFuze
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2019, TechFuze. (http://techfuze.net)
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
*
|
||||
* @link http://techfuze.net/fuzeworks
|
||||
* @since Version 1.2.0
|
||||
*
|
||||
* @version Version 1.2.0
|
||||
*/
|
||||
|
||||
namespace FuzeWorks;
|
||||
|
||||
use FuzeWorks\Event\ResourceServeEvent;
|
||||
use FuzeWorks\Exception\WebException;
|
||||
|
||||
/**
|
||||
* FuzeWorks' handler for static resources.
|
||||
*
|
||||
* Objects in FuzeWorks can register a folder with static resources, which shall be served if requested by clients.
|
||||
* This system should be avoided for high-performance applications. It is recommended to make special configurations in the web server
|
||||
* in those kinds of cases.
|
||||
*/
|
||||
class Resources
|
||||
{
|
||||
|
||||
private $resources = [];
|
||||
|
||||
/**
|
||||
* @var Output
|
||||
*/
|
||||
private $output;
|
||||
|
||||
public function init()
|
||||
{
|
||||
$this->output = Factory::getInstance()->output;
|
||||
}
|
||||
|
||||
public function resourceExists(string $requestURL): bool
|
||||
{
|
||||
// First find the resource
|
||||
$file = $this->findResource($requestURL);
|
||||
|
||||
// If not found, return false;
|
||||
if (is_null($file))
|
||||
return false;
|
||||
|
||||
// If found, simply return true
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serves a static file if found.
|
||||
*
|
||||
* @param string $requestURL
|
||||
* @return bool
|
||||
* @throws WebException
|
||||
*
|
||||
* @todo Bypass the Output system and use the readFile() method.
|
||||
* @todo Run as FuzeWorks pre-code, before creating the container
|
||||
*/
|
||||
public function serveResource(string $requestURL): bool
|
||||
{
|
||||
// First find the resource
|
||||
$file = $this->findResource($requestURL);
|
||||
|
||||
// If not found return false
|
||||
if (is_null($file))
|
||||
return false;
|
||||
|
||||
// If a file is found, fire a serveResourceEvent
|
||||
/** @var ResourceServeEvent $event */
|
||||
try {
|
||||
$event = Events::fireEvent('resourceServeEvent', $file['resourceName'], $file['requestURL'], $file['file']);
|
||||
} catch (Exception\EventException $e) {
|
||||
throw new WebException("Could not serve resource. resourceServeEvent threw exception: '" . $e->getMessage() . "'");
|
||||
}
|
||||
|
||||
// If cancelled, don't serve
|
||||
if ($event->isCancelled())
|
||||
return false;
|
||||
|
||||
// Log the resource serving
|
||||
Logger::log("Serving static resource '/" . $file['resourceName'] . '/' . $file['requestURL'] . "'");
|
||||
|
||||
// Serve file in accordance with event
|
||||
$fileExtension = pathinfo($event->resourceFilePath, PATHINFO_EXTENSION);
|
||||
$this->output->setContentType($fileExtension);
|
||||
$this->output->setOutput(file_get_contents($event->resourceFilePath));
|
||||
#readfile($event->resourceFilePath);
|
||||
|
||||
// And return true at the end
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function findResource(string $requestURL): ?array
|
||||
{
|
||||
// First segment should be the resourceName, check if it exists
|
||||
foreach ($this->resources as $resourceName => $resourceDir)
|
||||
{
|
||||
if (substr($requestURL, 0, strlen($resourceName)) === $resourceName)
|
||||
{
|
||||
$fileURL = ltrim(substr($requestURL, strlen($resourceName)), '/');
|
||||
$fileURL = str_replace('/', DS, $fileURL);
|
||||
$file = $this->resources[$resourceName] . DS . $fileURL;
|
||||
|
||||
// Test if file exists, if it does, return the string
|
||||
if (file_exists($file) && is_file($file))
|
||||
return ['file' => $file, 'resourceName' => $resourceName, 'requestURL' => $fileURL];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a resource which can be served statically.
|
||||
*
|
||||
* The resourceName will be the directory under which the files shall be served on the web server.
|
||||
* The filePath is where FuzeWorks should look for the files.
|
||||
*
|
||||
* @param string $resourceName
|
||||
* @param string $filePath
|
||||
* @throws WebException
|
||||
* @return bool
|
||||
*/
|
||||
public function registerResources(string $resourceName, string $filePath): bool
|
||||
{
|
||||
// First check if the resource already exists
|
||||
$resourceName = urldecode($resourceName);
|
||||
if (isset($this->resources[$resourceName]))
|
||||
throw new WebException("Could not register resources. Resources with same name already exists.");
|
||||
|
||||
// Also check if the file path exists and is a directory
|
||||
if (!file_exists($filePath) && !is_dir($filePath))
|
||||
throw new WebException("Could not register resources. Provided filePath does not exist.");
|
||||
|
||||
// Add the resource
|
||||
$this->resources[$resourceName] = $filePath;
|
||||
|
||||
// Log the registration
|
||||
Logger::log("Adding static resources on: '/" . $resourceName . "'");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -188,7 +188,7 @@ class Security {
|
|||
$this->input = Factory::getInstance()->input;
|
||||
|
||||
// Is CSRF protection enabled?
|
||||
if ($this->config->csrf_protection)
|
||||
if ($this->config->get('csrf_protection'))
|
||||
{
|
||||
// CSRF config
|
||||
foreach (array('csrf_expire', 'csrf_token_name', 'csrf_cookie_name') as $key)
|
||||
|
@ -222,6 +222,10 @@ class Security {
|
|||
*/
|
||||
public function csrf_verify(): self
|
||||
{
|
||||
// If not enabled, do not run
|
||||
if (!$this->config->get('csrf_protection'))
|
||||
return $this;
|
||||
|
||||
// If it's not a POST request we will set the CSRF cookie
|
||||
if (strtoupper($this->input->server('REQUEST_METHOD')) !== 'POST')
|
||||
return $this->csrf_set_cookie();
|
||||
|
@ -320,7 +324,7 @@ class Security {
|
|||
* @see Security::$_csrf_hash
|
||||
* @return string CSRF hash
|
||||
*/
|
||||
public function get_csrf_hash(): string
|
||||
public function get_csrf_hash(): ?string
|
||||
{
|
||||
return $this->_csrf_hash;
|
||||
}
|
||||
|
@ -371,10 +375,8 @@ class Security {
|
|||
// Is the string an array?
|
||||
if (is_array($str))
|
||||
{
|
||||
while (list($key) = each($str))
|
||||
{
|
||||
$str[$key] = $this->xss_clean($str[$key]);
|
||||
}
|
||||
foreach ($str as $key => $value)
|
||||
$str[$key] = $this->xss_clean($value);
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
|
|
@ -60,8 +60,8 @@ class URI
|
|||
private $input;
|
||||
|
||||
protected $baseUri;
|
||||
protected $uriString;
|
||||
protected $segments;
|
||||
protected $uriString = '';
|
||||
protected $segments = [];
|
||||
|
||||
public function init()
|
||||
{
|
||||
|
|
|
@ -37,12 +37,15 @@
|
|||
namespace FuzeWorks;
|
||||
|
||||
use FuzeWorks\Event\HaltExecutionEvent;
|
||||
use FuzeWorks\Event\LayoutDisplayEvent;
|
||||
use FuzeWorks\Event\LayoutLoadEvent;
|
||||
use FuzeWorks\Event\RouterCallViewEvent;
|
||||
use FuzeWorks\Event\RouterLoadViewAndControllerEvent;
|
||||
use FuzeWorks\Event\RouteWebRequestEvent;
|
||||
use FuzeWorks\Exception\ConfigException;
|
||||
use FuzeWorks\Exception\CSRFException;
|
||||
use FuzeWorks\Exception\EventException;
|
||||
use FuzeWorks\Exception\Exception;
|
||||
use FuzeWorks\Exception\FactoryException;
|
||||
use FuzeWorks\Exception\HaltException;
|
||||
use FuzeWorks\Exception\NotFoundException;
|
||||
use FuzeWorks\Exception\OutputException;
|
||||
|
@ -57,7 +60,7 @@ class WebComponent implements iComponent
|
|||
*
|
||||
* @var bool
|
||||
*/
|
||||
public static $willHandleRequest = false;
|
||||
public static bool $willHandleRequest = false;
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
|
@ -72,6 +75,7 @@ class WebComponent implements iComponent
|
|||
'input' => '\FuzeWorks\Input',
|
||||
'output' => '\FuzeWorks\Output',
|
||||
'uri' => '\FuzeWorks\URI',
|
||||
'resources' => '\FuzeWorks\Resources'
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -89,10 +93,8 @@ class WebComponent implements iComponent
|
|||
|
||||
// If WebComponent will handle a request, add some calls to the configurator
|
||||
if (self::$willHandleRequest)
|
||||
{
|
||||
// Invoke methods to prepare system for HTTP calls
|
||||
$configurator->call('logger', 'setLoggerTemplate', null, 'logger_http');
|
||||
}
|
||||
}
|
||||
|
||||
public function onCreateContainer(Factory $container)
|
||||
|
@ -120,13 +122,44 @@ class WebComponent implements iComponent
|
|||
}
|
||||
|
||||
/**
|
||||
* Disable the WebComponent so it won't prepare for handling requests
|
||||
* Disable the WebComponent, so it won't prepare for handling requests
|
||||
*/
|
||||
public function disableComponent()
|
||||
{
|
||||
self::$willHandleRequest = false;
|
||||
}
|
||||
|
||||
public function shutdownEventListener(Event $event): Event
|
||||
{
|
||||
/** @var Output $output */
|
||||
Logger::logInfo("Parsing output...");
|
||||
$output = Factory::getInstance()->output;
|
||||
$output->display();
|
||||
return $event;
|
||||
}
|
||||
|
||||
public function layoutDisplayEventListener(Event $event)
|
||||
{
|
||||
/** @var $event LayoutDisplayEvent */
|
||||
/** @var Output $output */
|
||||
$output = Factory::getInstance('output');
|
||||
$output->appendOutput($event->contents);
|
||||
$event->setCancelled(true);
|
||||
}
|
||||
|
||||
public function routerLoadViewAndControllerEventListener(Event $event)
|
||||
{
|
||||
/** @var Input $input */
|
||||
/** @var RouterLoadViewAndControllerEvent $event */
|
||||
$input = Factory::getInstance('input');
|
||||
$methods = $event->viewMethods[Priority::NORMAL];
|
||||
foreach ($methods as $method)
|
||||
$event->addMethod(strtolower($input->method()) . '_' . $method);
|
||||
|
||||
Logger::log("Added input method '" . $input->method() . "' as a prefix to view methods.");
|
||||
return $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a Web request.
|
||||
*
|
||||
|
@ -138,6 +171,7 @@ class WebComponent implements iComponent
|
|||
* @throws RouterException
|
||||
* @throws WebException
|
||||
* @throws EventException
|
||||
* @throws FactoryException
|
||||
*/
|
||||
public function routeWebRequest(): bool
|
||||
{
|
||||
|
@ -146,12 +180,13 @@ class WebComponent implements iComponent
|
|||
|
||||
try {
|
||||
// Set the output to display when shutting down
|
||||
Events::addListener(function ($event) {
|
||||
/** @var Output $output */
|
||||
Logger::logInfo("Parsing output...");
|
||||
$output = Factory::getInstance()->output;
|
||||
$output->display();
|
||||
}, 'coreShutdownEvent', Priority::NORMAL);
|
||||
Events::addListener([$this, 'shutdownEventListener'], 'coreShutdownEvent', Priority::NORMAL);
|
||||
|
||||
// Intercept output of Layout and redirect it to Output
|
||||
Events::addListener([$this, 'layoutDisplayEventListener'], 'layoutDisplayEvent', Priority::NORMAL);
|
||||
|
||||
// Add HTTP method prefix to requests to views
|
||||
Events::addListener([$this, 'routerLoadViewAndControllerEventListener'], 'routerLoadViewAndControllerEvent', Priority::NORMAL);
|
||||
|
||||
// Create an error 500 page when a haltEvent is fired
|
||||
Events::addListener([$this, 'haltEventListener'], 'haltExecutionEvent', Priority::NORMAL);
|
||||
|
@ -164,12 +199,31 @@ class WebComponent implements iComponent
|
|||
|
||||
/** @var Router $router */
|
||||
/** @var URI $uri */
|
||||
/** @var Input $input */
|
||||
/** @var Output $output */
|
||||
/** @var Security $security */
|
||||
$router = Factory::getInstance()->router;
|
||||
$uri = Factory::getInstance()->uri;
|
||||
$output = Factory::getInstance()->output;
|
||||
$security = Factory::getInstance()->security;
|
||||
/** @var Resources $resources */
|
||||
/** @var Config $config */
|
||||
$router = Factory::getInstance('router');
|
||||
$uri = Factory::getInstance('uri');
|
||||
$input = Factory::getInstance('input');
|
||||
$output = Factory::getInstance('output');
|
||||
$security = Factory::getInstance('security');
|
||||
$resources = Factory::getInstance('resources');
|
||||
$config = Factory::getInstance('config');
|
||||
|
||||
// First check if this isn't https and we need to redirect
|
||||
$redirect = $config->getConfig('web')->get('redirect_to_https');
|
||||
if ($redirect && !$input->isHttps())
|
||||
{
|
||||
Logger::log("Redirecting http traffic to https...");
|
||||
$httpsInputs = $input->server(['HTTPS', 'HTTP_HOST', 'REQUEST_URI']);
|
||||
$location = 'https://' . $httpsInputs['HTTP_HOST'] . $httpsInputs['REQUEST_URI'];
|
||||
|
||||
$output->setStatusHeader(301);
|
||||
$output->setHeader('Location: ' . $location);
|
||||
return true;
|
||||
}
|
||||
|
||||
// And start logging the request
|
||||
Logger::newLevel("Routing web request...");
|
||||
|
@ -179,6 +233,16 @@ class WebComponent implements iComponent
|
|||
if ($output->getCache($uriString))
|
||||
return true;
|
||||
|
||||
// Send webRequestEvent, if no cache is found
|
||||
/** @var RouteWebRequestEvent $event */
|
||||
$event = Events::fireEvent('routeWebRequestEvent', $uriString);
|
||||
if ($event->isCancelled())
|
||||
return true;
|
||||
|
||||
// Attempt to load a static resource
|
||||
if ($resources->serveResource($uri->uriString()))
|
||||
return true;
|
||||
|
||||
// First test for Cross Site Request Forgery
|
||||
try {
|
||||
$security->csrf_verify();
|
||||
|
@ -192,7 +256,7 @@ class WebComponent implements iComponent
|
|||
|
||||
// Attempt to load the requested page
|
||||
try {
|
||||
$viewOutput = $router->route($uriString);
|
||||
$viewOutput = $router->route($event->uriString);
|
||||
} catch (NotFoundException $e) {
|
||||
Logger::logWarning("Requested page not found. Requesting Error/error404 View");
|
||||
$output->setStatusHeader(404);
|
||||
|
@ -200,7 +264,7 @@ class WebComponent implements iComponent
|
|||
// Remove listener so that error pages won't be intercepted
|
||||
Events::removeListener([$this, 'callViewEventListener'], 'routerCallViewEvent',Priority::HIGHEST);
|
||||
|
||||
// Request 404 page=
|
||||
// Request 404 page
|
||||
try {
|
||||
$viewOutput = $router->route('Error/error404');
|
||||
} catch (NotFoundException $e) {
|
||||
|
@ -248,7 +312,6 @@ class WebComponent implements iComponent
|
|||
*/
|
||||
public function callViewEventListener(RouterCallViewEvent $event, SecurityException $exception)
|
||||
{
|
||||
/** @var RouterCallViewEvent $event */
|
||||
// If the securityExceptionHandler method exists, cancel based on that methods output
|
||||
if (method_exists($event->view, 'securityExceptionHandler'))
|
||||
$event->setCancelled(!$event->view->securityExceptionHandler($exception));
|
||||
|
@ -263,8 +326,9 @@ class WebComponent implements iComponent
|
|||
*
|
||||
* Fired when FuzeWorks halts it's execution. Loads an error 500 page.
|
||||
*
|
||||
* @param $event
|
||||
* @param HaltExecutionEvent $event
|
||||
* @throws EventException
|
||||
* @throws FactoryException
|
||||
* @TODO remove FuzeWorks\Layout dependency
|
||||
*/
|
||||
public function haltEventListener(HaltExecutionEvent $event)
|
||||
|
@ -276,14 +340,17 @@ class WebComponent implements iComponent
|
|||
/** @var Layout $layout */
|
||||
$output = Factory::getInstance()->output;
|
||||
$router = Factory::getInstance()->router;
|
||||
$layout = Factory::getInstance()->layouts;
|
||||
|
||||
// Reset the layout engine
|
||||
if (isset(Factory::getInstance()->layouts))
|
||||
{
|
||||
$layout = Factory::getInstance()->layouts;
|
||||
$layout->reset();
|
||||
}
|
||||
|
||||
// Cancel event
|
||||
$event->setCancelled(true);
|
||||
|
||||
// Reset the layout engine
|
||||
$layout->reset();
|
||||
|
||||
// Remove listener so that error pages won't be intercepted
|
||||
Events::removeListener([$this, 'callViewEventListener'], 'routerCallViewEvent',Priority::HIGHEST);
|
||||
|
||||
|
@ -308,6 +375,7 @@ class WebComponent implements iComponent
|
|||
*
|
||||
* @param LayoutLoadEvent $event
|
||||
* @throws ConfigException
|
||||
* @throws FactoryException
|
||||
*/
|
||||
public function layoutLoadEventListener($event)
|
||||
{
|
||||
|
@ -317,10 +385,10 @@ class WebComponent implements iComponent
|
|||
$security = Factory::getInstance()->security;
|
||||
$config = Factory::getInstance()->config;
|
||||
|
||||
/** @var LayoutLoadEvent $event */
|
||||
$event->assign('csrfHash', $security->get_csrf_hash());
|
||||
$event->assign('csrfTokenName', $security->get_csrf_token_name());
|
||||
$event->assign('siteURL', $config->getConfig('web')->get('base_url'));
|
||||
$event->assign('serverName', $config->getConfig('web')->get('serverName'));
|
||||
|
||||
Logger::logInfo("Assigned variables to TemplateEngine from WebComponent");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue