Skip to content
This repository has been archived by the owner on Nov 17, 2021. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
[FileByteStream] Ensure Stream is seekable before trying to seek through
this should address bug #187 and allow embedding of url altough it's clearly not recommended
  • Loading branch information
xdecock committed Mar 22, 2011
1 parent ad9f90f commit e69661c
Showing 1 changed file with 61 additions and 2 deletions.
63 changes: 61 additions & 2 deletions lib/classes/Swift/ByteStream/FileByteStream.php
Expand Up @@ -37,6 +37,9 @@ class Swift_ByteStream_FileByteStream

/** If magic_quotes_runtime is on, this will be true */
private $_quotes = false;

/** If stream is seekable true/false, or null if not known */
private $_seekable = null;

/**
* Create a new FileByteStream for $path.
Expand Down Expand Up @@ -100,7 +103,7 @@ public function setReadPointer($byteOffset)
{
if (isset($this->_reader))
{
fseek($this->_reader, $byteOffset, SEEK_SET);
$this->_seekReadStreamToPosition($byteOffset);
}
$this->_offset = $byteOffset;
}
Expand Down Expand Up @@ -130,7 +133,10 @@ private function _getReadHandle()
'Unable to open file for reading [' . $this->_path . ']'
);
}
fseek($this->_reader, $this->_offset, SEEK_SET);
if ($this->_offset <> 0) {
$this->_getReadStreamSeekableStatus();
$this->_seekReadStreamToPosition($this->_offset);
}
}
return $this->_reader;
}
Expand Down Expand Up @@ -160,4 +166,57 @@ private function _resetReadHandle()
}
}

/** Check if ReadOnly Stream is seekable */
private function _getReadStreamSeekableStatus() {
$metas = stream_get_meta_data($this->_reader);
$this->_seekable = $metas['seekable'];
}

/** Streams in a readOnly stream ensuring copy if needed */
private function _seekReadStreamToPosition($offset) {
if ($this->_seekable===null) {
$this->_getReadStreamSeekableStatus();
}
if ($this->_seekable === false) {
$currentPos = ftell($this->_reader);
if ($currentPos<$offset) {
$toDiscard = $offset-$currentPos;
fread($this->_reader, $toDiscard);
return;
}
$this->_copyReadStream();
}
fseek($this->_reader, $offset, SEEK_SET);
}

/** Copy a readOnly Stream to ensure seekability */
private function _copyReadStream() {
if ($tmpFile = fopen('php://temp/maxmemory:4096', 'w+b'))
{
/* We have opened a php:// Stream Should work without problem */
}
elseif (function_exists('sys_get_temp_dir') && is_writable(sys_get_temp_dir()) && ($tmpFile = tmpfile()))
{
/* We have opened a tmpfile */
}
else
{
throw new Swift_IoException('Unable to copy the file to make it seekable, sys_temp_dir is not writable, php://memory not available');
}
$currentPos = ftell($this->_reader);
fclose($this->_reader);
$source = fopen($this->_path, 'rb');
if (!$source)
{
throw new Swift_IoException('Unable to open file for copying [' . $this->_path . ']');
}
fseek($tmpFile, 0, SEEK_SET);
while (!feof($source))
{
fwrite($tmpFile, fread($source, 4096));
}
fseek($tmpFile, $currentPos, SEEK_SET);
fclose($source);
$this->_reader = $tmpFile;
}
}

0 comments on commit e69661c

Please sign in to comment.