📄 ftpcli.pas
字号:
function TCustomFtpCli.CheckReady : Boolean;
begin
Result := (FState in [ftpReady, ftpInternalReady]);
if not Result then
HandleError('FTP component not ready');
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.OpenAsync;
begin
if not CheckReady then
Exit;
if FConnected then begin
HandleError('FTP component already connected');
Exit;
end;
if not FHighLevelFlag then
FRequestType := ftpOpenAsync;
FRequestDoneFlag := FALSE;
FReceiveLen := 0;
FRequestResult := 0;
FDnsResult := '';
StateChange(ftpDnsLookup);
FControlSocket.DnsLookup(FHostName);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.ExecAsync(
RqType : TFtpRequest;
Cmd : String; { Command to execute }
OkResponses : array of Word; { List of responses like '200 221 342' }
DoneAsync : TFtpNextProc); { What to do when done }
var
I : Integer;
begin
if not CheckReady then
Exit;
if not FConnected then begin
HandleError('FTP component not connected');
Exit;
end;
if not FHighLevelFlag then
FRequestType := RqType;
for I := 0 to High(OkResponses) do
FOkResponses[I] := OkResponses[I];
FOkResponses[High(OkResponses) + 1] := 0;
FRequestDoneFlag := FALSE;
FNext := NextExecAsync;
FDoneAsync := DoneAsync;
StateChange(ftpWaitingResponse);
SendCommand(Cmd);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.ExtractMoreResults;
var
NumericCode : LongInt;
p : PChar;
begin
if FRequestResult = 0 then begin
if FFctPrv in [ftpFctSize] then begin
p := GetInteger(@FLastResponse[1], NumericCode);
GetInteger(p, FSizeResult);
end;
if FFctPrv in [ftpFctCDup, ftpFctPwd, ftpFctMkd, ftpFctCwd] then begin
p := GetInteger(@FLastResponse[1], NumericCode);
GetQuotedString(p, FDirResult);
end;
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.NextExecAsync;
var
I : Integer;
p : PChar;
begin
DisplayLastResponse;
if not (FLastResponse[1] in ['0'..'9']) then
Exit; { Continuation line, nothing to do }
p := GetInteger(@FLastResponse[1], FStatusCode);
if p^ = '-' then
Exit; { Continuation line, nothing to do }
if FOkResponses[0] = 0 then begin
{ The list of ok responses is empty }
if FStatusCode >= 500 then begin
{ Not a good response }
FRequestResult := FStatusCode;
SetErrorMessage;
end
else
FRequestResult := 0;
end
else begin
{ We have a list of ok response codes }
for I := 0 to High(FOkResponses) do begin
if FOkResponses[I] = 0 then begin
{ No good response found }
FRequestResult := FStatusCode;
SetErrorMessage;
break;
end;
if FOkResponses[I] = FStatusCode then begin
{ Good response found }
FRequestResult := 0;
Break;
end;
end;
end;
if FPassive and (FStatusCode = 227) then
FPasvResponse := FLastResponse;
ExtractMoreResults;
if Assigned(FDoneAsync) then
FDoneAsync
else
TriggerRequestDone(FRequestResult);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.QuitAsync;
begin
if Assigned(FLocalStream) then begin
FLocalStream.Destroy;
FLocalStream := nil;
end;
FFctPrv := ftpFctQuit;
ExecAsync(ftpQuitAsync, 'QUIT', [221], DoneQuitAsync);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.DoneQuitAsync;
begin
FControlSocket.Close;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.CwdAsync;
begin
if Length(FHostDirName) <= 0 then begin
HandleError('HostDirName emtpy');
Exit;
end;
FFctPrv := ftpFctCwd;
ExecAsync(ftpCwdAsync, 'CWD '+ FHostDirName, [200, 250, 257], nil);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.UserAsync;
begin
if Length(FUserName) <= 0 then begin
HandleError('UserName emtpy');
Exit;
end;
FFctPrv := ftpFctUser;
ExecAsync(ftpUserAsync, 'USER '+ FUserName, [331, 230], nil);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.PassAsync;
begin
if Length(FPassword) <= 0 then begin
HandleError('Password emtpy');
Exit;
end;
FFctPrv := ftpFctPass;
ExecAsync(ftpPassAsync, 'PASS '+ FPassword, [230], nil);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.SystAsync;
begin
FFctPrv := ftpFctSyst;
ExecAsync(ftpSystAsync, 'SYST', [215], nil);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.RestAsync;
begin
FFctPrv := ftpFctRest;
FResumeAt := GetFileSize(FLocalFileName);
if FResumeAt > 0 then
ExecAsync(ftpRestAsync, 'REST ' + IntToStr(FResumeAt), [0], nil)
else begin
FRequestDoneFlag := FALSE;
FNext := NextExecAsync;
FDoneAsync := nil;
TriggerRequestDone(0);
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.SizeAsync;
begin
FSizeResult := 0;
FFctPrv := ftpFctSize;
ExecAsync(ftpSizeAsync, 'SIZE ' + FHostFileName, [213], nil);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.TypeSetAsync;
begin
FFctPrv := ftpFctTypeSet;
ExecAsync(ftpTypeSetAsync, 'TYPE ' + FType, [200], nil);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.TypeBinaryAsync;
begin
Binary := TRUE;
TypeSetAsync;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.TypeAsciiAsync;
begin
Binary := FALSE;
TypeSetAsync;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.MkdAsync;
begin
FFctPrv := ftpFctMkd;
ExecAsync(ftpMkdAsync, 'MKD ' + FHostFileName, [257], nil);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.RmdAsync;
begin
FFctPrv := ftpFctRmd;
ExecAsync(ftpRmdAsync, 'RMD ' + FHostFileName, [250, 257], nil);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.DeleAsync;
begin
FFctPrv := ftpFctDele;
ExecAsync(ftpDeleAsync, 'DELE ' + FHostFileName, [250, 257], nil);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.QuoteAsync;
begin
FFctPrv := ftpFctQuote;
ExecAsync(ftpQuoteAsync, FLocalFileName, [0], nil);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.PwdAsync;
begin
FFctPrv := ftpFctPwd;
ExecAsync(ftpPwdAsync, 'PWD', [250, 257], nil);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.CDupAsync;
begin
FFctPrv := ftpFctCDup;
ExecAsync(ftpCDupAsync, 'CDUP', [250], nil);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.RenFromAsync;
begin
FFctPrv := ftpFctRenFrom;
ExecAsync(ftpRenFromAsync, 'RNFR ' + FHostFileName, [350], nil);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.RenToAsync;
begin
FFctPrv := ftpFctRenTo;
ExecAsync(ftpRenToAsync, 'RNTO ' + FLocalFileName, [200, 250, 257], nil);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.AbortAsync;
var
bFlag : Boolean;
begin
{$IFDEF TRACE} TriggerDisplay('! Aborting'); {$ENDIF}
bFlag := (FState = ftpDnsLookup);
StateChange(ftpAbort);
if Assigned(FLocalStream) then begin
FLocalStream.Destroy;
FLocalStream := nil;
end;
if bFlag then
FControlSocket.CancelDnsLookup;
if FControlSocket.State <> wsClosed then
FControlSocket.Close;
if FDataSocket.State <> wsClosed then
FDataSocket.Close;
if FLocalStream <> nil then begin
FLocalStream.Destroy;
FLocalStream := nil;
end;
FConnected := FALSE;
StateChange(ftpReady);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomFtpCli.DoHighLevelAsync;
begin
{$IFDEF TRACE} TriggerDisplay('! HighLevelAsync ' + IntToStr(FRequestResult)); {$ENDIF}
if FState = ftpAbort then begin
{$IFDEF TRACE} TriggerDisplay('! Abort detected'); {$ENDIF}
FFctSet := [];
FHighLevelResult := 426;
FErrorMessage := '426 Operation aborted.';
end;
FNextRequest := DoHighLevelAsync;
if FRequestResult <> 0 then begin
{ Previous command had errors }
FHighLevelResult := FRequestResult;
if (FFctPrv = ftpFctQuit) or (not (ftpFctQuit in FFctSet)) then
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -