blob: 4694035b19463f3442c8cc4cccfad805409f3d15 [file] [log] [blame]
<?php
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/*
* This is a somewhat liberal interpretation of the HttpServlet class
* Mixed with some essentials to make propper http header handling
* happen in php.
*/
class HttpServlet {
private $lastModified = false;
private $contentType = 'text/html';
private $charset = 'UTF-8';
private $noCache = false;
private $cacheTime;
public $noHeaders = false;
/**
* Enables output buffering so we can do correct header handling in the destructor
*
*/
public function __construct() {
// set our default cache time (config cache time defaults to 24 hours aka 1 day)
$this->cacheTime = Config::get('cache_time');
// to do our header magic, we need output buffering on
ob_start();
}
/**
* Code ran after the event handler, adds headers etc to the request
* If noHeaders is false, it adds all the correct http/1.1 headers to the request
* and deals with modified/expires/e-tags/etc. This makes the server behave more like
* a real http server.
*/
public function __destruct() {
if (! $this->noHeaders) {
header("Content-Type: $this->contentType" . (! empty($this->charset) ? "; charset={$this->charset}" : ''));
header('Accept-Ranges: bytes');
if ($this->noCache) {
header("Cache-Control: no-cache, must-revalidate", true);
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT", true);
} else {
// attempt at some propper header handling from php
// this departs a little from the shindig code but it should give is valid http protocol handling
header('Cache-Control: public,max-age=' . $this->cacheTime, true);
header("Expires: " . gmdate("D, d M Y H:i:s", time() + $this->cacheTime) . " GMT", true);
// Obey browsers (or proxy's) request to send a fresh copy if we recieve a no-cache pragma or cache-control request
if (! isset($_SERVER['HTTP_PRAGMA']) || ! strstr(strtolower($_SERVER['HTTP_PRAGMA']), 'no-cache') && (! isset($_SERVER['HTTP_CACHE_CONTROL']) || ! strstr(strtolower($_SERVER['HTTP_CACHE_CONTROL']), 'no-cache'))) {
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $this->lastModified && ! isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
$if_modified_since = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
if ($this->lastModified <= $if_modified_since) {
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $this->lastModified) . ' GMT', true);
header("HTTP/1.1 304 Not Modified", true);
header('Content-Length: 0', true);
ob_end_clean();
die();
}
}
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', ($this->lastModified ? $this->lastModified : time())) . ' GMT', true);
}
}
}
}
public function getCharset() {
return $this->charset;
}
public function setCharset($charset) {
$this->charset = $charset;
}
/**
* Sets the time in seconds that the browser's cache should be
* considered out of date (through the Expires header)
*
* @param int $time time in seconds
*/
public function setCacheTime($time) {
$this->cacheTime = $time;
}
/**
* Returns the time in seconds that the browser is allowed to cache the content
*
* @return int $time
*/
public function getCacheTime() {
return $this->cacheTime;
}
/**
* Sets the content type of this request (forinstance: text/html or text/javascript, etc)
*
* @param string $type content type header to use
*/
public function setContentType($type) {
$this->contentType = $type;
}
/**
* Returns the current content type
*
* @return string content type string
*/
public function getContentType() {
return $this->contentType;
}
/**
* returns the current last modified time stamp
*
* @return int timestamp
*/
public function getLastModified() {
return $this->lastModified;
}
/**
* Sets the last modified timestamp. It automaticly checks if this timestamp
* is larger then its current timestamp, and if not ignores the call
*
* @param int $modified timestamp
*/
public function setLastModified($modified) {
$this->lastModified = max($this->lastModified, $modified);
}
/**
* Sets the noCache boolean. If its set to true, no-caching headers will be send
* (pragma no cache, expiration in the past)
*
* @param boolean $cache send no-cache headers?
*/
public function setNoCache($cache = false) {
$this->noCache = $cache;
}
/**
* returns the noCache boolean
*
* @return boolean
*/
public function getNoCache() {
return $this->noCache;
}
}