/server/lib/Slim/Slim/Http/Util.php
PHP | 389 lines | 182 code | 29 blank | 178 comment | 41 complexity | d8f41593cb8449fd35c14f2580d36436 MD5 | raw file
- <?php
- /**
- * Slim - a micro PHP 5 framework
- *
- * @author Josh Lockhart <info@slimframework.com>
- * @copyright 2011 Josh Lockhart
- * @link http://www.slimframework.com
- * @license http://www.slimframework.com/license
- * @version 2.0.0
- * @package Slim
- *
- * MIT LICENSE
- *
- * 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.
- */
- namespace Slim\Http;
- /**
- * Slim HTTP Utilities
- *
- * This class provides useful methods for handling HTTP requests.
- *
- * @package Slim
- * @author Josh Lockhart
- * @since 1.0.0
- */
- class Util
- {
- /**
- * Strip slashes from string or array
- *
- * This method strips slashes from its input. By default, this method will only
- * strip slashes from its input if magic quotes are enabled. Otherwise, you may
- * override the magic quotes setting with either TRUE or FALSE as the send argument
- * to force this method to strip or not strip slashes from its input.
- *
- * @var array|string $rawData
- * @return array|string
- */
- public static function stripSlashesIfMagicQuotes($rawData, $overrideStripSlashes = null)
- {
- $strip = is_null($overrideStripSlashes) ? get_magic_quotes_gpc() : $overrideStripSlashes;
- if ($strip) {
- return self::_stripSlashes($rawData);
- } else {
- return $rawData;
- }
- }
- /**
- * Strip slashes from string or array
- * @param array|string $rawData
- * @return array|string
- */
- protected static function _stripSlashes($rawData)
- {
- return is_array($rawData) ? array_map(array('self', '_stripSlashes'), $rawData) : stripslashes($rawData);
- }
- /**
- * Encrypt data
- *
- * This method will encrypt data using a given key, vector, and cipher.
- * By default, this will encrypt data using the RIJNDAEL/AES 256 bit cipher. You
- * may override the default cipher and cipher mode by passing your own desired
- * cipher and cipher mode as the final key-value array argument.
- *
- * @param string $data The unencrypted data
- * @param string $key The encryption key
- * @param string $iv The encryption initialization vector
- * @param array $settings Optional key-value array with custom algorithm and mode
- * @return string
- */
- public static function encrypt($data, $key, $iv, $settings = array())
- {
- if ($data === '' || !extension_loaded('mcrypt')) {
- return $data;
- }
- //Merge settings with defaults
- $settings = array_merge(array(
- 'algorithm' => MCRYPT_RIJNDAEL_256,
- 'mode' => MCRYPT_MODE_CBC
- ), $settings);
- //Get module
- $module = mcrypt_module_open($settings['algorithm'], '', $settings['mode'], '');
- //Validate IV
- $ivSize = mcrypt_enc_get_iv_size($module);
- if (strlen($iv) > $ivSize) {
- $iv = substr($iv, 0, $ivSize);
- }
- //Validate key
- $keySize = mcrypt_enc_get_key_size($module);
- if (strlen($key) > $keySize) {
- $key = substr($key, 0, $keySize);
- }
- //Encrypt value
- mcrypt_generic_init($module, $key, $iv);
- $res = @mcrypt_generic($module, $data);
- mcrypt_generic_deinit($module);
- return $res;
- }
- /**
- * Decrypt data
- *
- * This method will decrypt data using a given key, vector, and cipher.
- * By default, this will decrypt data using the RIJNDAEL/AES 256 bit cipher. You
- * may override the default cipher and cipher mode by passing your own desired
- * cipher and cipher mode as the final key-value array argument.
- *
- * @param string $data The encrypted data
- * @param string $key The encryption key
- * @param string $iv The encryption initialization vector
- * @param array $settings Optional key-value array with custom algorithm and mode
- * @return string
- */
- public static function decrypt($data, $key, $iv, $settings = array())
- {
- if ($data === '' || !extension_loaded('mcrypt')) {
- return $data;
- }
- //Merge settings with defaults
- $settings = array_merge(array(
- 'algorithm' => MCRYPT_RIJNDAEL_256,
- 'mode' => MCRYPT_MODE_CBC
- ), $settings);
- //Get module
- $module = mcrypt_module_open($settings['algorithm'], '', $settings['mode'], '');
- //Validate IV
- $ivSize = mcrypt_enc_get_iv_size($module);
- if (strlen($iv) > $ivSize) {
- $iv = substr($iv, 0, $ivSize);
- }
- //Validate key
- $keySize = mcrypt_enc_get_key_size($module);
- if (strlen($key) > $keySize) {
- $key = substr($key, 0, $keySize);
- }
- //Decrypt value
- mcrypt_generic_init($module, $key, $iv);
- $decryptedData = @mdecrypt_generic($module, $data);
- $res = str_replace("\x0", '', $decryptedData);
- mcrypt_generic_deinit($module);
- return $res;
- }
- /**
- * Encode secure cookie value
- *
- * This method will create the secure value of an HTTP cookie. The
- * cookie value is encrypted and hashed so that its value is
- * secure and checked for integrity when read in subsequent requests.
- *
- * @param string $value The unsecure HTTP cookie value
- * @param int $expires The UNIX timestamp at which this cookie will expire
- * @param string $secret The secret key used to hash the cookie value
- * @param int $algorithm The algorithm to use for encryption
- * @param int $mode The algorithm mode to use for encryption
- * @param string
- */
- public static function encodeSecureCookie($value, $expires, $secret, $algorithm, $mode)
- {
- $key = hash_hmac('sha1', $expires, $secret);
- $iv = self::get_iv($expires, $secret);
- $secureString = base64_encode(self::encrypt($value, $key, $iv, array(
- 'algorithm' => $algorithm,
- 'mode' => $mode
- )));
- $verificationString = hash_hmac('sha1', $expires . $value, $key);
- return implode('|', array($expires, $secureString, $verificationString));
- }
- /**
- * Decode secure cookie value
- *
- * This method will decode the secure value of an HTTP cookie. The
- * cookie value is encrypted and hashed so that its value is
- * secure and checked for integrity when read in subsequent requests.
- *
- * @param string $value The secure HTTP cookie value
- * @param int $expires The UNIX timestamp at which this cookie will expire
- * @param string $secret The secret key used to hash the cookie value
- * @param int $algorithm The algorithm to use for encryption
- * @param int $mode The algorithm mode to use for encryption
- * @param string
- */
- public static function decodeSecureCookie($value, $secret, $algorithm, $mode)
- {
- if ($value) {
- $value = explode('|', $value);
- if (count($value) === 3 && ((int) $value[0] === 0 || (int) $value[0] > time())) {
- $key = hash_hmac('sha1', $value[0], $secret);
- $iv = self::get_iv($value[0], $secret);
- $data = self::decrypt(base64_decode($value[1]), $key, $iv, array(
- 'algorithm' => $algorithm,
- 'mode' => $mode
- ));
- $verificationString = hash_hmac('sha1', $value[0] . $data, $key);
- if ($verificationString === $value[2]) {
- return $data;
- }
- }
- }
- return false;
- }
- /**
- * Set HTTP cookie header
- *
- * This method will construct and set the HTTP `Set-Cookie` header. Slim
- * uses this method instead of PHP's native `setcookie` method. This allows
- * more control of the HTTP header irrespective of the native implementation's
- * dependency on PHP versions.
- *
- * This method accepts the Slim_Http_Headers object by reference as its
- * first argument; this method directly modifies this object instead of
- * returning a value.
- *
- * @param array $header
- * @param string $name
- * @param string $value
- */
- public static function setCookieHeader(&$header, $name, $value)
- {
- //Build cookie header
- if (is_array($value)) {
- $domain = '';
- $path = '';
- $expires = '';
- $secure = '';
- $httponly = '';
- if (isset($value['domain']) && $value['domain']) {
- $domain = '; domain=' . $value['domain'];
- }
- if (isset($value['path']) && $value['path']) {
- $path = '; path=' . $value['path'];
- }
- if (isset($value['expires'])) {
- if (is_string($value['expires'])) {
- $timestamp = strtotime($value['expires']);
- } else {
- $timestamp = (int) $value['expires'];
- }
- if ($timestamp !== 0) {
- $expires = '; expires=' . gmdate('D, d-M-Y H:i:s e', $timestamp);
- }
- }
- if (isset($value['secure']) && $value['secure']) {
- $secure = '; secure';
- }
- if (isset($value['httponly']) && $value['httponly']) {
- $httponly = '; HttpOnly';
- }
- $cookie = sprintf('%s=%s%s', urlencode($name), urlencode((string) $value['value']), $domain . $path . $expires . $secure . $httponly);
- } else {
- $cookie = sprintf('%s=%s', urlencode($name), urlencode((string) $value));
- }
- //Set cookie header
- if (!isset($header['Set-Cookie']) || $header['Set-Cookie'] === '') {
- $header['Set-Cookie'] = $cookie;
- } else {
- $header['Set-Cookie'] = implode("\n", array($header['Set-Cookie'], $cookie));
- }
- }
- /**
- * Delete HTTP cookie header
- *
- * This method will construct and set the HTTP `Set-Cookie` header to invalidate
- * a client-side HTTP cookie. If a cookie with the same name (and, optionally, domain)
- * is already set in the HTTP response, it will also be removed. Slim uses this method
- * instead of PHP's native `setcookie` method. This allows more control of the HTTP header
- * irrespective of PHP's native implementation's dependency on PHP versions.
- *
- * This method accepts the Slim_Http_Headers object by reference as its
- * first argument; this method directly modifies this object instead of
- * returning a value.
- *
- * @param array $header
- * @param string $name
- * @param string $value
- */
- public static function deleteCookieHeader(&$header, $name, $value = array())
- {
- //Remove affected cookies from current response header
- $cookiesOld = array();
- $cookiesNew = array();
- if (isset($header['Set-Cookie'])) {
- $cookiesOld = explode("\n", $header['Set-Cookie']);
- }
- foreach ($cookiesOld as $c) {
- if (isset($value['domain']) && $value['domain']) {
- $regex = sprintf('@%s=.*domain=%s@', urlencode($name), preg_quote($value['domain']));
- } else {
- $regex = sprintf('@%s=@', urlencode($name));
- }
- if (preg_match($regex, $c) === 0) {
- $cookiesNew[] = $c;
- }
- }
- if ($cookiesNew) {
- $header['Set-Cookie'] = implode("\n", $cookiesNew);
- } else {
- unset($header['Set-Cookie']);
- }
- //Set invalidating cookie to clear client-side cookie
- self::setCookieHeader($header, $name, array_merge(array('value' => '', 'path' => null, 'domain' => null, 'expires' => time() - 100), $value));
- }
- /**
- * Parse cookie header
- *
- * This method will parse the HTTP requst's `Cookie` header
- * and extract cookies into an associative array.
- *
- * @param string
- * @return array
- */
- public static function parseCookieHeader($header)
- {
- $cookies = array();
- $header = rtrim($header, "\r\n");
- $headerPieces = preg_split('@\s*[;,]\s*@', $header);
- foreach ($headerPieces as $c) {
- $cParts = explode('=', $c);
- if (count($cParts) === 2) {
- $key = urldecode($cParts[0]);
- $value = urldecode($cParts[1]);
- if (!isset($cookies[$key])) {
- $cookies[$key] = $value;
- }
- }
- }
- return $cookies;
- }
- /**
- * Generate a random IV
- *
- * This method will generate a non-predictable IV for use with
- * the cookie encryption
- *
- * @param int $expires The UNIX timestamp at which this cookie will expire
- * @param string $secret The secret key used to hash the cookie value
- * @return binary string with length 40
- */
- private static function get_iv($expires, $secret)
- {
- $data1 = hash_hmac('sha1', 'a'.$expires.'b', $secret);
- $data2 = hash_hmac('sha1', 'z'.$expires.'y', $secret);
- return pack("h*", $data1.$data2);
- }
- }