| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854 | //---------------------------------------------------------------------------#include <vcl.h>#pragma hdrstop#include <FileInfo.h>#include "Common.h"#include "Exceptions.h"#include "Configuration.h"#include "PuttyIntf.h"#include "TextsCore.h"#include "Interface.h"#include "CoreMain.h"#include "Security.h"#include "FileMasks.h"#include "CopyParam.h"#include <shlobj.h>#include <System.IOUtils.hpp>#include <System.StrUtils.hpp>//---------------------------------------------------------------------------#pragma package(smart_init)//---------------------------------------------------------------------------const wchar_t * AutoSwitchNames = L"On;Off;Auto";const wchar_t * NotAutoSwitchNames = L"Off;On;Auto";//---------------------------------------------------------------------------// See https://www.iana.org/assignments/hash-function-text-names/hash-function-text-names.xhtmlconst UnicodeString Sha1ChecksumAlg(L"sha-1");const UnicodeString Sha224ChecksumAlg(L"sha-224");const UnicodeString Sha256ChecksumAlg(L"sha-256");const UnicodeString Sha384ChecksumAlg(L"sha-384");const UnicodeString Sha512ChecksumAlg(L"sha-512");const UnicodeString Md5ChecksumAlg(L"md5");// Not defined by IANAconst UnicodeString Crc32ChecksumAlg(L"crc32");//---------------------------------------------------------------------------const UnicodeString SshFingerprintType(L"ssh");const UnicodeString TlsFingerprintType(L"tls");//---------------------------------------------------------------------------const UnicodeString FtpsCertificateStorageKey(L"FtpsCertificates");const UnicodeString HttpsCertificateStorageKey(L"HttpsCertificates");const UnicodeString LastFingerprintsStorageKey(L"LastFingerprints");//---------------------------------------------------------------------------__fastcall TConfiguration::TConfiguration(){  FCriticalSection = new TCriticalSection();  FUpdating = 0;  FStorage = stDetect;  FDontSave = false;  FForceSave = false;  FApplicationInfo = NULL;  FUsage = new TUsage(this);  FDefaultCollectUsage = false;  FScripting = false;  UnicodeString RandomSeedPath;  if (!GetEnvironmentVariable(L"APPDATA").IsEmpty())  {    RandomSeedPath = L"%APPDATA%";  }  else  {    RandomSeedPath = GetShellFolderPath(CSIDL_LOCAL_APPDATA);    if (RandomSeedPath.IsEmpty())    {      RandomSeedPath = GetShellFolderPath(CSIDL_APPDATA);    }  }  FDefaultRandomSeedFile = IncludeTrailingBackslash(RandomSeedPath) + L"winscp.rnd";}//---------------------------------------------------------------------------void __fastcall TConfiguration::Default(){  TGuard Guard(FCriticalSection);  FDisablePasswordStoring = false;  FForceBanners = false;  FDisableAcceptingHostKeys = false;  TRegistryStorage * AdminStorage;  AdminStorage = new TRegistryStorage(RegistryStorageKey, HKEY_LOCAL_MACHINE);  try  {    if (AdminStorage->OpenRootKey(false))    {      LoadAdmin(AdminStorage);      AdminStorage->CloseSubKey();    }  }  __finally  {    delete AdminStorage;  }  RandomSeedFile = FDefaultRandomSeedFile;  PuttyRegistryStorageKey = OriginalPuttyRegistryStorageKey;  FConfirmOverwriting = true;  FConfirmResume = true;  FAutoReadDirectoryAfterOp = true;  FSessionReopenAuto = 5000;  FSessionReopenBackground = 2000;  FSessionReopenTimeout = 0;  FSessionReopenAutoStall = 60000;  FTunnelLocalPortNumberLow = 50000;  FTunnelLocalPortNumberHigh = 50099;  FCacheDirectoryChangesMaxSize = 100;  FShowFtpWelcomeMessage = false;  FExternalIpAddress = L"";  FTryFtpWhenSshFails = true;  FParallelDurationThreshold = 10;  FMimeTypes = UnicodeString();  FDontReloadMoreThanSessions = 1000;  FScriptProgressFileNameLimit = 25;  CollectUsage = FDefaultCollectUsage;  FLogging = false;  FPermanentLogging = false;  FLogFileName = DefaultLogFileName;  FPermanentLogFileName = FLogFileName;  FLogFileAppend = true;  FLogSensitive = false;  FPermanentLogSensitive = FLogSensitive;  FLogMaxSize = 0;  FPermanentLogMaxSize = FLogMaxSize;  FLogMaxCount = 0;  FPermanentLogMaxCount = FLogMaxCount;  FLogProtocol = 0;  FPermanentLogProtocol = FLogProtocol;  UpdateActualLogProtocol();  FLogActions = false;  FPermanentLogActions = false;  FLogActionsRequired = false;  FActionsLogFileName = L"%TEMP%\\!S.xml";  FPermanentActionsLogFileName = FActionsLogFileName;  FProgramIniPathWrittable = -1;  FCustomIniFileStorageName = LoadCustomIniFileStorageName();  Changed();}//---------------------------------------------------------------------------__fastcall TConfiguration::~TConfiguration(){  DebugAssert(!FUpdating);  if (FApplicationInfo) FreeFileInfo(FApplicationInfo);  delete FCriticalSection;  delete FUsage;}//---------------------------------------------------------------------------void __fastcall TConfiguration::UpdateStaticUsage(){  Usage->Set(L"ConfigurationIniFile", (Storage == stIniFile));  Usage->Set(L"ConfigurationIniFileCustom", !CustomIniFileStorageName.IsEmpty());  Usage->Set("Unofficial", IsUnofficial);  // this is called from here, because we are guarded from calling into  // master password handler here, see TWinConfiguration::UpdateStaticUsage  StoredSessions->UpdateStaticUsage();}//---------------------------------------------------------------------------THierarchicalStorage * TConfiguration::CreateConfigStorage(){  bool SessionList = false;  return CreateScpStorage(SessionList);}//---------------------------------------------------------------------------THierarchicalStorage * TConfiguration::CreateScpStorage(bool & SessionList){  TGuard Guard(FCriticalSection);  THierarchicalStorage * Result;  if (Storage == stRegistry)  {    Result = new TRegistryStorage(RegistryStorageKey);  }  else if (Storage == stNul)  {    Result = TIniFileStorage::CreateFromPath(INI_NUL);  }  else  {    UnicodeString StorageName = IniFileStorageName;    Result = TIniFileStorage::CreateFromPath(StorageName);  }  if ((FOptionsStorage.get() != NULL) && (FOptionsStorage->Count > 0))  {    if (!SessionList)    {      Result = new TOptionsStorage(FOptionsStorage.get(), ConfigurationSubKey, Result);    }    else    {      // cannot reuse session list storage for configuration as for it we need      // the option-override storage above    }  }  else  {    // All the above stores can be reused for configuration,    // if no options-overrides are set    SessionList = false;  }  return Result;}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::PropertyToKey(const UnicodeString & Property){  // no longer useful  int P = Property.LastDelimiter(L".>");  return Property.SubString(P + 1, Property.Length() - P);}//---------------------------------------------------------------------------#define BLOCK(KEY, CANCREATE, BLOCK) \  if (Storage->OpenSubKey(KEY, CANCREATE, true)) try { BLOCK } __finally { Storage->CloseSubKey(); }#define KEY(TYPE, VAR) KEYEX(TYPE, VAR, PropertyToKey(TEXT(#VAR)))#define REGCONFIG(CANCREATE) \  BLOCK(L"Interface", CANCREATE, \    KEY(String,   RandomSeedFile); \    KEY(String,   PuttyRegistryStorageKey); \    KEY(Bool,     ConfirmOverwriting); \    KEY(Bool,     ConfirmResume); \    KEY(Bool,     AutoReadDirectoryAfterOp); \    KEY(Integer,  SessionReopenAuto); \    KEY(Integer,  SessionReopenBackground); \    KEY(Integer,  SessionReopenTimeout); \    KEY(Integer,  SessionReopenAutoStall); \    KEY(Integer,  TunnelLocalPortNumberLow); \    KEY(Integer,  TunnelLocalPortNumberHigh); \    KEY(Integer,  CacheDirectoryChangesMaxSize); \    KEY(Bool,     ShowFtpWelcomeMessage); \    KEY(String,   ExternalIpAddress); \    KEY(Bool,     TryFtpWhenSshFails); \    KEY(Integer,  ParallelDurationThreshold); \    KEY(String,   MimeTypes); \    KEY(Integer,  DontReloadMoreThanSessions); \    KEY(Integer,  ScriptProgressFileNameLimit); \    KEY(Bool,     CollectUsage); \  ); \  BLOCK(L"Logging", CANCREATE, \    KEYEX(Bool,  PermanentLogging, L"Logging"); \    KEYEX(String,PermanentLogFileName, L"LogFileName"); \    KEY(Bool,    LogFileAppend); \    KEYEX(Bool,  PermanentLogSensitive, L"LogSensitive"); \    KEYEX(Int64, PermanentLogMaxSize, L"LogMaxSize"); \    KEYEX(Integer, PermanentLogMaxCount, L"LogMaxCount"); \    KEYEX(Integer,PermanentLogProtocol, L"LogProtocol"); \    KEYEX(Bool,  PermanentLogActions, L"LogActions"); \    KEYEX(String,PermanentActionsLogFileName, L"ActionsLogFileName"); \  );//---------------------------------------------------------------------------void __fastcall TConfiguration::SaveData(THierarchicalStorage * Storage, bool /*All*/){  #define KEYEX(TYPE, VAR, NAME) Storage->Write ## TYPE(NAME, VAR)  REGCONFIG(true);  #undef KEYEX  if (Storage->OpenSubKey(L"Usage", true))  {    FUsage->Save(Storage);    Storage->CloseSubKey();  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::Save(){  // only modified, implicit  DoSave(false, false);}//---------------------------------------------------------------------------void __fastcall TConfiguration::SaveExplicit(){  // only modified, explicit  DoSave(false, true);}//---------------------------------------------------------------------------void __fastcall TConfiguration::DoSave(bool All, bool Explicit){  if (FDontSave) return;  THierarchicalStorage * AStorage = CreateConfigStorage();  try  {    AStorage->AccessMode = smReadWrite;    AStorage->Explicit = Explicit;    AStorage->ForceSave = FForceSave;    if (AStorage->OpenSubKey(ConfigurationSubKey, true))    {      // if saving to TOptionsStorage, make sure we save everything so that      // all configuration is properly transferred to the master storage      bool ConfigAll = All || AStorage->Temporary;      SaveData(AStorage, ConfigAll);    }  }  __finally  {    delete AStorage;  }  Saved();  if (All)  {    StoredSessions->Save(true, Explicit);  }  // clean up as last, so that if it fails (read only INI), the saving can proceed  if (Storage == stRegistry)  {    CleanupIniFile();  }  SaveCustomIniFileStorageName();}//---------------------------------------------------------------------------void __fastcall TConfiguration::SaveCustomIniFileStorageName(){  // Particularly, not to create an empty "Override" key, unless the custom INI file is ever set  if (CustomIniFileStorageName != LoadCustomIniFileStorageName())  {    std::unique_ptr<TRegistryStorage> RegistryStorage(new TRegistryStorage(GetRegistryStorageOverrideKey()));    RegistryStorage->AccessMode = smReadWrite;    RegistryStorage->Explicit = true;    if (RegistryStorage->OpenRootKey(true))    {      RegistryStorage->WriteString(L"IniFile", CustomIniFileStorageName);      RegistryStorage->CloseSubKey();    }  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::Export(const UnicodeString & FileName){  // not to "append" the export to an existing file  if (FileExists(FileName))  {    DeleteFileChecked(FileName);  }  THierarchicalStorage * Storage = NULL;  THierarchicalStorage * ExportStorage = NULL;  try  {    ExportStorage = TIniFileStorage::CreateFromPath(FileName);    ExportStorage->AccessMode = smReadWrite;    ExportStorage->Explicit = true;    Storage = CreateConfigStorage();    Storage->AccessMode = smRead;    CopyData(Storage, ExportStorage);    if (ExportStorage->OpenSubKey(ConfigurationSubKey, true))    {      SaveData(ExportStorage, true);    }  }  __finally  {    delete ExportStorage;    delete Storage;  }  StoredSessions->Export(FileName);}//---------------------------------------------------------------------------void __fastcall TConfiguration::Import(const UnicodeString & FileName){  THierarchicalStorage * Storage = NULL;  THierarchicalStorage * ImportStorage = NULL;  try  {    ImportStorage = TIniFileStorage::CreateFromPath(FileName);    ImportStorage->AccessMode = smRead;    Storage = CreateConfigStorage();    Storage->AccessMode = smReadWrite;    Storage->Explicit = true;    CopyData(ImportStorage, Storage);    Default();    LoadFrom(ImportStorage);    if (ImportStorage->OpenSubKey(Configuration->StoredSessionsSubKey, false))    {      StoredSessions->Clear();      StoredSessions->DefaultSettings->Default();      StoredSessions->Load(ImportStorage);    }  }  __finally  {    delete ImportStorage;    delete Storage;  }  // save all and explicit  DoSave(true, true);}//---------------------------------------------------------------------------void __fastcall TConfiguration::LoadData(THierarchicalStorage * Storage){  #define KEYEX(TYPE, VAR, NAME) VAR = Storage->Read ## TYPE(NAME, VAR)  #pragma warn -eas  REGCONFIG(false);  #pragma warn +eas  #undef KEYEX  if (Storage->OpenSubKey(L"Usage", false))  {    FUsage->Load(Storage);    Storage->CloseSubKey();  }  if (FPermanentLogActions && FPermanentActionsLogFileName.IsEmpty() &&      FPermanentLogging && !FPermanentLogFileName.IsEmpty())  {     FPermanentActionsLogFileName = FPermanentLogFileName;     FPermanentLogging = false;     FPermanentLogFileName = L"";  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::LoadAdmin(THierarchicalStorage * Storage){  FDisablePasswordStoring = Storage->ReadBool(L"DisablePasswordStoring", FDisablePasswordStoring);  FForceBanners = Storage->ReadBool(L"ForceBanners", FForceBanners);  FDisableAcceptingHostKeys = Storage->ReadBool(L"DisableAcceptingHostKeys", FDisableAcceptingHostKeys);  FDefaultCollectUsage = Storage->ReadBool(L"DefaultCollectUsage", FDefaultCollectUsage);}//---------------------------------------------------------------------------void __fastcall TConfiguration::LoadFrom(THierarchicalStorage * Storage){  if (Storage->OpenSubKey(ConfigurationSubKey, false))  {    LoadData(Storage);    Storage->CloseSubKey();  }}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetRegistryStorageOverrideKey(){  return GetRegistryStorageKey() + L" Override";}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::LoadCustomIniFileStorageName(){  UnicodeString Result;  std::unique_ptr<TRegistryStorage> RegistryStorage(new TRegistryStorage(GetRegistryStorageOverrideKey()));  if (RegistryStorage->OpenRootKey(false))  {    Result = RegistryStorage->ReadString(L"IniFile", L"");    RegistryStorage->CloseSubKey();  }  RegistryStorage.reset(NULL);  return Result;}//---------------------------------------------------------------------------void __fastcall TConfiguration::Load(THierarchicalStorage * Storage){  TGuard Guard(FCriticalSection);  TStorageAccessMode StorageAccessMode = Storage->AccessMode;  try  {    Storage->AccessMode = smRead;    LoadFrom(Storage);  }  __finally  {    Storage->AccessMode = StorageAccessMode;  }}//---------------------------------------------------------------------------bool __fastcall TConfiguration::CopySubKey(THierarchicalStorage * Source, THierarchicalStorage * Target, const UnicodeString & Name){  bool Result = Source->OpenSubKey(Name, false);  if (Result)  {    Result = Target->OpenSubKey(Name, true);    if (!Result)    {      Source->CloseSubKey();    }  }  return Result;}//---------------------------------------------------------------------------void __fastcall TConfiguration::CopyAllStringsInSubKey(  THierarchicalStorage * Source, THierarchicalStorage * Target, const UnicodeString & Name){  if (CopySubKey(Source, Target, Name))  {    std::unique_ptr<TStrings> Names(new TStringList());    Source->GetValueNames(Names.get());    for (int Index = 0; Index < Names->Count; Index++)    {      UnicodeString Buf = Source->ReadStringRaw(Names->Strings[Index], UnicodeString());      Target->WriteStringRaw(Names->Strings[Index], Buf);    }    Target->CloseSubKey();    Source->CloseSubKey();  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::CopyData(THierarchicalStorage * Source,  THierarchicalStorage * Target){  if (CopySubKey(Source, Target, ConfigurationSubKey))  {    if (CopySubKey(Source, Target, L"CDCache"))    {      std::unique_ptr<TStrings> Names(new TStringList());      Source->GetValueNames(Names.get());      for (int Index = 0; Index < Names->Count; Index++)      {        Target->WriteBinaryData(Names->Strings[Index], Source->ReadBinaryData(Names->Strings[Index]));      }      Target->CloseSubKey();      Source->CloseSubKey();    }    CopyAllStringsInSubKey(Source, Target, L"Banners");    CopyAllStringsInSubKey(Source, Target, LastFingerprintsStorageKey);    Target->CloseSubKey();    Source->CloseSubKey();  }  CopyAllStringsInSubKey(Source, Target, SshHostKeysSubKey);  CopyAllStringsInSubKey(Source, Target, FtpsCertificateStorageKey);  CopyAllStringsInSubKey(Source, Target, HttpsCertificateStorageKey);}//---------------------------------------------------------------------------void __fastcall TConfiguration::LoadDirectoryChangesCache(const UnicodeString SessionKey,  TRemoteDirectoryChangesCache * DirectoryChangesCache){  THierarchicalStorage * Storage = CreateConfigStorage();  try  {    Storage->AccessMode = smRead;    if (Storage->OpenSubKey(ConfigurationSubKey, false) &&        Storage->OpenSubKey(L"CDCache", false) &&        Storage->ValueExists(SessionKey))    {      DirectoryChangesCache->Deserialize(Storage->ReadBinaryData(SessionKey));    }  }  __finally  {    delete Storage;  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::SaveDirectoryChangesCache(const UnicodeString SessionKey,  TRemoteDirectoryChangesCache * DirectoryChangesCache){  THierarchicalStorage * Storage = CreateConfigStorage();  try  {    Storage->AccessMode = smReadWrite;    if (Storage->OpenSubKey(ConfigurationSubKey, true) &&        Storage->OpenSubKey(L"CDCache", true))    {      UnicodeString Data;      DirectoryChangesCache->Serialize(Data);      Storage->WriteBinaryData(SessionKey, Data);    }  }  __finally  {    delete Storage;  }}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::BannerHash(const UnicodeString & Banner){  RawByteString Result;  Result.SetLength(16);  md5checksum(    reinterpret_cast<const char*>(Banner.c_str()), Banner.Length() * sizeof(wchar_t),    (unsigned char*)Result.c_str());  return BytesToHex(Result);}//---------------------------------------------------------------------------void __fastcall TConfiguration::GetBannerData(  const UnicodeString & SessionKey, UnicodeString & BannerHash, unsigned int & Params){  BannerHash = UnicodeString();  Params = 0;  std::unique_ptr<THierarchicalStorage> Storage(CreateConfigStorage());  Storage->AccessMode = smRead;  if (Storage->OpenSubKey(ConfigurationSubKey, false) &&      Storage->OpenSubKey(L"Banners", false))  {    UnicodeString S = Storage->ReadString(SessionKey, L"");    BannerHash = CutToChar(S, L',', true);    Params = StrToIntDef(L"$" + CutToChar(S, L',', true), 0);  }}//---------------------------------------------------------------------------bool __fastcall TConfiguration::ShowBanner(  const UnicodeString & SessionKey, const UnicodeString & Banner, unsigned int & Params){  UnicodeString StoredBannerHash;  GetBannerData(SessionKey, StoredBannerHash, Params);  bool Result = (StoredBannerHash != BannerHash(Banner));  return Result;}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetBannerData(  const UnicodeString & SessionKey, const UnicodeString & BannerHash, unsigned int Params){  std::unique_ptr<THierarchicalStorage> Storage(CreateConfigStorage());  Storage->AccessMode = smReadWrite;  if (Storage->OpenSubKey(ConfigurationSubKey, true) &&      Storage->OpenSubKey(L"Banners", true))  {    Storage->WriteString(SessionKey, BannerHash + L"," + UIntToStr(Params));  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::NeverShowBanner(const UnicodeString & SessionKey, const UnicodeString & Banner){  UnicodeString DummyBannerHash;  unsigned int Params;  GetBannerData(SessionKey, DummyBannerHash, Params);  SetBannerData(SessionKey, BannerHash(Banner), Params);}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetBannerParams(const UnicodeString & SessionKey, unsigned int Params){  UnicodeString BannerHash;  unsigned int DummyParams;  GetBannerData(SessionKey, BannerHash, DummyParams);  SetBannerData(SessionKey, BannerHash, Params);}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::FormatFingerprintKey(const UnicodeString & SiteKey, const UnicodeString & FingerprintType){  return FORMAT(L"%s:%s", (SiteKey, FingerprintType));}//---------------------------------------------------------------------------void __fastcall TConfiguration::RememberLastFingerprint(const UnicodeString & SiteKey, const UnicodeString & FingerprintType, const UnicodeString & Fingerprint){  std::unique_ptr<THierarchicalStorage> Storage(CreateConfigStorage());  Storage->AccessMode = smReadWrite;  if (Storage->OpenSubKey(ConfigurationSubKey, true) &&      Storage->OpenSubKey(LastFingerprintsStorageKey, true))  {    UnicodeString FingerprintKey = FormatFingerprintKey(SiteKey, FingerprintType);    Storage->WriteString(FingerprintKey, Fingerprint);  }}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::LastFingerprint(const UnicodeString & SiteKey, const UnicodeString & FingerprintType){  UnicodeString Result;  std::unique_ptr<THierarchicalStorage> Storage(CreateConfigStorage());  Storage->AccessMode = smRead;  if (Storage->OpenSubKey(ConfigurationSubKey, false) &&      Storage->OpenSubKey(LastFingerprintsStorageKey, false))  {    UnicodeString FingerprintKey = FormatFingerprintKey(SiteKey, FingerprintType);    Result = Storage->ReadString(FingerprintKey, L"");  }  return Result;}//---------------------------------------------------------------------------void __fastcall TConfiguration::Changed(){  TNotifyEvent AOnChange = NULL;  {    TGuard Guard(FCriticalSection);    if (FUpdating == 0)    {      AOnChange = OnChange;    }    else    {      FChanged = true;    }  }  // No specific reason to call this outside of a guard, just that it is less of a change to a previous unguarded code  if (AOnChange != NULL)  {    AOnChange(this);  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::BeginUpdate(){  FCriticalSection->Enter();  if (FUpdating == 0)  {    FChanged = false;  }  FUpdating++;  // Greater value would probably indicate some nesting problem in code  DebugAssert(FUpdating < 6);}//---------------------------------------------------------------------------void __fastcall TConfiguration::EndUpdate(){  DebugAssert(FUpdating > 0);  FUpdating--;  if ((FUpdating == 0) && FChanged)  {    FChanged = false;    Changed();  }  FCriticalSection->Leave();}//---------------------------------------------------------------------------void __fastcall TConfiguration::CleanupConfiguration(){  try  {    CleanupRegistry(ConfigurationSubKey);    if (Storage == stRegistry)    {      FDontSave = true;    }  }  catch (Exception &E)  {    throw ExtException(&E, LoadStr(CLEANUP_CONFIG_ERROR));  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::CleanupRegistry(UnicodeString CleanupSubKey){  TRegistryStorage *Registry = new TRegistryStorage(RegistryStorageKey);  try  {    Registry->RecursiveDeleteSubKey(CleanupSubKey);  }  __finally  {    delete Registry;  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::CleanupHostKeys(){  try  {    CleanupRegistry(SshHostKeysSubKey);  }  catch (Exception &E)  {    throw ExtException(&E, LoadStr(CLEANUP_HOSTKEYS_ERROR));  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::CleanupRandomSeedFile(){  try  {    DontSaveRandomSeed();    if (FileExists(ApiPath(RandomSeedFileName)))    {      DeleteFileChecked(RandomSeedFileName);    }  }  catch (Exception &E)  {    throw ExtException(&E, LoadStr(CLEANUP_SEEDFILE_ERROR));  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::CleanupIniFile(){  try  {    if (FileExists(ApiPath(IniFileStorageNameForReading)))    {      DeleteFileChecked(IniFileStorageNameForReading);    }    if (Storage == stIniFile)    {      FDontSave = true;    }  }  catch (Exception &E)  {    throw ExtException(&E, LoadStr(CLEANUP_INIFILE_ERROR));  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::DontSave(){  FDontSave = true;}//---------------------------------------------------------------------------RawByteString __fastcall TConfiguration::EncryptPassword(UnicodeString Password, UnicodeString Key){  if (Password.IsEmpty())  {    return RawByteString();  }  else  {    return ::EncryptPassword(Password, Key);  }}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::DecryptPassword(RawByteString Password, UnicodeString Key){  if (Password.IsEmpty())  {    return UnicodeString();  }  else  {    return ::DecryptPassword(Password, Key);  }}//---------------------------------------------------------------------------RawByteString __fastcall TConfiguration::StronglyRecryptPassword(RawByteString Password, UnicodeString /*Key*/){  return Password;}//---------------------------------------------------------------------------TVSFixedFileInfo *__fastcall TConfiguration::GetFixedApplicationInfo(){  return GetFixedFileInfo(ApplicationInfo);}//---------------------------------------------------------------------------int __fastcall TConfiguration::GetCompoundVersion(){  TVSFixedFileInfo * FileInfo = FixedApplicationInfo;  return CalculateCompoundVersion(    HIWORD(FileInfo->dwFileVersionMS), LOWORD(FileInfo->dwFileVersionMS),    HIWORD(FileInfo->dwFileVersionLS), LOWORD(FileInfo->dwFileVersionLS));}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::ModuleFileName(){  return ParamStr(0);}//---------------------------------------------------------------------------void * __fastcall TConfiguration::GetFileApplicationInfo(const UnicodeString FileName){  void * Result;  if (FileName.IsEmpty())  {    if (!FApplicationInfo)    {      FApplicationInfo = CreateFileInfo(ModuleFileName());    }    Result = FApplicationInfo;  }  else  {    Result = CreateFileInfo(FileName);  }  return Result;}//---------------------------------------------------------------------------void * __fastcall TConfiguration::GetApplicationInfo(){  return GetFileApplicationInfo("");}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetFileProductName(const UnicodeString FileName){  return GetFileFileInfoString(L"ProductName", FileName);}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetFileCompanyName(const UnicodeString FileName){  // particularly in IDE build, company name is empty  return GetFileFileInfoString(L"CompanyName", FileName, true);}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetProductName(){  return GetFileProductName(L"");}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetCompanyName(){  return GetFileCompanyName(L"");}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetFileProductVersion(const UnicodeString FileName){  return TrimVersion(GetFileFileInfoString(L"ProductVersion", FileName));}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetFileDescription(const UnicodeString & FileName){  return GetFileFileInfoString(L"FileDescription", FileName);}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetProductVersion(){  return GetFileProductVersion(L"");}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetReleaseType(){  return GetFileInfoString(L"ReleaseType");}//---------------------------------------------------------------------------bool __fastcall TConfiguration::GetIsUnofficial(){  #ifdef BUILD_OFFICIAL  return false;  #else  return true;  #endif}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetVersionStr(){  TGuard Guard(FCriticalSection);  try  {    UnicodeString BuildStr;    if (!IsUnofficial)    {      BuildStr = LoadStr(VERSION_BUILD);    }    else    {      #ifdef _DEBUG      BuildStr = LoadStr(VERSION_DEBUG_BUILD);      #else      BuildStr = LoadStr(VERSION_DEV_BUILD);      #endif    }    int Build = LOWORD(FixedApplicationInfo->dwFileVersionLS);    if (Build > 0)    {      BuildStr += L" " + IntToStr(Build);    }    #ifndef BUILD_OFFICIAL    UnicodeString BuildDate = __DATE__;    UnicodeString MonthStr = CutToChar(BuildDate, L' ', true);    int Month = ParseShortEngMonthName(MonthStr);    int Day = StrToInt(CutToChar(BuildDate, L' ', true));    int Year = StrToInt(Trim(BuildDate));    UnicodeString DateStr = FORMAT(L"%d-%2.2d-%2.2d", (Year, Month, Day));    AddToList(BuildStr, DateStr, L" ");    #endif    UnicodeString FullVersion = Version;    UnicodeString AReleaseType = GetReleaseType();    if (DebugAlwaysTrue(!AReleaseType.IsEmpty()) &&        !SameText(AReleaseType, L"stable") &&        !SameText(AReleaseType, L"development"))    {      FullVersion += L" " + AReleaseType;    }    UnicodeString Result = FMTLOAD(VERSION2, (FullVersion, BuildStr));    #ifndef BUILD_OFFICIAL    Result += L" " + LoadStr(VERSION_DONT_DISTRIBUTE);    #endif    return Result;  }  catch (Exception &E)  {    throw ExtException(&E, L"Can't get application version");  }}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetFileVersion(const UnicodeString & FileName){  UnicodeString Result;  void * FileInfo = CreateFileInfo(FileName);  try  {    Result = GetFileVersion(GetFixedFileInfo(FileInfo));  }  __finally  {    FreeFileInfo(FileInfo);  }  return Result;}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetFileVersion(TVSFixedFileInfo * Info){  TGuard Guard(FCriticalSection);  try  {    UnicodeString Result =      FormatVersion(        HIWORD(Info->dwFileVersionMS),        LOWORD(Info->dwFileVersionMS),        HIWORD(Info->dwFileVersionLS));    return Result;  }  catch (Exception &E)  {    throw ExtException(&E, L"Can't get file version");  }}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetVersion(){  return GetFileVersion(FixedApplicationInfo);}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetFileFileInfoString(const UnicodeString Key,  const UnicodeString FileName, bool AllowEmpty){  TGuard Guard(FCriticalSection);  UnicodeString Result;  void * Info = GetFileApplicationInfo(FileName);  try  {    if ((Info != NULL) && (GetTranslationCount(Info) > 0))    {      TTranslation Translation;      Translation = GetTranslation(Info, 0);      Result = ::GetFileInfoString(Info, Translation, Key, AllowEmpty);    }    else    {      DebugAssert(!FileName.IsEmpty());    }  }  __finally  {    if (!FileName.IsEmpty())    {      FreeFileInfo(Info);    }  }  return Result;}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetFileInfoString(const UnicodeString Key){  return GetFileFileInfoString(Key, L"");}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetFileMimeType(const UnicodeString & FileName){  UnicodeString Result;  bool Found = false;  if (!MimeTypes.IsEmpty())  {    UnicodeString FileNameOnly = ExtractFileName(FileName);    UnicodeString AMimeTypes = MimeTypes;    while (!Found && !AMimeTypes.IsEmpty())    {      UnicodeString Token = CutToChar(AMimeTypes, L',', true);      UnicodeString MaskStr = CutToChar(Token, L'=', true);      TFileMasks Mask(MaskStr);      if (Mask.Matches(FileNameOnly))      {        Result = Token.Trim();        Found = true;      }    }  }  if (!Found) // allow an override to "no" Content-Type  {    Result = ::GetFileMimeType(FileName);  }  return Result;}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetRegistryStorageKey(){  return GetRegistryKey();}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetNulStorage(){  FStorage = stNul;}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetDefaultStorage(){  FStorage = stDetect;}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetIniFileStorageName(UnicodeString value){  FIniFileStorageName = value;  FStorage = stIniFile;}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetDefaultIniFileExportPath(){  UnicodeString PersonalDirectory = GetPersonalFolder();  UnicodeString FileName = IncludeTrailingBackslash(PersonalDirectory) +    ExtractFileName(ExpandEnvironmentVariables(IniFileStorageName));  return FileName;}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetIniFileStorageNameForReading(){  return GetIniFileStorageName(true);}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetIniFileStorageNameForReadingWriting(){  return GetIniFileStorageName(false);}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetAutomaticIniFileStorageName(bool ReadingOnly){  UnicodeString ProgramPath = ParamStr(0);  UnicodeString ProgramIniPath = ChangeFileExt(ProgramPath, L".ini");  UnicodeString IniPath;  if (FileExists(ApiPath(ProgramIniPath)))  {    IniPath = ProgramIniPath;  }  else  {    UnicodeString AppDataIniPath =      IncludeTrailingBackslash(GetShellFolderPath(CSIDL_APPDATA)) +      ExtractFileName(ProgramIniPath);    if (FileExists(ApiPath(AppDataIniPath)))    {      IniPath = AppDataIniPath;    }    else    {      // avoid expensive test if we are interested in existing files only      if (!ReadingOnly && (FProgramIniPathWrittable < 0))      {        UnicodeString ProgramDir = ExtractFilePath(ProgramPath);        FProgramIniPathWrittable = IsDirectoryWriteable(ProgramDir) ? 1 : 0;      }      // does not really matter what we return when < 0      IniPath = (FProgramIniPathWrittable == 0) ? AppDataIniPath : ProgramIniPath;    }  }  // BACKWARD COMPATIBILITY with 4.x  if (FVirtualIniFileStorageName.IsEmpty() &&      TPath::IsDriveRooted(IniPath))  {    UnicodeString LocalAppDataPath = GetShellFolderPath(CSIDL_LOCAL_APPDATA);    // virtual store for non-system drives have a different virtual store,    // do not bother about them    if (TPath::IsDriveRooted(LocalAppDataPath) &&        SameText(ExtractFileDrive(IniPath), ExtractFileDrive(LocalAppDataPath)))    {      FVirtualIniFileStorageName =        IncludeTrailingBackslash(LocalAppDataPath) +        L"VirtualStore\\" +        IniPath.SubString(4, IniPath.Length() - 3);    }  }  if (!FVirtualIniFileStorageName.IsEmpty() &&      FileExists(ApiPath(FVirtualIniFileStorageName)))  {    return FVirtualIniFileStorageName;  }  else  {    return IniPath;  }}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetIniFileStorageName(bool ReadingOnly){  UnicodeString Result;  if (!FIniFileStorageName.IsEmpty())  {    Result = FIniFileStorageName;  }  else if (!FCustomIniFileStorageName.IsEmpty())  {    Result = FCustomIniFileStorageName;  }  else  {    Result = GetAutomaticIniFileStorageName(ReadingOnly);  }  return Result;}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetOptionsStorage(TStrings * value){  TGuard Guard(FCriticalSection);  if (FOptionsStorage.get() == NULL)  {    FOptionsStorage.reset(new TStringList());  }  FOptionsStorage->AddStrings(value);}//---------------------------------------------------------------------------TStrings * __fastcall TConfiguration::GetOptionsStorage(){  return FOptionsStorage.get();}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetPuttySessionsKey(){  return PuttyRegistryStorageKey + L"\\Sessions";}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetStoredSessionsSubKey(){  return L"Sessions";}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetSshHostKeysSubKey(){  return L"SshHostKeys";}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetConfigurationSubKey(){  return L"Configuration";}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetRootKeyStr(){  return RootKeyToStr(HKEY_CURRENT_USER);}//---------------------------------------------------------------------------void __fastcall TConfiguration::MoveStorage(TStorage AStorage, const UnicodeString & ACustomIniFileStorageName){  if ((FStorage != AStorage) ||      !IsPathToSameFile(FCustomIniFileStorageName, ACustomIniFileStorageName))  {    TStorage StorageBak = FStorage;    UnicodeString CustomIniFileStorageNameBak = FCustomIniFileStorageName;    try    {      THierarchicalStorage * SourceStorage = NULL;      THierarchicalStorage * TargetStorage = NULL;      try      {        SourceStorage = CreateConfigStorage();        SourceStorage->AccessMode = smRead;        FStorage = AStorage;        FCustomIniFileStorageName = ACustomIniFileStorageName;        TargetStorage = CreateConfigStorage();        TargetStorage->AccessMode = smReadWrite;        TargetStorage->Explicit = true;        // copy before save as it removes the ini file,        // when switching from ini to registry        CopyData(SourceStorage, TargetStorage);      }      __finally      {        delete SourceStorage;        delete TargetStorage;      }      // save all and explicit,      // this also removes an INI file, when switching to registry storage      DoSave(true, true);    }    catch (...)    {      // If this fails, do not pretend that storage was switched.      // For instance:      // - When writing to an INI file fails (unlikely, as we fallback to user profile)      // - When removing INI file fails, when switching to registry      //   (possible, when the INI file is in Program Files folder)      FStorage = StorageBak;      FCustomIniFileStorageName = CustomIniFileStorageNameBak;      throw;    }  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::ScheduleCustomIniFileStorageUse(const UnicodeString & ACustomIniFileStorageName){  FStorage = stIniFile;  FCustomIniFileStorageName = ACustomIniFileStorageName;  SaveCustomIniFileStorageName();}//---------------------------------------------------------------------------void __fastcall TConfiguration::Saved(){  // nothing}//---------------------------------------------------------------------------TStorage __fastcall TConfiguration::GetStorage(){  TGuard Guard(FCriticalSection);  if (FStorage == stDetect)  {    if (FileExists(ApiPath(IniFileStorageNameForReading)))    {      FStorage = stIniFile;    }    else    {      FStorage = stRegistry;    }  }  return FStorage;}//---------------------------------------------------------------------TStoredSessionList * __fastcall TConfiguration::SelectFilezillaSessionsForImport(  TStoredSessionList * Sessions, UnicodeString & Error){  std::unique_ptr<TStoredSessionList> ImportSessionList(new TStoredSessionList(true));  ImportSessionList->DefaultSettings = Sessions->DefaultSettings;  UnicodeString AppDataPath = GetShellFolderPath(CSIDL_APPDATA);  UnicodeString FilezillaSiteManagerFile =    IncludeTrailingBackslash(AppDataPath) + L"FileZilla\\sitemanager.xml";  UnicodeString FilezillaConfigurationFile =    IncludeTrailingBackslash(AppDataPath) + L"FileZilla\\filezilla.xml";  if (FileExists(ApiPath(FilezillaSiteManagerFile)))  {    ImportSessionList->ImportFromFilezilla(FilezillaSiteManagerFile, FilezillaConfigurationFile);    if (ImportSessionList->Count > 0)    {      ImportSessionList->SelectSessionsToImport(Sessions, true);    }    else    {      Error = FMTLOAD(FILEZILLA_NO_SITES, (FilezillaSiteManagerFile));    }  }  else  {    Error = FMTLOAD(FILEZILLA_SITE_MANAGER_NOT_FOUND, (FilezillaSiteManagerFile));  }  return ImportSessionList.release();}//---------------------------------------------------------------------bool __fastcall TConfiguration::AnyFilezillaSessionForImport(TStoredSessionList * Sessions){  try  {    UnicodeString Error;    std::unique_ptr<TStoredSessionList> Sesssions(SelectFilezillaSessionsForImport(Sessions, Error));    return (Sesssions->Count > 0);  }  catch (...)  {    return false;  }}//---------------------------------------------------------------------TStoredSessionList * __fastcall TConfiguration::SelectKnownHostsSessionsForImport(  TStoredSessionList * Sessions, UnicodeString & Error){  std::unique_ptr<TStoredSessionList> ImportSessionList(new TStoredSessionList(true));  ImportSessionList->DefaultSettings = Sessions->DefaultSettings;  UnicodeString ProfilePath = GetShellFolderPath(CSIDL_PROFILE);  UnicodeString KnownHostsFile = IncludeTrailingBackslash(ProfilePath) + L".ssh\\known_hosts";  try  {    if (FileExists(ApiPath(KnownHostsFile)))    {      std::unique_ptr<TStrings> Lines(new TStringList());      LoadScriptFromFile(KnownHostsFile, Lines.get());      ImportSessionList->ImportFromKnownHosts(Lines.get());    }    else    {      throw Exception(LoadStr(KNOWN_HOSTS_NOT_FOUND));    }  }  catch (Exception & E)  {    Error = FORMAT(L"%s\n(%s)", (E.Message, KnownHostsFile));  }  return ImportSessionList.release();}//---------------------------------------------------------------------TStoredSessionList * __fastcall TConfiguration::SelectKnownHostsSessionsForImport(  TStrings * Lines, TStoredSessionList * Sessions, UnicodeString & Error){  std::unique_ptr<TStoredSessionList> ImportSessionList(new TStoredSessionList(true));  ImportSessionList->DefaultSettings = Sessions->DefaultSettings;  try  {    ImportSessionList->ImportFromKnownHosts(Lines);  }  catch (Exception & E)  {    Error = E.Message;  }  return ImportSessionList.release();}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetRandomSeedFile(UnicodeString value){  if (RandomSeedFile != value)  {    UnicodeString PrevRandomSeedFileName = RandomSeedFileName;    FRandomSeedFile = value;    // never allow empty seed file to avoid Putty trying to reinitialize the path    if (RandomSeedFileName.IsEmpty())    {      FRandomSeedFile = FDefaultRandomSeedFile;    }    if (!PrevRandomSeedFileName.IsEmpty() &&        (PrevRandomSeedFileName != RandomSeedFileName) &&        FileExists(ApiPath(PrevRandomSeedFileName)))    {      // ignore any error      DeleteFile(ApiPath(PrevRandomSeedFileName));    }  }}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetDirectoryStatisticsCacheKey(  const UnicodeString & SessionKey, const UnicodeString & Path, const TCopyParamType & CopyParam){  std::unique_ptr<TStringList> RawOptions(new TStringList());  RawOptions->Add(SessionKey);  RawOptions->Add(UnixExcludeTrailingBackslash(Path));  TCopyParamType Defaults;  TCopyParamType FilterCopyParam;  FilterCopyParam.IncludeFileMask = CopyParam.IncludeFileMask;  FilterCopyParam.ExcludeHiddenFiles = CopyParam.ExcludeHiddenFiles;  FilterCopyParam.ExcludeEmptyDirectories = CopyParam.ExcludeEmptyDirectories;  std::unique_ptr<TOptionsStorage> OptionsStorage(new TOptionsStorage(RawOptions.get(), true));  FilterCopyParam.Save(OptionsStorage.get(), &Defaults);  UTF8String RawOptionsBuf(RawOptions->CommaText.LowerCase());  UnicodeString Result = Sha256(RawOptionsBuf.c_str(), RawOptionsBuf.Length());  return Result;}//---------------------------------------------------------------------------THierarchicalStorage * TConfiguration::OpenDirectoryStatisticsCache(bool CanCreate){  std::unique_ptr<THierarchicalStorage> Storage(Configuration->CreateConfigStorage());  Storage->AccessMode = CanCreate ? smReadWrite : smRead;  if (!Storage->OpenSubKey(L"DirectoryStatisticsCache", CanCreate))  {    Storage.reset(NULL);  }  return Storage.release();}//---------------------------------------------------------------------------TStrings * __fastcall TConfiguration::LoadDirectoryStatisticsCache(  const UnicodeString & SessionKey, const UnicodeString & Path, const TCopyParamType & CopyParam){  std::unique_ptr<THierarchicalStorage> Storage(OpenDirectoryStatisticsCache(false));  std::unique_ptr<TStringList> Result(new TStringList());  if (Storage.get() != NULL)  {    UnicodeString Key = GetDirectoryStatisticsCacheKey(SessionKey, Path, CopyParam);    UnicodeString Buf = Storage->ReadString(Key, UnicodeString());    Result->CommaText = Buf;  }  return Result.release();}//---------------------------------------------------------------------------void __fastcall TConfiguration::SaveDirectoryStatisticsCache(  const UnicodeString & SessionKey, const UnicodeString & Path, const TCopyParamType & CopyParam, TStrings * DataList){  std::unique_ptr<THierarchicalStorage> Storage(OpenDirectoryStatisticsCache(true));  if (Storage.get() != NULL)  {    UnicodeString Key = GetDirectoryStatisticsCacheKey(SessionKey, Path, CopyParam);    UnicodeString Buf = DataList->CommaText;    Storage->WriteString(Key, Buf);  }}//---------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetRandomSeedFileName(){  // StripPathQuotes should not be needed as we do not feed quotes anymore  return StripPathQuotes(ExpandEnvironmentVariables(FRandomSeedFile)).Trim();}//---------------------------------------------------------------------void __fastcall TConfiguration::SetExternalIpAddress(UnicodeString value){  SET_CONFIG_PROPERTY(ExternalIpAddress);}//---------------------------------------------------------------------void __fastcall TConfiguration::SetMimeTypes(UnicodeString value){  SET_CONFIG_PROPERTY(MimeTypes);}//---------------------------------------------------------------------void __fastcall TConfiguration::SetTryFtpWhenSshFails(bool value){  SET_CONFIG_PROPERTY(TryFtpWhenSshFails);}//---------------------------------------------------------------------void __fastcall TConfiguration::SetParallelDurationThreshold(int value){  SET_CONFIG_PROPERTY(ParallelDurationThreshold);}//---------------------------------------------------------------------void __fastcall TConfiguration::SetPuttyRegistryStorageKey(UnicodeString value){  SET_CONFIG_PROPERTY(PuttyRegistryStorageKey);}//---------------------------------------------------------------------------TEOLType __fastcall TConfiguration::GetLocalEOLType(){  return eolCRLF;}//---------------------------------------------------------------------bool __fastcall TConfiguration::GetCollectUsage(){  return FUsage->Collect;}//---------------------------------------------------------------------void __fastcall TConfiguration::SetCollectUsage(bool value){  FUsage->Collect = value;}//---------------------------------------------------------------------void __fastcall TConfiguration::TemporaryLogging(const UnicodeString ALogFileName){  if (SameText(ExtractFileExt(ALogFileName), L".xml"))  {    TemporaryActionsLogging(ALogFileName);  }  else  {    FLogging = true;    FLogFileName = ALogFileName;    UpdateActualLogProtocol();  }}//---------------------------------------------------------------------void __fastcall TConfiguration::TemporaryActionsLogging(const UnicodeString ALogFileName){  FLogActions = true;  FActionsLogFileName = ALogFileName;}//---------------------------------------------------------------------void __fastcall TConfiguration::TemporaryLogProtocol(int ALogProtocol){  FLogProtocol = ALogProtocol;  UpdateActualLogProtocol();}//---------------------------------------------------------------------void __fastcall TConfiguration::TemporaryLogSensitive(bool ALogSensitive){  FLogSensitive = ALogSensitive;}//---------------------------------------------------------------------void __fastcall TConfiguration::TemporaryLogMaxSize(__int64 ALogMaxSize){  FLogMaxSize = ALogMaxSize;}//---------------------------------------------------------------------void __fastcall TConfiguration::TemporaryLogMaxCount(int ALogMaxCount){  FLogMaxCount = ALogMaxCount;}//---------------------------------------------------------------------void __fastcall TConfiguration::SetLogging(bool value){  TGuard Guard(FCriticalSection);  if (Logging != value)  {    FPermanentLogging = value;    FLogging = value;    UpdateActualLogProtocol();    Changed();  }}//---------------------------------------------------------------------bool __fastcall TConfiguration::GetLogging(){  TGuard Guard(FCriticalSection);  return FPermanentLogging;}//---------------------------------------------------------------------void __fastcall TConfiguration::SetLogFileName(UnicodeString value){  TGuard Guard(FCriticalSection);  if (LogFileName != value)  {    FPermanentLogFileName = value;    FLogFileName = value;    Changed();  }}//---------------------------------------------------------------------UnicodeString  __fastcall TConfiguration::GetLogFileName(){  TGuard Guard(FCriticalSection);  return FPermanentLogFileName;}//---------------------------------------------------------------------void __fastcall TConfiguration::SetActionsLogFileName(UnicodeString value){  TGuard Guard(FCriticalSection);  if (ActionsLogFileName != value)  {    FPermanentActionsLogFileName = value;    FActionsLogFileName = value;    Changed();  }}//---------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetPermanentActionsLogFileName(){  TGuard Guard(FCriticalSection);  return FPermanentActionsLogFileName;}//---------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetActionsLogFileName(){  TGuard Guard(FCriticalSection);  return FActionsLogFileName;}//---------------------------------------------------------------------bool __fastcall TConfiguration::GetLogToFile(){  // guarded within GetLogFileName  return !LogFileName.IsEmpty();}//---------------------------------------------------------------------void __fastcall TConfiguration::UpdateActualLogProtocol(){  FActualLogProtocol = FLogging ? FLogProtocol : 0;}//---------------------------------------------------------------------void __fastcall TConfiguration::SetLogProtocol(int value){  TGuard Guard(FCriticalSection);  if (LogProtocol != value)  {    FPermanentLogProtocol = value;    FLogProtocol = value;    Changed();    UpdateActualLogProtocol();  }}//---------------------------------------------------------------------void __fastcall TConfiguration::SetLogActions(bool value){  TGuard Guard(FCriticalSection);  if (LogActions != value)  {    FPermanentLogActions = value;    FLogActions = value;    Changed();  }}//---------------------------------------------------------------------bool __fastcall TConfiguration::GetLogActions(){  TGuard Guard(FCriticalSection);  return FPermanentLogActions;}//---------------------------------------------------------------------void __fastcall TConfiguration::SetLogFileAppend(bool value){  SET_CONFIG_PROPERTY(LogFileAppend);}//---------------------------------------------------------------------void __fastcall TConfiguration::SetLogSensitive(bool value){  if (LogSensitive != value)  {    FPermanentLogSensitive = value;    FLogSensitive = value;    Changed();  }}//---------------------------------------------------------------------void __fastcall TConfiguration::SetLogMaxSize(__int64 value){  TGuard Guard(FCriticalSection);  if (LogMaxSize != value)  {    FPermanentLogMaxSize = value;    FLogMaxSize = value;    Changed();  }}//---------------------------------------------------------------------__int64 __fastcall TConfiguration::GetLogMaxSize(){  TGuard Guard(FCriticalSection);  return FPermanentLogMaxSize;}//---------------------------------------------------------------------void __fastcall TConfiguration::SetLogMaxCount(int value){  if (LogMaxCount != value)  {    FPermanentLogMaxCount = value;    FLogMaxCount = value;    Changed();  }}//---------------------------------------------------------------------int __fastcall TConfiguration::GetLogMaxCount(){  TGuard Guard(FCriticalSection);  return FPermanentLogMaxCount;}//---------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetDefaultLogFileName(){  return L"%TEMP%\\!S.log";}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetConfirmOverwriting(bool value){  TGuard Guard(FCriticalSection);  SET_CONFIG_PROPERTY(ConfirmOverwriting);}//---------------------------------------------------------------------------bool __fastcall TConfiguration::GetConfirmOverwriting(){  TGuard Guard(FCriticalSection);  return FConfirmOverwriting;}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetConfirmResume(bool value){  TGuard Guard(FCriticalSection);  SET_CONFIG_PROPERTY(ConfirmResume);}//---------------------------------------------------------------------------bool __fastcall TConfiguration::GetConfirmResume(){  TGuard Guard(FCriticalSection);  return FConfirmResume;}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetAutoReadDirectoryAfterOp(bool value){  TGuard Guard(FCriticalSection);  SET_CONFIG_PROPERTY(AutoReadDirectoryAfterOp);}//---------------------------------------------------------------------------bool __fastcall TConfiguration::GetAutoReadDirectoryAfterOp(){  TGuard Guard(FCriticalSection);  return FAutoReadDirectoryAfterOp;}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetTimeFormat(){  return L"h:nn:ss";}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetPartialExt() const{  return PARTIAL_EXT;}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetDefaultKeyFile(){  return L"";}//---------------------------------------------------------------------------bool __fastcall TConfiguration::GetRememberPassword(){  return false;}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetSessionReopenAuto(int value){  SET_CONFIG_PROPERTY(SessionReopenAuto);}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetSessionReopenBackground(int value){  SET_CONFIG_PROPERTY(SessionReopenBackground);}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetSessionReopenTimeout(int value){  SET_CONFIG_PROPERTY(SessionReopenTimeout);}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetSessionReopenAutoStall(int value){  SET_CONFIG_PROPERTY(SessionReopenAutoStall);}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetTunnelLocalPortNumberLow(int value){  SET_CONFIG_PROPERTY(TunnelLocalPortNumberLow);}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetTunnelLocalPortNumberHigh(int value){  SET_CONFIG_PROPERTY(TunnelLocalPortNumberHigh);}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetCacheDirectoryChangesMaxSize(int value){  SET_CONFIG_PROPERTY(CacheDirectoryChangesMaxSize);}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetShowFtpWelcomeMessage(bool value){  SET_CONFIG_PROPERTY(ShowFtpWelcomeMessage);}//---------------------------------------------------------------------------bool __fastcall TConfiguration::GetPersistent(){  return (Storage != stNul) && !FDontSave;}//---------------------------------------------------------------------------//---------------------------------------------------------------------------void __fastcall TShortCuts::Add(TShortCut ShortCut){  FShortCuts.insert(ShortCut);}//---------------------------------------------------------------------------bool __fastcall TShortCuts::Has(TShortCut ShortCut) const{  return (FShortCuts.count(ShortCut) != 0);}
 |