1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2021 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Author: Ruslan Osmanov <osmanov@php.net> |
16 +----------------------------------------------------------------------+
17 */
18
19 #include "php_ev.h"
20 #include "util.h"
21 #include "zend_exceptions.h"
22
23 /* {{{ php_ev_zval_to_fd
24 * Get numeric file descriptor from PHP stream or Socket resource */
php_ev_zval_to_fd(zval * pfd)25 php_socket_t php_ev_zval_to_fd(zval *pfd)
26 {
27 php_socket_t file_desc = -1;
28 php_stream *stream;
29 #ifdef PHP_EV_USE_SOCKETS
30 php_socket *php_sock;
31 #endif
32
33 if (Z_TYPE_P(pfd) == IS_RESOURCE) {
34 /* PHP stream or PHP socket resource */
35 if ((stream = (php_stream *)zend_fetch_resource2(Z_RES_P(pfd), NULL, php_file_le_stream(), php_file_le_pstream())) != NULL) {
36 if (php_stream_is(stream, PHP_STREAM_IS_MEMORY) || php_stream_is(stream, PHP_STREAM_IS_TEMP)) {
37 zend_throw_exception(zend_exception_get_default(),
38 "Cannot fetch file descriptor from memory based stream", 0);
39 return -1;
40 }
41
42 php_stream_from_zval_no_verify(stream, pfd);
43
44 if (stream == NULL) {
45 zend_throw_exception(zend_exception_get_default(), "Stream resource is invalid", 0);
46 return -1;
47 }
48
49 /* PHP stream */
50 if (php_stream_can_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT) == SUCCESS) {
51 if (php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT,
52 (void *) &file_desc, 1) != SUCCESS || file_desc < 0) {
53 return -1;
54 }
55 } else if (php_stream_can_cast(stream, PHP_STREAM_AS_FD) == SUCCESS) {
56 if (php_stream_cast(stream, PHP_STREAM_AS_FD,
57 (void *) &file_desc, 1) != SUCCESS || file_desc < 0) {
58 return -1;
59 }
60 } else if (php_stream_can_cast(stream, PHP_STREAM_AS_STDIO) == SUCCESS) {
61 if (php_stream_cast(stream, PHP_STREAM_AS_STDIO,
62 (void *) &file_desc, 1) != SUCCESS || file_desc < 0) {
63 return -1;
64 }
65 } else { /* STDIN, STDOUT, STDERR etc. */
66 file_desc = Z_LVAL_P(pfd);
67 }
68 } else {
69 /* PHP socket resource */
70 #ifdef PHP_EV_USE_SOCKETS
71 if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(pfd),
72 php_sockets_le_socket_name, php_sockets_le_socket())) != NULL) {
73 if (php_sock->error) {
74 if (!php_sock->blocking && php_sock->error == EINPROGRESS) {
75 #ifdef PHP_EV_DEBUG
76 php_error_docref(NULL, E_NOTICE, "Operation is in progress");
77 #endif
78 } else {
79 return -1;
80 }
81 }
82 return php_sock->bsd_socket;
83 } else {
84 zend_throw_exception(zend_exception_get_default(),
85 "Expected either valid PHP stream or valid PHP socket resource", 0);
86 }
87 #else
88 zend_throw_exception(zend_exception_get_default(), "Expected a valid PHP stream resource", 0);
89 #endif
90 return -1;
91 }
92 } else if (Z_TYPE_P(pfd) == IS_LONG) {
93 /* Numeric fd */
94 file_desc = Z_LVAL_P(pfd);
95 if (file_desc < 0) {
96 zend_throw_exception(zend_exception_get_default(), "Invalid file descriptor", 0);
97 return -1;
98 }
99 } else {
100 zend_throw_exception(zend_exception_get_default(), "Invalid file descriptor", 0);
101 return -1;
102 }
103
104 return file_desc;
105 }
106 /* }}} */
107
108 /**
109 * @note `error` must be freed, if not NULL
110 */
php_ev_import_func_info(php_ev_func_info * pf,zval * zcb,char * error)111 int php_ev_import_func_info(php_ev_func_info *pf, zval *zcb, char *error)/*{{{*/
112 {
113 if (zcb) {
114 zend_fcall_info_cache fcc;
115 zend_object *obj_ptr;
116
117 if (!zend_is_callable_ex(zcb, NULL, IS_CALLABLE_STRICT, NULL, &fcc, &error)) {
118 return FAILURE;
119 }
120
121 PHP_EV_EFREE(error);
122
123 pf->ce = fcc.calling_scope;
124 pf->func_ptr = fcc.function_handler;
125 obj_ptr = fcc.object;
126
127 if (Z_TYPE_P(zcb) == IS_OBJECT) {
128 ZVAL_COPY(&pf->closure, zcb);
129 } else {
130 ZVAL_UNDEF(&pf->closure);
131 }
132
133 if (obj_ptr && !(pf->func_ptr->common.fn_flags & ZEND_ACC_STATIC)) {
134 ZVAL_OBJ(&pf->obj, obj_ptr);
135 Z_ADDREF(pf->obj);
136 } else {
137 ZVAL_UNDEF(&pf->obj);
138 }
139 } else {
140 pf->ce = NULL;
141 pf->func_ptr = NULL;
142 ZVAL_UNDEF(&pf->closure);
143 ZVAL_UNDEF(&pf->obj);
144 }
145
146 return SUCCESS;
147 }
148 /*}}}*/
149
php_ev_func_info_free(php_ev_func_info * pf,zend_bool self)150 void php_ev_func_info_free(php_ev_func_info *pf, zend_bool self)/*{{{*/
151 {
152 if (!Z_ISUNDEF(pf->obj)) {
153 zval_ptr_dtor(&pf->obj);
154 ZVAL_UNDEF(&pf->obj);
155 }
156 if (!Z_ISUNDEF(pf->closure)) {
157 zval_ptr_dtor(&pf->closure);
158 ZVAL_UNDEF(&pf->closure);
159 }
160 if (self != FALSE) {
161 efree(pf);
162 }
163 }
164 /*}}}*/
165
166 /*
167 * Local variables:
168 * tab-width: 4
169 * c-basic-offset: 4
170 * End:
171 * vim600: noet sw=4 ts=4 sts=4 fdm=marker
172 * vim<600: noet sw=4 ts=4 sts=4
173 */
174