mirror of
https://github.com/Lastorder-DC/rhymix.git
synced 2026-05-11 04:52:14 +09:00
Initial implementation of Security and URL classes
This commit is contained in:
parent
21a8e7db6b
commit
28da8948d7
2 changed files with 262 additions and 0 deletions
120
common/framework/security.php
Normal file
120
common/framework/security.php
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Rhymix\Framework;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The security class.
|
||||||
|
*/
|
||||||
|
class Security
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Sanitize a variable.
|
||||||
|
*
|
||||||
|
* @param string $input
|
||||||
|
* @param string $type
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
|
public static function sanitize($input, $type)
|
||||||
|
{
|
||||||
|
switch ($type)
|
||||||
|
{
|
||||||
|
// Escape HTML special characters.
|
||||||
|
case 'escape':
|
||||||
|
if (!detectUTF8($input)) return false;
|
||||||
|
return escape($input);
|
||||||
|
|
||||||
|
// Strip all HTML tags.
|
||||||
|
case 'strip':
|
||||||
|
if (!detectUTF8($input)) return false;
|
||||||
|
return escape(strip_tags($input));
|
||||||
|
|
||||||
|
// Clean up HTML content to prevent XSS attacks.
|
||||||
|
case 'html':
|
||||||
|
if (!detectUTF8($input)) return false;
|
||||||
|
return Security\HTMLFilter::clean($input);
|
||||||
|
|
||||||
|
// Clean up the input to be used as a safe filename.
|
||||||
|
case 'filename':
|
||||||
|
if (!detectUTF8($input)) return false;
|
||||||
|
return Security\FilenameFilter::clean($input);
|
||||||
|
|
||||||
|
// Unknown filters return false.
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current request seems to be a CSRF attack.
|
||||||
|
*
|
||||||
|
* This method returns true if the request seems to be innocent,
|
||||||
|
* and false if it seems to be a CSRF attack.
|
||||||
|
*
|
||||||
|
* @param string $referer (optional)
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function checkCSRF($referer = null)
|
||||||
|
{
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST')
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$referer)
|
||||||
|
{
|
||||||
|
$referer = strval($_SERVER['HTTP_REFERER']);
|
||||||
|
if ($referer === '')
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return URL::isInternalURL($referer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current request seems to be an XEE attack.
|
||||||
|
*
|
||||||
|
* This method returns true if the request seems to be innocent,
|
||||||
|
* and false if it seems to be an XEE attack.
|
||||||
|
* This is the opposite of XE's Security::detectXEE() method.
|
||||||
|
*
|
||||||
|
* @param string $xml (optional)
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function checkXEE($xml = null)
|
||||||
|
{
|
||||||
|
// Stop if there is no XML content.
|
||||||
|
if (!$xml)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reject entity tags.
|
||||||
|
if (strpos($xml, '<!ENTITY') !== false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if there is no content after the xml tag.
|
||||||
|
$header = preg_replace('/<\?xml.*?\?'.'>/s', '', substr($xml, 0, 100), 1);
|
||||||
|
if (($xml = trim(substr_replace($xml, $header, 0, 100))) === '')
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if there is no content after the DTD.
|
||||||
|
$header = preg_replace('/^<!DOCTYPE[^>]*+>/i', '', substr($xml, 0, 200), 1);
|
||||||
|
if (($xml = trim(substr_replace($xml, $header, 0, 200))) === '')
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the root tag is valid.
|
||||||
|
if (!preg_match('/^<(methodCall|methodResponse|fault)/', $xml))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
142
common/framework/url.php
Normal file
142
common/framework/url.php
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Rhymix\Framework;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL class.
|
||||||
|
*/
|
||||||
|
class URL
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the current URL.
|
||||||
|
*
|
||||||
|
* If $changes are given, they will be appended to the current URL as a query string.
|
||||||
|
* To delete an existing query string, set its value to null.
|
||||||
|
*
|
||||||
|
* @param array $changes
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function getCurrentURL(array $changes = array())
|
||||||
|
{
|
||||||
|
$proto = \RX_SSL ? 'https://' : 'http://';
|
||||||
|
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost';
|
||||||
|
$local = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '/';
|
||||||
|
if (count($changes))
|
||||||
|
{
|
||||||
|
if (($qpos = strpos($local, '?')) !== false)
|
||||||
|
{
|
||||||
|
$querystring = substr($local, $qpos + 1);
|
||||||
|
$local = substr($local, 0, $qpos);
|
||||||
|
parse_str($querystring, $args);
|
||||||
|
$changes = array_merge($args, $changes);
|
||||||
|
}
|
||||||
|
$changes = array_filter($changes, function($val) { return $val !== null; });
|
||||||
|
$local = $local . '?' . http_build_query($changes);
|
||||||
|
}
|
||||||
|
return self::getCanonicalURL($proto . $host) . $local;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a URL to its canonical format.
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function getCanonicalURL($url)
|
||||||
|
{
|
||||||
|
if (preg_match('#^\.?/([^/]|$)#', $url))
|
||||||
|
{
|
||||||
|
$proto = \RX_SSL ? 'https://' : 'http://';
|
||||||
|
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost';
|
||||||
|
$url = $proto . $host . \RX_BASEURL . ltrim($url, './');
|
||||||
|
}
|
||||||
|
return preg_replace_callback('#^(https?:|)//([^/]+)#i', function($matches) {
|
||||||
|
if ($matches[1] === '') $matches[1] = \RX_SSL ? 'https:' : 'http:';
|
||||||
|
return $matches[1] . '//' . self::decodeIdna($matches[2]);
|
||||||
|
}, $url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the domain from a URL.
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
|
public static function getDomainFromURL($url)
|
||||||
|
{
|
||||||
|
$domain = @parse_url($url, \PHP_URL_HOST);
|
||||||
|
if ($domain === false || $domain === null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return self::decodeIdna($domain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a URL is internal to this site.
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function isInternalURL($url)
|
||||||
|
{
|
||||||
|
$domain = self::getDomainFromURL($url);
|
||||||
|
if ($domain === false)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($domain === self::getDomainFromURL($_SERVER['HTTP_HOST']))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($domain === self::getDomainFromURL(\Context::getDefaultUrl()))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode UTF-8 domain into IDNA (punycode)
|
||||||
|
*
|
||||||
|
* @param string $domain
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function encodeIdna($domain)
|
||||||
|
{
|
||||||
|
if (function_exists('idn_to_ascii'))
|
||||||
|
{
|
||||||
|
return idn_to_ascii($domain);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$encoder = new \TrueBV\Punycode();
|
||||||
|
return $encoder->encode($domain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert IDNA (punycode) domain into UTF-8
|
||||||
|
*
|
||||||
|
* @param string $domain
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function decodeIdna($domain)
|
||||||
|
{
|
||||||
|
if (function_exists('idn_to_utf8'))
|
||||||
|
{
|
||||||
|
return idn_to_utf8($domain);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$decoder = new \TrueBV\Punycode();
|
||||||
|
return $decoder->decode($domain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue