📄 ftpsrv.pas
字号:
inherited Create(AOwner);
FWindowHandle := ftpsrvAllocateHWnd(WndProc);
FServSocket := TWSocket.Create(Self);
FServSocket.Name := 'ServerWSocket';
FClientList := TList.Create;
FPort := 'ftp';
FAddr := '0.0.0.0';
FBanner := msgDftBanner;
FClientClass := TFtpCtrlSocket;
FOptions := [];
{ !!!!!!!!!!! NGB: Added next five lines }
FPasvIpAddr := '';
FPasvPortRangeStart := 0;
FPasvPortRangeSize := 0;
FPasvPortTable := nil;
FPasvPortTableSize := 0;
{ !!!!!!!!!!! NGB: Added previous five lines }
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);
AddCommand('MDTM', CommandMDTM);
AddCommand('MODE', CommandMODE);
AddCommand('OVER', CommandOverflow);
AddCommand('STOU', CommandSTOU);
AddCommand('FEAT', CommandFEAT);
AddCommand('MLST', CommandMLST); { angus V1.38 }
AddCommand('MLSD', CommandMLSD); { angus V1.38 }
AddCommand('MFMT', CommandMDTM); { angus V1.39 }
AddCommand('MD5', CommandMD5); { angus V1.39 }
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;
if Assigned(FPasvPortTable) then begin
FreeMem(FPasvPortTable, FPasvPortTableSize);
FPasvPortTable := nil;
FPasvPortTableSize := 0;
end;
ftpsrvDeallocateHWnd(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);
WM_FTPSRV_START_SEND : WMFtpSrvStartSend(MsgRec);
else
Result := DefWindowProc(Handle, Msg, wParam, lParam);
end;
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TFtpServer.WMFtpSrvCloseRequest(var msg: TMessage);
var
Client : TFtpCtrlSocket;
I : Integer;
begin
Client := TFtpCtrlSocket(msg.LParam);
I := FClientList.IndexOf(Client);
if I >= 0 then begin
{ Check if client.ID is still the same as when message where posted }
if WPARAM(TFtpCtrlSocket(FClientList.Items[I]).ID) = Msg.WParam then begin
if Client.AllSent then
Client.Close
else
Client.CloseRequest := TRUE;
end;
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TFtpServer.Notification(AComponent: TComponent; operation: TOperation);
begin
inherited Notification(AComponent, operation);
if operation = opRemove then begin
if AComponent = FServSocket then
FServSocket := nil;
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TFtpServer.AddCommand(
const Keyword : String;
const Proc : TFtpSrvCommandProc);
begin
if FLastCmd > High(FCmdTable) then
raise FtpServerException.Create('Too many command');
FCmdTable[FLastCmd].KeyWord := KeyWord;
FCmdTable[FLastCmd].Proc := Proc;
Inc(FLastCmd);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TFtpServer.Start;
begin
if FServSocket.State = wsListening then
Exit; { Server is already running }
FServSocket.Port := Port;
FServSocket.Proto := 'tcp';
FServSocket.Addr := FAddr;
FServSocket.OnSessionAvailable := ServSocketSessionAvailable;
FServSocket.OnChangeState := ServSocketStateChange;
FServSocket.ComponentOptions := [wsoNoReceiveLoop];
FServSocket.Listen;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TFtpServer.Stop;
begin
FServSocket.Close;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TFtpServer.DisconnectAll;
var
Client : TFtpCtrlSocket;
Msg : TMessage;
begin
while FClientList.Count > 0 do begin
Client := TFtpCtrlSocket(FClientList.Items[0]);
FillChar(Msg, SizeOf(Msg), 0);
Msg.LParam := Integer(Client);
Msg.WParam := Client.ID;
WMFtpSrvClientClosed(Msg);
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TFtpServer.Disconnect(Client : TFtpCtrlSocket);
var
I : Integer;
Msg : TMessage;
begin
I := FClientList.IndexOf(Client);
if I < 0 then
raise FtpServerException.Create('Disconnect: Not one of our clients');
FillChar(Msg, SizeOf(Msg), 0);
Msg.LParam := Integer(Client);
Msg.WParam := Client.ID;
WMFtpSrvClientClosed(Msg);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
function TFtpServer.GetActive : Boolean;
begin
Result := (FServSocket.State = wsListening);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TFtpServer.SetActive(newValue : Boolean);
begin
if newValue then
Start
else
Stop;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TFtpServer.ServSocketStateChange(Sender : TObject; OldState, NewState : TSocketState);
begin
if csDestroying in ComponentState then
Exit;
if NewState = wsListening then
TriggerServerStart
else if NewState = wsClosed then
TriggerServerStop;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TFtpServer.ServSocketSessionAvailable(Sender : TObject; AError : Word);
var
Client : TFtpCtrlSocket;
begin
if AError <> 0 then
raise FtpServerException.Create('Session available error #' + IntToStr(AError));
Inc(FClientNum);
Client := FClientClass.Create(Self);
FClientList.Add(Client);
Client.Name := 'ClientWSocket' + IntToStr(FClientNum);
Client.DataSocket.Name := 'DataWSocket' + IntToStr(FClientNum);
Client.ID := FClientNum;
Client.Banner := FBanner;
Client.HSocket := ServSocket.Accept;
Client.OnCommand := ClientCommand;
Client.OnSessionClosed := ClientSessionClosed;
Client.OnDataSent := ClientDataSent;
if ftpsCdupHome in FOptions then
Client.Op
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -