Login.cpp 112 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557
  1. //---------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include <StrUtils.hpp>
  5. #include <CoreMain.h>
  6. #include <Common.h>
  7. #include <PuttyTools.h>
  8. #include <TextsWin.h>
  9. #include <TextsCore.h>
  10. #include <HelpWin.h>
  11. #include <VCLCommon.h>
  12. #include "WinInterface.h"
  13. #include "Login.h"
  14. #include "GUITools.h"
  15. #include "Tools.h"
  16. #include "Setup.h"
  17. #include "WinConfiguration.h"
  18. //---------------------------------------------------------------------
  19. #pragma link "ComboEdit"
  20. #pragma link "GeneralSettings"
  21. #pragma link "LogSettings"
  22. #pragma link "PasswordEdit"
  23. #pragma link "UpDownEdit"
  24. #ifndef NO_RESOURCES
  25. #pragma resource "*.dfm"
  26. #endif
  27. //---------------------------------------------------------------------------
  28. // Sheet tag:
  29. // 01 top, 02 indented
  30. //---------------------------------------------------------------------------
  31. const int OpenFolderStateIndex = 2;
  32. const int ClosedFolderStateIndex = 3;
  33. const int WorkspaceStateIndex = 4;
  34. //---------------------------------------------------------------------------
  35. bool __fastcall DoLoginDialog(TStoredSessionList *SessionList,
  36. TList * DataList, int Options)
  37. {
  38. assert(DataList != NULL);
  39. TLoginDialog * LoginDialog = SafeFormCreate<TLoginDialog>();
  40. bool Result;
  41. try
  42. {
  43. LoginDialog->Init(SessionList, Options);
  44. Result = LoginDialog->Execute(DataList);
  45. }
  46. __finally
  47. {
  48. delete LoginDialog;
  49. }
  50. return Result;
  51. }
  52. //---------------------------------------------------------------------
  53. static const TFSProtocol FSOrder[] = { fsSFTPonly, fsSCPonly, fsFTP, fsWebDAV };
  54. static const UnicodeString DefaultRecycleBinPath = L"/tmp";
  55. //---------------------------------------------------------------------
  56. __fastcall TLoginDialog::TLoginDialog(TComponent* AOwner)
  57. : TForm(AOwner)
  58. {
  59. FSessionData = new TSessionData(L"");
  60. NoUpdate = 0;
  61. FLanguagesPopupMenu = NULL;
  62. FInitialized = false;
  63. FSavedTab = NULL;
  64. FSavedSession = -1;
  65. FOptions = loStartup;
  66. FLocaleChanging = false;
  67. FColor = (TColor)0;
  68. FEditingSessionData = NULL;
  69. FTreeLabels = new TStringList();
  70. FHintNode = NULL;
  71. FScrollOnDragOver = new TTreeViewScrollOnDragOver(SessionTree, true);
  72. FDataList = NULL;
  73. FUpdatePortWithProtocol = true;
  74. FIncrementalSearching = 0;
  75. FSitesIncrementalSearchHaveNext = false;
  76. // we need to make sure that window procedure is set asap
  77. // (so that CM_SHOWINGCHANGED handling is applied)
  78. UseSystemSettingsPre(this, &FSystemSettings);
  79. InitControls();
  80. }
  81. //---------------------------------------------------------------------
  82. __fastcall TLoginDialog::~TLoginDialog()
  83. {
  84. delete FScrollOnDragOver;
  85. assert(FSystemSettings);
  86. DeleteSystemSettings(this, FSystemSettings);
  87. FSystemSettings = NULL;
  88. delete FTreeLabels;
  89. delete FSessionData;
  90. delete FLanguagesPopupMenu;
  91. }
  92. //---------------------------------------------------------------------
  93. void __fastcall TLoginDialog::Init(TStoredSessionList *SessionList,
  94. int Options)
  95. {
  96. FStoredSessions = SessionList;
  97. LoadSessions();
  98. FOptions = Options;
  99. UnicodeString Dummy;
  100. RunPageantAction->Visible = FindTool(PageantTool, Dummy);
  101. RunPuttygenAction->Visible = FindTool(PuttygenTool, Dummy);
  102. UpdateControls();
  103. }
  104. //---------------------------------------------------------------------
  105. void __fastcall TLoginDialog::InitControls()
  106. {
  107. LoggingFrame->Init();
  108. ComboAutoSwitchInitialize(UtfCombo);
  109. ComboAutoSwitchInitialize(BugIgnore1Combo);
  110. ComboAutoSwitchInitialize(BugPlainPW1Combo);
  111. ComboAutoSwitchInitialize(BugRSA1Combo);
  112. ComboAutoSwitchInitialize(BugHMAC2Combo);
  113. ComboAutoSwitchInitialize(BugDeriveKey2Combo);
  114. ComboAutoSwitchInitialize(BugRSAPad2Combo);
  115. ComboAutoSwitchInitialize(BugPKSessID2Combo);
  116. ComboAutoSwitchInitialize(BugRekey2Combo);
  117. ComboAutoSwitchInitialize(BugMaxPkt2Combo);
  118. ComboAutoSwitchInitialize(BugIgnore2Combo);
  119. ComboAutoSwitchInitialize(SFTPBugSymlinkCombo);
  120. ComboAutoSwitchInitialize(SFTPBugSignedTSCombo);
  121. ComboAutoSwitchInitialize(FtpListAllCombo);
  122. ComboAutoSwitchInitialize(FtpUseMlsdCombo);
  123. ComboAutoSwitchInitialize(FtpForcePasvIpCombo);
  124. TunnelLocalPortNumberEdit->Items->BeginUpdate();
  125. try
  126. {
  127. UnicodeString TunnelLocalPortNumberAutoassign = TunnelLocalPortNumberEdit->Items->Strings[0];
  128. TunnelLocalPortNumberEdit->Items->Clear();
  129. TunnelLocalPortNumberEdit->Items->Add(TunnelLocalPortNumberAutoassign);
  130. for (int Index = Configuration->TunnelLocalPortNumberLow;
  131. Index <= Configuration->TunnelLocalPortNumberHigh; Index++)
  132. {
  133. TunnelLocalPortNumberEdit->Items->Add(IntToStr(Index));
  134. }
  135. }
  136. __finally
  137. {
  138. TunnelLocalPortNumberEdit->Items->EndUpdate();
  139. }
  140. HintLabel(ProxyTelnetCommandHintText, LoadStr(LOGIN_PROXY_COMMAND_PATTERNS_HINT));
  141. HintLabel(ProxyLocalCommandHintText, LoadStr(LOGIN_PROXY_COMMAND_PATTERNS_HINT));
  142. if (SessionTree->WindowProc != SessionTreeProc)
  143. {
  144. FOldSessionTreeProc = SessionTree->WindowProc;
  145. SessionTree->WindowProc = SessionTreeProc;
  146. }
  147. FtpsCombo->Items->Strings[1] = LoadStr(FTPS_IMPLICIT);
  148. FtpsCombo->Items->Strings[2] = LoadStr(FTPS_EXPLICIT_SSL);
  149. FtpsCombo->Items->Strings[3] = LoadStr(FTPS_EXPLICIT_TLS);
  150. WebDavsCombo->Items->Strings[0] = FtpsCombo->Items->Strings[0];
  151. WebDavsCombo->Items->Strings[1] = FtpsCombo->Items->Strings[1];
  152. BasicSshGroup->Top = BasicFtpGroup->Top;
  153. SitesIncrementalSearchLabel->AutoSize = false;
  154. SitesIncrementalSearchLabel->Left = SessionTree->Left;
  155. SitesIncrementalSearchLabel->Width = SessionTree->Width;
  156. SitesIncrementalSearchLabel->Top = SessionTree->BoundsRect.Bottom - SitesIncrementalSearchLabel->Height;
  157. SitesIncrementalSearchLabel->Visible = false;
  158. }
  159. //---------------------------------------------------------------------
  160. void __fastcall TLoginDialog::Init()
  161. {
  162. if (!FInitialized)
  163. {
  164. UseSystemSettingsPost(this, FSystemSettings);
  165. }
  166. else
  167. {
  168. UseSystemSettings(this, &FSystemSettings);
  169. }
  170. FInitialized = true;
  171. InstallPathWordBreakProc(RemoteDirectoryEdit);
  172. InstallPathWordBreakProc(LocalDirectoryEdit);
  173. InstallPathWordBreakProc(PrivateKeyEdit);
  174. InstallPathWordBreakProc(RecycleBinPathEdit);
  175. Caption = FORMAT(L"%s %s", (AppName, Caption));
  176. InitControls();
  177. FTreeLabels->Clear();
  178. int Index = 0;
  179. while (Index < PageControl->PageCount)
  180. {
  181. FTreeLabels->Add(PageControl->Pages[Index]->Caption);
  182. PageControl->Pages[Index]->Caption = L"";
  183. Index++;
  184. }
  185. UpdateNavigationTree();
  186. if ((FOptions & loLocalDirectory) == 0)
  187. {
  188. LocalDirectoryLabel->Visible = false;
  189. LocalDirectoryEdit->Visible = false;
  190. LocalDirectoryDescLabel->Visible = false;
  191. DirectoriesGroup->Height = RemoteDirectoryEdit->Top + RemoteDirectoryEdit->Height + 12;
  192. DirectoryOptionsGroup->Top = DirectoriesGroup->Top + DirectoriesGroup->Height + 8;
  193. }
  194. #ifdef NO_FILEZILLA
  195. assert(TransferProtocolCombo->Items->Count == FSPROTOCOL_COUNT - 2 - 1);
  196. TransferProtocolCombo->Items->Delete(TransferProtocolCombo->Items->Count - 1);
  197. #endif
  198. if ((StoredSessions && StoredSessions->Count &&
  199. (FSessionData->Name == StoredSessions->DefaultSettings->Name)) ||
  200. FLAGSET(FOptions, loSiteManager))
  201. {
  202. ChangePage(SessionListSheet);
  203. if (SessionTree->Items->Count > 0)
  204. {
  205. ActiveControl = SessionTree;
  206. SessionTree->Selected = SessionTree->Items->GetFirstNode();
  207. }
  208. else
  209. {
  210. ActiveControl = NewButton;
  211. }
  212. }
  213. else
  214. {
  215. EditSession();
  216. }
  217. UpdateControls();
  218. }
  219. //---------------------------------------------------------------------
  220. TTreeNode * __fastcall TLoginDialog::AddSessionPath(UnicodeString Path,
  221. bool CanCreate, bool IsWorkspace)
  222. {
  223. TTreeNode * Parent = NULL;
  224. while (!Path.IsEmpty())
  225. {
  226. UnicodeString Folder = ::CutToChar(Path, L'/', false);
  227. TTreeNode * Node =
  228. ((Parent == NULL) ? SessionTree->Items->GetFirstNode() : Parent->getFirstChild());
  229. // note that we allow folder with the same name as existing session
  230. // on the same level (see also SessionTreeEdited)
  231. while ((Node != NULL) && (IsSessionNode(Node) || !AnsiSameText(Node->Text, Folder)))
  232. {
  233. Node = Node->getNextSibling();
  234. }
  235. if (Node == NULL)
  236. {
  237. if (!CanCreate)
  238. {
  239. return NULL;
  240. }
  241. else
  242. {
  243. TTreeNode * AParent = Parent;
  244. Parent = SessionTree->Items->AddChild(Parent, Folder);
  245. // once workspace, forever workspace
  246. if (!IsWorkspaceNode(Parent))
  247. {
  248. if (IsWorkspace)
  249. {
  250. Parent->StateIndex = WorkspaceStateIndex;
  251. }
  252. else
  253. {
  254. UpdateFolderNode(Parent);
  255. }
  256. }
  257. // folders seem not to be sorted automatically (not having set the data property)
  258. if (AParent == NULL)
  259. {
  260. SessionTree->Items->AlphaSort();
  261. }
  262. else
  263. {
  264. AParent->AlphaSort();
  265. }
  266. }
  267. }
  268. else
  269. {
  270. Parent = Node;
  271. }
  272. }
  273. return Parent;
  274. }
  275. //---------------------------------------------------------------------
  276. bool __fastcall TLoginDialog::IsFolderNode(TTreeNode * Node)
  277. {
  278. return (Node != NULL) && (Node->Data == NULL) && (Node->StateIndex != WorkspaceStateIndex);
  279. }
  280. //---------------------------------------------------------------------
  281. bool __fastcall TLoginDialog::IsWorkspaceNode(TTreeNode * Node)
  282. {
  283. return (Node != NULL) && (Node->Data == NULL) && (Node->StateIndex == WorkspaceStateIndex);
  284. }
  285. //---------------------------------------------------------------------
  286. bool __fastcall TLoginDialog::IsFolderOrWorkspaceNode(TTreeNode * Node)
  287. {
  288. return (Node != NULL) && (Node->Data == NULL);
  289. }
  290. //---------------------------------------------------------------------
  291. bool __fastcall TLoginDialog::IsSessionNode(TTreeNode * Node)
  292. {
  293. return (Node != NULL) && (Node->Data != NULL);
  294. }
  295. //---------------------------------------------------------------------
  296. TSessionData * __fastcall TLoginDialog::GetNodeSession(TTreeNode * Node)
  297. {
  298. TSessionData * Data = static_cast<TSessionData *>(Node->Data);
  299. assert(Data != NULL);
  300. return Data;
  301. }
  302. //---------------------------------------------------------------------
  303. TTreeNode * __fastcall TLoginDialog::AddSession(TSessionData * Data)
  304. {
  305. TTreeNode * Parent = AddSessionPath(UnixExtractFilePath(Data->Name), true, Data->IsWorkspace);
  306. TTreeNode * Node = SessionTree->Items->AddChild(Parent, UnixExtractFileName(Data->Name));
  307. Node->Data = Data;
  308. return Node;
  309. }
  310. //---------------------------------------------------------------------
  311. void __fastcall TLoginDialog::DestroySession(TSessionData * Data)
  312. {
  313. if (FEditingSessionData == Data)
  314. {
  315. FEditingSessionData = NULL;
  316. }
  317. StoredSessions->Remove(Data);
  318. }
  319. //---------------------------------------------------------------------
  320. void __fastcall TLoginDialog::LoadSessions()
  321. {
  322. SessionTree->Items->BeginUpdate();
  323. try
  324. {
  325. SessionTree->Items->Clear();
  326. assert(StoredSessions != NULL);
  327. for (int Index = 0; Index < StoredSessions->Count; Index++)
  328. {
  329. AddSession(StoredSessions->Sessions[Index]);
  330. }
  331. }
  332. __finally
  333. {
  334. // folders seem not to be sorted automatically (not having set the data property)
  335. SessionTree->AlphaSort();
  336. SessionTree->Items->EndUpdate();
  337. }
  338. SessionTree->Selected = SessionTree->Items->GetFirstNode();
  339. UpdateControls();
  340. }
  341. //---------------------------------------------------------------------------
  342. void __fastcall TLoginDialog::UpdateFolderNode(TTreeNode * Node)
  343. {
  344. assert((Node->StateIndex == -1) ||
  345. (Node->StateIndex == OpenFolderStateIndex) || (Node->StateIndex == ClosedFolderStateIndex));
  346. Node->StateIndex = (Node->Expanded ? OpenFolderStateIndex : ClosedFolderStateIndex);
  347. }
  348. //---------------------------------------------------------------------------
  349. void __fastcall TLoginDialog::Default()
  350. {
  351. if (StoredSessions)
  352. {
  353. FSessionData->Assign(StoredSessions->DefaultSettings);
  354. }
  355. else
  356. {
  357. FSessionData->Default();
  358. }
  359. FEditingSessionData = NULL;
  360. LoadSession(FSessionData);
  361. FCurrentSessionName = "";
  362. FUpdatePortWithProtocol = true;
  363. }
  364. //---------------------------------------------------------------------
  365. void __fastcall TLoginDialog::LoadSession(TSessionData * aSessionData)
  366. {
  367. // it was always true
  368. assert(aSessionData == FSessionData);
  369. NoUpdate++;
  370. try
  371. {
  372. // Basic tab
  373. UserNameEdit->Text = aSessionData->UserName;
  374. PortNumberEdit->AsInteger = aSessionData->PortNumber;
  375. HostNameEdit->Text = aSessionData->HostName;
  376. PasswordEdit->Text = aSessionData->Password;
  377. FtpAccountEdit->Text = aSessionData->FtpAccount;
  378. PrivateKeyEdit->Text = aSessionData->PublicKeyFile;
  379. FtpsCombo->ItemIndex = aSessionData->Ftps;
  380. WebDavsCombo->ItemIndex = aSessionData->Ftps;
  381. FColor = (TColor)aSessionData->Color;
  382. bool AllowScpFallback;
  383. TransferProtocolCombo->ItemIndex =
  384. FSProtocolToIndex(aSessionData->FSProtocol, AllowScpFallback);
  385. AllowScpFallbackCheck->Checked = AllowScpFallback;
  386. FDefaultPort = DefaultPort();
  387. // Directories tab
  388. SynchronizeBrowsingCheck->Checked = aSessionData->SynchronizeBrowsing;
  389. LocalDirectoryEdit->Text = aSessionData->LocalDirectory;
  390. RemoteDirectoryEdit->Text = aSessionData->RemoteDirectory;
  391. UpdateDirectoriesCheck->Checked = aSessionData->UpdateDirectories;
  392. CacheDirectoriesCheck->Checked = aSessionData->CacheDirectories;
  393. CacheDirectoryChangesCheck->Checked = aSessionData->CacheDirectoryChanges;
  394. PreserveDirectoryChangesCheck->Checked = aSessionData->PreserveDirectoryChanges;
  395. ResolveSymlinksCheck->Checked = aSessionData->ResolveSymlinks;
  396. // Environment tab
  397. switch (aSessionData->DSTMode)
  398. {
  399. case dstmWin:
  400. DSTModeWinCheck->Checked = true;
  401. break;
  402. case dstmKeep:
  403. DSTModeKeepCheck->Checked = true;
  404. break;
  405. default:
  406. case dstmUnix:
  407. DSTModeUnixCheck->Checked = true;
  408. break;
  409. }
  410. if (aSessionData->EOLType == eolLF)
  411. {
  412. EOLTypeCombo->ItemIndex = 0;
  413. }
  414. else
  415. {
  416. EOLTypeCombo->ItemIndex = 1;
  417. }
  418. switch (aSessionData->NotUtf)
  419. {
  420. case asOn:
  421. UtfCombo->ItemIndex = 1;
  422. break;
  423. case asOff:
  424. UtfCombo->ItemIndex = 2;
  425. break;
  426. default:
  427. UtfCombo->ItemIndex = 0;
  428. break;
  429. }
  430. int TimeDifferenceMin = TimeToMinutes(aSessionData->TimeDifference);
  431. TimeDifferenceEdit->AsInteger = TimeDifferenceMin / MinsPerHour;
  432. TimeDifferenceMinutesEdit->AsInteger = TimeDifferenceMin % MinsPerHour;
  433. // Environment/Recycle bin tab
  434. DeleteToRecycleBinCheck->Checked = aSessionData->DeleteToRecycleBin;
  435. OverwrittenToRecycleBinCheck->Checked = aSessionData->OverwrittenToRecycleBin;
  436. RecycleBinPathEdit->Text =
  437. !aSessionData->RecycleBinPath.IsEmpty() ?
  438. aSessionData->RecycleBinPath : DefaultRecycleBinPath;
  439. // SFTP tab
  440. if (aSessionData->SftpServer.IsEmpty())
  441. {
  442. SftpServerEdit->Text = SftpServerEdit->Items->Strings[0];
  443. }
  444. else
  445. {
  446. SftpServerEdit->Text = aSessionData->SftpServer;
  447. }
  448. // hide selection, which is wrongly shown initially even when the box has not focus
  449. SftpServerEdit->SelLength = 0;
  450. SFTPMaxVersionCombo->ItemIndex = aSessionData->SFTPMaxVersion;
  451. #define LOAD_SFTP_BUG_COMBO(BUG) \
  452. ComboAutoSwitchLoad(SFTPBug ## BUG ## Combo, aSessionData->SFTPBug[sb ## BUG])
  453. LOAD_SFTP_BUG_COMBO(Symlink);
  454. LOAD_SFTP_BUG_COMBO(SignedTS);
  455. #undef LOAD_SFTP_BUG_COMBO
  456. // FTP tab
  457. PostLoginCommandsMemo->Lines->Text = aSessionData->PostLoginCommands;
  458. ComboAutoSwitchLoad(FtpListAllCombo, aSessionData->FtpListAll);
  459. ComboAutoSwitchLoad(FtpUseMlsdCombo, aSessionData->FtpUseMlsd);
  460. ComboAutoSwitchLoad(FtpForcePasvIpCombo, aSessionData->FtpForcePasvIp);
  461. // Authentication tab
  462. SshNoUserAuthCheck->Checked = aSessionData->SshNoUserAuth;
  463. TryAgentCheck->Checked = aSessionData->TryAgent;
  464. AuthTISCheck->Checked = aSessionData->AuthTIS;
  465. AuthKICheck->Checked = aSessionData->AuthKI;
  466. AuthKIPasswordCheck->Checked = aSessionData->AuthKIPassword;
  467. AuthGSSAPICheck3->Checked = aSessionData->AuthGSSAPI;
  468. GSSAPIFwdTGTCheck->Checked = aSessionData->GSSAPIFwdTGT;
  469. AgentFwdCheck->Checked = aSessionData->AgentFwd;
  470. // SSH tab
  471. Ssh2LegacyDESCheck->Checked = aSessionData->Ssh2DES;
  472. CompressionCheck->Checked = aSessionData->Compression;
  473. switch (aSessionData->SshProt) {
  474. case ssh1only: SshProt1onlyButton->Checked = true; break;
  475. case ssh1: SshProt1Button->Checked = true; break;
  476. case ssh2: SshProt2Button->Checked = true; break;
  477. case ssh2only: SshProt2onlyButton->Checked = true; break;
  478. }
  479. CipherListBox->Items->Clear();
  480. assert(CIPHER_NAME_WARN+CIPHER_COUNT-1 == CIPHER_NAME_ARCFOUR);
  481. for (int Index = 0; Index < CIPHER_COUNT; Index++)
  482. {
  483. CipherListBox->Items->AddObject(
  484. LoadStr(CIPHER_NAME_WARN+aSessionData->Cipher[Index]),
  485. (TObject*)aSessionData->Cipher[Index]);
  486. }
  487. // KEX tab
  488. KexListBox->Items->Clear();
  489. assert(KEX_NAME_WARN+KEX_COUNT-1 == KEX_NAME_RSA);
  490. for (int Index = 0; Index < KEX_COUNT; Index++)
  491. {
  492. KexListBox->Items->AddObject(
  493. LoadStr(KEX_NAME_WARN+aSessionData->Kex[Index]),
  494. (TObject*)aSessionData->Kex[Index]);
  495. }
  496. RekeyTimeEdit->AsInteger = aSessionData->RekeyTime;
  497. RekeyDataEdit->Text = aSessionData->RekeyData;
  498. // Connection tab
  499. FtpPasvModeCheck->Checked = aSessionData->FtpPasvMode;
  500. BufferSizeCheck->Checked = (aSessionData->SendBuf > 0) && aSessionData->SshSimple;
  501. switch (aSessionData->PingType)
  502. {
  503. case ptNullPacket:
  504. PingNullPacketButton->Checked = true;
  505. break;
  506. case ptDummyCommand:
  507. PingDummyCommandButton->Checked = true;
  508. break;
  509. default:
  510. PingOffButton->Checked = true;
  511. break;
  512. }
  513. PingIntervalSecEdit->AsInteger = aSessionData->PingInterval;
  514. switch (aSessionData->FtpPingType)
  515. {
  516. case ptDummyCommand:
  517. FtpPingDummyCommandButton->Checked = true;
  518. break;
  519. default:
  520. FtpPingOffButton->Checked = true;
  521. break;
  522. }
  523. FtpPingIntervalSecEdit->AsInteger = aSessionData->FtpPingInterval;
  524. TimeoutEdit->AsInteger = aSessionData->Timeout;
  525. switch (aSessionData->AddressFamily)
  526. {
  527. case afIPv4:
  528. IPv4Button->Checked = true;
  529. break;
  530. case afIPv6:
  531. IPv6Button->Checked = true;
  532. break;
  533. case afAuto:
  534. default:
  535. IPAutoButton->Checked = true;
  536. break;
  537. }
  538. // Shell tab
  539. if (aSessionData->DefaultShell)
  540. {
  541. ShellEdit->Text = ShellEdit->Items->Strings[0];
  542. }
  543. else
  544. {
  545. ShellEdit->Text = aSessionData->Shell;
  546. }
  547. // hide selection, which is wrongly shown initially even when the box has not focus
  548. ShellEdit->SelLength = 0;
  549. if (aSessionData->DetectReturnVar)
  550. {
  551. ReturnVarEdit->Text = ReturnVarEdit->Items->Strings[0];
  552. }
  553. else
  554. {
  555. ReturnVarEdit->Text = aSessionData->ReturnVar;
  556. }
  557. ReturnVarEdit->SelLength = 0;
  558. ListingCommandEdit->Text = aSessionData->ListingCommand;
  559. ListingCommandEdit->SelLength = 0;
  560. CheckBoxAutoSwitchLoad(LookupUserGroupsCheck, aSessionData->LookupUserGroups);
  561. ClearAliasesCheck->Checked = aSessionData->ClearAliases;
  562. IgnoreLsWarningsCheck->Checked = aSessionData->IgnoreLsWarnings;
  563. Scp1CompatibilityCheck->Checked = aSessionData->Scp1Compatibility;
  564. UnsetNationalVarsCheck->Checked = aSessionData->UnsetNationalVars;
  565. SCPLsFullTimeAutoCheck->Checked = (aSessionData->SCPLsFullTime != asOff);
  566. // Proxy tab
  567. SshProxyMethodCombo->ItemIndex = aSessionData->ProxyMethod;
  568. FtpProxyMethodCombo->ItemIndex = GetSupportedFtpProxyMethod(aSessionData->ProxyMethod);
  569. if (aSessionData->FtpProxyLogonType != 0)
  570. {
  571. FtpProxyMethodCombo->ItemIndex = LastSupportedFtpProxyMethod() + aSessionData->FtpProxyLogonType;
  572. }
  573. WebDavProxyMethodCombo->ItemIndex = GetSupportedWebDavProxyMethod(aSessionData->ProxyMethod);
  574. ProxyHostEdit->Text = aSessionData->ProxyHost;
  575. ProxyPortEdit->AsInteger = aSessionData->ProxyPort;
  576. ProxyUsernameEdit->Text = aSessionData->ProxyUsername;
  577. ProxyPasswordEdit->Text = aSessionData->ProxyPassword;
  578. ProxyTelnetCommandEdit->Text = aSessionData->ProxyTelnetCommand;
  579. ProxyLocalCommandEdit->Text = aSessionData->ProxyLocalCommand;
  580. ProxyLocalhostCheck->Checked = aSessionData->ProxyLocalhost;
  581. ProxyDNSCombo->ItemIndex = 2 - aSessionData->ProxyDNS;
  582. // Bugs tab
  583. #define LOAD_BUG_COMBO(BUG) \
  584. ComboAutoSwitchLoad(Bug ## BUG ## Combo, aSessionData->Bug[sb ## BUG])
  585. LOAD_BUG_COMBO(Ignore1);
  586. LOAD_BUG_COMBO(PlainPW1);
  587. LOAD_BUG_COMBO(RSA1);
  588. LOAD_BUG_COMBO(HMAC2);
  589. LOAD_BUG_COMBO(DeriveKey2);
  590. LOAD_BUG_COMBO(RSAPad2);
  591. LOAD_BUG_COMBO(PKSessID2);
  592. LOAD_BUG_COMBO(Rekey2);
  593. LOAD_BUG_COMBO(MaxPkt2);
  594. LOAD_BUG_COMBO(Ignore2);
  595. #undef LOAD_BUG_COMBO
  596. // Tunnel tab
  597. TunnelCheck->Checked = aSessionData->Tunnel;
  598. TunnelUserNameEdit->Text = aSessionData->TunnelUserName;
  599. TunnelPortNumberEdit->AsInteger = aSessionData->TunnelPortNumber;
  600. TunnelHostNameEdit->Text = aSessionData->TunnelHostName;
  601. TunnelPasswordEdit->Text = aSessionData->TunnelPassword;
  602. TunnelPrivateKeyEdit->Text = aSessionData->TunnelPublicKeyFile;
  603. if (aSessionData->TunnelAutoassignLocalPortNumber)
  604. {
  605. TunnelLocalPortNumberEdit->Text = TunnelLocalPortNumberEdit->Items->Strings[0];
  606. }
  607. else
  608. {
  609. TunnelLocalPortNumberEdit->Text = IntToStr(aSessionData->TunnelLocalPortNumber);
  610. }
  611. // hide selection, which is wrongly shown initially even when the box has not focus
  612. TunnelLocalPortNumberEdit->SelLength = 0;
  613. }
  614. __finally
  615. {
  616. NoUpdate--;
  617. UpdateControls();
  618. }
  619. if (UnixExtractFileName(aSessionData->Name) != aSessionData->DefaultSessionName)
  620. {
  621. FCurrentSessionName = aSessionData->Name;
  622. }
  623. else
  624. {
  625. FCurrentSessionName = L"";
  626. }
  627. FUpdatePortWithProtocol = true;
  628. }
  629. //---------------------------------------------------------------------
  630. void __fastcall TLoginDialog::SaveSession(TSessionData * aSessionData)
  631. {
  632. // it was always true
  633. assert(aSessionData == FSessionData);
  634. // Basic tab
  635. aSessionData->UserName = UserNameEdit->Text.Trim();
  636. aSessionData->PortNumber = PortNumberEdit->AsInteger;
  637. // must be loaded after UserName, because HostName may be in format user@host
  638. aSessionData->HostName = HostNameEdit->Text.Trim();
  639. aSessionData->Password = PasswordEdit->Text;
  640. aSessionData->FtpAccount = FtpAccountEdit->Text;
  641. aSessionData->PublicKeyFile = PrivateKeyEdit->Text;
  642. aSessionData->Ftps = GetFtps();
  643. aSessionData->Color = FColor;
  644. aSessionData->FSProtocol = GetFSProtocol();
  645. // SSH tab
  646. aSessionData->Compression = CompressionCheck->Checked;
  647. aSessionData->Ssh2DES = Ssh2LegacyDESCheck->Checked;
  648. if (SshProt1onlyButton->Checked) aSessionData->SshProt = ssh1only;
  649. else
  650. if (SshProt1Button->Checked) aSessionData->SshProt = ssh1;
  651. else
  652. if (SshProt2Button->Checked) aSessionData->SshProt = ssh2;
  653. else aSessionData->SshProt = ssh2only;
  654. for (int Index = 0; Index < CIPHER_COUNT; Index++)
  655. {
  656. aSessionData->Cipher[Index] = (TCipher)CipherListBox->Items->Objects[Index];
  657. }
  658. // Kex tab
  659. for (int Index = 0; Index < KEX_COUNT; Index++)
  660. {
  661. aSessionData->Kex[Index] = (TKex)KexListBox->Items->Objects[Index];
  662. }
  663. aSessionData->RekeyTime = RekeyTimeEdit->AsInteger;
  664. aSessionData->RekeyData = RekeyDataEdit->Text;
  665. // Authentication tab
  666. aSessionData->SshNoUserAuth = SshNoUserAuthCheck->Checked;
  667. aSessionData->TryAgent = TryAgentCheck->Checked;
  668. aSessionData->AuthTIS = AuthTISCheck->Checked;
  669. aSessionData->AuthKI = AuthKICheck->Checked;
  670. aSessionData->AuthKIPassword = AuthKIPasswordCheck->Checked;
  671. aSessionData->AuthGSSAPI = AuthGSSAPICheck3->Checked;
  672. aSessionData->GSSAPIFwdTGT = GSSAPIFwdTGTCheck->Checked;
  673. aSessionData->AgentFwd = AgentFwdCheck->Checked;
  674. // Connection tab
  675. aSessionData->FtpPasvMode = FtpPasvModeCheck->Checked;
  676. aSessionData->SendBuf = BufferSizeCheck->Checked ? DefaultSendBuf : 0;
  677. aSessionData->SshSimple = BufferSizeCheck->Checked;
  678. if (PingNullPacketButton->Checked)
  679. {
  680. aSessionData->PingType = ptNullPacket;
  681. }
  682. else if (PingDummyCommandButton->Checked)
  683. {
  684. aSessionData->PingType = ptDummyCommand;
  685. }
  686. else
  687. {
  688. aSessionData->PingType = ptOff;
  689. }
  690. aSessionData->PingInterval = PingIntervalSecEdit->AsInteger;
  691. aSessionData->FtpPingType = (FtpPingDummyCommandButton->Checked ? ptDummyCommand : ptOff);
  692. aSessionData->FtpPingInterval = FtpPingIntervalSecEdit->AsInteger;
  693. aSessionData->Timeout = TimeoutEdit->AsInteger;
  694. if (IPv4Button->Checked)
  695. {
  696. aSessionData->AddressFamily = afIPv4;
  697. }
  698. else if (IPv6Button->Checked)
  699. {
  700. aSessionData->AddressFamily = afIPv6;
  701. }
  702. else
  703. {
  704. aSessionData->AddressFamily = afAuto;
  705. }
  706. // Directories tab
  707. aSessionData->SynchronizeBrowsing = SynchronizeBrowsingCheck->Checked;
  708. aSessionData->LocalDirectory = LocalDirectoryEdit->Text;
  709. aSessionData->RemoteDirectory = RemoteDirectoryEdit->Text;
  710. aSessionData->UpdateDirectories = UpdateDirectoriesCheck->Checked;
  711. aSessionData->CacheDirectories = CacheDirectoriesCheck->Checked;
  712. aSessionData->CacheDirectoryChanges = CacheDirectoryChangesCheck->Checked;
  713. aSessionData->PreserveDirectoryChanges = PreserveDirectoryChangesCheck->Checked;
  714. aSessionData->ResolveSymlinks = ResolveSymlinksCheck->Checked;
  715. // Environment tab
  716. if (DSTModeUnixCheck->Checked) aSessionData->DSTMode = dstmUnix;
  717. else
  718. if (DSTModeKeepCheck->Checked) aSessionData->DSTMode = dstmKeep;
  719. else aSessionData->DSTMode = dstmWin;
  720. if (EOLTypeCombo->ItemIndex == 0) aSessionData->EOLType = eolLF;
  721. else aSessionData->EOLType = eolCRLF;
  722. switch (UtfCombo->ItemIndex)
  723. {
  724. case 1:
  725. aSessionData->NotUtf = asOn;
  726. break;
  727. case 2:
  728. aSessionData->NotUtf = asOff;
  729. break;
  730. default:
  731. aSessionData->NotUtf = asAuto;
  732. break;
  733. }
  734. aSessionData->TimeDifference =
  735. (double(TimeDifferenceEdit->AsInteger) / HoursPerDay) +
  736. (double(TimeDifferenceMinutesEdit->AsInteger) / MinsPerDay);
  737. // Environment/Recycle bin tab
  738. aSessionData->DeleteToRecycleBin = DeleteToRecycleBinCheck->Checked;
  739. aSessionData->OverwrittenToRecycleBin = OverwrittenToRecycleBinCheck->Checked;
  740. aSessionData->RecycleBinPath =
  741. aSessionData->DeleteToRecycleBin || aSessionData->OverwrittenToRecycleBin ||
  742. (RecycleBinPathEdit->Text != DefaultRecycleBinPath) ?
  743. RecycleBinPathEdit->Text : UnicodeString();
  744. // SCP tab
  745. aSessionData->DefaultShell = (ShellEdit->Text == ShellEdit->Items->Strings[0]);
  746. aSessionData->Shell = (aSessionData->DefaultShell ? UnicodeString() : ShellEdit->Text);
  747. aSessionData->DetectReturnVar = (ReturnVarEdit->Text == ReturnVarEdit->Items->Strings[0]);
  748. aSessionData->ReturnVar = (aSessionData->DetectReturnVar ? UnicodeString() : ReturnVarEdit->Text);
  749. aSessionData->ListingCommand = ListingCommandEdit->Text;
  750. aSessionData->LookupUserGroups = CheckBoxAutoSwitchSave(LookupUserGroupsCheck);
  751. aSessionData->ClearAliases = ClearAliasesCheck->Checked;
  752. aSessionData->IgnoreLsWarnings = IgnoreLsWarningsCheck->Checked;
  753. aSessionData->Scp1Compatibility = Scp1CompatibilityCheck->Checked;
  754. aSessionData->UnsetNationalVars = UnsetNationalVarsCheck->Checked;
  755. aSessionData->SCPLsFullTime = SCPLsFullTimeAutoCheck->Checked ? asAuto : asOff;
  756. // SFTP tab
  757. aSessionData->SftpServer =
  758. ((SftpServerEdit->Text == SftpServerEdit->Items->Strings[0]) ?
  759. UnicodeString() : SftpServerEdit->Text);
  760. aSessionData->SFTPMaxVersion = SFTPMaxVersionCombo->ItemIndex;
  761. #define SAVE_SFTP_BUG_COMBO(BUG) aSessionData->SFTPBug[sb ## BUG] = ComboAutoSwitchSave(SFTPBug ## BUG ## Combo);
  762. SAVE_SFTP_BUG_COMBO(Symlink);
  763. SAVE_SFTP_BUG_COMBO(SignedTS);
  764. #undef SAVE_SFTP_BUG_COMBO
  765. // FTP tab
  766. aSessionData->PostLoginCommands = PostLoginCommandsMemo->Lines->Text;
  767. aSessionData->FtpListAll = ComboAutoSwitchSave(FtpListAllCombo);
  768. aSessionData->FtpUseMlsd = ComboAutoSwitchSave(FtpUseMlsdCombo);
  769. aSessionData->FtpForcePasvIp = ComboAutoSwitchSave(FtpForcePasvIpCombo);
  770. // Proxy tab
  771. aSessionData->ProxyMethod = GetProxyMethod();
  772. aSessionData->FtpProxyLogonType = GetFtpProxyLogonType();
  773. aSessionData->ProxyHost = ProxyHostEdit->Text;
  774. aSessionData->ProxyPort = ProxyPortEdit->AsInteger;
  775. aSessionData->ProxyUsername = ProxyUsernameEdit->Text;
  776. aSessionData->ProxyPassword = ProxyPasswordEdit->Text;
  777. aSessionData->ProxyTelnetCommand = ProxyTelnetCommandEdit->Text;
  778. aSessionData->ProxyLocalCommand = ProxyLocalCommandEdit->Text;
  779. aSessionData->ProxyLocalhost = ProxyLocalhostCheck->Checked;
  780. aSessionData->ProxyDNS = (TAutoSwitch)(2 - ProxyDNSCombo->ItemIndex);
  781. // Bugs tab
  782. #define SAVE_BUG_COMBO(BUG) aSessionData->Bug[sb ## BUG] = ComboAutoSwitchSave(Bug ## BUG ## Combo)
  783. SAVE_BUG_COMBO(Ignore1);
  784. SAVE_BUG_COMBO(PlainPW1);
  785. SAVE_BUG_COMBO(RSA1);
  786. SAVE_BUG_COMBO(HMAC2);
  787. SAVE_BUG_COMBO(DeriveKey2);
  788. SAVE_BUG_COMBO(RSAPad2);
  789. SAVE_BUG_COMBO(PKSessID2);
  790. SAVE_BUG_COMBO(Rekey2);
  791. SAVE_BUG_COMBO(MaxPkt2);
  792. SAVE_BUG_COMBO(Ignore2);
  793. #undef SAVE_BUG_COMBO
  794. // Tunnel tab
  795. aSessionData->Tunnel = TunnelCheck->Checked;
  796. aSessionData->TunnelUserName = TunnelUserNameEdit->Text;
  797. aSessionData->TunnelPortNumber = TunnelPortNumberEdit->AsInteger;
  798. aSessionData->TunnelHostName = TunnelHostNameEdit->Text;
  799. aSessionData->TunnelPassword = TunnelPasswordEdit->Text;
  800. aSessionData->TunnelPublicKeyFile = TunnelPrivateKeyEdit->Text;
  801. if (TunnelLocalPortNumberEdit->Text == TunnelLocalPortNumberEdit->Items->Strings[0])
  802. {
  803. aSessionData->TunnelLocalPortNumber = 0;
  804. }
  805. else
  806. {
  807. aSessionData->TunnelLocalPortNumber = StrToIntDef(TunnelLocalPortNumberEdit->Text, 0);
  808. }
  809. UnicodeString Name = FCurrentSessionName;
  810. if (Name.IsEmpty())
  811. {
  812. Name = UnixIncludeTrailingBackslash(SessionNodePath(CurrentSessionFolderNode())) +
  813. aSessionData->DefaultSessionName;
  814. }
  815. aSessionData->Name = Name;
  816. }
  817. //---------------------------------------------------------------------
  818. void __fastcall TLoginDialog::UpdateNavigationTree()
  819. {
  820. TTreeNode * ActiveNode = NULL;
  821. NoUpdate++;
  822. try
  823. {
  824. int Index = 0;
  825. TTreeNode * PrevNode = NULL;
  826. while (Index < PageControl->PageCount)
  827. {
  828. TTabSheet * Tab = PageControl->Pages[Index];
  829. if (Tab->Enabled)
  830. {
  831. bool Indented = ((Tab->Tag % 100) == 2);
  832. UnicodeString Label = FTreeLabels->Strings[Index];
  833. TTreeNode * Node;
  834. if (PrevNode == NULL)
  835. {
  836. assert(!Indented);
  837. Node = NavigationTree->Items->GetFirstNode();
  838. }
  839. else
  840. {
  841. if (Indented)
  842. {
  843. if (PrevNode->Level == 0)
  844. {
  845. Node = PrevNode->getFirstChild();
  846. if (Node == NULL)
  847. {
  848. Node = NavigationTree->Items->AddChild(PrevNode, Label);
  849. }
  850. }
  851. else
  852. {
  853. Node = PrevNode->getNextSibling();
  854. if (Node == NULL)
  855. {
  856. Node = NavigationTree->Items->Add(PrevNode, Label);
  857. }
  858. }
  859. }
  860. else
  861. {
  862. if (PrevNode->Level == 0)
  863. {
  864. // delete all excess children of previous top level node
  865. while ((Node = PrevNode->GetNext()) != PrevNode->getNextSibling())
  866. {
  867. Node->Delete();
  868. }
  869. Node = PrevNode->getNextSibling();
  870. if (Node == NULL)
  871. {
  872. Node = NavigationTree->Items->Add(PrevNode, Label);
  873. }
  874. }
  875. else
  876. {
  877. // delete all excess children of previous top level node
  878. while ((Node = PrevNode->getNextSibling()) != NULL)
  879. {
  880. Node->Delete();
  881. }
  882. Node = PrevNode->GetNext();
  883. if (Node == NULL)
  884. {
  885. Node = NavigationTree->Items->Add(NULL, Label);
  886. }
  887. }
  888. }
  889. }
  890. Node->Text = Label;
  891. Node->SelectedIndex = reinterpret_cast<int>(Tab);
  892. PrevNode = Node;
  893. if (PageControl->ActivePage == Tab)
  894. {
  895. Node->Selected = true;
  896. ActiveNode = Node;
  897. }
  898. }
  899. Index++;
  900. }
  901. TTreeNode * Node;
  902. while ((Node = PrevNode->GetNext()) != NULL)
  903. {
  904. Node->Delete();
  905. }
  906. NavigationTree->FullExpand();
  907. }
  908. __finally
  909. {
  910. NoUpdate--;
  911. }
  912. // node of active page was hidden
  913. if (ActiveNode == NULL)
  914. {
  915. ChangePage(BasicSheet);
  916. }
  917. }
  918. //---------------------------------------------------------------------
  919. void __fastcall TLoginDialog::UpdateControls()
  920. {
  921. if (Visible && FInitialized)
  922. {
  923. NoUpdate++;
  924. try
  925. {
  926. TFSProtocol FSProtocol = GetFSProtocol();
  927. bool SshProtocol = IsSshProtocol(FSProtocol);
  928. bool SftpProtocol = (FSProtocol == fsSFTPonly) || (FSProtocol == fsSFTP);
  929. bool ScpProtocol = (FSProtocol == fsSCPonly);
  930. bool FtpProtocol = (FSProtocol == fsFTP);
  931. bool WebDavProtocol = (FSProtocol == fsWebDAV);
  932. bool Advanced = ShowAdvancedLoginOptionsCheck->Checked;
  933. // basic/session sheet
  934. FtpsCombo->Visible = FtpProtocol;
  935. FtpsLabel->Visible = FtpsCombo->Visible;
  936. WebDavsCombo->Visible = WebDavProtocol;
  937. WebDavsLabel->Visible = WebDavsCombo->Visible;
  938. BasicSshGroup->Visible = SshProtocol;
  939. BasicFtpGroup->Visible = FtpProtocol;
  940. AnonymousLoginCheck->Checked =
  941. SameText(UserNameEdit->Text, AnonymousUserName) &&
  942. SameText(PasswordEdit->Text, AnonymousPassword);
  943. TGroupBox * BottomGroup =
  944. (SshProtocol ? BasicSshGroup : (FtpProtocol ? BasicFtpGroup : BasicGroup));
  945. ColorButton->Top = BottomGroup->Top + BottomGroup->Height + 8;
  946. // log sheet
  947. LogSheet->Enabled = Advanced;
  948. // connection sheet
  949. ConnSheet->Enabled = Advanced;
  950. EnableControl(FtpPasvModeCheck, FtpProtocol);
  951. if (FtpProtocol &&
  952. (FtpProxyMethodCombo->ItemIndex != ::pmNone) &&
  953. SupportedFtpProxyMethod(FtpProxyMethodCombo->ItemIndex) &&
  954. !FtpPasvModeCheck->Checked)
  955. {
  956. FtpPasvModeCheck->Checked = true;
  957. MessageDialog(LoadStr(FTP_PASV_MODE_REQUIRED), qtInformation, qaOK);
  958. }
  959. EnableControl(BufferSizeCheck, SshProtocol);
  960. PingGroup->Visible = !FtpProtocol;
  961. EnableControl(PingGroup, SshProtocol);
  962. EnableControl(PingIntervalSecEdit, PingGroup->Enabled && !PingOffButton->Checked);
  963. EnableControl(PingIntervalLabel, PingGroup->Enabled && PingIntervalSecEdit->Enabled);
  964. FtpPingGroup->Visible = FtpProtocol;
  965. EnableControl(FtpPingIntervalSecEdit, !FtpPingOffButton->Checked);
  966. EnableControl(FtpPingIntervalLabel, FtpPingIntervalSecEdit->Enabled);
  967. EnableControl(IPvGroup, SshProtocol || FtpProtocol);
  968. EnableControl(IPAutoButton, IPvGroup->Enabled && SshProtocol);
  969. // sites sheet
  970. EnableControl(SessionTree, SessionTree->Items->Count > 0);
  971. if (SitesIncrementalSearchLabel->Visible != !FSitesIncrementalSearch.IsEmpty())
  972. {
  973. if (FSitesIncrementalSearch.IsEmpty())
  974. {
  975. SitesIncrementalSearchLabel->Visible = false;
  976. SessionTree->Height = SitesIncrementalSearchLabel->BoundsRect.Bottom - SessionTree->Top;
  977. }
  978. else
  979. {
  980. SitesIncrementalSearchLabel->Visible = true;
  981. SessionTree->Height = SitesIncrementalSearchLabel->BoundsRect.Top - SessionTree->Top;
  982. }
  983. }
  984. if (!FSitesIncrementalSearch.IsEmpty())
  985. {
  986. SitesIncrementalSearchLabel->Caption =
  987. L" " + FMTLOAD(LOGIN_SITES_INC_SEARCH, (FSitesIncrementalSearch)) +
  988. (FSitesIncrementalSearchHaveNext ? L" " + LoadStr(LOGIN_SITES_NEXT_SEARCH) : UnicodeString());
  989. }
  990. // ssh/authentication sheet
  991. AuthSheet->Enabled = SshProtocol && Advanced;
  992. EnableControl(SshNoUserAuthCheck, !SshProt1onlyButton->Checked);
  993. EnableControl(AuthenticationGroup,
  994. !SshNoUserAuthCheck->Enabled || !SshNoUserAuthCheck->Checked);
  995. EnableControl(AuthTISCheck, AuthenticationGroup->Enabled && !SshProt2onlyButton->Checked);
  996. EnableControl(AuthKICheck, AuthenticationGroup->Enabled && !SshProt1onlyButton->Checked);
  997. EnableControl(AuthKIPasswordCheck,
  998. AuthenticationGroup->Enabled &&
  999. ((AuthTISCheck->Enabled && AuthTISCheck->Checked) ||
  1000. (AuthKICheck->Enabled && AuthKICheck->Checked)));
  1001. EnableControl(AuthGSSAPICheck3,
  1002. AuthenticationGroup->Enabled && !SshProt1onlyButton->Checked);
  1003. EnableControl(GSSAPIFwdTGTCheck,
  1004. AuthGSSAPICheck3->Enabled && AuthGSSAPICheck3->Checked);
  1005. // ssh sheet
  1006. AdvancedSheet->Enabled = SshProtocol;
  1007. EnableControl(CipherUpButton, CipherListBox->ItemIndex > 0);
  1008. EnableControl(CipherDownButton, CipherListBox->ItemIndex >= 0 &&
  1009. CipherListBox->ItemIndex < CipherListBox->Items->Count-1);
  1010. EnableControl(Ssh2LegacyDESCheck, !SshProt1onlyButton->Checked);
  1011. // ssh/kex sheet
  1012. KexSheet->Enabled = SshProtocol && Advanced && !SshProt1onlyButton->Checked &&
  1013. (BugRekey2Combo->ItemIndex != 2);
  1014. EnableControl(KexUpButton, KexListBox->ItemIndex > 0);
  1015. EnableControl(KexDownButton, KexListBox->ItemIndex >= 0 &&
  1016. KexListBox->ItemIndex < KexListBox->Items->Count-1);
  1017. // ssh/bugs sheet
  1018. BugsSheet->Enabled = SshProtocol && Advanced;
  1019. EnableControl(BugIgnore1Combo, !SshProt2onlyButton->Checked);
  1020. EnableControl(BugIgnore1Label, BugIgnore1Combo->Enabled);
  1021. EnableControl(BugPlainPW1Combo, !SshProt2onlyButton->Checked);
  1022. EnableControl(BugPlainPW1Label, BugPlainPW1Combo->Enabled);
  1023. EnableControl(BugRSA1Combo, !SshProt2onlyButton->Checked);
  1024. EnableControl(BugRSA1Label, BugRSA1Combo->Enabled);
  1025. EnableControl(BugHMAC2Combo, !SshProt1onlyButton->Checked);
  1026. EnableControl(BugHMAC2Label, BugHMAC2Combo->Enabled);
  1027. EnableControl(BugDeriveKey2Combo, !SshProt1onlyButton->Checked);
  1028. EnableControl(BugDeriveKey2Label, BugDeriveKey2Combo->Enabled);
  1029. EnableControl(BugRSAPad2Combo, !SshProt1onlyButton->Checked);
  1030. EnableControl(BugRSAPad2Label, BugRSAPad2Combo->Enabled);
  1031. EnableControl(BugPKSessID2Combo, !SshProt1onlyButton->Checked);
  1032. EnableControl(BugPKSessID2Label, BugPKSessID2Combo->Enabled);
  1033. EnableControl(BugRekey2Combo, !SshProt1onlyButton->Checked);
  1034. EnableControl(BugRekey2Label, BugRekey2Combo->Enabled);
  1035. EnableControl(BugMaxPkt2Combo, !SshProt1onlyButton->Checked);
  1036. EnableControl(BugMaxPkt2Label, BugMaxPkt2Combo->Enabled);
  1037. EnableControl(BugIgnore2Combo, !SshProt1onlyButton->Checked);
  1038. EnableControl(BugIgnore2Label, BugIgnore2Combo->Enabled);
  1039. // connection/proxy sheet
  1040. TComboBox * ProxyMethodCombo =
  1041. (SshProtocol ? SshProxyMethodCombo : (FtpProtocol ? FtpProxyMethodCombo : WebDavProxyMethodCombo));
  1042. TProxyMethod ProxyMethod = GetProxyMethod();
  1043. ProxyMethodCombo->Visible = true;
  1044. ProxyMethodLabel->FocusControl = ProxyMethodCombo;
  1045. if (!SshProtocol)
  1046. {
  1047. SshProxyMethodCombo->Visible = false;
  1048. SshProxyMethodCombo->ItemIndex = ProxyMethod;
  1049. }
  1050. if (!FtpProtocol)
  1051. {
  1052. FtpProxyMethodCombo->Visible = false;
  1053. FtpProxyMethodCombo->ItemIndex = GetSupportedFtpProxyMethod(ProxyMethod);
  1054. }
  1055. if (!WebDavProtocol)
  1056. {
  1057. WebDavProxyMethodCombo->Visible = false;
  1058. WebDavProxyMethodCombo->ItemIndex = GetSupportedWebDavProxyMethod(ProxyMethod);
  1059. }
  1060. ProxySheet->Enabled = Advanced;
  1061. int FtpProxyLogonType = GetFtpProxyLogonType();
  1062. UnicodeString ProxyCommand =
  1063. ((ProxyMethod == pmCmd) ?
  1064. ProxyLocalCommandEdit->Text : ProxyTelnetCommandEdit->Text);
  1065. EnableControl(ProxyHostEdit,
  1066. (ProxyMethod == pmSocks4) ||
  1067. (ProxyMethod == pmSocks5) ||
  1068. (ProxyMethod == pmHTTP) ||
  1069. (ProxyMethod == pmTelnet) ||
  1070. ((ProxyMethod == pmCmd) && AnsiContainsText(ProxyCommand, L"%proxyhost")) ||
  1071. (FtpProxyLogonType > 0));
  1072. EnableControl(ProxyHostLabel, ProxyHostEdit->Enabled);
  1073. EnableControl(ProxyPortEdit,
  1074. (ProxyMethod == pmSocks4) ||
  1075. (ProxyMethod == pmSocks5) ||
  1076. (ProxyMethod == pmHTTP) ||
  1077. (ProxyMethod == pmTelnet) ||
  1078. ((ProxyMethod == pmCmd) && AnsiContainsText(ProxyCommand, L"%proxyport")) ||
  1079. (FtpProxyLogonType > 0));
  1080. EnableControl(ProxyPortLabel, ProxyPortEdit->Enabled);
  1081. EnableControl(ProxyUsernameEdit,
  1082. // FZAPI does not support username for SOCKS4
  1083. ((ProxyMethod == pmSocks4) && (SshProtocol || WebDavProtocol)) ||
  1084. (ProxyMethod == pmSocks5) ||
  1085. (ProxyMethod == pmHTTP) ||
  1086. (((ProxyMethod == pmTelnet) ||
  1087. (ProxyMethod == pmCmd)) &&
  1088. AnsiContainsText(ProxyCommand, L"%user")) ||
  1089. ((FtpProxyLogonType > 0) && (FtpProxyLogonType != 3) && (FtpProxyLogonType != 5)));
  1090. EnableControl(ProxyUsernameLabel, ProxyUsernameEdit->Enabled);
  1091. EnableControl(ProxyPasswordEdit,
  1092. (ProxyMethod == pmSocks5) ||
  1093. (ProxyMethod == pmHTTP) ||
  1094. (((ProxyMethod == pmTelnet) ||
  1095. (ProxyMethod == pmCmd)) &&
  1096. AnsiContainsText(ProxyCommand, L"%pass")) ||
  1097. ((FtpProxyLogonType > 0) && (FtpProxyLogonType != 3) && (FtpProxyLogonType != 5)));
  1098. EnableControl(ProxyPasswordLabel, ProxyPasswordEdit->Enabled);
  1099. bool ProxySettings = (ProxyMethod != ::pmNone) && SshProtocol;
  1100. EnableControl(ProxySettingsGroup, ProxySettings);
  1101. EnableControl(ProxyTelnetCommandEdit,
  1102. ProxySettings && (ProxyMethod == pmTelnet));
  1103. EnableControl(ProxyTelnetCommandLabel, ProxyTelnetCommandEdit->Enabled);
  1104. EnableControl(ProxyTelnetCommandHintText, ProxyTelnetCommandEdit->Enabled);
  1105. ProxyLocalCommandEdit->Visible = (ProxyMethod == pmCmd);
  1106. ProxyLocalCommandLabel->Visible = ProxyLocalCommandEdit->Visible;
  1107. ProxyLocalCommandBrowseButton->Visible = ProxyLocalCommandEdit->Visible;
  1108. ProxyLocalCommandHintText->Visible = ProxyLocalCommandEdit->Visible;
  1109. ProxyTelnetCommandEdit->Visible = !ProxyLocalCommandEdit->Visible;
  1110. ProxyTelnetCommandLabel->Visible = ProxyTelnetCommandEdit->Visible;
  1111. ProxyTelnetCommandHintText->Visible = ProxyTelnetCommandEdit->Visible;
  1112. // environment/directories sheet
  1113. DirectoryOptionsGroup->Visible = Advanced;
  1114. EnableControl(SynchronizeBrowsingCheck,
  1115. WinConfiguration->PreservePanelState &&
  1116. !WinConfiguration->ScpCommander.PreserveLocalDirectory);
  1117. EnableControl(CacheDirectoryChangesCheck,
  1118. (!ScpProtocol || CacheDirectoriesCheck->Checked) && DirectoriesSheet->Enabled);
  1119. EnableControl(PreserveDirectoryChangesCheck,
  1120. CacheDirectoryChangesCheck->Enabled && CacheDirectoryChangesCheck->Checked &&
  1121. DirectoriesSheet->Enabled);
  1122. EnableControl(ResolveSymlinksCheck, (SftpProtocol || ScpProtocol) && DirectoriesSheet->Enabled);
  1123. // environment sheet
  1124. EnableControl(EOLTypeCombo, (SftpProtocol || ScpProtocol) && EnvironmentSheet->Enabled);
  1125. EnableControl(EOLTypeLabel, EOLTypeCombo->Enabled);
  1126. EnableControl(DSTModeGroup, (SftpProtocol || ScpProtocol) && EnvironmentSheet->Enabled);
  1127. EnableControl(DSTModeKeepCheck, UsesDaylightHack() && DSTModeGroup->Enabled);
  1128. EnableControl(UtfCombo, (SftpProtocol || FtpProtocol) && EnvironmentSheet->Enabled);
  1129. EnableControl(UtfLabel, UtfCombo->Enabled);
  1130. // should be enabled for fsSFTP (SCP fallback) too, but it would cause confusion
  1131. EnableControl(TimeDifferenceEdit,
  1132. ((FtpProtocol && (ComboAutoSwitchSave(FtpUseMlsdCombo) == asOff)) ||
  1133. ScpProtocol) &&
  1134. EnvironmentSheet->Enabled);
  1135. EnableControl(TimeDifferenceLabel, TimeDifferenceEdit->Enabled);
  1136. EnableControl(TimeDifferenceHoursLabel, TimeDifferenceEdit->Enabled);
  1137. EnableControl(TimeDifferenceMinutesEdit, TimeDifferenceEdit->Enabled);
  1138. EnableControl(TimeDifferenceMinutesLabel, TimeDifferenceEdit->Enabled);
  1139. // environment/recycle bin sheet
  1140. RecycleBinSheet->Enabled = Advanced;
  1141. EnableControl(OverwrittenToRecycleBinCheck, SftpProtocol && RecycleBinSheet->Enabled);
  1142. EnableControl(RecycleBinPathEdit,
  1143. (DeleteToRecycleBinCheck->Enabled && DeleteToRecycleBinCheck->Checked) ||
  1144. (OverwrittenToRecycleBinCheck->Enabled && OverwrittenToRecycleBinCheck->Checked) &&
  1145. RecycleBinSheet->Enabled);
  1146. EnableControl(RecycleBinPathLabel, RecycleBinPathEdit->Enabled &&
  1147. RecycleBinSheet->Enabled);
  1148. // environment/sftp sheet
  1149. SftpSheet->Enabled = Advanced && SftpProtocol;
  1150. // environment/scp/shell
  1151. ScpSheet->Enabled = Advanced && SshProtocol;
  1152. // disable also for SFTP with SCP fallback, as if someone wants to configure
  1153. // these he/she probably intends to use SCP and should explicitly select it.
  1154. // (note that these are not used for secondary shell session)
  1155. EnableControl(ScpLsOptionsGroup, ScpProtocol);
  1156. EnableControl(OtherShellOptionsGroup, ScpProtocol);
  1157. // environment/ftp
  1158. FtpSheet->Enabled = Advanced && FtpProtocol;
  1159. EnableControl(FtpListAllCombo,
  1160. (ComboAutoSwitchSave(FtpUseMlsdCombo) == asOff));
  1161. EnableControl(FtpListAllLabel, FtpListAllCombo->Enabled);
  1162. EnableControl(FtpForcePasvIpCombo,
  1163. FtpPasvModeCheck->Checked &&
  1164. (IPAutoButton->Checked || IPv4Button->Checked));
  1165. EnableControl(FtpForcePasvIpLabel, FtpForcePasvIpCombo->Enabled);
  1166. // tunnel sheet
  1167. TunnelSheet->Enabled = Advanced && SshProtocol;
  1168. // probably needless
  1169. EnableControl(TunnelSessionGroup, TunnelCheck->Enabled && TunnelCheck->Checked);
  1170. EnableControl(TunnelOptionsGroup, TunnelSessionGroup->Enabled);
  1171. // preferences sheet
  1172. GeneralSheet->Enabled = FLAGSET(FOptions, loPreferences);
  1173. // this methods saves us from calling GetSessionData,
  1174. // which breaks changing locale (session data are not preserved,
  1175. // as we would overwrite them with non-initialized control data)
  1176. if (PageControl->ActivePage == SessionListSheet)
  1177. {
  1178. LoginButton->Default =
  1179. (SelectedSession != NULL) &&
  1180. FStoredSessions->CanLogin(SelectedSession);
  1181. }
  1182. else
  1183. {
  1184. LoginButton->Default = true;
  1185. }
  1186. LoadButton->Default = !LoginButton->Default;
  1187. SetDefaultSessionButton->Visible = !SupportsSplitButton();
  1188. AboutButton->Visible = (FOptions & loAbout);
  1189. LanguagesButton->Visible = (FOptions & loLanguage);
  1190. ShellIconsButton->Visible = (FOptions & loTools);
  1191. ToolsMenuButton->Visible = (FOptions & loTools);
  1192. LoggingFrame->EnableLogWindow = (FOptions & loLogWindow);
  1193. ColorButton->Visible = (FOptions & loColor);
  1194. UpdateNavigationTree();
  1195. }
  1196. __finally
  1197. {
  1198. NoUpdate--;
  1199. }
  1200. }
  1201. }
  1202. //---------------------------------------------------------------------------
  1203. void __fastcall TLoginDialog::DataChange(TObject * /*Sender*/)
  1204. {
  1205. if (NoUpdate == 0)
  1206. {
  1207. UpdateControls();
  1208. }
  1209. }
  1210. //---------------------------------------------------------------------------
  1211. void __fastcall TLoginDialog::FormShow(TObject * /*Sender*/)
  1212. {
  1213. if (!FInitialized)
  1214. {
  1215. Init();
  1216. TSessionData * Data = GetSessionData();
  1217. if (Data == FSessionData)
  1218. {
  1219. LoadSession(Data);
  1220. }
  1221. else
  1222. {
  1223. Default();
  1224. }
  1225. }
  1226. if (FLocaleChanging)
  1227. {
  1228. Init();
  1229. LoadSession(FSessionData);
  1230. ChangePage(FSavedTab);
  1231. if (FSavedSession >= 0)
  1232. {
  1233. SessionTree->Selected = SessionTree->Items->Item[FSavedSession];
  1234. SessionTree->Selected->MakeVisible();
  1235. }
  1236. LoadConfiguration();
  1237. }
  1238. // among other this makes the expanded nodes look like expanded,
  1239. // because the LoadState call in Execute is too early,
  1240. // and some stray call to collapsed event during showing process,
  1241. // make the image be set to collapsed
  1242. LoadState();
  1243. UpdateControls();
  1244. }
  1245. //---------------------------------------------------------------------------
  1246. void __fastcall TLoginDialog::SessionTreeChange(TObject * /*Sender*/,
  1247. TTreeNode * /*Node*/)
  1248. {
  1249. if (FIncrementalSearching <= 0)
  1250. {
  1251. // Make sure UpdateControls is called here, no matter what,
  1252. // now it is always called from ResetSitesIncrementalSearch.
  1253. // For the "else" cenarion, UpdateControls is called later from SitesIncrementalSearch.
  1254. ResetSitesIncrementalSearch();
  1255. }
  1256. }
  1257. //---------------------------------------------------------------------------
  1258. void __fastcall TLoginDialog::SetSessionData(TSessionData * value)
  1259. {
  1260. FSessionData->Assign(value);
  1261. FSessionData->Special = false;
  1262. FEditingSessionData = value;
  1263. LoadSession(FSessionData);
  1264. }
  1265. //---------------------------------------------------------------------------
  1266. TSessionData * __fastcall TLoginDialog::GetSessionData()
  1267. {
  1268. if (PageControl->ActivePage == SessionListSheet)
  1269. {
  1270. return SelectedSession;
  1271. }
  1272. else
  1273. {
  1274. SaveSession(FSessionData);
  1275. return FSessionData;
  1276. }
  1277. }
  1278. //---------------------------------------------------------------------------
  1279. void __fastcall TLoginDialog::SessionTreeDblClick(TObject * /*Sender*/)
  1280. {
  1281. TPoint P = SessionTree->ScreenToClient(Mouse->CursorPos);
  1282. TTreeNode * Node = SessionTree->GetNodeAt(P.x, P.y);
  1283. if (IsSessionNode(Node))
  1284. {
  1285. TSessionData * Data = GetNodeSession(Node);
  1286. if (ALWAYS_TRUE(Data == SelectedSession))
  1287. {
  1288. if (FStoredSessions->CanLogin(Data))
  1289. {
  1290. ModalResult = mrOk;
  1291. }
  1292. else
  1293. {
  1294. SetSessionData(Data);
  1295. EditSession();
  1296. }
  1297. }
  1298. }
  1299. else if (IsWorkspaceNode(Node))
  1300. {
  1301. if (HasNodeAnySession(Node, true))
  1302. {
  1303. ModalResult = mrOk;
  1304. }
  1305. }
  1306. }
  1307. //---------------------------------------------------------------------------
  1308. TSessionData * __fastcall TLoginDialog::GetSelectedSession()
  1309. {
  1310. if (SessionTree->Selected != NULL)
  1311. {
  1312. return (TSessionData *)SessionTree->Selected->Data;
  1313. }
  1314. else
  1315. {
  1316. return NULL;
  1317. }
  1318. }
  1319. //---------------------------------------------------------------------------
  1320. void __fastcall TLoginDialog::SessionTreeKeyDown(TObject * /*Sender*/,
  1321. WORD & Key, TShiftState /*Shift*/)
  1322. {
  1323. if (!SessionTree->IsEditing())
  1324. {
  1325. if (Key == VK_DELETE)
  1326. {
  1327. DeleteSessionAction->Execute();
  1328. Key = 0;
  1329. }
  1330. else if (Key == VK_F2)
  1331. {
  1332. RenameSessionAction->Execute();
  1333. Key = 0;
  1334. }
  1335. else if (Key == VK_BACK)
  1336. {
  1337. Key = 0;
  1338. }
  1339. }
  1340. }
  1341. //---------------------------------------------------------------------------
  1342. void __fastcall TLoginDialog::SessionTreeKeyPress(TObject * /*Sender*/, System::WideChar & Key)
  1343. {
  1344. if (!SessionTree->IsEditing())
  1345. {
  1346. // filter control sequences
  1347. if (Key >= VK_SPACE)
  1348. {
  1349. if (!SitesIncrementalSearch(FSitesIncrementalSearch + Key, false, false))
  1350. {
  1351. MessageBeep(0);
  1352. }
  1353. Key = 0;
  1354. }
  1355. else if (Key == VK_BACK)
  1356. {
  1357. if (!FSitesIncrementalSearch.IsEmpty())
  1358. {
  1359. if (FSitesIncrementalSearch.Length() == 1)
  1360. {
  1361. ResetSitesIncrementalSearch();
  1362. }
  1363. else
  1364. {
  1365. UnicodeString NewText =
  1366. FSitesIncrementalSearch.SubString(1, FSitesIncrementalSearch.Length() - 1);
  1367. SitesIncrementalSearch(NewText, false, false);
  1368. }
  1369. Key = 0;
  1370. }
  1371. }
  1372. }
  1373. }
  1374. //---------------------------------------------------------------------------
  1375. void __fastcall TLoginDialog::EditSession()
  1376. {
  1377. ChangePage(BasicSheet);
  1378. HostNameEdit->SetFocus();
  1379. }
  1380. //---------------------------------------------------------------------------
  1381. void __fastcall TLoginDialog::EditSessionActionExecute(TObject * /*Sender*/)
  1382. {
  1383. if (SelectedSession)
  1384. {
  1385. SetSessionData(SelectedSession);
  1386. EditSession();
  1387. }
  1388. }
  1389. //---------------------------------------------------------------------------
  1390. void __fastcall TLoginDialog::SaveSessionActionExecute(TObject * /*Sender*/)
  1391. {
  1392. SaveSession(FSessionData);
  1393. bool SavePassword;
  1394. bool * PSavePassword;
  1395. bool NotRecommendedSavingPassword =
  1396. !CustomWinConfiguration->UseMasterPassword &&
  1397. !SameText(UserNameEdit->Text, AnonymousUserName);
  1398. if (Configuration->DisablePasswordStoring ||
  1399. !FSessionData->HasAnyPassword())
  1400. {
  1401. PSavePassword = NULL;
  1402. }
  1403. else
  1404. {
  1405. PSavePassword = &SavePassword;
  1406. SavePassword =
  1407. ((FEditingSessionData != NULL) &&
  1408. (FEditingSessionData->Password == FSessionData->Password)) ||
  1409. !NotRecommendedSavingPassword;
  1410. }
  1411. UnicodeString SessionName = FSessionData->SessionName;
  1412. if (DoSaveSessionDialog(SessionName, PSavePassword, FEditingSessionData, NotRecommendedSavingPassword))
  1413. {
  1414. if ((PSavePassword != NULL) && !*PSavePassword)
  1415. {
  1416. FSessionData->Password = L"";
  1417. }
  1418. TTreeNode * ParentNode = AddSessionPath(UnixExtractFilePath(SessionName), false, false);
  1419. CheckIsSessionFolder(ParentNode);
  1420. TSessionData * NewSession =
  1421. StoredSessions->NewSession(SessionName, FSessionData);
  1422. // modified only, explicit
  1423. StoredSessions->Save(false, true);
  1424. SaveConfiguration();
  1425. TTreeNode * Node = SessionTree->Items->GetFirstNode();
  1426. while ((Node != NULL) && (Node->Data != NewSession))
  1427. {
  1428. Node = Node->GetNext();
  1429. }
  1430. if (Node == NULL)
  1431. {
  1432. Node = AddSession(NewSession);
  1433. }
  1434. SessionTree->Selected = Node;
  1435. SetSessionData(NewSession);
  1436. ChangePage(SessionListSheet);
  1437. SessionTree->SetFocus();
  1438. }
  1439. }
  1440. //---------------------------------------------------------------------------
  1441. UnicodeString __fastcall TLoginDialog::SessionNodePath(TTreeNode * Node)
  1442. {
  1443. UnicodeString Path;
  1444. if (Node != NULL)
  1445. {
  1446. Path = Node->Text;
  1447. Node = Node->Parent;
  1448. while (Node != NULL)
  1449. {
  1450. Path.Insert(UnixIncludeTrailingBackslash(Node->Text), 1);
  1451. Node = Node->Parent;
  1452. }
  1453. }
  1454. return Path;
  1455. }
  1456. //---------------------------------------------------------------------------
  1457. void __fastcall TLoginDialog::DeleteSessionActionExecute(TObject * /*Sender*/)
  1458. {
  1459. assert(SessionTree->Selected != NULL);
  1460. TTreeNode * Node = SessionTree->Selected;
  1461. if (IsSessionNode(Node))
  1462. {
  1463. TSessionData * Session = SelectedSession;
  1464. if (MessageDialog(FMTLOAD(CONFIRM_DELETE_SESSION, (Session->SessionName)),
  1465. qtConfirmation, qaOK | qaCancel, HELP_DELETE_SESSION) == qaOK)
  1466. {
  1467. WinConfiguration->DeleteSessionFromJumpList(Session->SessionName);
  1468. Session->Remove();
  1469. DestroySession(Session);
  1470. SessionTree->Selected->Delete();
  1471. }
  1472. }
  1473. else if (IsFolderNode(Node) || IsWorkspaceNode(Node))
  1474. {
  1475. int Sessions = 0;
  1476. TTreeNode * ANode = Node->GetNext();
  1477. while ((ANode != NULL) && ANode->HasAsParent(Node))
  1478. {
  1479. if (IsSessionNode(ANode))
  1480. {
  1481. TSessionData * Session = GetNodeSession(ANode);
  1482. if (Session->Special)
  1483. {
  1484. SessionTree->Selected = ANode;
  1485. ANode->MakeVisible();
  1486. throw Exception(FMTLOAD(LOGIN_DELETE_SPECIAL_SESSION, (Session->SessionName)));
  1487. }
  1488. Sessions++;
  1489. }
  1490. ANode = ANode->GetNext();
  1491. }
  1492. UnicodeString Path = SessionNodePath(Node);
  1493. int Prompt;
  1494. UnicodeString HelpKeyword;
  1495. if (IsFolderNode(Node))
  1496. {
  1497. Prompt = LOGIN_DELETE_SESSION_FOLDER;
  1498. HelpKeyword = HELP_DELETE_SESSION_FOLDER;
  1499. }
  1500. else
  1501. {
  1502. Prompt = LOGIN_DELETE_WORKSPACE;
  1503. HelpKeyword = HELP_DELETE_WORKSPACE;
  1504. }
  1505. if ((Sessions == 0) ||
  1506. (MessageDialog(FMTLOAD(Prompt, (Path, Sessions)),
  1507. qtConfirmation, qaOK | qaCancel, HelpKeyword) == qaOK))
  1508. {
  1509. if (IsWorkspaceNode(Node))
  1510. {
  1511. WinConfiguration->DeleteWorkspaceFromJumpList(Path);
  1512. }
  1513. Node = SessionTree->Selected;
  1514. TTreeNode * ANode = Node->GetNext();
  1515. while ((ANode != NULL) && ANode->HasAsParent(Node))
  1516. {
  1517. if (IsSessionNode(ANode))
  1518. {
  1519. TSessionData * Session = GetNodeSession(ANode);
  1520. Session->Remove();
  1521. DestroySession(Session);
  1522. }
  1523. ANode = ANode->GetNext();
  1524. }
  1525. SessionTree->Selected->Delete();
  1526. }
  1527. }
  1528. }
  1529. //---------------------------------------------------------------------------
  1530. void __fastcall TLoginDialog::ReloadSessions()
  1531. {
  1532. SaveState();
  1533. LoadSessions();
  1534. LoadState();
  1535. if (SessionTree->Items->Count > 0)
  1536. {
  1537. SessionTree->Items->GetFirstNode()->MakeVisible();
  1538. }
  1539. }
  1540. //---------------------------------------------------------------------------
  1541. void __fastcall TLoginDialog::ImportSessionsActionExecute(TObject * /*Sender*/)
  1542. {
  1543. if (DoImportSessionsDialog())
  1544. {
  1545. ReloadSessions();
  1546. }
  1547. }
  1548. //---------------------------------------------------------------------------
  1549. void __fastcall TLoginDialog::CleanUpActionExecute(TObject * /*Sender*/)
  1550. {
  1551. if (DoCleanupDialog(StoredSessions, Configuration))
  1552. {
  1553. SaveState();
  1554. LoadSessions();
  1555. LoadState();
  1556. }
  1557. }
  1558. //---------------------------------------------------------------------------
  1559. void __fastcall TLoginDialog::AboutActionExecute(TObject * /*Sender*/)
  1560. {
  1561. DoAboutDialog(Configuration);
  1562. }
  1563. //---------------------------------------------------------------------------
  1564. void __fastcall TLoginDialog::ActionListUpdate(TBasicAction *Action,
  1565. bool &Handled)
  1566. {
  1567. bool SessionSelected =
  1568. (PageControl->ActivePage == SessionListSheet) &&
  1569. IsSessionNode(SessionTree->Selected);
  1570. bool FolderOrWorkspaceSelected =
  1571. (PageControl->ActivePage == SessionListSheet) &&
  1572. IsFolderOrWorkspaceNode(SessionTree->Selected);
  1573. if (Action == EditSessionAction)
  1574. {
  1575. EditSessionAction->Enabled = SessionSelected;
  1576. }
  1577. else if (Action == DeleteSessionAction)
  1578. {
  1579. TSessionData * Data = GetSessionData();
  1580. DeleteSessionAction->Enabled =
  1581. (SessionSelected && !Data->Special) ||
  1582. FolderOrWorkspaceSelected;
  1583. }
  1584. else if (Action == RenameSessionAction)
  1585. {
  1586. TSessionData * Data = GetSessionData();
  1587. RenameSessionAction->Enabled =
  1588. (SessionSelected && !Data->Special) ||
  1589. FolderOrWorkspaceSelected;
  1590. }
  1591. else if (Action == DesktopIconAction)
  1592. {
  1593. DesktopIconAction->Enabled =
  1594. SessionSelected ||
  1595. (FolderOrWorkspaceSelected && HasNodeAnySession(SessionTree->Selected));
  1596. }
  1597. else if (Action == SendToHookAction)
  1598. {
  1599. SendToHookAction->Enabled = SessionSelected;
  1600. }
  1601. else if (Action == LoginAction)
  1602. {
  1603. TSessionData * Data = GetSessionData();
  1604. LoginAction->Enabled =
  1605. (Data && FStoredSessions->CanLogin(Data) && (PageControl->ActivePage != GeneralSheet)) ||
  1606. (FolderOrWorkspaceSelected && HasNodeAnySession(SessionTree->Selected, true));
  1607. }
  1608. else if (Action == SaveSessionAction)
  1609. {
  1610. SaveSessionAction->Enabled =
  1611. (PageControl->ActivePage != SessionListSheet) &&
  1612. (PageControl->ActivePage != LogSheet) &&
  1613. (PageControl->ActivePage != GeneralSheet);
  1614. }
  1615. else if (Action == ShellIconSessionAction)
  1616. {
  1617. ShellIconSessionAction->Enabled =
  1618. SessionSelected ||
  1619. (FolderOrWorkspaceSelected && HasNodeAnySession(SessionTree->Selected));
  1620. }
  1621. else if (Action == NewSessionFolderAction)
  1622. {
  1623. NewSessionFolderAction->Enabled = true;
  1624. }
  1625. else if (Action == ImportSessionsAction)
  1626. {
  1627. ImportSessionsAction->Enabled =
  1628. GUIConfiguration->AnyPuttySessionForImport(StoredSessions) ||
  1629. GUIConfiguration->AnyFilezillaSessionForImport(StoredSessions);
  1630. }
  1631. else if (Action == ImportAction)
  1632. {
  1633. ImportAction->Enabled = true;
  1634. }
  1635. else if (Action == ExportAction)
  1636. {
  1637. ExportAction->Enabled = true;
  1638. }
  1639. Handled = true;
  1640. if (!SessionTree->IsEditing())
  1641. {
  1642. // default property setter does not have guard for "the same value"
  1643. if (!LoginButton->Default)
  1644. {
  1645. LoginButton->Default = true;
  1646. }
  1647. CloseButton->Cancel = true;
  1648. }
  1649. }
  1650. //---------------------------------------------------------------------------
  1651. bool __fastcall TLoginDialog::Execute(TList * DataList)
  1652. {
  1653. FDataList = DataList;
  1654. if (DataList->Count > 0)
  1655. {
  1656. SetSessionData(reinterpret_cast<TSessionData * >(DataList->Items[0]));
  1657. }
  1658. else
  1659. {
  1660. Default();
  1661. }
  1662. LoadConfiguration();
  1663. LoadState();
  1664. bool Result = (ShowModal() == mrOk);
  1665. SaveState();
  1666. if (Result)
  1667. {
  1668. SaveConfiguration();
  1669. // DataList saved already from FormCloseQuery
  1670. }
  1671. return Result;
  1672. }
  1673. //---------------------------------------------------------------------------
  1674. void __fastcall TLoginDialog::SaveDataList(TList * DataList)
  1675. {
  1676. // Normally we would call this from Execute,
  1677. // but at that point the windows is already hidden.
  1678. // Cloning session data may pop up master password dialog:
  1679. // - if it happens between closing and destroyiong login dialog
  1680. // the next window will appear in background for some reason
  1681. // - and its actually even nicer when master password dialog pops up over
  1682. // the login dialog
  1683. DataList->Clear();
  1684. if (PageControl->ActivePage == SessionListSheet)
  1685. {
  1686. TTreeNode * Node = SessionTree->Selected;
  1687. if (IsFolderOrWorkspaceNode(Node))
  1688. {
  1689. UnicodeString Name = SessionNodePath(Node);
  1690. if (IsWorkspaceNode(Node))
  1691. {
  1692. WinConfiguration->AddWorkspaceToJumpList(Name);
  1693. }
  1694. StoredSessions->GetFolderOrWorkspace(Name, DataList);
  1695. }
  1696. else if (IsSessionNode(Node))
  1697. {
  1698. TSessionData * Data2 = new TSessionData(L"");
  1699. Data2->Assign(GetNodeSession(Node));
  1700. DataList->Add(Data2);
  1701. }
  1702. }
  1703. else
  1704. {
  1705. TSessionData * Data = GetSessionData();
  1706. TSessionData * Data2 = new TSessionData(L"");
  1707. Data2->Assign(Data);
  1708. // we carry the name of the edited stored session around while on the dialog,
  1709. // but we do not want it to leave the dialog, so that we can distinguish
  1710. // stored and ad-hoc sessions
  1711. Data2->Name = L"";
  1712. DataList->Add(Data2);
  1713. }
  1714. }
  1715. //---------------------------------------------------------------------------
  1716. void __fastcall TLoginDialog::SaveOpenedStoredSessionFolders(
  1717. TTreeNode * Node, TStrings * OpenedStoredSessionFolders)
  1718. {
  1719. if (IsFolderNode(Node))
  1720. {
  1721. if (Node->Expanded)
  1722. {
  1723. OpenedStoredSessionFolders->Add(SessionNodePath(Node));
  1724. }
  1725. for (int Index = 0; Index < Node->Count; Index++)
  1726. {
  1727. SaveOpenedStoredSessionFolders(Node->Item[Index], OpenedStoredSessionFolders);
  1728. }
  1729. }
  1730. }
  1731. //---------------------------------------------------------------------------
  1732. void __fastcall TLoginDialog::SaveState()
  1733. {
  1734. assert(WinConfiguration != NULL);
  1735. TStringList * OpenedStoredSessionFolders = new TStringList();
  1736. WinConfiguration->BeginUpdate();
  1737. try
  1738. {
  1739. CustomWinConfiguration->ShowAdvancedLoginOptions = ShowAdvancedLoginOptionsCheck->Checked;
  1740. OpenedStoredSessionFolders->CaseSensitive = false;
  1741. OpenedStoredSessionFolders->Sorted = true;
  1742. for (int Index = 0; Index < SessionTree->Items->Count; Index++)
  1743. {
  1744. SaveOpenedStoredSessionFolders(
  1745. SessionTree->Items->Item[Index], OpenedStoredSessionFolders);
  1746. }
  1747. WinConfiguration->OpenedStoredSessionFolders = OpenedStoredSessionFolders->CommaText;
  1748. }
  1749. __finally
  1750. {
  1751. WinConfiguration->EndUpdate();
  1752. delete OpenedStoredSessionFolders;
  1753. }
  1754. WinConfiguration->LastStoredSession = SessionNodePath(SessionTree->Selected);
  1755. }
  1756. //---------------------------------------------------------------------------
  1757. void __fastcall TLoginDialog::LoadOpenedStoredSessionFolders(
  1758. TTreeNode * Node, TStrings * OpenedStoredSessionFolders)
  1759. {
  1760. if (IsFolderNode(Node))
  1761. {
  1762. UnicodeString Path = SessionNodePath(Node);
  1763. if (OpenedStoredSessionFolders->IndexOf(Path) >= 0)
  1764. {
  1765. Node->Expand(false);
  1766. UpdateFolderNode(Node);
  1767. }
  1768. }
  1769. }
  1770. //---------------------------------------------------------------------------
  1771. void __fastcall TLoginDialog::LoadState()
  1772. {
  1773. ShowAdvancedLoginOptionsCheck->Checked = CustomWinConfiguration->ShowAdvancedLoginOptions;
  1774. TStringList * OpenedStoredSessionFolders = new TStringList();
  1775. try
  1776. {
  1777. OpenedStoredSessionFolders->CaseSensitive = false;
  1778. OpenedStoredSessionFolders->Sorted = true;
  1779. OpenedStoredSessionFolders->CommaText = WinConfiguration->OpenedStoredSessionFolders;
  1780. for (int Index = 0; Index < SessionTree->Items->Count; Index++)
  1781. {
  1782. LoadOpenedStoredSessionFolders(
  1783. SessionTree->Items->Item[Index], OpenedStoredSessionFolders);
  1784. }
  1785. // tree view tried to make expanded node children all visible, what
  1786. // may scroll the selected node (what should be the first one here),
  1787. // out of the view
  1788. if (SessionTree->Selected != NULL)
  1789. {
  1790. SessionTree->Selected->MakeVisible();
  1791. }
  1792. }
  1793. __finally
  1794. {
  1795. delete OpenedStoredSessionFolders;
  1796. }
  1797. if (!WinConfiguration->LastStoredSession.IsEmpty())
  1798. {
  1799. UnicodeString Path = WinConfiguration->LastStoredSession;
  1800. UnicodeString ParentPath = UnixExtractFilePath(Path);
  1801. TTreeNode * Node;
  1802. if (ParentPath.IsEmpty())
  1803. {
  1804. Node = SessionTree->Items->GetFirstNode();
  1805. }
  1806. else
  1807. {
  1808. TTreeNode * Parent = AddSessionPath(ParentPath, false, false);
  1809. Node = (Parent != NULL) ? Parent->getFirstChild() : NULL;
  1810. }
  1811. if (Node != NULL)
  1812. {
  1813. UnicodeString Name = UnixExtractFileName(Path);
  1814. // actually we cannot distinguish folder and session here
  1815. // (note that we allow folder and session with the same name),
  1816. // this is pending for future improvements
  1817. while ((Node != NULL) && !AnsiSameText(Node->Text, Name))
  1818. {
  1819. Node = Node->getNextSibling();
  1820. }
  1821. if (Node != NULL)
  1822. {
  1823. SessionTree->Selected = Node;
  1824. SessionTree->Selected->MakeVisible();
  1825. }
  1826. }
  1827. }
  1828. }
  1829. //---------------------------------------------------------------------------
  1830. void __fastcall TLoginDialog::SaveConfiguration()
  1831. {
  1832. assert(CustomWinConfiguration);
  1833. CustomWinConfiguration->BeginUpdate();
  1834. try
  1835. {
  1836. LoggingFrame->SaveConfiguration();
  1837. GeneralSettingsFrame->SaveConfiguration();
  1838. TTreeNode * Node = SessionTree->Selected;
  1839. if (IsWorkspaceNode(Node))
  1840. {
  1841. WinConfiguration->LastWorkspace = SessionNodePath(Node);
  1842. }
  1843. }
  1844. __finally
  1845. {
  1846. CustomWinConfiguration->EndUpdate();
  1847. }
  1848. }
  1849. //---------------------------------------------------------------------------
  1850. void __fastcall TLoginDialog::LoadConfiguration()
  1851. {
  1852. assert(CustomWinConfiguration);
  1853. LoggingFrame->LoadConfiguration();
  1854. GeneralSettingsFrame->LoadConfiguration();
  1855. UpdateControls();
  1856. }
  1857. //---------------------------------------------------------------------------
  1858. void __fastcall TLoginDialog::PreferencesButtonClick(TObject * /*Sender*/)
  1859. {
  1860. ShowPreferencesDialog();
  1861. UpdateControls();
  1862. }
  1863. //---------------------------------------------------------------------------
  1864. void __fastcall TLoginDialog::MasterPasswordRecrypt(TObject * /*Sender*/)
  1865. {
  1866. FSessionData->RecryptPasswords();
  1867. }
  1868. //---------------------------------------------------------------------------
  1869. void __fastcall TLoginDialog::ShowPreferencesDialog()
  1870. {
  1871. assert(CustomWinConfiguration->OnMasterPasswordRecrypt == NULL);
  1872. CustomWinConfiguration->OnMasterPasswordRecrypt = MasterPasswordRecrypt;
  1873. try
  1874. {
  1875. DoPreferencesDialog(pmLogin);
  1876. }
  1877. __finally
  1878. {
  1879. assert(CustomWinConfiguration->OnMasterPasswordRecrypt == MasterPasswordRecrypt);
  1880. CustomWinConfiguration->OnMasterPasswordRecrypt = NULL;
  1881. }
  1882. }
  1883. //---------------------------------------------------------------------------
  1884. void __fastcall TLoginDialog::NewSessionActionExecute(TObject * /*Sender*/)
  1885. {
  1886. Default();
  1887. EditSession();
  1888. }
  1889. //---------------------------------------------------------------------------
  1890. void __fastcall TLoginDialog::NavigationTreeChange(TObject * /*Sender*/,
  1891. TTreeNode *Node)
  1892. {
  1893. if (NoUpdate == 0)
  1894. {
  1895. TAutoNestingCounter Guard(NoUpdate);
  1896. TTabSheet * Tab = reinterpret_cast<TTabSheet *>(Node->SelectedIndex);
  1897. // should happen only while loading language
  1898. // (UpdateNavigationTree may not be called yet)
  1899. if (Tab != NULL)
  1900. {
  1901. PageControl->ActivePage = Tab;
  1902. // reshow the accelerators, etc
  1903. ResetSystemSettings(this);
  1904. }
  1905. UpdateControls();
  1906. }
  1907. }
  1908. //---------------------------------------------------------------------------
  1909. void __fastcall TLoginDialog::ChangePage(TTabSheet * Tab)
  1910. {
  1911. PageControl->ActivePage = Tab;
  1912. PageControlChange(PageControl);
  1913. }
  1914. //---------------------------------------------------------------------------
  1915. void __fastcall TLoginDialog::PageControlChange(TObject *Sender)
  1916. {
  1917. bool Found = false;
  1918. if (PageControl->ActivePage)
  1919. {
  1920. for (int Index = 0; Index < NavigationTree->Items->Count; Index++)
  1921. {
  1922. if (NavigationTree->Items->Item[Index]->SelectedIndex ==
  1923. reinterpret_cast<int>(PageControl->ActivePage))
  1924. {
  1925. NavigationTree->Items->Item[Index]->Selected = true;
  1926. Found = true;
  1927. }
  1928. }
  1929. }
  1930. if (!Found)
  1931. {
  1932. assert(false);
  1933. ChangePage(BasicSheet);
  1934. }
  1935. else
  1936. {
  1937. DataChange(Sender);
  1938. }
  1939. }
  1940. //---------------------------------------------------------------------------
  1941. void __fastcall TLoginDialog::CMDialogKey(TWMKeyDown & Message)
  1942. {
  1943. if (Message.CharCode == VK_TAB)
  1944. {
  1945. TShiftState Shift = KeyDataToShiftState(Message.KeyData);
  1946. if (Shift.Contains(ssCtrl))
  1947. {
  1948. TTreeNode * Node = NavigationTree->Selected;
  1949. if (!Shift.Contains(ssShift))
  1950. {
  1951. Node = Node->GetNext();
  1952. if (!Node) Node = NavigationTree->Items->GetFirstNode();
  1953. }
  1954. else
  1955. {
  1956. if (Node->GetPrev()) Node = Node->GetPrev();
  1957. else
  1958. while (Node->GetNext()) Node = Node->GetNext();
  1959. }
  1960. Node->Selected = True;
  1961. Message.Result = 1;
  1962. return;
  1963. }
  1964. else
  1965. {
  1966. if (!FSitesIncrementalSearch.IsEmpty())
  1967. {
  1968. bool Reverse = Shift.Contains(ssShift);
  1969. if (!SitesIncrementalSearch(FSitesIncrementalSearch, true, Reverse))
  1970. {
  1971. MessageBeep(0);
  1972. }
  1973. Message.Result = 1;
  1974. return;
  1975. }
  1976. }
  1977. }
  1978. else if (Message.CharCode == VK_ESCAPE)
  1979. {
  1980. if (!FSitesIncrementalSearch.IsEmpty())
  1981. {
  1982. ResetSitesIncrementalSearch();
  1983. Message.Result = 1;
  1984. return;
  1985. }
  1986. }
  1987. TForm::Dispatch(&Message);
  1988. }
  1989. //---------------------------------------------------------------------------
  1990. void __fastcall TLoginDialog::WMHelp(TWMHelp & Message)
  1991. {
  1992. assert(Message.HelpInfo != NULL);
  1993. if (Message.HelpInfo->iContextType == HELPINFO_WINDOW)
  1994. {
  1995. // invoke help for active page (not for whole form), regardless of focus
  1996. // (e.g. even if focus is on control outside pagecontrol)
  1997. Message.HelpInfo->hItemHandle = PageControl->ActivePage->Handle;
  1998. }
  1999. TForm::Dispatch(&Message);
  2000. }
  2001. //---------------------------------------------------------------------------
  2002. void __fastcall TLoginDialog::Dispatch(void * Message)
  2003. {
  2004. TMessage * M = reinterpret_cast<TMessage*>(Message);
  2005. assert(M);
  2006. if (M->Msg == CM_DIALOGKEY)
  2007. {
  2008. CMDialogKey(*((TWMKeyDown *)Message));
  2009. }
  2010. else if (M->Msg == WM_LOCALE_CHANGE)
  2011. {
  2012. if (M->WParam == 0)
  2013. {
  2014. SaveConfiguration();
  2015. SaveState();
  2016. SaveSession(FSessionData);
  2017. FSavedTab = PageControl->ActivePage;
  2018. FSavedSession = ((SessionTree->Selected != NULL) ?
  2019. SessionTree->Selected->AbsoluteIndex : -1);
  2020. assert(FSystemSettings);
  2021. RevokeSystemSettings(this, FSystemSettings);
  2022. FSystemSettings = NULL;
  2023. Hide();
  2024. }
  2025. else
  2026. {
  2027. FLocaleChanging = true;
  2028. try
  2029. {
  2030. Show();
  2031. }
  2032. __finally
  2033. {
  2034. FLocaleChanging = false;
  2035. }
  2036. }
  2037. }
  2038. else if (M->Msg == WM_HELP)
  2039. {
  2040. WMHelp(*((TWMHelp *)Message));
  2041. }
  2042. else
  2043. {
  2044. TForm::Dispatch(Message);
  2045. }
  2046. }
  2047. //---------------------------------------------------------------------------
  2048. void __fastcall TLoginDialog::AlgListBoxStartDrag(TObject * Sender,
  2049. TDragObject *& /*DragObject*/)
  2050. {
  2051. FAlgDragSource = dynamic_cast<TListBox*>(Sender)->ItemIndex;
  2052. FAlgDragDest = -1;
  2053. }
  2054. //---------------------------------------------------------------------------
  2055. void __fastcall TLoginDialog::AlgListBoxDragOver(TObject * Sender,
  2056. TObject *Source, int X, int Y, TDragState /*State*/, bool &Accept)
  2057. {
  2058. if (Source == Sender)
  2059. {
  2060. Accept = AllowAlgDrag(dynamic_cast<TListBox*>(Sender), X, Y);
  2061. }
  2062. else
  2063. {
  2064. Accept = false;
  2065. }
  2066. }
  2067. //---------------------------------------------------------------------------
  2068. void __fastcall TLoginDialog::AlgListBoxDragDrop(TObject * Sender,
  2069. TObject * Source, int X, int Y)
  2070. {
  2071. if (Source == Sender)
  2072. {
  2073. TListBox * AlgListBox = dynamic_cast<TListBox*>(Sender);
  2074. if (AllowAlgDrag(AlgListBox, X, Y))
  2075. {
  2076. AlgMove(AlgListBox, FAlgDragSource, FAlgDragDest);
  2077. }
  2078. }
  2079. }
  2080. //---------------------------------------------------------------------------
  2081. void __fastcall TLoginDialog::CipherButtonClick(TObject *Sender)
  2082. {
  2083. AlgMove(CipherListBox, CipherListBox->ItemIndex,
  2084. CipherListBox->ItemIndex + (Sender == CipherUpButton ? -1 : 1));
  2085. }
  2086. //---------------------------------------------------------------------------
  2087. void __fastcall TLoginDialog::KexButtonClick(TObject *Sender)
  2088. {
  2089. AlgMove(KexListBox, KexListBox->ItemIndex,
  2090. KexListBox->ItemIndex + (Sender == KexUpButton ? -1 : 1));
  2091. }
  2092. //---------------------------------------------------------------------------
  2093. bool __fastcall TLoginDialog::AllowAlgDrag(TListBox * AlgListBox, int X, int Y)
  2094. {
  2095. FAlgDragDest = AlgListBox->ItemAtPos(TPoint(X, Y), true);
  2096. return (FAlgDragDest >= 0) && (FAlgDragDest != FAlgDragSource);
  2097. }
  2098. //---------------------------------------------------------------------------
  2099. void __fastcall TLoginDialog::AlgMove(TListBox * AlgListBox, int Source, int Dest)
  2100. {
  2101. if (Source >= 0 && Source < AlgListBox->Items->Count &&
  2102. Dest >= 0 && Dest < AlgListBox->Items->Count)
  2103. {
  2104. AlgListBox->Items->Move(Source, Dest);
  2105. AlgListBox->ItemIndex = Dest;
  2106. AlgListBox->SetFocus();
  2107. }
  2108. UpdateControls();
  2109. }
  2110. //---------------------------------------------------------------------------
  2111. void __fastcall TLoginDialog::SetDefaultSessionActionExecute(
  2112. TObject * /*Sender*/)
  2113. {
  2114. if (MessageDialog(LoadStr(SET_DEFAULT_SESSION_SETTINGS), qtConfirmation,
  2115. qaOK | qaCancel, HELP_SESSION_SAVE_DEFAULT) == qaOK)
  2116. {
  2117. SaveSession(FSessionData);
  2118. if (!Configuration->DisablePasswordStoring &&
  2119. FSessionData->HasAnyPassword() &&
  2120. CustomWinConfiguration->UseMasterPassword)
  2121. {
  2122. CustomWinConfiguration->AskForMasterPasswordIfNotSet();
  2123. }
  2124. StoredSessions->DefaultSettings = FSessionData;
  2125. }
  2126. }
  2127. //---------------------------------------------------------------------------
  2128. void __fastcall TLoginDialog::ToolsMenuButtonClick(TObject * /*Sender*/)
  2129. {
  2130. MenuPopup(ToolsPopupMenu, ToolsMenuButton);
  2131. }
  2132. //---------------------------------------------------------------------------
  2133. void __fastcall TLoginDialog::ShellIconSessionActionExecute(
  2134. TObject * /*Sender*/)
  2135. {
  2136. MenuPopup(IconsPopupMenu, ShellIconsButton);
  2137. }
  2138. //---------------------------------------------------------------------------
  2139. void __fastcall TLoginDialog::DesktopIconActionExecute(TObject * /*Sender*/)
  2140. {
  2141. TTreeNode * Node = SessionTree->Selected;
  2142. UnicodeString Message;
  2143. UnicodeString Name;
  2144. UnicodeString AdditionalParams;
  2145. if (IsSessionNode(Node))
  2146. {
  2147. Name = GetNodeSession(Node)->Name;
  2148. Message = FMTLOAD(CONFIRM_CREATE_SHORTCUT, (Name));
  2149. AdditionalParams = L"/UploadIfAny";
  2150. }
  2151. else if (IsFolderNode(Node))
  2152. {
  2153. Name = SessionNodePath(SessionTree->Selected);
  2154. Message = FMTLOAD(CONFIRM_CREATE_SHORTCUT_FOLDER, (Name));
  2155. }
  2156. else if (IsWorkspaceNode(Node))
  2157. {
  2158. Name = SessionNodePath(SessionTree->Selected);
  2159. Message = FMTLOAD(CONFIRM_CREATE_SHORTCUT_WORKSPACE, (Name));
  2160. }
  2161. if (MessageDialog(Message, qtConfirmation, qaYes | qaNo, HELP_CREATE_SHORTCUT) == qaYes)
  2162. {
  2163. CreateDesktopSessionShortCut(Name, L"", AdditionalParams);
  2164. }
  2165. }
  2166. //---------------------------------------------------------------------------
  2167. void __fastcall TLoginDialog::SendToHookActionExecute(TObject * /*Sender*/)
  2168. {
  2169. if (MessageDialog(FMTLOAD(CONFIRM_CREATE_SENDTO, (SelectedSession->Name)),
  2170. qtConfirmation, qaYes | qaNo, HELP_CREATE_SENDTO) == qaYes)
  2171. {
  2172. assert(SelectedSession);
  2173. CreateDesktopSessionShortCut(SelectedSession->Name,
  2174. FMTLOAD(SESSION_SENDTO_HOOK_NAME, (SelectedSession->LocalName)),
  2175. L"/Upload", CSIDL_SENDTO);
  2176. }
  2177. }
  2178. //---------------------------------------------------------------------------
  2179. bool __fastcall TLoginDialog::HasNodeAnySession(TTreeNode * Node, bool NeedCanLogin)
  2180. {
  2181. bool Result = false;
  2182. TTreeNode * ANode = Node->GetNext();
  2183. while (!Result && (ANode != NULL) && ANode->HasAsParent(Node))
  2184. {
  2185. Result =
  2186. IsSessionNode(ANode) &&
  2187. (!NeedCanLogin || FStoredSessions->CanLogin(GetNodeSession(ANode)));
  2188. ANode = ANode->GetNext();
  2189. }
  2190. return Result;
  2191. }
  2192. //---------------------------------------------------------------------------
  2193. void __fastcall TLoginDialog::SessionTreeCustomDrawItem(
  2194. TCustomTreeView * Sender, TTreeNode * Node, TCustomDrawState State,
  2195. bool & DefaultDraw)
  2196. {
  2197. TFontStyles Styles = Sender->Canvas->Font->Style;
  2198. if (IsSessionNode(Node) && GetNodeSession(Node)->Special)
  2199. {
  2200. Styles = Styles << fsBold << fsUnderline;
  2201. }
  2202. else
  2203. {
  2204. Styles = Styles >> fsBold >> fsUnderline;
  2205. }
  2206. if (State.Empty() && !Node->DropTarget)
  2207. {
  2208. if (IsFolderOrWorkspaceNode(Node))
  2209. {
  2210. if (!HasNodeAnySession(Node))
  2211. {
  2212. Sender->Canvas->Font->Color = clGrayText;
  2213. }
  2214. }
  2215. else if (ALWAYS_TRUE(IsSessionNode(Node)))
  2216. {
  2217. TSessionData * Data = GetNodeSession(Node);
  2218. if (Data->Color != 0)
  2219. {
  2220. Sender->Canvas->Brush->Color = (TColor)Data->Color;
  2221. }
  2222. }
  2223. }
  2224. Sender->Canvas->Font->Style = Styles;
  2225. DefaultDraw = true;
  2226. }
  2227. //---------------------------------------------------------------------------
  2228. void __fastcall TLoginDialog::CheckForUpdatesActionExecute(TObject * /*Sender*/)
  2229. {
  2230. CheckForUpdates(false);
  2231. }
  2232. //---------------------------------------------------------------------------
  2233. void __fastcall TLoginDialog::LanguagesButtonClick(TObject * /*Sender*/)
  2234. {
  2235. delete FLanguagesPopupMenu;
  2236. FLanguagesPopupMenu = new TPopupMenu(this);
  2237. TMenuItem * Item;
  2238. TStrings * Locales = GUIConfiguration->Locales;
  2239. for (int Index = 0; Index < Locales->Count; Index++)
  2240. {
  2241. Item = new TMenuItem(FLanguagesPopupMenu);
  2242. FLanguagesPopupMenu->Items->Add(Item);
  2243. Item->Caption = Locales->Strings[Index];
  2244. Item->Tag = reinterpret_cast<int>(Locales->Objects[Index]);
  2245. Item->OnClick = LocaleClick;
  2246. Item->Checked = (reinterpret_cast<LCID>(Locales->Objects[Index]) ==
  2247. GUIConfiguration->Locale);
  2248. }
  2249. Item = new TMenuItem(FLanguagesPopupMenu);
  2250. FLanguagesPopupMenu->Items->Add(Item);
  2251. Item->Caption = L"-";
  2252. Item = new TMenuItem(FLanguagesPopupMenu);
  2253. FLanguagesPopupMenu->Items->Add(Item);
  2254. Item->Caption = LoadStr(LOGIN_GET_LOCALES);
  2255. Item->OnClick = LocaleGetClick;
  2256. MenuPopup(FLanguagesPopupMenu, LanguagesButton);
  2257. }
  2258. //---------------------------------------------------------------------------
  2259. void __fastcall TLoginDialog::LocaleClick(TObject * Sender)
  2260. {
  2261. assert(Sender);
  2262. GUIConfiguration->Locale =
  2263. static_cast<LCID>(dynamic_cast<TComponent*>(Sender)->Tag);
  2264. LanguagesButton->SetFocus();
  2265. }
  2266. //---------------------------------------------------------------------------
  2267. void __fastcall TLoginDialog::LocaleGetClick(TObject * /*Sender*/)
  2268. {
  2269. OpenBrowser(LoadStr(LOCALES_URL));
  2270. }
  2271. //---------------------------------------------------------------------------
  2272. void __fastcall TLoginDialog::AuthGSSAPICheck3Click(TObject * /*Sender*/)
  2273. {
  2274. if (NoUpdate)
  2275. {
  2276. UpdateControls();
  2277. if (AuthGSSAPICheck3->Checked && !Configuration->GSSAPIInstalled)
  2278. {
  2279. throw Exception(LoadStr(GSSAPI_NOT_INSTALLED2));
  2280. }
  2281. }
  2282. }
  2283. //---------------------------------------------------------------------------
  2284. void __fastcall TLoginDialog::HelpButtonClick(TObject * /*Sender*/)
  2285. {
  2286. FormHelp(this);
  2287. }
  2288. //---------------------------------------------------------------------------
  2289. void __fastcall TLoginDialog::VerifyKey(UnicodeString FileName, bool TypeOnly)
  2290. {
  2291. if (!FileName.Trim().IsEmpty())
  2292. {
  2293. FileName = ExpandEnvironmentVariables(FileName);
  2294. TKeyType Type = KeyType(FileName);
  2295. UnicodeString Message;
  2296. switch (Type)
  2297. {
  2298. case ktOpenSSH:
  2299. Message = FMTLOAD(KEY_TYPE_UNSUPPORTED, (FileName, L"OpenSSH SSH-2"));
  2300. break;
  2301. case ktSSHCom:
  2302. Message = FMTLOAD(KEY_TYPE_UNSUPPORTED, (FileName, L"ssh.com SSH-2"));
  2303. break;
  2304. case ktSSH1:
  2305. case ktSSH2:
  2306. // on file select do not check for SSH version as user may
  2307. // intend to change it only after he/she selects key file
  2308. if (!TypeOnly)
  2309. {
  2310. TSessionData * Data = GetSessionData();
  2311. if ((Type == ktSSH1) !=
  2312. ((Data->SshProt == ssh1only) || (Data->SshProt == ssh1)))
  2313. {
  2314. Message = FMTLOAD(KEY_TYPE_DIFFERENT_SSH,
  2315. (FileName, (Type == ktSSH1 ? L"SSH-1" : L"PuTTY SSH-2")));
  2316. }
  2317. }
  2318. break;
  2319. default:
  2320. assert(false);
  2321. // fallthru
  2322. case ktUnopenable:
  2323. case ktUnknown:
  2324. Message = FMTLOAD(KEY_TYPE_UNKNOWN, (FileName));
  2325. break;
  2326. }
  2327. if (!Message.IsEmpty())
  2328. {
  2329. if (MessageDialog(Message, qtWarning, qaIgnore | qaAbort,
  2330. HELP_LOGIN_KEY_TYPE) == qaAbort)
  2331. {
  2332. Abort();
  2333. }
  2334. }
  2335. }
  2336. }
  2337. //---------------------------------------------------------------------------
  2338. void __fastcall TLoginDialog::PrivateKeyEditAfterDialog(TObject * Sender,
  2339. UnicodeString & Name, bool & /*Action*/)
  2340. {
  2341. if (CompareFileName(Name, ExpandEnvironmentVariables(FBeforeDialogPath)))
  2342. {
  2343. Name = FBeforeDialogPath;
  2344. }
  2345. TFilenameEdit * Edit = dynamic_cast<TFilenameEdit *>(Sender);
  2346. if (Name != Edit->Text)
  2347. {
  2348. VerifyKey(Name, true);
  2349. }
  2350. }
  2351. //---------------------------------------------------------------------------
  2352. void __fastcall TLoginDialog::FormCloseQuery(TObject * /*Sender*/,
  2353. bool & /*CanClose*/)
  2354. {
  2355. if (ModalResult != mrCancel)
  2356. {
  2357. TSessionData * SessionData = GetSessionData();
  2358. if (SessionData != NULL)
  2359. {
  2360. VerifyKey(SessionData->PublicKeyFile, false);
  2361. // for tunnel key do not check SSH version as it is not configurable
  2362. VerifyKey(SessionData->TunnelPublicKeyFile, true);
  2363. }
  2364. SaveDataList(FDataList);
  2365. }
  2366. }
  2367. //---------------------------------------------------------------------------
  2368. void __fastcall TLoginDialog::ColorButtonClick(TObject * /*Sender*/)
  2369. {
  2370. ColorDefaultItem->Checked = (FColor == 0);
  2371. PickColorItem->Checked = (FColor != 0);
  2372. PickColorItem->ImageIndex = (FColor != 0 ? 0 : -1);
  2373. ColorImageList->BkColor = FColor;
  2374. MenuPopup(ColorPopupMenu, ColorButton);
  2375. }
  2376. //---------------------------------------------------------------------------
  2377. void __fastcall TLoginDialog::ColorDefaultItemClick(TObject * /*Sender*/)
  2378. {
  2379. FColor = (TColor)0;
  2380. }
  2381. //---------------------------------------------------------------------------
  2382. void __fastcall TLoginDialog::PickColorItemClick(TObject * /*Sender*/)
  2383. {
  2384. TColorDialog * Dialog = new TColorDialog(this);
  2385. try
  2386. {
  2387. Dialog->Options = Dialog->Options << cdFullOpen;
  2388. Dialog->Color = (FColor != 0 ? FColor : clSkyBlue);
  2389. if (Dialog->Execute())
  2390. {
  2391. FColor = Dialog->Color;
  2392. }
  2393. }
  2394. __finally
  2395. {
  2396. delete Dialog;
  2397. }
  2398. }
  2399. //---------------------------------------------------------------------------
  2400. void __fastcall TLoginDialog::SessionTreeEditing(TObject * /*Sender*/,
  2401. TTreeNode * Node, bool & AllowEdit)
  2402. {
  2403. AllowEdit =
  2404. IsFolderOrWorkspaceNode(Node) ||
  2405. (ALWAYS_TRUE(IsSessionNode(Node)) && !GetNodeSession(Node)->Special);
  2406. if (AllowEdit)
  2407. {
  2408. LoginButton->Default = false;
  2409. CloseButton->Cancel = false;
  2410. }
  2411. }
  2412. //---------------------------------------------------------------------------
  2413. void __fastcall TLoginDialog::RenameSessionActionExecute(TObject * /*Sender*/)
  2414. {
  2415. if (SessionTree->Selected != NULL)
  2416. {
  2417. // would be more appropriate in SessionTreeEditing, but it does not work there
  2418. ResetSitesIncrementalSearch();
  2419. SessionTree->Selected->EditText();
  2420. }
  2421. }
  2422. //---------------------------------------------------------------------------
  2423. void __fastcall TLoginDialog::CheckDuplicateFolder(TTreeNode * Parent,
  2424. UnicodeString Text, TTreeNode * Node)
  2425. {
  2426. TTreeNode * ANode =
  2427. ((Parent == NULL) ? SessionTree->Items->GetFirstNode() :
  2428. Parent->getFirstChild());
  2429. // note that we allow folder with the same name as existing session
  2430. // on the same level (see also AddSession)
  2431. while ((ANode != NULL) &&
  2432. ((ANode == Node) || IsSessionNode(ANode) || !AnsiSameText(ANode->Text, Text)))
  2433. {
  2434. ANode = ANode->getNextSibling();
  2435. }
  2436. if (ANode != NULL)
  2437. {
  2438. throw Exception(FMTLOAD(LOGIN_DUPLICATE_SESSION_FOLDER_WORKSPACE, (Text)));
  2439. }
  2440. }
  2441. //---------------------------------------------------------------------------
  2442. void __fastcall TLoginDialog::CheckIsSessionFolder(TTreeNode * Node)
  2443. {
  2444. if ((Node != NULL) && (Node->Parent != NULL))
  2445. {
  2446. CheckIsSessionFolder(Node->Parent);
  2447. }
  2448. if (IsWorkspaceNode(Node))
  2449. {
  2450. throw Exception(FMTLOAD(WORKSPACE_NOT_FOLDER, (SessionNodePath(Node))));
  2451. }
  2452. }
  2453. //---------------------------------------------------------------------------
  2454. void __fastcall TLoginDialog::SessionTreeEdited(TObject * /*Sender*/,
  2455. TTreeNode * Node, UnicodeString & S)
  2456. {
  2457. if (Node->Text != S)
  2458. {
  2459. TSessionData * Session = SelectedSession;
  2460. TSessionData::ValidateName(S);
  2461. if (Session != NULL)
  2462. {
  2463. UnicodeString Path = UnixExtractFilePath(Session->Name) + S;
  2464. SessionNameValidate(Path, Session);
  2465. // remove from storage
  2466. Session->Remove();
  2467. TSessionData * NewSession = StoredSessions->NewSession(Path, Session);
  2468. // modified, only explicit
  2469. StoredSessions->Save(false, true);
  2470. // the session may be the same, if only letter case has changed
  2471. if (Session != NewSession)
  2472. {
  2473. // if we overwrite existing session, remove the original item
  2474. // (we must not delete the node we are editing)
  2475. TTreeNode * ANode =
  2476. ((Node->Parent == NULL) ? SessionTree->Items->GetFirstNode() :
  2477. Node->Parent->getFirstChild());
  2478. while ((ANode != NULL) && (ANode->Data != NewSession))
  2479. {
  2480. ANode = ANode->getNextSibling();
  2481. }
  2482. if (ANode != NULL)
  2483. {
  2484. ANode->Delete();
  2485. }
  2486. Node->Data = NewSession;
  2487. DestroySession(Session);
  2488. }
  2489. SetSessionData(NewSession);
  2490. }
  2491. else
  2492. {
  2493. CheckDuplicateFolder(Node->Parent, S, Node);
  2494. UnicodeString ParentPath = UnixIncludeTrailingBackslash(SessionNodePath(Node->Parent));
  2495. UnicodeString OldRoot = ParentPath + Node->Text;
  2496. UnicodeString NewRoot = ParentPath + S;
  2497. bool AnySession = false;
  2498. TSortType PrevSortType = SessionTree->SortType;
  2499. // temporarily disable automatic sorting, so that nodes are kept in order
  2500. // while we traverse them. otherwise it may happen that we omit some.
  2501. SessionTree->SortType = Comctrls::stNone;
  2502. try
  2503. {
  2504. TTreeNode * ANode = Node->GetNext();
  2505. while ((ANode != NULL) && ANode->HasAsParent(Node))
  2506. {
  2507. if (IsSessionNode(ANode))
  2508. {
  2509. AnySession = true;
  2510. TSessionData * Session = GetNodeSession(ANode);
  2511. // remove from storage
  2512. Session->Remove();
  2513. UnicodeString Path = Session->Name;
  2514. assert(Path.SubString(1, OldRoot.Length()) == OldRoot);
  2515. Path.Delete(1, OldRoot.Length());
  2516. Path.Insert(NewRoot, 1);
  2517. TSessionData * NewSession = StoredSessions->NewSession(Path, Session);
  2518. // the session may be the same, if only letter case has changed
  2519. if (NewSession != Session)
  2520. {
  2521. ANode->Data = NewSession;
  2522. DestroySession(Session);
  2523. }
  2524. }
  2525. ANode = ANode->GetNext();
  2526. }
  2527. }
  2528. __finally
  2529. {
  2530. SessionTree->SortType = PrevSortType;
  2531. }
  2532. if (AnySession)
  2533. {
  2534. // modified, only explicit
  2535. StoredSessions->Save(false, true);
  2536. }
  2537. }
  2538. }
  2539. }
  2540. //---------------------------------------------------------------------------
  2541. void __fastcall TLoginDialog::PathEditBeforeDialog(TObject * /*Sender*/,
  2542. UnicodeString & Name, bool & /*Action*/)
  2543. {
  2544. FBeforeDialogPath = Name;
  2545. Name = ExpandEnvironmentVariables(Name);
  2546. }
  2547. //---------------------------------------------------------------------------
  2548. int __fastcall TLoginDialog::FSProtocolToIndex(TFSProtocol FSProtocol,
  2549. bool & AllowScpFallback)
  2550. {
  2551. if (FSProtocol == fsSFTP)
  2552. {
  2553. AllowScpFallback = true;
  2554. bool Dummy;
  2555. return FSProtocolToIndex(fsSFTPonly, Dummy);
  2556. }
  2557. else
  2558. {
  2559. AllowScpFallback = false;
  2560. for (int Index = 0; Index < TransferProtocolCombo->Items->Count; Index++)
  2561. {
  2562. if (FSOrder[Index] == FSProtocol)
  2563. {
  2564. return Index;
  2565. }
  2566. }
  2567. // SFTP is always present
  2568. return FSProtocolToIndex(fsSFTP, AllowScpFallback);
  2569. }
  2570. }
  2571. //---------------------------------------------------------------------------
  2572. TFSProtocol __fastcall TLoginDialog::IndexToFSProtocol(int Index, bool AllowScpFallback)
  2573. {
  2574. bool InBounds = (Index >= 0) && (Index < static_cast<int>(LENOF(FSOrder)));
  2575. // can be temporary "unselected" while new language is being loaded
  2576. assert(InBounds || (Index == -1));
  2577. TFSProtocol Result = fsSFTP;
  2578. if (InBounds)
  2579. {
  2580. Result = FSOrder[Index];
  2581. if ((Result == fsSFTPonly) && AllowScpFallback)
  2582. {
  2583. Result = fsSFTP;
  2584. }
  2585. }
  2586. return Result;
  2587. }
  2588. //---------------------------------------------------------------------------
  2589. int __fastcall TLoginDialog::LastSupportedFtpProxyMethod()
  2590. {
  2591. return pmHTTP;
  2592. }
  2593. //---------------------------------------------------------------------------
  2594. bool __fastcall TLoginDialog::SupportedFtpProxyMethod(int Method)
  2595. {
  2596. return (Method >= 0) && (Method <= LastSupportedFtpProxyMethod());
  2597. }
  2598. //---------------------------------------------------------------------------
  2599. int __fastcall TLoginDialog::GetSupportedFtpProxyMethod(int Method)
  2600. {
  2601. if (SupportedFtpProxyMethod(Method))
  2602. {
  2603. return Method;
  2604. }
  2605. else
  2606. {
  2607. return ::pmNone;
  2608. }
  2609. }
  2610. //---------------------------------------------------------------------------
  2611. int __fastcall TLoginDialog::GetSupportedWebDavProxyMethod(int Method)
  2612. {
  2613. if ((Method >= 0) && (Method <= pmHTTP))
  2614. {
  2615. return Method;
  2616. }
  2617. else
  2618. {
  2619. return ::pmNone;
  2620. }
  2621. }
  2622. //---------------------------------------------------------------------------
  2623. TProxyMethod __fastcall TLoginDialog::GetProxyMethod()
  2624. {
  2625. TProxyMethod Result;
  2626. TFSProtocol FSProtocol = GetFSProtocol();
  2627. if (IsSshProtocol(FSProtocol))
  2628. {
  2629. Result = (TProxyMethod)SshProxyMethodCombo->ItemIndex;
  2630. }
  2631. else if (FSProtocol == fsFTP)
  2632. {
  2633. if (SupportedFtpProxyMethod(FtpProxyMethodCombo->ItemIndex))
  2634. {
  2635. Result = (TProxyMethod)FtpProxyMethodCombo->ItemIndex;
  2636. }
  2637. else
  2638. {
  2639. Result = ::pmNone;
  2640. }
  2641. }
  2642. else if (FSProtocol == fsWebDAV)
  2643. {
  2644. Result = (TProxyMethod)WebDavProxyMethodCombo->ItemIndex;
  2645. }
  2646. else
  2647. {
  2648. FAIL;
  2649. Result = ::pmNone;
  2650. }
  2651. return Result;
  2652. }
  2653. //---------------------------------------------------------------------------
  2654. int __fastcall TLoginDialog::GetFtpProxyLogonType()
  2655. {
  2656. int Result;
  2657. if (GetFSProtocol() != fsFTP)
  2658. {
  2659. Result = 0;
  2660. }
  2661. else
  2662. {
  2663. if (SupportedFtpProxyMethod(FtpProxyMethodCombo->ItemIndex))
  2664. {
  2665. Result = 0;
  2666. }
  2667. else
  2668. {
  2669. Result = FtpProxyMethodCombo->ItemIndex - LastSupportedFtpProxyMethod();
  2670. }
  2671. }
  2672. return Result;
  2673. }
  2674. //---------------------------------------------------------------------------
  2675. TFtps __fastcall TLoginDialog::GetFtps()
  2676. {
  2677. return (TFtps)((GetFSProtocol() == fsWebDAV) ? WebDavsCombo->ItemIndex : FtpsCombo->ItemIndex);
  2678. }
  2679. //---------------------------------------------------------------------------
  2680. TFSProtocol __fastcall TLoginDialog::GetFSProtocol()
  2681. {
  2682. return IndexToFSProtocol(TransferProtocolCombo->ItemIndex, AllowScpFallbackCheck->Checked);
  2683. }
  2684. //---------------------------------------------------------------------------
  2685. bool __fastcall TLoginDialog::IsSshProtocol(TFSProtocol FSProtocol)
  2686. {
  2687. return
  2688. (FSProtocol == fsSFTPonly) || (FSProtocol == fsSFTP) ||
  2689. (FSProtocol == fsSCPonly);
  2690. }
  2691. //---------------------------------------------------------------------------
  2692. int __fastcall TLoginDialog::DefaultPort()
  2693. {
  2694. TFSProtocol FSProtocol = GetFSProtocol();
  2695. TFtps Ftps = GetFtps();
  2696. int Result;
  2697. switch (FSProtocol)
  2698. {
  2699. case fsFTP:
  2700. if (Ftps == ftpsImplicit)
  2701. {
  2702. Result = FtpsImplicitPortNumber;
  2703. }
  2704. else
  2705. {
  2706. Result = FtpPortNumber;
  2707. }
  2708. break;
  2709. case fsWebDAV:
  2710. if (Ftps == ftpsNone)
  2711. {
  2712. Result = HTTPPortNumber;
  2713. }
  2714. else
  2715. {
  2716. Result = HTTPSPortNumber;
  2717. }
  2718. break;
  2719. default:
  2720. if (IsSshProtocol(FSProtocol))
  2721. {
  2722. Result = SshPortNumber;
  2723. }
  2724. else
  2725. {
  2726. FAIL;
  2727. Result = -1;
  2728. }
  2729. break;
  2730. }
  2731. return Result;
  2732. }
  2733. //---------------------------------------------------------------------------
  2734. void __fastcall TLoginDialog::TransferProtocolComboChange(TObject * Sender)
  2735. {
  2736. int ADefaultPort = DefaultPort();
  2737. if (!NoUpdate && FUpdatePortWithProtocol)
  2738. {
  2739. NoUpdate++;
  2740. try
  2741. {
  2742. if (PortNumberEdit->AsInteger == FDefaultPort)
  2743. {
  2744. PortNumberEdit->AsInteger = ADefaultPort;
  2745. }
  2746. }
  2747. __finally
  2748. {
  2749. NoUpdate--;
  2750. }
  2751. }
  2752. FDefaultPort = ADefaultPort;
  2753. DataChange(Sender);
  2754. }
  2755. //---------------------------------------------------------------------------
  2756. void __fastcall TLoginDialog::NavigationTreeCollapsing(
  2757. TObject * /*Sender*/, TTreeNode * /*Node*/, bool & AllowCollapse)
  2758. {
  2759. AllowCollapse = false;
  2760. }
  2761. //---------------------------------------------------------------------------
  2762. void __fastcall TLoginDialog::ProxyLocalCommandBrowseButtonClick(
  2763. TObject * /*Sender*/)
  2764. {
  2765. BrowseForExecutable(ProxyLocalCommandEdit,
  2766. LoadStr(LOGIN_SELECT_LOCAL_PROXY),
  2767. LoadStr(EXECUTABLE_FILTER), false, true);
  2768. }
  2769. //---------------------------------------------------------------------------
  2770. void __fastcall TLoginDialog::SessionTreeExpandedCollapsed(TObject * /*Sender*/,
  2771. TTreeNode * Node)
  2772. {
  2773. UpdateFolderNode(Node);
  2774. }
  2775. //---------------------------------------------------------------------------
  2776. void __fastcall TLoginDialog::SessionTreeCompare(TObject * /*Sender*/,
  2777. TTreeNode * Node1, TTreeNode * Node2, int /*Data*/, int & Compare)
  2778. {
  2779. bool Node1IsWorkspace = IsWorkspaceNode(Node1);
  2780. bool Node2IsWorkspace = IsWorkspaceNode(Node2);
  2781. bool Node1IsFolder = IsFolderNode(Node1);
  2782. bool Node2IsFolder = IsFolderNode(Node2);
  2783. if (Node1IsWorkspace && !Node2IsWorkspace)
  2784. {
  2785. Compare = -1;
  2786. }
  2787. else if (!Node1IsWorkspace && Node2IsWorkspace)
  2788. {
  2789. Compare = 1;
  2790. }
  2791. else if (Node1IsFolder && !Node2IsFolder)
  2792. {
  2793. Compare = -1;
  2794. }
  2795. else if (!Node1IsFolder && Node2IsFolder)
  2796. {
  2797. Compare = 1;
  2798. }
  2799. else if (Node1IsWorkspace || Node1IsFolder)
  2800. {
  2801. Compare = AnsiCompareText(Node1->Text, Node2->Text);
  2802. }
  2803. else
  2804. {
  2805. Compare = NamedObjectSortProc(Node1->Data, Node2->Data);
  2806. }
  2807. }
  2808. //---------------------------------------------------------------------------
  2809. void __fastcall TLoginDialog::NewSessionFolderInputDialogInitialize(
  2810. TObject * /*Sender*/, TInputDialogData * Data)
  2811. {
  2812. TEdit * Edit = Data->Edit;
  2813. int P = Edit->Text.LastDelimiter(L"/");
  2814. if (P > 0)
  2815. {
  2816. Edit->SetFocus();
  2817. Edit->SelStart = P;
  2818. Edit->SelLength = Edit->Text.Length() - P;
  2819. }
  2820. }
  2821. //---------------------------------------------------------------------------
  2822. TTreeNode * __fastcall TLoginDialog::SessionFolderNode(TTreeNode * Node)
  2823. {
  2824. TTreeNode * Parent;
  2825. if (IsSessionNode(Node))
  2826. {
  2827. Parent = Node->Parent;
  2828. }
  2829. else if (IsFolderNode(Node))
  2830. {
  2831. Parent = Node;
  2832. }
  2833. else if (IsWorkspaceNode(Node))
  2834. {
  2835. Parent = NULL;
  2836. }
  2837. else
  2838. {
  2839. assert(Node == NULL);
  2840. Parent = NULL;
  2841. }
  2842. return Parent;
  2843. }
  2844. //---------------------------------------------------------------------------
  2845. TTreeNode * __fastcall TLoginDialog::CurrentSessionFolderNode()
  2846. {
  2847. return SessionFolderNode(SessionTree->Selected);
  2848. }
  2849. //---------------------------------------------------------------------------
  2850. void __fastcall TLoginDialog::NewSessionFolderActionExecute(
  2851. TObject * /*Sender*/)
  2852. {
  2853. UnicodeString Name =
  2854. UnixIncludeTrailingBackslash(SessionNodePath(CurrentSessionFolderNode())) +
  2855. LoadStr(NEW_FOLDER);
  2856. if (InputDialog(LoadStr(LOGIN_NEW_SESSION_FOLDER_CAPTION),
  2857. LoadStr(LOGIN_NEW_SESSION_FOLDER_PROMPT), Name, HELP_NEW_SESSION_FOLDER,
  2858. NULL, true, NewSessionFolderInputDialogInitialize))
  2859. {
  2860. Name = UnixExcludeTrailingBackslash(Name);
  2861. if (!Name.IsEmpty())
  2862. {
  2863. TTreeNode * Parent = AddSessionPath(UnixExtractFilePath(Name), true, false);
  2864. // this does not prevent creation of subfolder under workspace,
  2865. // if user creates more levels at once (but it does not show up anyway)
  2866. CheckIsSessionFolder(Parent);
  2867. CheckDuplicateFolder(Parent, UnixExtractFileName(Name), NULL);
  2868. TTreeNode * Node = AddSessionPath(Name, true, false);
  2869. SessionTree->Selected = Node;
  2870. Node->MakeVisible();
  2871. }
  2872. }
  2873. }
  2874. //---------------------------------------------------------------------------
  2875. bool __fastcall TLoginDialog::SessionAllowDrop(TTreeNode * DropTarget)
  2876. {
  2877. return
  2878. (SessionTree->Selected != NULL) &&
  2879. (SessionTree->Selected->Parent != DropTarget) &&
  2880. !IsWorkspaceNode(DropTarget);
  2881. }
  2882. //---------------------------------------------------------------------------
  2883. void __fastcall TLoginDialog::SessionTreeProc(TMessage & AMessage)
  2884. {
  2885. if (AMessage.Msg == CM_DRAG)
  2886. {
  2887. TCMDrag & Message = reinterpret_cast<TCMDrag &>(AMessage);
  2888. // reimplement dmDragMove to avoid TCustomTreeView.DoDragOver,
  2889. // which resets DropTarget to pointed-to node
  2890. // (note that this disables OnDragOver event handler)
  2891. if ((Message.DragMessage == dmDragMove) ||
  2892. (Message.DragMessage == dmDragEnter) ||
  2893. (Message.DragMessage == dmDragLeave))
  2894. {
  2895. if (Message.DragMessage != dmDragMove)
  2896. {
  2897. // must call it at least for dmDragLeave, because it does some cleanup,
  2898. // but we need to override result below, as it defaults to "not accepted"
  2899. FOldSessionTreeProc(AMessage);
  2900. }
  2901. TDragControlObject * DragObject = dynamic_cast<TDragControlObject *>(Message.DragRec->Source);
  2902. if ((DragObject != NULL) && (DragObject->Control == SessionTree))
  2903. {
  2904. TPoint P = SessionTree->ScreenToClient(Message.DragRec->Pos);
  2905. TTreeNode * Node = SessionTree->GetNodeAt(P.x, P.y);
  2906. TTreeNode * DropTarget =
  2907. IsWorkspaceNode(Node) ? Node : SessionFolderNode(Node);
  2908. if (!SessionAllowDrop(DropTarget))
  2909. {
  2910. DropTarget = NULL;
  2911. Message.Result = 0;
  2912. }
  2913. else
  2914. {
  2915. Message.Result = 1;
  2916. }
  2917. if (Message.DragMessage == dmDragMove)
  2918. {
  2919. SessionTree->DropTarget = DropTarget;
  2920. }
  2921. FScrollOnDragOver->DragOver(P);
  2922. }
  2923. else
  2924. {
  2925. Message.Result = 0;
  2926. }
  2927. }
  2928. else
  2929. {
  2930. FOldSessionTreeProc(AMessage);
  2931. }
  2932. }
  2933. else
  2934. {
  2935. FOldSessionTreeProc(AMessage);
  2936. }
  2937. }
  2938. //---------------------------------------------------------------------------
  2939. void __fastcall TLoginDialog::SessionTreeStartDrag(TObject * /*Sender*/,
  2940. TDragObject *& /*DragObject*/)
  2941. {
  2942. assert(SessionTree->Selected != NULL);
  2943. // neither session folders/workspaces not special sessions can be dragged
  2944. if ((SessionTree->Selected == NULL) ||
  2945. IsFolderOrWorkspaceNode(SessionTree->Selected) ||
  2946. (IsSessionNode(SessionTree->Selected) && SelectedSession->Special))
  2947. {
  2948. Abort();
  2949. }
  2950. FScrollOnDragOver->StartDrag();
  2951. }
  2952. //---------------------------------------------------------------------------
  2953. void __fastcall TLoginDialog::SessionTreeDragDrop(TObject * Sender,
  2954. TObject * Source, int /*X*/, int /*Y*/)
  2955. {
  2956. TTreeNode * DropTarget = SessionTree->DropTarget;
  2957. if ((Sender == Source) && SessionAllowDrop(DropTarget))
  2958. {
  2959. TSessionData * Session = SelectedSession;
  2960. UnicodeString Path =
  2961. UnixIncludeTrailingBackslash(SessionNodePath(DropTarget)) +
  2962. UnixExtractFileName(Session->SessionName);
  2963. SessionNameValidate(Path, Session);
  2964. // remove from storage
  2965. Session->Remove();
  2966. TSessionData * NewSession = StoredSessions->NewSession(Path, Session);
  2967. // modified, only explicit
  2968. StoredSessions->Save(false, true);
  2969. // this should aways be the case
  2970. if (Session != NewSession)
  2971. {
  2972. TTreeNode * Node = SessionTree->Selected;
  2973. // look for overwritten node (if any)
  2974. TTreeNode * ANode = SessionTree->Items->GetFirstNode();
  2975. while (ANode != NULL)
  2976. {
  2977. if (ANode->Data == NewSession)
  2978. {
  2979. ANode->Delete();
  2980. break;
  2981. }
  2982. ANode = ANode->GetNext();
  2983. }
  2984. Node->MoveTo(DropTarget, naAddChild);
  2985. Node->Data = NewSession;
  2986. // try to make both visible
  2987. if (DropTarget != NULL)
  2988. {
  2989. DropTarget->MakeVisible();
  2990. }
  2991. Node->MakeVisible();
  2992. DestroySession(Session);
  2993. }
  2994. else
  2995. {
  2996. assert(false);
  2997. }
  2998. SetSessionData(NewSession);
  2999. }
  3000. else
  3001. {
  3002. assert(false);
  3003. }
  3004. }
  3005. //---------------------------------------------------------------------------
  3006. void __fastcall TLoginDialog::SessionTreeMouseMove(TObject * /*Sender*/,
  3007. TShiftState /*Shift*/, int X, int Y)
  3008. {
  3009. TTreeNode * Node = SessionTree->GetNodeAt(X, Y);
  3010. THitTests HitTest = SessionTree->GetHitTestInfoAt(X, Y);
  3011. if (Node != FHintNode)
  3012. {
  3013. Application->CancelHint();
  3014. UnicodeString Hint;
  3015. if (HitTest.Contains(htOnItem) || HitTest.Contains(htOnIcon) ||
  3016. HitTest.Contains(htOnLabel) || HitTest.Contains(htOnStateIcon))
  3017. {
  3018. FHintNode = Node;
  3019. if (IsSessionNode(Node))
  3020. {
  3021. Hint = GetNodeSession(Node)->InfoTip;
  3022. }
  3023. else if (IsWorkspaceNode(Node))
  3024. {
  3025. UnicodeString Path = SessionNodePath(Node);
  3026. Hint = FMTLOAD(WORKSPACE_INFO_TIP, (Path));
  3027. std::auto_ptr<TStrings> Names(FStoredSessions->GetFolderOrWorkspaceList(Path));
  3028. for (int Index = 0; Index < Names->Count; Index++)
  3029. {
  3030. Hint += L"\n " + Names->Strings[Index];
  3031. }
  3032. }
  3033. else
  3034. {
  3035. Hint = L"";
  3036. }
  3037. }
  3038. else
  3039. {
  3040. FHintNode = NULL;
  3041. Hint = L"";
  3042. }
  3043. SessionTree->Hint = Hint;
  3044. }
  3045. }
  3046. //---------------------------------------------------------------------------
  3047. void __fastcall TLoginDialog::SessionTreeEndDrag(TObject * /*Sender*/,
  3048. TObject * /*Target*/, int /*X*/, int /*Y*/)
  3049. {
  3050. FScrollOnDragOver->EndDrag();
  3051. }
  3052. //---------------------------------------------------------------------------
  3053. void __fastcall TLoginDialog::AnonymousLoginCheckClick(TObject * /*Sender*/)
  3054. {
  3055. if (AnonymousLoginCheck->Checked)
  3056. {
  3057. UserNameEdit->Text = AnonymousUserName;
  3058. PasswordEdit->Text = AnonymousPassword;
  3059. }
  3060. UpdateControls();
  3061. }
  3062. //---------------------------------------------------------------------------
  3063. void __fastcall TLoginDialog::SaveButtonDropDownClick(TObject * /*Sender*/)
  3064. {
  3065. MenuPopup(SaveDropDownMenu, SaveButton);
  3066. }
  3067. //---------------------------------------------------------------------------
  3068. void __fastcall TLoginDialog::SessionTreeExpanding(TObject * /*Sender*/,
  3069. TTreeNode * Node, bool & AllowExpansion)
  3070. {
  3071. AllowExpansion = IsFolderNode(Node);
  3072. }
  3073. //---------------------------------------------------------------------------
  3074. void __fastcall TLoginDialog::ExecuteTool(const UnicodeString & Name)
  3075. {
  3076. UnicodeString Path;
  3077. if (!FindTool(Name, Path) ||
  3078. !ExecuteShell(Path, L""))
  3079. {
  3080. throw Exception(FMTLOAD(EXECUTE_APP_ERROR, (Name)));
  3081. }
  3082. }
  3083. //---------------------------------------------------------------------------
  3084. void __fastcall TLoginDialog::RunPageantActionExecute(TObject * /*Sender*/)
  3085. {
  3086. ExecuteTool(PageantTool);
  3087. }
  3088. //---------------------------------------------------------------------------
  3089. void __fastcall TLoginDialog::RunPuttygenActionExecute(TObject * /*Sender*/)
  3090. {
  3091. ExecuteTool(PuttygenTool);
  3092. }
  3093. //---------------------------------------------------------------------------
  3094. void __fastcall TLoginDialog::PortNumberEditChange(TObject * Sender)
  3095. {
  3096. if (!NoUpdate)
  3097. {
  3098. bool WellKnownPort = false;
  3099. TFSProtocol FSProtocol;
  3100. TFtps Ftps = ftpsNone;
  3101. int PortNumber = PortNumberEdit->AsInteger;
  3102. if (PortNumber == SshPortNumber)
  3103. {
  3104. FSProtocol = fsSFTP;
  3105. WellKnownPort = true;
  3106. }
  3107. else if (PortNumber == FtpPortNumber)
  3108. {
  3109. FSProtocol = fsFTP;
  3110. WellKnownPort = true;
  3111. }
  3112. else if (PortNumber == FtpsImplicitPortNumber)
  3113. {
  3114. FSProtocol = fsFTP;
  3115. Ftps = ftpsImplicit;
  3116. WellKnownPort = true;
  3117. }
  3118. else if (PortNumber == HTTPPortNumber)
  3119. {
  3120. FSProtocol = fsWebDAV;
  3121. WellKnownPort = true;
  3122. }
  3123. else if (PortNumber == HTTPSPortNumber)
  3124. {
  3125. FSProtocol = fsWebDAV;
  3126. Ftps = ftpsImplicit;
  3127. WellKnownPort = true;
  3128. }
  3129. if (WellKnownPort)
  3130. {
  3131. bool AllowScpFallback;
  3132. int ProtocolIndex = FSProtocolToIndex(FSProtocol, AllowScpFallback);
  3133. if ((TransferProtocolCombo->ItemIndex == ProtocolIndex) &&
  3134. (GetFtps() == Ftps))
  3135. {
  3136. FUpdatePortWithProtocol = true;
  3137. }
  3138. else
  3139. {
  3140. FUpdatePortWithProtocol = false;
  3141. NoUpdate++;
  3142. try
  3143. {
  3144. TransferProtocolCombo->ItemIndex = ProtocolIndex;
  3145. FtpsCombo->ItemIndex = Ftps;
  3146. WebDavsCombo->ItemIndex = Ftps;
  3147. }
  3148. __finally
  3149. {
  3150. NoUpdate--;
  3151. }
  3152. }
  3153. }
  3154. }
  3155. DataChange(Sender);
  3156. }
  3157. //---------------------------------------------------------------------------
  3158. UnicodeString __fastcall TLoginDialog::ImportExportIniFilePath()
  3159. {
  3160. UnicodeString PersonalDirectory;
  3161. ::SpecialFolderLocation(CSIDL_PERSONAL, PersonalDirectory);
  3162. UnicodeString FileName = IncludeTrailingBackslash(PersonalDirectory) +
  3163. ExtractFileName(ExpandEnvironmentVariables(Configuration->IniFileStorageName));
  3164. return FileName;
  3165. }
  3166. //---------------------------------------------------------------------------
  3167. void __fastcall TLoginDialog::ExportActionExecute(TObject * /*Sender*/)
  3168. {
  3169. UnicodeString FileName = ImportExportIniFilePath();
  3170. if (SaveDialog(LoadStr(EXPORT_CONF_TITLE), LoadStr(EXPORT_CONF_FILTER), L"ini", FileName))
  3171. {
  3172. Configuration->Export(FileName);
  3173. }
  3174. }
  3175. //---------------------------------------------------------------------------
  3176. void __fastcall TLoginDialog::ImportActionExecute(TObject * /*Sender*/)
  3177. {
  3178. if (MessageDialog(LoadStr(IMPORT_CONFIGURATION),
  3179. qtWarning, qaOK | qaCancel, HELP_IMPORT_CONFIGURATION) == qaOK)
  3180. {
  3181. std::auto_ptr<TOpenDialog> OpenDialog(new TOpenDialog(Application));
  3182. OpenDialog->Title = LoadStr(IMPORT_CONF_TITLE);
  3183. OpenDialog->Filter = LoadStr(EXPORT_CONF_FILTER);
  3184. OpenDialog->DefaultExt = L"ini";
  3185. OpenDialog->FileName = ImportExportIniFilePath();
  3186. if (OpenDialog->Execute())
  3187. {
  3188. // before the session list gets destroyed
  3189. SessionTree->Items->Clear();
  3190. Configuration->Import(OpenDialog->FileName);
  3191. ReloadSessions();
  3192. }
  3193. }
  3194. }
  3195. //---------------------------------------------------------------------------
  3196. void __fastcall TLoginDialog::ResetSitesIncrementalSearch()
  3197. {
  3198. FSitesIncrementalSearch = L"";
  3199. // this is to prevent active tree node being set back to Sites tab
  3200. // (from UpdateNavigationTree) when we are called from SessionTreeExit,
  3201. // while tab is changing
  3202. if (NoUpdate == 0)
  3203. {
  3204. UpdateControls();
  3205. }
  3206. }
  3207. //---------------------------------------------------------------------------
  3208. bool __fastcall TLoginDialog::SitesIncrementalSearch(const UnicodeString & Text,
  3209. bool SkipCurrent, bool Reverse)
  3210. {
  3211. TTreeNode * Node = SearchSite(Text, false, SkipCurrent, Reverse);
  3212. if (Node == NULL)
  3213. {
  3214. Node = SearchSite(Text, true, SkipCurrent, Reverse);
  3215. if (Node != NULL)
  3216. {
  3217. TTreeNode * Parent = Node->Parent;
  3218. while (Parent != NULL)
  3219. {
  3220. Parent->Expand(false);
  3221. Parent = Parent->Parent;
  3222. }
  3223. }
  3224. }
  3225. bool Result = (Node != NULL);
  3226. if (Result)
  3227. {
  3228. {
  3229. TAutoNestingCounter Guard(FIncrementalSearching);
  3230. SessionTree->Selected = Node;
  3231. }
  3232. FSitesIncrementalSearch = Text;
  3233. // Tab always searches even in collapsed nodes
  3234. TTreeNode * NextNode = SearchSite(Text, true, true, Reverse);
  3235. FSitesIncrementalSearchHaveNext =
  3236. (NextNode != NULL) && (NextNode != Node);
  3237. UpdateControls();
  3238. // make visible only after search panel is shown, what may obscure the node
  3239. Node->MakeVisible();
  3240. }
  3241. return Result;
  3242. }
  3243. //---------------------------------------------------------------------------
  3244. TTreeNode * __fastcall TLoginDialog::GetNextNode(TTreeNode * Node, bool Reverse)
  3245. {
  3246. if (Reverse)
  3247. {
  3248. Node = Node->GetPrev();
  3249. if (Node == NULL)
  3250. {
  3251. // GetLastNode
  3252. // http://stackoverflow.com/questions/6257348/how-should-i-implement-getlastnode-for-ttreenodes
  3253. Node = SessionTree->Items->GetFirstNode();
  3254. TTreeNode * Node2 = Node;
  3255. if (Node2 != NULL)
  3256. {
  3257. do
  3258. {
  3259. Node2 = Node;
  3260. if (Node != NULL)
  3261. {
  3262. Node = Node2->getNextSibling();
  3263. }
  3264. if (Node == NULL)
  3265. {
  3266. Node = Node2->getFirstChild();
  3267. }
  3268. }
  3269. while (Node != NULL);
  3270. }
  3271. Node = Node2;
  3272. }
  3273. }
  3274. else
  3275. {
  3276. Node = Node->GetNext();
  3277. if (Node == NULL)
  3278. {
  3279. Node = SessionTree->Items->GetFirstNode();
  3280. }
  3281. }
  3282. return Node;
  3283. }
  3284. //---------------------------------------------------------------------------
  3285. TTreeNode * __fastcall TLoginDialog::SearchSite(const UnicodeString & Text,
  3286. bool AllowExpanding, bool SkipCurrent, bool Reverse)
  3287. {
  3288. TTreeNode * CurrentNode =
  3289. (SessionTree->Selected != NULL) ? SessionTree->Selected : SessionTree->Items->GetFirstNode();
  3290. if (CurrentNode == NULL)
  3291. {
  3292. return NULL;
  3293. }
  3294. else
  3295. {
  3296. TTreeNode * Node = CurrentNode;
  3297. if (SkipCurrent)
  3298. {
  3299. Node = GetNextNode(Node, Reverse);
  3300. if (Node == NULL)
  3301. {
  3302. return NULL;
  3303. }
  3304. }
  3305. while (true)
  3306. {
  3307. bool Eligible = true;
  3308. TTreeNode * Parent = Node->Parent;
  3309. while (Eligible && (Parent != NULL))
  3310. {
  3311. Eligible =
  3312. IsFolderNode(Parent) &&
  3313. (Parent->Expanded || AllowExpanding);
  3314. Parent = Parent->Parent;
  3315. }
  3316. if (Eligible && ContainsText(Node->Text, Text))
  3317. {
  3318. return Node;
  3319. }
  3320. Node = GetNextNode(Node, Reverse);
  3321. if (Node == CurrentNode)
  3322. {
  3323. return NULL;
  3324. }
  3325. }
  3326. }
  3327. }
  3328. //---------------------------------------------------------------------------
  3329. void __fastcall TLoginDialog::SessionTreeExit(TObject * /*Sender*/)
  3330. {
  3331. ResetSitesIncrementalSearch();
  3332. }
  3333. //---------------------------------------------------------------------------