📄 ftpsrv1.cpp
字号:
StopServer();
}
//---------------------------------------------------------------------------
void __fastcall TFtpServerForm::MnuStartServerClick(TObject *Sender)
{
StartServer();
}
//---------------------------------------------------------------------------
void __fastcall TFtpServerForm::ImagesDblClick(TObject *Sender)
{
if (FtpServer1->Active)
StopServer();
else
StartServer();
}
//---------------------------------------------------------------------------
void __fastcall TFtpServerForm::UpdateClientCount(void)
{
if (FtpServer1->ClientCount == 0)
ClientCountLabel->Caption = "No user";
else
ClientCountLabel->Caption = IntToStr(FtpServer1->ClientCount) + " users";
}
//---------------------------------------------------------------------------
void __fastcall TFtpServerForm::FtpServer1ClientConnect(TObject *Sender,
TFtpCtrlSocket *Client, WORD Error)
{
// The next test shows how to refuse a client
if (Client->GetPeerAddr() == "193.121.12.25") {
Client->SendStr("421 Connection not allowed.\r\n");
Client->Close();
return;
}
InfoMemo->Lines->Add("! " + Client->GetPeerAddr() + " connected");
UpdateClientCount();
}
//---------------------------------------------------------------------------
void __fastcall TFtpServerForm::FtpServer1ClientDisconnect(TObject *Sender,
TFtpCtrlSocket *Client, WORD Error)
{
InfoMemo->Lines->Add("! " + Client->GetPeerAddr() + " disconnected");
UpdateClientCount();
}
//---------------------------------------------------------------------------
void __fastcall TFtpServerForm::FtpServer1Start(TObject *Sender)
{
GreenImage->Visible = TRUE;
RedImage->Visible = FALSE;
InfoMemo->Lines->Add("! Server started");
}
//---------------------------------------------------------------------------
void __fastcall TFtpServerForm::FtpServer1Stop(TObject *Sender)
{
GreenImage->Visible = FALSE;
RedImage->Visible = TRUE;
InfoMemo->Lines->Add("! Server stopped");
}
//---------------------------------------------------------------------------
void __fastcall TFtpServerForm::FtpServer1StorSessionConnected(
TObject *Sender, TFtpCtrlSocket *Client, TWSocket *Data, WORD Error)
{
if (Error)
InfoMemo->Lines->Add("! " + Client->GetPeerAddr() +
" Data session failed to open. Error #" +
IntToStr(Error));
}
//---------------------------------------------------------------------------
void __fastcall TFtpServerForm::FtpServer1StorSessionClosed(
TObject *Sender, TFtpCtrlSocket *Client, TWSocket *Data, WORD Error)
{
if (Error)
InfoMemo->Lines->Add("! " + Client->GetPeerAddr() +
" Data session closed. Error #" + IntToStr(Error));
}
//---------------------------------------------------------------------------
void __fastcall TFtpServerForm::FtpServer1RetrDataSent(TObject *Sender,
TFtpCtrlSocket *Client, TWSocket *Data, WORD Error)
{
if (Error)
InfoMemo->Lines->Add("! " + Client->GetPeerAddr() +
" Data sent. Error #" + IntToStr(Error));
}
//---------------------------------------------------------------------------
// This event handler is called when the data session for a get file has
// been opened. This is a good place build a file or a stream if the data
// requested is not already stored in a file on the file system.
// This feature is very powerfull and enable the FTP protocol to be used to
// retrieve any kind of data. It this sample, we just check for C:\VIRTUAL
// directory. If this directory is curent, then a TMemoryStream is created
// on the fly with some data. If another directory is selected, the FTP
// server works as any other: just send the requested file, if it exist !
// This event handler is also a place where you can abort the file transfer.
// Simply trigger an exception and transfer will not take place.
// Note that if you just wants to prohibe access to some directory or file,
// the best place to code that is in the OnValidateGet or OnValidatePut
// event handlers.
void __fastcall TFtpServerForm::FtpServer1RetrSessionConnected(
TObject *Sender, TFtpCtrlSocket *Client, TWSocket *Data, WORD Error)
{
AnsiString Buf;
if (Error)
InfoMemo->Lines->Add("! " + Client->GetPeerAddr() +
" Data session connected. Error #" + IntToStr(Error));
else if (UpperCase(Client->FilePath).SubString(1, 19) == "C:\\VIRTUAL\\FORBIDEN")
throw Exception("Access prohibed !");
else if (UpperCase(Client->FilePath).SubString(1, 11) == "C:\\VIRTUAL\\") {
InfoMemo->Lines->Add("! VIRTUAL FILE");
Client->UserData = 1; // Remember we created a stream
if (Client->DataStream)
delete Client->DataStream; // Prevent memory leaks
Client->DataStream = new TMemoryStream;
Buf = "This is a file created on the fly by the FTP server\r\n"
"It could result of a query to a database or anything else.\r\n"
"The request was: \"" + Client->FilePath + "\"\r\n";
Client->DataStream->Write(&Buf[1], Buf.Length());
Client->DataStream->Seek(0, 0);
}
}
//---------------------------------------------------------------------------
void __fastcall TFtpServerForm::FtpServer1RetrSessionClosed(
TObject *Sender, TFtpCtrlSocket *Client, TWSocket *Data, WORD Error)
{
if (Error)
InfoMemo->Lines->Add("! " + Client->GetPeerAddr() +
" Data session closed. Error #" + IntToStr(Error));
if (Client->UserData == 1) {
// We created a stream for a virtual file or dir. Delete the TStream
if (Client->DataStream) {
// There is no reason why we should not come here, but who knows ?
delete Client->DataStream;
Client->DataStream = NULL;
}
Client->UserData = 0; // Reset the flag
}
}
//---------------------------------------------------------------------------
// This event handler is called when the FTP component needs to build a
// directory listing. You can just return without doing anything then the
// component will build the directory for you, based on the actual disk
// content. But you can also build your own directory listing with anything
// you like in it. Just create a stream with the required content. The
// example below construct a virtual directory when the user is on the
// C:\VIRTUAL subdirectory (use elsewhere in this sample program).
void __fastcall TFtpServerForm::FtpServer1BuildDirectory(TObject *Sender,
TFtpCtrlSocket *Client, TFtpString &Directory, bool Detailed)
{
AnsiString Buf;
if (UpperCase(Client->Directory) != "C:\\VIRTUAL\\")
return;
InfoMemo->Lines->Add("! VIRTUAL DIR");
Client->UserData = 1; // Remember we created a stream
if (Client->DataStream)
delete Client->DataStream; // Prevent memory leaks
Client->DataStream = new TMemoryStream;
if (Detailed)
// We need to format directory lines according to the Unix standard
Buf =
"-rwxrwxrwx 1 ftp ftp 0 Apr 30 19:00 FORBIDEN\r\n"
"-rwxrwxrwx 1 ftp ftp 0 Apr 30 19:00 TEST\r\n"
"drwxrwxrwx 1 ftp ftp 0 Apr 30 19:00 SOME DIR\r\n";
else
Buf = "FORBIDEN\r\nTEST\r\r";
Client->DataStream->Write(&Buf[1], Buf.Length());
Client->DataStream->Seek(0, 0);
}
//---------------------------------------------------------------------------
// This event handler is called by the FTP component once it has built the
// directory listing. We can use this handler to alter the listing, adding
// or removing some info. This sample add the 'virtual' directory.
void __fastcall TFtpServerForm::FtpServer1AlterDirectory(TObject *Sender,
TFtpCtrlSocket *Client, TFtpString &Directory, bool Detailed)
{
AnsiString Buf;
if (UpperCase(Client->Directory) != "C:\\")
return;
// Add our 'virtual' directory to the list
if (Detailed) {
// We need to format directory lines according to the Unix standard
Buf =
"drwxrwxrwx 1 ftp ftp 0 Apr 30 19:00 VIRTUAL\r\n";
Client->DataStream->Write(&Buf[1], Buf.Length());
}
}
//---------------------------------------------------------------------------
void __fastcall TFtpServerForm::FtpServer1ClientCommand(TObject *Sender,
TFtpCtrlSocket *Client, TFtpString &Keyword, TFtpString &Params,
TFtpString &Answer)
{
InfoMemo->Lines->Add("< " + Client->GetPeerAddr() + " " +
Keyword + " " + Params);
}
//---------------------------------------------------------------------------
void __fastcall TFtpServerForm::FtpServer1AnswerToClient(TObject *Sender,
TFtpCtrlSocket *Client, TFtpString &Answer)
{
InfoMemo->Lines->Add("> " + Client->GetPeerAddr() + " " + Answer);
}
//---------------------------------------------------------------------------
void __fastcall TFtpServerForm::FtpServer1Authenticate(TObject *Sender,
TFtpCtrlSocket *Client, TFtpString &UserName, TFtpString &Password,
bool &Authenticated)
{
// You should place here the code needed to authenticate the user.
// For example a text file with all permitted username/password.
// If the user can't be authenticated, just set Authenticated to
// false before returning.
// It is also the right place to setup Client.HomeDir
// If you need to store info about the client for later processing
// you can use Client->UserData to store a pointer to an object or
// a record with the needed info.
InfoMemo->Lines->Add("! " + Client->GetPeerAddr() +
" User \"" + UserName + "\" is authenticated");
}
//---------------------------------------------------------------------------
void __fastcall TFtpServerForm::FtpServer1ChangeDirectory(TObject *Sender,
TFtpCtrlSocket *Client, TFtpString &Directory, bool &Allowed)
{
#ifdef never
// It the right place to check if a user has access to a given directory
// The example below disable C:\ access to non root user.
if (UpperCase(Client->UserName) != "ROOT") &&
(UpperCase(Client->Directory) = "C:\\")
Allowed = FALSE;
#endif
}
//---------------------------------------------------------------------------
void __fastcall TFtpServerForm::Cleardisplay1Click(TObject *Sender)
{
InfoMemo->Clear();
}
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -