Support header locking

Locking for http header. Throw exceptions. Socket shouldn't be affected
by this since these classes are http specific.
This commit is contained in:
Dennis Eichhorn 2016-03-19 12:20:44 +01:00
parent 9dd230df36
commit 09ca1a5c08
3 changed files with 106 additions and 7 deletions

View File

@ -28,6 +28,8 @@ class CookieJar
{ {
private $cookies = []; private $cookies = [];
private static $isLocked = false;
public function __construct() public function __construct()
{ {
$this->cookies = $_COOKIE; $this->cookies = $_COOKIE;
@ -70,8 +72,22 @@ class CookieJar
public function save() public function save()
{ {
if(self::$isLocked) {
throw new \Exception('Already locked');
}
foreach ($this->cookies as $key => $cookie) { foreach ($this->cookies as $key => $cookie) {
setcookie($key, $cookie['value'], $cookie['expiry'], $cookie['path'], $cookie['domain'], $cookie['secure'], $cookie['httponly']); setcookie($key, $cookie['value'], $cookie['expiry'], $cookie['path'], $cookie['domain'], $cookie['secure'], $cookie['httponly']);
} }
} }
public static function lock()
{
self::$isLocked = true;
}
public static function isLocked() : bool
{
return self::$isLocked;
}
} }

View File

@ -41,6 +41,14 @@ class HttpSession implements SessionInterface
*/ */
private $sid = null; private $sid = null;
/**
* Is session locked/already set.
*
* @var bool
* @since 1.0.0
*/
private static $isLocked = false;
/** /**
* Constructor. * Constructor.
* *
@ -52,6 +60,10 @@ class HttpSession implements SessionInterface
*/ */
public function __construct(int $liftetime = 3600, $sid = false) public function __construct(int $liftetime = 3600, $sid = false)
{ {
if(self::$isLocked) {
throw new \Exception('Already locked');
}
if (!is_bool($sid)) { if (!is_bool($sid)) {
session_id($sid); session_id($sid);
} }
@ -62,6 +74,19 @@ class HttpSession implements SessionInterface
$_SESSION = null; $_SESSION = null;
$this->sid = session_id(); $this->sid = session_id();
$this->setCsrfProtection();
self::$isLocked = true;
}
/**
* Set Csrf protection for forms.
*
* @since 1.0.0
* @author Dennis Eichhorn <d.eichhorn@oms.com>
*/
private function setCsrfProtection()
{
$this->set('UID', 0, false); $this->set('UID', 0, false);
if(($CSRF = $this->get('CSRF')) === null) { if(($CSRF = $this->get('CSRF')) === null) {
@ -138,4 +163,14 @@ class HttpSession implements SessionInterface
session_write_close(); session_write_close();
} }
public static function lock()
{
self::$isLocked = true;
}
public static function isLocked()
{
return self::$isLocked;
}
} }

View File

@ -51,6 +51,8 @@ class Response extends ResponseAbstract implements RenderableInterface
*/ */
private $head = null; private $head = null;
private static $isLocked = false;
/** /**
* Constructor. * Constructor.
* *
@ -75,9 +77,15 @@ class Response extends ResponseAbstract implements RenderableInterface
*/ */
public function pushHeaderId($name) public function pushHeaderId($name)
{ {
if(self::$isLocked) {
throw new \Exception('Already locked');
}
foreach ($this->header[$name] as $key => $value) { foreach ($this->header[$name] as $key => $value) {
header($name, $value); header($name, $value);
} }
$this->lock();
} }
/** /**
@ -92,6 +100,10 @@ class Response extends ResponseAbstract implements RenderableInterface
*/ */
public function removeHeader(int $key) : bool public function removeHeader(int $key) : bool
{ {
if(self::$isLocked) {
throw new \Exception('Already locked');
}
if (isset($this->header[$key])) { if (isset($this->header[$key])) {
unset($this->header[$key]); unset($this->header[$key]);
@ -114,18 +126,33 @@ class Response extends ResponseAbstract implements RenderableInterface
public function generateHeader(int $code) public function generateHeader(int $code)
{ {
if ($code === 403) { if ($code === 403) {
$this->setHeader('HTTP', 'HTTP/1.0 403 Forbidden'); $this->generate403();
$this->setHeader('Status', 'Status: HTTP/1.0 403 Forbidden');
} elseif ($code === 406) { } elseif ($code === 406) {
$this->setHeader('HTTP', 'HTTP/1.0 406 Not acceptable'); $this->generate406();
$this->setHeader('Status', 'Status:406 Not acceptable');
} elseif ($code === 503) { } elseif ($code === 503) {
$this->setHeader('HTTP', 'HTTP/1.0 503 Service Temporarily Unavailable'); $this->generate503();
$this->setHeader('Status', 'Status: 503 Service Temporarily Unavailable');
$this->setHeader('Retry-After', 'Retry-After: 300');
} }
} }
private function generate403()
{
$this->setHeader('HTTP', 'HTTP/1.0 403 Forbidden');
$this->setHeader('Status', 'Status: HTTP/1.0 403 Forbidden');
}
private function generate406()
{
$this->setHeader('HTTP', 'HTTP/1.0 406 Not acceptable');
$this->setHeader('Status', 'Status: 406 Not acceptable');
}
private function generate503()
{
$this->setHeader('HTTP', 'HTTP/1.0 503 Service Temporarily Unavailable');
$this->setHeader('Status', 'Status: 503 Service Temporarily Unavailable');
$this->setHeader('Retry-After', 'Retry-After: 300');
}
/** /**
* Set response. * Set response.
* *
@ -183,11 +210,17 @@ class Response extends ResponseAbstract implements RenderableInterface
*/ */
public function pushHeader() public function pushHeader()
{ {
if(self::$isLocked) {
throw new \Exception('Already locked');
}
foreach ($this->header as $name => $arr) { foreach ($this->header as $name => $arr) {
foreach ($arr as $ele => $value) { foreach ($arr as $ele => $value) {
header($name . ': ' . $value); header($name . ': ' . $value);
} }
} }
$this->lock();
} }
/** /**
@ -202,6 +235,10 @@ class Response extends ResponseAbstract implements RenderableInterface
*/ */
public function remove(int $id) : bool public function remove(int $id) : bool
{ {
if(self::$isLocked) {
throw new \Exception('Already locked');
}
if (isset($this->response[$id])) { if (isset($this->response[$id])) {
unset($this->response[$id]); unset($this->response[$id]);
@ -335,6 +372,10 @@ class Response extends ResponseAbstract implements RenderableInterface
*/ */
public function setHeader($key, string $header, bool $overwrite = false) : bool public function setHeader($key, string $header, bool $overwrite = false) : bool
{ {
if(self::$isLocked) {
throw new \Exception('Already locked');
}
if (!$overwrite && isset($this->header[$key])) { if (!$overwrite && isset($this->header[$key])) {
return false; return false;
} elseif ($overwrite) { } elseif ($overwrite) {
@ -349,4 +390,11 @@ class Response extends ResponseAbstract implements RenderableInterface
return true; return true;
} }
private function lock()
{
CookieJar::lock();
HttpSession::lock();
self::$isLocked = true;
}
} }