Support Joomla!

Joomla! 1.5 Documentation

Packages

Package: Joomla-Framework

License

Content on this site is copyright © 2005 - 2008 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution- NonCommercial- ShareAlike 2.5. Some parts of this website may be subject to other licenses.
Source code for file /joomla/client/ftp.php

Documentation is available at ftp.php

  1. <?php
  2. /**
  3. @version        $Id: ftp.php 9764 2007-12-30 07:48:11Z ircmaxell $
  4. @package        Joomla.Framework
  5. @subpackage    Client
  6. @copyright    Copyright (C) 2005 - 2008 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.  
  13. // Check to ensure this file is within the rest of the framework
  14. defined('JPATH_BASE'or die();
  15.  
  16. /** Error Codes:
  17.  *  - 30 : Unable to connect to host
  18.  *  - 31 : Not connected
  19.  *  - 32 : Unable to send command to server
  20.  *  - 33 : Bad username
  21.  *  - 34 : Bad password
  22.  *  - 35 : Bad response
  23.  *  - 36 : Passive mode failed
  24.  *  - 37 : Data transfer error
  25.  *  - 38 : Local filesystem error
  26.  */
  27.  
  28. if (!defined('CRLF')) {
  29.     define('CRLF'"\r\n");
  30. }
  31. if (!defined("FTP_AUTOASCII")) {
  32.     define("FTP_AUTOASCII"-1);
  33. }
  34. if (!defined("FTP_BINARY")) {
  35.     define("FTP_BINARY"1);
  36. }
  37. if (!defined("FTP_ASCII")) {
  38.     define("FTP_ASCII"0);
  39. }
  40.  
  41. // Is FTP extension loaded?  If not try to load it
  42. if (!extension_loaded('ftp')) {
  43.     if (strtoupper(substr(PHP_OS03)) === 'WIN'{
  44.         dl('php_ftp.dll');
  45.     else {
  46.         dl('ftp.so');
  47.     }
  48. }
  49. if (!defined('FTP_NATIVE')) {
  50.     define('FTP_NATIVE'(function_exists('ftp_connect'))0);
  51. }
  52.  
  53. /**
  54.  * FTP client class
  55.  *
  56.  * @author        Louis Landry  <louis.landry@joomla.org>
  57.  * @package        Joomla.Framework
  58.  * @subpackage    Client
  59.  * @since        1.5
  60.  */
  61. class JFTP extends JObject
  62. {
  63.  
  64.     /**
  65.      * Server connection resource
  66.      *
  67.      * @access private
  68.      * @var socket resource
  69.      */
  70.     var $_conn null;
  71.  
  72.     /**
  73.      * Data port connection resource
  74.      *
  75.      * @access private
  76.      * @var socket resource
  77.      */
  78.     var $_dataconn null;
  79.  
  80.     /**
  81.      * Passive connection information
  82.      *
  83.      * @access private
  84.      * @var array 
  85.      */
  86.     var $_pasv null;
  87.  
  88.     /**
  89.      * Response Message
  90.      *
  91.      * @access private
  92.      * @var string 
  93.      */
  94.     var $_response null;
  95.  
  96.     /**
  97.      * Timeout limit
  98.      *
  99.      * @access private
  100.      * @var int 
  101.      */
  102.     var $_timeout 15;
  103.  
  104.     /**
  105.      * Transfer Type
  106.      *
  107.      * @access private
  108.      * @var int 
  109.      */
  110.     var $_type null;
  111.  
  112.     /**
  113.      * Native OS Type
  114.      *
  115.      * @access private
  116.      * @var string 
  117.      */
  118.     var $_OS null;
  119.  
  120.     /**
  121.      * Array to hold ascii format file extensions
  122.      *
  123.      * @final
  124.      * @access private
  125.      * @var array 
  126.      */
  127.     var $_autoAscii array ("asp""bat""c""cpp""csv""h""htm""html""shtml""ini""inc""log""php""php3""pl""perl""sh""sql""txt""xhtml""xml");
  128.  
  129.     /**
  130.      * Array to hold native line ending characters
  131.      *
  132.      * @final
  133.      * @access private
  134.      * @var array 
  135.      */
  136.     var $_lineEndings array ('UNIX' => "\n"'MAC' => "\r"'WIN' => "\r\n");
  137.  
  138.     /**
  139.      * JFTP object constructor
  140.      *
  141.      * @access protected
  142.      * @param array $options Associative array of options to set
  143.      * @since 1.5
  144.      */
  145.     function __construct($options=array()) {
  146.  
  147.         // If default transfer type is no set, set it to autoascii detect
  148.         if (!isset ($options['type'])) {
  149.             $options['type'FTP_BINARY;
  150.         }
  151.         $this->setOptions($options);
  152.  
  153.         if (strtoupper(substr(PHP_OS03)) === 'WIN'{
  154.             $this->_OS 'WIN';
  155.         elseif (strtoupper(substr(PHP_OS03)) === 'MAC'{
  156.             $this->_OS 'MAC';
  157.         else {
  158.             $this->_OS 'UNIX';
  159.         }
  160.  
  161.         if (FTP_NATIVE{
  162.             // Import the generic buffer stream handler
  163.             jimport('joomla.utilities.buffer');
  164.             // Autoloading fails for JBuffer as the class is used as a stream handler
  165.             JLoader::load('JBuffer');
  166.         }
  167.  
  168.         // Register faked "destructor" in PHP4 to close all connections we might have made
  169.         if (version_compare(PHP_VERSION'5'== -1{
  170.             register_shutdown_function(array(&$this'__destruct'));
  171.         }
  172.     }
  173.  
  174.     /**
  175.      * JFTP object destructor
  176.      *
  177.      * Closes an existing connection, if we have one
  178.      *
  179.      * @access protected
  180.      * @since 1.5
  181.      */
  182.     function __destruct({
  183.         if (is_resource($this->_conn)) {
  184.             $this->quit();
  185.         }
  186.     }
  187.  
  188.     /**
  189.      * Returns a reference to the global FTP connector object, only creating it
  190.      * if it doesn't already exist.
  191.      *
  192.      * This method must be invoked as:
  193.      *         <pre>  $ftp = &JFTP::getInstance($host);</pre>
  194.      *
  195.      * You may optionally specify a username and password in the parameters. If you do so,
  196.      * you may not login() again with different credentials using the same object.
  197.      * If you do not use this option, you must quit() the current connection when you
  198.      * are done, to free it for use by others.
  199.      *
  200.      * @param    string    $host        Host to connect to
  201.      * @param    string    $port        Port to connect to
  202.      * @param    array    $options    Array with any of these options: type=>[FTP_AUTOASCII|FTP_ASCII|FTP_BINARY], timeout=>(int)
  203.      * @param    string    $user        Username to use for a connection
  204.      * @param    string    $pass        Password to use for a connection
  205.      * @return    JFTP    The FTP Client object.
  206.      * @since 1.5
  207.      */
  208.     function &getInstance($host '127.0.0.1'$port '21'$options null$user null$pass null)
  209.     {
  210.         static $instances array();
  211.  
  212.         $signature $user.':'.$pass.'@'.$host.":".$port;
  213.  
  214.         // Create a new instance, or set the options of an existing one
  215.                 if (!isset ($instances[$signature]|| !is_object($instances[$signature])) {
  216.             $instances[$signaturenew JFTP($options);
  217.         else {
  218.             $instances[$signature]->setOptions($options);
  219.         }
  220.  
  221.         // Connect to the server, and login, if requested
  222.                 if (!$instances[$signature]->isConnected()) {
  223.             $return $instances[$signature]->connect($host$port);
  224.             if ($return && $user !== null && $pass !== null{
  225.                 $instances[$signature]->login($user$pass);
  226.             }
  227.         }
  228.  
  229.         return $instances[$signature];
  230.     }
  231.  
  232.     /**
  233.      * Set client options
  234.      *
  235.      * @access public
  236.      * @param array $options Associative array of options to set
  237.      * @return boolean True if successful
  238.      */
  239.     function setOptions($options{
  240.  
  241.         if (isset ($options['type'])) {
  242.             $this->_type $options['type'];
  243.         }
  244.         if (isset ($options['timeout'])) {
  245.             $this->_timeout $options['timeout'];
  246.         }
  247.         return true;
  248.     }
  249.  
  250.     /**
  251.      * Method to connect to a FTP server
  252.      *
  253.      * @access public
  254.      * @param string $host Host to connect to [Default: 127.0.0.1]
  255.      * @param string $port Port to connect on [Default: port 21]
  256.      * @return boolean True if successful
  257.      */
  258.     function connect($host '127.0.0.1'$port 21{
  259.  
  260.         // Initialize variables
  261.         $errno null;
  262.         $err null;
  263.  
  264.         // If already connected, return
  265.         if (is_resource($this->_conn)) {
  266.             return true;
  267.         }
  268.  
  269.         // If native FTP support is enabled lets use it...
  270.         if (FTP_NATIVE{
  271.             $this->_conn @ftp_connect($host$port$this->_timeout);
  272.             if ($this->_conn === false{
  273.                 JError::raiseWarning('30''JFTP::connect: Could not connect to host "'.$host.'" on port '.$port);
  274.                 return false;
  275.             }
  276.             // Set the timeout for this connection
  277.             ftp_set_option($this->_connFTP_TIMEOUT_SEC$this->_timeout);
  278.             return true;
  279.         }
  280.  
  281.         // Connect to the FTP server.
  282.         $this->_conn fsockopen($host$port$errno$err$this->_timeout);
  283.         if (!$this->_conn{
  284.             JError::raiseWarning('30''JFTP::connect: Could not connect to host "'.$host.'" on port '.$port'Socket error number '.$errno.' and error message: '.$err);
  285.             return false;
  286.         }
  287.  
  288.         // Set the timeout for this connection
  289.         socket_set_timeout($this->_conn$this->_timeout);
  290.  
  291.         // Check for welcome response code
  292.         if (!$this->_verifyResponse(220)) {
  293.             JError::raiseWarning('35''JFTP::connect: Bad response''Server response: '.$this->_response.' [Expected: 220]');
  294.             return false;
  295.         }
  296.  
  297.         return true;
  298.     }
  299.  
  300.     /**
  301.      * Method to determine if the object is connected to an FTP server
  302.      *
  303.      * @access    public
  304.      * @return    boolean    True if connected
  305.      * @since    1.5
  306.      */
  307.     function isConnected()
  308.     {
  309.         return is_resource($this->_conn);
  310.     }
  311.  
  312.     /**
  313.      * Method to login to a server once connected
  314.      *
  315.      * @access public
  316.      * @param string $user Username to login to the server
  317.      * @param string $pass Password to login to the server
  318.      * @return boolean True if successful
  319.      */
  320.     function login($user 'anonymous'$pass 'jftp@joomla.org'{
  321.  
  322.         // If native FTP support is enabled lets use it...
  323.         if (FTP_NATIVE{
  324.             if (@ftp_login($this->_conn$user$pass=== false{
  325.                 JError::raiseWarning('30''JFTP::login: Unable to login' );
  326.                 return false;
  327.             }
  328.             return true;
  329.         }
  330.  
  331.         // Send the username
  332.         if (!$this->_putCmd('USER '.$userarray(331503))) {
  333.             JError::raiseWarning('33''JFTP::login: Bad Username''Server response: '.$this->_response.' [Expected: 331] Username sent: '.$user );
  334.             return false;
  335.         }
  336.  
  337.         // If we are already logged in, continue :)
  338.         if ($this->_responseCode == 503{
  339.             return true;
  340.         }
  341.  
  342.         // Send the password
  343.         if (!$this->_putCmd('PASS '.$pass230)) {
  344.             JError::raiseWarning('34''JFTP::login: Bad Password''Server response: '.$this->_response.' [Expected: 230] Password sent: '.str_repeat('*'strlen($pass)));
  345.             return false;
  346.         }
  347.  
  348.         return true;
  349.     }
  350.  
  351.     /**
  352.      * Method to quit and close the connection
  353.      *
  354.      * @access public
  355.      * @return boolean True if successful
  356.      */
  357.     function quit({
  358.  
  359.         // If native FTP support is enabled lets use it...
  360.         if (FTP_NATIVE{
  361.             @ftp_close($this->_conn);
  362.             return true;
  363.         }
  364.  
  365.         // Logout and close connection
  366.         @fwrite($this->_conn"QUIT\r\n");
  367.         @fclose($this->_conn);
  368.  
  369.         return true;
  370.     }
  371.  
  372.     /**
  373.      * Method to retrieve the current working directory on the FTP server
  374.      *
  375.      * @access public
  376.      * @return string Current working directory
  377.      */
  378.     function pwd({
  379.  
  380.         // If native FTP support is enabled lets use it...
  381.         if (FTP_NATIVE{
  382.             if (($ret @ftp_pwd($this->_conn)) === false{
  383.                 JError::raiseWarning('35''JFTP::pwd: Bad response' );
  384.                 return false;
  385.             }
  386.             return $ret;
  387.         }
  388.  
  389.         // Initialize variables
  390.         $match array (null);
  391.  
  392.         // Send print working directory command and verify success
  393.         if (!$this->_putCmd('PWD'257)) {
  394.             JError::raiseWarning('35''JFTP::pwd: Bad response''Server response: '.$this->_response.' [Expected: 257]' );
  395.             return false;
  396.         }
  397.  
  398.         // Match just the path
  399.         preg_match('/"[^"\r\n]*"/'$this->_response$match);
  400.  
  401.         // Return the cleaned path
  402.         return preg_replace("/\"/"""$match[0]);
  403.     }
  404.  
  405.     /**
  406.      * Method to system string from the FTP server
  407.      *
  408.      * @access public
  409.      * @return string System identifier string
  410.      */
  411.     function syst({
  412.  
  413.         // If native FTP support is enabled lets use it...
  414.         if (FTP_NATIVE{
  415.             if (($ret @ftp_systype($this->_conn)) === false{
  416.                 JError::raiseWarning('35''JFTP::syst: Bad response' );
  417.                 return false;
  418.             }
  419.         else {
  420.             // Send print working directory command and verify success
  421.             if (!$this->_putCmd('SYST'215)) {
  422.                 JError::raiseWarning('35''JFTP::syst: Bad response''Server response: '.$this->_response.' [Expected: 215]' );
  423.                 return false;
  424.             }
  425.             $ret $this->_response;
  426.         }
  427.  
  428.         // Match the system string to an OS
  429.         if (strpos(strtoupper($ret)'MAC'!== false{
  430.             $ret 'MAC';
  431.         elseif (strpos(strtoupper($ret)'WIN'!== false{
  432.             $ret 'WIN';
  433.         else {
  434.             $ret 'UNIX';
  435.         }
  436.  
  437.         // Return the os type
  438.         return $ret;
  439.     }
  440.  
  441.     /**
  442.      * Method to change the current working directory on the FTP server
  443.      *
  444.      * @access public
  445.      * @param string $path Path to change into on the server
  446.      * @return boolean True if successful
  447.      */
  448.     function chdir($path{
  449.  
  450.         // If native FTP support is enabled lets use it...
  451.         if (FTP_NATIVE{
  452.             if (@ftp_chdir($this->_conn$path=== false{
  453.                 JError::raiseWarning('35''JFTP::chdir: Bad response' );
  454.                 return false;
  455.             }
  456.             return true;
  457.         }
  458.  
  459.         // Send change directory command and verify success
  460.         if (!$this->_putCmd('CWD '.$path250)) {
  461.             JError::raiseWarning('35''JFTP::chdir: Bad response''Server response: '.$this->_response.' [Expected: 250] Path sent: '.$path );
  462.             return false;
  463.         }
  464.  
  465.         return true;
  466.     }
  467.  
  468.     /**
  469.      * Method to reinitialize the server, ie. need to login again
  470.      *
  471.      * NOTE: This command not available on all servers
  472.      *
  473.      * @access public
  474.      * @return boolean True if successful
  475.      */
  476.     function reinit({
  477.  
  478.         // If native FTP support is enabled lets use it...
  479.         if (FTP_NATIVE{
  480.             if (@ftp_site($this->_conn'REIN'=== false{
  481.                 JError::raiseWarning('35''JFTP::reinit: Bad response' );
  482.  &