RemoteFiles.cpp 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include "RemoteFiles.h"
  5. #include <SysUtils.hpp>
  6. #include "Common.h"
  7. #include "Exceptions.h"
  8. #include "Interface.h"
  9. #include "Terminal.h"
  10. #include "TextsCore.h"
  11. /* TODO 1 : Path class instead of AnsiString (handle relativity...) */
  12. //---------------------------------------------------------------------------
  13. AnsiString __fastcall UnixIncludeTrailingBackslash(const AnsiString Path)
  14. {
  15. if (!Path.IsDelimiter("/", Path.Length())) return Path + "/";
  16. else return Path;
  17. }
  18. //---------------------------------------------------------------------------
  19. AnsiString __fastcall UnixExcludeTrailingBackslash(const AnsiString Path)
  20. {
  21. if ((Path.Length() > 1) && Path.IsDelimiter("/", Path.Length()))
  22. return Path.SubString(1, Path.Length() - 1);
  23. else return Path;
  24. }
  25. //---------------------------------------------------------------------------
  26. Boolean __fastcall UnixComparePaths(const AnsiString Path1, const AnsiString Path2)
  27. {
  28. return (UnixIncludeTrailingBackslash(Path1) == UnixIncludeTrailingBackslash(Path2));
  29. }
  30. //---------------------------------------------------------------------------
  31. AnsiString __fastcall UnixExtractFileDir(const AnsiString Path)
  32. {
  33. Integer Pos = Path.LastDelimiter('/');
  34. if (Pos > 1) return Path.SubString(1, Pos - 1);
  35. else
  36. if (Pos == 1) return "/";
  37. else return Path;
  38. }
  39. //---------------------------------------------------------------------------
  40. // must return trailing backslash
  41. AnsiString __fastcall UnixExtractFilePath(const AnsiString Path)
  42. {
  43. Integer Pos = Path.LastDelimiter('/');
  44. if (Pos) return Path.SubString(1, Pos);
  45. else return Path;
  46. }
  47. //---------------------------------------------------------------------------
  48. AnsiString __fastcall UnixExtractFileName(const AnsiString Path)
  49. {
  50. Integer Pos = Path.LastDelimiter('/');
  51. if (Pos) return Path.SubString(Pos + 1, Path.Length() - Pos);
  52. else return Path;
  53. }
  54. //---------------------------------------------------------------------------
  55. AnsiString __fastcall UnixExtractFileExt(const AnsiString Path)
  56. {
  57. AnsiString FileName = UnixExtractFileName(Path);
  58. Integer Pos = FileName.LastDelimiter(".");
  59. if (Pos) return Path.SubString(Pos, Path.Length() - Pos + 1);
  60. else return "";
  61. }
  62. //---------------------------------------------------------------------------
  63. void __fastcall DateTimeParams(TDateTime * AUnixEpoch, double * ADifference)
  64. {
  65. static double Difference;
  66. static TDateTime UnixEpoch = 0;
  67. if (double(UnixEpoch) == 0)
  68. {
  69. TIME_ZONE_INFORMATION TZI;
  70. unsigned long GTZI;
  71. GTZI = GetTimeZoneInformation(&TZI);
  72. switch (GTZI) {
  73. case TIME_ZONE_ID_UNKNOWN:
  74. Difference = 0;
  75. break;
  76. case TIME_ZONE_ID_STANDARD:
  77. Difference = double(TZI.Bias + TZI.StandardBias) / 1440;
  78. break;
  79. case TIME_ZONE_ID_DAYLIGHT:
  80. Difference = double(TZI.Bias + TZI.DaylightBias) / 1440;
  81. break;
  82. case TIME_ZONE_ID_INVALID:
  83. default:
  84. throw Exception(TIMEZONE_ERROR);
  85. }
  86. // Is it same as SysUtils::UnixDateDelta = 25569 ??
  87. UnixEpoch = EncodeDate(1970, 1, 1);
  88. }
  89. if (AUnixEpoch) *AUnixEpoch = UnixEpoch;
  90. if (ADifference) *ADifference = Difference;
  91. }
  92. //---------------------------------------------------------------------------
  93. TDateTime __fastcall UnixToDateTime(unsigned long TimeStamp)
  94. {
  95. TDateTime UnixEpoch;
  96. double Difference;
  97. DateTimeParams(&UnixEpoch, &Difference);
  98. TDateTime Result;
  99. Result = UnixEpoch + (double(TimeStamp) / 86400) - Difference;
  100. return Result;
  101. }
  102. //---------------------------------------------------------------------------
  103. FILETIME __fastcall DateTimeToFileTime(const TDateTime DateTime)
  104. {
  105. unsigned long UnixTimeStamp;
  106. FILETIME Result;
  107. TDateTime UnixEpoch;
  108. double Difference;
  109. DateTimeParams(&UnixEpoch, &Difference);
  110. UnixTimeStamp = (unsigned long)((double(DateTime - UnixEpoch + Difference) * 86400));
  111. TIME_POSIX_TO_WIN(UnixTimeStamp, Result);
  112. return Result;
  113. }
  114. //---------------------------------------------------------------------------
  115. TDateTime AdjustDateTimeFromUnix(const TDateTime DateTime)
  116. {
  117. // to be implemented
  118. return DateTime;
  119. }
  120. //- TRemoteFiles ------------------------------------------------------------
  121. __fastcall TRemoteFile::TRemoteFile(TRemoteFile * ALinkedByFile):
  122. TPersistent()
  123. {
  124. FLinkedFile = NULL;
  125. FRights = new TRights();
  126. FIconIndex = -1;
  127. FCyclicLink = false;
  128. FModificationFmt = mfFull;
  129. FLinkedByFile = ALinkedByFile;
  130. FTerminal = NULL;
  131. FDirectory = NULL;
  132. }
  133. //---------------------------------------------------------------------------
  134. __fastcall TRemoteFile::~TRemoteFile()
  135. {
  136. delete FRights;
  137. delete FLinkedFile;
  138. }
  139. //---------------------------------------------------------------------------
  140. TRemoteFile * __fastcall TRemoteFile::Duplicate()
  141. {
  142. TRemoteFile * Result;
  143. Result = new TRemoteFile();
  144. try
  145. {
  146. if (FLinkedFile)
  147. {
  148. Result->FLinkedFile = FLinkedFile->Duplicate();
  149. Result->FLinkedFile->FLinkedByFile = Result;
  150. }
  151. *Result->Rights = *FRights;
  152. #define COPY_FP(PROP) Result->F ## PROP = F ## PROP;
  153. COPY_FP(Terminal);
  154. COPY_FP(Owner);
  155. COPY_FP(ModificationFmt);
  156. COPY_FP(Size);
  157. COPY_FP(FileName);
  158. COPY_FP(INodeBlocks);
  159. COPY_FP(Modification);
  160. COPY_FP(Group);
  161. COPY_FP(IconIndex);
  162. COPY_FP(IsSymLink);
  163. COPY_FP(LinkTo);
  164. COPY_FP(Type);
  165. COPY_FP(Selected);
  166. COPY_FP(CyclicLink);
  167. #undef COPY_FP
  168. }
  169. catch(...)
  170. {
  171. delete Result;
  172. throw;
  173. }
  174. return Result;
  175. }
  176. //---------------------------------------------------------------------------
  177. Integer __fastcall TRemoteFile::GetIconIndex()
  178. {
  179. assert(FIconIndex >= -1);
  180. if (FIconIndex < 0)
  181. {
  182. /* TODO : If file is link: Should be attributes taken from linked file? */
  183. unsigned long Attrs = FILE_ATTRIBUTE_NORMAL;
  184. if (IsDirectory) Attrs |= FILE_ATTRIBUTE_DIRECTORY;
  185. if (IsHidden) Attrs |= FILE_ATTRIBUTE_HIDDEN;
  186. TSHFileInfo SHFileInfo;
  187. AnsiString DumbFileName = (IsSymLink && !LinkTo.IsEmpty() ? LinkTo : FileName);
  188. // On Win2k we get icon of "ZIP drive" for ".." (parent directory)
  189. if (DumbFileName == "..") DumbFileName = "dumb";
  190. SHGetFileInfo(DumbFileName.c_str(),
  191. Attrs, &SHFileInfo, sizeof(SHFileInfo),
  192. SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES);
  193. FIconIndex = SHFileInfo.iIcon;
  194. }
  195. return FIconIndex;
  196. }
  197. //---------------------------------------------------------------------------
  198. Boolean __fastcall TRemoteFile::GetIsHidden()
  199. {
  200. return (!IsParentDirectory && !IsThisDirectory &&
  201. !FileName.IsEmpty() && (FileName[1] == '.'));
  202. }
  203. //---------------------------------------------------------------------------
  204. Boolean __fastcall TRemoteFile::GetIsDirectory() const
  205. {
  206. return (toupper(Type) == FILETYPE_DIRECTORY);
  207. }
  208. //---------------------------------------------------------------------------
  209. Boolean __fastcall TRemoteFile::GetIsParentDirectory()
  210. {
  211. return (FileName == PARENTDIRECTORY);
  212. }
  213. //---------------------------------------------------------------------------
  214. Boolean __fastcall TRemoteFile::GetIsThisDirectory()
  215. {
  216. return (FileName == THISDIRECTORY);
  217. }
  218. //---------------------------------------------------------------------------
  219. Boolean __fastcall TRemoteFile::GetIsInaccesibleDirectory()
  220. {
  221. Boolean Result;
  222. if (IsDirectory)
  223. {
  224. assert(Terminal);
  225. Result = !
  226. (((Rights->RightUndef[rfOtherExec] != rsNo)) ||
  227. ((Rights->Right[rfGroupExec] != rsNo) &&
  228. (Terminal->UserGroups->IndexOf(Group) >= 0)) ||
  229. ((Rights->Right[rfUserExec] != rsNo) &&
  230. (AnsiCompareText(Terminal->UserName, Owner) == 0)));
  231. }
  232. else Result = False;
  233. return Result;
  234. }
  235. //---------------------------------------------------------------------------
  236. char __fastcall TRemoteFile::GetType() const
  237. {
  238. if (IsSymLink && FLinkedFile) return FLinkedFile->Type;
  239. else return FType;
  240. }
  241. //---------------------------------------------------------------------------
  242. void __fastcall TRemoteFile::SetType(char AType)
  243. {
  244. FType = AType;
  245. // Allow even non-standard file types (e.g. 'S')
  246. // if (!AnsiString("-DL").Pos((Char)toupper(FType))) Abort();
  247. FIsSymLink = ((Char)toupper(FType) == FILETYPE_SYMLINK);
  248. }
  249. //---------------------------------------------------------------------------
  250. TRemoteFile * __fastcall TRemoteFile::GetLinkedFile()
  251. {
  252. // it would be called releatedly for broken symlinks
  253. //if (!FLinkedFile) FindLinkedFile();
  254. return FLinkedFile;
  255. }
  256. //---------------------------------------------------------------------------
  257. void __fastcall TRemoteFile::SetLinkedFile(TRemoteFile * value)
  258. {
  259. if (FLinkedFile != value)
  260. {
  261. if (FLinkedFile) delete FLinkedFile;
  262. FLinkedFile = value;
  263. }
  264. }
  265. //---------------------------------------------------------------------------
  266. bool __fastcall TRemoteFile::GetBrokenLink()
  267. {
  268. assert(Terminal);
  269. // If file is symlink but we couldn't find linked file we assume broken link
  270. return (IsSymLink && (FCyclicLink || !FLinkedFile) &&
  271. Terminal->SessionData->ResolveSymlinks && Terminal->IsCapable[fcResolveSymlink]);
  272. // "!FLinkTo.IsEmpty()" removed because it does not work with SFTP
  273. }
  274. //---------------------------------------------------------------------------
  275. void __fastcall TRemoteFile::ShiftTime(const TDateTime & Difference)
  276. {
  277. double D = double(Difference);
  278. if ((D != 0) && (FModificationFmt != mfMDY))
  279. {
  280. assert(int(FModification) != 0);
  281. FModification = double(FModification) + D;
  282. assert(int(FLastAccess) != 0);
  283. FLastAccess = double(FLastAccess) + D;
  284. }
  285. }
  286. //---------------------------------------------------------------------------
  287. void __fastcall TRemoteFile::SetModification(const TDateTime & value)
  288. {
  289. if (FModification != value)
  290. {
  291. FModificationFmt = mfFull;
  292. FModification = value;
  293. }
  294. }
  295. //---------------------------------------------------------------------------
  296. AnsiString __fastcall TRemoteFile::GetUserModificationStr()
  297. {
  298. if (FModificationFmt == mfFull)
  299. {
  300. return FormatDateTime("ddddd tt", Modification);
  301. }
  302. else
  303. {
  304. return FormatDateTime("ddddd t", Modification);
  305. }
  306. }
  307. //---------------------------------------------------------------------------
  308. AnsiString __fastcall TRemoteFile::GetModificationStr()
  309. {
  310. Word Year, Month, Day, Hour, Min, Sec, MSec;
  311. Modification.DecodeDate(&Year, &Month, &Day);
  312. Modification.DecodeTime(&Hour, &Min, &Sec, &MSec);
  313. if (FModificationFmt != mfMDY)
  314. return FORMAT("%3s %2d %2d:%2.2d",
  315. (EngShortMonthNames[Month-1], Day, Hour, Min));
  316. else
  317. return FORMAT("%3s %2d %2d",
  318. (EngShortMonthNames[Month-1], Day, Year));
  319. }
  320. //---------------------------------------------------------------------------
  321. AnsiString __fastcall TRemoteFile::GetExtension()
  322. {
  323. return UnixExtractFileExt(FFileName);
  324. }
  325. //---------------------------------------------------------------------------
  326. void __fastcall TRemoteFile::SetRights(TRights * value)
  327. {
  328. FRights->Assign(value);
  329. }
  330. //---------------------------------------------------------------------------
  331. AnsiString __fastcall TRemoteFile::GetRightsStr()
  332. {
  333. return FRights->Text;
  334. }
  335. //---------------------------------------------------------------------------
  336. void __fastcall TRemoteFile::SetListingStr(AnsiString value)
  337. {
  338. // Value stored in 'value' can be used for error message
  339. AnsiString Line = value;
  340. FIconIndex = -1;
  341. try
  342. {
  343. AnsiString Col;
  344. // Do we need to do this (is ever TAB is LS output)?
  345. Line = ReplaceChar(Line, '\t', ' ');
  346. Type = Line[1];
  347. Line.Delete(1, 1);
  348. #define GETNCOL \
  349. { if (Line.IsEmpty()) throw Exception(""); \
  350. Integer P = Line.Pos(' '); \
  351. if (P) { Col = Line.SubString(1, P-1); Line.Delete(1, P); } \
  352. else { Col = Line; Line = ""; } \
  353. }
  354. #define GETCOL { GETNCOL; Line = TrimLeft(Line); }
  355. // Rights string may contain special permission attributes (S,t, ...)
  356. Rights->AllowUndef = True;
  357. // On some system there is no space between permissions and node blocks count columns
  358. // so we get only first 9 characters and trim all following spaces (if any)
  359. Rights->Text = Line.SubString(1, 9);
  360. Line.Delete(1, 9);
  361. // Rights column maybe followed by '+' sign, we ignore it
  362. if (!Line.IsEmpty() && (Line[1] == '+')) Line.Delete(1, 1);
  363. Line = Line.TrimLeft();
  364. GETCOL;
  365. FINodeBlocks = StrToInt(Col);
  366. GETCOL;
  367. FOwner = Col;
  368. // #60 17.10.01: group name can contain space
  369. FGroup = "";
  370. GETCOL;
  371. __int64 ASize;
  372. do
  373. {
  374. FGroup += Col;
  375. GETCOL;
  376. assert(!Col.IsEmpty());
  377. // for devices etc.. there is additional column ending by comma, we ignore it
  378. if (Col[Col.Length()] == ',') GETCOL;
  379. ASize = StrToInt64Def(Col, -1);
  380. // if it's not a number (file size) we take it as part of group name
  381. // (at least on CygWin, there can be group with space in its name)
  382. if (ASize < 0) Col = " " + Col;
  383. }
  384. while (ASize < 0);
  385. // do not read modification time and filename if it is already set
  386. if (double(FModification) == 0 && FileName.IsEmpty())
  387. {
  388. FSize = ASize;
  389. Word Day, Month, Year, Hour, Min, P;
  390. GETCOL;
  391. Month = 0;
  392. for (Word IMonth = 0; IMonth < 12; IMonth++)
  393. if (!Col.AnsiCompareIC(EngShortMonthNames[IMonth])) { Month = IMonth; Month++; break; }
  394. if (!Month) Abort();
  395. // don't trim possible leading space of year column
  396. // we need to know is space is before (most systems) or after year
  397. GETNCOL;
  398. Day = (Word)StrToInt(Col);
  399. if ((Day < 1) || (Day > 31)) Abort();
  400. // Time/Year indicator is always 5 charactes long (???), on most
  401. // systems year is aligned to right (_YYYY), but on some to left (YYYY_),
  402. // we must ensure that trailing space is also deleted, so real
  403. // separator space is not treated as part of file name
  404. Col = Line.SubString(1, 6).Trim();
  405. Line.Delete(1, 6);
  406. // GETNCOL; // We don't want to trim input strings (name with space at beginning???)
  407. // Check if we got time (contains :) or year
  408. if ((P = (Word)Col.Pos(':')) > 0)
  409. {
  410. Word CurrMonth, CurrDay;
  411. Hour = (Word)StrToInt(Col.SubString(1, P-1));
  412. Min = (Word)StrToInt(Col.SubString(P+1, Col.Length() - P));
  413. if (Hour > 23 || Hour > 59) Abort();
  414. // When we don't got year, we assume current year
  415. // with exception that the date would be in future
  416. // in this case we assume last year.
  417. DecodeDate(Date(), Year, CurrMonth, CurrDay);
  418. if ((Month > CurrMonth) ||
  419. (Month == CurrMonth && Day > CurrDay)) Year--;
  420. FModificationFmt = mfMDHM;
  421. }
  422. else
  423. {
  424. Year = (Word)StrToInt(Col);
  425. if (Year > 10000) Abort();
  426. // When we don't got time we assume midnight
  427. Hour = 0; Min = 0;
  428. FModificationFmt = mfMDY;
  429. }
  430. FModification = AdjustDateTimeFromUnix(
  431. EncodeDate(Year, Month, Day) + EncodeTime(Hour, Min, 0, 0));
  432. if (double(FLastAccess) == 0)
  433. {
  434. FLastAccess = FModification;
  435. }
  436. // separating space is already deleted, other spaces are treated as part of name
  437. {
  438. int P;
  439. FLinkTo = "";
  440. if (IsSymLink)
  441. {
  442. P = Line.Pos(SYMLINKSTR);
  443. if (P)
  444. {
  445. FLinkTo = Line.SubString(
  446. P + strlen(SYMLINKSTR), Line.Length() - P + strlen(SYMLINKSTR) + 1);
  447. Line.SetLength(P - 1);
  448. }
  449. else
  450. {
  451. Abort();
  452. }
  453. }
  454. FFileName = UnixExtractFileName(Line);
  455. }
  456. }
  457. #undef GETNCOL
  458. #undef GETCOL
  459. }
  460. catch (Exception &E)
  461. {
  462. throw ETerminal(&E, FmtLoadStr(LIST_LINE_ERROR, ARRAYOFCONST((value))));
  463. }
  464. assert(Terminal);
  465. if (IsSymLink && Terminal->SessionData->ResolveSymlinks &&
  466. Terminal->IsCapable[fcResolveSymlink])
  467. {
  468. FindLinkedFile();
  469. }
  470. }
  471. //---------------------------------------------------------------------------
  472. void __fastcall TRemoteFile::FindLinkedFile()
  473. {
  474. assert(Terminal && IsSymLink);
  475. if (FLinkedFile) delete FLinkedFile;
  476. FLinkedFile = NULL;
  477. FCyclicLink = false;
  478. if (!LinkTo.IsEmpty())
  479. {
  480. // check for cyclic link
  481. TRemoteFile * LinkedBy = FLinkedByFile;
  482. while (LinkedBy)
  483. {
  484. if (LinkedBy->LinkTo == LinkTo)
  485. {
  486. // this is currenly redundant information, because it is used only to
  487. // detect broken symlink, which would be otherwise detected
  488. // by FLinkedFile == NULL
  489. FCyclicLink = true;
  490. break;
  491. }
  492. LinkedBy = LinkedBy->FLinkedByFile;
  493. }
  494. }
  495. if (FCyclicLink)
  496. {
  497. TRemoteFile * LinkedBy = FLinkedByFile;
  498. while (LinkedBy)
  499. {
  500. LinkedBy->FCyclicLink = true;
  501. LinkedBy = LinkedBy->FLinkedByFile;
  502. }
  503. }
  504. else
  505. {
  506. assert(Terminal->SessionData->ResolveSymlinks && Terminal->IsCapable[fcResolveSymlink]);
  507. Terminal->ExceptionOnFail = true;
  508. try
  509. {
  510. try
  511. {
  512. Terminal->ReadSymlink(this, FLinkedFile);
  513. }
  514. __finally
  515. {
  516. Terminal->ExceptionOnFail = false;
  517. }
  518. }
  519. catch (Exception &E)
  520. {
  521. if (E.InheritsFrom(__classid(EFatal))) throw;
  522. else HandleExtendedException(&E, this);
  523. }
  524. }
  525. }
  526. //---------------------------------------------------------------------------
  527. AnsiString __fastcall TRemoteFile::GetListingStr()
  528. {
  529. return Format("%s%s %3s %s-8s %-8s %9d %s %s%s", ARRAYOFCONST((
  530. Type, Rights->Text, IntToStr(INodeBlocks), Owner,
  531. Group, IntToStr(Size), ModificationStr, FileName,
  532. (FLinkedFile ? AnsiString(SYMLINKSTR) + FLinkedFile->FileName : AnsiString()))));
  533. }
  534. //---------------------------------------------------------------------------
  535. AnsiString __fastcall TRemoteFile::GetFullFileName()
  536. {
  537. assert(Terminal);
  538. AnsiString Path;
  539. if (IsParentDirectory) Path = Directory->ParentPath;
  540. else
  541. if (IsDirectory) Path = UnixIncludeTrailingBackslash(Directory->FullDirectory + FileName);
  542. else Path = Directory->FullDirectory + FileName;
  543. return Terminal->TranslateLockedPath(Path, true);
  544. }
  545. //---------------------------------------------------------------------------
  546. Integer __fastcall TRemoteFile::GetAttr()
  547. {
  548. Integer Result = 0;
  549. if (Rights->ReadOnly) Result |= faReadOnly;
  550. if (IsHidden) Result |= faHidden;
  551. return Result;
  552. }
  553. //---------------------------------------------------------------------------
  554. void __fastcall TRemoteFile::SetTerminal(TTerminal * value)
  555. {
  556. FTerminal = value;
  557. if (FLinkedFile)
  558. {
  559. FLinkedFile->Terminal = value;
  560. }
  561. }
  562. //=== TRemoteFileList ------------------------------------------------------
  563. __fastcall TRemoteFileList::TRemoteFileList():
  564. TObjectList()
  565. {
  566. }
  567. //---------------------------------------------------------------------------
  568. void __fastcall TRemoteFileList::AddFile(TRemoteFile * File)
  569. {
  570. Add(File);
  571. File->Directory = this;
  572. }
  573. //---------------------------------------------------------------------------
  574. void __fastcall TRemoteFileList::DuplicateTo(TRemoteFileList * Copy)
  575. {
  576. Copy->Clear();
  577. for (int Index = 0; Index < Count; Index++)
  578. {
  579. TRemoteFile * File = Files[Index];
  580. Copy->AddFile(File->Duplicate());
  581. }
  582. Copy->FDirectory = Directory;
  583. }
  584. //---------------------------------------------------------------------------
  585. void __fastcall TRemoteFileList::Clear()
  586. {
  587. TObjectList::Clear();
  588. }
  589. //---------------------------------------------------------------------------
  590. void __fastcall TRemoteFileList::SetDirectory(AnsiString value)
  591. {
  592. FDirectory = UnixExcludeTrailingBackslash(value);
  593. }
  594. //---------------------------------------------------------------------------
  595. AnsiString __fastcall TRemoteFileList::GetFullDirectory()
  596. {
  597. return UnixIncludeTrailingBackslash(Directory);
  598. }
  599. //---------------------------------------------------------------------------
  600. TRemoteFile * __fastcall TRemoteFileList::GetFiles(Integer Index)
  601. {
  602. return (TRemoteFile *)Items[Index];
  603. }
  604. //---------------------------------------------------------------------------
  605. Boolean __fastcall TRemoteFileList::GetIsRoot()
  606. {
  607. return (Directory == ROOTDIRECTORY);
  608. }
  609. //---------------------------------------------------------------------------
  610. AnsiString __fastcall TRemoteFileList::GetParentPath()
  611. {
  612. return UnixExtractFilePath(Directory);
  613. }
  614. //---------------------------------------------------------------------------
  615. __int64 __fastcall TRemoteFileList::GetTotalSize()
  616. {
  617. __int64 Result = 0;
  618. for (Integer Index = 0; Index < Count; Index++)
  619. if (!Files[Index]->IsDirectory) Result += Files[Index]->Size;
  620. return Result;
  621. }
  622. //---------------------------------------------------------------------------
  623. TRemoteFile * __fastcall TRemoteFileList::FindFile(const AnsiString &FileName)
  624. {
  625. for (Integer Index = 0; Index < Count; Index++)
  626. if (Files[Index]->FileName == FileName) return Files[Index];
  627. return NULL;
  628. }
  629. //=== TRemoteDirectory ------------------------------------------------------
  630. __fastcall TRemoteDirectory::TRemoteDirectory(TTerminal * aTerminal):
  631. TRemoteFileList(), FTerminal(aTerminal)
  632. {
  633. FSelectedFiles = NULL;
  634. FThisDirectory = NULL;
  635. FParentDirectory = NULL;
  636. FIncludeThisDirectory = false;
  637. FIncludeParentDirectory = true;
  638. }
  639. //---------------------------------------------------------------------------
  640. void __fastcall TRemoteDirectory::Clear()
  641. {
  642. if (ThisDirectory && !IncludeThisDirectory)
  643. {
  644. delete FThisDirectory;
  645. FThisDirectory = NULL;
  646. }
  647. if (ParentDirectory && !IncludeParentDirectory)
  648. {
  649. delete FParentDirectory;
  650. FParentDirectory = NULL;
  651. }
  652. TRemoteFileList::Clear();
  653. }
  654. //---------------------------------------------------------------------------
  655. void __fastcall TRemoteDirectory::SetDirectory(AnsiString value)
  656. {
  657. TRemoteFileList::SetDirectory(value);
  658. //Load();
  659. }
  660. //---------------------------------------------------------------------------
  661. void __fastcall TRemoteDirectory::AddFile(TRemoteFile * File)
  662. {
  663. if (File->IsThisDirectory) FThisDirectory = File;
  664. if (File->IsParentDirectory) FParentDirectory = File;
  665. if ((!File->IsThisDirectory || IncludeThisDirectory) &&
  666. (!File->IsParentDirectory || IncludeParentDirectory))
  667. {
  668. TRemoteFileList::AddFile(File);
  669. }
  670. File->Terminal = Terminal;
  671. }
  672. //---------------------------------------------------------------------------
  673. void __fastcall TRemoteDirectory::DuplicateTo(TRemoteFileList * Copy)
  674. {
  675. TRemoteFileList::DuplicateTo(Copy);
  676. if (ThisDirectory && !IncludeThisDirectory)
  677. {
  678. Copy->AddFile(ThisDirectory->Duplicate());
  679. }
  680. if (ParentDirectory && !IncludeParentDirectory)
  681. {
  682. Copy->AddFile(ParentDirectory->Duplicate());
  683. }
  684. }
  685. //---------------------------------------------------------------------------
  686. bool __fastcall TRemoteDirectory::GetLoaded()
  687. {
  688. return ((Terminal != NULL) && Terminal->Active && !Directory.IsEmpty());
  689. }
  690. //---------------------------------------------------------------------------
  691. TStrings * __fastcall TRemoteDirectory::GetSelectedFiles()
  692. {
  693. if (!FSelectedFiles)
  694. {
  695. FSelectedFiles = new TStringList();
  696. }
  697. else
  698. {
  699. FSelectedFiles->Clear();
  700. }
  701. for (int Index = 0; Index < Count; Index ++)
  702. {
  703. if (Files[Index]->Selected)
  704. {
  705. FSelectedFiles->Add(Files[Index]->FullFileName);
  706. }
  707. }
  708. return FSelectedFiles;
  709. }
  710. //---------------------------------------------------------------------------
  711. void __fastcall TRemoteDirectory::SetIncludeParentDirectory(Boolean value)
  712. {
  713. if (IncludeParentDirectory != value)
  714. {
  715. FIncludeParentDirectory = value;
  716. if (value && ParentDirectory)
  717. {
  718. assert(IndexOf(ParentDirectory) < 0);
  719. Add(ParentDirectory);
  720. }
  721. else if (!value && ParentDirectory)
  722. {
  723. assert(IndexOf(ParentDirectory) >= 0);
  724. Extract(ParentDirectory);
  725. }
  726. }
  727. }
  728. //---------------------------------------------------------------------------
  729. void __fastcall TRemoteDirectory::SetIncludeThisDirectory(Boolean value)
  730. {
  731. if (IncludeThisDirectory != value)
  732. {
  733. FIncludeThisDirectory = value;
  734. if (value && ThisDirectory)
  735. {
  736. assert(IndexOf(ThisDirectory) < 0);
  737. Add(ThisDirectory);
  738. }
  739. else if (!value && ThisDirectory)
  740. {
  741. assert(IndexOf(ThisDirectory) >= 0);
  742. Extract(ThisDirectory);
  743. }
  744. }
  745. }
  746. //===========================================================================
  747. __fastcall TRemoteDirectoryCache::TRemoteDirectoryCache(): TStringList()
  748. {
  749. Sorted = true;
  750. Duplicates = dupError;
  751. CaseSensitive = true;
  752. }
  753. //---------------------------------------------------------------------------
  754. __fastcall TRemoteDirectoryCache::~TRemoteDirectoryCache()
  755. {
  756. for (int Index = 0; Index < Count; Index++)
  757. {
  758. delete (TRemoteFileList *)Objects[Index];
  759. Objects[Index] = NULL;
  760. }
  761. }
  762. //---------------------------------------------------------------------------
  763. TRemoteFileList * __fastcall TRemoteDirectoryCache::GetFileList(const AnsiString Directory)
  764. {
  765. int Index = IndexOf(UnixExcludeTrailingBackslash(Directory));
  766. return (Index >= 0 ? (TRemoteFileList *)Objects[Index] : NULL);
  767. }
  768. //---------------------------------------------------------------------------
  769. void __fastcall TRemoteDirectoryCache::AddFileList(TRemoteFileList * FileList)
  770. {
  771. assert(FileList);
  772. TRemoteFileList * Copy = new TRemoteFileList();
  773. FileList->DuplicateTo(Copy);
  774. AddObject(Copy->Directory, Copy);
  775. }
  776. //---------------------------------------------------------------------------
  777. void __fastcall TRemoteDirectoryCache::ClearFileList(AnsiString Directory, bool SubDirs)
  778. {
  779. Directory = UnixExcludeTrailingBackslash(Directory);
  780. int Index = IndexOf(Directory);
  781. if (Index >= 0)
  782. {
  783. Delete(Index);
  784. }
  785. if (SubDirs)
  786. {
  787. Directory = UnixIncludeTrailingBackslash(Directory);
  788. Index = Count-1;
  789. while (Index >= 0)
  790. {
  791. if (Strings[Index].SubString(1, Directory.Length()) == Directory)
  792. {
  793. Delete(Index);
  794. }
  795. Index--;
  796. }
  797. }
  798. }
  799. //---------------------------------------------------------------------------
  800. void __fastcall TRemoteDirectoryCache::Delete(int Index)
  801. {
  802. delete (TRemoteFileList *)Objects[Index];
  803. TStringList::Delete(Index);
  804. }
  805. //=== TRights ---------------------------------------------------------------
  806. __fastcall TRights::TRights()
  807. {
  808. FAllowUndef = False;
  809. FText.SetLength(RightsFlagCount);
  810. Number = 0;
  811. }
  812. //---------------------------------------------------------------------------
  813. __fastcall TRights::TRights(Word aNumber)
  814. {
  815. FAllowUndef = False;
  816. FText.SetLength(RightsFlagCount);
  817. Number = aNumber;
  818. }
  819. //---------------------------------------------------------------------------
  820. __fastcall TRights::TRights(const TRights & Source)
  821. {
  822. Assign(&Source);
  823. }
  824. //---------------------------------------------------------------------------
  825. void __fastcall TRights::Assign(const TRights * Source)
  826. {
  827. AllowUndef = Source->AllowUndef;
  828. Text = Source->Text;
  829. }
  830. //---------------------------------------------------------------------------
  831. void __fastcall TRights::SetText(AnsiString value)
  832. {
  833. if (value != FText)
  834. {
  835. if ((value.Length() != RightsFlagCount) ||
  836. (!AllowUndef && value.Pos(UNDEFRIGHT)) ||
  837. value.Pos(" "))
  838. throw Exception(FmtLoadStr(RIGHTS_ERROR, ARRAYOFCONST((value))));
  839. FText = value;
  840. }
  841. }
  842. //---------------------------------------------------------------------------
  843. void __fastcall TRights::SetOctal(AnsiString value)
  844. {
  845. bool Correct = (value.Length() == 3);
  846. if (Correct)
  847. {
  848. for (int i = 1; i <= value.Length() && Correct; i++)
  849. {
  850. Correct = value[i] >= '0' && value[i] <= '7';
  851. }
  852. }
  853. if (!Correct)
  854. {
  855. throw Exception(FMTLOAD(INVALID_OCTAL_PERMISSIONS, (value)));
  856. }
  857. #pragma option push -w-sig
  858. Number =
  859. ((value[1] - '0') << 6) +
  860. ((value[2] - '0') << 3) +
  861. ((value[3] - '0') << 0);
  862. #pragma option pop
  863. }
  864. //---------------------------------------------------------------------------
  865. void __fastcall TRights::SetNumber(Word value)
  866. {
  867. for (int Index = 0; Index < RightsFlagCount; Index++)
  868. {
  869. Right[(TRightsFlag)Index] = (Boolean)((value & (1 << (RightsFlagCount - 1 - Index))) != 0);
  870. }
  871. }
  872. //---------------------------------------------------------------------------
  873. AnsiString __fastcall TRights::GetOctal() const
  874. {
  875. AnsiString Result;
  876. Word N = NumberSet; // used to be "Number"
  877. Result += (char)('0' + ((N & 0700) >> 6));
  878. Result += (char)('0' + ((N & 0070) >> 3));
  879. Result += (char)('0' + ((N & 0007) >> 0));
  880. return Result;
  881. }
  882. //---------------------------------------------------------------------------
  883. Word __fastcall TRights::CalcNumber(TRightState State, Boolean
  884. #ifdef _DEBUG
  885. AllowUndef
  886. #endif
  887. ) const
  888. {
  889. Word Result = 0;
  890. for (int Index = 0; Index < RightsFlagCount; Index++)
  891. {
  892. TRightState AState = RightUndef[(TRightsFlag)Index];
  893. assert(AllowUndef || (AState != rsUndef));
  894. if (AState == State) Result |= (Word)(1 << (RightsFlagCount - 1 - Index));
  895. }
  896. return Result;
  897. }
  898. //---------------------------------------------------------------------------
  899. Word __fastcall TRights::GetNumber() const
  900. {
  901. return CalcNumber(rsYes, False);
  902. }
  903. //---------------------------------------------------------------------------
  904. Word __fastcall TRights::GetNumberSet() const
  905. {
  906. return CalcNumber(rsYes, True);
  907. }
  908. //---------------------------------------------------------------------------
  909. Word __fastcall TRights::GetNumberUnset() const
  910. {
  911. return CalcNumber(rsNo, True);
  912. }
  913. //---------------------------------------------------------------------------
  914. AnsiString __fastcall TRights::GetText() const
  915. {
  916. return FText;
  917. }
  918. //---------------------------------------------------------------------------
  919. void __fastcall TRights::SetAllowUndef(Boolean value)
  920. {
  921. if (FAllowUndef != value)
  922. {
  923. assert(!value || !FText.Pos(UNDEFRIGHT));
  924. FAllowUndef = value;
  925. }
  926. }
  927. //---------------------------------------------------------------------------
  928. AnsiString __fastcall TRights::GetFullRights() const
  929. {
  930. return FULLRIGHTS;
  931. }
  932. //---------------------------------------------------------------------------
  933. void __fastcall TRights::SetRight(TRightsFlag Flag, Boolean value)
  934. {
  935. RightUndef[Flag] = (value ? rsYes : rsNo);
  936. }
  937. //---------------------------------------------------------------------------
  938. Boolean __fastcall TRights::GetRight(TRightsFlag Flag) const
  939. {
  940. TRightState State = RightUndef[Flag];
  941. assert(State != rsUndef);
  942. return (State == rsYes);
  943. }
  944. //---------------------------------------------------------------------------
  945. void __fastcall TRights::SetRightUndef(TRightsFlag Flag, TRightState value)
  946. {
  947. if (value != RightUndef[Flag])
  948. {
  949. assert((value != rsUndef) || AllowUndef);
  950. switch (value) {
  951. case rsUndef: FText[Flag+1] = UNDEFRIGHT; break;
  952. case rsNo: FText[Flag+1] = NORIGHT; break;
  953. default: FText[Flag+1] = FullRights[Flag+1];
  954. }
  955. }
  956. }
  957. //---------------------------------------------------------------------------
  958. TRightState __fastcall TRights::GetRightUndef(TRightsFlag Flag) const
  959. {
  960. Char FlagChar = Text[Flag+1];
  961. if (FlagChar == NORIGHT) return rsNo;
  962. else
  963. if (FlagChar == FULLRIGHTS[Flag]) return rsYes;
  964. else return rsUndef;
  965. }
  966. //---------------------------------------------------------------------------
  967. TRights __fastcall TRights::operator |(const TRights & rhr) const
  968. {
  969. TRights Result = *this;
  970. Result |= rhr;
  971. return Result;
  972. }
  973. //---------------------------------------------------------------------------
  974. TRights __fastcall TRights::operator |(Integer rhr) const
  975. {
  976. TRights Result = *this;
  977. Result |= rhr;
  978. return Result;
  979. }
  980. //---------------------------------------------------------------------------
  981. TRights & __fastcall TRights::operator =(const TRights & rhr)
  982. {
  983. Assign(&rhr);
  984. return *this;
  985. }
  986. //---------------------------------------------------------------------------
  987. TRights & __fastcall TRights::operator =(Integer rhr)
  988. {
  989. Number = (Word)rhr;
  990. return *this;
  991. }
  992. //---------------------------------------------------------------------------
  993. TRights & __fastcall TRights::operator |=(const TRights & rhr)
  994. {
  995. Number |= rhr.Number;
  996. return *this;
  997. }
  998. //---------------------------------------------------------------------------
  999. TRights & __fastcall TRights::operator |=(Integer rhr)
  1000. {
  1001. Number |= (Word)rhr;
  1002. return *this;
  1003. }
  1004. //---------------------------------------------------------------------------
  1005. TRights __fastcall TRights::operator &(Integer rhr) const
  1006. {
  1007. TRights Result = *this;
  1008. Result &= rhr;
  1009. return Result;
  1010. }
  1011. //---------------------------------------------------------------------------
  1012. TRights __fastcall TRights::operator &(const TRights & rhr) const
  1013. {
  1014. TRights Result = *this;
  1015. Result &= rhr;
  1016. return Result;
  1017. }
  1018. //---------------------------------------------------------------------------
  1019. TRights & __fastcall TRights::operator &=(Integer rhr)
  1020. {
  1021. Number &= (Word)rhr;
  1022. return *this;
  1023. }
  1024. //---------------------------------------------------------------------------
  1025. TRights & __fastcall TRights::operator &=(const TRights & rhr)
  1026. {
  1027. if (AllowUndef)
  1028. {
  1029. for (int Index = 0; Index < RightsFlagCount; Index++)
  1030. if (RightUndef[(TRightsFlag)Index] != rhr.RightUndef[(TRightsFlag)Index])
  1031. RightUndef[(TRightsFlag)Index] = rsUndef;
  1032. }
  1033. else Number &= rhr.Number;
  1034. return *this;
  1035. }
  1036. //---------------------------------------------------------------------------
  1037. TRights __fastcall TRights::operator ~() const
  1038. {
  1039. TRights Result;
  1040. Result.Number = (Word)~Number;
  1041. return Result;
  1042. }
  1043. //---------------------------------------------------------------------------
  1044. bool __fastcall TRights::operator ==(const TRights & rhr) const
  1045. {
  1046. if (AllowUndef || rhr.AllowUndef)
  1047. {
  1048. for (int Index = 0; Index < RightsFlagCount; Index++)
  1049. if (RightUndef[(TRightsFlag)Index] != rhr.RightUndef[(TRightsFlag)Index])
  1050. return False;
  1051. return True;
  1052. }
  1053. else return (bool)(Number == rhr.Number);
  1054. }
  1055. //---------------------------------------------------------------------------
  1056. bool __fastcall TRights::operator ==(Integer rhr) const
  1057. {
  1058. return (bool)(Number == rhr);
  1059. }
  1060. //---------------------------------------------------------------------------
  1061. bool __fastcall TRights::operator !=(const TRights & rhr) const
  1062. {
  1063. return !(*this == rhr);
  1064. }
  1065. //---------------------------------------------------------------------------
  1066. void __fastcall TRights::SetReadOnly(Boolean value)
  1067. {
  1068. Right[rfUserWrite] = !value;
  1069. Right[rfGroupWrite] = !value;
  1070. Right[rfOtherWrite] = !value;
  1071. }
  1072. //---------------------------------------------------------------------------
  1073. Boolean __fastcall TRights::GetReadOnly()
  1074. {
  1075. return (Boolean)((NumberUnset & raWrite) == raWrite);
  1076. }
  1077. //---------------------------------------------------------------------------
  1078. AnsiString __fastcall TRights::GetSimplestStr() const
  1079. {
  1080. return IsUndef ? ModeStr : Octal;
  1081. }
  1082. //---------------------------------------------------------------------------
  1083. AnsiString __fastcall TRights::GetModeStr() const
  1084. {
  1085. AnsiString Result = "";
  1086. AnsiString SetModeStr, UnsetModeStr;
  1087. TRightsFlag Flag;
  1088. for (Integer Group = 0; Group < 3; Group++)
  1089. {
  1090. SetModeStr = "";
  1091. UnsetModeStr = "";
  1092. for (Integer Mode = 0; Mode < 3; Mode++)
  1093. {
  1094. Flag = (TRightsFlag)((Group * 3) + Mode);
  1095. switch (RightUndef[Flag]) {
  1096. case rsYes: SetModeStr += FULLRIGHTS[(int)Flag]; break;
  1097. case rsNo: UnsetModeStr += FULLRIGHTS[(int)Flag]; break;
  1098. }
  1099. }
  1100. if (!SetModeStr.IsEmpty() || !UnsetModeStr.IsEmpty())
  1101. {
  1102. if (!Result.IsEmpty()) Result += ',';
  1103. Result += MODEGROUPS[Group];
  1104. if (!SetModeStr.IsEmpty()) Result += "+" + SetModeStr;
  1105. if (!UnsetModeStr.IsEmpty()) Result += "-" + UnsetModeStr;
  1106. }
  1107. }
  1108. return Result;
  1109. }
  1110. //---------------------------------------------------------------------------
  1111. void __fastcall TRights::AddExecute()
  1112. {
  1113. for (int Index = 0; Index < 3; Index++)
  1114. {
  1115. if (NumberSet & (0700 >> (Index * 3)))
  1116. {
  1117. Right[(TRightsFlag)(rfUserExec + (Index * 3))] = true;
  1118. }
  1119. }
  1120. }
  1121. //---------------------------------------------------------------------------
  1122. void __fastcall TRights::AllUndef()
  1123. {
  1124. for (int Index = 0; Index < RightsFlagCount; Index++)
  1125. {
  1126. RightUndef[(TRightsFlag)Index] = rsUndef;
  1127. }
  1128. }
  1129. //---------------------------------------------------------------------------
  1130. Boolean __fastcall TRights::GetIsUndef() const
  1131. {
  1132. for (int Index = 0; Index < RightsFlagCount; Index++)
  1133. if (RightUndef[(TRightsFlag)Index] == rsUndef)
  1134. return True;
  1135. return False;
  1136. }
  1137. //---------------------------------------------------------------------------
  1138. __fastcall TRights::operator unsigned short() const
  1139. {
  1140. return Number;
  1141. }
  1142. //---------------------------------------------------------------------------
  1143. __fastcall TRights::operator unsigned long() const
  1144. {
  1145. return Number;
  1146. }
  1147. //=== TRemoteProperties -------------------------------------------------------
  1148. __fastcall TRemoteProperties::TRemoteProperties()
  1149. {
  1150. Valid.Clear();
  1151. AddXToDirectories = false;
  1152. Rights.AllowUndef = false;
  1153. Rights.Number = 0;
  1154. Group = "";
  1155. Owner = "";
  1156. Recursive = false;
  1157. };
  1158. /*//---------------------------------------------------------------------------
  1159. __fastcall TRemoteProperties::TRemoteProperties(const TRemoteProperties & Source)
  1160. {
  1161. *this = Source;
  1162. }
  1163. //---------------------------------------------------------------------------
  1164. void __fastcall TRemoteProperties::Clear()
  1165. {
  1166. };
  1167. //---------------------------------------------------------------------------
  1168. void __fastcall TRemoteProperties::operator =(const TRemoteProperties &rhp)
  1169. {
  1170. Valid = rhp.Valid;
  1171. Recursive = rhp.Recursive;
  1172. Rights = rhp.Rights;
  1173. AddXToDirectories = rhp.AddXToDirectories;
  1174. Group = rhp.Group;
  1175. Owner = rhp.Owner;
  1176. } */
  1177. //---------------------------------------------------------------------------
  1178. bool __fastcall TRemoteProperties::operator ==(const TRemoteProperties & rhp) const
  1179. {
  1180. bool Result = (Valid == rhp.Valid && Recursive == rhp.Recursive);
  1181. if (Result)
  1182. {
  1183. if ((Valid.Contains(vpRights) &&
  1184. (Rights != rhp.Rights || AddXToDirectories != rhp.AddXToDirectories)) ||
  1185. (Valid.Contains(vpOwner) && Owner != rhp.Owner) ||
  1186. (Valid.Contains(vpGroup) && Group != rhp.Group))
  1187. {
  1188. Result = false;
  1189. }
  1190. }
  1191. return Result;
  1192. }
  1193. //---------------------------------------------------------------------------
  1194. bool __fastcall TRemoteProperties::operator !=(const TRemoteProperties & rhp) const
  1195. {
  1196. return !(*this == rhp);
  1197. }
  1198. //---------------------------------------------------------------------------
  1199. TRemoteProperties __fastcall TRemoteProperties::CommonProperties(TStrings * FileList)
  1200. {
  1201. TRemoteProperties CommonProperties;
  1202. for (int Index = 0; Index < FileList->Count; Index++)
  1203. {
  1204. TRemoteFile * File = (TRemoteFile *)(FileList->Objects[Index]);
  1205. assert(File);
  1206. if (!Index)
  1207. {
  1208. CommonProperties.Rights = *(File->Rights);
  1209. CommonProperties.Rights.AllowUndef = File->IsDirectory || File->Rights->IsUndef;
  1210. CommonProperties.Valid << vpRights;
  1211. if (!File->Owner.IsEmpty())
  1212. {
  1213. CommonProperties.Owner = File->Owner;
  1214. CommonProperties.Valid << vpOwner;
  1215. }
  1216. if (!File->Group.IsEmpty())
  1217. {
  1218. CommonProperties.Group = File->Group;
  1219. CommonProperties.Valid << vpGroup;
  1220. }
  1221. }
  1222. else
  1223. {
  1224. CommonProperties.Rights.AllowUndef = True;
  1225. CommonProperties.Rights &= *File->Rights;
  1226. if (CommonProperties.Owner != File->Owner)
  1227. {
  1228. CommonProperties.Owner = "";
  1229. CommonProperties.Valid >> vpOwner;
  1230. };
  1231. if (CommonProperties.Group != File->Group)
  1232. {
  1233. CommonProperties.Group = "";
  1234. CommonProperties.Valid >> vpGroup;
  1235. };
  1236. }
  1237. }
  1238. return CommonProperties;
  1239. }
  1240. //---------------------------------------------------------------------------
  1241. TRemoteProperties __fastcall TRemoteProperties::ChangedProperties(
  1242. const TRemoteProperties & OriginalProperties, TRemoteProperties NewProperties)
  1243. {
  1244. if (!NewProperties.Recursive)
  1245. {
  1246. if (NewProperties.Rights == OriginalProperties.Rights &&
  1247. !NewProperties.AddXToDirectories)
  1248. {
  1249. NewProperties.Valid >> vpRights;
  1250. }
  1251. if (NewProperties.Group == OriginalProperties.Group)
  1252. {
  1253. NewProperties.Valid >> vpGroup;
  1254. }
  1255. if (NewProperties.Owner == OriginalProperties.Owner)
  1256. {
  1257. NewProperties.Valid >> vpOwner;
  1258. }
  1259. }
  1260. return NewProperties;
  1261. }