{ $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.9 2/23/2005 6:34:28 PM JPMugaas New property for displaying permissions ina GUI column. Note that this should not be used like a CHMOD because permissions are different on different platforms - you have been warned. Rev 1.8 10/26/2004 9:51:14 PM JPMugaas Updated refs. Rev 1.7 4/19/2004 5:05:58 PM JPMugaas Class rework Kudzu wanted. Rev 1.6 2004.02.03 5:45:34 PM czhower Name changes Rev 1.5 1/22/2004 4:58:24 PM SPerry fixed set problems Rev 1.4 1/22/2004 7:20:46 AM JPMugaas System.Delete changed to IdDelete so the code can work in NET. Rev 1.3 10/19/2003 3:36:10 PM DSiders Added localization comments. Rev 1.2 6/27/2003 02:07:40 PM JPMugaas Should now compile now that IsNumeric was moved to IdCoreGlobal. Rev 1.1 4/7/2003 04:04:12 PM JPMugaas User can now descover what output a parser may give. Rev 1.0 2/19/2003 10:13:42 PM JPMugaas Moved parsers to their own classes. } unit IdFTPListParseNovellNetwarePSU; interface {$i IdCompilerDefines.inc} uses Classes, IdFTPList, IdFTPListParseBase, IdFTPListTypes; type TIdNovellPSU_DOSFTPListItem = class(TIdNovellBaseFTPListItem); TIdFTPLPNetwarePSUDos = 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; TIdNovellPSU_NFSFTPListItem = class(TIdUnixBaseFTPListItem); TIdFTPLPNetwarePSUNFS = 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; const NOVELLNETWAREPSU = 'Novell Netware Print Services for Unix: '; {do not localize} // 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 "IdFTPListParseNovellNetwarePSU"'} {$ENDIF} implementation uses IdException, IdGlobal, IdFTPCommon, IdGlobalProtocols, IdStrings, SysUtils; { TIdFTPLPNetwarePSUDos } class function TIdFTPLPNetwarePSUDos.CheckListing(AListing: TStrings; const ASysDescript: String; const ADetails: Boolean): Boolean; var LPerms : String; LData : String; begin Result := True; if AListing.Count >0 then begin LData := AListing[0]; Result := LData <> ''; if Result then begin Result := CharIsInSet(LData, 1, 'dD-'); {do not localize} if Result then begin //we have to be careful to distinguish between Hellsoft and //NetWare Print Services for UNIX, FTP File Transfer Service LPerms := ExtractNovellPerms(Copy(LData, 1, 12)); Result := (Length(LPerms) = 8) and IsValidNovellPermissionStr(LPerms) and IsNovelPSPattern(LData); end; end; end; end; class function TIdFTPLPNetwarePSUDos.GetIdent: String; begin Result := NOVELLNETWAREPSU + 'DOS Namespace'; {do not localize} end; class function TIdFTPLPNetwarePSUDos.MakeNewItem(AOwner: TIdFTPListItems): TIdFTPListItem; begin Result := TIdNovellPSU_DOSFTPListItem.Create(AOwner); end; class function TIdFTPLPNetwarePSUDos.ParseLine(const AItem: TIdFTPListItem; const APath: String): Boolean; var LBuf : String; LModifiedDate : String; LModifiedTime : String; LI : TIdNovellPSU_DOSFTPListItem; begin //-[RWCEAFMS] server1 3166 Sept 14, 99 2:30 pm vol$log.err LI := AItem as TIdNovellPSU_DOSFTPListItem; LBuf := LI.Data; //item type if TextStartsWith(LBuf, 'D') then begin {do not localize} LI.ItemType := ditDirectory; end else begin LI.ItemType := ditFile; end; IdDelete(LBuf, 1, 1); LBuf := TrimLeft(LBuf); //Permissions LI.NovellPermissions := ExtractNovellPerms(Fetch(LBuf)); LI.PermissionDisplay := '[' + LI.NovellPermissions + ']'; {do not localize} LBuf := TrimLeft(LBuf); //Owner LI.OwnerName := Fetch(LBuf); LBuf := TrimLeft(LBuf); //size LI.Size := IndyStrToInt64(Fetch(LBuf), 0); LBuf := TrimLeft(LBuf); //month //we have to make sure that the month is 3 chars. The list might return Sept instead of Sep LModifiedDate := Copy(Fetch(LBuf), 1, 3); LBuf := TrimLeft(LBuf); //day LModifiedDate := LModifiedDate + ' ' + Fetch(LBuf); {do not localize} LModifiedDate := Fetch(LModifiedDate, ','); {do not localize} LBuf := TrimLeft(LBuf); //year LModifiedDate := LModifiedDate + ' ' + Fetch(LBuf); {do not localize} LBuf := TrimLeft(LBuf); LI.ModifiedDate := DateStrMonthDDYY(LModifiedDate, ' '); {do not localize} //time LModifiedTime := Fetch(LBuf); LBuf := TrimLeft(LBuf); //am/pm LModifiedTime := LModifiedTime + Fetch(LBuf); LI.ModifiedDate := AItem.ModifiedDate + TimeHHMMSS(LModifiedTime); //name LI.FileName := LBuf; Result := True; end; { TIdFTPLPNetwarePSUNFS } class function TIdFTPLPNetwarePSUNFS.CheckListing(AListing: TStrings; const ASysDescript: String; const ADetails: Boolean): Boolean; var s : TStrings; LBuf : string; begin Result := False; { 1234567890 -rw------ - 2 root wheel 512 Oct 14, 99 8:45 pm deleted.sav -rw------ - 1 bill support 1285 Oct 14, 99 9:55 pm 123456789.123456 or -rw------ 1 root wheel 512 Oct 14 99 8:45 pm deleted.sav -rw------ 1 bill support 1285 Oct 14 99 9:55 pm 123456789.123456 } if AListing.Count > 0 then begin LBuf := AListing[0]; //remove the extra space that sometimes appears in older versions to "flatten" //out the listing if (Length(LBuf) > 9) and (LBuf[10] = ' ') then {do not localize} begin IdDelete(LBuf, 10, 1); end; Result := IsValidUnixPerms(LBuf, True); if Result then begin s := TStringList.Create; try SplitDelimitedString(LBuf, s, True); Result := (s.Count > 9) and (PosInStrArray(s[9], ['AM', 'PM'], False) <> -1); {do not localize} if Result then begin LBuf := s[6]; LBuf := Fetch(LBuf, ','); {do not localize} Result := IsNumeric(LBuf) and IsNumeric(s[7]) and CharEquals(s[8], 3, ':'); if Result then begin Result := StrToMonth(s[5]) > 0; end; end; finally FreeAndNil(s); end; end; end; end; class function TIdFTPLPNetwarePSUNFS.GetIdent: String; begin Result := NOVELLNETWAREPSU + 'NFS Namespace'; {do not localize} end; class function TIdFTPLPNetwarePSUNFS.MakeNewItem(AOwner: TIdFTPListItems): TIdFTPListItem; begin Result := TIdNovellPSU_NFSFTPListItem.Create(AOwner); end; class function TIdFTPLPNetwarePSUNFS.ParseLine(const AItem: TIdFTPListItem; const APath: String): Boolean; var LBuf, LBuf2 : String; LI : TIdNovellPSU_NFSFTPListItem; begin { -rw------ - 2 root wheel 512 Oct 14, 99 8:45 pm deleted.sav -rw------ - 1 bill support 1285 Oct 14, 99 9:55 pm 123456789.123456 or -rw------- 1 root wheel 512 Oct 14, 99 8:45 pm deleted.sav -rw------- 1 root wheel 3166 Oct 14, 99 8:45 pm vol$log.err -rw------- 1 bill support 1285 Oct 14, 99 9:55 pm 123456789.123456 drw------- 2 mary support 512 Oct 14, 99 7:33 pm locktst drwxr-xr-x 1 root wheel 512 Oct 14, 99 4:33 pm brief Based on: http://www.novell.com/documentation/lg/nw42/unixpenu/data/tut0i3h5.html#cnovdocsdocenglishnw42unixpenudatahpyvrshhhtml http://www.novell.com/documentation/lg/nw5/usprint/unixpenu/data/tut0i3h5.html#dnovdocsdocenglishnw5usprintunixpenudatahpyvrshhhtm http://www.novell.com/documentation/lg/nfs24/docui/index.html#../nfs24enu/data/hpyvrshh.html } { 0 - type of item and Permissions 1 - # of links 2 - Owner 3 - Group 4 - size 5 - month 6 - day 7 - year 8 - time 9 - am/pm 10 - name } LI := AItem as TIdNovellPSU_NFSFTPListItem; LBuf := LI.Data; LBuf2 := Fetch(LBuf); if not IsNumeric(Fetch(LBuf, ' ', False)) then begin {do not localize} LBuf2 := LBuf2 + Fetch(LBuf); end; if TextStartsWith(LBuf2, '-') then begin {do not localize} LI.ItemType := ditFile; end else begin LI.ItemType := ditDirectory; end; LI.UnixOwnerPermissions := Copy(LBuf2, 2, 3); LI.UnixGroupPermissions := Copy(LBuf2, 5, 3); LI.UnixOtherPermissions := Copy(LBuf2, 8, 3); LI.PermissionDisplay := LBuf2; //number of links LI.LinkCount := IndyStrToInt(Fetch(LBuf), 0); //Owner LBuf := TrimLeft(LBuf); LI.OwnerName := Fetch(LBuf); //Group LBuf := TrimLeft(LBuf); LI.GroupName := Fetch(LBuf); //Size LBuf := TrimLeft(LBuf); AItem.Size := IndyStrToInt64(Fetch(LBuf), 0); //Date - month LBuf := TrimLeft(LBuf); LBuf2 := UpperCase(Fetch(LBuf)) + ' '; {do not localize} //Date - day LBuf := TrimLeft(LBuf); LBuf2 := TrimRight(LBuf2) + ' ' + Fetch(LBuf); {do not localize} LBuf2 := Fetch(LBuf2, ','); {do not localize} //Year - year LBuf := TrimLeft(LBuf); LBuf2 := Fetch(LBuf) + ' ' + LBuf2; {do not localize} //Process Day LI.ModifiedDate := DateYYStrMonthDD(LBuf2, ' '); {do not localize} //time LBuf := TrimLeft(LBuf); LBuf2 := Fetch(LBuf); //make sure AM/pm are processed LBuf2 := LBuf2 + Fetch(LBuf); LI.ModifiedDate := AItem.ModifiedDate + TimeHHMMSS(LBuf2); // File name if IndyPos(UNIX_LINKTO_SYM,LBuf) > 0 then begin LI.FileName := Fetch(LBuf, UNIX_LINKTO_SYM); LI.LinkedItemName := LBuf; end else if IndyPos(UNIX_LINKTO_SYM, LBuf) > 0 then begin LI.FileName := Fetch(LBuf, UNIX_LINKTO_SYM); LI.LinkedItemName := LBuf; end else begin LI.FileName := LBuf; end; //Novell Netware is case sensitive I think. LI.LocalFileName := AItem.FileName; Result := True; end; initialization RegisterFTPListParser(TIdFTPLPNetwarePSUDos); RegisterFTPListParser(TIdFTPLPNetwarePSUNFS); finalization UnRegisterFTPListParser(TIdFTPLPNetwarePSUDos); UnRegisterFTPListParser(TIdFTPLPNetwarePSUNFS); end.