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

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

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