RemoteFiles.cpp 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174
  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. // it used to return "/" when input path was empty
  16. if (!Path.IsEmpty() && !Path.IsDelimiter("/", Path.Length()))
  17. {
  18. return Path + "/";
  19. }
  20. else
  21. {
  22. return Path;
  23. }
  24. }
  25. //---------------------------------------------------------------------------
  26. // Keeps "/" for root path
  27. AnsiString __fastcall UnixExcludeTrailingBackslash(const AnsiString Path)
  28. {
  29. if ((Path.Length() > 1) && Path.IsDelimiter("/", Path.Length()))
  30. return Path.SubString(1, Path.Length() - 1);
  31. else return Path;
  32. }
  33. //---------------------------------------------------------------------------
  34. Boolean __fastcall UnixComparePaths(const AnsiString Path1, const AnsiString Path2)
  35. {
  36. return (UnixIncludeTrailingBackslash(Path1) == UnixIncludeTrailingBackslash(Path2));
  37. }
  38. //---------------------------------------------------------------------------
  39. AnsiString __fastcall UnixExtractFileDir(const AnsiString Path)
  40. {
  41. int Pos = Path.LastDelimiter('/');
  42. // it used to return Path when no slash was found
  43. if (Pos > 1)
  44. {
  45. return Path.SubString(1, Pos - 1);
  46. }
  47. else
  48. {
  49. return (Pos == 1) ? AnsiString("/") : AnsiString();
  50. }
  51. }
  52. //---------------------------------------------------------------------------
  53. // must return trailing backslash
  54. AnsiString __fastcall UnixExtractFilePath(const AnsiString Path)
  55. {
  56. int Pos = Path.LastDelimiter('/');
  57. // it used to return Path when no slash was found
  58. return (Pos > 0) ? Path.SubString(1, Pos) : AnsiString();
  59. }
  60. //---------------------------------------------------------------------------
  61. AnsiString __fastcall UnixExtractFileName(const AnsiString Path)
  62. {
  63. int Pos = Path.LastDelimiter('/');
  64. return (Pos > 0) ? Path.SubString(Pos + 1, Path.Length() - Pos) : Path;
  65. }
  66. //---------------------------------------------------------------------------
  67. AnsiString __fastcall UnixExtractFileExt(const AnsiString Path)
  68. {
  69. AnsiString FileName = UnixExtractFileName(Path);
  70. int Pos = FileName.LastDelimiter(".");
  71. return (Pos > 0) ? Path.SubString(Pos, Path.Length() - Pos + 1) : AnsiString();
  72. }
  73. //---------------------------------------------------------------------------
  74. AnsiString __fastcall ExtractFileName(const AnsiString & Path, bool Unix)
  75. {
  76. if (Unix)
  77. {
  78. return UnixExtractFileName(Path);
  79. }
  80. else
  81. {
  82. return ExtractFileName(Path);
  83. }
  84. }
  85. //---------------------------------------------------------------------------
  86. bool __fastcall ExtractCommonPath(TStrings * Files, AnsiString & Path)
  87. {
  88. assert(Files->Count > 0);
  89. Path = ExtractFilePath(Files->Strings[0]);
  90. bool Result = !Path.IsEmpty();
  91. if (Result)
  92. {
  93. for (int Index = 1; Index < Files->Count; Index++)
  94. {
  95. while (Path.IsEmpty() &&
  96. (Files->Strings[Index].SubString(1, Path.Length()) != Path))
  97. {
  98. int PrevLen = Path.Length();
  99. Path = ExtractFilePath(ExcludeTrailingBackslash(Path));
  100. if (Path.Length() == PrevLen)
  101. {
  102. Path = "";
  103. }
  104. }
  105. }
  106. }
  107. return Result;
  108. }
  109. //---------------------------------------------------------------------------
  110. bool __fastcall UnixExtractCommonPath(TStrings * Files, AnsiString & Path)
  111. {
  112. assert(Files->Count > 0);
  113. Path = UnixExtractFilePath(Files->Strings[0]);
  114. bool Result = !Path.IsEmpty();
  115. if (Result)
  116. {
  117. for (int Index = 1; Index < Files->Count; Index++)
  118. {
  119. while (Path.IsEmpty() &&
  120. (Files->Strings[Index].SubString(1, Path.Length()) != Path))
  121. {
  122. int PrevLen = Path.Length();
  123. Path = UnixExtractFilePath(UnixExcludeTrailingBackslash(Path));
  124. if (Path.Length() == PrevLen)
  125. {
  126. Path = "";
  127. }
  128. }
  129. }
  130. }
  131. return Result;
  132. }
  133. //---------------------------------------------------------------------------
  134. bool __fastcall IsUnixRootPath(const AnsiString Path)
  135. {
  136. return Path.IsEmpty() || (Path == ROOTDIRECTORY);
  137. }
  138. //---------------------------------------------------------------------------
  139. bool __fastcall IsUnixHiddenFile(const AnsiString FileName)
  140. {
  141. return (FileName != ROOTDIRECTORY) && (FileName != PARENTDIRECTORY) &&
  142. !FileName.IsEmpty() && (FileName[1] == '.');
  143. }
  144. //---------------------------------------------------------------------------
  145. AnsiString __fastcall AbsolutePath(const AnsiString & Base, const AnsiString & Path)
  146. {
  147. AnsiString Result;
  148. if (Path.IsEmpty())
  149. {
  150. Result = Base;
  151. }
  152. else if (Path[1] == '/')
  153. {
  154. Result = UnixExcludeTrailingBackslash(Path);
  155. }
  156. else
  157. {
  158. Result = UnixIncludeTrailingBackslash(
  159. UnixIncludeTrailingBackslash(Base) + Path);
  160. int P;
  161. while ((P = Result.Pos("/../")) > 0)
  162. {
  163. int P2 = Result.SubString(1, P-1).LastDelimiter("/");
  164. assert(P2 > 0);
  165. Result.Delete(P2, P - P2 + 3);
  166. }
  167. while ((P = Result.Pos("/./")) > 0)
  168. {
  169. Result.Delete(P, 2);
  170. }
  171. Result = UnixExcludeTrailingBackslash(Result);
  172. }
  173. return Result;
  174. }
  175. //---------------------------------------------------------------------------
  176. AnsiString __fastcall FromUnixPath(const AnsiString Path)
  177. {
  178. return StringReplace(Path, "/", "\\", TReplaceFlags() << rfReplaceAll);
  179. }
  180. //---------------------------------------------------------------------------
  181. AnsiString __fastcall ToUnixPath(const AnsiString Path)
  182. {
  183. return StringReplace(Path, "\\", "/", TReplaceFlags() << rfReplaceAll);
  184. }
  185. //---------------------------------------------------------------------------
  186. static void __fastcall CutFirstDirectory(AnsiString & S, bool Unix)
  187. {
  188. bool Root;
  189. int P;
  190. AnsiString Sep = Unix ? "/" : "\\";
  191. if (S == Sep)
  192. {
  193. S = "";
  194. }
  195. else
  196. {
  197. if (S[1] == Sep[1])
  198. {
  199. Root = true;
  200. S.Delete(1, 1);
  201. }
  202. else
  203. {
  204. Root = false;
  205. }
  206. if (S[1] == '.')
  207. {
  208. S.Delete(1, 4);
  209. }
  210. P = S.AnsiPos(Sep[1]);
  211. if (P)
  212. {
  213. S.Delete(1, P);
  214. S = "..." + Sep + S;
  215. }
  216. else
  217. {
  218. S = "";
  219. }
  220. if (Root)
  221. {
  222. S = Sep + S;
  223. }
  224. }
  225. }
  226. //---------------------------------------------------------------------------
  227. AnsiString __fastcall MinimizeName(const AnsiString FileName, int MaxLen, bool Unix)
  228. {
  229. AnsiString Drive, Dir, Name, Result;
  230. AnsiString Sep = Unix ? "/" : "\\";
  231. Result = FileName;
  232. if (Unix)
  233. {
  234. int P = Result.LastDelimiter("/");
  235. if (P)
  236. {
  237. Dir = Result.SubString(1, P);
  238. Name = Result.SubString(P + 1, Result.Length() - P);
  239. }
  240. else
  241. {
  242. Dir = "";
  243. Name = Result;
  244. }
  245. }
  246. else
  247. {
  248. Dir = ExtractFilePath(Result);
  249. Name = ExtractFileName(Result);
  250. if (Dir.Length() >= 2 && Dir[2] == ':')
  251. {
  252. Drive = Dir.SubString(1, 2);
  253. Dir.Delete(1, 2);
  254. }
  255. }
  256. while ((!Dir.IsEmpty() || !Drive.IsEmpty()) && (Result.Length() > MaxLen))
  257. {
  258. if (Dir == Sep + "..." + Sep)
  259. {
  260. Dir = "..." + Sep;
  261. }
  262. else if (Dir == "")
  263. {
  264. Drive = "";
  265. }
  266. else
  267. {
  268. CutFirstDirectory(Dir, Unix);
  269. }
  270. Result = Drive + Dir + Name;
  271. }
  272. if (Result.Length() > MaxLen)
  273. {
  274. Result = Result.SubString(1, MaxLen);
  275. }
  276. return Result;
  277. }
  278. //---------------------------------------------------------------------------
  279. AnsiString __fastcall MakeFileList(TStrings * FileList)
  280. {
  281. AnsiString Result;
  282. for (int Index = 0; Index < FileList->Count; Index++)
  283. {
  284. if (!Result.IsEmpty())
  285. {
  286. Result += " ";
  287. }
  288. AnsiString FileName = FileList->Strings[Index];
  289. // currently this is used for local file only, so no delimiting is done
  290. if (FileName.Pos(" ") > 0)
  291. {
  292. Result += "\"" + FileName + "\"";
  293. }
  294. else
  295. {
  296. Result += FileName;
  297. }
  298. }
  299. return Result;
  300. }
  301. //---------------------------------------------------------------------------
  302. // copy from BaseUtils.pas
  303. void __fastcall ReduceDateTimePrecision(TDateTime & DateTime,
  304. TModificationFmt Precision)
  305. {
  306. if (Precision == mfNone)
  307. {
  308. DateTime = double(0);
  309. }
  310. else if (Precision != mfFull)
  311. {
  312. unsigned short Y, M, D, H, N, S, MS;
  313. DecodeDate(DateTime, Y, M, D);
  314. DecodeTime(DateTime, H, N, S, MS);
  315. switch (Precision)
  316. {
  317. case mfMDHM:
  318. S = 0;
  319. MS = 0;
  320. break;
  321. case mfMDY:
  322. H = 0;
  323. N = 0;
  324. S = 0;
  325. MS = 0;
  326. default:
  327. assert(false);
  328. }
  329. DateTime = EncodeDate(Y, M, D) + EncodeTime(H, N, S, MS);
  330. }
  331. }
  332. //---------------------------------------------------------------------------
  333. AnsiString __fastcall UserModificationStr(TDateTime DateTime,
  334. TModificationFmt Precision)
  335. {
  336. switch (Precision)
  337. {
  338. case mfNone:
  339. return "";
  340. case mfMDY:
  341. return FormatDateTime("ddddd", DateTime);
  342. case mfMDHM:
  343. return FormatDateTime("ddddd t", DateTime);
  344. case mfFull:
  345. default:
  346. return FormatDateTime("ddddd tt", DateTime);
  347. }
  348. }
  349. //---------------------------------------------------------------------------
  350. int __fastcall FakeFileImageIndex(AnsiString FileName, unsigned long Attrs,
  351. AnsiString * TypeName)
  352. {
  353. Attrs |= FILE_ATTRIBUTE_NORMAL;
  354. TSHFileInfo SHFileInfo;
  355. // On Win2k we get icon of "ZIP drive" for ".." (parent directory)
  356. if ((FileName == "..") ||
  357. ((FileName.Length() == 2) && (FileName[2] == ':') &&
  358. (tolower(FileName[1]) >= 'a') && (tolower(FileName[1]) <= 'z')))
  359. {
  360. FileName = "dumb";
  361. }
  362. // this should be somewhere else, probably in TUnixDirView,
  363. // as the "partial" overlay is added there too
  364. if (AnsiSameText(UnixExtractFileExt(FileName), PARTIAL_EXT))
  365. {
  366. static const size_t PartialExtLen = sizeof(PARTIAL_EXT) - 1;
  367. FileName.SetLength(FileName.Length() - PartialExtLen);
  368. }
  369. int Icon;
  370. if (SHGetFileInfo(FileName.c_str(),
  371. Attrs, &SHFileInfo, sizeof(SHFileInfo),
  372. SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES | SHGFI_TYPENAME) != 0)
  373. {
  374. if (TypeName != NULL)
  375. {
  376. *TypeName = SHFileInfo.szTypeName;
  377. }
  378. Icon = SHFileInfo.iIcon;
  379. }
  380. else
  381. {
  382. if (TypeName != NULL)
  383. {
  384. *TypeName = "";
  385. }
  386. Icon = -1;
  387. }
  388. return Icon;
  389. }
  390. //- TRemoteFiles ------------------------------------------------------------
  391. __fastcall TRemoteFile::TRemoteFile(TRemoteFile * ALinkedByFile):
  392. TPersistent()
  393. {
  394. FLinkedFile = NULL;
  395. FRights = new TRights();
  396. FIconIndex = -1;
  397. FCyclicLink = false;
  398. FModificationFmt = mfFull;
  399. FLinkedByFile = ALinkedByFile;
  400. FTerminal = NULL;
  401. FDirectory = NULL;
  402. FIsHidden = -1;
  403. }
  404. //---------------------------------------------------------------------------
  405. __fastcall TRemoteFile::~TRemoteFile()
  406. {
  407. delete FRights;
  408. delete FLinkedFile;
  409. }
  410. //---------------------------------------------------------------------------
  411. TRemoteFile * __fastcall TRemoteFile::Duplicate(bool Standalone) const
  412. {
  413. TRemoteFile * Result;
  414. Result = new TRemoteFile();
  415. try
  416. {
  417. if (FLinkedFile)
  418. {
  419. Result->FLinkedFile = FLinkedFile->Duplicate(true);
  420. Result->FLinkedFile->FLinkedByFile = Result;
  421. }
  422. *Result->Rights = *FRights;
  423. #define COPY_FP(PROP) Result->F ## PROP = F ## PROP;
  424. COPY_FP(Terminal);
  425. COPY_FP(Owner);
  426. COPY_FP(ModificationFmt);
  427. COPY_FP(Size);
  428. COPY_FP(FileName);
  429. COPY_FP(INodeBlocks);
  430. COPY_FP(Modification);
  431. COPY_FP(LastAccess);
  432. COPY_FP(Group);
  433. COPY_FP(IconIndex);
  434. COPY_FP(TypeName);
  435. COPY_FP(IsSymLink);
  436. COPY_FP(LinkTo);
  437. COPY_FP(Type);
  438. COPY_FP(Selected);
  439. COPY_FP(CyclicLink);
  440. #undef COPY_FP
  441. if (Standalone && (!FFullFileName.IsEmpty() || (Directory != NULL)))
  442. {
  443. Result->FFullFileName = FullFileName;
  444. }
  445. }
  446. catch(...)
  447. {
  448. delete Result;
  449. throw;
  450. }
  451. return Result;
  452. }
  453. //---------------------------------------------------------------------------
  454. void __fastcall TRemoteFile::LoadTypeInfo()
  455. {
  456. /* TODO : If file is link: Should be attributes taken from linked file? */
  457. unsigned long Attrs = 0;
  458. if (IsDirectory) Attrs |= FILE_ATTRIBUTE_DIRECTORY;
  459. if (IsHidden) Attrs |= FILE_ATTRIBUTE_HIDDEN;
  460. AnsiString DumbFileName = (IsSymLink && !LinkTo.IsEmpty() ? LinkTo : FileName);
  461. FIconIndex = FakeFileImageIndex(DumbFileName, Attrs, &FTypeName);
  462. }
  463. //---------------------------------------------------------------------------
  464. Integer __fastcall TRemoteFile::GetIconIndex() const
  465. {
  466. if (FIconIndex == -1)
  467. {
  468. const_cast<TRemoteFile *>(this)->LoadTypeInfo();
  469. }
  470. return FIconIndex;
  471. }
  472. //---------------------------------------------------------------------------
  473. AnsiString __fastcall TRemoteFile::GetTypeName()
  474. {
  475. // check avilability of type info by icon index, because type name can be empty
  476. if (FIconIndex < 0)
  477. {
  478. LoadTypeInfo();
  479. }
  480. return FTypeName;
  481. }
  482. //---------------------------------------------------------------------------
  483. Boolean __fastcall TRemoteFile::GetIsHidden()
  484. {
  485. bool Result;
  486. switch (FIsHidden)
  487. {
  488. case 0:
  489. Result = false;
  490. break;
  491. case 1:
  492. Result = true;
  493. break;
  494. default:
  495. Result = IsUnixHiddenFile(FileName);
  496. break;
  497. }
  498. return Result;
  499. }
  500. //---------------------------------------------------------------------------
  501. void __fastcall TRemoteFile::SetIsHidden(bool value)
  502. {
  503. FIsHidden = value ? 1 : 0;
  504. }
  505. //---------------------------------------------------------------------------
  506. Boolean __fastcall TRemoteFile::GetIsDirectory() const
  507. {
  508. return (toupper(Type) == FILETYPE_DIRECTORY);
  509. }
  510. //---------------------------------------------------------------------------
  511. Boolean __fastcall TRemoteFile::GetIsParentDirectory() const
  512. {
  513. return (FileName == PARENTDIRECTORY);
  514. }
  515. //---------------------------------------------------------------------------
  516. Boolean __fastcall TRemoteFile::GetIsThisDirectory() const
  517. {
  518. return (FileName == THISDIRECTORY);
  519. }
  520. //---------------------------------------------------------------------------
  521. Boolean __fastcall TRemoteFile::GetIsInaccesibleDirectory() const
  522. {
  523. Boolean Result;
  524. if (IsDirectory)
  525. {
  526. assert(Terminal);
  527. Result = !
  528. (((Rights->RightUndef[TRights::rrOtherExec] != TRights::rsNo)) ||
  529. ((Rights->Right[TRights::rrGroupExec] != TRights::rsNo) &&
  530. (Terminal->Groups->IndexOf(Group) >= 0)) ||
  531. ((Rights->Right[TRights::rrUserExec] != TRights::rsNo) &&
  532. (AnsiCompareText(Terminal->UserName, Owner) == 0)));
  533. }
  534. else Result = False;
  535. return Result;
  536. }
  537. //---------------------------------------------------------------------------
  538. char __fastcall TRemoteFile::GetType() const
  539. {
  540. if (IsSymLink && FLinkedFile) return FLinkedFile->Type;
  541. else return FType;
  542. }
  543. //---------------------------------------------------------------------------
  544. void __fastcall TRemoteFile::SetType(char AType)
  545. {
  546. FType = AType;
  547. // Allow even non-standard file types (e.g. 'S')
  548. // if (!AnsiString("-DL").Pos((Char)toupper(FType))) Abort();
  549. FIsSymLink = ((Char)toupper(FType) == FILETYPE_SYMLINK);
  550. }
  551. //---------------------------------------------------------------------------
  552. TRemoteFile * __fastcall TRemoteFile::GetLinkedFile()
  553. {
  554. // it would be called releatedly for broken symlinks
  555. //if (!FLinkedFile) FindLinkedFile();
  556. return FLinkedFile;
  557. }
  558. //---------------------------------------------------------------------------
  559. void __fastcall TRemoteFile::SetLinkedFile(TRemoteFile * value)
  560. {
  561. if (FLinkedFile != value)
  562. {
  563. if (FLinkedFile) delete FLinkedFile;
  564. FLinkedFile = value;
  565. }
  566. }
  567. //---------------------------------------------------------------------------
  568. bool __fastcall TRemoteFile::GetBrokenLink()
  569. {
  570. assert(Terminal);
  571. // If file is symlink but we couldn't find linked file we assume broken link
  572. return (IsSymLink && (FCyclicLink || !FLinkedFile) &&
  573. Terminal->ResolvingSymlinks);
  574. // "!FLinkTo.IsEmpty()" removed because it does not work with SFTP
  575. }
  576. //---------------------------------------------------------------------------
  577. void __fastcall TRemoteFile::ShiftTime(const TDateTime & Difference)
  578. {
  579. double D = double(Difference);
  580. if ((D != 0) && (FModificationFmt != mfMDY))
  581. {
  582. assert(int(FModification) != 0);
  583. FModification = double(FModification) + D;
  584. assert(int(FLastAccess) != 0);
  585. FLastAccess = double(FLastAccess) + D;
  586. }
  587. }
  588. //---------------------------------------------------------------------------
  589. void __fastcall TRemoteFile::SetModification(const TDateTime & value)
  590. {
  591. if (FModification != value)
  592. {
  593. FModificationFmt = mfFull;
  594. FModification = value;
  595. }
  596. }
  597. //---------------------------------------------------------------------------
  598. AnsiString __fastcall TRemoteFile::GetUserModificationStr()
  599. {
  600. return ::UserModificationStr(Modification, FModificationFmt);
  601. }
  602. //---------------------------------------------------------------------------
  603. AnsiString __fastcall TRemoteFile::GetModificationStr()
  604. {
  605. Word Year, Month, Day, Hour, Min, Sec, MSec;
  606. Modification.DecodeDate(&Year, &Month, &Day);
  607. Modification.DecodeTime(&Hour, &Min, &Sec, &MSec);
  608. switch (FModificationFmt)
  609. {
  610. case mfNone:
  611. return "";
  612. case mfMDY:
  613. return FORMAT("%3s %2d %2d", (EngShortMonthNames[Month-1], Day, Year));
  614. case mfMDHM:
  615. return FORMAT("%3s %2d %2d:%2.2d",
  616. (EngShortMonthNames[Month-1], Day, Hour, Min));
  617. default:
  618. assert(false);
  619. // fall thru
  620. case mfFull:
  621. return FORMAT("%3s %2d %2d:%2.2d:%2.2d %4d",
  622. (EngShortMonthNames[Month-1], Day, Hour, Min, Sec, Year));
  623. }
  624. }
  625. //---------------------------------------------------------------------------
  626. AnsiString __fastcall TRemoteFile::GetExtension()
  627. {
  628. return UnixExtractFileExt(FFileName);
  629. }
  630. //---------------------------------------------------------------------------
  631. void __fastcall TRemoteFile::SetRights(TRights * value)
  632. {
  633. FRights->Assign(value);
  634. }
  635. //---------------------------------------------------------------------------
  636. AnsiString __fastcall TRemoteFile::GetRightsStr()
  637. {
  638. return FRights->Unknown ? AnsiString() : FRights->Text;
  639. }
  640. //---------------------------------------------------------------------------
  641. void __fastcall TRemoteFile::SetListingStr(AnsiString value)
  642. {
  643. // Value stored in 'value' can be used for error message
  644. AnsiString Line = value;
  645. FIconIndex = -1;
  646. try
  647. {
  648. AnsiString Col;
  649. // Do we need to do this (is ever TAB is LS output)?
  650. Line = ReplaceChar(Line, '\t', ' ');
  651. Type = Line[1];
  652. Line.Delete(1, 1);
  653. #define GETNCOL \
  654. { if (Line.IsEmpty()) throw Exception(""); \
  655. Integer P = Line.Pos(' '); \
  656. if (P) { Col = Line.SubString(1, P-1); Line.Delete(1, P); } \
  657. else { Col = Line; Line = ""; } \
  658. }
  659. #define GETCOL { GETNCOL; Line = TrimLeft(Line); }
  660. // Rights string may contain special permission attributes (S,t, ...)
  661. // (TODO: maybe no longer necessary, once we can handle the special permissions)
  662. Rights->AllowUndef = True;
  663. // On some system there is no space between permissions and node blocks count columns
  664. // so we get only first 9 characters and trim all following spaces (if any)
  665. Rights->Text = Line.SubString(1, 9);
  666. Line.Delete(1, 9);
  667. // Rights column maybe followed by '+' sign, we ignore it
  668. // (On MacOS, there may be a space in between)
  669. if (!Line.IsEmpty() && (Line[1] == '+'))
  670. {
  671. Line.Delete(1, 1);
  672. }
  673. else if ((Line.Length() >= 2) && (Line[1] == ' ') && (Line[2] == '+'))
  674. {
  675. Line.Delete(1, 2);
  676. }
  677. Line = Line.TrimLeft();
  678. GETCOL;
  679. FINodeBlocks = StrToInt(Col);
  680. GETCOL;
  681. FOwner = Col;
  682. // #60 17.10.01: group name can contain space
  683. FGroup = "";
  684. GETCOL;
  685. __int64 ASize;
  686. do
  687. {
  688. FGroup += Col;
  689. GETCOL;
  690. assert(!Col.IsEmpty());
  691. // for devices etc.. there is additional column ending by comma, we ignore it
  692. if (Col[Col.Length()] == ',') GETCOL;
  693. ASize = StrToInt64Def(Col, -1);
  694. // if it's not a number (file size) we take it as part of group name
  695. // (at least on CygWin, there can be group with space in its name)
  696. if (ASize < 0) Col = " " + Col;
  697. }
  698. while (ASize < 0);
  699. // do not read modification time and filename if it is already set
  700. if (double(FModification) == 0 && FileName.IsEmpty())
  701. {
  702. FSize = ASize;
  703. bool FullTime = false;
  704. bool DayMonthFormat = false;
  705. Word Day, Month, Year, Hour, Min, Sec, P;
  706. GETCOL;
  707. // format dd mmm or mmm dd ?
  708. Day = (Word)StrToIntDef(Col, 0);
  709. if (Day > 0)
  710. {
  711. DayMonthFormat = true;
  712. GETCOL;
  713. }
  714. Month = 0;
  715. #define COL2MONTH \
  716. for (Word IMonth = 0; IMonth < 12; IMonth++) \
  717. if (!Col.AnsiCompareIC(EngShortMonthNames[IMonth])) { Month = IMonth; Month++; break; }
  718. COL2MONTH;
  719. // if the column is not known month name, it may have been "yyyy-mm-dd"
  720. // for --full-time format
  721. if ((Month == 0) && (Col.Length() == 10) && (Col[5] == '-') && (Col[8] == '-'))
  722. {
  723. Year = (Word)Col.SubString(1, 4).ToInt();
  724. Month = (Word)Col.SubString(6, 2).ToInt();
  725. Day = (Word)Col.SubString(9, 2).ToInt();
  726. GETCOL;
  727. Hour = (Word)Col.SubString(1, 2).ToInt();
  728. Min = (Word)Col.SubString(4, 2).ToInt();
  729. Sec = (Word)Col.SubString(7, 2).ToInt();
  730. FModificationFmt = mfFull;
  731. // skip TZ (TODO)
  732. // do not trim leading space of filename
  733. GETNCOL;
  734. }
  735. else
  736. {
  737. // or it may have been day name for another format of --full-time
  738. if (Month == 0)
  739. {
  740. GETCOL;
  741. COL2MONTH;
  742. // neither standard, not --full-time format
  743. if (Month == 0)
  744. {
  745. Abort();
  746. }
  747. else
  748. {
  749. FullTime = true;
  750. }
  751. }
  752. #undef COL2MONTH
  753. if (Day == 0)
  754. {
  755. GETNCOL;
  756. Day = (Word)StrToInt(Col);
  757. }
  758. if ((Day < 1) || (Day > 31)) Abort();
  759. // second full-time format
  760. // ddd mmm dd hh:nn:ss yyyy
  761. if (FullTime)
  762. {
  763. GETCOL;
  764. if (Col.Length() != 8)
  765. {
  766. Abort();
  767. }
  768. Hour = (Word)StrToInt(Col.SubString(1, 2));
  769. Min = (Word)StrToInt(Col.SubString(4, 2));
  770. Sec = (Word)StrToInt(Col.SubString(7, 2));
  771. FModificationFmt = mfFull;
  772. // do not trim leading space of filename
  773. GETNCOL;
  774. Year = (Word)StrToInt(Col);
  775. }
  776. else
  777. {
  778. // for format dd mmm the below description seems not to be true,
  779. // the year is not aligned to 5 characters
  780. if (DayMonthFormat)
  781. {
  782. GETCOL;
  783. }
  784. else
  785. {
  786. // Time/Year indicator is always 5 charactes long (???), on most
  787. // systems year is aligned to right (_YYYY), but on some to left (YYYY_),
  788. // we must ensure that trailing space is also deleted, so real
  789. // separator space is not treated as part of file name
  790. Col = Line.SubString(1, 6).Trim();
  791. Line.Delete(1, 6);
  792. }
  793. // GETNCOL; // We don't want to trim input strings (name with space at beginning???)
  794. // Check if we got time (contains :) or year
  795. if ((P = (Word)Col.Pos(':')) > 0)
  796. {
  797. Word CurrMonth, CurrDay;
  798. Hour = (Word)StrToInt(Col.SubString(1, P-1));
  799. Min = (Word)StrToInt(Col.SubString(P+1, Col.Length() - P));
  800. if (Hour > 23 || Hour > 59) Abort();
  801. // When we don't got year, we assume current year
  802. // with exception that the date would be in future
  803. // in this case we assume last year.
  804. DecodeDate(Date(), Year, CurrMonth, CurrDay);
  805. if ((Month > CurrMonth) ||
  806. (Month == CurrMonth && Day > CurrDay)) Year--;
  807. Sec = 0;
  808. FModificationFmt = mfMDHM;
  809. }
  810. else
  811. {
  812. Year = (Word)StrToInt(Col);
  813. if (Year > 10000) Abort();
  814. // When we don't got time we assume midnight
  815. Hour = 0; Min = 0; Sec = 0;
  816. FModificationFmt = mfMDY;
  817. }
  818. }
  819. }
  820. FModification = EncodeDate(Year, Month, Day) + EncodeTime(Hour, Min, Sec, 0);
  821. // adjust only when time is known,
  822. // adjusting default "midnight" time makes no sense
  823. if ((FModificationFmt == mfMDHM) || (FModificationFmt == mfFull))
  824. {
  825. assert(Terminal != NULL);
  826. FModification = AdjustDateTimeFromUnix(FModification,
  827. Terminal->SessionData->DSTMode);
  828. }
  829. if (double(FLastAccess) == 0)
  830. {
  831. FLastAccess = FModification;
  832. }
  833. // separating space is already deleted, other spaces are treated as part of name
  834. {
  835. int P;
  836. FLinkTo = "";
  837. if (IsSymLink)
  838. {
  839. P = Line.Pos(SYMLINKSTR);
  840. if (P)
  841. {
  842. FLinkTo = Line.SubString(
  843. P + strlen(SYMLINKSTR), Line.Length() - P + strlen(SYMLINKSTR) + 1);
  844. Line.SetLength(P - 1);
  845. }
  846. else
  847. {
  848. Abort();
  849. }
  850. }
  851. FFileName = UnixExtractFileName(Line);
  852. }
  853. }
  854. #undef GETNCOL
  855. #undef GETCOL
  856. }
  857. catch (Exception &E)
  858. {
  859. throw ETerminal(&E, FmtLoadStr(LIST_LINE_ERROR, ARRAYOFCONST((value))));
  860. }
  861. }
  862. //---------------------------------------------------------------------------
  863. void __fastcall TRemoteFile::Complete()
  864. {
  865. assert(Terminal != NULL);
  866. if (IsSymLink && Terminal->ResolvingSymlinks)
  867. {
  868. FindLinkedFile();
  869. }
  870. }
  871. //---------------------------------------------------------------------------
  872. void __fastcall TRemoteFile::FindLinkedFile()
  873. {
  874. assert(Terminal && IsSymLink);
  875. if (FLinkedFile) delete FLinkedFile;
  876. FLinkedFile = NULL;
  877. FCyclicLink = false;
  878. if (!LinkTo.IsEmpty())
  879. {
  880. // check for cyclic link
  881. TRemoteFile * LinkedBy = FLinkedByFile;
  882. while (LinkedBy)
  883. {
  884. if (LinkedBy->LinkTo == LinkTo)
  885. {
  886. // this is currenly redundant information, because it is used only to
  887. // detect broken symlink, which would be otherwise detected
  888. // by FLinkedFile == NULL
  889. FCyclicLink = true;
  890. break;
  891. }
  892. LinkedBy = LinkedBy->FLinkedByFile;
  893. }
  894. }
  895. if (FCyclicLink)
  896. {
  897. TRemoteFile * LinkedBy = FLinkedByFile;
  898. while (LinkedBy)
  899. {
  900. LinkedBy->FCyclicLink = true;
  901. LinkedBy = LinkedBy->FLinkedByFile;
  902. }
  903. }
  904. else
  905. {
  906. assert(Terminal->ResolvingSymlinks);
  907. Terminal->ExceptionOnFail = true;
  908. try
  909. {
  910. try
  911. {
  912. Terminal->ReadSymlink(this, FLinkedFile);
  913. }
  914. __finally
  915. {
  916. Terminal->ExceptionOnFail = false;
  917. }
  918. }
  919. catch (Exception &E)
  920. {
  921. if (E.InheritsFrom(__classid(EFatal))) throw;
  922. else Terminal->Log->AddException(&E);
  923. }
  924. }
  925. }
  926. //---------------------------------------------------------------------------
  927. AnsiString __fastcall TRemoteFile::GetListingStr()
  928. {
  929. // note that ModificationStr is longer than 12 for mfFull
  930. AnsiString LinkPart;
  931. // expanded from ?: to avoid memory leaks
  932. if (IsSymLink)
  933. {
  934. LinkPart = AnsiString(SYMLINKSTR) + LinkTo;
  935. }
  936. return Format("%s%s %3s %-8s %-8s %9s %-12s %s%s", ARRAYOFCONST((
  937. Type, Rights->Text, IntToStr(INodeBlocks), Owner,
  938. Group, IntToStr(Size), ModificationStr, FileName,
  939. LinkPart)));
  940. }
  941. //---------------------------------------------------------------------------
  942. AnsiString __fastcall TRemoteFile::GetFullFileName() const
  943. {
  944. if (FFullFileName.IsEmpty())
  945. {
  946. assert(Terminal);
  947. assert(Directory != NULL);
  948. AnsiString Path;
  949. if (IsParentDirectory) Path = Directory->ParentPath;
  950. else
  951. if (IsDirectory) Path = UnixIncludeTrailingBackslash(Directory->FullDirectory + FileName);
  952. else Path = Directory->FullDirectory + FileName;
  953. return Terminal->TranslateLockedPath(Path, true);
  954. }
  955. else
  956. {
  957. return FFullFileName;
  958. }
  959. }
  960. //---------------------------------------------------------------------------
  961. bool __fastcall TRemoteFile::GetHaveFullFileName() const
  962. {
  963. return !FFullFileName.IsEmpty() || (Directory != NULL);
  964. }
  965. //---------------------------------------------------------------------------
  966. Integer __fastcall TRemoteFile::GetAttr()
  967. {
  968. Integer Result = 0;
  969. if (Rights->ReadOnly) Result |= faReadOnly;
  970. if (IsHidden) Result |= faHidden;
  971. return Result;
  972. }
  973. //---------------------------------------------------------------------------
  974. void __fastcall TRemoteFile::SetTerminal(TTerminal * value)
  975. {
  976. FTerminal = value;
  977. if (FLinkedFile)
  978. {
  979. FLinkedFile->Terminal = value;
  980. }
  981. }
  982. //---------------------------------------------------------------------------
  983. //---------------------------------------------------------------------------
  984. __fastcall TRemoteDirectoryFile::TRemoteDirectoryFile() : TRemoteFile()
  985. {
  986. Modification = double(0);
  987. ModificationFmt = mfNone;
  988. LastAccess = Modification;
  989. Type = 'D';
  990. Size = 0;
  991. }
  992. //---------------------------------------------------------------------------
  993. //---------------------------------------------------------------------------
  994. __fastcall TRemoteParentDirectory::TRemoteParentDirectory() : TRemoteDirectoryFile()
  995. {
  996. FileName = PARENTDIRECTORY;
  997. }
  998. //=== TRemoteFileList ------------------------------------------------------
  999. __fastcall TRemoteFileList::TRemoteFileList():
  1000. TObjectList()
  1001. {
  1002. FTimestamp = Now();
  1003. }
  1004. //---------------------------------------------------------------------------
  1005. void __fastcall TRemoteFileList::AddFile(TRemoteFile * File)
  1006. {
  1007. Add(File);
  1008. File->Directory = this;
  1009. }
  1010. //---------------------------------------------------------------------------
  1011. void __fastcall TRemoteFileList::DuplicateTo(TRemoteFileList * Copy)
  1012. {
  1013. Copy->Clear();
  1014. for (int Index = 0; Index < Count; Index++)
  1015. {
  1016. TRemoteFile * File = Files[Index];
  1017. Copy->AddFile(File->Duplicate(false));
  1018. }
  1019. Copy->FDirectory = Directory;
  1020. Copy->FTimestamp = FTimestamp;
  1021. }
  1022. //---------------------------------------------------------------------------
  1023. void __fastcall TRemoteFileList::Clear()
  1024. {
  1025. FTimestamp = Now();
  1026. TObjectList::Clear();
  1027. }
  1028. //---------------------------------------------------------------------------
  1029. void __fastcall TRemoteFileList::SetDirectory(AnsiString value)
  1030. {
  1031. FDirectory = UnixExcludeTrailingBackslash(value);
  1032. }
  1033. //---------------------------------------------------------------------------
  1034. AnsiString __fastcall TRemoteFileList::GetFullDirectory()
  1035. {
  1036. return UnixIncludeTrailingBackslash(Directory);
  1037. }
  1038. //---------------------------------------------------------------------------
  1039. TRemoteFile * __fastcall TRemoteFileList::GetFiles(Integer Index)
  1040. {
  1041. return (TRemoteFile *)Items[Index];
  1042. }
  1043. //---------------------------------------------------------------------------
  1044. Boolean __fastcall TRemoteFileList::GetIsRoot()
  1045. {
  1046. return (Directory == ROOTDIRECTORY);
  1047. }
  1048. //---------------------------------------------------------------------------
  1049. AnsiString __fastcall TRemoteFileList::GetParentPath()
  1050. {
  1051. return UnixExtractFilePath(Directory);
  1052. }
  1053. //---------------------------------------------------------------------------
  1054. __int64 __fastcall TRemoteFileList::GetTotalSize()
  1055. {
  1056. __int64 Result = 0;
  1057. for (Integer Index = 0; Index < Count; Index++)
  1058. if (!Files[Index]->IsDirectory) Result += Files[Index]->Size;
  1059. return Result;
  1060. }
  1061. //---------------------------------------------------------------------------
  1062. TRemoteFile * __fastcall TRemoteFileList::FindFile(const AnsiString &FileName)
  1063. {
  1064. for (Integer Index = 0; Index < Count; Index++)
  1065. if (Files[Index]->FileName == FileName) return Files[Index];
  1066. return NULL;
  1067. }
  1068. //=== TRemoteDirectory ------------------------------------------------------
  1069. __fastcall TRemoteDirectory::TRemoteDirectory(TTerminal * aTerminal):
  1070. TRemoteFileList(), FTerminal(aTerminal)
  1071. {
  1072. FSelectedFiles = NULL;
  1073. FThisDirectory = NULL;
  1074. FParentDirectory = NULL;
  1075. FIncludeThisDirectory = false;
  1076. FIncludeParentDirectory = true;
  1077. }
  1078. //---------------------------------------------------------------------------
  1079. void __fastcall TRemoteDirectory::Clear()
  1080. {
  1081. if (ThisDirectory && !IncludeThisDirectory)
  1082. {
  1083. delete FThisDirectory;
  1084. FThisDirectory = NULL;
  1085. }
  1086. if (ParentDirectory && !IncludeParentDirectory)
  1087. {
  1088. delete FParentDirectory;
  1089. FParentDirectory = NULL;
  1090. }
  1091. TRemoteFileList::Clear();
  1092. }
  1093. //---------------------------------------------------------------------------
  1094. void __fastcall TRemoteDirectory::SetDirectory(AnsiString value)
  1095. {
  1096. TRemoteFileList::SetDirectory(value);
  1097. //Load();
  1098. }
  1099. //---------------------------------------------------------------------------
  1100. void __fastcall TRemoteDirectory::AddFile(TRemoteFile * File)
  1101. {
  1102. if (File->IsThisDirectory) FThisDirectory = File;
  1103. if (File->IsParentDirectory) FParentDirectory = File;
  1104. if ((!File->IsThisDirectory || IncludeThisDirectory) &&
  1105. (!File->IsParentDirectory || IncludeParentDirectory))
  1106. {
  1107. TRemoteFileList::AddFile(File);
  1108. }
  1109. File->Terminal = Terminal;
  1110. }
  1111. //---------------------------------------------------------------------------
  1112. void __fastcall TRemoteDirectory::DuplicateTo(TRemoteFileList * Copy)
  1113. {
  1114. TRemoteFileList::DuplicateTo(Copy);
  1115. if (ThisDirectory && !IncludeThisDirectory)
  1116. {
  1117. Copy->AddFile(ThisDirectory->Duplicate(false));
  1118. }
  1119. if (ParentDirectory && !IncludeParentDirectory)
  1120. {
  1121. Copy->AddFile(ParentDirectory->Duplicate(false));
  1122. }
  1123. }
  1124. //---------------------------------------------------------------------------
  1125. bool __fastcall TRemoteDirectory::GetLoaded()
  1126. {
  1127. return ((Terminal != NULL) && Terminal->Active && !Directory.IsEmpty());
  1128. }
  1129. //---------------------------------------------------------------------------
  1130. TStrings * __fastcall TRemoteDirectory::GetSelectedFiles()
  1131. {
  1132. if (!FSelectedFiles)
  1133. {
  1134. FSelectedFiles = new TStringList();
  1135. }
  1136. else
  1137. {
  1138. FSelectedFiles->Clear();
  1139. }
  1140. for (int Index = 0; Index < Count; Index ++)
  1141. {
  1142. if (Files[Index]->Selected)
  1143. {
  1144. FSelectedFiles->Add(Files[Index]->FullFileName);
  1145. }
  1146. }
  1147. return FSelectedFiles;
  1148. }
  1149. //---------------------------------------------------------------------------
  1150. void __fastcall TRemoteDirectory::SetIncludeParentDirectory(Boolean value)
  1151. {
  1152. if (IncludeParentDirectory != value)
  1153. {
  1154. FIncludeParentDirectory = value;
  1155. if (value && ParentDirectory)
  1156. {
  1157. assert(IndexOf(ParentDirectory) < 0);
  1158. Add(ParentDirectory);
  1159. }
  1160. else if (!value && ParentDirectory)
  1161. {
  1162. assert(IndexOf(ParentDirectory) >= 0);
  1163. Extract(ParentDirectory);
  1164. }
  1165. }
  1166. }
  1167. //---------------------------------------------------------------------------
  1168. void __fastcall TRemoteDirectory::SetIncludeThisDirectory(Boolean value)
  1169. {
  1170. if (IncludeThisDirectory != value)
  1171. {
  1172. FIncludeThisDirectory = value;
  1173. if (value && ThisDirectory)
  1174. {
  1175. assert(IndexOf(ThisDirectory) < 0);
  1176. Add(ThisDirectory);
  1177. }
  1178. else if (!value && ThisDirectory)
  1179. {
  1180. assert(IndexOf(ThisDirectory) >= 0);
  1181. Extract(ThisDirectory);
  1182. }
  1183. }
  1184. }
  1185. //===========================================================================
  1186. __fastcall TRemoteDirectoryCache::TRemoteDirectoryCache(): TStringList()
  1187. {
  1188. FSection = new TCriticalSection();
  1189. Sorted = true;
  1190. Duplicates = dupError;
  1191. CaseSensitive = true;
  1192. }
  1193. //---------------------------------------------------------------------------
  1194. __fastcall TRemoteDirectoryCache::~TRemoteDirectoryCache()
  1195. {
  1196. Clear();
  1197. delete FSection;
  1198. }
  1199. //---------------------------------------------------------------------------
  1200. void __fastcall TRemoteDirectoryCache::Clear()
  1201. {
  1202. TGuard Guard(FSection);
  1203. try
  1204. {
  1205. for (int Index = 0; Index < Count; Index++)
  1206. {
  1207. delete (TRemoteFileList *)Objects[Index];
  1208. Objects[Index] = NULL;
  1209. }
  1210. }
  1211. __finally
  1212. {
  1213. TStringList::Clear();
  1214. }
  1215. }
  1216. //---------------------------------------------------------------------------
  1217. bool __fastcall TRemoteDirectoryCache::GetIsEmpty() const
  1218. {
  1219. TGuard Guard(FSection);
  1220. return (const_cast<TRemoteDirectoryCache*>(this)->Count == 0);
  1221. }
  1222. //---------------------------------------------------------------------------
  1223. bool __fastcall TRemoteDirectoryCache::HasFileList(const AnsiString Directory)
  1224. {
  1225. TGuard Guard(FSection);
  1226. int Index = IndexOf(UnixExcludeTrailingBackslash(Directory));
  1227. return (Index >= 0);
  1228. }
  1229. //---------------------------------------------------------------------------
  1230. bool __fastcall TRemoteDirectoryCache::HasNewerFileList(const AnsiString Directory,
  1231. TDateTime Timestamp)
  1232. {
  1233. TGuard Guard(FSection);
  1234. int Index = IndexOf(UnixExcludeTrailingBackslash(Directory));
  1235. if (Index >= 0)
  1236. {
  1237. TRemoteFileList * FileList = dynamic_cast<TRemoteFileList *>(Objects[Index]);
  1238. if (FileList->Timestamp <= Timestamp)
  1239. {
  1240. Index = -1;
  1241. }
  1242. }
  1243. return (Index >= 0);
  1244. }
  1245. //---------------------------------------------------------------------------
  1246. bool __fastcall TRemoteDirectoryCache::GetFileList(const AnsiString Directory,
  1247. TRemoteFileList * FileList)
  1248. {
  1249. TGuard Guard(FSection);
  1250. int Index = IndexOf(UnixExcludeTrailingBackslash(Directory));
  1251. bool Result = (Index >= 0);
  1252. if (Result)
  1253. {
  1254. assert(Objects[Index] != NULL);
  1255. dynamic_cast<TRemoteFileList *>(Objects[Index])->DuplicateTo(FileList);
  1256. }
  1257. return Result;
  1258. }
  1259. //---------------------------------------------------------------------------
  1260. void __fastcall TRemoteDirectoryCache::AddFileList(TRemoteFileList * FileList)
  1261. {
  1262. // file list cannot be cached already with only one thread, but it can be
  1263. // when directory is loaded by secondary terminal
  1264. ClearFileList(FileList->Directory, false);
  1265. assert(FileList);
  1266. TRemoteFileList * Copy = new TRemoteFileList();
  1267. FileList->DuplicateTo(Copy);
  1268. {
  1269. TGuard Guard(FSection);
  1270. AddObject(Copy->Directory, Copy);
  1271. }
  1272. }
  1273. //---------------------------------------------------------------------------
  1274. void __fastcall TRemoteDirectoryCache::ClearFileList(AnsiString Directory, bool SubDirs)
  1275. {
  1276. TGuard Guard(FSection);
  1277. Directory = UnixExcludeTrailingBackslash(Directory);
  1278. int Index = IndexOf(Directory);
  1279. if (Index >= 0)
  1280. {
  1281. Delete(Index);
  1282. }
  1283. if (SubDirs)
  1284. {
  1285. Directory = UnixIncludeTrailingBackslash(Directory);
  1286. Index = Count-1;
  1287. while (Index >= 0)
  1288. {
  1289. if (Strings[Index].SubString(1, Directory.Length()) == Directory)
  1290. {
  1291. Delete(Index);
  1292. }
  1293. Index--;
  1294. }
  1295. }
  1296. }
  1297. //---------------------------------------------------------------------------
  1298. void __fastcall TRemoteDirectoryCache::Delete(int Index)
  1299. {
  1300. delete (TRemoteFileList *)Objects[Index];
  1301. TStringList::Delete(Index);
  1302. }
  1303. //---------------------------------------------------------------------------
  1304. //---------------------------------------------------------------------------
  1305. __fastcall TRemoteDirectoryChangesCache::TRemoteDirectoryChangesCache() :
  1306. TStringList()
  1307. {
  1308. }
  1309. //---------------------------------------------------------------------------
  1310. void __fastcall TRemoteDirectoryChangesCache::Clear()
  1311. {
  1312. TStringList::Clear();
  1313. }
  1314. //---------------------------------------------------------------------------
  1315. bool __fastcall TRemoteDirectoryChangesCache::GetIsEmpty() const
  1316. {
  1317. return (const_cast<TRemoteDirectoryChangesCache*>(this)->Count == 0);
  1318. }
  1319. //---------------------------------------------------------------------------
  1320. void __fastcall TRemoteDirectoryChangesCache::AddDirectoryChange(
  1321. const AnsiString SourceDir, const AnsiString Change,
  1322. const AnsiString TargetDir)
  1323. {
  1324. assert(!TargetDir.IsEmpty());
  1325. Values[TargetDir] = "//";
  1326. if (TTerminal::ExpandFileName(Change, SourceDir) != TargetDir)
  1327. {
  1328. AnsiString Key;
  1329. if (DirectoryChangeKey(SourceDir, Change, Key))
  1330. {
  1331. Values[Key] = TargetDir;
  1332. }
  1333. }
  1334. }
  1335. //---------------------------------------------------------------------------
  1336. void __fastcall TRemoteDirectoryChangesCache::ClearDirectoryChange(
  1337. AnsiString SourceDir)
  1338. {
  1339. for (int Index = 0; Index < Count; Index++)
  1340. {
  1341. if (Names[Index].SubString(1, SourceDir.Length()) == SourceDir)
  1342. {
  1343. Delete(Index);
  1344. Index--;
  1345. }
  1346. }
  1347. }
  1348. //---------------------------------------------------------------------------
  1349. void __fastcall TRemoteDirectoryChangesCache::ClearDirectoryChangeTarget(
  1350. AnsiString TargetDir)
  1351. {
  1352. AnsiString Key;
  1353. // hack to clear at least local sym-link change in case symlink is deleted
  1354. DirectoryChangeKey(UnixExcludeTrailingBackslash(UnixExtractFilePath(TargetDir)),
  1355. UnixExtractFileName(TargetDir), Key);
  1356. for (int Index = 0; Index < Count; Index++)
  1357. {
  1358. AnsiString Name = Names[Index];
  1359. if ((Name.SubString(1, TargetDir.Length()) == TargetDir) ||
  1360. (Values[Name].SubString(1, TargetDir.Length()) == TargetDir) ||
  1361. (!Key.IsEmpty() && (Name == Key)))
  1362. {
  1363. Delete(Index);
  1364. Index--;
  1365. }
  1366. }
  1367. }
  1368. //---------------------------------------------------------------------------
  1369. bool __fastcall TRemoteDirectoryChangesCache::GetDirectoryChange(
  1370. const AnsiString SourceDir, const AnsiString Change, AnsiString & TargetDir)
  1371. {
  1372. AnsiString Key;
  1373. bool Result;
  1374. Key = TTerminal::ExpandFileName(Change, SourceDir);
  1375. Result = (IndexOfName(Key) >= 0);
  1376. if (Result)
  1377. {
  1378. TargetDir = Values[Key];
  1379. // TargetDir is not "//" here only when Change is full path to symbolic link
  1380. if (TargetDir == "//")
  1381. {
  1382. TargetDir = Key;
  1383. }
  1384. }
  1385. else
  1386. {
  1387. Result = DirectoryChangeKey(SourceDir, Change, Key);
  1388. if (Result)
  1389. {
  1390. AnsiString Directory = Values[Key];
  1391. Result = !Directory.IsEmpty();
  1392. if (Result)
  1393. {
  1394. TargetDir = Directory;
  1395. }
  1396. }
  1397. }
  1398. return Result;
  1399. }
  1400. //---------------------------------------------------------------------------
  1401. void __fastcall TRemoteDirectoryChangesCache::Serialize(AnsiString & Data)
  1402. {
  1403. Data = "A" + Text;
  1404. }
  1405. //---------------------------------------------------------------------------
  1406. void __fastcall TRemoteDirectoryChangesCache::Deserialize(const AnsiString Data)
  1407. {
  1408. if (Data.IsEmpty())
  1409. {
  1410. Text = "";
  1411. }
  1412. else
  1413. {
  1414. Text = Data.c_str() + 1;
  1415. }
  1416. }
  1417. //---------------------------------------------------------------------------
  1418. bool __fastcall TRemoteDirectoryChangesCache::DirectoryChangeKey(
  1419. const AnsiString SourceDir, const AnsiString Change, AnsiString & Key)
  1420. {
  1421. bool Result = !Change.IsEmpty();
  1422. if (Result)
  1423. {
  1424. bool Absolute = TTerminal::IsAbsolutePath(Change);
  1425. Result = !SourceDir.IsEmpty() || Absolute;
  1426. if (Result)
  1427. {
  1428. // expanded from ?: to avoid memory leaks
  1429. if (Absolute)
  1430. {
  1431. Key = Change;
  1432. }
  1433. else
  1434. {
  1435. Key = SourceDir + "," + Change;
  1436. }
  1437. }
  1438. }
  1439. return Result;
  1440. }
  1441. //=== TRights ---------------------------------------------------------------
  1442. const char TRights::BasicSymbols[] = "rwxrwxrwx";
  1443. const char TRights::CombinedSymbols[] = "--s--s--t";
  1444. const char TRights::ExtendedSymbols[] = "--S--S--T";
  1445. const char TRights::ModeGroups[] = "ugo";
  1446. //---------------------------------------------------------------------------
  1447. __fastcall TRights::TRights()
  1448. {
  1449. FAllowUndef = false;
  1450. FSet = 0;
  1451. FUnset = 0;
  1452. Number = 0;
  1453. FUnknown = true;
  1454. }
  1455. //---------------------------------------------------------------------------
  1456. __fastcall TRights::TRights(unsigned short ANumber)
  1457. {
  1458. FAllowUndef = false;
  1459. FSet = 0;
  1460. FUnset = 0;
  1461. Number = ANumber;
  1462. }
  1463. //---------------------------------------------------------------------------
  1464. __fastcall TRights::TRights(const TRights & Source)
  1465. {
  1466. Assign(&Source);
  1467. }
  1468. //---------------------------------------------------------------------------
  1469. void __fastcall TRights::Assign(const TRights * Source)
  1470. {
  1471. FAllowUndef = Source->AllowUndef;
  1472. FSet = Source->FSet;
  1473. FUnset = Source->FUnset;
  1474. FText = Source->FText;
  1475. FUnknown = Source->FUnknown;
  1476. }
  1477. //---------------------------------------------------------------------------
  1478. TRights::TFlag __fastcall TRights::RightToFlag(TRights::TRight Right)
  1479. {
  1480. return static_cast<TFlag>(1 << (rrLast - Right));
  1481. }
  1482. //---------------------------------------------------------------------------
  1483. bool __fastcall TRights::operator ==(const TRights & rhr) const
  1484. {
  1485. if (AllowUndef || rhr.AllowUndef)
  1486. {
  1487. for (int Right = rrFirst; Right <= rrLast; Right++)
  1488. {
  1489. if (RightUndef[static_cast<TRight>(Right)] !=
  1490. rhr.RightUndef[static_cast<TRight>(Right)])
  1491. {
  1492. return false;
  1493. }
  1494. }
  1495. return true;
  1496. }
  1497. else
  1498. {
  1499. return (Number == rhr.Number);
  1500. }
  1501. }
  1502. //---------------------------------------------------------------------------
  1503. bool __fastcall TRights::operator ==(unsigned short rhr) const
  1504. {
  1505. return (Number == rhr);
  1506. }
  1507. //---------------------------------------------------------------------------
  1508. bool __fastcall TRights::operator !=(const TRights & rhr) const
  1509. {
  1510. return !(*this == rhr);
  1511. }
  1512. //---------------------------------------------------------------------------
  1513. TRights & __fastcall TRights::operator =(unsigned short rhr)
  1514. {
  1515. Number = rhr;
  1516. return *this;
  1517. }
  1518. //---------------------------------------------------------------------------
  1519. TRights & __fastcall TRights::operator =(const TRights & rhr)
  1520. {
  1521. Assign(&rhr);
  1522. return *this;
  1523. }
  1524. //---------------------------------------------------------------------------
  1525. TRights __fastcall TRights::operator ~() const
  1526. {
  1527. TRights Result(static_cast<unsigned short>(~Number));
  1528. return Result;
  1529. }
  1530. //---------------------------------------------------------------------------
  1531. TRights __fastcall TRights::operator &(const TRights & rhr) const
  1532. {
  1533. TRights Result(*this);
  1534. Result &= rhr;
  1535. return Result;
  1536. }
  1537. //---------------------------------------------------------------------------
  1538. TRights __fastcall TRights::operator &(unsigned short rhr) const
  1539. {
  1540. TRights Result(*this);
  1541. Result &= rhr;
  1542. return Result;
  1543. }
  1544. //---------------------------------------------------------------------------
  1545. TRights & __fastcall TRights::operator &=(const TRights & rhr)
  1546. {
  1547. if (AllowUndef || rhr.AllowUndef)
  1548. {
  1549. for (int Right = rrFirst; Right <= rrLast; Right++)
  1550. {
  1551. if (RightUndef[static_cast<TRight>(Right)] !=
  1552. rhr.RightUndef[static_cast<TRight>(Right)])
  1553. {
  1554. RightUndef[static_cast<TRight>(Right)] = rsUndef;
  1555. }
  1556. }
  1557. }
  1558. else
  1559. {
  1560. Number &= rhr.Number;
  1561. }
  1562. return *this;
  1563. }
  1564. //---------------------------------------------------------------------------
  1565. TRights & __fastcall TRights::operator &=(unsigned short rhr)
  1566. {
  1567. Number &= rhr;
  1568. return *this;
  1569. }
  1570. //---------------------------------------------------------------------------
  1571. TRights __fastcall TRights::operator |(const TRights & rhr) const
  1572. {
  1573. TRights Result(*this);
  1574. Result |= rhr;
  1575. return Result;
  1576. }
  1577. //---------------------------------------------------------------------------
  1578. TRights __fastcall TRights::operator |(unsigned short rhr) const
  1579. {
  1580. TRights Result(*this);
  1581. Result |= rhr;
  1582. return Result;
  1583. }
  1584. //---------------------------------------------------------------------------
  1585. TRights & __fastcall TRights::operator |=(const TRights & rhr)
  1586. {
  1587. Number |= rhr.Number;
  1588. return *this;
  1589. }
  1590. //---------------------------------------------------------------------------
  1591. TRights & __fastcall TRights::operator |=(unsigned short rhr)
  1592. {
  1593. Number |= rhr;
  1594. return *this;
  1595. }
  1596. //---------------------------------------------------------------------------
  1597. void __fastcall TRights::SetAllowUndef(bool value)
  1598. {
  1599. if (FAllowUndef != value)
  1600. {
  1601. assert(!value || ((FSet | FUnset) == rfAllSpecials));
  1602. FAllowUndef = value;
  1603. }
  1604. }
  1605. //---------------------------------------------------------------------------
  1606. void __fastcall TRights::SetText(const AnsiString & value)
  1607. {
  1608. if (value != Text)
  1609. {
  1610. if ((value.Length() != TextLen) ||
  1611. (!AllowUndef && (value.Pos(UndefSymbol) > 0)) ||
  1612. (value.Pos(" ") > 0))
  1613. {
  1614. throw Exception(FMTLOAD(RIGHTS_ERROR, (value)));
  1615. }
  1616. FSet = 0;
  1617. FUnset = 0;
  1618. int Flag = 00001;
  1619. int ExtendedFlag = 01000;
  1620. bool KeepText = false;
  1621. for (int i = TextLen; i >= 1; i--)
  1622. {
  1623. if (value[i] == UnsetSymbol)
  1624. {
  1625. FUnset |= static_cast<unsigned short>(Flag | ExtendedFlag);
  1626. }
  1627. else if (value[i] == UndefSymbol)
  1628. {
  1629. // do nothing
  1630. }
  1631. else if (value[i] == CombinedSymbols[i - 1])
  1632. {
  1633. FSet |= static_cast<unsigned short>(Flag | ExtendedFlag);
  1634. }
  1635. else if (value[i] == ExtendedSymbols[i - 1])
  1636. {
  1637. FSet |= static_cast<unsigned short>(ExtendedFlag);
  1638. FUnset |= static_cast<unsigned short>(Flag);
  1639. }
  1640. else
  1641. {
  1642. if (value[i] != BasicSymbols[i - 1])
  1643. {
  1644. KeepText = true;
  1645. }
  1646. FSet |= static_cast<unsigned short>(Flag);
  1647. FUnset |= static_cast<unsigned short>(ExtendedFlag);
  1648. }
  1649. Flag <<= 1;
  1650. if (i % 3 == 1)
  1651. {
  1652. ExtendedFlag <<= 1;
  1653. }
  1654. }
  1655. FText = KeepText ? value : AnsiString();
  1656. }
  1657. FUnknown = false;
  1658. }
  1659. //---------------------------------------------------------------------------
  1660. AnsiString __fastcall TRights::GetText() const
  1661. {
  1662. if (!FText.IsEmpty())
  1663. {
  1664. return FText;
  1665. }
  1666. else
  1667. {
  1668. AnsiString Result;
  1669. Result.SetLength(TextLen);
  1670. int Flag = 00001;
  1671. int ExtendedFlag = 01000;
  1672. bool ExtendedPos = true;
  1673. char Symbol;
  1674. int i = TextLen;
  1675. while (i >= 1)
  1676. {
  1677. if (ExtendedPos &&
  1678. ((FSet & (Flag | ExtendedFlag)) == (Flag | ExtendedFlag)))
  1679. {
  1680. Symbol = CombinedSymbols[i - 1];
  1681. }
  1682. else if ((FSet & Flag) != 0)
  1683. {
  1684. Symbol = BasicSymbols[i - 1];
  1685. }
  1686. else if (ExtendedPos && ((FSet & ExtendedFlag) != 0))
  1687. {
  1688. Symbol = ExtendedSymbols[i - 1];
  1689. }
  1690. else if ((!ExtendedPos && ((FUnset & Flag) == Flag)) ||
  1691. (ExtendedPos && ((FUnset & (Flag | ExtendedFlag)) == (Flag | ExtendedFlag))))
  1692. {
  1693. Symbol = UnsetSymbol;
  1694. }
  1695. else
  1696. {
  1697. Symbol = UndefSymbol;
  1698. }
  1699. Result[i] = Symbol;
  1700. Flag <<= 1;
  1701. i--;
  1702. ExtendedPos = ((i % 3) == 0);
  1703. if (ExtendedPos)
  1704. {
  1705. ExtendedFlag <<= 1;
  1706. }
  1707. }
  1708. return Result;
  1709. }
  1710. }
  1711. //---------------------------------------------------------------------------
  1712. void __fastcall TRights::SetOctal(AnsiString value)
  1713. {
  1714. AnsiString AValue(value);
  1715. if (AValue.Length() == 3)
  1716. {
  1717. AValue = "0" + AValue;
  1718. }
  1719. if (Octal != AValue)
  1720. {
  1721. bool Correct = (AValue.Length() == 4);
  1722. if (Correct)
  1723. {
  1724. for (int i = 1; (i <= AValue.Length()) && Correct; i++)
  1725. {
  1726. Correct = (AValue[i] >= '0') && (AValue[i] <= '7');
  1727. }
  1728. }
  1729. if (!Correct)
  1730. {
  1731. throw Exception(FMTLOAD(INVALID_OCTAL_PERMISSIONS, (value)));
  1732. }
  1733. Number = static_cast<unsigned short>(
  1734. ((AValue[1] - '0') << 9) +
  1735. ((AValue[2] - '0') << 6) +
  1736. ((AValue[3] - '0') << 3) +
  1737. ((AValue[4] - '0') << 0));
  1738. }
  1739. FUnknown = false;
  1740. }
  1741. //---------------------------------------------------------------------------
  1742. unsigned long __fastcall TRights::GetNumberDecadic() const
  1743. {
  1744. unsigned long N = NumberSet; // used to be "Number"
  1745. unsigned long Result =
  1746. ((N & 07000) / 01000 * 1000) +
  1747. ((N & 00700) / 0100 * 100) +
  1748. ((N & 00070) / 010 * 10) +
  1749. ((N & 00007) / 01 * 1);
  1750. return Result;
  1751. }
  1752. //---------------------------------------------------------------------------
  1753. AnsiString __fastcall TRights::GetOctal() const
  1754. {
  1755. AnsiString Result;
  1756. unsigned short N = NumberSet; // used to be "Number"
  1757. Result.SetLength(4);
  1758. Result[1] = static_cast<char>('0' + ((N & 07000) >> 9));
  1759. Result[2] = static_cast<char>('0' + ((N & 00700) >> 6));
  1760. Result[3] = static_cast<char>('0' + ((N & 00070) >> 3));
  1761. Result[4] = static_cast<char>('0' + ((N & 00007) >> 0));
  1762. return Result;
  1763. }
  1764. //---------------------------------------------------------------------------
  1765. void __fastcall TRights::SetNumber(unsigned short value)
  1766. {
  1767. if ((FSet != value) || ((FSet | FUnset) != rfAllSpecials))
  1768. {
  1769. FSet = value;
  1770. FUnset = static_cast<unsigned short>(rfAllSpecials & ~FSet);
  1771. FText = "";
  1772. }
  1773. FUnknown = false;
  1774. }
  1775. //---------------------------------------------------------------------------
  1776. unsigned short __fastcall TRights::GetNumber() const
  1777. {
  1778. assert(!IsUndef);
  1779. return FSet;
  1780. }
  1781. //---------------------------------------------------------------------------
  1782. void __fastcall TRights::SetRight(TRight Right, bool value)
  1783. {
  1784. RightUndef[Right] = (value ? rsYes : rsNo);
  1785. }
  1786. //---------------------------------------------------------------------------
  1787. bool __fastcall TRights::GetRight(TRight Right) const
  1788. {
  1789. TState State = RightUndef[Right];
  1790. assert(State != rsUndef);
  1791. return (State == rsYes);
  1792. }
  1793. //---------------------------------------------------------------------------
  1794. void __fastcall TRights::SetRightUndef(TRight Right, TState value)
  1795. {
  1796. if (value != RightUndef[Right])
  1797. {
  1798. assert((value != rsUndef) || AllowUndef);
  1799. TFlag Flag = RightToFlag(Right);
  1800. switch (value)
  1801. {
  1802. case rsYes:
  1803. FSet |= Flag;
  1804. FUnset &= ~Flag;
  1805. break;
  1806. case rsNo:
  1807. FSet &= ~Flag;
  1808. FUnset |= Flag;
  1809. break;
  1810. case rsUndef:
  1811. default:
  1812. FSet &= ~Flag;
  1813. FUnset &= ~Flag;
  1814. break;
  1815. }
  1816. FText = "";
  1817. }
  1818. FUnknown = false;
  1819. }
  1820. //---------------------------------------------------------------------------
  1821. TRights::TState __fastcall TRights::GetRightUndef(TRight Right) const
  1822. {
  1823. TFlag Flag = RightToFlag(Right);
  1824. TState Result;
  1825. if ((FSet & Flag) != 0)
  1826. {
  1827. Result = rsYes;
  1828. }
  1829. else if ((FUnset & Flag) != 0)
  1830. {
  1831. Result = rsNo;
  1832. }
  1833. else
  1834. {
  1835. Result = rsUndef;
  1836. }
  1837. return Result;
  1838. }
  1839. //---------------------------------------------------------------------------
  1840. void __fastcall TRights::SetReadOnly(bool value)
  1841. {
  1842. Right[rrUserWrite] = !value;
  1843. Right[rrGroupWrite] = !value;
  1844. Right[rrOtherWrite] = !value;
  1845. }
  1846. //---------------------------------------------------------------------------
  1847. bool __fastcall TRights::GetReadOnly()
  1848. {
  1849. return Right[rrUserWrite] && Right[rrGroupWrite] && Right[rrOtherWrite];
  1850. }
  1851. //---------------------------------------------------------------------------
  1852. AnsiString __fastcall TRights::GetSimplestStr() const
  1853. {
  1854. return IsUndef ? ModeStr : Octal;
  1855. }
  1856. //---------------------------------------------------------------------------
  1857. AnsiString __fastcall TRights::GetModeStr() const
  1858. {
  1859. AnsiString Result;
  1860. AnsiString SetModeStr, UnsetModeStr;
  1861. TRight Right;
  1862. int Index;
  1863. for (int Group = 0; Group < 3; Group++)
  1864. {
  1865. SetModeStr = "";
  1866. UnsetModeStr = "";
  1867. for (int Mode = 0; Mode < 3; Mode++)
  1868. {
  1869. Index = (Group * 3) + Mode;
  1870. Right = static_cast<TRight>(rrUserRead + Index);
  1871. switch (RightUndef[Right])
  1872. {
  1873. case rsYes:
  1874. SetModeStr += BasicSymbols[Index];
  1875. break;
  1876. case rsNo:
  1877. UnsetModeStr += BasicSymbols[Index];
  1878. break;
  1879. }
  1880. }
  1881. Right = static_cast<TRight>(rrUserIDExec + Group);
  1882. Index = (Group * 3) + 2;
  1883. switch (RightUndef[Right])
  1884. {
  1885. case rsYes:
  1886. SetModeStr += CombinedSymbols[Index];
  1887. break;
  1888. case rsNo:
  1889. UnsetModeStr += CombinedSymbols[Index];
  1890. break;
  1891. }
  1892. if (!SetModeStr.IsEmpty() || !UnsetModeStr.IsEmpty())
  1893. {
  1894. if (!Result.IsEmpty())
  1895. {
  1896. Result += ',';
  1897. }
  1898. Result += ModeGroups[Group];
  1899. if (!SetModeStr.IsEmpty())
  1900. {
  1901. Result += "+" + SetModeStr;
  1902. }
  1903. if (!UnsetModeStr.IsEmpty())
  1904. {
  1905. Result += "-" + UnsetModeStr;
  1906. }
  1907. }
  1908. }
  1909. return Result;
  1910. }
  1911. //---------------------------------------------------------------------------
  1912. void __fastcall TRights::AddExecute()
  1913. {
  1914. for (int Group = 0; Group < 3; Group++)
  1915. {
  1916. if ((RightUndef[static_cast<TRight>(rrUserRead + (Group * 3))] == rsYes) ||
  1917. (RightUndef[static_cast<TRight>(rrUserWrite + (Group * 3))] == rsYes))
  1918. {
  1919. Right[static_cast<TRight>(rrUserExec + (Group * 3))] = true;
  1920. }
  1921. }
  1922. FUnknown = false;
  1923. }
  1924. //---------------------------------------------------------------------------
  1925. void __fastcall TRights::AllUndef()
  1926. {
  1927. if ((FSet != 0) || (FUnset != 0))
  1928. {
  1929. FSet = 0;
  1930. FUnset = 0;
  1931. FText = "";
  1932. }
  1933. FUnknown = false;
  1934. }
  1935. //---------------------------------------------------------------------------
  1936. bool __fastcall TRights::GetIsUndef() const
  1937. {
  1938. return ((FSet | FUnset) != rfAllSpecials);
  1939. }
  1940. //---------------------------------------------------------------------------
  1941. __fastcall TRights::operator unsigned short() const
  1942. {
  1943. return Number;
  1944. }
  1945. //---------------------------------------------------------------------------
  1946. __fastcall TRights::operator unsigned long() const
  1947. {
  1948. return Number;
  1949. }
  1950. //=== TRemoteProperties -------------------------------------------------------
  1951. __fastcall TRemoteProperties::TRemoteProperties()
  1952. {
  1953. Default();
  1954. }
  1955. //---------------------------------------------------------------------------
  1956. void __fastcall TRemoteProperties::Default()
  1957. {
  1958. Valid.Clear();
  1959. AddXToDirectories = false;
  1960. Rights.AllowUndef = false;
  1961. Rights.Number = 0;
  1962. Group = "";
  1963. Owner = "";
  1964. Recursive = false;
  1965. }
  1966. //---------------------------------------------------------------------------
  1967. bool __fastcall TRemoteProperties::operator ==(const TRemoteProperties & rhp) const
  1968. {
  1969. bool Result = (Valid == rhp.Valid && Recursive == rhp.Recursive);
  1970. if (Result)
  1971. {
  1972. if ((Valid.Contains(vpRights) &&
  1973. (Rights != rhp.Rights || AddXToDirectories != rhp.AddXToDirectories)) ||
  1974. (Valid.Contains(vpOwner) && Owner != rhp.Owner) ||
  1975. (Valid.Contains(vpGroup) && Group != rhp.Group) ||
  1976. (Valid.Contains(vpModification) && (Modification != rhp.Modification)) ||
  1977. (Valid.Contains(vpLastAccess) && (LastAccess != rhp.LastAccess)))
  1978. {
  1979. Result = false;
  1980. }
  1981. }
  1982. return Result;
  1983. }
  1984. //---------------------------------------------------------------------------
  1985. bool __fastcall TRemoteProperties::operator !=(const TRemoteProperties & rhp) const
  1986. {
  1987. return !(*this == rhp);
  1988. }
  1989. //---------------------------------------------------------------------------
  1990. TRemoteProperties __fastcall TRemoteProperties::CommonProperties(TStrings * FileList)
  1991. {
  1992. // TODO: Modification and LastAccess
  1993. TRemoteProperties CommonProperties;
  1994. for (int Index = 0; Index < FileList->Count; Index++)
  1995. {
  1996. TRemoteFile * File = (TRemoteFile *)(FileList->Objects[Index]);
  1997. assert(File);
  1998. if (!Index)
  1999. {
  2000. CommonProperties.Rights = *(File->Rights);
  2001. // previously we allowed undef implicitly for directories,
  2002. // now we do it explicitly in properties dialog and only in combination
  2003. // with "recursive" option
  2004. CommonProperties.Rights.AllowUndef = File->Rights->IsUndef;
  2005. CommonProperties.Valid << vpRights;
  2006. if (!File->Owner.IsEmpty())
  2007. {
  2008. CommonProperties.Owner = File->Owner;
  2009. CommonProperties.Valid << vpOwner;
  2010. }
  2011. if (!File->Group.IsEmpty())
  2012. {
  2013. CommonProperties.Group = File->Group;
  2014. CommonProperties.Valid << vpGroup;
  2015. }
  2016. }
  2017. else
  2018. {
  2019. CommonProperties.Rights.AllowUndef = True;
  2020. CommonProperties.Rights &= *File->Rights;
  2021. if (CommonProperties.Owner != File->Owner)
  2022. {
  2023. CommonProperties.Owner = "";
  2024. CommonProperties.Valid >> vpOwner;
  2025. };
  2026. if (CommonProperties.Group != File->Group)
  2027. {
  2028. CommonProperties.Group = "";
  2029. CommonProperties.Valid >> vpGroup;
  2030. };
  2031. }
  2032. }
  2033. return CommonProperties;
  2034. }
  2035. //---------------------------------------------------------------------------
  2036. TRemoteProperties __fastcall TRemoteProperties::ChangedProperties(
  2037. const TRemoteProperties & OriginalProperties, TRemoteProperties NewProperties)
  2038. {
  2039. // TODO: Modification and LastAccess
  2040. if (!NewProperties.Recursive)
  2041. {
  2042. if (NewProperties.Rights == OriginalProperties.Rights &&
  2043. !NewProperties.AddXToDirectories)
  2044. {
  2045. NewProperties.Valid >> vpRights;
  2046. }
  2047. if (NewProperties.Group == OriginalProperties.Group)
  2048. {
  2049. NewProperties.Valid >> vpGroup;
  2050. }
  2051. if (NewProperties.Owner == OriginalProperties.Owner)
  2052. {
  2053. NewProperties.Valid >> vpOwner;
  2054. }
  2055. }
  2056. return NewProperties;
  2057. }
  2058. //---------------------------------------------------------------------------
  2059. void __fastcall TRemoteProperties::Load(THierarchicalStorage * Storage)
  2060. {
  2061. unsigned char Buf[sizeof(Valid)];
  2062. if (Storage->ReadBinaryData("Valid", &Buf, sizeof(Buf)) == sizeof(Buf))
  2063. {
  2064. memcpy(&Valid, Buf, sizeof(Valid));
  2065. }
  2066. if (Valid.Contains(vpRights))
  2067. {
  2068. Rights.Text = Storage->ReadString("Rights", Rights.Text);
  2069. }
  2070. // TODO
  2071. }
  2072. //---------------------------------------------------------------------------
  2073. void __fastcall TRemoteProperties::Save(THierarchicalStorage * Storage) const
  2074. {
  2075. Storage->WriteBinaryData(AnsiString("Valid"),
  2076. static_cast<const void *>(&Valid), sizeof(Valid));
  2077. if (Valid.Contains(vpRights))
  2078. {
  2079. Storage->WriteString("Rights", Rights.Text);
  2080. }
  2081. // TODO
  2082. }