PageRenderTime 45ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://gitlab.com/thisishayat/itv-2016
PHP | 602 lines | 322 code | 72 blank | 208 comment | 81 complexity | 96cabeaa2703d76de5ee2fc005ea0838 MD5 | raw file
  1. <?php
  2. /**
  3. * WordPress FTP Filesystem.
  4. *
  5. * @package WordPress
  6. * @subpackage Filesystem
  7. */
  8. /**
  9. * WordPress Filesystem Class for implementing FTP.
  10. *
  11. * @since 2.5.0
  12. * @package WordPress
  13. * @subpackage Filesystem
  14. * @uses WP_Filesystem_Base Extends class
  15. */
  16. class WP_Filesystem_FTPext extends WP_Filesystem_Base {
  17. public $link;
  18. /**
  19. * @access public
  20. *
  21. * @param array $opt
  22. */
  23. public function __construct( $opt = '' ) {
  24. $this->method = 'ftpext';
  25. $this->errors = new WP_Error();
  26. // Check if possible to use ftp functions.
  27. if ( ! extension_loaded('ftp') ) {
  28. $this->errors->add('no_ftp_ext', __('The ftp PHP extension is not available'));
  29. return;
  30. }
  31. // This Class uses the timeout on a per-connection basis, Others use it on a per-action basis.
  32. if ( ! defined('FS_TIMEOUT') )
  33. define('FS_TIMEOUT', 240);
  34. if ( empty($opt['port']) )
  35. $this->options['port'] = 21;
  36. else
  37. $this->options['port'] = $opt['port'];
  38. if ( empty($opt['hostname']) )
  39. $this->errors->add('empty_hostname', __('FTP hostname is required'));
  40. else
  41. $this->options['hostname'] = $opt['hostname'];
  42. // Check if the options provided are OK.
  43. if ( empty($opt['username']) )
  44. $this->errors->add('empty_username', __('FTP username is required'));
  45. else
  46. $this->options['username'] = $opt['username'];
  47. if ( empty($opt['password']) )
  48. $this->errors->add('empty_password', __('FTP password is required'));
  49. else
  50. $this->options['password'] = $opt['password'];
  51. $this->options['ssl'] = false;
  52. if ( isset($opt['connection_type']) && 'ftps' == $opt['connection_type'] )
  53. $this->options['ssl'] = true;
  54. }
  55. /**
  56. * @access public
  57. *
  58. * @return bool
  59. */
  60. public function connect() {
  61. if ( isset($this->options['ssl']) && $this->options['ssl'] && function_exists('ftp_ssl_connect') )
  62. $this->link = @ftp_ssl_connect($this->options['hostname'], $this->options['port'], FS_CONNECT_TIMEOUT);
  63. else
  64. $this->link = @ftp_connect($this->options['hostname'], $this->options['port'], FS_CONNECT_TIMEOUT);
  65. if ( ! $this->link ) {
  66. $this->errors->add( 'connect',
  67. /* translators: %s: hostname:port */
  68. sprintf( __( 'Failed to connect to FTP Server %s' ),
  69. $this->options['hostname'] . ':' . $this->options['port']
  70. )
  71. );
  72. return false;
  73. }
  74. if ( ! @ftp_login( $this->link,$this->options['username'], $this->options['password'] ) ) {
  75. $this->errors->add( 'auth',
  76. /* translators: %s: username */
  77. sprintf( __( 'Username/Password incorrect for %s' ),
  78. $this->options['username']
  79. )
  80. );
  81. return false;
  82. }
  83. // Set the Connection to use Passive FTP
  84. @ftp_pasv( $this->link, true );
  85. if ( @ftp_get_option($this->link, FTP_TIMEOUT_SEC) < FS_TIMEOUT )
  86. @ftp_set_option($this->link, FTP_TIMEOUT_SEC, FS_TIMEOUT);
  87. return true;
  88. }
  89. /**
  90. * Retrieves the file contents.
  91. *
  92. * @since 2.5.0
  93. * @access public
  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 couldn't be retrieved.
  98. */
  99. public function get_contents( $file ) {
  100. $tempfile = wp_tempnam($file);
  101. $temp = fopen($tempfile, 'w+');
  102. if ( ! $temp )
  103. return false;
  104. if ( ! @ftp_fget($this->link, $temp, $file, FTP_BINARY ) )
  105. return false;
  106. fseek( $temp, 0 ); // Skip back to the start of the file being written to
  107. $contents = '';
  108. while ( ! feof($temp) )
  109. $contents .= fread($temp, 8192);
  110. fclose($temp);
  111. unlink($tempfile);
  112. return $contents;
  113. }
  114. /**
  115. * @access public
  116. *
  117. * @param string $file
  118. * @return array
  119. */
  120. public function get_contents_array($file) {
  121. return explode("\n", $this->get_contents($file));
  122. }
  123. /**
  124. * @access public
  125. *
  126. * @param string $file
  127. * @param string $contents
  128. * @param bool|int $mode
  129. * @return bool
  130. */
  131. public function put_contents($file, $contents, $mode = false ) {
  132. $tempfile = wp_tempnam($file);
  133. $temp = fopen( $tempfile, 'wb+' );
  134. if ( ! $temp )
  135. return false;
  136. mbstring_binary_safe_encoding();
  137. $data_length = strlen( $contents );
  138. $bytes_written = fwrite( $temp, $contents );
  139. reset_mbstring_encoding();
  140. if ( $data_length !== $bytes_written ) {
  141. fclose( $temp );
  142. unlink( $tempfile );
  143. return false;
  144. }
  145. fseek( $temp, 0 ); // Skip back to the start of the file being written to
  146. $ret = @ftp_fput( $this->link, $file, $temp, FTP_BINARY );
  147. fclose($temp);
  148. unlink($tempfile);
  149. $this->chmod($file, $mode);
  150. return $ret;
  151. }
  152. /**
  153. * @access public
  154. *
  155. * @return string
  156. */
  157. public function cwd() {
  158. $cwd = @ftp_pwd($this->link);
  159. if ( $cwd )
  160. $cwd = trailingslashit($cwd);
  161. return $cwd;
  162. }
  163. /**
  164. * @access public
  165. *
  166. * @param string $dir
  167. * @return bool
  168. */
  169. public function chdir($dir) {
  170. return @ftp_chdir($this->link, $dir);
  171. }
  172. /**
  173. * @access public
  174. *
  175. * @param string $file
  176. * @param int $mode
  177. * @param bool $recursive
  178. * @return bool
  179. */
  180. public function chmod($file, $mode = false, $recursive = false) {
  181. if ( ! $mode ) {
  182. if ( $this->is_file($file) )
  183. $mode = FS_CHMOD_FILE;
  184. elseif ( $this->is_dir($file) )
  185. $mode = FS_CHMOD_DIR;
  186. else
  187. return false;
  188. }
  189. // chmod any sub-objects if recursive.
  190. if ( $recursive && $this->is_dir($file) ) {
  191. $filelist = $this->dirlist($file);
  192. foreach ( (array)$filelist as $filename => $filemeta )
  193. $this->chmod($file . '/' . $filename, $mode, $recursive);
  194. }
  195. // chmod the file or directory
  196. if ( ! function_exists('ftp_chmod') )
  197. return (bool)@ftp_site($this->link, sprintf('CHMOD %o %s', $mode, $file));
  198. return (bool)@ftp_chmod($this->link, $mode, $file);
  199. }
  200. /**
  201. * @access public
  202. *
  203. * @param string $file
  204. * @return string
  205. */
  206. public function owner($file) {
  207. $dir = $this->dirlist($file);
  208. return $dir[$file]['owner'];
  209. }
  210. /**
  211. * @access public
  212. *
  213. * @param string $file
  214. * @return string
  215. */
  216. public function getchmod($file) {
  217. $dir = $this->dirlist($file);
  218. return $dir[$file]['permsn'];
  219. }
  220. /**
  221. * @access public
  222. *
  223. * @param string $file
  224. * @return string
  225. */
  226. public function group($file) {
  227. $dir = $this->dirlist($file);
  228. return $dir[$file]['group'];
  229. }
  230. /**
  231. * @access public
  232. *
  233. * @param string $source
  234. * @param string $destination
  235. * @param bool $overwrite
  236. * @param string|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. * @access public
  249. *
  250. * @param string $source
  251. * @param string $destination
  252. * @param bool $overwrite
  253. * @return bool
  254. */
  255. public function move($source, $destination, $overwrite = false) {
  256. return ftp_rename($this->link, $source, $destination);
  257. }
  258. /**
  259. * @access public
  260. *
  261. * @param string $file
  262. * @param bool $recursive
  263. * @param string $type
  264. * @return bool
  265. */
  266. public function delete($file, $recursive = false, $type = false) {
  267. if ( empty($file) )
  268. return false;
  269. if ( 'f' == $type || $this->is_file($file) )
  270. return @ftp_delete($this->link, $file);
  271. if ( !$recursive )
  272. return @ftp_rmdir($this->link, $file);
  273. $filelist = $this->dirlist( trailingslashit($file) );
  274. if ( !empty($filelist) )
  275. foreach ( $filelist as $delete_file )
  276. $this->delete( trailingslashit($file) . $delete_file['name'], $recursive, $delete_file['type'] );
  277. return @ftp_rmdir($this->link, $file);
  278. }
  279. /**
  280. * @access public
  281. *
  282. * @param string $file
  283. * @return bool
  284. */
  285. public function exists($file) {
  286. $list = @ftp_nlist($this->link, $file);
  287. if ( empty( $list ) && $this->is_dir( $file ) ) {
  288. return true; // File is an empty directory.
  289. }
  290. return !empty($list); //empty list = no file, so invert.
  291. }
  292. /**
  293. * @access public
  294. *
  295. * @param string $file
  296. * @return bool
  297. */
  298. public function is_file($file) {
  299. return $this->exists($file) && !$this->is_dir($file);
  300. }
  301. /**
  302. * @access public
  303. *
  304. * @param string $path
  305. * @return bool
  306. */
  307. public function is_dir($path) {
  308. $cwd = $this->cwd();
  309. $result = @ftp_chdir($this->link, trailingslashit($path) );
  310. if ( $result && $path == $this->cwd() || $this->cwd() != $cwd ) {
  311. @ftp_chdir($this->link, $cwd);
  312. return true;
  313. }
  314. return false;
  315. }
  316. /**
  317. * @access public
  318. *
  319. * @param string $file
  320. * @return bool
  321. */
  322. public function is_readable($file) {
  323. return true;
  324. }
  325. /**
  326. * @access public
  327. *
  328. * @param string $file
  329. * @return bool
  330. */
  331. public function is_writable($file) {
  332. return true;
  333. }
  334. /**
  335. * @access public
  336. *
  337. * @param string $file
  338. * @return bool
  339. */
  340. public function atime($file) {
  341. return false;
  342. }
  343. /**
  344. * @access public
  345. *
  346. * @param string $file
  347. * @return int
  348. */
  349. public function mtime($file) {
  350. return ftp_mdtm($this->link, $file);
  351. }
  352. /**
  353. * @access public
  354. *
  355. * @param string $file
  356. * @return int
  357. */
  358. public function size($file) {
  359. return ftp_size($this->link, $file);
  360. }
  361. /**
  362. * @access public
  363. *
  364. * @param string $file
  365. * @return bool
  366. */
  367. public function touch($file, $time = 0, $atime = 0) {
  368. return false;
  369. }
  370. /**
  371. * @access public
  372. *
  373. * @param string $path
  374. * @param mixed $chmod
  375. * @param mixed $chown
  376. * @param mixed $chgrp
  377. * @return bool
  378. */
  379. public function mkdir($path, $chmod = false, $chown = false, $chgrp = false) {
  380. $path = untrailingslashit($path);
  381. if ( empty($path) )
  382. return false;
  383. if ( !@ftp_mkdir($this->link, $path) )
  384. return false;
  385. $this->chmod($path, $chmod);
  386. return true;
  387. }
  388. /**
  389. * @access public
  390. *
  391. * @param string $path
  392. * @param bool $recursive
  393. * @return bool
  394. */
  395. public function rmdir($path, $recursive = false) {
  396. return $this->delete($path, $recursive);
  397. }
  398. /**
  399. * @access public
  400. *
  401. * @staticvar bool $is_windows
  402. * @param string $line
  403. * @return array
  404. */
  405. public function parselisting($line) {
  406. static $is_windows = null;
  407. if ( is_null($is_windows) )
  408. $is_windows = stripos( ftp_systype($this->link), 'win') !== false;
  409. if ( $is_windows && preg_match('/([0-9]{2})-([0-9]{2})-([0-9]{2}) +([0-9]{2}):([0-9]{2})(AM|PM) +([0-9]+|<DIR>) +(.+)/', $line, $lucifer) ) {
  410. $b = array();
  411. if ( $lucifer[3] < 70 )
  412. $lucifer[3] +=2000;
  413. else
  414. $lucifer[3] += 1900; // 4digit year fix
  415. $b['isdir'] = ( $lucifer[7] == '<DIR>');
  416. if ( $b['isdir'] )
  417. $b['type'] = 'd';
  418. else
  419. $b['type'] = 'f';
  420. $b['size'] = $lucifer[7];
  421. $b['month'] = $lucifer[1];
  422. $b['day'] = $lucifer[2];
  423. $b['year'] = $lucifer[3];
  424. $b['hour'] = $lucifer[4];
  425. $b['minute'] = $lucifer[5];
  426. $b['time'] = @mktime($lucifer[4] + (strcasecmp($lucifer[6], "PM") == 0 ? 12 : 0), $lucifer[5], 0, $lucifer[1], $lucifer[2], $lucifer[3]);
  427. $b['am/pm'] = $lucifer[6];
  428. $b['name'] = $lucifer[8];
  429. } elseif ( !$is_windows && $lucifer = preg_split('/[ ]/', $line, 9, PREG_SPLIT_NO_EMPTY)) {
  430. //echo $line."\n";
  431. $lcount = count($lucifer);
  432. if ( $lcount < 8 )
  433. return '';
  434. $b = array();
  435. $b['isdir'] = $lucifer[0]{0} === 'd';
  436. $b['islink'] = $lucifer[0]{0} === 'l';
  437. if ( $b['isdir'] )
  438. $b['type'] = 'd';
  439. elseif ( $b['islink'] )
  440. $b['type'] = 'l';
  441. else
  442. $b['type'] = 'f';
  443. $b['perms'] = $lucifer[0];
  444. $b['permsn'] = $this->getnumchmodfromh( $b['perms'] );
  445. $b['number'] = $lucifer[1];
  446. $b['owner'] = $lucifer[2];
  447. $b['group'] = $lucifer[3];
  448. $b['size'] = $lucifer[4];
  449. if ( $lcount == 8 ) {
  450. sscanf($lucifer[5], '%d-%d-%d', $b['year'], $b['month'], $b['day']);
  451. sscanf($lucifer[6], '%d:%d', $b['hour'], $b['minute']);
  452. $b['time'] = @mktime($b['hour'], $b['minute'], 0, $b['month'], $b['day'], $b['year']);
  453. $b['name'] = $lucifer[7];
  454. } else {
  455. $b['month'] = $lucifer[5];
  456. $b['day'] = $lucifer[6];
  457. if ( preg_match('/([0-9]{2}):([0-9]{2})/', $lucifer[7], $l2) ) {
  458. $b['year'] = date("Y");
  459. $b['hour'] = $l2[1];
  460. $b['minute'] = $l2[2];
  461. } else {
  462. $b['year'] = $lucifer[7];
  463. $b['hour'] = 0;
  464. $b['minute'] = 0;
  465. }
  466. $b['time'] = strtotime( sprintf('%d %s %d %02d:%02d', $b['day'], $b['month'], $b['year'], $b['hour'], $b['minute']) );
  467. $b['name'] = $lucifer[8];
  468. }
  469. }
  470. // Replace symlinks formatted as "source -> target" with just the source name
  471. if ( isset( $b['islink'] ) && $b['islink'] ) {
  472. $b['name'] = preg_replace( '/(\s*->\s*.*)$/', '', $b['name'] );
  473. }
  474. return $b;
  475. }
  476. /**
  477. * @access public
  478. *
  479. * @param string $path
  480. * @param bool $include_hidden
  481. * @param bool $recursive
  482. * @return bool|array
  483. */
  484. public function dirlist($path = '.', $include_hidden = true, $recursive = false) {
  485. if ( $this->is_file($path) ) {
  486. $limit_file = basename($path);
  487. $path = dirname($path) . '/';
  488. } else {
  489. $limit_file = false;
  490. }
  491. $pwd = @ftp_pwd($this->link);
  492. if ( ! @ftp_chdir($this->link, $path) ) // Cant change to folder = folder doesn't exist
  493. return false;
  494. $list = @ftp_rawlist($this->link, '-a', false);
  495. @ftp_chdir($this->link, $pwd);
  496. if ( empty($list) ) // Empty array = non-existent folder (real folder will show . at least)
  497. return false;
  498. $dirlist = array();
  499. foreach ( $list as $k => $v ) {
  500. $entry = $this->parselisting($v);
  501. if ( empty($entry) )
  502. continue;
  503. if ( '.' == $entry['name'] || '..' == $entry['name'] )
  504. continue;
  505. if ( ! $include_hidden && '.' == $entry['name'][0] )
  506. continue;
  507. if ( $limit_file && $entry['name'] != $limit_file)
  508. continue;
  509. $dirlist[ $entry['name'] ] = $entry;
  510. }
  511. $ret = array();
  512. foreach ( (array)$dirlist as $struc ) {
  513. if ( 'd' == $struc['type'] ) {
  514. if ( $recursive )
  515. $struc['files'] = $this->dirlist($path . '/' . $struc['name'], $include_hidden, $recursive);
  516. else
  517. $struc['files'] = array();
  518. }
  519. $ret[ $struc['name'] ] = $struc;
  520. }
  521. return $ret;
  522. }
  523. /**
  524. * @access public
  525. */
  526. public function __destruct() {
  527. if ( $this->link )
  528. ftp_close($this->link);
  529. }
  530. }