This source file includes following definitions.
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- stream_array_to_fd_set
- stream_array_from_fd_set
- stream_array_emulate_read_fd_set
- PHP_FUNCTION
- user_space_stream_notifier
- user_space_stream_notifier_dtor
- parse_context_options
- parse_context_params
- decode_context_param
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- apply_filter_to_stream
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include "php.h"
23 #include "php_globals.h"
24 #include "ext/standard/flock_compat.h"
25 #include "ext/standard/file.h"
26 #include "ext/standard/php_filestat.h"
27 #include "php_open_temporary_file.h"
28 #include "ext/standard/basic_functions.h"
29 #include "php_ini.h"
30 #include "streamsfuncs.h"
31 #include "php_network.h"
32 #include "php_string.h"
33
34 #ifndef PHP_WIN32
35 #define php_select(m, r, w, e, t) select(m, r, w, e, t)
36 typedef unsigned long long php_timeout_ull;
37 #else
38 #include "win32/select.h"
39 #include "win32/sockets.h"
40 typedef unsigned __int64 php_timeout_ull;
41 #endif
42
43 #define GET_CTX_OPT(stream, wrapper, name, val) (PHP_STREAM_CONTEXT(stream) && NULL != (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), wrapper, name)))
44
45 static php_stream_context *decode_context_param(zval *contextresource);
46
47
48
49 #if HAVE_SOCKETPAIR
50
51
52 PHP_FUNCTION(stream_socket_pair)
53 {
54 zend_long domain, type, protocol;
55 php_stream *s1, *s2;
56 php_socket_t pair[2];
57
58 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "lll",
59 &domain, &type, &protocol)) {
60 RETURN_FALSE;
61 }
62
63 if (0 != socketpair((int)domain, (int)type, (int)protocol, pair)) {
64 char errbuf[256];
65 php_error_docref(NULL, E_WARNING, "failed to create sockets: [%d]: %s",
66 php_socket_errno(), php_socket_strerror(php_socket_errno(), errbuf, sizeof(errbuf)));
67 RETURN_FALSE;
68 }
69
70 array_init(return_value);
71
72 s1 = php_stream_sock_open_from_socket(pair[0], 0);
73 s2 = php_stream_sock_open_from_socket(pair[1], 0);
74
75
76
77 php_stream_auto_cleanup(s1);
78 php_stream_auto_cleanup(s2);
79
80 add_next_index_resource(return_value, s1->res);
81 add_next_index_resource(return_value, s2->res);
82 }
83
84 #endif
85
86
87
88 PHP_FUNCTION(stream_socket_client)
89 {
90 zend_string *host;
91 zval *zerrno = NULL, *zerrstr = NULL, *zcontext = NULL;
92 double timeout = (double)FG(default_socket_timeout);
93 php_timeout_ull conv;
94 struct timeval tv;
95 char *hashkey = NULL;
96 php_stream *stream = NULL;
97 int err;
98 zend_long flags = PHP_STREAM_CLIENT_CONNECT;
99 zend_string *errstr = NULL;
100 php_stream_context *context = NULL;
101
102 RETVAL_FALSE;
103
104 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|z/z/dlr", &host, &zerrno, &zerrstr, &timeout, &flags, &zcontext) == FAILURE) {
105 RETURN_FALSE;
106 }
107
108 context = php_stream_context_from_zval(zcontext, flags & PHP_FILE_NO_DEFAULT_CONTEXT);
109
110 if (flags & PHP_STREAM_CLIENT_PERSISTENT) {
111 spprintf(&hashkey, 0, "stream_socket_client__%s", ZSTR_VAL(host));
112 }
113
114
115 conv = (php_timeout_ull) (timeout * 1000000.0);
116 #ifdef PHP_WIN32
117 tv.tv_sec = (long)(conv / 1000000);
118 tv.tv_usec =(long)(conv % 1000000);
119 #else
120 tv.tv_sec = conv / 1000000;
121 tv.tv_usec = conv % 1000000;
122 #endif
123 if (zerrno) {
124 zval_dtor(zerrno);
125 ZVAL_LONG(zerrno, 0);
126 }
127 if (zerrstr) {
128 zval_dtor(zerrstr);
129 ZVAL_EMPTY_STRING(zerrstr);
130 }
131
132 stream = php_stream_xport_create(ZSTR_VAL(host), ZSTR_LEN(host), REPORT_ERRORS,
133 STREAM_XPORT_CLIENT | (flags & PHP_STREAM_CLIENT_CONNECT ? STREAM_XPORT_CONNECT : 0) |
134 (flags & PHP_STREAM_CLIENT_ASYNC_CONNECT ? STREAM_XPORT_CONNECT_ASYNC : 0),
135 hashkey, &tv, context, &errstr, &err);
136
137
138 if (stream == NULL) {
139
140 zend_string *quoted_host = php_addslashes(host, 0);
141
142 php_error_docref(NULL, E_WARNING, "unable to connect to %s (%s)", ZSTR_VAL(quoted_host), errstr == NULL ? "Unknown error" : ZSTR_VAL(errstr));
143 zend_string_release(quoted_host);
144 }
145
146 if (hashkey) {
147 efree(hashkey);
148 }
149
150 if (stream == NULL) {
151 if (zerrno) {
152 zval_dtor(zerrno);
153 ZVAL_LONG(zerrno, err);
154 }
155 if (zerrstr && errstr) {
156 zval_dtor(zerrstr);
157 ZVAL_STR(zerrstr, errstr);
158 } else if (errstr) {
159 zend_string_release(errstr);
160 }
161 RETURN_FALSE;
162 }
163
164 if (errstr) {
165 zend_string_release(errstr);
166 }
167
168 php_stream_to_zval(stream, return_value);
169
170 }
171
172
173
174
175 PHP_FUNCTION(stream_socket_server)
176 {
177 char *host;
178 size_t host_len;
179 zval *zerrno = NULL, *zerrstr = NULL, *zcontext = NULL;
180 php_stream *stream = NULL;
181 int err = 0;
182 zend_long flags = STREAM_XPORT_BIND | STREAM_XPORT_LISTEN;
183 zend_string *errstr = NULL;
184 php_stream_context *context = NULL;
185
186 RETVAL_FALSE;
187
188 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|z/z/lr", &host, &host_len, &zerrno, &zerrstr, &flags, &zcontext) == FAILURE) {
189 RETURN_FALSE;
190 }
191
192 context = php_stream_context_from_zval(zcontext, flags & PHP_FILE_NO_DEFAULT_CONTEXT);
193
194 if (context) {
195 GC_REFCOUNT(context->res)++;
196 }
197
198 if (zerrno) {
199 zval_dtor(zerrno);
200 ZVAL_LONG(zerrno, 0);
201 }
202 if (zerrstr) {
203 zval_dtor(zerrstr);
204 ZVAL_EMPTY_STRING(zerrstr);
205 }
206
207 stream = php_stream_xport_create(host, host_len, REPORT_ERRORS,
208 STREAM_XPORT_SERVER | (int)flags,
209 NULL, NULL, context, &errstr, &err);
210
211 if (stream == NULL) {
212 php_error_docref(NULL, E_WARNING, "unable to connect to %s (%s)", host, errstr == NULL ? "Unknown error" : ZSTR_VAL(errstr));
213 }
214
215 if (stream == NULL) {
216 if (zerrno) {
217 zval_dtor(zerrno);
218 ZVAL_LONG(zerrno, err);
219 }
220 if (zerrstr && errstr) {
221 zval_dtor(zerrstr);
222 ZVAL_STR(zerrstr, errstr);
223 } else if (errstr) {
224 zend_string_release(errstr);
225 }
226 RETURN_FALSE;
227 }
228
229 if (errstr) {
230 zend_string_release(errstr);
231 }
232
233 php_stream_to_zval(stream, return_value);
234 }
235
236
237
238
239 PHP_FUNCTION(stream_socket_accept)
240 {
241 double timeout = (double)FG(default_socket_timeout);
242 zval *zpeername = NULL;
243 zend_string *peername = NULL;
244 php_timeout_ull conv;
245 struct timeval tv;
246 php_stream *stream = NULL, *clistream = NULL;
247 zval *zstream;
248 zend_string *errstr = NULL;
249
250 #ifndef FAST_ZPP
251 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|dz/", &zstream, &timeout, &zpeername) == FAILURE) {
252 RETURN_FALSE;
253 }
254 #else
255 ZEND_PARSE_PARAMETERS_START(1, 3)
256 Z_PARAM_RESOURCE(zstream)
257 Z_PARAM_OPTIONAL
258 Z_PARAM_DOUBLE(timeout)
259 Z_PARAM_ZVAL_EX(zpeername, 0, 1)
260 ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
261 #endif
262
263 php_stream_from_zval(stream, zstream);
264
265
266 conv = (php_timeout_ull) (timeout * 1000000.0);
267 #ifdef PHP_WIN32
268 tv.tv_sec = (long)(conv / 1000000);
269 tv.tv_usec = (long)(conv % 1000000);
270 #else
271 tv.tv_sec = conv / 1000000;
272 tv.tv_usec = conv % 1000000;
273 #endif
274 if (zpeername) {
275 zval_dtor(zpeername);
276 ZVAL_NULL(zpeername);
277 }
278
279 if (0 == php_stream_xport_accept(stream, &clistream,
280 zpeername ? &peername : NULL,
281 NULL, NULL,
282 &tv, &errstr
283 ) && clistream) {
284
285 if (peername) {
286 ZVAL_STR(zpeername, peername);
287 }
288 php_stream_to_zval(clistream, return_value);
289 } else {
290 php_error_docref(NULL, E_WARNING, "accept failed: %s", errstr ? ZSTR_VAL(errstr) : "Unknown error");
291 RETVAL_FALSE;
292 }
293
294 if (errstr) {
295 zend_string_release(errstr);
296 }
297 }
298
299
300
301
302 PHP_FUNCTION(stream_socket_get_name)
303 {
304 php_stream *stream;
305 zval *zstream;
306 zend_bool want_peer;
307 zend_string *name = NULL;
308
309 #ifndef FAST_ZPP
310 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rb", &zstream, &want_peer) == FAILURE) {
311 RETURN_FALSE;
312 }
313 #else
314 ZEND_PARSE_PARAMETERS_START(2, 2)
315 Z_PARAM_RESOURCE(zstream)
316 Z_PARAM_BOOL(want_peer)
317 ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
318 #endif
319
320 php_stream_from_zval(stream, zstream);
321
322 if (0 != php_stream_xport_get_name(stream, want_peer,
323 &name,
324 NULL, NULL
325 )) {
326 RETURN_FALSE;
327 }
328
329 RETVAL_STR(name);
330 }
331
332
333
334
335 PHP_FUNCTION(stream_socket_sendto)
336 {
337 php_stream *stream;
338 zval *zstream;
339 zend_long flags = 0;
340 char *data, *target_addr = NULL;
341 size_t datalen, target_addr_len = 0;
342 php_sockaddr_storage sa;
343 socklen_t sl = 0;
344
345 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|ls", &zstream, &data, &datalen, &flags, &target_addr, &target_addr_len) == FAILURE) {
346 RETURN_FALSE;
347 }
348 php_stream_from_zval(stream, zstream);
349
350 if (target_addr_len) {
351
352 if (FAILURE == php_network_parse_network_address_with_port(target_addr, target_addr_len, (struct sockaddr*)&sa, &sl)) {
353 php_error_docref(NULL, E_WARNING, "Failed to parse `%s' into a valid network address", target_addr);
354 RETURN_FALSE;
355 }
356 }
357
358 RETURN_LONG(php_stream_xport_sendto(stream, data, datalen, (int)flags, target_addr ? &sa : NULL, sl));
359 }
360
361
362
363
364 PHP_FUNCTION(stream_socket_recvfrom)
365 {
366 php_stream *stream;
367 zval *zstream, *zremote = NULL;
368 zend_string *remote_addr = NULL;
369 zend_long to_read = 0;
370 zend_string *read_buf;
371 zend_long flags = 0;
372 int recvd;
373
374 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl|lz/", &zstream, &to_read, &flags, &zremote) == FAILURE) {
375 RETURN_FALSE;
376 }
377
378 php_stream_from_zval(stream, zstream);
379
380 if (zremote) {
381 zval_dtor(zremote);
382 ZVAL_NULL(zremote);
383 }
384
385 if (to_read <= 0) {
386 php_error_docref(NULL, E_WARNING, "Length parameter must be greater than 0");
387 RETURN_FALSE;
388 }
389
390 read_buf = zend_string_alloc(to_read, 0);
391
392 recvd = php_stream_xport_recvfrom(stream, ZSTR_VAL(read_buf), to_read, (int)flags, NULL, NULL,
393 zremote ? &remote_addr : NULL
394 );
395
396 if (recvd >= 0) {
397 if (zremote) {
398 ZVAL_STR(zremote, remote_addr);
399 }
400 ZSTR_VAL(read_buf)[recvd] = '\0';
401 ZSTR_LEN(read_buf) = recvd;
402 RETURN_NEW_STR(read_buf);
403 }
404
405 zend_string_free(read_buf);
406 RETURN_FALSE;
407 }
408
409
410
411
412 PHP_FUNCTION(stream_get_contents)
413 {
414 php_stream *stream;
415 zval *zsrc;
416 zend_long maxlen = (ssize_t) PHP_STREAM_COPY_ALL,
417 desiredpos = -1L;
418 zend_string *contents;
419
420 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|ll", &zsrc, &maxlen, &desiredpos) == FAILURE) {
421 RETURN_FALSE;
422 }
423
424 php_stream_from_zval(stream, zsrc);
425
426 if (desiredpos >= 0) {
427 int seek_res = 0;
428 zend_off_t position;
429
430 position = php_stream_tell(stream);
431 if (position >= 0 && desiredpos > position) {
432
433 seek_res = php_stream_seek(stream, desiredpos - position, SEEK_CUR);
434 } else if (desiredpos < position) {
435
436 seek_res = php_stream_seek(stream, desiredpos, SEEK_SET);
437 }
438
439 if (seek_res != 0) {
440 php_error_docref(NULL, E_WARNING,
441 "Failed to seek to position %pd in the stream", desiredpos);
442 RETURN_FALSE;
443 }
444 }
445
446 if (maxlen > INT_MAX) {
447 php_error_docref(NULL, E_WARNING, "maxlen truncated from %pd to %d bytes", maxlen, INT_MAX);
448 maxlen = INT_MAX;
449 }
450 if ((contents = php_stream_copy_to_mem(stream, maxlen, 0))) {
451 RETURN_STR(contents);
452 } else {
453 RETURN_EMPTY_STRING();
454 }
455 }
456
457
458
459
460 PHP_FUNCTION(stream_copy_to_stream)
461 {
462 php_stream *src, *dest;
463 zval *zsrc, *zdest;
464 zend_long maxlen = PHP_STREAM_COPY_ALL, pos = 0;
465 size_t len;
466 int ret;
467
468 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr|ll", &zsrc, &zdest, &maxlen, &pos) == FAILURE) {
469 RETURN_FALSE;
470 }
471
472 php_stream_from_zval(src, zsrc);
473 php_stream_from_zval(dest, zdest);
474
475 if (pos > 0 && php_stream_seek(src, pos, SEEK_SET) < 0) {
476 php_error_docref(NULL, E_WARNING, "Failed to seek to position " ZEND_LONG_FMT " in the stream", pos);
477 RETURN_FALSE;
478 }
479
480 ret = php_stream_copy_to_stream_ex(src, dest, maxlen, &len);
481
482 if (ret != SUCCESS) {
483 RETURN_FALSE;
484 }
485 RETURN_LONG(len);
486 }
487
488
489
490
491 PHP_FUNCTION(stream_get_meta_data)
492 {
493 zval *zstream;
494 php_stream *stream;
495
496 #ifndef FAST_ZPP
497 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zstream) == FAILURE) {
498 return;
499 }
500 #else
501 ZEND_PARSE_PARAMETERS_START(1, 1)
502 Z_PARAM_RESOURCE(zstream)
503 ZEND_PARSE_PARAMETERS_END();
504 #endif
505
506 php_stream_from_zval(stream, zstream);
507
508 array_init(return_value);
509
510 if (!php_stream_populate_meta_data(stream, return_value)) {
511 add_assoc_bool(return_value, "timed_out", 0);
512 add_assoc_bool(return_value, "blocked", 1);
513 add_assoc_bool(return_value, "eof", php_stream_eof(stream));
514 }
515
516 if (!Z_ISUNDEF(stream->wrapperdata)) {
517 Z_ADDREF_P(&stream->wrapperdata);
518 add_assoc_zval(return_value, "wrapper_data", &stream->wrapperdata);
519 }
520 if (stream->wrapper) {
521 add_assoc_string(return_value, "wrapper_type", (char *)stream->wrapper->wops->label);
522 }
523 add_assoc_string(return_value, "stream_type", (char *)stream->ops->label);
524
525 add_assoc_string(return_value, "mode", stream->mode);
526
527 #if 0
528 if (stream->filterhead) {
529 php_stream_filter *filter;
530
531 MAKE_STD_ZVAL(newval);
532 array_init(newval);
533
534 for (filter = stream->filterhead; filter != NULL; filter = filter->next) {
535 add_next_index_string(newval, (char *)filter->fops->label);
536 }
537
538 add_assoc_zval(return_value, "filters", newval);
539 }
540 #endif
541
542 add_assoc_long(return_value, "unread_bytes", stream->writepos - stream->readpos);
543
544 add_assoc_bool(return_value, "seekable", (stream->ops->seek) && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0);
545 if (stream->orig_path) {
546 add_assoc_string(return_value, "uri", stream->orig_path);
547 }
548
549 }
550
551
552
553
554 PHP_FUNCTION(stream_get_transports)
555 {
556 HashTable *stream_xport_hash;
557 zend_string *stream_xport;
558
559 if (zend_parse_parameters_none() == FAILURE) {
560 return;
561 }
562
563 if ((stream_xport_hash = php_stream_xport_get_hash())) {
564 array_init(return_value);
565 ZEND_HASH_FOREACH_STR_KEY(stream_xport_hash, stream_xport) {
566 add_next_index_str(return_value, zend_string_copy(stream_xport));
567 } ZEND_HASH_FOREACH_END();
568 } else {
569 RETURN_FALSE;
570 }
571 }
572
573
574
575
576 PHP_FUNCTION(stream_get_wrappers)
577 {
578 HashTable *url_stream_wrappers_hash;
579 zend_string *stream_protocol;
580
581 if (zend_parse_parameters_none() == FAILURE) {
582 return;
583 }
584
585 if ((url_stream_wrappers_hash = php_stream_get_url_stream_wrappers_hash())) {
586 array_init(return_value);
587 ZEND_HASH_FOREACH_STR_KEY(url_stream_wrappers_hash, stream_protocol) {
588 if (stream_protocol) {
589 add_next_index_str(return_value, zend_string_copy(stream_protocol));
590 }
591 } ZEND_HASH_FOREACH_END();
592 } else {
593 RETURN_FALSE;
594 }
595
596 }
597
598
599
600 static int stream_array_to_fd_set(zval *stream_array, fd_set *fds, php_socket_t *max_fd)
601 {
602 zval *elem;
603 php_stream *stream;
604 int cnt = 0;
605
606 if (Z_TYPE_P(stream_array) != IS_ARRAY) {
607 return 0;
608 }
609
610 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(stream_array), elem) {
611
612
613
614 php_socket_t this_fd;
615
616 php_stream_from_zval_no_verify(stream, elem);
617 if (stream == NULL) {
618 continue;
619 }
620
621
622
623
624
625 if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&this_fd, 1) && this_fd != -1) {
626
627 PHP_SAFE_FD_SET(this_fd, fds);
628
629 if (this_fd > *max_fd) {
630 *max_fd = this_fd;
631 }
632 cnt++;
633 }
634 } ZEND_HASH_FOREACH_END();
635 return cnt ? 1 : 0;
636 }
637
638 static int stream_array_from_fd_set(zval *stream_array, fd_set *fds)
639 {
640 zval *elem, *dest_elem, new_array;
641 php_stream *stream;
642 int ret = 0;
643 zend_string *key;
644 zend_ulong num_ind;
645
646 if (Z_TYPE_P(stream_array) != IS_ARRAY) {
647 return 0;
648 }
649 ZVAL_NEW_ARR(&new_array);
650 zend_hash_init(Z_ARRVAL(new_array), zend_hash_num_elements(Z_ARRVAL_P(stream_array)), NULL, ZVAL_PTR_DTOR, 0);
651
652 ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(stream_array), num_ind, key, elem) {
653 php_socket_t this_fd;
654
655 php_stream_from_zval_no_verify(stream, elem);
656 if (stream == NULL) {
657 continue;
658 }
659
660
661
662
663
664 if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&this_fd, 1) && this_fd != SOCK_ERR) {
665 if (PHP_SAFE_FD_ISSET(this_fd, fds)) {
666 if (!key) {
667 dest_elem = zend_hash_index_update(Z_ARRVAL(new_array), num_ind, elem);
668 } else {
669 dest_elem = zend_hash_update(Z_ARRVAL(new_array), key, elem);
670 }
671
672 if (dest_elem) {
673 zval_add_ref(dest_elem);
674 }
675 ret++;
676 continue;
677 }
678 }
679 } ZEND_HASH_FOREACH_END();
680
681
682 zend_array_destroy(Z_ARR_P(stream_array));
683 Z_ARR_P(stream_array) = Z_ARR(new_array);
684
685 return ret;
686 }
687
688 static int stream_array_emulate_read_fd_set(zval *stream_array)
689 {
690 zval *elem, *dest_elem, new_array;
691 php_stream *stream;
692 int ret = 0;
693
694 if (Z_TYPE_P(stream_array) != IS_ARRAY) {
695 return 0;
696 }
697 ZVAL_NEW_ARR(&new_array);
698 zend_hash_init(Z_ARRVAL(new_array), zend_hash_num_elements(Z_ARRVAL_P(stream_array)), NULL, ZVAL_PTR_DTOR, 0);
699
700 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(stream_array), elem) {
701 php_stream_from_zval_no_verify(stream, elem);
702 if (stream == NULL) {
703 continue;
704 }
705 if ((stream->writepos - stream->readpos) > 0) {
706
707
708
709
710
711
712 dest_elem = zend_hash_next_index_insert(Z_ARRVAL(new_array), elem);
713 if (dest_elem) {
714 zval_add_ref(dest_elem);
715 }
716 ret++;
717 continue;
718 }
719 } ZEND_HASH_FOREACH_END();
720
721 if (ret > 0) {
722
723 zend_array_destroy(Z_ARR_P(stream_array));
724 Z_ARR_P(stream_array) = Z_ARR(new_array);
725 } else {
726 zend_array_destroy(Z_ARR(new_array));
727 }
728
729 return ret;
730 }
731
732
733
734
735 PHP_FUNCTION(stream_select)
736 {
737 zval *r_array, *w_array, *e_array;
738 struct timeval tv, *tv_p = NULL;
739 fd_set rfds, wfds, efds;
740 php_socket_t max_fd = 0;
741 int retval, sets = 0;
742 zend_long sec, usec = 0;
743 zend_bool secnull;
744 int set_count, max_set_count = 0;
745
746 #ifndef FAST_ZPP
747 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/!a/!a/!l!|l", &r_array, &w_array, &e_array, &sec, &secnull, &usec) == FAILURE) {
748 return;
749 }
750 #else
751 ZEND_PARSE_PARAMETERS_START(4, 5)
752 Z_PARAM_ARRAY_EX(r_array, 1, 1)
753 Z_PARAM_ARRAY_EX(w_array, 1, 1)
754 Z_PARAM_ARRAY_EX(e_array, 1, 1)
755 Z_PARAM_LONG_EX(sec, secnull, 1, 0)
756 Z_PARAM_OPTIONAL
757 Z_PARAM_LONG(usec)
758 ZEND_PARSE_PARAMETERS_END();
759 #endif
760
761 FD_ZERO(&rfds);
762 FD_ZERO(&wfds);
763 FD_ZERO(&efds);
764
765 if (r_array != NULL) {
766 set_count = stream_array_to_fd_set(r_array, &rfds, &max_fd);
767 if (set_count > max_set_count)
768 max_set_count = set_count;
769 sets += set_count;
770 }
771
772 if (w_array != NULL) {
773 set_count = stream_array_to_fd_set(w_array, &wfds, &max_fd);
774 if (set_count > max_set_count)
775 max_set_count = set_count;
776 sets += set_count;
777 }
778
779 if (e_array != NULL) {
780 set_count = stream_array_to_fd_set(e_array, &efds, &max_fd);
781 if (set_count > max_set_count)
782 max_set_count = set_count;
783 sets += set_count;
784 }
785
786 if (!sets) {
787 php_error_docref(NULL, E_WARNING, "No stream arrays were passed");
788 RETURN_FALSE;
789 }
790
791 PHP_SAFE_MAX_FD(max_fd, max_set_count);
792
793
794 if (!secnull) {
795 if (sec < 0) {
796 php_error_docref(NULL, E_WARNING, "The seconds parameter must be greater than 0");
797 RETURN_FALSE;
798 } else if (usec < 0) {
799 php_error_docref(NULL, E_WARNING, "The microseconds parameter must be greater than 0");
800 RETURN_FALSE;
801 }
802
803
804 tv.tv_sec = (long)(sec + (usec / 1000000));
805 tv.tv_usec = (long)(usec % 1000000);
806 tv_p = &tv;
807 }
808
809
810
811
812 if (r_array != NULL) {
813 retval = stream_array_emulate_read_fd_set(r_array);
814 if (retval > 0) {
815 if (w_array != NULL) {
816 zend_hash_clean(Z_ARRVAL_P(w_array));
817 }
818 if (e_array != NULL) {
819 zend_hash_clean(Z_ARRVAL_P(e_array));
820 }
821 RETURN_LONG(retval);
822 }
823 }
824
825 retval = php_select(max_fd+1, &rfds, &wfds, &efds, tv_p);
826
827 if (retval == -1) {
828 php_error_docref(NULL, E_WARNING, "unable to select [%d]: %s (max_fd=%d)",
829 errno, strerror(errno), max_fd);
830 RETURN_FALSE;
831 }
832
833 if (r_array != NULL) stream_array_from_fd_set(r_array, &rfds);
834 if (w_array != NULL) stream_array_from_fd_set(w_array, &wfds);
835 if (e_array != NULL) stream_array_from_fd_set(e_array, &efds);
836
837 RETURN_LONG(retval);
838 }
839
840
841
842 static void user_space_stream_notifier(php_stream_context *context, int notifycode, int severity,
843 char *xmsg, int xcode, size_t bytes_sofar, size_t bytes_max, void * ptr)
844 {
845 zval *callback = &context->notifier->ptr;
846 zval retval;
847 zval zvs[6];
848 int i;
849
850 ZVAL_LONG(&zvs[0], notifycode);
851 ZVAL_LONG(&zvs[1], severity);
852 if (xmsg) {
853 ZVAL_STRING(&zvs[2], xmsg);
854 } else {
855 ZVAL_NULL(&zvs[2]);
856 }
857 ZVAL_LONG(&zvs[3], xcode);
858 ZVAL_LONG(&zvs[4], bytes_sofar);
859 ZVAL_LONG(&zvs[5], bytes_max);
860
861 if (FAILURE == call_user_function_ex(EG(function_table), NULL, callback, &retval, 6, zvs, 0, NULL)) {
862 php_error_docref(NULL, E_WARNING, "failed to call user notifier");
863 }
864 for (i = 0; i < 6; i++) {
865 zval_ptr_dtor(&zvs[i]);
866 }
867 zval_ptr_dtor(&retval);
868 }
869
870 static void user_space_stream_notifier_dtor(php_stream_notifier *notifier)
871 {
872 if (notifier && Z_TYPE(notifier->ptr) != IS_UNDEF) {
873 zval_ptr_dtor(¬ifier->ptr);
874 ZVAL_UNDEF(¬ifier->ptr);
875 }
876 }
877
878 static int parse_context_options(php_stream_context *context, zval *options)
879 {
880 zval *wval, *oval;
881 zend_string *wkey, *okey;
882 int ret = SUCCESS;
883
884 ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(options), wkey, wval) {
885 ZVAL_DEREF(wval);
886 if (Z_TYPE_P(wval) == IS_ARRAY) {
887 ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(wval), okey, oval) {
888 if (okey) {
889 php_stream_context_set_option(context, ZSTR_VAL(wkey), ZSTR_VAL(okey), oval);
890 }
891 } ZEND_HASH_FOREACH_END();
892
893 } else {
894 php_error_docref(NULL, E_WARNING, "options should have the form [\"wrappername\"][\"optionname\"] = $value");
895 }
896 } ZEND_HASH_FOREACH_END();
897
898 return ret;
899 }
900
901 static int parse_context_params(php_stream_context *context, zval *params)
902 {
903 int ret = SUCCESS;
904 zval *tmp;
905
906 if (NULL != (tmp = zend_hash_str_find(Z_ARRVAL_P(params), "notification", sizeof("notification")-1))) {
907
908 if (context->notifier) {
909 php_stream_notification_free(context->notifier);
910 context->notifier = NULL;
911 }
912
913 context->notifier = php_stream_notification_alloc();
914 context->notifier->func = user_space_stream_notifier;
915 ZVAL_COPY(&context->notifier->ptr, tmp);
916 context->notifier->dtor = user_space_stream_notifier_dtor;
917 }
918 if (NULL != (tmp = zend_hash_str_find(Z_ARRVAL_P(params), "options", sizeof("options")-1))) {
919 if (Z_TYPE_P(tmp) == IS_ARRAY) {
920 parse_context_options(context, tmp);
921 } else {
922 php_error_docref(NULL, E_WARNING, "Invalid stream/context parameter");
923 }
924 }
925
926 return ret;
927 }
928
929
930
931
932 static php_stream_context *decode_context_param(zval *contextresource)
933 {
934 php_stream_context *context = NULL;
935
936 context = zend_fetch_resource_ex(contextresource, NULL, php_le_stream_context());
937 if (context == NULL) {
938 php_stream *stream;
939
940 stream = zend_fetch_resource2_ex(contextresource, NULL, php_file_le_stream(), php_file_le_pstream());
941
942 if (stream) {
943 context = PHP_STREAM_CONTEXT(stream);
944 if (context == NULL) {
945
946
947
948
949 context = php_stream_context_alloc();
950 stream->ctx = context->res;
951 }
952 }
953 }
954
955 return context;
956 }
957
958
959
960
961 PHP_FUNCTION(stream_context_get_options)
962 {
963 zval *zcontext;
964 php_stream_context *context;
965
966 #ifndef FAST_ZPP
967 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zcontext) == FAILURE) {
968 RETURN_FALSE;
969 }
970 #else
971 ZEND_PARSE_PARAMETERS_START(1, 1)
972 Z_PARAM_RESOURCE(zcontext)
973 ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
974 #endif
975
976 context = decode_context_param(zcontext);
977 if (!context) {
978 php_error_docref(NULL, E_WARNING, "Invalid stream/context parameter");
979 RETURN_FALSE;
980 }
981
982 ZVAL_COPY(return_value, &context->options);
983 }
984
985
986
987
988 PHP_FUNCTION(stream_context_set_option)
989 {
990 zval *zcontext = NULL;
991 php_stream_context *context;
992
993 if (ZEND_NUM_ARGS() == 2) {
994 zval *options;
995
996 #ifndef FAST_ZPP
997 if (zend_parse_parameters(, ZEND_NUM_ARGS(), "ra", &zcontext, &options) == FAILURE) {
998 RETURN_FALSE;
999 }
1000 #else
1001 ZEND_PARSE_PARAMETERS_START(2, 2)
1002 Z_PARAM_RESOURCE(zcontext)
1003 Z_PARAM_ARRAY(options)
1004 ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
1005 #endif
1006
1007
1008 if (!(context = decode_context_param(zcontext))) {
1009 php_error_docref(NULL, E_WARNING, "Invalid stream/context parameter");
1010 RETURN_FALSE;
1011 }
1012
1013 RETURN_BOOL(parse_context_options(context, options) == SUCCESS);
1014 } else {
1015 zval *zvalue;
1016 char *wrappername, *optionname;
1017 size_t wrapperlen, optionlen;
1018
1019 #ifndef FAST_ZPP
1020 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rssz", &zcontext, &wrappername, &wrapperlen, &optionname, &optionlen, &zvalue) == FAILURE) {
1021 RETURN_FALSE;
1022 }
1023 #else
1024 ZEND_PARSE_PARAMETERS_START(4, 4)
1025 Z_PARAM_RESOURCE(zcontext)
1026 Z_PARAM_STRING(wrappername, wrapperlen)
1027 Z_PARAM_STRING(optionname, optionlen)
1028 Z_PARAM_ZVAL(zvalue)
1029 ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
1030 #endif
1031
1032
1033 if (!(context = decode_context_param(zcontext))) {
1034 php_error_docref(NULL, E_WARNING, "Invalid stream/context parameter");
1035 RETURN_FALSE;
1036 }
1037
1038 RETURN_BOOL(php_stream_context_set_option(context, wrappername, optionname, zvalue) == SUCCESS);
1039 }
1040 }
1041
1042
1043
1044
1045 PHP_FUNCTION(stream_context_set_params)
1046 {
1047 zval *params, *zcontext;
1048 php_stream_context *context;
1049
1050 #ifndef FAST_ZPP
1051 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ra", &zcontext, ¶ms) == FAILURE) {
1052 RETURN_FALSE;
1053 }
1054 #else
1055 ZEND_PARSE_PARAMETERS_START(2, 2)
1056 Z_PARAM_RESOURCE(zcontext)
1057 Z_PARAM_ARRAY(params)
1058 ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
1059 #endif
1060
1061 context = decode_context_param(zcontext);
1062 if (!context) {
1063 php_error_docref(NULL, E_WARNING, "Invalid stream/context parameter");
1064 RETURN_FALSE;
1065 }
1066
1067 RETVAL_BOOL(parse_context_params(context, params) == SUCCESS);
1068 }
1069
1070
1071
1072
1073 PHP_FUNCTION(stream_context_get_params)
1074 {
1075 zval *zcontext;
1076 php_stream_context *context;
1077
1078 #ifndef FAST_ZPP
1079 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zcontext) == FAILURE) {
1080 RETURN_FALSE;
1081 }
1082 #else
1083 ZEND_PARSE_PARAMETERS_START(1, 1)
1084 Z_PARAM_RESOURCE(zcontext)
1085 ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
1086 #endif
1087
1088 context = decode_context_param(zcontext);
1089 if (!context) {
1090 php_error_docref(NULL, E_WARNING, "Invalid stream/context parameter");
1091 RETURN_FALSE;
1092 }
1093
1094 array_init(return_value);
1095 if (context->notifier && Z_TYPE(context->notifier->ptr) != IS_UNDEF && context->notifier->func == user_space_stream_notifier) {
1096 add_assoc_zval_ex(return_value, "notification", sizeof("notification")-1, &context->notifier->ptr);
1097 if (Z_REFCOUNTED(context->notifier->ptr)) Z_ADDREF(context->notifier->ptr);
1098 }
1099 if (Z_REFCOUNTED(context->options)) Z_ADDREF(context->options);
1100 add_assoc_zval_ex(return_value, "options", sizeof("options")-1, &context->options);
1101 }
1102
1103
1104
1105
1106 PHP_FUNCTION(stream_context_get_default)
1107 {
1108 zval *params = NULL;
1109 php_stream_context *context;
1110
1111 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|a", ¶ms) == FAILURE) {
1112 RETURN_FALSE;
1113 }
1114
1115 if (FG(default_context) == NULL) {
1116 FG(default_context) = php_stream_context_alloc();
1117 }
1118 context = FG(default_context);
1119
1120 if (params) {
1121 parse_context_options(context, params);
1122 }
1123
1124 php_stream_context_to_zval(context, return_value);
1125 }
1126
1127
1128
1129
1130 PHP_FUNCTION(stream_context_set_default)
1131 {
1132 zval *options = NULL;
1133 php_stream_context *context;
1134
1135 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &options) == FAILURE) {
1136 return;
1137 }
1138
1139 if (FG(default_context) == NULL) {
1140 FG(default_context) = php_stream_context_alloc();
1141 }
1142 context = FG(default_context);
1143
1144 parse_context_options(context, options);
1145
1146 php_stream_context_to_zval(context, return_value);
1147 }
1148
1149
1150
1151
1152 PHP_FUNCTION(stream_context_create)
1153 {
1154 zval *options = NULL, *params = NULL;
1155 php_stream_context *context;
1156
1157 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|a!a!", &options, ¶ms) == FAILURE) {
1158 RETURN_FALSE;
1159 }
1160
1161 context = php_stream_context_alloc();
1162
1163 if (options) {
1164 parse_context_options(context, options);
1165 }
1166
1167 if (params) {
1168 parse_context_params(context, params);
1169 }
1170
1171 RETURN_RES(context->res);
1172 }
1173
1174
1175
1176 static void apply_filter_to_stream(int append, INTERNAL_FUNCTION_PARAMETERS)
1177 {
1178 zval *zstream;
1179 php_stream *stream;
1180 char *filtername;
1181 size_t filternamelen;
1182 zend_long read_write = 0;
1183 zval *filterparams = NULL;
1184 php_stream_filter *filter = NULL;
1185 int ret;
1186
1187 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|lz", &zstream,
1188 &filtername, &filternamelen, &read_write, &filterparams) == FAILURE) {
1189 RETURN_FALSE;
1190 }
1191
1192 php_stream_from_zval(stream, zstream);
1193
1194 if ((read_write & PHP_STREAM_FILTER_ALL) == 0) {
1195
1196
1197
1198
1199
1200 if (strchr(stream->mode, 'r') || strchr(stream->mode, '+')) {
1201 read_write |= PHP_STREAM_FILTER_READ;
1202 }
1203 if (strchr(stream->mode, 'w') || strchr(stream->mode, '+') || strchr(stream->mode, 'a')) {
1204 read_write |= PHP_STREAM_FILTER_WRITE;
1205 }
1206 }
1207
1208 if (read_write & PHP_STREAM_FILTER_READ) {
1209 filter = php_stream_filter_create(filtername, filterparams, php_stream_is_persistent(stream));
1210 if (filter == NULL) {
1211 RETURN_FALSE;
1212 }
1213
1214 if (append) {
1215 ret = php_stream_filter_append_ex(&stream->readfilters, filter);
1216 } else {
1217 ret = php_stream_filter_prepend_ex(&stream->readfilters, filter);
1218 }
1219 if (ret != SUCCESS) {
1220 php_stream_filter_remove(filter, 1);
1221 RETURN_FALSE;
1222 }
1223 }
1224
1225 if (read_write & PHP_STREAM_FILTER_WRITE) {
1226 filter = php_stream_filter_create(filtername, filterparams, php_stream_is_persistent(stream));
1227 if (filter == NULL) {
1228 RETURN_FALSE;
1229 }
1230
1231 if (append) {
1232 ret = php_stream_filter_append_ex(&stream->writefilters, filter);
1233 } else {
1234 ret = php_stream_filter_prepend_ex(&stream->writefilters, filter);
1235 }
1236 if (ret != SUCCESS) {
1237 php_stream_filter_remove(filter, 1);
1238 RETURN_FALSE;
1239 }
1240 }
1241
1242 if (filter) {
1243 filter->res = zend_register_resource(filter, php_file_le_stream_filter());
1244 GC_REFCOUNT(filter->res)++;
1245 RETURN_RES(filter->res);
1246 } else {
1247 RETURN_FALSE;
1248 }
1249 }
1250
1251
1252
1253
1254 PHP_FUNCTION(stream_filter_prepend)
1255 {
1256 apply_filter_to_stream(0, INTERNAL_FUNCTION_PARAM_PASSTHRU);
1257 }
1258
1259
1260
1261
1262 PHP_FUNCTION(stream_filter_append)
1263 {
1264 apply_filter_to_stream(1, INTERNAL_FUNCTION_PARAM_PASSTHRU);
1265 }
1266
1267
1268
1269
1270 PHP_FUNCTION(stream_filter_remove)
1271 {
1272 zval *zfilter;
1273 php_stream_filter *filter;
1274
1275 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zfilter) == FAILURE) {
1276 RETURN_FALSE;
1277 }
1278
1279 filter = zend_fetch_resource(Z_RES_P(zfilter), NULL, php_file_le_stream_filter());
1280 if (!filter) {
1281 php_error_docref(NULL, E_WARNING, "Invalid resource given, not a stream filter");
1282 RETURN_FALSE;
1283 }
1284
1285 if (php_stream_filter_flush(filter, 1) == FAILURE) {
1286 php_error_docref(NULL, E_WARNING, "Unable to flush filter, not removing");
1287 RETURN_FALSE;
1288 }
1289
1290 if (zend_list_close(Z_RES_P(zfilter)) == FAILURE) {
1291 php_error_docref(NULL, E_WARNING, "Could not invalidate filter, not removing");
1292 RETURN_FALSE;
1293 } else {
1294 php_stream_filter_remove(filter, 1);
1295 RETURN_TRUE;
1296 }
1297 }
1298
1299
1300
1301
1302 PHP_FUNCTION(stream_get_line)
1303 {
1304 char *str = NULL;
1305 size_t str_len = 0;
1306 zend_long max_length;
1307 zval *zstream;
1308 zend_string *buf;
1309 php_stream *stream;
1310
1311 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl|s", &zstream, &max_length, &str, &str_len) == FAILURE) {
1312 RETURN_FALSE;
1313 }
1314
1315 if (max_length < 0) {
1316 php_error_docref(NULL, E_WARNING, "The maximum allowed length must be greater than or equal to zero");
1317 RETURN_FALSE;
1318 }
1319 if (!max_length) {
1320 max_length = PHP_SOCK_CHUNK_SIZE;
1321 }
1322
1323 php_stream_from_zval(stream, zstream);
1324
1325 if ((buf = php_stream_get_record(stream, max_length, str, str_len))) {
1326 RETURN_STR(buf);
1327 } else {
1328 RETURN_FALSE;
1329 }
1330 }
1331
1332
1333
1334
1335
1336 PHP_FUNCTION(stream_set_blocking)
1337 {
1338 zval *zstream;
1339 zend_bool block;
1340 php_stream *stream;
1341
1342 #ifndef FAST_ZPP
1343 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rb", &zstream, &block) == FAILURE) {
1344 return;
1345 }
1346 #else
1347 ZEND_PARSE_PARAMETERS_START(2, 2)
1348 Z_PARAM_RESOURCE(zstream)
1349 Z_PARAM_BOOL(block)
1350 ZEND_PARSE_PARAMETERS_END();
1351 #endif
1352
1353 php_stream_from_zval(stream, zstream);
1354
1355 if (php_stream_set_option(stream, PHP_STREAM_OPTION_BLOCKING, block, NULL) == -1) {
1356 RETURN_FALSE;
1357 }
1358
1359 RETURN_TRUE;
1360 }
1361
1362
1363
1364
1365
1366 #if HAVE_SYS_TIME_H || defined(PHP_WIN32)
1367 PHP_FUNCTION(stream_set_timeout)
1368 {
1369 zval *socket;
1370 zend_long seconds, microseconds = 0;
1371 struct timeval t;
1372 php_stream *stream;
1373 int argc = ZEND_NUM_ARGS();
1374
1375 if (zend_parse_parameters(argc, "rl|l", &socket, &seconds, µseconds) == FAILURE) {
1376 return;
1377 }
1378
1379 php_stream_from_zval(stream, socket);
1380
1381 #ifdef PHP_WIN32
1382 t.tv_sec = (long)seconds;
1383
1384 if (argc == 3) {
1385 t.tv_usec = (long)(microseconds % 1000000);
1386 t.tv_sec +=(long)(microseconds / 1000000);
1387 } else {
1388 t.tv_usec = 0;
1389 }
1390 #else
1391 t.tv_sec = seconds;
1392
1393 if (argc == 3) {
1394 t.tv_usec = microseconds % 1000000;
1395 t.tv_sec += microseconds / 1000000;
1396 } else {
1397 t.tv_usec = 0;
1398 }
1399 #endif
1400
1401 if (PHP_STREAM_OPTION_RETURN_OK == php_stream_set_option(stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &t)) {
1402 RETURN_TRUE;
1403 }
1404
1405 RETURN_FALSE;
1406 }
1407 #endif
1408
1409
1410
1411
1412 PHP_FUNCTION(stream_set_write_buffer)
1413 {
1414 zval *arg1;
1415 int ret;
1416 zend_long arg2;
1417 size_t buff;
1418 php_stream *stream;
1419
1420 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &arg1, &arg2) == FAILURE) {
1421 RETURN_FALSE;
1422 }
1423
1424 php_stream_from_zval(stream, arg1);
1425
1426 buff = arg2;
1427
1428
1429 if (buff == 0) {
1430 ret = php_stream_set_option(stream, PHP_STREAM_OPTION_WRITE_BUFFER, PHP_STREAM_BUFFER_NONE, NULL);
1431 } else {
1432 ret = php_stream_set_option(stream, PHP_STREAM_OPTION_WRITE_BUFFER, PHP_STREAM_BUFFER_FULL, &buff);
1433 }
1434
1435 RETURN_LONG(ret == 0 ? 0 : EOF);
1436 }
1437
1438
1439
1440
1441 PHP_FUNCTION(stream_set_chunk_size)
1442 {
1443 int ret;
1444 zend_long csize;
1445 zval *zstream;
1446 php_stream *stream;
1447
1448 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &zstream, &csize) == FAILURE) {
1449 RETURN_FALSE;
1450 }
1451
1452 if (csize <= 0) {
1453 php_error_docref(NULL, E_WARNING, "The chunk size must be a positive integer, given " ZEND_LONG_FMT, csize);
1454 RETURN_FALSE;
1455 }
1456
1457
1458
1459
1460 if (csize > INT_MAX) {
1461 php_error_docref(NULL, E_WARNING, "The chunk size cannot be larger than %d", INT_MAX);
1462 RETURN_FALSE;
1463 }
1464
1465 php_stream_from_zval(stream, zstream);
1466
1467 ret = php_stream_set_option(stream, PHP_STREAM_OPTION_SET_CHUNK_SIZE, (int)csize, NULL);
1468
1469 RETURN_LONG(ret > 0 ? (zend_long)ret : (zend_long)EOF);
1470 }
1471
1472
1473
1474
1475 PHP_FUNCTION(stream_set_read_buffer)
1476 {
1477 zval *arg1;
1478 int ret;
1479 zend_long arg2;
1480 size_t buff;
1481 php_stream *stream;
1482
1483 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &arg1, &arg2) == FAILURE) {
1484 RETURN_FALSE;
1485 }
1486
1487 php_stream_from_zval(stream, arg1);
1488
1489 buff = arg2;
1490
1491
1492 if (buff == 0) {
1493 ret = php_stream_set_option(stream, PHP_STREAM_OPTION_READ_BUFFER, PHP_STREAM_BUFFER_NONE, NULL);
1494 } else {
1495 ret = php_stream_set_option(stream, PHP_STREAM_OPTION_READ_BUFFER, PHP_STREAM_BUFFER_FULL, &buff);
1496 }
1497
1498 RETURN_LONG(ret == 0 ? 0 : EOF);
1499 }
1500
1501
1502
1503
1504 PHP_FUNCTION(stream_socket_enable_crypto)
1505 {
1506 zend_long cryptokind = 0;
1507 zval *zstream, *zsessstream = NULL;
1508 php_stream *stream, *sessstream = NULL;
1509 zend_bool enable, cryptokindnull;
1510 int ret;
1511
1512 #ifdef FAST_ZPP
1513 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rb|l!r", &zstream, &enable, &cryptokind, &cryptokindnull, &zsessstream) == FAILURE) {
1514 RETURN_FALSE;
1515 }
1516 #else
1517 ZEND_PARSE_PARAMETERS_START(2, 4)
1518 Z_PARAM_RESOURCE(zstream)
1519 Z_PARAM_BOOL(enable)
1520 Z_PARAM_OPTIONAL
1521 Z_PARAM_LONG_EX(cryptokind, cryptokindnull, 1, 0)
1522 Z_PARAM_RESOURCE(zsessstream)
1523 ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
1524 #endif
1525
1526 php_stream_from_zval(stream, zstream);
1527
1528 if (enable) {
1529 if (ZEND_NUM_ARGS() < 3 || cryptokindnull) {
1530 zval *val;
1531
1532 if (!GET_CTX_OPT(stream, "ssl", "crypto_method", val)) {
1533 php_error_docref(NULL, E_WARNING, "When enabling encryption you must specify the crypto type");
1534 RETURN_FALSE;
1535 }
1536
1537 cryptokind = Z_LVAL_P(val);
1538 }
1539
1540 if (zsessstream) {
1541 php_stream_from_zval(sessstream, zsessstream);
1542 }
1543
1544 if (php_stream_xport_crypto_setup(stream, cryptokind, sessstream) < 0) {
1545 RETURN_FALSE;
1546 }
1547 }
1548
1549 ret = php_stream_xport_crypto_enable(stream, enable);
1550 switch (ret) {
1551 case -1:
1552 RETURN_FALSE;
1553
1554 case 0:
1555 RETURN_LONG(0);
1556
1557 default:
1558 RETURN_TRUE;
1559 }
1560 }
1561
1562
1563
1564
1565 PHP_FUNCTION(stream_resolve_include_path)
1566 {
1567 char *filename;
1568 size_t filename_len;
1569 zend_string *resolved_path;
1570
1571 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &filename, &filename_len) == FAILURE) {
1572 return;
1573 }
1574
1575 resolved_path = zend_resolve_path(filename, (int)filename_len);
1576
1577 if (resolved_path) {
1578 RETURN_STR(resolved_path);
1579 }
1580 RETURN_FALSE;
1581 }
1582
1583
1584
1585
1586 PHP_FUNCTION(stream_is_local)
1587 {
1588 zval *zstream;
1589 php_stream *stream = NULL;
1590 php_stream_wrapper *wrapper = NULL;
1591
1592 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zstream) == FAILURE) {
1593 RETURN_FALSE;
1594 }
1595
1596 if (Z_TYPE_P(zstream) == IS_RESOURCE) {
1597 php_stream_from_zval(stream, zstream);
1598 if (stream == NULL) {
1599 RETURN_FALSE;
1600 }
1601 wrapper = stream->wrapper;
1602 } else {
1603 convert_to_string_ex(zstream);
1604
1605 wrapper = php_stream_locate_url_wrapper(Z_STRVAL_P(zstream), NULL, 0);
1606 }
1607
1608 if (!wrapper) {
1609 RETURN_FALSE;
1610 }
1611
1612 RETURN_BOOL(wrapper->is_url==0);
1613 }
1614
1615
1616
1617
1618 PHP_FUNCTION(stream_supports_lock)
1619 {
1620 php_stream *stream;
1621 zval *zsrc;
1622
1623 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zsrc) == FAILURE) {
1624 RETURN_FALSE;
1625 }
1626
1627 php_stream_from_zval(stream, zsrc);
1628
1629 if (!php_stream_supports_lock(stream)) {
1630 RETURN_FALSE;
1631 }
1632
1633 RETURN_TRUE;
1634 }
1635
1636 #ifdef HAVE_SHUTDOWN
1637
1638
1639
1640
1641
1642
1643 PHP_FUNCTION(stream_socket_shutdown)
1644 {
1645 zend_long how;
1646 zval *zstream;
1647 php_stream *stream;
1648
1649 #ifndef FAST_ZPP
1650 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &zstream, &how) == FAILURE) {
1651 RETURN_FALSE;
1652 }
1653 #else
1654 ZEND_PARSE_PARAMETERS_START(2, 2)
1655 Z_PARAM_RESOURCE(zstream)
1656 Z_PARAM_LONG(how)
1657 ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
1658 #endif
1659
1660 if (how != STREAM_SHUT_RD &&
1661 how != STREAM_SHUT_WR &&
1662 how != STREAM_SHUT_RDWR) {
1663 php_error_docref(NULL, E_WARNING, "Second parameter $how needs to be one of STREAM_SHUT_RD, STREAM_SHUT_WR or STREAM_SHUT_RDWR");
1664 RETURN_FALSE;
1665 }
1666
1667 php_stream_from_zval(stream, zstream);
1668
1669 RETURN_BOOL(php_stream_xport_shutdown(stream, (stream_shutdown_t)how) == 0);
1670 }
1671
1672 #endif
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682