608 lines
19 KiB
Plaintext
608 lines
19 KiB
Plaintext
{
|
||
$Project$
|
||
$Workfile$
|
||
$Revision$
|
||
$DateUTC$
|
||
$Id$
|
||
|
||
This file is part of the Indy (Internet Direct) project, and is offered
|
||
under the dual-licensing agreement described on the Indy website.
|
||
(http://www.indyproject.org/)
|
||
|
||
Copyright:
|
||
(c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
|
||
}
|
||
{
|
||
$Log$
|
||
}
|
||
{
|
||
Rev 1.8 2/24/2005 10:01:34 AM JPMugaas
|
||
Fixed estimation of filesize for variable record length files (V) in z/VM to
|
||
conform to what was specified in:
|
||
|
||
z/VMTCP/IP User’s Guide Version 5 Release 1.0
|
||
|
||
This will not always give the same estimate as the server would when listing
|
||
in Unix format "SITE LISTFORMAT UNIX" because we can't know the block size
|
||
(we have to assume a size of 4096).
|
||
|
||
Rev 1.7 10/26/2004 10:03:20 PM JPMugaas
|
||
Updated refs.
|
||
|
||
Rev 1.6 9/7/2004 10:02:30 AM JPMugaas
|
||
Tightened the VM/BFS parser detector so that valid dates have to start the
|
||
listing item. This should reduce the likelyhood of error.
|
||
|
||
Rev 1.5 6/28/2004 4:34:18 AM JPMugaas
|
||
VM_CMS-ftp.marist.edu-7.txt was being detected as VM/BFS instead of VM/CMS
|
||
causing a date encode error.
|
||
|
||
Rev 1.4 4/19/2004 5:05:32 PM JPMugaas
|
||
Class rework Kudzu wanted.
|
||
|
||
Rev 1.3 2004.02.03 5:45:22 PM czhower
|
||
Name changes
|
||
|
||
Rev 1.2 10/19/2003 3:48:12 PM DSiders
|
||
Added localization comments.
|
||
|
||
Rev 1.1 4/7/2003 04:04:30 PM JPMugaas
|
||
User can now descover what output a parser may give.
|
||
|
||
Rev 1.0 2/19/2003 04:18:20 AM JPMugaas
|
||
More things restructured for the new list framework.
|
||
}
|
||
|
||
unit IdFTPListParseVM;
|
||
|
||
{
|
||
IBM VM and z/VM parser
|
||
}
|
||
|
||
interface
|
||
|
||
{$i IdCompilerDefines.inc}
|
||
|
||
uses
|
||
Classes,
|
||
IdFTPList, IdFTPListParseBase, IdFTPListTypes;
|
||
|
||
type
|
||
TIdVMCMSFTPListItem = class(TIdRecFTPListItem)
|
||
protected
|
||
FOwnerName : String;
|
||
FNumberBlocks : Integer;
|
||
public
|
||
property RecLength : Integer read FRecLength write FRecLength;
|
||
property RecFormat : String read FRecFormat write FRecFormat;
|
||
property NumberRecs : Integer read FNumberRecs write FNumberRecs;
|
||
property OwnerName : String read FOwnerName write FOwnerName;
|
||
property NumberBlocks : Integer read FNumberBlocks write FNumberBlocks;
|
||
end;
|
||
|
||
TIdVMVirtualReaderFTPListItem = class(TIdFTPListItem)
|
||
protected
|
||
FNumberRecs : Integer;
|
||
public
|
||
constructor Create(AOwner: TCollection); override;
|
||
property NumberRecs : Integer read FNumberRecs write FNumberRecs;
|
||
end;
|
||
|
||
TIdVMBFSFTPListItem = class(TIdFTPListItem);
|
||
|
||
TIdFTPLPVMCMS = class(TIdFTPListBaseHeaderOpt)
|
||
protected
|
||
class function IsHeader(const AData : String): Boolean; override;
|
||
class function MakeNewItem(AOwner : TIdFTPListItems) : TIdFTPListItem; override;
|
||
class function ParseLine(const AItem : TIdFTPListItem; const APath : String = ''): Boolean; override;
|
||
class function CheckListingAlt(AListing : TStrings; const ASysDescript : String = ''; const ADetails : Boolean = True): Boolean; override;
|
||
public
|
||
class function GetIdent : String; override;
|
||
end;
|
||
|
||
TIdFTPLPVMBFS = class(TIdFTPListBase)
|
||
protected
|
||
class function MakeNewItem(AOwner : TIdFTPListItems) : TIdFTPListItem; override;
|
||
class function ParseLine(const AItem : TIdFTPListItem; const APath : String = ''): Boolean; override;
|
||
public
|
||
class function GetIdent : String; override;
|
||
class function CheckListing(AListing : TStrings; const ASysDescript : String = ''; const ADetails : Boolean = True): Boolean; override;
|
||
end;
|
||
|
||
TIdFTPLVirtualReader = class(TIdFTPListBase)
|
||
protected
|
||
class function MakeNewItem(AOwner : TIdFTPListItems) : TIdFTPListItem; override;
|
||
class function ParseLine(const AItem : TIdFTPListItem; const APath : String = ''): Boolean; override;
|
||
public
|
||
class function GetIdent : String; override;
|
||
class function CheckListing(AListing : TStrings; const ASysDescript : String = ''; const ADetails : Boolean = True): Boolean; override;
|
||
|
||
end;
|
||
|
||
// RLebeau 2/14/09: this forces C++Builder to link to this unit so
|
||
// RegisterFTPListParser can be called correctly at program startup...
|
||
|
||
{$IFDEF HAS_DIRECTIVE_HPPEMIT_LINKUNIT}
|
||
{$HPPEMIT LINKUNIT}
|
||
{$ELSE}
|
||
{$HPPEMIT '#pragma link "IdFTPListParseVM"'}
|
||
{$ENDIF}
|
||
|
||
implementation
|
||
|
||
uses
|
||
IdException,
|
||
IdGlobal, IdFTPCommon, IdGlobalProtocols,
|
||
SysUtils;
|
||
|
||
function IsFileMode(const AStr : String) : Boolean;
|
||
begin
|
||
Result := CharIsInSet(AStr,1,'ABCDEFGHIJKLMNOPQRSTUV') and
|
||
CharIsInSet(AStr,2,'0123456');
|
||
end;
|
||
|
||
{ TIdFTPLPVMCMS }
|
||
|
||
class function TIdFTPLPVMCMS.CheckListingAlt(AListing: TStrings; const ASysDescript: String;
|
||
const ADetails: Boolean): Boolean;
|
||
const
|
||
VMTypes : array [1..3] of string = ('F','V','DIR'); {do not localize}
|
||
var
|
||
LData : String;
|
||
|
||
begin
|
||
Result := False;
|
||
if AListing.Count > 0 then begin
|
||
LData := AListing[0];
|
||
if IsFileMode(Trim(Copy(LData, 19, 3))) then begin
|
||
Result := PosInStrArray(Trim(Copy(LData, 22, 3)), VMTypes) <> -1;
|
||
if Result then begin
|
||
Result := IsMMDDYY(Trim(Copy(LData,52,10)),'/');
|
||
end;
|
||
end else begin
|
||
Result := PosInStrArray(Trim(Copy(LData, 19, 3)), VMTypes) <> -1;
|
||
if Result then begin
|
||
Result := (Copy(LData, 56, 1) = '/') and (Copy(LData, 59, 1) = '/'); {do not localize}
|
||
if not Result then begin
|
||
Result := (Copy(LData, 58, 1) = '-') and (Copy(LData, 61, 1) = '-'); {do not localize}
|
||
if not Result then begin
|
||
Result := (Copy(LData, 48, 1) = '-') and (Copy(LData, 51, 1) = '-'); {do not localize}
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
class function TIdFTPLPVMCMS.GetIdent: String;
|
||
begin
|
||
Result := 'VM/CMS'; {do not localize}
|
||
end;
|
||
|
||
class function TIdFTPLPVMCMS.IsHeader(const AData: String): Boolean;
|
||
begin
|
||
Result := Trim(AData) = 'Filename FileType Fm Format Lrecl Records Blocks Date Time'
|
||
end;
|
||
|
||
class function TIdFTPLPVMCMS.MakeNewItem(AOwner: TIdFTPListItems): TIdFTPListItem;
|
||
begin
|
||
Result := TIdVMCMSFTPListItem.Create(AOwner);
|
||
end;
|
||
|
||
class function TIdFTPLPVMCMS.ParseLine(const AItem: TIdFTPListItem;
|
||
const APath: String): Boolean;
|
||
var
|
||
LBuffer : String;
|
||
LCols : TStrings;
|
||
LI : TIdVMCMSFTPListItem;
|
||
LSize : Int64;
|
||
LPRecLn,LLRecLn : Integer;
|
||
LPRecNo, LLRecNo : Integer;
|
||
LPBkNo,LLBkNo : Integer;
|
||
LPCol : Integer;
|
||
begin
|
||
{Some of this is based on the following:
|
||
|
||
http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=utf-8&threadm=4e7k0p%24t1v%40blackice.winternet.com&rnum=4&prev=/groups%3Fq%3DVM%2BFile%2BRecords%2Bdirectory%26hl%3Den%26lr%3D%26ie%3DUTF-8%26oe%3Dutf-8%26selm%3D4e7k0p%2524t1v%2540blackice.winternet.com%26rnum%3D4
|
||
|
||
and
|
||
|
||
http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=utf-8&selm=DLspv2.G2w%40epsilon.com&rnum=2
|
||
}
|
||
{
|
||
123456789012345678901234567890123456789012345678901234567890123456789012
|
||
1 2 3 4 5 6 7
|
||
OMA00215 PLAN V 64 28 1 6/26/02 9:33:21 -
|
||
WEBSHARE DIR - - - 5/30/97 18:44:17 -
|
||
|
||
or
|
||
|
||
README ANONYMOU V 71 26 1 1997-04-02 12:33:20 TCP291
|
||
|
||
or maybe this:
|
||
|
||
ENDTRACE TCPIP F 80 1 1 1999-07-28 12:24:01 TCM191
|
||
123456789012345678901234567890123456789012345678901234567890123456789012
|
||
1 2 3 4 5 6 7
|
||
|
||
or possibly this FILELIST format:
|
||
|
||
Filename FileType Fm Format Lrecl Records Blocks Date Time
|
||
LASTING GLOBALV A1 V 41 21 1 9/16/91 15:10:32
|
||
J43401 NETLOG A0 V 77 1 1 9/12/91 12:36:04
|
||
PROFILE EXEC A1 V 17 3 1 9/12/91 12:39:07
|
||
DIRUNIX SCRIPT A1 V 77 1216 17 1/04/93 20:30:47
|
||
MAIL PROFILE A2 F 80 1 1 10/14/92 16:12:27
|
||
BADY2K TEXT A0 V 1 1 1 1/03/102 10:11:12
|
||
AUTHORS A1 DIR - - - 9/20/99 10:31:11
|
||
---------------
|
||
|
||
123456789012345678901234567890123456789012345678901234567890123456789012
|
||
1 2 3 4 5 6 7
|
||
|
||
}
|
||
LI := AItem as TIdVMCMSFTPListItem;
|
||
//File Name
|
||
LI.FileName := Trim(Copy(AItem.Data, 1, 8));
|
||
//File Type - extension
|
||
if LI.Data[9] = ' ' then begin
|
||
LBuffer := Copy(AItem.Data, 10, 9);
|
||
end else begin
|
||
LBuffer := Copy(AItem.Data, 9, 9);
|
||
end;
|
||
LBuffer := Trim(LBuffer);
|
||
if LBuffer <> '' then begin
|
||
LI.FileName := LI.FileName + '.' + LBuffer; {do not localize}
|
||
end;
|
||
//Record format
|
||
LBuffer := Trim(Copy(AItem.Data, 19, 3));
|
||
if IsFileMode(LBuffer) then begin
|
||
LBuffer := Trim(Copy(AItem.Data, 23, 3));
|
||
LPRecLn := 30;
|
||
LLRecLn := 7;
|
||
LPRecNo := 37;
|
||
LLRecNo := 7;
|
||
LPBkNo := 44;
|
||
LLBkNo := 8;
|
||
LPCol := 52;
|
||
end else begin
|
||
LPRecLn := 22;
|
||
LLRecLn := 9;
|
||
LPRecNo := 31;
|
||
LLRecNo := 11;
|
||
LPBkNo := 42;
|
||
LLBkNo := 11;
|
||
if (Copy(AItem.Data, 48, 1) = '-') and (Copy(AItem.Data, 51, 1) = '-') then begin {do not localize}
|
||
LPCol := 44;
|
||
end else begin
|
||
LPCol := 54;
|
||
end;
|
||
end;
|
||
LI.RecFormat := LBuffer;
|
||
if LI.RecFormat = 'DIR' then begin {do not localize}
|
||
LI.ItemType := ditDirectory;
|
||
LI.RecLength := 0;
|
||
end else begin
|
||
LI.ItemType := ditFile;
|
||
//Record Length - for files
|
||
LBuffer := Copy(AItem.Data, LPRecLn, LLRecLn);
|
||
LI.RecLength := IndyStrToInt(LBuffer, 0);
|
||
//Record numbers
|
||
LBuffer := Trim(Copy(AItem.Data, LPRecNo, LLRecNo));
|
||
LBuffer := Fetch(LBuffer);
|
||
LI.NumberRecs := IndyStrToInt(LBuffer, 0);
|
||
//Number of Blocks
|
||
{
|
||
From:
|
||
|
||
http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=utf-8&selm=DLspv2.G2w%40epsilon.com&rnum=2
|
||
|
||
Block sizes can be 800, 512, 1024,
|
||
2048, or 4096, per the whim of the user. IBM loves 4096, but it wastes
|
||
space (just like on FAT partitions on DOS.)
|
||
|
||
For F files (any type which begins with F), record count times logical
|
||
record length.
|
||
|
||
For V files, you need to read the file for an exact count, or the block
|
||
size (times block count) for a good guess. In other words, you're up
|
||
the creek because you don't KNOW the block size. Use record size times
|
||
record length for a _maximum_ file size.
|
||
|
||
Anyway, you can not know from the directory list.
|
||
}
|
||
LBuffer := Trim(Copy(AItem.Data, LPBkNo, LLBkNo));
|
||
LI.NumberBlocks := IndyStrToInt(LBuffer, 0);
|
||
LI.Size := LI.RecLength * LI.NumberRecs;
|
||
//File Size - note that this is just an estimiate
|
||
|
||
{From:
|
||
z/VMTCP/IP User’s Guide Version 5 Release 1.0
|
||
© Copyright International Business Machines Corporation 1987, 2004.
|
||
All rights reserved.
|
||
|
||
For fixed-record (F) format minidisk and SFS files,
|
||
the size field indicates the actual size of a file.
|
||
For variable-record (V) format minidisk and SFS files,
|
||
the size field contains an estimated file size, this
|
||
being the lesser value determined by:
|
||
|
||
– the number of records in the file and its maximum record length
|
||
– the size and number of blocks required to maintain the file.
|
||
|
||
For virtual reader files, a size of 0 is always indicated.}
|
||
|
||
if LI.RecFormat = 'V' then begin
|
||
LSize := LI.NumberBlocks * 4096;
|
||
if LI.Size > LSize then begin
|
||
LI.Size := LSize;
|
||
end;
|
||
end;
|
||
if LI.RecFormat = 'DIR' then begin
|
||
LI.SizeAvail := False;
|
||
end;
|
||
end;
|
||
LCols := TStringList.Create;
|
||
try
|
||
// we do things this way for the rest because vm.sc.edu has
|
||
// a variation on VM/CMS that does directory dates differently
|
||
//and some columns could be off.
|
||
//Note that the start position in one server it's column 44 while in others, it's column 54
|
||
// handle both cases.
|
||
LBuffer := Trim(Copy(AItem.Data, LPCol, MaxInt));
|
||
SplitDelimitedString(LBuffer, LCols, True);
|
||
//LCols - 0 - Date
|
||
//LCols - 1 - Time
|
||
//LCols - 2 - Owner if present
|
||
if LCols.Count > 0 then begin
|
||
//date
|
||
if IsNumeric(LCols[0], 3) then begin
|
||
// vm.sc.edu date stamps yyyy-mm-dd
|
||
LI.ModifiedDate := DateYYMMDD(LCols[0]);
|
||
end else begin
|
||
//Note that the date is displayed as 2 digits not 4 digits
|
||
//mm/dd/yy
|
||
LI.ModifiedDate := DateMMDDYY(LCols[0]);
|
||
end;
|
||
//time
|
||
LI.ModifiedDate := LI.ModifiedDate + TimeHHMMSS(LCols[1]);
|
||
//owner
|
||
if (LCols.Count > 2) and (LCols[2] <> '-') then begin {do not localize}
|
||
LI.OwnerName := LCols[2];
|
||
end;
|
||
end;
|
||
finally
|
||
FreeAndNil(LCols);
|
||
end;
|
||
Result := True;
|
||
end;
|
||
|
||
{ TIdFTPLPVMBFS }
|
||
|
||
{List format like:
|
||
|
||
===
|
||
05/20/2000 13:38:19 F 1 65758 ’bfsline.cpy’
|
||
05/19/2000 11:02:15 F 1 65758 ’bfsline.txt’
|
||
06/03/2000 12:27:48 F 1 15414 ’bfstest.cpy’
|
||
05/20/2000 13:38:05 F 1 15414 ’bfstest.output’
|
||
05/20/2000 13:38:42 F 1 772902 ’bfswork.output’
|
||
03/31/2000 15:49:27 F 1 782444 ’bfswork.txt’
|
||
05/20/2000 13:39:20 F 1 13930 ’lotsonl.putdata’
|
||
05/19/2000 09:41:21 F 1 13930 ’lotsonl.txt’
|
||
06/15/2000 09:29:25 F 1 278 ’mail.maw’
|
||
05/20/2000 13:39:34 F 1 278 ’mail.putdata’
|
||
05/20/2000 15:30:45 F 1 13930 ’nls.new’
|
||
05/20/2000 14:02:24 F 1 13931 ’nls.txt’
|
||
08/21/2000 10:03:17 F 1 328 ’rock.rules’
|
||
05/20/2000 13:40:05 F 1 58 ’testfil2.putdata’
|
||
04/26/2000 14:34:42 F 1 63 ’testfil2.txt’
|
||
08/21/2000 05:28:40 D - - ’ALTERNATE’
|
||
12/28/2000 17:36:19 D - - ’FIRST
|
||
===
|
||
}
|
||
class function TIdFTPLPVMBFS.CheckListing(AListing: TStrings;
|
||
const ASysDescript: String; const ADetails: Boolean): Boolean;
|
||
var
|
||
s : TStrings;
|
||
begin
|
||
Result := False;
|
||
|
||
if AListing.Count > 0 then begin
|
||
//should have a "'" as the terminator
|
||
if AListing[0] <> '' then begin
|
||
if not TextEndsWith(AListing[0], '''') then begin
|
||
Exit;
|
||
end;
|
||
end;
|
||
s := TStringList.Create;
|
||
try
|
||
SplitDelimitedString(AListing[0], s, True);
|
||
if s.Count > 4 then begin
|
||
if not IsMMDDYY(s[0], '/') then begin {do not localize}
|
||
Exit;
|
||
end;
|
||
Result := CharIsInSet(s[2], 1, 'FD'); {do not localize}
|
||
if Result then begin
|
||
Result := IsNumeric(s[4]) or (s[4] <> '-'); {do not localize}
|
||
end;
|
||
end;
|
||
finally
|
||
FreeAndNil(s);
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
class function TIdFTPLPVMBFS.GetIdent: String;
|
||
begin
|
||
Result := 'VM/BFS'; {do not localize}
|
||
end;
|
||
|
||
class function TIdFTPLPVMBFS.MakeNewItem(AOwner: TIdFTPListItems): TIdFTPListItem;
|
||
begin
|
||
Result := TIdVMBFSFTPListItem.Create(AOwner);
|
||
end;
|
||
|
||
class function TIdFTPLPVMBFS.ParseLine(const AItem: TIdFTPListItem;
|
||
const APath: String): Boolean;
|
||
var
|
||
LBuffer : String;
|
||
LCols : TStrings;
|
||
begin
|
||
// z/VM Byte File System
|
||
|
||
//This is based on:
|
||
//
|
||
// z/VM: TCP/IP Level 430 User's Guide Version 4 Release 3.0
|
||
//
|
||
// http://www.vm.ibm.com/pubs/pdf/hcsk7a10.pdf
|
||
//
|
||
LBuffer := AItem.Data;
|
||
LCols := TStringList.Create;
|
||
try
|
||
SplitDelimitedString(Fetch(LBuffer, #39), LCols, True); {do not localize}
|
||
//0 - date
|
||
//1 - time
|
||
//2 - (D) dir or file (F)
|
||
//3 - not sure what this is
|
||
//4 - file size
|
||
AItem.FileName := LBuffer;
|
||
if TextEndsWith(AItem.FileName, '''') then begin
|
||
AItem.FileName := Copy(AItem.FileName, 1, Length(AItem.FileName)-1);
|
||
end;
|
||
//date
|
||
if LCols.Count > 0 then begin
|
||
AItem.ModifiedDate := DateMMDDYY(LCols[0]);
|
||
end;
|
||
if LCols.Count > 1 then begin
|
||
AItem.ModifiedDate := AItem.ModifiedDate + TimeHHMMSS(LCols[1]);
|
||
end;
|
||
if LCols.Count > 2 then
|
||
begin
|
||
if LCols[2] = 'D' then begin
|
||
AItem.ItemType := ditDirectory;
|
||
end else begin
|
||
AItem.ItemType := ditFile;
|
||
end;
|
||
end;
|
||
//file size
|
||
if LCols.Count > 4 then begin
|
||
if IsNumeric(LCols[3]) then begin
|
||
AItem.Size := IndyStrToInt64(LCols[4], 0);
|
||
AItem.SizeAvail := True;
|
||
end else begin
|
||
AItem.SizeAvail := False;
|
||
end;
|
||
end;
|
||
finally
|
||
FreeAndNil(LCols);
|
||
end;
|
||
Result := True;
|
||
end;
|
||
|
||
{ TIdFTPLVirtualReader }
|
||
|
||
class function TIdFTPLVirtualReader.CheckListing(AListing: TStrings;
|
||
const ASysDescript: String; const ADetails: Boolean): Boolean;
|
||
var
|
||
s : TStrings;
|
||
begin
|
||
Result := False;
|
||
if AListing.Count > 0 then begin
|
||
s := TStringList.Create;
|
||
try
|
||
SplitDelimitedString(AListing[0], s, True);
|
||
if s.Count > 2 then begin
|
||
if (Length(s[0]) = 4) and IsNumeric(s[0]) then begin
|
||
Result := (Length(s[2]) = 8) and (IsNumeric(s[2]));
|
||
end;
|
||
end;
|
||
finally
|
||
FreeAndNil(s);
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
class function TIdFTPLVirtualReader.GetIdent: String;
|
||
begin
|
||
Result := 'VM Virtual Reader'; {do not localize}
|
||
end;
|
||
|
||
class function TIdFTPLVirtualReader.MakeNewItem(AOwner: TIdFTPListItems): TIdFTPListItem;
|
||
begin
|
||
Result := TIdVMVirtualReaderFTPListItem.Create(AOwner);
|
||
end;
|
||
|
||
class function TIdFTPLVirtualReader.ParseLine(const AItem: TIdFTPListItem;
|
||
const APath: String): Boolean;
|
||
var
|
||
LCols : TStrings;
|
||
LI : TIdVMVirtualReaderFTPListItem;
|
||
begin
|
||
// z/VM Byte File System
|
||
|
||
//This is based on:
|
||
//
|
||
// z/VM: TCP/IP Level 430 User's Guide Version 4 Release 3.0
|
||
//
|
||
// http://www.vm.ibm.com/pubs/pdf/hcsk7a10.pdf
|
||
//
|
||
LI := AItem as TIdVMVirtualReaderFTPListItem;
|
||
LCols := TStringList.Create;
|
||
try
|
||
// z/VM Virtual Reader (RDR)
|
||
//Col 0 - spool ID
|
||
//Col 1 - origin
|
||
//Col 2 - records
|
||
//Col 3 - date
|
||
//Col 4 - time
|
||
//Col 5 - filename
|
||
//Col 6 - file type
|
||
SplitDelimitedString(AItem.Data, LCols, True);
|
||
if LCols.Count > 5 then begin
|
||
LI.FileName := LCols[5];
|
||
end;
|
||
if LCols.Count > 6 then begin
|
||
LI.FileName := LI.FileName + '.' + LCols[6]; {do not localize}
|
||
end;
|
||
//record count
|
||
if LCols.Count > 2 then begin
|
||
LI.NumberRecs := IndyStrToInt(LCols[2], 0);
|
||
end;
|
||
//date
|
||
if LCols.Count > 3 then begin
|
||
LI.ModifiedDate := DateYYMMDD(LCols[3]);
|
||
end;
|
||
//Time
|
||
if LCols.Count > 4 then begin
|
||
LI.ModifiedDate := LI.ModifiedDate + TimeHHMMSS(LCols[1]);
|
||
end;
|
||
//Note that IBM does not even try to give an estimate
|
||
//with reader file sizes when emulating Unix. We can't support file sizes
|
||
//with this.
|
||
finally
|
||
FreeAndNil(LCols);
|
||
end;
|
||
Result := True;
|
||
end;
|
||
|
||
{ TIdVMVirtualReaderFTPListItem }
|
||
|
||
constructor TIdVMVirtualReaderFTPListItem.Create(AOwner: TCollection);
|
||
begin
|
||
inherited Create(AOwner);
|
||
//There's no size for things in a virtual reader
|
||
SizeAvail := False;
|
||
end;
|
||
|
||
initialization
|
||
RegisterFTPListParser(TIdFTPLVirtualReader);
|
||
RegisterFTPListParser(TIdFTPLPVMBFS);
|
||
RegisterFTPListParser(TIdFTPLPVMCMS);
|
||
finalization
|
||
UnRegisterFTPListParser(TIdFTPLVirtualReader);
|
||
UnRegisterFTPListParser(TIdFTPLPVMBFS);
|
||
UnRegisterFTPListParser(TIdFTPLPVMCMS);
|
||
|
||
end.
|