PageRenderTime 29ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-admin/includes/class-wp-filesystem-ssh2.php

https://gitlab.com/Blueprint-Marketing/WordPress-1
PHP | 391 lines | 280 code | 63 blank | 48 comment | 71 complexity | c5a841378285b599d8f5b75d3a181033 MD5 | raw file
  1. <?php
  2. /**
  3. * WordPress Filesystem Class for implementing SSH2
  4. *
  5. * To use this class you must follow these steps for PHP 5.2.6+
  6. *
  7. * @contrib http://kevin.vanzonneveld.net/techblog/article/make_ssh_connections_with_php/ - Installation Notes
  8. *
  9. * Complie libssh2 (Note: Only 0.14 is officaly working with PHP 5.2.6+ right now, But many users have found the latest versions work)
  10. *
  11. * cd /usr/src
  12. * wget http://surfnet.dl.sourceforge.net/sourceforge/libssh2/libssh2-0.14.tar.gz
  13. * tar -zxvf libssh2-0.14.tar.gz
  14. * cd libssh2-0.14/
  15. * ./configure
  16. * make all install
  17. *
  18. * Note: Do not leave the directory yet!
  19. *
  20. * Enter: pecl install -f ssh2
  21. *
  22. * Copy the ssh.so file it creates to your PHP Module Directory.
  23. * Open up your PHP.INI file and look for where extensions are placed.
  24. * Add in your PHP.ini file: extension=ssh2.so
  25. *
  26. * Restart Apache!
  27. * Check phpinfo() streams to confirm that: ssh2.shell, ssh2.exec, ssh2.tunnel, ssh2.scp, ssh2.sftp exist.
  28. *
  29. * Note: as of WordPress 2.8, This utilises the PHP5+ function 'stream_get_contents'
  30. *
  31. * @since 2.7.0
  32. *
  33. * @package WordPress
  34. * @subpackage Filesystem
  35. */
  36. class WP_Filesystem_SSH2 extends WP_Filesystem_Base {
  37. var $link = false;
  38. var $sftp_link = false;
  39. var $keys = false;
  40. var $errors = array();
  41. var $options = array();
  42. function __construct($opt='') {
  43. $this->method = 'ssh2';
  44. $this->errors = new WP_Error();
  45. //Check if possible to use ssh2 functions.
  46. if ( ! extension_loaded('ssh2') ) {
  47. $this->errors->add('no_ssh2_ext', __('The ssh2 PHP extension is not available'));
  48. return false;
  49. }
  50. if ( !function_exists('stream_get_contents') ) {
  51. $this->errors->add('ssh2_php_requirement', __('The ssh2 PHP extension is available, however, we require the PHP5 function <code>stream_get_contents()</code>'));
  52. return false;
  53. }
  54. // Set defaults:
  55. if ( empty($opt['port']) )
  56. $this->options['port'] = 22;
  57. else
  58. $this->options['port'] = $opt['port'];
  59. if ( empty($opt['hostname']) )
  60. $this->errors->add('empty_hostname', __('SSH2 hostname is required'));
  61. else
  62. $this->options['hostname'] = $opt['hostname'];
  63. if ( ! empty($opt['base']) )
  64. $this->wp_base = $opt['base'];
  65. // Check if the options provided are OK.
  66. if ( !empty ($opt['public_key']) && !empty ($opt['private_key']) ) {
  67. $this->options['public_key'] = $opt['public_key'];
  68. $this->options['private_key'] = $opt['private_key'];
  69. $this->options['hostkey'] = array('hostkey' => 'ssh-rsa');
  70. $this->keys = true;
  71. } elseif ( empty ($opt['username']) ) {
  72. $this->errors->add('empty_username', __('SSH2 username is required'));
  73. }
  74. if ( !empty($opt['username']) )
  75. $this->options['username'] = $opt['username'];
  76. if ( empty ($opt['password']) ) {
  77. if ( !$this->keys ) //password can be blank if we are using keys
  78. $this->errors->add('empty_password', __('SSH2 password is required'));
  79. } else {
  80. $this->options['password'] = $opt['password'];
  81. }
  82. }
  83. function connect() {
  84. if ( ! $this->keys ) {
  85. $this->link = @ssh2_connect($this->options['hostname'], $this->options['port']);
  86. } else {
  87. $this->link = @ssh2_connect($this->options['hostname'], $this->options['port'], $this->options['hostkey']);
  88. }
  89. if ( ! $this->link ) {
  90. $this->errors->add('connect', sprintf(__('Failed to connect to SSH2 Server %1$s:%2$s'), $this->options['hostname'], $this->options['port']));
  91. return false;
  92. }
  93. if ( !$this->keys ) {
  94. if ( ! @ssh2_auth_password($this->link, $this->options['username'], $this->options['password']) ) {
  95. $this->errors->add('auth', sprintf(__('Username/Password incorrect for %s'), $this->options['username']));
  96. return false;
  97. }
  98. } else {
  99. if ( ! @ssh2_auth_pubkey_file($this->link, $this->options['username'], $this->options['public_key'], $this->options['private_key'], $this->options['password'] ) ) {
  100. $this->errors->add('auth', sprintf(__('Public and Private keys incorrect for %s'), $this->options['username']));
  101. return false;
  102. }
  103. }
  104. $this->sftp_link = ssh2_sftp($this->link);
  105. return true;
  106. }
  107. function run_command( $command, $returnbool = false) {
  108. if ( ! $this->link )
  109. return false;
  110. if ( ! ($stream = ssh2_exec($this->link, $command)) ) {
  111. $this->errors->add('command', sprintf(__('Unable to perform command: %s'), $command));
  112. } else {
  113. stream_set_blocking( $stream, true );
  114. stream_set_timeout( $stream, FS_TIMEOUT );
  115. $data = stream_get_contents( $stream );
  116. fclose( $stream );
  117. if ( $returnbool )
  118. return ( $data === false ) ? false : '' != trim($data);
  119. else
  120. return $data;
  121. }
  122. return false;
  123. }
  124. function get_contents( $file ) {
  125. $file = ltrim($file, '/');
  126. return file_get_contents('ssh2.sftp://' . $this->sftp_link . '/' . $file);
  127. }
  128. function get_contents_array($file) {
  129. $file = ltrim($file, '/');
  130. return file('ssh2.sftp://' . $this->sftp_link . '/' . $file);
  131. }
  132. function put_contents($file, $contents, $mode = false ) {
  133. $ret = file_put_contents( 'ssh2.sftp://' . $this->sftp_link . '/' . ltrim( $file, '/' ), $contents );
  134. if ( $ret !== strlen( $contents ) )
  135. return false;
  136. $this->chmod($file, $mode);
  137. return true;
  138. }
  139. function cwd() {
  140. $cwd = $this->run_command('pwd');
  141. if ( $cwd )
  142. $cwd = trailingslashit($cwd);
  143. return $cwd;
  144. }
  145. function chdir($dir) {
  146. return $this->run_command('cd ' . $dir, true);
  147. }
  148. function chgrp($file, $group, $recursive = false ) {
  149. if ( ! $this->exists($file) )
  150. return false;
  151. if ( ! $recursive || ! $this->is_dir($file) )
  152. return $this->run_command(sprintf('chgrp %s %s', escapeshellarg($group), escapeshellarg($file)), true);
  153. return $this->run_command(sprintf('chgrp -R %s %s', escapeshellarg($group), escapeshellarg($file)), true);
  154. }
  155. function chmod($file, $mode = false, $recursive = false) {
  156. if ( ! $this->exists($file) )
  157. return false;
  158. if ( ! $mode ) {
  159. if ( $this->is_file($file) )
  160. $mode = FS_CHMOD_FILE;
  161. elseif ( $this->is_dir($file) )
  162. $mode = FS_CHMOD_DIR;
  163. else
  164. return false;
  165. }
  166. if ( ! $recursive || ! $this->is_dir($file) )
  167. return $this->run_command(sprintf('chmod %o %s', $mode, escapeshellarg($file)), true);
  168. return $this->run_command(sprintf('chmod -R %o %s', $mode, escapeshellarg($file)), true);
  169. }
  170. /**
  171. * Change the ownership of a file / folder.
  172. *
  173. * @since Unknown
  174. *
  175. * @param string $file Path to the file.
  176. * @param mixed $owner A user name or number.
  177. * @param bool $recursive Optional. If set True changes file owner recursivly. Defaults to False.
  178. * @return bool Returns true on success or false on failure.
  179. */
  180. function chown( $file, $owner, $recursive = false ) {
  181. if ( ! $this->exists($file) )
  182. return false;
  183. if ( ! $recursive || ! $this->is_dir($file) )
  184. return $this->run_command(sprintf('chown %s %s', escapeshellarg($owner), escapeshellarg($file)), true);
  185. return $this->run_command(sprintf('chown -R %s %s', escapeshellarg($owner), escapeshellarg($file)), true);
  186. }
  187. function owner($file) {
  188. $owneruid = @fileowner('ssh2.sftp://' . $this->sftp_link . '/' . ltrim($file, '/'));
  189. if ( ! $owneruid )
  190. return false;
  191. if ( ! function_exists('posix_getpwuid') )
  192. return $owneruid;
  193. $ownerarray = posix_getpwuid($owneruid);
  194. return $ownerarray['name'];
  195. }
  196. function getchmod($file) {
  197. return substr(decoct(@fileperms( 'ssh2.sftp://' . $this->sftp_link . '/' . ltrim($file, '/') )),3);
  198. }
  199. function group($file) {
  200. $gid = @filegroup('ssh2.sftp://' . $this->sftp_link . '/' . ltrim($file, '/'));
  201. if ( ! $gid )
  202. return false;
  203. if ( ! function_exists('posix_getgrgid') )
  204. return $gid;
  205. $grouparray = posix_getgrgid($gid);
  206. return $grouparray['name'];
  207. }
  208. function copy($source, $destination, $overwrite = false, $mode = false) {
  209. if ( ! $overwrite && $this->exists($destination) )
  210. return false;
  211. $content = $this->get_contents($source);
  212. if ( false === $content)
  213. return false;
  214. return $this->put_contents($destination, $content, $mode);
  215. }
  216. function move($source, $destination, $overwrite = false) {
  217. return @ssh2_sftp_rename($this->link, $source, $destination);
  218. }
  219. function delete($file, $recursive = false, $type = false) {
  220. if ( 'f' == $type || $this->is_file($file) )
  221. return ssh2_sftp_unlink($this->sftp_link, $file);
  222. if ( ! $recursive )
  223. return ssh2_sftp_rmdir($this->sftp_link, $file);
  224. $filelist = $this->dirlist($file);
  225. if ( is_array($filelist) ) {
  226. foreach ( $filelist as $filename => $fileinfo) {
  227. $this->delete($file . '/' . $filename, $recursive, $fileinfo['type']);
  228. }
  229. }
  230. return ssh2_sftp_rmdir($this->sftp_link, $file);
  231. }
  232. function exists($file) {
  233. $file = ltrim($file, '/');
  234. return file_exists('ssh2.sftp://' . $this->sftp_link . '/' . $file);
  235. }
  236. function is_file($file) {
  237. $file = ltrim($file, '/');
  238. return is_file('ssh2.sftp://' . $this->sftp_link . '/' . $file);
  239. }
  240. function is_dir($path) {
  241. $path = ltrim($path, '/');
  242. return is_dir('ssh2.sftp://' . $this->sftp_link . '/' . $path);
  243. }
  244. function is_readable($file) {
  245. $file = ltrim($file, '/');
  246. return is_readable('ssh2.sftp://' . $this->sftp_link . '/' . $file);
  247. }
  248. function is_writable($file) {
  249. $file = ltrim($file, '/');
  250. return is_writable('ssh2.sftp://' . $this->sftp_link . '/' . $file);
  251. }
  252. function atime($file) {
  253. $file = ltrim($file, '/');
  254. return fileatime('ssh2.sftp://' . $this->sftp_link . '/' . $file);
  255. }
  256. function mtime($file) {
  257. $file = ltrim($file, '/');
  258. return filemtime('ssh2.sftp://' . $this->sftp_link . '/' . $file);
  259. }
  260. function size($file) {
  261. $file = ltrim($file, '/');
  262. return filesize('ssh2.sftp://' . $this->sftp_link . '/' . $file);
  263. }
  264. function touch($file, $time = 0, $atime = 0) {
  265. //Not implemented.
  266. }
  267. function mkdir($path, $chmod = false, $chown = false, $chgrp = false) {
  268. $path = untrailingslashit($path);
  269. if ( empty($path) )
  270. return false;
  271. if ( ! $chmod )
  272. $chmod = FS_CHMOD_DIR;
  273. if ( ! ssh2_sftp_mkdir($this->sftp_link, $path, $chmod, true) )
  274. return false;
  275. if ( $chown )
  276. $this->chown($path, $chown);
  277. if ( $chgrp )
  278. $this->chgrp($path, $chgrp);
  279. return true;
  280. }
  281. function rmdir($path, $recursive = false) {
  282. return $this->delete($path, $recursive);
  283. }
  284. function dirlist($path, $include_hidden = true, $recursive = false) {
  285. if ( $this->is_file($path) ) {
  286. $limit_file = basename($path);
  287. $path = dirname($path);
  288. } else {
  289. $limit_file = false;
  290. }
  291. if ( ! $this->is_dir($path) )
  292. return false;
  293. $ret = array();
  294. $dir = @dir('ssh2.sftp://' . $this->sftp_link .'/' . ltrim($path, '/') );
  295. if ( ! $dir )
  296. return false;
  297. while (false !== ($entry = $dir->read()) ) {
  298. $struc = array();
  299. $struc['name'] = $entry;
  300. if ( '.' == $struc['name'] || '..' == $struc['name'] )
  301. continue; //Do not care about these folders.
  302. if ( ! $include_hidden && '.' == $struc['name'][0] )
  303. continue;
  304. if ( $limit_file && $struc['name'] != $limit_file )
  305. continue;
  306. $struc['perms'] = $this->gethchmod($path.'/'.$entry);
  307. $struc['permsn'] = $this->getnumchmodfromh($struc['perms']);
  308. $struc['number'] = false;
  309. $struc['owner'] = $this->owner($path.'/'.$entry);
  310. $struc['group'] = $this->group($path.'/'.$entry);
  311. $struc['size'] = $this->size($path.'/'.$entry);
  312. $struc['lastmodunix']= $this->mtime($path.'/'.$entry);
  313. $struc['lastmod'] = date('M j',$struc['lastmodunix']);
  314. $struc['time'] = date('h:i:s',$struc['lastmodunix']);
  315. $struc['type'] = $this->is_dir($path.'/'.$entry) ? 'd' : 'f';
  316. if ( 'd' == $struc['type'] ) {
  317. if ( $recursive )
  318. $struc['files'] = $this->dirlist($path . '/' . $struc['name'], $include_hidden, $recursive);
  319. else
  320. $struc['files'] = array();
  321. }
  322. $ret[ $struc['name'] ] = $struc;
  323. }
  324. $dir->close();
  325. unset($dir);
  326. return $ret;
  327. }
  328. }