PageRenderTime 45ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/inc/Cache/OutputCompression.php

https://github.com/chregu/fluxcms
PHP | 301 lines | 115 code | 60 blank | 126 comment | 25 complexity | 51f6e13d27f115a573b89fde57a1ac67 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, Apache-2.0, LGPL-2.1
  1. <?php
  2. // +----------------------------------------------------------------------+
  3. // | PEAR :: Cache |
  4. // +----------------------------------------------------------------------+
  5. // | Copyright (c) 1997-2003 The PHP Group |
  6. // +----------------------------------------------------------------------+
  7. // | This source file is subject to version 2.0 of the PHP license, |
  8. // | that is bundled with this package in the file LICENSE, and is |
  9. // | available at through the world-wide-web at |
  10. // | http://www.php.net/license/2_02.txt. |
  11. // | If you did not receive a copy of the PHP license and are unable to |
  12. // | obtain it through the world-wide-web, please send a note to |
  13. // | license@php.net so we can mail you a copy immediately. |
  14. // +----------------------------------------------------------------------+
  15. // | Authors: Ulf Wendel <ulf.wendel@phpdoc.de> |
  16. // | Christian Stocker <chregu@phant.ch> |
  17. // +----------------------------------------------------------------------+
  18. require_once 'Cache/Output.php';
  19. /**
  20. * Cache using Output Buffering and contnet (gz) compression.
  21. ** Usage example:
  22. *
  23. * // place this somewhere in a central config file
  24. * define(CACHE_STORAGE_CLASS, 'file');
  25. * // file storage needs a dir to put the cache files
  26. * define(CACHE_DIR, '/var/tmp/');
  27. *
  28. * // get a cache object
  29. * $cache = new Cache_Output(CACHE_STORAGE_CLASS, array('cache_dir' => CACHE_DIR));
  30. *
  31. * if (!($content = $cache->start($cache->generateID($REQUEST_URI)))) {
  32. * print "hello world";
  33. * $cache->endPrint(+1000);
  34. * }
  35. * else {
  36. * $cache->printContent();
  37. * }
  38. *
  39. * OR
  40. *
  41. * if (($content = $cache->start($cache->generateID($REQUEST_URI)))) {
  42. * $cache->printContent();
  43. * die();
  44. * }
  45. * print "hello world";
  46. * $cache->endPrint(+1000);
  47. *
  48. *
  49. * Based upon a case study from Christian Stocker and inspired by jpcache.
  50. *
  51. * @version $Id$
  52. * @author Ulf Wendel <ulf.wendel@phpdoc.de>, Christian Stocker <chregu@phant.ch>
  53. * @access public
  54. * @package Cache
  55. */
  56. class Cache_OutputCompression extends Cache_Output {
  57. /**
  58. * Encoding, what the user (its browser) of your website accepts
  59. *
  60. * "auto" stands for test using $_SERVER['HTTP_ACCEPT_ENCODING']($HTTP_ACCEPT_ENCODING).
  61. *
  62. * @var string
  63. * @see Cache_OutputCompression(), setEncoding()
  64. */
  65. var $encoding = 'auto';
  66. /**
  67. * Method used for compression
  68. *
  69. * @var string
  70. * @see isCompressed()
  71. */
  72. var $compression = '';
  73. /**
  74. * Sets the storage details and the content encoding used (if not autodetection)
  75. *
  76. * @param string Name of container class
  77. * @param array Array with container class options
  78. * @param string content encoding mode - auto => test which encoding the user accepts
  79. */
  80. function Cache_OutputCompression($container, $container_options = '', $encoding = 'auto') {
  81. $this->setEncoding($encoding);
  82. $this->Cache($container, $container_options);
  83. } // end constructor
  84. /**
  85. * Call parent deconstructor.
  86. */
  87. function _Cache_OutputCompression() {
  88. $this->_Cache();
  89. } // end deconstructor
  90. function generateID($variable) {
  91. $this->compression = $this->getEncoding();
  92. return md5(serialize($variable) . serialize($this->compression));
  93. } // end generateID
  94. function get($id, $group) {
  95. $this->content = '';
  96. if (!$this->caching)
  97. return '';
  98. if ($this->isCached($id, $group) && !$this->isExpired($id, $group))
  99. $this->content = $this->load($id, $group);
  100. return $this->content;
  101. } // end func get
  102. /**
  103. * Stops the output buffering, saves it to the cache and returns the _compressed_ content.
  104. *
  105. * If you need the uncompressed content for further procession before
  106. * it's saved in the cache use endGet(). endGet() does _not compress_.
  107. */
  108. function end($expire = 0, $userdata = '') {
  109. $content = ob_get_contents();
  110. ob_end_clean();
  111. // store in the cache
  112. if ($this->caching) {
  113. $this->extSave($this->output_id, $content, $userdata, $expire, $this->output_group);
  114. return $this->content;
  115. }
  116. return $content;
  117. } // end func end()
  118. function endPrint($expire = 0, $userdata = '') {
  119. $this->printContent($this->end($expire, $userdata));
  120. } // end func endPrint
  121. /**
  122. * Saves the given data to the cache.
  123. *
  124. */
  125. function extSave($id, $cachedata, $userdata, $expires = 0, $group = 'default') {
  126. if (!$this->caching)
  127. return true;
  128. if ($this->compression) {
  129. $len = strlen($cachedata);
  130. $crc = crc32($cachedata);
  131. $cachedata = gzcompress($cachedata, 9);
  132. $this->content = substr($cachedata, 0, strlen($cachedata) - 4) . pack('V', $crc) . pack('V', $len);
  133. } else {
  134. $this->content = $cachedata;
  135. }
  136. return $this->container->save($id, $this->content, $expires, $group, $userdata);
  137. } // end func extSave
  138. /**
  139. * Sends the compressed data to the user.
  140. *
  141. * @param string
  142. * @access public
  143. */
  144. function printContent($content = '') {
  145. $server = &$this->_importGlobalVariable("server");
  146. if ('' == $content)
  147. $content = &$this->container->cachedata;
  148. if ($this->compression && $this->caching) {
  149. $etag = 'PEAR-Cache-' . md5(substr($content, -40));
  150. header("ETag: $etag");
  151. if (isset($server['HTTP_IF_NONE_MATCH']) && strstr(stripslashes($server['HTTP_IF_NONE_MATCH']), $etag)) {
  152. // not modified
  153. header('HTTP/1.0 304');
  154. return;
  155. } else {
  156. // client acceppts some encoding - send headers & data
  157. header("Content-Encoding: {$this->compression}");
  158. header('Vary: Accept-Encoding');
  159. print "\x1f\x8b\x08\x00\x00\x00\x00\x00";
  160. }
  161. }
  162. die($content);
  163. } // end func printContent
  164. /**
  165. * Returns the encoding method of the current dataset.
  166. *
  167. * @access public
  168. * @return string Empty string (which evaluates to false) means no compression
  169. */
  170. function isCompressed() {
  171. return $this->compression;
  172. } // end func isCompressed
  173. /**
  174. * Sets the encoding to be used.
  175. *
  176. * @param string "auto" means autodetect for every client
  177. * @access public
  178. * @see $encoding
  179. */
  180. function setEncoding($encoding = 'auto') {
  181. $this->encoding = $encoding;
  182. } // end func setEncoding
  183. /**
  184. * Returns the encoding to be used for the data transmission to the client.
  185. *
  186. * @see setEncoding()
  187. */
  188. function getEncoding() {
  189. $server = &$this->_importGlobalVariable("server");
  190. // encoding set by user
  191. if ('auto' != $this->encoding)
  192. return $this->encoding;
  193. // check what the client accepts
  194. if (false !== strpos($server['HTTP_ACCEPT_ENCODING'], 'x-gzip'))
  195. return 'x-gzip';
  196. if (false !== strpos($server['HTTP_ACCEPT_ENCODING'], 'gzip'))
  197. return 'gzip';
  198. // no compression
  199. return '';
  200. } // end func getEncoding
  201. // {{{ _importGlobalVariable()
  202. /**
  203. * Import variables from special namespaces.
  204. *
  205. * @access private
  206. * @param string Type of variable (server, session, post)
  207. * @return array
  208. */
  209. function &_importGlobalVariable($variable)
  210. {
  211. $var = null;
  212. switch (strtolower($variable)) {
  213. case "server" :
  214. if (isset($_SERVER)) {
  215. $var = &$_SERVER;
  216. } else {
  217. $var = &$GLOBALS['HTTP_SERVER_VARS'];
  218. }
  219. break;
  220. case "session" :
  221. if (isset($_SESSION)) {
  222. $var = &$_SESSION;
  223. } else {
  224. $var = &$GLOBALS['HTTP_SESSION_VARS'];
  225. }
  226. break;
  227. case "post" :
  228. if (isset($_POST)) {
  229. $var = &$_POST;
  230. } else {
  231. $var = &$GLOBALS['HTTP_POST_VARS'];
  232. }
  233. break;
  234. default:
  235. break;
  236. }
  237. return $var;
  238. }
  239. // }}
  240. } // end class OutputCompression
  241. ?>