PluginProbe
ManageWP Worker / 3.9.28
ManageWP Worker v3.9.28
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 / lib / PHPSecLib / Net / SCP.php

SCP.php in ManageWP Worker 3.9.28, at lib/PHPSecLib/Net/SCP.php

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