parent
fb8a84416a
commit
3f199db814
@ -0,0 +1 @@ |
||||
nbproject/ |
||||
@ -0,0 +1 @@ |
||||
deny from all |
||||
@ -0,0 +1,52 @@ |
||||
<?php |
||||
include "component.php"; |
||||
|
||||
class Harmonious_Components_Factory implements IteratorAggregate, ArrayAccess, Countable { |
||||
|
||||
private $instances = array(); |
||||
private $app; |
||||
|
||||
public function __construct(Harmonious $app) { |
||||
$this->app = $app; |
||||
} |
||||
|
||||
public function getIterator() { |
||||
return new ArrayIterator($this->instances); |
||||
} |
||||
|
||||
public function offsetSet($key, $value) { |
||||
if (isset($this->instances[$key])) throw new Exception('Component ' . $key . ' allready exists'); |
||||
$this->instances[$key] = $value; |
||||
} |
||||
|
||||
public function offsetUnset($key) { |
||||
unset($this->instances[$key]); |
||||
} |
||||
|
||||
public function offsetGet($key) { |
||||
if ( !isset($this->instances[$key]) ) { |
||||
$path = $this->app->config('components_path'); |
||||
if ( isset($path) and file_exists($path . '/' . strtolower($key) . '.php') ) { |
||||
include_once $path . '/' . strtolower($key) . '.php'; |
||||
$classname = $key; |
||||
$this->instances[$key] = new $classname($this->app); |
||||
} elseif ( file_exists(__DIR__ . '/' . ucfirst(strtolower($key)) . '.php') ) { |
||||
include_once ucfirst(strtolower($key)) . '.php'; |
||||
$classname = 'Harmonious_Components_' . ucfirst(strtolower($key)); |
||||
$this->instances[$key] = new $classname($this->app); |
||||
} else { |
||||
throw new Exception('Component ' . $key . ' not exists'); |
||||
} |
||||
} |
||||
return $this->instances[$key]; |
||||
} |
||||
|
||||
public function offsetExists($key) { |
||||
return isset($this->instances[$key]); |
||||
} |
||||
|
||||
public function count() { |
||||
return count($this->instances); |
||||
} |
||||
} |
||||
?> |
||||
@ -0,0 +1,144 @@ |
||||
<?php |
||||
// класс для работы с memcached-серверами |
||||
class Harmonious_Components_Memcached implements IHarmonious_Component{ |
||||
private $mc_servers; |
||||
|
||||
// инициализация |
||||
public function __construct (Harmonious $app) { |
||||
$this->app = $app; |
||||
$this->mc_servers = $this->app->config('memcached_servers'); |
||||
} |
||||
|
||||
private function get_server($key) { |
||||
$mc_server = $this->mc_servers[crc32($key) % count($this->mc_servers)]; |
||||
$m = new Memcached(); |
||||
$m->setOption(Memcached::OPT_NO_BLOCK, true); |
||||
$m->setOption(Memcached::OPT_COMPRESSION, false); |
||||
|
||||
/* foreach ($this->mc_servers as $mc_server) { |
||||
$m->addServer($mc_server, 11211); |
||||
} */ |
||||
$m->addServer($mc_server, 11211); |
||||
return $m; |
||||
} |
||||
|
||||
// запись в memcached без блокировок |
||||
function set($key, $value, $expiration = 3600/*1 час*/) { |
||||
$m = $this->get_server($key); |
||||
$ret = $m->set($key, $value, $expiration); |
||||
if (!$ret) $retcode = $m->getResultCode(); |
||||
unset($m); |
||||
if (!$ret) return array ('result'=>false, 'result_code'=>$retcode, 'result_string'=>$this->retcode2string($retcode)); |
||||
else return array('result'=>true ); |
||||
} |
||||
|
||||
// чтение из memcached |
||||
//$usecas - будет ли использоваться Check And Set |
||||
function get($key, $usecas = false) { |
||||
$m = $this->get_server($key); |
||||
if (!$usecas) $ret = $m->get($key); |
||||
else $ret = $m->get($key, null, $cas); |
||||
if ($ret === false) $retcode = $m->getResultCode(); |
||||
unset($m); |
||||
if ($ret === false) return array ('result'=>false, 'result_code'=>$retcode, 'result_string'=>$this->retcode2string($retcode)); |
||||
$ret = array ('result'=>true, 'value'=>$ret); |
||||
if ($usecas) $ret['cas'] = $cas; |
||||
return $ret; |
||||
} |
||||
|
||||
// удаление из memcached |
||||
function delete($key) { |
||||
$m = $this->get_server($key); |
||||
$ret = $m->delete($key); |
||||
if ($ret === false) $retcode = $m->getResultCode(); |
||||
unset($m); |
||||
if ($ret === false) return array ('result'=>false, 'result_code'=>$retcode, 'result_string'=>$this->retcode2string($retcode)); |
||||
else return array ('result'=>true); |
||||
} |
||||
|
||||
//запись в memcached только в том случае, если данные не изменялись другим параллельным потоком. |
||||
function cas($cas, $key, $value, $expiration = 3600/*1 час*/) { |
||||
$m = $this->get_server($key); |
||||
$ret = $m->cas($cas, $key, $value, $expiration); |
||||
if ($ret === false) $retcode = $m->getResultCode(); |
||||
unset($m); |
||||
if ($ret === false) return array ('result'=>false, 'result_code'=>$retcode, 'result_string'=>$this->retcode2string($retcode)); |
||||
else return array('result'=>true); |
||||
} |
||||
|
||||
// увеличение счетчика на смещение |
||||
function inc($key, $offset = 1) { |
||||
$m = $this->get_server($key); |
||||
$ret = $m->increment($key, $offset); |
||||
if ($ret === false) $retcode = $m->getResultCode(); |
||||
unset($m); |
||||
if ($ret === false) return array ('result'=>false, 'result_code'=>$retcode, 'result_string'=>$this->retcode2string($retcode)); |
||||
else return array('result'=> true, 'value'=>$ret); |
||||
} |
||||
|
||||
// уменьшение счетчика на смещение |
||||
function dec($key, $offset = 1) { |
||||
$m = $this->get_server($key); |
||||
$ret = $m->decrement($key, $offset); |
||||
if ($ret === false) $retcode = $m->getResultCode(); |
||||
unset($m); |
||||
if ($ret === false) return array ('result'=>false, 'result_code'=>$retcode, 'result_string'=>$this->retcode2string($retcode)); |
||||
else return array('result'=> true, 'value'=>$ret); |
||||
} |
||||
|
||||
// добавление строки в конец строки, хранящейся в ключе memcached |
||||
function append($key, $value) { |
||||
$m = $this->get_server($key); |
||||
$ret = $m->append($key, $value); |
||||
if ($ret === false) $retcode = $m->getResultCode(); |
||||
unset($m); |
||||
if ($ret === false) return array ('result'=>false, 'result_code'=>$retcode, 'result_string'=>$this->retcode2string($retcode)); |
||||
else return array('result'=> true); |
||||
} |
||||
|
||||
// добавление строки в начало строки, хранящейся в ключе memcached |
||||
function prepend($key, $value) { |
||||
$m = $this->get_server($key); |
||||
$ret = $m->prepend($key, $value); |
||||
if ($ret === false) $retcode = $m->getResultCode(); |
||||
unset($m); |
||||
if ($ret === false) return array ('result'=>false, 'result_code'=>$retcode, 'result_string'=>$this->retcode2string($retcode)); |
||||
else return array('result'=> true); |
||||
} |
||||
|
||||
public function getStatus() { |
||||
$m = new Memcached(); |
||||
$m->setOption(Memcached::OPT_NO_BLOCK, true); |
||||
foreach ($this->mc_servers as $mc_server) $m->addServer($mc_server, 11211); |
||||
return $m->getStats(); |
||||
} |
||||
|
||||
private function retcode2string ($retcode) { |
||||
switch ($retcode) { |
||||
case 0: return 'RES_SUCCESS'; |
||||
case 1: return 'RES_FAILURE'; |
||||
case 2: return 'RES_HOST_LOOKUP_FAILURE'; |
||||
case 7: return 'RES_UNKNOWN_READ_FAILURE'; |
||||
case 8: return 'RES_PROTOCOL_ERROR'; |
||||
case 9: return 'RES_CLIENT_ERROR'; |
||||
case 10: return 'RES_SERVER_ERROR'; |
||||
case 5: return 'RES_WRITE_FAILURE'; |
||||
case 12: return 'RES_DATA_EXISTS'; |
||||
case 14: return 'RES_NOTSTORED'; |
||||
case 16: return 'RES_NOTFOUND'; |
||||
case 18: return 'RES_PARTIAL_READ'; |
||||
case 19: return 'RES_SOME_ERRORS'; |
||||
case 20: return 'RES_NO_SERVERS'; |
||||
case 21: return 'RES_END'; |
||||
case 26: return 'RES_ERRNO'; |
||||
case 32: return 'RES_BUFFERED'; |
||||
case 31: return 'RES_TIMEOUT'; |
||||
case 33: return 'RES_BAD_KEY_PROVIDED'; |
||||
case 11: return 'RES_CONNECTION_SOCKET_CREATE_FAILURE'; |
||||
case -1001: return 'RES_PAYLOAD_FAILURE'; |
||||
|
||||
} |
||||
} |
||||
} |
||||
|
||||
?> |
||||
@ -0,0 +1,368 @@ |
||||
<?php |
||||
class Harmonious_Components_Request implements IHarmonious_Component{ |
||||
const METHOD_HEAD = 'HEAD'; |
||||
const METHOD_GET = 'GET'; |
||||
const METHOD_POST = 'POST'; |
||||
const METHOD_PUT = 'PUT'; |
||||
const METHOD_DELETE = 'DELETE'; |
||||
const METHOD_OPTIONS = 'OPTIONS'; |
||||
const METHOD_OVERRIDE = '_METHOD'; |
||||
|
||||
/** |
||||
* @var string Request method (ie. "GET", "POST", "PUT", "DELETE", "HEAD") |
||||
*/ |
||||
protected $method; |
||||
|
||||
/** |
||||
* @var array Key-value array of HTTP request headers |
||||
*/ |
||||
protected $headers; |
||||
|
||||
/** |
||||
* @var array Names of additional headers to parse from the current |
||||
* HTTP request that are not prefixed with "HTTP_" |
||||
*/ |
||||
protected $additionalHeaders = array('content-type', 'content-length', 'php-auth-user', 'php-auth-pw', 'auth-type', 'x-requested-with'); |
||||
|
||||
/** |
||||
* @var array Key-value array of cookies sent with the |
||||
* current HTTP request |
||||
*/ |
||||
protected $cookies; |
||||
|
||||
/** |
||||
* @var array Key-value array of HTTP GET parameters |
||||
*/ |
||||
protected $get; |
||||
|
||||
/** |
||||
* @var array Key-value array of HTTP POST parameters |
||||
*/ |
||||
protected $post; |
||||
|
||||
/** |
||||
* @var array Key-value array of HTTP PUT parameters |
||||
*/ |
||||
protected $put; |
||||
|
||||
/** |
||||
* @var string Raw body of HTTP request |
||||
*/ |
||||
protected $body; |
||||
|
||||
/** |
||||
* @var string Content type of HTTP request |
||||
*/ |
||||
protected $contentType; |
||||
|
||||
/** |
||||
* @var string Resource URI (ie. "/person/1") |
||||
*/ |
||||
protected $resource; |
||||
|
||||
/** |
||||
* @var string The root URI of the Slim application without trailing slash. |
||||
* This will be "" if the app is installed at the web |
||||
* document root. If the app is installed in a |
||||
* sub-directory "/foo", this will be "/foo". |
||||
*/ |
||||
protected $root; |
||||
|
||||
/** |
||||
* Constructor |
||||
*/ |
||||
public function __construct(Harmonious $app) { |
||||
$this->method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : false; |
||||
$this->headers = $this->loadHttpHeaders(); |
||||
$this->body = @file_get_contents('php://input'); |
||||
$this->get = self::stripSlashesIfMagicQuotes($_GET); |
||||
$this->post = self::stripSlashesIfMagicQuotes($_POST); |
||||
$this->put = self::stripSlashesIfMagicQuotes($this->loadPutParameters()); |
||||
$this->cookies = self::stripSlashesIfMagicQuotes($_COOKIE); |
||||
$this->root = Slim_Http_Uri::getBaseUri(true); |
||||
$this->resource = Slim_Http_Uri::getUri(true); |
||||
$this->checkForHttpMethodOverride(); |
||||
} |
||||
|
||||
/** |
||||
* Is this a GET request? |
||||
* @return bool |
||||
*/ |
||||
public function isGet() { |
||||
return $this->method === self::METHOD_GET; |
||||
} |
||||
|
||||
/** |
||||
* Is this a POST request? |
||||
* @return bool |
||||
*/ |
||||
public function isPost() { |
||||
return $this->method === self::METHOD_POST; |
||||
} |
||||
|
||||
/** |
||||
* Is this a PUT request? |
||||
* @return bool |
||||
*/ |
||||
public function isPut() { |
||||
return $this->method === self::METHOD_PUT; |
||||
} |
||||
|
||||
/** |
||||
* Is this a DELETE request? |
||||
* @return bool |
||||
*/ |
||||
public function isDelete() { |
||||
return $this->method === self::METHOD_DELETE; |
||||
} |
||||
|
||||
/** |
||||
* Is this a HEAD request? |
||||
* @return bool |
||||
*/ |
||||
public function isHead() { |
||||
return $this->method === self::METHOD_HEAD; |
||||
} |
||||
|
||||
/** |
||||
* Is this a OPTIONS request? |
||||
* @return bool |
||||
*/ |
||||
public function isOptions() { |
||||
return $this->method === self::METHOD_OPTIONS; |
||||
} |
||||
|
||||
/** |
||||
* Is this a XHR request? |
||||
* @return bool |
||||
*/ |
||||
public function isAjax() { |
||||
return ( $this->params('isajax') || $this->headers('X_REQUESTED_WITH') === 'XMLHttpRequest' ); |
||||
} |
||||
|
||||
/** |
||||
* Fetch a PUT|POST|GET parameter value |
||||
* |
||||
* The preferred method to fetch the value of a |
||||
* PUT, POST, or GET parameter (searched in that order). |
||||
* |
||||
* @param string $key The paramter name |
||||
* @return string|null The value of parameter, or NULL if parameter not found |
||||
*/ |
||||
public function params( $key ) { |
||||
foreach ( array('put', 'post', 'get') as $dataSource ) { |
||||
$source = $this->$dataSource; |
||||
if ( isset($source[(string)$key]) ) { |
||||
return $source[(string)$key]; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Fetch GET parameter(s) |
||||
* @param string $key Name of parameter |
||||
* @return array|string|null All parameters, parameter value if $key |
||||
* and parameter exists, or NULL if $key |
||||
* and parameter does not exist. |
||||
*/ |
||||
public function get( $key = null ) { |
||||
return $this->arrayOrArrayValue($this->get, $key); |
||||
} |
||||
|
||||
/** |
||||
* Fetch POST parameter(s) |
||||
* @param string $key Name of parameter |
||||
* @return array|string|null All parameters, parameter value if $key |
||||
* and parameter exists, or NULL if $key |
||||
* and parameter does not exist. |
||||
*/ |
||||
public function post( $key = null ) { |
||||
return $this->arrayOrArrayValue($this->post, $key); |
||||
} |
||||
|
||||
/** |
||||
* Fetch PUT parameter(s) |
||||
* @param string $key Name of parameter |
||||
* @return array|string|null All parameters, parameter value if $key |
||||
* and parameter exists, or NULL if $key |
||||
* and parameter does not exist. |
||||
*/ |
||||
public function put( $key = null ) { |
||||
return $this->arrayOrArrayValue($this->put, $key); |
||||
} |
||||
|
||||
/** |
||||
* Fetch COOKIE value(s) |
||||
* @param string $key The cookie name |
||||
* @return array|string|null All parameters, parameter value if $key |
||||
* and parameter exists, or NULL if $key |
||||
* and parameter does not exist. |
||||
*/ |
||||
public function cookies( $key = null ) { |
||||
return $this->arrayOrArrayValue($this->cookies, $key); |
||||
} |
||||
|
||||
/** |
||||
* Get HTTP request header |
||||
* @param string $key The header name |
||||
* @return array|string|null All parameters, parameter value if $key |
||||
* and parameter exists, or NULL if $key |
||||
* and parameter does not exist. |
||||
*/ |
||||
public function headers( $key = null ) { |
||||
return is_null($key) ? $this->headers : $this->arrayOrArrayValue($this->headers, $this->convertHttpHeaderName($key)); |
||||
} |
||||
|
||||
/** |
||||
* Get HTTP request body |
||||
* @return string|false String, or FALSE if body could not be read |
||||
*/ |
||||
public function getBody() { |
||||
return $this->body; |
||||
} |
||||
|
||||
/** |
||||
* Get HTTP method |
||||
* @return string |
||||
*/ |
||||
public function getMethod() { |
||||
return $this->method; |
||||
} |
||||
|
||||
/** |
||||
* Get HTTP request content type |
||||
* @return string |
||||
*/ |
||||
public function getContentType() { |
||||
if ( !isset($this->contentType) ) { |
||||
$contentType = 'application/x-www-form-urlencoded'; |
||||
$header = $this->headers('CONTENT_TYPE'); |
||||
if ( !is_null($header) ) { |
||||
$headerParts = preg_split('/\s*;\s*/', $header); |
||||
$contentType = $headerParts[0]; |
||||
} |
||||
$this->contentType = $contentType; |
||||
} |
||||
return $this->contentType; |
||||
} |
||||
|
||||
/** |
||||
* Get HTTP request resource URI |
||||
* @return string |
||||
*/ |
||||
public function getResourceUri() { |
||||
return $this->resource; |
||||
} |
||||
|
||||
/** |
||||
* Get HTTP request root URI |
||||
* @return string |
||||
*/ |
||||
public function getRootUri() { |
||||
return $this->root; |
||||
} |
||||
|
||||
/** |
||||
* Fetch array or array value |
||||
* @param array $array |
||||
* @param string $key |
||||
* @return array|mixed Array if key is null, else array value |
||||
*/ |
||||
protected function arrayOrArrayValue( array &$array, $key = null ) { |
||||
return is_null($key) ? $array : $this->arrayValueForKey($array, $key); |
||||
} |
||||
|
||||
/** |
||||
* Fetch value from array |
||||
* @return mixed|null |
||||
*/ |
||||
protected function arrayValueForKey( array &$array, $key ) { |
||||
return isset($array[(string)$key]) ? $array[(string)$key] : null; |
||||
} |
||||
|
||||
/** |
||||
* Strip slashes from string or array of strings |
||||
* @param array|string $rawData |
||||
* @return array|string |
||||
*/ |
||||
public static function stripSlashesIfMagicQuotes( $rawData ) { |
||||
/* if ( get_magic_quotes_gpc() ) { |
||||
return is_array($rawData) ? array_map(array('self', 'stripSlashesIfMagicQuotes'), $rawData) : stripslashes($rawData); |
||||
} else { |
||||
return $rawData; |
||||
}*/ |
||||
if (is_array($rawData)) { |
||||
return array_map(array('self', 'stripSlashesIfMagicQuotes'), $rawData); |
||||
} else { |
||||
$data = $rawData; |
||||
// $data = stripslashes($rawData); |
||||
// $data = htmlspecialchars($data); |
||||
// $data = strip_tags($data); |
||||
return $data; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Get PUT parameters |
||||
* @return array Key-value array of HTTP request PUT parameters |
||||
*/ |
||||
protected function loadPutParameters() { |
||||
if ( $this->getContentType() === 'application/x-www-form-urlencoded' ) { |
||||
$input = is_string($this->body) ? $this->body : ''; |
||||
if ( function_exists('mb_parse_str') ) { |
||||
mb_parse_str($input, $output); |
||||
} else { |
||||
parse_str($input, $output); |
||||
} |
||||
return $output; |
||||
} else { |
||||
return array(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Get HTTP request headers |
||||
* @return array Key-value array of HTTP request headers |
||||
*/ |
||||
protected function loadHttpHeaders() { |
||||
$headers = array(); |
||||
foreach ( $_SERVER as $key => $value ) { |
||||
$key = $this->convertHttpHeaderName($key); |
||||
if ( strpos($key, 'http-') === 0 || in_array($key, $this->additionalHeaders) ) { |
||||
$name = str_replace('http-', '', $key); |
||||
$headers[$name] = $value; |
||||
} |
||||
} |
||||
return $headers; |
||||
} |
||||
|
||||
/** |
||||
* Convert HTTP header name |
||||
* @return string |
||||
*/ |
||||
protected function convertHttpHeaderName( $name ) { |
||||
return str_replace('_', '-', strtolower($name)); |
||||
} |
||||
|
||||
/** |
||||
* Check for HTTP request method override |
||||
* |
||||
* Because traditional web browsers do not support PUT and DELETE |
||||
* HTTP methods, we use a hidden form input field to |
||||
* mimic PUT and DELETE requests. We check for this override here. |
||||
* |
||||
* @return void |
||||
*/ |
||||
protected function checkForHttpMethodOverride() { |
||||
if ( isset($this->post[self::METHOD_OVERRIDE]) ) { |
||||
$this->method = $this->post[self::METHOD_OVERRIDE]; |
||||
unset($this->post[self::METHOD_OVERRIDE]); |
||||
if ( $this->isPut() ) { |
||||
$this->put = $this->post; |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
?> |
||||
@ -0,0 +1,282 @@ |
||||
<?php |
||||
class Harmonious_Components_Response implements IHarmonious_Component { |
||||
|
||||
/** |
||||
* @var Slim_Http_Request |
||||
*/ |
||||
protected $request; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
protected $httpVersion = '1.1'; |
||||
|
||||
/** |
||||
* @var int HTTP status code |
||||
*/ |
||||
protected $status = 200; |
||||
|
||||
/** |
||||
* @var array Key-value array of HTTP response headers |
||||
*/ |
||||
protected $headers = array(); |
||||
|
||||
/** |
||||
* @var string HTTP response body |
||||
*/ |
||||
protected $body = ''; |
||||
|
||||
/** |
||||
* @var int Length of HTTP response body |
||||
*/ |
||||
protected $length = 0; |
||||
|
||||
/** |
||||
* @var array HTTP response codes and messages |
||||
*/ |
||||
protected static $messages = array( |
||||
//Informational 1xx |
||||
100 => '100 Continue', |
||||
101 => '101 Switching Protocols', |
||||
//Successful 2xx |
||||
200 => '200 OK', |
||||
201 => '201 Created', |
||||
202 => '202 Accepted', |
||||
203 => '203 Non-Authoritative Information', |
||||
204 => '204 No Content', |
||||
205 => '205 Reset Content', |
||||
206 => '206 Partial Content', |
||||
//Redirection 3xx |
||||
300 => '300 Multiple Choices', |
||||
301 => '301 Moved Permanently', |
||||
302 => '302 Found', |
||||
303 => '303 See Other', |
||||
304 => '304 Not Modified', |
||||
305 => '305 Use Proxy', |
||||
306 => '306 (Unused)', |
||||
307 => '307 Temporary Redirect', |
||||
//Client Error 4xx |
||||
400 => '400 Bad Request', |
||||
401 => '401 Unauthorized', |
||||
402 => '402 Payment Required', |
||||
403 => '403 Forbidden', |
||||
404 => '404 Not Found', |
||||
405 => '405 Method Not Allowed', |
||||
406 => '406 Not Acceptable', |
||||
407 => '407 Proxy Authentication Required', |
||||
408 => '408 Request Timeout', |
||||
409 => '409 Conflict', |
||||
410 => '410 Gone', |
||||
411 => '411 Length Required', |
||||
412 => '412 Precondition Failed', |
||||
413 => '413 Request Entity Too Large', |
||||
414 => '414 Request-URI Too Long', |
||||
415 => '415 Unsupported Media Type', |
||||
416 => '416 Requested Range Not Satisfiable', |
||||
417 => '417 Expectation Failed', |
||||
422 => '422 Unprocessable Entity', |
||||
423 => '423 Locked', |
||||
//Server Error 5xx |
||||
500 => '500 Internal Server Error', |
||||
501 => '501 Not Implemented', |
||||
502 => '502 Bad Gateway', |
||||
503 => '503 Service Unavailable', |
||||
504 => '504 Gateway Timeout', |
||||
505 => '505 HTTP Version Not Supported', |
||||
550 => '550 Incorrect hash', |
||||
551 => '551 Internal Server Error', |
||||
552 => '552 Internal Server Error' |
||||
); |
||||
|
||||
/** |
||||
* @var CookieJar Manages Cookies to be sent with this Response |
||||
*/ |
||||
protected $cookieJar; |
||||
|
||||
/** |
||||
* Constructor |
||||
*/ |
||||
public function __construct(Harmonious $app ) { |
||||
$this->request = $app->request; |
||||
$this->header('Content-Type', 'text/html'); |
||||
} |
||||
|
||||
/** |
||||
* Set and/or get the HTTP response version |
||||
* @param string $version |
||||
* @return void |
||||
* @throws InvalidArgumentException If argument is not a valid HTTP version |
||||
*/ |
||||
public function httpVersion( $version = null ) { |
||||
if ( $version ) { |
||||
$version = (string)$version; |
||||
if ( $version === '1.0' || $version === '1.1' ) { |
||||
$this->httpVersion = $version; |
||||
} else { |
||||
throw new InvalidArgumentException('Invalid HTTP version in Response object'); |
||||
} |
||||
} |
||||
return $this->httpVersion; |
||||
} |
||||
|
||||
/** |
||||
* Set and/or get the HTTP response status code |
||||
* @param int $status |
||||
* @return int |
||||
* @throws InvalidArgumentException If argument is not a valid HTTP status code |
||||
*/ |
||||
public function status( $status = null ) { |
||||
if ( !is_null($status) ) { |
||||
if ( !in_array(intval($status), array_keys(self::$messages)) ) { |
||||
throw new InvalidArgumentException('Cannot set Response status. Provided status code "' . $status . '" is not a valid HTTP response code.'); |
||||
} |
||||
$this->status = intval($status); |
||||
} |
||||
return $this->status; |
||||
} |
||||
|
||||
/** |
||||
* Get HTTP response headers |
||||
* @return array |
||||
*/ |
||||
public function headers() { |
||||
return $this->headers; |
||||
} |
||||
|
||||
/** |
||||
* Get and/or set an HTTP response header |
||||
* @param string $key The header name |
||||
* @param string $value The header value |
||||
* @return string|null The header value, or NULL if header not set |
||||
*/ |
||||
public function header( $key, $value = null ) { |
||||
if ( !is_null($value) ) { |
||||
$this->headers[$key] = $value; |
||||
} |
||||
return isset($this->headers[$key]) ? $this->headers[$key] : null; |
||||
} |
||||
|
||||
/** |
||||
* Set the HTTP response body |
||||
* @param string $body The new HTTP response body |
||||
* @return string The new HTTP response body |
||||
*/ |
||||
public function body( $body = null ) { |
||||
if ( !is_null($body) ) { |
||||
$this->body = ''; |
||||
$this->length = 0; |
||||
$this->write($body); |
||||
} |
||||
return $this->body; |
||||
} |
||||
|
||||
/** |
||||
* Append the HTTP response body |
||||
* @param string $body Content to append to the current HTTP response body |
||||
* @return string The updated HTTP response body |
||||
*/ |
||||
public function write( $body ) { |
||||
$body = (string)$body; |
||||
$this->length += strlen($body); |
||||
$this->body .= $body; |
||||
$this->header('Content-Length', $this->length); |
||||
return $body; |
||||
} |
||||
|
||||
/** |
||||
* Set cookie jar |
||||
* @param Slim_Http_CookieJar $cookieJar |
||||
* @return void |
||||
*/ |
||||
public function setCookieJar( Slim_Http_CookieJar $cookieJar ) { |
||||
$this->cookieJar = $cookieJar; |
||||
} |
||||
|
||||
/** |
||||
* Get cookie jar |
||||
* @return Slim_Http_CookieJar |
||||
*/ |
||||
public function getCookieJar() { |
||||
return $this->cookieJar; |
||||
} |
||||
|
||||
/** |
||||
* Finalize response headers before response is sent |
||||
* @return void |
||||
*/ |
||||
public function finalize() { |
||||
if ( in_array($this->status, array(204, 304)) ) { |
||||
$this->body(''); |
||||
unset($this->headers['Content-Type']); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Get message for HTTP status code |
||||
* @return string|null |
||||
*/ |
||||
public static function getMessageForCode( $status ) { |
||||
return isset(self::$messages[$status]) ? self::$messages[$status] : null; |
||||
} |
||||
|
||||
/** |
||||
* Can this HTTP response have a body? |
||||
* @return bool |
||||
*/ |
||||
public function canHaveBody() { |
||||
return ( $this->status < 100 || $this->status >= 200 ) && $this->status != 204 && $this->status != 304; |
||||
} |
||||
|
||||
/** |
||||
* Send headers for HTTP response |
||||
* @return void |
||||
*/ |
||||
protected function sendHeaders() { |
||||
//Finalize response |
||||
$this->finalize(); |
||||
|
||||
if ( substr(PHP_SAPI, 0, 3) === 'cgi') { |
||||
//Send Status header if running with fastcgi |
||||
header('Status: ' . self::getMessageForCode($this->status())); |
||||
} else { |
||||
//Else send HTTP message |
||||
header(sprintf('HTTP/%s %s', $this->httpVersion, self::getMessageForCode($this->status()))); |
||||
} |
||||
|
||||
//Send headers |
||||
foreach ( $this->headers() as $name => $value ) { |
||||
header("$name: $value"); |
||||
} |
||||
|
||||
//Send cookies |
||||
foreach ( $this->getCookieJar()->getResponseCookies() as $name => $cookie ) { |
||||
/* httponly option is only available for PHP version >= 5.2 */ |
||||
if ( version_compare(PHP_VERSION, '5.2.0', '>=') ) { |
||||
setcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpires(), $cookie->getPath(), $cookie->getDomain(), $cookie->getSecure(), $cookie->getHttpOnly()); |
||||
} else { |
||||
setcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpires(), $cookie->getPath(), $cookie->getDomain(), $cookie->getSecure()); |
||||
} |
||||
} |
||||
|
||||
//Flush all output to client |
||||
flush(); |
||||
} |
||||
|
||||
/** |
||||
* Send HTTP response |
||||
* |
||||
* This method will set Response headers, set Response cookies, |
||||
* and `echo` the Response body to the current output buffer. |
||||
* |
||||
* @return void |
||||
*/ |
||||
public function send() { |
||||
if ( !headers_sent() ) { |
||||
$this->sendHeaders(); |
||||
} |
||||
if ( $this->canHaveBody() && $this->request->isHead() === false ) { |
||||
echo $this->body; |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,6 @@ |
||||
<?php |
||||
interface IHarmonious_Component |
||||
{ |
||||
public function __construct(Harmonious $app) ; |
||||
} |
||||
?> |
||||
@ -0,0 +1,10 @@ |
||||
<?php |
||||
abstract class Harmonious_Controller |
||||
{ |
||||
public function supportsHttpMethod($method) { |
||||
return false; |
||||
} |
||||
|
||||
abstract public function run($app); |
||||
} |
||||
?> |
||||
@ -0,0 +1 @@ |
||||
deny from all |
||||
@ -0,0 +1,43 @@ |
||||
<?php |
||||
/** |
||||
* Slim - a micro PHP 5 framework |
||||
* |
||||
* @author Josh Lockhart <info@joshlockhart.com> |
||||
* @copyright 2011 Josh Lockhart |
||||
* @link http://www.slimframework.com |
||||
* @license http://www.slimframework.com/license |
||||
* @version 1.5.0 |
||||
* |
||||
* MIT LICENSE |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining |
||||
* a copy of this software and associated documentation files (the |
||||
* "Software"), to deal in the Software without restriction, including |
||||
* without limitation the rights to use, copy, modify, merge, publish, |
||||
* distribute, sublicense, and/or sell copies of the Software, and to |
||||
* permit persons to whom the Software is furnished to do so, subject to |
||||
* the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be |
||||
* included in all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
/** |
||||
* Stop Exception |
||||
* |
||||
* This Exception is thrown when the Slim application needs to abort |
||||
* processing and return control flow to the outer PHP script. |
||||
* |
||||
* @package Slim |
||||
* @author Josh Lockhart <info@joshlockhart.com> |
||||
* @since Version 1.0 |
||||
*/ |
||||
class Slim_Exception_Stop extends Exception {} |
||||
@ -0,0 +1,871 @@ |
||||
<?php |
||||
//Ensure PHP session IDs only use the characters [a-z0-9] |
||||
ini_set('session.hash_bits_per_character', 4); |
||||
ini_set('session.hash_function', 0); |
||||
|
||||
//Slim's Encryted Cookies rely on libmcyrpt and these two constants. |
||||
//If libmycrpt is unavailable, we ensure the expected constants |
||||
//are available to avoid errors. |
||||
if ( !defined('MCRYPT_RIJNDAEL_256') ) { |
||||
define('MCRYPT_RIJNDAEL_256', 0); |
||||
} |
||||
if ( !defined('MCRYPT_MODE_CBC') ) { |
||||
define('MCRYPT_MODE_CBC', 0); |
||||
} |
||||
|
||||
//This determines which errors are reported by PHP. By default, all |
||||
//errors (including E_STRICT) are reported. |
||||
error_reporting(E_ALL | E_STRICT); |
||||
|
||||
//PHP 5.3 will complain if you don't set a timezone. If you do not |
||||
//specify your own timezone before requiring Slim, this tells PHP to use UTC. |
||||
if ( @date_default_timezone_set(date_default_timezone_get()) === false ) { |
||||
date_default_timezone_set('UTC'); |
||||
} |
||||
|
||||
spl_autoload_register(array('Harmonious', 'autoloader')); |
||||
|
||||
class Harmonious |
||||
{ |
||||
protected $template_params = array(); |
||||
protected $components; |
||||
protected $request; |
||||
protected $response; |
||||
protected $view; |
||||
protected $log; |
||||
protected $mode; |
||||
protected $settings; |
||||
protected $hooks = array( |
||||
'app.before' => array(array()), |
||||
'app.before.router' => array(array()), |
||||
'app.before.run' => array(array()), |
||||
'app.after.run' => array(array()), |
||||
'app.after.router' => array(array()), |
||||
'app.after' => array(array()), |
||||
'error.not.found' => array(array()), |
||||
'error.500' => array(array()), |
||||
'error.halt' => array(array()) |
||||
); |
||||
|
||||
/** |
||||
* Constructor |
||||
* @param array $userSettings |
||||
* @return void |
||||
*/ |
||||
public function __construct( $userSettings = array() ) { |
||||
//Merge application settings |
||||
$this->settings = array_merge(array( |
||||
//Mode |
||||
'mode' => 'development', |
||||
//Logging |
||||
'log.enable' => false, |
||||
'log.logger' => null, |
||||
'log.path' => './logs', |
||||
'log.level' => 4, |
||||
//Debugging |
||||
'debug' => true, |
||||
//View |
||||
'templates.path' => './templates', |
||||
'view' => 'Slim_View', |
||||
//Settings for all cookies |
||||
'cookies.lifetime' => '20 minutes', |
||||
'cookies.path' => '/', |
||||
'cookies.domain' => '', |
||||
'cookies.secure' => false, |
||||
'cookies.httponly' => false, |
||||
//Settings for encrypted cookies |
||||
'cookies.secret_key' => 'CHANGE_ME', |
||||
'cookies.cipher' => MCRYPT_RIJNDAEL_256, |
||||
'cookies.cipher_mode' => MCRYPT_MODE_CBC, |
||||
'cookies.encrypt' => true, |
||||
'cookies.user_id' => 'DEFAULT', |
||||
//Session handler |
||||
'session.handler' => null, //new Harmonious_Session_Handler_Files(), |
||||
'session.flash_key' => 'flash', |
||||
//HTTP |
||||
'http.version' => null, |
||||
'controller_path'=>'./controllers' |
||||
), $userSettings); |
||||
|
||||
//Determine application mode |
||||
$this->getMode(); |
||||
|
||||
$this->components = new Harmonious_Components_Factory($this); |
||||
|
||||
//Setup HTTP request and response handling |
||||
$this->request = $this->components['request']; |
||||
$this->response = $this->components['response'];; |
||||
$this->response->setCookieJar(new Slim_Http_CookieJar($this->settings['cookies.secret_key'], array( |
||||
'high_confidentiality' => $this->settings['cookies.encrypt'], |
||||
'mcrypt_algorithm' => $this->settings['cookies.cipher'], |
||||
'mcrypt_mode' => $this->settings['cookies.cipher_mode'], |
||||
'enable_ssl' => $this->settings['cookies.secure'] |
||||
))); |
||||
$this->response->httpVersion($this->settings['http.version']); |
||||
|
||||
//Start session if not already started |
||||
if ( session_id() === '' ) { |
||||
$sessionHandler = $this->config('session.handler'); |
||||
if ( $sessionHandler instanceof Harmonious_Session_Handler ) { |
||||
$sessionHandler->register($this); |
||||
} |
||||
session_cache_limiter(false); |
||||
session_start(); |
||||
} |
||||
|
||||
//Setup view |
||||
$this->view($this->config('view')); |
||||
|
||||
//Set global Error handler after Harmonious app instantiated |
||||
set_error_handler(array('Harmonious', 'handleErrors')); |
||||
|
||||
//set_exception_handler(array('Harmonious', 'handleExceptions')); |
||||
|
||||
register_shutdown_function(array($this, 'FatalErrorCatcher')); |
||||
} |
||||
|
||||
/** |
||||
* Run the Harmonious application |
||||
* @return void |
||||
*/ |
||||
public function run() { |
||||
try { |
||||
try { |
||||
$this->applyHook('app.before', $this); |
||||
ob_start(); |
||||
$this->applyHook('app.before.router', $this); |
||||
$httpMethod = $this->request->getMethod(); |
||||
$uri = rtrim($this->request->getResourceUri(), "/"); |
||||
if ($uri == '') $uri = '/index'; |
||||
$controller_name = $this->config('controller_path') . $uri . "_controller.php"; |
||||
$controller_class_name = substr($uri, strrpos($uri, '/') + 1) . "Controller"; |
||||
if (file_exists($controller_name)) { |
||||
include ($controller_name); |
||||
//создать экземпляр класса и проверить поддерживается ли http метод, если нет - ошибка 405 |
||||
$controller = new $controller_class_name(); |
||||
if (!$controller->supportsHttpMethod($httpMethod)) $this->halt(405, 'HTTP Method not supported'); |
||||
$this->applyHook('app.before.run', $this); |
||||
$controller->run($this); |
||||
$this->applyHook('app.after.run', $this); |
||||
} else { |
||||
//404 |
||||
$this->getLog()->debug('404 controller_name: ' . $controller_name); |
||||
$this->notFound(); |
||||
} |
||||
$this->response->write(ob_get_clean()); |
||||
$this->applyHook('app.after.router', $this); |
||||
session_write_close(); |
||||
$this->response->send(); |
||||
$this->applyHook('app.after', $this); |
||||
} catch ( Exception $e ) { |
||||
if ( $e instanceof Slim_Exception_Stop ) throw $e; |
||||
$this->getLog()->error($e); |
||||
if ( $this->config('debug') === true ) { |
||||
$this->halt(500, self::generateErrorMarkup($e->getMessage(), $e->getFile(), $e->getLine(), $e->getTraceAsString())); |
||||
} else { |
||||
$this->error($e); |
||||
} |
||||
} |
||||
} catch ( Slim_Exception_Stop $e ) { |
||||
//Exit application context |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* "Магические" методы для работы с компонентами Harmonious. |
||||
* http://www.php.net/manual/ru/language.oop5.magic.php |
||||
* |
||||
* Возвращает компонент Harmonious из фабрики. |
||||
* @param type $name - Имя компонента |
||||
* @return type - объект(компонент Harmonious) |
||||
*/ |
||||
public function __get($name) { |
||||
if ($name == 'components') return $this->components; |
||||
return $this->components[$name]; |
||||
} |
||||
|
||||
/** |
||||
* Добавляет компонент в фабрику |
||||
* @param type $name - имя компонента |
||||
* @param type $value - объект(компонент Harmonious) |
||||
*/ |
||||
public function __set($name, $value) |
||||
{ |
||||
$this->components[$name] = $value; |
||||
} |
||||
|
||||
/****** Параметры шаблона ******/ |
||||
|
||||
/** |
||||
* Глобальный массив параметров шаблона используется для наполнения шаблона параметрами из различных |
||||
* участков кода. Например, часть параметров может быть передана посредством хука, а остальные посредством |
||||
* контроллена. См. также метод render, в котором этот глобальные массив объединяется с переданным перед |
||||
* передачей в шаблон. |
||||
* |
||||
* Объединяет два массива: переданный в параметре и глобальный массив параметров шаблона |
||||
* @param type $array |
||||
*/ |
||||
public function addTemplateParam($array) { |
||||
$this->template_params = array_merge($this->template_params, $array); |
||||
} |
||||
|
||||
/** |
||||
* Чистит глобальный массив параметров шаблона |
||||
*/ |
||||
public function clearTemplateParams() { |
||||
unset($this->template_params); |
||||
$this->template_params = array(); |
||||
} |
||||
|
||||
/** |
||||
* Возвращает глобальный массив параметров шаблона |
||||
* @return type |
||||
*/ |
||||
public function getTemplateParams() { |
||||
return $this->template_params; |
||||
} |
||||
|
||||
/** |
||||
* Render a template |
||||
* @param string $template The name of the template passed into the View::render method |
||||
* @param array $data Associative array of data made available to the View |
||||
* @param int $status The HTTP response status code to use (Optional) |
||||
* @return void |
||||
*/ |
||||
public function render( $template, $data = array(), $status = null ) { |
||||
if ( !is_null($status) ) $this->response->status($status); |
||||
$data = array_merge($this->template_params, $data); |
||||
$this->view->appendData($data); |
||||
$this->view->display($template); |
||||
} |
||||
|
||||
/** |
||||
* Render a template |
||||
* @param string $template The name of the template passed into the View::render method |
||||
* @param array $data Associative array of data made available to the View |
||||
* @param int $status The HTTP response status code to use (Optional) |
||||
* @return void |
||||
*/ |
||||
public function fetch( $template, $data = array(), $status = null ) { |
||||
if ( !is_null($status) ) $this->response->status($status); |
||||
$data = array_merge($this->template_params, $data); |
||||
$this->view->appendData($data); |
||||
return $this->view->fetch($template); |
||||
} |
||||
|
||||
/** |
||||
* Harmonious auto-loader |
||||
* Этот метод производит загрузку файлов с классами при первом обращении к ним. Грузит свои классы и классы Slim-а |
||||
* @return void |
||||
*/ |
||||
public static function autoloader( $className ) { |
||||
$className = str_replace('Slim', 'Harmonious', $className); |
||||
|
||||
if ( strpos($className, 'Harmonious') !== 0 ) { |
||||
return; |
||||
} |
||||
$file = dirname(__FILE__) . '/' . str_replace('_', DIRECTORY_SEPARATOR, substr($className, 11)) . '.php'; |
||||
|
||||
if ( file_exists($file) ) { |
||||
require $file; |
||||
} |
||||
} |
||||
|
||||
|
||||
/***** CONFIGURATION *****/ |
||||
/** |
||||
* Get application mode |
||||
* @return string |
||||
*/ |
||||
public function getMode() { |
||||
if ( !isset($this->mode) ) { |
||||
$mode = $this->config('mode'); |
||||
if ( !is_null($mode) ) $this->mode = (string)$this->config('mode'); |
||||
else $this->mode = 'production'; |
||||
} |
||||
return $this->mode; |
||||
} |
||||
|
||||
/** |
||||
* Configure Slim for a given mode |
||||
* |
||||
* This method will immediately invoke the callable if |
||||
* the specified mode matches the current application mode. |
||||
* Otherwise, the callable is ignored. This should be called |
||||
* only _after_ you initialize your Slim app. |
||||
* |
||||
* @param string $mode |
||||
* @param mixed $callable |
||||
* @return void |
||||
*/ |
||||
public function configureMode( $mode, $callable ) { |
||||
if ( $mode === $this->getMode() && is_callable($callable) ) { |
||||
call_user_func($callable); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Configure Slim Settings |
||||
* |
||||
* This method defines application settings and acts as a setter and a getter. |
||||
* |
||||
* If only one argument is specified and that argument is a string, the value |
||||
* of the setting identified by the first argument will be returned, or NULL if |
||||
* that setting does not exist. |
||||
* |
||||
* If only one argument is specified and that argument is an associative array, |
||||
* the array will be merged into the existing application settings. |
||||
* |
||||
* If two arguments are provided, the first argument is the name of the setting |
||||
* to be created or updated, and the second argument is the setting value. |
||||
* |
||||
* @param string|array $name If a string, the name of the setting to set or retrieve. Else an associated array of setting names and values |
||||
* @param mixed $value If name is a string, the value of the setting identified by $name |
||||
* @return mixed The value of a setting if only one argument is a string |
||||
*/ |
||||
public function config( $name, $value = null ) { |
||||
if ( func_num_args() === 1 ) { |
||||
if ( is_array($name) ) $this->settings = array_merge($this->settings, $name); |
||||
else return in_array($name, array_keys($this->settings)) ? $this->settings[$name] : null; |
||||
} else { |
||||
$this->settings[$name] = $value; |
||||
} |
||||
} |
||||
|
||||
/***** LOGGING *****/ |
||||
|
||||
/** |
||||
* Get application Log (lazy-loaded) |
||||
* @return Slim_Log |
||||
*/ |
||||
public function getLog() { |
||||
if ( !isset($this->log) ) { |
||||
$this->log = new Slim_Log(); |
||||
$this->log->setEnabled($this->config('log.enable')); |
||||
$logger = $this->config('log.logger'); |
||||
if ( $logger ) { |
||||
$this->log->setLogger($logger); |
||||
} else { |
||||
$this->log->setLogger(new Slim_Logger($this->config('log.path'), $this->config('log.level'))); |
||||
} |
||||
} |
||||
return $this->log; |
||||
} |
||||
|
||||
/** |
||||
* Not Found Handler |
||||
* @return void |
||||
*/ |
||||
public function notFound() { |
||||
ob_start(); |
||||
$this->applyHook('error.not.found', $this); |
||||
if (ob_get_contents() == '') call_user_func(array($this, 'defaultNotFound')); |
||||
$this->halt(404, ob_get_clean()); |
||||
} |
||||
|
||||
/** |
||||
* Error Handler |
||||
* @return void |
||||
*/ |
||||
public function error( $argument = null ) { |
||||
ob_start(); |
||||
$this->applyHook('error.500', $argument ); |
||||
call_user_func_array(array($this, 'defaultError'), array($argument)); |
||||
$this->halt(500, ob_get_clean()); |
||||
} |
||||
|
||||
/***** ACCESSORS *****/ |
||||
/** |
||||
* Get and/or set the View |
||||
* |
||||
* This method declares the View to be used by the Slim application. |
||||
* If the argument is a string, Slim will instantiate a new object |
||||
* of the same class. If the argument is an instance of View or a subclass |
||||
* of View, Slim will use the argument as the View. |
||||
* |
||||
* If a View already exists and this method is called to create a |
||||
* new View, data already set in the existing View will be |
||||
* transferred to the new View. |
||||
* |
||||
* @param string|Slim_View $viewClass The name of a Slim_View class; |
||||
* An instance of Slim_View; |
||||
* @return Slim_View |
||||
*/ |
||||
public function view( $viewClass = null ) { |
||||
if ( !is_null($viewClass) ) { |
||||
$existingData = is_null($this->view) ? array() : $this->view->getData(); |
||||
if ( $viewClass instanceOf Slim_View ) { |
||||
$this->view = $viewClass; |
||||
} else { |
||||
$this->view = new $viewClass(); |
||||
} |
||||
$this->view->appendData($existingData); |
||||
$this->view->setTemplatesDirectory($this->config('templates.path')); |
||||
} |
||||
return $this->view; |
||||
} |
||||
|
||||
/***** HTTP CACHING *****/ |
||||
|
||||
/** |
||||
* Set Last-Modified HTTP Response Header |
||||
* |
||||
* Set the HTTP 'Last-Modified' header and stop if a conditional |
||||
* GET request's `If-Modified-Since` header matches the last modified time |
||||
* of the resource. The `time` argument is a UNIX timestamp integer value. |
||||
* When the current request includes an 'If-Modified-Since' header that |
||||
* matches the specified last modified time, the application will stop |
||||
* and send a '304 Not Modified' response to the client. |
||||
* |
||||
* @param int $time The last modified UNIX timestamp |
||||
* @throws SlimException Returns HTTP 304 Not Modified response if resource last modified time matches `If-Modified-Since` header |
||||
* @throws InvalidArgumentException If provided timestamp is not an integer |
||||
* @return void |
||||
*/ |
||||
public function lastModified( $time ) { |
||||
if ( is_integer($time) ) { |
||||
$this->response->header('Last-Modified', date(DATE_RFC1123, $time)); |
||||
if ( $time === strtotime($this->request->headers('IF_MODIFIED_SINCE')) ) $this->halt(304); |
||||
} else { |
||||
throw new InvalidArgumentException('Slim::lastModified only accepts an integer UNIX timestamp value.'); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Set ETag HTTP Response Header |
||||
* |
||||
* Set the etag header and stop if the conditional GET request matches. |
||||
* The `value` argument is a unique identifier for the current resource. |
||||
* The `type` argument indicates whether the etag should be used as a strong or |
||||
* weak cache validator. |
||||
* |
||||
* When the current request includes an 'If-None-Match' header with |
||||
* a matching etag, execution is immediately stopped. If the request |
||||
* method is GET or HEAD, a '304 Not Modified' response is sent. |
||||
* |
||||
* @param string $value The etag value |
||||
* @param string $type The type of etag to create; either "strong" or "weak" |
||||
* @throws InvalidArgumentException If provided type is invalid |
||||
* @return void |
||||
*/ |
||||
public function etag( $value, $type = 'strong' ) { |
||||
|
||||
//Ensure type is correct |
||||
if ( !in_array($type, array('strong', 'weak')) ) { |
||||
throw new InvalidArgumentException('Invalid Slim::etag type. Expected "strong" or "weak".'); |
||||
} |
||||
|
||||
//Set etag value |
||||
$value = '"' . $value . '"'; |
||||
if ( $type === 'weak' ) $value = 'W/'.$value; |
||||
$this->response->header('ETag', $value); |
||||
|
||||
//Check conditional GET |
||||
if ( $etagsHeader = $this->request->headers('IF_NONE_MATCH')) { |
||||
$etags = preg_split('@\s*,\s*@', $etagsHeader); |
||||
if ( in_array($value, $etags) || in_array('*', $etags) ) $this->halt(304); |
||||
} |
||||
|
||||
} |
||||
|
||||
/***** COOKIES *****/ |
||||
|
||||
/** |
||||
* Set a normal, unencrypted Cookie |
||||
* |
||||
* @param string $name The cookie name |
||||
* @param mixed $value The cookie value |
||||
* @param mixed $time The duration of the cookie; |
||||
* If integer, should be UNIX timestamp; |
||||
* If string, converted to UNIX timestamp with `strtotime`; |
||||
* @param string $path The path on the server in which the cookie will be available on |
||||
* @param string $domain The domain that the cookie is available to |
||||
* @param bool $secure Indicates that the cookie should only be transmitted over a secure |
||||
* HTTPS connection to/from the client |
||||
* @param bool $httponly When TRUE the cookie will be made accessible only through the HTTP protocol |
||||
* @return void |
||||
*/ |
||||
public function setCookie( $name, $value, $time = null, $path = null, $domain = null, $secure = null, $httponly = null ) { |
||||
$time = is_null($time) ? $this->config('cookies.lifetime') : $time; |
||||
$path = is_null($path) ? $this->config('cookies.path') : $path; |
||||
$domain = is_null($domain) ? $this->config('cookies.domain') : $domain; |
||||
$secure = is_null($secure) ? $this->config('cookies.secure') : $secure; |
||||
$httponly = is_null($httponly) ? $this->config('cookies.httponly') : $httponly; |
||||
$this->response->getCookieJar()->setClassicCookie($name, $value, $time, $path, $domain, $secure, $httponly); |
||||
} |
||||
|
||||
/** |
||||
* Get the value of a Cookie from the current HTTP Request |
||||
* |
||||
* Return the value of a cookie from the current HTTP request, |
||||
* or return NULL if cookie does not exist. Cookies created during |
||||
* the current request will not be available until the next request. |
||||
* |
||||
* @param string $name |
||||
* @return string|null |
||||
*/ |
||||
public function getCookie( $name ) { |
||||
return $this->request->cookies($name); |
||||
} |
||||
|
||||
/** |
||||
* Set an encrypted Cookie |
||||
* |
||||
* @param string $name The cookie name |
||||
* @param mixed $value The cookie value |
||||
* @param mixed $time The duration of the cookie; |
||||
* If integer, should be UNIX timestamp; |
||||
* If string, converted to UNIX timestamp with `strtotime`; |
||||
* @param string $path The path on the server in which the cookie will be available on |
||||
* @param string $domain The domain that the cookie is available to |
||||
* @param bool $secure Indicates that the cookie should only be transmitted over a secure |
||||
* HTTPS connection from the client |
||||
* @param bool $httponly When TRUE the cookie will be made accessible only through the HTTP protocol |
||||
* @return void |
||||
*/ |
||||
public function setEncryptedCookie( $name, $value, $time = null, $path = null, $domain = null, $secure = null, $httponly = null ) { |
||||
$time = is_null($time) ? $this->config('cookies.lifetime') : $time; |
||||
$path = is_null($path) ? $this->config('cookies.path') : $path; |
||||
$domain = is_null($domain) ? $this->config('cookies.domain') : $domain; |
||||
$secure = is_null($secure) ? $this->config('cookies.secure') : $secure; |
||||
$httponly = is_null($httponly) ? $this->config('cookies.httponly') : $httponly; |
||||
$userId = $this->config('cookies.user_id'); |
||||
$this->response->getCookieJar()->setCookie($name, $value, $userId, $time, $path, $domain, $secure, $httponly); |
||||
} |
||||
|
||||
/** |
||||
* Get the value of an encrypted Cookie from the current HTTP request |
||||
* |
||||
* Return the value of an encrypted cookie from the current HTTP request, |
||||
* or return NULL if cookie does not exist. Encrypted cookies created during |
||||
* the current request will not be available until the next request. |
||||
* |
||||
* @param string $name |
||||
* @return string|null |
||||
*/ |
||||
public function getEncryptedCookie( $name ) { |
||||
$value = $this->response->getCookieJar()->getCookieValue($name); |
||||
return ($value === false) ? null : $value; |
||||
} |
||||
|
||||
/** |
||||
* Delete a Cookie (for both normal or encrypted Cookies) |
||||
* |
||||
* Remove a Cookie from the client. This method will overwrite an existing Cookie |
||||
* with a new, empty, auto-expiring Cookie. This method's arguments must match |
||||
* the original Cookie's respective arguments for the original Cookie to be |
||||
* removed. If any of this method's arguments are omitted or set to NULL, the |
||||
* default Cookie setting values (set during Slim::init) will be used instead. |
||||
* |
||||
* @param string $name The cookie name |
||||
* @param string $path The path on the server in which the cookie will be available on |
||||
* @param string $domain The domain that the cookie is available to |
||||
* @param bool $secure Indicates that the cookie should only be transmitted over a secure |
||||
* HTTPS connection from the client |
||||
* @param bool $httponly When TRUE the cookie will be made accessible only through the HTTP protocol |
||||
* @return void |
||||
*/ |
||||
public function deleteCookie( $name, $path = null, $domain = null, $secure = null, $httponly = null ) { |
||||
$path = is_null($path) ? $this->config('cookies.path') : $path; |
||||
$domain = is_null($domain) ? $this->config('cookies.domain') : $domain; |
||||
$secure = is_null($secure) ? $this->config('cookies.secure') : $secure; |
||||
$httponly = is_null($httponly) ? $this->config('cookies.httponly') : $httponly; |
||||
$this->response->getCookieJar()->deleteCookie( $name, $path, $domain, $secure, $httponly ); |
||||
} |
||||
|
||||
/***** HELPERS *****/ |
||||
|
||||
/** |
||||
* Get the Slim application's absolute directory path |
||||
* |
||||
* This method returns the absolute path to the Slim application's |
||||
* directory. If the Slim application is installed in a public-accessible |
||||
* sub-directory, the sub-directory path will be included. This method |
||||
* will always return an absolute path WITH a trailing slash. |
||||
* |
||||
* @return string |
||||
*/ |
||||
public function root() { |
||||
return rtrim($_SERVER['DOCUMENT_ROOT'], '/') . rtrim($this->request->getRootUri(), '/') . '/'; |
||||
} |
||||
|
||||
/** |
||||
* Stop |
||||
* |
||||
* Send the current Response as is and stop executing the Slim |
||||
* application. The thrown exception will be caught by the Slim |
||||
* custom exception handler which exits this script. |
||||
* |
||||
* @throws Slim_Exception_Stop |
||||
* @return void |
||||
*/ |
||||
public function stop() { |
||||
session_write_close(); |
||||
$this->response->send(); |
||||
throw new Slim_Exception_Stop(); |
||||
} |
||||
|
||||
/** |
||||
* Halt |
||||
* |
||||
* Halt the application and immediately send an HTTP response with a |
||||
* specific status code and body. This may be used to send any type of |
||||
* response: info, success, redirect, client error, or server error. |
||||
* If you need to render a template AND customize the response status, |
||||
* you should use Slim::render() instead. |
||||
* |
||||
* @param int $status The HTTP response status |
||||
* @param string $message The HTTP response body |
||||
* @return void |
||||
*/ |
||||
public function halt( $status, $message = '') { |
||||
if ( ob_get_level() !== 0 ) { |
||||
ob_clean(); |
||||
} |
||||
$this->applyHook('error.halt', $this); |
||||
$this->response->status($status); |
||||
if (ob_get_contents() == '') $this->response->body($message); |
||||
$this->stop(); |
||||
} |
||||
|
||||
/** |
||||
* Set the HTTP response Content-Type |
||||
* @param string $type The Content-Type for the Response (ie. text/html) |
||||
* @return void |
||||
*/ |
||||
public function contentType( $type ) { |
||||
$this->response->header('Content-Type', $type); |
||||
} |
||||
|
||||
/** |
||||
* Set the HTTP response status code |
||||
* @param int $status The HTTP response status code |
||||
* @return void |
||||
*/ |
||||
public function status( $code ) { |
||||
$this->response->status($code); |
||||
} |
||||
|
||||
/** |
||||
* Redirect |
||||
* |
||||
* This method immediately redirects to a new URL. By default, |
||||
* this issues a 302 Found response; this is considered the default |
||||
* generic redirect response. You may also specify another valid |
||||
* 3xx status code if you want. This method will automatically set the |
||||
* HTTP Location header for you using the URL parameter and place the |
||||
* destination URL into the response body. |
||||
* |
||||
* @param string $url The destination URL |
||||
* @param int $status The HTTP redirect status code (Optional) |
||||
* @throws InvalidArgumentException If status parameter is not a valid 3xx status code |
||||
* @return void |
||||
*/ |
||||
public function redirect( $url, $status = 302 ) { |
||||
if ( $status >= 300 && $status <= 307 ) { |
||||
$this->response->header('Location', (string)$url); |
||||
$this->halt($status, (string)$url); |
||||
} else { |
||||
throw new InvalidArgumentException('Slim::redirect only accepts HTTP 300-307 status codes.'); |
||||
} |
||||
} |
||||
|
||||
/***** HOOKS *****/ |
||||
|
||||
/** |
||||
* Assign hook |
||||
* @param string $name The hook name |
||||
* @param mixed $callable A callable object |
||||
* @param int $priority The hook priority; 0 = high, 10 = low |
||||
* @return void |
||||
*/ |
||||
public function hook( $name, $callable, $priority = 10 ) { |
||||
if ( !isset($this->hooks[$name]) ) { |
||||
$this->hooks[$name] = array(array()); |
||||
} |
||||
if ( is_callable($callable) ) { |
||||
$this->hooks[$name][(int)$priority][] = $callable; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Invoke hook |
||||
* @param string $name The hook name |
||||
* @param mixed $hookArgs (Optional) Argument for hooked functions |
||||
* @return mixed |
||||
*/ |
||||
public function applyHook( $name, $hookArg = null ) { |
||||
if ( !isset($this->hooks[$name]) ) { |
||||
$this->hooks[$name] = array(array()); |
||||
} |
||||
if( !empty($this->hooks[$name]) ) { |
||||
// Sort by priority, low to high, if there's more than one priority |
||||
if ( count($this->hooks[$name]) > 1 ) { |
||||
ksort($this->hooks[$name]); |
||||
} |
||||
foreach( $this->hooks[$name] as $priority ) { |
||||
if( !empty($priority) ) { |
||||
foreach($priority as $callable) { |
||||
$hookArg = call_user_func($callable, $hookArg); |
||||
} |
||||
} |
||||
} |
||||
return $hookArg; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Get hook listeners |
||||
* |
||||
* Return an array of registered hooks. If `$name` is a valid |
||||
* hook name, only the listeners attached to that hook are returned. |
||||
* Else, all listeners are returned as an associative array whose |
||||
* keys are hook names and whose values are arrays of listeners. |
||||
* |
||||
* @param string $name A hook name (Optional) |
||||
* @return array|null |
||||
*/ |
||||
public function getHooks( $name = null ) { |
||||
if ( !is_null($name) ) { |
||||
return isset($this->hooks[(string)$name]) ? $this->hooks[(string)$name] : null; |
||||
} else { |
||||
return $this->hooks; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Clear hook listeners |
||||
* |
||||
* Clear all listeners for all hooks. If `$name` is |
||||
* a valid hook name, only the listeners attached |
||||
* to that hook will be cleared. |
||||
* |
||||
* @param string $name A hook name (Optional) |
||||
* @return void |
||||
*/ |
||||
public function clearHooks( $name = null ) { |
||||
if ( !is_null($name) && isset($this->hooks[(string)$name]) ) { |
||||
$this->hooks[(string)$name] = array(array()); |
||||
} else { |
||||
foreach( $this->hooks as $key => $value ) { |
||||
$this->hooks[$key] = array(array()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/***** EXCEPTION AND ERROR HANDLING *****/ |
||||
|
||||
/** |
||||
* Handle errors |
||||
* |
||||
* This is the global Error handler that will catch reportable Errors |
||||
* and convert them into ErrorExceptions that are caught and handled |
||||
* by each Slim application. |
||||
* |
||||
* @param int $errno The numeric type of the Error |
||||
* @param string $errstr The error message |
||||
* @param string $errfile The absolute path to the affected file |
||||
* @param int $errline The line number of the error in the affected file |
||||
* @return true |
||||
* @throws ErrorException |
||||
*/ |
||||
public static function handleErrors( $errno, $errstr = '', $errfile = '', $errline = '' ) { |
||||
if ( error_reporting() & $errno ) { |
||||
if (isset($this)) $this->getLog()->error('Unhandled Error: '.$errstr); |
||||
throw new ErrorException($errstr, $errno, 0, $errfile, $errline); |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
public static function handleExceptions( $exception ) { |
||||
$this->getLog()->error('Unhandled Exception: '.$exception->getMessage()); |
||||
throw $exception; |
||||
} |
||||
|
||||
public function FatalErrorCatcher() |
||||
{ |
||||
$error = error_get_last(); |
||||
if (isset($error)) { |
||||
if($error['type'] == E_ERROR |
||||
|| $error['type'] == E_PARSE |
||||
|| $error['type'] == E_COMPILE_ERROR |
||||
|| $error['type'] == E_CORE_ERROR) |
||||
{ |
||||
ob_end_clean(); // сбросить буфер, завершить работу буфера |
||||
|
||||
if (isset($this)) { |
||||
$this->getLog()->error('Fatal Error Catched: '.$error['message']); |
||||
if ( $this->config('debug') === true ) { |
||||
$this->halt(500, self::generateErrorMarkup($error['message'], $error['file'], $error['line'], '')); |
||||
} else { |
||||
$e = new Exception( $error['message'] ) ; |
||||
$this->error($e); |
||||
} |
||||
} else { |
||||
throw new Exception('Fatal Error Catched but not logged: ' . $error['message']); |
||||
} |
||||
} else { |
||||
} |
||||
} else { |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Generate markup for error message |
||||
* |
||||
* This method accepts details about an error or exception and |
||||
* generates HTML markup for the 500 response body that will |
||||
* be sent to the client. |
||||
* |
||||
* @param string $message The error message |
||||
* @param string $file The absolute file path to the affected file |
||||
* @param int $line The line number in the affected file |
||||
* @param string $trace A stack trace of the error |
||||
* @return string |
||||
*/ |
||||
protected static function generateErrorMarkup( $message, $file = '', $line = '', $trace = '' ) { |
||||
$body = '<p>The application could not run because of the following error:</p>'; |
||||
$body .= "<h2>Details:</h2><strong>Message:</strong> $message<br/>"; |
||||
if ( $file !== '' ) $body .= "<strong>File:</strong> $file<br/>"; |
||||
if ( $line !== '' ) $body .= "<strong>Line:</strong> $line<br/>"; |
||||
if ( $trace !== '' ) $body .= '<h2>Stack Trace:</h2>' . nl2br($trace); |
||||
return self::generateTemplateMarkup('Harmonious Application Error', $body); |
||||
} |
||||
|
||||
/** |
||||
* Generate default template markup |
||||
* |
||||
* This method accepts a title and body content to generate |
||||
* an HTML page. This is primarily used to generate the layout markup |
||||
* for Error handlers and Not Found handlers. |
||||
* |
||||
* @param string $title The title of the HTML template |
||||
* @param string $body The body content of the HTML template |
||||
* @return string |
||||
*/ |
||||
protected static function generateTemplateMarkup( $title, $body ) { |
||||
$html = "<html><head><title>$title</title><style>body{margin:0;padding:30px;font:12px/1.5 Helvetica,Arial,Verdana,sans-serif;}h1{margin:0;font-size:48px;font-weight:normal;line-height:48px;}strong{display:inline-block;width:65px;}</style></head><body>"; |
||||
$html .= "<h1>$title</h1>"; |
||||
$html .= $body; |
||||
$html .= '</body></html>'; |
||||
return $html; |
||||
} |
||||
|
||||
/** |
||||
* Default Not Found handler |
||||
* @return void |
||||
*/ |
||||
protected function defaultNotFound() { |
||||
echo self::generateTemplateMarkup('404 Page Not Found', '<p>The page you are looking for could not be found. Check the address bar to ensure your URL is spelled correctly. If all else fails, you can visit our home page at the link below.</p><a href="' . $this->request->getRootUri() . '">Visit the Home Page</a>'); |
||||
} |
||||
|
||||
/** |
||||
* Default Error handler |
||||
* @return void |
||||
*/ |
||||
protected function defaultError() { |
||||
echo self::generateTemplateMarkup('Error', '<p>A website error has occured. The website administrator has been notified of the issue. Sorry for the temporary inconvenience.</p>'); |
||||
} |
||||
|
||||
} |
||||
?> |
||||
@ -0,0 +1 @@ |
||||
deny from all |
||||
@ -0,0 +1,222 @@ |
||||
<?php |
||||
/** |
||||
* Slim - a micro PHP 5 framework |
||||
* |
||||
* @author Josh Lockhart <info@joshlockhart.com> |
||||
* @copyright 2011 Josh Lockhart |
||||
* @link http://www.slimframework.com |
||||
* @license http://www.slimframework.com/license |
||||
* @version 1.5.0 |
||||
* |
||||
* MIT LICENSE |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining |
||||
* a copy of this software and associated documentation files (the |
||||
* "Software"), to deal in the Software without restriction, including |
||||
* without limitation the rights to use, copy, modify, merge, publish, |
||||
* distribute, sublicense, and/or sell copies of the Software, and to |
||||
* permit persons to whom the Software is furnished to do so, subject to |
||||
* the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be |
||||
* included in all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
/** |
||||
* Cookie |
||||
* |
||||
* Object-oriented representation of a Cookie to be sent in an HTTP response |
||||
* |
||||
* @package Slim |
||||
* @author Josh Lockhart <info@joshlockhart.com> |
||||
* @since Version 1.0 |
||||
*/ |
||||
class Slim_Http_Cookie { |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
protected $name; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
protected $value; |
||||
|
||||
/** |
||||
* @var int UNIX timestamp |
||||
*/ |
||||
protected $expires; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
protected $path; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
protected $domain; |
||||
|
||||
/** |
||||
* @var bool |
||||
*/ |
||||
protected $secure; |
||||
|
||||
/** |
||||
* @var bool |
||||
*/ |
||||
protected $httponly; |
||||
|
||||
/** |
||||
* Constructor |
||||
* @param string $name The cookie name |
||||
* @param string $value The cookie value |
||||
* @param mixed $time The duration of the cookie; |
||||
* If integer, should be a UNIX timestamp; |
||||
* If string, converted to UNIX timestamp with `strtotime`; |
||||
* @param string $path The path on the server in which the cookie will be available on |
||||
* @param string $domain The domain that the cookie is available to |
||||
* @param bool $secure Indicates that the cookie should only be transmitted over a secure |
||||
* HTTPS connection from the client |
||||
* @param bool $httponly When TRUE the cookie will be made accessible only through the HTTP protocol |
||||
* @return void |
||||
*/ |
||||
public function __construct( $name, $value = null, $expires = 0, $path = null, $domain = null, $secure = false, $httponly = false ) { |
||||
$this->setName($name); |
||||
$this->setValue($value); |
||||
$this->setExpires($expires); |
||||
$this->setPath($path); |
||||
$this->setDomain($domain); |
||||
$this->setSecure($secure); |
||||
$this->setHttpOnly($httponly); |
||||
} |
||||
|
||||
/** |
||||
* Get cookie name |
||||
* @return string |
||||
*/ |
||||
public function getName() { |
||||
return $this->name; |
||||
} |
||||
|
||||
/** |
||||
* Set cookie name |
||||
* @param string $name |
||||
* @return void |
||||
*/ |
||||
public function setName( $name ) { |
||||
$this->name = (string)$name; |
||||
} |
||||
|
||||
/** |
||||
* Get cookie value |
||||
* @return string |
||||
*/ |
||||
public function getValue() { |
||||
return $this->value; |
||||
} |
||||
|
||||
/** |
||||
* Set cookie value |
||||
* @param string $value |
||||
* @return void |
||||
*/ |
||||
public function setValue( $value ) { |
||||
$this->value = (string)$value; |
||||
} |
||||
|
||||
/** |
||||
* Get cookie expiration time |
||||
* @return int UNIX timestamp |
||||
*/ |
||||
public function getExpires() { |
||||
return $this->expires; |
||||
} |
||||
|
||||
/** |
||||
* Set cookie expiration time |
||||
* @param string|int Cookie expiration time |
||||
* @return void |
||||
*/ |
||||
public function setExpires( $time ) { |
||||
$this->expires = is_string($time) ? strtotime($time) : (int)$time; |
||||
} |
||||
|
||||
/** |
||||
* Get cookie path |
||||
* @return string |
||||
*/ |
||||
public function getPath() { |
||||
return $this->path; |
||||
} |
||||
|
||||
/** |
||||
* Set cookie path |
||||
* @param string $path |
||||
* @return void |
||||
*/ |
||||
public function setPath( $path ) { |
||||
$this->path = (string)$path; |
||||
} |
||||
|
||||
/** |
||||
* Get cookie domain |
||||
* @return string |
||||
*/ |
||||
public function getDomain() { |
||||
return $this->domain; |
||||
} |
||||
|
||||
/** |
||||
* Set cookie domain |
||||
* @param string $domain |
||||
* @return void |
||||
*/ |
||||
public function setDomain( $domain ) { |
||||
$this->domain = (string)$domain; |
||||
} |
||||
|
||||
/** |
||||
* Is cookie sent only if SSL/HTTPS is used? |
||||
* @return bool |
||||
*/ |
||||
public function getSecure() { |
||||
return $this->secure; |
||||
} |
||||
|
||||
/** |
||||
* Set whether cookie is sent only if SSL/HTTPS is used |
||||
* @param bool $secure |
||||
* @return void |
||||
*/ |
||||
public function setSecure( $secure ) { |
||||
$this->secure = (bool)$secure; |
||||
} |
||||
|
||||
/** |
||||
* Is cookie sent with HTTP protocol only? |
||||
* @return bool |
||||
*/ |
||||
public function getHttpOnly() { |
||||
return $this->httponly; |
||||
} |
||||
|
||||
/** |
||||
* Set whether cookie is sent with HTTP protocol only |
||||
* @param bool $httponly |
||||
* @return void |
||||
*/ |
||||
public function setHttpOnly( $httponly ) { |
||||
$this->httponly = (bool)$httponly; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,401 @@ |
||||
<?php |
||||
/** |
||||
* Slim - a micro PHP 5 framework |
||||
* |
||||
* @author Josh Lockhart <info@joshlockhart.com> |
||||
* @copyright 2011 Josh Lockhart |
||||
* @link http://www.slimframework.com |
||||
* @license http://www.slimframework.com/license |
||||
* @version 1.5.0 |
||||
* |
||||
* MIT LICENSE |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining |
||||
* a copy of this software and associated documentation files (the |
||||
* "Software"), to deal in the Software without restriction, including |
||||
* without limitation the rights to use, copy, modify, merge, publish, |
||||
* distribute, sublicense, and/or sell copies of the Software, and to |
||||
* permit persons to whom the Software is furnished to do so, subject to |
||||
* the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be |
||||
* included in all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
/** |
||||
* Cooke Jar |
||||
* |
||||
* Used to manage signed, encrypted Cookies. Provides: |
||||
* |
||||
* - Cookie integrity and authenticity with HMAC |
||||
* - Confidentiality with symmetric encryption |
||||
* - Protection from replay attack if using SSL or TLS |
||||
* - Protection from interception if using SSL or TLS |
||||
* |
||||
* This code was originally called "BigOrNot_CookieManager" and written by |
||||
* Matthieu Huguet released under "CopyLeft" license. I have cleaned up the |
||||
* code formatting to conform with Slim Framework contributor guidelines and |
||||
* added additional code where necessary to play nice with Slim Cookie objects. |
||||
* |
||||
* Requirements: |
||||
* |
||||
* - libmcrypt > 2.4.x |
||||
* |
||||
* @author Matthies Huguet <http://bigornot.blogspot.com/2008/06/security-cookies-and-rest.html> |
||||
*/ |
||||
class Slim_Http_CookieJar { |
||||
|
||||
/** |
||||
* @var string Server secret key |
||||
*/ |
||||
protected $_secret = ''; |
||||
|
||||
/** |
||||
* @var int Cryptographic algorithm used to encrypt cookies data |
||||
*/ |
||||
protected $_algorithm = MCRYPT_RIJNDAEL_256; |
||||
|
||||
/** |
||||
* @var int Cryptographic mode (CBC, CFB ...) |
||||
*/ |
||||
protected $_mode = MCRYPT_MODE_CBC; |
||||
|
||||
/** |
||||
* @var resource mcrypt module resource |
||||
*/ |
||||
protected $_cryptModule = null; |
||||
|
||||
/** |
||||
* @var bool Enable high confidentiality for cookie value (symmetric encryption) |
||||
*/ |
||||
protected $_highConfidentiality = true; |
||||
|
||||
/** |
||||
* @var bool Enable SSL support |
||||
*/ |
||||
protected $_ssl = false; |
||||
|
||||
/** |
||||
* @var array[Cookie] Cookie objects |
||||
*/ |
||||
protected $_cookies = array(); |
||||
|
||||
/** |
||||
* Constructor |
||||
* |
||||
* Initialize cookie manager and mcrypt module. |
||||
* |
||||
* @param string $secret Server's secret key |
||||
* @param array $config |
||||
* @throws Exception If secret key is empty |
||||
* @throws Exception If unable to open mcypt module |
||||
*/ |
||||
public function __construct( $secret, $config = null ) { |
||||
if ( empty($secret) ) { |
||||
throw new Exception('You must provide a secret key'); |
||||
} |
||||
$this->_secret = $secret; |
||||
if ( $config !== null && !is_array($config) ) { |
||||
throw new Exception('Config must be an array'); |
||||
} |
||||
if ( is_array($config) ) { |
||||
if ( isset($config['high_confidentiality']) ) { |
||||
$this->_highConfidentiality = $config['high_confidentiality']; |
||||
} |
||||
if ( isset($config['mcrypt_algorithm']) ) { |
||||
$this->_algorithm = $config['mcrypt_algorithm']; |
||||
} |
||||
if ( isset($config['mcrypt_mode']) ) { |
||||
$this->_mode = $config['mcrypt_mode']; |
||||
} |
||||
if ( isset($config['enable_ssl']) ) { |
||||
$this->_ssl = $config['enable_ssl']; |
||||
} |
||||
} |
||||
if ( extension_loaded('mcrypt') ) { |
||||
$this->_cryptModule = mcrypt_module_open($this->_algorithm, '', $this->_mode, ''); |
||||
if ( $this->_cryptModule === false ) { |
||||
throw new Exception('Error while loading mcrypt module'); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Get the high confidentiality mode |
||||
* |
||||
* @return bool TRUE if cookie data encryption is enabled, or FALSE if it isn't |
||||
*/ |
||||
public function getHighConfidentiality() { |
||||
return $this->_highConfidentiality; |
||||
} |
||||
|
||||
/** |
||||
* Enable or disable cookie data encryption |
||||
* |
||||
* @param bool $enable TRUE to enable, FALSE to disable |
||||
* @return CookieJar |
||||
*/ |
||||
public function setHighConfidentiality( $enable ) { |
||||
$this->_highConfidentiality = (bool)$enable; |
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* Get the SSL status (enabled or disabled?) |
||||
* |
||||
* @return bool TRUE if SSL support is enabled, or FALSE if it isn't |
||||
*/ |
||||
public function getSSL() { |
||||
return $this->_ssl; |
||||
} |
||||
|
||||
/** |
||||
* Enable SSL support (not enabled by default) |
||||
* |
||||
* Pro: Protect against replay attack |
||||
* Con: Cookie's lifetime is limited to SSL session's lifetime |
||||
* |
||||
* @param bool $enable TRUE to enable, FALSE to disable |
||||
* @return CookieJar |
||||
*/ |
||||
public function setSSL( $enable ) { |
||||
$this->_ssl = (bool)$enable; |
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* Get Cookies for Response |
||||
* |
||||
* @author Josh Lockhart <info@joshlockhart.com> |
||||
* @return array[Cookie] |
||||
*/ |
||||
public function getResponseCookies() { |
||||
return $this->_cookies; |
||||
} |
||||
|
||||
/** |
||||
* Get Cookie with name for Response |
||||
* |
||||
* @author Josh Lockhart <info@joshlockhart.com> |
||||
* @param string $cookiename The name of the Cookie |
||||
* @return Cookie|null Cookie, or NULL if Cookie with name not found |
||||
*/ |
||||
public function getResponseCookie( $cookiename ) { |
||||
return isset($this->_cookies[$cookiename]) ? $this->_cookies[$cookiename] : null; |
||||
} |
||||
|
||||
/** |
||||
* Set a secure cookie |
||||
* |
||||
* @param string $name Cookie name |
||||
* @param string $value Cookie value |
||||
* @param string $username User identifier |
||||
* @param integer $expire Expiration time |
||||
* @param string $path Cookie path |
||||
* @param string $domain Cookie domain |
||||
* @param bool $secure When TRUE, send the cookie only on a secure connection |
||||
* @param bool $httponly When TRUE the cookie will be made accessible only through the HTTP protocol |
||||
*/ |
||||
public function setCookie( $cookiename, $value, $username, $expire = 0, $path = '/', $domain = '', $secure = false, $httponly = null ) { |
||||
$secureValue = extension_loaded('mcrypt') ? $this->_secureCookieValue($value, $username, $expire) : $value; |
||||
$this->setClassicCookie($cookiename, $secureValue, $expire, $path, $domain, $secure, $httponly); |
||||
} |
||||
|
||||
/** |
||||
* Delete a cookie |
||||
* |
||||
* @param string $name Cookie name |
||||
* @param string $path Cookie path |
||||
* @param string $domain Cookie domain |
||||
* @param bool $secure When TRUE, send the cookie only on a secure connection |
||||
* @param bool $httponly When TRUE the cookie will be made accessible only through the HTTP protocol |
||||
*/ |
||||
public function deleteCookie( $name, $path = '/', $domain = '', $secure = false, $httponly = null ) { |
||||
$expire = 315554400; /* 1980-01-01 */ |
||||
$this->_cookies[$name] = new Slim_Http_Cookie($name, '', $expire, $path, $domain, $secure, $httponly); |
||||
//setcookie($name, '', $expire, $path, $domain, $secure, $httponly); |
||||
} |
||||
|
||||
/** |
||||
* Get a secure cookie value |
||||
* |
||||
* Verify the integrity of cookie data and decrypt it. If the cookie |
||||
* is invalid, it can be automatically destroyed (default behaviour) |
||||
* |
||||
* @param string $cookiename Cookie name |
||||
* @param bool $delete Destroy the cookie if invalid? |
||||
* @return string|false The Cookie value, or FALSE if Cookie invalid |
||||
*/ |
||||
public function getCookieValue( $cookiename, $deleteIfInvalid = true ) { |
||||
if ( $this->cookieExists($cookiename) ) { |
||||
if ( extension_loaded('mcrypt') ) { |
||||
$cookieValues = explode('|', $_COOKIE[$cookiename]); |
||||
if ( (count($cookieValues) === 4) && ($cookieValues[1] == 0 || $cookieValues[1] >= time()) ) { |
||||
$key = hash_hmac('sha1', $cookieValues[0] . $cookieValues[1], $this->_secret); |
||||
$cookieData = base64_decode($cookieValues[2]); |
||||
if ( $cookieData !== '' && $this->getHighConfidentiality() ) { |
||||
$data = $this->_decrypt($cookieData, $key, md5($cookieValues[1])); |
||||
} else { |
||||
$data = $cookieData; |
||||
} |
||||
if ( $this->_ssl && isset($_SERVER['SSL_SESSION_ID']) ) { |
||||
$verifKey = hash_hmac('sha1', $cookieValues[0] . $cookieValues[1] . $data . $_SERVER['SSL_SESSION_ID'], $key); |
||||
} else { |
||||
$verifKey = hash_hmac('sha1', $cookieValues[0] . $cookieValues[1] . $data, $key); |
||||
} |
||||
if ( $verifKey == $cookieValues[3] ) { |
||||
return $data; |
||||
} |
||||
} |
||||
} else { |
||||
return $_COOKIE[$cookiename]; |
||||
} |
||||
} |
||||
if ( $deleteIfInvalid ) { |
||||
$this->deleteCookie($cookiename); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Send a classic (unsecure) cookie |
||||
* |
||||
* @param string $name Cookie name |
||||
* @param string $value Cookie value |
||||
* @param integer $expire Expiration time |
||||
* @param string $path Cookie path |
||||
* @param string $domain Cookie domain |
||||
* @param bool $secure When TRUE, send the cookie only on a secure connection |
||||
* @param bool $httponly When TRUE the cookie will be made accessible only through the HTTP protocol |
||||
*/ |
||||
public function setClassicCookie( $cookiename, $value, $expire = 0, $path = '/', $domain = '', $secure = false, $httponly = null ) { |
||||
/* httponly option is only available for PHP version >= 5.2 */ |
||||
if ( $httponly === null ) { |
||||
$this->_cookies[$cookiename] = new Slim_Http_Cookie($cookiename, $value, $expire, $path, $domain, $secure); |
||||
//setcookie($cookiename, $value, $expire, $path, $domain, $secure); |
||||
} else { |
||||
$this->_cookies[$cookiename] = new Slim_Http_Cookie($cookiename, $value, $expire, $path, $domain, $secure, $httponly); |
||||
//setcookie($cookiename, $value, $expire, $path, $domain, $secure, $httponly); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Verify if a cookie exists |
||||
* |
||||
* @param string $cookiename |
||||
* @return bool TRUE if cookie exist, or FALSE if not |
||||
*/ |
||||
public function cookieExists($cookiename) { |
||||
return isset($_COOKIE[$cookiename]); |
||||
} |
||||
|
||||
/** |
||||
* Secure a cookie value |
||||
* |
||||
* The initial value is transformed with this protocol: |
||||
* |
||||
* secureValue = username|expire|base64((value)k,expire)|HMAC(user|expire|value,k) |
||||
* where k = HMAC(user|expire, sk) |
||||
* and sk is server's secret key |
||||
* (value)k,md5(expire) is the result an cryptographic function (ex: AES256) on "value" with key k and initialisation vector = md5(expire) |
||||
* |
||||
* @param string $value Unsecure value |
||||
* @param string $username User identifier |
||||
* @param integer $expire Expiration time |
||||
* @return string Secured value |
||||
*/ |
||||
protected function _secureCookieValue( $value, $username, $expire ) { |
||||
if ( is_string($expire) ) { |
||||
$expire = strtotime($expire); |
||||
} |
||||
$key = hash_hmac('sha1', $username . $expire, $this->_secret); |
||||
if ( $value !== '' && $this->getHighConfidentiality() ) { |
||||
$encryptedValue = base64_encode($this->_encrypt($value, $key, md5($expire))); |
||||
} else { |
||||
$encryptedValue = base64_encode($value); |
||||
} |
||||
if ( $this->_ssl && isset($_SERVER['SSL_SESSION_ID']) ) { |
||||
$verifKey = hash_hmac('sha1', $username . $expire . $value . $_SERVER['SSL_SESSION_ID'], $key); |
||||
} else { |
||||
$verifKey = hash_hmac('sha1', $username . $expire . $value, $key); |
||||
} |
||||
$result = array($username, $expire, $encryptedValue, $verifKey); |
||||
return implode('|', $result); |
||||
} |
||||
|
||||
/** |
||||
* Encrypt a given data with a given key and a given initialisation vector |
||||
* |
||||
* @param string $data Data to crypt |
||||
* @param string $key Secret key |
||||
* @param string $iv Initialisation vector |
||||
* @return string Encrypted data |
||||
*/ |
||||
protected function _encrypt( $data, $key, $iv ) { |
||||
$iv = $this->_validateIv($iv); |
||||
$key = $this->_validateKey($key); |
||||
mcrypt_generic_init($this->_cryptModule, $key, $iv); |
||||
$res = @mcrypt_generic($this->_cryptModule, $data); |
||||
mcrypt_generic_deinit($this->_cryptModule); |
||||
return $res; |
||||
} |
||||
|
||||
/** |
||||
* Decrypt a given data with a given key and a given initialisation vector |
||||
* |
||||
* @param string $data Data to crypt |
||||
* @param string $key Secret key |
||||
* @param string $iv Initialisation vector |
||||
* @return string Encrypted data |
||||
*/ |
||||
protected function _decrypt( $data, $key, $iv ) { |
||||
$iv = $this->_validateIv($iv); |
||||
$key = $this->_validateKey($key); |
||||
mcrypt_generic_init($this->_cryptModule, $key, $iv); |
||||
$decryptedData = mdecrypt_generic($this->_cryptModule, $data); |
||||
$res = str_replace("\x0", '', $decryptedData); |
||||
mcrypt_generic_deinit($this->_cryptModule); |
||||
return $res; |
||||
} |
||||
|
||||
/** |
||||
* Validate Initialization vector |
||||
* |
||||
* If given IV is too long for the selected mcrypt algorithm, it will be truncated |
||||
* |
||||
* @param string $iv Initialization vector |
||||
* @return string |
||||
*/ |
||||
protected function _validateIv($iv) { |
||||
$ivSize = mcrypt_enc_get_iv_size($this->_cryptModule); |
||||
if ( strlen($iv) > $ivSize ) { |
||||
$iv = substr($iv, 0, $ivSize); |
||||
} |
||||
return $iv; |
||||
} |
||||
|
||||
/** |
||||
* Validate key |
||||
* |
||||
* If given key is too long for the selected mcrypt algorithm, it will be truncated |
||||
* |
||||
* @param string $key key |
||||
* @param string |
||||
*/ |
||||
protected function _validateKey($key) { |
||||
$keySize = mcrypt_enc_get_key_size($this->_cryptModule); |
||||
if ( strlen($key) > $keySize ) { |
||||
$key = substr($key, 0, $keySize); |
||||
} |
||||
return $key; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,131 @@ |
||||
<?php |
||||
/** |
||||
* Slim - a micro PHP 5 framework |
||||
* |
||||
* @author Josh Lockhart <info@joshlockhart.com> |
||||
* @copyright 2011 Josh Lockhart |
||||
* @link http://www.slimframework.com |
||||
* @license http://www.slimframework.com/license |
||||
* @version 1.5.0 |
||||
* |
||||
* MIT LICENSE |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining |
||||
* a copy of this software and associated documentation files (the |
||||
* "Software"), to deal in the Software without restriction, including |
||||
* without limitation the rights to use, copy, modify, merge, publish, |
||||
* distribute, sublicense, and/or sell copies of the Software, and to |
||||
* permit persons to whom the Software is furnished to do so, subject to |
||||
* the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be |
||||
* included in all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
/** |
||||
* Uri |
||||
* |
||||
* Parses base uri and application uri from Request. |
||||
* |
||||
* @package Slim |
||||
* @author Josh Lockhart <info@joshlockhart.com> |
||||
* @since Version 1.0 |
||||
*/ |
||||
class Slim_Http_Uri { |
||||
|
||||
/** |
||||
* @var string "https" or "http" |
||||
*/ |
||||
protected static $scheme; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
protected static $baseUri; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
protected static $uri; |
||||
|
||||
/** |
||||
* @var string The URI query string, excluding leading "?" |
||||
*/ |
||||
protected static $queryString; |
||||
|
||||
/** |
||||
* Get Base URI without trailing slash |
||||
* @param bool $reload Force reparse the base URI? |
||||
* @return string |
||||
*/ |
||||
public static function getBaseUri( $reload = false ) { |
||||
if ( $reload || is_null(self::$baseUri) ) { |
||||
$requestUri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : $_SERVER['PHP_SELF']; //Full Request URI |
||||
$scriptName = $_SERVER['SCRIPT_NAME']; //Script path from docroot |
||||
$baseUri = strpos($requestUri, $scriptName) === 0 ? $scriptName : str_replace('\\', '/', dirname($scriptName)); |
||||
self::$baseUri = rtrim($baseUri, '/'); |
||||
} |
||||
return self::$baseUri; |
||||
} |
||||
|
||||
/** |
||||
* Get URI with leading slash |
||||
* @param bool $reload Force reparse the URI? |
||||
* @return string |
||||
* @throws RuntimeException If unable if unable to determine URI |
||||
*/ |
||||
public static function getUri( $reload = false ) { |
||||
if ( $reload || is_null(self::$uri) ) { |
||||
$uri = ''; |
||||
if ( !empty($_SERVER['PATH_INFO']) ) { |
||||
$uri = $_SERVER['PATH_INFO']; |
||||
} else { |
||||
if ( isset($_SERVER['REQUEST_URI']) ) { |
||||
$uri = parse_url(self::getScheme() . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], PHP_URL_PATH); |
||||
} else if ( isset($_SERVER['PHP_SELF']) ) { |
||||
$uri = $_SERVER['PHP_SELF']; |
||||
} else { |
||||
throw new RuntimeException('Unable to detect request URI'); |
||||
} |
||||
} |
||||
if ( self::getBaseUri() !== '' && strpos($uri, self::getBaseUri()) === 0 ) { |
||||
$uri = substr($uri, strlen(self::getBaseUri())); |
||||
} |
||||
self::$uri = '/' . ltrim($uri, '/'); |
||||
} |
||||
return self::$uri; |
||||
} |
||||
|
||||
/** |
||||
* Get URI Scheme |
||||
* @param bool $reload For reparse the URL scheme? |
||||
* @return string "https" or "http" |
||||
*/ |
||||
public static function getScheme( $reload = false ) { |
||||
if ( $reload || is_null(self::$scheme) ) { |
||||
self::$scheme = ( empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] === 'off' ) ? 'http' : 'https'; |
||||
} |
||||
return self::$scheme; |
||||
} |
||||
|
||||
/** |
||||
* Get URI Query String |
||||
* @param bool $reload For reparse the URL query string? |
||||
* @return string |
||||
*/ |
||||
public static function getQueryString( $reload = false ) { |
||||
if ( $reload || is_null(self::$queryString) ) { |
||||
self::$queryString = $_SERVER['QUERY_STRING']; |
||||
} |
||||
return self::$queryString; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,155 @@ |
||||
<?php |
||||
/** |
||||
* Slim - a micro PHP 5 framework |
||||
* |
||||
* @author Josh Lockhart <info@joshlockhart.com> |
||||
* @copyright 2011 Josh Lockhart |
||||
* @link http://www.slimframework.com |
||||
* @license http://www.slimframework.com/license |
||||
* @version 1.5.0 |
||||
* |
||||
* MIT LICENSE |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining |
||||
* a copy of this software and associated documentation files (the |
||||
* "Software"), to deal in the Software without restriction, including |
||||
* without limitation the rights to use, copy, modify, merge, publish, |
||||
* distribute, sublicense, and/or sell copies of the Software, and to |
||||
* permit persons to whom the Software is furnished to do so, subject to |
||||
* the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be |
||||
* included in all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
/** |
||||
* Log Adapter |
||||
* |
||||
* This is an adapter for your own custom Logger. This adapter assumes |
||||
* your custom Logger provides the following public instance methods: |
||||
* |
||||
* debug( mixed $object ) |
||||
* info( mixed $object ) |
||||
* warn( mixed $object ) |
||||
* error( mixed $object ) |
||||
* fatal( mixed $object ) |
||||
* |
||||
* This class assumes nothing else about your custom Logger, so you are free |
||||
* to use Apache's Log4PHP logger or any other log class that, at the |
||||
* very least, implements the five public instance methods shown above. |
||||
* |
||||
* @package Slim |
||||
* @author Josh Lockhart <info@joshlockhart.com> |
||||
* @since Version 1.0 |
||||
*/ |
||||
class Slim_Log { |
||||
|
||||
/** |
||||
* @var mixed An object that implements expected Logger interface |
||||
*/ |
||||
protected $logger; |
||||
|
||||
/** |
||||
* @var bool Enable logging? |
||||
*/ |
||||
protected $enabled; |
||||
|
||||
/** |
||||
* Constructor |
||||
*/ |
||||
public function __construct() { |
||||
$this->enabled = true; |
||||
} |
||||
|
||||
/** |
||||
* Enable or disable logging |
||||
* @param bool $enabled |
||||
* @return void |
||||
*/ |
||||
public function setEnabled( $enabled ) { |
||||
if ( $enabled ) { |
||||
$this->enabled = true; |
||||
} else { |
||||
$this->enabled = false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Is logging enabled? |
||||
* @return bool |
||||
*/ |
||||
public function isEnabled() { |
||||
return $this->enabled; |
||||
} |
||||
|
||||
/** |
||||
* Log debug message |
||||
* @param mixed $object |
||||
* @return mixed|false What the Logger returns, or false if Logger not set or not enabled |
||||
*/ |
||||
public function debug( $object ) { |
||||
return isset($this->logger) && $this->isEnabled() ? $this->logger->debug($object) : false; |
||||
} |
||||
|
||||
/** |
||||
* Log info message |
||||
* @param mixed $object |
||||
* @return mixed|false What the Logger returns, or false if Logger not set or not enabled |
||||
*/ |
||||
public function info( $object ) { |
||||
return isset($this->logger) && $this->isEnabled() ? $this->logger->info($object) : false; |
||||
} |
||||
|
||||
/** |
||||
* Log warn message |
||||
* @param mixed $object |
||||
* @return mixed|false What the Logger returns, or false if Logger not set or not enabled |
||||
*/ |
||||
public function warn( $object ) { |
||||
return isset($this->logger) && $this->isEnabled() ? $this->logger->warn($object) : false; |
||||
} |
||||
|
||||
/** |
||||
* Log error message |
||||
* @param mixed $object |
||||
* @return mixed|false What the Logger returns, or false if Logger not set or not enabled |
||||
*/ |
||||
public function error( $object ) { |
||||
return isset($this->logger) && $this->isEnabled() ? $this->logger->error($object) : false; |
||||
} |
||||
|
||||
/** |
||||
* Log fatal message |
||||
* @param mixed $object |
||||
* @return mixed|false What the Logger returns, or false if Logger not set or not enabled |
||||
*/ |
||||
public function fatal( $object ) { |
||||
return isset($this->logger) && $this->isEnabled() ? $this->logger->fatal($object) : false; |
||||
} |
||||
|
||||
/** |
||||
* Set Logger |
||||
* @param mixed $logger |
||||
* @return void |
||||
*/ |
||||
public function setLogger( $logger ) { |
||||
$this->logger = $logger; |
||||
} |
||||
|
||||
/** |
||||
* Get Logger |
||||
* @return mixed |
||||
*/ |
||||
public function getLogger() { |
||||
return $this->logger; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,200 @@ |
||||
<?php |
||||
/** |
||||
* Slim - a micro PHP 5 framework |
||||
* |
||||
* @author Josh Lockhart <info@joshlockhart.com> |
||||
* @copyright 2011 Josh Lockhart |
||||
* @link http://www.slimframework.com |
||||
* @license http://www.slimframework.com/license |
||||
* @version 1.5.0 |
||||
* |
||||
* MIT LICENSE |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining |
||||
* a copy of this software and associated documentation files (the |
||||
* "Software"), to deal in the Software without restriction, including |
||||
* without limitation the rights to use, copy, modify, merge, publish, |
||||
* distribute, sublicense, and/or sell copies of the Software, and to |
||||
* permit persons to whom the Software is furnished to do so, subject to |
||||
* the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be |
||||
* included in all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
/** |
||||
* Logger |
||||
* |
||||
* A simple Logger that writes to a daily-unique log file in |
||||
* a user-specified directory. By default, this class will write log |
||||
* messages for all log levels; the log level may be changed to filter |
||||
* unwanted log messages from the log file. |
||||
* |
||||
* @package Slim |
||||
* @author Josh Lockhart <info@joshlockhart.com> |
||||
* @since Version 1.0 |
||||
*/ |
||||
class Slim_Logger { |
||||
|
||||
/** |
||||
* @var array Log levels |
||||
*/ |
||||
protected $levels = array( |
||||
0 => 'FATAL', |
||||
1 => 'ERROR', |
||||
2 => 'WARN', |
||||
3 => 'INFO', |
||||
4 => 'DEBUG' |
||||
); |
||||
|
||||
/** |
||||
* @var string Absolute path to log directory with trailing slash |
||||
*/ |
||||
protected $directory; |
||||
|
||||
/** |
||||
* Constructor |
||||
* @param string $directory Absolute or relative path to log directory |
||||
* @param int $level The maximum log level reported by this Logger |
||||
*/ |
||||
public function __construct( $directory, $level = 4 ) { |
||||
$this->setDirectory($directory); |
||||
$this->setLevel($level); |
||||
} |
||||
|
||||
/** |
||||
* Set log directory |
||||
* @param string $directory Absolute or relative path to log directory |
||||
* @return void |
||||
*/ |
||||
public function setDirectory( $directory ) { |
||||
$realPath = realpath($directory); |
||||
if ( $realPath ) { |
||||
$this->directory = rtrim($realPath, '/') . '/'; |
||||
} else { |
||||
$this->directory = false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Get log directory |
||||
* @return string|false Absolute path to log directory with trailing slash |
||||
*/ |
||||
public function getDirectory() { |
||||
return $this->directory; |
||||
} |
||||
|
||||
/** |
||||
* Set log level |
||||
* @param int The maximum log level reported by this Logger |
||||
* @return void |
||||
* @throws InvalidArgumentException If level specified is not 0, 1, 2, 3, 4 |
||||
*/ |
||||
public function setLevel( $level ) { |
||||
$theLevel = (int)$level; |
||||
if ( $theLevel >= 0 && $theLevel <= 4 ) { |
||||
$this->level = $theLevel; |
||||
} else { |
||||
throw new InvalidArgumentException('Invalid Log Level. Must be one of: 0, 1, 2, 3, 4.'); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Get log level |
||||
* @return int |
||||
*/ |
||||
public function getLevel() { |
||||
return $this->level; |
||||
} |
||||
|
||||
/** |
||||
* Log debug data |
||||
* @param mixed $data |
||||
* @return void |
||||
*/ |
||||
public function debug( $data ) { |
||||
$this->log($data, 4); |
||||
} |
||||
|
||||
/** |
||||
* Log info data |
||||
* @param mixed $data |
||||
* @return void |
||||
*/ |
||||
public function info( $data ) { |
||||
$this->log($data, 3); |
||||
} |
||||
|
||||
/** |
||||
* Log warn data |
||||
* @param mixed $data |
||||
* @return void |
||||
*/ |
||||
public function warn( $data ) { |
||||
$this->log($data, 2); |
||||
} |
||||
|
||||
/** |
||||
* Log error data |
||||
* @param mixed $data |
||||
* @return void |
||||
*/ |
||||
public function error( $data ) { |
||||
$this->log($data, 1); |
||||
} |
||||
|
||||
/** |
||||
* Log fatal data |
||||
* @param mixed $data |
||||
* @return void |
||||
*/ |
||||
public function fatal( $data ) { |
||||
$this->log($data, 0); |
||||
} |
||||
|
||||
/** |
||||
* Get absolute path to current daily log file |
||||
* @return string |
||||
*/ |
||||
public function getFile() { |
||||
return $this->getDirectory() . strftime('%Y-%m-%d') . '.log'; |
||||
} |
||||
|
||||
/** |
||||
* Log data to file |
||||
* @param mixed $data |
||||
* @param int $level |
||||
* @return void |
||||
* @throws RuntimeException If log directory not found or not writable |
||||
*/ |
||||
protected function log( $data, $level ) { |
||||
$dir = $this->getDirectory(); |
||||
if ( $dir == false || !is_dir($dir) ) { |
||||
throw new RuntimeException("Log directory '$dir' invalid."); |
||||
} |
||||
if ( !is_writable($dir) ) { |
||||
throw new RuntimeException("Log directory '$dir' not writable."); |
||||
} |
||||
if ( $level <= $this->getLevel() ) { |
||||
$this->write(sprintf("[%s] %s - %s\r\n", $this->levels[$level], date('c'), (string)$data)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Persist data to log |
||||
* @param string Log message |
||||
* @return void |
||||
*/ |
||||
protected function write( $data ) { |
||||
@file_put_contents($this->getFile(), $data, FILE_APPEND | LOCK_EX); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1 @@ |
||||
deny from all |
||||
@ -0,0 +1,125 @@ |
||||
<?php |
||||
/** |
||||
* Slim - a micro PHP 5 framework |
||||
* |
||||
* @author Josh Lockhart |
||||
* @link http://www.slimframework.com |
||||
* @copyright 2011 Josh Lockhart |
||||
* |
||||
* MIT LICENSE |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining |
||||
* a copy of this software and associated documentation files (the |
||||
* "Software"), to deal in the Software without restriction, including |
||||
* without limitation the rights to use, copy, modify, merge, publish, |
||||
* distribute, sublicense, and/or sell copies of the Software, and to |
||||
* permit persons to whom the Software is furnished to do so, subject to |
||||
* the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be |
||||
* included in all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
/** |
||||
* Abstract Session Handler |
||||
* |
||||
* This abstract class should be extended by each concrete |
||||
* session handler. This class defines the contractual class interface |
||||
* methods that must be implemented in concrete subclasses. This class |
||||
* also provides the final `register` method used by Slim itself to |
||||
* actually register the concrete session handler with PHP. |
||||
* |
||||
* @package Slim |
||||
* @author Josh Lockhart |
||||
* @since Version 1.3 |
||||
*/ |
||||
abstract class Harmonious_Session_Handler { |
||||
|
||||
/** |
||||
* @var Slim |
||||
*/ |
||||
protected $app; |
||||
|
||||
/** |
||||
* Register session handler |
||||
* |
||||
* @return bool |
||||
*/ |
||||
final public function register( Harmonious $app ) { |
||||
$this->app = $app; |
||||
return session_set_save_handler( |
||||
array($this, 'open'), |
||||
array($this, 'close'), |
||||
array($this, 'read'), |
||||
array($this, 'write'), |
||||
array($this, 'destroy'), |
||||
array($this, 'gc') |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Open session |
||||
* |
||||
* @param string $savePath |
||||
* @param string $sessionName |
||||
* @return mixed |
||||
*/ |
||||
abstract public function open( $savePath, $sessionName ); |
||||
|
||||
/** |
||||
* Close session |
||||
* |
||||
* @return mixed |
||||
*/ |
||||
abstract public function close(); |
||||
|
||||
/** |
||||
* Read session data with ID |
||||
* |
||||
* @param string $id The session identifier |
||||
* @return string |
||||
*/ |
||||
abstract public function read( $id ); |
||||
|
||||
/** |
||||
* Write session data with ID |
||||
* |
||||
* The "write" handler is not executed until after the output stream is |
||||
* closed. Thus, output from debugging statements in the "write" handler |
||||
* will never be seen in the browser. If debugging output is necessary, it |
||||
* is suggested that the debug output be written to a file instead. |
||||
* |
||||
* @param string $id The session identifier |
||||
* @param mixed $sessionData The session data |
||||
* @return mixed |
||||
*/ |
||||
abstract public function write( $id, $sessionData ); |
||||
|
||||
/** |
||||
* Destroy session with ID |
||||
* |
||||
* @param string $id The session identifier |
||||
* @return mixed |
||||
*/ |
||||
abstract public function destroy( $id ); |
||||
|
||||
/** |
||||
* Session garbage collection |
||||
* |
||||
* Executed when the PHP session garbage collector is invoked; should |
||||
* remove all session data older than the `$maxLifetime`. |
||||
* |
||||
* @param int $maxLifetime |
||||
* @return mixed |
||||
*/ |
||||
abstract public function gc( $maxLifetime ); |
||||
|
||||
} |
||||
@ -0,0 +1 @@ |
||||
deny from all |
||||
@ -0,0 +1,71 @@ |
||||
<?php |
||||
/** |
||||
* Slim - a micro PHP 5 framework |
||||
* |
||||
* @author Josh Lockhart |
||||
* @link http://www.slimframework.com |
||||
* @copyright 2011 Josh Lockhart |
||||
* |
||||
* MIT LICENSE |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining |
||||
* a copy of this software and associated documentation files (the |
||||
* "Software"), to deal in the Software without restriction, including |
||||
* without limitation the rights to use, copy, modify, merge, publish, |
||||
* distribute, sublicense, and/or sell copies of the Software, and to |
||||
* permit persons to whom the Software is furnished to do so, subject to |
||||
* the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be |
||||
* included in all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
/** |
||||
* Session Cookie Handler |
||||
* |
||||
* This class is used as an adapter for PHP's $_SESSION handling. |
||||
* Session data will be written to and read from signed, encrypted |
||||
* cookies. If the current PHP installation does not have the `mcrypt` |
||||
* extension, session data will be written to signed but unencrypted |
||||
* cookies; however, the session cookies will still be secure and will |
||||
* become invalid if manually edited after set by PHP. |
||||
* |
||||
* @package Slim |
||||
* @author Josh Lockhart |
||||
* @since Version 1.3 |
||||
*/ |
||||
class Harmonious_Session_Handler_Cookies extends Harmonious_Session_Handler { |
||||
|
||||
public function open( $savePath, $sessionName ) { |
||||
return true; |
||||
} |
||||
|
||||
public function close() { |
||||
return true; //Not used |
||||
} |
||||
|
||||
public function read( $id ) { |
||||
return $this->app->getEncryptedCookie($id); |
||||
} |
||||
|
||||
public function write( $id, $sessionData ) { |
||||
$this->app->setEncryptedCookie($id, $sessionData, 0); |
||||
} |
||||
|
||||
public function destroy( $id ) { |
||||
$this->app->deleteCookie($id); |
||||
} |
||||
|
||||
public function gc( $maxLifetime ) { |
||||
return true; //Not used |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,33 @@ |
||||
<?php |
||||
/** |
||||
* Адаптация стандартного механизма работы с сессиями для Harmonious |
||||
* Код взят отсюда: http://php.net/manual/ru/function.session-set-save-handler.php |
||||
*/ |
||||
|
||||
class Harmonious_Session_Handler_Fake extends Harmonious_Session_Handler { |
||||
|
||||
public function open( $savePath, $sessionName ) { |
||||
return(true); |
||||
} |
||||
|
||||
public function close() { |
||||
return true; |
||||
} |
||||
|
||||
public function read( $id ) { |
||||
return (string) ""; |
||||
} |
||||
|
||||
public function write( $id, $sessionData ) { |
||||
return strlen($sessionData); |
||||
} |
||||
|
||||
public function destroy( $id ) { |
||||
return true; |
||||
} |
||||
|
||||
public function gc( $maxLifetime ) { |
||||
return true; |
||||
} |
||||
} |
||||
?> |
||||
@ -0,0 +1,58 @@ |
||||
<?php |
||||
/** |
||||
* Адаптация стандартного механизма работы с сессиями для Harmonious |
||||
* Код взят отсюда: http://php.net/manual/ru/function.session-set-save-handler.php |
||||
*/ |
||||
|
||||
class Harmonious_Session_Handler_Files extends Harmonious_Session_Handler { |
||||
|
||||
public function open( $savePath, $sessionName ) { |
||||
global $sess_save_path; |
||||
|
||||
$sess_save_path = $savePath; |
||||
return(true); |
||||
} |
||||
|
||||
public function close() { |
||||
return true; |
||||
} |
||||
|
||||
public function read( $id ) { |
||||
global $sess_save_path; |
||||
|
||||
$sess_file = "$sess_save_path/sess_$id"; |
||||
return (string) @file_get_contents($sess_file); |
||||
} |
||||
|
||||
public function write( $id, $sessionData ) { |
||||
global $sess_save_path; |
||||
|
||||
$sess_file = "$sess_save_path/sess_$id"; |
||||
if ($fp = @fopen($sess_file, "w")) { |
||||
$return = fwrite($fp, $sessionData); |
||||
fclose($fp); |
||||
return $return; |
||||
} else { |
||||
return(false); |
||||
} |
||||
} |
||||
|
||||
public function destroy( $id ) { |
||||
global $sess_save_path; |
||||
|
||||
$sess_file = "$sess_save_path/sess_$id"; |
||||
return(@unlink($sess_file)); |
||||
} |
||||
|
||||
public function gc( $maxLifetime ) { |
||||
global $sess_save_path; |
||||
|
||||
foreach (glob("$sess_save_path/sess_*") as $filename) { |
||||
if (filemtime($filename) + $maxlifetime < time()) { |
||||
@unlink($filename); |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
} |
||||
?> |
||||
@ -0,0 +1,45 @@ |
||||
<?php |
||||
|
||||
class Harmonious_Session_Handler_Memcached extends Harmonious_Session_Handler { |
||||
|
||||
public function open( $savePath, $sessionName ) { |
||||
return(true); |
||||
} |
||||
|
||||
public function close() { |
||||
return true; |
||||
} |
||||
|
||||
public function read( $id ) { |
||||
$mc = $this->app->memcached; |
||||
$key = "php_session_file_". $id; |
||||
$ret = $mc->get($key); |
||||
if(!$ret['result']) return ""; |
||||
else { |
||||
$maxlifetime = ini_get('session.gc_maxlifetime'); |
||||
$mc->set($key, $ret['value'], $maxlifetime); |
||||
return (string) $ret['value']; |
||||
} |
||||
} |
||||
|
||||
public function write( $id, $sessionData ) { |
||||
$mc = $this->app->memcached; |
||||
$key = "php_session_file_". $id; |
||||
$maxlifetime = ini_get('session.gc_maxlifetime'); |
||||
$ret = $mc->set($key, $sessionData, $maxlifetime); |
||||
if ($ret['result']) return true; |
||||
else return(false); |
||||
} |
||||
|
||||
public function destroy( $id ) { |
||||
$mc = $this->app->memcached; |
||||
$key = "php_session_file_". $id; |
||||
$mc->delete($key); |
||||
return(true); |
||||
} |
||||
|
||||
public function gc( $maxLifetime ) { |
||||
return true; |
||||
} |
||||
} |
||||
?> |
||||
@ -0,0 +1,176 @@ |
||||
<?php |
||||
/** |
||||
* Slim - a micro PHP 5 framework |
||||
* |
||||
* @author Josh Lockhart <info@joshlockhart.com> |
||||
* @copyright 2011 Josh Lockhart |
||||
* @link http://www.slimframework.com |
||||
* @license http://www.slimframework.com/license |
||||
* @version 1.5.0 |
||||
* |
||||
* MIT LICENSE |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining |
||||
* a copy of this software and associated documentation files (the |
||||
* "Software"), to deal in the Software without restriction, including |
||||
* without limitation the rights to use, copy, modify, merge, publish, |
||||
* distribute, sublicense, and/or sell copies of the Software, and to |
||||
* permit persons to whom the Software is furnished to do so, subject to |
||||
* the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be |
||||
* included in all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
/** |
||||
* Slim View |
||||
* |
||||
* The View is responsible for rendering and/or displaying a template. |
||||
* It is recommended that you subclass View and re-implement the |
||||
* `View::render` method to use a custom templating engine such as |
||||
* Smarty, Twig, Mustache, etc. It is important that `View::render` |
||||
* `return` the final template output. Do not `echo` the output. |
||||
* |
||||
* @package Slim |
||||
* @author Josh Lockhart <info@joshlockhart.com> |
||||
* @since Version 1.0 |
||||
*/ |
||||
class Slim_View { |
||||
|
||||
/** |
||||
* @var array Key-value array of data available to the template |
||||
*/ |
||||
protected $data = array(); |
||||
|
||||
/** |
||||
* @var string Absolute or relative path to the templates directory |
||||
*/ |
||||
protected $templatesDirectory; |
||||
|
||||
/** |
||||
* Constructor |
||||
* |
||||
* This is empty but may be overridden in a subclass |
||||
*/ |
||||
public function __construct() {} |
||||
|
||||
/** |
||||
* Get data |
||||
* @param string $key |
||||
* @return array|mixed|null All View data if no $key, value of datum |
||||
* if $key, or NULL if $key but datum |
||||
* does not exist. |
||||
*/ |
||||
public function getData( $key = null ) { |
||||
if ( !is_null($key) ) { |
||||
return isset($this->data[$key]) ? $this->data[$key] : null; |
||||
} else { |
||||
return $this->data; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Set data |
||||
* |
||||
* This method is overloaded to accept two different method signatures. |
||||
* You may use this to set a specific key with a specfic value, |
||||
* or you may use this to set all data to a specific array. |
||||
* |
||||
* USAGE: |
||||
* |
||||
* View::setData('color', 'red'); |
||||
* View::setData(array('color' => 'red', 'number' => 1)); |
||||
* |
||||
* @param string|array |
||||
* @param mixed Optional. Only use if first argument is a string. |
||||
* @return void |
||||
* @throws InvalidArgumentException If incorrect method signature |
||||
*/ |
||||
public function setData() { |
||||
$args = func_get_args(); |
||||
if ( count($args) === 1 && is_array($args[0]) ) { |
||||
$this->data = $args[0]; |
||||
} else if ( count($args) === 2 ) { |
||||
$this->data[(string)$args[0]] = $args[1]; |
||||
} else { |
||||
throw new InvalidArgumentException('Cannot set View data with provided arguments. Usage: `View::setData( $key, $value );` or `View::setData([ key => value, ... ]);`'); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Append data to existing View data |
||||
* @param array $data |
||||
* @return void |
||||
*/ |
||||
public function appendData( array $data ) { |
||||
$this->data = array_merge($this->data, $data); |
||||
} |
||||
|
||||
/** |
||||
* Get templates directory |
||||
* @return string|null Path to templates directory without trailing slash |
||||
*/ |
||||
public function getTemplatesDirectory() { |
||||
return $this->templatesDirectory; |
||||
} |
||||
|
||||
/** |
||||
* Set templates directory |
||||
* @param string $dir |
||||
* @return void |
||||
* @throws RuntimeException If directory is not a directory or does not exist |
||||
*/ |
||||
public function setTemplatesDirectory( $dir ) { |
||||
$this->templatesDirectory = rtrim($dir, '/'); |
||||
} |
||||
|
||||
/** |
||||
* Display template |
||||
* |
||||
* This method echoes the rendered template to the current output buffer |
||||
* |
||||
* @param string $template Path to template file relative to templates directoy |
||||
* @return void |
||||
*/ |
||||
public function display( $template ) { |
||||
echo $this->render($template); |
||||
} |
||||
|
||||
/** |
||||
* Display template |
||||
* |
||||
* This method echoes the rendered template to the current output buffer |
||||
* |
||||
* @param string $template Path to template file relative to templates directoy |
||||
* @return void |
||||
*/ |
||||
public function fetch( $template ) { |
||||
return $this->render($template); |
||||
} |
||||
|
||||
/** |
||||
* Render template |
||||
* @param string $template Path to template file relative to templates directory |
||||
* @return string Rendered template |
||||
* @throws RuntimeException If template does not exist |
||||
*/ |
||||
public function render( $template ) { |
||||
extract($this->data); |
||||
$templatePath = $this->getTemplatesDirectory() . '/' . ltrim($template, '/'); |
||||
if ( !file_exists($templatePath) ) { |
||||
throw new RuntimeException('View cannot render template `' . $templatePath . '`. Template does not exist.'); |
||||
} |
||||
ob_start(); |
||||
require $templatePath; |
||||
return ob_get_clean(); |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue