PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/184.168.182.1/wp-content/plugins/updraftplus/includes/phpseclib/Net/SCP.php

https://gitlab.com/endomorphosis/falkenstein
PHP | 354 lines | 159 code | 36 blank | 159 comment | 30 complexity | b373d664f0e7416e366a5aad21dc59b1 MD5 | raw file
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  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. * @access public
  52. * @see Net_SCP::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 Net_SCP::_send()
  66. * @see Net_SCP::_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. * @author Jim Wigginton <terrafrost@php.net>
  81. * @version 0.1.0
  82. * @access public
  83. * @package Net_SCP
  84. */
  85. class Net_SCP {
  86. /**
  87. * SSH Object
  88. *
  89. * @var Object
  90. * @access private
  91. */
  92. var $ssh;
  93. /**
  94. * Packet Size
  95. *
  96. * @var Integer
  97. * @access private
  98. */
  99. var $packet_size;
  100. /**
  101. * Mode
  102. *
  103. * @var Integer
  104. * @access private
  105. */
  106. var $mode;
  107. /**
  108. * Default Constructor.
  109. *
  110. * Connects to an SSH server
  111. *
  112. * @param String $host
  113. * @param optional Integer $port
  114. * @param optional Integer $timeout
  115. * @return Net_SCP
  116. * @access public
  117. */
  118. function Net_SCP($ssh)
  119. {
  120. if (!is_object($ssh)) {
  121. return;
  122. }
  123. switch (strtolower(get_class($ssh))) {
  124. case'net_ssh2':
  125. $this->mode = NET_SCP_SSH2;
  126. break;
  127. case 'net_ssh1':
  128. $this->packet_size = 50000;
  129. $this->mode = NET_SCP_SSH1;
  130. break;
  131. default:
  132. return;
  133. }
  134. $this->ssh = $ssh;
  135. }
  136. /**
  137. * Uploads a file to the SCP server.
  138. *
  139. * By default, Net_SCP::put() does not read from the local filesystem. $data is dumped directly into $remote_file.
  140. * So, for example, if you set $data to 'filename.ext' and then do Net_SCP::get(), you will get a file, twelve bytes
  141. * long, containing 'filename.ext' as its contents.
  142. *
  143. * Setting $mode to NET_SCP_LOCAL_FILE will change the above behavior. With NET_SCP_LOCAL_FILE, $remote_file will
  144. * contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how
  145. * large $remote_file will be, as well.
  146. *
  147. * Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take
  148. * care of that, yourself.
  149. *
  150. * @param String $remote_file
  151. * @param String $data
  152. * @param optional Integer $mode
  153. * @return Boolean
  154. * @access public
  155. */
  156. function put($remote_file, $data, $mode = NET_SCP_STRING)
  157. {
  158. if (!isset($this->ssh)) {
  159. return false;
  160. }
  161. $this->ssh->exec('scp -t ' . $remote_file, false); // -t = to
  162. $temp = $this->_receive();
  163. if ($temp !== chr(0)) {
  164. return false;
  165. }
  166. if ($this->mode == NET_SCP_SSH2) {
  167. $this->packet_size = $this->ssh->packet_size_client_to_server[NET_SSH2_CHANNEL_EXEC];
  168. }
  169. $remote_file = basename($remote_file);
  170. if ($mode == NET_SCP_STRING) {
  171. $size = strlen($data);
  172. } else {
  173. if (!is_file($data)) {
  174. user_error("$data is not a valid file", E_USER_NOTICE);
  175. return false;
  176. }
  177. $fp = @fopen($data, 'rb');
  178. if (!$fp) {
  179. fclose($fp);
  180. return false;
  181. }
  182. $size = filesize($data);
  183. }
  184. $this->_send('C0644 ' . $size . ' ' . $remote_file . "\n");
  185. $temp = $this->_receive();
  186. if ($temp !== chr(0)) {
  187. return false;
  188. }
  189. $sent = 0;
  190. while ($sent < $size) {
  191. $temp = $mode & NET_SCP_STRING ? substr($data, $sent, $this->packet_size) : fread($fp, $this->packet_size);
  192. $this->_send($temp);
  193. $sent+= strlen($temp);
  194. }
  195. $this->_close();
  196. if ($mode != NET_SCP_STRING) {
  197. fclose($fp);
  198. }
  199. return true;
  200. }
  201. /**
  202. * Downloads a file from the SCP server.
  203. *
  204. * Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if
  205. * the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the
  206. * operation
  207. *
  208. * @param String $remote_file
  209. * @param optional String $local_file
  210. * @return Mixed
  211. * @access public
  212. */
  213. function get($remote_file, $local_file = false)
  214. {
  215. if (!isset($this->ssh)) {
  216. return false;
  217. }
  218. $this->ssh->exec('scp -f ' . $remote_file, false); // -f = from
  219. $this->_send("\0");
  220. if (!preg_match('#(?<perms>[^ ]+) (?<size>\d+) (?<name>.+)#', rtrim($this->_receive()), $info)) {
  221. return false;
  222. }
  223. $this->_send("\0");
  224. $size = 0;
  225. if ($local_file !== false) {
  226. $fp = @fopen($local_file, 'wb');
  227. if (!$fp) {
  228. return false;
  229. }
  230. }
  231. $content = '';
  232. while ($size < $info['size']) {
  233. $data = $this->_receive();
  234. if (strlen($data) + $size > $info['size']) $data = substr($data, 0, $info['size'] - $size);
  235. // SCP usually seems to split stuff out into 16k chunks
  236. $size+= strlen($data);
  237. if ($local_file === false) {
  238. $content.= $data;
  239. } else {
  240. fputs($fp, $data);
  241. }
  242. }
  243. $this->_close();
  244. if ($local_file !== false) {
  245. fclose($fp);
  246. return true;
  247. }
  248. return $content;
  249. }
  250. /**
  251. * Sends a packet to an SSH server
  252. *
  253. * @param String $data
  254. * @access private
  255. */
  256. function _send($data)
  257. {
  258. switch ($this->mode) {
  259. case NET_SCP_SSH2:
  260. $this->ssh->_send_channel_packet(NET_SSH2_CHANNEL_EXEC, $data);
  261. break;
  262. case NET_SCP_SSH1:
  263. $data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($data), $data);
  264. $this->ssh->_send_binary_packet($data);
  265. }
  266. }
  267. /**
  268. * Receives a packet from an SSH server
  269. *
  270. * @return String
  271. * @access private
  272. */
  273. function _receive()
  274. {
  275. switch ($this->mode) {
  276. case NET_SCP_SSH2:
  277. return $this->ssh->_get_channel_packet(NET_SSH2_CHANNEL_EXEC, true);
  278. case NET_SCP_SSH1:
  279. if (!$this->ssh->bitmap) {
  280. return false;
  281. }
  282. while (true) {
  283. $response = $this->ssh->_get_binary_packet();
  284. switch ($response[NET_SSH1_RESPONSE_TYPE]) {
  285. case NET_SSH1_SMSG_STDOUT_DATA:
  286. extract(unpack('Nlength', $response[NET_SSH1_RESPONSE_DATA]));
  287. return $this->ssh->_string_shift($response[NET_SSH1_RESPONSE_DATA], $length);
  288. case NET_SSH1_SMSG_STDERR_DATA:
  289. break;
  290. case NET_SSH1_SMSG_EXITSTATUS:
  291. $this->ssh->_send_binary_packet(chr(NET_SSH1_CMSG_EXIT_CONFIRMATION));
  292. fclose($this->ssh->fsock);
  293. $this->ssh->bitmap = 0;
  294. return false;
  295. default:
  296. user_error('Unknown packet received', E_USER_NOTICE);
  297. return false;
  298. }
  299. }
  300. }
  301. }
  302. /**
  303. * Closes the connection to an SSH server
  304. *
  305. * @access private
  306. */
  307. function _close()
  308. {
  309. switch ($this->mode) {
  310. case NET_SCP_SSH2:
  311. $this->ssh->_close_channel(NET_SSH2_CHANNEL_EXEC);
  312. break;
  313. case NET_SCP_SSH1:
  314. $this->ssh->disconnect();
  315. }
  316. }
  317. }