rpicms

A CMS for the Raspberry Pi
git clone git://archive.git.mtrnord.blog/RpicmsTeam/rpicms.git
Log | Files | Refs | README | LICENSE

Util.php (15795B)


      1 <?php
      2 /**
      3  * Slim - a micro PHP 5 framework
      4  *
      5  * @author      Josh Lockhart <info@slimframework.com>
      6  * @copyright   2011 Josh Lockhart
      7  * @link        http://www.slimframework.com
      8  * @license     http://www.slimframework.com/license
      9  * @version     2.4.2
     10  * @package     Slim
     11  *
     12  * MIT LICENSE
     13  *
     14  * Permission is hereby granted, free of charge, to any person obtaining
     15  * a copy of this software and associated documentation files (the
     16  * "Software"), to deal in the Software without restriction, including
     17  * without limitation the rights to use, copy, modify, merge, publish,
     18  * distribute, sublicense, and/or sell copies of the Software, and to
     19  * permit persons to whom the Software is furnished to do so, subject to
     20  * the following conditions:
     21  *
     22  * The above copyright notice and this permission notice shall be
     23  * included in all copies or substantial portions of the Software.
     24  *
     25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     26  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     27  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     28  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
     29  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     30  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     31  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     32  */
     33 namespace Slim\Http;
     34 
     35 /**
     36  * Slim HTTP Utilities
     37  *
     38  * This class provides useful methods for handling HTTP requests.
     39  *
     40  * @package Slim
     41  * @author  Josh Lockhart
     42  * @since   1.0.0
     43  */
     44 class Util
     45 {
     46     /**
     47      * Strip slashes from string or array
     48      *
     49      * This method strips slashes from its input. By default, this method will only
     50      * strip slashes from its input if magic quotes are enabled. Otherwise, you may
     51      * override the magic quotes setting with either TRUE or FALSE as the send argument
     52      * to force this method to strip or not strip slashes from its input.
     53      *
     54      * @param  array|string    $rawData
     55      * @param  bool            $overrideStripSlashes
     56      * @return array|string
     57      */
     58     public static function stripSlashesIfMagicQuotes($rawData, $overrideStripSlashes = null)
     59     {
     60         $strip = is_null($overrideStripSlashes) ? get_magic_quotes_gpc() : $overrideStripSlashes;
     61         if ($strip) {
     62             return self::stripSlashes($rawData);
     63         } else {
     64             return $rawData;
     65         }
     66     }
     67 
     68     /**
     69      * Strip slashes from string or array
     70      * @param  array|string $rawData
     71      * @return array|string
     72      */
     73     protected static function stripSlashes($rawData)
     74     {
     75         return is_array($rawData) ? array_map(array('self', 'stripSlashes'), $rawData) : stripslashes($rawData);
     76     }
     77 
     78     /**
     79      * Encrypt data
     80      *
     81      * This method will encrypt data using a given key, vector, and cipher.
     82      * By default, this will encrypt data using the RIJNDAEL/AES 256 bit cipher. You
     83      * may override the default cipher and cipher mode by passing your own desired
     84      * cipher and cipher mode as the final key-value array argument.
     85      *
     86      * @param  string $data     The unencrypted data
     87      * @param  string $key      The encryption key
     88      * @param  string $iv       The encryption initialization vector
     89      * @param  array  $settings Optional key-value array with custom algorithm and mode
     90      * @return string
     91      */
     92     public static function encrypt($data, $key, $iv, $settings = array())
     93     {
     94         if ($data === '' || !extension_loaded('mcrypt')) {
     95             return $data;
     96         }
     97 
     98         //Merge settings with defaults
     99         $defaults = array(
    100             'algorithm' => MCRYPT_RIJNDAEL_256,
    101             'mode' => MCRYPT_MODE_CBC
    102         );
    103         $settings = array_merge($defaults, $settings);
    104 
    105         //Get module
    106         $module = mcrypt_module_open($settings['algorithm'], '', $settings['mode'], '');
    107 
    108         //Validate IV
    109         $ivSize = mcrypt_enc_get_iv_size($module);
    110         if (strlen($iv) > $ivSize) {
    111             $iv = substr($iv, 0, $ivSize);
    112         }
    113 
    114         //Validate key
    115         $keySize = mcrypt_enc_get_key_size($module);
    116         if (strlen($key) > $keySize) {
    117             $key = substr($key, 0, $keySize);
    118         }
    119 
    120         //Encrypt value
    121         mcrypt_generic_init($module, $key, $iv);
    122         $res = @mcrypt_generic($module, $data);
    123         mcrypt_generic_deinit($module);
    124 
    125         return $res;
    126     }
    127 
    128     /**
    129      * Decrypt data
    130      *
    131      * This method will decrypt data using a given key, vector, and cipher.
    132      * By default, this will decrypt data using the RIJNDAEL/AES 256 bit cipher. You
    133      * may override the default cipher and cipher mode by passing your own desired
    134      * cipher and cipher mode as the final key-value array argument.
    135      *
    136      * @param  string $data     The encrypted data
    137      * @param  string $key      The encryption key
    138      * @param  string $iv       The encryption initialization vector
    139      * @param  array  $settings Optional key-value array with custom algorithm and mode
    140      * @return string
    141      */
    142     public static function decrypt($data, $key, $iv, $settings = array())
    143     {
    144         if ($data === '' || !extension_loaded('mcrypt')) {
    145             return $data;
    146         }
    147 
    148         //Merge settings with defaults
    149         $defaults = array(
    150             'algorithm' => MCRYPT_RIJNDAEL_256,
    151             'mode' => MCRYPT_MODE_CBC
    152         );
    153         $settings = array_merge($defaults, $settings);
    154 
    155         //Get module
    156         $module = mcrypt_module_open($settings['algorithm'], '', $settings['mode'], '');
    157 
    158         //Validate IV
    159         $ivSize = mcrypt_enc_get_iv_size($module);
    160         if (strlen($iv) > $ivSize) {
    161             $iv = substr($iv, 0, $ivSize);
    162         }
    163 
    164         //Validate key
    165         $keySize = mcrypt_enc_get_key_size($module);
    166         if (strlen($key) > $keySize) {
    167             $key = substr($key, 0, $keySize);
    168         }
    169 
    170         //Decrypt value
    171         mcrypt_generic_init($module, $key, $iv);
    172         $decryptedData = @mdecrypt_generic($module, $data);
    173         $res = rtrim($decryptedData, "\0");
    174         mcrypt_generic_deinit($module);
    175 
    176         return $res;
    177     }
    178 
    179     /**
    180      * Serialize Response cookies into raw HTTP header
    181      * @param  \Slim\Http\Headers $headers The Response headers
    182      * @param  \Slim\Http\Cookies $cookies The Response cookies
    183      * @param  array              $config  The Slim app settings
    184      */
    185     public static function serializeCookies(\Slim\Http\Headers &$headers, \Slim\Http\Cookies $cookies, array $config)
    186     {
    187         if ($config['cookies.encrypt']) {
    188             foreach ($cookies as $name => $settings) {
    189                 if (is_string($settings['expires'])) {
    190                     $expires = strtotime($settings['expires']);
    191                 } else {
    192                     $expires = (int) $settings['expires'];
    193                 }
    194 
    195                 $settings['value'] = static::encodeSecureCookie(
    196                     $settings['value'],
    197                     $expires,
    198                     $config['cookies.secret_key'],
    199                     $config['cookies.cipher'],
    200                     $config['cookies.cipher_mode']
    201                 );
    202                 static::setCookieHeader($headers, $name, $settings);
    203             }
    204         } else {
    205             foreach ($cookies as $name => $settings) {
    206                 static::setCookieHeader($headers, $name, $settings);
    207             }
    208         }
    209     }
    210 
    211     /**
    212      * Encode secure cookie value
    213      *
    214      * This method will create the secure value of an HTTP cookie. The
    215      * cookie value is encrypted and hashed so that its value is
    216      * secure and checked for integrity when read in subsequent requests.
    217      *
    218      * @param string $value     The insecure HTTP cookie value
    219      * @param int    $expires   The UNIX timestamp at which this cookie will expire
    220      * @param string $secret    The secret key used to hash the cookie value
    221      * @param int    $algorithm The algorithm to use for encryption
    222      * @param int    $mode      The algorithm mode to use for encryption
    223      * @return string
    224      */
    225     public static function encodeSecureCookie($value, $expires, $secret, $algorithm, $mode)
    226     {
    227         $key = hash_hmac('sha1', (string) $expires, $secret);
    228         $iv = self::getIv($expires, $secret);
    229         $secureString = base64_encode(
    230             self::encrypt(
    231                 $value,
    232                 $key,
    233                 $iv,
    234                 array(
    235                     'algorithm' => $algorithm,
    236                     'mode' => $mode
    237                 )
    238             )
    239         );
    240         $verificationString = hash_hmac('sha1', $expires . $value, $key);
    241 
    242         return implode('|', array($expires, $secureString, $verificationString));
    243     }
    244 
    245     /**
    246      * Decode secure cookie value
    247      *
    248      * This method will decode the secure value of an HTTP cookie. The
    249      * cookie value is encrypted and hashed so that its value is
    250      * secure and checked for integrity when read in subsequent requests.
    251      *
    252      * @param string $value     The secure HTTP cookie value
    253      * @param string $secret    The secret key used to hash the cookie value
    254      * @param int    $algorithm The algorithm to use for encryption
    255      * @param int    $mode      The algorithm mode to use for encryption
    256      * @return bool|string
    257      */
    258     public static function decodeSecureCookie($value, $secret, $algorithm, $mode)
    259     {
    260         if ($value) {
    261             $value = explode('|', $value);
    262             if (count($value) === 3 && ((int) $value[0] === 0 || (int) $value[0] > time())) {
    263                 $key = hash_hmac('sha1', $value[0], $secret);
    264                 $iv = self::getIv($value[0], $secret);
    265                 $data = self::decrypt(
    266                     base64_decode($value[1]),
    267                     $key,
    268                     $iv,
    269                     array(
    270                         'algorithm' => $algorithm,
    271                         'mode' => $mode
    272                     )
    273                 );
    274                 $verificationString = hash_hmac('sha1', $value[0] . $data, $key);
    275                 if ($verificationString === $value[2]) {
    276                     return $data;
    277                 }
    278             }
    279         }
    280 
    281         return false;
    282     }
    283 
    284     /**
    285      * Set HTTP cookie header
    286      *
    287      * This method will construct and set the HTTP `Set-Cookie` header. Slim
    288      * uses this method instead of PHP's native `setcookie` method. This allows
    289      * more control of the HTTP header irrespective of the native implementation's
    290      * dependency on PHP versions.
    291      *
    292      * This method accepts the Slim_Http_Headers object by reference as its
    293      * first argument; this method directly modifies this object instead of
    294      * returning a value.
    295      *
    296      * @param  array  $header
    297      * @param  string $name
    298      * @param  string $value
    299      */
    300     public static function setCookieHeader(&$header, $name, $value)
    301     {
    302         //Build cookie header
    303         if (is_array($value)) {
    304             $domain = '';
    305             $path = '';
    306             $expires = '';
    307             $secure = '';
    308             $httponly = '';
    309             if (isset($value['domain']) && $value['domain']) {
    310                 $domain = '; domain=' . $value['domain'];
    311             }
    312             if (isset($value['path']) && $value['path']) {
    313                 $path = '; path=' . $value['path'];
    314             }
    315             if (isset($value['expires'])) {
    316                 if (is_string($value['expires'])) {
    317                     $timestamp = strtotime($value['expires']);
    318                 } else {
    319                     $timestamp = (int) $value['expires'];
    320                 }
    321                 if ($timestamp !== 0) {
    322                     $expires = '; expires=' . gmdate('D, d-M-Y H:i:s e', $timestamp);
    323                 }
    324             }
    325             if (isset($value['secure']) && $value['secure']) {
    326                 $secure = '; secure';
    327             }
    328             if (isset($value['httponly']) && $value['httponly']) {
    329                 $httponly = '; HttpOnly';
    330             }
    331             $cookie = sprintf('%s=%s%s', urlencode($name), urlencode((string) $value['value']), $domain . $path . $expires . $secure . $httponly);
    332         } else {
    333             $cookie = sprintf('%s=%s', urlencode($name), urlencode((string) $value));
    334         }
    335 
    336         //Set cookie header
    337         if (!isset($header['Set-Cookie']) || $header['Set-Cookie'] === '') {
    338             $header['Set-Cookie'] = $cookie;
    339         } else {
    340             $header['Set-Cookie'] = implode("\n", array($header['Set-Cookie'], $cookie));
    341         }
    342     }
    343 
    344     /**
    345      * Delete HTTP cookie header
    346      *
    347      * This method will construct and set the HTTP `Set-Cookie` header to invalidate
    348      * a client-side HTTP cookie. If a cookie with the same name (and, optionally, domain)
    349      * is already set in the HTTP response, it will also be removed. Slim uses this method
    350      * instead of PHP's native `setcookie` method. This allows more control of the HTTP header
    351      * irrespective of PHP's native implementation's dependency on PHP versions.
    352      *
    353      * This method accepts the Slim_Http_Headers object by reference as its
    354      * first argument; this method directly modifies this object instead of
    355      * returning a value.
    356      *
    357      * @param  array  $header
    358      * @param  string $name
    359      * @param  array  $value
    360      */
    361     public static function deleteCookieHeader(&$header, $name, $value = array())
    362     {
    363         //Remove affected cookies from current response header
    364         $cookiesOld = array();
    365         $cookiesNew = array();
    366         if (isset($header['Set-Cookie'])) {
    367             $cookiesOld = explode("\n", $header['Set-Cookie']);
    368         }
    369         foreach ($cookiesOld as $c) {
    370             if (isset($value['domain']) && $value['domain']) {
    371                 $regex = sprintf('@%s=.*domain=%s@', urlencode($name), preg_quote($value['domain']));
    372             } else {
    373                 $regex = sprintf('@%s=@', urlencode($name));
    374             }
    375             if (preg_match($regex, $c) === 0) {
    376                 $cookiesNew[] = $c;
    377             }
    378         }
    379         if ($cookiesNew) {
    380             $header['Set-Cookie'] = implode("\n", $cookiesNew);
    381         } else {
    382             unset($header['Set-Cookie']);
    383         }
    384 
    385         //Set invalidating cookie to clear client-side cookie
    386         self::setCookieHeader($header, $name, array_merge(array('value' => '', 'path' => null, 'domain' => null, 'expires' => time() - 100), $value));
    387     }
    388 
    389     /**
    390      * Parse cookie header
    391      *
    392      * This method will parse the HTTP request's `Cookie` header
    393      * and extract cookies into an associative array.
    394      *
    395      * @param  string
    396      * @return array
    397      */
    398     public static function parseCookieHeader($header)
    399     {
    400         $cookies = array();
    401         $header = rtrim($header, "\r\n");
    402         $headerPieces = preg_split('@\s*[;,]\s*@', $header);
    403         foreach ($headerPieces as $c) {
    404             $cParts = explode('=', $c, 2);
    405             if (count($cParts) === 2) {
    406                 $key = urldecode($cParts[0]);
    407                 $value = urldecode($cParts[1]);
    408                 if (!isset($cookies[$key])) {
    409                     $cookies[$key] = $value;
    410                 }
    411             }
    412         }
    413 
    414         return $cookies;
    415     }
    416 
    417     /**
    418      * Generate a random IV
    419      *
    420      * This method will generate a non-predictable IV for use with
    421      * the cookie encryption
    422      *
    423      * @param  int    $expires The UNIX timestamp at which this cookie will expire
    424      * @param  string $secret  The secret key used to hash the cookie value
    425      * @return string Hash
    426      */
    427     private static function getIv($expires, $secret)
    428     {
    429         $data1 = hash_hmac('sha1', 'a'.$expires.'b', $secret);
    430         $data2 = hash_hmac('sha1', 'z'.$expires.'y', $secret);
    431 
    432         return pack("h*", $data1.$data2);
    433     }
    434 }