Back to FtpClient class

Method _passive

protected bool
_passive
()
Set server to passive mode and open a data port connection
Returns
  • bool True if successful
Since
  • 1.5
Class: FtpClient
Project: Joomla

Method _passive - Source code

/**
 * Set server to passive mode and open a data port connection
 *
 * @return  boolean  True if successful
 *
 * @since   1.5
 */
protected function _passive()
{
    $match = array();
    $parts = array();
    $errno = null;
    $err = null;
    // Make sure we have a connection to the server
    if (!\is_resource($this->_conn)) {
        Log::add(Text::sprintf('JLIB_CLIENT_ERROR_FTP_NO_CONNECT', __METHOD__), Log::WARNING, 'jerror');
        return false;
    }
    // Request a passive connection - this means, we'll talk to you, you don't talk to us.
    @fwrite($this->_conn, "PASV\r\n");
    // Wait for a response from the server, but timeout after the set time limit
    $endTime = time() + $this->_timeout;
    $this->_response = '';
    do {
        $this->_response .= fgets($this->_conn, 4096);
    } while (!preg_match('/^([0-9]{3})(-(.*' . CRLF . ')+\\1)? [^' . CRLF . ']+' . CRLF . "\$/", $this->_response, $parts) && time() < $endTime);
    // Catch a timeout or bad response
    if (!isset($parts[1])) {
        Log::add(Text::sprintf('JLIB_CLIENT_ERROR_FTP_TIMEOUT', __METHOD__, $this->_response), Log::WARNING, 'jerror');
        return false;
    }
    // Separate the code from the message
    $this->_responseCode = $parts[1];
    $this->_responseMsg = $parts[0];
    // If it's not 227, we weren't given an IP and port, which means it failed.
    if ($this->_responseCode != '227') {
        Log::add(Text::sprintf('JLIB_CLIENT_ERROR_FTP_PASSIVE_IP_OBTAIN', __METHOD__, $this->_responseMsg), Log::WARNING, 'jerror');
        return false;
    }
    // Snatch the IP and port information, or die horribly trying...
    if (preg_match('~\\((\\d+),\\s*(\\d+),\\s*(\\d+),\\s*(\\d+),\\s*(\\d+)(?:,\\s*(\\d+))\\)~', $this->_responseMsg, $match) == 0) {
        Log::add(Text::sprintf('JLIB_CLIENT_ERROR_FTP_PASSIVE_IP_VALID', __METHOD__, $this->_responseMsg), Log::WARNING, 'jerror');
        return false;
    }
    // This is pretty simple - store it for later use ;).
    $this->_pasv = array('ip' => $match[1] . '.' . $match[2] . '.' . $match[3] . '.' . $match[4], 'port' => $match[5] * 256 + $match[6]);
    // Connect, assuming we've got a connection.
    $this->_dataconn = @fsockopen($this->_pasv['ip'], $this->_pasv['port'], $errno, $err, $this->_timeout);
    if (!$this->_dataconn) {
        Log::add(Text::sprintf('JLIB_CLIENT_ERROR_FTP_NO_CONNECT', __METHOD__, $this->_pasv['ip'], $this->_pasv['port'], $errno, $err), Log::WARNING, 'jerror');
        return false;
    }
    // Set the timeout for this connection
    socket_set_timeout($this->_conn, $this->_timeout, 0);
    return true;
}