Вход Регистрация
Файл: min/lib/HTTP/Encoder.php
Строк: 431
<?php
/**
 * Class HTTP_Encoder  
 * @package Minify
 * @subpackage HTTP
 */
 
/**
 * Encode and send gzipped/deflated content
 *
 * The "Vary: Accept-Encoding" header is sent. If the client allows encoding, 
 * Content-Encoding and Content-Length are added.
 *
 * <code>
 * // Send a CSS file, compressed if possible
 * $he = new HTTP_Encoder(array(
 *     'content' => file_get_contents($cssFile)
 *     ,'type' => 'text/css'
 * ));
 * $he->encode();
 * $he->sendAll();
 * </code>
 *
 * <code>
 * // Shortcut to encoding output
 * header('Content-Type: text/css'); // needed if not HTML
 * HTTP_Encoder::output($css);
 * </code>
 * 
 * <code>
 * // Just sniff for the accepted encoding
 * $encoding = HTTP_Encoder::getAcceptedEncoding();
 * </code>
 *
 * For more control over headers, use getHeaders() and getData() and send your
 * own output.
 * 
 * Note: If you don't need header mgmt, use PHP's native gzencode, gzdeflate, 
 * and gzcompress functions for gzip, deflate, and compress-encoding
 * respectively.
 * 
 * @package Minify
 * @subpackage HTTP
 * @author Stephen Clay <steve@mrclay.org>
 */
