Configuration.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include <shlobj.hpp>
  5. #include <FileInfo.h>
  6. #include "Exceptions.h"
  7. #include "Common.h"
  8. #include "Configuration.h"
  9. #include "PuttyIntf.h"
  10. #include "TextsCore.h"
  11. #include "Interface.h"
  12. //---------------------------------------------------------------------------
  13. #pragma package(smart_init)
  14. //---------------------------------------------------------------------------
  15. const char CustomCommandFileNamePattern[] = "!";
  16. //---------------------------------------------------------------------------
  17. bool SpecialFolderLocation(int PathID, AnsiString & Path)
  18. {
  19. LPITEMIDLIST Pidl;
  20. char Buf[256];
  21. if (SHGetSpecialFolderLocation(NULL, PathID, &Pidl) == NO_ERROR &&
  22. SHGetPathFromIDList(Pidl, Buf))
  23. {
  24. Path = AnsiString(Buf);
  25. return true;
  26. }
  27. return false;
  28. }
  29. //---------------------------------------------------------------------------
  30. __fastcall TConfiguration::TConfiguration()
  31. {
  32. FUpdating = 0;
  33. FStorage = stDetect;
  34. DontSave = false;
  35. RandomSeedSave = true;
  36. FApplicationInfo = NULL;
  37. }
  38. //---------------------------------------------------------------------------
  39. void __fastcall TConfiguration::Default()
  40. {
  41. AnsiString ARandomSeedFile = RandomSeedFile;
  42. // This works correct only when Default() is called before first
  43. // change to RandomSeedFile property
  44. RandomSeedFile = StringReplace(ExtractFilePath(ARandomSeedFile) +
  45. "winscp" + ExtractFileExt(ARandomSeedFile), "\\\\", "\\",
  46. TReplaceFlags() << rfReplaceAll);
  47. FIgnoreCancelBeforeFinish = TDateTime(0, 0, 3, 0);
  48. FConfirmOverwriting = true;
  49. FDefaultDirIsHome = true;
  50. FCopyParam.Default();
  51. FLogging = false;
  52. FLogFileName = "";
  53. FLogFileAppend = true;
  54. FLogWindowLines = 100;
  55. FDisablePasswordStoring = false;
  56. Changed();
  57. }
  58. //---------------------------------------------------------------------------
  59. __fastcall TConfiguration::~TConfiguration()
  60. {
  61. assert(!FUpdating);
  62. if (RandomSeedSave) random_save_seed();
  63. if (FApplicationInfo) FreeFileInfo(FApplicationInfo);
  64. }
  65. //---------------------------------------------------------------------------
  66. THierarchicalStorage * TConfiguration::CreateScpStorage(bool /*SessionList*/)
  67. {
  68. if (Storage == stRegistry)
  69. {
  70. return new TRegistryStorage(RegistryStorageKey);
  71. }
  72. else
  73. {
  74. return new TIniFileStorage(IniFileStorageName);
  75. }
  76. }
  77. //---------------------------------------------------------------------------
  78. #define LASTELEM(ELEM) \
  79. ELEM.SubString(ELEM.LastDelimiter(".>")+1, ELEM.Length() - ELEM.LastDelimiter(".>"))
  80. #define BLOCK(KEY, CANCREATE, BLOCK) \
  81. if (Storage->OpenSubKey(KEY, CANCREATE)) try { BLOCK } __finally { Storage->CloseSubKey(); }
  82. #define REGCONFIG(ACCESS, CANCREATE, ADDON) \
  83. THierarchicalStorage * Storage = CreateScpStorage(false); \
  84. try { \
  85. Storage->AccessMode = ACCESS; \
  86. if (Storage->OpenSubKey(ConfigurationSubKey, CANCREATE)) { \
  87. BLOCK("Interface", CANCREATE, \
  88. KEY(Bool, DefaultDirIsHome); \
  89. KEY(String, RandomSeedFile); \
  90. KEY(DateTime, IgnoreCancelBeforeFinish); \
  91. KEY(Bool, ConfirmOverwriting); \
  92. ); \
  93. BLOCK("Interface\\CopyParam", CANCREATE, \
  94. KEY(Bool, CopyParam.AddXToDirectories); \
  95. KEY(String, CopyParam.AsciiFileMask.Masks); \
  96. KEY(Integer, CopyParam.FileNameCase); \
  97. KEY(Bool, CopyParam.PreserveReadOnly); \
  98. KEY(Bool, CopyParam.PreserveTime); \
  99. KEY(Bool, CopyParam.PreserveRights); \
  100. KEY(String, CopyParam.Rights.Text); \
  101. KEY(Integer, CopyParam.TransferMode); \
  102. KEY(Integer, CopyParam.ResumeSupport); \
  103. KEY(Int64, CopyParam.ResumeThreshold); \
  104. KEY(Bool, CopyParam.ReplaceInvalidChars); \
  105. KEY(String, CopyParam.LocalInvalidChars); \
  106. ); \
  107. BLOCK("Logging", CANCREATE, \
  108. KEY(Bool, Logging); \
  109. KEY(String, LogFileName); \
  110. KEY(Bool, LogFileAppend); \
  111. KEY(Integer, LogWindowLines); \
  112. ); \
  113. ADDON(Storage); \
  114. }; \
  115. } __finally { \
  116. delete Storage; \
  117. }
  118. //---------------------------------------------------------------------------
  119. void __fastcall TConfiguration::SaveSpecial(THierarchicalStorage * /*Storage*/)
  120. {
  121. }
  122. //---------------------------------------------------------------------------
  123. void __fastcall TConfiguration::Save()
  124. {
  125. if (DontSave) return;
  126. if (Storage == stRegistry) CleanupIniFile();
  127. #define KEY(TYPE, VAR) Storage->Write ## TYPE(LASTELEM(AnsiString(#VAR)), VAR)
  128. REGCONFIG(smReadWrite, true, SaveSpecial);
  129. #undef KEY
  130. }
  131. //---------------------------------------------------------------------------
  132. void __fastcall TConfiguration::LoadSpecial(THierarchicalStorage * /*Storage*/)
  133. {
  134. }
  135. //---------------------------------------------------------------------------
  136. void __fastcall TConfiguration::LoadAdmin(THierarchicalStorage * Storage)
  137. {
  138. FDisablePasswordStoring = Storage->ReadBool("DisablePasswordStoring", FDisablePasswordStoring);
  139. }
  140. //---------------------------------------------------------------------------
  141. void __fastcall TConfiguration::Load()
  142. {
  143. #define KEY(TYPE, VAR) VAR = Storage->Read ## TYPE(LASTELEM(AnsiString(#VAR)), VAR)
  144. #pragma warn -eas
  145. REGCONFIG(smRead, false, LoadSpecial);
  146. #pragma warn +eas
  147. #undef KEY
  148. TRegistryStorage * AdminStorage;
  149. AdminStorage = new TRegistryStorage(RegistryStorageKey, HKEY_LOCAL_MACHINE);
  150. try
  151. {
  152. if (AdminStorage->OpenRootKey(false))
  153. {
  154. LoadAdmin(AdminStorage);
  155. AdminStorage->CloseSubKey();
  156. }
  157. }
  158. __finally
  159. {
  160. delete AdminStorage;
  161. }
  162. }
  163. //---------------------------------------------------------------------------
  164. void __fastcall TConfiguration::Changed()
  165. {
  166. if (FUpdating == 0)
  167. {
  168. if (OnChange)
  169. {
  170. OnChange(this);
  171. }
  172. }
  173. else
  174. {
  175. FChanged = true;
  176. }
  177. }
  178. //---------------------------------------------------------------------------
  179. void __fastcall TConfiguration::BeginUpdate()
  180. {
  181. if (FUpdating == 0)
  182. {
  183. FChanged = false;
  184. }
  185. FUpdating++;
  186. // Greater value would probably indicate some nesting problem in code
  187. assert(FUpdating < 6);
  188. }
  189. //---------------------------------------------------------------------------
  190. void __fastcall TConfiguration::EndUpdate()
  191. {
  192. assert(FUpdating > 0);
  193. FUpdating--;
  194. if ((FUpdating == 0) && FChanged)
  195. {
  196. FChanged = false;
  197. Changed();
  198. }
  199. }
  200. //---------------------------------------------------------------------------
  201. void __fastcall TConfiguration::CleanupConfiguration()
  202. {
  203. try
  204. {
  205. CleanupRegistry(ConfigurationSubKey);
  206. if (Storage == stRegistry)
  207. {
  208. DontSave = true;
  209. }
  210. }
  211. catch (Exception &E)
  212. {
  213. throw ExtException(&E, CLEANUP_CONFIG_ERROR);
  214. }
  215. }
  216. //---------------------------------------------------------------------------
  217. void __fastcall TConfiguration::CleanupRegistry(AnsiString CleanupSubKey)
  218. {
  219. TRegistryStorage *Registry = new TRegistryStorage(RegistryStorageKey);
  220. try
  221. {
  222. Registry->RecursiveDeleteSubKey(CleanupSubKey);
  223. }
  224. __finally
  225. {
  226. delete Registry;
  227. }
  228. }
  229. //---------------------------------------------------------------------------
  230. void __fastcall TConfiguration::CleanupHostKeys()
  231. {
  232. try
  233. {
  234. CleanupRegistry(SshHostKeysSubKey);
  235. }
  236. catch (Exception &E)
  237. {
  238. throw ExtException(&E, CLEANUP_HOSTKEYS_ERROR);
  239. }
  240. }
  241. //---------------------------------------------------------------------------
  242. void __fastcall TConfiguration::CleanupRandomSeedFile()
  243. {
  244. try
  245. {
  246. RandomSeedSave = false;
  247. if (FileExists(RandomSeedFile))
  248. {
  249. if (!DeleteFile(RandomSeedFile)) Abort();
  250. }
  251. }
  252. catch (Exception &E)
  253. {
  254. throw ExtException(&E, CLEANUP_SEEDFILE_ERROR);
  255. }
  256. }
  257. //---------------------------------------------------------------------------
  258. void __fastcall TConfiguration::CleanupIniFile()
  259. {
  260. try
  261. {
  262. if (FileExists(IniFileStorageName))
  263. {
  264. if (!DeleteFile(IniFileStorageName)) Abort();
  265. }
  266. if (Storage == stIniFile)
  267. {
  268. DontSave = true;
  269. }
  270. }
  271. catch (Exception &E)
  272. {
  273. throw ExtException(&E, CLEANUP_INIFILE_ERROR);
  274. }
  275. }
  276. //---------------------------------------------------------------------------
  277. TVSFixedFileInfo *__fastcall TConfiguration::GetFixedApplicationInfo()
  278. {
  279. return GetFixedFileInfo(ApplicationInfo);
  280. }
  281. //---------------------------------------------------------------------------
  282. AnsiString __fastcall TConfiguration::ModuleFileName()
  283. {
  284. return ParamStr(0);
  285. }
  286. //---------------------------------------------------------------------------
  287. void * __fastcall TConfiguration::GetApplicationInfo()
  288. {
  289. if (!FApplicationInfo)
  290. {
  291. FApplicationInfo = CreateFileInfo(ModuleFileName());
  292. }
  293. return FApplicationInfo;
  294. }
  295. //---------------------------------------------------------------------------
  296. AnsiString __fastcall TConfiguration::GetProductVersion()
  297. {
  298. return TrimVersion(FileInfoString["ProductVersion"]);
  299. }
  300. //---------------------------------------------------------------------------
  301. AnsiString __fastcall TConfiguration::TrimVersion(AnsiString Version)
  302. {
  303. while (Version.SubString(Version.Length() - 1, 2) == ".0")
  304. {
  305. Version.SetLength(Version.Length() - 2);
  306. }
  307. return Version;
  308. }
  309. //---------------------------------------------------------------------------
  310. AnsiString __fastcall TConfiguration::GetVersionStr()
  311. {
  312. try
  313. {
  314. return FmtLoadStr(VERSION, ARRAYOFCONST((
  315. HIWORD(FixedApplicationInfo->dwFileVersionMS),
  316. LOWORD(FixedApplicationInfo->dwFileVersionMS),
  317. HIWORD(FixedApplicationInfo->dwFileVersionLS),
  318. LOWORD(FixedApplicationInfo->dwFileVersionLS))));
  319. }
  320. catch (Exception &E)
  321. {
  322. throw ExtException(&E, "Can't get application version");
  323. }
  324. }
  325. //---------------------------------------------------------------------------
  326. AnsiString __fastcall TConfiguration::GetVersion()
  327. {
  328. try
  329. {
  330. AnsiString Result;
  331. Result = TrimVersion(FORMAT("%d.%d.%d.%d", (HIWORD(FixedApplicationInfo->dwFileVersionMS),
  332. LOWORD(FixedApplicationInfo->dwFileVersionMS),
  333. HIWORD(FixedApplicationInfo->dwFileVersionLS),
  334. LOWORD(FixedApplicationInfo->dwFileVersionLS))));
  335. return Result;
  336. }
  337. catch (Exception &E)
  338. {
  339. throw ExtException(&E, "Can't get application version");
  340. }
  341. }
  342. //---------------------------------------------------------------------------
  343. AnsiString __fastcall TConfiguration::GetFileInfoString(const AnsiString Key)
  344. {
  345. AnsiString Result;
  346. if (GetTranslationCount(ApplicationInfo) > 0)
  347. {
  348. TTranslation Translation;
  349. Translation = GetTranslation(ApplicationInfo, 0);
  350. Result = ::GetFileInfoString(ApplicationInfo,
  351. Translation, Key);
  352. PackStr(Result);
  353. }
  354. else
  355. {
  356. assert(false);
  357. }
  358. return Result;
  359. }
  360. //---------------------------------------------------------------------------
  361. AnsiString __fastcall TConfiguration::GetRegistryStorageKey()
  362. {
  363. return GetRegistryKey();
  364. }
  365. //---------------------------------------------------------------------------
  366. void __fastcall TConfiguration::SetIniFileStorageName(AnsiString value)
  367. {
  368. if (!value.IsEmpty() && !FileExists(value))
  369. {
  370. throw Exception(FMTLOAD(FILE_NOT_EXISTS, (value)));
  371. }
  372. FIniFileStorageName = value;
  373. FStorage = stIniFile;
  374. }
  375. //---------------------------------------------------------------------------
  376. AnsiString __fastcall TConfiguration::GetIniFileStorageName()
  377. {
  378. if (FIniFileStorageName.IsEmpty())
  379. {
  380. return ChangeFileExt(ParamStr(0), ".ini");
  381. }
  382. else
  383. {
  384. return FIniFileStorageName;
  385. }
  386. }
  387. //---------------------------------------------------------------------------
  388. AnsiString __fastcall TConfiguration::GetPuttyRegistryStorageKey()
  389. {
  390. return PUTTY_REG_POS;
  391. }
  392. //---------------------------------------------------------------------------
  393. AnsiString __fastcall TConfiguration::GetPuttySessionsKey()
  394. {
  395. return PuttyRegistryStorageKey + "\\Sessions";
  396. }
  397. //---------------------------------------------------------------------------
  398. AnsiString __fastcall TConfiguration::GetStoredSessionsSubKey()
  399. {
  400. return "Sessions";
  401. }
  402. //---------------------------------------------------------------------------
  403. AnsiString __fastcall TConfiguration::GetSshHostKeysSubKey()
  404. {
  405. return "SshHostKeys";
  406. }
  407. //---------------------------------------------------------------------------
  408. AnsiString __fastcall TConfiguration::GetConfigurationSubKey()
  409. {
  410. return "Configuration";
  411. }
  412. //---------------------------------------------------------------------------
  413. AnsiString __fastcall TConfiguration::GetRootKeyStr()
  414. {
  415. return RootKeyToStr(HKEY_CURRENT_USER);
  416. }
  417. //---------------------------------------------------------------------------
  418. void __fastcall TConfiguration::SetStorage(TStorage value)
  419. {
  420. if (FStorage != value)
  421. {
  422. FStorage = value;
  423. ModifyAll();
  424. Save();
  425. }
  426. }
  427. //---------------------------------------------------------------------------
  428. void __fastcall TConfiguration::ModifyAll()
  429. {
  430. // nothing
  431. }
  432. //---------------------------------------------------------------------------
  433. TStorage __fastcall TConfiguration::GetStorage()
  434. {
  435. if (FStorage == stDetect)
  436. {
  437. FStorage = FileExists(IniFileStorageName) ? stIniFile : stRegistry;
  438. }
  439. return FStorage;
  440. }
  441. //---------------------------------------------------------------------------
  442. void __fastcall TConfiguration::SetRandomSeedFile(AnsiString value)
  443. {
  444. char *seedpath = seedpath_ptr();
  445. if (value.Length() > seedpath_size())
  446. {
  447. value.SetLength(seedpath_size());
  448. }
  449. strcpy(seedpath, StripPathQuotes(value).c_str());
  450. }
  451. //---------------------------------------------------------------------------
  452. void __fastcall TConfiguration::SetCopyParam(TCopyParamType value)
  453. {
  454. FCopyParam.Assign(value);
  455. Changed();
  456. }
  457. //---------------------------------------------------------------------------
  458. AnsiString __fastcall TConfiguration::GetRandomSeedFile()
  459. {
  460. return AnsiString(seedpath_ptr());
  461. }
  462. //---------------------------------------------------------------------------
  463. TEOLType __fastcall TConfiguration::GetLocalEOLType()
  464. {
  465. return eolCRLF;
  466. }
  467. //---------------------------------------------------------------------
  468. void __fastcall TConfiguration::SetLogging(bool value)
  469. {
  470. SET_CONFIG_PROPERTY(Logging);
  471. }
  472. //---------------------------------------------------------------------
  473. void __fastcall TConfiguration::SetLogFileName(AnsiString value)
  474. {
  475. SET_CONFIG_PROPERTY(LogFileName);
  476. }
  477. //---------------------------------------------------------------------
  478. void __fastcall TConfiguration::SetLogToFile(bool value)
  479. {
  480. if (value != LogToFile)
  481. {
  482. LogFileName = value ? DefaultLogFileName : AnsiString("");
  483. Changed();
  484. }
  485. }
  486. //---------------------------------------------------------------------
  487. bool __fastcall TConfiguration::GetLogToFile()
  488. {
  489. return !LogFileName.IsEmpty();
  490. }
  491. //---------------------------------------------------------------------
  492. void __fastcall TConfiguration::SetLogFileAppend(bool value)
  493. {
  494. SET_CONFIG_PROPERTY(LogFileAppend);
  495. }
  496. //---------------------------------------------------------------------
  497. void __fastcall TConfiguration::SetLogWindowLines(int value)
  498. {
  499. SET_CONFIG_PROPERTY(LogWindowLines);
  500. }
  501. //---------------------------------------------------------------------
  502. void __fastcall TConfiguration::SetLogWindowComplete(bool value)
  503. {
  504. if (value != LogWindowComplete)
  505. {
  506. LogWindowLines = value ? 0 : 50;
  507. Changed();
  508. }
  509. }
  510. //---------------------------------------------------------------------
  511. bool __fastcall TConfiguration::GetLogWindowComplete()
  512. {
  513. return (bool)(LogWindowLines == 0);
  514. }
  515. //---------------------------------------------------------------------
  516. AnsiString __fastcall TConfiguration::GetDefaultLogFileName()
  517. {
  518. return GetTemporaryPath() + "winscp.log";
  519. }
  520. //---------------------------------------------------------------------------
  521. void __fastcall TConfiguration::SetConfirmOverwriting(bool value)
  522. {
  523. SET_CONFIG_PROPERTY(ConfirmOverwriting);
  524. }
  525. //---------------------------------------------------------------------------
  526. bool __fastcall TConfiguration::GetConfirmOverwriting()
  527. {
  528. return FConfirmOverwriting;
  529. }
  530. //---------------------------------------------------------------------------
  531. void __fastcall TConfiguration::SetDefaultDirIsHome(bool value)
  532. {
  533. SET_CONFIG_PROPERTY(DefaultDirIsHome);
  534. }
  535. //---------------------------------------------------------------------------
  536. void __fastcall TConfiguration::SetIgnoreCancelBeforeFinish(TDateTime value)
  537. {
  538. SET_CONFIG_PROPERTY(IgnoreCancelBeforeFinish);
  539. }
  540. //---------------------------------------------------------------------------
  541. AnsiString __fastcall TConfiguration::GetTimeFormat()
  542. {
  543. return "h:nn:ss";
  544. }
  545. //---------------------------------------------------------------------------
  546. AnsiString __fastcall TConfiguration::GetPartialExt() const
  547. {
  548. return ".filepart";
  549. }
  550. //---------------------------------------------------------------------------
  551. AnsiString __fastcall TConfiguration::GetDefaultKeyFile()
  552. {
  553. return "";
  554. }