home *** CD-ROM | disk | FTP | other *** search
/ HTML Examples / WP.iso / wordpress / wp-includes / SimplePie / gzdecode.php < prev    next >
Encoding:
PHP Script  |  2012-11-21  |  8.4 KB  |  372 lines

  1. <?php
  2. /**
  3.  * SimplePie
  4.  *
  5.  * A PHP-Based RSS and Atom Feed Framework.
  6.  * Takes the hard work out of managing a complete RSS/Atom solution.
  7.  *
  8.  * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
  9.  * All rights reserved.
  10.  *
  11.  * Redistribution and use in source and binary forms, with or without modification, are
  12.  * permitted provided that the following conditions are met:
  13.  *
  14.  *     * Redistributions of source code must retain the above copyright notice, this list of
  15.  *       conditions and the following disclaimer.
  16.  *
  17.  *     * Redistributions in binary form must reproduce the above copyright notice, this list
  18.  *       of conditions and the following disclaimer in the documentation and/or other materials
  19.  *       provided with the distribution.
  20.  *
  21.  *     * Neither the name of the SimplePie Team nor the names of its contributors may be used
  22.  *       to endorse or promote products derived from this software without specific prior
  23.  *       written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
  26.  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  27.  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
  28.  * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  29.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  30.  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  31.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  32.  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  33.  * POSSIBILITY OF SUCH DAMAGE.
  34.  *
  35.  * @package SimplePie
  36.  * @version 1.3.1
  37.  * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue
  38.  * @author Ryan Parman
  39.  * @author Geoffrey Sneddon
  40.  * @author Ryan McCue
  41.  * @link http://simplepie.org/ SimplePie
  42.  * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  43.  */
  44.  
  45.  
  46. /**
  47.  * Decode 'gzip' encoded HTTP data
  48.  *
  49.  * @package SimplePie
  50.  * @subpackage HTTP
  51.  * @link http://www.gzip.org/format.txt
  52.  */
  53. class SimplePie_gzdecode
  54. {
  55.     /**
  56.      * Compressed data
  57.      *
  58.      * @access private
  59.      * @var string
  60.      * @see gzdecode::$data
  61.      */
  62.     var $compressed_data;
  63.  
  64.     /**
  65.      * Size of compressed data
  66.      *
  67.      * @access private
  68.      * @var int
  69.      */
  70.     var $compressed_size;
  71.  
  72.     /**
  73.      * Minimum size of a valid gzip string
  74.      *
  75.      * @access private
  76.      * @var int
  77.      */
  78.     var $min_compressed_size = 18;
  79.  
  80.     /**
  81.      * Current position of pointer
  82.      *
  83.      * @access private
  84.      * @var int
  85.      */
  86.     var $position = 0;
  87.  
  88.     /**
  89.      * Flags (FLG)
  90.      *
  91.      * @access private
  92.      * @var int
  93.      */
  94.     var $flags;
  95.  
  96.     /**
  97.      * Uncompressed data
  98.      *
  99.      * @access public
  100.      * @see gzdecode::$compressed_data
  101.      * @var string
  102.      */
  103.     var $data;
  104.  
  105.     /**
  106.      * Modified time
  107.      *
  108.      * @access public
  109.      * @var int
  110.      */
  111.     var $MTIME;
  112.  
  113.     /**
  114.      * Extra Flags
  115.      *
  116.      * @access public
  117.      * @var int
  118.      */
  119.     var $XFL;
  120.  
  121.     /**
  122.      * Operating System
  123.      *
  124.      * @access public
  125.      * @var int
  126.      */
  127.     var $OS;
  128.  
  129.     /**
  130.      * Subfield ID 1
  131.      *
  132.      * @access public
  133.      * @see gzdecode::$extra_field
  134.      * @see gzdecode::$SI2
  135.      * @var string
  136.      */
  137.     var $SI1;
  138.  
  139.     /**
  140.      * Subfield ID 2
  141.      *
  142.      * @access public
  143.      * @see gzdecode::$extra_field
  144.      * @see gzdecode::$SI1
  145.      * @var string
  146.      */
  147.     var $SI2;
  148.  
  149.     /**
  150.      * Extra field content
  151.      *
  152.      * @access public
  153.      * @see gzdecode::$SI1
  154.      * @see gzdecode::$SI2
  155.      * @var string
  156.      */
  157.     var $extra_field;
  158.  
  159.     /**
  160.      * Original filename
  161.      *
  162.      * @access public
  163.      * @var string
  164.      */
  165.     var $filename;
  166.  
  167.     /**
  168.      * Human readable comment
  169.      *
  170.      * @access public
  171.      * @var string
  172.      */
  173.     var $comment;
  174.  
  175.     /**
  176.      * Don't allow anything to be set
  177.      *
  178.      * @param string $name
  179.      * @param mixed $value
  180.      */
  181.     public function __set($name, $value)
  182.     {
  183.         trigger_error("Cannot write property $name", E_USER_ERROR);
  184.     }
  185.  
  186.     /**
  187.      * Set the compressed string and related properties
  188.      *
  189.      * @param string $data
  190.      */
  191.     public function __construct($data)
  192.     {
  193.         $this->compressed_data = $data;
  194.         $this->compressed_size = strlen($data);
  195.     }
  196.  
  197.     /**
  198.      * Decode the GZIP stream
  199.      *
  200.      * @return bool Successfulness
  201.      */
  202.     public function parse()
  203.     {
  204.         if ($this->compressed_size >= $this->min_compressed_size)
  205.         {
  206.             // Check ID1, ID2, and CM
  207.             if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
  208.             {
  209.                 return false;
  210.             }
  211.  
  212.             // Get the FLG (FLaGs)
  213.             $this->flags = ord($this->compressed_data[3]);
  214.  
  215.             // FLG bits above (1 << 4) are reserved
  216.             if ($this->flags > 0x1F)
  217.             {
  218.                 return false;
  219.             }
  220.  
  221.             // Advance the pointer after the above
  222.             $this->position += 4;
  223.  
  224.             // MTIME
  225.             $mtime = substr($this->compressed_data, $this->position, 4);
  226.             // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
  227.             if (current(unpack('S', "\x00\x01")) === 1)
  228.             {
  229.                 $mtime = strrev($mtime);
  230.             }
  231.             $this->MTIME = current(unpack('l', $mtime));
  232.             $this->position += 4;
  233.  
  234.             // Get the XFL (eXtra FLags)
  235.             $this->XFL = ord($this->compressed_data[$this->position++]);
  236.  
  237.             // Get the OS (Operating System)
  238.             $this->OS = ord($this->compressed_data[$this->position++]);
  239.  
  240.             // Parse the FEXTRA
  241.             if ($this->flags & 4)
  242.             {
  243.                 // Read subfield IDs
  244.                 $this->SI1 = $this->compressed_data[$this->position++];
  245.                 $this->SI2 = $this->compressed_data[$this->position++];
  246.  
  247.                 // SI2 set to zero is reserved for future use
  248.                 if ($this->SI2 === "\x00")
  249.                 {
  250.                     return false;
  251.                 }
  252.  
  253.                 // Get the length of the extra field
  254.                 $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
  255.                 $this->position += 2;
  256.  
  257.                 // Check the length of the string is still valid
  258.                 $this->min_compressed_size += $len + 4;
  259.                 if ($this->compressed_size >= $this->min_compressed_size)
  260.                 {
  261.                     // Set the extra field to the given data
  262.                     $this->extra_field = substr($this->compressed_data, $this->position, $len);
  263.                     $this->position += $len;
  264.                 }
  265.                 else
  266.                 {
  267.                     return false;
  268.                 }
  269.             }
  270.  
  271.             // Parse the FNAME
  272.             if ($this->flags & 8)
  273.             {
  274.                 // Get the length of the filename
  275.                 $len = strcspn($this->compressed_data, "\x00", $this->position);
  276.  
  277.                 // Check the length of the string is still valid
  278.                 $this->min_compressed_size += $len + 1;
  279.                 if ($this->compressed_size >= $this->min_compressed_size)
  280.                 {
  281.                     // Set the original filename to the given string
  282.                     $this->filename = substr($this->compressed_data, $this->position, $len);
  283.                     $this->position += $len + 1;
  284.                 }
  285.                 else
  286.                 {
  287.                     return false;
  288.                 }
  289.             }
  290.  
  291.             // Parse the FCOMMENT
  292.             if ($this->flags & 16)
  293.             {
  294.                 // Get the length of the comment
  295.                 $len = strcspn($this->compressed_data, "\x00", $this->position);
  296.  
  297.                 // Check the length of the string is still valid
  298.                 $this->min_compressed_size += $len + 1;
  299.                 if ($this->compressed_size >= $this->min_compressed_size)
  300.                 {
  301.                     // Set the original comment to the given string
  302.                     $this->comment = substr($this->compressed_data, $this->position, $len);
  303.                     $this->position += $len + 1;
  304.                 }
  305.                 else
  306.                 {
  307.                     return false;
  308.                 }
  309.             }
  310.  
  311.             // Parse the FHCRC
  312.             if ($this->flags & 2)
  313.             {
  314.                 // Check the length of the string is still valid
  315.                 $this->min_compressed_size += $len + 2;
  316.                 if ($this->compressed_size >= $this->min_compressed_size)
  317.                 {
  318.                     // Read the CRC
  319.                     $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
  320.  
  321.                     // Check the CRC matches
  322.                     if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
  323.                     {
  324.                         $this->position += 2;
  325.                     }
  326.                     else
  327.                     {
  328.                         return false;
  329.                     }
  330.                 }
  331.                 else
  332.                 {
  333.                     return false;
  334.                 }
  335.             }
  336.  
  337.             // Decompress the actual data
  338.             if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
  339.             {
  340.                 return false;
  341.             }
  342.             else
  343.             {
  344.                 $this->position = $this->compressed_size - 8;
  345.             }
  346.  
  347.             // Check CRC of data
  348.             $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
  349.             $this->position += 4;
  350.             /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
  351.             {
  352.                 return false;
  353.             }*/
  354.  
  355.             // Check ISIZE of data
  356.             $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
  357.             $this->position += 4;
  358.             if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
  359.             {
  360.                 return false;
  361.             }
  362.  
  363.             // Wow, against all odds, we've actually got a valid gzip string
  364.             return true;
  365.         }
  366.         else
  367.         {
  368.             return false;
  369.         }
  370.     }
  371. }
  372.