annotate vendor/zendframework/zend-diactoros/src/Stream.php @ 13:5fb285c0d0e3

Update Drupal core to 8.4.7 via Composer. Security update; I *think* we've been lucky to get away with this so far, as we don't support self-registration which seems to be used by the so-called "drupalgeddon 2" attack that 8.4.5 was vulnerable to.
author Chris Cannam
date Mon, 23 Apr 2018 09:33:26 +0100
parents 7a779792577d
children c2387f117808
rev   line source
Chris@0 1 <?php
Chris@0 2 /**
Chris@12 3 * @see https://github.com/zendframework/zend-diactoros for the canonical source repository
Chris@12 4 * @copyright Copyright (c) 2015-2017 Zend Technologies USA Inc. (http://www.zend.com)
Chris@0 5 * @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
Chris@0 6 */
Chris@0 7
Chris@0 8 namespace Zend\Diactoros;
Chris@0 9
Chris@0 10 use InvalidArgumentException;
Chris@0 11 use RuntimeException;
Chris@0 12 use Psr\Http\Message\StreamInterface;
Chris@0 13
Chris@0 14 /**
Chris@0 15 * Implementation of PSR HTTP streams
Chris@0 16 */
Chris@0 17 class Stream implements StreamInterface
Chris@0 18 {
Chris@0 19 /**
Chris@0 20 * @var resource|null
Chris@0 21 */
Chris@0 22 protected $resource;
Chris@0 23
Chris@0 24 /**
Chris@0 25 * @var string|resource
Chris@0 26 */
Chris@0 27 protected $stream;
Chris@0 28
Chris@0 29 /**
Chris@0 30 * @param string|resource $stream
Chris@0 31 * @param string $mode Mode with which to open stream
Chris@0 32 * @throws InvalidArgumentException
Chris@0 33 */
Chris@0 34 public function __construct($stream, $mode = 'r')
Chris@0 35 {
Chris@0 36 $this->setStream($stream, $mode);
Chris@0 37 }
Chris@0 38
Chris@0 39 /**
Chris@0 40 * {@inheritdoc}
Chris@0 41 */
Chris@0 42 public function __toString()
Chris@0 43 {
Chris@0 44 if (! $this->isReadable()) {
Chris@0 45 return '';
Chris@0 46 }
Chris@0 47
Chris@0 48 try {
Chris@0 49 if ($this->isSeekable()) {
Chris@0 50 $this->rewind();
Chris@0 51 }
Chris@0 52
Chris@0 53 return $this->getContents();
Chris@0 54 } catch (RuntimeException $e) {
Chris@0 55 return '';
Chris@0 56 }
Chris@0 57 }
Chris@0 58
Chris@0 59 /**
Chris@0 60 * {@inheritdoc}
Chris@0 61 */
Chris@0 62 public function close()
Chris@0 63 {
Chris@0 64 if (! $this->resource) {
Chris@0 65 return;
Chris@0 66 }
Chris@0 67
Chris@0 68 $resource = $this->detach();
Chris@0 69 fclose($resource);
Chris@0 70 }
Chris@0 71
Chris@0 72 /**
Chris@0 73 * {@inheritdoc}
Chris@0 74 */
Chris@0 75 public function detach()
Chris@0 76 {
Chris@0 77 $resource = $this->resource;
Chris@0 78 $this->resource = null;
Chris@0 79 return $resource;
Chris@0 80 }
Chris@0 81
Chris@0 82 /**
Chris@0 83 * Attach a new stream/resource to the instance.
Chris@0 84 *
Chris@0 85 * @param string|resource $resource
Chris@0 86 * @param string $mode
Chris@0 87 * @throws InvalidArgumentException for stream identifier that cannot be
Chris@0 88 * cast to a resource
Chris@0 89 * @throws InvalidArgumentException for non-resource stream
Chris@0 90 */
Chris@0 91 public function attach($resource, $mode = 'r')
Chris@0 92 {
Chris@0 93 $this->setStream($resource, $mode);
Chris@0 94 }
Chris@0 95
Chris@0 96 /**
Chris@0 97 * {@inheritdoc}
Chris@0 98 */
Chris@0 99 public function getSize()
Chris@0 100 {
Chris@0 101 if (null === $this->resource) {
Chris@0 102 return null;
Chris@0 103 }
Chris@0 104
Chris@0 105 $stats = fstat($this->resource);
Chris@13 106 if ($stats !== false) {
Chris@13 107 return $stats['size'];
Chris@13 108 }
Chris@13 109
Chris@13 110 return null;
Chris@0 111 }
Chris@0 112
Chris@0 113 /**
Chris@0 114 * {@inheritdoc}
Chris@0 115 */
Chris@0 116 public function tell()
Chris@0 117 {
Chris@0 118 if (! $this->resource) {
Chris@0 119 throw new RuntimeException('No resource available; cannot tell position');
Chris@0 120 }
Chris@0 121
Chris@0 122 $result = ftell($this->resource);
Chris@0 123 if (! is_int($result)) {
Chris@0 124 throw new RuntimeException('Error occurred during tell operation');
Chris@0 125 }
Chris@0 126
Chris@0 127 return $result;
Chris@0 128 }
Chris@0 129
Chris@0 130 /**
Chris@0 131 * {@inheritdoc}
Chris@0 132 */
Chris@0 133 public function eof()
Chris@0 134 {
Chris@0 135 if (! $this->resource) {
Chris@0 136 return true;
Chris@0 137 }
Chris@0 138
Chris@0 139 return feof($this->resource);
Chris@0 140 }
Chris@0 141
Chris@0 142 /**
Chris@0 143 * {@inheritdoc}
Chris@0 144 */
Chris@0 145 public function isSeekable()
Chris@0 146 {
Chris@0 147 if (! $this->resource) {
Chris@0 148 return false;
Chris@0 149 }
Chris@0 150
Chris@0 151 $meta = stream_get_meta_data($this->resource);
Chris@0 152 return $meta['seekable'];
Chris@0 153 }
Chris@0 154
Chris@0 155 /**
Chris@0 156 * {@inheritdoc}
Chris@0 157 */
Chris@0 158 public function seek($offset, $whence = SEEK_SET)
Chris@0 159 {
Chris@0 160 if (! $this->resource) {
Chris@0 161 throw new RuntimeException('No resource available; cannot seek position');
Chris@0 162 }
Chris@0 163
Chris@0 164 if (! $this->isSeekable()) {
Chris@0 165 throw new RuntimeException('Stream is not seekable');
Chris@0 166 }
Chris@0 167
Chris@0 168 $result = fseek($this->resource, $offset, $whence);
Chris@0 169
Chris@0 170 if (0 !== $result) {
Chris@0 171 throw new RuntimeException('Error seeking within stream');
Chris@0 172 }
Chris@0 173
Chris@0 174 return true;
Chris@0 175 }
Chris@0 176
Chris@0 177 /**
Chris@0 178 * {@inheritdoc}
Chris@0 179 */
Chris@0 180 public function rewind()
Chris@0 181 {
Chris@0 182 return $this->seek(0);
Chris@0 183 }
Chris@0 184
Chris@0 185 /**
Chris@0 186 * {@inheritdoc}
Chris@0 187 */
Chris@0 188 public function isWritable()
Chris@0 189 {
Chris@0 190 if (! $this->resource) {
Chris@0 191 return false;
Chris@0 192 }
Chris@0 193
Chris@0 194 $meta = stream_get_meta_data($this->resource);
Chris@0 195 $mode = $meta['mode'];
Chris@0 196
Chris@0 197 return (
Chris@0 198 strstr($mode, 'x')
Chris@0 199 || strstr($mode, 'w')
Chris@0 200 || strstr($mode, 'c')
Chris@0 201 || strstr($mode, 'a')
Chris@0 202 || strstr($mode, '+')
Chris@0 203 );
Chris@0 204 }
Chris@0 205
Chris@0 206 /**
Chris@0 207 * {@inheritdoc}
Chris@0 208 */
Chris@0 209 public function write($string)
Chris@0 210 {
Chris@0 211 if (! $this->resource) {
Chris@0 212 throw new RuntimeException('No resource available; cannot write');
Chris@0 213 }
Chris@0 214
Chris@0 215 if (! $this->isWritable()) {
Chris@0 216 throw new RuntimeException('Stream is not writable');
Chris@0 217 }
Chris@0 218
Chris@0 219 $result = fwrite($this->resource, $string);
Chris@0 220
Chris@0 221 if (false === $result) {
Chris@0 222 throw new RuntimeException('Error writing to stream');
Chris@0 223 }
Chris@0 224 return $result;
Chris@0 225 }
Chris@0 226
Chris@0 227 /**
Chris@0 228 * {@inheritdoc}
Chris@0 229 */
Chris@0 230 public function isReadable()
Chris@0 231 {
Chris@0 232 if (! $this->resource) {
Chris@0 233 return false;
Chris@0 234 }
Chris@0 235
Chris@0 236 $meta = stream_get_meta_data($this->resource);
Chris@0 237 $mode = $meta['mode'];
Chris@0 238
Chris@0 239 return (strstr($mode, 'r') || strstr($mode, '+'));
Chris@0 240 }
Chris@0 241
Chris@0 242 /**
Chris@0 243 * {@inheritdoc}
Chris@0 244 */
Chris@0 245 public function read($length)
Chris@0 246 {
Chris@0 247 if (! $this->resource) {
Chris@0 248 throw new RuntimeException('No resource available; cannot read');
Chris@0 249 }
Chris@0 250
Chris@0 251 if (! $this->isReadable()) {
Chris@0 252 throw new RuntimeException('Stream is not readable');
Chris@0 253 }
Chris@0 254
Chris@0 255 $result = fread($this->resource, $length);
Chris@0 256
Chris@0 257 if (false === $result) {
Chris@0 258 throw new RuntimeException('Error reading stream');
Chris@0 259 }
Chris@0 260
Chris@0 261 return $result;
Chris@0 262 }
Chris@0 263
Chris@0 264 /**
Chris@0 265 * {@inheritdoc}
Chris@0 266 */
Chris@0 267 public function getContents()
Chris@0 268 {
Chris@0 269 if (! $this->isReadable()) {
Chris@0 270 throw new RuntimeException('Stream is not readable');
Chris@0 271 }
Chris@0 272
Chris@0 273 $result = stream_get_contents($this->resource);
Chris@0 274 if (false === $result) {
Chris@0 275 throw new RuntimeException('Error reading from stream');
Chris@0 276 }
Chris@0 277 return $result;
Chris@0 278 }
Chris@0 279
Chris@0 280 /**
Chris@0 281 * {@inheritdoc}
Chris@0 282 */
Chris@0 283 public function getMetadata($key = null)
Chris@0 284 {
Chris@0 285 if (null === $key) {
Chris@0 286 return stream_get_meta_data($this->resource);
Chris@0 287 }
Chris@0 288
Chris@0 289 $metadata = stream_get_meta_data($this->resource);
Chris@0 290 if (! array_key_exists($key, $metadata)) {
Chris@0 291 return null;
Chris@0 292 }
Chris@0 293
Chris@0 294 return $metadata[$key];
Chris@0 295 }
Chris@0 296
Chris@0 297 /**
Chris@0 298 * Set the internal stream resource.
Chris@0 299 *
Chris@0 300 * @param string|resource $stream String stream target or stream resource.
Chris@0 301 * @param string $mode Resource mode for stream target.
Chris@0 302 * @throws InvalidArgumentException for invalid streams or resources.
Chris@0 303 */
Chris@0 304 private function setStream($stream, $mode = 'r')
Chris@0 305 {
Chris@0 306 $error = null;
Chris@0 307 $resource = $stream;
Chris@0 308
Chris@0 309 if (is_string($stream)) {
Chris@0 310 set_error_handler(function ($e) use (&$error) {
Chris@0 311 $error = $e;
Chris@0 312 }, E_WARNING);
Chris@0 313 $resource = fopen($stream, $mode);
Chris@0 314 restore_error_handler();
Chris@0 315 }
Chris@0 316
Chris@0 317 if ($error) {
Chris@0 318 throw new InvalidArgumentException('Invalid stream reference provided');
Chris@0 319 }
Chris@0 320
Chris@0 321 if (! is_resource($resource) || 'stream' !== get_resource_type($resource)) {
Chris@0 322 throw new InvalidArgumentException(
Chris@0 323 'Invalid stream provided; must be a string stream identifier or stream resource'
Chris@0 324 );
Chris@0 325 }
Chris@0 326
Chris@0 327 if ($stream !== $resource) {
Chris@0 328 $this->stream = $stream;
Chris@0 329 }
Chris@0 330
Chris@0 331 $this->resource = $resource;
Chris@0 332 }
Chris@0 333 }