ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
SCP.php
Go to the documentation of this file.
1 <?php
2 
33 namespace phpseclib\Net;
34 
37 
45 class SCP
46 {
54  const SOURCE_LOCAL_FILE = 1;
58  const SOURCE_STRING = 2;
69  const MODE_SSH1 = 1;
73  const MODE_SSH2 = 2;
82  var $ssh;
83 
91 
98  var $mode;
99 
111  function __construct($ssh)
112  {
113  if ($ssh instanceof SSH2) {
114  $this->mode = self::MODE_SSH2;
115  } elseif ($ssh instanceof SSH1) {
116  $this->packet_size = 50000;
117  $this->mode = self::MODE_SSH1;
118  } else {
119  return;
120  }
121 
122  $this->ssh = $ssh;
123  }
124 
146  function put($remote_file, $data, $mode = self::SOURCE_STRING, $callback = null)
147  {
148  if (!isset($this->ssh)) {
149  return false;
150  }
151 
152  if (!$this->ssh->exec('scp -t ' . escapeshellarg($remote_file), false)) { // -t = to
153  return false;
154  }
155 
156  $temp = $this->_receive();
157  if ($temp !== chr(0)) {
158  return false;
159  }
160 
161  if ($this->mode == self::MODE_SSH2) {
162  $this->packet_size = $this->ssh->packet_size_client_to_server[SSH2::CHANNEL_EXEC] - 4;
163  }
164 
165  $remote_file = basename($remote_file);
166 
167  if ($mode == self::SOURCE_STRING) {
168  $size = strlen($data);
169  } else {
170  if (!is_file($data)) {
171  user_error("$data is not a valid file", E_USER_NOTICE);
172  return false;
173  }
174 
175  $fp = @fopen($data, 'rb');
176  if (!$fp) {
177  return false;
178  }
179  $size = filesize($data);
180  }
181 
182  $this->_send('C0644 ' . $size . ' ' . $remote_file . "\n");
183 
184  $temp = $this->_receive();
185  if ($temp !== chr(0)) {
186  return false;
187  }
188 
189  $sent = 0;
190  while ($sent < $size) {
191  $temp = $mode & self::SOURCE_STRING ? substr($data, $sent, $this->packet_size) : fread($fp, $this->packet_size);
192  $this->_send($temp);
193  $sent+= strlen($temp);
194 
195  if (is_callable($callback)) {
196  call_user_func($callback, $sent);
197  }
198  }
199  $this->_close();
200 
201  if ($mode != self::SOURCE_STRING) {
202  fclose($fp);
203  }
204 
205  return true;
206  }
207 
220  function get($remote_file, $local_file = false)
221  {
222  if (!isset($this->ssh)) {
223  return false;
224  }
225 
226  if (!$this->ssh->exec('scp -f ' . escapeshellarg($remote_file), false)) { // -f = from
227  return false;
228  }
229 
230  $this->_send("\0");
231 
232  if (!preg_match('#(?<perms>[^ ]+) (?<size>\d+) (?<name>.+)#', rtrim($this->_receive()), $info)) {
233  return false;
234  }
235 
236  $this->_send("\0");
237 
238  $size = 0;
239 
240  if ($local_file !== false) {
241  $fp = @fopen($local_file, 'wb');
242  if (!$fp) {
243  return false;
244  }
245  }
246 
247  $content = '';
248  while ($size < $info['size']) {
249  $data = $this->_receive();
250  // SCP usually seems to split stuff out into 16k chunks
251  $size+= strlen($data);
252 
253  if ($local_file === false) {
254  $content.= $data;
255  } else {
256  fputs($fp, $data);
257  }
258  }
259 
260  $this->_close();
261 
262  if ($local_file !== false) {
263  fclose($fp);
264  return true;
265  }
266 
267  return $content;
268  }
269 
276  function _send($data)
277  {
278  switch ($this->mode) {
279  case self::MODE_SSH2:
280  $this->ssh->_send_channel_packet(SSH2::CHANNEL_EXEC, $data);
281  break;
282  case self::MODE_SSH1:
283  $data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($data), $data);
284  $this->ssh->_send_binary_packet($data);
285  }
286  }
287 
294  function _receive()
295  {
296  switch ($this->mode) {
297  case self::MODE_SSH2:
298  return $this->ssh->_get_channel_packet(SSH2::CHANNEL_EXEC, true);
299  case self::MODE_SSH1:
300  if (!$this->ssh->bitmap) {
301  return false;
302  }
303  while (true) {
304  $response = $this->ssh->_get_binary_packet();
305  switch ($response[SSH1::RESPONSE_TYPE]) {
306  case NET_SSH1_SMSG_STDOUT_DATA:
307  extract(unpack('Nlength', $response[SSH1::RESPONSE_DATA]));
308  return $this->ssh->_string_shift($response[SSH1::RESPONSE_DATA], $length);
309  case NET_SSH1_SMSG_STDERR_DATA:
310  break;
311  case NET_SSH1_SMSG_EXITSTATUS:
312  $this->ssh->_send_binary_packet(chr(NET_SSH1_CMSG_EXIT_CONFIRMATION));
313  fclose($this->ssh->fsock);
314  $this->ssh->bitmap = 0;
315  return false;
316  default:
317  user_error('Unknown packet received', E_USER_NOTICE);
318  return false;
319  }
320  }
321  }
322  }
323 
329  function _close()
330  {
331  switch ($this->mode) {
332  case self::MODE_SSH2:
333  $this->ssh->_close_channel(SSH2::CHANNEL_EXEC, true);
334  break;
335  case self::MODE_SSH1:
336  $this->ssh->disconnect();
337  }
338  }
339 }
const RESPONSE_TYPE
#-
Definition: SSH1.php:166
$size
Definition: RandomTest.php:84
const SOURCE_STRING
Reads data from a string.
Definition: SCP.php:58
Pure-PHP implementations of SCP.
Pure-PHP implementation of SSHv1.
_send($data)
Sends a packet to an SSH server.
Definition: SCP.php:276
const CHANNEL_EXEC
#-
Definition: SSH2.php:103
Pure-PHP implementation of SSHv2.
_close()
Closes the connection to an SSH server.
Definition: SCP.php:329
__construct($ssh)
Default Constructor.
Definition: SCP.php:111
const SOURCE_LOCAL_FILE
#+ public
Definition: SCP.php:54
const MODE_SSH1
#-
Definition: SCP.php:69
put($remote_file, $data, $mode=self::SOURCE_STRING, $callback=null)
Uploads a file to the SCP server.
Definition: SCP.php:146
_receive()
Receives a packet from an SSH server.
Definition: SCP.php:294
const RESPONSE_DATA
The Response Data.
Definition: SSH1.php:174
$info
Definition: index.php:5
$response
const MODE_SSH2
SSH2 is being used.
Definition: SCP.php:73
$data
Definition: bench.php:6