| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 | <?php/** * An FTP transfer wrapper using the OSInet Finite_State_Machine * * @copyright  (c) 2007 OSI * @author     Frédéric G. MARAND * @license    Licensed under the CeCILL 2.0 * @version    CVS: $Id: Ftp_Client.php,v 1.3 2007-06-10 19:39:54 marand Exp $ * @link * @since      Not applicable yet * @package    osinetoffice * @subpackage bo_up_ingram * *//** * Save current reporting level while we set it */$_ftpEr = error_reporting(E_ALL | E_STRICT);/** * Class implements a finite-state-machine-based * FTP client with *very* limited functionality, * but that can display progress information * states are: * - init: not yet set up * - offline: no link established * - online: client connected to server * - live: client connected and logged in * - active: a data transfer operation is under way * - unsafe: something failed, disconnect can happen out of our control * * @package    osinetoffice * @subpackage bo_up_ingram */class Ftp_Client extends Finite_State_Machine  {  /**   * Code currently depends on the actual FSM location. Future versions should   * probably locate it on their own.   */  const FTP_FSM = 'e:/src/osinetoffice/lib/Ftp.xml';  /**   * remote properties   */  private $fRemoteFile;  private $fRemoteHost;  private $fRemotePass;  private $fRemoteUser;  private $fRemoteWd;  /**   * local properties   */  private $fLocalWd;  private $fLocalFile;  private $fLocalFp;       // file pointer to local file, used in get/put/continue  /**   * FTP properties   */  private $fFtpCallback;   // name of callback function for progress information  private $fFtpGoal;       // bytes to be transferred  private $fFtpConnection; // connection  /**   * Initialize parameters from an array   *   * @todo should really check names and values.   * @param array $params   * @return Fsm_Result   */  public function setParameters($params)    {    foreach ($params as $name => $value)      {      $field_name = "f$name";      $this->$field_name = $value;      }    $ret = $this->apply_event('CheckParameters');    return $ret;    }  /**   * ============ utility functions ============   */  /**   * format a boolean value as a string   *   * @param boolean $val   * @return string   */  static function stringFromBoolean($val)    {    return $val ? 'true' : 'false';    }  /**   * Enter description here...   *   * @param unknown_type $status   * @return unknown   */  static function stringFromFtp($status)    {    switch ($status)      {      case FTP_FINISHED: $ret = 'FTP_FINISHED'; break;      case FTP_MOREDATA: $ret = 'FTP_MOREDATA'; break;      case FTP_FAILED:   $ret = 'FTP_MOREDATA'; break;      default:           $ret = 'FTP_INVALID_STATUS'; break;      }    return $ret;    }  /**   * ============ event handlers ============   */  /**   * implement change remote directory   * @return string (boolean)   */  protected function eventChdir()    {    $ret = ftp_chdir($this->fFtpConnection, $this->fRemoteWd);    return ftp_client::stringFromBoolean($ret);    }  /**   * does the instance have all necessary info for a FTP transfer ?   *   * @return string (boolean)   */  public function eventCheckParameters()    {    $ret = isset($this->fRemoteHost)      && isset($this->fRemoteUser)      && isset($this->fRemotePass)      && isset($this->fRemoteWd)      && isset($this->fRemoteFile)      && isset($this->fLocalWd)      && isset($this->fLocalFile)      && isset($this->fFtpCallback)      ;    $ret = ftp_client::stringFromBoolean($ret);    // echo func_name() . ", ret = $ret\n";    return $ret;    }  /**   * implementation of Close event   *   * @return string (boolean)   */  protected function eventClose()    {    $ret = 'true';    // echo "Trying to close socket...";    if (is_resource($this->fFtpConnection))      {      try        {        // echo "Trying to close connection...";        ftp_close($this->fFtpConnection);        // echo "Done.";        }      catch (Exception $e)        {        print_r($e);        $ret = 'false';        }      }    // echo "Socket closed\n";    return $ret;    }  /**   * implementation of Connect event   *   * @return string (boolean)   */  protected function eventConnect()    {    // echo func_name() . "\n";    $this->fFtpConnection = ftp_connect($this->fRemoteHost); // default port, default timeout    $ret = is_resource($this->fFtpConnection);    return Ftp_Client::stringFromBoolean($ret);    }  /**   * implementation of continue   * @return string FTP_FINISHED | FTP_MOREDATA | FTP_FAILED   */  protected function eventContinue()    {    // echo func_name();    if ($this->fFtpCallback)      {      call_user_func($this->fFtpCallback, $this, 'pre');      }    $ret = ftp_nb_continue($this->fFtpConnection);    if ($ret == FTP_FINISHED)      {      fclose($this->fLocalFp);      }    if ($this->fFtpCallback)      call_user_func($this->fFtpCallback, $this, 'post');    $ret = Ftp_Client::stringFromFtp($ret);    return $ret;    }  /**   * implementation of get   *   * @return string FTP_FINISHED | FTP_MOREDATA | FTP_FAILED   * @throws Exception fail creating local file   */  protected function eventGet()    {    // echo func_name() . "\n";    $this->fLocalFp = fopen($this->fLocalFile, "wb");    if (!is_resource($this->fLocalFp))      {      $ret = Ftp_Client::stringFromFtp(FTP_FAILED);      // throw new Exception(func_name() . ": could not create local file $this->fLocalFile");      return $ret;      }    $this->fFtpGoal = ftp_size($this->fFtpConnection, $this->fRemoteFile);    $ret = ftp_nb_fget($this->fFtpConnection, $this->fLocalFp,      $this->fRemoteFile, FTP_BINARY);    if ($ret == FTP_FINISHED)      {      fclose($this->fLocalFp);      }    call_user_func($this->fFtpCallback, $this, 'post');    // echo func_name() . " => $ret\n"; flush();    return Ftp_Client::stringFromFtp($ret);    }  /**   * implementation of login   * @return string (boolean)   */  protected function eventLogin()    {    // echo func_name() . "\n";    $ret = ftp_login($this->fFtpConnection, $this->fRemoteUser, $this->fRemotePass);    return Ftp_Client::stringFromBoolean($ret);    }  /**   * handler must be implemented, but does nothing   * @return void   */  protected function eventProgress()    {    return; // the FSM needs nothing for this    }  /**   * @return void   */  public function __construct()    {    $this->load_fsm(Ftp_Client::FTP_FSM);    // print_r($this->f_transitions);    parent::__construct();    // print_r($this);die();    }  /**   * close connection if it hasn't been done, to prevent connection   * lingering on the server if avoidable   * @return void   */  public function __destruct()    {    // echo func_name() . PHP_EOL;    if ($this->is_event_allowed('Close'))      {      $this->apply_event('Close');      }    if(is_resource($this->fLocalFp))      try        {        echo "Trying to close file...";        fclose($this->fLocalFp);        echo "Done\n";        }      catch (Exception $e)        {        print_r($e);        }    // echo "End of " . func_name() . "\n";    }  /**   * Make sure name can be resolved   * ignore hosts that don't resolve in DNS or hosts file   *   * @param string $host   * @return boolean   */  public function isHostValid($host = null)    {    $ret = is_array(gethostbynamel($host));    return $ret;    }  /**   * If a transfer is under way, return the progress percentile, otherwise 0.0   *   * @return float   */  public function getProgress()    {    if ((!$this->f_state == 'active') || (!is_resource($this->fLocalFp)))      {      $ret = 0.0;      }    else      {      $pos = ftell($this->fLocalFp);      $ret = $pos / $this->fFtpGoal;      }    return $ret;    }  }/** * Restore previous reporting level */error_reporting($_ftpEr);
 |