TYPO3  7.6
FileByteStream.php
Go to the documentation of this file.
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 
17 {
19  private $_offset = 0;
20 
22  private $_path;
23 
25  private $_mode;
26 
28  private $_reader;
29 
31  private $_writer;
32 
34  private $_quotes = false;
35 
37  private $_seekable = null;
38 
45  public function __construct($path, $writable = false)
46  {
47  if (empty($path)) {
48  throw new Swift_IoException('The path cannot be empty');
49  }
50  $this->_path = $path;
51  $this->_mode = $writable ? 'w+b' : 'rb';
52 
53  if (function_exists('get_magic_quotes_runtime') && @get_magic_quotes_runtime() == 1) {
54  $this->_quotes = true;
55  }
56  }
57 
63  public function getPath()
64  {
65  return $this->_path;
66  }
67 
82  public function read($length)
83  {
84  $fp = $this->_getReadHandle();
85  if (!feof($fp)) {
86  if ($this->_quotes) {
87  ini_set('magic_quotes_runtime', 0);
88  }
89  $bytes = fread($fp, $length);
90  if ($this->_quotes) {
91  ini_set('magic_quotes_runtime', 1);
92  }
93  $this->_offset = ftell($fp);
94 
95  // If we read one byte after reaching the end of the file
96  // feof() will return false and an empty string is returned
97  if ($bytes === '' && feof($fp)) {
98  $this->_resetReadHandle();
99 
100  return false;
101  }
102 
103  return $bytes;
104  }
105 
106  $this->_resetReadHandle();
107 
108  return false;
109  }
110 
118  public function setReadPointer($byteOffset)
119  {
120  if (isset($this->_reader)) {
121  $this->_seekReadStreamToPosition($byteOffset);
122  }
123  $this->_offset = $byteOffset;
124  }
125 
127  protected function _commit($bytes)
128  {
129  fwrite($this->_getWriteHandle(), $bytes);
130  $this->_resetReadHandle();
131  }
132 
134  protected function _flush()
135  {
136  }
137 
139  private function _getReadHandle()
140  {
141  if (!isset($this->_reader)) {
142  if (!$this->_reader = fopen($this->_path, 'rb')) {
143  throw new Swift_IoException(
144  'Unable to open file for reading ['.$this->_path.']'
145  );
146  }
147  if ($this->_offset != 0) {
149  $this->_seekReadStreamToPosition($this->_offset);
150  }
151  }
152 
153  return $this->_reader;
154  }
155 
157  private function _getWriteHandle()
158  {
159  if (!isset($this->_writer)) {
160  if (!$this->_writer = fopen($this->_path, $this->_mode)) {
161  throw new Swift_IoException(
162  'Unable to open file for writing ['.$this->_path.']'
163  );
164  }
165  }
166 
167  return $this->_writer;
168  }
169 
171  private function _resetReadHandle()
172  {
173  if (isset($this->_reader)) {
174  fclose($this->_reader);
175  $this->_reader = null;
176  }
177  }
178 
180  private function _getReadStreamSeekableStatus()
181  {
182  $metas = stream_get_meta_data($this->_reader);
183  $this->_seekable = $metas['seekable'];
184  }
185 
187  private function _seekReadStreamToPosition($offset)
188  {
189  if ($this->_seekable === null) {
191  }
192  if ($this->_seekable === false) {
193  $currentPos = ftell($this->_reader);
194  if ($currentPos < $offset) {
195  $toDiscard = $offset - $currentPos;
196  fread($this->_reader, $toDiscard);
197 
198  return;
199  }
200  $this->_copyReadStream();
201  }
202  fseek($this->_reader, $offset, SEEK_SET);
203  }
204 
206  private function _copyReadStream()
207  {
208  if ($tmpFile = fopen('php://temp/maxmemory:4096', 'w+b')) {
209  /* We have opened a php:// Stream Should work without problem */
210  } elseif (function_exists('sys_get_temp_dir') && is_writable(sys_get_temp_dir()) && ($tmpFile = tmpfile())) {
211  /* We have opened a tmpfile */
212  } else {
213  throw new Swift_IoException('Unable to copy the file to make it seekable, sys_temp_dir is not writable, php://memory not available');
214  }
215  $currentPos = ftell($this->_reader);
216  fclose($this->_reader);
217  $source = fopen($this->_path, 'rb');
218  if (!$source) {
219  throw new Swift_IoException('Unable to open file for copying ['.$this->_path.']');
220  }
221  fseek($tmpFile, 0, SEEK_SET);
222  while (!feof($source)) {
223  fwrite($tmpFile, fread($source, 4096));
224  }
225  fseek($tmpFile, $currentPos, SEEK_SET);
226  fclose($source);
227  $this->_reader = $tmpFile;
228  }
229 }