LDAPAccountManager/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Stream_Wrapper/Horde/Stream/Wrapper/Combine.php

316 lines
7.0 KiB
PHP

<?php
/**
* Copyright 2009-2017 Horde LLC (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (BSD). If you
* did not receive this file, see http://www.horde.org/licenses/bsd.
*
* @category Horde
* @copyright 2009-2017 Horde LLC
* @license http://www.horde.org/licenses/bsd BSD
* @package Stream_Wrapper
*/
/**
* A stream wrapper that will combine multiple strings/streams into a single
* stream.
*
* @author Michael Slusarz <slusarz@horde.org>
* @category Horde
* @copyright 2009-2017 Horde LLC
* @license http://www.horde.org/licenses/bsd BSD
* @package Stream_Wrapper
*/
class Horde_Stream_Wrapper_Combine
{
/**/
const WRAPPER_NAME = 'horde-stream-wrapper-combine';
/**
* Context.
*
* @var resource
*/
public $context;
/**
* Array that holds the various streams.
*
* @var array
*/
protected $_data = array();
/**
* The combined length of the stream.
*
* @var integer
*/
protected $_length = 0;
/**
* The current position in the string.
*
* @var integer
*/
protected $_position = 0;
/**
* The current position in the data array.
*
* @var integer
*/
protected $_datapos = 0;
/**
* Have we reached EOF?
*
* @var boolean
*/
protected $_ateof = false;
/**
* Unique ID tracker for the streams.
*
* @var integer
*/
private static $_id = 0;
/**
* Create a stream from multiple data sources.
*
* @since 2.1.0
*
* @param array $data An array of strings and/or streams to combine into
* a single stream.
*
* @return resource A PHP stream.
*/
public static function getStream($data)
{
if (!self::$_id) {
stream_wrapper_register(self::WRAPPER_NAME, __CLASS__);
}
return fopen(
self::WRAPPER_NAME . '://' . ++self::$_id,
'wb',
false,
stream_context_create(array(
self::WRAPPER_NAME => array(
'data' => $data
)
))
);
}
/**
* @see streamWrapper::stream_open()
*
* @param string $path
* @param string $mode
* @param integer $options
* @param string &$opened_path
*
* @throws Exception
*/
public function stream_open($path, $mode, $options, &$opened_path)
{
$opts = stream_context_get_options($this->context);
if (isset($opts[self::WRAPPER_NAME]['data'])) {
$data = $opts[self::WRAPPER_NAME]['data'];
} elseif (isset($opts['horde-combine']['data'])) {
// @deprecated
$data = $opts['horde-combine']['data']->getData();
} else {
throw new Exception('Use ' . __CLASS__ . '::getStream() to initialize the stream.');
}
foreach ($data as $val) {
if (is_string($val)) {
$fp = fopen('php://temp', 'r+');
fwrite($fp, $val);
} else {
$fp = $val;
}
fseek($fp, 0, SEEK_END);
$length = ftell($fp);
rewind($fp);
$this->_data[] = array(
'fp' => $fp,
'l' => $length,
'p' => 0
);
$this->_length += $length;
}
return true;
}
/**
* @see streamWrapper::stream_read()
*
* @param integer $count
*
* @return mixed
*/
public function stream_read($count)
{
if ($this->stream_eof()) {
return false;
}
$out = '';
$tmp = &$this->_data[$this->_datapos];
while ($count) {
if (!is_resource($tmp['fp'])) {
return false;
}
$curr_read = min($count, $tmp['l'] - $tmp['p']);
$out .= fread($tmp['fp'], $curr_read);
$count -= $curr_read;
$this->_position += $curr_read;
if ($this->_position == $this->_length) {
if ($count) {
$this->_ateof = true;
break;
} else {
$tmp['p'] += $curr_read;
}
} elseif ($count) {
if (!isset($this->_data[++$this->_datapos])) {
return false;
}
$tmp = &$this->_data[$this->_datapos];
rewind($tmp['fp']);
$tmp['p'] = 0;
} else {
$tmp['p'] += $curr_read;
}
}
return $out;
}
/**
* @see streamWrapper::stream_write()
*
* @param string $data
*
* @return integer
*/
public function stream_write($data)
{
$tmp = &$this->_data[$this->_datapos];
$oldlen = $tmp['l'];
$res = fwrite($tmp['fp'], $data);
if ($res === false) {
return false;
}
$tmp['p'] = ftell($tmp['fp']);
if ($tmp['p'] > $oldlen) {
$tmp['l'] = $tmp['p'];
$this->_length += ($tmp['l'] - $oldlen);
}
return $res;
}
/**
* @see streamWrapper::stream_tell()
*
* @return integer
*/
public function stream_tell()
{
return $this->_position;
}
/**
* @see streamWrapper::stream_eof()
*
* @return boolean
*/
public function stream_eof()
{
return $this->_ateof;
}
/**
* @see streamWrapper::stream_stat()
*
* @return array
*/
public function stream_stat()
{
return array(
'dev' => 0,
'ino' => 0,
'mode' => 0,
'nlink' => 0,
'uid' => 0,
'gid' => 0,
'rdev' => 0,
'size' => $this->_length,
'atime' => 0,
'mtime' => 0,
'ctime' => 0,
'blksize' => 0,
'blocks' => 0
);
}
/**
* @see streamWrapper::stream_seek()
*
* @param integer $offset
* @param integer $whence SEEK_SET, SEEK_CUR, or SEEK_END
*
* @return boolean
*/
public function stream_seek($offset, $whence)
{
$oldpos = $this->_position;
$this->_ateof = false;
switch ($whence) {
case SEEK_SET:
$offset = $offset;
break;
case SEEK_CUR:
$offset = $this->_position + $offset;
break;
case SEEK_END:
$offset = $this->_length + $offset;
break;
default:
return false;
}
$count = $this->_position = min($this->_length, $offset);
foreach ($this->_data as $key => $val) {
if ($count < $val['l']) {
$this->_datapos = $key;
$val['p'] = $count;
fseek($val['fp'], $count, SEEK_SET);
break;
}
$count -= $val['l'];
}
return ($oldpos != $this->_position);
}
}