|
The OnMLST event Recently, I added a new OnMLST event to our FTP server
component. I decided that this was necessary because the
regular OnListDirectory event handler would probably be a mess if I
didn't. The reason is that the OnListDirectory is triggered by the LIST
and MLSD commands. Usually, when listing
a directory, if you specify a subdirectory such as "pub", you usually want
the contents of that directory and the MLSD
command requires that behavior. The MLST
command is intended to give information about one particular item so if you
wanted information about the pub directory, the command would be "MLST
pub". I have found that NcFTP Client
does use the MLST command to get information
about a file or verify that it exists.
The MLST event is defined like this:
procedure TForm1.IdFTPServer1MLST(ASender: TIdFTPServerContext;
const APath: string; ADirectoryListing: TIdFTPListOutput);
The reason why we do not simply provide one TIdFTPListOutputItem that you
simply fill in is because you might have an occaision where you may need to have
two "type" facts in your information. Thus, there can be more than one
entry.
Here is a sample showing how this event is used. Note that this does
use the Win32 API. I've already described the reason that I don't use FindFirst Borland RTL function.
function TForm1.FileTimeToTDateTime(const AFileTime: TFileTime): TDateTime;
var LDosTime : LongInt;
begin
Result := 0;
if Windows.FileTimeToDosDateTime(AFileTime, LongRec(LDosTime).Hi,
LongRec(LDosTime).Lo) then
begin
Result := SysUtils.FileDateToDateTime(LDosTime);
end
else
begin
SysUtils.RaiseLastOSError;
end;
end;
procedure TForm1.IdFTPServer1MLST(ASender: TIdFTPServerContext;
const APath: string; ADirectoryListing: TIdFTPListOutput);
var
LFTPItem :TIdFTPListOutputItem;
SR : TSearchRec;
SRI : Integer;
LTmpPath : String;
begin
//for this, we return information only about the item, not the contents
LTmpPath := RemoveTrailingPathDel ( ReplaceChars(AppDir + APath));
if LTmpPath = '' then
begin
LFTPItem := ADirectoryListing.Add;
LFTPItem.ItemType := ditDirectory;
LFTPItem.FileName := '/';
Exit;
end;
SRI := FindFirst(LTmpPath, faAnyFile , SR);
if SRI = 0 then
begin
LFTPItem := ADirectoryListing.Add;
//This is necessary because the Borland RTL FindData Size is an Integer and can't handle
//anything greater than 2GB.
LFTPItem.Size := Int64(SR.FindData.nFileSizeHigh shl 32) + SR.FindData.nFileSizeLow;
//
// The file name returned in the MLST response should be the same name
// as was specified in the MLST command, or, where TVFS is supported, a
// fully qualified TVFS path naming the same file. Where no argument
// was given to the MLST command, the server-PI may either include an
// empty file name in the response, or it may supply a name that refers
// to the current directory, if such a name is available. Where TVFS is
// supported, a fully qualified pathname of the current directory SHOULD
// be returned.
//
LTmpPath := RemoveTrailingPathDel(ReplaceChars(ASender.HomeDir + APath));
if LTmpPath = '' then
begin
LTmpPath := '/';
end;
LFTPItem.FileName := StringReplace(LTmpPath,'\','/',[rfReplaceAll]);
LFTPItem.ModifiedDateGMT := FileTimeToTDateTime( SR.FindData.ftLastWriteTime);
LFTPItem.CreationDateGMT := FileTimeToTDateTime( SR.FindData.ftCreationTime);
LFTPItem.LastAccessDateGMT := FileTimeToTDateTime( SR.FindData.ftLastAccessTime);
LFTPItem.WinAttribs := SR.FindData.dwFileAttributes;
if SR.Attr and faDirectory > 0 then
begin
LFTPItem.ItemType := ditDirectory;
end
else
begin
LFTPItem.ItemType := ditFile;
end;
FindClose(SR);
end
else
begin
RaiseLastOSError;
end;
end;
As you can tell, this fairly streinghforward. The code is from a sample I
intend to make available soon. If you want to be more selective
about processing certain file facts (only obtain them if the client specifically
negotiated them), you can use the ASender.MLSOpts set (or enumeration in
C#). The values it contains currently are:
ItemType,Modify,Size,Perm,Unique,UnixMODE,UnixOwner, UnixGroup,CreateTime,LastAccessTime,WinAttribs
I will leave the more fancy work as an excersize for our
readers.
|
|
Corporate Sponsors

|