FTP Klasse

  • Themenstarter Themenstarter Bgag
  • Beginndatum Beginndatum
B

Bgag

Morgen!
Habe mich mal wieder an die Klasse gesetzt und habe auch in der Grundstruktur noch einige Änderungen vor genommen. Allerdings will es nun nicht ganz so laufen, wie ich das möchte. Findet vielleicht jemand von euch den Fehler? Bin echt ein bisschen am Verzweifeln.
PHP:
<pre>

<?php  
error_reporting(E_ALL);

/* The FtpConnect class */
class FtpConnect
{
	// public class variables
	protected $host; 
	protected $port;
	
	protected $ctrlCon;
	protected $dataCon;
	
	protected $response;
	
	public $logStats = 0;

	/**
	* Constructor - Is called when the class is instanced
	*
	* @name: FtpConnect::__construct()
	* @access: public
	* @param Str $host
	* @param Int $port
	* @param Str $name
	* @param Str $pwd
	* @return NONE
	*/
	public function __construct($host='localhost', $port=21, $user, $pwd)
	{
		// control-connection handle is save to $ctrlCon
		$this->ctrlCon = @fsockopen($host, $port);
		
		// switch to non-blocking mode - just return data no response
		// @set_socket_blocking($this->ctrlCon, false);
		
		// set timeout of the ctrlCon
		@stream_set_timeout($this->ctrlCon, 0, 3600); 
		
		if($this->ctrlCon)
		{   			
			// send username to the server
			$this->sendCmd("USER $user");
			if ($this->valid()) continue;
					
			// send password to the server
			$this->sendCmd("PASS $pwd");
			if ($this->valid()) continue;
			
			// set type of data
			$this->sendCmd("TYPE I");   
		}
		else  throw new Exception("Connection failed.");   
	}

	/**
	* Destructor - Is called when the instance of the class is closed
	*
	* @name: FtpConnect::__destruct()
	* @access: public
	* @return NONE
	*/
	public function __destruct()
	{
		if($this->ctrlCon)
		{
			$this->sendCmd("QUIT");
			fclose($this->ctrlCon);
		}
	}		
	
	/**
	* Opens connection in passive mode for file transferes
	*
	* @name: FtpConnect::getReply()
	* @access: public
	* @return boolean
	*/
	public function getReply()
	{
		// get response from ftp-connection
		$reply = stream_get_contents($this->ctrlCon);
				
		$this->log($reply);
		
		return $reply;
	}

	/**
	* Checks if the response of a command is ok
	*
	* @name: FtpConnect::valid()
	* @param Sting $reply
	* @access: public
	* @return mixed
	*/
	public function valid()
	{
		// get response of the server
		$this->response = $this->getReply();
		
		// check the response and say if everything is allright
		return (empty($this->response) || preg_match('/^[5]/', $this->response)) ? false : true;
	}

	/**
	* Sets a ftp-command given by the user
	*
	* @name: FtpConnect::sendCmd()
	* @param Sting $command
	* @access: public
	* @return boolean
	*/
	public function sendCmd($command)
	{
		fwrite($this->ctrlCon, "$command\r\n");
		$this->log("&gt; $command");
	}
	
	/**
	* Lists the directory $path
	*
	* @name: FtpConnect::listPath()
	* @access: public
	* @return boolean
	*/
	public function listPath($path = "")
	{
		// initiate the cariable to save the listing of $path
		$list = "";
		if($this->pasv())
		{
			if(empty($path))
			{
				// ask for listing
				$this->sendCmd("LIST");
			}
			
			else
			{	
				// ask for listing of $path
				$this->sendCmd("LIST $path");
			}
			
			if($this->valid())
			{
				// save response from server to $list
				while(true)
				{
					$line = fgets($this->dataCon);
					$list .= $line;
					if($line =='')
						break;
				}
			}
		}
		
		return $list;
	}
	
	/**
	* Opens connection in passive mode for file transferes
	* so now there are two connections - the control- and the data-connection
	*
	* @name: FtpConnect::pasv()
	* @access: public
	* @return boolean
	*/
	public function pasv()
	{
		// send command for passive connection
		$this->sendCmd("PASV");
		if($this->valid())
		{
			// get response for PASV
			$offset = strpos($this->response, "(");	
			$res = substr($this->response, ++$offset, strlen($this->response)-2);
			
			// split string to array by delimiter ","			 
			$parts = explode(",", trim($res));
			
			// save host and port for passive connection
			$host = "$parts[0].$parts[1].$parts[2].$parts[3]";
			$port = ((int)$parts[4] << 8) + (int) $parts[5];
			
			// data-connection handle is save to $dataCon
			$this->dataCon = fsockopen($host, $port);
			
			return $this->dataCon;
		}
	}
			
	/**
	* Prints out all requests to the server and their responses 
	*
	* @name: FtpConnect::log()
	* @access: public
	* @return boolean
	*/
	private function log($str)
	{
		if($this->logStats)
		{
			echo "$str<br>";
		}
	}
}

//---------------- testgebiet ----------------
try
{
	$ftp = new FtpConnect($host, $port, $user, $pwd);
	$ftp->logStats = 1;
	$ftp->pasv();
}
catch(Exception $e)
{
	echo $e->getMessage();
}
?>

</pre>
MfG, Andy
 

Was mir so auf den ersten Blick aufgefallen ist die Verwendung von continue außerhalb einer Schleife. Continue wird nur innerhalb von Schleifen verwendet.

Allerdings will es nun nicht ganz so laufen, wie ich das möchte.
Jetzt zu deinem Problem - was ist eigentlich dein Problem? Kannst du das genauer erläutern?!
 
Hi, im Konstruktor müssten die Abfragen anders sein, statt
PHP:
$this->sendCmd("USER $user");
if ($this->valid()) continue;
müsste dort z.B. so etwas stehen:
PHP:
$this->sendCmd("USER $user");
if (!$this->valid())
  throw new Exception('User not accepted: ' . $user);
Ansonsten kann ich nur das Tutorial von Dennis zu FTP empfehlen, da steht eigentlich alles drin was man braucht, und du kriegst sogar schon eine fertige Klasse präsentiert.
 
Zuletzt bearbeitet:
Danke erstmal für eure Hilfe. Schaue es mir gleich nochmal genauer an und Korrigiere den Fehler mit dem continue. Das Tutorial von Denis hab ich schon gesehen, aber ich finde, dass er das an einigen Stellen zu kompliziert gemacht hat. Deshalb habe ich die vier zusätzlichen Methoden getReply(), valid(), sendCmd() und log() gebastelt. Die machen das ganze, wie ich finde deutlich übersichtlicher.
MfG, Andy
 
Zurück