1<?php 2 3/* 4 CharacterStream implementation using an array in Swift Mailer. 5 6 This program is free software: you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18 19 */ 20 21//@require 'Swift/CharacterStream.php'; 22//@require 'Swift/OutputByteStream.php'; 23 24 25/** 26 * A CharacterStream implementation which stores characters in an internal array. 27 * @package Swift 28 * @subpackage CharacterStream 29 * @author Xavier De Cock <xdecock@gmail.com> 30 */ 31 32Class Swift_CharacterStream_NgCharacterStream 33 implements Swift_CharacterStream 34{ 35 36 /** 37 * The char reader (lazy-loaded) for the current charset. 38 * @var Swift_CharacterReader 39 * @access private 40 */ 41 private $_charReader; 42 43 /** 44 * A factory for creatiing CharacterReader instances. 45 * @var Swift_CharacterReaderFactory 46 * @access private 47 */ 48 private $_charReaderFactory; 49 50 /** 51 * The character set this stream is using. 52 * @var string 53 * @access private 54 */ 55 private $_charset; 56 57 /** 58 * The datas stored as is 59 * 60 * @var string 61 */ 62 private $_datas = ""; 63 64 /** 65 * Number of bytes in the stream 66 * 67 * @var int 68 */ 69 private $_datasSize = 0; 70 71 /** 72 * Map 73 * 74 * @var mixed 75 */ 76 private $_map; 77 78 /** 79 * Map Type 80 * 81 * @var int 82 */ 83 private $_mapType = 0; 84 85 /** 86 * Number of characters in the stream 87 * 88 * @var int 89 */ 90 private $_charCount = 0; 91 92 /** 93 * Position in the stream 94 * 95 * @var unknown_type 96 */ 97 private $_currentPos = 0; 98 99 /** 100 * The constructor 101 * 102 * @param Swift_CharacterReaderFactory $factory 103 * @param unknown_type $charset 104 */ 105 public function __construct(Swift_CharacterReaderFactory $factory, 106 $charset) 107 { 108 $this->setCharacterReaderFactory($factory); 109 $this->setCharacterSet($charset); 110 } 111 112 /* -- Changing parameters of the stream -- */ 113 114 /** 115 * Set the character set used in this CharacterStream. 116 * @param string $charset 117 */ 118 public function setCharacterSet($charset) 119 { 120 $this->_charset = $charset; 121 $this->_charReader = null; 122 $this->_mapType = 0; 123 } 124 125 /** 126 * Set the CharacterReaderFactory for multi charset support. 127 * @param Swift_CharacterReaderFactory $factory 128 */ 129 public function setCharacterReaderFactory( 130 Swift_CharacterReaderFactory $factory) 131 { 132 $this->_charReaderFactory = $factory; 133 } 134 135 /** 136 * @see Swift_CharacterStream::flushContents() 137 * 138 */ 139 public function flushContents() 140 { 141 $this->_datas = null; 142 $this->_map = null; 143 $this->_charCount = 0; 144 $this->_currentPos = 0; 145 $this->_datasSize = 0; 146 } 147 148 /** 149 * @see Swift_CharacterStream::importByteStream() 150 * 151 * @param Swift_OutputByteStream $os 152 */ 153 public function importByteStream(Swift_OutputByteStream $os) 154 { 155 $this->flushContents(); 156 $blocks=512; 157 $os->setReadPointer(0); 158 while(false!==($read = $os->read($blocks))) 159 $this->write($read); 160 } 161 162 /** 163 * @see Swift_CharacterStream::importString() 164 * 165 * @param string $string 166 */ 167 public function importString($string) 168 { 169 $this->flushContents(); 170 $this->write($string); 171 } 172 173 /** 174 * @see Swift_CharacterStream::read() 175 * 176 * @param int $length 177 * @return string 178 */ 179 public function read($length) 180 { 181 if ($this->_currentPos>=$this->_charCount) 182 { 183 return false; 184 } 185 $ret=false; 186 $length = ($this->_currentPos+$length > $this->_charCount) 187 ? $this->_charCount - $this->_currentPos 188 : $length; 189 switch ($this->_mapType) 190 { 191 case Swift_CharacterReader::MAP_TYPE_FIXED_LEN: 192 $len = $length*$this->_map; 193 $ret = substr($this->_datas, 194 $this->_currentPos * $this->_map, 195 $len); 196 $this->_currentPos += $length; 197 break; 198 199 case Swift_CharacterReader::MAP_TYPE_INVALID: 200 $end = $this->_currentPos + $length; 201 $end = $end > $this->_charCount 202 ?$this->_charCount 203 :$end; 204 $ret = ''; 205 for (; $this->_currentPos < $length; ++$this->_currentPos) 206 { 207 if (isset ($this->_map[$this->_currentPos])) 208 { 209 $ret .= '?'; 210 } 211 else 212 { 213 $ret .= $this->_datas[$this->_currentPos]; 214 } 215 } 216 break; 217 218 case Swift_CharacterReader::MAP_TYPE_POSITIONS: 219 $end = $this->_currentPos + $length; 220 $end = $end > $this->_charCount 221 ?$this->_charCount 222 :$end; 223 $ret = ''; 224 $start = 0; 225 if ($this->_currentPos>0) 226 { 227 $start = $this->_map['p'][$this->_currentPos-1]; 228 } 229 $to = $start; 230 for (; $this->_currentPos < $end; ++$this->_currentPos) 231 { 232 if (isset($this->_map['i'][$this->_currentPos])) { 233 $ret .= substr($this->_datas, $start, $to - $start).'?'; 234 $start = $this->_map['p'][$this->_currentPos]; 235 } else { 236 $to = $this->_map['p'][$this->_currentPos]; 237 } 238 } 239 $ret .= substr($this->_datas, $start, $to - $start); 240 break; 241 } 242 return $ret; 243 } 244 245 /** 246 * @see Swift_CharacterStream::readBytes() 247 * 248 * @param int $length 249 * @return int[] 250 */ 251 public function readBytes($length) 252 { 253 $read=$this->read($length); 254 if ($read!==false) 255 { 256 $ret = array_map('ord', str_split($read, 1)); 257 return $ret; 258 } 259 return false; 260 } 261 262 /** 263 * @see Swift_CharacterStream::setPointer() 264 * 265 * @param int $charOffset 266 */ 267 public function setPointer($charOffset) 268 { 269 if ($this->_charCount<$charOffset){ 270 $charOffset=$this->_charCount; 271 } 272 $this->_currentPos = $charOffset; 273 } 274 275 /** 276 * @see Swift_CharacterStream::write() 277 * 278 * @param string $chars 279 */ 280 public function write($chars) 281 { 282 if (!isset($this->_charReader)) 283 { 284 $this->_charReader = $this->_charReaderFactory->getReaderFor( 285 $this->_charset); 286 $this->_map = array(); 287 $this->_mapType = $this->_charReader->getMapType(); 288 } 289 $ignored=''; 290 $this->_datas .= $chars; 291 $this->_charCount += $this->_charReader->getCharPositions(substr($this->_datas, $this->_datasSize), $this->_datasSize, $this->_map, $ignored); 292 if ($ignored!==false) { 293 $this->_datasSize=strlen($this->_datas)-strlen($ignored); 294 } 295 else 296 { 297 $this->_datasSize=strlen($this->_datas); 298 } 299 } 300}