<?php
# for full comments, look in modules/class.gzip_encode.docs
class gzip_encode {
/*
* gzip_encode - a class to gzip encode php output
* By Sandy McArthur, Jr. <hide@address.com>
*
* Things to note:
* 1. There is no space before the beginning of the file and the '<?php' tag
* 2. The ob_start() line is optional if output buffering is turned on in
* the main config file.
* 3. Turning on and off output buffering just won't work.
* 4. There must be nothing after the last '?>' tag at the end of the file.
* Be careful of a space hiding there.
* 5. There are better ways to compress served content but I think this is
* the only way to compress php output.
* 6. Your auto_prepend_file is a good place for the ob_start() and
* your auto_append_file is a good place for new gzip_encode().
* 7. If you put new gzip_encode() in your auto.append file then you can
* call ob_end_flush in your script to disable compression.
*/
var $_version = 0.67; // Version of the gzip_encode class
var $level; // Compression level
var $encoding; // Encoding type
var $crc; // crc of the output
var $size; // size of the uncompressed content
var $gzsize; // size of the compressed content
function gzip_encode($level = 3, $debug = false) {
global $HTTP_ACCEPT_ENCODING;
if (!function_exists('gzcompress')) {
trigger_error('gzcompress not found, ' .
'zlib needs to be installed for gzip_encode',
E_USER_WARNING);
return;
}
if (!function_exists('crc32')) {
trigger_error('crc32() not found, ' .
'PHP >= 4.0.1 needed for gzip_encode', E_USER_WARNING);
return;
}
if (headers_sent()) return;
if (connection_status() !== 0) return;
$encoding = $this->gzip_accepted();
if (!$encoding) return;
$this->encoding = $encoding;
if ($level === true) {
$level = $this->get_complevel();
}
$this->level = $level;
$contents = ob_get_contents();
if ($contents === false) return;
$gzdata = "\x1f\x8b\x08\x00\x00\x00\x00\x00"; // gzip header
$size = strlen($contents);
$crc = crc32($contents);
$gzdata .= gzcompress($contents, $level);
$gzdata = substr($gzdata, 0, strlen($gzdata) - 4); // fix crc bug
$gzdata .= pack("V",$crc) . pack("V", $size);
$this->size = $size;
$this->crc = $crc;
$this->gzsize = strlen($gzdata);
if ($debug) {
return;
}
ob_end_clean();
Header('Content-Encoding: ' . $encoding);
Header('Vary: Accept-Encoding');
Header('Content-Length: ' . strlen($gzdata));
Header('X-Content-Encoded-By: class.gzip_encode '.$this->_version);
echo $gzdata;
}
function gzip_accepted() {
global $HTTP_ACCEPT_ENCODING;
if (strpos($HTTP_ACCEPT_ENCODING, 'gzip') === false) return false;
if (strpos($HTTP_ACCEPT_ENCODING, 'x-gzip') === false) {
$encoding = 'gzip';
} else {
$encoding = 'x-gzip';
}
// Test file type. I wish I could get HTTP response headers.
$magic = substr(ob_get_contents(),0,4);
if (substr($magic,0,2) === '^_') {
// gzip data
$encoding = false;
} else if (substr($magic,0,3) === 'GIF') {
// gif images
$encoding = false;
} else if (substr($magic,0,2) === "\xFF\xD8") {
// jpeg images
$encoding = false;
} else if (substr($magic,0,4) === "\x89PNG") {
// png images
$encoding = false;
} else if (substr($magic,0,3) === 'FWS') {
// Don't gzip Shockwave Flash files. Flash on windows incorrectly
// claims it accepts gzip'd content.
$encoding = false;
} else if (substr($magic,0,2) === 'PK') {
// pk zip file
$encoding = false;
}
return $encoding;
}
function get_complevel() {
$uname = posix_uname();
switch ($uname['sysname']) {
case 'Linux':
$cl = (1 - $this->linux_loadavg()) * 10;
$level = (int)max(min(9, $cl), 0);
break;
case 'FreeBSD':
$cl = (1 - $this->freebsd_loadavg()) * 10;
$level = (int)max(min(9, $cl), 0);
break;
default:
$level = 3;
break;
}
return $level;
}
function linux_loadavg() {
$buffer = "0 0 0";
$f = fopen("/proc/loadavg","r");
if (!feof($f)) {
$buffer = fgets($f, 1024);
}
fclose($f);
$load = explode(" ",$buffer);
return max((float)$load[0], (float)$load[1], (float)$load[2]);
}
function freebsd_loadavg() {
$buffer= `uptime`;
ereg("averag(es|e): ([0-9][.][0-9][0-9]), ([0-9][.][0-9][0-9]), ([0-9][.][0-9][0-9]*)", $buffer, $load);
return max((float)$load[2], (float)$load[3], (float)$load[4]);
}
}
?>