📄 idftp.pas
字号:
end;
FDataChannel.IOHandler.Free;
FreeAndNil(FDataChannel);
end;
end
else
begin
// PORT or EPRT
FDataChannel := TIdSimpleServer.Create(nil);
LPortSv := FDataChannel as TIdSimpleServer;
try
InitDataChannel;
LPortSv.BoundIP := (Self.IOHandler as TIdIOHandlerSocket).Binding.IP;
LPortSv.BoundPort := FDataPort;
LPortSv.BoundPortMin := FDataPortMin;
LPortSv.BoundPortMax := FDataPortMax;
if Assigned(FOnDataChannelCreate) then begin
OnDataChannelCreate(Self, FDataChannel);
end;
LPortSv.BeginListen;
if FUsingExtDataPort then begin
SendEPort(LPortSv.Binding);
end else begin
SendPort(LPortSv.Binding);
end;
if AResume then begin
SendCmd('REST ' + IntToStr(ADest.VCLStream.Position), [350]); {do not localize}
end;
SendCmd(ACommand, [125, 150, 154]); //APR: Ericsson Switch FTP);
LPortSv.Listen;
if FUsingSFTP and (FDataPortProtection = ftpdpsPrivate) then begin
TIdSSLIOHandlerSocketBase(FDataChannel.IOHandler).PassThrough := False;
end;
if FCurrentTransferMode = dmStream then begin
FDataChannel.IOHandler.ReadStream(ADest, -1, True);
end else begin
FCompressor.DecompressFTPFromIO( FDataChannel.IOHandler, FZLibWindowBits, ADest.VCLStream);
// ReadCompressedData(FCompressor, ADest, FDataChannel.IOHandler, FZLibWindowBits);
end;
finally
if Assigned(FOnDataChannelDestroy) then begin
OnDataChannelDestroy(Self, FDataChannel);
end;
FDataChannel.IOHandler.Free;
FDataChannel.IOHandler := nil;
FreeAndNil(FDataChannel);
end;
end;
finally
DoStatus(ftpReady, [RSFTPStatusDoneTransfer]);
end;
// ToDo: Change that to properly handle response code (not just success or except)
// 226 = download successful, 225 = Abort successful}
LResponse := GetResponse([225, 226, 250, 426, 450]);
if (LResponse = 426) or (LResponse = 450) then begin
GetResponse([226, 225]);
DoStatus(ftpAborted, [RSFTPStatusAbortTransfer]);
end;
end;
procedure TIdFTP.Quit;
begin
if Connected then begin
IOHandler.WriteLn('QUIT'); {do not localize}
end;
Disconnect;
end;
procedure TIdFTP.KillDataChannel;
begin
// Had kill the data channel ()
if Assigned(FDataChannel) then begin
FDataChannel.Disconnect;//FDataChannel.IOHandler.DisconnectSocket; {//BGO}
end;
end;
procedure TIdFTP.Abort;
begin
// only send the abort command. The Data channel is supposed to disconnect
if Connected then begin
IOHandler.WriteLn('ABOR'); {do not localize}
end;
// Kill the data channel: usually, the server doesn't close it by itself
KillDataChannel;
end;
procedure TIdFTP.SendPort(AHandle: TIdSocketHandle);
begin
if FExternalIP <> '' then
begin
SendPort(FExternalIP,AHandle.Port);
end
else
begin
SendPort(AHandle.IP, AHandle.Port);
end;
end;
procedure TIdFTP.SendPort(const AIP: String; const APort: Integer);
begin
SendDataSettings;
SendCmd('PORT ' + StringReplace(AIP, '.', ',', [rfReplaceAll]) {do not localize}
+ ',' + IntToStr(APort div 256) + ',' + IntToStr(APort mod 256), [200]); {do not localize}
end;
procedure TIdFTP.InternalPut(const ACommand: string; ASource: TIdStreamVCL; AFromBeginning: Boolean = true);
var
LIP: string;
LPort: Integer;
LResponse: Integer;
LPasvCl : TIdTCPClient;
LPortSv : TIdSimpleServer;
LIO : TIdIOHandler;
begin
//for SSL FXP, we have to do it here because there is no command were a client
//submits data through a data port where the SSCN setting is ignored.
ClearSSCN;
DoStatus(ftpTransfer, [RSFTPStatusStartTransfer]);
try
if FPassive then begin
SendPret(ACommand);
if FUsingExtDataPort then begin
SendEPassive(LIP, LPort);
end else begin
SendPassive(LIP, LPort);
end;
IOHandler.WriteLn(ACommand);
FDataChannel := TIdTCPClient.Create(nil);
LPasvCl := FDataChannel as TIdTCPClient;
try
InitDataChannel;
LPasvCl.Host := LIP;
LPasvCl.Port := LPort;
if Assigned(FOnDataChannelCreate) then begin
OnDataChannelCreate(self,FDataChannel);
end;
LPasvCl.Connect;
try
Self.GetResponse([110, 125, 150]);
try
if FUsingSFTP and (FDataPortProtection = ftpdpsPrivate) then begin
TIdSSLIOHandlerSocketBase(FDataChannel.IOHandler).Passthrough := False;
end;
if FCurrentTransferMode<>dmDeflate then begin
if AFromBeginning then begin
FDataChannel.IOHandler.Write(ASource,0, false); // from beginning
end else begin
FDataChannel.IOHandler.Write(ASource,-1, false); // from current position
end;
end else begin
FCompressor.CompressFTPToIO(ASource.VCLStream,FDataChannel.IOHandler,FZLibCompressionLevel,FZLibWindowBits,FZLibMemLevel, FZLibStratagy);
end;
except
on E: EIdSocketError do
begin
// If 10038 - abort was called. Server will return 225
if E.LastError <> 10038 then begin
raise;
end;
end;
end;
finally
LPasvCl.Disconnect;
end;
finally
if Assigned(FOnDataChannelDestroy) then begin
OnDataChannelDestroy(self,FDataChannel);
end;
LIO := FDataChannel.IOHandler;
FDataChannel.IOHandler := nil;
FreeAndNil(LIO);
FreeAndNil(FDataChannel);
end;
end else begin
FDataChannel := TIdSimpleServer.Create(nil);
LPortSv := FDataChannel as TIdSimpleServer;
try
InitDataChannel;
LPortSv.BoundIP := (Self.IOHandler as TIdIOHandlerSocket).Binding.IP;
LPortSv.BoundPort := FDataPort;
LPortSv.BoundPortMin := FDataPortMin;
LPortSv.BoundPortMax := FDataPortMax;
if Assigned(FOnDataChannelCreate) then begin
OnDataChannelCreate(Self, FDataChannel);
end;
LPortSv.BeginListen;
if FUsingExtDataPort then begin
SendEPort(LPortSv.Binding);
end else begin
SendPort(LPortSv.Binding);
end;
Self.SendCmd(ACommand, [125, 150]);
LPortSv.Listen;
if FUsingSFTP and (FDataPortProtection = ftpdpsPrivate) then begin
TIdSSLIOHandlerSocketBase(FDataChannel.IOHandler).PassThrough := False;
end;
if FCurrentTransferMode<>dmDeflate then begin
if AFromBeginning then begin
FDataChannel.IOHandler.Write(ASource,0, false); // from beginning
end else begin
FDataChannel.IOHandler.Write(ASource,-1, false); // from current position
end;
end else begin
FCompressor.CompressFTPToIO(ASource.VCLStream,FDataChannel.IOHandler,FZLibCompressionLevel,FZLibWindowBits,FZLibMemLevel, FZLibStratagy);
end;
finally
if Assigned(FOnDataChannelDestroy) then begin
OnDataChannelDestroy(Self, FDataChannel);
end;
FDataChannel.IOHandler.Free;
FDataChannel.IOHandler := nil;
FreeAndNil(FDataChannel);
end;
end;
finally
DoStatus(ftpReady, [RSFTPStatusDoneTransfer]);
end;
// 226 = download successful, 225 = Abort successful}
LResponse := GetResponse([225, 226, 250, 426, 450]);
if (LResponse = 426) or (LResponse = 450) then
begin
// some servers respond with 226 on ABOR
GetResponse([226, 225]);
DoStatus(ftpAborted, [RSFTPStatusAbortTransfer]);
end;
end;
procedure TIdFTP.InitDataChannel;
var LSSL : TIdSSLIOHandlerSocketBase;
begin
if (FDataPortProtection = ftpdpsPrivate) then
begin
LSSL := TIdSSLIOHandlerSocketBase(Self.IOHandler);
FDataChannel.IOHandler := LSSL.Clone;
//we have to delay the actual negotiation until we get the reply and
//and just before the readString
TIdSSLIOHandlerSocketBase(FDataChannel.IOHandler).Passthrough := True;
end else begin
FDataChannel.IOHandler := TIdIOHandler.MakeDefaultIOHandler(Self);
end;
if FDataChannel is TIdTCPClient then
begin
//Now SocksInfo are multi-thread safe
FDataChannel.IOHandler.ConnectTimeout := Self.IOHandler.ConnectTimeout;
end;
if (FDataChannel.IOHandler is TIdIOHandlerSocket) and (Self.IOHandler is TIdIOHandlerSocket) then
begin
TIdIOHandlerSocket(FDataChannel.IOHandler).TransparentProxy := TIdIOHandlerSocket(Self.IOHandler).TransparentProxy;
TIdIOHandlerSocket(FDataChannel.IOHandler).IPVersion := TIdIOHandlerSocket(Self.IOHandler).IPVersion;
end;
FDataChannel.IOHandler.ReadTimeout := FTransferTimeout;
FDataChannel.IOHandler.SendBufferSize := IOHandler.SendBufferSize;
FDataChannel.IOHandler.RecvBufferSize := IOHandler.RecvBufferSize;
FDataChannel.OnWork := OnWork;
FDataChannel.OnWorkBegin := OnWorkBegin;
FDataChannel.OnWorkEnd := OnWorkEnd;
end;
procedure TIdFTP.Put(const ASource: TIdStreamVCL; const ADestFile: string;
const AAppend: boolean = false);
begin
if ADestFile = '' then
begin
raise EIdFTPUploadFileNameCanNotBeEmpty.Create(RSFTPFileNameCanNotBeEmpty);
end
else
begin
DoBeforePut(ASource.VCLStream ); //APR);
if AAppend then
begin
InternalPut('APPE ' + ADestFile, ASource, false); {Do not localize}
end
else
begin
InternalPut('STOR ' + ADestFile, ASource); {Do not localize}
end;
DoAfterPut;
end;
end;
procedure TIdFTP.Put(const ASource: TStream; const ADestFile: string;
const AAppend: boolean = false);
var LStream : TIdStreamVCL;
begin
LStream := TIdStreamVCL.Create(ASource);
try
Put(LStream,ADestFile,AAppend);
finally
FreeAndNil(LStream);
end;
end;
procedure TIdFTP.Put(const ASourceFile: string; const ADestFile: string='';
const AAppend: boolean = false);
var
LSourceStream: TFileStream;
LDestFileName : String;
begin
LDestFileName := ADestFile;
if LDestFileName = '' then
begin
LDestFileName := ExtractFileName(ASourceFile);
end;
LSourceStream := TFileStream.Create(ASourceFile, fmOpenRead or fmShareDenyNone); try
Put(LSourceStream, LDestFileName, AAppend);
finally FreeAndNil(LSourceStream); end;
end;
procedure TIdFTP.StoreUnique(const ASource: TIdStreamVCL);
begin
InternalPut('STOU', ASource); {Do not localize}
end;
procedure TIdFTP.StoreUnique(const ASource: TStream);
var LStream : TIdStreamVCL;
begin
LStream := TIdStreamVCL.Create(ASource);
try
StoreUnique(LStream);
finally
FreeAndNil(LStream);
end;
end;
procedure TIdFTP.StoreUnique(const ASourceFile: string);
var
LSourceStream: TFileStream;
begin
LSourceStream := TFileStream.Create(ASourceFile, fmOpenRead or fmShareDenyNone); try
StoreUnique(LSourceStream);
finally FreeAndNil(LSourceStream); end;
end;
procedure TIdFTP.SendInternalPassive(const ACmd: String; var VIP: string;
var VPort: integer);
var
i,bLeft,bRight: integer;
s: string;
begin
SendDataSettings;
SendCmd(ACmd, 227); {do not localize}
s := Trim(LastCmdResult.Text[0]);
// Case 1 (Normal)
// 227 Entering passive mode(100,1,1,1,23,45)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -