vendor/swiftmailer/lib/classes/Swift/CharacterStream/ArrayCharacterStream.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 /**
       
    14  * A CharacterStream implementation which stores characters in an internal array.
       
    15  * @package Swift
       
    16  * @subpackage CharacterStream
       
    17  * @author Chris Corbyn
       
    18  */
       
    19 class Swift_CharacterStream_ArrayCharacterStream
       
    20   implements Swift_CharacterStream
       
    21 {
       
    22   
       
    23   /** A map of byte values and their respective characters */
       
    24   private static $_charMap;
       
    25   
       
    26   /** A map of characters and their derivative byte values */
       
    27   private static $_byteMap;
       
    28   
       
    29   /** The char reader (lazy-loaded) for the current charset */
       
    30   private $_charReader;
       
    31 
       
    32   /** A factory for creatiing CharacterReader instances */
       
    33   private $_charReaderFactory;
       
    34 
       
    35   /** The character set this stream is using */
       
    36   private $_charset;
       
    37 
       
    38   /** Array of characters */
       
    39   private $_array = array();
       
    40 
       
    41   /** Size of the array of character */
       
    42   private $_array_size = array();
       
    43 
       
    44   /** The current character offset in the stream */
       
    45   private $_offset = 0;
       
    46 
       
    47   /**
       
    48    * Create a new CharacterStream with the given $chars, if set.
       
    49    * @param Swift_CharacterReaderFactory $factory for loading validators
       
    50    * @param string $charset used in the stream
       
    51    */
       
    52   public function __construct(Swift_CharacterReaderFactory $factory,
       
    53     $charset)
       
    54   {
       
    55     self::_initializeMaps();
       
    56     $this->setCharacterReaderFactory($factory);
       
    57     $this->setCharacterSet($charset);
       
    58   }
       
    59 
       
    60   /**
       
    61    * Set the character set used in this CharacterStream.
       
    62    * @param string $charset
       
    63    */
       
    64   public function setCharacterSet($charset)
       
    65   {
       
    66     $this->_charset = $charset;
       
    67     $this->_charReader = null;
       
    68   }
       
    69 
       
    70   /**
       
    71    * Set the CharacterReaderFactory for multi charset support.
       
    72    * @param Swift_CharacterReaderFactory $factory
       
    73    */
       
    74   public function setCharacterReaderFactory(
       
    75     Swift_CharacterReaderFactory $factory)
       
    76   {
       
    77     $this->_charReaderFactory = $factory;
       
    78   }
       
    79 
       
    80   /**
       
    81    * Overwrite this character stream using the byte sequence in the byte stream.
       
    82    * @param Swift_OutputByteStream $os output stream to read from
       
    83    */
       
    84   public function importByteStream(Swift_OutputByteStream $os)
       
    85   {
       
    86     if (!isset($this->_charReader))
       
    87     {
       
    88       $this->_charReader = $this->_charReaderFactory
       
    89         ->getReaderFor($this->_charset);
       
    90     }
       
    91 
       
    92     $startLength = $this->_charReader->getInitialByteSize();
       
    93     while (false !== $bytes = $os->read($startLength))
       
    94     {
       
    95       $c = array();
       
    96       for ($i = 0, $len = strlen($bytes); $i < $len; ++$i)
       
    97       {
       
    98         $c[] = self::$_byteMap[$bytes[$i]];
       
    99       }
       
   100       $size = count($c);
       
   101       $need = $this->_charReader
       
   102         ->validateByteSequence($c, $size);
       
   103       if ($need > 0 &&
       
   104         false !== $bytes = $os->read($need))
       
   105       {
       
   106         for ($i = 0, $len = strlen($bytes); $i < $len; ++$i)
       
   107         {
       
   108           $c[] = self::$_byteMap[$bytes[$i]];
       
   109         }
       
   110       }
       
   111       $this->_array[] = $c;
       
   112       ++$this->_array_size;
       
   113     }
       
   114   }
       
   115 
       
   116   /**
       
   117    * Import a string a bytes into this CharacterStream, overwriting any existing
       
   118    * data in the stream.
       
   119    * @param string $string
       
   120    */
       
   121   public function importString($string)
       
   122   {
       
   123     $this->flushContents();
       
   124     $this->write($string);
       
   125   }
       
   126 
       
   127   /**
       
   128    * Read $length characters from the stream and move the internal pointer
       
   129    * $length further into the stream.
       
   130    * @param int $length
       
   131    * @return string
       
   132    */
       
   133   public function read($length)
       
   134   {
       
   135     if ($this->_offset == $this->_array_size)
       
   136     {
       
   137       return false;
       
   138     }
       
   139 
       
   140     // Don't use array slice
       
   141     $arrays = array();
       
   142     $end = $length + $this->_offset;
       
   143     for ($i = $this->_offset; $i < $end; ++$i)
       
   144     {
       
   145       if (!isset($this->_array[$i]))
       
   146       {
       
   147         break;
       
   148       }
       
   149       $arrays[] = $this->_array[$i];
       
   150     }
       
   151     $this->_offset += $i - $this->_offset; // Limit function calls
       
   152     $chars = false;
       
   153     foreach ($arrays as $array)
       
   154     {
       
   155       $chars .= implode('', array_map('chr', $array));
       
   156     }
       
   157     return $chars;
       
   158   }
       
   159 
       
   160   /**
       
   161    * Read $length characters from the stream and return a 1-dimensional array
       
   162    * containing there octet values.
       
   163    * @param int $length
       
   164    * @return int[]
       
   165    */
       
   166   public function readBytes($length)
       
   167   {
       
   168     if ($this->_offset == $this->_array_size)
       
   169     {
       
   170       return false;
       
   171     }
       
   172     $arrays = array();
       
   173     $end = $length + $this->_offset;
       
   174     for ($i = $this->_offset; $i < $end; ++$i)
       
   175     {
       
   176       if (!isset($this->_array[$i]))
       
   177       {
       
   178         break;
       
   179       }
       
   180       $arrays[] = $this->_array[$i];
       
   181     }
       
   182     $this->_offset += ($i - $this->_offset); // Limit function calls
       
   183     return call_user_func_array('array_merge', $arrays);
       
   184   }
       
   185 
       
   186   /**
       
   187    * Write $chars to the end of the stream.
       
   188    * @param string $chars
       
   189    */
       
   190   public function write($chars)
       
   191   {
       
   192     if (!isset($this->_charReader))
       
   193     {
       
   194       $this->_charReader = $this->_charReaderFactory->getReaderFor(
       
   195         $this->_charset);
       
   196     }
       
   197 
       
   198     $startLength = $this->_charReader->getInitialByteSize();
       
   199 
       
   200     $fp = fopen('php://memory', 'w+b');
       
   201     fwrite($fp, $chars);
       
   202     unset($chars);
       
   203     fseek($fp, 0, SEEK_SET);
       
   204 
       
   205     $buffer = array(0);
       
   206     $buf_pos = 1;
       
   207     $buf_len = 1;
       
   208     $has_datas = true;
       
   209     do
       
   210     {
       
   211       $bytes = array();
       
   212       // Buffer Filing
       
   213       if ($buf_len - $buf_pos < $startLength)
       
   214       {
       
   215         $buf = array_splice($buffer, $buf_pos);
       
   216         $new = $this->_reloadBuffer($fp, 100);
       
   217         if ($new)
       
   218         {
       
   219           $buffer = array_merge($buf, $new);
       
   220           $buf_len = count($buffer);
       
   221           $buf_pos = 0;
       
   222         }
       
   223         else
       
   224         {
       
   225           $has_datas = false;
       
   226         }
       
   227       }
       
   228       if ($buf_len - $buf_pos > 0)
       
   229       {
       
   230         $size = 0;
       
   231         for ($i = 0; $i < $startLength && isset($buffer[$buf_pos]); ++$i)
       
   232         {
       
   233           ++$size;
       
   234           $bytes[] = $buffer[$buf_pos++];
       
   235         }
       
   236         $need = $this->_charReader->validateByteSequence(
       
   237           $bytes, $size);
       
   238         if ($need > 0)
       
   239         {
       
   240           if ($buf_len - $buf_pos < $need)
       
   241           {
       
   242             $new = $this->_reloadBuffer($fp, $need);
       
   243             
       
   244             if ($new)
       
   245             {
       
   246               $buffer = array_merge($buffer, $new);
       
   247               $buf_len = count($buffer);
       
   248             }
       
   249           }
       
   250           for ($i = 0; $i < $need && isset($buffer[$buf_pos]); ++$i)
       
   251           {
       
   252             $bytes[] = $buffer[$buf_pos++];
       
   253           }
       
   254         }
       
   255         $this->_array[] = $bytes;
       
   256         ++$this->_array_size;
       
   257       }
       
   258     }
       
   259     while ($has_datas);
       
   260     
       
   261     fclose($fp);
       
   262   }
       
   263 
       
   264   /**
       
   265    * Move the internal pointer to $charOffset in the stream.
       
   266    * @param int $charOffset
       
   267    */
       
   268   public function setPointer($charOffset)
       
   269   {
       
   270     if ($charOffset > $this->_array_size)
       
   271     {
       
   272       $charOffset = $this->_array_size;
       
   273     }
       
   274     elseif ($charOffset < 0)
       
   275     {
       
   276       $charOffset = 0;
       
   277     }
       
   278     $this->_offset = $charOffset;
       
   279   }
       
   280 
       
   281   /**
       
   282    * Empty the stream and reset the internal pointer.
       
   283    */
       
   284   public function flushContents()
       
   285   {
       
   286     $this->_offset = 0;
       
   287     $this->_array = array();
       
   288     $this->_array_size = 0;
       
   289   }
       
   290   
       
   291   private function _reloadBuffer($fp, $len)
       
   292   {
       
   293     if (!feof($fp) && ($bytes = fread($fp, $len)) !== false)
       
   294     {
       
   295       $buf = array();
       
   296       for ($i = 0, $len = strlen($bytes); $i < $len; ++$i)
       
   297       {
       
   298         $buf[] = self::$_byteMap[$bytes[$i]];
       
   299       }
       
   300       return $buf;
       
   301     }
       
   302     return false;
       
   303   }
       
   304   
       
   305   private static function _initializeMaps()
       
   306   {
       
   307     if (!isset(self::$_charMap))
       
   308     {
       
   309       self::$_charMap = array();
       
   310       for ($byte = 0; $byte < 256; ++$byte)
       
   311       {
       
   312         self::$_charMap[$byte] = chr($byte);
       
   313       }
       
   314       self::$_byteMap = array_flip(self::$_charMap);
       
   315     }
       
   316   }
       
   317 }