forked from GNUsocial/gnu-social
		
	
		
			
	
	
		
			327 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
		
		
			
		
	
	
			327 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| 
								 | 
							
								<?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 (0 === strpos($ae, 'gzip,')             // most browsers
							 | 
						||
| 
								 | 
							
								            || 0 === 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 (0 === strpos($aeRev, 'etalfed ,') // ie, webkit
							 | 
						||
| 
								 | 
							
								                || 0 === strpos($aeRev, 'etalfed,') // gecko
							 | 
						||
| 
								 | 
							
								                || 0 === 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 (0 !== strpos($ua, 'Mozilla/4.0 (compatible; MSIE ')
							 | 
						||
| 
								 | 
							
								            || false !== strpos($ua, 'Opera')) {
							 | 
						||
| 
								 | 
							
								            return false;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        // no regex = faaast
							 | 
						||
| 
								 | 
							
								        $version = (float)substr($ua, 30); 
							 | 
						||
| 
								 | 
							
								        return self::$encodeToIe6
							 | 
						||
| 
								 | 
							
								            ? ($version < 6 || ($version == 6 && false === strpos($ua, 'SV1')))
							 | 
						||
| 
								 | 
							
								            : ($version < 7);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 |