Differences Between: [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403]
1 <?php 2 /** 3 * Copyright 2009-2017 Horde LLC (http://www.horde.org/) 4 * 5 * See the enclosed file LICENSE for license information (BSD). If you 6 * did not receive this file, see http://www.horde.org/licenses/bsd. 7 * 8 * @category Horde 9 * @copyright 2009-2017 Horde LLC 10 * @license http://www.horde.org/licenses/bsd BSD 11 * @package Stream_Wrapper 12 */ 13 14 /** 15 * A stream wrapper that will combine multiple strings/streams into a single 16 * stream. 17 * 18 * @author Michael Slusarz <slusarz@horde.org> 19 * @category Horde 20 * @copyright 2009-2017 Horde LLC 21 * @license http://www.horde.org/licenses/bsd BSD 22 * @package Stream_Wrapper 23 */ 24 class Horde_Stream_Wrapper_Combine 25 { 26 /**/ 27 const WRAPPER_NAME = 'horde-stream-wrapper-combine'; 28 29 /** 30 * Context. 31 * 32 * @var resource 33 */ 34 public $context; 35 36 /** 37 * Array that holds the various streams. 38 * 39 * @var array 40 */ 41 protected $_data = array(); 42 43 /** 44 * The combined length of the stream. 45 * 46 * @var integer 47 */ 48 protected $_length = 0; 49 50 /** 51 * The current position in the string. 52 * 53 * @var integer 54 */ 55 protected $_position = 0; 56 57 /** 58 * The current position in the data array. 59 * 60 * @var integer 61 */ 62 protected $_datapos = 0; 63 64 /** 65 * Have we reached EOF? 66 * 67 * @var boolean 68 */ 69 protected $_ateof = false; 70 71 /** 72 * Unique ID tracker for the streams. 73 * 74 * @var integer 75 */ 76 private static $_id = 0; 77 78 /** 79 * Create a stream from multiple data sources. 80 * 81 * @since 2.1.0 82 * 83 * @param array $data An array of strings and/or streams to combine into 84 * a single stream. 85 * 86 * @return resource A PHP stream. 87 */ 88 public static function getStream($data) 89 { 90 if (!self::$_id) { 91 stream_wrapper_register(self::WRAPPER_NAME, __CLASS__); 92 } 93 94 return fopen( 95 self::WRAPPER_NAME . '://' . ++self::$_id, 96 'wb', 97 false, 98 stream_context_create(array( 99 self::WRAPPER_NAME => array( 100 'data' => $data 101 ) 102 )) 103 ); 104 } 105 /** 106 * @see streamWrapper::stream_open() 107 * 108 * @param string $path 109 * @param string $mode 110 * @param integer $options 111 * @param string &$opened_path 112 * 113 * @throws Exception 114 */ 115 public function stream_open($path, $mode, $options, &$opened_path) 116 { 117 $opts = stream_context_get_options($this->context); 118 119 if (isset($opts[self::WRAPPER_NAME]['data'])) { 120 $data = $opts[self::WRAPPER_NAME]['data']; 121 } elseif (isset($opts['horde-combine']['data'])) { 122 // @deprecated 123 $data = $opts['horde-combine']['data']->getData(); 124 } else { 125 throw new Exception('Use ' . __CLASS__ . '::getStream() to initialize the stream.'); 126 } 127 128 foreach ($data as $val) { 129 if (is_string($val)) { 130 $fp = fopen('php://temp', 'r+'); 131 fwrite($fp, $val); 132 } else { 133 $fp = $val; 134 } 135 136 fseek($fp, 0, SEEK_END); 137 $length = ftell($fp); 138 rewind($fp); 139 140 $this->_data[] = array( 141 'fp' => $fp, 142 'l' => $length, 143 'p' => 0 144 ); 145 146 $this->_length += $length; 147 } 148 149 return true; 150 } 151 152 /** 153 * @see streamWrapper::stream_read() 154 * 155 * @param integer $count 156 * 157 * @return mixed 158 */ 159 public function stream_read($count) 160 { 161 if ($this->stream_eof()) { 162 return false; 163 } 164 165 $out = ''; 166 $tmp = &$this->_data[$this->_datapos]; 167 168 while ($count) { 169 if (!is_resource($tmp['fp'])) { 170 return false; 171 } 172 173 $curr_read = min($count, $tmp['l'] - $tmp['p']); 174 $out .= fread($tmp['fp'], $curr_read); 175 $count -= $curr_read; 176 $this->_position += $curr_read; 177 178 if ($this->_position == $this->_length) { 179 if ($count) { 180 $this->_ateof = true; 181 break; 182 } else { 183 $tmp['p'] += $curr_read; 184 } 185 } elseif ($count) { 186 if (!isset($this->_data[++$this->_datapos])) { 187 return false; 188 } 189 $tmp = &$this->_data[$this->_datapos]; 190 rewind($tmp['fp']); 191 $tmp['p'] = 0; 192 } else { 193 $tmp['p'] += $curr_read; 194 } 195 } 196 197 return $out; 198 } 199 200 /** 201 * @see streamWrapper::stream_write() 202 * 203 * @param string $data 204 * 205 * @return integer 206 */ 207 public function stream_write($data) 208 { 209 $tmp = &$this->_data[$this->_datapos]; 210 211 $oldlen = $tmp['l']; 212 $res = fwrite($tmp['fp'], $data); 213 if ($res === false) { 214 return false; 215 } 216 217 $tmp['p'] = ftell($tmp['fp']); 218 if ($tmp['p'] > $oldlen) { 219 $tmp['l'] = $tmp['p']; 220 $this->_length += ($tmp['l'] - $oldlen); 221 } 222 223 return $res; 224 } 225 226 /** 227 * @see streamWrapper::stream_tell() 228 * 229 * @return integer 230 */ 231 public function stream_tell() 232 { 233 return $this->_position; 234 } 235 236 /** 237 * @see streamWrapper::stream_eof() 238 * 239 * @return boolean 240 */ 241 public function stream_eof() 242 { 243 return $this->_ateof; 244 } 245 246 /** 247 * @see streamWrapper::stream_stat() 248 * 249 * @return array 250 */ 251 public function stream_stat() 252 { 253 return array( 254 'dev' => 0, 255 'ino' => 0, 256 'mode' => 0, 257 'nlink' => 0, 258 'uid' => 0, 259 'gid' => 0, 260 'rdev' => 0, 261 'size' => $this->_length, 262 'atime' => 0, 263 'mtime' => 0, 264 'ctime' => 0, 265 'blksize' => 0, 266 'blocks' => 0 267 ); 268 } 269 270 /** 271 * @see streamWrapper::stream_seek() 272 * 273 * @param integer $offset 274 * @param integer $whence SEEK_SET, SEEK_CUR, or SEEK_END 275 * 276 * @return boolean 277 */ 278 public function stream_seek($offset, $whence) 279 { 280 $oldpos = $this->_position; 281 $this->_ateof = false; 282 283 switch ($whence) { 284 case SEEK_SET: 285 $offset = $offset; 286 break; 287 288 case SEEK_CUR: 289 $offset = $this->_position + $offset; 290 break; 291 292 case SEEK_END: 293 $offset = $this->_length + $offset; 294 break; 295 296 default: 297 return false; 298 } 299 300 $count = $this->_position = min($this->_length, $offset); 301 302 foreach ($this->_data as $key => $val) { 303 if ($count < $val['l']) { 304 $this->_datapos = $key; 305 $val['p'] = $count; 306 fseek($val['fp'], $count, SEEK_SET); 307 break; 308 } 309 $count -= $val['l']; 310 } 311 312 return ($oldpos != $this->_position); 313 } 314 315 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body