Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

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