Fixed issue #1136: Proxy password with @ symbol not parsed/saved correctly
[TortoiseGit.git] / src / TortoiseProc / Settings / SetProxyPage.cpp
blob8be02137e03b6867c232f9cb258b4be38c500179
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2010-2012 - TortoiseGit
4 // Copyright (C) 2003-2007 - TortoiseSVN
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "stdafx.h"
21 #include "TortoiseProc.h"
22 #include "SetProxyPage.h"
23 #include "AppUtils.h"
24 #include "StringUtils.h"
25 #include "git.h"
26 #include ".\setproxypage.h"
27 #include "MessageBox.h"
29 IMPLEMENT_DYNAMIC(CSetProxyPage, ISettingsPropPage)
30 CSetProxyPage::CSetProxyPage()
31 : ISettingsPropPage(CSetProxyPage::IDD)
32 , m_serveraddress(_T(""))
33 , m_serverport(0)
34 , m_username(_T(""))
35 , m_password(_T(""))
36 , m_isEnabled(FALSE)
37 , m_SSHClient(_T(""))
39 m_regServeraddress = CRegString(_T("Software\\TortoiseGit\\Git\\Servers\\global\\http-proxy-host"), _T(""));
40 m_regServerport = CRegString(_T("Software\\TortoiseGit\\Git\\Servers\\global\\http-proxy-port"), _T(""));
41 m_regUsername = CRegString(_T("Software\\TortoiseGit\\Git\\Servers\\global\\http-proxy-username"), _T(""));
42 m_regPassword = CRegString(_T("Software\\TortoiseGit\\Git\\Servers\\global\\http-proxy-password"), _T(""));
43 m_regSSHClient = CRegString(_T("Software\\TortoiseGit\\SSH"));
44 m_SSHClient = m_regSSHClient;
48 CSetProxyPage::~CSetProxyPage()
52 void CSetProxyPage::DoDataExchange(CDataExchange* pDX)
54 ISettingsPropPage::DoDataExchange(pDX);
55 DDX_Text(pDX, IDC_SERVERADDRESS, m_serveraddress);
56 DDX_Text(pDX, IDC_SERVERPORT, m_serverport);
57 DDX_Text(pDX, IDC_USERNAME, m_username);
58 DDX_Text(pDX, IDC_PASSWORD, m_password);
59 DDX_Check(pDX, IDC_ENABLE, m_isEnabled);
60 DDX_Text(pDX, IDC_SSHCLIENT, m_SSHClient);
61 DDX_Control(pDX, IDC_SSHCLIENT, m_cSSHClientEdit);
65 BEGIN_MESSAGE_MAP(CSetProxyPage, ISettingsPropPage)
66 ON_EN_CHANGE(IDC_SERVERADDRESS, OnChange)
67 ON_EN_CHANGE(IDC_SERVERPORT, OnChange)
68 ON_EN_CHANGE(IDC_USERNAME, OnChange)
69 ON_EN_CHANGE(IDC_PASSWORD, OnChange)
70 ON_EN_CHANGE(IDC_TIMEOUT, OnChange)
71 ON_EN_CHANGE(IDC_SSHCLIENT, OnChange)
72 ON_EN_CHANGE(IDC_EXCEPTIONS, OnChange)
73 ON_BN_CLICKED(IDC_ENABLE, OnBnClickedEnable)
74 ON_BN_CLICKED(IDC_SSHBROWSE, OnBnClickedSshbrowse)
75 END_MESSAGE_MAP()
77 HRESULT StringEscape(const CString& str_in, CString* escaped_string) {
78 // http://tools.ietf.org/html/rfc3986#section-3.2.1
79 if (!escaped_string)
80 return E_INVALIDARG;
82 DWORD buf_len = INTERNET_MAX_URL_LENGTH + 1;
83 HRESULT hr = ::UrlEscape(str_in, escaped_string->GetBufferSetLength(buf_len), &buf_len, URL_ESCAPE_PERCENT | URL_ESCAPE_SEGMENT_ONLY);
84 if (SUCCEEDED(hr)) {
85 escaped_string->ReleaseBuffer();
88 escaped_string->Replace(_T("@"), _T("%40"));
89 escaped_string->Replace(_T(":"), _T("%3a"));
91 return hr;
94 HRESULT StringUnescape(const CString& str_in, CString* unescaped_string) {
95 if (!unescaped_string)
96 return E_INVALIDARG;
98 DWORD buf_len = INTERNET_MAX_URL_LENGTH + 1;
99 HRESULT hr = ::UrlUnescape(str_in.AllocSysString(), unescaped_string->GetBufferSetLength(buf_len), &buf_len, 0);
100 if (SUCCEEDED(hr)) {
101 unescaped_string->ReleaseBuffer();
104 return hr;
107 BOOL CSetProxyPage::OnInitDialog()
109 ISettingsPropPage::OnInitDialog();
111 m_tooltips.Create(this);
112 m_tooltips.AddTool(IDC_SERVERADDRESS, IDS_SETTINGS_PROXYSERVER_TT);
114 CString proxy=g_Git.GetConfigValue(_T("http.proxy"),CP_ACP);
116 m_SSHClient = m_regSSHClient;
117 m_serveraddress = m_regServeraddress;
118 m_serverport = _ttoi((LPCTSTR)(CString)m_regServerport);
119 m_username = m_regUsername;
120 m_password = m_regPassword;
122 if (proxy.IsEmpty())
124 m_isEnabled = FALSE;
125 EnableGroup(FALSE);
127 else
129 int start=0;
130 start = proxy.Find(_T("://"),start);
131 if(start<0)
132 start =0;
133 else
134 start+=3;
136 int at = proxy.Find(_T("@"), 0);
137 int port;
139 if(at<0)
141 m_username=_T("");
142 m_password=_T("");
143 port=proxy.Find(_T(":"),start);
144 if(port<0)
145 m_serveraddress = proxy.Mid(start);
146 else
147 m_serveraddress = proxy.Mid(start, port-start);
150 else
152 int username;
153 username = proxy.Find(_T(":"),start);
154 if(username<=0 || username >at)
156 StringUnescape(proxy.Mid(start, at - start), &m_username);
157 m_password=_T("");
159 else if(username < at)
161 StringUnescape(proxy.Mid(start, username - start), &m_username);
162 StringUnescape(proxy.Mid(username + 1, at - username - 1), &m_password);
165 port=proxy.Find(_T(":"),at);
166 if(port<0)
167 m_serveraddress = proxy.Mid(at+1);
168 else
169 m_serveraddress = proxy.Mid(at+1, port-at-1);
172 if(port<0)
174 m_serverport= 0;
176 else
177 m_serverport = _ttoi(proxy.Mid(port+1));
179 m_isEnabled = TRUE;
180 EnableGroup(TRUE);
183 SHAutoComplete(::GetDlgItem(m_hWnd, IDC_SSHCLIENT), SHACF_FILESYSTEM | SHACF_FILESYS_ONLY);
185 UpdateData(FALSE);
187 return TRUE;
190 void CSetProxyPage::OnBnClickedEnable()
192 UpdateData();
193 if (m_isEnabled)
195 EnableGroup(TRUE);
197 else
199 EnableGroup(FALSE);
201 SetModified();
204 void CSetProxyPage::EnableGroup(BOOL b)
206 GetDlgItem(IDC_SERVERADDRESS)->EnableWindow(b);
207 GetDlgItem(IDC_SERVERPORT)->EnableWindow(b);
208 GetDlgItem(IDC_USERNAME)->EnableWindow(b);
209 GetDlgItem(IDC_PASSWORD)->EnableWindow(b);
210 GetDlgItem(IDC_PROXYLABEL1)->EnableWindow(b);
211 GetDlgItem(IDC_PROXYLABEL2)->EnableWindow(b);
212 GetDlgItem(IDC_PROXYLABEL3)->EnableWindow(b);
213 GetDlgItem(IDC_PROXYLABEL6)->EnableWindow(b);
216 BOOL CSetProxyPage::PreTranslateMessage(MSG* pMsg)
218 m_tooltips.RelayEvent(pMsg);
219 return ISettingsPropPage::PreTranslateMessage(pMsg);
222 void CSetProxyPage::OnChange()
224 SetModified();
227 BOOL CSetProxyPage::OnApply()
229 UpdateData();
231 CString temp;
232 Store (m_serveraddress, m_regServeraddress);
233 temp.Format(_T("%d"), m_serverport);
234 Store (temp, m_regServerport);
235 Store (m_username, m_regUsername);
236 Store (m_password, m_regPassword);
239 CString http_proxy;
240 if(!m_serveraddress.IsEmpty())
242 if(m_serveraddress.Left(5) != _T("http:"))
243 http_proxy=_T("http://");
245 if(!m_username.IsEmpty())
247 CString escapedUsername;
249 if (StringEscape(m_username, &escapedUsername))
251 ::MessageBox(NULL, _T("Could not encode username."), _T("TortoiseGit"), MB_ICONERROR);
252 return FALSE;
255 http_proxy += escapedUsername;
257 if(!m_password.IsEmpty())
259 CString escapedPassword;
260 if (StringEscape(m_password, &escapedPassword))
262 ::MessageBox(NULL, _T("Could not encode password."), _T("TortoiseGit"), MB_ICONERROR);
263 return FALSE;
265 http_proxy += _T(":") + escapedPassword;
268 http_proxy += _T("@");
270 http_proxy+=m_serveraddress;
272 if(m_serverport)
274 temp.Format(_T("%d"), m_serverport);
275 http_proxy += _T(":")+temp;
279 if (m_isEnabled)
281 g_Git.SetConfigValue(_T("http.proxy"),http_proxy,CONFIG_GLOBAL);
283 else
285 g_Git.UnsetConfigValue(_T("http.proxy"), CONFIG_GLOBAL);
287 m_regSSHClient = m_SSHClient;
288 SetModified(FALSE);
289 return ISettingsPropPage::OnApply();
292 void CSetProxyPage::OnBnClickedSshbrowse()
294 CString openPath;
295 if (CAppUtils::FileOpenSave(openPath, NULL, IDS_SETTINGS_SELECTSSH, IDS_PROGRAMSFILEFILTER, true, m_hWnd))
297 UpdateData();
298 m_SSHClient = openPath;
299 UpdateData(FALSE);
300 SetModified();