Files
restemplate/indy/Protocols/IdFTPListParseMPEiX.pas
2015-10-04 14:14:55 +02:00

355 lines
10 KiB
ObjectPascal
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
$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.5 10/26/2004 9:46:34 PM JPMugaas
Updated refs.
Rev 1.4 4/19/2004 5:05:48 PM JPMugaas
Class rework Kudzu wanted.
Rev 1.3 2004.02.03 5:45:28 PM czhower
Name changes
Rev 1.2 10/19/2003 2:27:22 PM DSiders
Added localization comments.
Rev 1.1 4/7/2003 04:03:52 PM JPMugaas
User can now descover what output a parser may give.
Rev 1.0 2/19/2003 05:51:24 PM JPMugaas
Parsers ported from old framework.
}
unit IdFTPListParseMPEiX;
interface
{$i IdCompilerDefines.inc}
uses
Classes,
IdGlobal,
IdFTPList, IdFTPListParseBase, IdFTPListTypes;
type
TIdMPiXFTPListItem = class(TIdRecFTPListItem)
protected
FLimit : UInt32;
public
constructor Create(AOwner: TCollection); override;
property RecLength;
property RecFormat;
property NumberRecs;
property Limit : UInt32 read FLimit write FLimit;
end;
//Anscestor for the MPE/iX Parsers
//This is necessary because they both have a second line a function parses
//Do not register this one
TIdFTPLPMPiXBase = class(TIdFTPListBaseHeader)
protected
class function MakeNewItem(AOwner : TIdFTPListItems) : TIdFTPListItem; override;
class function IsSecondHeader(ACols: TStrings): Boolean; virtual;
public
class function GetIdent : String; override;
end;
TIdFTPLPMPiX = class(TIdFTPLPMPiXBase)
protected
class function ParseLine(const AItem : TIdFTPListItem; const APath : String = ''): Boolean; override;
class function IsHeader(const AData: String): Boolean; override;
public
class function GetIdent : String; override;
end;
TIdFTPLPMPiXWithPOSIX = class(TIdFTPLPMPiXBase)
protected
class function ParseLine(const AItem : TIdFTPListItem; const APath : String = ''): Boolean; override;
class function IsHeader(const AData: String): Boolean; override;
public
class function GetIdent : String; 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 "IdFTPListParseMPEiX"'}
{$ENDIF}
implementation
uses
IdFTPCommon, IdGlobalProtocols, IdStrings, SysUtils;
{ TIdFTPLPMPiXBase }
class function TIdFTPLPMPiXBase.GetIdent: String;
begin
Result := 'MPE/iX: '; {do not localize}
end;
class function TIdFTPLPMPiXBase.IsSecondHeader(ACols: TStrings): Boolean;
begin
Result := (ACols.Count > 3) and
(ACols[0] = 'SIZE') and {do not localize}
(ACols[1] = 'TYP') and {do not localize}
(ACols[2] = 'EOF') and {do not localize}
(ACols[3] = 'LIMIT'); {do not localize}
if Result and (ACols.Count = 8) then
begin
Result := (ACols[4] = 'R/B') and {do not localize}
(ACols[5] = 'SECTORS') and {do not localize}
(ACols[6] = '#X') and {do not localize}
(ACols[7] = 'MX') {do not localize}
end;
{
This is for a Not Found banner such as:
"@ not found"
"./@ not found"
}
if (not Result) and (ACols.Count = 3) then
begin
Result := (IndyPos('@', ACols[0]) > 0) and
(ACols[1] = 'not') and {do not localize}
(ACols[2] = 'found'); {do not localize}
end;
end;
class function TIdFTPLPMPiXBase.MakeNewItem(AOwner: TIdFTPListItems): TIdFTPListItem;
begin
Result := TIdMPiXFTPListItem.Create(AOwner);
end;
{ TIdFTPLPMPiX }
class function TIdFTPLPMPiX.GetIdent: String;
begin
Result := inherited GetIdent + 'LISTF'; {do not localize}
end;
class function TIdFTPLPMPiX.IsHeader(const AData: String): Boolean;
var
LCols : TStrings;
LAccP, LGrpP : Integer;
begin
LAccP := IndyPos('ACCOUNT=', AData); {do not localize}
if LAccP = 0 then begin
LAccP := IndyPos('ACCOUNT =', AData); {do not localize}
end;
LGrpP := IndyPos('GROUP=', AData); {do not localize}
if LGrpP = 0 then begin
LGrpP := IndyPos('GROUP =', AData); {do not localize}
end;
Result := (LAccP > 0) and (LGrpP > LAccP);
if not Result then
begin
LCols := TStringList.Create;
try
SplitDelimitedString(ReplaceAll(AData, '-', ' '), LCols, True);
Result := (LCols.Count > 3) and
(LCols[0] = 'FILENAME') and {do not localize}
(LCols[1] = 'CODE') and {do not localize}
(LCols[2] = 'LOGICAL') and {do not localize}
(LCols[3] = 'RECORD'); {do not localize}
if Result and (LCols.Count = 5) then begin
Result := (LCols[4] = 'SPACE'); {do not localize}
end;
if not Result then begin
Result := IsSecondHeader(LCols);
end;
finally
FreeAndNil(LCols);
end;
end;
end;
class function TIdFTPLPMPiX.ParseLine(const AItem: TIdFTPListItem;
const APath: String): Boolean;
var
LCols : TStrings;
LBuf : String;
LI : TIdMPiXFTPListItem;
begin
LI := AItem as TIdMPiXFTPListItem;
LCols := TStringList.Create;
try
//According to "HP ARPA File Transfer Protocol, Users Guide, HP 3000 MPE/iX Computer Systems,Edition 6"
//the filename here can be 8 chars long
LI.FileName := Trim(Copy(AItem.Data, 1, 8));
LBuf := Copy(AItem.Data, 8, MaxInt);
if (Length(LBuf) > 0) and (LBuf[1] <> ' ') then begin
Fetch(LBuf);
end;
SplitDelimitedString(LBuf, LCols, True);
if LCols.Count > 1 then begin
LI.Size := ExtractNumber(LCols[1]);
end;
//Type
if LCols.Count > 2 then begin
LI.RecFormat := LCols[2];
end;
//record COunt - EOF
if LCols.Count > 3 then begin
LI.NumberRecs := IndyStrToInt64(LCols[3], 0);
end;
//Limit
if LCols.Count > 4 then begin
LI.Limit := IndyStrToInt64(LCols[4], 0);
end;
{
HP3000 is a flat file system where there are no
subdirs. There is a file group created by the user
but that is mroe logical than anything. There might
be a command for obtaining file groups but I have not
seen one. Note that file groups can not obtain other groups.
}
LI.ItemType := ditFile;
{
Note that HP3000 does not give you the date at all.
}
LI.ModifiedAvail := False;
finally
FreeAndNil(LCols);
end;
Result := True;
end;
{ TIdFTPLPMPiXWithPOSIX }
class function TIdFTPLPMPiXWithPOSIX.GetIdent: String;
begin
Result := inherited GetIdent + 'With POSIX'; {do not localize}
end;
class function TIdFTPLPMPiXWithPOSIX.IsHeader(const AData: String): Boolean;
var
LCols : TStrings;
begin
{
Often is something like this (spacing may very):
==
PATH= /PH/SAPHP/
CODE ------------LOGICAL RECORD----------- ----SPACE---- FILENAME
SIZE TYP EOF LIMIT R/B SECTORS #X MX
==
or maybe this:
===
ACCOUNT= SYS GROUP= WORK
FILENAME CODE ------------LOGICAL RECORD----------- ----SPACE----
===
}
Result := IndyPos('PATH=', AData) > 0; {do not localize}
if not Result then
begin
LCols := TStringList.Create;
try
SplitDelimitedString(ReplaceAll(AData, '-', ' '), LCols, True);
Result := (LCols.Count = 5) and
(LCols[0] = 'CODE') and {do not localize}
(LCols[1] = 'LOGICAL') and {do not localize}
(LCols[2] = 'RECORD') and {do not localize}
(LCols[3] = 'SPACE') and {do not localize}
(LCols[4] = 'FILENAME'); {do not localize}
if not Result then begin
Result := IsSecondHeader(LCols);
end;
finally
FreeAndNil(LCols);
end;
end;
end;
class function TIdFTPLPMPiXWithPOSIX.ParseLine(const AItem: TIdFTPListItem;
const APath: String): Boolean;
var
LCols : TStrings;
LI : TIdMPiXFTPListItem;
begin
LI := AItem as TIdMPiXFTPListItem;
LCols := TStringList.Create;
try
SplitDelimitedString(AItem.Data, LCols, True);
if LCols.Count > 0 then begin
LI.Size := ExtractNumber(LCols[0]);
end;
if LCols.Count > 1 then begin
LI.RecFormat := LCols[1];
end;
if LCols.Count > 2 then begin
LI.NumberRecs := IndyStrToInt64(LCols[2], 0);
end;
if LCols.Count > 3 then begin
LI.Limit := IndyStrToInt64(LCols[3], 0);
end;
if LCols.Count > 8 then begin
LI.FileName := LCols[8];
end;
{
The original HP3000 is a flat file system where there are no
subdirs. There is a file group created by the user
but that is more logical than anything. There might
be a command for obtaining file groups but I have not
seen one. Note that file groups can not obtain other groups.
More recent versions of HP3000 have Posix support including a
hierarchical file system. Verified with test at:
jazz.external.hp.com
}
if TextEndsWith(LI.FileName, '/') then
begin
LI.ItemType := ditDirectory;
LI.FileName := Copy(AItem.FileName, 1, Length(LI.FileName) - 1);
end else begin
LI.ItemType := ditFile;
end;
{
Note that HP3000 does not give you the date at all.
}
finally
FreeAndNil(LCols);
end;
Result := True;
end;
{ TIdMPiXFTPListItem }
constructor TIdMPiXFTPListItem.Create(AOwner: TCollection);
begin
inherited Create(AOwner);
//MP/iX or HP3000 will not give you a modified date at all
ModifiedAvail := False;
end;
initialization
RegisterFTPListParser(TIdFTPLPMPiX);
RegisterFTPListParser(TIdFTPLPMPiXWithPOSIX);
finalization
UnRegisterFTPListParser(TIdFTPLPMPiX);
UnRegisterFTPListParser(TIdFTPLPMPiXWithPOSIX);
end.