Permalink
Browse files

Merge remote-tracking branch 'origin/master' into release-1.0.3

  • Loading branch information...
2 parents b827dc2 + 0fd2f83 commit 718a005a0861e2f1f31f31f3af173b35707fd973 @silentworks silentworks committed Jun 3, 2012
Showing with 352 additions and 0 deletions.
  1. +131 −0 Log Writers/TimestampLogFileWriter.php
  2. +89 −0 Middleware/HttpBasicAuth.php
  3. +132 −0 Middleware/HttpDigestAuth.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);
+ }
+}
@@ -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));
+ }
+ }
+}
@@ -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.