set_url($url); $this->fTransitions = array( 'init' => array( 'check_params' => array( true => 'offline', false => 'init', ), 'set_progress' => array( true => 'offline', false => 'offline', ), ), 'offline' => array( 'check_params' => array( true => 'offline', false => 'init', ), 'connect' => array ( true => 'online', false => 'unsafe', ), 'set_progress' => array( true => 'offline', false => 'offline', ), ), 'online' => array( 'close' => array( true => 'offline', false => 'unsafe', ), 'login' => array( true => 'live', false => 'unsafe', ), ), 'live' => array( 'close' => array( true => 'offline', false => 'unsafe', ), 'chdir' => array( true => 'live', false => 'unsafe', ), 'get' => array( FTP_FINISHED => 'live', FTP_FAILED => 'unsafe', FTP_MOREDATA => 'active', ), 'put' => array( FTP_FINISHED => 'live', FTP_FAILED => 'unsafe', FTP_MOREDATA => 'active', ), ), 'active' => array( 'close' => array( true => 'offline', false => 'unsafe', ), 'continue' => array( FTP_FINISHED => 'live', FTP_FAILED => 'unsafe', FTP_MOREDATA => 'active', ), ), 'unsafe' => array(), /** * no transition allowed * Even retrying connect would not be safe * Must destruct */ ); parent::__construct(); } /** * close connection if it hasn't been done, to prevent connection * lingering on the server if avoidable * @return void */ public function __destruct() { if ($this->is_event_allowed('close')) $this->f_close(); if (is_resource($this->f_fp)) { try { fclose($this->f_fp); } catch (Exception $e) { print_r($e); } } } /** * setter for f_host. Make sur name can be resolved * * @param string $host * @return ftp_client */ public function set_host($host = null) { /** * ignore hosts that don't resolve in DNS */ if (is_array(gethostbynamel($host))) $this->f_host = $host; else throw new Exception(func_name() . ": cannot resolve host name \"$host\""); $this->applyEvent('check_params'); return $this; } /** * setter for f_user * * @param string $user * @return ftp_client */ public function set_user($user = 'anonymous') { $this->f_user = $user; $this->applyEvent('check_params'); return $this; } /** * setter for f_pass * * @param string $pass * @return ftp_client */ public function set_pass($pass = null) { $this->f_pass = $pass; $this->applyEvent('check_params'); return $this; } /** * callback is invoked at the end of get, put * and before and after continue * * @param string $callback */ public function set_callback($callback) { if ($callback && !function_exists($callback)) throw new Exception(func_name() . ": cannot use undefined function $callback as callback"); else $this->f_callback = $callback; /** * this setter does not cause a state change, so no call to applyEvent */ return $this; } /** * implement change remote directory * @return boolean */ protected function f_chdir() { $ret = ftp_chdir($this->f_conn, $this->f_pwd); return $ret; } /** * change remote directory * * @param string $pwd * @return boolean */ public function chdir($pwd = null) { $this->f_pwd = $pwd; $ret = $this->applyEvent('chdir'); return $ret; } /** * setter for f_file * * @param string $file * @return ftp_client */ public function set_file($file = null) { $this->f_file = $file; if (!isset($this->f_localfile)) $this->f_localfile = $file; $this->applyEvent('check_params'); return $this; } /** * setter for f_localfile * * @param string $file * @return ftp_client */ public function set_localfile($file = null) { $this->f_localfile = $file; $this->applyEvent('check_params'); return $this; } /** * does the instance have all necessary info for a FTP transfer ? * * @return boolean */ protected function f_check_params() { $ret = isset($this->f_host) && isset($this->f_user) && isset($this->f_pass) && isset($this->f_file) && isset($this->f_localfile) ; // echo func_name() . ", ret = " . ($ret ? 'TRUE' : 'FALSE') . PHP_EOL; return $ret; } /** * implementation of connect * * @return boolean */ protected function f_connect() { // echo func_name() . "\n"; $this->f_conn = ftp_connect($this->f_host); // default port, default timeout $ret = is_resource($this->f_conn); return $ret; } /** * implementation of close * @return boolean */ protected function f_close() { // echo func_name() . "\n"; $ret = ftp_close($this->f_conn); return $ret; } /** * implementation of login * @return boolean */ protected function f_login() { // echo func_name() . "\n"; $ret = ftp_login($this->f_conn, $this->f_user, $this->f_pass); return $ret; } /** * implementation of get * * @return int FTP_FINISHED | FTP_MOREDATA | FTP_FAILED */ protected function f_get() { // echo func_name() . "\n"; $this->f_fp = fopen($this->f_localfile, "wb"); if (!is_resource($this->f_fp)) { $ret = FTP_FAILED; throw new Exception(func_name() . ": could not create local file $this->f_file"); } $this->f_goal = ftp_size($this->f_conn, $this->f_file); $ret = ftp_nb_fget($this->f_conn, $this->f_fp, $this->f_file, FTP_BINARY); if ($ret == FTP_FINISHED) fclose($this->f_fp); call_user_func($this->f_callback, $this, 'post'); return $ret; } /** * implementation of continue * @return int FTP_FINISHED | FTP_MOREDATA | FTP_FAILED */ protected function f_continue() { if ($this->f_callback) call_user_func($this->f_callback, $this, 'pre'); $ret = ftp_nb_continue($this->f_conn); if ($ret == FTP_FINISHED) fclose($this->f_fp); if ($this->f_callback) call_user_func($this->f_callback, $this, 'post'); return $ret; } /** * interface to connect * @return void */ public function connect() { // echo func_name() . "\n"; return $this->applyEvent('connect'); } /** * interface to login * * @return boolean */ public function login() { // echo func_name() . "\n"; return $this->applyEvent('login'); } /** * interface to close * * @return boolean */ public function close() { // echo func_name() . "\n"; return $this->applyEvent('close'); } /** * get a file using previously defined parameters * @return int FTP_FAILED | FTP_MOREDATA | FTP_FINISHED */ public function get() { // echo func_name() . "\n"; return $this->applyEvent('get'); } /** * continue a current transfer * * @param string $callback name of function to be called before and after * @return int FTP_FINISHED | FTP_MOREDATA | FTP_FAILED */ // continue is a php reserved word public function cont() { // echo func_name() . "\n"; $ret = $this->applyEvent('continue'); $ret = $ret->fsmState; return $ret; } public function get_progress() { if ((!$this->fState == 'active') || (!is_resource($this->f_fp))) $ret = 0; else { $pos = ftell($this->f_fp); $ret = $pos / $this->f_goal; } return $ret; } /* missing: put*/ }