CopyParam.cpp 35 KB

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