]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/pear/Cache/OutputCompression.php
Update to PEAR Cache-1.5.6
[SourceForge/phpwiki.git] / lib / pear / Cache / OutputCompression.php
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
19 require_once 'Cache/Output.php';
20
21 /**
22 * Cache using Output Buffering and contnet (gz) compression.
23 ** Usage example:
24 *
25 *  // place this somewhere in a central config file
26 *  define(CACHE_STORAGE_CLASS, 'file');
27 *  // file storage needs a dir to put the cache files
28 *  define(CACHE_DIR, '/var/tmp/');
29 *
30 *  // get a cache object
31 *  $cache = new Cache_Output(CACHE_STORAGE_CLASS, array('cache_dir' => CACHE_DIR));
32 *
33 *  if (!($content = $cache->start($cache->generateID($REQUEST_URI)))) {
34 *    print "hello world";
35 *    $cache->endPrint(+1000);
36 *  }
37 *  else {
38 *    $cache->printContent();
39 *  }
40 *
41 *   OR
42 *
43 *  if (($content = $cache->start($cache->generateID($REQUEST_URI)))) {
44 *    $cache->printContent();
45 *    die();
46 *  }
47 *    print "hello world";
48 *    $cache->endPrint(+1000);
49 *
50 *
51 * Based upon a case study from Christian Stocker and inspired by jpcache.
52 *
53 * @version  $Id: OutputCompression.php 178289 2005-01-26 09:47:28Z dufuz $
54 * @author   Ulf Wendel <ulf.wendel@phpdoc.de>, Christian Stocker <chregu@phant.ch>
55 * @access   public
56 * @package  Cache
57 */
58 class Cache_OutputCompression extends Cache_Output
59 {
60     
61     /**
62     * Encoding, what the user (its browser) of your website accepts
63     * 
64     * "auto" stands for test using $_SERVER['HTTP_ACCEPT_ENCODING']($HTTP_ACCEPT_ENCODING).
65     *
66     * @var  string
67     * @see  Cache_OutputCompression(), setEncoding()
68     */
69     var $encoding = 'auto';
70  
71     
72     /**
73     * Method used for compression
74     *
75     * @var  string
76     * @see  isCompressed()
77     */ 
78     var $compression = '';
79
80     
81     /**
82     * Sets the storage details and the content encoding used (if not autodetection)
83     * 
84     * @param    string  Name of container class
85     * @param    array   Array with container class options
86     * @param    string  content encoding mode - auto => test which encoding the user accepts
87     */    
88     function Cache_OutputCompression($container, $container_options = '', $encoding = 'auto')
89     {
90         $this->setEncoding($encoding);
91         $this->Cache($container, $container_options);
92         
93     } // end constructor
94
95     
96     /**
97     * Call parent deconstructor.
98     */
99     function _Cache_OutputCompression()
100     {
101         $this->_Cache();
102     } // end deconstructor
103     
104
105     function generateID($variable)
106     {
107         $this->compression = $this->getEncoding();
108         return md5(serialize($variable) . serialize($this->compression));
109     } // end generateID
110
111     
112     function get($id, $group)
113     {
114         $this->content = '';
115         
116         if (!$this->caching) {
117             return '';
118         }
119
120         if ($this->isCached($id, $group) && !$this->isExpired($id, $group)) {
121             $this->content = $this->load($id, $group);
122         }
123         return $this->content;
124     } // end func get
125     
126     
127     /**
128     * Stops the output buffering, saves it to the cache and returns the _compressed_ content. 
129     *
130     * If you need the uncompressed content for further procession before
131     * it's saved in the cache use endGet(). endGet() does _not compress_.
132     */    
133     function end($expire = 0, $userdata = '')
134     {
135         $content = ob_get_contents();
136         ob_end_clean();
137
138         // store in the cache
139         if ($this->caching) {
140             $this->extSave($this->output_id, $content, $userdata, $expire, $this->output_group);
141             return $this->content;                
142         }
143             
144         return $content;        
145     } // end func end()
146     
147     
148     function endPrint($expire = 0, $userdata = '')
149     {
150         $this->printContent($this->end($expire, $userdata));
151     } // end func endPrint
152
153     
154     /**
155     * Saves the given data to the cache.
156     * 
157     */   
158     function extSave($id, $cachedata, $userdata, $expires = 0, $group = 'default')
159     {
160         if (!$this->caching) {
161             return true;
162         }
163
164         if ($this->compression) {
165             $len = strlen($cachedata);            
166             $crc = crc32($cachedata);
167             $cachedata = gzcompress($cachedata, 9);
168             $this->content = substr($cachedata, 0, strlen($cachedata) - 4) . pack('V', $crc) . pack('V', $len);
169         } else {
170             $this->content = $cachedata;
171         }
172         return $this->container->save($id, $this->content, $expires, $group, $userdata);
173     } // end func extSave
174     
175     /**
176     * Sends the compressed data to the user.
177     * 
178     * @param    string
179     * @access   public
180     */    
181     function printContent($content = '')
182     {
183         $server = &$this->_importGlobalVariable("server");
184
185         if ($content == '') {
186             $content = &$this->container->cachedata;
187         }
188
189         if ($this->compression && $this->caching) {
190             $etag = '"PEAR-Cache-' . md5(substr($content, -40)) .'"';
191             header("ETag: $etag");
192             if (isset($server['HTTP_IF_NONE_MATCH']) && strstr(stripslashes($server['HTTP_IF_NONE_MATCH']), $etag)) {
193                 // not modified
194                 header('HTTP/1.0 304');
195                 return;
196             } else {
197                 // client acceppts some encoding - send headers & data
198                 header("Content-Encoding: {$this->compression}");
199                 header('Vary: Accept-Encoding');
200                 print "\x1f\x8b\x08\x00\x00\x00\x00\x00";
201             }
202         
203         }
204         
205         die($content);
206     } // end func printContent
207     
208     
209     /**
210     * Returns the encoding method of the current dataset. 
211     *
212     * @access   public
213     * @return   string  Empty string (which evaluates to false) means no compression
214     */
215     function isCompressed()
216     {
217         return $this->compression;
218     } // end func isCompressed
219
220     /**
221     * Sets the encoding to be used.
222     * 
223     * @param    string  "auto" means autodetect for every client
224     * @access   public
225     * @see      $encoding
226     */
227     function setEncoding($encoding = 'auto')
228     {
229         $this->encoding = $encoding;
230     } // end func setEncoding
231     
232     
233     /**
234     * Returns the encoding to be used for the data transmission to the client.
235     *
236     * @see      setEncoding()
237     */    
238     function getEncoding()
239     {
240         $server = &$this->_importGlobalVariable("server");
241
242         // encoding set by user    
243         if ('auto' != $this->encoding) {
244             return $this->encoding;
245         }
246         // check what the client accepts
247         if (false !== strpos($server['HTTP_ACCEPT_ENCODING'], 'x-gzip')) {
248             return 'x-gzip';
249         }
250         if (false !== strpos($server['HTTP_ACCEPT_ENCODING'], 'gzip')) {
251             return 'gzip';
252         }
253         // no compression
254         return '';
255         
256     } // end func getEncoding
257
258     // {{{ _importGlobalVariable()
259
260     /**
261      * Import variables from special namespaces.
262      *
263      * @access private
264      * @param string Type of variable (server, session, post)
265      * @return array
266      */
267     function &_importGlobalVariable($variable) 
268     {
269       
270         $var = null;
271
272         switch (strtolower($variable)) {
273
274             case 'server':
275                 if (isset($_SERVER)) {
276                     $var = &$_SERVER;
277                 } else {
278                     $var = &$GLOBALS['HTTP_SERVER_VARS'];
279                 }
280                 break;
281
282             case 'session':
283                 if (isset($_SESSION)) {
284                     $var = &$_SESSION;
285                 } else {
286                     $var = &$GLOBALS['HTTP_SESSION_VARS'];
287                 }
288                 break;
289
290             case 'post':
291                 if (isset($_POST)) {
292                     $var = &$_POST;
293                 } else {
294                     $var = &$GLOBALS['HTTP_POST_VARS'];
295                 }
296                 break;
297
298             default:
299                 break;
300
301         }
302
303         return $var;
304     } 
305
306     // }}
307 } // end class OutputCompression
308 ?>