Initial Release of the calendar plugin

This commit is contained in:
Tobias Hößl 2012-06-03 18:19:28 +00:00
parent 45cc9885fc
commit 7115197a33
561 changed files with 189494 additions and 0 deletions

View file

@ -0,0 +1,227 @@
<?php
/**
* HTTP AWS Authentication handler
*
* Use this class to leverage amazon's AWS authentication header
*
* @package Sabre
* @subpackage HTTP
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth {
/**
* The signature supplied by the HTTP client
*
* @var string
*/
private $signature = null;
/**
* The accesskey supplied by the HTTP client
*
* @var string
*/
private $accessKey = null;
/**
* An error code, if any
*
* This value will be filled with one of the ERR_* constants
*
* @var int
*/
public $errorCode = 0;
const ERR_NOAWSHEADER = 1;
const ERR_MD5CHECKSUMWRONG = 2;
const ERR_INVALIDDATEFORMAT = 3;
const ERR_REQUESTTIMESKEWED = 4;
const ERR_INVALIDSIGNATURE = 5;
/**
* Gathers all information from the headers
*
* This method needs to be called prior to anything else.
*
* @return bool
*/
public function init() {
$authHeader = $this->httpRequest->getHeader('Authorization');
$authHeader = explode(' ',$authHeader);
if ($authHeader[0]!='AWS' || !isset($authHeader[1])) {
$this->errorCode = self::ERR_NOAWSHEADER;
return false;
}
list($this->accessKey,$this->signature) = explode(':',$authHeader[1]);
return true;
}
/**
* Returns the username for the request
*
* @return string
*/
public function getAccessKey() {
return $this->accessKey;
}
/**
* Validates the signature based on the secretKey
*
* @param string $secretKey
* @return bool
*/
public function validate($secretKey) {
$contentMD5 = $this->httpRequest->getHeader('Content-MD5');
if ($contentMD5) {
// We need to validate the integrity of the request
$body = $this->httpRequest->getBody(true);
$this->httpRequest->setBody($body,true);
if ($contentMD5!=base64_encode(md5($body,true))) {
// content-md5 header did not match md5 signature of body
$this->errorCode = self::ERR_MD5CHECKSUMWRONG;
return false;
}
}
if (!$requestDate = $this->httpRequest->getHeader('x-amz-date'))
$requestDate = $this->httpRequest->getHeader('Date');
if (!$this->validateRFC2616Date($requestDate))
return false;
$amzHeaders = $this->getAmzHeaders();
$signature = base64_encode(
$this->hmacsha1($secretKey,
$this->httpRequest->getMethod() . "\n" .
$contentMD5 . "\n" .
$this->httpRequest->getHeader('Content-type') . "\n" .
$requestDate . "\n" .
$amzHeaders .
$this->httpRequest->getURI()
)
);
if ($this->signature != $signature) {
$this->errorCode = self::ERR_INVALIDSIGNATURE;
return false;
}
return true;
}
/**
* Returns an HTTP 401 header, forcing login
*
* This should be called when username and password are incorrect, or not supplied at all
*
* @return void
*/
public function requireLogin() {
$this->httpResponse->setHeader('WWW-Authenticate','AWS');
$this->httpResponse->sendStatus(401);
}
/**
* Makes sure the supplied value is a valid RFC2616 date.
*
* If we would just use strtotime to get a valid timestamp, we have no way of checking if a
* user just supplied the word 'now' for the date header.
*
* This function also makes sure the Date header is within 15 minutes of the operating
* system date, to prevent replay attacks.
*
* @param string $dateHeader
* @return bool
*/
protected function validateRFC2616Date($dateHeader) {
$date = Sabre_HTTP_Util::parseHTTPDate($dateHeader);
// Unknown format
if (!$date) {
$this->errorCode = self::ERR_INVALIDDATEFORMAT;
return false;
}
$min = new DateTime('-15 minutes');
$max = new DateTime('+15 minutes');
// We allow 15 minutes around the current date/time
if ($date > $max || $date < $min) {
$this->errorCode = self::ERR_REQUESTTIMESKEWED;
return false;
}
return $date;
}
/**
* Returns a list of AMZ headers
*
* @return string
*/
protected function getAmzHeaders() {
$amzHeaders = array();
$headers = $this->httpRequest->getHeaders();
foreach($headers as $headerName => $headerValue) {
if (strpos(strtolower($headerName),'x-amz-')===0) {
$amzHeaders[strtolower($headerName)] = str_replace(array("\r\n"),array(' '),$headerValue) . "\n";
}
}
ksort($amzHeaders);
$headerStr = '';
foreach($amzHeaders as $h=>$v) {
$headerStr.=$h.':'.$v;
}
return $headerStr;
}
/**
* Generates an HMAC-SHA1 signature
*
* @param string $key
* @param string $message
* @return string
*/
private function hmacsha1($key, $message) {
$blocksize=64;
if (strlen($key)>$blocksize)
$key=pack('H*', sha1($key));
$key=str_pad($key,$blocksize,chr(0x00));
$ipad=str_repeat(chr(0x36),$blocksize);
$opad=str_repeat(chr(0x5c),$blocksize);
$hmac = pack('H*',sha1(($key^$opad).pack('H*',sha1(($key^$ipad).$message))));
return $hmac;
}
}

