cvs: php4 /pear/Experimental/Cache OutputCompression.php
| From: | Ulf Wendel | Date: | Sun, 22 Apr 2001 17:25:12 +0000 |
| Subject: | cvs: php4 /pear/Experimental/Cache OutputCompression.php | ||
| Groups: | php.pear.cvs | ||
| Request: | Send a blank email to pear-cvs+get-73@lists.php.net to get a copy of this message | ||
uw Sun Apr 22 10:25:12 2001 EDT
Added files:
/php4/pear/Experimental/Cache OutputCompression.php
Log:
Added experimental class that deliveres compressed (gz) content to the client
Although this code seems to be working Christian and I are not 100% satisfied
with it. We're wondering if there's another API that requires less overriden
methods, so we decided to put it into the Experimental directory requesting
comments.
Index: php4/pear/Experimental/Cache/OutputCompression.php +++ php4/pear/Experimental/Cache/OutputCompression.php <?php // +----------------------------------------------------------------------+ // | PHP version 4.0 | // +----------------------------------------------------------------------+ // | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group | // +----------------------------------------------------------------------+ // | This source file is subject to version 2.0 of the PHP license, | // | that is bundled with this package in the file LICENSE, and is | // | available at through the world-wide-web at | // | http://www.php.net/license/2_02.txt. | // | If you did not receive a copy of the PHP license and are unable to | // | obtain it through the world-wide-web, please send a note to | // | license@php.net so we can mail you a copy immediately. | // +----------------------------------------------------------------------+ // | Authors: Ulf Wendel <ulf.wendel@phpdoc.de> | // | Christian Stocker <chregu@nomad.ch> | // +----------------------------------------------------------------------+ require_once 'Cache/Output.php'; /** * Cache using Output Buffering and contnet (gz) compression. * * Based upon a case study from Christian Stocker and inspired by jpcache. * * @version $Id: OutputCompression.php,v 1.1 2001/04/22 17:25:12 uw Exp $ * @author Ulf Wendel <ulf.wendel@phpdoc.de>, Christian Stocker <chregu@nomad.ch> * @access public * @package Cache */ class Cache_OutputCompression extends Cache_Output { /** * Encoding the user of your website (it's browser) accepts * * "auto" stands for test using $HTTP_ACCEPT_ENCODING. * * @var string * @see Cache_OutputCompression(), setEncoding() */ var $encoding = "auto"; /** * Method used for compression * * @var string * @see isCompressed() */ var $compression = ""; /** * Sets the storage details and the content encoding used (if not autodetection) * * @param string name of the storage container to use * @param array storage container options * @param string content encoding mode - auto => test which encoding the user accepts */ function Cache_OutputCompression($storage_driver, $storage_options = "", $encoding = "auto") { $this->setEncoding($encoding); $this->Cache($storage_driver, $storage_options); } // end constructor /** * Call parent deconstructor. */ function _Cache_OutputCompression() { $this->_Cache(); } // end deconstructor function generateID($variable) { $this->compression = $this->getEncoding(); return md5(serialize($variable) . serialize($this->compression)); } // end generateID function get($id, $group) { $this->content = ""; if ($this->no_cache) return ""; if ($this->isCached($id, $group) && !$this->isExired($id, $group)) $this->content = $this->load($id, $group); return $this->content; } // end func get /** * Stops the output buffering, saves it to the cache and returns the _compressed_ content. * * If you need the uncomporssed content for further procession before * it's saved in the cache use endGet(). endGet() does _not compress_. */ function end($expire = 0, $userdata = "") { $content = ob_get_contents(); ob_end_clean(); // store in the cache if (!$this->no_cache) { $this->extSave($this->output_id, $content, $userdata, $expire, $this->output_group); return $this->content; } return $content; } // end func end() function endPrint($expire = 0, $userdata = "") { $this->printContent($this->end($expire, $userdata)); } // end func endPrint /** * Saves the given data to the cache. * * Your data does not get saved 1 by 1 in the cache, it's hidden * within an array with other required data fields. Both start() and * get() know about this fact and extract the data * from the hash before returning it to you. * */ function save($id, $data, $expires = 0, $group = "default") { if ($this->no_cache) return true; return $this->extSave($id, $data, "", $expires, $group); } // end func save /** * Saves the given data to the cache. * * Your data does not get saved 1 by 1 in the cache, it's hidden * within an array with other required data fields. Both start() and * get() know about this fact and extract the data * from the hash before returning it to you. * */ function extSave($id, $cachedata, $userdata, $expires = 0, $group = "default") { if ($this->no_cache) return true; if ($this->compression) { $len = strlen($cachedata); $crc = crc32($cachedata); $cachedata = gzcompress($cachedata, 9); $this->content = substr($cachedata, 0, strlen($cachedata) - 4) . pack("V", $crc) . pack("V", $len); } else { $this->content = $cachedata; } return $this->container->save($id, $this->content, $expires, $group, $userdata); } // end func extSave /** * Sends the compressed data to the user. * * @param string * @access public * @global $HTTP_SERVER_VARS */ function printContent($content = "") { global $HTTP_SERVER_VARS; if ("" == $content) $content = &$this->content; if ($this->compression) { $etag = 'PEAR-Cache-' . md5(substr($content, -40)); header("ETag: $etag"); if (strstr(stripslashes($HTTP_SERVER_VARS["HTTP_IF_NONE_MATCH"]), $etag)) { // not modified header("HTTP/1.0 304"); return; } else { // client acceppts some encoding - send headers & data header("Content-Encoding: {$this->compression}"); header("Vary: Accept-Encoding"); print "\x1f\x8b\x08\x00\x00\x00\x00\x00"; } } print $content; } // end func printContent /** * Returns the encoding method of the current dataset. * * @access public * @return string Empty string (which evaluates to false) means no compression */ function isCompressed() { return $this->compression; } // end func isCompressed /** * Sets the encoding to be used. * * @param string "auto" means autodetect for every client * @access public * @see $encoding */ function setEncoding($encoding = "auto") { $this->encoding = $encoding; } // end func setEncoding /** * Returns the encoding to be used for the data transmission to the client. * * @global $HTTP_ACCEPT_ENCODING * @see setEncoding() */ function getEncoding() { global $HTTP_ACCEPT_ENCODING; // can't send headers any more if (headers_sent() || connection_timeout() || connection_aborted()) return ""; // encoding set by user if ("auto" != $this->encoding) return $this->encoding; // check what the client accepts if (false !== strpos($HTTP_ACCEPT_ENCODING, "x-gzip")) return "x-gzip"; if (false !== strpos($HTTP_ACCEPT_ENCODING, "gzip")) return "gzip"; // no compression return ""; } // end func getEncoding } // end class OutputCompression ?>
Index: php4/pear/Experimental/Cache/OutputCompression.php +++ php4/pear/Experimental/Cache/OutputCompression.php <?php // +----------------------------------------------------------------------+ // | PHP version 4.0 | // +----------------------------------------------------------------------+ // | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group | // +----------------------------------------------------------------------+ // | This source file is subject to version 2.0 of the PHP license, | // | that is bundled with this package in the file LICENSE, and is | // | available at through the world-wide-web at | // | http://www.php.net/license/2_02.txt. | // | If you did not receive a copy of the PHP license and are unable to | // | obtain it through the world-wide-web, please send a note to | // | license@php.net so we can mail you a copy immediately. | // +----------------------------------------------------------------------+ // | Authors: Ulf Wendel <ulf.wendel@phpdoc.de> | // | Christian Stocker <chregu@nomad.ch> | // +----------------------------------------------------------------------+ require_once 'Cache/Output.php'; /** * Cache using Output Buffering and contnet (gz) compression. * * Based upon a case study from Christian Stocker and inspired by jpcache. * * @version $Id: OutputCompression.php,v 1.1 2001/04/22 17:25:12 uw Exp $ * @author Ulf Wendel <ulf.wendel@phpdoc.de>, Christian Stocker <chregu@nomad.ch> * @access public * @package Cache */ class Cache_OutputCompression extends Cache_Output { /** * Encoding the user of your website (it's browser) accepts * * "auto" stands for test using $HTTP_ACCEPT_ENCODING. * * @var string * @see Cache_OutputCompression(), setEncoding() */ var $encoding = "auto"; /** * Method used for compression * * @var string * @see isCompressed() */ var $compression = ""; /** * Sets the storage details and the content encoding used (if not autodetection) * * @param string name of the storage container to use * @param array storage container options * @param string content encoding mode - auto => test which encoding the user accepts */ function Cache_OutputCompression($storage_driver, $storage_options = "", $encoding = "auto") { $this->setEncoding($encoding); $this->Cache($storage_driver, $storage_options); } // end constructor /** * Call parent deconstructor. */ function _Cache_OutputCompression() { $this->_Cache(); } // end deconstructor function generateID($variable) { $this->compression = $this->getEncoding(); return md5(serialize($variable) . serialize($this->compression)); } // end generateID function get($id, $group) { $this->content = ""; if ($this->no_cache) return ""; if ($this->isCached($id, $group) && !$this->isExired($id, $group)) $this->content = $this->load($id, $group); return $this->content; } // end func get /** * Stops the output buffering, saves it to the cache and returns the _compressed_ content. * * If you need the uncomporssed content for further procession before * it's saved in the cache use endGet(). endGet() does _not compress_. */ function end($expire = 0, $userdata = "") { $content = ob_get_contents(); ob_end_clean(); // store in the cache if (!$this->no_cache) { $this->extSave($this->output_id, $content, $userdata, $expire, $this->output_group); return $this->content; } return $content; } // end func end() function endPrint($expire = 0, $userdata = "") { $this->printContent($this->end($expire, $userdata)); } // end func endPrint /** * Saves the given data to the cache. * * Your data does not get saved 1 by 1 in the cache, it's hidden * within an array with other required data fields. Both start() and * get() know about this fact and extract the data * from the hash before returning it to you. * */ function save($id, $data, $expires = 0, $group = "default") { if ($this->no_cache) return true; return $this->extSave($id, $data, "", $expires, $group); } // end func save /** * Saves the given data to the cache. * * Your data does not get saved 1 by 1 in the cache, it's hidden * within an array with other required data fields. Both start() and * get() know about this fact and extract the data * from the hash before returning it to you. * */ function extSave($id, $cachedata, $userdata, $expires = 0, $group = "default") { if ($this->no_cache) return true; if ($this->compression) { $len = strlen($cachedata); $crc = crc32($cachedata); $cachedata = gzcompress($cachedata, 9); $this->content = substr($cachedata, 0, strlen($cachedata) - 4) . pack("V", $crc) . pack("V", $len); } else { $this->content = $cachedata; } return $this->container->save($id, $this->content, $expires, $group, $userdata); } // end func extSave /** * Sends the compressed data to the user. * * @param string * @access public * @global $HTTP_SERVER_VARS */ function printContent($content = "") { global $HTTP_SERVER_VARS; if ("" == $content) $content = &$this->content; if ($this->compression) { $etag = 'PEAR-Cache-' . md5(substr($content, -40)); header("ETag: $etag"); if (strstr(stripslashes($HTTP_SERVER_VARS["HTTP_IF_NONE_MATCH"]), $etag)) { // not modified header("HTTP/1.0 304"); return; } else { // client acceppts some encoding - send headers & data header("Content-Encoding: {$this->compression}"); header("Vary: Accept-Encoding"); print "\x1f\x8b\x08\x00\x00\x00\x00\x00"; } } print $content; } // end func printContent /** * Returns the encoding method of the current dataset. * * @access public * @return string Empty string (which evaluates to false) means no compression */ function isCompressed() { return $this->compression; } // end func isCompressed /** * Sets the encoding to be used. * * @param string "auto" means autodetect for every client * @access public * @see $encoding */ function setEncoding($encoding = "auto") { $this->encoding = $encoding; } // end func setEncoding /** * Returns the encoding to be used for the data transmission to the client. * * @global $HTTP_ACCEPT_ENCODING * @see setEncoding() */ function getEncoding() { global $HTTP_ACCEPT_ENCODING; // can't send headers any more if (headers_sent() || connection_timeout() || connection_aborted()) return ""; // encoding set by user if ("auto" != $this->encoding) return $this->encoding; // check what the client accepts if (false !== strpos($HTTP_ACCEPT_ENCODING, "x-gzip")) return "x-gzip"; if (false !== strpos($HTTP_ACCEPT_ENCODING, "gzip")) return "gzip"; // no compression return ""; } // end func getEncoding } // end class OutputCompression ?>