PageRenderTime 40ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/wp-content/plugins/updraftplus/vendor/phpseclib/phpseclib/phpseclib/Net/SCP.php

https://gitlab.com/code26/selah
PHP | 373 lines | 172 code | 38 blank | 163 comment | 33 complexity | 9d466aee8b03f2d715dd15cff35b5dfc MD5 | raw file
  1. <?php
  2. /**
  3. * Pure-PHP implementation of SCP.
  4. *
  5. * PHP versions 4 and 5
  6. *
  7. * The API for this library is modeled after the API from PHP's {@link http://php.net/book.ftp FTP extension}.
  8. *
  9. * Here's a short example of how to use this library:
  10. * <code>
  11. * <?php
  12. * include 'Net/SCP.php';
  13. * include 'Net/SSH2.php';
  14. *
  15. * $ssh = new Net_SSH2('www.domain.tld');
  16. * if (!$ssh->login('username', 'password')) {
  17. * exit('bad login');
  18. * }
  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 2010 Jim Wigginton
  47. * @license http://www.opensource.org/licenses/mit-license.html MIT License
  48. * @link http://phpseclib.sourceforge.net
  49. */
  50. /**#@+
  51. * @access public
  52. * @see self::put()
  53. */
  54. /**
  55. * Reads data from a local file.
  56. */
  57. define('NET_SCP_LOCAL_FILE', 1);
  58. /**
  59. * Reads data from a string.
  60. */
  61. define('NET_SCP_STRING', 2);
  62. /**#@-*/
  63. /**#@+
  64. * @access private
  65. * @see self::_send()
  66. * @see self::_receive()
  67. */
  68. /**
  69. * SSH1 is being used.
  70. */
  71. define('NET_SCP_SSH1', 1);
  72. /**
  73. * SSH2 is being used.
  74. */
  75. define('NET_SCP_SSH2', 2);
  76. /**#@-*/
  77. /**
  78. * Pure-PHP implementations of SCP.
  79. *
  80. * @package Net_SCP
  81. * @author Jim Wigginton <terrafrost@php.net>
  82. * @access public
  83. */
  84. class Net_SCP
  85. {
  86. /**
  87. * SSH Object
  88. *
  89. * @var object
  90. * @access private
  91. */
  92. var $ssh;
  93. /**
  94. * Packet Size
  95. *
  96. * @var int
  97. * @access private
  98. */
  99. var $packet_size;
  100. /**
  101. * Mode
  102. *
  103. * @var int
  104. * @access private
  105. */
  106. var $mode;
  107. /**
  108. * Default Constructor.
  109. *
  110. * Connects to an SSH server
  111. *
  112. * @param Net_SSH1|Net_SSH2 $ssh
  113. * @return Net_SCP
  114. * @access public
  115. */
  116. function __construct($ssh)
  117. {
  118. if (!is_object($ssh)) {
  119. return;
  120. }
  121. switch (strtolower(get_class($ssh))) {
  122. case 'net_ssh2':
  123. $this->mode = NET_SCP_SSH2;
  124. break;
  125. case 'net_ssh1':
  126. $this->packet_size = 50000;
  127. $this->mode = NET_SCP_SSH1;
  128. break;
  129. default:
  130. return;
  131. }
  132. $this->ssh = $ssh;
  133. }
  134. /**
  135. * PHP4 compatible Default Constructor.
  136. *
  137. * @see self::__construct()
  138. * @param Net_SSH1|Net_SSH2 $ssh
  139. * @access public
  140. */
  141. function Net_SCP($ssh)
  142. {
  143. $this->__construct($ssh);
  144. }
  145. /**
  146. * Uploads a file to the SCP server.
  147. *
  148. * By default, Net_SCP::put() does not read from the local filesystem. $data is dumped directly into $remote_file.
  149. * So, for example, if you set $data to 'filename.ext' and then do Net_SCP::get(), you will get a file, twelve bytes
  150. * long, containing 'filename.ext' as its contents.
  151. *
  152. * Setting $mode to NET_SCP_LOCAL_FILE will change the above behavior. With NET_SCP_LOCAL_FILE, $remote_file will
  153. * contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how
  154. * large $remote_file will be, as well.
  155. *
  156. * Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take
  157. * care of that, yourself.
  158. *
  159. * @param string $remote_file
  160. * @param string $data
  161. * @param int $mode
  162. * @param callable $callback
  163. * @return bool
  164. * @access public
  165. */
  166. function put($remote_file, $data, $mode = NET_SCP_STRING, $callback = null)
  167. {
  168. if (!isset($this->ssh)) {
  169. return false;
  170. }
  171. if (!$this->ssh->exec('scp -t ' . escapeshellarg($remote_file), false)) { // -t = to
  172. return false;
  173. }
  174. $temp = $this->_receive();
  175. if ($temp !== chr(0)) {
  176. return false;
  177. }
  178. if ($this->mode == NET_SCP_SSH2) {
  179. $this->packet_size = $this->ssh->packet_size_client_to_server[NET_SSH2_CHANNEL_EXEC] - 4;
  180. }
  181. $remote_file = basename($remote_file);
  182. if ($mode == NET_SCP_STRING) {
  183. $size = strlen($data);
  184. } else {
  185. if (!is_file($data)) {
  186. user_error("$data is not a valid file", E_USER_NOTICE);
  187. return false;
  188. }
  189. $fp = @fopen($data, 'rb');
  190. if (!$fp) {
  191. return false;
  192. }
  193. $size = filesize($data);
  194. }
  195. $this->_send('C0644 ' . $size . ' ' . $remote_file . "\n");
  196. $temp = $this->_receive();
  197. if ($temp !== chr(0)) {
  198. return false;
  199. }
  200. $sent = 0;
  201. while ($sent < $size) {
  202. $temp = $mode & NET_SCP_STRING ? substr($data, $sent, $this->packet_size) : fread($fp, $this->packet_size);
  203. $this->_send($temp);
  204. $sent+= strlen($temp);
  205. if (is_callable($callback)) {
  206. call_user_func($callback, $sent);
  207. }
  208. }
  209. $this->_close();
  210. if ($mode != NET_SCP_STRING) {
  211. fclose($fp);
  212. }
  213. return true;
  214. }
  215. /**
  216. * Downloads a file from the SCP server.
  217. *
  218. * Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if
  219. * the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the
  220. * operation
  221. *
  222. * @param string $remote_file
  223. * @param string $local_file
  224. * @return mixed
  225. * @access public
  226. */
  227. function get($remote_file, $local_file = false)
  228. {
  229. if (!isset($this->ssh)) {
  230. return false;
  231. }
  232. if (!$this->ssh->exec('scp -f ' . escapeshellarg($remote_file), false)) { // -f = from
  233. return false;
  234. }
  235. $this->_send("\0");
  236. if (!preg_match('#(?<perms>[^ ]+) (?<size>\d+) (?<name>.+)#', rtrim($this->_receive()), $info)) {
  237. return false;
  238. }
  239. $this->_send("\0");
  240. $size = 0;
  241. if ($local_file !== false) {
  242. $fp = @fopen($local_file, 'wb');
  243. if (!$fp) {
  244. return false;
  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. if ($local_file === false) {
  253. $content.= $data;
  254. } else {
  255. fputs($fp, $data);
  256. }
  257. }
  258. $this->_close();
  259. if ($local_file !== false) {
  260. fclose($fp);
  261. return true;
  262. }
  263. return $content;
  264. }
  265. /**
  266. * Sends a packet to an SSH server
  267. *
  268. * @param string $data
  269. * @access private
  270. */
  271. function _send($data)
  272. {
  273. switch ($this->mode) {
  274. case NET_SCP_SSH2:
  275. $this->ssh->_send_channel_packet(NET_SSH2_CHANNEL_EXEC, $data);
  276. break;
  277. case NET_SCP_SSH1:
  278. $data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($data), $data);
  279. $this->ssh->_send_binary_packet($data);
  280. }
  281. }
  282. /**
  283. * Receives a packet from an SSH server
  284. *
  285. * @return string
  286. * @access private
  287. */
  288. function _receive()
  289. {
  290. switch ($this->mode) {
  291. case NET_SCP_SSH2:
  292. return $this->ssh->_get_channel_packet(NET_SSH2_CHANNEL_EXEC, true);
  293. case NET_SCP_SSH1:
  294. if (!$this->ssh->bitmap) {
  295. return false;
  296. }
  297. while (true) {
  298. $response = $this->ssh->_get_binary_packet();
  299. switch ($response[NET_SSH1_RESPONSE_TYPE]) {
  300. case NET_SSH1_SMSG_STDOUT_DATA:
  301. if (strlen($response[NET_SSH1_RESPONSE_DATA]) < 4) {
  302. return false;
  303. }
  304. extract(unpack('Nlength', $response[NET_SSH1_RESPONSE_DATA]));
  305. return $this->ssh->_string_shift($response[NET_SSH1_RESPONSE_DATA], $length);
  306. case NET_SSH1_SMSG_STDERR_DATA:
  307. break;
  308. case NET_SSH1_SMSG_EXITSTATUS:
  309. $this->ssh->_send_binary_packet(chr(NET_SSH1_CMSG_EXIT_CONFIRMATION));
  310. fclose($this->ssh->fsock);
  311. $this->ssh->bitmap = 0;
  312. return false;
  313. default:
  314. user_error('Unknown packet received', E_USER_NOTICE);
  315. return false;
  316. }
  317. }
  318. }
  319. }
  320. /**
  321. * Closes the connection to an SSH server
  322. *
  323. * @access private
  324. */
  325. function _close()
  326. {
  327. switch ($this->mode) {
  328. case NET_SCP_SSH2:
  329. $this->ssh->_close_channel(NET_SSH2_CHANNEL_EXEC, true);
  330. break;
  331. case NET_SCP_SSH1:
  332. $this->ssh->disconnect();
  333. }
  334. }
  335. }