PageRenderTime 97ms CodeModel.GetById 19ms RepoModel.GetById 4ms app.codeStats 0ms

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

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