views:

177

answers:

2

I'm trying to access an FTP server from my PHP script using Codeigniter's FTP Library. These functions work great, but when testing the script I discovered that if I attempt to connect to a server that does not exist, the script does not terminate with an error message of any kind.

The page continues to execute, until the web server gives up, returning an empty document.

So I am wondering, is there a way to limit the amount of time that Codeigniter can try to connect to an FTP server, then display a message if that times out?

I tried using the php function set_time_limit(), but it does not behave how I expected it to.

Thanks for your help.

A: 

The answer is simple, don't attempt to connect to a server that doesn't exist.

Josh K
well yes, that would be sensible, but is there simply no way for me to trap this error?how about a way to check that the server exists before i attempt to connect to it?
Jack Hayter
-1 in a perfect world a programmer could assume that the user can be trusted to enter correct information. But... that never happens. Always prepare for the worst.
gruntled
I don't know, maybe [ping](http://www.dynamicdrive.com/forums/showthread.php?t=37370) it? There are creative ways to work around this issue. I'm **not** saying *trust the user*, I'm saying *validate before you attempt to connect*.
Josh K
Validation is the single most important thing for my app. I did find a nice little script to ping the server before attempting an FTP connection, but it added an extra couple of seconds to execution time that were not really nescessary if the server was in fact, up.The solution provided by Maurice works great. A nice little extension to the library. Strange how CI does not use that extra parameter of the built in php ftp functions!Thanks for your help guys.
Jack Hayter
+1  A: 

Codeigniter's ftp class uses the underlying ftp_connect php call that supports a 3rd optional parameter, timeout (http://ca2.php.net/manual/en/function.ftp-connect.php).

Codeigniter however does not use it, but allows for extending the default libraries it provides (providing that you're willing to do some work and check that any updates you do to the core will not break the functionality of your extended class). So to solve your problem you could create a new library in you application library folder:

<?php

class MY_FTP extends CI_FTP { //Assuming that in your config.php file, your subclass prefix is set to 'MY_' like so: $config['subclass_prefix'] = 'MY_';

    var $timeout = 90;
    /**
     * FTP Connect
     *
     * @access  public
     * @param   array    the connection values
     * @return  bool
     */
    function connect($config = array())
    {
        if (count($config) > 0)
        {
            $this->initialize($config);
        }

        if (FALSE === ($this->conn_id = ftp_connect($this->hostname, $this->port, $this->timeout)))
        {
            if ($this->debug == TRUE)
            {
                $this->_error('ftp_unable_to_connect');
            }
            return FALSE;
        }

        if ( ! $this->_login())
        {
            if ($this->debug == TRUE)
            {
                $this->_error('ftp_unable_to_login');
            }
            return FALSE;
        }

        // Set passive mode if needed
        if ($this->passive == TRUE)
        {
            ftp_pasv($this->conn_id, TRUE);
        }

        return TRUE;
    }
}
?>

and from your script, you could add to your configuration array the timeout option:

$this->load->library('ftp'); //if ftp is not autoloaded
$ftp_params = array('hostname'=>'1.2.3.4', 'port'=>21, 'timeout'=>10); //timout is 10 seconds instead of default 90
$ftp_conn = $this->ftp->connect($ftp_params);
if(FALSE === $ftp_conn) {
//Code to handle error
}

The ftp class is not designed to give error messages unless the debug parameter is set to TRUE in te config array, in which case it'll just display an error. However it can also be override, because all errors call the function _error() in the class. So you could set 'debug' => true in your $ftp_params array, and add a function in MY_ftp like so:

/**
 * This function overrides 
 */
function _error($line)
{
    $this->error = $line;
}

And then have a function getError() /** * This function overrides */ function get_error() { return $this->error; }

So if

$ftp_conn = $this->ftp->connect($ftp_params);

returns false, you can call

$error = $this->ftp->get_error();

to get your error and display it. Now, you can always customize and have a more complex error handling mechanism by further customizing the class...

Hope it answers your question.

Maurice Kherlakian
Wow! Thanks Maurice!That worked perfectly.That was supprisingly simple actually. Why on earth does CI not use that option by default? strage....Thanks a lot for your help :D
Jack Hayter
You're welcome! glad I could help :)
Maurice Kherlakian