1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2016-2017 - TortoiseGit
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "TortoiseProc.h"
21 #include "FirstStartWizard.h"
22 #include "FirstStartWizardAuthentication.h"
24 #include "Settings\SettingGitCredential.h"
25 #include "PathUtils.h"
27 #define WM_SETPAGEFOCUS WM_APP+2
29 IMPLEMENT_DYNAMIC(CFirstStartWizardAuthentication
, CFirstStartWizardBasePage
)
31 CFirstStartWizardAuthentication::CFirstStartWizardAuthentication() : CFirstStartWizardBasePage(CFirstStartWizardAuthentication::IDD
)
34 m_psp
.dwFlags
|= PSP_DEFAULT
| PSP_USEHEADERTITLE
;
35 m_psp
.pszHeaderTitle
= MAKEINTRESOURCE(IDS_FIRSTSTART_AUTHENTICATIONTITLE
);
38 CFirstStartWizardAuthentication::~CFirstStartWizardAuthentication()
42 void CFirstStartWizardAuthentication::DoDataExchange(CDataExchange
* pDX
)
44 CFirstStartWizardBasePage::DoDataExchange(pDX
);
45 DDX_Check(pDX
, IDC_DONTSAVE
, m_bNoSave
);
46 DDX_Control(pDX
, IDC_COMBO_SIMPLECREDENTIAL
, m_ctrlSimpleCredential
);
47 DDX_Control(pDX
, IDC_COMBO_SSHCLIENT
, m_ctrlSSHClient
);
50 BEGIN_MESSAGE_MAP(CFirstStartWizardAuthentication
, CFirstStartWizardBasePage
)
51 ON_BN_CLICKED(IDC_GENERATEPUTTYKEY
, &CFirstStartWizardAuthentication::OnBnClickedGenerateputtykey
)
52 ON_BN_CLICKED(IDC_ADVANCEDCONFIGURATION
, &CFirstStartWizardAuthentication::OnBnClickedAdvancedconfiguration
)
53 ON_BN_CLICKED(IDC_DONTSAVE
, OnClickedNoSave
)
54 ON_MESSAGE(WM_SETPAGEFOCUS
, OnDialogDisplayed
)
55 ON_NOTIFY(NM_CLICK
, IDC_FIRSTSTART_SSHHINT
, OnClickedLink
)
58 void CFirstStartWizardAuthentication::OnClickedNoSave()
61 m_ctrlSimpleCredential
.EnableWindow(!m_bNoSave
);
64 static bool IsToolBasename(const CString
& toolname
, LPCTSTR setting
)
66 if (toolname
.CompareNoCase(setting
) == 0)
69 if ((toolname
+ L
".exe").CompareNoCase(setting
) == 0)
75 static bool IsTool(const CString
& toolname
, LPCTSTR setting
)
77 if (IsToolBasename(toolname
, setting
))
80 if (!IsToolBasename(toolname
, PathFindFileName(setting
)))
83 if (PathIsRelative(setting
) || !PathFileExists(setting
))
89 BOOL
CFirstStartWizardAuthentication::OnWizardFinish()
93 CString sshclient
= CRegString(L
"Software\\TortoiseGit\\SSH");
94 if (sshclient
.IsEmpty())
95 sshclient
= CRegString(L
"Software\\TortoiseGit\\SSH", L
"", FALSE
, HKEY_LOCAL_MACHINE
);
96 if (m_ctrlSSHClient
.GetCurSel() == 0 && !(sshclient
.IsEmpty() || IsTool(L
"tortoisegitplink", sshclient
) || IsTool(L
"tortoiseplink", sshclient
)))
97 CRegString(L
"Software\\TortoiseGit\\SSH") = CPathUtils::GetAppDirectory() + L
"TortoiseGitPlink.exe";
98 else if (m_ctrlSSHClient
.GetCurSel() == 1 && !IsTool(L
"ssh", sshclient
))
99 CRegString(L
"Software\\TortoiseGit\\SSH") = L
"ssh.exe";
101 if (m_ctrlSimpleCredential
.IsWindowEnabled() && !m_bNoSave
&& m_ctrlSimpleCredential
.GetCurSel() != -1)
103 CAutoConfig
config(true);
104 int err
= git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitGlobalXDGConfig()), GIT_CONFIG_LEVEL_XDG
, FALSE
);
105 if (!err
&& (PathFileExists(g_Git
.GetGitGlobalConfig()) || !PathFileExists(g_Git
.GetGitGlobalXDGConfig())))
106 err
= git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitGlobalConfig()), GIT_CONFIG_LEVEL_GLOBAL
, FALSE
);
109 MessageBox(g_Git
.GetLibGit2LastErr(), L
"TortoiseGit", MB_ICONEXCLAMATION
);
113 if (m_ctrlSimpleCredential
.GetCurSel() == 0 && m_availableHelpers
.at(0) == CString(MAKEINTRESOURCE(IDS_NONE
)))
115 int ret
= git_config_delete_entry(config
, "credential.helper");
116 if (ret
!= 0 && ret
!= GIT_ENOTFOUND
)
118 MessageBox(g_Git
.GetLibGit2LastErr(), L
"TortoiseGit", MB_ICONEXCLAMATION
);
122 else if (git_config_set_string(config
, "credential.helper", CUnicodeUtils::GetUTF8(m_availableHelpers
.at(m_ctrlSimpleCredential
.GetCurSel()))))
124 MessageBox(g_Git
.GetLibGit2LastErr(), L
"TortoiseGit", MB_ICONEXCLAMATION
);
129 return __super::OnWizardFinish();
132 static void AddHelper(CComboBox
& combobox
, STRING_VECTOR
& availableHelpers
, const CString
& helper
, const CString
& selected
= L
"")
134 availableHelpers
.push_back(helper
);
135 int idx
= combobox
.AddString(helper
);
136 if (selected
== helper
)
137 combobox
.SetCurSel(idx
);
140 BOOL
CFirstStartWizardAuthentication::OnInitDialog()
142 CFirstStartWizardBasePage::OnInitDialog();
145 tmp
.LoadString(IDS_FIRSTSTART_SSHHINT
);
146 GetDlgItem(IDC_FIRSTSTART_SSHHINT
)->SetWindowText(tmp
);
148 CAutoConfig
config(true);
149 if (git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitGlobalConfig()), GIT_CONFIG_LEVEL_GLOBAL
, FALSE
))
150 MessageBox(g_Git
.GetLibGit2LastErr(), L
"TortoiseGit", MB_ICONEXCLAMATION
);
153 if (git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitGlobalXDGConfig()), GIT_CONFIG_LEVEL_XDG
, FALSE
))
154 MessageBox(g_Git
.GetLibGit2LastErr(), L
"TortoiseGit", MB_ICONEXCLAMATION
);
156 if (!g_Git
.ms_bCygwinGit
&& !g_Git
.ms_bMsys2Git
)
158 if (git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitProgramDataConfig()), GIT_CONFIG_LEVEL_PROGRAMDATA
, FALSE
))
159 MessageBox(g_Git
.GetLibGit2LastErr(), L
"TortoiseGit", MB_ICONEXCLAMATION
);
161 if (git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitSystemConfig()), GIT_CONFIG_LEVEL_SYSTEM
, FALSE
))
162 MessageBox(g_Git
.GetLibGit2LastErr(), L
"TortoiseGit", MB_ICONEXCLAMATION
);
164 STRING_VECTOR defaultList
;
165 git_config_foreach_match(config
, "credential\\.helper", CSettingGitCredential::GetCredentialDefaultUrlCallback
, &defaultList
);
167 if (defaultList
.size() <= 1 && (defaultList
.empty() || defaultList
.at(0)[0] == 'X' || defaultList
.at(0)[0] == 'G'))
168 AddHelper(m_ctrlSimpleCredential
, m_availableHelpers
, MAKEINTRESOURCE(IDS_NONE
));
169 CString selectedHelper
;
170 if (config
.GetString(L
"credential.helper", selectedHelper
) == GIT_ENOTFOUND
)
171 m_ctrlSimpleCredential
.SetCurSel(0);
173 if (CSettingGitCredential::GCMExists())
174 AddHelper(m_ctrlSimpleCredential
, m_availableHelpers
, L
"manager", selectedHelper
);
175 if (CSettingGitCredential::WincredExists())
176 AddHelper(m_ctrlSimpleCredential
, m_availableHelpers
, L
"wincred", selectedHelper
);
177 if (CSettingGitCredential::WinstoreExists())
178 AddHelper(m_ctrlSimpleCredential
, m_availableHelpers
, CSettingGitCredential::GetWinstorePath(), selectedHelper
);
180 STRING_VECTOR urlList
;
181 git_config_foreach_match(config
, "credential\\..*\\.helper", CSettingGitCredential::GetCredentialUrlCallback
, &urlList
);
182 if (!urlList
.empty() || m_ctrlSimpleCredential
.GetCurSel() == -1)
184 m_ctrlSimpleCredential
.EnableWindow(FALSE
);
185 m_availableHelpers
.clear();
186 m_ctrlSimpleCredential
.Clear();
187 AddHelper(m_ctrlSimpleCredential
, m_availableHelpers
, MAKEINTRESOURCE(IDS_ADVANCED
));
188 m_ctrlSimpleCredential
.SetCurSel(0);
191 AdjustControlSize(IDC_DONTSAVE
);
193 CString sshclient
= CRegString(L
"Software\\TortoiseGit\\SSH");
194 if (sshclient
.IsEmpty())
195 sshclient
= CRegString(L
"Software\\TortoiseGit\\SSH", L
"", FALSE
, HKEY_LOCAL_MACHINE
);
197 int idx
= m_ctrlSSHClient
.AddString(L
"TortoiseGitPlink");
198 if (sshclient
.IsEmpty() || IsTool(L
"tortoisegitplink", sshclient
) || IsTool(L
"tortoiseplink", sshclient
))
199 m_ctrlSSHClient
.SetCurSel(idx
);
200 idx
= m_ctrlSSHClient
.AddString(L
"OpenSSH");
201 if (IsTool(L
"ssh", sshclient
))
202 m_ctrlSSHClient
.SetCurSel(idx
);
203 if (m_ctrlSSHClient
.GetCurSel() == -1)
205 idx
= m_ctrlSSHClient
.AddString(sshclient
);
206 m_ctrlSSHClient
.SetCurSel(idx
);
209 // TODO: Hide the button if PuTTY is not used?
210 //GetDlgItem(IDC_GENERATEPUTTYKEY)->ShowWindow(CAppUtils::IsSSHPutty() ? SW_SHOW : SW_HIDE);
217 BOOL
CFirstStartWizardAuthentication::OnSetActive()
219 CFirstStartWizard
* wiz
= (CFirstStartWizard
*)GetParent();
221 wiz
->SetWizardButtons(PSWIZB_FINISH
| PSWIZB_BACK
);
223 PostMessage(WM_SETPAGEFOCUS
, 0, 0);
225 return CFirstStartWizardBasePage::OnSetActive();
228 void CFirstStartWizardAuthentication::OnBnClickedGenerateputtykey()
230 CCommonAppUtils::LaunchApplication(CPathUtils::GetAppDirectory() + L
"puttygen.exe", 0, false);
233 void CFirstStartWizardAuthentication::OnBnClickedAdvancedconfiguration()
239 CAppUtils::RunTortoiseGitProc(L
"/command:settings /page:gitcredential", false, false);
242 LRESULT
CFirstStartWizardAuthentication::OnDialogDisplayed(WPARAM
/*wParam*/, LPARAM
/*lParam*/)
244 GetDlgItem(IDC_COMBO_SSHCLIENT
)->SetFocus();
249 void CFirstStartWizardAuthentication::OnClickedLink(NMHDR
* pNMHDR
, LRESULT
* pResult
)
251 ATLASSERT(pNMHDR
&& pResult
);
252 auto pNMLink
= reinterpret_cast<PNMLINK
>(pNMHDR
);
253 if (wcscmp(pNMLink
->item
.szID
, L
"manual") == 0)
254 HtmlHelp(0x20000 + IDD_FIRSTSTARTWIZARD_AUTHENTICATION
);
255 else if (wcscmp(pNMLink
->item
.szID
, L
"sshfaq") == 0)
257 CString
helppath(theApp
.m_pszHelpFilePath
);
258 helppath
+= L
"::/tgit-ssh-howto.html";
259 ::HtmlHelp(GetSafeHwnd(), helppath
, HH_DISPLAY_TOPIC
, 0);