vendor/swiftmailer/lib/classes/Swift/ByteStream/FileByteStream.php
changeset 0 7f95f8617b0b
equal deleted inserted replaced
-1:000000000000 0:7f95f8617b0b
       
     1 <?php
       
     2 
       
     3 /*
       
     4  * This file is part of SwiftMailer.
       
     5  * (c) 2004-2009 Chris Corbyn
       
     6  *
       
     7  * For the full copyright and license information, please view the LICENSE
       
     8  * file that was distributed with this source code.
       
     9  */
       
    10 
       
    11 
       
    12 /**
       
    13  * Allows reading and writing of bytes to and from a file.
       
    14  * @package Swift
       
    15  * @subpackage ByteStream
       
    16  * @author Chris Corbyn
       
    17  */
       
    18 class Swift_ByteStream_FileByteStream
       
    19   extends Swift_ByteStream_AbstractFilterableInputStream
       
    20   implements Swift_FileStream
       
    21 {
       
    22   
       
    23   /** The internal pointer offset */
       
    24   private $_offset = 0;
       
    25   
       
    26   /** The path to the file */
       
    27   private $_path;
       
    28   
       
    29   /** The mode this file is opened in for writing */
       
    30   private $_mode;
       
    31   
       
    32   /** A lazy-loaded resource handle for reading the file */
       
    33   private $_reader;
       
    34   
       
    35   /** A lazy-loaded resource handle for writing the file */
       
    36   private $_writer;
       
    37   
       
    38   /** If magic_quotes_runtime is on, this will be true */
       
    39   private $_quotes = false;
       
    40 
       
    41   /** If stream is seekable true/false, or null if not known */
       
    42   private $_seekable = null;
       
    43   
       
    44   /**
       
    45    * Create a new FileByteStream for $path.
       
    46    * @param string $path
       
    47    * @param string $writable if true
       
    48    */
       
    49   public function __construct($path, $writable = false)
       
    50   {
       
    51     $this->_path = $path;
       
    52     $this->_mode = $writable ? 'w+b' : 'rb';
       
    53     $this->_quotes = ini_get('magic_quotes_runtime');
       
    54   }
       
    55   
       
    56   /**
       
    57    * Get the complete path to the file.
       
    58    * @return string
       
    59    */
       
    60   public function getPath()
       
    61   {
       
    62     return $this->_path;
       
    63   }
       
    64   
       
    65   /**
       
    66    * Reads $length bytes from the stream into a string and moves the pointer
       
    67    * through the stream by $length. If less bytes exist than are requested the
       
    68    * remaining bytes are given instead. If no bytes are remaining at all, boolean
       
    69    * false is returned.
       
    70    * @param int $length
       
    71    * @return string
       
    72    * @throws Swift_IoException
       
    73    */
       
    74   public function read($length)
       
    75   {
       
    76     $fp = $this->_getReadHandle();
       
    77     if (!feof($fp))
       
    78     {
       
    79       if ($this->_quotes)
       
    80       {
       
    81         ini_set('magic_quotes_runtime', 0);
       
    82       }
       
    83       $bytes = fread($fp, $length);
       
    84       if ($this->_quotes)
       
    85       {
       
    86         ini_set('magic_quotes_runtime', 1);
       
    87       }
       
    88       $this->_offset = ftell($fp);
       
    89       return $bytes;
       
    90     }
       
    91     else
       
    92     {
       
    93       return false;
       
    94     }
       
    95   }
       
    96   
       
    97   /**
       
    98    * Move the internal read pointer to $byteOffset in the stream.
       
    99    * @param int $byteOffset
       
   100    * @return boolean
       
   101    */
       
   102   public function setReadPointer($byteOffset)
       
   103   {
       
   104     if (isset($this->_reader))
       
   105     {
       
   106       $this->_seekReadStreamToPosition($byteOffset);
       
   107     }
       
   108     $this->_offset = $byteOffset;
       
   109   }
       
   110   
       
   111   // -- Private methods
       
   112   
       
   113   /** Just write the bytes to the file */
       
   114   protected function _commit($bytes)
       
   115   {
       
   116     fwrite($this->_getWriteHandle(), $bytes);
       
   117     $this->_resetReadHandle();
       
   118   }
       
   119   
       
   120   /** Not used */
       
   121   protected function _flush()
       
   122   {
       
   123   }
       
   124   
       
   125   /** Get the resource for reading */
       
   126   private function _getReadHandle()
       
   127   {
       
   128     if (!isset($this->_reader))
       
   129     {
       
   130       if (!$this->_reader = fopen($this->_path, 'rb'))
       
   131       {
       
   132         throw new Swift_IoException(
       
   133           'Unable to open file for reading [' . $this->_path . ']'
       
   134         );
       
   135       }
       
   136       if ($this->_offset <> 0)
       
   137       {
       
   138         $this->_getReadStreamSeekableStatus();
       
   139         $this->_seekReadStreamToPosition($this->_offset);
       
   140       }
       
   141     }
       
   142     return $this->_reader;
       
   143   }
       
   144   
       
   145   /** Get the resource for writing */
       
   146   private function _getWriteHandle()
       
   147   {
       
   148     if (!isset($this->_writer))
       
   149     {
       
   150       if (!$this->_writer = fopen($this->_path, $this->_mode))
       
   151       {
       
   152         throw new Swift_IoException(
       
   153           'Unable to open file for writing [' . $this->_path . ']'
       
   154         );
       
   155       }
       
   156     }
       
   157     return $this->_writer;
       
   158   }
       
   159   
       
   160   /** Force a reload of the resource for reading */
       
   161   private function _resetReadHandle()
       
   162   {
       
   163     if (isset($this->_reader))
       
   164     {
       
   165       fclose($this->_reader);
       
   166       $this->_reader = null;
       
   167     }
       
   168   }
       
   169   
       
   170   /** Check if ReadOnly Stream is seekable */
       
   171   private function _getReadStreamSeekableStatus()
       
   172   {
       
   173     $metas = stream_get_meta_data($this->_reader);
       
   174     $this->_seekable = $metas['seekable'];
       
   175   }
       
   176   
       
   177   /** Streams in a readOnly stream ensuring copy if needed */
       
   178   private function _seekReadStreamToPosition($offset)
       
   179   {
       
   180     if ($this->_seekable===null)
       
   181     {
       
   182       $this->_getReadStreamSeekableStatus();
       
   183     }
       
   184     if ($this->_seekable === false)
       
   185     {
       
   186       $currentPos = ftell($this->_reader);
       
   187       if ($currentPos<$offset)
       
   188       {
       
   189         $toDiscard = $offset-$currentPos;
       
   190         fread($this->_reader, $toDiscard);
       
   191         return;
       
   192       }
       
   193       $this->_copyReadStream();
       
   194     }
       
   195     fseek($this->_reader, $offset, SEEK_SET);
       
   196   }
       
   197   
       
   198   /** Copy a readOnly Stream to ensure seekability */
       
   199   private function _copyReadStream()
       
   200   {
       
   201     if ($tmpFile = fopen('php://temp/maxmemory:4096', 'w+b'))
       
   202     {
       
   203       /* We have opened a php:// Stream Should work without problem */
       
   204     } 
       
   205     elseif (function_exists('sys_get_temp_dir') && is_writable(sys_get_temp_dir()) && ($tmpFile = tmpfile())) 
       
   206     {
       
   207       /* We have opened a tmpfile */
       
   208     } 
       
   209     else
       
   210     {
       
   211       throw new Swift_IoException('Unable to copy the file to make it seekable, sys_temp_dir is not writable, php://memory not available');
       
   212     }
       
   213     $currentPos = ftell($this->_reader);
       
   214     fclose($this->_reader);
       
   215     $source = fopen($this->_path, 'rb');
       
   216     if (!$source)
       
   217     {
       
   218       throw new Swift_IoException('Unable to open file for copying [' . $this->_path . ']');
       
   219     }
       
   220     fseek($tmpFile, 0, SEEK_SET);
       
   221     while (!feof($source)) 
       
   222     {
       
   223       fwrite($tmpFile, fread($source, 4096));
       
   224     }
       
   225     fseek($tmpFile, $currentPos, SEEK_SET);
       
   226     fclose($source);
       
   227     $this->_reader = $tmpFile;
       
   228   }
       
   229 }