View file

@ -0,0 +1,111 @@
<?php
/**
* HTTP Authentication baseclass
*
* This class has the common functionality for BasicAuth and DigestAuth
*
* @package Sabre
* @subpackage HTTP
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
abstract class Sabre_HTTP_AbstractAuth {
/**
* The realm will be displayed in the dialog boxes
*
* This identifier can be changed through setRealm()
*
* @var string
*/
protected $realm = 'SabreDAV';
/**
* HTTP response helper
*
* @var Sabre_HTTP_Response
*/
protected $httpResponse;
/**
* HTTP request helper
*
* @var Sabre_HTTP_Request
*/
protected $httpRequest;
/**
* __construct
*
*/
public function __construct() {
$this->httpResponse = new Sabre_HTTP_Response();
$this->httpRequest = new Sabre_HTTP_Request();
}
/**
* Sets an alternative HTTP response object
*
* @param Sabre_HTTP_Response $response
* @return void
*/
public function setHTTPResponse(Sabre_HTTP_Response $response) {
$this->httpResponse = $response;
}
/**
* Sets an alternative HTTP request object
*
* @param Sabre_HTTP_Request $request
* @return void
*/
public function setHTTPRequest(Sabre_HTTP_Request $request) {
$this->httpRequest = $request;
}
/**
* Sets the realm
*
* The realm is often displayed in authentication dialog boxes
* Commonly an application name displayed here
*
* @param string $realm
* @return void
*/
public function setRealm($realm) {
$this->realm = $realm;
}
/**
* Returns the realm
*
* @return string
*/
public function getRealm() {
return $this->realm;
}
/**
* Returns an HTTP 401 header, forcing login
*
* This should be called when username and password are incorrect, or not supplied at all
*
* @return void
*/
abstract public function requireLogin();
}

View file

@ -0,0 +1,67 @@
<?php
/**
* HTTP Basic Authentication handler
*
* Use this class for easy http authentication setup
*
* @package Sabre
* @subpackage HTTP
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_HTTP_BasicAuth extends Sabre_HTTP_AbstractAuth {
/**
* Returns the supplied username and password.
*
* The returned array has two values:
* * 0 - username
* * 1 - password
*
* If nothing was supplied, 'false' will be returned
*
* @return mixed
*/
public function getUserPass() {
// Apache and mod_php
if (($user = $this->httpRequest->getRawServerValue('PHP_AUTH_USER')) && ($pass = $this->httpRequest->getRawServerValue('PHP_AUTH_PW'))) {
return array($user,$pass);
}
// Most other webservers
$auth = $this->httpRequest->getHeader('Authorization');
// Apache could prefix environment variables with REDIRECT_ when urls
// are passed through mod_rewrite
if (!$auth) {
$auth = $this->httpRequest->getRawServerValue('REDIRECT_HTTP_AUTHORIZATION');
}
if (!$auth) return false;
if (strpos(strtolower($auth),'basic')!==0) return false;
return explode(':', base64_decode(substr($auth, 6)));
}
/**
* Returns an HTTP 401 header, forcing login
*
* This should be called when username and password are incorrect, or not supplied at all
*
* @return void
*/
public function requireLogin() {
$this->httpResponse->setHeader('WWW-Authenticate','Basic realm="' . $this->realm . '"');
$this->httpResponse->sendStatus(401);
}
}

View file

