{
  $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.6    12/5/2004 5:06:30 PM  JPMugaas
  Tightened the detection for NCSA Telnet FTP Server for DOS.  The parser was
  causing problems with SuperTCP because the formats are similar.  By
  preventing SuperTCP from being detected, LongFilenames were not parsed in
  SuperTCP running on Windows 2000.

  Rev 1.5    10/26/2004 9:51:14 PM  JPMugaas
  Updated refs.

  Rev 1.4    6/5/2004 4:45:22 PM  JPMugaas
  Reports SizeAvail=False for directories in a list.  As per the dir format.

  Rev 1.3    4/19/2004 5:05:58 PM  JPMugaas
  Class rework Kudzu wanted.

  Rev 1.2    2004.02.03 5:45:32 PM  czhower
  Name changes

  Rev 1.1    10/19/2003 3:36:04 PM  DSiders
  Added localization comments.

  Rev 1.0    2/19/2003 10:13:38 PM  JPMugaas
  Moved parsers to their own classes.
}

unit IdFTPListParseNCSAForDOS;

interface

uses
  IdFTPList, IdFTPListParseBase, IdObjs;

type
  TIdNCSAforDOSFTPListItem = class(TIdFTPListItem);
  TIdFTPLPNCSAforDOS = class(TIdFTPListBaseHeader)
  protected
    class function MakeNewItem(AOwner : TIdFTPListItems)  : TIdFTPListItem; override;
    class function IsHeader(const AData: String): Boolean; override;
    class function IsFooter(const AData : String): Boolean; override;
    class function ParseLine(const AItem : TIdFTPListItem; const APath : String=''): Boolean; override;
  public
    class function CheckListing(AListing : TIdStrings; const ASysDescript : String =''; const ADetails : Boolean = True): boolean; override;
    class function GetIdent : String; override;
  end;

implementation

uses
  IdGlobal, IdFTPCommon, IdGlobalProtocols, IdSys;


{ TIdFTPLPNCSAforDOS }

class function TIdFTPLPNCSAforDOS.CheckListing(AListing: TIdStrings;
  const ASysDescript: String; const ADetails: Boolean): boolean;
var s : TIdStrings;
  LData : String;
  i : Integer;
begin
  Result := False;
  if AListing.Count > 0 then
  begin
    //we have to loop through because there is a similar format
    //in SuperTCP but that one has an additional feild with spaces
    //for long filenames.
    for i := 0 to AListing.Count -2 do
    begin
      LData := AListing[i];

      s := TIdStringList.Create;
      try
        SplitColumns(LData,s);
        if (s.Count = 4) then
        begin
          Result := (s[1] = '<DIR>') or (IsNumeric(s[1]));  {do not localize}
          Result := Result and IsHHMMSS(s[3], ':') and IsMMDDYY(s[2], '-')
            and ExcludeQVNET(LData);
        end;
      finally
        Sys.FreeAndNil(s);
      end;
      if not Result then
      begin
        break;
      end;
    end;
    Result := IsFooter(AListing[AListing.Count-1]);

  end;
end;

class function TIdFTPLPNCSAforDOS.GetIdent: String;
begin
  Result := 'NCSA for MS-DOS (CU/TCP)'; {do not localize}
end;

class function TIdFTPLPNCSAforDOS.IsFooter(const AData: String): Boolean;
var LWords : TIdStrings;
begin
  Result := False;
  LWords := TIdStringList.Create;
  try
    SplitColumns(Sys.Trim(Sys.StringReplace(AData, '-', ' ')), LWords);
    while (LWords.Count >2) do
    begin
      LWords.Delete(0);
    end;
    if LWords.Count = 2 then
    begin
      Result := (LWords[0] = 'Bytes') and (LWords[1] = 'Available');  {do not localize}
    end;
  finally
    Sys.FreeAndNil(LWords);
  end;
end;

class function TIdFTPLPNCSAforDOS.IsHeader(const AData: String): Boolean;
begin
  Result := False;
end;

class function TIdFTPLPNCSAforDOS.MakeNewItem(
  AOwner: TIdFTPListItems): TIdFTPListItem;
begin
  Result := TIdNCSAforDOSFTPListItem.Create(AOwner);
end;

class function TIdFTPLPNCSAforDOS.ParseLine(const AItem: TIdFTPListItem;
  const APath: String): Boolean;
var LBuf, LPt : String;

begin
  LBuf := AItem.Data;
  {filename - note that a space is illegal in MS-DOS so this should be safe}
  AItem.FileName := Fetch(LBuf);
  {type or size}
  LBuf := Sys.Trim(LBuf);
  LPt := Fetch(LBuf);
  if LPt = '<DIR>' then {do not localize}
  begin
    AItem.ItemType := ditDirectory;
    AItem.SizeAvail := False;
  end
  else
  begin
    AItem.ItemType := ditFile;
    AItem.Size := Sys.StrToInt64(LPt,0);
  end;
  //time stamp
  if LBuf <> '' then
  begin
    LBuf := Sys.Trim(LBuf);
    LPt := Fetch(LBuf);
    if LPt <> '' then
    begin
      //Date
      AItem.ModifiedDate := DateMMDDYY(LPt);
      LBuf := Sys.Trim(LBuf);
      LPt := Fetch(LBuf);
      if LPt <> '' then
      begin
        AItem.ModifiedDate := AItem.ModifiedDate + TimeHHMMSS(LPt);
      end;
    end;
  end;
  Result := True;
end;

initialization
  RegisterFTPListParser(TIdFTPLPNCSAforDOS);
finalization
  UnRegisterFTPListParser(TIdFTPLPNCSAforDOS);
end.
