This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | |||
4 | namespace Beanie\Server; |
||
5 | |||
6 | |||
7 | use Beanie\Exception\SocketException; |
||
8 | |||
9 | class Socket |
||
10 | { |
||
11 | /** |
||
12 | * Longest possible response preface: |
||
13 | * <code>USING <tubeName=max 200 byte>\r\n</code> |
||
14 | */ |
||
15 | const MAX_SINGLE_RESPONSE_LENGTH = 208; |
||
16 | |||
17 | /** @var bool */ |
||
18 | protected $connected = false; |
||
19 | |||
20 | /** @var string */ |
||
21 | protected $hostname; |
||
22 | |||
23 | /** @var int */ |
||
24 | protected $port; |
||
25 | |||
26 | /** @var resource */ |
||
27 | protected $socket; |
||
28 | |||
29 | /** @var string */ |
||
30 | private $readBuffer = ''; |
||
31 | |||
32 | /** |
||
33 | * @param string $hostname |
||
34 | * @param int $port |
||
35 | * @throws SocketException When socket creation fails. Will have the underlying code and message. |
||
36 | */ |
||
37 | 35 | public function __construct($hostname = Server::DEFAULT_HOST, $port = Server::DEFAULT_PORT) |
|
38 | { |
||
39 | 35 | $this->hostname = (string) $hostname; |
|
40 | 35 | $this->port = (int) $port; |
|
41 | |||
42 | 35 | $this->createSocket(); |
|
43 | 33 | } |
|
44 | |||
45 | /** |
||
46 | * @param string $data |
||
47 | * @return int bytes written |
||
48 | * @throws SocketException When the connection is dropped in the middle of writing. |
||
49 | */ |
||
50 | 4 | public function write($data) |
|
51 | { |
||
52 | 4 | $this->ensureConnected(); |
|
53 | 3 | $dataLength = $leftToWrite = strlen($data); |
|
54 | |||
55 | do { |
||
56 | if ( |
||
57 | 3 | ($written = @socket_write( |
|
58 | 3 | $this->socket, |
|
59 | 3 | substr($data, -$leftToWrite), |
|
60 | $leftToWrite |
||
61 | 3 | )) === false |
|
62 | 3 | ) { |
|
63 | 1 | throw $this->createSocketException(); |
|
64 | } |
||
65 | |||
66 | 2 | $leftToWrite -= $written; |
|
67 | 2 | } while ($leftToWrite > 0); |
|
68 | |||
69 | 2 | return $dataLength; |
|
70 | } |
||
71 | |||
72 | /** |
||
73 | * Reads data from the connected socket in chunks of MAX_SINGLE_RESPONSE_LENGTH |
||
74 | * |
||
75 | * The MAX_SINGLE_RESPONSE_LENGTH should always capture at least the first line of a response, assuming the longest |
||
76 | * possible response is the USING <tubename>\r\n response, which could be up to 208 bytes in length, for any valid |
||
77 | * <tubename>. As a result, this function will, in reality, read some overflow of data for any response containing |
||
78 | * data. This data is saved in a read-buffer, which `readData()` will read from first. |
||
79 | * |
||
80 | * @see readData() |
||
81 | * |
||
82 | * @param string $endOfLine |
||
83 | * @return string |
||
84 | * @throws SocketException |
||
85 | */ |
||
86 | 7 | public function readLine($endOfLine = Server::EOL) |
|
87 | { |
||
88 | 7 | $this->ensureConnected(); |
|
89 | 6 | $buffer = ''; |
|
90 | |||
91 | do { |
||
92 | 6 | $buffer .= $this->read(self::MAX_SINGLE_RESPONSE_LENGTH); |
|
93 | |||
94 | 4 | $eolPosition = strpos($buffer, $endOfLine); |
|
95 | 4 | } while ($eolPosition === false); |
|
96 | |||
97 | 4 | $this->readBuffer = substr($buffer, $eolPosition + strlen($endOfLine)); |
|
98 | 4 | return substr($buffer, 0, $eolPosition + strlen($endOfLine)); |
|
99 | } |
||
100 | |||
101 | /** |
||
102 | * Read exactly $bytes of data from the connected sockets |
||
103 | * |
||
104 | * If there is not enough data to read $bytes from the read-buffer created by a previous `readLine` call combined |
||
105 | * with the actual socket, this will block until data becomes available. Use with care. |
||
106 | * |
||
107 | * @param int $bytes |
||
108 | * @return string |
||
109 | * @throws SocketException When the connection drops during reading |
||
110 | */ |
||
111 | 6 | public function readData($bytes) |
|
112 | { |
||
113 | 6 | $this->ensureConnected(); |
|
114 | |||
115 | 5 | $read = strlen($this->readBuffer); |
|
116 | 5 | $buffer = $this->readBuffer; |
|
117 | 5 | $this->readBuffer = ''; |
|
118 | |||
119 | 5 | while ($read < $bytes) { |
|
120 | 5 | $incoming = $this->read($bytes - $read); |
|
121 | 3 | $buffer .= $incoming; |
|
122 | 3 | $read += strlen($incoming); |
|
123 | 3 | } |
|
124 | |||
125 | 3 | return substr($buffer, 0, $bytes); |
|
126 | } |
||
127 | |||
128 | /** |
||
129 | * @param int $bytes |
||
130 | * @return bool |
||
131 | * @throws SocketException |
||
132 | */ |
||
133 | 10 | protected function read($bytes) |
|
134 | { |
||
135 | 10 | if (($incoming = @socket_read($this->socket, $bytes)) === false) { |
|
136 | 3 | throw $this->createSocketException(); |
|
137 | } |
||
138 | |||
139 | 7 | if ($incoming === '') { |
|
140 | 1 | throw new SocketException('No more data', -1); |
|
141 | } |
||
142 | |||
143 | 6 | return $incoming; |
|
144 | } |
||
145 | |||
146 | /** |
||
147 | * @return boolean |
||
148 | */ |
||
149 | 5 | public function isConnected() |
|
150 | { |
||
151 | 5 | return $this->connected; |
|
152 | } |
||
153 | |||
154 | /** |
||
155 | * @return string |
||
156 | */ |
||
157 | 4 | public function getHostname() |
|
158 | { |
||
159 | 4 | return $this->hostname; |
|
160 | } |
||
161 | |||
162 | /** |
||
163 | * @return int |
||
164 | */ |
||
165 | 4 | public function getPort() |
|
166 | { |
||
167 | 4 | return $this->port; |
|
168 | } |
||
169 | |||
170 | /** |
||
171 | * @return resource |
||
172 | */ |
||
173 | 2 | public function getRaw() |
|
174 | { |
||
175 | 2 | return $this->socket; |
|
176 | } |
||
177 | |||
178 | /** |
||
179 | * @throws SocketException |
||
180 | */ |
||
181 | 2 | public function disconnect() |
|
182 | { |
||
183 | 2 | $this->connected = false; |
|
184 | 2 | @socket_close($this->socket); |
|
0 ignored issues
–
show
|
|||
185 | |||
186 | 2 | $this->createSocket(); |
|
187 | 1 | } |
|
188 | |||
189 | /** |
||
190 | * @throws SocketException When connecting fails |
||
191 | */ |
||
192 | 16 | public function connect() |
|
193 | { |
||
194 | 16 | if (($this->connected = @socket_connect($this->socket, $this->hostname, $this->port)) === false) { |
|
195 | 2 | throw $this->createSocketException(); |
|
196 | } |
||
197 | 14 | } |
|
198 | |||
199 | /** |
||
200 | * @throws SocketException Ensure the Socket is connected. If it is not, throws and exception |
||
201 | */ |
||
202 | 16 | protected function ensureConnected() |
|
203 | { |
||
204 | 16 | if ($this->connected !== true) { |
|
205 | 3 | throw new SocketException('Socket is not connected.'); |
|
206 | } |
||
207 | 13 | } |
|
208 | |||
209 | /** |
||
210 | * @return SocketException |
||
211 | */ |
||
212 | 9 | protected function createSocketException() |
|
213 | { |
||
214 | 9 | $errorCode = socket_last_error(); |
|
215 | 9 | $errorMessage = socket_strerror($errorCode); |
|
216 | 9 | $exception = new SocketException($errorMessage, $errorCode); |
|
217 | 9 | return $exception; |
|
218 | } |
||
219 | |||
220 | /** |
||
221 | * Attempt to close the socket if it is still open. |
||
222 | */ |
||
223 | 34 | public function __destruct() |
|
224 | { |
||
225 | 34 | @socket_close($this->socket); |
|
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
|
|||
226 | 34 | } |
|
227 | |||
228 | 35 | protected function createSocket() |
|
229 | { |
||
230 | 35 | if (($this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) { |
|
231 | 3 | throw $this->createSocketException(); |
|
232 | } |
||
233 | 33 | } |
|
234 | } |
||
235 |
If you suppress an error, we recommend checking for the error condition explicitly: