├── README.md ├── angular-crud.sql ├── api ├── .htaccess ├── Slim │ ├── Environment.php │ ├── Exception │ │ ├── Pass.php │ │ └── Stop.php │ ├── Helper │ │ └── Set.php │ ├── Http │ │ ├── Cookies.php │ │ ├── Headers.php │ │ ├── Request.php │ │ ├── Response.php │ │ └── Util.php │ ├── Log.php │ ├── LogWriter.php │ ├── Middleware.php │ ├── Middleware │ │ ├── ContentTypes.php │ │ ├── Flash.php │ │ ├── MethodOverride.php │ │ ├── PrettyExceptions.php │ │ └── SessionCookie.php │ ├── Route.php │ ├── Router.php │ ├── Slim.php │ └── View.php └── index.php ├── assets ├── js │ ├── add │ │ ├── add.controller.js │ │ ├── add.html │ │ └── add.module.js │ ├── app.js │ ├── config │ │ ├── config.module.js │ │ └── config.routes.js │ ├── edit │ │ ├── edit.controller.js │ │ ├── edit.html │ │ └── edit.module.js │ └── home │ │ ├── home.controller.js │ │ ├── home.html │ │ └── home.module.js ├── styles │ └── main.css └── vendor │ ├── angular-loading │ ├── loading-bar.min.css │ └── loading-bar.min.js │ ├── angular-ui-router.min.js │ ├── angular.min.js │ ├── boostrap │ ├── css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ └── bootstrap.min.css │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ └── js │ │ └── bootstrap.min.js │ └── jquery-1.11.2.min.js └── index.html /README.md: -------------------------------------------------------------------------------- 1 | PHP-Angular-MYSQL CRUD 2 | ====================== 3 | 4 | An example CRUD application using AngularJS, Slim PHP framework and MySql. 5 | 6 | Requirements: 7 | * AngularJS 8 | * Slim Framework -------------------------------------------------------------------------------- /angular-crud.sql: -------------------------------------------------------------------------------- 1 | -- phpMyAdmin SQL Dump 2 | -- version 4.0.10deb1 3 | -- http://www.phpmyadmin.net 4 | -- 5 | -- Host: localhost 6 | -- Generation Time: Apr 12, 2015 at 10:50 PM 7 | -- Server version: 5.5.41-0ubuntu0.14.04.1 8 | -- PHP Version: 5.5.9-1ubuntu4.7 9 | 10 | SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; 11 | SET time_zone = "+00:00"; 12 | 13 | 14 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 15 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 16 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 17 | /*!40101 SET NAMES utf8 */; 18 | 19 | -- 20 | -- Database: `angular-crud` 21 | -- 22 | 23 | -- -------------------------------------------------------- 24 | 25 | -- 26 | -- Table structure for table `products` 27 | -- 28 | 29 | CREATE TABLE IF NOT EXISTS `products` ( 30 | `product_id` int(10) NOT NULL AUTO_INCREMENT, 31 | `product_name` varchar(500) NOT NULL, 32 | `product_description` varchar(500) NOT NULL, 33 | `product_price` int(10) NOT NULL, 34 | `product_stock` int(10) NOT NULL, 35 | `deleted` tinyint(1) DEFAULT '0', 36 | PRIMARY KEY (`product_id`) 37 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=67 ; 38 | 39 | -- 40 | -- Table structure for table `users` 41 | -- 42 | 43 | CREATE TABLE IF NOT EXISTS `users` ( 44 | `id` int(11) NOT NULL AUTO_INCREMENT, 45 | `username` varchar(255) NOT NULL, 46 | `password` varchar(50) NOT NULL, 47 | `first_name` varchar(100) NOT NULL, 48 | `last_name` varchar(100) NOT NULL, 49 | `address` varchar(255) DEFAULT NULL, 50 | PRIMARY KEY (`id`) 51 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ; 52 | 53 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 54 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 55 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 56 | -------------------------------------------------------------------------------- /api/.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine On 2 | 3 | # Some hosts may require you to use the `RewriteBase` directive. 4 | # If you need to use the `RewriteBase` directive, it should be the 5 | # absolute physical path to the directory that contains this htaccess file. 6 | # 7 | # RewriteBase / 8 | 9 | RewriteCond %{REQUEST_FILENAME} !-f 10 | RewriteRule ^(.*)$ index.php [QSA,L] -------------------------------------------------------------------------------- /api/Slim/Environment.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 2.6.1 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; 34 | 35 | /** 36 | * Environment 37 | * 38 | * This class creates and returns a key/value array of common 39 | * environment variables for the current HTTP request. 40 | * 41 | * This is a singleton class; derived environment variables will 42 | * be common across multiple Slim applications. 43 | * 44 | * This class matches the Rack (Ruby) specification as closely 45 | * as possible. More information available below. 46 | * 47 | * @package Slim 48 | * @author Josh Lockhart 49 | * @since 1.6.0 50 | */ 51 | class Environment implements \ArrayAccess, \IteratorAggregate 52 | { 53 | /** 54 | * @var array 55 | */ 56 | protected $properties; 57 | 58 | /** 59 | * @var \Slim\Environment 60 | */ 61 | protected static $environment; 62 | 63 | /** 64 | * Get environment instance (singleton) 65 | * 66 | * This creates and/or returns an environment instance (singleton) 67 | * derived from $_SERVER variables. You may override the global server 68 | * variables by using `\Slim\Environment::mock()` instead. 69 | * 70 | * @param bool $refresh Refresh properties using global server variables? 71 | * @return \Slim\Environment 72 | */ 73 | public static function getInstance($refresh = false) 74 | { 75 | if (is_null(self::$environment) || $refresh) { 76 | self::$environment = new self(); 77 | } 78 | 79 | return self::$environment; 80 | } 81 | 82 | /** 83 | * Get mock environment instance 84 | * 85 | * @param array $userSettings 86 | * @return \Slim\Environment 87 | */ 88 | public static function mock($userSettings = array()) 89 | { 90 | $defaults = array( 91 | 'REQUEST_METHOD' => 'GET', 92 | 'SCRIPT_NAME' => '', 93 | 'PATH_INFO' => '', 94 | 'QUERY_STRING' => '', 95 | 'SERVER_NAME' => 'localhost', 96 | 'SERVER_PORT' => 80, 97 | 'ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 98 | 'ACCEPT_LANGUAGE' => 'en-US,en;q=0.8', 99 | 'ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.3', 100 | 'USER_AGENT' => 'Slim Framework', 101 | 'REMOTE_ADDR' => '127.0.0.1', 102 | 'slim.url_scheme' => 'http', 103 | 'slim.input' => '', 104 | 'slim.errors' => @fopen('php://stderr', 'w') 105 | ); 106 | self::$environment = new self(array_merge($defaults, $userSettings)); 107 | 108 | return self::$environment; 109 | } 110 | 111 | /** 112 | * Constructor (private access) 113 | * 114 | * @param array|null $settings If present, these are used instead of global server variables 115 | */ 116 | private function __construct($settings = null) 117 | { 118 | if ($settings) { 119 | $this->properties = $settings; 120 | } else { 121 | $env = array(); 122 | 123 | //The HTTP request method 124 | $env['REQUEST_METHOD'] = $_SERVER['REQUEST_METHOD']; 125 | 126 | //The IP 127 | $env['REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR']; 128 | 129 | // Server params 130 | $scriptName = $_SERVER['SCRIPT_NAME']; // <-- "/foo/index.php" 131 | $requestUri = $_SERVER['REQUEST_URI']; // <-- "/foo/bar?test=abc" or "/foo/index.php/bar?test=abc" 132 | $queryString = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : ''; // <-- "test=abc" or "" 133 | 134 | // Physical path 135 | if (strpos($requestUri, $scriptName) !== false) { 136 | $physicalPath = $scriptName; // <-- Without rewriting 137 | } else { 138 | $physicalPath = str_replace('\\', '', dirname($scriptName)); // <-- With rewriting 139 | } 140 | $env['SCRIPT_NAME'] = rtrim($physicalPath, '/'); // <-- Remove trailing slashes 141 | 142 | // Virtual path 143 | $env['PATH_INFO'] = $requestUri; 144 | if (substr($requestUri, 0, strlen($physicalPath)) == $physicalPath) { 145 | $env['PATH_INFO'] = substr($requestUri, strlen($physicalPath)); // <-- Remove physical path 146 | } 147 | $env['PATH_INFO'] = str_replace('?' . $queryString, '', $env['PATH_INFO']); // <-- Remove query string 148 | $env['PATH_INFO'] = '/' . ltrim($env['PATH_INFO'], '/'); // <-- Ensure leading slash 149 | 150 | // Query string (without leading "?") 151 | $env['QUERY_STRING'] = $queryString; 152 | 153 | //Name of server host that is running the script 154 | $env['SERVER_NAME'] = $_SERVER['SERVER_NAME']; 155 | 156 | //Number of server port that is running the script 157 | //Fixes: https://github.com/slimphp/Slim/issues/962 158 | $env['SERVER_PORT'] = isset($_SERVER['SERVER_PORT']) ? $_SERVER['SERVER_PORT'] : 80; 159 | 160 | //HTTP request headers (retains HTTP_ prefix to match $_SERVER) 161 | $headers = \Slim\Http\Headers::extract($_SERVER); 162 | foreach ($headers as $key => $value) { 163 | $env[$key] = $value; 164 | } 165 | 166 | //Is the application running under HTTPS or HTTP protocol? 167 | $env['slim.url_scheme'] = empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] === 'off' ? 'http' : 'https'; 168 | 169 | //Input stream (readable one time only; not available for multipart/form-data requests) 170 | $rawInput = @file_get_contents('php://input'); 171 | if (!$rawInput) { 172 | $rawInput = ''; 173 | } 174 | $env['slim.input'] = $rawInput; 175 | 176 | //Error stream 177 | $env['slim.errors'] = @fopen('php://stderr', 'w'); 178 | 179 | $this->properties = $env; 180 | } 181 | } 182 | 183 | /** 184 | * Array Access: Offset Exists 185 | */ 186 | public function offsetExists($offset) 187 | { 188 | return isset($this->properties[$offset]); 189 | } 190 | 191 | /** 192 | * Array Access: Offset Get 193 | */ 194 | public function offsetGet($offset) 195 | { 196 | if (isset($this->properties[$offset])) { 197 | return $this->properties[$offset]; 198 | } 199 | 200 | return null; 201 | } 202 | 203 | /** 204 | * Array Access: Offset Set 205 | */ 206 | public function offsetSet($offset, $value) 207 | { 208 | $this->properties[$offset] = $value; 209 | } 210 | 211 | /** 212 | * Array Access: Offset Unset 213 | */ 214 | public function offsetUnset($offset) 215 | { 216 | unset($this->properties[$offset]); 217 | } 218 | 219 | /** 220 | * IteratorAggregate 221 | * 222 | * @return \ArrayIterator 223 | */ 224 | public function getIterator() 225 | { 226 | return new \ArrayIterator($this->properties); 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /api/Slim/Exception/Pass.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 2.6.1 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\Exception; 34 | 35 | /** 36 | * Pass Exception 37 | * 38 | * This Exception will cause the Router::dispatch method 39 | * to skip the current matching route and continue to the next 40 | * matching route. If no subsequent routes are found, a 41 | * HTTP 404 Not Found response will be sent to the client. 42 | * 43 | * @package Slim 44 | * @author Josh Lockhart 45 | * @since 1.0.0 46 | */ 47 | class Pass extends \Exception 48 | { 49 | } 50 | -------------------------------------------------------------------------------- /api/Slim/Exception/Stop.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 2.6.1 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\Exception; 34 | 35 | /** 36 | * Stop Exception 37 | * 38 | * This Exception is thrown when the Slim application needs to abort 39 | * processing and return control flow to the outer PHP script. 40 | * 41 | * @package Slim 42 | * @author Josh Lockhart 43 | * @since 1.0.0 44 | */ 45 | class Stop extends \Exception 46 | { 47 | } 48 | -------------------------------------------------------------------------------- /api/Slim/Helper/Set.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 2.6.1 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\Helper; 34 | 35 | class Set implements \ArrayAccess, \Countable, \IteratorAggregate 36 | { 37 | /** 38 | * Key-value array of arbitrary data 39 | * @var array 40 | */ 41 | protected $data = array(); 42 | 43 | /** 44 | * Constructor 45 | * @param array $items Pre-populate set with this key-value array 46 | */ 47 | public function __construct($items = array()) 48 | { 49 | $this->replace($items); 50 | } 51 | 52 | /** 53 | * Normalize data key 54 | * 55 | * Used to transform data key into the necessary 56 | * key format for this set. Used in subclasses 57 | * like \Slim\Http\Headers. 58 | * 59 | * @param string $key The data key 60 | * @return mixed The transformed/normalized data key 61 | */ 62 | protected function normalizeKey($key) 63 | { 64 | return $key; 65 | } 66 | 67 | /** 68 | * Set data key to value 69 | * @param string $key The data key 70 | * @param mixed $value The data value 71 | */ 72 | public function set($key, $value) 73 | { 74 | $this->data[$this->normalizeKey($key)] = $value; 75 | } 76 | 77 | /** 78 | * Get data value with key 79 | * @param string $key The data key 80 | * @param mixed $default The value to return if data key does not exist 81 | * @return mixed The data value, or the default value 82 | */ 83 | public function get($key, $default = null) 84 | { 85 | if ($this->has($key)) { 86 | $isInvokable = is_object($this->data[$this->normalizeKey($key)]) && method_exists($this->data[$this->normalizeKey($key)], '__invoke'); 87 | 88 | return $isInvokable ? $this->data[$this->normalizeKey($key)]($this) : $this->data[$this->normalizeKey($key)]; 89 | } 90 | 91 | return $default; 92 | } 93 | 94 | /** 95 | * Add data to set 96 | * @param array $items Key-value array of data to append to this set 97 | */ 98 | public function replace($items) 99 | { 100 | foreach ($items as $key => $value) { 101 | $this->set($key, $value); // Ensure keys are normalized 102 | } 103 | } 104 | 105 | /** 106 | * Fetch set data 107 | * @return array This set's key-value data array 108 | */ 109 | public function all() 110 | { 111 | return $this->data; 112 | } 113 | 114 | /** 115 | * Fetch set data keys 116 | * @return array This set's key-value data array keys 117 | */ 118 | public function keys() 119 | { 120 | return array_keys($this->data); 121 | } 122 | 123 | /** 124 | * Does this set contain a key? 125 | * @param string $key The data key 126 | * @return boolean 127 | */ 128 | public function has($key) 129 | { 130 | return array_key_exists($this->normalizeKey($key), $this->data); 131 | } 132 | 133 | /** 134 | * Remove value with key from this set 135 | * @param string $key The data key 136 | */ 137 | public function remove($key) 138 | { 139 | unset($this->data[$this->normalizeKey($key)]); 140 | } 141 | 142 | /** 143 | * Property Overloading 144 | */ 145 | 146 | public function __get($key) 147 | { 148 | return $this->get($key); 149 | } 150 | 151 | public function __set($key, $value) 152 | { 153 | $this->set($key, $value); 154 | } 155 | 156 | public function __isset($key) 157 | { 158 | return $this->has($key); 159 | } 160 | 161 | public function __unset($key) 162 | { 163 | $this->remove($key); 164 | } 165 | 166 | /** 167 | * Clear all values 168 | */ 169 | public function clear() 170 | { 171 | $this->data = array(); 172 | } 173 | 174 | /** 175 | * Array Access 176 | */ 177 | 178 | public function offsetExists($offset) 179 | { 180 | return $this->has($offset); 181 | } 182 | 183 | public function offsetGet($offset) 184 | { 185 | return $this->get($offset); 186 | } 187 | 188 | public function offsetSet($offset, $value) 189 | { 190 | $this->set($offset, $value); 191 | } 192 | 193 | public function offsetUnset($offset) 194 | { 195 | $this->remove($offset); 196 | } 197 | 198 | /** 199 | * Countable 200 | */ 201 | 202 | public function count() 203 | { 204 | return count($this->data); 205 | } 206 | 207 | /** 208 | * IteratorAggregate 209 | */ 210 | 211 | public function getIterator() 212 | { 213 | return new \ArrayIterator($this->data); 214 | } 215 | 216 | /** 217 | * Ensure a value or object will remain globally unique 218 | * @param string $key The value or object name 219 | * @param \Closure $value The closure that defines the object 220 | * @return mixed 221 | */ 222 | public function singleton($key, $value) 223 | { 224 | $this->set($key, function ($c) use ($value) { 225 | static $object; 226 | 227 | if (null === $object) { 228 | $object = $value($c); 229 | } 230 | 231 | return $object; 232 | }); 233 | } 234 | 235 | /** 236 | * Protect closure from being directly invoked 237 | * @param \Closure $callable A closure to keep from being invoked and evaluated 238 | * @return \Closure 239 | */ 240 | public function protect(\Closure $callable) 241 | { 242 | return function () use ($callable) { 243 | return $callable; 244 | }; 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /api/Slim/Http/Cookies.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 2.6.1 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 | class Cookies extends \Slim\Helper\Set 36 | { 37 | /** 38 | * Default cookie settings 39 | * @var array 40 | */ 41 | protected $defaults = array( 42 | 'value' => '', 43 | 'domain' => null, 44 | 'path' => null, 45 | 'expires' => null, 46 | 'secure' => false, 47 | 'httponly' => false 48 | ); 49 | 50 | /** 51 | * Set cookie 52 | * 53 | * The second argument may be a single scalar value, in which case 54 | * it will be merged with the default settings and considered the `value` 55 | * of the merged result. 56 | * 57 | * The second argument may also be an array containing any or all of 58 | * the keys shown in the default settings above. This array will be 59 | * merged with the defaults shown above. 60 | * 61 | * @param string $key Cookie name 62 | * @param mixed $value Cookie settings 63 | */ 64 | public function set($key, $value) 65 | { 66 | if (is_array($value)) { 67 | $cookieSettings = array_replace($this->defaults, $value); 68 | } else { 69 | $cookieSettings = array_replace($this->defaults, array('value' => $value)); 70 | } 71 | parent::set($key, $cookieSettings); 72 | } 73 | 74 | /** 75 | * Remove cookie 76 | * 77 | * Unlike \Slim\Helper\Set, this will actually *set* a cookie with 78 | * an expiration date in the past. This expiration date will force 79 | * the client-side cache to remove its cookie with the given name 80 | * and settings. 81 | * 82 | * @param string $key Cookie name 83 | * @param array $settings Optional cookie settings 84 | */ 85 | public function remove($key, $settings = array()) 86 | { 87 | $settings['value'] = ''; 88 | $settings['expires'] = time() - 86400; 89 | $this->set($key, array_replace($this->defaults, $settings)); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /api/Slim/Http/Headers.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 2.6.1 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 | * HTTP Headers 37 | * 38 | * @package Slim 39 | * @author Josh Lockhart 40 | * @since 1.6.0 41 | */ 42 | class Headers extends \Slim\Helper\Set 43 | { 44 | /******************************************************************************** 45 | * Static interface 46 | *******************************************************************************/ 47 | 48 | /** 49 | * Special-case HTTP headers that are otherwise unidentifiable as HTTP headers. 50 | * Typically, HTTP headers in the $_SERVER array will be prefixed with 51 | * `HTTP_` or `X_`. These are not so we list them here for later reference. 52 | * 53 | * @var array 54 | */ 55 | protected static $special = array( 56 | 'CONTENT_TYPE', 57 | 'CONTENT_LENGTH', 58 | 'PHP_AUTH_USER', 59 | 'PHP_AUTH_PW', 60 | 'PHP_AUTH_DIGEST', 61 | 'AUTH_TYPE' 62 | ); 63 | 64 | /** 65 | * Extract HTTP headers from an array of data (e.g. $_SERVER) 66 | * @param array $data 67 | * @return array 68 | */ 69 | public static function extract($data) 70 | { 71 | $results = array(); 72 | foreach ($data as $key => $value) { 73 | $key = strtoupper($key); 74 | if (strpos($key, 'X_') === 0 || strpos($key, 'HTTP_') === 0 || in_array($key, static::$special)) { 75 | if ($key === 'HTTP_CONTENT_LENGTH') { 76 | continue; 77 | } 78 | $results[$key] = $value; 79 | } 80 | } 81 | 82 | return $results; 83 | } 84 | 85 | /******************************************************************************** 86 | * Instance interface 87 | *******************************************************************************/ 88 | 89 | /** 90 | * Transform header name into canonical form 91 | * @param string $key 92 | * @return string 93 | */ 94 | protected function normalizeKey($key) 95 | { 96 | $key = strtolower($key); 97 | $key = str_replace(array('-', '_'), ' ', $key); 98 | $key = preg_replace('#^http #', '', $key); 99 | $key = ucwords($key); 100 | $key = str_replace(' ', '-', $key); 101 | 102 | return $key; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /api/Slim/Http/Request.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 2.6.1 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 Request 37 | * 38 | * This class provides a human-friendly interface to the Slim environment variables; 39 | * environment variables are passed by reference and will be modified directly. 40 | * 41 | * @package Slim 42 | * @author Josh Lockhart 43 | * @since 1.0.0 44 | */ 45 | class Request 46 | { 47 | const METHOD_HEAD = 'HEAD'; 48 | const METHOD_GET = 'GET'; 49 | const METHOD_POST = 'POST'; 50 | const METHOD_PUT = 'PUT'; 51 | const METHOD_PATCH = 'PATCH'; 52 | const METHOD_DELETE = 'DELETE'; 53 | const METHOD_OPTIONS = 'OPTIONS'; 54 | const METHOD_OVERRIDE = '_METHOD'; 55 | 56 | /** 57 | * @var array 58 | */ 59 | protected static $formDataMediaTypes = array('application/x-www-form-urlencoded'); 60 | 61 | /** 62 | * Application Environment 63 | * @var \Slim\Environment 64 | */ 65 | protected $env; 66 | 67 | /** 68 | * HTTP Headers 69 | * @var \Slim\Http\Headers 70 | */ 71 | public $headers; 72 | 73 | /** 74 | * HTTP Cookies 75 | * @var \Slim\Helper\Set 76 | */ 77 | public $cookies; 78 | 79 | /** 80 | * Constructor 81 | * @param \Slim\Environment $env 82 | */ 83 | public function __construct(\Slim\Environment $env) 84 | { 85 | $this->env = $env; 86 | $this->headers = new \Slim\Http\Headers(\Slim\Http\Headers::extract($env)); 87 | $this->cookies = new \Slim\Helper\Set(\Slim\Http\Util::parseCookieHeader($env['HTTP_COOKIE'])); 88 | } 89 | 90 | /** 91 | * Get HTTP method 92 | * @return string 93 | */ 94 | public function getMethod() 95 | { 96 | return $this->env['REQUEST_METHOD']; 97 | } 98 | 99 | /** 100 | * Is this a GET request? 101 | * @return bool 102 | */ 103 | public function isGet() 104 | { 105 | return $this->getMethod() === self::METHOD_GET; 106 | } 107 | 108 | /** 109 | * Is this a POST request? 110 | * @return bool 111 | */ 112 | public function isPost() 113 | { 114 | return $this->getMethod() === self::METHOD_POST; 115 | } 116 | 117 | /** 118 | * Is this a PUT request? 119 | * @return bool 120 | */ 121 | public function isPut() 122 | { 123 | return $this->getMethod() === self::METHOD_PUT; 124 | } 125 | 126 | /** 127 | * Is this a PATCH request? 128 | * @return bool 129 | */ 130 | public function isPatch() 131 | { 132 | return $this->getMethod() === self::METHOD_PATCH; 133 | } 134 | 135 | /** 136 | * Is this a DELETE request? 137 | * @return bool 138 | */ 139 | public function isDelete() 140 | { 141 | return $this->getMethod() === self::METHOD_DELETE; 142 | } 143 | 144 | /** 145 | * Is this a HEAD request? 146 | * @return bool 147 | */ 148 | public function isHead() 149 | { 150 | return $this->getMethod() === self::METHOD_HEAD; 151 | } 152 | 153 | /** 154 | * Is this a OPTIONS request? 155 | * @return bool 156 | */ 157 | public function isOptions() 158 | { 159 | return $this->getMethod() === self::METHOD_OPTIONS; 160 | } 161 | 162 | /** 163 | * Is this an AJAX request? 164 | * @return bool 165 | */ 166 | public function isAjax() 167 | { 168 | if ($this->params('isajax')) { 169 | return true; 170 | } elseif (isset($this->headers['X_REQUESTED_WITH']) && $this->headers['X_REQUESTED_WITH'] === 'XMLHttpRequest') { 171 | return true; 172 | } 173 | 174 | return false; 175 | } 176 | 177 | /** 178 | * Is this an XHR request? (alias of Slim_Http_Request::isAjax) 179 | * @return bool 180 | */ 181 | public function isXhr() 182 | { 183 | return $this->isAjax(); 184 | } 185 | 186 | /** 187 | * Fetch GET and POST data 188 | * 189 | * This method returns a union of GET and POST data as a key-value array, or the value 190 | * of the array key if requested; if the array key does not exist, NULL is returned, 191 | * unless there is a default value specified. 192 | * 193 | * @param string $key 194 | * @param mixed $default 195 | * @return array|mixed|null 196 | */ 197 | public function params($key = null, $default = null) 198 | { 199 | $union = array_merge($this->get(), $this->post()); 200 | if ($key) { 201 | return isset($union[$key]) ? $union[$key] : $default; 202 | } 203 | 204 | return $union; 205 | } 206 | 207 | /** 208 | * Fetch GET data 209 | * 210 | * This method returns a key-value array of data sent in the HTTP request query string, or 211 | * the value of the array key if requested; if the array key does not exist, NULL is returned. 212 | * 213 | * @param string $key 214 | * @param mixed $default Default return value when key does not exist 215 | * @return array|mixed|null 216 | */ 217 | public function get($key = null, $default = null) 218 | { 219 | if (!isset($this->env['slim.request.query_hash'])) { 220 | $output = array(); 221 | if (function_exists('mb_parse_str') && !isset($this->env['slim.tests.ignore_multibyte'])) { 222 | mb_parse_str($this->env['QUERY_STRING'], $output); 223 | } else { 224 | parse_str($this->env['QUERY_STRING'], $output); 225 | } 226 | $this->env['slim.request.query_hash'] = Util::stripSlashesIfMagicQuotes($output); 227 | } 228 | if ($key) { 229 | if (isset($this->env['slim.request.query_hash'][$key])) { 230 | return $this->env['slim.request.query_hash'][$key]; 231 | } else { 232 | return $default; 233 | } 234 | } else { 235 | return $this->env['slim.request.query_hash']; 236 | } 237 | } 238 | 239 | /** 240 | * Fetch POST data 241 | * 242 | * This method returns a key-value array of data sent in the HTTP request body, or 243 | * the value of a hash key if requested; if the array key does not exist, NULL is returned. 244 | * 245 | * @param string $key 246 | * @param mixed $default Default return value when key does not exist 247 | * @return array|mixed|null 248 | * @throws \RuntimeException If environment input is not available 249 | */ 250 | public function post($key = null, $default = null) 251 | { 252 | if (!isset($this->env['slim.input'])) { 253 | throw new \RuntimeException('Missing slim.input in environment variables'); 254 | } 255 | if (!isset($this->env['slim.request.form_hash'])) { 256 | $this->env['slim.request.form_hash'] = array(); 257 | if ($this->isFormData() && is_string($this->env['slim.input'])) { 258 | $output = array(); 259 | if (function_exists('mb_parse_str') && !isset($this->env['slim.tests.ignore_multibyte'])) { 260 | mb_parse_str($this->env['slim.input'], $output); 261 | } else { 262 | parse_str($this->env['slim.input'], $output); 263 | } 264 | $this->env['slim.request.form_hash'] = Util::stripSlashesIfMagicQuotes($output); 265 | } else { 266 | $this->env['slim.request.form_hash'] = Util::stripSlashesIfMagicQuotes($_POST); 267 | } 268 | } 269 | if ($key) { 270 | if (isset($this->env['slim.request.form_hash'][$key])) { 271 | return $this->env['slim.request.form_hash'][$key]; 272 | } else { 273 | return $default; 274 | } 275 | } else { 276 | return $this->env['slim.request.form_hash']; 277 | } 278 | } 279 | 280 | /** 281 | * Fetch PUT data (alias for \Slim\Http\Request::post) 282 | * @param string $key 283 | * @param mixed $default Default return value when key does not exist 284 | * @return array|mixed|null 285 | */ 286 | public function put($key = null, $default = null) 287 | { 288 | return $this->post($key, $default); 289 | } 290 | 291 | /** 292 | * Fetch PATCH data (alias for \Slim\Http\Request::post) 293 | * @param string $key 294 | * @param mixed $default Default return value when key does not exist 295 | * @return array|mixed|null 296 | */ 297 | public function patch($key = null, $default = null) 298 | { 299 | return $this->post($key, $default); 300 | } 301 | 302 | /** 303 | * Fetch DELETE data (alias for \Slim\Http\Request::post) 304 | * @param string $key 305 | * @param mixed $default Default return value when key does not exist 306 | * @return array|mixed|null 307 | */ 308 | public function delete($key = null, $default = null) 309 | { 310 | return $this->post($key, $default); 311 | } 312 | 313 | /** 314 | * Fetch COOKIE data 315 | * 316 | * This method returns a key-value array of Cookie data sent in the HTTP request, or 317 | * the value of a array key if requested; if the array key does not exist, NULL is returned. 318 | * 319 | * @param string $key 320 | * @return array|string|null 321 | */ 322 | public function cookies($key = null) 323 | { 324 | if ($key) { 325 | return $this->cookies->get($key); 326 | } 327 | 328 | return $this->cookies; 329 | // if (!isset($this->env['slim.request.cookie_hash'])) { 330 | // $cookieHeader = isset($this->env['COOKIE']) ? $this->env['COOKIE'] : ''; 331 | // $this->env['slim.request.cookie_hash'] = Util::parseCookieHeader($cookieHeader); 332 | // } 333 | // if ($key) { 334 | // if (isset($this->env['slim.request.cookie_hash'][$key])) { 335 | // return $this->env['slim.request.cookie_hash'][$key]; 336 | // } else { 337 | // return null; 338 | // } 339 | // } else { 340 | // return $this->env['slim.request.cookie_hash']; 341 | // } 342 | } 343 | 344 | /** 345 | * Does the Request body contain parsed form data? 346 | * @return bool 347 | */ 348 | public function isFormData() 349 | { 350 | $method = isset($this->env['slim.method_override.original_method']) ? $this->env['slim.method_override.original_method'] : $this->getMethod(); 351 | 352 | return ($method === self::METHOD_POST && is_null($this->getContentType())) || in_array($this->getMediaType(), self::$formDataMediaTypes); 353 | } 354 | 355 | /** 356 | * Get Headers 357 | * 358 | * This method returns a key-value array of headers sent in the HTTP request, or 359 | * the value of a hash key if requested; if the array key does not exist, NULL is returned. 360 | * 361 | * @param string $key 362 | * @param mixed $default The default value returned if the requested header is not available 363 | * @return mixed 364 | */ 365 | public function headers($key = null, $default = null) 366 | { 367 | if ($key) { 368 | return $this->headers->get($key, $default); 369 | } 370 | 371 | return $this->headers; 372 | // if ($key) { 373 | // $key = strtoupper($key); 374 | // $key = str_replace('-', '_', $key); 375 | // $key = preg_replace('@^HTTP_@', '', $key); 376 | // if (isset($this->env[$key])) { 377 | // return $this->env[$key]; 378 | // } else { 379 | // return $default; 380 | // } 381 | // } else { 382 | // $headers = array(); 383 | // foreach ($this->env as $key => $value) { 384 | // if (strpos($key, 'slim.') !== 0) { 385 | // $headers[$key] = $value; 386 | // } 387 | // } 388 | // 389 | // return $headers; 390 | // } 391 | } 392 | 393 | /** 394 | * Get Body 395 | * @return string 396 | */ 397 | public function getBody() 398 | { 399 | return $this->env['slim.input']; 400 | } 401 | 402 | /** 403 | * Get Content Type 404 | * @return string|null 405 | */ 406 | public function getContentType() 407 | { 408 | return $this->headers->get('CONTENT_TYPE'); 409 | } 410 | 411 | /** 412 | * Get Media Type (type/subtype within Content Type header) 413 | * @return string|null 414 | */ 415 | public function getMediaType() 416 | { 417 | $contentType = $this->getContentType(); 418 | if ($contentType) { 419 | $contentTypeParts = preg_split('/\s*[;,]\s*/', $contentType); 420 | 421 | return strtolower($contentTypeParts[0]); 422 | } 423 | 424 | return null; 425 | } 426 | 427 | /** 428 | * Get Media Type Params 429 | * @return array 430 | */ 431 | public function getMediaTypeParams() 432 | { 433 | $contentType = $this->getContentType(); 434 | $contentTypeParams = array(); 435 | if ($contentType) { 436 | $contentTypeParts = preg_split('/\s*[;,]\s*/', $contentType); 437 | $contentTypePartsLength = count($contentTypeParts); 438 | for ($i = 1; $i < $contentTypePartsLength; $i++) { 439 | $paramParts = explode('=', $contentTypeParts[$i]); 440 | $contentTypeParams[strtolower($paramParts[0])] = $paramParts[1]; 441 | } 442 | } 443 | 444 | return $contentTypeParams; 445 | } 446 | 447 | /** 448 | * Get Content Charset 449 | * @return string|null 450 | */ 451 | public function getContentCharset() 452 | { 453 | $mediaTypeParams = $this->getMediaTypeParams(); 454 | if (isset($mediaTypeParams['charset'])) { 455 | return $mediaTypeParams['charset']; 456 | } 457 | 458 | return null; 459 | } 460 | 461 | /** 462 | * Get Content-Length 463 | * @return int 464 | */ 465 | public function getContentLength() 466 | { 467 | return $this->headers->get('CONTENT_LENGTH', 0); 468 | } 469 | 470 | /** 471 | * Get Host 472 | * @return string 473 | */ 474 | public function getHost() 475 | { 476 | if (isset($this->env['HTTP_HOST'])) { 477 | if (strpos($this->env['HTTP_HOST'], ':') !== false) { 478 | $hostParts = explode(':', $this->env['HTTP_HOST']); 479 | 480 | return $hostParts[0]; 481 | } 482 | 483 | return $this->env['HTTP_HOST']; 484 | } 485 | 486 | return $this->env['SERVER_NAME']; 487 | } 488 | 489 | /** 490 | * Get Host with Port 491 | * @return string 492 | */ 493 | public function getHostWithPort() 494 | { 495 | return sprintf('%s:%s', $this->getHost(), $this->getPort()); 496 | } 497 | 498 | /** 499 | * Get Port 500 | * @return int 501 | */ 502 | public function getPort() 503 | { 504 | return (int)$this->env['SERVER_PORT']; 505 | } 506 | 507 | /** 508 | * Get Scheme (https or http) 509 | * @return string 510 | */ 511 | public function getScheme() 512 | { 513 | return $this->env['slim.url_scheme']; 514 | } 515 | 516 | /** 517 | * Get Script Name (physical path) 518 | * @return string 519 | */ 520 | public function getScriptName() 521 | { 522 | return $this->env['SCRIPT_NAME']; 523 | } 524 | 525 | /** 526 | * LEGACY: Get Root URI (alias for Slim_Http_Request::getScriptName) 527 | * @return string 528 | */ 529 | public function getRootUri() 530 | { 531 | return $this->getScriptName(); 532 | } 533 | 534 | /** 535 | * Get Path (physical path + virtual path) 536 | * @return string 537 | */ 538 | public function getPath() 539 | { 540 | return $this->getScriptName() . $this->getPathInfo(); 541 | } 542 | 543 | /** 544 | * Get Path Info (virtual path) 545 | * @return string 546 | */ 547 | public function getPathInfo() 548 | { 549 | return $this->env['PATH_INFO']; 550 | } 551 | 552 | /** 553 | * LEGACY: Get Resource URI (alias for Slim_Http_Request::getPathInfo) 554 | * @return string 555 | */ 556 | public function getResourceUri() 557 | { 558 | return $this->getPathInfo(); 559 | } 560 | 561 | /** 562 | * Get URL (scheme + host [ + port if non-standard ]) 563 | * @return string 564 | */ 565 | public function getUrl() 566 | { 567 | $url = $this->getScheme() . '://' . $this->getHost(); 568 | if (($this->getScheme() === 'https' && $this->getPort() !== 443) || ($this->getScheme() === 'http' && $this->getPort() !== 80)) { 569 | $url .= sprintf(':%s', $this->getPort()); 570 | } 571 | 572 | return $url; 573 | } 574 | 575 | /** 576 | * Get IP 577 | * @return string 578 | */ 579 | public function getIp() 580 | { 581 | $keys = array('X_FORWARDED_FOR', 'HTTP_X_FORWARDED_FOR', 'CLIENT_IP', 'REMOTE_ADDR'); 582 | foreach ($keys as $key) { 583 | if (isset($this->env[$key])) { 584 | return $this->env[$key]; 585 | } 586 | } 587 | 588 | return $this->env['REMOTE_ADDR']; 589 | } 590 | 591 | /** 592 | * Get Referrer 593 | * @return string|null 594 | */ 595 | public function getReferrer() 596 | { 597 | return $this->headers->get('HTTP_REFERER'); 598 | } 599 | 600 | /** 601 | * Get Referer (for those who can't spell) 602 | * @return string|null 603 | */ 604 | public function getReferer() 605 | { 606 | return $this->getReferrer(); 607 | } 608 | 609 | /** 610 | * Get User Agent 611 | * @return string|null 612 | */ 613 | public function getUserAgent() 614 | { 615 | return $this->headers->get('HTTP_USER_AGENT'); 616 | } 617 | } 618 | -------------------------------------------------------------------------------- /api/Slim/Http/Response.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 2.6.1 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 | * Response 37 | * 38 | * This is a simple abstraction over top an HTTP response. This 39 | * provides methods to set the HTTP status, the HTTP headers, 40 | * and the HTTP body. 41 | * 42 | * @package Slim 43 | * @author Josh Lockhart 44 | * @since 1.0.0 45 | */ 46 | class Response implements \ArrayAccess, \Countable, \IteratorAggregate 47 | { 48 | /** 49 | * @var int HTTP status code 50 | */ 51 | protected $status; 52 | 53 | /** 54 | * @var \Slim\Http\Headers 55 | */ 56 | public $headers; 57 | 58 | /** 59 | * @var \Slim\Http\Cookies 60 | */ 61 | public $cookies; 62 | 63 | /** 64 | * @var string HTTP response body 65 | */ 66 | protected $body; 67 | 68 | /** 69 | * @var int Length of HTTP response body 70 | */ 71 | protected $length; 72 | 73 | /** 74 | * @var array HTTP response codes and messages 75 | */ 76 | protected static $messages = array( 77 | //Informational 1xx 78 | 100 => '100 Continue', 79 | 101 => '101 Switching Protocols', 80 | //Successful 2xx 81 | 200 => '200 OK', 82 | 201 => '201 Created', 83 | 202 => '202 Accepted', 84 | 203 => '203 Non-Authoritative Information', 85 | 204 => '204 No Content', 86 | 205 => '205 Reset Content', 87 | 206 => '206 Partial Content', 88 | 226 => '226 IM Used', 89 | //Redirection 3xx 90 | 300 => '300 Multiple Choices', 91 | 301 => '301 Moved Permanently', 92 | 302 => '302 Found', 93 | 303 => '303 See Other', 94 | 304 => '304 Not Modified', 95 | 305 => '305 Use Proxy', 96 | 306 => '306 (Unused)', 97 | 307 => '307 Temporary Redirect', 98 | //Client Error 4xx 99 | 400 => '400 Bad Request', 100 | 401 => '401 Unauthorized', 101 | 402 => '402 Payment Required', 102 | 403 => '403 Forbidden', 103 | 404 => '404 Not Found', 104 | 405 => '405 Method Not Allowed', 105 | 406 => '406 Not Acceptable', 106 | 407 => '407 Proxy Authentication Required', 107 | 408 => '408 Request Timeout', 108 | 409 => '409 Conflict', 109 | 410 => '410 Gone', 110 | 411 => '411 Length Required', 111 | 412 => '412 Precondition Failed', 112 | 413 => '413 Request Entity Too Large', 113 | 414 => '414 Request-URI Too Long', 114 | 415 => '415 Unsupported Media Type', 115 | 416 => '416 Requested Range Not Satisfiable', 116 | 417 => '417 Expectation Failed', 117 | 418 => '418 I\'m a teapot', 118 | 422 => '422 Unprocessable Entity', 119 | 423 => '423 Locked', 120 | 426 => '426 Upgrade Required', 121 | 428 => '428 Precondition Required', 122 | 429 => '429 Too Many Requests', 123 | 431 => '431 Request Header Fields Too Large', 124 | //Server Error 5xx 125 | 500 => '500 Internal Server Error', 126 | 501 => '501 Not Implemented', 127 | 502 => '502 Bad Gateway', 128 | 503 => '503 Service Unavailable', 129 | 504 => '504 Gateway Timeout', 130 | 505 => '505 HTTP Version Not Supported', 131 | 506 => '506 Variant Also Negotiates', 132 | 510 => '510 Not Extended', 133 | 511 => '511 Network Authentication Required' 134 | ); 135 | 136 | /** 137 | * Constructor 138 | * @param string $body The HTTP response body 139 | * @param int $status The HTTP response status 140 | * @param \Slim\Http\Headers|array $headers The HTTP response headers 141 | */ 142 | public function __construct($body = '', $status = 200, $headers = array()) 143 | { 144 | $this->setStatus($status); 145 | $this->headers = new \Slim\Http\Headers(array('Content-Type' => 'text/html')); 146 | $this->headers->replace($headers); 147 | $this->cookies = new \Slim\Http\Cookies(); 148 | $this->write($body); 149 | } 150 | 151 | public function getStatus() 152 | { 153 | return $this->status; 154 | } 155 | 156 | public function setStatus($status) 157 | { 158 | $this->status = (int)$status; 159 | } 160 | 161 | /** 162 | * DEPRECATION WARNING! Use `getStatus` or `setStatus` instead. 163 | * 164 | * Get and set status 165 | * @param int|null $status 166 | * @return int 167 | */ 168 | public function status($status = null) 169 | { 170 | if (!is_null($status)) { 171 | $this->status = (int) $status; 172 | } 173 | 174 | return $this->status; 175 | } 176 | 177 | /** 178 | * DEPRECATION WARNING! Access `headers` property directly. 179 | * 180 | * Get and set header 181 | * @param string $name Header name 182 | * @param string|null $value Header value 183 | * @return string Header value 184 | */ 185 | public function header($name, $value = null) 186 | { 187 | if (!is_null($value)) { 188 | $this->headers->set($name, $value); 189 | } 190 | 191 | return $this->headers->get($name); 192 | } 193 | 194 | /** 195 | * DEPRECATION WARNING! Access `headers` property directly. 196 | * 197 | * Get headers 198 | * @return \Slim\Http\Headers 199 | */ 200 | public function headers() 201 | { 202 | return $this->headers; 203 | } 204 | 205 | public function getBody() 206 | { 207 | return $this->body; 208 | } 209 | 210 | public function setBody($content) 211 | { 212 | $this->write($content, true); 213 | } 214 | 215 | /** 216 | * DEPRECATION WARNING! use `getBody` or `setBody` instead. 217 | * 218 | * Get and set body 219 | * @param string|null $body Content of HTTP response body 220 | * @return string 221 | */ 222 | public function body($body = null) 223 | { 224 | if (!is_null($body)) { 225 | $this->write($body, true); 226 | } 227 | 228 | return $this->body; 229 | } 230 | 231 | /** 232 | * Append HTTP response body 233 | * @param string $body Content to append to the current HTTP response body 234 | * @param bool $replace Overwrite existing response body? 235 | * @return string The updated HTTP response body 236 | */ 237 | public function write($body, $replace = false) 238 | { 239 | if ($replace) { 240 | $this->body = $body; 241 | } else { 242 | $this->body .= (string)$body; 243 | } 244 | $this->length = strlen($this->body); 245 | 246 | return $this->body; 247 | } 248 | 249 | public function getLength() 250 | { 251 | return $this->length; 252 | } 253 | 254 | /** 255 | * DEPRECATION WARNING! Use `getLength` or `write` or `body` instead. 256 | * 257 | * Get and set length 258 | * @param int|null $length 259 | * @return int 260 | */ 261 | public function length($length = null) 262 | { 263 | if (!is_null($length)) { 264 | $this->length = (int) $length; 265 | } 266 | 267 | return $this->length; 268 | } 269 | 270 | /** 271 | * Finalize 272 | * 273 | * This prepares this response and returns an array 274 | * of [status, headers, body]. This array is passed to outer middleware 275 | * if available or directly to the Slim run method. 276 | * 277 | * @return array[int status, array headers, string body] 278 | */ 279 | public function finalize() 280 | { 281 | // Prepare response 282 | if (in_array($this->status, array(204, 304))) { 283 | $this->headers->remove('Content-Type'); 284 | $this->headers->remove('Content-Length'); 285 | $this->setBody(''); 286 | } 287 | 288 | return array($this->status, $this->headers, $this->body); 289 | } 290 | 291 | /** 292 | * DEPRECATION WARNING! Access `cookies` property directly. 293 | * 294 | * Set cookie 295 | * 296 | * Instead of using PHP's `setcookie()` function, Slim manually constructs the HTTP `Set-Cookie` 297 | * header on its own and delegates this responsibility to the `Slim_Http_Util` class. This 298 | * response's header is passed by reference to the utility class and is directly modified. By not 299 | * relying on PHP's native implementation, Slim allows middleware the opportunity to massage or 300 | * analyze the raw header before the response is ultimately delivered to the HTTP client. 301 | * 302 | * @param string $name The name of the cookie 303 | * @param string|array $value If string, the value of cookie; if array, properties for 304 | * cookie including: value, expire, path, domain, secure, httponly 305 | */ 306 | public function setCookie($name, $value) 307 | { 308 | // Util::setCookieHeader($this->header, $name, $value); 309 | $this->cookies->set($name, $value); 310 | } 311 | 312 | /** 313 | * DEPRECATION WARNING! Access `cookies` property directly. 314 | * 315 | * Delete cookie 316 | * 317 | * Instead of using PHP's `setcookie()` function, Slim manually constructs the HTTP `Set-Cookie` 318 | * header on its own and delegates this responsibility to the `Slim_Http_Util` class. This 319 | * response's header is passed by reference to the utility class and is directly modified. By not 320 | * relying on PHP's native implementation, Slim allows middleware the opportunity to massage or 321 | * analyze the raw header before the response is ultimately delivered to the HTTP client. 322 | * 323 | * This method will set a cookie with the given name that has an expiration time in the past; this will 324 | * prompt the HTTP client to invalidate and remove the client-side cookie. Optionally, you may 325 | * also pass a key/value array as the second argument. If the "domain" key is present in this 326 | * array, only the Cookie with the given name AND domain will be removed. The invalidating cookie 327 | * sent with this response will adopt all properties of the second argument. 328 | * 329 | * @param string $name The name of the cookie 330 | * @param array $settings Properties for cookie including: value, expire, path, domain, secure, httponly 331 | */ 332 | public function deleteCookie($name, $settings = array()) 333 | { 334 | $this->cookies->remove($name, $settings); 335 | // Util::deleteCookieHeader($this->header, $name, $value); 336 | } 337 | 338 | /** 339 | * Redirect 340 | * 341 | * This method prepares this response to return an HTTP Redirect response 342 | * to the HTTP client. 343 | * 344 | * @param string $url The redirect destination 345 | * @param int $status The redirect HTTP status code 346 | */ 347 | public function redirect ($url, $status = 302) 348 | { 349 | $this->setStatus($status); 350 | $this->headers->set('Location', $url); 351 | } 352 | 353 | /** 354 | * Helpers: Empty? 355 | * @return bool 356 | */ 357 | public function isEmpty() 358 | { 359 | return in_array($this->status, array(201, 204, 304)); 360 | } 361 | 362 | /** 363 | * Helpers: Informational? 364 | * @return bool 365 | */ 366 | public function isInformational() 367 | { 368 | return $this->status >= 100 && $this->status < 200; 369 | } 370 | 371 | /** 372 | * Helpers: OK? 373 | * @return bool 374 | */ 375 | public function isOk() 376 | { 377 | return $this->status === 200; 378 | } 379 | 380 | /** 381 | * Helpers: Successful? 382 | * @return bool 383 | */ 384 | public function isSuccessful() 385 | { 386 | return $this->status >= 200 && $this->status < 300; 387 | } 388 | 389 | /** 390 | * Helpers: Redirect? 391 | * @return bool 392 | */ 393 | public function isRedirect() 394 | { 395 | return in_array($this->status, array(301, 302, 303, 307)); 396 | } 397 | 398 | /** 399 | * Helpers: Redirection? 400 | * @return bool 401 | */ 402 | public function isRedirection() 403 | { 404 | return $this->status >= 300 && $this->status < 400; 405 | } 406 | 407 | /** 408 | * Helpers: Forbidden? 409 | * @return bool 410 | */ 411 | public function isForbidden() 412 | { 413 | return $this->status === 403; 414 | } 415 | 416 | /** 417 | * Helpers: Not Found? 418 | * @return bool 419 | */ 420 | public function isNotFound() 421 | { 422 | return $this->status === 404; 423 | } 424 | 425 | /** 426 | * Helpers: Client error? 427 | * @return bool 428 | */ 429 | public function isClientError() 430 | { 431 | return $this->status >= 400 && $this->status < 500; 432 | } 433 | 434 | /** 435 | * Helpers: Server Error? 436 | * @return bool 437 | */ 438 | public function isServerError() 439 | { 440 | return $this->status >= 500 && $this->status < 600; 441 | } 442 | 443 | /** 444 | * DEPRECATION WARNING! ArrayAccess interface will be removed from \Slim\Http\Response. 445 | * Iterate `headers` or `cookies` properties directly. 446 | */ 447 | 448 | /** 449 | * Array Access: Offset Exists 450 | */ 451 | public function offsetExists($offset) 452 | { 453 | return isset($this->headers[$offset]); 454 | } 455 | 456 | /** 457 | * Array Access: Offset Get 458 | */ 459 | public function offsetGet($offset) 460 | { 461 | return $this->headers[$offset]; 462 | } 463 | 464 | /** 465 | * Array Access: Offset Set 466 | */ 467 | public function offsetSet($offset, $value) 468 | { 469 | $this->headers[$offset] = $value; 470 | } 471 | 472 | /** 473 | * Array Access: Offset Unset 474 | */ 475 | public function offsetUnset($offset) 476 | { 477 | unset($this->headers[$offset]); 478 | } 479 | 480 | /** 481 | * DEPRECATION WARNING! Countable interface will be removed from \Slim\Http\Response. 482 | * Call `count` on `headers` or `cookies` properties directly. 483 | * 484 | * Countable: Count 485 | */ 486 | public function count() 487 | { 488 | return count($this->headers); 489 | } 490 | 491 | /** 492 | * DEPRECATION WARNING! IteratorAggregate interface will be removed from \Slim\Http\Response. 493 | * Iterate `headers` or `cookies` properties directly. 494 | * 495 | * Get Iterator 496 | * 497 | * This returns the contained `\Slim\Http\Headers` instance which 498 | * is itself iterable. 499 | * 500 | * @return \Slim\Http\Headers 501 | */ 502 | public function getIterator() 503 | { 504 | return $this->headers->getIterator(); 505 | } 506 | 507 | /** 508 | * Get message for HTTP status code 509 | * @param int $status 510 | * @return string|null 511 | */ 512 | public static function getMessageForCode($status) 513 | { 514 | if (isset(self::$messages[$status])) { 515 | return self::$messages[$status]; 516 | } else { 517 | return null; 518 | } 519 | } 520 | } 521 | -------------------------------------------------------------------------------- /api/Slim/Http/Util.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 2.6.1 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 | } 64 | 65 | return $rawData; 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 | } 435 | -------------------------------------------------------------------------------- /api/Slim/Log.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 2.6.1 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; 34 | 35 | /** 36 | * Log 37 | * 38 | * This is the primary logger for a Slim application. You may provide 39 | * a Log Writer in conjunction with this Log to write to various output 40 | * destinations (e.g. a file). This class provides this interface: 41 | * 42 | * debug( mixed $object, array $context ) 43 | * info( mixed $object, array $context ) 44 | * notice( mixed $object, array $context ) 45 | * warning( mixed $object, array $context ) 46 | * error( mixed $object, array $context ) 47 | * critical( mixed $object, array $context ) 48 | * alert( mixed $object, array $context ) 49 | * emergency( mixed $object, array $context ) 50 | * log( mixed $level, mixed $object, array $context ) 51 | * 52 | * This class assumes only that your Log Writer has a public `write()` method 53 | * that accepts any object as its one and only argument. The Log Writer 54 | * class may write or send its argument anywhere: a file, STDERR, 55 | * a remote web API, etc. The possibilities are endless. 56 | * 57 | * @package Slim 58 | * @author Josh Lockhart 59 | * @since 1.0.0 60 | */ 61 | class Log 62 | { 63 | const EMERGENCY = 1; 64 | const ALERT = 2; 65 | const CRITICAL = 3; 66 | const FATAL = 3; //DEPRECATED replace with CRITICAL 67 | const ERROR = 4; 68 | const WARN = 5; 69 | const NOTICE = 6; 70 | const INFO = 7; 71 | const DEBUG = 8; 72 | 73 | /** 74 | * @var array 75 | */ 76 | protected static $levels = array( 77 | self::EMERGENCY => 'EMERGENCY', 78 | self::ALERT => 'ALERT', 79 | self::CRITICAL => 'CRITICAL', 80 | self::ERROR => 'ERROR', 81 | self::WARN => 'WARNING', 82 | self::NOTICE => 'NOTICE', 83 | self::INFO => 'INFO', 84 | self::DEBUG => 'DEBUG' 85 | ); 86 | 87 | /** 88 | * @var mixed 89 | */ 90 | protected $writer; 91 | 92 | /** 93 | * @var bool 94 | */ 95 | protected $enabled; 96 | 97 | /** 98 | * @var int 99 | */ 100 | protected $level; 101 | 102 | /** 103 | * Constructor 104 | * @param mixed $writer 105 | */ 106 | public function __construct($writer) 107 | { 108 | $this->writer = $writer; 109 | $this->enabled = true; 110 | $this->level = self::DEBUG; 111 | } 112 | 113 | /** 114 | * Is logging enabled? 115 | * @return bool 116 | */ 117 | public function getEnabled() 118 | { 119 | return $this->enabled; 120 | } 121 | 122 | /** 123 | * Enable or disable logging 124 | * @param bool $enabled 125 | */ 126 | public function setEnabled($enabled) 127 | { 128 | if ($enabled) { 129 | $this->enabled = true; 130 | } else { 131 | $this->enabled = false; 132 | } 133 | } 134 | 135 | /** 136 | * Set level 137 | * @param int $level 138 | * @throws \InvalidArgumentException If invalid log level specified 139 | */ 140 | public function setLevel($level) 141 | { 142 | if (!isset(self::$levels[$level])) { 143 | throw new \InvalidArgumentException('Invalid log level'); 144 | } 145 | $this->level = $level; 146 | } 147 | 148 | /** 149 | * Get level 150 | * @return int 151 | */ 152 | public function getLevel() 153 | { 154 | return $this->level; 155 | } 156 | 157 | /** 158 | * Set writer 159 | * @param mixed $writer 160 | */ 161 | public function setWriter($writer) 162 | { 163 | $this->writer = $writer; 164 | } 165 | 166 | /** 167 | * Get writer 168 | * @return mixed 169 | */ 170 | public function getWriter() 171 | { 172 | return $this->writer; 173 | } 174 | 175 | /** 176 | * Is logging enabled? 177 | * @return bool 178 | */ 179 | public function isEnabled() 180 | { 181 | return $this->enabled; 182 | } 183 | 184 | /** 185 | * Log debug message 186 | * @param mixed $object 187 | * @param array $context 188 | * @return mixed|bool What the Logger returns, or false if Logger not set or not enabled 189 | */ 190 | public function debug($object, $context = array()) 191 | { 192 | return $this->log(self::DEBUG, $object, $context); 193 | } 194 | 195 | /** 196 | * Log info message 197 | * @param mixed $object 198 | * @param array $context 199 | * @return mixed|bool What the Logger returns, or false if Logger not set or not enabled 200 | */ 201 | public function info($object, $context = array()) 202 | { 203 | return $this->log(self::INFO, $object, $context); 204 | } 205 | 206 | /** 207 | * Log notice message 208 | * @param mixed $object 209 | * @param array $context 210 | * @return mixed|bool What the Logger returns, or false if Logger not set or not enabled 211 | */ 212 | public function notice($object, $context = array()) 213 | { 214 | return $this->log(self::NOTICE, $object, $context); 215 | } 216 | 217 | /** 218 | * Log warning message 219 | * @param mixed $object 220 | * @param array $context 221 | * @return mixed|bool What the Logger returns, or false if Logger not set or not enabled 222 | */ 223 | public function warning($object, $context = array()) 224 | { 225 | return $this->log(self::WARN, $object, $context); 226 | } 227 | 228 | /** 229 | * DEPRECATED for function warning 230 | * Log warning message 231 | * @param mixed $object 232 | * @param array $context 233 | * @return mixed|bool What the Logger returns, or false if Logger not set or not enabled 234 | */ 235 | public function warn($object, $context = array()) 236 | { 237 | return $this->log(self::WARN, $object, $context); 238 | } 239 | 240 | /** 241 | * Log error message 242 | * @param mixed $object 243 | * @param array $context 244 | * @return mixed|bool What the Logger returns, or false if Logger not set or not enabled 245 | */ 246 | public function error($object, $context = array()) 247 | { 248 | return $this->log(self::ERROR, $object, $context); 249 | } 250 | 251 | /** 252 | * Log critical message 253 | * @param mixed $object 254 | * @param array $context 255 | * @return mixed|bool What the Logger returns, or false if Logger not set or not enabled 256 | */ 257 | public function critical($object, $context = array()) 258 | { 259 | return $this->log(self::CRITICAL, $object, $context); 260 | } 261 | 262 | /** 263 | * DEPRECATED for function critical 264 | * Log fatal message 265 | * @param mixed $object 266 | * @param array $context 267 | * @return mixed|bool What the Logger returns, or false if Logger not set or not enabled 268 | */ 269 | public function fatal($object, $context = array()) 270 | { 271 | return $this->log(self::CRITICAL, $object, $context); 272 | } 273 | 274 | /** 275 | * Log alert message 276 | * @param mixed $object 277 | * @param array $context 278 | * @return mixed|bool What the Logger returns, or false if Logger not set or not enabled 279 | */ 280 | public function alert($object, $context = array()) 281 | { 282 | return $this->log(self::ALERT, $object, $context); 283 | } 284 | 285 | /** 286 | * Log emergency message 287 | * @param mixed $object 288 | * @param array $context 289 | * @return mixed|bool What the Logger returns, or false if Logger not set or not enabled 290 | */ 291 | public function emergency($object, $context = array()) 292 | { 293 | return $this->log(self::EMERGENCY, $object, $context); 294 | } 295 | 296 | /** 297 | * Log message 298 | * @param mixed $level 299 | * @param mixed $object 300 | * @param array $context 301 | * @return mixed|bool What the Logger returns, or false if Logger not set or not enabled 302 | * @throws \InvalidArgumentException If invalid log level 303 | */ 304 | public function log($level, $object, $context = array()) 305 | { 306 | if (!isset(self::$levels[$level])) { 307 | throw new \InvalidArgumentException('Invalid log level supplied to function'); 308 | } else if ($this->enabled && $this->writer && $level <= $this->level) { 309 | if (is_array($object) || (is_object($object) && !method_exists($object, "__toString"))) { 310 | $message = print_r($object, true); 311 | } else { 312 | $message = (string) $object; 313 | } 314 | 315 | if (count($context) > 0) { 316 | if (isset($context['exception']) && $context['exception'] instanceof \Exception) { 317 | $message .= ' - ' . $context['exception']; 318 | unset($context['exception']); 319 | } 320 | $message = $this->interpolate($message, $context); 321 | } 322 | return $this->writer->write($message, $level); 323 | } else { 324 | return false; 325 | } 326 | } 327 | 328 | /** 329 | * DEPRECATED for function log 330 | * Log message 331 | * @param mixed $object The object to log 332 | * @param int $level The message level 333 | * @return int|bool 334 | */ 335 | protected function write($object, $level) 336 | { 337 | return $this->log($level, $object); 338 | } 339 | 340 | /** 341 | * Interpolate log message 342 | * @param mixed $message The log message 343 | * @param array $context An array of placeholder values 344 | * @return string The processed string 345 | */ 346 | protected function interpolate($message, $context = array()) 347 | { 348 | $replace = array(); 349 | foreach ($context as $key => $value) { 350 | $replace['{' . $key . '}'] = $value; 351 | } 352 | return strtr($message, $replace); 353 | } 354 | } 355 | -------------------------------------------------------------------------------- /api/Slim/LogWriter.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 2.6.1 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; 34 | 35 | /** 36 | * Log Writer 37 | * 38 | * This class is used by Slim_Log to write log messages to a valid, writable 39 | * resource handle (e.g. a file or STDERR). 40 | * 41 | * @package Slim 42 | * @author Josh Lockhart 43 | * @since 1.6.0 44 | */ 45 | class LogWriter 46 | { 47 | /** 48 | * @var resource 49 | */ 50 | protected $resource; 51 | 52 | /** 53 | * Constructor 54 | * @param resource $resource 55 | * @throws \InvalidArgumentException If invalid resource 56 | */ 57 | public function __construct($resource) 58 | { 59 | if (!is_resource($resource)) { 60 | throw new \InvalidArgumentException('Cannot create LogWriter. Invalid resource handle.'); 61 | } 62 | $this->resource = $resource; 63 | } 64 | 65 | /** 66 | * Write message 67 | * @param mixed $message 68 | * @param int $level 69 | * @return int|bool 70 | */ 71 | public function write($message, $level = null) 72 | { 73 | return fwrite($this->resource, (string) $message . PHP_EOL); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /api/Slim/Middleware.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 2.6.1 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; 34 | 35 | /** 36 | * Middleware 37 | * 38 | * @package Slim 39 | * @author Josh Lockhart 40 | * @since 1.6.0 41 | */ 42 | abstract class Middleware 43 | { 44 | /** 45 | * @var \Slim\Slim Reference to the primary application instance 46 | */ 47 | protected $app; 48 | 49 | /** 50 | * @var mixed Reference to the next downstream middleware 51 | */ 52 | protected $next; 53 | 54 | /** 55 | * Set application 56 | * 57 | * This method injects the primary Slim application instance into 58 | * this middleware. 59 | * 60 | * @param \Slim\Slim $application 61 | */ 62 | final public function setApplication($application) 63 | { 64 | $this->app = $application; 65 | } 66 | 67 | /** 68 | * Get application 69 | * 70 | * This method retrieves the application previously injected 71 | * into this middleware. 72 | * 73 | * @return \Slim\Slim 74 | */ 75 | final public function getApplication() 76 | { 77 | return $this->app; 78 | } 79 | 80 | /** 81 | * Set next middleware 82 | * 83 | * This method injects the next downstream middleware into 84 | * this middleware so that it may optionally be called 85 | * when appropriate. 86 | * 87 | * @param \Slim|\Slim\Middleware 88 | */ 89 | final public function setNextMiddleware($nextMiddleware) 90 | { 91 | $this->next = $nextMiddleware; 92 | } 93 | 94 | /** 95 | * Get next middleware 96 | * 97 | * This method retrieves the next downstream middleware 98 | * previously injected into this middleware. 99 | * 100 | * @return \Slim\Slim|\Slim\Middleware 101 | */ 102 | final public function getNextMiddleware() 103 | { 104 | return $this->next; 105 | } 106 | 107 | /** 108 | * Call 109 | * 110 | * Perform actions specific to this middleware and optionally 111 | * call the next downstream middleware. 112 | */ 113 | abstract public function call(); 114 | } 115 | -------------------------------------------------------------------------------- /api/Slim/Middleware/ContentTypes.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 2.6.1 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\Middleware; 34 | 35 | /** 36 | * Content Types 37 | * 38 | * This is middleware for a Slim application that intercepts 39 | * the HTTP request body and parses it into the appropriate 40 | * PHP data structure if possible; else it returns the HTTP 41 | * request body unchanged. This is particularly useful 42 | * for preparing the HTTP request body for an XML or JSON API. 43 | * 44 | * @package Slim 45 | * @author Josh Lockhart 46 | * @since 1.6.0 47 | */ 48 | class ContentTypes extends \Slim\Middleware 49 | { 50 | /** 51 | * @var array 52 | */ 53 | protected $contentTypes; 54 | 55 | /** 56 | * Constructor 57 | * @param array $settings 58 | */ 59 | public function __construct($settings = array()) 60 | { 61 | $defaults = array( 62 | 'application/json' => array($this, 'parseJson'), 63 | 'application/xml' => array($this, 'parseXml'), 64 | 'text/xml' => array($this, 'parseXml'), 65 | 'text/csv' => array($this, 'parseCsv') 66 | ); 67 | $this->contentTypes = array_merge($defaults, $settings); 68 | } 69 | 70 | /** 71 | * Call 72 | */ 73 | public function call() 74 | { 75 | $mediaType = $this->app->request()->getMediaType(); 76 | if ($mediaType) { 77 | $env = $this->app->environment(); 78 | $env['slim.input_original'] = $env['slim.input']; 79 | $env['slim.input'] = $this->parse($env['slim.input'], $mediaType); 80 | } 81 | $this->next->call(); 82 | } 83 | 84 | /** 85 | * Parse input 86 | * 87 | * This method will attempt to parse the request body 88 | * based on its content type if available. 89 | * 90 | * @param string $input 91 | * @param string $contentType 92 | * @return mixed 93 | */ 94 | protected function parse ($input, $contentType) 95 | { 96 | if (isset($this->contentTypes[$contentType]) && is_callable($this->contentTypes[$contentType])) { 97 | $result = call_user_func($this->contentTypes[$contentType], $input); 98 | if ($result) { 99 | return $result; 100 | } 101 | } 102 | 103 | return $input; 104 | } 105 | 106 | /** 107 | * Parse JSON 108 | * 109 | * This method converts the raw JSON input 110 | * into an associative array. 111 | * 112 | * @param string $input 113 | * @return array|string 114 | */ 115 | protected function parseJson($input) 116 | { 117 | if (function_exists('json_decode')) { 118 | $result = json_decode($input, true); 119 | if(json_last_error() === JSON_ERROR_NONE) { 120 | return $result; 121 | } 122 | } 123 | } 124 | 125 | /** 126 | * Parse XML 127 | * 128 | * This method creates a SimpleXMLElement 129 | * based upon the XML input. If the SimpleXML 130 | * extension is not available, the raw input 131 | * will be returned unchanged. 132 | * 133 | * @param string $input 134 | * @return \SimpleXMLElement|string 135 | */ 136 | protected function parseXml($input) 137 | { 138 | if (class_exists('SimpleXMLElement')) { 139 | try { 140 | $backup = libxml_disable_entity_loader(true); 141 | $result = new \SimpleXMLElement($input); 142 | libxml_disable_entity_loader($backup); 143 | return $result; 144 | } catch (\Exception $e) { 145 | // Do nothing 146 | } 147 | } 148 | 149 | return $input; 150 | } 151 | 152 | /** 153 | * Parse CSV 154 | * 155 | * This method parses CSV content into a numeric array 156 | * containing an array of data for each CSV line. 157 | * 158 | * @param string $input 159 | * @return array 160 | */ 161 | protected function parseCsv($input) 162 | { 163 | $temp = fopen('php://memory', 'rw'); 164 | fwrite($temp, $input); 165 | fseek($temp, 0); 166 | $res = array(); 167 | while (($data = fgetcsv($temp)) !== false) { 168 | $res[] = $data; 169 | } 170 | fclose($temp); 171 | 172 | return $res; 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /api/Slim/Middleware/Flash.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 2.6.1 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\Middleware; 34 | 35 | /** 36 | * Flash 37 | * 38 | * This is middleware for a Slim application that enables 39 | * Flash messaging between HTTP requests. This allows you 40 | * set Flash messages for the current request, for the next request, 41 | * or to retain messages from the previous request through to 42 | * the next request. 43 | * 44 | * @package Slim 45 | * @author Josh Lockhart 46 | * @since 1.6.0 47 | */ 48 | class Flash extends \Slim\Middleware implements \ArrayAccess, \IteratorAggregate, \Countable 49 | { 50 | /** 51 | * @var array 52 | */ 53 | protected $settings; 54 | 55 | /** 56 | * @var array 57 | */ 58 | protected $messages; 59 | 60 | /** 61 | * Constructor 62 | * @param array $settings 63 | */ 64 | public function __construct($settings = array()) 65 | { 66 | $this->settings = array_merge(array('key' => 'slim.flash'), $settings); 67 | $this->messages = array( 68 | 'prev' => array(), //flash messages from prev request (loaded when middleware called) 69 | 'next' => array(), //flash messages for next request 70 | 'now' => array() //flash messages for current request 71 | ); 72 | } 73 | 74 | /** 75 | * Call 76 | */ 77 | public function call() 78 | { 79 | //Read flash messaging from previous request if available 80 | $this->loadMessages(); 81 | 82 | //Prepare flash messaging for current request 83 | $env = $this->app->environment(); 84 | $env['slim.flash'] = $this; 85 | $this->next->call(); 86 | $this->save(); 87 | } 88 | 89 | /** 90 | * Now 91 | * 92 | * Specify a flash message for a given key to be shown for the current request 93 | * 94 | * @param string $key 95 | * @param string $value 96 | */ 97 | public function now($key, $value) 98 | { 99 | $this->messages['now'][(string) $key] = $value; 100 | } 101 | 102 | /** 103 | * Set 104 | * 105 | * Specify a flash message for a given key to be shown for the next request 106 | * 107 | * @param string $key 108 | * @param string $value 109 | */ 110 | public function set($key, $value) 111 | { 112 | $this->messages['next'][(string) $key] = $value; 113 | } 114 | 115 | /** 116 | * Keep 117 | * 118 | * Retain flash messages from the previous request for the next request 119 | */ 120 | public function keep() 121 | { 122 | foreach ($this->messages['prev'] as $key => $val) { 123 | $this->messages['next'][$key] = $val; 124 | } 125 | } 126 | 127 | /** 128 | * Save 129 | */ 130 | public function save() 131 | { 132 | $_SESSION[$this->settings['key']] = $this->messages['next']; 133 | } 134 | 135 | /** 136 | * Load messages from previous request if available 137 | */ 138 | public function loadMessages() 139 | { 140 | if (isset($_SESSION[$this->settings['key']])) { 141 | $this->messages['prev'] = $_SESSION[$this->settings['key']]; 142 | } 143 | } 144 | 145 | /** 146 | * Return array of flash messages to be shown for the current request 147 | * 148 | * @return array 149 | */ 150 | public function getMessages() 151 | { 152 | return array_merge($this->messages['prev'], $this->messages['now']); 153 | } 154 | 155 | /** 156 | * Array Access: Offset Exists 157 | */ 158 | public function offsetExists($offset) 159 | { 160 | $messages = $this->getMessages(); 161 | 162 | return isset($messages[$offset]); 163 | } 164 | 165 | /** 166 | * Array Access: Offset Get 167 | */ 168 | public function offsetGet($offset) 169 | { 170 | $messages = $this->getMessages(); 171 | 172 | return isset($messages[$offset]) ? $messages[$offset] : null; 173 | } 174 | 175 | /** 176 | * Array Access: Offset Set 177 | */ 178 | public function offsetSet($offset, $value) 179 | { 180 | $this->now($offset, $value); 181 | } 182 | 183 | /** 184 | * Array Access: Offset Unset 185 | */ 186 | public function offsetUnset($offset) 187 | { 188 | unset($this->messages['prev'][$offset], $this->messages['now'][$offset]); 189 | } 190 | 191 | /** 192 | * Iterator Aggregate: Get Iterator 193 | * @return \ArrayIterator 194 | */ 195 | public function getIterator() 196 | { 197 | $messages = $this->getMessages(); 198 | 199 | return new \ArrayIterator($messages); 200 | } 201 | 202 | /** 203 | * Countable: Count 204 | */ 205 | public function count() 206 | { 207 | return count($this->getMessages()); 208 | } 209 | 210 | 211 | 212 | } 213 | -------------------------------------------------------------------------------- /api/Slim/Middleware/MethodOverride.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 2.6.1 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\Middleware; 34 | 35 | /** 36 | * HTTP Method Override 37 | * 38 | * This is middleware for a Slim application that allows traditional 39 | * desktop browsers to submit pseudo PUT and DELETE requests by relying 40 | * on a pre-determined request parameter. Without this middleware, 41 | * desktop browsers are only able to submit GET and POST requests. 42 | * 43 | * This middleware is included automatically! 44 | * 45 | * @package Slim 46 | * @author Josh Lockhart 47 | * @since 1.6.0 48 | */ 49 | class MethodOverride extends \Slim\Middleware 50 | { 51 | /** 52 | * @var array 53 | */ 54 | protected $settings; 55 | 56 | /** 57 | * Constructor 58 | * @param array $settings 59 | */ 60 | public function __construct($settings = array()) 61 | { 62 | $this->settings = array_merge(array('key' => '_METHOD'), $settings); 63 | } 64 | 65 | /** 66 | * Call 67 | * 68 | * Implements Slim middleware interface. This method is invoked and passed 69 | * an array of environment variables. This middleware inspects the environment 70 | * variables for the HTTP method override parameter; if found, this middleware 71 | * modifies the environment settings so downstream middleware and/or the Slim 72 | * application will treat the request with the desired HTTP method. 73 | * 74 | * @return array[status, header, body] 75 | */ 76 | public function call() 77 | { 78 | $env = $this->app->environment(); 79 | if (isset($env['HTTP_X_HTTP_METHOD_OVERRIDE'])) { 80 | // Header commonly used by Backbone.js and others 81 | $env['slim.method_override.original_method'] = $env['REQUEST_METHOD']; 82 | $env['REQUEST_METHOD'] = strtoupper($env['HTTP_X_HTTP_METHOD_OVERRIDE']); 83 | } elseif (isset($env['REQUEST_METHOD']) && $env['REQUEST_METHOD'] === 'POST') { 84 | // HTML Form Override 85 | $req = new \Slim\Http\Request($env); 86 | $method = $req->post($this->settings['key']); 87 | if ($method) { 88 | $env['slim.method_override.original_method'] = $env['REQUEST_METHOD']; 89 | $env['REQUEST_METHOD'] = strtoupper($method); 90 | } 91 | } 92 | $this->next->call(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /api/Slim/Middleware/PrettyExceptions.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 2.6.1 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\Middleware; 34 | 35 | /** 36 | * Pretty Exceptions 37 | * 38 | * This middleware catches any Exception thrown by the surrounded 39 | * application and displays a developer-friendly diagnostic screen. 40 | * 41 | * @package Slim 42 | * @author Josh Lockhart 43 | * @since 1.0.0 44 | */ 45 | class PrettyExceptions extends \Slim\Middleware 46 | { 47 | /** 48 | * @var array 49 | */ 50 | protected $settings; 51 | 52 | /** 53 | * Constructor 54 | * @param array $settings 55 | */ 56 | public function __construct($settings = array()) 57 | { 58 | $this->settings = $settings; 59 | } 60 | 61 | /** 62 | * Call 63 | */ 64 | public function call() 65 | { 66 | try { 67 | $this->next->call(); 68 | } catch (\Exception $e) { 69 | $log = $this->app->getLog(); // Force Slim to append log to env if not already 70 | $env = $this->app->environment(); 71 | $env['slim.log'] = $log; 72 | $env['slim.log']->error($e); 73 | $this->app->contentType('text/html'); 74 | $this->app->response()->status(500); 75 | $this->app->response()->body($this->renderBody($env, $e)); 76 | } 77 | } 78 | 79 | /** 80 | * Render response body 81 | * @param array $env 82 | * @param \Exception $exception 83 | * @return string 84 | */ 85 | protected function renderBody(&$env, $exception) 86 | { 87 | $title = 'Slim Application Error'; 88 | $code = $exception->getCode(); 89 | $message = $exception->getMessage(); 90 | $file = $exception->getFile(); 91 | $line = $exception->getLine(); 92 | $trace = str_replace(array('#', "\n"), array('
The application could not run because of the following error:
'; 95 | $html .= '%s', $trace); 112 | } 113 | 114 | return sprintf("