@ -0,0 +1,240 @@
<?php
/**
* HTTP Digest Authentication handler
*
* Use this class for easy http digest authentication.
* Instructions:
*
* 1. Create the object
* 2. Call the setRealm() method with the realm you plan to use
* 3. Call the init method function.
* 4. Call the getUserName() function. This function may return false if no
* authentication information was supplied. Based on the username you
* should check your internal database for either the associated password,
* or the so-called A1 hash of the digest.
* 5. Call either validatePassword() or validateA1(). This will return true
* or false.
* 6. To make sure an authentication prompt is displayed, call the
* requireLogin() method.
*
*
* @package Sabre
* @subpackage HTTP
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth {
/**
* These constants are used in setQOP();
*/
const QOP_AUTH = 1;
const QOP_AUTHINT = 2;
protected $nonce;
protected $opaque;
protected $digestParts;
protected $A1;
protected $qop = self::QOP_AUTH;
/**
* Initializes the object
*/
public function __construct() {
$this->nonce = uniqid();
$this->opaque = md5($this->realm);
parent::__construct();
}
/**
* Gathers all information from the headers
*
* This method needs to be called prior to anything else.
*
* @return void
*/
public function init() {
$digest = $this->getDigest();
$this->digestParts = $this->parseDigest($digest);
}
/**
* Sets the quality of protection value.
*
* Possible values are:
* Sabre_HTTP_DigestAuth::QOP_AUTH
* Sabre_HTTP_DigestAuth::QOP_AUTHINT
*
* Multiple values can be specified using logical OR.
*
* QOP_AUTHINT ensures integrity of the request body, but this is not
* supported by most HTTP clients. QOP_AUTHINT also requires the entire
* request body to be md5'ed, which can put strains on CPU and memory.
*
* @param int $qop
* @return void
*/
public function setQOP($qop) {
$this->qop = $qop;
}
/**
* Validates the user.
*
* The A1 parameter should be md5($username . ':' . $realm . ':' . $password);
*
* @param string $A1
* @return bool
*/
public function validateA1($A1) {
$this->A1 = $A1;
return $this->validate();
}
/**
* Validates authentication through a password. The actual password must be provided here.
* It is strongly recommended not store the password in plain-text and use validateA1 instead.
*
* @param string $password
* @return bool
*/
public function validatePassword($password) {
$this->A1 = md5($this->digestParts['username'] . ':' . $this->realm . ':' . $password);
return $this->validate();
}
/**
* Returns the username for the request
*
* @return string
*/
public function getUsername() {
return $this->digestParts['username'];
}
/**
* Validates the digest challenge
*
* @return bool
*/
protected function validate() {
$A2 = $this->httpRequest->getMethod() . ':' . $this->digestParts['uri'];
if ($this->digestParts['qop']=='auth-int') {
// Making sure we support this qop value
if (!($this->qop & self::QOP_AUTHINT)) return false;
// We need to add an md5 of the entire request body to the A2 part of the hash
$body = $this->httpRequest->getBody(true);
$this->httpRequest->setBody($body,true);
$A2 .= ':' . md5($body);
} else {
// We need to make sure we support this qop value
if (!($this->qop & self::QOP_AUTH)) return false;
}
$A2 = md5($A2);
$validResponse = md5("{$this->A1}:{$this->digestParts['nonce']}:{$this->digestParts['nc']}:{$this->digestParts['cnonce']}:{$this->digestParts['qop']}:{$A2}");
return $this->digestParts['response']==$validResponse;
}
/**
* Returns an HTTP 401 header, forcing login
*
* This should be called when username and password are incorrect, or not supplied at all
*
* @return void
*/
public function requireLogin() {
$qop = '';
switch($this->qop) {
case self::QOP_AUTH : $qop = 'auth'; break;
case self::QOP_AUTHINT : $qop = 'auth-int'; break;
case self::QOP_AUTH | self::QOP_AUTHINT : $qop = 'auth,auth-int'; break;
}
$this->httpResponse->setHeader('WWW-Authenticate','Digest realm="' . $this->realm . '",qop="'.$qop.'",nonce="' . $this->nonce . '",opaque="' . $this->opaque . '"');
$this->httpResponse->sendStatus(401);
}
/**
* This method returns the full digest string.
*
* It should be compatibile with mod_php format and other webservers.
*
* If the header could not be found, null will be returned
*
* @return mixed
*/
public function getDigest() {
// mod_php
$digest = $this->httpRequest->getRawServerValue('PHP_AUTH_DIGEST');
if ($digest) return $digest;
// most other servers
$digest = $this->httpRequest->getHeader('Authorization');
// Apache could prefix environment variables with REDIRECT_ when urls
// are passed through mod_rewrite
if (!$digest) {
$digest = $this->httpRequest->getRawServerValue('REDIRECT_HTTP_AUTHORIZATION');
}
if ($digest && strpos(strtolower($digest),'digest')===0) {
return substr($digest,7);
} else {
return null;
}
}
/**
* Parses the different pieces of the digest string into an array.
*
* This method returns false if an incomplete digest was supplied
*
* @param string $digest
* @return mixed
*/
protected function parseDigest($digest) {
// protect against missing data
$needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
$data = array();
preg_match_all('@(\w+)=(?:(?:")([^"]+)"|([^\s,$]+))@', $digest, $matches, PREG_SET_ORDER);
foreach ($matches as $m) {
$data[$m[1]] = $m[2] ? $m[2] : $m[3];
unset($needed_parts[$m[1]]);
}
return $needed_parts ? false : $data;
}
}

