Don't try to store credential settings if advanced settings were detected
[TortoiseGit.git] / src / TortoiseProc / FirstStartWizardAuthentication.cpp
blob73d1f00301d7dc34b4f5c76e79fceae1b4ff243f
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.
19 #include "stdafx.h"
20 #include "TortoiseProc.h"
21 #include "FirstStartWizard.h"
22 #include "FirstStartWizardAuthentication.h"
23 #include "Git.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)
32 , m_bNoSave(FALSE)
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)
56 END_MESSAGE_MAP()
58 void CFirstStartWizardAuthentication::OnClickedNoSave()
60 UpdateData();
61 m_ctrlSimpleCredential.EnableWindow(!m_bNoSave);
64 static bool IsToolBasename(const CString& toolname, LPCTSTR setting)
66 if (toolname.CompareNoCase(setting) == 0)
67 return true;
69 if ((toolname + L".exe").CompareNoCase(setting) == 0)
70 return true;
72 return false;
75 static bool IsTool(const CString& toolname, LPCTSTR setting)
77 if (IsToolBasename(toolname, setting))
78 return true;
80 if (!IsToolBasename(toolname, PathFindFileName(setting)))
81 return false;
83 if (PathIsRelative(setting) || !PathFileExists(setting))
84 return false;
86 return true;
89 BOOL CFirstStartWizardAuthentication::OnWizardFinish()
91 UpdateData();
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);
107 if (err)
109 MessageBox(g_Git.GetLibGit2LastErr(), L"TortoiseGit", MB_ICONEXCLAMATION);
110 return FALSE;
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);
119 return FALSE;
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);
125 return FALSE;
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();
144 CString tmp;
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);
151 else
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);
212 UpdateData(FALSE);
214 return TRUE;
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()
235 UpdateData();
236 m_bNoSave = TRUE;
237 UpdateData(FALSE);
238 OnClickedNoSave();
239 CAppUtils::RunTortoiseGitProc(L"/command:settings /page:gitcredential", false, false);
242 LRESULT CFirstStartWizardAuthentication::OnDialogDisplayed(WPARAM /*wParam*/, LPARAM /*lParam*/)
244 GetDlgItem(IDC_COMBO_SSHCLIENT)->SetFocus();
246 return 0;
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);
261 *pResult = 0;