CopyParam.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include "Common.h"
  5. #include "Exceptions.h"
  6. #include "CopyParam.h"
  7. #include "HierarchicalStorage.h"
  8. #include "TextsCore.h"
  9. #include "Interface.h"
  10. //---------------------------------------------------------------------------
  11. const wchar_t * TransferModeNames[] = { L"binary", L"ascii", L"automatic" };
  12. const int TransferModeNamesCount = LENOF(TransferModeNames);
  13. //---------------------------------------------------------------------------
  14. __fastcall TCopyParamType::TCopyParamType()
  15. {
  16. Default();
  17. }
  18. //---------------------------------------------------------------------------
  19. __fastcall TCopyParamType::TCopyParamType(const TCopyParamType & Source)
  20. {
  21. Assign(&Source);
  22. }
  23. //---------------------------------------------------------------------------
  24. __fastcall TCopyParamType::~TCopyParamType()
  25. {
  26. }
  27. //---------------------------------------------------------------------------
  28. void __fastcall TCopyParamType::Default()
  29. {
  30. // when changing defaults, make sure GetInfoStr() can handle it
  31. FileNameCase = ncNoChange;
  32. PreserveReadOnly = false;
  33. PreserveTime = true;
  34. PreserveTimeDirs = false;
  35. Rights.Number = TRights::rfDefault;
  36. PreserveRights = false; // Was True until #106
  37. IgnorePermErrors = false;
  38. AsciiFileMask.Masks = L"*.*html; *.htm; *.txt; *.php; *.php3; *.cgi; *.c; *.cpp; *.h; *.pas; "
  39. "*.bas; *.tex; *.pl; *.js; .htaccess; *.xtml; *.css; *.cfg; *.ini; *.sh; *.xml";
  40. TransferMode = tmBinary;
  41. AddXToDirectories = true;
  42. ResumeSupport = rsSmart;
  43. ResumeThreshold = 100 * 1024; // (100 KB)
  44. InvalidCharsReplacement = TokenReplacement;
  45. LocalInvalidChars = ::LocalInvalidChars;
  46. CalculateSize = true;
  47. FileMask = AnyMask;
  48. IncludeFileMask.Masks = L"";
  49. TransferSkipList = NULL;
  50. TransferResumeFile = L"";
  51. ClearArchive = false;
  52. RemoveCtrlZ = false;
  53. RemoveBOM = false;
  54. CPSLimit = 0;
  55. NewerOnly = false;
  56. EncryptNewFiles = true;
  57. }
  58. //---------------------------------------------------------------------------
  59. UnicodeString __fastcall TCopyParamType::GetInfoStr(
  60. UnicodeString Separator, int Attrs) const
  61. {
  62. UnicodeString Result;
  63. bool SomeAttrIncluded;
  64. UnicodeString ScriptArgs;
  65. bool NoScriptArgs;
  66. UnicodeString AssemblyCode;
  67. bool NoCodeProperties;
  68. DoGetInfoStr(
  69. Separator, Attrs, Result, SomeAttrIncluded,
  70. UnicodeString(), ScriptArgs, NoScriptArgs, TAssemblyLanguage(0), AssemblyCode, NoCodeProperties);
  71. return Result;
  72. }
  73. //---------------------------------------------------------------------------
  74. bool __fastcall TCopyParamType::AnyUsableCopyParam(int Attrs) const
  75. {
  76. UnicodeString Result;
  77. bool SomeAttrIncluded;
  78. UnicodeString ScriptArgs;
  79. bool NoScriptArgs;
  80. UnicodeString AssemblyCode;
  81. bool NoCodeProperties;
  82. DoGetInfoStr(
  83. L";", Attrs, Result, SomeAttrIncluded,
  84. UnicodeString(), ScriptArgs, NoScriptArgs, TAssemblyLanguage(0), AssemblyCode, NoCodeProperties);
  85. return SomeAttrIncluded;
  86. }
  87. //---------------------------------------------------------------------------
  88. UnicodeString __fastcall TCopyParamType::GenerateTransferCommandArgs(int Attrs, const UnicodeString & Link, bool & NoScriptArgs) const
  89. {
  90. UnicodeString Result;
  91. bool SomeAttrIncluded;
  92. UnicodeString ScriptArgs;
  93. UnicodeString AssemblyCode;
  94. bool NoCodeProperties;
  95. DoGetInfoStr(
  96. L";", Attrs, Result, SomeAttrIncluded,
  97. Link, ScriptArgs, NoScriptArgs, TAssemblyLanguage(0), AssemblyCode, NoCodeProperties);
  98. return ScriptArgs;
  99. }
  100. //---------------------------------------------------------------------------
  101. UnicodeString __fastcall TCopyParamType::GenerateAssemblyCode(
  102. TAssemblyLanguage Language, int Attrs, bool & NoCodeProperties) const
  103. {
  104. UnicodeString Result;
  105. bool SomeAttrIncluded;
  106. UnicodeString ScriptArgs;
  107. bool NoScriptArgs;
  108. UnicodeString AssemblyCode;
  109. DoGetInfoStr(L";", Attrs, Result, SomeAttrIncluded, UnicodeString(), ScriptArgs, NoScriptArgs, Language, AssemblyCode, NoCodeProperties);
  110. return AssemblyCode;
  111. }
  112. //---------------------------------------------------------------------------
  113. void __fastcall TCopyParamType::DoGetInfoStr(
  114. UnicodeString Separator, int Options,
  115. UnicodeString & Result, bool & SomeAttrIncluded,
  116. const UnicodeString & Link, UnicodeString & ScriptArgs, bool & NoScriptArgs, TAssemblyLanguage Language, UnicodeString & AssemblyCode,
  117. bool & NoCodeProperties) const
  118. {
  119. TCopyParamType Defaults;
  120. bool SomeAttrExcluded = false;
  121. NoScriptArgs = false;
  122. NoCodeProperties = false;
  123. SomeAttrIncluded = false;
  124. #define ADD(STR, EXCEPT) \
  125. if (FLAGCLEAR(Options, EXCEPT)) \
  126. { \
  127. AddToList(Result, (STR), Separator); \
  128. SomeAttrIncluded = true; \
  129. } \
  130. else \
  131. { \
  132. SomeAttrExcluded = true; \
  133. }
  134. bool AsciiFileMaskDiffers = (TransferMode == tmAutomatic) && !(AsciiFileMask == Defaults.AsciiFileMask);
  135. bool TransferModeDiffers = ((TransferMode != Defaults.TransferMode) || AsciiFileMaskDiffers);
  136. if (FLAGCLEAR(Options, cpaIncludeMaskOnly | cpaNoTransferMode))
  137. {
  138. // Adding Transfer type unconditionally
  139. bool FormatMask;
  140. int Ident;
  141. switch (TransferMode)
  142. {
  143. case tmBinary:
  144. FormatMask = false;
  145. Ident = 2;
  146. break;
  147. case tmAscii:
  148. FormatMask = false;
  149. Ident = 3;
  150. break;
  151. case tmAutomatic:
  152. default:
  153. FormatMask = !(AsciiFileMask == Defaults.AsciiFileMask);
  154. Ident = FormatMask ? 4 : 5;
  155. break;
  156. }
  157. UnicodeString S = FORMAT(LoadStrPart(COPY_INFO_TRANSFER_TYPE2, 1),
  158. (LoadStrPart(COPY_INFO_TRANSFER_TYPE2, Ident)));
  159. if (FormatMask)
  160. {
  161. S = FORMAT(S, (AsciiFileMask.Masks));
  162. }
  163. AddToList(Result, S, Separator);
  164. if (TransferModeDiffers)
  165. {
  166. ADD("", cpaIncludeMaskOnly | cpaNoTransferMode);
  167. ScriptArgs += RtfSwitchValue(TRANSFER_SWITCH, Link, TransferModeNames[TransferMode]);
  168. const wchar_t * TransferModeMembers[] = { L"Binary", L"Ascii", L"Automatic" };
  169. AssemblyCode += AssemblyProperty(
  170. Language, TransferOptionsClassName, L"TransferMode", L"TransferMode", TransferModeMembers[TransferMode], false);
  171. if (AsciiFileMaskDiffers)
  172. {
  173. NoScriptArgs = true;
  174. NoCodeProperties = true;
  175. }
  176. }
  177. }
  178. else
  179. {
  180. if (TransferModeDiffers)
  181. {
  182. SomeAttrExcluded = true;
  183. NoScriptArgs = true;
  184. NoCodeProperties = true;
  185. }
  186. }
  187. if (FileNameCase != Defaults.FileNameCase)
  188. {
  189. ADD(FORMAT(LoadStrPart(COPY_INFO_FILENAME, 1),
  190. (LoadStrPart(COPY_INFO_FILENAME, FileNameCase + 2))),
  191. cpaIncludeMaskOnly);
  192. NoScriptArgs = true;
  193. NoCodeProperties = true;
  194. }
  195. if ((InvalidCharsReplacement == NoReplacement) !=
  196. (Defaults.InvalidCharsReplacement == NoReplacement))
  197. {
  198. DebugAssert(InvalidCharsReplacement == NoReplacement);
  199. if (InvalidCharsReplacement == NoReplacement)
  200. {
  201. ADD(LoadStr(COPY_INFO_DONT_REPLACE_INV_CHARS), cpaIncludeMaskOnly);
  202. }
  203. NoScriptArgs = true;
  204. NoCodeProperties = true;
  205. }
  206. if ((PreserveRights != Defaults.PreserveRights) ||
  207. (PreserveRights &&
  208. ((Rights != Defaults.Rights) || (AddXToDirectories != Defaults.AddXToDirectories))))
  209. {
  210. const int Except = cpaIncludeMaskOnly | cpaNoRights;
  211. if (DebugAlwaysTrue(PreserveRights))
  212. {
  213. UnicodeString RightsStr = Rights.Text;
  214. if (AddXToDirectories)
  215. {
  216. RightsStr += L", " + LoadStr(COPY_INFO_ADD_X_TO_DIRS);
  217. }
  218. ADD(FORMAT(LoadStr(COPY_INFO_PERMISSIONS), (RightsStr)),
  219. Except);
  220. if (FLAGCLEAR(Options, Except))
  221. {
  222. ScriptArgs += RtfSwitchValue(PERMISSIONS_SWITCH, Link, Rights.Octal);
  223. const UnicodeString FilePermissionsClassName = L"FilePermissions";
  224. const bool Inline = true;
  225. UnicodeString FilePermissions =
  226. AssemblyNewClassInstanceStart(Language, FilePermissionsClassName, Inline) +
  227. AssemblyProperty(Language, FilePermissionsClassName, L"Octal", Rights.Octal, Inline) +
  228. AssemblyNewClassInstanceEnd(Language, Inline);
  229. AssemblyCode += AssemblyPropertyRaw(Language, TransferOptionsClassName, L"FilePermissions", FilePermissions, false);
  230. }
  231. }
  232. if ((AddXToDirectories != Defaults.AddXToDirectories) && FLAGCLEAR(Options, Except))
  233. {
  234. NoScriptArgs = true;
  235. NoCodeProperties = true;
  236. }
  237. }
  238. bool APreserveTimeDirs = PreserveTime && PreserveTimeDirs;
  239. if ((PreserveTime != Defaults.PreserveTime) || (APreserveTimeDirs != Defaults.PreserveTimeDirs))
  240. {
  241. bool AddPreserveTime = false;
  242. UnicodeString Str = LoadStr(PreserveTime ? COPY_INFO_TIMESTAMP : COPY_INFO_DONT_PRESERVE_TIME);
  243. const int ExceptDirs = cpaNoPreserveTimeDirs;
  244. if (APreserveTimeDirs != Defaults.PreserveTimeDirs)
  245. {
  246. if (DebugAlwaysTrue(PreserveTimeDirs))
  247. {
  248. if (FLAGCLEAR(Options, ExceptDirs))
  249. {
  250. Str = FMTLOAD(COPY_INFO_PRESERVE_TIME_DIRS, (Str));
  251. AddPreserveTime = true;
  252. }
  253. }
  254. ADD("", ExceptDirs);
  255. }
  256. const int Except = cpaIncludeMaskOnly | cpaNoPreserveTime;
  257. if (PreserveTime != Defaults.PreserveTime)
  258. {
  259. if (FLAGCLEAR(Options, Except))
  260. {
  261. AddPreserveTime = true;
  262. }
  263. ADD(L"", Except);
  264. }
  265. if (AddPreserveTime)
  266. {
  267. AddToList(Result, Str, Separator);
  268. }
  269. if (FLAGCLEAR(Options, Except))
  270. {
  271. if (PreserveTime)
  272. {
  273. if (PreserveTimeDirs && FLAGCLEAR(Options, ExceptDirs))
  274. {
  275. ScriptArgs += RtfSwitchValue(PRESERVETIME_SWITCH, Link, PRESERVETIMEDIRS_SWITCH_VALUE);
  276. NoCodeProperties = true;
  277. }
  278. else
  279. {
  280. DebugFail(); // should never get here
  281. ScriptArgs += RtfSwitch(PRESERVETIME_SWITCH, Link);
  282. }
  283. }
  284. else
  285. {
  286. ScriptArgs += RtfSwitch(NOPRESERVETIME_SWITCH, Link);
  287. AssemblyCode += AssemblyProperty(Language, TransferOptionsClassName, L"PreserveTimestamp", false, false);
  288. }
  289. }
  290. }
  291. if ((PreserveRights || PreserveTime) &&
  292. (IgnorePermErrors != Defaults.IgnorePermErrors))
  293. {
  294. if (DebugAlwaysTrue(IgnorePermErrors))
  295. {
  296. const int Except = cpaIncludeMaskOnly | cpaNoIgnorePermErrors;
  297. ADD(LoadStr(COPY_INFO_IGNORE_PERM_ERRORS), Except);
  298. if (FLAGCLEAR(Options, Except))
  299. {
  300. NoScriptArgs = true;
  301. NoCodeProperties = true;
  302. }
  303. }
  304. }
  305. if (PreserveReadOnly != Defaults.PreserveReadOnly)
  306. {
  307. if (DebugAlwaysTrue(PreserveReadOnly))
  308. {
  309. const int Except = cpaIncludeMaskOnly | cpaNoPreserveReadOnly;
  310. ADD(LoadStr(COPY_INFO_PRESERVE_READONLY), Except);
  311. if (FLAGCLEAR(Options, Except))
  312. {
  313. NoScriptArgs = true;
  314. NoCodeProperties = true;
  315. }
  316. }
  317. }
  318. if (CalculateSize != Defaults.CalculateSize)
  319. {
  320. if (DebugAlwaysTrue(!CalculateSize))
  321. {
  322. ADD(LoadStr(COPY_INFO_DONT_CALCULATE_SIZE), cpaIncludeMaskOnly);
  323. // Always false in scripting, in assembly controlled by use of FileTransferProgress
  324. }
  325. }
  326. if (ClearArchive != Defaults.ClearArchive)
  327. {
  328. if (DebugAlwaysTrue(ClearArchive))
  329. {
  330. const int Except = cpaIncludeMaskOnly | cpaNoClearArchive;
  331. ADD(LoadStr(COPY_INFO_CLEAR_ARCHIVE), Except);
  332. if (FLAGCLEAR(Options, Except))
  333. {
  334. NoScriptArgs = true;
  335. NoCodeProperties = true;
  336. }
  337. }
  338. }
  339. if ((TransferMode == tmAscii) || (TransferMode == tmAutomatic))
  340. {
  341. if (RemoveBOM != Defaults.RemoveBOM)
  342. {
  343. if (DebugAlwaysTrue(RemoveBOM))
  344. {
  345. const int Except = cpaIncludeMaskOnly | cpaNoRemoveBOM | cpaNoTransferMode;
  346. ADD(LoadStr(COPY_INFO_REMOVE_BOM), Except);
  347. if (FLAGCLEAR(Options, Except))
  348. {
  349. NoScriptArgs = true;
  350. NoCodeProperties = true;
  351. }
  352. }
  353. }
  354. if (RemoveCtrlZ != Defaults.RemoveCtrlZ)
  355. {
  356. if (DebugAlwaysTrue(RemoveCtrlZ))
  357. {
  358. const int Except = cpaIncludeMaskOnly | cpaNoRemoveCtrlZ | cpaNoTransferMode;
  359. ADD(LoadStr(COPY_INFO_REMOVE_CTRLZ),Except);
  360. if (FLAGCLEAR(Options, Except))
  361. {
  362. NoScriptArgs = true;
  363. NoCodeProperties = true;
  364. }
  365. }
  366. }
  367. }
  368. if (!(IncludeFileMask == Defaults.IncludeFileMask))
  369. {
  370. ADD(FORMAT(LoadStr(COPY_INFO_FILE_MASK), (IncludeFileMask.Masks)),
  371. cpaNoIncludeMask);
  372. ScriptArgs += RtfSwitch(FILEMASK_SWITCH, Link, IncludeFileMask.Masks);
  373. AssemblyCode += AssemblyProperty(Language, TransferOptionsClassName, L"FileMask", IncludeFileMask.Masks, false);
  374. }
  375. DebugAssert(FTransferSkipList.get() == NULL);
  376. DebugAssert(FTransferResumeFile.IsEmpty());
  377. if (CPSLimit > 0)
  378. {
  379. int LimitKB = int(CPSLimit / 1024);
  380. ADD(FMTLOAD(COPY_INFO_CPS_LIMIT2, (LimitKB)), cpaIncludeMaskOnly);
  381. ScriptArgs += RtfSwitch(SPEED_SWITCH, Link, LimitKB);
  382. AssemblyCode += AssemblyProperty(Language, TransferOptionsClassName, L"SpeedLimit", LimitKB, false);
  383. }
  384. if (NewerOnly != Defaults.NewerOnly)
  385. {
  386. if (DebugAlwaysTrue(NewerOnly))
  387. {
  388. const int Except = cpaIncludeMaskOnly | cpaNoNewerOnly;
  389. ADD(StripHotkey(LoadStr(COPY_PARAM_NEWER_ONLY)), Except);
  390. if (FLAGCLEAR(Options, Except))
  391. {
  392. ScriptArgs += RtfSwitch(NEWERONLY_SWICH, Link);
  393. NoCodeProperties = true;
  394. }
  395. }
  396. }
  397. if (EncryptNewFiles != Defaults.EncryptNewFiles)
  398. {
  399. if (!DebugAlwaysFalse(EncryptNewFiles))
  400. {
  401. const int Except = cpaIncludeMaskOnly | cpaNoEncryptNewFiles;
  402. ADD(StripHotkey(LoadStr(COPY_INFO_DONT_ENCRYPT_NEW_FILES)), Except);
  403. if (FLAGCLEAR(Options, Except))
  404. {
  405. NoScriptArgs = true;
  406. NoCodeProperties = true;
  407. }
  408. }
  409. }
  410. bool ResumeThresholdDiffers = ((ResumeSupport == rsSmart) && (ResumeThreshold != Defaults.ResumeThreshold));
  411. if (((ResumeSupport != Defaults.ResumeSupport) || ResumeThresholdDiffers) &&
  412. (TransferMode != tmAscii) && FLAGCLEAR(Options, cpaNoResumeSupport))
  413. {
  414. UnicodeString Value;
  415. UnicodeString CodeState;
  416. int ResumeThresholdKB = (ResumeThreshold / 1024);
  417. switch (ResumeSupport)
  418. {
  419. case rsOff:
  420. Value = ToggleNames[ToggleOff];
  421. CodeState = L"Off";
  422. break;
  423. case rsOn:
  424. Value = ToggleNames[ToggleOn];
  425. CodeState = L"On";
  426. break;
  427. case rsSmart:
  428. Value = IntToStr(ResumeThresholdKB);
  429. break;
  430. }
  431. ScriptArgs += RtfSwitchValue(RESUMESUPPORT_SWITCH, Link, Value);
  432. const UnicodeString ResumeSupportClassName = L"TransferResumeSupport";
  433. const bool Inline = true;
  434. UnicodeString ResumeSupportCode =
  435. AssemblyNewClassInstanceStart(Language, ResumeSupportClassName, Inline);
  436. if (ResumeSupport == rsSmart)
  437. {
  438. ResumeSupportCode += AssemblyProperty(Language, ResumeSupportClassName, L"Threshold", ResumeThresholdKB, Inline);
  439. }
  440. else
  441. {
  442. ResumeSupportCode += AssemblyProperty(Language, ResumeSupportClassName, L"State", L"TransferResumeSupportState", CodeState, Inline);
  443. }
  444. ResumeSupportCode += AssemblyNewClassInstanceEnd(Language, Inline);
  445. AssemblyCode += AssemblyPropertyRaw(Language, TransferOptionsClassName, L"ResumeSupport", ResumeSupportCode, false);
  446. }
  447. if (SomeAttrExcluded)
  448. {
  449. Result += (Result.IsEmpty() ? UnicodeString() : Separator) +
  450. FORMAT(LoadStrPart(COPY_INFO_NOT_USABLE, 1),
  451. (LoadStrPart(COPY_INFO_NOT_USABLE, (SomeAttrIncluded ? 2 : 3))));
  452. }
  453. else if (Result.IsEmpty())
  454. {
  455. Result = LoadStr(COPY_INFO_DEFAULT);
  456. }
  457. #undef ADD
  458. }
  459. //---------------------------------------------------------------------------
  460. void __fastcall TCopyParamType::Assign(const TCopyParamType * Source)
  461. {
  462. DebugAssert(Source != NULL);
  463. #define COPY(Prop) Prop = Source->Prop
  464. COPY(FileNameCase);
  465. COPY(PreserveReadOnly);
  466. COPY(PreserveTime);
  467. COPY(PreserveTimeDirs);
  468. COPY(Rights);
  469. COPY(AsciiFileMask);
  470. COPY(TransferMode);
  471. COPY(AddXToDirectories);
  472. COPY(PreserveRights);
  473. COPY(IgnorePermErrors);
  474. COPY(ResumeSupport);
  475. COPY(ResumeThreshold);
  476. COPY(InvalidCharsReplacement);
  477. COPY(LocalInvalidChars);
  478. COPY(CalculateSize);
  479. COPY(FileMask);
  480. COPY(IncludeFileMask);
  481. COPY(TransferSkipList);
  482. COPY(TransferResumeFile);
  483. COPY(ClearArchive);
  484. COPY(RemoveCtrlZ);
  485. COPY(RemoveBOM);
  486. COPY(CPSLimit);
  487. COPY(NewerOnly);
  488. COPY(EncryptNewFiles);
  489. #undef COPY
  490. }
  491. //---------------------------------------------------------------------------
  492. TCopyParamType & __fastcall TCopyParamType::operator =(const TCopyParamType & rhp)
  493. {
  494. Assign(&rhp);
  495. return *this;
  496. }
  497. //---------------------------------------------------------------------------
  498. void __fastcall TCopyParamType::SetLocalInvalidChars(UnicodeString value)
  499. {
  500. if (value != LocalInvalidChars)
  501. {
  502. FLocalInvalidChars = value;
  503. FTokenizibleChars = FLocalInvalidChars + TokenPrefix;
  504. }
  505. }
  506. //---------------------------------------------------------------------------
  507. bool __fastcall TCopyParamType::GetReplaceInvalidChars() const
  508. {
  509. return (InvalidCharsReplacement != NoReplacement);
  510. }
  511. //---------------------------------------------------------------------------
  512. void __fastcall TCopyParamType::SetReplaceInvalidChars(bool value)
  513. {
  514. if (ReplaceInvalidChars != value)
  515. {
  516. InvalidCharsReplacement = (value ? TokenReplacement : NoReplacement);
  517. }
  518. }
  519. //---------------------------------------------------------------------------
  520. UnicodeString __fastcall TCopyParamType::ValidLocalFileName(UnicodeString FileName) const
  521. {
  522. return ::ValidLocalFileName(FileName, InvalidCharsReplacement, FTokenizibleChars, LocalInvalidChars);
  523. }
  524. //---------------------------------------------------------------------------
  525. UnicodeString __fastcall TCopyParamType::RestoreChars(UnicodeString FileName) const
  526. {
  527. if (InvalidCharsReplacement == TokenReplacement)
  528. {
  529. wchar_t * InvalidChar = FileName.c_str();
  530. while ((InvalidChar = wcschr(InvalidChar, TokenPrefix)) != NULL)
  531. {
  532. int Index = InvalidChar - FileName.c_str() + 1;
  533. if (FileName.Length() >= Index + 2)
  534. {
  535. UnicodeString Hex = FileName.SubString(Index + 1, 2);
  536. wchar_t Char = static_cast<wchar_t>(HexToByte(Hex));
  537. if ((Char != L'\0') &&
  538. ((FTokenizibleChars.Pos(Char) > 0) ||
  539. (((Char == L' ') || (Char == L'.')) && (Index == FileName.Length() - 2))))
  540. {
  541. FileName[Index] = Char;
  542. FileName.Delete(Index + 1, 2);
  543. InvalidChar = FileName.c_str() + Index;
  544. }
  545. else if ((Hex == L"00") &&
  546. ((Index == FileName.Length() - 2) || (FileName[Index + 3] == L'.')) &&
  547. IsReservedName(FileName.SubString(1, Index - 1) + FileName.SubString(Index + 3, FileName.Length() - Index - 3 + 1)))
  548. {
  549. FileName.Delete(Index, 3);
  550. InvalidChar = FileName.c_str() + Index - 1;
  551. }
  552. else
  553. {
  554. InvalidChar++;
  555. }
  556. }
  557. else
  558. {
  559. InvalidChar++;
  560. }
  561. }
  562. }
  563. return FileName;
  564. }
  565. //---------------------------------------------------------------------------
  566. UnicodeString __fastcall TCopyParamType::ValidLocalPath(UnicodeString Path) const
  567. {
  568. UnicodeString Result;
  569. while (!Path.IsEmpty())
  570. {
  571. if (!Result.IsEmpty())
  572. {
  573. Result += L"\\";
  574. }
  575. Result += ValidLocalFileName(CutToChar(Path, L'\\', false));
  576. }
  577. return Result;
  578. }
  579. //---------------------------------------------------------------------------
  580. UnicodeString __fastcall TCopyParamType::ChangeFileName(UnicodeString FileName,
  581. TOperationSide Side, bool FirstLevel) const
  582. {
  583. if (FirstLevel)
  584. {
  585. FileName = MaskFileName(FileName, FileMask);
  586. }
  587. switch (FileNameCase) {
  588. case ncUpperCase: FileName = FileName.UpperCase(); break;
  589. case ncLowerCase: FileName = FileName.LowerCase(); break;
  590. case ncFirstUpperCase: FileName = FileName.SubString(1, 1).UpperCase() +
  591. FileName.SubString(2, FileName.Length()-1).LowerCase(); break;
  592. case ncLowerCaseShort:
  593. if ((FileName.Length() <= 12) && (FileName.Pos(L".") <= 9) &&
  594. (FileName == FileName.UpperCase()))
  595. {
  596. FileName = FileName.LowerCase();
  597. }
  598. break;
  599. case ncNoChange:
  600. default:
  601. /*nothing*/
  602. break;
  603. }
  604. if (Side == osRemote)
  605. {
  606. FileName = ValidLocalFileName(FileName);
  607. }
  608. else
  609. {
  610. FileName = RestoreChars(FileName);
  611. }
  612. return FileName;
  613. }
  614. //---------------------------------------------------------------------------
  615. bool __fastcall TCopyParamType::UseAsciiTransfer(UnicodeString FileName,
  616. TOperationSide Side, const TFileMasks::TParams & Params) const
  617. {
  618. switch (TransferMode)
  619. {
  620. case tmBinary: return false;
  621. case tmAscii: return true;
  622. case tmAutomatic: return AsciiFileMask.Matches(FileName, (Side == osLocal),
  623. false, &Params);
  624. default: DebugFail(); return false;
  625. }
  626. }
  627. //---------------------------------------------------------------------------
  628. TRights __fastcall TCopyParamType::RemoteFileRights(Integer Attrs) const
  629. {
  630. TRights R = Rights;
  631. if ((Attrs & faDirectory) && AddXToDirectories)
  632. R.AddExecute();
  633. return R;
  634. }
  635. //---------------------------------------------------------------------------
  636. UnicodeString __fastcall TCopyParamType::GetLogStr() const
  637. {
  638. wchar_t CaseC[] = L"NULFS";
  639. wchar_t ModeC[] = L"BAM";
  640. wchar_t ResumeC[] = L"YSN";
  641. // OpenArray (ARRAYOFCONST) supports only up to 19 arguments, so we had to split it
  642. return
  643. FORMAT(
  644. L" PrTime: %s%s; PrRO: %s; Rght: %s; PrR: %s (%s); FnCs: %s; RIC: %s; "
  645. "Resume: %s (%d); CalcS: %s; Mask: %s\n",
  646. (BooleanToEngStr(PreserveTime),
  647. UnicodeString(PreserveTime && PreserveTimeDirs ? L"+Dirs" : L""),
  648. BooleanToEngStr(PreserveReadOnly),
  649. Rights.Text,
  650. BooleanToEngStr(PreserveRights),
  651. BooleanToEngStr(IgnorePermErrors),
  652. CaseC[FileNameCase],
  653. CharToHex(InvalidCharsReplacement),
  654. ResumeC[ResumeSupport],
  655. (int)ResumeThreshold,
  656. BooleanToEngStr(CalculateSize),
  657. FileMask)) +
  658. FORMAT(
  659. L" TM: %s; ClAr: %s; RemEOF: %s; RemBOM: %s; CPS: %u; NewerOnly: %s; EncryptNewFiles: %s; InclM: %s; ResumeL: %d\n"
  660. " AscM: %s\n",
  661. (ModeC[TransferMode],
  662. BooleanToEngStr(ClearArchive),
  663. BooleanToEngStr(RemoveCtrlZ),
  664. BooleanToEngStr(RemoveBOM),
  665. int(CPSLimit),
  666. BooleanToEngStr(NewerOnly),
  667. BooleanToEngStr(EncryptNewFiles),
  668. IncludeFileMask.Masks,
  669. ((FTransferSkipList.get() != NULL) ? FTransferSkipList->Count : 0) + (!FTransferResumeFile.IsEmpty() ? 1 : 0),
  670. AsciiFileMask.Masks));
  671. }
  672. //---------------------------------------------------------------------------
  673. int __fastcall TCopyParamType::LocalFileAttrs(const TRights & Rights) const
  674. {
  675. int Result = 0;
  676. if (PreserveReadOnly && !Rights.Right[TRights::rrUserWrite])
  677. {
  678. Result |= faReadOnly;
  679. }
  680. return Result;
  681. }
  682. //---------------------------------------------------------------------------
  683. bool __fastcall TCopyParamType::AllowResume(__int64 Size) const
  684. {
  685. switch (ResumeSupport)
  686. {
  687. case rsOn: return true;
  688. case rsOff: return false;
  689. case rsSmart: return (Size >= ResumeThreshold);
  690. default: DebugFail(); return false;
  691. }
  692. }
  693. //---------------------------------------------------------------------------
  694. bool __fastcall TCopyParamType::AllowAnyTransfer() const
  695. {
  696. return
  697. IncludeFileMask.Masks.IsEmpty() &&
  698. ((FTransferSkipList.get() == NULL) || (FTransferSkipList->Count == 0)) &&
  699. FTransferResumeFile.IsEmpty();
  700. }
  701. //---------------------------------------------------------------------------
  702. bool __fastcall TCopyParamType::AllowTransfer(UnicodeString FileName,
  703. TOperationSide Side, bool Directory, const TFileMasks::TParams & Params) const
  704. {
  705. bool Result = true;
  706. if (!IncludeFileMask.Masks.IsEmpty())
  707. {
  708. Result = IncludeFileMask.Matches(FileName, (Side == osLocal),
  709. Directory, &Params);
  710. }
  711. return Result;
  712. }
  713. //---------------------------------------------------------------------------
  714. bool __fastcall TCopyParamType::SkipTransfer(
  715. UnicodeString FileName, bool Directory) const
  716. {
  717. bool Result = false;
  718. // we deliberatelly do not filter directories, as path is added to resume list
  719. // when a transfer of file or directory is started,
  720. // so for directories we need to recurse and check every single file
  721. if (!Directory && (FTransferSkipList.get() != NULL))
  722. {
  723. Result = (FTransferSkipList->IndexOf(FileName) >= 0);
  724. }
  725. return Result;
  726. }
  727. //---------------------------------------------------------------------------
  728. bool __fastcall TCopyParamType::ResumeTransfer(UnicodeString FileName) const
  729. {
  730. // Returning true has the same effect as cpResume
  731. return
  732. (FileName == FTransferResumeFile) &&
  733. DebugAlwaysTrue(!FTransferResumeFile.IsEmpty());
  734. }
  735. //---------------------------------------------------------------------------
  736. TStrings * __fastcall TCopyParamType::GetTransferSkipList() const
  737. {
  738. return FTransferSkipList.get();
  739. }
  740. //---------------------------------------------------------------------------
  741. void __fastcall TCopyParamType::SetTransferSkipList(TStrings * value)
  742. {
  743. if ((value == NULL) || (value->Count == 0))
  744. {
  745. FTransferSkipList.reset(NULL);
  746. }
  747. else
  748. {
  749. FTransferSkipList.reset(new TStringList());
  750. FTransferSkipList->AddStrings(value);
  751. FTransferSkipList->Sorted = true;
  752. }
  753. }
  754. //---------------------------------------------------------------------------
  755. void __fastcall TCopyParamType::Load(THierarchicalStorage * Storage)
  756. {
  757. AddXToDirectories = Storage->ReadBool(L"AddXToDirectories", AddXToDirectories);
  758. AsciiFileMask.Masks = Storage->ReadString(L"Masks", AsciiFileMask.Masks);
  759. FileNameCase = (TFileNameCase)Storage->ReadInteger(L"FileNameCase", FileNameCase);
  760. PreserveReadOnly = Storage->ReadBool(L"PreserveReadOnly", PreserveReadOnly);
  761. PreserveTime = Storage->ReadBool(L"PreserveTime", PreserveTime);
  762. PreserveTimeDirs = Storage->ReadBool(L"PreserveTimeDirs", PreserveTimeDirs);
  763. PreserveRights = Storage->ReadBool(L"PreserveRights", PreserveRights);
  764. IgnorePermErrors = Storage->ReadBool(L"IgnorePermErrors", IgnorePermErrors);
  765. Rights.Text = Storage->ReadString(L"Text", Rights.Text);
  766. TransferMode = (TTransferMode)Storage->ReadInteger(L"TransferMode", TransferMode);
  767. ResumeSupport = (TResumeSupport)Storage->ReadInteger(L"ResumeSupport", ResumeSupport);
  768. ResumeThreshold = Storage->ReadInt64(L"ResumeThreshold", ResumeThreshold);
  769. InvalidCharsReplacement = (wchar_t)Storage->ReadInteger(L"ReplaceInvalidChars",
  770. (unsigned int)InvalidCharsReplacement);
  771. LocalInvalidChars = Storage->ReadString(L"LocalInvalidChars", LocalInvalidChars);
  772. CalculateSize = Storage->ReadBool(L"CalculateSize", CalculateSize);
  773. if (Storage->ValueExists(L"IncludeFileMask"))
  774. {
  775. IncludeFileMask.Masks = Storage->ReadString(L"IncludeFileMask", IncludeFileMask.Masks);
  776. }
  777. else if (Storage->ValueExists(L"ExcludeFileMask"))
  778. {
  779. UnicodeString ExcludeFileMask = Storage->ReadString(L"ExcludeFileMask", L"");
  780. if (!ExcludeFileMask.IsEmpty())
  781. {
  782. bool NegativeExclude = Storage->ReadBool(L"NegativeExclude", false);
  783. if (NegativeExclude)
  784. {
  785. IncludeFileMask.Masks = ExcludeFileMask;
  786. }
  787. // convert at least simple cases to new format
  788. else if (ExcludeFileMask.Pos(IncludeExcludeFileMasksDelimiter) == 0)
  789. {
  790. IncludeFileMask.Masks = UnicodeString(IncludeExcludeFileMasksDelimiter) + ExcludeFileMask;
  791. }
  792. }
  793. }
  794. TransferSkipList = NULL;
  795. TransferResumeFile = L"";
  796. ClearArchive = Storage->ReadBool(L"ClearArchive", ClearArchive);
  797. RemoveCtrlZ = Storage->ReadBool(L"RemoveCtrlZ", RemoveCtrlZ);
  798. RemoveBOM = Storage->ReadBool(L"RemoveBOM", RemoveBOM);
  799. CPSLimit = Storage->ReadInteger(L"CPSLimit", CPSLimit);
  800. NewerOnly = Storage->ReadBool(L"NewerOnly", NewerOnly);
  801. EncryptNewFiles = Storage->ReadBool(L"EncryptNewFiles", EncryptNewFiles);
  802. }
  803. //---------------------------------------------------------------------------
  804. void __fastcall TCopyParamType::Save(THierarchicalStorage * Storage, const TCopyParamType * Defaults) const
  805. {
  806. // Same as in TSessionData::DoSave
  807. #define WRITE_DATA_EX(TYPE, NAME, PROPERTY, CONV) \
  808. if ((Defaults != NULL) && (CONV(Defaults->PROPERTY) == CONV(PROPERTY))) \
  809. { \
  810. Storage->DeleteValue(NAME); \
  811. } \
  812. else \
  813. { \
  814. Storage->Write ## TYPE(NAME, CONV(PROPERTY)); \
  815. }
  816. #define WRITE_DATA_CONV(TYPE, NAME, PROPERTY) WRITE_DATA_EX(TYPE, NAME, PROPERTY, WRITE_DATA_CONV_FUNC)
  817. #define WRITE_DATA(TYPE, PROPERTY) WRITE_DATA_EX(TYPE, TEXT(#PROPERTY), PROPERTY, )
  818. WRITE_DATA(Bool, AddXToDirectories);
  819. WRITE_DATA_EX(String, L"Masks", AsciiFileMask.Masks, );
  820. WRITE_DATA(Integer, FileNameCase);
  821. WRITE_DATA(Bool, PreserveReadOnly);
  822. WRITE_DATA(Bool, PreserveTime);
  823. WRITE_DATA(Bool, PreserveTimeDirs);
  824. WRITE_DATA(Bool, PreserveRights);
  825. WRITE_DATA(Bool, IgnorePermErrors);
  826. WRITE_DATA_EX(String, L"Text", Rights.Text, );
  827. WRITE_DATA(Integer, TransferMode);
  828. WRITE_DATA(Integer, ResumeSupport);
  829. WRITE_DATA(Int64, ResumeThreshold);
  830. #define WRITE_DATA_CONV_FUNC(X) (unsigned int)(X)
  831. WRITE_DATA_CONV(Integer, L"ReplaceInvalidChars", InvalidCharsReplacement);
  832. WRITE_DATA(String, LocalInvalidChars);
  833. WRITE_DATA(Bool, CalculateSize);
  834. WRITE_DATA_EX(String, L"IncludeFileMask", IncludeFileMask.Masks, );
  835. Storage->DeleteValue(L"ExcludeFileMask"); // obsolete
  836. Storage->DeleteValue(L"NegativeExclude"); // obsolete
  837. DebugAssert(FTransferSkipList.get() == NULL);
  838. DebugAssert(FTransferResumeFile.IsEmpty());
  839. WRITE_DATA(Bool, ClearArchive);
  840. WRITE_DATA(Bool, RemoveCtrlZ);
  841. WRITE_DATA(Bool, RemoveBOM);
  842. WRITE_DATA(Integer, CPSLimit);
  843. WRITE_DATA(Bool, NewerOnly);
  844. WRITE_DATA(Bool, EncryptNewFiles);
  845. }
  846. //---------------------------------------------------------------------------
  847. #define C(Property) (Property == rhp.Property)
  848. bool __fastcall TCopyParamType::operator==(const TCopyParamType & rhp) const
  849. {
  850. DebugAssert(FTransferSkipList.get() == NULL);
  851. DebugAssert(FTransferResumeFile.IsEmpty());
  852. DebugAssert(rhp.FTransferSkipList.get() == NULL);
  853. DebugAssert(rhp.FTransferResumeFile.IsEmpty());
  854. return
  855. C(AddXToDirectories) &&
  856. C(AsciiFileMask) &&
  857. C(FileNameCase) &&
  858. C(PreserveReadOnly) &&
  859. C(PreserveTime) &&
  860. C(PreserveTimeDirs) &&
  861. C(PreserveRights) &&
  862. C(IgnorePermErrors) &&
  863. C(Rights) &&
  864. C(TransferMode) &&
  865. C(ResumeSupport) &&
  866. C(ResumeThreshold) &&
  867. C(InvalidCharsReplacement) &&
  868. C(LocalInvalidChars) &&
  869. C(CalculateSize) &&
  870. C(IncludeFileMask) &&
  871. C(ClearArchive) &&
  872. C(RemoveCtrlZ) &&
  873. C(RemoveBOM) &&
  874. C(CPSLimit) &&
  875. C(NewerOnly) &&
  876. C(EncryptNewFiles) &&
  877. true;
  878. }
  879. #undef C
  880. //---------------------------------------------------------------------------
  881. static bool __fastcall TryGetSpeedLimit(const UnicodeString & Text, unsigned long & Speed)
  882. {
  883. bool Result;
  884. if (AnsiSameText(Text, LoadStr(SPEED_UNLIMITED)))
  885. {
  886. Speed = 0;
  887. Result = true;
  888. }
  889. else
  890. {
  891. int SSpeed;
  892. Result = TryStrToInt(Text, SSpeed) && (SSpeed >= 0);
  893. if (Result)
  894. {
  895. Speed = SSpeed * 1024;
  896. }
  897. }
  898. return Result;
  899. }
  900. //---------------------------------------------------------------------------
  901. unsigned long __fastcall GetSpeedLimit(const UnicodeString & Text)
  902. {
  903. unsigned long Speed;
  904. if (!TryGetSpeedLimit(Text, Speed))
  905. {
  906. throw Exception(FMTLOAD(SPEED_INVALID, (Text)));
  907. }
  908. return Speed;
  909. }
  910. //---------------------------------------------------------------------------
  911. UnicodeString __fastcall SetSpeedLimit(unsigned long Limit)
  912. {
  913. UnicodeString Text;
  914. if (Limit == 0)
  915. {
  916. Text = LoadStr(SPEED_UNLIMITED);
  917. }
  918. else
  919. {
  920. Text = IntToStr(int(Limit / 1024));
  921. }
  922. return Text;
  923. }
  924. //---------------------------------------------------------------------------
  925. void __fastcall CopySpeedLimits(TStrings * Source, TStrings * Dest)
  926. {
  927. std::unique_ptr<TStringList> Temp(new TStringList());
  928. bool Unlimited = false;
  929. for (int Index = 0; Index < Source->Count; Index++)
  930. {
  931. UnicodeString Text = Source->Strings[Index];
  932. unsigned long Speed;
  933. bool Valid = TryGetSpeedLimit(Text, Speed);
  934. if ((!Valid || (Speed == 0)) && !Unlimited)
  935. {
  936. Temp->Add(LoadStr(SPEED_UNLIMITED));
  937. Unlimited = true;
  938. }
  939. else if (Valid && (Speed > 0))
  940. {
  941. Temp->Add(Text);
  942. }
  943. }
  944. if (!Unlimited)
  945. {
  946. Temp->Insert(0, LoadStr(SPEED_UNLIMITED));
  947. }
  948. Dest->Assign(Temp.get());
  949. }
  950. //---------------------------------------------------------------------------
  951. TOperationSide ReverseOperationSide(TOperationSide Side)
  952. {
  953. TOperationSide Result;
  954. switch (Side)
  955. {
  956. case osLocal:
  957. Result = osRemote;
  958. break;
  959. case osRemote:
  960. Result = osLocal;
  961. break;
  962. default:
  963. case osCurrent:
  964. DebugFail();
  965. Result = Side;
  966. break;
  967. }
  968. return Result;
  969. }