CopyParam.cpp 34 KB

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