PageRenderTime 61ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/system/libraries/Ftp.php

https://github.com/katzgrau/notes
PHP | 618 lines | 296 code | 86 blank | 236 comment | 65 complexity | 71cb0ce5b79431e16878a66e6e97751f MD5 | raw file
  1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2. /**
  3. * CodeIgniter
  4. *
  5. * An open source application development framework for PHP 4.3.2 or newer
  6. *
  7. * @package CodeIgniter
  8. * @author ExpressionEngine Dev Team
  9. * @copyright Copyright (c) 2008, EllisLab, Inc.
  10. * @license http://codeigniter.com/user_guide/license.html
  11. * @link http://codeigniter.com
  12. * @since Version 1.0
  13. * @filesource
  14. */
  15. // ------------------------------------------------------------------------
  16. /**
  17. * FTP Class
  18. *
  19. * @package CodeIgniter
  20. * @subpackage Libraries
  21. * @category Libraries
  22. * @author ExpressionEngine Dev Team
  23. * @link http://codeigniter.com/user_guide/libraries/ftp.html
  24. */
  25. class CI_FTP {
  26. var $hostname = '';
  27. var $username = '';
  28. var $password = '';
  29. var $port = 21;
  30. var $passive = TRUE;
  31. var $debug = FALSE;
  32. var $conn_id = FALSE;
  33. /**
  34. * Constructor - Sets Preferences
  35. *
  36. * The constructor can be passed an array of config values
  37. */
  38. function CI_FTP($config = array())
  39. {
  40. if (count($config) > 0)
  41. {
  42. $this->initialize($config);
  43. }
  44. log_message('debug', "FTP Class Initialized");
  45. }
  46. // --------------------------------------------------------------------
  47. /**
  48. * Initialize preferences
  49. *
  50. * @access public
  51. * @param array
  52. * @return void
  53. */
  54. function initialize($config = array())
  55. {
  56. foreach ($config as $key => $val)
  57. {
  58. if (isset($this->$key))
  59. {
  60. $this->$key = $val;
  61. }
  62. }
  63. // Prep the hostname
  64. $this->hostname = preg_replace('|.+?://|', '', $this->hostname);
  65. }
  66. // --------------------------------------------------------------------
  67. /**
  68. * FTP Connect
  69. *
  70. * @access public
  71. * @param array the connection values
  72. * @return bool
  73. */
  74. function connect($config = array())
  75. {
  76. if (count($config) > 0)
  77. {
  78. $this->initialize($config);
  79. }
  80. if (FALSE === ($this->conn_id = @ftp_connect($this->hostname, $this->port)))
  81. {
  82. if ($this->debug == TRUE)
  83. {
  84. $this->_error('ftp_unable_to_connect');
  85. }
  86. return FALSE;
  87. }
  88. if ( ! $this->_login())
  89. {
  90. if ($this->debug == TRUE)
  91. {
  92. $this->_error('ftp_unable_to_login');
  93. }
  94. return FALSE;
  95. }
  96. // Set passive mode if needed
  97. if ($this->passive == TRUE)
  98. {
  99. ftp_pasv($this->conn_id, TRUE);
  100. }
  101. return TRUE;
  102. }
  103. // --------------------------------------------------------------------
  104. /**
  105. * FTP Login
  106. *
  107. * @access private
  108. * @return bool
  109. */
  110. function _login()
  111. {
  112. return @ftp_login($this->conn_id, $this->username, $this->password);
  113. }
  114. // --------------------------------------------------------------------
  115. /**
  116. * Validates the connection ID
  117. *
  118. * @access private
  119. * @return bool
  120. */
  121. function _is_conn()
  122. {
  123. if ( ! is_resource($this->conn_id))
  124. {
  125. if ($this->debug == TRUE)
  126. {
  127. $this->_error('ftp_no_connection');
  128. }
  129. return FALSE;
  130. }
  131. return TRUE;
  132. }
  133. // --------------------------------------------------------------------
  134. /**
  135. * Change direcotry
  136. *
  137. * The second parameter lets us momentarily turn off debugging so that
  138. * this function can be used to test for the existance of a folder
  139. * without throwing an error. There's no FTP equivalent to is_dir()
  140. * so we do it by trying to change to a particular directory.
  141. * Internally, this paramter is only used by the "mirror" function below.
  142. *
  143. * @access public
  144. * @param string
  145. * @param bool
  146. * @return bool
  147. */
  148. function changedir($path = '', $supress_debug = FALSE)
  149. {
  150. if ($path == '' OR ! $this->_is_conn())
  151. {
  152. return FALSE;
  153. }
  154. $result = @ftp_chdir($this->conn_id, $path);
  155. if ($result === FALSE)
  156. {
  157. if ($this->debug == TRUE AND $supress_debug == FALSE)
  158. {
  159. $this->_error('ftp_unable_to_changedir');
  160. }
  161. return FALSE;
  162. }
  163. return TRUE;
  164. }
  165. // --------------------------------------------------------------------
  166. /**
  167. * Create a directory
  168. *
  169. * @access public
  170. * @param string
  171. * @return bool
  172. */
  173. function mkdir($path = '', $permissions = NULL)
  174. {
  175. if ($path == '' OR ! $this->_is_conn())
  176. {
  177. return FALSE;
  178. }
  179. $result = @ftp_mkdir($this->conn_id, $path);
  180. if ($result === FALSE)
  181. {
  182. if ($this->debug == TRUE)
  183. {
  184. $this->_error('ftp_unable_to_makdir');
  185. }
  186. return FALSE;
  187. }
  188. // Set file permissions if needed
  189. if ( ! is_null($permissions))
  190. {
  191. $this->chmod($path, (int)$permissions);
  192. }
  193. return TRUE;
  194. }
  195. // --------------------------------------------------------------------
  196. /**
  197. * Upload a file to the server
  198. *
  199. * @access public
  200. * @param string
  201. * @param string
  202. * @param string
  203. * @return bool
  204. */
  205. function upload($locpath, $rempath, $mode = 'auto', $permissions = NULL)
  206. {
  207. if ( ! $this->_is_conn())
  208. {
  209. return FALSE;
  210. }
  211. if ( ! file_exists($locpath))
  212. {
  213. $this->_error('ftp_no_source_file');
  214. return FALSE;
  215. }
  216. // Set the mode if not specified
  217. if ($mode == 'auto')
  218. {
  219. // Get the file extension so we can set the upload type
  220. $ext = $this->_getext($locpath);
  221. $mode = $this->_settype($ext);
  222. }
  223. $mode = ($mode == 'ascii') ? FTP_ASCII : FTP_BINARY;
  224. $result = @ftp_put($this->conn_id, $rempath, $locpath, $mode);
  225. if ($result === FALSE)
  226. {
  227. if ($this->debug == TRUE)
  228. {
  229. $this->_error('ftp_unable_to_upload');
  230. }
  231. return FALSE;
  232. }
  233. // Set file permissions if needed
  234. if ( ! is_null($permissions))
  235. {
  236. $this->chmod($rempath, (int)$permissions);
  237. }
  238. return TRUE;
  239. }
  240. // --------------------------------------------------------------------
  241. /**
  242. * Rename (or move) a file
  243. *
  244. * @access public
  245. * @param string
  246. * @param string
  247. * @param bool
  248. * @return bool
  249. */
  250. function rename($old_file, $new_file, $move = FALSE)
  251. {
  252. if ( ! $this->_is_conn())
  253. {
  254. return FALSE;
  255. }
  256. $result = @ftp_rename($this->conn_id, $old_file, $new_file);
  257. if ($result === FALSE)
  258. {
  259. if ($this->debug == TRUE)
  260. {
  261. $msg = ($move == FALSE) ? 'ftp_unable_to_rename' : 'ftp_unable_to_move';
  262. $this->_error($msg);
  263. }
  264. return FALSE;
  265. }
  266. return TRUE;
  267. }
  268. // --------------------------------------------------------------------
  269. /**
  270. * Move a file
  271. *
  272. * @access public
  273. * @param string
  274. * @param string
  275. * @return bool
  276. */
  277. function move($old_file, $new_file)
  278. {
  279. return $this->rename($old_file, $new_file, TRUE);
  280. }
  281. // --------------------------------------------------------------------
  282. /**
  283. * Rename (or move) a file
  284. *
  285. * @access public
  286. * @param string
  287. * @return bool
  288. */
  289. function delete_file($filepath)
  290. {
  291. if ( ! $this->_is_conn())
  292. {
  293. return FALSE;
  294. }
  295. $result = @ftp_delete($this->conn_id, $filepath);
  296. if ($result === FALSE)
  297. {
  298. if ($this->debug == TRUE)
  299. {
  300. $this->_error('ftp_unable_to_delete');
  301. }
  302. return FALSE;
  303. }
  304. return TRUE;
  305. }
  306. // --------------------------------------------------------------------
  307. /**
  308. * Delete a folder and recursively delete everything (including sub-folders)
  309. * containted within it.
  310. *
  311. * @access public
  312. * @param string
  313. * @return bool
  314. */
  315. function delete_dir($filepath)
  316. {
  317. if ( ! $this->_is_conn())
  318. {
  319. return FALSE;
  320. }
  321. // Add a trailing slash to the file path if needed
  322. $filepath = preg_replace("/(.+?)\/*$/", "\\1/", $filepath);
  323. $list = $this->list_files($filepath);
  324. if ($list !== FALSE AND count($list) > 0)
  325. {
  326. foreach ($list as $item)
  327. {
  328. // If we can't delete the item it's probaly a folder so
  329. // we'll recursively call delete_dir()
  330. if ( ! @ftp_delete($this->conn_id, $item))
  331. {
  332. $this->delete_dir($item);
  333. }
  334. }
  335. }
  336. $result = @ftp_rmdir($this->conn_id, $filepath);
  337. if ($result === FALSE)
  338. {
  339. if ($this->debug == TRUE)
  340. {
  341. $this->_error('ftp_unable_to_delete');
  342. }
  343. return FALSE;
  344. }
  345. return TRUE;
  346. }
  347. // --------------------------------------------------------------------
  348. /**
  349. * Set file permissions
  350. *
  351. * @access public
  352. * @param string the file path
  353. * @param string the permissions
  354. * @return bool
  355. */
  356. function chmod($path, $perm)
  357. {
  358. if ( ! $this->_is_conn())
  359. {
  360. return FALSE;
  361. }
  362. // Permissions can only be set when running PHP 5
  363. if ( ! function_exists('ftp_chmod'))
  364. {
  365. if ($this->debug == TRUE)
  366. {
  367. $this->_error('ftp_unable_to_chmod');
  368. }
  369. return FALSE;
  370. }
  371. $result = @ftp_chmod($this->conn_id, $perm, $path);
  372. if ($result === FALSE)
  373. {
  374. if ($this->debug == TRUE)
  375. {
  376. $this->_error('ftp_unable_to_chmod');
  377. }
  378. return FALSE;
  379. }
  380. return TRUE;
  381. }
  382. // --------------------------------------------------------------------
  383. /**
  384. * FTP List files in the specified directory
  385. *
  386. * @access public
  387. * @return array
  388. */
  389. function list_files($path = '.')
  390. {
  391. if ( ! $this->_is_conn())
  392. {
  393. return FALSE;
  394. }
  395. return ftp_nlist($this->conn_id, $path);
  396. }
  397. // ------------------------------------------------------------------------
  398. /**
  399. * Read a directory and recreate it remotely
  400. *
  401. * This function recursively reads a folder and everything it contains (including
  402. * sub-folders) and creates a mirror via FTP based on it. Whatever the directory structure
  403. * of the original file path will be recreated on the server.
  404. *
  405. * @access public
  406. * @param string path to source with trailing slash
  407. * @param string path to destination - include the base folder with trailing slash
  408. * @return bool
  409. */
  410. function mirror($locpath, $rempath)
  411. {
  412. if ( ! $this->_is_conn())
  413. {
  414. return FALSE;
  415. }
  416. // Open the local file path
  417. if ($fp = @opendir($locpath))
  418. {
  419. // Attempt to open the remote file path.
  420. if ( ! $this->changedir($rempath, TRUE))
  421. {
  422. // If it doesn't exist we'll attempt to create the direcotory
  423. if ( ! $this->mkdir($rempath) OR ! $this->changedir($rempath))
  424. {
  425. return FALSE;
  426. }
  427. }
  428. // Recursively read the local directory
  429. while (FALSE !== ($file = readdir($fp)))
  430. {
  431. if (@is_dir($locpath.$file) && substr($file, 0, 1) != '.')
  432. {
  433. $this->mirror($locpath.$file."/", $rempath.$file."/");
  434. }
  435. elseif (substr($file, 0, 1) != ".")
  436. {
  437. // Get the file extension so we can se the upload type
  438. $ext = $this->_getext($file);
  439. $mode = $this->_settype($ext);
  440. $this->upload($locpath.$file, $rempath.$file, $mode);
  441. }
  442. }
  443. return TRUE;
  444. }
  445. return FALSE;
  446. }
  447. // --------------------------------------------------------------------
  448. /**
  449. * Extract the file extension
  450. *
  451. * @access private
  452. * @param string
  453. * @return string
  454. */
  455. function _getext($filename)
  456. {
  457. if (FALSE === strpos($filename, '.'))
  458. {
  459. return 'txt';
  460. }
  461. $x = explode('.', $filename);
  462. return end($x);
  463. }
  464. // --------------------------------------------------------------------
  465. /**
  466. * Set the upload type
  467. *
  468. * @access private
  469. * @param string
  470. * @return string
  471. */
  472. function _settype($ext)
  473. {
  474. $text_types = array(
  475. 'txt',
  476. 'text',
  477. 'php',
  478. 'phps',
  479. 'php4',
  480. 'js',
  481. 'css',
  482. 'htm',
  483. 'html',
  484. 'phtml',
  485. 'shtml',
  486. 'log',
  487. 'xml'
  488. );
  489. return (in_array($ext, $text_types)) ? 'ascii' : 'binary';
  490. }
  491. // ------------------------------------------------------------------------
  492. /**
  493. * Close the connection
  494. *
  495. * @access public
  496. * @param string path to source
  497. * @param string path to destination
  498. * @return bool
  499. */
  500. function close()
  501. {
  502. if ( ! $this->_is_conn())
  503. {
  504. return FALSE;
  505. }
  506. @ftp_close($this->conn_id);
  507. }
  508. // ------------------------------------------------------------------------
  509. /**
  510. * Display error message
  511. *
  512. * @access private
  513. * @param string
  514. * @return bool
  515. */
  516. function _error($line)
  517. {
  518. $CI =& get_instance();
  519. $CI->lang->load('ftp');
  520. show_error($CI->lang->line($line));
  521. }
  522. }
  523. // END FTP Class
  524. /* End of file Ftp.php */
  525. /* Location: ./system/libraries/Ftp.php */