📄 ftpsrv.pas
字号:
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Start;
procedure Stop;
procedure DisconnectAll;
procedure WndProc(var MsgRec: TMessage);
property ServSocket : TWSocket read FServSocket;
property Handle : HWND read FWindowHandle;
property ClientCount : Integer read GetClientCount;
property Active : Boolean read GetActive
write SetActive;
property ClientClass : TFtpCtrlSocketClass
read FClientClass
write FClientClass;
published
property Port : String read FPort
write FPort;
property Banner : String read FBanner
write FBanner;
property UserData : LongInt read FUserData
write FUserData;
property MaxClients : LongInt read FMaxClients
write FMaxClients;
property OnStart : TNotifyEvent
read FOnStart
write FOnStart;
property OnStop : TNotifyEvent
read FOnStop
write FOnStop;
property OnAuthenticate : TFtpSrvAuthenticateEvent
read FOnAuthenticate
write FOnAuthenticate;
property OnClientDisconnect : TFtpSrvClientConnectEvent
read FOnClientDisconnect
write FOnClientDisconnect;
property OnClientConnect : TFtpSrvClientConnectEvent
read FOnClientConnect
write FOnClientConnect;
property OnClientCommand : TFtpSrvClientCommandEvent
read FOnClientCommand
write FOnClientCommand;
property OnAnswerToClient : TFtpSrvAnswerToClientEvent
read FOnAnswerToClient
write FOnAnswerToClient;
property OnChangeDirectory : TFtpSrvChangeDirectoryEvent
read FOnChangeDirectory
write FOnChangeDirectory;
property OnMakeDirectory : TFtpSrvChangeDirectoryEvent
read FOnMakeDirectory
write FOnMakeDirectory;
property OnBuildDirectory : TFtpSrvBuildDirectoryEvent
read FOnBuildDirectory
write FOnBuildDirectory;
property OnAlterDirectory : TFtpSrvBuildDirectoryEvent
read FOnAlterDirectory
write FOnAlterDirectory;
property OnStorSessionConnected : TFtpSrvDataSessionConnectedEvent
read FOnStorSessionConnected
write FOnStorSessionConnected;
property OnRetrSessionConnected : TFtpSrvDataSessionConnectedEvent
read FOnRetrSessionConnected
write FOnRetrSessionConnected;
property OnStorSessionClosed : TFtpSrvDataSessionConnectedEvent
read FOnStorSessionClosed
write FOnStorSessionClosed;
property OnRetrSessionClosed : TFtpSrvDataSessionConnectedEvent
read FOnRetrSessionClosed
write FOnRetrSessionClosed;
property OnRetrDataSent : TFtpSrvRetrDataSentEvent
read FOnRetrDataSent
write FOnRetrDataSent;
property OnValidatePut : TFtpSrvValidateXferEvent
read FOnValidatePut
write FOnValidatePut;
property OnValidateDele : TFtpSrvValidateXferEvent
read FOnValidateDele
write FOnValidateDele;
property OnValidateGet : TFtpSrvValidateXferEvent
read FOnValidateGet
write FOnValidateGet;
property OnStorDataAvailable : TFtpSrvDataAvailableEvent
read FOnStorDataAvailable
write FOnStorDataAvailable;
end;
procedure Register;
implementation
const
msgDftBanner = '220 ICS FTP Server ready.';
msgTooMuchClients = '421 Too many users connected.';
msgCmdUnknown = '500 ''%s'': command not understood.';
msgLoginFailed = '530 Login incorrect.';
msgNotLogged = '530 Please login with USER and PASS.';
msgNoUser = '503 Login with USER first.';
msgLogged = '230 User %s logged in.';
msgPassRequired = '331 Password required for %s.';
msgCWDSuccess = '250 CWD command successful. "%s" is current directory.';
msgCWDFailed = '501 CWD failed. %s';
msgPWDSuccess = '257 "%s" is current directory.';
msgQuit = '221 Goodbye.';
msgPortSuccess = '200 Port command successful.';
msgPortFailed = '501 Invalid PORT command.';
msgStorDisabled = '501 Permission Denied'; {'500 Cannot STOR.';}
msgStorSuccess = '150 Opening data connection for %s.';
msgStorFailed = '501 Cannot STOR. %s';
msgStorAborted = '426 Connection closed; %s.';
msgStorOk = '226 File received ok';
msgStorError = '426 Connection closed; transfer aborted. Error #%d';
msgRetrDisabled = '500 Cannot RETR.';
msgRetrSuccess = '150 Opening data connection for %s.';
msgRetrFailed = '501 Cannot RETR. %s';
msgRetrAborted = '426 Connection closed; %s.';
msgRetrOk = '226 File sent ok';
msgRetrError = '426 Connection closed; transfer aborted. Error #%d';
msgSystem = '215 UNIX Type: L8 Internet Component Suite';
msgDirOpen = '150 Opening data connection for directory list.';
msgDirFailed = '451 Failed: %s.';
msgTypeOk = '200 Type set to %s.';
msgTypeFailed = '500 ''TYPE %s'': command not understood.';
msgDeleNotExists = '550 ''%s'': no such file or directory.';
msgDeleOk = '250 File ''%s'' deleted.';
msgDeleFailed = '450 File ''%s'' can''t be deleted.';
msgDeleSyntax = '501 Syntax error in parameter.';
msgDeleDisabled = '500 Cannot DELE.';
msgRnfrNotExists = '550 ''%s'': no such file or directory.';
msgRnfrSyntax = '501 Syntax error is parameter.';
msgRnfrOk = '350 File exists, ready for destination name.';
msgRntoNotExists = '550 ''%s'': no such file or directory.';
msgRntoAlready = '553 ''%s'': file already exists.';
msgRntoOk = '250 File ''%s'' renamed to ''%s''.';
msgRntoFailed = '450 File ''%s'' can''t be renamed.';
msgRntoSyntax = '501 Syntax error in parameter.';
msgMkdOk = '257 ''%s'': directory created.';
msgMkdAlready = '550 ''%s'': file or directory already exists.';
msgMkdFailed = '550 ''%s'': can''t create directory.';
msgMkdSyntax = '501 Syntax error in parameter.';
msgRmdOk = '250 ''%s'': directory removed.';
msgRmdNotExists = '550 ''%s'': no such directory.';
msgRmdFailed = '550 ''%s'': can''t remove directory.';
msgRmdSyntax = '501 Syntax error in parameter.';
msgNoopOk = '200 Ok. Parameter was ''%s''.';
msgAborOk = '225 ABOR command successful.';
msgPasvLocal = '227 Entering Passive Mode (127,0,0,1,%d,%d).';
msgPasvRemote = '227 Entering Passive Mode (%d,%d,%d,%d,%d,%d).';
msgPasvExcept = '500 PASV exception: ''%s''.';
msgSizeOk = '213 %d';
msgSizeFailed = '550 Command failed: %s.';
msgSizeSyntax = '501 Syntax error in parameter.';
msgRestOk = '350 REST supported. Ready to resume at byte offset %d.';
msgRestZero = '501 Required byte offset parameter bad or missing.';
msgRestFailed = '501 Syntax error in parameter: %s.';
msgAppeFailed = '550 APPE failed.';
msgAppeSuccess = '150 Opening data connection for %s (append).';
msgAppeDisabled = '500 Cannot APPE.';
msgAppeAborted = '426 Connection closed; %s.';
msgAppeOk = '226 File received ok';
msgAppeError = '426 Connection closed; transfer aborted. Error #%d';
msgAppeReady = '150 APPE supported. Ready to append file "%s" at offset %d.';
msgStruOk = '200 Ok. STRU parameter ''%s'' ignored.';
function SlashesToBackSlashes(const S : String) : String; forward;
function BackSlashesToSlashes(const S : String) : String; forward;
function BuildFilePath(const Directory : String;
FileName : String) : String; forward;
var
ThisYear, ThisMonth, ThisDay : Word;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure Register;
begin
RegisterComponents('FPiette', [TFtpServer]);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{$IFDEF VER80}
procedure SetLength(var S: string; NewLength: Integer);
begin
S[0] := chr(NewLength);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
function TrimRight(Str : String) : String;
var
i : Integer;
begin
i := Length(Str);
while (i > 0) and (Str[i] = ' ') do
i := i - 1;
Result := Copy(Str, 1, i);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
function TrimLeft(Str : String) : String;
var
i : Integer;
begin
if Str[1] <> ' ' then
Result := Str
else begin
i := 1;
while (i <= Length(Str)) and (Str[i] = ' ') do
i := i + 1;
Result := Copy(Str, i, Length(Str) - i + 1);
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
function Trim(Str : String) : String;
begin
Result := TrimLeft(TrimRight(Str));
end;
{$ENDIF}
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
function GetFileSize(FileName : String) : LongInt;
var
SR : TSearchRec;
begin
if FindFirst(FileName, faReadOnly or faHidden or
faSysFile or faArchive, SR) = 0 then
Result := SR.Size
else
Result := -1;
FindClose(SR);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
constructor TFtpServer.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FWindowHandle := AllocateHWnd(WndProc);
FServSocket := TWSocket.Create(Self);
FServSocket.Name := 'ServerWSocket';
FClientList := TList.Create;
FPort := 'ftp';
FBanner := msgDftBanner;
FClientClass := TFtpCtrlSocket;
AddCommand('PORT', CommandPORT);
AddCommand('STOR', CommandSTOR);
AddCommand('RETR', CommandRETR);
AddCommand('CWD', CommandCWD);
AddCommand('XPWD', CommandXPWD);
AddCommand('PWD', CommandPWD);
AddCommand('USER', CommandUSER);
AddCommand('PASS', CommandPASS);
AddCommand('LIST', CommandLIST);
AddCommand('NLST', CommandNLST);
AddCommand('TYPE', CommandTYPE);
AddCommand('SYST', CommandSYST);
AddCommand('QUIT', CommandQUIT);
AddCommand('DELE', CommandDELE);
AddCommand('SIZE', CommandSIZE);
AddCommand('REST', CommandREST);
AddCommand('RNFR', CommandRNFR);
AddCommand('RNTO', CommandRNTO);
AddCommand('MKD', CommandMKD);
AddCommand('RMD', CommandRMD);
AddCommand('ABOR', CommandABOR);
AddCommand('PASV', CommandPASV);
AddCommand('NOOP', CommandNOOP);
AddCommand('CDUP', CommandCDUP);
AddCommand('APPE', CommandAPPE);
AddCommand('STRU', CommandSTRU);
AddCommand('XMKD', CommandMKD);
AddCommand('XRMD', CommandRMD);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
destructor TFtpServer.Destroy;
begin
if Assigned(FServSocket) then begin
FServSocket.Destroy;
FServSocket := nil;
end;
if Assigned(FClientList) then begin
FClientList.Destroy;
FClientList := nil;
end;
DeallocateHWnd(FWindowHandle);
inherited Destroy;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TFtpServer.WndProc(var MsgRec: TMessage);
begin
with MsgRec do begin
case Msg of
WM_FTPSRV_CLOSE_REQUEST : WMFtpSrvCloseRequest(MsgRec);
WM_FTPSRV_CLIENT_CLOSED : WMFtpSrvClientClosed(MsgRec);
WM_FTPSRV_ABORT_TRANSFER : WMFtpSrvAbortTransfer(MsgRec);
WM_FTPSRV_CLOSE_DATA : WMFtpSrvCloseData(MsgRec);
else
Result := DefWindowProc(Handle, Msg, wParam, lParam);
end;
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TFtpServer.WMFtpSrvCloseRequest(var msg: TMessage);
var
Client : TFtpCtrlSocket;
begin
Client := TFtpCtrlSocket(msg.LParam);
if Client.AllSent then
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -