PageRenderTime 43ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 1ms

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

https://gitlab.com/Gashler/sg
PHP | 469 lines | 245 code | 73 blank | 151 comment | 56 complexity | 52903bd88f231efadb6fffb53809eeb2 MD5 | raw file
  1. <?php
  2. /**
  3. * WordPress FTP Sockets Filesystem.
  4. *
  5. * @package WordPress
  6. * @subpackage Filesystem
  7. */
  8. /**
  9. * WordPress Filesystem Class for implementing FTP Sockets.
  10. *
  11. * @since 2.5.0
  12. * @package WordPress
  13. * @subpackage Filesystem
  14. * @uses WP_Filesystem_Base Extends class
  15. */
  16. class WP_Filesystem_ftpsockets extends WP_Filesystem_Base {
  17. /**
  18. * @var ftp
  19. */
  20. public $ftp;
  21. /**
  22. *
  23. * @param array $opt
  24. */
  25. public function __construct( $opt = '' ) {
  26. $this->method = 'ftpsockets';
  27. $this->errors = new WP_Error();
  28. // Check if possible to use ftp functions.
  29. if ( ! @include_once( ABSPATH . 'wp-admin/includes/class-ftp.php' ) ) {
  30. return;
  31. }
  32. $this->ftp = new ftp();
  33. if ( empty($opt['port']) )
  34. $this->options['port'] = 21;
  35. else
  36. $this->options['port'] = $opt['port'];
  37. if ( empty($opt['hostname']) )
  38. $this->errors->add('empty_hostname', __('FTP hostname is required'));
  39. else
  40. $this->options['hostname'] = $opt['hostname'];
  41. // Check if the options provided are OK.
  42. if ( empty ($opt['username']) )
  43. $this->errors->add('empty_username', __('FTP username is required'));
  44. else
  45. $this->options['username'] = $opt['username'];
  46. if ( empty ($opt['password']) )
  47. $this->errors->add('empty_password', __('FTP password is required'));
  48. else
  49. $this->options['password'] = $opt['password'];
  50. }
  51. /**
  52. *
  53. * @return bool
  54. */
  55. public function connect() {
  56. if ( ! $this->ftp )
  57. return false;
  58. $this->ftp->setTimeout(FS_CONNECT_TIMEOUT);
  59. if ( ! $this->ftp->SetServer($this->options['hostname'], $this->options['port']) ) {
  60. $this->errors->add('connect', sprintf(__('Failed to connect to FTP Server %1$s:%2$s'), $this->options['hostname'], $this->options['port']));
  61. return false;
  62. }
  63. if ( ! $this->ftp->connect() ) {
  64. $this->errors->add('connect', sprintf(__('Failed to connect to FTP Server %1$s:%2$s'), $this->options['hostname'], $this->options['port']));
  65. return false;
  66. }
  67. if ( ! $this->ftp->login($this->options['username'], $this->options['password']) ) {
  68. $this->errors->add('auth', sprintf(__('Username/Password incorrect for %s'), $this->options['username']));
  69. return false;
  70. }
  71. $this->ftp->SetType( FTP_BINARY );
  72. $this->ftp->Passive( true );
  73. $this->ftp->setTimeout( FS_TIMEOUT );
  74. return true;
  75. }
  76. /**
  77. * @param string $file
  78. * @return false|string
  79. */
  80. public function get_contents( $file ) {
  81. if ( ! $this->exists($file) )
  82. return false;
  83. $temp = wp_tempnam( $file );
  84. if ( ! $temphandle = fopen($temp, 'w+') )
  85. return false;
  86. mbstring_binary_safe_encoding();
  87. if ( ! $this->ftp->fget($temphandle, $file) ) {
  88. fclose($temphandle);
  89. unlink($temp);
  90. reset_mbstring_encoding();
  91. return ''; // Blank document, File does exist, It's just blank.
  92. }
  93. reset_mbstring_encoding();
  94. fseek( $temphandle, 0 ); // Skip back to the start of the file being written to
  95. $contents = '';
  96. while ( ! feof($temphandle) )
  97. $contents .= fread($temphandle, 8192);
  98. fclose($temphandle);
  99. unlink($temp);
  100. return $contents;
  101. }
  102. /**
  103. * @param string $file
  104. * @return array
  105. */
  106. public function get_contents_array($file) {
  107. return explode("\n", $this->get_contents($file) );
  108. }
  109. /**
  110. * @param string $file
  111. * @param string $contents
  112. * @param int|bool $mode
  113. * @return bool
  114. */
  115. public function put_contents($file, $contents, $mode = false ) {
  116. $temp = wp_tempnam( $file );
  117. if ( ! $temphandle = @fopen($temp, 'w+') ) {
  118. unlink($temp);
  119. return false;
  120. }
  121. // The FTP class uses string functions internally during file download/upload
  122. mbstring_binary_safe_encoding();
  123. $bytes_written = fwrite( $temphandle, $contents );
  124. if ( false === $bytes_written || $bytes_written != strlen( $contents ) ) {
  125. fclose( $temphandle );
  126. unlink( $temp );
  127. reset_mbstring_encoding();
  128. return false;
  129. }
  130. fseek( $temphandle, 0 ); // Skip back to the start of the file being written to
  131. $ret = $this->ftp->fput($file, $temphandle);
  132. reset_mbstring_encoding();
  133. fclose($temphandle);
  134. unlink($temp);
  135. $this->chmod($file, $mode);
  136. return $ret;
  137. }
  138. /**
  139. *
  140. * @return string
  141. */
  142. public function cwd() {
  143. $cwd = $this->ftp->pwd();
  144. if ( $cwd )
  145. $cwd = trailingslashit($cwd);
  146. return $cwd;
  147. }
  148. /**
  149. *
  150. * @param string $file
  151. * @return bool
  152. */
  153. public function chdir($file) {
  154. return $this->ftp->chdir($file);
  155. }
  156. /**
  157. * @param string $file
  158. * @param int|bool $mode
  159. * @param bool $recursive
  160. * @return bool
  161. */
  162. public function chmod($file, $mode = false, $recursive = false ) {
  163. if ( ! $mode ) {
  164. if ( $this->is_file($file) )
  165. $mode = FS_CHMOD_FILE;
  166. elseif ( $this->is_dir($file) )
  167. $mode = FS_CHMOD_DIR;
  168. else
  169. return false;
  170. }
  171. // chmod any sub-objects if recursive.
  172. if ( $recursive && $this->is_dir($file) ) {
  173. $filelist = $this->dirlist($file);
  174. foreach ( (array)$filelist as $filename => $filemeta )
  175. $this->chmod($file . '/' . $filename, $mode, $recursive);
  176. }
  177. // chmod the file or directory
  178. return $this->ftp->chmod($file, $mode);
  179. }
  180. /**
  181. * @param string $file
  182. * @return string
  183. */
  184. public function owner($file) {
  185. $dir = $this->dirlist($file);
  186. return $dir[$file]['owner'];
  187. }
  188. /**
  189. * @param string $file
  190. * @return string
  191. */
  192. public function getchmod($file) {
  193. $dir = $this->dirlist($file);
  194. return $dir[$file]['permsn'];
  195. }
  196. /**
  197. * @param string $file
  198. * @return string
  199. */
  200. public function group($file) {
  201. $dir = $this->dirlist($file);
  202. return $dir[$file]['group'];
  203. }
  204. /**
  205. * @param string $source
  206. * @param string $destination
  207. * @param bool $overwrite
  208. * @param int|bool $mode
  209. * @return bool
  210. */
  211. public function copy($source, $destination, $overwrite = false, $mode = false) {
  212. if ( ! $overwrite && $this->exists($destination) )
  213. return false;
  214. $content = $this->get_contents($source);
  215. if ( false === $content )
  216. return false;
  217. return $this->put_contents($destination, $content, $mode);
  218. }
  219. /**
  220. * @param string $source
  221. * @param string $destination
  222. * @param bool $overwrite
  223. * @return bool
  224. */
  225. public function move($source, $destination, $overwrite = false ) {
  226. return $this->ftp->rename($source, $destination);
  227. }
  228. /**
  229. * @param string $file
  230. * @param bool $recursive
  231. * @param string $type
  232. * @return bool
  233. */
  234. public function delete($file, $recursive = false, $type = false) {
  235. if ( empty($file) )
  236. return false;
  237. if ( 'f' == $type || $this->is_file($file) )
  238. return $this->ftp->delete($file);
  239. if ( !$recursive )
  240. return $this->ftp->rmdir($file);
  241. return $this->ftp->mdel($file);
  242. }
  243. /**
  244. * @param string $file
  245. * @return bool
  246. */
  247. public function exists( $file ) {
  248. $list = $this->ftp->nlist( $file );
  249. if ( empty( $list ) && $this->is_dir( $file ) ) {
  250. return true; // File is an empty directory.
  251. }
  252. return !empty( $list ); //empty list = no file, so invert.
  253. // Return $this->ftp->is_exists($file); has issues with ABOR+426 responses on the ncFTPd server.
  254. }
  255. /**
  256. * @param string $file
  257. * @return bool
  258. */
  259. public function is_file($file) {
  260. if ( $this->is_dir($file) )
  261. return false;
  262. if ( $this->exists($file) )
  263. return true;
  264. return false;
  265. }
  266. /**
  267. * @param string $path
  268. * @return bool
  269. */
  270. public function is_dir($path) {
  271. $cwd = $this->cwd();
  272. if ( $this->chdir($path) ) {
  273. $this->chdir($cwd);
  274. return true;
  275. }
  276. return false;
  277. }
  278. /**
  279. * @param string $file
  280. * @return bool
  281. */
  282. public function is_readable($file) {
  283. return true;
  284. }
  285. /**
  286. * @param string $file
  287. * @return bool
  288. */
  289. public function is_writable($file) {
  290. return true;
  291. }
  292. /**
  293. * @param string $file
  294. * @return bool
  295. */
  296. public function atime($file) {
  297. return false;
  298. }
  299. /**
  300. * @param string $file
  301. * @return int
  302. */
  303. public function mtime($file) {
  304. return $this->ftp->mdtm($file);
  305. }
  306. /**
  307. * @param string $file
  308. * @return int
  309. */
  310. public function size($file) {
  311. return $this->ftp->filesize($file);
  312. }
  313. /**
  314. * @param string $file
  315. * @param int $time
  316. * @param int $atime
  317. * @return bool
  318. */
  319. public function touch($file, $time = 0, $atime = 0 ) {
  320. return false;
  321. }
  322. /**
  323. * @param string $path
  324. * @param mixed $chmod
  325. * @param mixed $chown
  326. * @param mixed $chgrp
  327. * @return bool
  328. */
  329. public function mkdir($path, $chmod = false, $chown = false, $chgrp = false ) {
  330. $path = untrailingslashit($path);
  331. if ( empty($path) )
  332. return false;
  333. if ( ! $this->ftp->mkdir($path) )
  334. return false;
  335. if ( ! $chmod )
  336. $chmod = FS_CHMOD_DIR;
  337. $this->chmod($path, $chmod);
  338. return true;
  339. }
  340. /**
  341. * @param sting $path
  342. * @param bool $recursive
  343. */
  344. public function rmdir($path, $recursive = false ) {
  345. $this->delete($path, $recursive);
  346. }
  347. /**
  348. * @param string $path
  349. * @param bool $include_hidden
  350. * @param bool $recursive
  351. * @return bool|array
  352. */
  353. public function dirlist($path = '.', $include_hidden = true, $recursive = false ) {
  354. if ( $this->is_file($path) ) {
  355. $limit_file = basename($path);
  356. $path = dirname($path) . '/';
  357. } else {
  358. $limit_file = false;
  359. }
  360. mbstring_binary_safe_encoding();
  361. $list = $this->ftp->dirlist($path);
  362. if ( empty( $list ) && ! $this->exists( $path ) ) {
  363. reset_mbstring_encoding();
  364. return false;
  365. }
  366. $ret = array();
  367. foreach ( $list as $struc ) {
  368. if ( '.' == $struc['name'] || '..' == $struc['name'] )
  369. continue;
  370. if ( ! $include_hidden && '.' == $struc['name'][0] )
  371. continue;
  372. if ( $limit_file && $struc['name'] != $limit_file )
  373. continue;
  374. if ( 'd' == $struc['type'] ) {
  375. if ( $recursive )
  376. $struc['files'] = $this->dirlist($path . '/' . $struc['name'], $include_hidden, $recursive);
  377. else
  378. $struc['files'] = array();
  379. }
  380. // Replace symlinks formatted as "source -> target" with just the source name
  381. if ( $struc['islink'] )
  382. $struc['name'] = preg_replace( '/(\s*->\s*.*)$/', '', $struc['name'] );
  383. // Add the Octal representation of the file permissions
  384. $struc['permsn'] = $this->getnumchmodfromh( $struc['perms'] );
  385. $ret[ $struc['name'] ] = $struc;
  386. }
  387. reset_mbstring_encoding();
  388. return $ret;
  389. }
  390. /**
  391. * @access public
  392. */
  393. public function __destruct() {
  394. $this->ftp->quit();
  395. }
  396. }