1<?php
2
3namespace Safe;
4
5use Safe\Exceptions\StreamException;
6
7/**
8 * Sets parameters on the specified context.
9 *
10 * @param resource $stream_or_context The stream or context to apply the parameters too.
11 * @param array $params An array of parameters to set.
12 *
13 * params should be an associative array of the structure:
14 * $params['paramname'] = "paramvalue";.
15 * @throws StreamException
16 *
17 */
18function stream_context_set_params($stream_or_context, array $params): void
19{
20    error_clear_last();
21    $result = \stream_context_set_params($stream_or_context, $params);
22    if ($result === false) {
23        throw StreamException::createFromPhpError();
24    }
25}
26
27
28/**
29 * Makes a copy of up to maxlength bytes
30 * of data from the current position (or from the
31 * offset position, if specified) in
32 * source to dest. If
33 * maxlength is not specified, all remaining content in
34 * source will be copied.
35 *
36 * @param resource $source The source stream
37 * @param resource $dest The destination stream
38 * @param int $maxlength Maximum bytes to copy
39 * @param int $offset The offset where to start to copy data
40 * @return int Returns the total count of bytes copied.
41 * @throws StreamException
42 *
43 */
44function stream_copy_to_stream($source, $dest, int $maxlength = -1, int $offset = 0): int
45{
46    error_clear_last();
47    $result = \stream_copy_to_stream($source, $dest, $maxlength, $offset);
48    if ($result === false) {
49        throw StreamException::createFromPhpError();
50    }
51    return $result;
52}
53
54
55/**
56 * Adds filtername to the list of filters
57 * attached to stream.
58 *
59 * @param resource $stream The target stream.
60 * @param string $filtername The filter name.
61 * @param int $read_write By default, stream_filter_append will
62 * attach the filter to the read filter chain
63 * if the file was opened for reading (i.e. File Mode:
64 * r, and/or +).  The filter
65 * will also be attached to the write filter chain
66 * if the file was opened for writing (i.e. File Mode:
67 * w, a, and/or +).
68 * STREAM_FILTER_READ,
69 * STREAM_FILTER_WRITE, and/or
70 * STREAM_FILTER_ALL can also be passed to the
71 * read_write parameter to override this behavior.
72 * @param mixed $params This filter will be added with the specified
73 * params to the end of
74 * the list and will therefore be called last during stream operations.
75 * To add a filter to the beginning of the list, use
76 * stream_filter_prepend.
77 * @return resource Returns a resource on success. The resource can be
78 * used to refer to this filter instance during a call to
79 * stream_filter_remove.
80 *
81 * FALSE is returned if stream is not a resource or
82 * if filtername cannot be located.
83 * @throws StreamException
84 *
85 */
86function stream_filter_append($stream, string $filtername, int $read_write = null, $params = null)
87{
88    error_clear_last();
89    if ($params !== null) {
90        $result = \stream_filter_append($stream, $filtername, $read_write, $params);
91    } elseif ($read_write !== null) {
92        $result = \stream_filter_append($stream, $filtername, $read_write);
93    } else {
94        $result = \stream_filter_append($stream, $filtername);
95    }
96    if ($result === false) {
97        throw StreamException::createFromPhpError();
98    }
99    return $result;
100}
101
102
103/**
104 * Adds filtername to the list of filters
105 * attached to stream.
106 *
107 * @param resource $stream The target stream.
108 * @param string $filtername The filter name.
109 * @param int $read_write By default, stream_filter_prepend will
110 * attach the filter to the read filter chain
111 * if the file was opened for reading (i.e. File Mode:
112 * r, and/or +).  The filter
113 * will also be attached to the write filter chain
114 * if the file was opened for writing (i.e. File Mode:
115 * w, a, and/or +).
116 * STREAM_FILTER_READ,
117 * STREAM_FILTER_WRITE, and/or
118 * STREAM_FILTER_ALL can also be passed to the
119 * read_write parameter to override this behavior.
120 * See stream_filter_append for an example of
121 * using this parameter.
122 * @param mixed $params This filter will be added with the specified params
123 * to the beginning of the list and will therefore be
124 * called first during stream operations.  To add a filter to the end of the
125 * list, use stream_filter_append.
126 * @return resource Returns a resource on success. The resource can be
127 * used to refer to this filter instance during a call to
128 * stream_filter_remove.
129 *
130 * FALSE is returned if stream is not a resource or
131 * if filtername cannot be located.
132 * @throws StreamException
133 *
134 */
135function stream_filter_prepend($stream, string $filtername, int $read_write = null, $params = null)
136{
137    error_clear_last();
138    if ($params !== null) {
139        $result = \stream_filter_prepend($stream, $filtername, $read_write, $params);
140    } elseif ($read_write !== null) {
141        $result = \stream_filter_prepend($stream, $filtername, $read_write);
142    } else {
143        $result = \stream_filter_prepend($stream, $filtername);
144    }
145    if ($result === false) {
146        throw StreamException::createFromPhpError();
147    }
148    return $result;
149}
150
151
152/**
153 * stream_filter_register allows you to implement
154 * your own filter on any registered stream used with all the other
155 * filesystem functions (such as fopen,
156 * fread etc.).
157 *
158 * @param string $filtername The filter name to be registered.
159 * @param string $classname To implement a filter, you need to define a class as an extension of
160 * php_user_filter with a number of member
161 * functions. When performing read/write operations on the stream
162 * to which your filter is attached, PHP will pass the data through your
163 * filter (and any other filters attached to that stream) so that the
164 * data may be modified as desired. You must implement the methods
165 * exactly as described in php_user_filter - doing
166 * otherwise will lead to undefined behaviour.
167 * @throws StreamException
168 *
169 */
170function stream_filter_register(string $filtername, string $classname): void
171{
172    error_clear_last();
173    $result = \stream_filter_register($filtername, $classname);
174    if ($result === false) {
175        throw StreamException::createFromPhpError();
176    }
177}
178
179
180/**
181 * Removes a stream filter previously added to a stream with
182 * stream_filter_prepend or
183 * stream_filter_append.  Any data remaining in the
184 * filter's internal buffer will be flushed through to the next filter before
185 * removing it.
186 *
187 * @param resource $stream_filter The stream filter to be removed.
188 * @throws StreamException
189 *
190 */
191function stream_filter_remove($stream_filter): void
192{
193    error_clear_last();
194    $result = \stream_filter_remove($stream_filter);
195    if ($result === false) {
196        throw StreamException::createFromPhpError();
197    }
198}
199
200
201/**
202 * Identical to file_get_contents, except that
203 * stream_get_contents operates on an already open
204 * stream resource and returns the remaining contents in a string, up to
205 * maxlength bytes and starting at the specified
206 * offset.
207 *
208 * @param resource $handle A stream resource (e.g. returned from fopen)
209 * @param int $maxlength The maximum bytes to read. Defaults to -1 (read all the remaining
210 * buffer).
211 * @param int $offset Seek to the specified offset before reading. If this number is negative,
212 * no seeking will occur and reading will start from the current position.
213 * @return string Returns a string.
214 * @throws StreamException
215 *
216 */
217function stream_get_contents($handle, int $maxlength = -1, int $offset = -1): string
218{
219    error_clear_last();
220    $result = \stream_get_contents($handle, $maxlength, $offset);
221    if ($result === false) {
222        throw StreamException::createFromPhpError();
223    }
224    return $result;
225}
226
227
228/**
229 * Determines if stream stream refers to a valid terminal type device.
230 * This is a more portable version of posix_isatty, since it works on Windows systems too.
231 *
232 * @param resource $stream
233 * @throws StreamException
234 *
235 */
236function stream_isatty($stream): void
237{
238    error_clear_last();
239    $result = \stream_isatty($stream);
240    if ($result === false) {
241        throw StreamException::createFromPhpError();
242    }
243}
244
245
246/**
247 * Resolve filename against the include path according to the same rules as fopen/include.
248 *
249 * @param string $filename The filename to resolve.
250 * @return string Returns a string containing the resolved absolute filename.
251 * @throws StreamException
252 *
253 */
254function stream_resolve_include_path(string $filename): string
255{
256    error_clear_last();
257    $result = \stream_resolve_include_path($filename);
258    if ($result === false) {
259        throw StreamException::createFromPhpError();
260    }
261    return $result;
262}
263
264
265/**
266 * Sets blocking or non-blocking mode on a stream.
267 *
268 * This function works for any stream that supports non-blocking mode
269 * (currently, regular files and socket streams).
270 *
271 * @param resource $stream The stream.
272 * @param bool $mode If mode is FALSE, the given stream
273 * will be switched to non-blocking mode, and if TRUE, it
274 * will be switched to blocking mode.  This affects calls like
275 * fgets and fread
276 * that read from the stream.  In non-blocking mode an
277 * fgets call will always return right away
278 * while in blocking mode it will wait for data to become available
279 * on the stream.
280 * @throws StreamException
281 *
282 */
283function stream_set_blocking($stream, bool $mode): void
284{
285    error_clear_last();
286    $result = \stream_set_blocking($stream, $mode);
287    if ($result === false) {
288        throw StreamException::createFromPhpError();
289    }
290}
291
292
293/**
294 * Sets the timeout value on stream,
295 * expressed in the sum of seconds and
296 * microseconds.
297 *
298 * When the stream times out, the 'timed_out' key of the array returned by
299 * stream_get_meta_data is set to TRUE, although no
300 * error/warning is generated.
301 *
302 * @param resource $stream The target stream.
303 * @param int $seconds The seconds part of the timeout to be set.
304 * @param int $microseconds The microseconds part of the timeout to be set.
305 * @throws StreamException
306 *
307 */
308function stream_set_timeout($stream, int $seconds, int $microseconds = 0): void
309{
310    error_clear_last();
311    $result = \stream_set_timeout($stream, $seconds, $microseconds);
312    if ($result === false) {
313        throw StreamException::createFromPhpError();
314    }
315}
316
317
318/**
319 * Accept a connection on a socket previously created by
320 * stream_socket_server.
321 *
322 * @param resource $server_socket The server socket to accept a connection from.
323 * @param float $timeout Override the default socket accept timeout. Time should be given in
324 * seconds.
325 * @param string|null $peername Will be set to the name (address) of the client which connected, if
326 * included and available from the selected transport.
327 *
328 * Can also be determined later using
329 * stream_socket_get_name.
330 * @return resource Returns a stream to the accepted socket connection.
331 * @throws StreamException
332 *
333 */
334function stream_socket_accept($server_socket, float $timeout = null, ?string &$peername = null)
335{
336    error_clear_last();
337    if ($peername !== null) {
338        $result = \stream_socket_accept($server_socket, $timeout, $peername);
339    } elseif ($timeout !== null) {
340        $result = \stream_socket_accept($server_socket, $timeout);
341    } else {
342        $result = \stream_socket_accept($server_socket);
343    }
344    if ($result === false) {
345        throw StreamException::createFromPhpError();
346    }
347    return $result;
348}
349
350
351/**
352 * Initiates a stream or datagram connection to the destination specified
353 * by remote_socket.  The type of socket created
354 * is determined by the transport specified using standard URL formatting:
355 * transport://target.  For Internet Domain sockets
356 * (AF_INET) such as TCP and UDP, the target portion
357 * of the remote_socket parameter should consist of
358 * a hostname or IP address followed by a colon and a port number.  For Unix
359 * domain sockets, the target portion should point
360 * to the socket file on the filesystem.
361 *
362 * @param string $remote_socket Address to the socket to connect to.
363 * @param int $errno Will be set to the system level error number if connection fails.
364 * @param string $errstr Will be set to the system level error message if the connection fails.
365 * @param float $timeout Number of seconds until the connect() system call
366 * should timeout.
367 *
368 *
369 * This parameter only applies when not making asynchronous
370 * connection attempts.
371 *
372 *
373 *
374 *
375 * To set a timeout for reading/writing data over the socket, use the
376 * stream_set_timeout, as the
377 * timeout only applies while making connecting
378 * the socket.
379 *
380 *
381 *
382 * To set a timeout for reading/writing data over the socket, use the
383 * stream_set_timeout, as the
384 * timeout only applies while making connecting
385 * the socket.
386 * @param int $flags Bitmask field which may be set to any combination of connection flags.
387 * Currently the select of connection flags is limited to
388 * STREAM_CLIENT_CONNECT (default),
389 * STREAM_CLIENT_ASYNC_CONNECT and
390 * STREAM_CLIENT_PERSISTENT.
391 * @param resource $context A valid context resource created with stream_context_create.
392 * @return resource On success a stream resource is returned which may
393 * be used together with the other file functions (such as
394 * fgets, fgetss,
395 * fwrite, fclose, and
396 * feof), FALSE on failure.
397 * @throws StreamException
398 *
399 */
400function stream_socket_client(string $remote_socket, int &$errno = null, string &$errstr = null, float $timeout = null, int $flags = STREAM_CLIENT_CONNECT, $context = null)
401{
402    error_clear_last();
403    if ($context !== null) {
404        $result = \stream_socket_client($remote_socket, $errno, $errstr, $timeout, $flags, $context);
405    } elseif ($flags !== STREAM_CLIENT_CONNECT) {
406        $result = \stream_socket_client($remote_socket, $errno, $errstr, $timeout, $flags);
407    } elseif ($timeout !== null) {
408        $result = \stream_socket_client($remote_socket, $errno, $errstr, $timeout);
409    } else {
410        $result = \stream_socket_client($remote_socket, $errno, $errstr);
411    }
412    if ($result === false) {
413        throw StreamException::createFromPhpError();
414    }
415    return $result;
416}
417
418
419/**
420 * stream_socket_pair creates a pair of connected,
421 * indistinguishable socket streams. This function is commonly used in IPC
422 * (Inter-Process Communication).
423 *
424 * @param int $domain The protocol family to be used: STREAM_PF_INET,
425 * STREAM_PF_INET6 or
426 * STREAM_PF_UNIX
427 * @param int $type The type of communication to be used:
428 * STREAM_SOCK_DGRAM,
429 * STREAM_SOCK_RAW,
430 * STREAM_SOCK_RDM,
431 * STREAM_SOCK_SEQPACKET or
432 * STREAM_SOCK_STREAM
433 * @param int $protocol The protocol to be used: STREAM_IPPROTO_ICMP,
434 * STREAM_IPPROTO_IP,
435 * STREAM_IPPROTO_RAW,
436 * STREAM_IPPROTO_TCP or
437 * STREAM_IPPROTO_UDP
438 * @return resource[] Returns an array with the two socket resources on success.
439 * @throws StreamException
440 *
441 */
442function stream_socket_pair(int $domain, int $type, int $protocol): iterable
443{
444    error_clear_last();
445    $result = \stream_socket_pair($domain, $type, $protocol);
446    if ($result === false) {
447        throw StreamException::createFromPhpError();
448    }
449    return $result;
450}
451
452
453/**
454 * Creates a stream or datagram socket on the specified
455 * local_socket.
456 *
457 * This function only creates a socket, to begin accepting connections
458 * use stream_socket_accept.
459 *
460 * @param string $local_socket The type of socket created is determined by the transport specified
461 * using standard URL formatting: transport://target.
462 *
463 * For Internet Domain sockets (AF_INET) such as TCP and UDP, the
464 * target portion of the
465 * remote_socket parameter should consist of a
466 * hostname or IP address followed by a colon and a port number.  For
467 * Unix domain sockets, the target portion should
468 * point to the socket file on the filesystem.
469 *
470 * Depending on the environment, Unix domain sockets may not be available.
471 * A list of available transports can be retrieved using
472 * stream_get_transports. See
473 * for a list of bulitin transports.
474 * @param int $errno If the optional errno and errstr
475 * arguments are present they will be set to indicate the actual system
476 * level error that occurred in the system-level socket(),
477 * bind(), and listen() calls. If
478 * the value returned in errno is
479 * 0 and the function returned FALSE, it is an
480 * indication that the error occurred before the bind()
481 * call. This is most likely due to a problem initializing the socket.
482 * Note that the errno and
483 * errstr arguments will always be passed by reference.
484 * @param string $errstr See errno description.
485 * @param int $flags A bitmask field which may be set to any combination of socket creation
486 * flags.
487 *
488 * For UDP sockets, you must use STREAM_SERVER_BIND as
489 * the flags parameter.
490 * @param resource $context
491 * @return resource Returns the created stream.
492 * @throws StreamException
493 *
494 */
495function stream_socket_server(string $local_socket, int &$errno = null, string &$errstr = null, int $flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $context = null)
496{
497    error_clear_last();
498    if ($context !== null) {
499        $result = \stream_socket_server($local_socket, $errno, $errstr, $flags, $context);
500    } else {
501        $result = \stream_socket_server($local_socket, $errno, $errstr, $flags);
502    }
503    if ($result === false) {
504        throw StreamException::createFromPhpError();
505    }
506    return $result;
507}
508
509
510/**
511 * Shutdowns (partially or not) a full-duplex connection.
512 *
513 * @param resource $stream An open stream (opened with stream_socket_client,
514 * for example)
515 * @param int $how One of the following constants: STREAM_SHUT_RD
516 * (disable further receptions), STREAM_SHUT_WR
517 * (disable further transmissions) or
518 * STREAM_SHUT_RDWR (disable further receptions and
519 * transmissions).
520 * @throws StreamException
521 *
522 */
523function stream_socket_shutdown($stream, int $how): void
524{
525    error_clear_last();
526    $result = \stream_socket_shutdown($stream, $how);
527    if ($result === false) {
528        throw StreamException::createFromPhpError();
529    }
530}
531
532
533/**
534 * Tells whether the stream supports locking through
535 * flock.
536 *
537 * @param resource $stream The stream to check.
538 * @throws StreamException
539 *
540 */
541function stream_supports_lock($stream): void
542{
543    error_clear_last();
544    $result = \stream_supports_lock($stream);
545    if ($result === false) {
546        throw StreamException::createFromPhpError();
547    }
548}
549
550
551/**
552 * Allows you to implement your own protocol handlers and streams for use
553 * with all the other filesystem functions (such as fopen,
554 * fread etc.).
555 *
556 * @param string $protocol The wrapper name to be registered.
557 * @param string $classname The classname which implements the protocol.
558 * @param int $flags Should be set to STREAM_IS_URL if
559 * protocol is a URL protocol. Default is 0, local
560 * stream.
561 * @throws StreamException
562 *
563 */
564function stream_wrapper_register(string $protocol, string $classname, int $flags = 0): void
565{
566    error_clear_last();
567    $result = \stream_wrapper_register($protocol, $classname, $flags);
568    if ($result === false) {
569        throw StreamException::createFromPhpError();
570    }
571}
572
573
574/**
575 * Restores a built-in wrapper previously unregistered with
576 * stream_wrapper_unregister.
577 *
578 * @param string $protocol
579 * @throws StreamException
580 *
581 */
582function stream_wrapper_restore(string $protocol): void
583{
584    error_clear_last();
585    $result = \stream_wrapper_restore($protocol);
586    if ($result === false) {
587        throw StreamException::createFromPhpError();
588    }
589}
590
591
592/**
593 * Allows you to disable an already defined stream wrapper. Once the wrapper
594 * has been disabled you may override it with a user-defined wrapper using
595 * stream_wrapper_register or reenable it later on with
596 * stream_wrapper_restore.
597 *
598 * @param string $protocol
599 * @throws StreamException
600 *
601 */
602function stream_wrapper_unregister(string $protocol): void
603{
604    error_clear_last();
605    $result = \stream_wrapper_unregister($protocol);
606    if ($result === false) {
607        throw StreamException::createFromPhpError();
608    }
609}
610