mysticbbs/mdl/m_tcp_client_ftp.pas

304 lines
6.4 KiB
ObjectPascal
Raw Normal View History

2013-09-05 18:07:07 -07:00
Unit m_Tcp_Client_FTP;
{$I M_OPS.PAS}
Interface
Uses
m_io_Sockets,
m_Tcp_Client;
2013-09-16 13:31:33 -07:00
Const
ftpResOK = 0;
ftpResFailed = 1;
ftpResBadData = 2;
2013-09-17 19:28:41 -07:00
ftpResNoFile = 3;
2013-09-16 13:31:33 -07:00
2013-09-05 18:07:07 -07:00
Type
2013-09-07 20:52:11 -07:00
WordRec = Record
Lo : Byte;
Hi : Byte;
End;
2013-09-05 18:07:07 -07:00
TFTPClient = Class(TTCPClient)
DataPort : Word;
DataIP : String;
DataSocket : TIOSocket;
IsPassive : Boolean;
MinPort : Word;
MaxPort : Word;
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;
2013-09-21 22:32:34 -07:00
Function GetDirectoryList (Passive, Change: Boolean; Str: String) : Boolean;
Function SendFile (Passive: Boolean; LocalFile, RemoteFile: String) : Byte;
2013-09-16 13:31:33 -07:00
Function GetFile (Passive: Boolean; FileName: String) : Byte;
2013-09-07 14:25:43 -07:00
Procedure CloseConnection;
2013-09-05 18:07:07 -07:00
End;
Implementation
Uses
m_FileIO,
m_Strings;
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 := '';
MinPort := 49152;
MaxPort := 65535;
DataPort := Random(MaxPort - MinPort) + MinPort;
2013-09-05 18:07:07 -07:00
End;
Function TFTPClient.OpenDataSession : Boolean;
Var
WaitSock : TIOSocket;
Begin
Result := False;
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
WaitSock := TIOSocket.Create;
WaitSock.FTelnetServer := False;
WaitSock.FTelnetClient := False;
WaitSock.WaitInit(NetInterface, DataPort);
DataSocket := WaitSock.WaitConnection(10000);
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
2013-09-21 22:32:34 -07:00
//DataSocket.Disconnect;
2013-09-05 18:07:07 -07:00
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;
DataPort := Random(MaxPort - MinPort) + MinPort;
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;
2013-09-21 22:32:34 -07:00
Function TFTPClient.SendFile (Passive: Boolean; LocalFile, RemoteFile: String) : Byte;
2013-09-05 18:07:07 -07:00
Var
F : File;
Buffer : Array[1..8 * 1024] of Char;
2013-09-05 18:07:07 -07:00
Res : LongInt;
OK : Boolean;
2013-09-05 18:07:07 -07:00
Begin
2013-09-16 13:31:33 -07:00
Result := ftpResFailed;
2013-09-05 18:07:07 -07:00
2013-09-21 22:32:34 -07:00
If Not FileExist(LocalFile) Then Exit;
2013-09-05 18:07:07 -07:00
SetPassive(Passive);
2013-09-21 22:32:34 -07:00
Client.WriteLine ('STOR ' + JustFile(RemoteFile));
2013-09-05 18:07:07 -07:00
2013-09-17 19:28:41 -07:00
OK := OpenDataSession;
Res := GetResponse;
2013-09-05 18:07:07 -07:00
2013-09-17 19:28:41 -07:00
If OK and (Res = 150) Then Begin
2013-09-21 22:32:34 -07:00
Assign (F, LocalFile);
2013-09-05 18:07:07 -07:00
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;
2013-09-16 13:31:33 -07:00
If GetResponse = 226 Then
Result := ftpResOK;
End Else Begin
2013-09-17 19:28:41 -07:00
If Res = 550 Then
Result := ftpResNoFile
Else
Result := ftpResBadData;
2013-09-05 18:07:07 -07:00
CloseDataSession;
End;
2013-09-05 18:07:07 -07:00
End;
2013-09-16 13:31:33 -07:00
Function TFTPClient.GetFile (Passive: Boolean; FileName: String) : Byte;
2013-09-05 21:57:11 -07:00
Var
F : File;
Res : LongInt;
2013-09-16 13:31:33 -07:00
Buffer : Array[1..8 * 1024] of Char;
OK : Boolean;
2013-09-05 18:07:07 -07:00
Begin
2013-09-16 13:31:33 -07:00
Result := ftpResFailed;
2013-09-05 21:57:11 -07:00
If FileExist(FileName) Then Exit;
SetPassive(Passive);
Client.WriteLine('RETR ' + JustFile(FileName));
2013-09-17 19:28:41 -07:00
OK := OpenDataSession;
Res := GetResponse;
2013-09-05 21:57:11 -07:00
2013-09-17 19:28:41 -07:00
If OK And (Res = 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;
2013-09-16 13:31:33 -07:00
If GetResponse = 226 Then
Result := ftpResOK;
End Else Begin
2013-09-17 19:28:41 -07:00
If Res = 550 Then
Result := ftpResNoFile
Else
Result := ftpResBadData;
2013-09-05 21:57:11 -07:00
CloseDataSession;
End;
2013-09-05 18:07:07 -07:00
End;
Function TFTPClient.ChangeDirectory (Str: String) : Boolean;
Begin
Result := SendCommand('CWD ' + Str) = 250;
End;
2013-09-21 22:32:34 -07:00
Function TFTPClient.GetDirectoryList (Passive, Change: Boolean; Str: String) : Boolean;
Begin
Result := False;
If Change Then Begin
Result := ChangeDirectory(Str);
If Not Result Then Exit;
End;
SetPassive(Passive);
Client.WriteLine ('NLST');
If OpenDataSession and (GetResponse = 150) Then Begin
ResponseData.Clear;
Repeat
If DataSocket.ReadLine(Str) <> -1 Then
ResponseData.Add(Str)
Else
Break;
Until Not DataSocket.Connected;
Result := GetResponse = 226;
End;
CloseDataSession;
End;
2013-09-05 18:07:07 -07:00
Procedure TFTPClient.CloseConnection;
Begin
If Client.Connected Then
Client.WriteLine('QUIT');
End;
End.