[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/vendor/simplepie/simplepie/library/SimplePie/ -> gzdecode.php (source)

   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-2016, 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   * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
  37   * @author Ryan Parman
  38   * @author Geoffrey Sneddon
  39   * @author Ryan McCue
  40   * @link http://simplepie.org/ SimplePie
  41   * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  42   */
  43  
  44  
  45  /**
  46   * Decode 'gzip' encoded HTTP data
  47   *
  48   * @package SimplePie
  49   * @subpackage HTTP
  50   * @link http://www.gzip.org/format.txt
  51   */
  52  class SimplePie_gzdecode
  53  {
  54      /**
  55       * Compressed data
  56       *
  57       * @access private
  58       * @var string
  59       * @see gzdecode::$data
  60       */
  61      var $compressed_data;
  62  
  63      /**
  64       * Size of compressed data
  65       *
  66       * @access private
  67       * @var int
  68       */
  69      var $compressed_size;
  70  
  71      /**
  72       * Minimum size of a valid gzip string
  73       *
  74       * @access private
  75       * @var int
  76       */
  77      var $min_compressed_size = 18;
  78  
  79      /**
  80       * Current position of pointer
  81       *
  82       * @access private
  83       * @var int
  84       */
  85      var $position = 0;
  86  
  87      /**
  88       * Flags (FLG)
  89       *
  90       * @access private
  91       * @var int
  92       */
  93      var $flags;
  94  
  95      /**
  96       * Uncompressed data
  97       *
  98       * @access public
  99       * @see gzdecode::$compressed_data
 100       * @var string
 101       */
 102      var $data;
 103  
 104      /**
 105       * Modified time
 106       *
 107       * @access public
 108       * @var int
 109       */
 110      var $MTIME;
 111  
 112      /**
 113       * Extra Flags
 114       *
 115       * @access public
 116       * @var int
 117       */
 118      var $XFL;
 119  
 120      /**
 121       * Operating System
 122       *
 123       * @access public
 124       * @var int
 125       */
 126      var $OS;
 127  
 128      /**
 129       * Subfield ID 1
 130       *
 131       * @access public
 132       * @see gzdecode::$extra_field
 133       * @see gzdecode::$SI2
 134       * @var string
 135       */
 136      var $SI1;
 137  
 138      /**
 139       * Subfield ID 2
 140       *
 141       * @access public
 142       * @see gzdecode::$extra_field
 143       * @see gzdecode::$SI1
 144       * @var string
 145       */
 146      var $SI2;
 147  
 148      /**
 149       * Extra field content
 150       *
 151       * @access public
 152       * @see gzdecode::$SI1
 153       * @see gzdecode::$SI2
 154       * @var string
 155       */
 156      var $extra_field;
 157  
 158      /**
 159       * Original filename
 160       *
 161       * @access public
 162       * @var string
 163       */
 164      var $filename;
 165  
 166      /**
 167       * Human readable comment
 168       *
 169       * @access public
 170       * @var string
 171       */
 172      var $comment;
 173  
 174      /**
 175       * Don't allow anything to be set
 176       *
 177       * @param string $name
 178       * @param mixed $value
 179       */
 180  	public function __set($name, $value)
 181      {
 182          trigger_error("Cannot write property $name", E_USER_ERROR);
 183      }
 184  
 185      /**
 186       * Set the compressed string and related properties
 187       *
 188       * @param string $data
 189       */
 190  	public function __construct($data)
 191      {
 192          $this->compressed_data = $data;
 193          $this->compressed_size = strlen($data);
 194      }
 195  
 196      /**
 197       * Decode the GZIP stream
 198       *
 199       * @return bool Successfulness
 200       */
 201  	public function parse()
 202      {
 203          if ($this->compressed_size >= $this->min_compressed_size)
 204          {
 205              // Check ID1, ID2, and CM
 206              if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
 207              {
 208                  return false;
 209              }
 210  
 211              // Get the FLG (FLaGs)
 212              $this->flags = ord($this->compressed_data[3]);
 213  
 214              // FLG bits above (1 << 4) are reserved
 215              if ($this->flags > 0x1F)
 216              {
 217                  return false;
 218              }
 219  
 220              // Advance the pointer after the above
 221              $this->position += 4;
 222  
 223              // MTIME
 224              $mtime = substr($this->compressed_data, $this->position, 4);
 225              // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
 226              if (current(unpack('S', "\x00\x01")) === 1)
 227              {
 228                  $mtime = strrev($mtime);
 229              }
 230              $this->MTIME = current(unpack('l', $mtime));
 231              $this->position += 4;
 232  
 233              // Get the XFL (eXtra FLags)
 234              $this->XFL = ord($this->compressed_data[$this->position++]);
 235  
 236              // Get the OS (Operating System)
 237              $this->OS = ord($this->compressed_data[$this->position++]);
 238  
 239              // Parse the FEXTRA
 240              if ($this->flags & 4)
 241              {
 242                  // Read subfield IDs
 243                  $this->SI1 = $this->compressed_data[$this->position++];
 244                  $this->SI2 = $this->compressed_data[$this->position++];
 245  
 246                  // SI2 set to zero is reserved for future use
 247                  if ($this->SI2 === "\x00")
 248                  {
 249                      return false;
 250                  }
 251  
 252                  // Get the length of the extra field
 253                  $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
 254                  $this->position += 2;
 255  
 256                  // Check the length of the string is still valid
 257                  $this->min_compressed_size += $len + 4;
 258                  if ($this->compressed_size >= $this->min_compressed_size)
 259                  {
 260                      // Set the extra field to the given data
 261                      $this->extra_field = substr($this->compressed_data, $this->position, $len);
 262                      $this->position += $len;
 263                  }
 264                  else
 265                  {
 266                      return false;
 267                  }
 268              }
 269  
 270              // Parse the FNAME
 271              if ($this->flags & 8)
 272              {
 273                  // Get the length of the filename
 274                  $len = strcspn($this->compressed_data, "\x00", $this->position);
 275  
 276                  // Check the length of the string is still valid
 277                  $this->min_compressed_size += $len + 1;
 278                  if ($this->compressed_size >= $this->min_compressed_size)
 279                  {
 280                      // Set the original filename to the given string
 281                      $this->filename = substr($this->compressed_data, $this->position, $len);
 282                      $this->position += $len + 1;
 283                  }
 284                  else
 285                  {
 286                      return false;
 287                  }
 288              }
 289  
 290              // Parse the FCOMMENT
 291              if ($this->flags & 16)
 292              {
 293                  // Get the length of the comment
 294                  $len = strcspn($this->compressed_data, "\x00", $this->position);
 295  
 296                  // Check the length of the string is still valid
 297                  $this->min_compressed_size += $len + 1;
 298                  if ($this->compressed_size >= $this->min_compressed_size)
 299                  {
 300                      // Set the original comment to the given string
 301                      $this->comment = substr($this->compressed_data, $this->position, $len);
 302                      $this->position += $len + 1;
 303                  }
 304                  else
 305                  {
 306                      return false;
 307                  }
 308              }
 309  
 310              // Parse the FHCRC
 311              if ($this->flags & 2)
 312              {
 313                  // Check the length of the string is still valid
 314                  $this->min_compressed_size += $len + 2;
 315                  if ($this->compressed_size >= $this->min_compressed_size)
 316                  {
 317                      // Read the CRC
 318                      $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
 319  
 320                      // Check the CRC matches
 321                      if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
 322                      {
 323                          $this->position += 2;
 324                      }
 325                      else
 326                      {
 327                          return false;
 328                      }
 329                  }
 330                  else
 331                  {
 332                      return false;
 333                  }
 334              }
 335  
 336              // Decompress the actual data
 337              if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
 338              {
 339                  return false;
 340              }
 341  
 342              $this->position = $this->compressed_size - 8;
 343  
 344              // Check CRC of data
 345              $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
 346              $this->position += 4;
 347              /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
 348              {
 349                  return false;
 350              }*/
 351  
 352              // Check ISIZE of data
 353              $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
 354              $this->position += 4;
 355              if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
 356              {
 357                  return false;
 358              }
 359  
 360              // Wow, against all odds, we've actually got a valid gzip string
 361              return true;
 362          }
 363  
 364          return false;
 365      }
 366  }