Documentation TYPO3 par Ameos |
00001 <?php 00002 00003 // News: I had once said that when PHP4.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. PHP4.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 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 class gzip_encode { 00017 /* 00018 * gzip_encode - a class to gzip encode php output 00019 * 00020 * By Sandy McArthur, Jr. <Leknor@Leknor.com> 00021 * 00022 * Copyright 2001 (c) All Rights Reserved, All Responsibility Yours. 00023 * 00024 * This code is released under the GNU LGPL Go read it over here: 00025 * http://www.gnu.org/copyleft/lesser.html 00026 * 00027 * I do make one optional request, I would like an account on or a 00028 * copy of where this code is used. If that is not possible then 00029 * an email would be cool. 00030 * 00031 * How to use: 00032 * 1. Output buffering has to be turned on. You can do this with ob_start() 00033 * <http://php.net/manual/function.ob-start.php> or in the php config 00034 * file. Nothing bad happens if output buffering isn't turned on, your 00035 * page just won't get compressed. 00036 * 2. Include the class file. 00037 * 3. At the _very_ end of your script create an instance of the encode 00038 * class. 00039 * 00040 * eg: 00041 * ------------Start of file---------- 00042 * |<?php 00043 * | ob_start(); 00044 * | include('class.gzip_encode.php'); 00045 * |?> 00046 * |<HTML> 00047 * |... the page ... 00048 * |</HTML> 00049 * |<?php 00050 * | new gzip_encode(); 00051 * |?> 00052 * -------------End of file----------- 00053 * 00054 * Things to note: 00055 * 1. There is no space before the beginning of the file and the '<?php ' tag 00056 * 2. The ob_start() line is optional if output buffering is turned on in 00057 * the main config file. 00058 * 3. Turning on and off output buffering just won't work. 00059 * 4. There must be nothing after the last '?>' tag at the end of the file. 00060 * Be careful of a space hiding there. 00061 * 5. There are better ways to compress served content but I think this is 00062 * the only way to compress php output. 00063 * 6. Your auto_prepend_file is a good place for the ob_start() and 00064 * your auto_append_file is a good place for new gzip_encode(). 00065 * 7. If you put new gzip_encode() in your auto.append file then you can 00066 * call ob_end_flush() in your script to disable compression. 00067 * 00068 * This was written from scratch from info freely available on the web. 00069 * 00070 * These site(s) were useful to me: 00071 * http://www.php.net/manual/ 00072 * http://www.ietf.org/rfc/rfc2616.txt (Sections: 3.5, 14.3, 14.11) 00073 * 00074 * Requirments: 00075 * PHP 4.0.1+: I use the '===' operator, and output buffering, crc32(); 00076 * zlib: Needed for the gzip encoding. (Odds are you have it) 00077 * 00078 * Benchmarks: 00079 * Take a look at http://Leknor.com/code/gziped.php and feed it a page to 00080 * get an idea of how it will preform on your data or page. 00081 * 00082 * To Do: 00083 * 1. I have reports of no content errors. I can't seem to duplicate this. 00084 * Please visit my discussion boards if you think you may be able to help 00085 * 2. The Accept-Encoding isn't handled to spec. Check out 14.3 in RFC 2616 00086 * to see how it should be done. 00087 * 00088 * Change Log: 00089 * 0.66: Big bug fix. It wouldn't compress when it should. 00090 * 0.65: Fix for PHP-4.0.5 suddenly removing the connection_timeout() function. 00091 * 0.62: Fixed a typo 00092 * 0.61: Detect file types more like described in the magic number files, also 00093 * added detection for gzip and pk zip files. 00094 * 0.6: Detect common file types that shouldn't be compressed, mainly 00095 * for images and swf (Shockwave Flash doesn't really accept gzip) 00096 * 0.53: Made gzip_accepted() method so everyone can detect if a page 00097 * will be gzip'ed with ease. 00098 * 0.52: Detection and graceful handling of improper install/missing libs 00099 * 0.51: Added FreeBSD load average detection. 00100 * 0.5: Passing true as the first parameter will try to calculate the 00101 * compression level from the server's load average. Passing true 00102 * as the second parameter will turn on debugging. 00103 * 0.4: No longer uses a temp file to compress the output. Should speed 00104 * thing up a bit and reduce wear on your hard disk. Also test if 00105 * the http headers have been sent. 00106 * 0.31: Made a small change to the tempnam() line to hopefully be more 00107 * portable. 00108 * 0.3: Added code for the 'x-gzip'. This is untested, I don't know of 00109 * any browser that uses it but the RFC said to look out for it. 00110 * 0.2: Checks for 'gzip' in the Accept-Encoding header 00111 * 0.1: First working version. 00112 * 00113 * Thanks To (Suggestions and stuff): 00114 * ?@boas.anthro.mnsu.edu http://php.net/manual/function.gzcompress.php 00115 * Kaoslord <kaoslord@chaos-productions.com> 00116 * Michael R. Gile <gilem@wsg.net> 00117 * Christian Hamm <chh@admaster.de> 00118 * 00119 * The most recent version is available at: 00120 * http://Leknor.com/code/ 00121 * 00122 */ 00123 00124 var $_version = 0.66; // Version of the gzip_encode class 00125 00126 var $level; // Compression level 00127 var $encoding; // Encoding type 00128 var $crc; // crc of the output 00129 var $size; // size of the uncompressed content 00130 var $gzsize; // size of the compressed content 00131 00132 /* 00133 * gzip_encode constructor - gzip encodes the current output buffer 00134 * if the browser supports it. 00135 * 00136 * Note: all arguments are optionial. 00137 * 00138 * You can specify one of the following for the first argument: 00139 * 0: No compression 00140 * 1: Min compression 00141 * ... Some compression (integer from 1 to 9) 00142 * 9: Max compression 00143 * true: Determin the compression level from the system load. The 00144 * higher the load the less the compression. 00145 * 00146 * You can specify one of the following for the second argument: 00147 * true: Don't actully output the compressed form but run as if it 00148 * had. Used for debugging. 00149 */ 00150 function gzip_encode($level = 3, $debug = false, $outputCompressedSizes=0) { 00151 if (!function_exists('gzcompress')) { 00152 trigger_error('gzcompress not found, ' . 00153 'zlib needs to be installed for gzip_encode', 00154 E_USER_WARNING); 00155 return; 00156 } 00157 if (!function_exists('crc32')) { 00158 trigger_error('crc32() not found, ' . 00159 'PHP >= 4.0.1 needed for gzip_encode', E_USER_WARNING); 00160 return; 00161 } 00162 if (headers_sent()) return; 00163 if (connection_status() !== 0) return; 00164 $encoding = $this->gzip_accepted(); 00165 if (!$encoding) return; 00166 $this->encoding = $encoding; 00167 00168 if ($level === true) { 00169 $level = $this->get_complevel(); 00170 } 00171 $this->level = $level; 00172 00173 $contents = ob_get_contents(); 00174 if ($contents === false) return; 00175 00176 $gzdata = "\x1f\x8b\x08\x00\x00\x00\x00\x00"; // gzip header 00177 00178 // By Kasper Skaarhoj, start 00179 if ($outputCompressedSizes) { 00180 $contents.=chr(10)."<!-- Compressed, level ".$level.", original size was ".strlen($contents)." bytes. New size is ".strlen(gzcompress($contents, $level))." bytes -->"; 00181 $size = strlen($contents); // Must set again! 00182 } 00183 // By Kasper Skaarhoj, end 00184 00185 $size = strlen($contents); 00186 $crc = crc32($contents); 00187 $gzdata .= gzcompress($contents, $level); 00188 $gzdata = substr($gzdata, 0, strlen($gzdata) - 4); // fix crc bug 00189 $gzdata .= pack("V",$crc) . pack("V", $size); 00190 00191 $this->size = $size; 00192 $this->crc = $crc; 00193 $this->gzsize = strlen($gzdata); 00194 00195 if ($debug) { 00196 return; 00197 } 00198 00199 ob_end_clean(); 00200 Header('Content-Encoding: ' . $encoding); 00201 Header('Content-Length: ' . strlen($gzdata)); 00202 Header('X-Content-Encoded-By: class.gzip_encode '.$this->_version); 00203 00204 echo $gzdata; 00205 } 00206 00207 00208 /* 00209 * gzip_accepted() - Test headers for Accept-Encoding: gzip 00210 * 00211 * Returns: if proper headers aren't found: false 00212 * if proper headers are found: 'gzip' or 'x-gzip' 00213 * 00214 * Tip: using this function you can test if the class will gzip the output 00215 * without actually compressing it yet, eg: 00216 * if (gzip_encode::gzip_accepted()) { 00217 * echo "Page will be gziped"; 00218 * } 00219 * note the double colon syntax, I don't know where it is documented but 00220 * somehow it got in my brain. 00221 */ 00222 function gzip_accepted() { 00223 if (strpos(getenv("HTTP_ACCEPT_ENCODING"), 'gzip') === false) return false; 00224 if (strpos(getenv("HTTP_ACCEPT_ENCODING"), 'x-gzip') === false) { 00225 $encoding = 'gzip'; 00226 } else { 00227 $encoding = 'x-gzip'; 00228 } 00229 00230 // Test file type. I wish I could get HTTP response headers. 00231 $magic = substr(ob_get_contents(),0,4); 00232 if (substr($magic,0,2) === '^_') { 00233 // gzip data 00234 $encoding = false; 00235 } else if (substr($magic,0,3) === 'GIF') { 00236 // gif images 00237 $encoding = false; 00238 } else if (substr($magic,0,2) === "\xFF\xD8") { 00239 // jpeg images 00240 $encoding = false; 00241 } else if (substr($magic,0,4) === "\x89PNG") { 00242 // png images 00243 $encoding = false; 00244 } else if (substr($magic,0,3) === 'FWS') { 00245 // Don't gzip Shockwave Flash files. Flash on windows incorrectly 00246 // claims it accepts gzip'd content. 00247 $encoding = false; 00248 } else if (substr($magic,0,2) === 'PK') { 00249 // pk zip file 00250 $encoding = false; 00251 } 00252 00253 return $encoding; 00254 } 00255 00256 /* 00257 * get_complevel() - The level of compression we should use. 00258 * 00259 * Returns an int between 0 and 9 inclusive. 00260 * 00261 * Tip: $gzleve = gzip_encode::get_complevel(); to get the compression level 00262 * that will be used with out actually compressing the output. 00263 * 00264 * Help: if you use an OS other then linux please send me code to make 00265 * this work with your OS - Thanks 00266 */ 00267 function get_complevel() { 00268 $uname = posix_uname(); 00269 switch ($uname['sysname']) { 00270 case 'Linux': 00271 $cl = (1 - $this->linux_loadavg()) * 10; 00272 $level = (int)max(min(9, $cl), 0); 00273 break; 00274 case 'FreeBSD': 00275 $cl = (1 - $this->freebsd_loadavg()) * 10; 00276 $level = (int)max(min(9, $cl), 0); 00277 break; 00278 default: 00279 $level = 3; 00280 break; 00281 } 00282 return $level; 00283 } 00284 00285 /* 00286 * linux_loadavg() - Gets the max() system load average from /proc/loadavg 00287 * 00288 * The max() Load Average will be returned 00289 */ 00290 function linux_loadavg() { 00291 $buffer = "0 0 0"; 00292 $f = fopen("/proc/loadavg","rb"); 00293 if (!feof($f)) { 00294 $buffer = fgets($f, 1024); 00295 } 00296 fclose($f); 00297 $load = explode(" ",$buffer); 00298 return max((float)$load[0], (float)$load[1], (float)$load[2]); 00299 } 00300 00301 /* 00302 * freebsd_loadavg() - Gets the max() system load average from uname(1) 00303 * 00304 * The max() Load Average will be returned 00305 * 00306 * I've been told the code below will work on solaris too, anyone wanna 00307 * test it? 00308 */ 00309 function freebsd_loadavg() { 00310 $buffer= `uptime`; 00311 ereg("averag(es|e): ([0-9][.][0-9][0-9]), ([0-9][.][0-9][0-9]), ([0-9][.][0-9][0-9]*)", $buffer, $load); 00312 00313 return max((float)$load[2], (float)$load[3], (float)$load[4]); 00314 } 00315 } 00316 00317 ?>