dolibarr/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream/ArrayCharacterStream.php

292 lines
8.1 KiB
PHP
Raw Permalink Normal View History

2016-04-16 18:15:03 +02:00
<?php
/*
* This file is part of SwiftMailer.
* (c) 2004-2009 Chris Corbyn
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* A CharacterStream implementation which stores characters in an internal array.
*
* @author Chris Corbyn
*/
class Swift_CharacterStream_ArrayCharacterStream implements Swift_CharacterStream
{
/** A map of byte values and their respective characters */
2018-01-21 15:55:56 +01:00
private static $charMap;
2016-04-16 18:15:03 +02:00
/** A map of characters and their derivative byte values */
2018-01-21 15:55:56 +01:00
private static $byteMap;
2016-04-16 18:15:03 +02:00
/** The char reader (lazy-loaded) for the current charset */
2018-01-21 15:55:56 +01:00
private $charReader;
2016-04-16 18:15:03 +02:00
/** A factory for creating CharacterReader instances */
2018-01-21 15:55:56 +01:00
private $charReaderFactory;
2016-04-16 18:15:03 +02:00
/** The character set this stream is using */
2018-01-21 15:55:56 +01:00
private $charset;
2016-04-16 18:15:03 +02:00
/** Array of characters */
2021-12-07 17:11:34 +01:00
private $array = [];
2016-04-16 18:15:03 +02:00
/** Size of the array of character */
2021-12-07 17:11:34 +01:00
private $array_size = [];
2016-04-16 18:15:03 +02:00
/** The current character offset in the stream */
2018-01-21 15:55:56 +01:00
private $offset = 0;
2016-04-16 18:15:03 +02:00
/**
* Create a new CharacterStream with the given $chars, if set.
*
* @param Swift_CharacterReaderFactory $factory for loading validators
* @param string $charset used in the stream
*/
public function __construct(Swift_CharacterReaderFactory $factory, $charset)
{
2018-01-21 15:55:56 +01:00
self::initializeMaps();
2016-04-16 18:15:03 +02:00
$this->setCharacterReaderFactory($factory);
$this->setCharacterSet($charset);
}
/**
* Set the character set used in this CharacterStream.
*
* @param string $charset
*/
public function setCharacterSet($charset)
{
2018-01-21 15:55:56 +01:00
$this->charset = $charset;
$this->charReader = null;
2016-04-16 18:15:03 +02:00
}
/**
* Set the CharacterReaderFactory for multi charset support.
*/
public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory)
{
2018-01-21 15:55:56 +01:00
$this->charReaderFactory = $factory;
2016-04-16 18:15:03 +02:00
}
/**
* Overwrite this character stream using the byte sequence in the byte stream.
*
* @param Swift_OutputByteStream $os output stream to read from
*/
public function importByteStream(Swift_OutputByteStream $os)
{
2018-01-21 15:55:56 +01:00
if (!isset($this->charReader)) {
$this->charReader = $this->charReaderFactory
->getReaderFor($this->charset);
2016-04-16 18:15:03 +02:00
}
2018-01-21 15:55:56 +01:00
$startLength = $this->charReader->getInitialByteSize();
2016-04-16 18:15:03 +02:00
while (false !== $bytes = $os->read($startLength)) {
2021-12-07 17:11:34 +01:00
$c = [];
for ($i = 0, $len = \strlen($bytes); $i < $len; ++$i) {
2018-01-21 15:55:56 +01:00
$c[] = self::$byteMap[$bytes[$i]];
2016-04-16 18:15:03 +02:00
}
2021-12-07 17:11:34 +01:00
$size = \count($c);
2018-01-21 15:55:56 +01:00
$need = $this->charReader
2016-04-16 18:15:03 +02:00
->validateByteSequence($c, $size);
if ($need > 0 &&
false !== $bytes = $os->read($need)) {
2021-12-07 17:11:34 +01:00
for ($i = 0, $len = \strlen($bytes); $i < $len; ++$i) {
2018-01-21 15:55:56 +01:00
$c[] = self::$byteMap[$bytes[$i]];
2016-04-16 18:15:03 +02:00
}
}
2018-01-21 15:55:56 +01:00
$this->array[] = $c;
++$this->array_size;
2016-04-16 18:15:03 +02:00
}
}
/**
* Import a string a bytes into this CharacterStream, overwriting any existing
* data in the stream.
*
* @param string $string
*/
public function importString($string)
{
$this->flushContents();
$this->write($string);
}
/**
* Read $length characters from the stream and move the internal pointer
* $length further into the stream.
*
* @param int $length
*
* @return string
*/
public function read($length)
{
2018-01-21 15:55:56 +01:00
if ($this->offset == $this->array_size) {
2016-04-16 18:15:03 +02:00
return false;
}
// Don't use array slice
2021-12-07 17:11:34 +01:00
$arrays = [];
2018-01-21 15:55:56 +01:00
$end = $length + $this->offset;
for ($i = $this->offset; $i < $end; ++$i) {
if (!isset($this->array[$i])) {
2016-04-16 18:15:03 +02:00
break;
}
2018-01-21 15:55:56 +01:00
$arrays[] = $this->array[$i];
2016-04-16 18:15:03 +02:00
}
2018-01-21 15:55:56 +01:00
$this->offset += $i - $this->offset; // Limit function calls
2016-04-16 18:15:03 +02:00
$chars = false;
foreach ($arrays as $array) {
$chars .= implode('', array_map('chr', $array));
}
return $chars;
}
/**
* Read $length characters from the stream and return a 1-dimensional array
* containing there octet values.
*
* @param int $length
*
2018-01-21 15:55:56 +01:00
* @return int[]
2016-04-16 18:15:03 +02:00
*/
public function readBytes($length)
{
2018-01-21 15:55:56 +01:00
if ($this->offset == $this->array_size) {
2016-04-16 18:15:03 +02:00
return false;
}
2021-12-07 17:11:34 +01:00
$arrays = [];
2018-01-21 15:55:56 +01:00
$end = $length + $this->offset;
for ($i = $this->offset; $i < $end; ++$i) {
if (!isset($this->array[$i])) {
2016-04-16 18:15:03 +02:00
break;
}
2018-01-21 15:55:56 +01:00
$arrays[] = $this->array[$i];
2016-04-16 18:15:03 +02:00
}
2018-01-21 15:55:56 +01:00
$this->offset += ($i - $this->offset); // Limit function calls
2016-04-16 18:15:03 +02:00
2021-12-07 17:11:34 +01:00
return array_merge(...$arrays);
2016-04-16 18:15:03 +02:00
}
/**
* Write $chars to the end of the stream.
*
* @param string $chars
*/
public function write($chars)
{
2018-01-21 15:55:56 +01:00
if (!isset($this->charReader)) {
$this->charReader = $this->charReaderFactory->getReaderFor(
$this->charset);
2016-04-16 18:15:03 +02:00
}
2018-01-21 15:55:56 +01:00
$startLength = $this->charReader->getInitialByteSize();
2016-04-16 18:15:03 +02:00
$fp = fopen('php://memory', 'w+b');
fwrite($fp, $chars);
unset($chars);
fseek($fp, 0, SEEK_SET);
2021-12-07 17:11:34 +01:00
$buffer = [0];
2016-04-16 18:15:03 +02:00
$buf_pos = 1;
$buf_len = 1;
$has_datas = true;
do {
2021-12-07 17:11:34 +01:00
$bytes = [];
2016-04-16 18:15:03 +02:00
// Buffer Filing
if ($buf_len - $buf_pos < $startLength) {
$buf = array_splice($buffer, $buf_pos);
2018-01-21 15:55:56 +01:00
$new = $this->reloadBuffer($fp, 100);
2016-04-16 18:15:03 +02:00
if ($new) {
$buffer = array_merge($buf, $new);
2021-12-07 17:11:34 +01:00
$buf_len = \count($buffer);
2016-04-16 18:15:03 +02:00
$buf_pos = 0;
} else {
$has_datas = false;
}
}
if ($buf_len - $buf_pos > 0) {
$size = 0;
for ($i = 0; $i < $startLength && isset($buffer[$buf_pos]); ++$i) {
++$size;
$bytes[] = $buffer[$buf_pos++];
}
2018-01-21 15:55:56 +01:00
$need = $this->charReader->validateByteSequence(
2016-04-16 18:15:03 +02:00
$bytes, $size);
if ($need > 0) {
if ($buf_len - $buf_pos < $need) {
2018-01-21 15:55:56 +01:00
$new = $this->reloadBuffer($fp, $need);
2016-04-16 18:15:03 +02:00
if ($new) {
$buffer = array_merge($buffer, $new);
2021-12-07 17:11:34 +01:00
$buf_len = \count($buffer);
2016-04-16 18:15:03 +02:00
}
}
for ($i = 0; $i < $need && isset($buffer[$buf_pos]); ++$i) {
$bytes[] = $buffer[$buf_pos++];
}
}
2018-01-21 15:55:56 +01:00
$this->array[] = $bytes;
++$this->array_size;
2016-04-16 18:15:03 +02:00
}
} while ($has_datas);
fclose($fp);
}
/**
* Move the internal pointer to $charOffset in the stream.
*
* @param int $charOffset
*/
public function setPointer($charOffset)
{
2018-01-21 15:55:56 +01:00
if ($charOffset > $this->array_size) {
$charOffset = $this->array_size;
2016-04-16 18:15:03 +02:00
} elseif ($charOffset < 0) {
$charOffset = 0;
}
2018-01-21 15:55:56 +01:00
$this->offset = $charOffset;
2016-04-16 18:15:03 +02:00
}
/**
* Empty the stream and reset the internal pointer.
*/
public function flushContents()
{
2018-01-21 15:55:56 +01:00
$this->offset = 0;
2021-12-07 17:11:34 +01:00
$this->array = [];
2018-01-21 15:55:56 +01:00
$this->array_size = 0;
2016-04-16 18:15:03 +02:00
}
2018-01-21 15:55:56 +01:00
private function reloadBuffer($fp, $len)
2016-04-16 18:15:03 +02:00
{
2021-12-07 17:11:34 +01:00
if (!feof($fp) && false !== ($bytes = fread($fp, $len))) {
$buf = [];
for ($i = 0, $len = \strlen($bytes); $i < $len; ++$i) {
2018-01-21 15:55:56 +01:00
$buf[] = self::$byteMap[$bytes[$i]];
2016-04-16 18:15:03 +02:00
}
return $buf;
}
return false;
}
2018-01-21 15:55:56 +01:00
private static function initializeMaps()
2016-04-16 18:15:03 +02:00
{
2018-01-21 15:55:56 +01:00
if (!isset(self::$charMap)) {
2021-12-07 17:11:34 +01:00
self::$charMap = [];
2016-04-16 18:15:03 +02:00
for ($byte = 0; $byte < 256; ++$byte) {
2021-12-07 17:11:34 +01:00
self::$charMap[$byte] = \chr($byte);
2016-04-16 18:15:03 +02:00
}
2018-01-21 15:55:56 +01:00
self::$byteMap = array_flip(self::$charMap);
2016-04-16 18:15:03 +02:00
}
}
}