/typo3/contrib/swiftmailer/classes/Swift/CharacterStream/ArrayCharacterStream.php

https://github.com/itag/TYPO3v4-Core · PHP · 319 lines · 218 code · 31 blank · 70 comment · 31 complexity · 05400d4d010f1512109d51f140e5fa77 MD5 · raw file

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