How to write FTPClient in MobiAccess
Introduction:
The purpose of this document is to set an example for the users of the MobiAccess framework about how to write a FTPClient modul. The following description will guide through the reader step-by-step in the construction of the Modul, constantly adding new functions.
We need first, one helper class for represent the socket connection, and the FTPClient class:
FTPConnection
//Class for represent the socket connection class { //The ip address of the host public var ip : String;
//The connection port public var port : Integer;
public CI() { super(); } }
FTPClient
class { //The socket to connect ftpServer private var socket : Socket;
//The InputSream to receive basic information from the server private var sis : InputStream;
//The OutputStream to send commands to server private var sos : OutputStream;
//The server host private var host : String;
//The server connection port private var port : Integer;
//The error message private var errorMesssage : String;
//The newLine buffer private var newLine : ByteBuffer;
//The apostrof character private var apostrof : String;
//The 1KByte bufferSize private static var OneK : Long; public CI() { super();this.newLine = ByteBuffer.CI(); this.newLine.AddByte(Byte.CI("13")); this.newLine.AddByte(Byte.CI("10"));var bb : ByteBuffer= ByteBuffer.CI(); bb.AddByte(Byte.CI("34")); this.apostrof = String.ParseBytes(bb); }
static { FTPClient.OneK = Long.CI("1024"); } }
Now we have one basic class to connect the FTP server
The Connection
We need one connection method:
//Connect to the remote host, return isSucces public function Connect(host : String, port : Integer) : Boolean;
Connect
Connect { var ex : Exception; try { this.socket = Socket.CI(host, port); this.sis = this.socket.GetInputStream(); this.sos = this.socket.GetOutputStream(); this.host = host; this.port = port; return true; } catch(ex) { this.errorMesssage = ex.GetMessage(); return false; } }
When the user connected, need login the server:
Login
For login the user we need some helper method to send command the server, and implement the login function.
ExecuteCommad
//Send command to server, end return the server response private function ExecuteCommand(command: String) : String;
ExecuteCommand { var bb : ByteBuffer = command.GetBytes(); bb.AddBytes(this.newLine); this.sos.WriteBytes(bb);this.sos.Flush(); while(this.sis.Available().NOT()){} bb= ByteBuffer.CI(); while(this.sis.Available())
{ bb.AddBytes(this.sis.ReadBytes(FTPClient.OneK)); }
var result : String = String.ParseBytes(bb); return result; }
Login
//Login the user to the connected host, return isSuccess public function Login(userName : String, password : String) : Boolean;
Login { var ex: Exception; try { this.ExecuteCommand("");var tmp : String = this.ExecuteCommand("USER ".Concatenate(userName)); if(tmp.Contains("331"))
{ tmp= this.ExecuteCommand("PASS ".Concatenate(password)); if(tmp.Contains("230"))
{ return true; } this.errorMesssage = tmp; } }
catch(ex) { this.errorMesssage = ex.GetMessage(); }
return false; }
Now, when user logged is, we can use some basic functions
Basic functions
PrintWorkingDirectory
//Returns the name of the current directory on the remote host. public function PrintWorkingDirectory() :String;
PrintWorkingDirectory { var ex : Exception; var tmp : String; try { tmp = this.ExecuteCommand("PWD");if(tmp.Contains("257 ")) { var startIndex : Integer = tmp.IndexOf(this.apostrof);
tmp= tmp.SubString(startIndex.Add(1), tmp.Length().Subtract(startIndex.Add(1)));
var endIndex : Integer = tmp.IndexOf(this.apostrof); tmp = tmp.SubString(0,endIndex);
return tmp; } throw Exception.CI("Exception in PWD",tmp, null); } catch(ex)
{ this.errorMesssage = ex.GetMessage(); }
return null; }
ChangeDirectoryUp
//Makes the parent of the current directory be the current directory. public function ChangeDirectoryUp() : Boolean; ChangeDirectoryUp
{ var ex : Exception; var tmp : String ; try { tmp = this.ExecuteCommand("CDUP");
if(tmp.Contains("250")) { return true; } this.errorMesssage = tmp; }
catch(ex) { this.errorMesssage = ex.GetMessage(); } return false; }
ChangeWorkingDirectory
//Makes the given directory be the current directory on the remote host. public function ChangeWorkingDirectory(path : String) : Boolean;
ChangeWorkingDirectory { var tmp : String; var ex : Exception; try{ tmp = this.ExecuteCommand("CWD ".Concatenate(path)); if(tmp.Contains("250"))
{ return true; } this.errorMesssage = tmp; } catch(ex)
{ this.errorMesssage = ex.GetMessage(); } return false; }
Delete
//Deletes the given file on the remote host. public function Delete(fileName : String) : Boolean;
Delete { var tmp : String; var ex : Exception; try { tmp = this.ExecuteCommand("DELE ".Concatenate(fileName));if(tmp.Contains("250")) { return true; } this.errorMesssage = tmp; } catch(ex)
{ this.errorMesssage = ex.GetMessage(); } return false; }
MakeDirectory
//Creates the named directory on the remote host. public function MakeDirectory(dirName : String) : Boolean;
MakeDirectory { var tmp : String; var ex : Exception; try{ tmp = this.ExecuteCommand("MKD ".Concatenate(dirName)); if(tmp.Contains("257"))
{ return true; } this.errorMesssage = tmp; } catch(ex)
{ this.errorMesssage = ex.GetMessage(); } return false; }
Quit
//Terminates the command connection. public function Quit() : Boolean;
Quit { var tmp : String; var ex : Exception; try { tmp = this.ExecuteCommand("QUIT"); if(tmp.Contains("221")){ return true; } this.errorMesssage = tmp; } catch(ex)
{ this.errorMesssage = ex.GetMessage(); } return false; }
GetFileSize
//Returns the size of the remote file as a decimal number. public function GetFileSize(fileName : String) : Long;
GetFileSize { var tmp : String; var ex : Exception; try { tmp = this.ExecuteCommand("SIZE ".Concatenate(fileName));if(tmp.StartsWith("213 ")) { tmp = tmp.Replace("213 ", "");
tmp = tmp.Replace(String.ParseBytes(this.newLine), ""); return Long.CI(tmp); }
this.errorMesssage = tmp; } catch(ex) { this.errorMesssage = ex.GetMessage(); }
return null; }
RemoveDirectory
//Deletes the named directory on the remote host. public function RemoveDirectory(dirName : String) : Boolean;
RemoveDirectory { var tmp : String; var ex : Exception; try{ tmp = this.ExecuteCommand("RMD ".Concatenate(dirName)); if(tmp.StartsWith("250"))
return true; } this.errorMesssage = tmp; } catch(ex)
{ this.errorMesssage = ex.GetMessage(); } return false; }
RenameFile
//Rename the given file public function RenameFile(oldName : String, newName : String) : Boolean;
RenameFile { var tmp : String; var ex : Exception; try { tmp = this.ExecuteCommand("RNFR ".Concatenate(oldName));if(tmp.StartsWith("350")) { tmp = this.ExecuteCommand("RNTO ".Concatenate(newName));
if(tmp.StartsWith("250")) { return true; } } }
catch(ex) { this.errorMesssage = ex.GetMessage(); } return false; }
DataTransfer functions
For send and receive files, we need implement some helper methods:
Helper methods:
InitPassiveConnection
//Init the passive connection for the data transfer private function InitPassiveConnection() : Void;
InitPassiveConnection { var connection : FTPConnection = this.PassiveMode(); this.ClosePassiveSocket();this.passiveSocket = Socket.CI(connection.ip, connection.port); this.passiveSocket.SetReadTimeOut(Long.CI("5000"));
this.passiveSIS= this.passiveSocket.GetInputStream(); this.passiveSOS = this.passiveSocket.GetOutputStream(); return; }
SetType
//Set the transfer type private function SetType(type : String) : Boolean;
SetType { var tmp : String; var ex : Exception; try { tmp = this.ExecuteCommand("TYPE ".Concatenate(type));if(tmp.Contains("200")) { return true; } this.errorMesssage = tmp; } catch(ex)
{ this.errorMesssage = ex.GetMessage(); } return false; }
ReadDataFromStream
//Read all data from the given stream, and return the ByteBuffer private function ReadDataFromStream(is : InputStream) : ByteBuffer;
ReadDataFromStream { var bb : ByteBuffer = ByteBuffer.CI(); while(is.Available().NOT()) { } while(is.Available()){ bb.AddBytes(is.ReadBytes(FTPClient.OneK)); } Log.PrintLine(String.ParseBytes(bb)); return bb; }
PassiveMode
//Send server passiveMode request, and return the connection info private function PassiveMode() :FTPConnection;
PassiveMode { var tmp : String; var ex : Exception; try { tmp= this.ExecuteCommand("PASV");if(tmp.Contains("227")) { var connection : FTPConnection = FTPConnection.CI();
var beginIndex : Integer = tmp.IndexOf("("); var endIndex : Integer = tmp.IndexOf(")");
tmp= tmp.SubString(beginIndex.Add(1), endIndex.Subtract(beginIndex).Subtract(1));
tmp = tmp.Replace(" ", ""); var list : List = tmp.Split(",");
connection.ip = ([String]list.GetItem(0)).Concatenate(".").Concatenate(([String]list.GetItem(1))).Concatenate(".").Concatenate(([String]list.GetItem(2))).Concatenate(".").Concatenate(([String]list.GetItem(3)));
connection.port = Integer.CI([String]list.GetItem(4)).Multiply(256).Add(Integer.CI([String]list.GetItem(5)));
//this.isPassiveMode = true; return connection; } this.errorMesssage = tmp; }
catch(ex) { this.errorMesssage = ex.GetMessage(); //throw ex; } return null; }
ClosePassiveSocket
//Close the dataTransfer socket private function ClosePassiveSocket() : Void;
ClosePassiveSocket { var ex : Exception; try { this.passiveSIS.Close(); } catch(ex){} try{ this.passiveSOS.Close(); } catch(ex){} try { this.passiveSocket.Close(); }
catch(ex){} return; }
TransferMethods
GetFile
//Receive the given file from the server and write it outputStream public function GetFile(fileName : String, fos : FileOutputStream) : Boolean;
GetFile { var tmp : String; var ex : Exception; var bb : ByteBuffer; var size : Long;var bufferSize : Long = Long.CI("131072"); var readCounter : Long = Long.CI("0"); try
{ size = this.GetFileSize(fileName); if(this.SetType("I").NOT())
{ return false; } this.InitPassiveConnection();
tmp = this.ExecuteCommand("RETR ".Concatenate(fileName)); if(tmp.Contains("150"))
{ while(readCounter.Smaller(size)) { bb= this.passiveSIS.ReadBytes(bufferSize);
readCounter = readCounter.Add(bb.GetLength().ToLong()); fos.WriteBytes(bb); fos.Flush(); }
tmp = String.ParseBytes(this.ReadDataFromStream(this.sis)); if(tmp.StartsWith("226"))
{ return true; } } this.errorMesssage = tmp; } catch(ex)
{ this.errorMesssage = ex.GetMessage(); } return false; }
PushFile
//Push file to the server public function PushFile(fileName : String, fis : InputStream) : Boolean;
PushFile { var tmp : String; var ex : Exception; var bb : ByteBuffer;
var bufferSize : Long = Long.CI("131072"); try { this.InitPassiveConnection();tmp = this.ExecuteCommand("STOR ".Concatenate(fileName)); if(tmp.StartsWith("150"))
{ while(fis.Available()) { bb = fis.ReadBytes(bufferSize);
this.passiveSOS.WriteBytes(bb); this.passiveSOS.Flush(); }
this.passiveSOS.Close(); tmp = String.ParseBytes(this.ReadDataFromStream(this.sis));
if(tmp.StartsWith("226")) { return true; } }
this.errorMesssage = tmp; catch(ex) { this.errorMesssage = ex.GetMessage(); } return false; }
Written by SJ