View file

@ -0,0 +1,268 @@
<?php
/**
* HTTP Request information
*
* This object can be used to easily access information about an HTTP request.
* It can additionally be used to create 'mock' requests.
*
* This class mostly operates independent, but because of the nature of a single
* request per run it can operate as a singleton. For more information check out
* the behaviour around 'defaultInputStream'.
*
* @package Sabre
* @subpackage HTTP
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_HTTP_Request {
/**
* PHP's $_SERVER data
*
* @var array
*/
protected $_SERVER;
/**
* PHP's $_POST data
*
* @var array
*/
protected $_POST;
/**
* The request body, if any.
*
* This is stored in the form of a stream resource.
*
* @var resource
*/
protected $body = null;
/**
* This will be set as the 'default' inputStream for a specific HTTP request
* We sometimes need to retain, or rebuild this if we need multiple runs
* of parsing the original HTTP request.
*
* @var resource
*/
static $defaultInputStream=null;
/**
* Sets up the object
*
* The serverData and postData array can be used to override usage of PHP's
* global _SERVER and _POST variable respectively.
*
* @param array $serverData
* @param array $postData
*/
public function __construct(array $serverData = null, array $postData = null) {
if ($serverData) $this->_SERVER = $serverData;
else $this->_SERVER =& $_SERVER;
if ($postData) $this->_POST = $postData;
else $this->_POST =& $_POST;
}
/**
* Returns the value for a specific http header.
*
* This method returns null if the header did not exist.
*
* @param string $name
* @return string
*/
public function getHeader($name) {
$name = strtoupper(str_replace(array('-'),array('_'),$name));
if (isset($this->_SERVER['HTTP_' . $name])) {
return $this->_SERVER['HTTP_' . $name];
}
// There's a few headers that seem to end up in the top-level
// server array.
switch($name) {
case 'CONTENT_TYPE' :
case 'CONTENT_LENGTH' :
if (isset($this->_SERVER[$name])) {
return $this->_SERVER[$name];
}
break;
}
return;
}
/**
* Returns all (known) HTTP headers.
*
* All headers are converted to lower-case, and additionally all underscores
* are automatically converted to dashes
*
* @return array
*/
public function getHeaders() {
$hdrs = array();
foreach($this->_SERVER as $key=>$value) {
switch($key) {
case 'CONTENT_LENGTH' :
case 'CONTENT_TYPE' :
$hdrs[strtolower(str_replace('_','-',$key))] = $value;
break;
default :
if (strpos($key,'HTTP_')===0) {
$hdrs[substr(strtolower(str_replace('_','-',$key)),5)] = $value;
}
break;
}
}
return $hdrs;
}
/**
* Returns the HTTP request method
*
* This is for example POST or GET
*
* @return string
*/
public function getMethod() {
return $this->_SERVER['REQUEST_METHOD'];
}
/**
* Returns the requested uri
*
* @return string
*/
public function getUri() {
return $this->_SERVER['REQUEST_URI'];
}
/**
* Will return protocol + the hostname + the uri
*
* @return string
*/
public function getAbsoluteUri() {
// Checking if the request was made through HTTPS. The last in line is for IIS
$protocol = isset($this->_SERVER['HTTPS']) && ($this->_SERVER['HTTPS']) && ($this->_SERVER['HTTPS']!='off');
return ($protocol?'https':'http') . '://' . $this->getHeader('Host') . $this->getUri();
}
/**
* Returns everything after the ? from the current url
*
* @return string
*/
public function getQueryString() {
return isset($this->_SERVER['QUERY_STRING'])?$this->_SERVER['QUERY_STRING']:'';
}
/**
* Returns the HTTP request body body
*
* This method returns a readable stream resource.
* If the asString parameter is set to true, a string is sent instead.
*
* @param bool $asString
* @return resource
*/
public function getBody($asString = false) {
if (is_null($this->body)) {
if (!is_null(self::$defaultInputStream)) {
$this->body = self::$defaultInputStream;
} else {
$this->body = fopen('php://input','r');
self::$defaultInputStream = $this->body;
}
}
if ($asString) {
$body = stream_get_contents($this->body);
return $body;
} else {
return $this->body;
}
}
/**
* Sets the contents of the HTTP request body
*
* This method can either accept a string, or a readable stream resource.
*
* If the setAsDefaultInputStream is set to true, it means for this run of the
* script the supplied body will be used instead of php://input.
*
* @param mixed $body
* @param bool $setAsDefaultInputStream
* @return void
*/
public function setBody($body,$setAsDefaultInputStream = false) {
if(is_resource($body)) {
$this->body = $body;
} else {
$stream = fopen('php://temp','r+');
fputs($stream,$body);
rewind($stream);
// String is assumed
$this->body = $stream;
}
if ($setAsDefaultInputStream) {
self::$defaultInputStream = $this->body;
}
}
/**
* Returns PHP's _POST variable.
*
* The reason this is in a method is so it can be subclassed and
* overridden.
*
* @return array
*/
public function getPostVars() {
return $this->_POST;
}
/**
* Returns a specific item from the _SERVER array.
*
* Do not rely on this feature, it is for internal use only.
*
* @param string $field
* @return string
*/
public function getRawServerValue($field) {
return isset($this->_SERVER[$field])?$this->_SERVER[$field]:null;
}
}

