Configuration.cpp 68 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include <FileInfo.h>
  5. #include "Common.h"
  6. #include "Exceptions.h"
  7. #include "Configuration.h"
  8. #include "PuttyIntf.h"
  9. #include "TextsCore.h"
  10. #include "Interface.h"
  11. #include "CoreMain.h"
  12. #include "Security.h"
  13. #include "FileMasks.h"
  14. #include "CopyParam.h"
  15. #include <shlobj.h>
  16. #include <System.IOUtils.hpp>
  17. #include <System.StrUtils.hpp>
  18. #include <System.DateUtils.hpp>
  19. //---------------------------------------------------------------------------
  20. #pragma package(smart_init)
  21. //---------------------------------------------------------------------------
  22. const wchar_t * AutoSwitchNames = L"On;Off;Auto";
  23. const wchar_t * NotAutoSwitchNames = L"Off;On;Auto";
  24. //---------------------------------------------------------------------------
  25. // See https://www.iana.org/assignments/hash-function-text-names/hash-function-text-names.xhtml
  26. const UnicodeString Sha1ChecksumAlg(L"sha-1");
  27. const UnicodeString Sha224ChecksumAlg(L"sha-224");
  28. const UnicodeString Sha256ChecksumAlg(L"sha-256");
  29. const UnicodeString Sha384ChecksumAlg(L"sha-384");
  30. const UnicodeString Sha512ChecksumAlg(L"sha-512");
  31. const UnicodeString Md5ChecksumAlg(L"md5");
  32. // Not defined by IANA
  33. const UnicodeString Crc32ChecksumAlg(L"crc32");
  34. //---------------------------------------------------------------------------
  35. const UnicodeString SshFingerprintType(L"ssh");
  36. const UnicodeString TlsFingerprintType(L"tls");
  37. //---------------------------------------------------------------------------
  38. const UnicodeString FtpsCertificateStorageKey(L"FtpsCertificates");
  39. const UnicodeString HttpsCertificateStorageKey(L"HttpsCertificates");
  40. const UnicodeString LastFingerprintsStorageKey(L"LastFingerprints");
  41. const UnicodeString DirectoryStatisticsCacheKey(L"DirectoryStatisticsCache");
  42. const UnicodeString CDCacheKey(L"CDCache");
  43. const UnicodeString BannersKey(L"Banners");
  44. //---------------------------------------------------------------------------
  45. const UnicodeString OpensshFolderName(L".ssh");
  46. const UnicodeString OpensshAuthorizedKeysFileName(L"authorized_keys");
  47. //---------------------------------------------------------------------------
  48. const int BelowNormalLogLevels = 1;
  49. //---------------------------------------------------------------------------
  50. __fastcall TConfiguration::TConfiguration()
  51. {
  52. FCriticalSection = new TCriticalSection();
  53. FUpdating = 0;
  54. FStorage = stDetect;
  55. FDontSave = false;
  56. FForceSave = false;
  57. FApplicationInfo = NULL;
  58. FUsage = new TUsage(this);
  59. FDefaultCollectUsage = false;
  60. FScripting = false;
  61. UnicodeString RandomSeedPath;
  62. if (!GetEnvironmentVariable(L"APPDATA").IsEmpty())
  63. {
  64. RandomSeedPath = L"%APPDATA%";
  65. }
  66. else
  67. {
  68. RandomSeedPath = GetShellFolderPath(CSIDL_LOCAL_APPDATA);
  69. if (RandomSeedPath.IsEmpty())
  70. {
  71. RandomSeedPath = GetShellFolderPath(CSIDL_APPDATA);
  72. }
  73. }
  74. FDefaultRandomSeedFile = IncludeTrailingBackslash(RandomSeedPath) + L"winscp.rnd";
  75. }
  76. //---------------------------------------------------------------------------
  77. void __fastcall TConfiguration::Default()
  78. {
  79. TGuard Guard(FCriticalSection);
  80. FDisablePasswordStoring = false;
  81. FForceBanners = false;
  82. FDisableAcceptingHostKeys = false;
  83. TRegistryStorage * AdminStorage;
  84. AdminStorage = new TRegistryStorage(RegistryStorageKey, HKEY_LOCAL_MACHINE);
  85. try
  86. {
  87. if (AdminStorage->OpenRootKey(false))
  88. {
  89. LoadAdmin(AdminStorage);
  90. AdminStorage->CloseSubKey();
  91. }
  92. }
  93. __finally
  94. {
  95. delete AdminStorage;
  96. }
  97. RandomSeedFile = FDefaultRandomSeedFile;
  98. PuttyRegistryStorageKey = OriginalPuttyRegistryStorageKey;
  99. FConfirmOverwriting = true;
  100. FConfirmResume = true;
  101. FAutoReadDirectoryAfterOp = true;
  102. FSessionReopenAuto = 5000;
  103. FSessionReopenBackground = 2000;
  104. FSessionReopenTimeout = 0;
  105. FSessionReopenAutoStall = 60000;
  106. FTunnelLocalPortNumberLow = 50000;
  107. FTunnelLocalPortNumberHigh = 50099;
  108. FCacheDirectoryChangesMaxSize = 100;
  109. FShowFtpWelcomeMessage = false;
  110. FExternalIpAddress = L"";
  111. FLocalPortNumberMin = 0;
  112. FLocalPortNumberMax = 0;
  113. FTryFtpWhenSshFails = true;
  114. FParallelDurationThreshold = 10;
  115. FMimeTypes = UnicodeString();
  116. FCertificateStorage = EmptyStr;
  117. FChecksumCommands = EmptyStr;
  118. FDontReloadMoreThanSessions = 1000;
  119. FScriptProgressFileNameLimit = 25;
  120. FQueueTransfersLimit = 2;
  121. FParallelTransferThreshold = -1; // default (currently off), 0 = explicitly off
  122. FKeyVersion = 0;
  123. CollectUsage = FDefaultCollectUsage;
  124. FLogging = false;
  125. FPermanentLogging = false;
  126. FLogFileName = DefaultLogFileName;
  127. FPermanentLogFileName = FLogFileName;
  128. FLogFileAppend = true;
  129. FLogSensitive = false;
  130. FPermanentLogSensitive = FLogSensitive;
  131. FLogMaxSize = 0;
  132. FPermanentLogMaxSize = FLogMaxSize;
  133. FLogMaxCount = 0;
  134. FPermanentLogMaxCount = FLogMaxCount;
  135. FLogProtocol = 0;
  136. FPermanentLogProtocol = FLogProtocol;
  137. UpdateActualLogProtocol();
  138. FLogActions = false;
  139. FPermanentLogActions = false;
  140. FLogActionsRequired = false;
  141. FActionsLogFileName = L"%TEMP%\\!S.xml";
  142. FPermanentActionsLogFileName = FActionsLogFileName;
  143. FProgramIniPathWrittable = -1;
  144. FCustomIniFileStorageName = LoadCustomIniFileStorageName();
  145. Changed();
  146. }
  147. //---------------------------------------------------------------------------
  148. __fastcall TConfiguration::~TConfiguration()
  149. {
  150. DebugAssert(!FUpdating);
  151. if (FApplicationInfo) FreeFileInfo(FApplicationInfo);
  152. delete FCriticalSection;
  153. delete FUsage;
  154. }
  155. //---------------------------------------------------------------------------
  156. void __fastcall TConfiguration::UpdateStaticUsage()
  157. {
  158. Usage->Set(L"ConfigurationIniFile", (Storage == stIniFile));
  159. Usage->Set(L"ConfigurationIniFileCustom", !CustomIniFileStorageName.IsEmpty());
  160. Usage->Set("Unofficial", IsUnofficial);
  161. // this is called from here, because we are guarded from calling into
  162. // master password handler here, see TWinConfiguration::UpdateStaticUsage
  163. StoredSessions->UpdateStaticUsage();
  164. }
  165. //---------------------------------------------------------------------------
  166. THierarchicalStorage * TConfiguration::CreateConfigStorage()
  167. {
  168. bool SessionList = false;
  169. return CreateScpStorage(SessionList);
  170. }
  171. //---------------------------------------------------------------------------
  172. THierarchicalStorage * TConfiguration::CreateConfigRegistryStorage()
  173. {
  174. return new TRegistryStorage(RegistryStorageKey);
  175. }
  176. //---------------------------------------------------------------------------
  177. THierarchicalStorage * TConfiguration::CreateScpStorage(bool & SessionList)
  178. {
  179. TGuard Guard(FCriticalSection);
  180. THierarchicalStorage * Result;
  181. if (Storage == stRegistry)
  182. {
  183. Result = CreateConfigRegistryStorage();
  184. }
  185. else if (Storage == stNul)
  186. {
  187. Result = TIniFileStorage::CreateNul();
  188. }
  189. else
  190. {
  191. UnicodeString StorageName = IniFileStorageName;
  192. Result = TIniFileStorage::CreateFromPath(StorageName);
  193. }
  194. if ((FOptionsStorage.get() != NULL) && (FOptionsStorage->Count > 0))
  195. {
  196. if (!SessionList)
  197. {
  198. Result = new TOptionsStorage(FOptionsStorage.get(), ConfigurationSubKey, Result);
  199. }
  200. else
  201. {
  202. // cannot reuse session list storage for configuration as for it we need
  203. // the option-override storage above
  204. }
  205. }
  206. else
  207. {
  208. // All the above stores can be reused for configuration,
  209. // if no options-overrides are set
  210. SessionList = false;
  211. }
  212. return Result;
  213. }
  214. //---------------------------------------------------------------------------
  215. UnicodeString __fastcall TConfiguration::PropertyToKey(const UnicodeString & Property)
  216. {
  217. // no longer useful
  218. int P = Property.LastDelimiter(L".>");
  219. UnicodeString Result = Property.SubString(P + 1, Property.Length() - P);
  220. if ((Result[1] == L'F') && ((wchar_t)toupper(Result[2]) == Result[2]))
  221. {
  222. Result.Delete(1, 1);
  223. }
  224. return Result;
  225. }
  226. //---------------------------------------------------------------------------
  227. #define BLOCK(KEY, CANCREATE, BLOCK) \
  228. if (Storage->OpenSubKeyPath(KEY, CANCREATE)) try { BLOCK } __finally { Storage->CloseSubKeyPath(); }
  229. #define KEY(TYPE, VAR) KEYEX(TYPE, VAR, PropertyToKey(TEXT(#VAR)))
  230. #define REGCONFIG(CANCREATE) \
  231. BLOCK(L"Interface", CANCREATE, \
  232. KEY(String, RandomSeedFile); \
  233. KEY(String, PuttyRegistryStorageKey); \
  234. KEY(Bool, ConfirmOverwriting); \
  235. KEY(Bool, ConfirmResume); \
  236. KEY(Bool, AutoReadDirectoryAfterOp); \
  237. KEY(Integer, SessionReopenAuto); \
  238. KEY(Integer, SessionReopenBackground); \
  239. KEY(Integer, SessionReopenTimeout); \
  240. KEY(Integer, SessionReopenAutoStall); \
  241. KEY(Integer, TunnelLocalPortNumberLow); \
  242. KEY(Integer, TunnelLocalPortNumberHigh); \
  243. KEY(Integer, CacheDirectoryChangesMaxSize); \
  244. KEY(Bool, ShowFtpWelcomeMessage); \
  245. KEY(String, ExternalIpAddress); \
  246. KEY(Integer, LocalPortNumberMin); \
  247. KEY(Integer, LocalPortNumberMax); \
  248. KEY(Bool, TryFtpWhenSshFails); \
  249. KEY(Integer, ParallelDurationThreshold); \
  250. KEY(String, MimeTypes); \
  251. KEY(Integer, DontReloadMoreThanSessions); \
  252. KEY(Integer, ScriptProgressFileNameLimit); \
  253. KEY(Integer, QueueTransfersLimit); \
  254. KEY(Integer, ParallelTransferThreshold); \
  255. KEY(Integer, KeyVersion); \
  256. KEY(Bool, CollectUsage); \
  257. KEY(String, CertificateStorage); \
  258. ); \
  259. BLOCK(L"Logging", CANCREATE, \
  260. KEYEX(Bool, PermanentLogging, L"Logging"); \
  261. KEYEX(String,PermanentLogFileName, L"LogFileName"); \
  262. KEY(Bool, LogFileAppend); \
  263. KEYEX(Bool, PermanentLogSensitive, L"LogSensitive"); \
  264. KEYEX(Int64, PermanentLogMaxSize, L"LogMaxSize"); \
  265. KEYEX(Integer, PermanentLogMaxCount, L"LogMaxCount"); \
  266. KEYEX(Integer,PermanentLogProtocol, L"LogProtocol"); \
  267. KEYEX(Bool, PermanentLogActions, L"LogActions"); \
  268. KEYEX(String,PermanentActionsLogFileName, L"ActionsLogFileName"); \
  269. );
  270. //---------------------------------------------------------------------------
  271. void __fastcall TConfiguration::SaveData(THierarchicalStorage * Storage, bool /*All*/)
  272. {
  273. #define KEYEX(TYPE, VAR, NAME) Storage->Write ## TYPE(NAME, VAR)
  274. REGCONFIG(true);
  275. #undef KEYEX
  276. if (Storage->OpenSubKey(L"Usage", true))
  277. {
  278. FUsage->Save(Storage);
  279. Storage->CloseSubKey();
  280. }
  281. }
  282. //---------------------------------------------------------------------------
  283. void __fastcall TConfiguration::Save()
  284. {
  285. // only modified, implicit
  286. DoSave(false, false);
  287. }
  288. //---------------------------------------------------------------------------
  289. void __fastcall TConfiguration::SaveExplicit()
  290. {
  291. // only modified, explicit
  292. DoSave(false, true);
  293. }
  294. //---------------------------------------------------------------------------
  295. void __fastcall TConfiguration::DoSave(bool All, bool Explicit)
  296. {
  297. if (FDontSave) return;
  298. THierarchicalStorage * AStorage = CreateConfigStorage();
  299. try
  300. {
  301. AStorage->AccessMode = smReadWrite;
  302. AStorage->Explicit = Explicit;
  303. AStorage->ForceSave = FForceSave;
  304. if (AStorage->OpenSubKey(ConfigurationSubKey, true))
  305. {
  306. // if saving to TOptionsStorage, make sure we save everything so that
  307. // all configuration is properly transferred to the master storage
  308. bool ConfigAll = All || AStorage->Temporary;
  309. SaveData(AStorage, ConfigAll);
  310. }
  311. }
  312. __finally
  313. {
  314. delete AStorage;
  315. }
  316. Saved();
  317. if (All)
  318. {
  319. StoredSessions->Save(true, Explicit);
  320. }
  321. // clean up as last, so that if it fails (read only INI), the saving can proceed
  322. if (Storage == stRegistry)
  323. {
  324. CleanupIniFile();
  325. }
  326. SaveCustomIniFileStorageName();
  327. }
  328. //---------------------------------------------------------------------------
  329. void __fastcall TConfiguration::SaveCustomIniFileStorageName()
  330. {
  331. // Particularly, not to create an empty "Override" key, unless the custom INI file is ever set
  332. if (CustomIniFileStorageName != LoadCustomIniFileStorageName())
  333. {
  334. std::unique_ptr<TRegistryStorage> RegistryStorage(new TRegistryStorage(GetRegistryStorageOverrideKey()));
  335. RegistryStorage->AccessMode = smReadWrite;
  336. RegistryStorage->Explicit = true;
  337. if (RegistryStorage->OpenRootKey(true))
  338. {
  339. RegistryStorage->WriteString(L"IniFile", CustomIniFileStorageName);
  340. RegistryStorage->CloseSubKey();
  341. }
  342. }
  343. }
  344. //---------------------------------------------------------------------------
  345. void __fastcall TConfiguration::Export(const UnicodeString & FileName)
  346. {
  347. // not to "append" the export to an existing file
  348. if (FileExists(FileName))
  349. {
  350. DeleteFileChecked(FileName);
  351. }
  352. THierarchicalStorage * Storage = NULL;
  353. THierarchicalStorage * ExportStorage = NULL;
  354. try
  355. {
  356. ExportStorage = TIniFileStorage::CreateFromPath(FileName);
  357. ExportStorage->AccessMode = smReadWrite;
  358. ExportStorage->Explicit = true;
  359. Storage = CreateConfigStorage();
  360. Storage->AccessMode = smRead;
  361. CopyData(Storage, ExportStorage);
  362. if (ExportStorage->OpenSubKey(ConfigurationSubKey, true))
  363. {
  364. SaveData(ExportStorage, true);
  365. }
  366. }
  367. __finally
  368. {
  369. delete ExportStorage;
  370. delete Storage;
  371. }
  372. StoredSessions->Export(FileName);
  373. }
  374. //---------------------------------------------------------------------------
  375. void __fastcall TConfiguration::Import(const UnicodeString & FileName)
  376. {
  377. THierarchicalStorage * Storage = NULL;
  378. THierarchicalStorage * ImportStorage = NULL;
  379. try
  380. {
  381. ImportStorage = TIniFileStorage::CreateFromPath(FileName);
  382. ImportStorage->AccessMode = smRead;
  383. Storage = CreateConfigStorage();
  384. Storage->AccessMode = smReadWrite;
  385. Storage->Explicit = true;
  386. CopyData(ImportStorage, Storage);
  387. Default();
  388. LoadFrom(ImportStorage);
  389. Storage->RecursiveDeleteSubKey(Configuration->StoredSessionsSubKey);
  390. if (ImportStorage->OpenSubKey(Configuration->StoredSessionsSubKey, false))
  391. {
  392. StoredSessions->Clear();
  393. StoredSessions->DefaultSettings->Default();
  394. StoredSessions->Load(ImportStorage);
  395. }
  396. }
  397. __finally
  398. {
  399. delete ImportStorage;
  400. delete Storage;
  401. }
  402. // save all and explicit
  403. DoSave(true, true);
  404. FDontSave = true;
  405. }
  406. //---------------------------------------------------------------------------
  407. void __fastcall TConfiguration::LoadData(THierarchicalStorage * Storage)
  408. {
  409. #define KEYEX(TYPE, VAR, NAME) VAR = Storage->Read ## TYPE(NAME, VAR)
  410. #pragma warn -eas
  411. REGCONFIG(false);
  412. #pragma warn +eas
  413. #undef KEYEX
  414. if (Storage->OpenSubKey(L"Usage", false))
  415. {
  416. FUsage->Load(Storage);
  417. Storage->CloseSubKey();
  418. }
  419. if (FPermanentLogActions && FPermanentActionsLogFileName.IsEmpty() &&
  420. FPermanentLogging && !FPermanentLogFileName.IsEmpty())
  421. {
  422. FPermanentActionsLogFileName = FPermanentLogFileName;
  423. FPermanentLogging = false;
  424. FPermanentLogFileName = L"";
  425. }
  426. }
  427. //---------------------------------------------------------------------------
  428. void __fastcall TConfiguration::LoadAdmin(THierarchicalStorage * Storage)
  429. {
  430. FDisablePasswordStoring = Storage->ReadBool(L"DisablePasswordStoring", FDisablePasswordStoring);
  431. FForceBanners = Storage->ReadBool(L"ForceBanners", FForceBanners);
  432. FDisableAcceptingHostKeys = Storage->ReadBool(L"DisableAcceptingHostKeys", FDisableAcceptingHostKeys);
  433. FDefaultCollectUsage = Storage->ReadBool(L"DefaultCollectUsage", FDefaultCollectUsage);
  434. }
  435. //---------------------------------------------------------------------------
  436. void __fastcall TConfiguration::LoadFrom(THierarchicalStorage * Storage)
  437. {
  438. if (Storage->OpenSubKey(ConfigurationSubKey, false))
  439. {
  440. LoadData(Storage);
  441. Storage->CloseSubKey();
  442. }
  443. }
  444. //---------------------------------------------------------------------------
  445. UnicodeString __fastcall TConfiguration::GetRegistryStorageOverrideKey()
  446. {
  447. return GetRegistryStorageKey() + L" Override";
  448. }
  449. //---------------------------------------------------------------------------
  450. UnicodeString __fastcall TConfiguration::LoadCustomIniFileStorageName()
  451. {
  452. UnicodeString Result;
  453. std::unique_ptr<TRegistryStorage> RegistryStorage(new TRegistryStorage(GetRegistryStorageOverrideKey()));
  454. if (RegistryStorage->OpenRootKey(false))
  455. {
  456. Result = RegistryStorage->ReadString(L"IniFile", L"");
  457. RegistryStorage->CloseSubKey();
  458. }
  459. RegistryStorage.reset(NULL);
  460. return Result;
  461. }
  462. //---------------------------------------------------------------------------
  463. void __fastcall TConfiguration::Load(THierarchicalStorage * Storage)
  464. {
  465. TGuard Guard(FCriticalSection);
  466. TStorageAccessMode StorageAccessMode = Storage->AccessMode;
  467. try
  468. {
  469. Storage->AccessMode = smRead;
  470. LoadFrom(Storage);
  471. }
  472. __finally
  473. {
  474. Storage->AccessMode = StorageAccessMode;
  475. }
  476. }
  477. //---------------------------------------------------------------------------
  478. bool __fastcall TConfiguration::CopySubKey(THierarchicalStorage * Source, THierarchicalStorage * Target, const UnicodeString & Name)
  479. {
  480. bool Result = Source->OpenSubKey(Name, false);
  481. if (Result)
  482. {
  483. Result = Target->OpenSubKey(Name, true);
  484. if (!Result)
  485. {
  486. Source->CloseSubKey();
  487. }
  488. }
  489. return Result;
  490. }
  491. //---------------------------------------------------------------------------
  492. void __fastcall TConfiguration::CopyAllStringsInSubKey(
  493. THierarchicalStorage * Source, THierarchicalStorage * Target, const UnicodeString & Name)
  494. {
  495. if (CopySubKey(Source, Target, Name))
  496. {
  497. std::unique_ptr<TStrings> Names(new TStringList());
  498. Source->GetValueNames(Names.get());
  499. for (int Index = 0; Index < Names->Count; Index++)
  500. {
  501. UnicodeString Buf = Source->ReadStringRaw(Names->Strings[Index], UnicodeString());
  502. Target->WriteStringRaw(Names->Strings[Index], Buf);
  503. }
  504. Target->CloseSubKey();
  505. Source->CloseSubKey();
  506. }
  507. }
  508. //---------------------------------------------------------------------------
  509. void __fastcall TConfiguration::CopyData(THierarchicalStorage * Source,
  510. THierarchicalStorage * Target)
  511. {
  512. if (CopySubKey(Source, Target, ConfigurationSubKey))
  513. {
  514. if (CopySubKey(Source, Target, CDCacheKey))
  515. {
  516. std::unique_ptr<TStrings> Names(new TStringList());
  517. Source->GetValueNames(Names.get());
  518. for (int Index = 0; Index < Names->Count; Index++)
  519. {
  520. Target->WriteBinaryData(Names->Strings[Index], Source->ReadBinaryData(Names->Strings[Index]));
  521. }
  522. Target->CloseSubKey();
  523. Source->CloseSubKey();
  524. }
  525. CopyAllStringsInSubKey(Source, Target, BannersKey);
  526. CopyAllStringsInSubKey(Source, Target, LastFingerprintsStorageKey);
  527. Target->CloseSubKey();
  528. Source->CloseSubKey();
  529. }
  530. CopyAllStringsInSubKey(Source, Target, SshHostKeysSubKey);
  531. CopyAllStringsInSubKey(Source, Target, FtpsCertificateStorageKey);
  532. CopyAllStringsInSubKey(Source, Target, HttpsCertificateStorageKey);
  533. }
  534. //---------------------------------------------------------------------------
  535. void __fastcall TConfiguration::LoadDirectoryChangesCache(const UnicodeString SessionKey,
  536. TRemoteDirectoryChangesCache * DirectoryChangesCache)
  537. {
  538. THierarchicalStorage * Storage = CreateConfigStorage();
  539. try
  540. {
  541. Storage->AccessMode = smRead;
  542. if (Storage->OpenSubKey(ConfigurationSubKey, false) &&
  543. Storage->OpenSubKey(CDCacheKey, false) &&
  544. Storage->ValueExists(SessionKey))
  545. {
  546. DirectoryChangesCache->Deserialize(Storage->ReadBinaryData(SessionKey));
  547. }
  548. }
  549. __finally
  550. {
  551. delete Storage;
  552. }
  553. }
  554. //---------------------------------------------------------------------------
  555. void __fastcall TConfiguration::SaveDirectoryChangesCache(const UnicodeString SessionKey,
  556. TRemoteDirectoryChangesCache * DirectoryChangesCache)
  557. {
  558. THierarchicalStorage * Storage = CreateConfigStorage();
  559. try
  560. {
  561. Storage->AccessMode = smReadWrite;
  562. if (Storage->OpenSubKey(ConfigurationSubKey, true) &&
  563. Storage->OpenSubKey(CDCacheKey, true))
  564. {
  565. UnicodeString Data;
  566. DirectoryChangesCache->Serialize(Data);
  567. Storage->WriteBinaryData(SessionKey, Data);
  568. }
  569. }
  570. __finally
  571. {
  572. delete Storage;
  573. }
  574. }
  575. //---------------------------------------------------------------------------
  576. UnicodeString __fastcall TConfiguration::BannerHash(const UnicodeString & Banner)
  577. {
  578. RawByteString Result;
  579. Result.SetLength(16);
  580. md5checksum(
  581. reinterpret_cast<const char*>(Banner.c_str()), Banner.Length() * sizeof(wchar_t),
  582. (unsigned char*)Result.c_str());
  583. return BytesToHex(Result);
  584. }
  585. //---------------------------------------------------------------------------
  586. void __fastcall TConfiguration::GetBannerData(
  587. const UnicodeString & SessionKey, UnicodeString & BannerHash, unsigned int & Params)
  588. {
  589. BannerHash = UnicodeString();
  590. Params = 0;
  591. std::unique_ptr<THierarchicalStorage> Storage(CreateConfigStorage());
  592. Storage->AccessMode = smRead;
  593. if (Storage->OpenSubKey(ConfigurationSubKey, false) &&
  594. Storage->OpenSubKey(BannersKey, false))
  595. {
  596. UnicodeString S = Storage->ReadString(SessionKey, L"");
  597. BannerHash = CutToChar(S, L',', true);
  598. Params = StrToIntDef(L"$" + CutToChar(S, L',', true), 0);
  599. }
  600. }
  601. //---------------------------------------------------------------------------
  602. bool __fastcall TConfiguration::ShowBanner(
  603. const UnicodeString & SessionKey, const UnicodeString & Banner, unsigned int & Params)
  604. {
  605. UnicodeString StoredBannerHash;
  606. GetBannerData(SessionKey, StoredBannerHash, Params);
  607. bool Result = (StoredBannerHash != BannerHash(Banner));
  608. return Result;
  609. }
  610. //---------------------------------------------------------------------------
  611. void __fastcall TConfiguration::SetBannerData(
  612. const UnicodeString & SessionKey, const UnicodeString & BannerHash, unsigned int Params)
  613. {
  614. std::unique_ptr<THierarchicalStorage> Storage(CreateConfigStorage());
  615. Storage->AccessMode = smReadWrite;
  616. if (Storage->OpenSubKey(ConfigurationSubKey, true) &&
  617. Storage->OpenSubKey(BannersKey, true))
  618. {
  619. Storage->WriteString(SessionKey, BannerHash + L"," + UIntToStr(Params));
  620. }
  621. }
  622. //---------------------------------------------------------------------------
  623. void __fastcall TConfiguration::NeverShowBanner(const UnicodeString & SessionKey, const UnicodeString & Banner)
  624. {
  625. UnicodeString DummyBannerHash;
  626. unsigned int Params;
  627. GetBannerData(SessionKey, DummyBannerHash, Params);
  628. SetBannerData(SessionKey, BannerHash(Banner), Params);
  629. }
  630. //---------------------------------------------------------------------------
  631. void __fastcall TConfiguration::SetBannerParams(const UnicodeString & SessionKey, unsigned int Params)
  632. {
  633. UnicodeString BannerHash;
  634. unsigned int DummyParams;
  635. GetBannerData(SessionKey, BannerHash, DummyParams);
  636. SetBannerData(SessionKey, BannerHash, Params);
  637. }
  638. //---------------------------------------------------------------------------
  639. UnicodeString __fastcall TConfiguration::FormatFingerprintKey(const UnicodeString & SiteKey, const UnicodeString & FingerprintType)
  640. {
  641. return FORMAT(L"%s:%s", (SiteKey, FingerprintType));
  642. }
  643. //---------------------------------------------------------------------------
  644. void __fastcall TConfiguration::RememberLastFingerprint(const UnicodeString & SiteKey, const UnicodeString & FingerprintType, const UnicodeString & Fingerprint)
  645. {
  646. std::unique_ptr<THierarchicalStorage> Storage(CreateConfigStorage());
  647. Storage->AccessMode = smReadWrite;
  648. if (Storage->OpenSubKey(ConfigurationSubKey, true) &&
  649. Storage->OpenSubKey(LastFingerprintsStorageKey, true))
  650. {
  651. UnicodeString FingerprintKey = FormatFingerprintKey(SiteKey, FingerprintType);
  652. Storage->WriteString(FingerprintKey, Fingerprint);
  653. }
  654. }
  655. //---------------------------------------------------------------------------
  656. UnicodeString __fastcall TConfiguration::LastFingerprint(const UnicodeString & SiteKey, const UnicodeString & FingerprintType)
  657. {
  658. UnicodeString Result;
  659. std::unique_ptr<THierarchicalStorage> Storage(CreateConfigStorage());
  660. Storage->AccessMode = smRead;
  661. if (Storage->OpenSubKey(ConfigurationSubKey, false) &&
  662. Storage->OpenSubKey(LastFingerprintsStorageKey, false))
  663. {
  664. UnicodeString FingerprintKey = FormatFingerprintKey(SiteKey, FingerprintType);
  665. Result = Storage->ReadString(FingerprintKey, L"");
  666. }
  667. return Result;
  668. }
  669. //---------------------------------------------------------------------------
  670. void __fastcall TConfiguration::Changed()
  671. {
  672. TNotifyEvent AOnChange = NULL;
  673. {
  674. TGuard Guard(FCriticalSection);
  675. if (FUpdating == 0)
  676. {
  677. AOnChange = OnChange;
  678. }
  679. else
  680. {
  681. FChanged = true;
  682. }
  683. }
  684. // No specific reason to call this outside of a guard, just that it is less of a change to a previous unguarded code
  685. if (AOnChange != NULL)
  686. {
  687. AOnChange(this);
  688. }
  689. }
  690. //---------------------------------------------------------------------------
  691. void __fastcall TConfiguration::BeginUpdate()
  692. {
  693. FCriticalSection->Enter();
  694. if (FUpdating == 0)
  695. {
  696. FChanged = false;
  697. }
  698. FUpdating++;
  699. // Greater value would probably indicate some nesting problem in code
  700. DebugAssert(FUpdating < 6);
  701. }
  702. //---------------------------------------------------------------------------
  703. void __fastcall TConfiguration::EndUpdate()
  704. {
  705. DebugAssert(FUpdating > 0);
  706. FUpdating--;
  707. if ((FUpdating == 0) && FChanged)
  708. {
  709. FChanged = false;
  710. Changed();
  711. }
  712. FCriticalSection->Leave();
  713. }
  714. //---------------------------------------------------------------------------
  715. void __fastcall TConfiguration::CleanupConfiguration()
  716. {
  717. try
  718. {
  719. CleanupRegistry(ConfigurationSubKey);
  720. if (Storage == stRegistry)
  721. {
  722. FDontSave = true;
  723. }
  724. }
  725. catch (Exception &E)
  726. {
  727. throw ExtException(&E, LoadStr(CLEANUP_CONFIG_ERROR));
  728. }
  729. }
  730. //---------------------------------------------------------------------------
  731. bool TConfiguration::RegistryPathExists(const UnicodeString & RegistryPath)
  732. {
  733. std::unique_ptr<TRegistryStorage> Registry(new TRegistryStorage(RegistryStorageKey));
  734. UnicodeString ParentKey = ExtractFileDir(RegistryPath);
  735. UnicodeString SubKey = ExtractFileName(RegistryPath);
  736. return
  737. Registry->OpenRootKey(false) &&
  738. (ParentKey.IsEmpty() ||
  739. Registry->OpenSubKeyPath(ParentKey, false)) &&
  740. Registry->KeyExists(SubKey);
  741. }
  742. //---------------------------------------------------------------------------
  743. void __fastcall TConfiguration::CleanupRegistry(const UnicodeString & RegistryPath)
  744. {
  745. std::unique_ptr<TRegistryStorage> Registry(new TRegistryStorage(RegistryStorageKey));
  746. UnicodeString ParentKey = ExtractFileDir(RegistryPath);
  747. if (ParentKey.IsEmpty() ||
  748. Registry->OpenSubKeyPath(ParentKey, false))
  749. {
  750. UnicodeString SubKey = ExtractFileName(RegistryPath);
  751. Registry->RecursiveDeleteSubKey(SubKey);
  752. }
  753. }
  754. //---------------------------------------------------------------------------
  755. TStrings * TConfiguration::GetCaches()
  756. {
  757. std::unique_ptr<TStrings> Result(new TStringList());
  758. Result->Add(SshHostKeysSubKey);
  759. Result->Add(FtpsCertificateStorageKey);
  760. Result->Add(HttpsCertificateStorageKey);
  761. Result->Add(DirectoryStatisticsCacheKey);
  762. Result->Add(TPath::Combine(ConfigurationSubKey, CDCacheKey));
  763. Result->Add(TPath::Combine(ConfigurationSubKey, BannersKey));
  764. Result->Add(TPath::Combine(ConfigurationSubKey, LastFingerprintsStorageKey));
  765. return Result.release();
  766. }
  767. //---------------------------------------------------------------------------
  768. bool __fastcall TConfiguration::HasAnyCache()
  769. {
  770. bool Result = false;
  771. std::unique_ptr<TStrings> Caches(GetCaches());
  772. for (int Index = 0; Index < Caches->Count; Index++)
  773. {
  774. if (RegistryPathExists(Caches->Strings[Index]))
  775. {
  776. Result = true;
  777. break;
  778. }
  779. }
  780. return Result;
  781. }
  782. //---------------------------------------------------------------------------
  783. void __fastcall TConfiguration::CleanupCaches()
  784. {
  785. try
  786. {
  787. std::unique_ptr<TStrings> Caches(GetCaches());
  788. for (int Index = 0; Index < Caches->Count; Index++)
  789. {
  790. CleanupRegistry(Caches->Strings[Index]);
  791. }
  792. }
  793. catch (Exception & E)
  794. {
  795. throw ExtException(&E, LoadStr(CLEANUP_CACHES_ERROR));
  796. }
  797. }
  798. //---------------------------------------------------------------------------
  799. void __fastcall TConfiguration::CleanupRandomSeedFile()
  800. {
  801. try
  802. {
  803. DontSaveRandomSeed();
  804. if (FileExists(ApiPath(RandomSeedFileName)))
  805. {
  806. DeleteFileChecked(RandomSeedFileName);
  807. }
  808. }
  809. catch (Exception &E)
  810. {
  811. throw ExtException(&E, LoadStr(CLEANUP_SEEDFILE_ERROR));
  812. }
  813. }
  814. //---------------------------------------------------------------------------
  815. void __fastcall TConfiguration::CleanupIniFile()
  816. {
  817. try
  818. {
  819. if (FileExists(ApiPath(IniFileStorageNameForReading)))
  820. {
  821. DeleteFileChecked(IniFileStorageNameForReading);
  822. }
  823. if (Storage == stIniFile)
  824. {
  825. FDontSave = true;
  826. }
  827. }
  828. catch (Exception &E)
  829. {
  830. throw ExtException(&E, LoadStr(CLEANUP_INIFILE_ERROR));
  831. }
  832. }
  833. //---------------------------------------------------------------------------
  834. void __fastcall TConfiguration::DontSave()
  835. {
  836. FDontSave = true;
  837. }
  838. //---------------------------------------------------------------------------
  839. RawByteString __fastcall TConfiguration::EncryptPassword(UnicodeString Password, UnicodeString Key)
  840. {
  841. if (Password.IsEmpty())
  842. {
  843. return RawByteString();
  844. }
  845. else
  846. {
  847. return ::EncryptPassword(Password, Key);
  848. }
  849. }
  850. //---------------------------------------------------------------------------
  851. UnicodeString __fastcall TConfiguration::DecryptPassword(RawByteString Password, UnicodeString Key)
  852. {
  853. if (Password.IsEmpty())
  854. {
  855. return UnicodeString();
  856. }
  857. else
  858. {
  859. return ::DecryptPassword(Password, Key);
  860. }
  861. }
  862. //---------------------------------------------------------------------------
  863. RawByteString __fastcall TConfiguration::StronglyRecryptPassword(RawByteString Password, UnicodeString /*Key*/)
  864. {
  865. return Password;
  866. }
  867. //---------------------------------------------------------------------------
  868. TVSFixedFileInfo *__fastcall TConfiguration::GetFixedApplicationInfo()
  869. {
  870. return GetFixedFileInfo(ApplicationInfo);
  871. }
  872. //---------------------------------------------------------------------------
  873. int __fastcall TConfiguration::GetCompoundVersion()
  874. {
  875. TVSFixedFileInfo * FileInfo = FixedApplicationInfo;
  876. return CalculateCompoundVersion(
  877. HIWORD(FileInfo->dwFileVersionMS), LOWORD(FileInfo->dwFileVersionMS),
  878. HIWORD(FileInfo->dwFileVersionLS));
  879. }
  880. //---------------------------------------------------------------------------
  881. UnicodeString __fastcall TConfiguration::ModuleFileName()
  882. {
  883. return ParamStr(0);
  884. }
  885. //---------------------------------------------------------------------------
  886. void * __fastcall TConfiguration::GetFileApplicationInfo(const UnicodeString FileName)
  887. {
  888. void * Result;
  889. if (FileName.IsEmpty())
  890. {
  891. if (!FApplicationInfo)
  892. {
  893. FApplicationInfo = CreateFileInfo(ModuleFileName());
  894. }
  895. Result = FApplicationInfo;
  896. }
  897. else
  898. {
  899. Result = CreateFileInfo(FileName);
  900. }
  901. return Result;
  902. }
  903. //---------------------------------------------------------------------------
  904. void * __fastcall TConfiguration::GetApplicationInfo()
  905. {
  906. return GetFileApplicationInfo("");
  907. }
  908. //---------------------------------------------------------------------------
  909. UnicodeString __fastcall TConfiguration::GetFileProductName(const UnicodeString FileName)
  910. {
  911. return GetFileFileInfoString(L"ProductName", FileName);
  912. }
  913. //---------------------------------------------------------------------------
  914. UnicodeString __fastcall TConfiguration::GetFileCompanyName(const UnicodeString FileName)
  915. {
  916. // particularly in IDE build, company name is empty
  917. return GetFileFileInfoString(L"CompanyName", FileName, true);
  918. }
  919. //---------------------------------------------------------------------------
  920. UnicodeString __fastcall TConfiguration::GetProductName()
  921. {
  922. return GetFileProductName(L"");
  923. }
  924. //---------------------------------------------------------------------------
  925. UnicodeString __fastcall TConfiguration::GetCompanyName()
  926. {
  927. return GetFileCompanyName(L"");
  928. }
  929. //---------------------------------------------------------------------------
  930. UnicodeString __fastcall TConfiguration::GetFileProductVersion(const UnicodeString FileName)
  931. {
  932. return TrimVersion(GetFileFileInfoString(L"ProductVersion", FileName));
  933. }
  934. //---------------------------------------------------------------------------
  935. UnicodeString __fastcall TConfiguration::GetFileDescription(const UnicodeString & FileName)
  936. {
  937. return GetFileFileInfoString(L"FileDescription", FileName);
  938. }
  939. //---------------------------------------------------------------------------
  940. UnicodeString __fastcall TConfiguration::GetProductVersion()
  941. {
  942. return GetFileProductVersion(L"");
  943. }
  944. //---------------------------------------------------------------------------
  945. UnicodeString __fastcall TConfiguration::GetReleaseType()
  946. {
  947. return GetFileInfoString(L"ReleaseType");
  948. }
  949. //---------------------------------------------------------------------------
  950. bool __fastcall TConfiguration::GetIsUnofficial()
  951. {
  952. #ifdef BUILD_OFFICIAL
  953. return false;
  954. #else
  955. return true;
  956. #endif
  957. }
  958. //---------------------------------------------------------------------------
  959. static TDateTime GetBuildDate()
  960. {
  961. UnicodeString BuildDateStr = __DATE__;
  962. UnicodeString MonthStr = CutToChar(BuildDateStr, L' ', true);
  963. int Month = ParseShortEngMonthName(MonthStr);
  964. int Day = StrToInt(CutToChar(BuildDateStr, L' ', true));
  965. int Year = StrToInt(Trim(BuildDateStr));
  966. TDateTime Result = EncodeDateVerbose(static_cast<Word>(Year), static_cast<Word>(Month), static_cast<Word>(Day));
  967. return Result;
  968. }
  969. //---------------------------------------------------------------------------
  970. UnicodeString TConfiguration::GetFullVersion()
  971. {
  972. UnicodeString Result = Version;
  973. UnicodeString AReleaseType = GetReleaseType();
  974. if (DebugAlwaysTrue(!AReleaseType.IsEmpty()) &&
  975. !SameText(AReleaseType, L"stable") &&
  976. !SameText(AReleaseType, L"development"))
  977. {
  978. Result += L" " + AReleaseType;
  979. }
  980. return Result;
  981. }
  982. //---------------------------------------------------------------------------
  983. static UnicodeString GetUnofficialBuildTag()
  984. {
  985. DebugAssert(Configuration->IsUnofficial);
  986. UnicodeString Result;
  987. #ifdef _DEBUG
  988. Result = LoadStr(VERSION_DEBUG_BUILD);
  989. #else
  990. Result = LoadStr(VERSION_DEV_BUILD);
  991. #endif
  992. return Result;
  993. }
  994. //---------------------------------------------------------------------------
  995. UnicodeString TConfiguration::GetVersionStrHuman()
  996. {
  997. TGuard Guard(FCriticalSection);
  998. try
  999. {
  1000. TDateTime BuildDate = GetBuildDate();
  1001. UnicodeString FullVersion = GetFullVersion();
  1002. if (IsUnofficial)
  1003. {
  1004. UnicodeString BuildStr = GetUnofficialBuildTag();
  1005. FullVersion += L" " + BuildStr;
  1006. }
  1007. UnicodeString DateStr;
  1008. TDateTime ANow = Now();
  1009. if (BuildDate < ANow)
  1010. {
  1011. DateStr = FormatRelativeTime(ANow, BuildDate, true);
  1012. }
  1013. else
  1014. {
  1015. DateStr = FormatDateTime(L"ddddd", BuildDate);
  1016. }
  1017. UnicodeString Result = FORMAT(L"%s (%s)", (FullVersion, DateStr));
  1018. return Result;
  1019. }
  1020. catch (Exception &E)
  1021. {
  1022. throw ExtException(&E, L"Can't get application version");
  1023. }
  1024. }
  1025. //---------------------------------------------------------------------------
  1026. UnicodeString __fastcall TConfiguration::GetVersionStr()
  1027. {
  1028. TGuard Guard(FCriticalSection);
  1029. try
  1030. {
  1031. UnicodeString BuildStr;
  1032. if (!IsUnofficial)
  1033. {
  1034. BuildStr = LoadStr(VERSION_BUILD);
  1035. }
  1036. else
  1037. {
  1038. BuildStr = GetUnofficialBuildTag();
  1039. }
  1040. UnicodeString FullVersion = GetFullVersion();
  1041. int Build = LOWORD(FixedApplicationInfo->dwFileVersionLS);
  1042. if (Build > 0)
  1043. {
  1044. BuildStr += L" " + IntToStr(Build);
  1045. }
  1046. UnicodeString DateStr = FormatDateTime(L"yyyy-mm-dd", GetBuildDate());
  1047. AddToList(BuildStr, DateStr, L" ");
  1048. UnicodeString Result = FMTLOAD(VERSION2, (FullVersion, BuildStr));
  1049. if (IsUnofficial)
  1050. {
  1051. Result += L" " + LoadStr(VERSION_DONT_DISTRIBUTE);
  1052. }
  1053. return Result;
  1054. }
  1055. catch (Exception &E)
  1056. {
  1057. throw ExtException(&E, L"Can't get application version");
  1058. }
  1059. }
  1060. //---------------------------------------------------------------------------
  1061. UnicodeString __fastcall TConfiguration::GetFileVersion(const UnicodeString & FileName)
  1062. {
  1063. UnicodeString Result;
  1064. void * FileInfo = CreateFileInfo(FileName);
  1065. try
  1066. {
  1067. Result = GetFileVersion(GetFixedFileInfo(FileInfo));
  1068. }
  1069. __finally
  1070. {
  1071. FreeFileInfo(FileInfo);
  1072. }
  1073. return Result;
  1074. }
  1075. //---------------------------------------------------------------------------
  1076. UnicodeString __fastcall TConfiguration::GetFileVersion(TVSFixedFileInfo * Info)
  1077. {
  1078. TGuard Guard(FCriticalSection);
  1079. try
  1080. {
  1081. UnicodeString Result =
  1082. FormatVersion(
  1083. HIWORD(Info->dwFileVersionMS),
  1084. LOWORD(Info->dwFileVersionMS),
  1085. HIWORD(Info->dwFileVersionLS));
  1086. return Result;
  1087. }
  1088. catch (Exception &E)
  1089. {
  1090. throw ExtException(&E, L"Can't get file version");
  1091. }
  1092. }
  1093. //---------------------------------------------------------------------------
  1094. UnicodeString __fastcall TConfiguration::GetVersion()
  1095. {
  1096. return GetFileVersion(FixedApplicationInfo);
  1097. }
  1098. //---------------------------------------------------------------------------
  1099. UnicodeString __fastcall TConfiguration::GetFileFileInfoString(const UnicodeString Key,
  1100. const UnicodeString FileName, bool AllowEmpty)
  1101. {
  1102. TGuard Guard(FCriticalSection);
  1103. UnicodeString Result;
  1104. void * Info = GetFileApplicationInfo(FileName);
  1105. try
  1106. {
  1107. if ((Info != NULL) && (GetTranslationCount(Info) > 0))
  1108. {
  1109. TTranslation Translation;
  1110. Translation = GetTranslation(Info, 0);
  1111. Result = ::GetFileInfoString(Info, Translation, Key, AllowEmpty);
  1112. }
  1113. else
  1114. {
  1115. DebugAssert(!FileName.IsEmpty());
  1116. }
  1117. }
  1118. __finally
  1119. {
  1120. if (!FileName.IsEmpty())
  1121. {
  1122. FreeFileInfo(Info);
  1123. }
  1124. }
  1125. return Result;
  1126. }
  1127. //---------------------------------------------------------------------------
  1128. UnicodeString __fastcall TConfiguration::GetFileInfoString(const UnicodeString Key)
  1129. {
  1130. return GetFileFileInfoString(Key, L"");
  1131. }
  1132. //---------------------------------------------------------------------------
  1133. UnicodeString __fastcall TConfiguration::GetFileMimeType(const UnicodeString & FileName)
  1134. {
  1135. UnicodeString Result;
  1136. bool Found = false;
  1137. if (!MimeTypes.IsEmpty())
  1138. {
  1139. UnicodeString FileNameOnly = ExtractFileName(FileName);
  1140. UnicodeString AMimeTypes = MimeTypes;
  1141. while (!Found && !AMimeTypes.IsEmpty())
  1142. {
  1143. UnicodeString Token = CutToChar(AMimeTypes, L',', true);
  1144. UnicodeString MaskStr = CutToChar(Token, L'=', true);
  1145. TFileMasks Mask(MaskStr);
  1146. if (Mask.MatchesFileName(FileNameOnly))
  1147. {
  1148. Result = Token.Trim();
  1149. Found = true;
  1150. }
  1151. }
  1152. }
  1153. if (!Found) // allow an override to "no" Content-Type
  1154. {
  1155. Result = ::GetFileMimeType(FileName);
  1156. }
  1157. return Result;
  1158. }
  1159. //---------------------------------------------------------------------------
  1160. UnicodeString __fastcall TConfiguration::GetRegistryStorageKey()
  1161. {
  1162. return GetRegistryKey();
  1163. }
  1164. //---------------------------------------------------------------------------
  1165. void __fastcall TConfiguration::SetNulStorage()
  1166. {
  1167. FStorage = stNul;
  1168. }
  1169. //---------------------------------------------------------------------------
  1170. void __fastcall TConfiguration::SetExplicitIniFileStorageName(const UnicodeString & FileName)
  1171. {
  1172. FIniFileStorageName = FileName;
  1173. FStorage = stIniFile;
  1174. }
  1175. //---------------------------------------------------------------------------
  1176. UnicodeString __fastcall TConfiguration::GetDefaultIniFileExportPath()
  1177. {
  1178. UnicodeString PersonalDirectory = GetPersonalFolder();
  1179. UnicodeString FileName = IncludeTrailingBackslash(PersonalDirectory) +
  1180. ExtractFileName(ExpandEnvironmentVariables(IniFileStorageName));
  1181. return FileName;
  1182. }
  1183. //---------------------------------------------------------------------------
  1184. UnicodeString __fastcall TConfiguration::GetIniFileStorageNameForReading()
  1185. {
  1186. return GetIniFileStorageName(true);
  1187. }
  1188. //---------------------------------------------------------------------------
  1189. UnicodeString __fastcall TConfiguration::GetIniFileStorageNameForReadingWriting()
  1190. {
  1191. return GetIniFileStorageName(false);
  1192. }
  1193. //---------------------------------------------------------------------------
  1194. UnicodeString __fastcall TConfiguration::GetAutomaticIniFileStorageName(bool ReadingOnly)
  1195. {
  1196. UnicodeString ProgramPath = ParamStr(0);
  1197. UnicodeString ProgramIniPath = ChangeFileExt(ProgramPath, L".ini");
  1198. UnicodeString IniPath;
  1199. if (FileExists(ApiPath(ProgramIniPath)))
  1200. {
  1201. IniPath = ProgramIniPath;
  1202. }
  1203. else
  1204. {
  1205. UnicodeString AppDataIniPath =
  1206. IncludeTrailingBackslash(GetShellFolderPath(CSIDL_APPDATA)) +
  1207. ExtractFileName(ProgramIniPath);
  1208. if (FileExists(ApiPath(AppDataIniPath)))
  1209. {
  1210. IniPath = AppDataIniPath;
  1211. }
  1212. else
  1213. {
  1214. // avoid expensive test if we are interested in existing files only
  1215. if (!ReadingOnly && (FProgramIniPathWrittable < 0))
  1216. {
  1217. UnicodeString ProgramDir = ExtractFilePath(ProgramPath);
  1218. FProgramIniPathWrittable = IsDirectoryWriteable(ProgramDir) ? 1 : 0;
  1219. }
  1220. // does not really matter what we return when < 0
  1221. IniPath = (FProgramIniPathWrittable == 0) ? AppDataIniPath : ProgramIniPath;
  1222. }
  1223. }
  1224. // BACKWARD COMPATIBILITY with 4.x
  1225. if (FVirtualIniFileStorageName.IsEmpty() &&
  1226. TPath::IsDriveRooted(IniPath))
  1227. {
  1228. UnicodeString LocalAppDataPath = GetShellFolderPath(CSIDL_LOCAL_APPDATA);
  1229. // virtual store for non-system drives have a different virtual store,
  1230. // do not bother about them
  1231. if (TPath::IsDriveRooted(LocalAppDataPath) &&
  1232. SameText(ExtractFileDrive(IniPath), ExtractFileDrive(LocalAppDataPath)))
  1233. {
  1234. FVirtualIniFileStorageName =
  1235. IncludeTrailingBackslash(LocalAppDataPath) +
  1236. L"VirtualStore\\" +
  1237. IniPath.SubString(4, IniPath.Length() - 3);
  1238. }
  1239. }
  1240. if (!FVirtualIniFileStorageName.IsEmpty() &&
  1241. FileExists(ApiPath(FVirtualIniFileStorageName)))
  1242. {
  1243. return FVirtualIniFileStorageName;
  1244. }
  1245. else
  1246. {
  1247. return IniPath;
  1248. }
  1249. }
  1250. //---------------------------------------------------------------------------
  1251. UnicodeString __fastcall TConfiguration::GetIniFileParamValue()
  1252. {
  1253. UnicodeString Result;
  1254. if (Storage == stNul)
  1255. {
  1256. Result = INI_NUL;
  1257. }
  1258. else if ((Storage == stIniFile) && !FIniFileStorageName.IsEmpty())
  1259. {
  1260. Result = FIniFileStorageName;
  1261. }
  1262. return Result;
  1263. }
  1264. //---------------------------------------------------------------------------
  1265. UnicodeString __fastcall TConfiguration::GetIniFileStorageName(bool ReadingOnly)
  1266. {
  1267. UnicodeString Result;
  1268. if (!FIniFileStorageName.IsEmpty())
  1269. {
  1270. Result = FIniFileStorageName;
  1271. }
  1272. else if (!FCustomIniFileStorageName.IsEmpty())
  1273. {
  1274. Result = ExpandEnvironmentVariables(FCustomIniFileStorageName);
  1275. }
  1276. else
  1277. {
  1278. Result = GetAutomaticIniFileStorageName(ReadingOnly);
  1279. }
  1280. return Result;
  1281. }
  1282. //---------------------------------------------------------------------------
  1283. void __fastcall TConfiguration::SetOptionsStorage(TStrings * value)
  1284. {
  1285. TGuard Guard(FCriticalSection);
  1286. if (FOptionsStorage.get() == NULL)
  1287. {
  1288. FOptionsStorage.reset(new TStringList());
  1289. }
  1290. FOptionsStorage->AddStrings(value);
  1291. }
  1292. //---------------------------------------------------------------------------
  1293. TStrings * __fastcall TConfiguration::GetOptionsStorage()
  1294. {
  1295. return FOptionsStorage.get();
  1296. }
  1297. //---------------------------------------------------------------------------
  1298. UnicodeString __fastcall TConfiguration::GetPuttySessionsSubKey()
  1299. {
  1300. return StoredSessionsSubKey;
  1301. }
  1302. //---------------------------------------------------------------------------
  1303. UnicodeString TConfiguration::GetPuttySessionsKey(const UnicodeString & RootKey)
  1304. {
  1305. return RootKey + L"\\" + PuttySessionsSubKey;
  1306. }
  1307. //---------------------------------------------------------------------------
  1308. UnicodeString __fastcall TConfiguration::DoGetPuttySessionsKey()
  1309. {
  1310. return GetPuttySessionsKey(PuttyRegistryStorageKey);
  1311. }
  1312. //---------------------------------------------------------------------------
  1313. UnicodeString __fastcall TConfiguration::GetStoredSessionsSubKey()
  1314. {
  1315. return L"Sessions";
  1316. }
  1317. //---------------------------------------------------------------------------
  1318. UnicodeString __fastcall TConfiguration::GetSshHostKeysSubKey()
  1319. {
  1320. return L"SshHostKeys";
  1321. }
  1322. //---------------------------------------------------------------------------
  1323. UnicodeString __fastcall TConfiguration::GetConfigurationSubKey()
  1324. {
  1325. return L"Configuration";
  1326. }
  1327. //---------------------------------------------------------------------------
  1328. UnicodeString __fastcall TConfiguration::GetRootKeyStr()
  1329. {
  1330. return RootKeyToStr(HKEY_CURRENT_USER);
  1331. }
  1332. //---------------------------------------------------------------------------
  1333. void __fastcall TConfiguration::MoveStorage(TStorage AStorage, const UnicodeString & ACustomIniFileStorageName)
  1334. {
  1335. if ((FStorage != AStorage) ||
  1336. ((FStorage == stIniFile) && !FIniFileStorageName.IsEmpty()) ||
  1337. // Not expanding, as we want to allow change from explicit path to path with variables and vice versa
  1338. !IsPathToSameFile(FCustomIniFileStorageName, ACustomIniFileStorageName))
  1339. {
  1340. TStorage StorageBak = FStorage;
  1341. UnicodeString CustomIniFileStorageNameBak = FCustomIniFileStorageName;
  1342. UnicodeString IniFileStorageNameBak = FIniFileStorageName;
  1343. try
  1344. {
  1345. THierarchicalStorage * SourceStorage = NULL;
  1346. THierarchicalStorage * TargetStorage = NULL;
  1347. try
  1348. {
  1349. SourceStorage = CreateConfigStorage();
  1350. SourceStorage->AccessMode = smRead;
  1351. FStorage = AStorage;
  1352. FCustomIniFileStorageName = ACustomIniFileStorageName;
  1353. FIniFileStorageName = UnicodeString();
  1354. TargetStorage = CreateConfigStorage();
  1355. TargetStorage->AccessMode = smReadWrite;
  1356. TargetStorage->Explicit = true;
  1357. // copy before save as it removes the ini file,
  1358. // when switching from ini to registry
  1359. CopyData(SourceStorage, TargetStorage);
  1360. }
  1361. __finally
  1362. {
  1363. delete SourceStorage;
  1364. delete TargetStorage;
  1365. }
  1366. // save all and explicit,
  1367. // this also removes an INI file, when switching to registry storage
  1368. DoSave(true, true);
  1369. }
  1370. catch (...)
  1371. {
  1372. // If this fails, do not pretend that storage was switched.
  1373. // For instance:
  1374. // - When writing to an INI file fails (unlikely, as we fallback to user profile)
  1375. // - When removing INI file fails, when switching to registry
  1376. // (possible, when the INI file is in Program Files folder)
  1377. FStorage = StorageBak;
  1378. FCustomIniFileStorageName = CustomIniFileStorageNameBak;
  1379. FIniFileStorageName = IniFileStorageNameBak;
  1380. throw;
  1381. }
  1382. }
  1383. }
  1384. //---------------------------------------------------------------------------
  1385. void __fastcall TConfiguration::ScheduleCustomIniFileStorageUse(const UnicodeString & ACustomIniFileStorageName)
  1386. {
  1387. FStorage = stIniFile;
  1388. FCustomIniFileStorageName = ACustomIniFileStorageName;
  1389. SaveCustomIniFileStorageName();
  1390. }
  1391. //---------------------------------------------------------------------------
  1392. void __fastcall TConfiguration::Saved()
  1393. {
  1394. // nothing
  1395. }
  1396. //---------------------------------------------------------------------------
  1397. TStorage __fastcall TConfiguration::GetStorage()
  1398. {
  1399. TGuard Guard(FCriticalSection);
  1400. if (FStorage == stDetect)
  1401. {
  1402. if (FileExists(ApiPath(IniFileStorageNameForReading)))
  1403. {
  1404. FStorage = stIniFile;
  1405. }
  1406. else
  1407. {
  1408. FStorage = stRegistry;
  1409. }
  1410. }
  1411. return FStorage;
  1412. }
  1413. //---------------------------------------------------------------------
  1414. static TStoredSessionList * CreateSessionsForImport(TStoredSessionList * Sessions)
  1415. {
  1416. std::unique_ptr<TStoredSessionList> Result(new TStoredSessionList(true));
  1417. Result->DefaultSettings = Sessions->DefaultSettings;
  1418. return Result.release();
  1419. }
  1420. //---------------------------------------------------------------------
  1421. TStoredSessionList * __fastcall TConfiguration::SelectFilezillaSessionsForImport(
  1422. TStoredSessionList * Sessions, UnicodeString & Error)
  1423. {
  1424. std::unique_ptr<TStoredSessionList> ImportSessionList(CreateSessionsForImport(Sessions));
  1425. UnicodeString AppDataPath = GetShellFolderPath(CSIDL_APPDATA);
  1426. UnicodeString FilezillaSiteManagerFile = TPath::Combine(AppDataPath, L"FileZilla\\sitemanager.xml");
  1427. UnicodeString FilezillaConfigurationFile = TPath::Combine(AppDataPath, L"FileZilla\\filezilla.xml");
  1428. if (FileExists(ApiPath(FilezillaSiteManagerFile)))
  1429. {
  1430. ImportSessionList->ImportFromFilezilla(FilezillaSiteManagerFile, FilezillaConfigurationFile);
  1431. if (ImportSessionList->Count > 0)
  1432. {
  1433. ImportSessionList->SelectSessionsToImport(Sessions, true);
  1434. }
  1435. else
  1436. {
  1437. Error = FMTLOAD(FILEZILLA_NO_SITES, (FilezillaSiteManagerFile));
  1438. }
  1439. }
  1440. else
  1441. {
  1442. Error = FMTLOAD(FILEZILLA_SITE_MANAGER_NOT_FOUND, (FilezillaSiteManagerFile));
  1443. }
  1444. return ImportSessionList.release();
  1445. }
  1446. //---------------------------------------------------------------------
  1447. bool __fastcall TConfiguration::AnyFilezillaSessionForImport(TStoredSessionList * Sessions)
  1448. {
  1449. try
  1450. {
  1451. UnicodeString Error;
  1452. std::unique_ptr<TStoredSessionList> SessionsForImport(SelectFilezillaSessionsForImport(Sessions, Error));
  1453. return (SessionsForImport->Count > 0);
  1454. }
  1455. catch (...)
  1456. {
  1457. return false;
  1458. }
  1459. }
  1460. //---------------------------------------------------------------------
  1461. static UnicodeString GetOpensshFolder()
  1462. {
  1463. UnicodeString ProfilePath = GetShellFolderPath(CSIDL_PROFILE);
  1464. UnicodeString Result = TPath::Combine(ProfilePath, OpensshFolderName);
  1465. return Result;
  1466. }
  1467. //---------------------------------------------------------------------
  1468. TStoredSessionList * __fastcall TConfiguration::SelectKnownHostsSessionsForImport(
  1469. TStoredSessionList * Sessions, UnicodeString & Error)
  1470. {
  1471. std::unique_ptr<TStoredSessionList> ImportSessionList(CreateSessionsForImport(Sessions));
  1472. UnicodeString KnownHostsFile = TPath::Combine(GetOpensshFolder(), L"known_hosts");
  1473. try
  1474. {
  1475. if (FileExists(ApiPath(KnownHostsFile)))
  1476. {
  1477. std::unique_ptr<TStrings> Lines(new TStringList());
  1478. LoadScriptFromFile(KnownHostsFile, Lines.get(), true);
  1479. ImportSessionList->ImportFromKnownHosts(Lines.get());
  1480. }
  1481. else
  1482. {
  1483. throw Exception(LoadStr(KNOWN_HOSTS_NOT_FOUND));
  1484. }
  1485. }
  1486. catch (Exception & E)
  1487. {
  1488. Error = FORMAT(L"%s\n(%s)", (E.Message, KnownHostsFile));
  1489. }
  1490. return ImportSessionList.release();
  1491. }
  1492. //---------------------------------------------------------------------
  1493. TStoredSessionList * __fastcall TConfiguration::SelectKnownHostsSessionsForImport(
  1494. TStrings * Lines, TStoredSessionList * Sessions, UnicodeString & Error)
  1495. {
  1496. std::unique_ptr<TStoredSessionList> ImportSessionList(CreateSessionsForImport(Sessions));
  1497. try
  1498. {
  1499. ImportSessionList->ImportFromKnownHosts(Lines);
  1500. }
  1501. catch (Exception & E)
  1502. {
  1503. Error = E.Message;
  1504. }
  1505. return ImportSessionList.release();
  1506. }
  1507. //---------------------------------------------------------------------------
  1508. TStoredSessionList * TConfiguration::SelectOpensshSessionsForImport(
  1509. TStoredSessionList * Sessions, UnicodeString & Error)
  1510. {
  1511. std::unique_ptr<TStoredSessionList> ImportSessionList(CreateSessionsForImport(Sessions));
  1512. UnicodeString ConfigFile = TPath::Combine(GetOpensshFolder(), L"config");
  1513. try
  1514. {
  1515. if (FileExists(ApiPath(ConfigFile)))
  1516. {
  1517. std::unique_ptr<TStrings> Lines(new TStringList());
  1518. LoadScriptFromFile(ConfigFile, Lines.get(), true);
  1519. ImportSessionList->ImportFromOpenssh(Lines.get());
  1520. if (ImportSessionList->Count > 0)
  1521. {
  1522. ImportSessionList->SelectSessionsToImport(Sessions, true);
  1523. }
  1524. else
  1525. {
  1526. throw Exception(LoadStr(OPENSSH_CONFIG_NO_SITES));
  1527. }
  1528. }
  1529. else
  1530. {
  1531. throw Exception(LoadStr(OPENSSH_CONFIG_NOT_FOUND));
  1532. }
  1533. }
  1534. catch (Exception & E)
  1535. {
  1536. Error = FORMAT(L"%s\n(%s)", (E.Message, ConfigFile));
  1537. }
  1538. return ImportSessionList.release();
  1539. }
  1540. //---------------------------------------------------------------------------
  1541. void __fastcall TConfiguration::SetRandomSeedFile(UnicodeString value)
  1542. {
  1543. if (RandomSeedFile != value)
  1544. {
  1545. UnicodeString PrevRandomSeedFileName = RandomSeedFileName;
  1546. FRandomSeedFile = value;
  1547. // never allow empty seed file to avoid Putty trying to reinitialize the path
  1548. if (RandomSeedFileName.IsEmpty())
  1549. {
  1550. FRandomSeedFile = FDefaultRandomSeedFile;
  1551. }
  1552. if (!PrevRandomSeedFileName.IsEmpty() &&
  1553. (PrevRandomSeedFileName != RandomSeedFileName) &&
  1554. FileExists(ApiPath(PrevRandomSeedFileName)))
  1555. {
  1556. // ignore any error
  1557. DeleteFile(ApiPath(PrevRandomSeedFileName));
  1558. }
  1559. }
  1560. }
  1561. //---------------------------------------------------------------------------
  1562. UnicodeString __fastcall TConfiguration::GetDirectoryStatisticsCacheKey(
  1563. const UnicodeString & SessionKey, const UnicodeString & Path, const TCopyParamType & CopyParam)
  1564. {
  1565. std::unique_ptr<TStringList> RawOptions(new TStringList());
  1566. RawOptions->Add(SessionKey);
  1567. RawOptions->Add(UnixExcludeTrailingBackslash(Path));
  1568. TCopyParamType Defaults;
  1569. TCopyParamType FilterCopyParam;
  1570. FilterCopyParam.IncludeFileMask = CopyParam.IncludeFileMask;
  1571. FilterCopyParam.ExcludeHiddenFiles = CopyParam.ExcludeHiddenFiles;
  1572. FilterCopyParam.ExcludeEmptyDirectories = CopyParam.ExcludeEmptyDirectories;
  1573. std::unique_ptr<TOptionsStorage> OptionsStorage(new TOptionsStorage(RawOptions.get(), true));
  1574. FilterCopyParam.Save(OptionsStorage.get(), &Defaults);
  1575. UTF8String RawOptionsBuf(RawOptions->CommaText.LowerCase());
  1576. UnicodeString Result = Sha256(RawOptionsBuf.c_str(), RawOptionsBuf.Length());
  1577. return Result;
  1578. }
  1579. //---------------------------------------------------------------------------
  1580. THierarchicalStorage * TConfiguration::OpenDirectoryStatisticsCache(bool CanCreate)
  1581. {
  1582. std::unique_ptr<THierarchicalStorage> Storage(Configuration->CreateConfigStorage());
  1583. Storage->AccessMode = CanCreate ? smReadWrite : smRead;
  1584. if (!Storage->OpenSubKey(DirectoryStatisticsCacheKey, CanCreate))
  1585. {
  1586. Storage.reset(NULL);
  1587. }
  1588. return Storage.release();
  1589. }
  1590. //---------------------------------------------------------------------------
  1591. TStrings * __fastcall TConfiguration::LoadDirectoryStatisticsCache(
  1592. const UnicodeString & SessionKey, const UnicodeString & Path, const TCopyParamType & CopyParam)
  1593. {
  1594. std::unique_ptr<THierarchicalStorage> Storage(OpenDirectoryStatisticsCache(false));
  1595. std::unique_ptr<TStringList> Result(new TStringList());
  1596. if (Storage.get() != NULL)
  1597. {
  1598. UnicodeString Key = GetDirectoryStatisticsCacheKey(SessionKey, Path, CopyParam);
  1599. UnicodeString Buf = Storage->ReadString(Key, UnicodeString());
  1600. Result->CommaText = Buf;
  1601. }
  1602. return Result.release();
  1603. }
  1604. //---------------------------------------------------------------------------
  1605. void __fastcall TConfiguration::SaveDirectoryStatisticsCache(
  1606. const UnicodeString & SessionKey, const UnicodeString & Path, const TCopyParamType & CopyParam, TStrings * DataList)
  1607. {
  1608. std::unique_ptr<THierarchicalStorage> Storage(OpenDirectoryStatisticsCache(true));
  1609. if (Storage.get() != NULL)
  1610. {
  1611. UnicodeString Key = GetDirectoryStatisticsCacheKey(SessionKey, Path, CopyParam);
  1612. UnicodeString Buf = DataList->CommaText;
  1613. Storage->WriteString(Key, Buf);
  1614. }
  1615. }
  1616. //---------------------------------------------------------------------
  1617. UnicodeString __fastcall TConfiguration::GetRandomSeedFileName()
  1618. {
  1619. // StripPathQuotes should not be needed as we do not feed quotes anymore
  1620. return StripPathQuotes(ExpandEnvironmentVariables(FRandomSeedFile)).Trim();
  1621. }
  1622. //---------------------------------------------------------------------
  1623. void __fastcall TConfiguration::SetExternalIpAddress(UnicodeString value)
  1624. {
  1625. SET_CONFIG_PROPERTY(ExternalIpAddress);
  1626. }
  1627. //---------------------------------------------------------------------
  1628. bool TConfiguration::HasLocalPortNumberLimits()
  1629. {
  1630. return (LocalPortNumberMin > 0) && (LocalPortNumberMax >= LocalPortNumberMin);
  1631. }
  1632. //---------------------------------------------------------------------
  1633. void TConfiguration::SetLocalPortNumberMin(int value)
  1634. {
  1635. SET_CONFIG_PROPERTY(LocalPortNumberMin);
  1636. }
  1637. //---------------------------------------------------------------------
  1638. void TConfiguration::SetLocalPortNumberMax(int value)
  1639. {
  1640. SET_CONFIG_PROPERTY(LocalPortNumberMax);
  1641. }
  1642. //---------------------------------------------------------------------
  1643. void __fastcall TConfiguration::SetMimeTypes(UnicodeString value)
  1644. {
  1645. SET_CONFIG_PROPERTY(MimeTypes);
  1646. }
  1647. //---------------------------------------------------------------------
  1648. void TConfiguration::SetCertificateStorage(const UnicodeString & value)
  1649. {
  1650. SET_CONFIG_PROPERTY(CertificateStorage);
  1651. }
  1652. //---------------------------------------------------------------------
  1653. UnicodeString TConfiguration::GetCertificateStorageExpanded()
  1654. {
  1655. UnicodeString Result = FCertificateStorage;
  1656. if (Result.IsEmpty())
  1657. {
  1658. UnicodeString DefaultCertificateStorage = TPath::Combine(ExtractFilePath(ModuleFileName()), L"cacert.pem");
  1659. if (FileExists(DefaultCertificateStorage))
  1660. {
  1661. Result = DefaultCertificateStorage;
  1662. }
  1663. }
  1664. return Result;
  1665. }
  1666. //---------------------------------------------------------------------
  1667. void __fastcall TConfiguration::SetTryFtpWhenSshFails(bool value)
  1668. {
  1669. SET_CONFIG_PROPERTY(TryFtpWhenSshFails);
  1670. }
  1671. //---------------------------------------------------------------------
  1672. void __fastcall TConfiguration::SetParallelDurationThreshold(int value)
  1673. {
  1674. SET_CONFIG_PROPERTY(ParallelDurationThreshold);
  1675. }
  1676. //---------------------------------------------------------------------
  1677. void __fastcall TConfiguration::SetPuttyRegistryStorageKey(UnicodeString value)
  1678. {
  1679. SET_CONFIG_PROPERTY(PuttyRegistryStorageKey);
  1680. }
  1681. //---------------------------------------------------------------------------
  1682. TEOLType __fastcall TConfiguration::GetLocalEOLType()
  1683. {
  1684. return eolCRLF;
  1685. }
  1686. //---------------------------------------------------------------------
  1687. bool __fastcall TConfiguration::GetCollectUsage()
  1688. {
  1689. return FUsage->Collect;
  1690. }
  1691. //---------------------------------------------------------------------
  1692. void __fastcall TConfiguration::SetCollectUsage(bool value)
  1693. {
  1694. FUsage->Collect = value;
  1695. }
  1696. //---------------------------------------------------------------------
  1697. void __fastcall TConfiguration::TemporaryLogging(const UnicodeString ALogFileName)
  1698. {
  1699. if (SameText(ExtractFileExt(ALogFileName), L".xml"))
  1700. {
  1701. TemporaryActionsLogging(ALogFileName);
  1702. }
  1703. else
  1704. {
  1705. FLogging = true;
  1706. FLogFileName = ALogFileName;
  1707. UpdateActualLogProtocol();
  1708. }
  1709. }
  1710. //---------------------------------------------------------------------
  1711. void __fastcall TConfiguration::TemporaryActionsLogging(const UnicodeString ALogFileName)
  1712. {
  1713. FLogActions = true;
  1714. FActionsLogFileName = ALogFileName;
  1715. }
  1716. //---------------------------------------------------------------------
  1717. void __fastcall TConfiguration::TemporaryLogProtocol(int ALogProtocol)
  1718. {
  1719. FLogProtocol = ALogProtocol;
  1720. UpdateActualLogProtocol();
  1721. }
  1722. //---------------------------------------------------------------------
  1723. void __fastcall TConfiguration::TemporaryLogSensitive(bool ALogSensitive)
  1724. {
  1725. FLogSensitive = ALogSensitive;
  1726. }
  1727. //---------------------------------------------------------------------
  1728. void __fastcall TConfiguration::TemporaryLogMaxSize(__int64 ALogMaxSize)
  1729. {
  1730. FLogMaxSize = ALogMaxSize;
  1731. }
  1732. //---------------------------------------------------------------------
  1733. void __fastcall TConfiguration::TemporaryLogMaxCount(int ALogMaxCount)
  1734. {
  1735. FLogMaxCount = ALogMaxCount;
  1736. }
  1737. //---------------------------------------------------------------------
  1738. void __fastcall TConfiguration::SetLogging(bool value)
  1739. {
  1740. TGuard Guard(FCriticalSection);
  1741. if (Logging != value)
  1742. {
  1743. FPermanentLogging = value;
  1744. FLogging = value;
  1745. UpdateActualLogProtocol();
  1746. Changed();
  1747. }
  1748. }
  1749. //---------------------------------------------------------------------
  1750. bool __fastcall TConfiguration::GetLogging()
  1751. {
  1752. TGuard Guard(FCriticalSection);
  1753. return FPermanentLogging;
  1754. }
  1755. //---------------------------------------------------------------------
  1756. void __fastcall TConfiguration::SetLogFileName(UnicodeString value)
  1757. {
  1758. TGuard Guard(FCriticalSection);
  1759. if (LogFileName != value)
  1760. {
  1761. FPermanentLogFileName = value;
  1762. FLogFileName = value;
  1763. Changed();
  1764. }
  1765. }
  1766. //---------------------------------------------------------------------
  1767. UnicodeString __fastcall TConfiguration::GetLogFileName()
  1768. {
  1769. TGuard Guard(FCriticalSection);
  1770. return FPermanentLogFileName;
  1771. }
  1772. //---------------------------------------------------------------------
  1773. void __fastcall TConfiguration::SetActionsLogFileName(UnicodeString value)
  1774. {
  1775. TGuard Guard(FCriticalSection);
  1776. if (ActionsLogFileName != value)
  1777. {
  1778. FPermanentActionsLogFileName = value;
  1779. FActionsLogFileName = value;
  1780. Changed();
  1781. }
  1782. }
  1783. //---------------------------------------------------------------------
  1784. UnicodeString __fastcall TConfiguration::GetPermanentActionsLogFileName()
  1785. {
  1786. TGuard Guard(FCriticalSection);
  1787. return FPermanentActionsLogFileName;
  1788. }
  1789. //---------------------------------------------------------------------
  1790. UnicodeString __fastcall TConfiguration::GetActionsLogFileName()
  1791. {
  1792. TGuard Guard(FCriticalSection);
  1793. return FActionsLogFileName;
  1794. }
  1795. //---------------------------------------------------------------------
  1796. bool __fastcall TConfiguration::GetLogToFile()
  1797. {
  1798. // guarded within GetLogFileName
  1799. return !LogFileName.IsEmpty();
  1800. }
  1801. //---------------------------------------------------------------------
  1802. void __fastcall TConfiguration::UpdateActualLogProtocol()
  1803. {
  1804. FActualLogProtocol = FLogging ? FLogProtocol : (-BelowNormalLogLevels - 1);
  1805. }
  1806. //---------------------------------------------------------------------
  1807. void __fastcall TConfiguration::SetLogProtocol(int value)
  1808. {
  1809. TGuard Guard(FCriticalSection);
  1810. if (LogProtocol != value)
  1811. {
  1812. FPermanentLogProtocol = value;
  1813. FLogProtocol = value;
  1814. Changed();
  1815. UpdateActualLogProtocol();
  1816. }
  1817. }
  1818. //---------------------------------------------------------------------
  1819. void __fastcall TConfiguration::SetLogActions(bool value)
  1820. {
  1821. TGuard Guard(FCriticalSection);
  1822. if (LogActions != value)
  1823. {
  1824. FPermanentLogActions = value;
  1825. FLogActions = value;
  1826. Changed();
  1827. }
  1828. }
  1829. //---------------------------------------------------------------------
  1830. bool __fastcall TConfiguration::GetLogActions()
  1831. {
  1832. TGuard Guard(FCriticalSection);
  1833. return FPermanentLogActions;
  1834. }
  1835. //---------------------------------------------------------------------
  1836. void __fastcall TConfiguration::SetLogFileAppend(bool value)
  1837. {
  1838. SET_CONFIG_PROPERTY(LogFileAppend);
  1839. }
  1840. //---------------------------------------------------------------------
  1841. void __fastcall TConfiguration::SetLogSensitive(bool value)
  1842. {
  1843. if (LogSensitive != value)
  1844. {
  1845. FPermanentLogSensitive = value;
  1846. FLogSensitive = value;
  1847. Changed();
  1848. }
  1849. }
  1850. //---------------------------------------------------------------------
  1851. void __fastcall TConfiguration::SetLogMaxSize(__int64 value)
  1852. {
  1853. TGuard Guard(FCriticalSection);
  1854. if (LogMaxSize != value)
  1855. {
  1856. FPermanentLogMaxSize = value;
  1857. FLogMaxSize = value;
  1858. Changed();
  1859. }
  1860. }
  1861. //---------------------------------------------------------------------
  1862. __int64 __fastcall TConfiguration::GetLogMaxSize()
  1863. {
  1864. TGuard Guard(FCriticalSection);
  1865. return FPermanentLogMaxSize;
  1866. }
  1867. //---------------------------------------------------------------------
  1868. void __fastcall TConfiguration::SetLogMaxCount(int value)
  1869. {
  1870. if (LogMaxCount != value)
  1871. {
  1872. FPermanentLogMaxCount = value;
  1873. FLogMaxCount = value;
  1874. Changed();
  1875. }
  1876. }
  1877. //---------------------------------------------------------------------
  1878. int __fastcall TConfiguration::GetLogMaxCount()
  1879. {
  1880. TGuard Guard(FCriticalSection);
  1881. return FPermanentLogMaxCount;
  1882. }
  1883. //---------------------------------------------------------------------
  1884. UnicodeString __fastcall TConfiguration::GetDefaultLogFileName()
  1885. {
  1886. return L"%TEMP%\\!S.log";
  1887. }
  1888. //---------------------------------------------------------------------------
  1889. void __fastcall TConfiguration::SetConfirmOverwriting(bool value)
  1890. {
  1891. TGuard Guard(FCriticalSection);
  1892. SET_CONFIG_PROPERTY(ConfirmOverwriting);
  1893. }
  1894. //---------------------------------------------------------------------------
  1895. bool __fastcall TConfiguration::GetConfirmOverwriting()
  1896. {
  1897. TGuard Guard(FCriticalSection);
  1898. return FConfirmOverwriting;
  1899. }
  1900. //---------------------------------------------------------------------------
  1901. void __fastcall TConfiguration::SetConfirmResume(bool value)
  1902. {
  1903. TGuard Guard(FCriticalSection);
  1904. SET_CONFIG_PROPERTY(ConfirmResume);
  1905. }
  1906. //---------------------------------------------------------------------------
  1907. bool __fastcall TConfiguration::GetConfirmResume()
  1908. {
  1909. TGuard Guard(FCriticalSection);
  1910. return FConfirmResume;
  1911. }
  1912. //---------------------------------------------------------------------------
  1913. void __fastcall TConfiguration::SetAutoReadDirectoryAfterOp(bool value)
  1914. {
  1915. TGuard Guard(FCriticalSection);
  1916. SET_CONFIG_PROPERTY(AutoReadDirectoryAfterOp);
  1917. }
  1918. //---------------------------------------------------------------------------
  1919. bool __fastcall TConfiguration::GetAutoReadDirectoryAfterOp()
  1920. {
  1921. TGuard Guard(FCriticalSection);
  1922. return FAutoReadDirectoryAfterOp;
  1923. }
  1924. //---------------------------------------------------------------------------
  1925. UnicodeString __fastcall TConfiguration::GetTimeFormat()
  1926. {
  1927. return L"h:nn:ss";
  1928. }
  1929. //---------------------------------------------------------------------------
  1930. UnicodeString __fastcall TConfiguration::GetDefaultKeyFile()
  1931. {
  1932. return L"";
  1933. }
  1934. //---------------------------------------------------------------------------
  1935. bool __fastcall TConfiguration::GetRememberPassword()
  1936. {
  1937. return false;
  1938. }
  1939. //---------------------------------------------------------------------------
  1940. void __fastcall TConfiguration::SetSessionReopenAuto(int value)
  1941. {
  1942. SET_CONFIG_PROPERTY(SessionReopenAuto);
  1943. }
  1944. //---------------------------------------------------------------------------
  1945. void __fastcall TConfiguration::SetSessionReopenBackground(int value)
  1946. {
  1947. SET_CONFIG_PROPERTY(SessionReopenBackground);
  1948. }
  1949. //---------------------------------------------------------------------------
  1950. void __fastcall TConfiguration::SetSessionReopenTimeout(int value)
  1951. {
  1952. SET_CONFIG_PROPERTY(SessionReopenTimeout);
  1953. }
  1954. //---------------------------------------------------------------------------
  1955. void __fastcall TConfiguration::SetSessionReopenAutoStall(int value)
  1956. {
  1957. SET_CONFIG_PROPERTY(SessionReopenAutoStall);
  1958. }
  1959. //---------------------------------------------------------------------------
  1960. void __fastcall TConfiguration::SetTunnelLocalPortNumberLow(int value)
  1961. {
  1962. SET_CONFIG_PROPERTY(TunnelLocalPortNumberLow);
  1963. }
  1964. //---------------------------------------------------------------------------
  1965. void __fastcall TConfiguration::SetTunnelLocalPortNumberHigh(int value)
  1966. {
  1967. SET_CONFIG_PROPERTY(TunnelLocalPortNumberHigh);
  1968. }
  1969. //---------------------------------------------------------------------------
  1970. void __fastcall TConfiguration::SetCacheDirectoryChangesMaxSize(int value)
  1971. {
  1972. SET_CONFIG_PROPERTY(CacheDirectoryChangesMaxSize);
  1973. }
  1974. //---------------------------------------------------------------------------
  1975. void __fastcall TConfiguration::SetShowFtpWelcomeMessage(bool value)
  1976. {
  1977. SET_CONFIG_PROPERTY(ShowFtpWelcomeMessage);
  1978. }
  1979. //---------------------------------------------------------------------------
  1980. void TConfiguration::SetQueueTransfersLimit(int value)
  1981. {
  1982. SET_CONFIG_PROPERTY(QueueTransfersLimit);
  1983. }
  1984. //---------------------------------------------------------------------------
  1985. bool __fastcall TConfiguration::GetPersistent()
  1986. {
  1987. return (Storage != stNul) && !FDontSave;
  1988. }
  1989. //---------------------------------------------------------------------------
  1990. //---------------------------------------------------------------------------
  1991. void __fastcall TShortCuts::Add(TShortCut ShortCut)
  1992. {
  1993. FShortCuts.insert(ShortCut);
  1994. }
  1995. //---------------------------------------------------------------------------
  1996. bool __fastcall TShortCuts::Has(TShortCut ShortCut) const
  1997. {
  1998. return (FShortCuts.count(ShortCut) != 0);
  1999. }