PluginProbe
ManageWP Worker / 4.9.25
ManageWP Worker v4.9.25
4.9.38 4.9.37 4.9.36 4.9.35 4.9.34 3.8.7 3.8.8 3.9.0 3.9.1 3.9.10 3.9.11 3.9.12 3.9.13 3.9.14 3.9.15 3.9.16 3.9.17 3.9.18 3.9.19 3.9.2 3.9.20 3.9.21 3.9.22 3.9.23 3.9.24 All 73 releases
worker / src / PHPSecLib / Net / SCP.php

SCP.php in ManageWP Worker 4.9.25, at src/PHPSecLib/Net/SCP.php

371 lines 9.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Pure-PHP implementation of SCP.
5 *
6 * PHP versions 4 and 5
7 *
8 * The API for this library is modeled after the API from PHP's {@link http://php.net/book.ftp FTP extension}.
9 *
10 * Here's a short example of how to use this library:
11 * <code>
12 * <?php
13 * include 'Net/SCP.php';
14 * include 'Net/SSH2.php';
15 *
16 * $ssh = new Net_SSH2('www.domain.tld');
17 * if (!$ssh->login('username', 'password')) {
18 * exit('bad login');
19 * }
20 * $scp = new Net_SCP($ssh);
21 * $scp->put('abcd', str_repeat('x', 1024*1024));
22 * ?>
23 * </code>
24 *
25 * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
26 * of this software and associated documentation files (the "Software"), to deal
27 * in the Software without restriction, including without limitation the rights
28 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
29 * copies of the Software, and to permit persons to whom the Software is
30 * furnished to do so, subject to the following conditions:
31 *
32 * The above copyright notice and this permission notice shall be included in
33 * all copies or substantial portions of the Software.
34 *
35 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
38 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
39 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
40 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
41 * THE SOFTWARE.
42 *
43 * @category Net
44 * @package Net_SCP
45 * @author Jim Wigginton <terrafrost@php.net>
46 * @copyright MMX Jim Wigginton
47 * @license http://www.opensource.org/licenses/mit-license.html MIT License
48 * @link http://phpseclib.sourceforge.net
49 */
50
51 /**#@+
52 * @access public
53 * @see Net_SCP::put()
54 */
55 /**
56 * Reads data from a local file.
57 */
58 define('NET_SCP_LOCAL_FILE', 1);
59 /**
60 * Reads data from a string.
61 */
62 define('NET_SCP_STRING', 2);
63 /**#@-*/
64
65 /**#@+
66 * @access private
67 * @see Net_SCP::_send()
68 * @see Net_SCP::_receive()
69 */
70 /**
71 * SSH1 is being used.
72 */
73 define('NET_SCP_SSH1', 1);
74 /**
75 * SSH2 is being used.
76 */
77 define('NET_SCP_SSH2', 2);
78 /**#@-*/
79
80 /**
81 * Pure-PHP implementations of SCP.
82 *
83 * @package Net_SCP
84 * @author Jim Wigginton <terrafrost@php.net>
85 * @access public
86 */
87 class Net_SCP
88 {
89 /**
90 * SSH Object
91 *
92 * @var Object
93 * @access private
94 */
95 public $ssh;
96
97 /**
98 * Packet Size
99 *
100 * @var Integer
101 * @access private
102 */
103 public $packet_size;
104
105 /**
106 * Mode
107 *
108 * @var Integer
109 * @access private
110 */
111 public $mode;
112
113 /**
114 * Default Constructor.
115 *
116 * Connects to an SSH server
117 *
118 * @param String $host
119 * @param optional Integer $port
120 * @param optional Integer $timeout
121 *
122 * @return Net_SCP
123 * @access public
124 */
125 public function __construct($ssh)
126 {
127 if (!is_object($ssh)) {
128 return;
129 }
130
131 switch (strtolower(get_class($ssh))) {
132 case'net_ssh2':
133 $this->mode = NET_SCP_SSH2;
134 break;
135 case 'net_ssh1':
136 $this->packet_size = 50000;
137 $this->mode = NET_SCP_SSH1;
138 break;
139 default:
140 return;
141 }
142
143 $this->ssh = $ssh;
144 }
145
146 /**
147 * Uploads a file to the SCP server.
148 *
149 * By default, Net_SCP::put() does not read from the local filesystem. $data is dumped directly into $remote_file.
150 * So, for example, if you set $data to 'filename.ext' and then do Net_SCP::get(), you will get a file, twelve bytes
151 * long, containing 'filename.ext' as its contents.
152 *
153 * Setting $mode to NET_SCP_LOCAL_FILE will change the above behavior. With NET_SCP_LOCAL_FILE, $remote_file will
154 * contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how
155 * large $remote_file will be, as well.
156 *
157 * Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take
158 * care of that, yourself.
159 *
160 * @param String $remote_file
161 * @param String $data
162 * @param optional Integer $mode
163 * @param optional Callable $callback
164 *
165 * @return Boolean
166 * @access public
167 */
168 public function put($remote_file, $data, $mode = NET_SCP_STRING, $callback = null)
169 {
170 if (!isset($this->ssh)) {
171 return false;
172 }
173
174 if (!$this->ssh->exec('scp -t "'.$remote_file.'"', false)) { // -t = to
175 return false;
176 }
177
178 $temp = $this->_receive();
179 if ($temp !== chr(0)) {
180 return false;
181 }
182
183 if ($this->mode == NET_SCP_SSH2) {
184 $this->packet_size = $this->ssh->packet_size_client_to_server[NET_SSH2_CHANNEL_EXEC] - 4;
185 }
186
187 $remote_file = basename($remote_file);
188
189 if ($mode == NET_SCP_STRING) {
190 $size = strlen($data);
191 } else {
192 if (!is_file($data)) {
193 user_error("$data is not a valid file", E_USER_NOTICE);
194
195 return false;
196 }
197
198 $fp = @fopen($data, 'rb');
199 if (!$fp) {
200 fclose($fp);
201
202 return false;
203 }
204 $size = filesize($data);
205 }
206
207 $this->_send('C0644 '.$size.' '.$remote_file."\n");
208
209 $temp = $this->_receive();
210 if ($temp !== chr(0)) {
211 return false;
212 }
213
214 $sent = 0;
215 while ($sent < $size) {
216 $temp = $mode & NET_SCP_STRING ? substr($data, $sent, $this->packet_size) : fread($fp, $this->packet_size);
217 $this->_send($temp);
218 $sent += strlen($temp);
219
220 if (is_callable($callback)) {
221 call_user_func($callback, $sent);
222 }
223 }
224 $this->_close();
225
226 if ($mode != NET_SCP_STRING) {
227 fclose($fp);
228 }
229
230 return true;
231 }
232
233 /**
234 * Downloads a file from the SCP server.
235 *
236 * Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if
237 * the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the
238 * operation
239 *
240 * @param String $remote_file
241 * @param optional String $local_file
242 *
243 * @return Mixed
244 * @access public
245 */
246 public function get($remote_file, $local_file = false)
247 {
248 if (!isset($this->ssh)) {
249 return false;
250 }
251
252 if (!$this->ssh->exec('scp -f "'.$remote_file.'"', false)) { // -f = from
253 return false;
254 }
255
256 $this->_send("\0");
257
258 if (!preg_match('#(?<perms>[^ ]+) (?<size>\d+) (?<name>.+)#', rtrim($this->_receive()), $info)) {
259 return false;
260 }
261
262 $this->_send("\0");
263
264 $size = 0;
265
266 if ($local_file !== false) {
267 $fp = @fopen($local_file, 'wb');
268 if (!$fp) {
269 return false;
270 }
271 }
272
273 $content = '';
274 while ($size < $info['size']) {
275 $data = $this->_receive();
276 // SCP usually seems to split stuff out into 16k chunks
277 $size += strlen($data);
278
279 if ($local_file === false) {
280 $content .= $data;
281 } else {
282 fputs($fp, $data);
283 }
284 }
285
286 $this->_close();
287
288 if ($local_file !== false) {
289 fclose($fp);
290
291 return true;
292 }
293
294 return $content;
295 }
296
297 /**
298 * Sends a packet to an SSH server
299 *
300 * @param String $data
301 *
302 * @access private
303 */
304 public function _send($data)
305 {
306 switch ($this->mode) {
307 case NET_SCP_SSH2:
308 $this->ssh->_send_channel_packet(NET_SSH2_CHANNEL_EXEC, $data);
309 break;
310 case NET_SCP_SSH1:
311 $data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($data), $data);
312 $this->ssh->_send_binary_packet($data);
313 }
314 }
315
316 /**
317 * Receives a packet from an SSH server
318 *
319 * @return String
320 * @access private
321 */
322 public function _receive()
323 {
324 switch ($this->mode) {
325 case NET_SCP_SSH2:
326 return $this->ssh->_get_channel_packet(NET_SSH2_CHANNEL_EXEC, true);
327 case NET_SCP_SSH1:
328 if (!$this->ssh->bitmap) {
329 return false;
330 }
331 while (true) {
332 $response = $this->ssh->_get_binary_packet();
333 switch ($response[NET_SSH1_RESPONSE_TYPE]) {
334 case NET_SSH1_SMSG_STDOUT_DATA:
335 extract(unpack('Nlength', $response[NET_SSH1_RESPONSE_DATA]));
336
337 return $this->ssh->_string_shift($response[NET_SSH1_RESPONSE_DATA], $length);
338 case NET_SSH1_SMSG_STDERR_DATA:
339 break;
340 case NET_SSH1_SMSG_EXITSTATUS:
341 $this->ssh->_send_binary_packet(chr(NET_SSH1_CMSG_EXIT_CONFIRMATION));
342 fclose($this->ssh->fsock);
343 $this->ssh->bitmap = 0;
344
345 return false;
346 default:
347 user_error('Unknown packet received', E_USER_NOTICE);
348
349 return false;
350 }
351 }
352 }
353 }
354
355 /**
356 * Closes the connection to an SSH server
357 *
358 * @access private
359 */
360 public function _close()
361 {
362 switch ($this->mode) {
363 case NET_SCP_SSH2:
364 $this->ssh->_close_channel(NET_SSH2_CHANNEL_EXEC, true);
365 break;
366 case NET_SCP_SSH1:
367 $this->ssh->disconnect();
368 }
369 }
370 }
371