Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
/**
4
 * Hoa
5
 *
6
 *
7
 * @license
8
 *
9
 * New BSD License
10
 *
11
 * Copyright © 2007-2017, Hoa community. All rights reserved.
12
 *
13
 * Redistribution and use in source and binary forms, with or without
14
 * modification, are permitted provided that the following conditions are met:
15
 *     * Redistributions of source code must retain the above copyright
16
 *       notice, this list of conditions and the following disclaimer.
17
 *     * Redistributions in binary form must reproduce the above copyright
18
 *       notice, this list of conditions and the following disclaimer in the
19
 *       documentation and/or other materials provided with the distribution.
20
 *     * Neither the name of the Hoa nor the names of its contributors may be
21
 *       used to endorse or promote products derived from this software without
22
 *       specific prior written permission.
23
 *
24
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
28
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
 * POSSIBILITY OF SUCH DAMAGE.
35
 */
36
 
37
namespace Psy\Readline\Hoa;
38
 
39
/**
40
 * Stream wrapper for the `hoa://` protocol.
41
 */
42
class ProtocolWrapper
43
{
44
    /**
45
     * Opened stream as a resource.
46
     */
47
    private $_stream = null;
48
 
49
    /**
50
     * Stream name (filename).
51
     */
52
    private $_streamName = null;
53
 
54
    /**
55
     * Stream context (given by the streamWrapper class) as a resource.
56
     */
57
    public $context = null;
58
 
59
    /**
60
     * Get the real path of the given URL.
61
     * Could return false if the path cannot be reached.
62
     */
63
    public static function realPath(string $path, bool $exists = true)
64
    {
65
        return ProtocolNode::getRoot()->resolve($path, $exists);
66
    }
67
 
68
    /**
69
     * Retrieve the underlying resource.
70
     *
71
     * `$castAs` can be `STREAM_CAST_FOR_SELECT` when `stream_select` is
72
     * calling `stream_cast` or `STREAM_CAST_AS_STREAM` when `stream_cast` is
73
     * called for other uses.
74
     */
75
    public function stream_cast(int $castAs)
76
    {
77
        return null;
78
    }
79
 
80
    /**
81
     * Closes a resource.
82
     * This method is called in response to `fclose`.
83
     * All resources that were locked, or allocated, by the wrapper should be
84
     * released.
85
     */
86
    public function stream_close()
87
    {
88
        if (true === @\fclose($this->getStream())) {
89
            $this->_stream = null;
90
            $this->_streamName = null;
91
        }
92
    }
93
 
94
    /**
95
     * Tests for end-of-file on a file pointer.
96
     * This method is called in response to feof().
97
     */
98
    public function stream_eof(): bool
99
    {
100
        return \feof($this->getStream());
101
    }
102
 
103
    /**
104
     * Flush the output.
105
     * This method is called in respond to fflush().
106
     * If we have cached data in our stream but not yet stored it into the
107
     * underlying storage, we should do so now.
108
     */
109
    public function stream_flush(): bool
110
    {
111
        return \fflush($this->getStream());
112
    }
113
 
114
    /**
115
     * Advisory file locking.
116
     * This method is called in response to flock(), when file_put_contents()
117
     * (when flags contains LOCK_EX), stream_set_blocking() and when closing the
118
     * stream (LOCK_UN).
119
     *
120
     * Operation is one the following:
121
     *   * LOCK_SH to acquire a shared lock (reader) ;
122
     *   * LOCK_EX to acquire an exclusive lock (writer) ;
123
     *   * LOCK_UN to release a lock (shared or exclusive) ;
124
     *   * LOCK_NB if we don't want flock() to
125
     *     block while locking (not supported on
126
     *     Windows).
127
     */
128
    public function stream_lock(int $operation): bool
129
    {
130
        return \flock($this->getStream(), $operation);
131
    }
132
 
133
    /**
134
     * Change stream options.
135
     * This method is called to set metadata on the stream. It is called when
136
     * one of the following functions is called on a stream URL: touch, chmod,
137
     * chown or chgrp.
138
     *
139
     * Option must be one of the following constant:
140
     *   * STREAM_META_TOUCH,
141
     *   * STREAM_META_OWNER_NAME,
142
     *   * STREAM_META_OWNER,
143
     *   * STREAM_META_GROUP_NAME,
144
     *   * STREAM_META_GROUP,
145
     *   * STREAM_META_ACCESS.
146
     *
147
     * Values are arguments of `touch`, `chmod`, `chown`, and `chgrp`.
148
     */
149
    public function stream_metadata(string $path, int $option, $values): bool
150
    {
151
        $path = static::realPath($path, false);
152
 
153
        switch ($option) {
154
            case \STREAM_META_TOUCH:
155
                $arity = \count($values);
156
 
157
                if (0 === $arity) {
158
                    $out = \touch($path);
159
                } elseif (1 === $arity) {
160
                    $out = \touch($path, $values[0]);
161
                } else {
162
                    $out = \touch($path, $values[0], $values[1]);
163
                }
164
 
165
                break;
166
 
167
            case \STREAM_META_OWNER_NAME:
168
            case \STREAM_META_OWNER:
169
                $out = \chown($path, $values);
170
 
171
                break;
172
 
173
            case \STREAM_META_GROUP_NAME:
174
            case \STREAM_META_GROUP:
175
                $out = \chgrp($path, $values);
176
 
177
                break;
178
 
179
            case \STREAM_META_ACCESS:
180
                $out = \chmod($path, $values);
181
 
182
                break;
183
 
184
            default:
185
                $out = false;
186
        }
187
 
188
        return $out;
189
    }
190
 
191
    /**
192
     * Open file or URL.
193
     * This method is called immediately after the wrapper is initialized (f.e.
194
     * by fopen() and file_get_contents()).
195
     */
196
    public function stream_open(string $path, string $mode, int $options, &$openedPath): bool
197
    {
198
        $path = static::realPath($path, 'r' === $mode[0]);
199
 
200
        if (Protocol::NO_RESOLUTION === $path) {
201
            return false;
202
        }
203
 
204
        if (null === $this->context) {
205
            $openedPath = \fopen($path, $mode, $options & \STREAM_USE_PATH);
206
        } else {
207
            $openedPath = \fopen(
208
                $path,
209
                $mode,
210
                (bool) ($options & \STREAM_USE_PATH),
211
                $this->context
212
            );
213
        }
214
 
215
        if (false === \is_resource($openedPath)) {
216
            return false;
217
        }
218
 
219
        $this->_stream = $openedPath;
220
        $this->_streamName = $path;
221
 
222
        return true;
223
    }
224
 
225
    /**
226
     * Read from stream.
227
     * This method is called in response to fread() and fgets().
228
     */
229
    public function stream_read(int $size): string
230
    {
231
        return \fread($this->getStream(), $size);
232
    }
233
 
234
    /**
235
     * Seek to specific location in a stream.
236
     * This method is called in response to fseek().
237
     * The read/write position of the stream should be updated according to the
238
     * $offset and $whence.
239
     *
240
     * The possible values for `$whence` are:
241
     *   * SEEK_SET to set position equal to $offset bytes,
242
     *   * SEEK_CUR to set position to current location plus `$offset`,
243
     *   * SEEK_END to set position to end-of-file plus `$offset`.
244
     */
245
    public function stream_seek(int $offset, int $whence = \SEEK_SET): bool
246
    {
247
        return 0 === \fseek($this->getStream(), $offset, $whence);
248
    }
249
 
250
    /**
251
     * Retrieve information about a file resource.
252
     * This method is called in response to fstat().
253
     */
254
    public function stream_stat(): array
255
    {
256
        return \fstat($this->getStream());
257
    }
258
 
259
    /**
260
     * Retrieve the current position of a stream.
261
     * This method is called in response to ftell().
262
     */
263
    public function stream_tell(): int
264
    {
265
        return \ftell($this->getStream());
266
    }
267
 
268
    /**
269
     * Truncate a stream to a given length.
270
     */
271
    public function stream_truncate(int $size): bool
272
    {
273
        return \ftruncate($this->getStream(), $size);
274
    }
275
 
276
    /**
277
     * Write to stream.
278
     * This method is called in response to fwrite().
279
     */
280
    public function stream_write(string $data): int
281
    {
282
        return \fwrite($this->getStream(), $data);
283
    }
284
 
285
    /**
286
     * Close directory handle.
287
     * This method is called in to closedir().
288
     * Any resources which were locked, or allocated, during opening and use of
289
     * the directory stream should be released.
290
     */
291
    public function dir_closedir()
292
    {
293
        \closedir($this->getStream());
294
        $this->_stream = null;
295
        $this->_streamName = null;
296
    }
297
 
298
    /**
299
     * Open directory handle.
300
     * This method is called in response to opendir().
301
     *
302
     * The `$options` input represents whether or not to enforce safe_mode
303
     * (0x04). It is not used here.
304
     */
305
    public function dir_opendir(string $path, int $options): bool
306
    {
307
        $path = static::realPath($path);
308
        $handle = null;
309
 
310
        if (null === $this->context) {
311
            $handle = @\opendir($path);
312
        } else {
313
            $handle = @\opendir($path, $this->context);
314
        }
315
 
316
        if (false === $handle) {
317
            return false;
318
        }
319
 
320
        $this->_stream = $handle;
321
        $this->_streamName = $path;
322
 
323
        return true;
324
    }
325
 
326
    /**
327
     * Read entry from directory handle.
328
     * This method is called in response to readdir().
329
     *
330
     * @return mixed
331
     */
332
    public function dir_readdir()
333
    {
334
        return \readdir($this->getStream());
335
    }
336
 
337
    /**
338
     * Rewind directory handle.
339
     * This method is called in response to rewinddir().
340
     * Should reset the output generated by self::dir_readdir, i.e. the next
341
     * call to self::dir_readdir should return the first entry in the location
342
     * returned by self::dir_opendir.
343
     */
344
    public function dir_rewinddir()
345
    {
346
        \rewinddir($this->getStream());
347
    }
348
 
349
    /**
350
     * Create a directory.
351
     * This method is called in response to mkdir().
352
     */
353
    public function mkdir(string $path, int $mode, int $options): bool
354
    {
355
        if (null === $this->context) {
356
            return \mkdir(
357
                static::realPath($path, false),
358
                $mode,
359
                $options | \STREAM_MKDIR_RECURSIVE
360
            );
361
        }
362
 
363
        return \mkdir(
364
            static::realPath($path, false),
365
            $mode,
366
            (bool) ($options | \STREAM_MKDIR_RECURSIVE),
367
            $this->context
368
        );
369
    }
370
 
371
    /**
372
     * Rename a file or directory.
373
     * This method is called in response to rename().
374
     * Should attempt to rename $from to $to.
375
     */
376
    public function rename(string $from, string $to): bool
377
    {
378
        if (null === $this->context) {
379
            return \rename(static::realPath($from), static::realPath($to, false));
380
        }
381
 
382
        return \rename(
383
            static::realPath($from),
384
            static::realPath($to, false),
385
            $this->context
386
        );
387
    }
388
 
389
    /**
390
     * Remove a directory.
391
     * This method is called in response to rmdir().
392
     * The `$options` input is a bitwise mask of values. It is not used here.
393
     */
394
    public function rmdir(string $path, int $options): bool
395
    {
396
        if (null === $this->context) {
397
            return \rmdir(static::realPath($path));
398
        }
399
 
400
        return \rmdir(static::realPath($path), $this->context);
401
    }
402
 
403
    /**
404
     * Delete a file.
405
     * This method is called in response to unlink().
406
     */
407
    public function unlink(string $path): bool
408
    {
409
        if (null === $this->context) {
410
            return \unlink(static::realPath($path));
411
        }
412
 
413
        return \unlink(static::realPath($path), $this->context);
414
    }
415
 
416
    /**
417
     * Retrieve information about a file.
418
     * This method is called in response to all stat() related functions.
419
     * The `$flags` input holds additional flags set by the streams API.  It
420
     * can hold one or more of the following values OR'd together.
421
     * STREAM_URL_STAT_LINK: for resource with the ability to link to other
422
     * resource (such as an HTTP location: forward, or a filesystem
423
     * symlink). This flag specified that only information about the link
424
     * itself should be returned, not the resource pointed to by the
425
     * link. This flag is set in response to calls to lstat(), is_link(), or
426
     * filetype().  STREAM_URL_STAT_QUIET: if this flag is set, our wrapper
427
     * should not raise any errors. If this flag is not set, we are
428
     * responsible for reporting errors using the trigger_error() function
429
     * during stating of the path.
430
     */
431
    public function url_stat(string $path, int $flags)
432
    {
433
        $path = static::realPath($path);
434
 
435
        if (Protocol::NO_RESOLUTION === $path) {
436
            if ($flags & \STREAM_URL_STAT_QUIET) {
437
                return 0;
438
            } else {
439
                return \trigger_error(
440
                    'Path '.$path.' cannot be resolved.',
441
                    \E_WARNING
442
                );
443
            }
444
        }
445
 
446
        if ($flags & \STREAM_URL_STAT_LINK) {
447
            return @\lstat($path);
448
        }
449
 
450
        return @\stat($path);
451
    }
452
 
453
    /**
454
     * Get stream resource.
455
     */
456
    public function getStream()
457
    {
458
        return $this->_stream;
459
    }
460
 
461
    /**
462
     * Get stream name.
463
     */
464
    public function getStreamName()
465
    {
466
        return $this->_streamName;
467
    }
468
}
469
 
470
/*
471
 * Register the `hoa://` protocol.
472
 */
473
\stream_wrapper_register('hoa', ProtocolWrapper::class);