Source for file ftp.php

Documentation is available at ftp.php

  1. <?php
  2. /**
  3.  * @package     Joomla.Platform
  4.  * @subpackage  Client
  5.  *
  6.  * @copyright   Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
  7.  * @license     GNU General Public License version 2 or later; see LICENSE
  8.  */
  9.  
  10. defined('JPATH_PLATFORM'or die;
  11.  
  12. /** Error Codes:
  13.  * - 30 : Unable to connect to host
  14.  * - 31 : Not connected
  15.  * - 32 : Unable to send command to server
  16.  * - 33 : Bad username
  17.  * - 34 : Bad password
  18.  * - 35 : Bad response
  19.  * - 36 : Passive mode failed
  20.  * - 37 : Data transfer error
  21.  * - 38 : Local filesystem error
  22.  */
  23.  
  24. if (!defined('CRLF'))
  25. {
  26.     define('CRLF'"\r\n");
  27. }
  28. if (!defined("FTP_AUTOASCII"))
  29. {
  30.     define("FTP_AUTOASCII"-1);
  31. }
  32. if (!defined("FTP_BINARY"))
  33. {
  34.     define("FTP_BINARY"1);
  35. }
  36. if (!defined("FTP_ASCII"))
  37. {
  38.     define("FTP_ASCII"0);
  39. }
  40.  
  41. if (!defined('FTP_NATIVE'))
  42. {
  43.     define('FTP_NATIVE'(function_exists('ftp_connect')) 0);
  44. }
  45.  
  46. /**
  47.  * FTP client class
  48.  *
  49.  * @package     Joomla.Platform
  50.  * @subpackage  Client
  51.  * @since       12.1
  52.  */
  53. class JClientFtp
  54. {
  55.     /**
  56.      * @var    resource  Socket resource
  57.      * @since  12.1
  58.      */
  59.     private $_conn null;
  60.  
  61.     /**
  62.      * @var    resource  Data port connection resource
  63.      * @since  12.1
  64.      */
  65.     private $_dataconn null;
  66.  
  67.     /**
  68.      * @var    array  Passive connection information
  69.      * @since  12.1
  70.      */
  71.     private $_pasv null;
  72.  
  73.     /**
  74.      * @var    string  Response Message
  75.      * @since  12.1
  76.      */
  77.     private $_response null;
  78.  
  79.     /**
  80.      * @var    integer  Timeout limit
  81.      * @since  12.1
  82.      */
  83.     private $_timeout 15;
  84.  
  85.     /**
  86.      * @var    integer  Transfer Type
  87.      * @since  12.1
  88.      */
  89.     private $_type null;
  90.  
  91.     /**
  92.      * @var    array  Array to hold ascii format file extensions
  93.      * @since   12.1
  94.      */
  95.     private $_autoAscii array(
  96.         "asp",
  97.         "bat",
  98.         "c",
  99.         "cpp",
  100.         "csv",
  101.         "h",
  102.         "htm",
  103.         "html",
  104.         "shtml",
  105.         "ini",
  106.         "inc",
  107.         "log",
  108.         "php",
  109.         "php3",
  110.         "pl",
  111.         "perl",
  112.         "sh",
  113.         "sql",
  114.         "txt",
  115.         "xhtml",
  116.         "xml");
  117.  
  118.     /**
  119.      * Array to hold native line ending characters
  120.      *
  121.      * @var    array 
  122.      * @since  12.1
  123.      */
  124.     private $_lineEndings array('UNIX' => "\n"'WIN' => "\r\n");
  125.  
  126.     /**
  127.      * @var    array  JClientFtp instances container.
  128.      * @since  12.1
  129.      */
  130.     protected static $instances array();
  131.  
  132.     /**
  133.      * JClientFtp object constructor
  134.      *
  135.      * @param   array  $options  Associative array of options to set
  136.      *
  137.      * @since   12.1
  138.      */
  139.     public function __construct(array $options array())
  140.     {
  141.         // If default transfer type is not set, set it to autoascii detect
  142.         if (!isset($options['type']))
  143.         {
  144.             $options['type'FTP_BINARY;
  145.         }
  146.         $this->setOptions($options);
  147.  
  148.         if (FTP_NATIVE)
  149.         {
  150.             // Import the generic buffer stream handler
  151.             jimport('joomla.utilities.buffer');
  152.  
  153.             // Autoloading fails for JBuffer as the class is used as a stream handler
  154.             JLoader::load('JBuffer');
  155.         }
  156.     }
  157.  
  158.     /**
  159.      * JClientFtp object destructor
  160.      *
  161.      * Closes an existing connection, if we have one
  162.      *
  163.      * @since   12.1
  164.      */
  165.     public function __destruct()
  166.     {
  167.         if (is_resource($this->_conn))
  168.         {
  169.             $this->quit();
  170.         }
  171.     }
  172.  
  173.     /**
  174.      * Returns the global FTP connector object, only creating it
  175.      * if it doesn't already exist.
  176.      *
  177.      * You may optionally specify a username and password in the parameters. If you do so,
  178.      * you may not login() again with different credentials using the same object.
  179.      * If you do not use this option, you must quit() the current connection when you
  180.      * are done, to free it for use by others.
  181.      *
  182.      * @param   string  $host     Host to connect to
  183.      * @param   string  $port     Port to connect to
  184.      * @param   array   $options  Array with any of these options: type=>[FTP_AUTOASCII|FTP_ASCII|FTP_BINARY], timeout=>(int)
  185.      * @param   string  $user     Username to use for a connection
  186.      * @param   string  $pass     Password to use for a connection
  187.      *
  188.      * @return  JClientFtp        The FTP Client object.
  189.      *
  190.      * @since   12.1
  191.      */
  192.     public static function getInstance($host '127.0.0.1'$port '21'array $options array()$user null$pass null)
  193.     {
  194.         $signature $user ':' $pass '@' $host ":" $port;
  195.  
  196.         // Create a new instance, or set the options of an existing one
  197.         if (!isset(self::$instances[$signature]|| !is_object(self::$instances[$signature]))
  198.         {
  199.             self::$instances[$signaturenew static($options);
  200.         }
  201.         else
  202.         {
  203.             self::$instances[$signature]->setOptions($options);
  204.         }
  205.  
  206.         // Connect to the server, and login, if requested
  207.         if (!self::$instances[$signature]->isConnected())
  208.         {
  209.             $return self::$instances[$signature]->connect($host$port);
  210.  
  211.             if ($return && $user !== null && $pass !== null)
  212.             {
  213.                 self::$instances[$signature]->login($user$pass);
  214.             }
  215.         }
  216.  
  217.         return self::$instances[$signature];
  218.     }
  219.  
  220.     /**
  221.      * Set client options
  222.      *
  223.      * @param   array  $options  Associative array of options to set
  224.      *
  225.      * @return  boolean  True if successful
  226.      *
  227.      * @since   12.1
  228.      */
  229.     public function setOptions(array $options)
  230.     {
  231.         if (isset($options['type']))
  232.         {
  233.             $this->_type $options['type'];
  234.         }
  235.         if (isset($options['timeout']))
  236.         {
  237.             $this->_timeout $options['timeout'];
  238.         }
  239.         return true;
  240.     }
  241.  
  242.     /**
  243.      * Method to connect to a FTP server
  244.      *
  245.      * @param   string  $host  Host to connect to [Default: 127.0.0.1]
  246.      * @param   string  $port  Port to connect on [Default: port 21]
  247.      *
  248.      * @return  boolean  True if successful
  249.      *
  250.      * @since   12.1
  251.      */
  252.     public function connect($host '127.0.0.1'$port 21)
  253.     {
  254.         $errno null;
  255.         $err null;
  256.  
  257.         // If already connected, return
  258.         if (is_resource($this->_conn))
  259.         {
  260.             return true;
  261.         }
  262.  
  263.         // If native FTP support is enabled let's use it...
  264.         if (FTP_NATIVE)
  265.         {
  266.             $this->_conn @ftp_connect($host$port$this->_timeout);
  267.  
  268.             if ($this->_conn === false)
  269.             {
  270.                 JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_NO_CONNECT'$host$port)JLog::WARNING'jerror');
  271.  
  272.                 return false;
  273.             }
  274.             // Set the timeout for this connection
  275.             ftp_set_option($this->_connFTP_TIMEOUT_SEC$this->_timeout);
  276.  
  277.             return true;
  278.         }
  279.  
  280.         // Connect to the FTP server.
  281.         $this->_conn fsockopen($host$port$errno$err$this->_timeout);
  282.  
  283.         if (!$this->_conn)
  284.         {
  285.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_NO_CONNECT_SOCKET'$host$port$errno$err)JLog::WARNING'jerror');
  286.  
  287.             return false;
  288.         }
  289.  
  290.         // Set the timeout for this connection
  291.         socket_set_timeout($this->_conn$this->_timeout0);
  292.  
  293.         // Check for welcome response code
  294.         if (!$this->_verifyResponse(220))
  295.         {
  296.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_BAD_RESPONSE'$this->_response)JLog::WARNING'jerror');
  297.  
  298.             return false;
  299.         }
  300.  
  301.         return true;
  302.     }
  303.  
  304.     /**
  305.      * Method to determine if the object is connected to an FTP server
  306.      *
  307.      * @return  boolean  True if connected
  308.      *
  309.      * @since   12.1
  310.      */
  311.     public function isConnected()
  312.     {
  313.         return is_resource($this->_conn);
  314.     }
  315.  
  316.     /**
  317.      * Method to login to a server once connected
  318.      *
  319.      * @param   string  $user  Username to login to the server
  320.      * @param   string  $pass  Password to login to the server
  321.      *
  322.      * @return  boolean  True if successful
  323.      *
  324.      * @since   12.1
  325.      */
  326.     public function login($user 'anonymous'$pass 'jftp@joomla.org')
  327.     {
  328.         // If native FTP support is enabled let's use it...
  329.         if (FTP_NATIVE)
  330.         {
  331.             if (@ftp_login($this->_conn$user$pass=== false)
  332.             {
  333.                 JLog::add('JFTP::login: Unable to login'JLog::WARNING'jerror');
  334.  
  335.                 return false;
  336.             }
  337.             return true;
  338.         }
  339.  
  340.         // Send the username
  341.         if (!$this->_putCmd('USER ' $userarray(331503)))
  342.         {
  343.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_BAD_USERNAME'$this->_response$user)JLog::WARNING'jerror');
  344.  
  345.             return false;
  346.         }
  347.  
  348.         // If we are already logged in, continue :)
  349.         if ($this->_responseCode == 503)
  350.         {
  351.             return true;
  352.         }
  353.  
  354.         // Send the password
  355.         if (!$this->_putCmd('PASS ' $pass230))
  356.         {
  357.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_BAD_PASSWORD'$this->_responsestr_repeat('*'strlen($pass)))JLog::WARNING'jerror');
  358.  
  359.             return false;
  360.         }
  361.  
  362.         return true;
  363.     }
  364.  
  365.     /**
  366.      * Method to quit and close the connection
  367.      *
  368.      * @return  boolean  True if successful
  369.      *
  370.      * @since   12.1
  371.      */
  372.     public function quit()
  373.     {
  374.         // If native FTP support is enabled lets use it...
  375.         if (FTP_NATIVE)
  376.         {
  377.             @ftp_close($this->_conn);
  378.  
  379.             return true;
  380.         }
  381.  
  382.         // Logout and close connection
  383.         @fwrite($this->_conn"QUIT\r\n");
  384.         @fclose($this->_conn);
  385.  
  386.         return true;
  387.     }
  388.  
  389.     /**
  390.      * Method to retrieve the current working directory on the FTP server
  391.      *
  392.      * @return  string   Current working directory
  393.      *
  394.      * @since   12.1
  395.      */
  396.     public function pwd()
  397.     {
  398.         // If native FTP support is enabled let's use it...
  399.         if (FTP_NATIVE)
  400.         {
  401.             if (($ret @ftp_pwd($this->_conn)) === false)
  402.             {
  403.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_PWD_BAD_RESPONSE_NATIVE')JLog::WARNING'jerror');
  404.  
  405.                 return false;
  406.             }
  407.             return $ret;
  408.         }
  409.  
  410.         $match array(null);
  411.  
  412.         // Send print working directory command and verify success
  413.         if (!$this->_putCmd('PWD'257))
  414.         {
  415.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_PWD_BAD_RESPONSE'$this->_response)JLog::WARNING'jerror');
  416.  
  417.             return false;
  418.         }
  419.  
  420.         // Match just the path
  421.         preg_match('/"[^"\r\n]*"/'$this->_response$match);
  422.  
  423.         // Return the cleaned path
  424.         return preg_replace("/\"/"""$match[0]);
  425.     }
  426.  
  427.     /**
  428.      * Method to system string from the FTP server
  429.      *
  430.      * @return  string   System identifier string
  431.      *
  432.      * @since   12.1
  433.      */
  434.     public function syst()
  435.     {
  436.         // If native FTP support is enabled lets use it...
  437.         if (FTP_NATIVE)
  438.         {
  439.             if (($ret @ftp_systype($this->_conn)) === false)
  440.             {
  441.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_SYS_BAD_RESPONSE_NATIVE')JLog::WARNING'jerror');
  442.  
  443.                 return false;
  444.             }
  445.         }
  446.         else
  447.         {
  448.             // Send print working directory command and verify success
  449.             if (!$this->_putCmd('SYST'215))
  450.             {
  451.                 JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_SYST_BAD_RESPONSE'$this->_response)JLog::WARNING'jerror');
  452.  
  453.                 return false;
  454.             }
  455.             $ret $this->_response;
  456.         }
  457.  
  458.         // Match the system string to an OS
  459.         if (strpos(strtoupper($ret)'MAC'!== false)
  460.         {
  461.             $ret 'MAC';
  462.         }
  463.         elseif (strpos(strtoupper($ret)'WIN'!== false)
  464.         {
  465.             $ret 'WIN';
  466.         }
  467.         else
  468.         {
  469.             $ret 'UNIX';
  470.         }
  471.  
  472.         // Return the os type
  473.         return $ret;
  474.     }
  475.  
  476.     /**
  477.      * Method to change the current working directory on the FTP server
  478.      *
  479.      * @param   string  $path  Path to change into on the server
  480.      *
  481.      * @return  boolean True if successful
  482.      *
  483.      * @since   12.1
  484.      */
  485.     public function chdir($path)
  486.     {
  487.         // If native FTP support is enabled lets use it...
  488.         if (FTP_NATIVE)
  489.         {
  490.             if (@ftp_chdir($this->_conn$path=== false)
  491.             {
  492.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_CHDIR_BAD_RESPONSE_NATIVE')JLog::WARNING'jerror');
  493.  
  494.                 return false;
  495.             }
  496.             return true;
  497.         }
  498.  
  499.         // Send change directory command and verify success
  500.         if (!$this->_putCmd('CWD ' $path250))
  501.         {
  502.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_CHDIR_BAD_RESPONSE'$this->_response$path)JLog::WARNING'jerror');
  503.  
  504.             return false;
  505.         }
  506.  
  507.         return true;
  508.     }
  509.  
  510.     /**
  511.      * Method to reinitialise the server, ie. need to login again
  512.      *
  513.      * NOTE: This command not available on all servers
  514.      *
  515.      * @return  boolean  True if successful
  516.      *
  517.      * @since   12.1
  518.      */
  519.     public function reinit()
  520.     {
  521.         // If native FTP support is enabled let's use it...
  522.         if (FTP_NATIVE)
  523.         {
  524.             if (@ftp_site($this->_conn'REIN'=== false)
  525.             {
  526.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_REINIT_BAD_RESPONSE_NATIVE')JLog::WARNING'jerror');
  527.  
  528.                 return false;
  529.             }
  530.             return true;
  531.         }
  532.  
  533.         // Send reinitialise command to the server
  534.         if (!$this->_putCmd('REIN'220))
  535.         {
  536.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_REINIT_BAD_RESPONSE'$this->_response)JLog::WARNING'jerror');
  537.  
  538.             return false;
  539.         }
  540.  
  541.         return true;
  542.     }
  543.  
  544.     /**
  545.      * Method to rename a file/folder on the FTP server
  546.      *
  547.      * @param   string  $from  Path to change file/folder from
  548.      * @param   string  $to    Path to change file/folder to
  549.      *
  550.      * @return  boolean  True if successful
  551.      *
  552.      * @since   12.1
  553.      */
  554.     public function rename($from$to)
  555.     {
  556.         // If native FTP support is enabled let's use it...
  557.         if (FTP_NATIVE)
  558.         {
  559.             if (@ftp_rename($this->_conn$from$to=== false)
  560.             {
  561.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_RENAME_BAD_RESPONSE_NATIVE')JLog::WARNING'jerror');
  562.  
  563.                 return false;
  564.             }
  565.             return true;
  566.         }
  567.  
  568.         // Send rename from command to the server
  569.         if (!$this->_putCmd('RNFR ' $from350))
  570.         {
  571.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_RENAME_BAD_RESPONSE_FROM'$this->_response$from)JLog::WARNING'jerror');
  572.  
  573.             return false;
  574.         }
  575.  
  576.         // Send rename to command to the server
  577.         if (!$this->_putCmd('RNTO ' $to250))
  578.         {
  579.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_RENAME_BAD_RESPONSE_TO'$this->_response$to)JLog::WARNING'jerror');
  580.  
  581.             return false;
  582.         }
  583.  
  584.         return true;
  585.     }
  586.  
  587.     /**
  588.      * Method to change mode for a path on the FTP server
  589.      *
  590.      * @param   string  $path  Path to change mode on
  591.      * @param   mixed   $mode  Octal value to change mode to, e.g. '0777', 0777 or 511 (string or integer)
  592.      *
  593.      * @return  boolean  True if successful
  594.      *
  595.      * @since   12.1
  596.      */
  597.     public function chmod($path$mode)
  598.     {
  599.         // If no filename is given, we assume the current directory is the target
  600.         if ($path == '')
  601.         {
  602.             $path '.';
  603.         }
  604.  
  605.         // Convert the mode to a string
  606.         if (is_int($mode))
  607.         {
  608.             $mode decoct($mode);
  609.         }
  610.  
  611.         // If native FTP support is enabled let's use it...
  612.         if (FTP_NATIVE)
  613.         {
  614.             if (@ftp_site($this->_conn'CHMOD ' $mode ' ' $path=== false)
  615.             {
  616.                 if (!IS_WIN)
  617.                 {
  618.                     JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_CHMOD_BAD_RESPONSE_NATIVE')JLog::WARNING'jerror');
  619.                 }
  620.                 return false;
  621.             }
  622.             return true;
  623.         }
  624.  
  625.         // Send change mode command and verify success [must convert mode from octal]
  626.         if (!$this->_putCmd('SITE CHMOD ' $mode ' ' $patharray(200250)))
  627.         {
  628.             if (!IS_WIN)
  629.             {
  630.                 JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_CHMOD_BAD_RESPONSE'$this->_response$path$mode)JLog::WARNING'jerror');
  631.             }
  632.             return false;
  633.         }
  634.         return true;
  635.     }
  636.  
  637.     /**
  638.      * Method to delete a path [file/folder] on the FTP server
  639.      *
  640.      * @param   string  $path  Path to delete
  641.      *
  642.      * @return  boolean  True if successful
  643.      *
  644.      * @since   12.1
  645.      */
  646.     public function delete($path)
  647.     {
  648.         // If native FTP support is enabled let's use it...
  649.         if (FTP_NATIVE)
  650.         {
  651.             if (@ftp_delete($this->_conn$path=== false)
  652.             {
  653.                 if (@ftp_rmdir($this->_conn$path=== false)
  654.                 {
  655.                     JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_DELETE_BAD_RESPONSE_NATIVE')JLog::WARNING'jerror');
  656.  
  657.                     return false;
  658.                 }
  659.             }
  660.             return true;
  661.         }
  662.  
  663.         // Send delete file command and if that doesn't work, try to remove a directory
  664.         if (!$this->_putCmd('DELE ' $path250))
  665.         {
  666.             if (!$this->_putCmd('RMD ' $path250))
  667.             {
  668.                 JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_DELETE_BAD_RESPONSE'$this->_response$path)JLog::WARNING'jerror');
  669.  
  670.                 return false;
  671.             }
  672.         }
  673.         return true;
  674.     }
  675.  
  676.     /**
  677.      * Method to create a directory on the FTP server
  678.      *
  679.      * @param   string  $path  Directory to create
  680.      *
  681.      * @return  boolean  True if successful
  682.      *
  683.      * @since   12.1
  684.      */
  685.     public function mkdir($path)
  686.     {
  687.         // If native FTP support is enabled let's use it...
  688.         if (FTP_NATIVE)
  689.         {
  690.             if (@ftp_mkdir($this->_conn$path=== false)
  691.             {
  692.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_MKDIR_BAD_RESPONSE_NATIVE')JLog::WARNING'jerror');
  693.  
  694.                 return false;
  695.             }
  696.             return true;
  697.         }
  698.  
  699.         // Send change directory command and verify success
  700.         if (!$this->_putCmd('MKD ' $path257))
  701.         {
  702.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_MKDIR_BAD_RESPONSE'$this->_response$path)JLog::WARNING'jerror');
  703.  
  704.             return false;
  705.         }
  706.         return true;
  707.     }
  708.  
  709.     /**
  710.      * Method to restart data transfer at a given byte
  711.      *
  712.      * @param   integer  $point  Byte to restart transfer at
  713.      *
  714.      * @return  boolean  True if successful
  715.      *
  716.      * @since   12.1
  717.      */
  718.     public function restart($point)
  719.     {
  720.         // If native FTP support is enabled let's use it...
  721.         if (FTP_NATIVE)
  722.         {
  723.             if (@ftp_site($this->_conn'REST ' $point=== false)
  724.             {
  725.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_RESTART_BAD_RESPONSE_NATIVE')JLog::WARNING'jerror');
  726.  
  727.                 return false;
  728.             }
  729.             return true;
  730.         }
  731.  
  732.         // Send restart command and verify success
  733.         if (!$this->_putCmd('REST ' $point350))
  734.         {
  735.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_RESTART_BAD_RESPONSE'$this->_response$point)JLog::WARNING'jerror');
  736.  
  737.             return false;
  738.         }
  739.  
  740.         return true;
  741.     }
  742.  
  743.     /**
  744.      * Method to create an empty file on the FTP server
  745.      *
  746.      * @param   string  $path  Path local file to store on the FTP server
  747.      *
  748.      * @return  boolean  True if successful
  749.      *
  750.      * @since   12.1
  751.      */
  752.     public function create($path)
  753.     {
  754.         // If native FTP support is enabled let's use it...
  755.         if (FTP_NATIVE)
  756.         {
  757.             // Turn passive mode on
  758.             if (@ftp_pasv($this->_conntrue=== false)
  759.             {
  760.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_CREATE_BAD_RESPONSE_PASSIVE')JLog::WARNING'jerror');
  761.  
  762.                 return false;
  763.             }
  764.  
  765.             $buffer fopen('buffer://tmp''r');
  766.  
  767.             if (@ftp_fput($this->_conn$path$bufferFTP_ASCII=== false)
  768.             {
  769.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_CREATE_BAD_RESPONSE_BUFFER')JLog::WARNING'jerror');
  770.                 fclose($buffer);
  771.  
  772.                 return false;
  773.             }
  774.             fclose($buffer);
  775.  
  776.             return true;
  777.         }
  778.  
  779.         // Start passive mode
  780.         if (!$this->_passive())
  781.         {
  782.             JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_CREATE_BAD_RESPONSE_PASSIVE')JLog::WARNING'jerror');
  783.  
  784.             return false;
  785.         }
  786.  
  787.         if (!$this->_putCmd('STOR ' $patharray(150125)))
  788.         {
  789.             fclose($this->_dataconn);
  790.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_CREATE_BAD_RESPONSE'$this->_response$path)JLog::WARNING'jerror');
  791.  
  792.             return false;
  793.         }
  794.  
  795.         // To create a zero byte upload close the data port connection
  796.         fclose($this->_dataconn);
  797.  
  798.         if (!$this->_verifyResponse(226))
  799.         {
  800.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_CREATE_BAD_RESPONSE_TRANSFER'$this->_response$path)JLog::WARNING'jerror');
  801.  
  802.             return false;
  803.         }
  804.  
  805.         return true;
  806.     }
  807.  
  808.     /**
  809.      * Method to read a file from the FTP server's contents into a buffer
  810.      *
  811.      * @param   string  $remote   Path to remote file to read on the FTP server
  812.      * @param   string  &$buffer  Buffer variable to read file contents into
  813.      *
  814.      * @return  boolean  True if successful
  815.      *
  816.      * @since   12.1
  817.      */
  818.     public function read($remote&$buffer)
  819.     {
  820.         // Determine file type
  821.         $mode $this->_findMode($remote);
  822.  
  823.         // If native FTP support is enabled let's use it...
  824.         if (FTP_NATIVE)
  825.         {
  826.             // Turn passive mode on
  827.             if (@ftp_pasv($this->_conntrue=== false)
  828.             {
  829.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_READ_BAD_RESPONSE_PASSIVE')JLog::WARNING'jerror');
  830.  
  831.                 return false;
  832.             }
  833.  
  834.             $tmp fopen('buffer://tmp''br+');
  835.  
  836.             if (@ftp_fget($this->_conn$tmp$remote$mode=== false)
  837.             {
  838.                 fclose($tmp);
  839.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_READ_BAD_RESPONSE_BUFFER')JLog::WARNING'jerror');
  840.  
  841.                 return false;
  842.             }
  843.             // Read tmp buffer contents
  844.             rewind($tmp);
  845.             $buffer '';
  846.  
  847.             while (!feof($tmp))
  848.             {
  849.                 $buffer .= fread($tmp8192);
  850.             }
  851.             fclose($tmp);
  852.  
  853.             return true;
  854.         }
  855.  
  856.         $this->_mode($mode);
  857.  
  858.         // Start passive mode
  859.         if (!$this->_passive())
  860.         {
  861.             JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_READ_BAD_RESPONSE_PASSIVE')JLog::WARNING'jerror');
  862.  
  863.             return false;
  864.         }
  865.  
  866.         if (!$this->_putCmd('RETR ' $remotearray(150125)))
  867.         {
  868.             fclose($this->_dataconn);
  869.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_READ_BAD_RESPONSE'$this->_response$remote)JLog::WARNING'jerror');
  870.  
  871.             return false;
  872.         }
  873.  
  874.         // Read data from data port connection and add to the buffer
  875.         $buffer '';
  876.  
  877.         while (!feof($this->_dataconn))
  878.         {
  879.             $buffer .= fread($this->_dataconn4096);
  880.         }
  881.  
  882.         // Close the data port connection
  883.         fclose($this->_dataconn);
  884.  
  885.         // Let's try to cleanup some line endings if it is ascii
  886.         if ($mode == FTP_ASCII)
  887.         {
  888.             $os 'UNIX';
  889.  
  890.             if (IS_WIN)
  891.             {
  892.                 $os 'WIN';
  893.             }
  894.  
  895.             $buffer preg_replace("/" CRLF "/"$this->_lineEndings[$os]$buffer);
  896.         }
  897.  
  898.         if (!$this->_verifyResponse(226))
  899.         {
  900.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_READ_BAD_RESPONSE_TRANSFER'$this->_response$remote)JLog::WARNING'jerror');
  901.  
  902.             return false;
  903.         }
  904.  
  905.         return true;
  906.     }
  907.  
  908.     /**
  909.      * Method to get a file from the FTP server and save it to a local file
  910.      *
  911.      * @param   string  $local   Local path to save remote file to
  912.      * @param   string  $remote  Path to remote file to get on the FTP server
  913.      *
  914.      * @return  boolean  True if successful
  915.      *
  916.      * @since   12.1
  917.      */
  918.     public function get($local$remote)
  919.     {
  920.         // Determine file type
  921.         $mode $this->_findMode($remote);
  922.  
  923.         // If native FTP support is enabled let's use it...
  924.         if (FTP_NATIVE)
  925.         {
  926.             // Turn passive mode on
  927.             if (@ftp_pasv($this->_conntrue=== false)
  928.             {
  929.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_GET_PASSIVE')JLog::WARNING'jerror');
  930.  
  931.                 return false;
  932.             }
  933.  
  934.             if (@ftp_get($this->_conn$local$remote$mode=== false)
  935.             {
  936.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_GET_BAD_RESPONSE')JLog::WARNING'jerror');
  937.  
  938.                 return false;
  939.             }
  940.             return true;
  941.         }
  942.  
  943.         $this->_mode($mode);
  944.  
  945.         // Check to see if the local file can be opened for writing
  946.         $fp fopen($local"wb");
  947.  
  948.         if (!$fp)
  949.         {
  950.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_GET_WRITING_LOCAL'$local)JLog::WARNING'jerror');
  951.  
  952.             return false;
  953.         }
  954.  
  955.         // Start passive mode
  956.         if (!$this->_passive())
  957.         {
  958.             JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_GET_PASSIVE')JLog::WARNING'jerror');
  959.  
  960.             return false;
  961.         }
  962.  
  963.         if (!$this->_putCmd('RETR ' $remotearray(150125)))
  964.         {
  965.             fclose($this->_dataconn);
  966.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_GET_BAD_RESPONSE_RETR'$this->_response$remote)JLog::WARNING'jerror');
  967.  
  968.             return false;
  969.         }
  970.  
  971.         // Read data from data port connection and add to the buffer
  972.         while (!feof($this->_dataconn))
  973.         {
  974.             $buffer fread($this->_dataconn4096);
  975.             fwrite($fp$buffer4096);
  976.         }
  977.  
  978.         // Close the data port connection and file pointer
  979.         fclose($this->_dataconn);
  980.         fclose($fp);
  981.  
  982.         if (!$this->_verifyResponse(226))
  983.         {
  984.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_GET_BAD_RESPONSE_TRANSFER'$this->_response$remote)JLog::WARNING'jerror');
  985.  
  986.             return false;
  987.         }
  988.  
  989.         return true;
  990.     }
  991.  
  992.     /**
  993.      * Method to store a file to the FTP server
  994.      *
  995.      * @param   string  $local   Path to local file to store on the FTP server
  996.      * @param   string  $remote  FTP path to file to create
  997.      *
  998.      * @return  boolean  True if successful
  999.      *
  1000.      * @since   12.1
  1001.      */
  1002.     public function store($local$remote null)
  1003.     {
  1004.         // If remote file is not given, use the filename of the local file in the current
  1005.         // working directory.
  1006.         if ($remote == null)
  1007.         {
  1008.             $remote basename($local);
  1009.         }
  1010.  
  1011.         // Determine file type
  1012.         $mode $this->_findMode($remote);
  1013.  
  1014.         // If native FTP support is enabled let's use it...
  1015.         if (FTP_NATIVE)
  1016.         {
  1017.             // Turn passive mode on
  1018.             if (@ftp_pasv($this->_conntrue=== false)
  1019.             {
  1020.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_STORE_PASSIVE')JLog::WARNING'jerror');
  1021.  
  1022.                 return false;
  1023.             }
  1024.  
  1025.             if (@ftp_put($this->_conn$remote$local$mode=== false)
  1026.             {
  1027.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_STORE_BAD_RESPONSE')JLog::WARNING'jerror');
  1028.  
  1029.                 return false;
  1030.             }
  1031.             return true;
  1032.         }
  1033.  
  1034.         $this->_mode($mode);
  1035.  
  1036.         // Check to see if the local file exists and if so open it for reading
  1037.         if (file_exists($local))
  1038.         {
  1039.             $fp fopen($local"rb");
  1040.  
  1041.             if (!$fp)
  1042.             {
  1043.                 JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_STORE_READING_LOCAL'$local)JLog::WARNING'jerror');
  1044.  
  1045.                 return false;
  1046.             }
  1047.         }
  1048.         else
  1049.         {
  1050.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_STORE_FIND_LOCAL'$local)JLog::WARNING'jerror');
  1051.  
  1052.             return false;
  1053.         }
  1054.  
  1055.         // Start passive mode
  1056.         if (!$this->_passive())
  1057.         {
  1058.             fclose($fp);
  1059.             JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_STORE_PASSIVE')JLog::WARNING'jerror');
  1060.  
  1061.             return false;
  1062.         }
  1063.  
  1064.         // Send store command to the FTP server
  1065.         if (!$this->_putCmd('STOR ' $remotearray(150125)))
  1066.         {
  1067.             fclose($fp);
  1068.             fclose($this->_dataconn);
  1069.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_STORE_BAD_RESPONSE_STOR'$this->_response$remote)JLog::WARNING'jerror');
  1070.  
  1071.             return false;
  1072.         }
  1073.  
  1074.         // Do actual file transfer, read local file and write to data port connection
  1075.         while (!feof($fp))
  1076.         {
  1077.             $line fread($fp4096);
  1078.  
  1079.             do
  1080.             {
  1081.                 if (($result fwrite($this->_dataconn$line)) === false)
  1082.                 {
  1083.                     JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_STORE_DATA_PORT')JLog::WARNING'jerror');
  1084.  
  1085.                     return false;
  1086.                 }
  1087.                 $line substr($line$result);
  1088.             }
  1089.             while ($line != "");
  1090.         }
  1091.  
  1092.         fclose($fp);
  1093.         fclose($this->_dataconn);
  1094.  
  1095.         if (!$this->_verifyResponse(226))
  1096.         {
  1097.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_STORE_BAD_RESPONSE_TRANSFER'$this->_response$remote)JLog::WARNING'jerror');
  1098.  
  1099.             return false;
  1100.         }
  1101.  
  1102.         return true;
  1103.     }
  1104.  
  1105.     /**
  1106.      * Method to write a string to the FTP server
  1107.      *
  1108.      * @param   string  $remote  FTP path to file to write to
  1109.      * @param   string  $buffer  Contents to write to the FTP server
  1110.      *
  1111.      * @return  boolean  True if successful
  1112.      *
  1113.      * @since   12.1
  1114.      */
  1115.     public function write($remote$buffer)
  1116.     {
  1117.         // Determine file type
  1118.         $mode $this->_findMode($remote);
  1119.  
  1120.         // If native FTP support is enabled let's use it...
  1121.         if (FTP_NATIVE)
  1122.         {
  1123.             // Turn passive mode on
  1124.             if (@ftp_pasv($this->_conntrue=== false)
  1125.             {
  1126.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_WRITE_PASSIVE')JLog::WARNING'jerror');
  1127.  
  1128.                 return false;
  1129.             }
  1130.  
  1131.             $tmp fopen('buffer://tmp''br+');
  1132.             fwrite($tmp$buffer);
  1133.             rewind($tmp);
  1134.  
  1135.             if (@ftp_fput($this->_conn$remote$tmp$mode=== false)
  1136.             {
  1137.                 fclose($tmp);
  1138.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_WRITE_BAD_RESPONSE')JLog::WARNING'jerror');
  1139.  
  1140.                 return false;
  1141.             }
  1142.             fclose($tmp);
  1143.  
  1144.             return true;
  1145.         }
  1146.  
  1147.         // First we need to set the transfer mode
  1148.         $this->_mode($mode);
  1149.  
  1150.         // Start passive mode
  1151.         if (!$this->_passive())
  1152.         {
  1153.             JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_WRITE_PASSIVE')JLog::WARNING'jerror');
  1154.  
  1155.             return false;
  1156.         }
  1157.  
  1158.         // Send store command to the FTP server
  1159.         if (!$this->_putCmd('STOR ' $remotearray(150125)))
  1160.         {
  1161.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_WRITE_BAD_RESPONSE_STOR'$this->_response$remote)JLog::WARNING'jerror');
  1162.             fclose($this->_dataconn);
  1163.  
  1164.             return false;
  1165.         }
  1166.  
  1167.         // Write buffer to the data connection port
  1168.         do
  1169.         {
  1170.             if (($result fwrite($this->_dataconn$buffer)) === false)
  1171.             {
  1172.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_WRITE_DATA_PORT')JLog::WARNING'jerror');
  1173.  
  1174.                 return false;
  1175.             }
  1176.             $buffer substr($buffer$result);
  1177.         }
  1178.         while ($buffer != "");
  1179.  
  1180.         // Close the data connection port [Data transfer complete]
  1181.         fclose($this->_dataconn);
  1182.  
  1183.         // Verify that the server recieved the transfer
  1184.         if (!$this->_verifyResponse(226))
  1185.         {
  1186.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_WRITE_BAD_RESPONSE_TRANSFER'$this->_response$remote)JLog::WARNING'jerror');
  1187.  
  1188.             return false;
  1189.         }
  1190.  
  1191.         return true;
  1192.     }
  1193.  
  1194.     /**
  1195.      * Method to list the filenames of the contents of a directory on the FTP server
  1196.      *
  1197.      * Note: Some servers also return folder names. However, to be sure to list folders on all
  1198.      * servers, you should use listDetails() instead if you also need to deal with folders
  1199.      *
  1200.      * @param   string  $path  Path local file to store on the FTP server
  1201.      *
  1202.      * @return  string  Directory listing
  1203.      *
  1204.      * @since   12.1
  1205.      */
  1206.     public function listNames($path null)
  1207.     {
  1208.         $data null;
  1209.  
  1210.         // If native FTP support is enabled let's use it...
  1211.         if (FTP_NATIVE)
  1212.         {
  1213.             // Turn passive mode on
  1214.             if (@ftp_pasv($this->_conntrue=== false)
  1215.             {
  1216.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_LISTNAMES_PASSIVE')JLog::WARNING'jerror');
  1217.  
  1218.                 return false;
  1219.             }
  1220.  
  1221.             if (($list @ftp_nlist($this->_conn$path)) === false)
  1222.             {
  1223.                 // Workaround for empty directories on some servers
  1224.                 if ($this->listDetails($path'files'=== array())
  1225.                 {
  1226.                     return array();
  1227.                 }
  1228.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_LISTNAMES_BAD_RESPONSE')JLog::WARNING'jerror');
  1229.  
  1230.                 return false;
  1231.             }
  1232.             $list preg_replace('#^' preg_quote($path'#''[/\\\\]?#'''$list);
  1233.  
  1234.             if ($keys array_merge(array_keys($list'.')array_keys($list'..')))
  1235.             {
  1236.                 foreach ($keys as $key)
  1237.                 {
  1238.                     unset($list[$key]);
  1239.                 }
  1240.             }
  1241.             return $list;
  1242.         }
  1243.  
  1244.         /*
  1245.          * If a path exists, prepend a space
  1246.          */
  1247.         if ($path != null)
  1248.         {
  1249.             $path ' ' $path;
  1250.         }
  1251.  
  1252.         // Start passive mode
  1253.         if (!$this->_passive())
  1254.         {
  1255.             JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_LISTNAMES_PASSIVE')JLog::WARNING'jerror');
  1256.  
  1257.             return false;
  1258.         }
  1259.  
  1260.         if (!$this->_putCmd('NLST' $patharray(150125)))
  1261.         {
  1262.             fclose($this->_dataconn);
  1263.  
  1264.             // Workaround for empty directories on some servers
  1265.             if ($this->listDetails($path'files'=== array())
  1266.             {
  1267.                 return array();
  1268.             }
  1269.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_LISTNAMES_BAD_RESPONSE_NLST'$this->_response$path)JLog::WARNING'jerror');
  1270.  
  1271.             return false;
  1272.         }
  1273.  
  1274.         // Read in the file listing.
  1275.         while (!feof($this->_dataconn))
  1276.         {
  1277.             $data .= fread($this->_dataconn4096);
  1278.         }
  1279.         fclose($this->_dataconn);
  1280.  
  1281.         // Everything go okay?
  1282.         if (!$this->_verifyResponse(226))
  1283.         {
  1284.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_LISTNAMES_BAD_RESPONSE_TRANSFER'$this->_response$path)JLog::WARNING'jerror');
  1285.  
  1286.             return false;
  1287.         }
  1288.  
  1289.         $data preg_split("/[" CRLF "]+/"$data-1PREG_SPLIT_NO_EMPTY);
  1290.         $data preg_replace('#^' preg_quote(substr($path1)'#''[/\\\\]?#'''$data);
  1291.  
  1292.         if ($keys array_merge(array_keys($data'.')array_keys($data'..')))
  1293.         {
  1294.             foreach ($keys as $key)
  1295.             {
  1296.                 unset($data[$key]);
  1297.             }
  1298.         }
  1299.         return $data;
  1300.     }
  1301.  
  1302.     /**
  1303.      * Method to list the contents of a directory on the FTP server
  1304.      *
  1305.      * @param   string  $path  Path to the local file to be stored on the FTP server
  1306.      * @param   string  $type  Return type [raw|all|folders|files]
  1307.      *
  1308.      * @return  mixed  If $type is raw: string Directory listing, otherwise array of string with file-names
  1309.      *
  1310.      * @since   12.1
  1311.      */
  1312.     public function listDetails($path null$type 'all')
  1313.     {
  1314.         $dir_list array();
  1315.         $data null;
  1316.         $regs null;
  1317.  
  1318.         // TODO: Deal with recurse -- nightmare
  1319.         // For now we will just set it to false
  1320.         $recurse false;
  1321.  
  1322.         // If native FTP support is enabled let's use it...
  1323.         if (FTP_NATIVE)
  1324.         {
  1325.             // Turn passive mode on
  1326.             if (@ftp_pasv($this->_conntrue=== false)
  1327.             {
  1328.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_LISTDETAILS_PASSIVE')JLog::WARNING'jerror');
  1329.  
  1330.                 return false;
  1331.             }
  1332.  
  1333.             if (($contents @ftp_rawlist($this->_conn$path)) === false)
  1334.             {
  1335.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_LISTDETAILS_BAD_RESPONSE')JLog::WARNING'jerror');
  1336.  
  1337.                 return false;
  1338.             }
  1339.         }
  1340.         else
  1341.         {
  1342.             // Non Native mode
  1343.  
  1344.             // Start passive mode
  1345.             if (!$this->_passive())
  1346.             {
  1347.                 JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_LISTDETAILS_PASSIVE')JLog::WARNING'jerror');
  1348.  
  1349.                 return false;
  1350.             }
  1351.  
  1352.             // If a path exists, prepend a space
  1353.             if ($path != null)
  1354.             {
  1355.                 $path ' ' $path;
  1356.             }
  1357.  
  1358.             // Request the file listing
  1359.             if (!$this->_putCmd(($recurse == true'LIST -R' 'LIST' $patharray(150125)))
  1360.             {
  1361.                 JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_LISTDETAILS_BAD_RESPONSE_LIST'$this->_response$path)JLog::WARNING'jerror');
  1362.                 fclose($this->_dataconn);
  1363.  
  1364.                 return false;
  1365.             }
  1366.  
  1367.             // Read in the file listing.
  1368.             while (!feof($this->_dataconn))
  1369.             {
  1370.                 $data .= fread($this->_dataconn4096);
  1371.             }
  1372.             fclose($this->_dataconn);
  1373.  
  1374.             // Everything go okay?
  1375.             if (!$this->_verifyResponse(226))
  1376.             {
  1377.                 JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_LISTDETAILS_BAD_RESPONSE_TRANSFER'$this->_response$path)JLog::WARNING'jerror');
  1378.  
  1379.                 return false;
  1380.             }
  1381.  
  1382.             $contents explode(CRLF$data);
  1383.         }
  1384.  
  1385.         // If only raw output is requested we are done
  1386.         if ($type == 'raw')
  1387.         {
  1388.             return $data;
  1389.         }
  1390.  
  1391.         // If we received the listing of an empty directory, we are done as well
  1392.         if (empty($contents[0]))
  1393.         {
  1394.             return $dir_list;
  1395.         }
  1396.  
  1397.         // If the server returned the number of results in the first response, let's dump it
  1398.         if (strtolower(substr($contents[0]06)) == 'total ')
  1399.         {
  1400.             array_shift($contents);
  1401.  
  1402.             if (!isset($contents[0]|| empty($contents[0]))
  1403.             {
  1404.                 return $dir_list;
  1405.             }
  1406.         }
  1407.  
  1408.         // Regular expressions for the directory listing parsing.
  1409.         $regexps array(
  1410.             'UNIX' => '#([-dl][rwxstST-]+).* ([0-9]*) ([a-zA-Z0-9]+).* ([a-zA-Z0-9]+).* ([0-9]*)'
  1411.                 . ' ([a-zA-Z]+[0-9: ]*[0-9])[ ]+(([0-9]{1,2}:[0-9]{2})|[0-9]{4}) (.+)#',
  1412.             'MAC' => '#([-dl][rwxstST-]+).* ?([0-9 ]*)?([a-zA-Z0-9]+).* ([a-zA-Z0-9]+).* ([0-9]*)'
  1413.                 . ' ([a-zA-Z]+[0-9: ]*[0-9])[ ]+(([0-9]{2}:[0-9]{2})|[0-9]{4}) (.+)#',
  1414.             'WIN' => '#([0-9]{2})-([0-9]{2})-([0-9]{2}) +([0-9]{2}):([0-9]{2})(AM|PM) +([0-9]+|<DIR>) +(.+)#'
  1415.         );
  1416.  
  1417.         // Find out the format of the directory listing by matching one of the regexps
  1418.         $osType null;
  1419.  
  1420.         foreach ($regexps as $k => $v)
  1421.         {
  1422.             if (@preg_match($v$contents[0]))
  1423.             {
  1424.                 $osType $k;
  1425.                 $regexp $v;
  1426.                 break;
  1427.             }
  1428.         }
  1429.         if (!$osType)
  1430.         {
  1431.             JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_LISTDETAILS_UNRECOGNISED')JLog::WARNING'jerror');
  1432.  
  1433.             return false;
  1434.         }
  1435.  
  1436.         /*
  1437.          * Here is where it is going to get dirty....
  1438.          */
  1439.         if ($osType == 'UNIX' || $osType == 'MAC')
  1440.         {
  1441.             foreach ($contents as $file)
  1442.             {
  1443.                 $tmp_array null;
  1444.  
  1445.                 if (@preg_match($regexp$file$regs))
  1446.                 {
  1447.                     $fType = (int) strpos("-dl"$regs[1]{0});
  1448.  
  1449.                     // $tmp_array['line'] = $regs[0];
  1450.                     $tmp_array['type'$fType;
  1451.                     $tmp_array['rights'$regs[1];
  1452.  
  1453.                     // $tmp_array['number'] = $regs[2];
  1454.                     $tmp_array['user'$regs[3];
  1455.                     $tmp_array['group'$regs[4];
  1456.                     $tmp_array['size'$regs[5];
  1457.                     $tmp_array['date'@date("m-d"strtotime($regs[6]));
  1458.                     $tmp_array['time'$regs[7];
  1459.                     $tmp_array['name'$regs[9];
  1460.                 }
  1461.                 // If we just want files, do not add a folder
  1462.                 if ($type == 'files' && $tmp_array['type'== 1)
  1463.                 {
  1464.                     continue;
  1465.                 }
  1466.                 // If we just want folders, do not add a file
  1467.                 if ($type == 'folders' && $tmp_array['type'== 0)
  1468.                 {
  1469.                     continue;
  1470.                 }
  1471.                 if (is_array($tmp_array&& $tmp_array['name'!= '.' && $tmp_array['name'!= '..')
  1472.                 {
  1473.                     $dir_list[$tmp_array;
  1474.                 }
  1475.             }
  1476.         }
  1477.         else
  1478.         {
  1479.             foreach ($contents as $file)
  1480.             {
  1481.                 $tmp_array null;
  1482.  
  1483.                 if (@preg_match($regexp$file$regs))
  1484.                 {
  1485.                     $fType = (int) ($regs[7== '<DIR>');
  1486.                     $timestamp strtotime("$regs[3]-$regs[1]-$regs[2] $regs[4]:$regs[5]$regs[6]");
  1487.  
  1488.                     // $tmp_array['line'] = $regs[0];
  1489.                     $tmp_array['type'$fType;
  1490.                     $tmp_array['rights''';
  1491.  
  1492.                     // $tmp_array['number'] = 0;
  1493.                     $tmp_array['user''';
  1494.                     $tmp_array['group''';
  1495.                     $tmp_array['size'= (int) $regs[7];
  1496.                     $tmp_array['date'date('m-d'$timestamp);
  1497.                     $tmp_array['time'date('H:i'$timestamp);
  1498.                     $tmp_array['name'$regs[8];
  1499.                 }
  1500.                 // If we just want files, do not add a folder
  1501.                 if ($type == 'files' && $tmp_array['type'== 1)
  1502.                 {
  1503.                     continue;
  1504.                 }
  1505.                 // If we just want folders, do not add a file
  1506.                 if ($type == 'folders' && $tmp_array['type'== 0)
  1507.                 {
  1508.                     continue;
  1509.                 }
  1510.                 if (is_array($tmp_array&& $tmp_array['name'!= '.' && $tmp_array['name'!= '..')
  1511.                 {
  1512.                     $dir_list[$tmp_array;
  1513.                 }
  1514.             }
  1515.         }
  1516.  
  1517.         return $dir_list;
  1518.     }
  1519.  
  1520.     /**
  1521.      * Send command to the FTP server and validate an expected response code
  1522.      *
  1523.      * @param   string  $cmd               Command to send to the FTP server
  1524.      * @param   mixed   $expectedResponse  Integer response code or array of integer response codes
  1525.      *
  1526.      * @return  boolean  True if command executed successfully
  1527.      *
  1528.      * @since   12.1
  1529.      */
  1530.     protected function _putCmd($cmd$expectedResponse)
  1531.     {
  1532.         // Make sure we have a connection to the server
  1533.         if (!is_resource($this->_conn))
  1534.         {
  1535.             JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_PUTCMD_UNCONNECTED')JLog::WARNING'jerror');
  1536.  
  1537.             return false;
  1538.         }
  1539.  
  1540.         // Send the command to the server
  1541.         if (!fwrite($this->_conn$cmd "\r\n"))
  1542.         {
  1543.             JLog::add(JText::sprintf('DDD'JText::sprintf('JLIB_CLIENT_ERROR_JFTP_PUTCMD_SEND'$cmd))JLog::WARNING'jerror');
  1544.         }
  1545.  
  1546.         return $this->_verifyResponse($expectedResponse);
  1547.     }
  1548.  
  1549.     /**
  1550.      * Verify the response code from the server and log response if flag is set
  1551.      *
  1552.      * @param   mixed  $expected  Integer response code or array of integer response codes
  1553.      *
  1554.      * @return  boolean  True if response code from the server is expected
  1555.      *
  1556.      * @since   12.1
  1557.      */
  1558.     protected function _verifyResponse($expected)
  1559.     {
  1560.         $parts null;
  1561.  
  1562.         // Wait for a response from the server, but timeout after the set time limit
  1563.         $endTime time($this->_timeout;
  1564.         $this->_response '';
  1565.  
  1566.         do
  1567.         {
  1568.             $this->_response .= fgets($this->_conn4096);
  1569.         }
  1570.         while (!preg_match("/^([0-9]{3})(-(.*" CRLF ")+\\1)? [^" CRLF "]+" CRLF "$/"$this->_response$parts&& time($endTime);
  1571.  
  1572.         // Catch a timeout or bad response
  1573.         if (!isset($parts[1]))
  1574.         {
  1575.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_VERIFYRESPONSE'$this->_response)JLog::WARNING'jerror');
  1576.  
  1577.             return false;
  1578.         }
  1579.  
  1580.         // Separate the code from the message
  1581.         $this->_responseCode $parts[1];
  1582.         $this->_responseMsg $parts[0];
  1583.  
  1584.         // Did the server respond with the code we wanted?
  1585.         if (is_array($expected))
  1586.         {
  1587.             if (in_array($this->_responseCode$expected))
  1588.             {
  1589.                 $retval true;
  1590.             }
  1591.             else
  1592.             {
  1593.                 $retval false;
  1594.             }
  1595.         }
  1596.         else
  1597.         {
  1598.             if ($this->_responseCode == $expected)
  1599.             {
  1600.                 $retval true;
  1601.             }
  1602.             else
  1603.             {
  1604.                 $retval false;
  1605.             }
  1606.         }
  1607.         return $retval;
  1608.     }
  1609.  
  1610.     /**
  1611.      * Set server to passive mode and open a data port connection
  1612.      *
  1613.      * @return  boolean  True if successful
  1614.      *
  1615.      * @since   12.1
  1616.      */
  1617.     protected function _passive()
  1618.     {
  1619.         $match array();
  1620.         $parts array();
  1621.         $errno null;
  1622.         $err null;
  1623.  
  1624.         // Make sure we have a connection to the server
  1625.         if (!is_resource($this->_conn))
  1626.         {
  1627.             JLog::add(JText::_('JLIB_CLIENT_ERROR_JFTP_PASSIVE_CONNECT_PORT')JLog::WARNING'jerror');
  1628.  
  1629.             return false;
  1630.         }
  1631.  
  1632.         // Request a passive connection - this means, we'll talk to you, you don't talk to us.
  1633.         fwrite($this->_conn"PASV\r\n");
  1634.  
  1635.         // Wait for a response from the server, but timeout after the set time limit
  1636.         $endTime time($this->_timeout;
  1637.         $this->_response '';
  1638.  
  1639.         do
  1640.         {
  1641.             $this->_response .= fgets($this->_conn4096);
  1642.         }
  1643.         while (!preg_match("/^([0-9]{3})(-(.*" CRLF ")+\\1)? [^" CRLF "]+" CRLF "$/"$this->_response$parts&& time($endTime);
  1644.  
  1645.         // Catch a timeout or bad response
  1646.         if (!isset($parts[1]))
  1647.         {
  1648.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_PASSIVE_RESPONSE'$this->_response)JLog::WARNING'jerror');
  1649.  
  1650.             return false;
  1651.         }
  1652.  
  1653.         // Separate the code from the message
  1654.         $this->_responseCode $parts[1];
  1655.         $this->_responseMsg $parts[0];
  1656.  
  1657.         // If it's not 227, we weren't given an IP and port, which means it failed.
  1658.         if ($this->_responseCode != '227')
  1659.         {
  1660.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_PASSIVE_IP_OBTAIN'$this->_responseMsg)JLog::WARNING'jerror');
  1661.  
  1662.             return false;
  1663.         }
  1664.  
  1665.         // Snatch the IP and port information, or die horribly trying...
  1666.         if (preg_match('~\((\d+),\s*(\d+),\s*(\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))\)~'$this->_responseMsg$match== 0)
  1667.         {
  1668.             JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_PASSIVE_IP_VALID'$this->_responseMsg)JLog::WARNING'jerror');
  1669.  
  1670.             return false;
  1671.         }
  1672.  
  1673.         // This is pretty simple - store it for later use ;).
  1674.         $this->_pasv array('ip' => $match[1'.' $match[2'.' $match[3'.' $match[4]'port' => $match[5256 $match[6]);
  1675.  
  1676.         // Connect, assuming we've got a connection.
  1677.         $this->_dataconn @fsockopen($this->_pasv['ip']$this->_pasv['port']$errno$err$this->_timeout);
  1678.  
  1679.         if (!$this->_dataconn)
  1680.         {
  1681.             JLog::add(
  1682.                 JText::sprintf('JLIB_CLIENT_ERROR_JFTP_PASSIVE_CONNECT'$this->_pasv['ip']$this->_pasv['port']$errno$err),
  1683.                 JLog::WARNING,
  1684.                 'jerror'
  1685.             );
  1686.  
  1687.             return false;
  1688.         }
  1689.  
  1690.         // Set the timeout for this connection
  1691.         socket_set_timeout($this->_conn$this->_timeout0);
  1692.  
  1693.         return true;
  1694.     }
  1695.  
  1696.     /**
  1697.      * Method to find out the correct transfer mode for a specific file
  1698.      *
  1699.      * @param   string  $fileName  Name of the file
  1700.      *
  1701.      * @return  integer Transfer-mode for this filetype [FTP_ASCII|FTP_BINARY]
  1702.      *
  1703.      * @since   12.1
  1704.      */
  1705.     protected function _findMode($fileName)
  1706.     {
  1707.         if ($this->_type == FTP_AUTOASCII)
  1708.         {
  1709.             $dot strrpos($fileName'.'1;
  1710.             $ext substr($fileName$dot);
  1711.  
  1712.             if (in_array($ext$this->_autoAscii))
  1713.             {
  1714.                 $mode FTP_ASCII;
  1715.             }
  1716.             else
  1717.             {
  1718.                 $mode FTP_BINARY;
  1719.             }
  1720.         }
  1721.         elseif ($this->_type == FTP_ASCII)
  1722.         {
  1723.             $mode FTP_ASCII;
  1724.         }
  1725.         else
  1726.         {
  1727.             $mode FTP_BINARY;
  1728.         }
  1729.         return $mode;
  1730.     }
  1731.  
  1732.     /**
  1733.      * Set transfer mode
  1734.      *
  1735.      * @param   integer  $mode  Integer representation of data transfer mode [1:Binary|0:Ascii]
  1736.      *  Defined constants can also be used [FTP_BINARY|FTP_ASCII]
  1737.      *
  1738.      * @return  boolean  True if successful
  1739.      *
  1740.      * @since   12.1
  1741.      */
  1742.     protected function _mode($mode)
  1743.     {
  1744.         if ($mode == FTP_BINARY)
  1745.         {
  1746.             if (!$this->_putCmd("TYPE I"200))
  1747.             {
  1748.                 JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_MODE_BINARY'$this->_response)JLog::WARNING'jerror');
  1749.  
  1750.                 return false;
  1751.             }
  1752.         }
  1753.         else
  1754.         {
  1755.             if (!$this->_putCmd("TYPE A"200))
  1756.             {
  1757.                 JLog::add(JText::sprintf('JLIB_CLIENT_ERROR_JFTP_MODE_ASCII'$this->_response)JLog::WARNING'jerror');
  1758.  
  1759.                 return false;
  1760.             }
  1761.         }
  1762.         return true;
  1763.     }
  1764. }
  1765.  
  1766. /**
  1767.  * Deprecated class placeholder. You should use JClientFtp instead.
  1768.  *
  1769.  * @package     Joomla.Platform
  1770.  * @subpackage  Client
  1771.  * @since       11.1
  1772.  * @deprecated  12.3 (Platform) & 4.0 (CMS)
  1773.  */
  1774. class JFTP extends JClientFtp
  1775. {
  1776.     /**
  1777.      * JFTP object constructor
  1778.      *
  1779.      * @param   array  $options  Associative array of options to set
  1780.      *
  1781.      * @since   11.1
  1782.      */
  1783.     public function __construct(array $options array())
  1784.     {
  1785.         JLog::add('JFTP is deprecated. Use JClientFtp instead.'JLog::WARNING'deprecated');
  1786.         parent::__construct($options);
  1787.     }
  1788. }

Documentation generated on Tue, 19 Nov 2013 15:03:56 +0100 by phpDocumentor 1.4.3