Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into release-1.0.3
Browse files Browse the repository at this point in the history
  • Loading branch information
silentworks committed Jun 3, 2012
2 parents b827dc2 + 0fd2f83 commit 718a005
Show file tree
Hide file tree
Showing 3 changed files with 352 additions and 0 deletions.
131 changes: 131 additions & 0 deletions Log Writers/TimestampLogFileWriter.php
@@ -0,0 +1,131 @@
<?php
/**
* Timestamp Log File Writer
*
* Use this custom log writer to output log messages
* to a daily, weekly, monthly, or yearly log file. Log
* files will inherently rotate based on the specified
* log file name format and the current time.
*
* USAGE
*
* $app = new Slim(array(
* 'log.writer' => new TimestampLogFileWriter()
* ));
*
* SETTINGS
*
* You may customize this log writer by passing an array of
* settings into the class constructor. Available options
* are shown above the constructor method below.
*
* @author Josh Lockhart <info@slimframework.com>
* @copyright 2012 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.
*/
class TimestampLogFileWriter {
/**
* @var resource
*/
protected $resource;

/**
* @var array
*/
protected $settings;

/**
* Constructor
*
* Prepare this log writer. Available settings are:
*
* path:
* (string) The relative or absolute filesystem path to a writable directory.
*
* name_format:
* (string) The log file name format; parsed with `date()`.
*
* message_format:
* (string) The log message format; available tokens are...
* %label% Replaced with the log message level (e.g. FATAL, ERROR, WARN).
* %date% Replaced with a ISO8601 date string for current timezone.
* %message% Replaced with the log message, coerced to a string.
*
* @param array $settings
* @return void
*/
public function __construct( $settings = array() ) {
//Merge user settings
$this->settings = array_merge(array(
'path' => './logs',
'name_format' => 'Y-m-d',
'message_format' => '%label% - %date% - %message%'
), $settings);

//Remove trailing slash from log path
$this->settings['path'] = rtrim($this->settings['path'], DIRECTORY_SEPARATOR);

//Open resource handle to log file
$this->resource = fopen($this->settings['path'] . DIRECTORY_SEPARATOR . date($this->settings['name_format']), 'a');
}

/**
* Write to log
*
* @param mixed $object
* @param int $level
* @return void
*/
public function write( $object, $level ) {
//Determine label
$label = 'DEBUG';
switch ( $level ) {
case 0:
$label = 'FATAL';
break;
case 1:
$label = 'ERROR';
break;
case 2:
$label = 'WARN';
break;
case 3:
$label = 'INFO';
break;
}

//Get formatted log message
$message = str_replace(array(
'%label%',
'%date%',
'%message%'
), array(
$label,
date('c'),
(string)$object
), $this->settings['message_format']);

//Output to resource
fwrite($this->resource, $message . PHP_EOL);
}
}
89 changes: 89 additions & 0 deletions Middleware/HttpBasicAuth.php
@@ -0,0 +1,89 @@
<?php
/**
* HTTP Basic Authentication
*
* Use this middleware with your Slim Framework application
* to require HTTP basic auth for all routes.
*
* @author Josh Lockhart <info@slimframework.com>
* @version 1.0
* @copyright 2012 Josh Lockhart
*
* USAGE
*
* $app = new Slim();
* $app->add(new HttpBasicAuth('theUsername', 'thePassword'));
*
* 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.
*/
class HttpBasicAuth extends Slim_Middleware {
/**
* @var string
*/
protected $realm;

/**
* @var string
*/
protected $username;

/**
* @var string
*/
protected $password;

/**
* Constructor
*
* @param string $username The HTTP Authentication username
* @param string $password The HTTP Authentication password
* @param string $realm The HTTP Authentication realm
* @return void
*/
public function __construct( $username, $password, $realm = 'Protected Area' ) {
$this->username = $username;
$this->password = $password;
$this->realm = $realm;
}

/**
* Call
*
* This method will check the HTTP request headers for previous authentication. If
* the request has already authenticated, the next middleware is called. Otherwise,
* a 401 Authentication Required response is returned to the client.
*
* @return void
*/
public function call() {
$req = $this->app->request();
$res = $this->app->response();
$authUser = $req->headers('PHP_AUTH_USER');
$authPass = $req->headers('PHP_AUTH_PW');
if ( $authUser && $authPass && $authUser === $this->username && $authPass === $this->password ) {
$this->next->call();
} else {
$res->status(401);
$res->header('WWW-Authenticate', sprintf('Basic realm="%s"', $this->realm));
}
}
}
132 changes: 132 additions & 0 deletions Middleware/HttpDigestAuth.php
@@ -0,0 +1,132 @@
<?php
/**
* HTTP Digest Authentication
*
* Use this middleware with your Slim Framework application
* to require HTTP digest auth for all routes.
*
* Much of this code was created using <http://php.net/manual/en/features.http-auth.php>
* as a reference. I do not claim ownership or copyright on this code. This
* derivative class is provided under the MIT public license.
*
* @author Josh Lockhart <info@slimframework.com>
* @version 1.0
*
* USAGE
*
* $app = new Slim();
* $app->add(new HttpDigestAuth('theUsername', 'thePassword'));
*
* 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.
*/
class HttpDigestAuth extends Slim_Middleware {
/**
* @var string
*/
protected $username;

/**
* @var string
*/
protected $password;

/**
* @var string
*/
protected $realm;

/**
* Constructor
*
* @param string $username The HTTP Authentication username
* @param string $password The HTTP Authentication password
* @param string $realm The HTTP Authentication realm
* @return void
*/
public function __construct( $username, $password, $realm = 'Protected Area' ) {
$this->username = $username;
$this->password = $password;
$this->realm = $realm;
}

/**
* Call
*
* This method will check the HTTP request headers for previous authentication. If
* the request has already authenticated, the next middleware is called. Otherwise,
* a 401 Authentication Required response is returned to the client.
*
* @return void
*/
public function call() {
//Check header and header username
if ( empty($_SERVER['PHP_AUTH_DIGEST']) ) {
$this->fail();
return;
} else {
$data = $this->parseHttpDigest($_SERVER['PHP_AUTH_DIGEST']);
if ( !$data || $data['username'] !== $this->username ) {
$this->fail();
return;
}
}

//Check header response
$A1 = md5($data['username'] . ':' . $this->realm . ':' . $this->password);
$A2 = md5($_SERVER['REQUEST_METHOD'] . ':' . $data['uri']);
$validResponse = md5($A1 . ':' . $data['nonce'] . ':' . $data['nc'] . ':' . $data['cnonce'] . ':' . $data['qop'] . ':' . $A2);
if ( $data['response'] !== $validResponse ) {
$this->fail();
return;
}

//By this point the request is authenticated
$this->next->call();
}

/**
* Require Authentication from HTTP Client
*
* @return void
*/
protected function fail() {
$this->app->response()->status(401);
$this->app->response()->header('WWW-Authenticate', sprintf('Digest realm="%s",qop="auth",nonce="%s",opaque="%s"', $this->realm, uniqid(), md5($this->realm)));
}

/**
* Parse HTTP Digest Authentication header
*
* @return array|false
*/
protected function parseHttpDigest( $headerValue ) {
$needed_parts = array('nonce' => 1, 'nc' => 1, 'cnonce' => 1, 'qop' => 1, 'username' => 1, 'uri' => 1, 'response' => 1);
$data = array();
$keys = implode('|', array_keys($needed_parts));
preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', $headerValue, $matches, PREG_SET_ORDER);
foreach ( $matches as $m ) {
$data[$m[1]] = $m[3] ? $m[3] : $m[4];
unset($needed_parts[$m[1]]);
}
return $needed_parts ? false : $data;
}
}

0 comments on commit 718a005

Please sign in to comment.