class HTTP_Encoder {

    
/**
     * Should the encoder allow HTTP encoding to IE6? 
     * 
     * If you have many IE6 users and the bandwidth savings is worth troubling 
     * some of them, set this to true.
     * 
     * By default, encoding is only offered to IE7+. When this is true,
     * getAcceptedEncoding() will return an encoding for IE6 if its user agent
     * string contains "SV1". This has been documented in many places as "safe",
     * but there seem to be remaining, intermittent encoding bugs in patched 
     * IE6 on the wild web.
     * 
     * @var bool
     */
    
public static $encodeToIe6 false;
    
    
    
/**
     * Default compression level for zlib operations
     * 
     * This level is used if encode() is not given a $compressionLevel
     * 
     * @var int
     */
    
public static $compressionLevel 6;
    

    
/**
     * Get an HTTP Encoder object
     * 
     * @param array $spec options
     * 
     * 'content': (string required) content to be encoded
     * 
     * 'type': (string) if set, the Content-Type header will have this value.
     * 
     * 'method: (string) only set this if you are forcing a particular encoding
     * method. If not set, the best method will be chosen by getAcceptedEncoding()
     * The available methods are 'gzip', 'deflate', 'compress', and '' (no
     * encoding)
     * 
     * @return null
     */
    
public function __construct($spec
    {
        
$this->_content $spec['content'];
        
$this->_headers['Content-Length'] = (string)strlen($this->_content);
        if (isset(
$spec['type'])) {
            
$this->_headers['Content-Type'] = $spec['type'];
        }
        if (isset(
$spec['method'])
            && 
in_array($spec['method'], array('gzip''deflate''compress''')))
        {
            
$this->_encodeMethod = array($spec['method'], $spec['method']);
        } else {
            
$this->_encodeMethod self::getAcceptedEncoding();
        }
    }

    
/**
     * Get content in current form
     * 
     * Call after encode() for encoded content.
     * 
     * return string
     */
    
public function getContent() 
    {
        return 
$this->_content;
    }
    
    
/**
     * Get array of output headers to be sent
     * 
     * E.g.
     * <code>
     * array(
     *     'Content-Length' => '615'
     *     ,'Content-Encoding' => 'x-gzip'
     *     ,'Vary' => 'Accept-Encoding'
     * )
     * </code>
     *
     * @return array 
     */
    
public function getHeaders()
    {
        return 
$this->_headers;
    }

    
/**
     * Send output headers
     * 
     * You must call this before headers are sent and it probably cannot be
     * used in conjunction with zlib output buffering / mod_gzip. Errors are
     * not handled purposefully.
     * 
     * @see getHeaders()
     * 
     * @return null
     */
    
public function sendHeaders()
    {
        foreach (
$this->_headers as $name => $val) {
            
header($name ': ' $val);
        }
    }
    
    
/**
     * Send output headers and content
     * 
     * A shortcut for sendHeaders() and echo getContent()
     *
     * You must call this before headers are sent and it probably cannot be
     * used in conjunction with zlib output buffering / mod_gzip. Errors are
     * not handled purposefully.
     * 
     * @return null
     */
    
public function sendAll()
    {
        
$this->sendHeaders();
        echo 
$this->_content;
    }

    
/**
     * Determine the client's best encoding method from the HTTP Accept-Encoding 
     * header.
     * 
     * If no Accept-Encoding header is set, or the browser is IE before v6 SP2,
     * this will return ('', ''), the "identity" encoding.
     * 
     * A syntax-aware scan is done of the Accept-Encoding, so the method must
     * be non 0. The methods are favored in order of gzip, deflate, then 
     * compress. Deflate is always smallest and generally faster, but is 
     * rarely sent by servers, so client support could be buggier.
     * 
     * @param bool $allowCompress allow the older compress encoding
     * 
     * @param bool $allowDeflate allow the more recent deflate encoding
     * 
     * @return array two values, 1st is the actual encoding method, 2nd is the
     * alias of that method to use in the Content-Encoding header (some browsers
     * call gzip "x-gzip" etc.)
     */
    
public static function getAcceptedEncoding($allowCompress true$allowDeflate true)
    {
        
// @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
        
        
if (! isset($_SERVER['HTTP_ACCEPT_ENCODING'])
            || 
self::_isBuggyIe())
        {
            return array(
'''');
        }
        
$ae $_SERVER['HTTP_ACCEPT_ENCODING'];
        
// gzip checks (quick)
        
if (=== strpos($ae'gzip,')             // most browsers
            
|| === strpos($ae'deflate, gzip,'// opera
        
) {
            return array(
'gzip''gzip');
        }
        
// gzip checks (slow)
        
if (preg_match(
                
'@(?:^|,)\s*((?:x-)?gzip)\s*(?:$|,|;\s*q=(?:0\.|1))@'
                
,$ae
                
,$m)) {
            return array(
'gzip'$m[1]);
        }
        if (
$allowDeflate) {
            
// deflate checks    
            
$aeRev strrev($ae);
            if (
=== strpos($aeRev'etalfed ,'// ie, webkit
                
|| === strpos($aeRev'etalfed,'// gecko
                
|| === strpos($ae'deflate,'// opera
                // slow parsing
                
|| preg_match(
                    
'@(?:^|,)\s*deflate\s*(?:$|,|;\s*q=(?:0\.|1))@'$ae)) {
                return array(
'deflate''deflate');
            }
        }
        if (
$allowCompress && preg_match(
                
'@(?:^|,)\s*((?:x-)?compress)\s*(?:$|,|;\s*q=(?:0\.|1))@'
                
,$ae
                
,$m)) {
            return array(
'compress'$m[1]);
        }
        return array(
'''');
    }

    
/**
     * Encode (compress) the content
     * 
     * If the encode method is '' (none) or compression level is 0, or the 'zlib'
     * extension isn't loaded, we return false.
     * 
     * Then the appropriate gz_* function is called to compress the content. If
     * this fails, false is returned.
     * 
     * The header "Vary: Accept-Encoding" is added. If encoding is successful, 
     * the Content-Length header is updated, and Content-Encoding is also added.
     * 
     * @param int $compressionLevel given to zlib functions. If not given, the
     * class default will be used.
     * 
     * @return bool success true if the content was actually compressed
     */
    
public function encode($compressionLevel null)
    {
        
$this->_headers['Vary'] = 'Accept-Encoding';
        if (
null === $compressionLevel) {
            
$compressionLevel self::$compressionLevel;
        }
        if (
'' === $this->_encodeMethod[0]
            || (
$compressionLevel == 0)
            || !
extension_loaded('zlib'))
        {
            return 
false;
        }
        if (
$this->_encodeMethod[0] === 'deflate') {
            
$encoded gzdeflate($this->_content$compressionLevel);
        } elseif (
$this->_encodeMethod[0] === 'gzip') {
            
$encoded gzencode($this->_content$compressionLevel);
        } else {
            
$encoded gzcompress($this->_content$compressionLevel);
        }
        if (
false === $encoded) {
            return 
false;
        }
        
$this->_headers['Content-Length'] = strlen($encoded);
        
$this->_headers['Content-Encoding'] = $this->_encodeMethod[1];
        
$this->_content $encoded;
        return 
true;
    }
    
    
/**
     * Encode and send appropriate headers and content
     *
     * This is a convenience method for common use of the class
     * 
     * @param string $content
     * 
     * @param int $compressionLevel given to zlib functions. If not given, the
     * class default will be used.
     * 
     * @return bool success true if the content was actually compressed
     */
    
public static function output($content$compressionLevel null)
    {
        if (
null === $compressionLevel) {
            
$compressionLevel self::$compressionLevel;
        }
        
$he = new HTTP_Encoder(array('content' => $content));
        
$ret $he->encode($compressionLevel);
        
$he->sendAll();
        return 
$ret;
    }
    
    protected 
$_content '';
    protected 
$_headers = array();
    protected 
$_encodeMethod = array('''');

    
/**
     * Is the browser an IE version earlier than 6 SP2?  
     */
    
protected static function _isBuggyIe()
    {
        
$ua $_SERVER['HTTP_USER_AGENT'];
        
// quick escape for non-IEs
        
if (!== strpos($ua'Mozilla/4.0 (compatible; MSIE ')
            || 
false !== strpos($ua'Opera')) {
            return 
false;
        }
        
// no regex = faaast
        
$version = (float)substr($ua30); 
        return 
self::$encodeToIe6
            
? ($version || ($version == && false === strpos($ua'SV1')))
            : (
$version 7);
    }
}
Онлайн: 1
Реклама