PageRenderTime 55ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/libraries/joomla/client/ftp.php

https://bitbucket.org/asosso/joomla15
PHP | 1467 lines | 1228 code | 52 blank | 187 comment | 39 complexity | 77a40306d283866bb85c64c5c5d25c55 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0
  1. <?php
  2. /**
  3. * @version $Id: ftp.php 14401 2010-01-26 14:10:00Z louis $
  4. * @package Joomla.Framework
  5. * @subpackage Client
  6. * @copyright Copyright (C) 2005 - 2010 Open Source Matters. All rights reserved.
  7. * @license GNU/GPL, see LICENSE.php
  8. * Joomla! is free software and parts of it may contain or be derived from the
  9. * GNU General Public License or other free or open source software licenses.
  10. * See COPYRIGHT.php for copyright notices and details.
  11. */
  12. // Check to ensure this file is within the rest of the framework
  13. defined('JPATH_BASE') or die();
  14. /** Error Codes:
  15. * - 30 : Unable to connect to host
  16. * - 31 : Not connected
  17. * - 32 : Unable to send command to server
  18. * - 33 : Bad username
  19. * - 34 : Bad password
  20. * - 35 : Bad response
  21. * - 36 : Passive mode failed
  22. * - 37 : Data transfer error
  23. * - 38 : Local filesystem error
  24. */
  25. if (!defined('CRLF')) {
  26. define('CRLF', "\r\n");
  27. }
  28. if (!defined("FTP_AUTOASCII")) {
  29. define("FTP_AUTOASCII", -1);
  30. }
  31. if (!defined("FTP_BINARY")) {
  32. define("FTP_BINARY", 1);
  33. }
  34. if (!defined("FTP_ASCII")) {
  35. define("FTP_ASCII", 0);
  36. }
  37. // Is FTP extension loaded? If not try to load it
  38. if (!extension_loaded('ftp')) {
  39. if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
  40. @ dl('php_ftp.dll');
  41. } else {
  42. @ dl('ftp.so');
  43. }
  44. }
  45. if (!defined('FTP_NATIVE')) {
  46. define('FTP_NATIVE', (function_exists('ftp_connect'))? 1 : 0);
  47. }
  48. /**
  49. * FTP client class
  50. *
  51. * @package Joomla.Framework
  52. * @subpackage Client
  53. * @since 1.5
  54. */
  55. class JFTP extends JObject
  56. {
  57. /**
  58. * Server connection resource
  59. *
  60. * @access private
  61. * @var socket resource
  62. */
  63. var $_conn = null;
  64. /**
  65. * Data port connection resource
  66. *
  67. * @access private
  68. * @var socket resource
  69. */
  70. var $_dataconn = null;
  71. /**
  72. * Passive connection information
  73. *
  74. * @access private
  75. * @var array
  76. */
  77. var $_pasv = null;
  78. /**
  79. * Response Message
  80. *
  81. * @access private
  82. * @var string
  83. */
  84. var $_response = null;
  85. /**
  86. * Timeout limit
  87. *
  88. * @access private
  89. * @var int
  90. */
  91. var $_timeout = 15;
  92. /**
  93. * Transfer Type
  94. *
  95. * @access private
  96. * @var int
  97. */
  98. var $_type = null;
  99. /**
  100. * Native OS Type
  101. *
  102. * @access private
  103. * @var string
  104. */
  105. var $_OS = null;
  106. /**
  107. * Array to hold ascii format file extensions
  108. *
  109. * @final
  110. * @access private
  111. * @var array
  112. */
  113. var $_autoAscii = array ("asp", "bat", "c", "cpp", "csv", "h", "htm", "html", "shtml", "ini", "inc", "log", "php", "php3", "pl", "perl", "sh", "sql", "txt", "xhtml", "xml");
  114. /**
  115. * Array to hold native line ending characters
  116. *
  117. * @final
  118. * @access private
  119. * @var array
  120. */
  121. var $_lineEndings = array ('UNIX' => "\n", 'MAC' => "\r", 'WIN' => "\r\n");
  122. /**
  123. * JFTP object constructor
  124. *
  125. * @access protected
  126. * @param array $options Associative array of options to set
  127. * @since 1.5
  128. */
  129. function __construct($options=array()) {
  130. // If default transfer type is no set, set it to autoascii detect
  131. if (!isset ($options['type'])) {
  132. $options['type'] = FTP_BINARY;
  133. }
  134. $this->setOptions($options);
  135. if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
  136. $this->_OS = 'WIN';
  137. } elseif (strtoupper(substr(PHP_OS, 0, 3)) === 'MAC') {
  138. $this->_OS = 'MAC';
  139. } else {
  140. $this->_OS = 'UNIX';
  141. }
  142. if (FTP_NATIVE) {
  143. // Import the generic buffer stream handler
  144. jimport('joomla.utilities.buffer');
  145. // Autoloading fails for JBuffer as the class is used as a stream handler
  146. JLoader::load('JBuffer');
  147. }
  148. // Register faked "destructor" in PHP4 to close all connections we might have made
  149. if (version_compare(PHP_VERSION, '5') == -1) {
  150. register_shutdown_function(array(&$this, '__destruct'));
  151. }
  152. }
  153. /**
  154. * JFTP object destructor
  155. *
  156. * Closes an existing connection, if we have one
  157. *
  158. * @access protected
  159. * @since 1.5
  160. */
  161. function __destruct() {
  162. if (is_resource($this->_conn)) {
  163. $this->quit();
  164. }
  165. }
  166. /**
  167. * Returns a reference to the global FTP connector object, only creating it
  168. * if it doesn't already exist.
  169. *
  170. * This method must be invoked as:
  171. * <pre> $ftp = &JFTP::getInstance($host);</pre>
  172. *
  173. * You may optionally specify a username and password in the parameters. If you do so,
  174. * you may not login() again with different credentials using the same object.
  175. * If you do not use this option, you must quit() the current connection when you
  176. * are done, to free it for use by others.
  177. *
  178. * @param string $host Host to connect to
  179. * @param string $port Port to connect to
  180. * @param array $options Array with any of these options: type=>[FTP_AUTOASCII|FTP_ASCII|FTP_BINARY], timeout=>(int)
  181. * @param string $user Username to use for a connection
  182. * @param string $pass Password to use for a connection
  183. * @return JFTP The FTP Client object.
  184. * @since 1.5
  185. */
  186. function &getInstance($host = '127.0.0.1', $port = '21', $options = null, $user = null, $pass = null)
  187. {
  188. static $instances = array();
  189. $signature = $user.':'.$pass.'@'.$host.":".$port;
  190. // Create a new instance, or set the options of an existing one
  191. if (!isset ($instances[$signature]) || !is_object($instances[$signature])) {
  192. $instances[$signature] = new JFTP($options);
  193. } else {
  194. $instances[$signature]->setOptions($options);
  195. }
  196. // Connect to the server, and login, if requested
  197. if (!$instances[$signature]->isConnected()) {
  198. $return = $instances[$signature]->connect($host, $port);
  199. if ($return && $user !== null && $pass !== null) {
  200. $instances[$signature]->login($user, $pass);
  201. }
  202. }
  203. return $instances[$signature];
  204. }
  205. /**
  206. * Set client options
  207. *
  208. * @access public
  209. * @param array $options Associative array of options to set
  210. * @return boolean True if successful
  211. */
  212. function setOptions($options) {
  213. if (isset ($options['type'])) {
  214. $this->_type = $options['type'];
  215. }
  216. if (isset ($options['timeout'])) {
  217. $this->_timeout = $options['timeout'];
  218. }
  219. return true;
  220. }
  221. /**
  222. * Method to connect to a FTP server
  223. *
  224. * @access public
  225. * @param string $host Host to connect to [Default: 127.0.0.1]
  226. * @param string $port Port to connect on [Default: port 21]
  227. * @return boolean True if successful
  228. */
  229. function connect($host = '127.0.0.1', $port = 21) {
  230. // Initialize variables
  231. $errno = null;
  232. $err = null;
  233. // If already connected, return
  234. if (is_resource($this->_conn)) {
  235. return true;
  236. }
  237. // If native FTP support is enabled lets use it...
  238. if (FTP_NATIVE) {
  239. $this->_conn = @ftp_connect($host, $port, $this->_timeout);
  240. if ($this->_conn === false) {
  241. JError::raiseWarning('30', 'JFTP::connect: Could not connect to host "'.$host.'" on port '.$port);
  242. return false;
  243. }
  244. // Set the timeout for this connection
  245. ftp_set_option($this->_conn, FTP_TIMEOUT_SEC, $this->_timeout);
  246. return true;
  247. }
  248. // Connect to the FTP server.
  249. $this->_conn = @ fsockopen($host, $port, $errno, $err, $this->_timeout);
  250. if (!$this->_conn) {
  251. JError::raiseWarning('30', 'JFTP::connect: Could not connect to host "'.$host.'" on port '.$port, 'Socket error number '.$errno.' and error message: '.$err);
  252. return false;
  253. }
  254. // Set the timeout for this connection
  255. socket_set_timeout($this->_conn, $this->_timeout);
  256. // Check for welcome response code
  257. if (!$this->_verifyResponse(220)) {
  258. JError::raiseWarning('35', 'JFTP::connect: Bad response', 'Server response: '.$this->_response.' [Expected: 220]');
  259. return false;
  260. }
  261. return true;
  262. }
  263. /**
  264. * Method to determine if the object is connected to an FTP server
  265. *
  266. * @access public
  267. * @return boolean True if connected
  268. * @since 1.5
  269. */
  270. function isConnected()
  271. {
  272. return is_resource($this->_conn);
  273. }
  274. /**
  275. * Method to login to a server once connected
  276. *
  277. * @access public
  278. * @param string $user Username to login to the server
  279. * @param string $pass Password to login to the server
  280. * @return boolean True if successful
  281. */
  282. function login($user = 'anonymous', $pass = 'jftp@joomla.org') {
  283. // If native FTP support is enabled lets use it...
  284. if (FTP_NATIVE) {
  285. if (@ftp_login($this->_conn, $user, $pass) === false) {
  286. JError::raiseWarning('30', 'JFTP::login: Unable to login' );
  287. return false;
  288. }
  289. return true;
  290. }
  291. // Send the username
  292. if (!$this->_putCmd('USER '.$user, array(331, 503))) {
  293. JError::raiseWarning('33', 'JFTP::login: Bad Username', 'Server response: '.$this->_response.' [Expected: 331] Username sent: '.$user );
  294. return false;
  295. }
  296. // If we are already logged in, continue :)
  297. if ($this->_responseCode == 503) {
  298. return true;
  299. }
  300. // Send the password
  301. if (!$this->_putCmd('PASS '.$pass, 230)) {
  302. JError::raiseWarning('34', 'JFTP::login: Bad Password', 'Server response: '.$this->_response.' [Expected: 230] Password sent: '.str_repeat('*', strlen($pass)));
  303. return false;
  304. }
  305. return true;
  306. }
  307. /**
  308. * Method to quit and close the connection
  309. *
  310. * @access public
  311. * @return boolean True if successful
  312. */
  313. function quit() {
  314. // If native FTP support is enabled lets use it...
  315. if (FTP_NATIVE) {
  316. @ftp_close($this->_conn);
  317. return true;
  318. }
  319. // Logout and close connection
  320. @fwrite($this->_conn, "QUIT\r\n");
  321. @fclose($this->_conn);
  322. return true;
  323. }
  324. /**
  325. * Method to retrieve the current working directory on the FTP server
  326. *
  327. * @access public
  328. * @return string Current working directory
  329. */
  330. function pwd() {
  331. // If native FTP support is enabled lets use it...
  332. if (FTP_NATIVE) {
  333. if (($ret = @ftp_pwd($this->_conn)) === false) {
  334. JError::raiseWarning('35', 'JFTP::pwd: Bad response' );
  335. return false;
  336. }
  337. return $ret;
  338. }
  339. // Initialize variables
  340. $match = array (null);
  341. // Send print working directory command and verify success
  342. if (!$this->_putCmd('PWD', 257)) {
  343. JError::raiseWarning('35', 'JFTP::pwd: Bad response', 'Server response: '.$this->_response.' [Expected: 257]' );
  344. return false;
  345. }
  346. // Match just the path
  347. preg_match('/"[^"\r\n]*"/', $this->_response, $match);
  348. // Return the cleaned path
  349. return preg_replace("/\"/", "", $match[0]);
  350. }
  351. /**
  352. * Method to system string from the FTP server
  353. *
  354. * @access public
  355. * @return string System identifier string
  356. */
  357. function syst() {
  358. // If native FTP support is enabled lets use it...
  359. if (FTP_NATIVE) {
  360. if (($ret = @ftp_systype($this->_conn)) === false) {
  361. JError::raiseWarning('35', 'JFTP::syst: Bad response' );
  362. return false;
  363. }
  364. } else {
  365. // Send print working directory command and verify success
  366. if (!$this->_putCmd('SYST', 215)) {
  367. JError::raiseWarning('35', 'JFTP::syst: Bad response', 'Server response: '.$this->_response.' [Expected: 215]' );
  368. return false;
  369. }
  370. $ret = $this->_response;
  371. }
  372. // Match the system string to an OS
  373. if (strpos(strtoupper($ret), 'MAC') !== false) {
  374. $ret = 'MAC';
  375. } elseif (strpos(strtoupper($ret), 'WIN') !== false) {
  376. $ret = 'WIN';
  377. } else {
  378. $ret = 'UNIX';
  379. }
  380. // Return the os type
  381. return $ret;
  382. }
  383. /**
  384. * Method to change the current working directory on the FTP server
  385. *
  386. * @access public
  387. * @param string $path Path to change into on the server
  388. * @return boolean True if successful
  389. */
  390. function chdir($path) {
  391. // If native FTP support is enabled lets use it...
  392. if (FTP_NATIVE) {
  393. if (@ftp_chdir($this->_conn, $path) === false) {
  394. JError::raiseWarning('35', 'JFTP::chdir: Bad response' );
  395. return false;
  396. }
  397. return true;
  398. }
  399. // Send change directory command and verify success
  400. if (!$this->_putCmd('CWD '.$path, 250)) {
  401. JError::raiseWarning('35', 'JFTP::chdir: Bad response', 'Server response: '.$this->_response.' [Expected: 250] Path sent: '.$path );
  402. return false;
  403. }
  404. return true;
  405. }
  406. /**
  407. * Method to reinitialize the server, ie. need to login again
  408. *
  409. * NOTE: This command not available on all servers
  410. *
  411. * @access public
  412. * @return boolean True if successful
  413. */
  414. function reinit() {
  415. // If native FTP support is enabled lets use it...
  416. if (FTP_NATIVE) {
  417. if (@ftp_site($this->_conn, 'REIN') === false) {
  418. JError::raiseWarning('35', 'JFTP::reinit: Bad response' );
  419. return false;
  420. }
  421. return true;
  422. }
  423. // Send reinitialize command to the server
  424. if (!$this->_putCmd('REIN', 220)) {
  425. JError::raiseWarning('35', 'JFTP::reinit: Bad response', 'Server response: '.$this->_response.' [Expected: 220]' );
  426. return false;
  427. }
  428. return true;
  429. }
  430. /**
  431. * Method to rename a file/folder on the FTP server
  432. *
  433. * @access public
  434. * @param string $from Path to change file/folder from
  435. * @param string $to Path to change file/folder to
  436. * @return boolean True if successful
  437. */
  438. function rename($from, $to) {
  439. // If native FTP support is enabled lets use it...
  440. if (FTP_NATIVE) {
  441. if (@ftp_rename($this->_conn, $from, $to) === false) {
  442. JError::raiseWarning('35', 'JFTP::rename: Bad response' );
  443. return false;
  444. }
  445. return true;
  446. }
  447. // Send rename from command to the server
  448. if (!$this->_putCmd('RNFR '.$from, 350)) {
  449. JError::raiseWarning('35', 'JFTP::rename: Bad response', 'Server response: '.$this->_response.' [Expected: 320] From path sent: '.$from );
  450. return false;
  451. }
  452. // Send rename to command to the server
  453. if (!$this->_putCmd('RNTO '.$to, 250)) {
  454. JError::raiseWarning('35', 'JFTP::rename: Bad response', 'Server response: '.$this->_response.' [Expected: 250] To path sent: '.$to );
  455. return false;
  456. }
  457. return true;
  458. }
  459. /**
  460. * Method to change mode for a path on the FTP server
  461. *
  462. * @access public
  463. * @param string $path Path to change mode on
  464. * @param string/int $mode Octal value to change mode to, e.g. '0777', 0777 or 511
  465. * @return boolean True if successful
  466. */
  467. function chmod($path, $mode) {
  468. // If no filename is given, we assume the current directory is the target
  469. if ($path == '') {
  470. $path = '.';
  471. }
  472. // Convert the mode to a string
  473. if (is_int($mode)) {
  474. $mode = decoct($mode);
  475. }
  476. // If native FTP support is enabled lets use it...
  477. if (FTP_NATIVE) {
  478. if (@ftp_site($this->_conn, 'CHMOD '.$mode.' '.$path) === false) {
  479. if($this->_OS != 'WIN') {
  480. JError::raiseWarning('35', 'JFTP::chmod: Bad response' );
  481. }
  482. return false;
  483. }
  484. return true;
  485. }
  486. // Send change mode command and verify success [must convert mode from octal]
  487. if (!$this->_putCmd('SITE CHMOD '.$mode.' '.$path, array(200, 250))) {
  488. if($this->_OS != 'WIN') {
  489. JError::raiseWarning('35', 'JFTP::chmod: Bad response', 'Server response: '.$this->_response.' [Expected: 200 or 250] Path sent: '.$path.' Mode sent: '.$mode);
  490. }
  491. return false;
  492. }
  493. return true;
  494. }
  495. /**
  496. * Method to delete a path [file/folder] on the FTP server
  497. *
  498. * @access public
  499. * @param string $path Path to delete
  500. * @return boolean True if successful
  501. */
  502. function delete($path) {
  503. // If native FTP support is enabled lets use it...
  504. if (FTP_NATIVE) {
  505. if (@ftp_delete($this->_conn, $path) === false) {
  506. if (@ftp_rmdir($this->_conn, $path) === false) {
  507. JError::raiseWarning('35', 'JFTP::delete: Bad response' );
  508. return false;
  509. }
  510. }
  511. return true;
  512. }
  513. // Send delete file command and if that doesn't work, try to remove a directory
  514. if (!$this->_putCmd('DELE '.$path, 250)) {
  515. if (!$this->_putCmd('RMD '.$path, 250)) {
  516. JError::raiseWarning('35', 'JFTP::delete: Bad response', 'Server response: '.$this->_response.' [Expected: 250] Path sent: '.$path );
  517. return false;
  518. }
  519. }
  520. return true;
  521. }
  522. /**
  523. * Method to create a directory on the FTP server
  524. *
  525. * @access public
  526. * @param string $path Directory to create
  527. * @return boolean True if successful
  528. */
  529. function mkdir($path) {
  530. // If native FTP support is enabled lets use it...
  531. if (FTP_NATIVE) {
  532. if (@ftp_mkdir($this->_conn, $path) === false) {
  533. JError::raiseWarning('35', 'JFTP::mkdir: Bad response' );
  534. return false;
  535. }
  536. return true;
  537. }
  538. // Send change directory command and verify success
  539. if (!$this->_putCmd('MKD '.$path, 257)) {
  540. JError::raiseWarning('35', 'JFTP::mkdir: Bad response', 'Server response: '.$this->_response.' [Expected: 257] Path sent: '.$path );
  541. return false;
  542. }
  543. return true;
  544. }
  545. /**
  546. * Method to restart data transfer at a given byte
  547. *
  548. * @access public
  549. * @param int $point Byte to restart transfer at
  550. * @return boolean True if successful
  551. */
  552. function restart($point) {
  553. // If native FTP support is enabled lets use it...
  554. if (FTP_NATIVE) {
  555. if (@ftp_site($this->_conn, 'REST '.$point) === false) {
  556. JError::raiseWarning('35', 'JFTP::restart: Bad response' );
  557. return false;
  558. }
  559. return true;
  560. }
  561. // Send restart command and verify success
  562. if (!$this->_putCmd('REST '.$point, 350)) {
  563. JError::raiseWarning('35', 'JFTP::restart: Bad response', 'Server response: '.$this->_response.' [Expected: 350] Restart point sent: '.$point );
  564. return false;
  565. }
  566. return true;
  567. }
  568. /**
  569. * Method to create an empty file on the FTP server
  570. *
  571. * @access public
  572. * @param string $path Path local file to store on the FTP server
  573. * @return boolean True if successful
  574. */
  575. function create($path) {
  576. // If native FTP support is enabled lets use it...
  577. if (FTP_NATIVE) {
  578. // turn passive mode on
  579. if (@ftp_pasv($this->_conn, true) === false) {
  580. JError::raiseWarning('36', 'JFTP::create: Unable to use passive mode' );
  581. return false;
  582. }
  583. $buffer = fopen('buffer://tmp', 'r');
  584. if (@ftp_fput($this->_conn, $path, $buffer, FTP_ASCII) === false) {
  585. JError::raiseWarning('35', 'JFTP::create: Bad response' );
  586. fclose($buffer);
  587. return false;
  588. }
  589. fclose($buffer);
  590. return true;
  591. }
  592. // Start passive mode
  593. if (!$this->_passive()) {
  594. JError::raiseWarning('36', 'JFTP::create: Unable to use passive mode' );
  595. return false;
  596. }
  597. if (!$this->_putCmd('STOR '.$path, array (150, 125))) {
  598. @ fclose($this->_dataconn);
  599. JError::raiseWarning('35', 'JFTP::create: Bad response', 'Server response: '.$this->_response.' [Expected: 150 or 125] Path sent: '.$path );
  600. return false;
  601. }
  602. // To create a zero byte upload close the data port connection
  603. fclose($this->_dataconn);
  604. if (!$this->_verifyResponse(226)) {
  605. JError::raiseWarning('37', 'JFTP::create: Transfer Failed', 'Server response: '.$this->_response.' [Expected: 226] Path sent: '.$path );
  606. return false;
  607. }
  608. return true;
  609. }
  610. /**
  611. * Method to read a file from the FTP server's contents into a buffer
  612. *
  613. * @access public
  614. * @param string $remote Path to remote file to read on the FTP server
  615. * @param string $buffer Buffer variable to read file contents into
  616. * @return boolean True if successful
  617. */
  618. function read($remote, &$buffer) {
  619. // Determine file type
  620. $mode = $this->_findMode($remote);
  621. // If native FTP support is enabled lets use it...
  622. if (FTP_NATIVE) {
  623. // turn passive mode on
  624. if (@ftp_pasv($this->_conn, true) === false) {
  625. JError::raiseWarning('36', 'JFTP::read: Unable to use passive mode' );
  626. return false;
  627. }
  628. $tmp = fopen('buffer://tmp', 'br+');
  629. if (@ftp_fget($this->_conn, $tmp, $remote, $mode) === false) {
  630. fclose($tmp);
  631. JError::raiseWarning('35', 'JFTP::read: Bad response' );
  632. return false;
  633. }
  634. // Read tmp buffer contents
  635. rewind($tmp);
  636. $buffer = '';
  637. while (!feof($tmp)) {
  638. $buffer .= fread($tmp, 8192);
  639. }
  640. fclose($tmp);
  641. return true;
  642. }
  643. $this->_mode($mode);
  644. // Start passive mode
  645. if (!$this->_passive()) {
  646. JError::raiseWarning('36', 'JFTP::read: Unable to use passive mode' );
  647. return false;
  648. }
  649. if (!$this->_putCmd('RETR '.$remote, array (150, 125))) {
  650. @ fclose($this->_dataconn);
  651. JError::raiseWarning('35', 'JFTP::read: Bad response', 'Server response: '.$this->_response.' [Expected: 150 or 125] Path sent: '.$remote );
  652. return false;
  653. }
  654. // Read data from data port connection and add to the buffer
  655. $buffer = '';
  656. while (!feof($this->_dataconn)) {
  657. $buffer .= fread($this->_dataconn, 4096);
  658. }
  659. // Close the data port connection
  660. fclose($this->_dataconn);
  661. // Let's try to cleanup some line endings if it is ascii
  662. if ($mode == FTP_ASCII) {
  663. $buffer = preg_replace("/".CRLF."/", $this->_lineEndings[$this->_OS], $buffer);
  664. }
  665. if (!$this->_verifyResponse(226)) {
  666. JError::raiseWarning('37', 'JFTP::read: Transfer Failed', 'Server response: '.$this->_response.' [Expected: 226] Path sent: '.$remote );
  667. return false;
  668. }
  669. return true;
  670. }
  671. /**
  672. * Method to get a file from the FTP server and save it to a local file
  673. *
  674. * @access public
  675. * @param string $local Path to local file to save remote file as
  676. * @param string $remote Path to remote file to get on the FTP server
  677. * @return boolean True if successful
  678. */
  679. function get($local, $remote) {
  680. // Determine file type
  681. $mode = $this->_findMode($remote);
  682. // If native FTP support is enabled lets use it...
  683. if (FTP_NATIVE) {
  684. // turn passive mode on
  685. if (@ftp_pasv($this->_conn, true) === false) {
  686. JError::raiseWarning('36', 'JFTP::get: Unable to use passive mode' );
  687. return false;
  688. }
  689. if (@ftp_get($this->_conn, $local, $remote, $mode) === false) {
  690. JError::raiseWarning('35', 'JFTP::get: Bad response' );
  691. return false;
  692. }
  693. return true;
  694. }
  695. $this->_mode($mode);
  696. // Check to see if the local file can be opened for writing
  697. $fp = fopen($local, "wb");
  698. if (!$fp) {
  699. JError::raiseWarning('38', 'JFTP::get: Unable to open local file for writing', 'Local path: '.$local );
  700. return false;
  701. }
  702. // Start passive mode
  703. if (!$this->_passive()) {
  704. JError::raiseWarning('36', 'JFTP::get: Unable to use passive mode' );
  705. return false;
  706. }
  707. if (!$this->_putCmd('RETR '.$remote, array (150, 125))) {
  708. @ fclose($this->_dataconn);
  709. JError::raiseWarning('35', 'JFTP::get: Bad response', 'Server response: '.$this->_response.' [Expected: 150 or 125] Path sent: '.$remote );
  710. return false;
  711. }
  712. // Read data from data port connection and add to the buffer
  713. while (!feof($this->_dataconn)) {
  714. $buffer = fread($this->_dataconn, 4096);
  715. $ret = fwrite($fp, $buffer, 4096);
  716. }
  717. // Close the data port connection and file pointer
  718. fclose($this->_dataconn);
  719. fclose($fp);
  720. if (!$this->_verifyResponse(226)) {
  721. JError::raiseWarning('37', 'JFTP::get: Transfer Failed', 'Server response: '.$this->_response.' [Expected: 226] Path sent: '.$remote );
  722. return false;
  723. }
  724. return true;
  725. }
  726. /**
  727. * Method to store a file to the FTP server
  728. *
  729. * @access public
  730. * @param string $local Path to local file to store on the FTP server
  731. * @param string $remote FTP path to file to create
  732. * @return boolean True if successful
  733. */
  734. function store($local, $remote = null) {
  735. // If remote file not given, use the filename of the local file in the current
  736. // working directory
  737. if ($remote == null) {
  738. $remote = basename($local);
  739. }
  740. // Determine file type
  741. $mode = $this->_findMode($remote);
  742. // If native FTP support is enabled lets use it...
  743. if (FTP_NATIVE) {
  744. // turn passive mode on
  745. if (@ftp_pasv($this->_conn, true) === false) {
  746. JError::raiseWarning('36', 'JFTP::store: Unable to use passive mode' );
  747. return false;
  748. }
  749. if (@ftp_put($this->_conn, $remote, $local, $mode) === false) {
  750. JError::raiseWarning('35', 'JFTP::store: Bad response' );
  751. return false;
  752. }
  753. return true;
  754. }
  755. $this->_mode($mode);
  756. // Check to see if the local file exists and open for reading if so
  757. if (@ file_exists($local)) {
  758. $fp = fopen($local, "rb");
  759. if (!$fp) {
  760. JError::raiseWarning('38', 'JFTP::store: Unable to open local file for reading', 'Local path: '.$local );
  761. return false;
  762. }
  763. } else {
  764. JError::raiseWarning('38', 'JFTP::store: Unable to find local path', 'Local path: '.$local );
  765. return false;
  766. }
  767. // Start passive mode
  768. if (!$this->_passive()) {
  769. @ fclose($fp);
  770. JError::raiseWarning('36', 'JFTP::store: Unable to use passive mode' );
  771. return false;
  772. }
  773. // Send store command to the FTP server
  774. if (!$this->_putCmd('STOR '.$remote, array (150, 125))) {
  775. @ fclose($fp);
  776. @ fclose($this->_dataconn);
  777. JError::raiseWarning('35', 'JFTP::store: Bad response', 'Server response: '.$this->_response.' [Expected: 150 or 125] Path sent: '.$remote );
  778. return false;
  779. }
  780. // Do actual file transfer, read local file and write to data port connection
  781. while (!feof($fp)) {
  782. $line = fread($fp, 4096);
  783. do {
  784. if (($result = @ fwrite($this->_dataconn, $line)) === false) {
  785. JError::raiseWarning('37', 'JFTP::store: Unable to write to data port socket' );
  786. return false;
  787. }
  788. $line = substr($line, $result);
  789. } while ($line != "");
  790. }
  791. fclose($fp);
  792. fclose($this->_dataconn);
  793. if (!$this->_verifyResponse(226)) {
  794. JError::raiseWarning('37', 'JFTP::store: Transfer Failed', 'Server response: '.$this->_response.' [Expected: 226] Path sent: '.$remote );
  795. return false;
  796. }
  797. return true;
  798. }
  799. /**
  800. * Method to write a string to the FTP server
  801. *
  802. * @access public
  803. * @param string $remote FTP path to file to write to
  804. * @param string $buffer Contents to write to the FTP server
  805. * @return boolean True if successful
  806. */
  807. function write($remote, $buffer) {
  808. // Determine file type
  809. $mode = $this->_findMode($remote);
  810. // If native FTP support is enabled lets use it...
  811. if (FTP_NATIVE) {
  812. // turn passive mode on
  813. if (@ftp_pasv($this->_conn, true) === false) {
  814. JError::raiseWarning('36', 'JFTP::write: Unable to use passive mode' );
  815. return false;
  816. }
  817. $tmp = fopen('buffer://tmp', 'br+');
  818. fwrite($tmp, $buffer);
  819. rewind($tmp);
  820. if (@ftp_fput($this->_conn, $remote, $tmp, $mode) === false) {
  821. fclose($tmp);
  822. JError::raiseWarning('35', 'JFTP::write: Bad response' );
  823. return false;
  824. }
  825. fclose($tmp);
  826. return true;
  827. }
  828. // First we need to set the transfer mode
  829. $this->_mode($mode);
  830. // Start passive mode
  831. if (!$this->_passive()) {
  832. JError::raiseWarning('36', 'JFTP::write: Unable to use passive mode' );
  833. return false;
  834. }
  835. // Send store command to the FTP server
  836. if (!$this->_putCmd('STOR '.$remote, array (150, 125))) {
  837. JError::raiseWarning('35', 'JFTP::write: Bad response', 'Server response: '.$this->_response.' [Expected: 150 or 125] Path sent: '.$remote );
  838. @ fclose($this->_dataconn);
  839. return false;
  840. }
  841. // Write buffer to the data connection port
  842. do {
  843. if (($result = @ fwrite($this->_dataconn, $buffer)) === false) {
  844. JError::raiseWarning('37', 'JFTP::write: Unable to write to data port socket' );
  845. return false;
  846. }
  847. $buffer = substr($buffer, $result);
  848. } while ($buffer != "");
  849. // Close the data connection port [Data transfer complete]
  850. fclose($this->_dataconn);
  851. // Verify that the server recieved the transfer
  852. if (!$this->_verifyResponse(226)) {
  853. JError::raiseWarning('37', 'JFTP::write: Transfer Failed', 'Server response: '.$this->_response.' [Expected: 226] Path sent: '.$remote );
  854. return false;
  855. }
  856. return true;
  857. }
  858. /**
  859. * Method to list the filenames of the contents of a directory on the FTP server
  860. *
  861. * Note: Some servers also return folder names. However, to be sure to list folders on all
  862. * servers, you should use listDetails() instead, if you also need to deal with folders
  863. *
  864. * @access public
  865. * @param string $path Path local file to store on the FTP server
  866. * @return string Directory listing
  867. */
  868. function listNames($path = null) {
  869. // Initialize variables
  870. $data = null;
  871. // If native FTP support is enabled lets use it...
  872. if (FTP_NATIVE) {
  873. // turn passive mode on
  874. if (@ftp_pasv($this->_conn, true) === false) {
  875. JError::raiseWarning('36', 'JFTP::listNames: Unable to use passive mode' );
  876. return false;
  877. }
  878. if (($list = @ftp_nlist($this->_conn,$path)) === false) {
  879. // Workaround for empty directories on some servers
  880. if ($this->listDetails($path, 'files') === array()) {
  881. return array();
  882. }
  883. JError::raiseWarning('35', 'JFTP::listNames: Bad response' );
  884. return false;
  885. }
  886. $list = preg_replace('#^'.preg_quote($path, '#').'[/\\\\]?#', '', $list);
  887. if ($keys = array_merge(array_keys($list, '.'), array_keys($list, '..'))) {
  888. foreach ($keys as $key) {
  889. unset($list[$key]);
  890. }
  891. }
  892. return $list;
  893. }
  894. /*
  895. * If a path exists, prepend a space
  896. */
  897. if ($path != null) {
  898. $path = ' ' . $path;
  899. }
  900. // Start passive mode
  901. if (!$this->_passive()) {
  902. JError::raiseWarning('36', 'JFTP::listNames: Unable to use passive mode' );
  903. return false;
  904. }
  905. if (!$this->_putCmd('NLST'.$path, array (150, 125))) {
  906. @ fclose($this->_dataconn);
  907. // Workaround for empty directories on some servers
  908. if ($this->listDetails($path, 'files') === array()) {
  909. return array();
  910. }
  911. JError::raiseWarning('35', 'JFTP::listNames: Bad response', 'Server response: '.$this->_response.' [Expected: 150 or 125] Path sent: '.$path );
  912. return false;
  913. }
  914. // Read in the file listing.
  915. while (!feof($this->_dataconn)) {
  916. $data .= fread($this->_dataconn, 4096);
  917. }
  918. fclose($this->_dataconn);
  919. // Everything go okay?
  920. if (!$this->_verifyResponse(226)) {
  921. JError::raiseWarning('37', 'JFTP::listNames: Transfer Failed', 'Server response: '.$this->_response.' [Expected: 226] Path sent: '.$path );
  922. return false;
  923. }
  924. $data = preg_split("/[".CRLF."]+/", $data, -1, PREG_SPLIT_NO_EMPTY);
  925. $data = preg_replace('#^'.preg_quote(substr($path, 1), '#').'[/\\\\]?#', '', $data);
  926. if ($keys = array_merge(array_keys($data, '.'), array_keys($data, '..'))) {
  927. foreach ($keys as $key) {
  928. unset($data[$key]);
  929. }
  930. }
  931. return $data;
  932. }
  933. /**
  934. * Method to list the contents of a directory on the FTP server
  935. *
  936. * @access public
  937. * @param string $path Path local file to store on the FTP server
  938. * @param string $type Return type [raw|all|folders|files]
  939. * @param boolean $search Recursively search subdirectories
  940. * @return mixed : if $type is raw: string Directory listing, otherwise array of string with file-names
  941. */
  942. function listDetails($path = null, $type = 'all') {
  943. // Initialize variables
  944. $dir_list = array();
  945. $data = null;
  946. $regs = null;
  947. // TODO: Deal with recurse -- nightmare
  948. // For now we will just set it to false
  949. $recurse = false;
  950. // If native FTP support is enabled lets use it...
  951. if (FTP_NATIVE) {
  952. // turn passive mode on
  953. if (@ftp_pasv($this->_conn, true) === false) {
  954. JError::raiseWarning('36', 'JFTP::listDetails: Unable to use passive mode' );
  955. return false;
  956. }
  957. if (($contents = @ftp_rawlist($this->_conn, $path)) === false) {
  958. JError::raiseWarning('35', 'JFTP::listDetails: Bad response' );
  959. return false;
  960. }
  961. } else {
  962. // Non Native mode
  963. // Start passive mode
  964. if (!$this->_passive()) {
  965. JError::raiseWarning('36', 'JFTP::listDetails: Unable to use passive mode' );
  966. return false;
  967. }
  968. // If a path exists, prepend a space
  969. if ($path != null) {
  970. $path = ' ' . $path;
  971. }
  972. // Request the file listing
  973. if (!$this->_putCmd(($recurse == true) ? 'LIST -R' : 'LIST'.$path, array (150, 125))) {
  974. JError::raiseWarning('35', 'JFTP::listDetails: Bad response', 'Server response: '.$this->_response.' [Expected: 150 or 125] Path sent: '.$path );
  975. @ fclose($this->_dataconn);
  976. return false;
  977. }
  978. // Read in the file listing.
  979. while (!feof($this->_dataconn)) {
  980. $data .= fread($this->_dataconn, 4096);
  981. }
  982. fclose($this->_dataconn);
  983. // Everything go okay?
  984. if (!$this->_verifyResponse(226)) {
  985. JError::raiseWarning('37', 'JFTP::listDetails: Transfer Failed', 'Server response: '.$this->_response.' [Expected: 226] Path sent: '.$path );
  986. return false;
  987. }
  988. $contents = explode(CRLF, $data);
  989. }
  990. // If only raw output is requested we are done
  991. if ($type == 'raw') {
  992. return $data;
  993. }
  994. // If we received the listing of an emtpy directory, we are done as well
  995. if (empty($contents[0])) {
  996. return $dir_list;
  997. }
  998. // If the server returned the number of results in the first response, let's dump it
  999. if (strtolower(substr($contents[0], 0, 6)) == 'total ') {
  1000. array_shift($contents);
  1001. if (!isset($contents[0]) || empty($contents[0])) {
  1002. return $dir_list;
  1003. }
  1004. }
  1005. // Regular expressions for the directory listing parsing
  1006. $regexps['UNIX'] = '([-dl][rwxstST-]+).* ([0-9]*) ([a-zA-Z0-9]+).* ([a-zA-Z0-9]+).* ([0-9]*) ([a-zA-Z]+[0-9: ]*[0-9])[ ]+(([0-9]{1,2}:[0-9]{2})|[0-9]{4}) (.+)';
  1007. $regexps['MAC'] = '([-dl][rwxstST-]+).* ?([0-9 ]* )?([a-zA-Z0-9]+).* ([a-zA-Z0-9]+).* ([0-9]*) ([a-zA-Z]+[0-9: ]*[0-9])[ ]+(([0-9]{2}:[0-9]{2})|[0-9]{4}) (.+)';
  1008. $regexps['WIN'] = '([0-9]{2})-([0-9]{2})-([0-9]{2}) +([0-9]{2}):([0-9]{2})(AM|PM) +([0-9]+|<DIR>) +(.+)';
  1009. // Find out the format of the directory listing by matching one of the regexps
  1010. $osType = null;
  1011. foreach ($regexps as $k=>$v) {
  1012. if (ereg($v, $contents[0])) {
  1013. $osType = $k;
  1014. $regexp = $v;
  1015. break;
  1016. }
  1017. }
  1018. if (!$osType) {
  1019. JError::raiseWarning('SOME_ERROR_CODE', 'JFTP::listDetails: Unrecognized directory listing format' );
  1020. return false;
  1021. }
  1022. /*
  1023. * Here is where it is going to get dirty....
  1024. */
  1025. if ($osType == 'UNIX') {
  1026. foreach ($contents as $file) {
  1027. $tmp_array = null;
  1028. if (ereg($regexp, $file, $regs)) {
  1029. $fType = (int) strpos("-dl", $regs[1] { 0 });
  1030. //$tmp_array['line'] = $regs[0];
  1031. $tmp_array['type'] = $fType;
  1032. $tmp_array['rights'] = $regs[1];
  1033. //$tmp_array['number'] = $regs[2];
  1034. $tmp_array['user'] = $regs[3];
  1035. $tmp_array['group'] = $regs[4];
  1036. $tmp_array['size'] = $regs[5];
  1037. $tmp_array['date'] = date("m-d", strtotime($regs[6]));
  1038. $tmp_array['time'] = $regs[7];
  1039. $tmp_array['name'] = $regs[9];
  1040. }
  1041. // If we just want files, do not add a folder
  1042. if ($type == 'files' && $tmp_array['type'] == 1) {
  1043. continue;
  1044. }
  1045. // If we just want folders, do not add a file
  1046. if ($type == 'folders' && $tmp_array['type'] == 0) {
  1047. continue;
  1048. }
  1049. if (is_array($tmp_array) && $tmp_array['name'] != '.' && $tmp_array['name'] != '..') {
  1050. $dir_list[] = $tmp_array;
  1051. }
  1052. }
  1053. }
  1054. elseif ($osType == 'MAC') {
  1055. foreach ($contents as $file) {
  1056. $tmp_array = null;
  1057. if (ereg($regexp, $file, $regs)) {
  1058. $fType = (int) strpos("-dl", $regs[1] { 0 });
  1059. //$tmp_array['line'] = $regs[0];
  1060. $tmp_array['type'] = $fType;
  1061. $tmp_array['rights'] = $regs[1];
  1062. //$tmp_array['number'] = $regs[2];
  1063. $tmp_array['user'] = $regs[3];
  1064. $tmp_array['group'] = $regs[4];
  1065. $tmp_array['size'] = $regs[5];
  1066. $tmp_array['date'] = date("m-d", strtotime($regs[6]));
  1067. $tmp_array['time'] = $regs[7];
  1068. $tmp_array['name'] = $regs[9];
  1069. }
  1070. // If we just want files, do not add a folder
  1071. if ($type == 'files' && $tmp_array['type'] == 1) {
  1072. continue;
  1073. }
  1074. // If we just want folders, do not add a file
  1075. if ($type == 'folders' && $tmp_array['type'] == 0) {
  1076. continue;
  1077. }
  1078. if (is_array($tmp_array) && $tmp_array['name'] != '.' && $tmp_array['name'] != '..') {
  1079. $dir_list[] = $tmp_array;
  1080. }
  1081. }
  1082. } else {
  1083. foreach ($contents as $file) {
  1084. $tmp_array = null;
  1085. if (ereg($regexp, $file, $regs)) {
  1086. $fType = (int) ($regs[7] == '<DIR>');
  1087. $timestamp = strtotime("$regs[3]-$regs[1]-$regs[2] $regs[4]:$regs[5]$regs[6]");
  1088. //$tmp_array['line'] = $regs[0];
  1089. $tmp_array['type'] = $fType;
  1090. $tmp_array['rights'] = '';
  1091. //$tmp_array['number'] = 0;
  1092. $tmp_array['user'] = '';
  1093. $tmp_array['group'] = '';
  1094. $tmp_array['size'] = (int) $regs[7];
  1095. $tmp_array['date'] = date('m-d', $timestamp);
  1096. $tmp_array['time'] = date('H:i', $timestamp);
  1097. $tmp_array['name'] = $regs[8];
  1098. }
  1099. // If we just want files, do not add a folder
  1100. if ($type == 'files' && $tmp_array['type'] == 1) {
  1101. continue;
  1102. }
  1103. // If we just want folders, do not add a file
  1104. if ($type == 'folders' && $tmp_array['type'] == 0) {
  1105. continue;
  1106. }
  1107. if (is_array($tmp_array) && $tmp_array['name'] != '.' && $tmp_array['name'] != '..') {
  1108. $dir_list[] = $tmp_array;
  1109. }
  1110. }
  1111. }
  1112. return $dir_list;
  1113. }
  1114. /**
  1115. * Send command to the FTP server and validate an expected response code
  1116. *
  1117. * @access private
  1118. * @param string $cmd Command to send to the FTP server
  1119. * @param mixed $expected Integer response code or array of integer response codes
  1120. * @return boolean True if command executed successfully
  1121. */
  1122. function _putCmd($cmd, $expectedResponse) {
  1123. // Make sure we have a connection to the server
  1124. if (!is_resource($this->_conn)) {
  1125. JError::raiseWarning('31', 'JFTP::_putCmd: Not connected to the control port' );
  1126. return false;
  1127. }
  1128. // Send the command to the server
  1129. if (!fwrite($this->_conn, $cmd."\r\n")) {
  1130. JError::raiseWarning('32', 'JFTP::_putCmd: Unable to send command: '.$cmd );
  1131. }
  1132. return $this->_verifyResponse($expectedResponse);
  1133. }
  1134. /**
  1135. * Verify the response code from the server and log response if flag is set
  1136. *
  1137. * @access private
  1138. * @param mixed $expected Integer response code or array of integer response codes
  1139. * @return boolean True if response code from the server is expected
  1140. */
  1141. function _verifyResponse($expected) {
  1142. // Initialize variables
  1143. $parts = null;
  1144. // Wait for a response from the server, but timeout after the set time limit
  1145. $endTime = time() + $this->_timeout;
  1146. $this->_response = '';
  1147. do {
  1148. $this->_response .= fgets($this->_conn, 4096);
  1149. } while (!preg_match("/^([0-9]{3})(-(.*".CRLF.")+\\1)? [^".CRLF."]+".CRLF."$/", $this->_response, $parts) && time() < $endTime);
  1150. // Catch a timeout or bad response
  1151. if (!isset($parts[1])) {
  1152. JError::raiseWarning('SOME_ERROR_CODE', 'JFTP::_verifyResponse: Timeout or unrecognized response while waiting for a response from the server', 'Server response: '.$this->_response);
  1153. return false;
  1154. }
  1155. // Separate the code from the message
  1156. $this->_responseCode = $parts[1];
  1157. $this->_responseMsg = $parts[0];
  1158. // Did the server respond with the code we wanted?
  1159. if (is_array($expected)) {
  1160. if (in_array($this->_responseCode, $expected)) {
  1161. $retval = true;
  1162. } else {
  1163. $retval = false;
  1164. }
  1165. } else {
  1166. if ($this->_responseCode == $expected) {
  1167. $retval = true;
  1168. } else {
  1169. $retval = false;
  1170. }
  1171. }
  1172. return $retval;
  1173. }
  1174. /**
  1175. * Set server to passive mode and open a data port connection
  1176. *
  1177. * @access private
  1178. * @return boolean True if successful
  1179. */
  1180. function _passive() {
  1181. //Initialize variables
  1182. $match = array();
  1183. $parts = array();
  1184. $errno = null;
  1185. $err = null;
  1186. // Make sure we have a connection to the server
  1187. if (!is_resource($this->_conn)) {
  1188. JError::raiseWarning('31', 'JFTP::_passive: Not connected to the control port' );
  1189. return false;
  1190. }
  1191. // Request a passive connection - this means, we'll talk to you, you don't talk to us.
  1192. @ fwrite($this->_conn, "PASV\r\n");
  1193. // Wait for a response from the server, but timeout after the set time limit
  1194. $endTime = time() + $this->_timeout;
  1195. $this->_response = '';
  1196. do {
  1197. $this->_response .= fgets($this->_conn, 4096);
  1198. } while (!preg_match("/^([0-9]{3})(-(.*".CRLF.")+\\1)? [^".CRLF."]+".CRLF."$/", $this->_response, $parts) && time() < $endTime);
  1199. // Catch a timeout or bad response
  1200. if (!isset($parts[1])) {
  1201. JError::raiseWarning('SOME_ERROR_CODE', 'JFTP::_passive: Timeout or unrecognized response while waiting for a response from the server', 'Server response: '.$this->_response);
  1202. return false;
  1203. }
  1204. // Separate the code from the message
  1205. $this->_responseCode = $parts[1];
  1206. $this->_responseMsg = $parts[0];
  1207. // If it's not 227, we weren't given an IP and port, which means it failed.
  1208. if ($this->_responseCode != '227') {
  1209. JError::raiseWarning('36', 'JFTP::_passive: Unable to obtain IP and port for data transfer', 'Server response: '.$this->_responseMsg);
  1210. return false;
  1211. }
  1212. // Snatch the IP and port information, or die horribly trying...
  1213. if (preg_match('~\((\d+),\s*(\d+),\s*(\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))\)~', $this->_responseMsg, $match) == 0) {
  1214. JError::raiseWarning('36', 'JFTP::_passive: IP and port for data transfer not valid', 'Server response: '.$this->_responseMsg);
  1215. return false;
  1216. }
  1217. // This is pretty simple - store it for later use ;).
  1218. $this->_pasv = array ('ip' => $match[1].'.'.$match[2].'.'.$match[3].'.'.$match[4], 'port' => $match[5] * 256 + $match[6]);
  1219. // Connect, assuming we've got a connection.
  1220. $this->_dataconn = @fsockopen($this->_pasv['ip'], $this->_pasv['port'], $errno, $err, $this->_timeout);
  1221. if (!$this->_dataconn) {
  1222. JError::raiseWarning('30', 'JFTP::_passive: Could not connect to host '.$this->_pasv['ip'].' on port '.$this->_pasv['port'].'. Socket error number '.$errno.' and error message: '.$err );
  1223. return false;
  1224. }
  1225. // Set the timeout for this connection
  1226. socket_set_timeout($this->_conn, $this->_timeout);
  1227. return true;
  1228. }
  1229. /**
  1230. * Method to find out the correct transfer mode for a specific file
  1231. *
  1232. * @access private
  1233. * @param string $fileName Name of the file
  1234. * @return integer Transfer-mode for this filetype [FTP_ASCII|FTP_BINARY]
  1235. */
  1236. function _findMode($fileName) {
  1237. if ($this->_type == FTP_AUTOASCII) {
  1238. $dot = strrpos($fileName, '.') + 1;
  1239. $ext = substr($fileName, $dot);
  1240. if (in_array($ext, $this->_autoAscii)) {
  1241. $mode = FTP_ASCII;
  1242. } else {
  1243. $mode = FTP_BINARY;
  1244. }
  1245. } elseif ($this->_type == FTP_ASCII) {
  1246. $mode = FTP_ASCII;
  1247. } else {
  1248. $mode = FTP_BINARY;
  1249. }
  1250. return $mode;
  1251. }
  1252. /**
  1253. * Set transfer mode
  1254. *
  1255. * @access private
  1256. * @param int $mode Integer representation of data transfer mode [1:Binary|0:Ascii]
  1257. * Defined constants can also be used [FTP_BINARY|FTP_ASCII]
  1258. * @return boolean True if successful
  1259. */
  1260. function _mode($mode) {
  1261. if ($mode == FTP_BINARY) {
  1262. if (!$this->_putCmd("TYPE I", 200)) {
  1263. JError::raiseWarning('35', 'JFTP::_mode: Bad response', 'Server response: '.$this->_response.' [Expected: 200] Mode sent: Binary' );
  1264. return false;
  1265. }
  1266. } else {
  1267. if (!$this->_putCmd("TYPE A", 200)) {
  1268. JError::raiseWarning('35', 'JFTP::_mode: Bad response', 'Server response: '.$this->_response.' [Expected: 200] Mode sent: Ascii' );
  1269. return false;
  1270. }
  1271. }
  1272. return true;
  1273. }
  1274. }