00001 <?php 00002 /** 00003 * News: I had once said that when PHP 4.0.5 comes out I will reccomend the built in 00004 * ob_gzhandler over my code unless you are generating flash or images on the fly. 00005 * 00006 * I was wrong. PHP 4.0.5 is out and ob_gzhandler doesn't work for me. 00007 * 00008 * Note: This is rather cool: http://leknor.com/code/gziped.php 00009 * It will calculate the effects of this class on a page. 00010 * compression level, cpu time, download time, etc 00011 * 00012 * Note: this may be better for some sites: 00013 * http://www.remotecommunications.com/apache/mod_gzip/ 00014 * I've read that the above doesn't work with PHP output. 00015 * 00016 * Changes compared to the upstream version: 00017 * 00018 * 2007-03-27 Oliver Hader <oh@inpublica.de> 00019 * - Fixed bug #4623: Content encoding with x-gzip not allowed 00020 * - Fixed missing comments and line formats (cleaner) 00021 * 2005-12-09 Peter Niederlag <peter@niederlag.de> 00022 * - Fixed bug #1976: PHP5 type-conversion of string 'true' and boolean 00023 * 00024 * $Id: class.gzip_encode.php 7307 2010-04-12 16:17:20Z benni $ 00025 * 00026 * @author Sandy McArthur, Jr. <leknor@leknor.com> 00027 * @deprecated since TYPO3 4.3, this function will be removed in TYPO3 4.5, we're using the "ob_gzhandler" for compression now. 00028 */ 00029 /** 00030 * [CLASS/FUNCTION INDEX of SCRIPT] 00031 * 00032 * 00033 * 00034 * 53: class gzip_encode 00035 * 193: function gzip_encode($level = 3, $debug=false, $outputCompressedSizes=false) 00036 * 268: function gzip_accepted() 00037 * 317: function get_complevel() 00038 * 342: function linux_loadavg() 00039 * 363: function freebsd_loadavg() 00040 * 00041 * TOTAL FUNCTIONS: 5 00042 * (This index is automatically created/updated by the extension "extdeveval") 00043 * 00044 */ 00045 00046 00047 00048 /** 00049 * gzip_encode - a class to gzip encode php output 00050 * 00051 * @author Sandy McArthur, Jr. <Leknor@Leknor.com> 00052 * @package TYPO3 00053 * @subpackage t3lib 00054 */ 00055 class gzip_encode { 00056 /** 00057 * gzip_encode - a class to gzip encode php output 00058 * 00059 * By Sandy McArthur, Jr. <Leknor@Leknor.com> 00060 * 00061 * Copyright 2001 (c) All Rights Reserved, All Responsibility Yours. 00062 * One very slight modification 2005 for PHP5 compatibility reasons for TYPO3 port by Peter Niederlag 00063 * 00064 * This code is released under the GNU LGPL Go read it over here: 00065 * http://www.gnu.org/copyleft/lesser.html 00066 * 00067 * I do make one optional request, I would like an account on or a 00068 * copy of where this code is used. If that is not possible then 00069 * an email would be cool. 00070 * 00071 * How to use: 00072 * 1. Output buffering has to be turned on. You can do this with ob_start() 00073 * <http://php.net/manual/function.ob-start.php> or in the php config 00074 * file. Nothing bad happens if output buffering isn't turned on, your 00075 * page just won't get compressed. 00076 * 2. Include the class file. 00077 * 3. At the _very_ end of your script create an instance of the encode 00078 * class. 00079 * 00080 * eg: 00081 * ------------Start of file---------- 00082 * |<?php 00083 * | ob_start(); 00084 * | include('class.gzip_encode.php'); 00085 * |?> 00086 * |<HTML> 00087 * |... the page ... 00088 * |</HTML> 00089 * |<?php 00090 * | new gzip_encode(); 00091 * |?> 00092 * -------------End of file----------- 00093 * 00094 * Things to note: 00095 * 1. There is no space before the beginning of the file and the '<?php ' tag 00096 * 2. The ob_start() line is optional if output buffering is turned on in 00097 * the main config file. 00098 * 3. Turning on and off output buffering just won't work. 00099 * 4. There must be nothing after the last '?>' tag at the end of the file. 00100 * Be careful of a space hiding there. 00101 * 5. There are better ways to compress served content but I think this is 00102 * the only way to compress php output. 00103 * 6. Your auto_prepend_file is a good place for the ob_start() and 00104 * your auto_append_file is a good place for new gzip_encode(). 00105 * 7. If you put new gzip_encode() in your auto.append file then you can 00106 * call ob_end_flush() in your script to disable compression. 00107 * 00108 * This was written from scratch from info freely available on the web. 00109 * 00110 * These site(s) were useful to me: 00111 * http://www.php.net/manual/ 00112 * http://www.ietf.org/rfc/rfc2616.txt (Sections: 3.5, 14.3, 14.11) 00113 * 00114 * Requirments: 00115 * PHP 4.0.1+: I use the '===' operator, and output buffering, crc32(); 00116 * zlib: Needed for the gzip encoding. (Odds are you have it) 00117 * 00118 * Benchmarks: 00119 * Take a look at http://Leknor.com/code/gziped.php and feed it a page to 00120 * get an idea of how it will preform on your data or page. 00121 * 00122 * To Do: 00123 * 1. I have reports of no content errors. I can't seem to duplicate this. 00124 * Please visit my discussion boards if you think you may be able to help 00125 * 2. The Accept-Encoding isn't handled to spec. Check out 14.3 in RFC 2616 00126 * to see how it should be done. 00127 * 00128 * Change Log: 00129 * 0.66: Big bug fix. It wouldn't compress when it should. 00130 * 0.65: Fix for PHP-4.0.5 suddenly removing the connection_timeout() function. 00131 * 0.62: Fixed a typo 00132 * 0.61: Detect file types more like described in the magic number files, also 00133 * added detection for gzip and pk zip files. 00134 * 0.6: Detect common file types that shouldn't be compressed, mainly 00135 * for images and swf (Shockwave Flash doesn't really accept gzip) 00136 * 0.53: Made gzip_accepted() method so everyone can detect if a page 00137 * will be gzip'ed with ease. 00138 * 0.52: Detection and graceful handling of improper install/missing libs 00139 * 0.51: Added FreeBSD load average detection. 00140 * 0.5: Passing true as the first parameter will try to calculate the 00141 * compression level from the server's load average. Passing true 00142 * as the second parameter will turn on debugging. 00143 * 0.4: No longer uses a temp file to compress the output. Should speed 00144 * thing up a bit and reduce wear on your hard disk. Also test if 00145 * the http headers have been sent. 00146 * 0.31: Made a small change to the tempnam() line to hopefully be more 00147 * portable. 00148 * 0.3: Added code for the 'x-gzip'. This is untested, I don't know of 00149 * any browser that uses it but the RFC said to look out for it. 00150 * 0.2: Checks for 'gzip' in the Accept-Encoding header 00151 * 0.1: First working version. 00152 * 00153 * Thanks To (Suggestions and stuff): 00154 * ?@boas.anthro.mnsu.edu http://php.net/manual/function.gzcompress.php 00155 * Kaoslord <kaoslord@chaos-productions.com> 00156 * Michael R. Gile <gilem@wsg.net> 00157 * Christian Hamm <chh@admaster.de> 00158 * 00159 * The most recent version is available at: 00160 * http://Leknor.com/code/ 00161 * 00162 */ 00163 00164 var $_version = 0.66; // Version of the gzip_encode class 00165 00166 var $level; // Compression level 00167 var $encoding; // Encoding type 00168 var $crc; // crc of the output 00169 var $size; // size of the uncompressed content 00170 var $gzsize; // size of the compressed content 00171 00172 /** 00173 * gzip_encode constructor - gzip encodes the current output buffer 00174 * if the browser supports it. 00175 * 00176 * Note: all arguments are optionial. 00177 * 00178 * You can specify one of the following for the first argument: 00179 * 0: No compression 00180 * 1: Min compression 00181 * ... Some compression (integer from 1 to 9) 00182 * 9: Max compression 00183 * true: Determin the compression level from the system load. The 00184 * higher the load the less the compression. 00185 * 00186 * You can specify one of the following for the second argument: 00187 * true: Don't actully output the compressed form but run as if it 00188 * had. Used for debugging. 00189 * 00190 * @param integer $level: Define the level of compression between 0 (none) and 9 (best compression) 00191 * @param boolean $debug: If true, no data will be outputted (default: false) 00192 * @param boolean $outputCompressedSizes: If true, the original and compressed size appended as HTML (default: false) 00193 * @return void 00194 * @deprecated since TYPO3 4.3, this function will be removed in TYPO3 4.5, we're using the "ob_gzhandler" for compression now. 00195 */ 00196 function gzip_encode($level=3, $debug=false, $outputCompressedSizes=false) { 00197 t3lib_div::logDeprecatedFunction(); 00198 00199 if (!function_exists('gzcompress')) { 00200 trigger_error('gzcompress not found, ' . 00201 'zlib needs to be installed for gzip_encode', 00202 E_USER_WARNING); 00203 return; 00204 } 00205 if (!function_exists('crc32')) { 00206 trigger_error('crc32() not found, ' . 00207 'PHP >= 4.0.1 needed for gzip_encode', E_USER_WARNING); 00208 return; 00209 } 00210 if (headers_sent()) return; 00211 if (connection_status() !== 0) return; 00212 $encoding = $this->gzip_accepted(); 00213 if (!$encoding) return; 00214 $this->encoding = $encoding; 00215 00216 if (strtolower($level) == 'true' || $level === true) { 00217 $level = $this->get_complevel(); 00218 } 00219 $this->level = $level; 00220 00221 $contents = ob_get_contents(); 00222 if ($contents === false) return; 00223 00224 $gzdata = "\x1f\x8b\x08\x00\x00\x00\x00\x00"; // gzip header 00225 00226 // By Kasper Skaarhoj, start 00227 if ($outputCompressedSizes) { 00228 $contents.=LF."<!-- Compressed, level ".$level.", original size was ".strlen($contents)." bytes. New size is ".strlen(gzcompress($contents, $level))." bytes -->"; 00229 $size = strlen($contents); // Must set again! 00230 } 00231 // By Kasper Skaarhoj, end 00232 00233 $size = strlen($contents); 00234 $crc = crc32($contents); 00235 $gzdata .= gzcompress($contents, $level); 00236 $gzdata = substr($gzdata, 0, strlen($gzdata) - 4); // fix crc bug 00237 $gzdata .= pack("V",$crc) . pack("V", $size); 00238 00239 $this->size = $size; 00240 $this->crc = $crc; 00241 $this->gzsize = strlen($gzdata); 00242 00243 if ($debug) { 00244 return; 00245 } 00246 00247 ob_end_clean(); 00248 Header('Content-Encoding: ' . $encoding); 00249 Header('Content-Length: ' . strlen($gzdata)); 00250 Header('X-Content-Encoded-By: class.gzip_encode '.$this->_version); 00251 00252 echo $gzdata; 00253 } 00254 00255 00256 /** 00257 * gzip_accepted() - Test headers for Accept-Encoding: gzip 00258 * Returns: if proper headers aren't found: false 00259 * if proper headers are found: 'gzip' or 'x-gzip' 00260 * 00261 * Tip: using this function you can test if the class will gzip the output 00262 * without actually compressing it yet, eg: 00263 * if (gzip_encode::gzip_accepted()) { 00264 * echo "Page will be gziped"; 00265 * } 00266 * note the double colon syntax, I don't know where it is documented but 00267 * somehow it got in my brain. 00268 * 00269 * @return mixed Returns 'gzip' if the client browser accepts gzip encoding, otherwise false 00270 * @deprecated since TYPO3 4.3, this function will be removed in TYPO3 4.5, we're using the "ob_gzhandler" for compression now. 00271 */ 00272 function gzip_accepted() { 00273 t3lib_div::logDeprecatedFunction(); 00274 00275 // Checks, if the accepted encoding supports gzip or x-gzip. 00276 // Furthermore a qvalue check is done. "gzip;q=0" means no gzip accepted at all. 00277 $acceptEncoding = t3lib_div::getIndpEnv('HTTP_ACCEPT_ENCODING'); 00278 if (preg_match('/(^|,\s*)(x-)?gzip(;q=(\d(\.\d+)?))?(,|$)/i', $acceptEncoding, $match) && ($match[4] === '' || $match[4] > 0)) { 00279 $encoding = 'gzip'; 00280 } else { 00281 return false; 00282 } 00283 00284 // Test file type. I wish I could get HTTP response headers. 00285 $magic = substr(ob_get_contents(),0,4); 00286 if (substr($magic,0,2) === '^_') { 00287 // gzip data 00288 $encoding = false; 00289 } else if (substr($magic,0,3) === 'GIF') { 00290 // gif images 00291 $encoding = false; 00292 } else if (substr($magic,0,2) === "\xFF\xD8") { 00293 // jpeg images 00294 $encoding = false; 00295 } else if (substr($magic,0,4) === "\x89PNG") { 00296 // png images 00297 $encoding = false; 00298 } else if (substr($magic,0,3) === 'FWS') { 00299 // Don't gzip Shockwave Flash files. Flash on windows incorrectly 00300 // claims it accepts gzip'd content. 00301 $encoding = false; 00302 } else if (substr($magic,0,2) === 'PK') { 00303 // pk zip file 00304 $encoding = false; 00305 } 00306 00307 return $encoding; 00308 } 00309 00310 /** 00311 * get_complevel() - The level of compression we should use. 00312 * 00313 * Returns an int between 0 and 9 inclusive. 00314 * 00315 * Tip: $gzleve = gzip_encode::get_complevel(); to get the compression level 00316 * that will be used with out actually compressing the output. 00317 * 00318 * Help: if you use an OS other then linux please send me code to make 00319 * this work with your OS - Thanks 00320 * 00321 * @return integer Suggests a level of compression (0..9) for the current situation 00322 * @deprecated since TYPO3 4.3, this function will be removed in TYPO3 4.5, we're using the "ob_gzhandler" for compression now. 00323 */ 00324 function get_complevel() { 00325 t3lib_div::logDeprecatedFunction(); 00326 00327 $uname = posix_uname(); 00328 switch ($uname['sysname']) { 00329 case 'Linux': 00330 $cl = (1 - $this->linux_loadavg()) * 10; 00331 $level = (int)max(min(9, $cl), 0); 00332 break; 00333 case 'FreeBSD': 00334 $cl = (1 - $this->freebsd_loadavg()) * 10; 00335 $level = (int)max(min(9, $cl), 0); 00336 break; 00337 default: 00338 $level = 3; 00339 break; 00340 } 00341 return $level; 00342 } 00343 00344 /** 00345 * linux_loadavg() - Gets the max() system load average from /proc/loadavg 00346 * 00347 * The max() Load Average will be returned 00348 * 00349 * @return float Returns the current load average 00350 * @deprecated since TYPO3 4.3, this function will be removed in TYPO3 4.5, we're using the "ob_gzhandler" for compression now. 00351 */ 00352 function linux_loadavg() { 00353 t3lib_div::logDeprecatedFunction(); 00354 00355 $buffer = '0 0 0'; 00356 $f = @fopen('/proc/loadavg', 'rb'); 00357 if ($f) { 00358 if (!feof($f)) { 00359 $buffer = fgets($f, 1024); 00360 } 00361 fclose($f); 00362 } 00363 $load = explode(' ', $buffer); 00364 return max((float)$load[0], (float)$load[1], (float)$load[2]); 00365 } 00366 00367 /** 00368 * freebsd_loadavg() - Gets the max() system load average from uname(1) 00369 * 00370 * The max() Load Average will be returned 00371 * 00372 * I've been told the code below will work on solaris too, anyone wanna 00373 * test it? 00374 * 00375 * @return float Returns the current load average 00376 * @deprecated since TYPO3 4.3, this function will be removed in TYPO3 4.5, we're using the "ob_gzhandler" for compression now. 00377 */ 00378 function freebsd_loadavg() { 00379 t3lib_div::logDeprecatedFunction(); 00380 00381 $buffer= `uptime`; 00382 $load = array(); 00383 preg_match('/averag(es|e): ([0-9][.][0-9][0-9]), ([0-9][.][0-9][0-9]), ([0-9][.][0-9][0-9]*)/', $buffer, $load); 00384 00385 return max((float)$load[2], (float)$load[3], (float)$load[4]); 00386 } 00387 } 00388 00389 ?>
1.4.7