Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 
 

545 rader
11 KiB

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