2013-09-05 18:07:07 -07:00
|
|
|
Unit m_Tcp_Client_FTP;
|
|
|
|
|
|
|
|
{$I M_OPS.PAS}
|
|
|
|
|
|
|
|
Interface
|
|
|
|
|
|
|
|
Uses
|
2013-09-07 14:56:12 -07:00
|
|
|
SysUtils, // replace wordrec and remove
|
2013-09-05 18:07:07 -07:00
|
|
|
m_io_Sockets,
|
|
|
|
m_Tcp_Client;
|
|
|
|
|
|
|
|
Type
|
|
|
|
TFTPClient = Class(TTCPClient)
|
2013-09-07 15:52:49 -07:00
|
|
|
DataPort : Word;
|
|
|
|
DataIP : String;
|
|
|
|
DataSocket : TIOSocket;
|
|
|
|
IsPassive : Boolean;
|
2013-09-05 18:07:07 -07:00
|
|
|
|
2013-09-07 14:25:43 -07:00
|
|
|
Constructor Create (NetI: String); Override;
|
|
|
|
Function OpenDataSession : Boolean;
|
|
|
|
Procedure CloseDataSession;
|
|
|
|
Function SetPassive (IsOn: Boolean) : Boolean;
|
|
|
|
Function OpenConnection (HostName: String) : Boolean;
|
|
|
|
Function Authenticate (Login, Password: String) : Boolean;
|
|
|
|
Function ChangeDirectory (Str: String) : Boolean;
|
|
|
|
Function SendFile (Passive: Boolean; FileName: String) : Boolean;
|
|
|
|
Function GetFile (Passive: Boolean; FileName: String) : Boolean;
|
|
|
|
Procedure CloseConnection;
|
2013-09-05 18:07:07 -07:00
|
|
|
End;
|
|
|
|
|
|
|
|
Implementation
|
|
|
|
|
|
|
|
Uses
|
|
|
|
m_FileIO,
|
|
|
|
m_Strings;
|
|
|
|
|
2013-09-07 15:52:49 -07:00
|
|
|
Const
|
|
|
|
ftpDefaultDataPort = 20;
|
|
|
|
|
2013-09-07 14:25:43 -07:00
|
|
|
Constructor TFTPClient.Create (NetI: String);
|
2013-09-05 18:07:07 -07:00
|
|
|
Begin
|
2013-09-07 14:25:43 -07:00
|
|
|
Inherited Create(NetI);
|
2013-09-05 18:07:07 -07:00
|
|
|
|
|
|
|
IsPassive := False;
|
|
|
|
DataIP := '';
|
2013-09-07 15:52:49 -07:00
|
|
|
DataPort := ftpDefaultDataPort;
|
2013-09-05 18:07:07 -07:00
|
|
|
End;
|
|
|
|
|
|
|
|
Function TFTPClient.OpenDataSession : Boolean;
|
|
|
|
Var
|
|
|
|
WaitSock : TIOSocket;
|
|
|
|
Begin
|
|
|
|
Result := False;
|
|
|
|
|
2013-09-07 14:25:43 -07:00
|
|
|
WriteLn ('DEBUG OPEN DATA 1');
|
|
|
|
|
2013-09-05 18:07:07 -07:00
|
|
|
If DataSocket <> NIL Then Begin
|
|
|
|
DataSocket.Free;
|
|
|
|
DataSocket := NIL;
|
|
|
|
End;
|
|
|
|
|
|
|
|
If IsPassive Then Begin
|
|
|
|
DataSocket := TIOSocket.Create;
|
|
|
|
|
|
|
|
If Not DataSocket.Connect(DataIP, DataPort) Then Begin
|
|
|
|
DataSocket.Free;
|
|
|
|
DataSocket := NIL;
|
|
|
|
|
|
|
|
Exit;
|
|
|
|
End;
|
|
|
|
End Else Begin
|
2013-09-07 14:25:43 -07:00
|
|
|
WriteLn ('DEBUG OPEN DATA 2');
|
|
|
|
|
2013-09-05 18:07:07 -07:00
|
|
|
WaitSock := TIOSocket.Create;
|
|
|
|
|
|
|
|
WaitSock.FTelnetServer := False;
|
|
|
|
WaitSock.FTelnetClient := False;
|
|
|
|
|
2013-09-07 14:25:43 -07:00
|
|
|
WriteLn ('DEBUG OPEN DATA 3');
|
|
|
|
|
2013-09-05 18:07:07 -07:00
|
|
|
WaitSock.WaitInit(NetInterface, DataPort);
|
|
|
|
|
2013-09-07 14:25:43 -07:00
|
|
|
WriteLn ('DEBUG OPEN DATA 4');
|
|
|
|
|
2013-09-05 18:07:07 -07:00
|
|
|
DataSocket := WaitSock.WaitConnection(10000);
|
|
|
|
|
2013-09-07 14:25:43 -07:00
|
|
|
WriteLn ('DEBUG OPEN DATA 5');
|
|
|
|
|
2013-09-07 12:52:31 -07:00
|
|
|
WaitSock.Free;
|
2013-09-05 18:07:07 -07:00
|
|
|
|
2013-09-07 12:52:31 -07:00
|
|
|
If Not Assigned(DataSocket) Then
|
2013-09-05 18:07:07 -07:00
|
|
|
Exit;
|
|
|
|
End;
|
|
|
|
|
|
|
|
Result := True;
|
|
|
|
End;
|
|
|
|
|
|
|
|
Procedure TFTPClient.CloseDataSession;
|
|
|
|
Begin
|
|
|
|
If DataSocket <> NIL Then Begin
|
|
|
|
DataSocket.Free;
|
|
|
|
|
|
|
|
DataSocket := NIL;
|
|
|
|
End;
|
|
|
|
End;
|
|
|
|
|
|
|
|
Function TFTPClient.OpenConnection (HostName: String) : Boolean;
|
|
|
|
Var
|
|
|
|
Port : Word;
|
|
|
|
Begin
|
|
|
|
Result := False;
|
|
|
|
|
|
|
|
Port := strS2I(strWordGet(2, HostName, ':'));
|
|
|
|
|
|
|
|
If Port = 0 Then Port := 21;
|
|
|
|
|
|
|
|
Result := Connect(strWordGet(1, HostName, ':'), Port);
|
|
|
|
|
|
|
|
If Result Then GetResponse; // eat banner/info tag
|
|
|
|
End;
|
|
|
|
|
|
|
|
Function TFTPClient.Authenticate (Login, Password: String) : Boolean;
|
|
|
|
Begin
|
|
|
|
Result := False;
|
|
|
|
|
|
|
|
If SendCommand('USER ' + Login) <> 331 Then Exit;
|
|
|
|
If SendCommand('PASS ' + Password) <> 230 Then Exit;
|
|
|
|
|
|
|
|
Result := True;
|
|
|
|
End;
|
|
|
|
|
|
|
|
Function TFTPClient.SetPassive (IsOn: Boolean) : Boolean;
|
|
|
|
Var
|
|
|
|
Str : String;
|
|
|
|
Count : Byte;
|
|
|
|
Begin
|
|
|
|
If IsOn Then Begin
|
|
|
|
Result := SendCommand('PASV') = 227;
|
|
|
|
|
|
|
|
If Result Then Begin
|
|
|
|
Str := (strWordGet(1, strWordGet(2, ResponseStr, '('), ')'));
|
|
|
|
|
|
|
|
For Count := 1 to 3 Do
|
|
|
|
Str[Pos(',', Str)] := '.';
|
|
|
|
|
|
|
|
DataIP := Copy(Str, 1, Pos(',', Str) - 1);
|
|
|
|
|
|
|
|
Delete (Str, 1, Pos(',', Str));
|
|
|
|
|
|
|
|
WordRec(DataPort).Hi := strS2I(Copy(Str, 1, Pos(',', Str) - 1));
|
|
|
|
WordRec(DataPort).Lo := strS2I(Copy(Str, Pos(',', Str) + 1, Length(Str)));
|
|
|
|
|
|
|
|
IsPassive := True;
|
|
|
|
End;
|
|
|
|
End Else Begin
|
|
|
|
IsPassive := False;
|
2013-09-07 15:52:49 -07:00
|
|
|
DataPort := ftpDefaultDataPort;
|
2013-09-05 18:07:07 -07:00
|
|
|
Result := SendCommand('PORT ' + strReplace(Client.PeerIP, '.', ',') + ',' + strI2S(WordRec(DataPort).Hi) + ',' + strI2S(WordRec(DataPort).Lo)) = 200;
|
|
|
|
End;
|
|
|
|
End;
|
|
|
|
|
|
|
|
Function TFTPClient.SendFile (Passive: Boolean; FileName: String) : Boolean;
|
|
|
|
Var
|
|
|
|
F : File;
|
2013-09-07 15:52:49 -07:00
|
|
|
Buffer : Array[1..8 * 1024] of Char;
|
2013-09-05 18:07:07 -07:00
|
|
|
Res : LongInt;
|
2013-09-07 15:52:49 -07:00
|
|
|
OK : Boolean;
|
2013-09-05 18:07:07 -07:00
|
|
|
Begin
|
|
|
|
Result := False;
|
|
|
|
|
|
|
|
If Not FileExist(FileName) Then Exit;
|
|
|
|
|
2013-09-07 12:52:31 -07:00
|
|
|
WriteLn ('DEBUG SendFile Passive ', Passive, ' Filename ', FileName);
|
|
|
|
|
2013-09-05 18:07:07 -07:00
|
|
|
SetPassive(Passive);
|
|
|
|
|
2013-09-07 14:25:43 -07:00
|
|
|
WriteLn ('DEBUG SETPASSIVE()');
|
|
|
|
|
2013-09-05 18:07:07 -07:00
|
|
|
Client.WriteLine ('STOR ' + JustFile(FileName));
|
|
|
|
|
2013-09-07 15:52:49 -07:00
|
|
|
OK := OpenDataSession;
|
2013-09-05 18:07:07 -07:00
|
|
|
|
2013-09-07 15:52:49 -07:00
|
|
|
If OK and (GetResponse = 150) Then Begin
|
2013-09-07 14:25:43 -07:00
|
|
|
WriteLn ('DEBUG BEGIN SEND FILE');
|
|
|
|
|
2013-09-05 18:07:07 -07:00
|
|
|
Assign (F, FileName);
|
|
|
|
|
|
|
|
If ioReset(F, 1, fmRWDN) Then Begin
|
|
|
|
Repeat
|
|
|
|
BlockRead (F, Buffer, SizeOf(Buffer), Res);
|
|
|
|
|
|
|
|
If Res > 0 Then
|
|
|
|
DataSocket.WriteBuf(Buffer, Res)
|
|
|
|
Else
|
|
|
|
Break;
|
|
|
|
Until False;
|
|
|
|
|
|
|
|
Close (F);
|
|
|
|
End;
|
|
|
|
|
|
|
|
CloseDataSession;
|
|
|
|
|
|
|
|
Result := GetResponse = 226;
|
2013-09-07 15:52:49 -07:00
|
|
|
End Else Begin
|
|
|
|
If IsPassive Then
|
|
|
|
WriteLn ('DEBUG unable to connect to FTP server for data session')
|
|
|
|
Else
|
|
|
|
WriteLn ('DEBUG unable to establish data session on port ', DataPort);
|
|
|
|
|
2013-09-05 18:07:07 -07:00
|
|
|
CloseDataSession;
|
2013-09-07 15:52:49 -07:00
|
|
|
End;
|
2013-09-05 18:07:07 -07:00
|
|
|
End;
|
|
|
|
|
2013-09-05 21:57:11 -07:00
|
|
|
Function TFTPClient.GetFile (Passive: Boolean; FileName: String) : Boolean;
|
|
|
|
Var
|
|
|
|
F : File;
|
|
|
|
Res : LongInt;
|
|
|
|
Buffer : Array[1..8*1024] of Char;
|
2013-09-07 15:52:49 -07:00
|
|
|
OK : Boolean;
|
2013-09-05 18:07:07 -07:00
|
|
|
Begin
|
|
|
|
Result := False;
|
2013-09-05 21:57:11 -07:00
|
|
|
|
|
|
|
If FileExist(FileName) Then Exit;
|
|
|
|
|
|
|
|
SetPassive(Passive);
|
|
|
|
|
|
|
|
Client.WriteLine('RETR ' + JustFile(FileName));
|
|
|
|
|
2013-09-07 15:52:49 -07:00
|
|
|
OK := OpenDataSession;
|
2013-09-05 21:57:11 -07:00
|
|
|
|
2013-09-07 15:52:49 -07:00
|
|
|
If OK And (GetResponse = 150) Then Begin
|
2013-09-05 21:57:11 -07:00
|
|
|
Assign (F, FileName);
|
|
|
|
|
|
|
|
If ioReWrite(F, 1, fmRWDW) Then Begin
|
|
|
|
Repeat
|
|
|
|
Res := DataSocket.ReadBuf (Buffer, SizeOf(Buffer));
|
|
|
|
|
|
|
|
If Res > 0 Then
|
|
|
|
BlockWrite (F, Buffer, Res)
|
|
|
|
Else
|
|
|
|
Break;
|
|
|
|
Until False;
|
|
|
|
|
|
|
|
Close (F);
|
|
|
|
End;
|
|
|
|
|
|
|
|
CloseDataSession;
|
|
|
|
|
|
|
|
Result := GetResponse = 226;
|
2013-09-07 15:52:49 -07:00
|
|
|
End Else Begin
|
|
|
|
WriteLn ('DEBUG unable to open data session, receive aborted');
|
|
|
|
|
2013-09-05 21:57:11 -07:00
|
|
|
CloseDataSession;
|
2013-09-07 15:52:49 -07:00
|
|
|
End;
|
2013-09-05 18:07:07 -07:00
|
|
|
End;
|
|
|
|
|
|
|
|
Function TFTPClient.ChangeDirectory (Str: String) : Boolean;
|
|
|
|
Begin
|
|
|
|
Result := SendCommand('CWD ' + Str) = 250;
|
|
|
|
End;
|
|
|
|
|
|
|
|
Procedure TFTPClient.CloseConnection;
|
|
|
|
Begin
|
|
|
|
If Client.Connected Then
|
|
|
|
Client.WriteLine('QUIT');
|
|
|
|
End;
|
|
|
|
|
|
|
|
End.
|