View file

@ -0,0 +1,157 @@
<?php
/**
* Sabre_HTTP_Response
*
* @package Sabre
* @subpackage HTTP
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_HTTP_Response {
/**
* Returns a full HTTP status message for an HTTP status code
*
* @param int $code
* @return string
*/
public function getStatusMessage($code) {
$msg = array(
100 => 'Continue',
101 => 'Switching Protocols',
102 => 'Processing',
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authorative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
207 => 'Multi-Status', // RFC 4918
208 => 'Already Reported', // RFC 5842
226 => 'IM Used', // RFC 3229
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found',
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
306 => 'Reserved',
307 => 'Temporary Redirect',
400 => 'Bad request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
418 => 'I\'m a teapot', // RFC 2324
422 => 'Unprocessable Entity', // RFC 4918
423 => 'Locked', // RFC 4918
424 => 'Failed Dependency', // RFC 4918
426 => 'Upgrade required',
428 => 'Precondition required', // draft-nottingham-http-new-status
429 => 'Too Many Requests', // draft-nottingham-http-new-status
431 => 'Request Header Fields Too Large', // draft-nottingham-http-new-status
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version not supported',
506 => 'Variant Also Negotiates',
507 => 'Insufficient Storage', // RFC 4918
508 => 'Loop Detected', // RFC 5842
509 => 'Bandwidth Limit Exceeded', // non-standard
510 => 'Not extended',
511 => 'Network Authentication Required', // draft-nottingham-http-new-status
);
return 'HTTP/1.1 ' . $code . ' ' . $msg[$code];
}
/**
* Sends an HTTP status header to the client
*
* @param int $code HTTP status code
* @return bool
*/
public function sendStatus($code) {
if (!headers_sent())
return header($this->getStatusMessage($code));
else return false;
}
/**
* Sets an HTTP header for the response
*
* @param string $name
* @param string $value
* @param bool $replace
* @return bool
*/
public function setHeader($name, $value, $replace = true) {
$value = str_replace(array("\r","\n"),array('\r','\n'),$value);
if (!headers_sent())
return header($name . ': ' . $value, $replace);
else return false;
}
/**
* Sets a bunch of HTTP Headers
*
* headersnames are specified as keys, value in the array value
*
* @param array $headers
* @return void
*/
public function setHeaders(array $headers) {
foreach($headers as $key=>$value)
$this->setHeader($key, $value);
}
/**
* Sends the entire response body
*
* This method can accept either an open filestream, or a string.
*
* @param mixed $body
* @return void
*/
public function sendBody($body) {
if (is_resource($body)) {
fpassthru($body);
} else {
// We assume a string
echo $body;
}
}
}

View file

@ -0,0 +1,82 @@
<?php
/**
* HTTP utility methods
*
* @package Sabre
* @subpackage HTTP
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @author Paul Voegler
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_HTTP_Util {
/**
* Parses a RFC2616-compatible date string
*
* This method returns false if the date is invalid
*
* @param string $dateHeader
* @return bool|DateTime
*/
static function parseHTTPDate($dateHeader) {
//RFC 2616 section 3.3.1 Full Date
//Only the format is checked, valid ranges are checked by strtotime below
$month = '(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)';
$weekday = '(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)';
$wkday = '(Mon|Tue|Wed|Thu|Fri|Sat|Sun)';
$time = '[0-2]\d(\:[0-5]\d){2}';
$date3 = $month . ' ([1-3]\d| \d)';
$date2 = '[0-3]\d\-' . $month . '\-\d\d';
//4-digit year cannot begin with 0 - unix timestamp begins in 1970
$date1 = '[0-3]\d ' . $month . ' [1-9]\d{3}';
//ANSI C's asctime() format
//4-digit year cannot begin with 0 - unix timestamp begins in 1970
$asctime_date = $wkday . ' ' . $date3 . ' ' . $time . ' [1-9]\d{3}';
//RFC 850, obsoleted by RFC 1036
$rfc850_date = $weekday . ', ' . $date2 . ' ' . $time . ' GMT';
//RFC 822, updated by RFC 1123
$rfc1123_date = $wkday . ', ' . $date1 . ' ' . $time . ' GMT';
//allowed date formats by RFC 2616
$HTTP_date = "($rfc1123_date|$rfc850_date|$asctime_date)";
//allow for space around the string and strip it
$dateHeader = trim($dateHeader, ' ');
if (!preg_match('/^' . $HTTP_date . '$/', $dateHeader))
return false;
//append implicit GMT timezone to ANSI C time format
if (strpos($dateHeader, ' GMT') === false)
$dateHeader .= ' GMT';
$realDate = strtotime($dateHeader);
//strtotime can return -1 or false in case of error
if ($realDate !== false && $realDate >= 0)
return new DateTime('@' . $realDate, new DateTimeZone('UTC'));
}
/**
* Transforms a DateTime object to HTTP's most common date format.
*
* We're serializing it as the RFC 1123 date, which, for HTTP must be
* specified as GMT.
*
* @param DateTime $dateTime
* @return string
*/
static function toHTTPDate(DateTime $dateTime) {
// We need to clone it, as we don't want to affect the existing
// DateTime.
$dateTime = clone $dateTime;
$dateTime->setTimeZone(new DateTimeZone('GMT'));
return $dateTime->format('D, d M Y H:i:s \G\M\T');
}
}

View file

@ -0,0 +1,24 @@
<?php
/**
* This class contains the Sabre_HTTP version constants.
*
* @package Sabre
* @subpackage HTTP
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_HTTP_Version {
/**
* Full version number
*/
const VERSION = '1.6.2';
/**
* Stability : alpha, beta, stable
*/
const STABILITY = 'stable';
}

View file

@ -0,0 +1,27 @@
<?php
/**
* Sabre_HTTP includes file
*
* Including this file will automatically include all files from the Sabre_HTTP
* package.
*
* This often allows faster loadtimes, as autoload-speed is often quite slow.
*
* @package Sabre
* @subpackage HTTP
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
// Begin includes
include __DIR__ . '/AbstractAuth.php';
include __DIR__ . '/AWSAuth.php';
include __DIR__ . '/BasicAuth.php';
include __DIR__ . '/DigestAuth.php';
include __DIR__ . '/Request.php';
include __DIR__ . '/Response.php';
include __DIR__ . '/Util.php';
include __DIR__ . '/Version.php';
// End includes