1 #include "filezilla.h"
2 #include "sitemanager_site.h"
3 
4 #include "filezillaapp.h"
5 #include "Options.h"
6 #include "sitemanager_controls.h"
7 #include "sitemanager_dialog.h"
8 #include "textctrlex.h"
9 #include "xrc_helper.h"
10 
11 #include "../include/s3sse.h"
12 
13 #include <libfilezilla/translate.hpp>
14 
15 #include <wx/dcclient.h>
16 #include <wx/gbsizer.h>
17 #include <wx/statline.h>
18 #include <wx/wupdlock.h>
19 
20 #ifdef __WXMSW__
21 #include "commctrl.h"
22 #endif
23 
CSiteManagerSite(CSiteManagerDialog & sitemanager)24 CSiteManagerSite::CSiteManagerSite(CSiteManagerDialog &sitemanager)
25     : sitemanager_(sitemanager)
26 {
27 }
28 
Load(wxWindow * parent)29 bool CSiteManagerSite::Load(wxWindow* parent)
30 {
31 	Create(parent, -1);
32 
33 	DialogLayout lay(static_cast<wxTopLevelWindow*>(wxGetTopLevelParent(parent)));
34 
35 	{
36 		auto onChange = [this](ServerProtocol protocol, LogonType type) {
37 			wxWindowUpdateLocker l(this);
38 			SetControlVisibility(protocol, type);
39 			for (auto & controls : controls_) {
40 				controls->SetControlState();
41 			}
42 			GetContainingSizer()->Layout();
43 		};
44 
45 		generalPage_ = new wxPanel(this);
46 		AddPage(generalPage_, _("General"));
47 
48 		auto* main = lay.createMain(generalPage_, 1);
49 		controls_.emplace_back(std::make_unique<GeneralSiteControls>(*generalPage_, lay, *main, onChange));
50 
51 		main->Add(new wxStaticLine(generalPage_), lay.grow);
52 
53 		auto row = lay.createFlex(0, 1);
54 		main->Add(row);
55 		row->Add(new wxStaticText(generalPage_, -1, _("&Background color:")), lay.valign);
56 		auto colors = new wxChoice(generalPage_, XRCID("ID_COLOR"));
57 		row->Add(colors, lay.valign);
58 
59 		main->Add(new wxStaticText(generalPage_, -1, _("Co&mments:")));
60 		main->Add(new wxTextCtrlEx(generalPage_, XRCID("ID_COMMENTS"), L"", wxDefaultPosition, wxSize(-1, lay.dlgUnits(43)), wxTE_MULTILINE), 1, wxGROW);
61 		main->AddGrowableRow(main->GetEffectiveRowsCount() - 1);
62 
63 		for (int i = 0; ; ++i) {
64 			wxString name = CSiteManager::GetColourName(i);
65 			if (name.empty()) {
66 				break;
67 			}
68 			colors->AppendString(wxGetTranslation(name));
69 		}
70 	}
71 
72 	{
73 		advancedPage_ = new wxPanel(this);
74 		AddPage(advancedPage_, _("Advanced"));
75 		auto * main = lay.createMain(advancedPage_, 1);
76 		controls_.emplace_back(std::make_unique<AdvancedSiteControls>(*advancedPage_, lay, *main));
77 	}
78 
79 	{
80 		transferPage_ = new wxPanel(this);
81 		AddPage(transferPage_, _("Transfer Settings"));
82 		auto * main = lay.createMain(transferPage_, 1);
83 		controls_.emplace_back(std::make_unique<TransferSettingsSiteControls>(*transferPage_, lay, *main));
84 	}
85 
86 	{
87 		charsetPage_ = new wxPanel(this);
88 		AddPage(charsetPage_, _("Charset"));
89 		auto * main = lay.createMain(charsetPage_, 1);
90 		controls_.emplace_back(std::make_unique<CharsetSiteControls>(*charsetPage_, lay, *main));
91 
92 		int const charsetPageIndex = FindPage(charsetPage_);
93 		m_charsetPageText = GetPageText(charsetPageIndex);
94 		wxGetApp().GetWrapEngine()->WrapRecursive(charsetPage_, 1.3);
95 	}
96 
97 	{
98 		s3Page_ = new wxPanel(this);
99 		AddPage(s3Page_, L"S3");
100 		auto * main = lay.createMain(s3Page_, 1);
101 		controls_.emplace_back(std::make_unique<S3SiteControls>(*s3Page_, lay, *main));
102 	}
103 
104 	{
105 		dropboxPage_ = new wxPanel(this);
106 		AddPage(dropboxPage_, L"Dropbox");
107 		auto * main = lay.createMain(dropboxPage_, 1);
108 		controls_.emplace_back(std::make_unique<DropboxSiteControls>(*dropboxPage_, lay, *main));
109 	}
110 
111 	{
112 		swiftPage_ = new wxPanel(this);
113 		AddPage(swiftPage_, L"Swift");
114 		auto * main = lay.createMain(swiftPage_, 1);
115 		controls_.emplace_back(std::make_unique<SwiftSiteControls>(*swiftPage_, lay, *main));
116 	}
117 
118 	m_totalPages = GetPageCount();
119 
120 	GetPage(0)->GetSizer()->Fit(GetPage(0));
121 
122 #ifdef __WXMSW__
123 	// Make pages at least wide enough to fit all tabs
124 	HWND hWnd = (HWND)GetHandle();
125 
126 	int width = 4;
127 	for (unsigned int i = 0; i < GetPageCount(); ++i) {
128 		RECT tab_rect{};
129 		if (TabCtrl_GetItemRect(hWnd, i, &tab_rect)) {
130 			width += tab_rect.right - tab_rect.left;
131 		}
132 	}
133 #else
134 	// Make pages at least wide enough to fit all tabs
135 	int width = 10; // Guessed
136 	wxClientDC dc(this);
137 	for (unsigned int i = 0; i < GetPageCount(); ++i) {
138 		wxCoord w, h;
139 		dc.GetTextExtent(GetPageText(i), &w, &h);
140 
141 		width += w;
142 #ifdef __WXMAC__
143 		width += 20; // Guessed
144 #else
145 		width += 20;
146 #endif
147 	}
148 #endif
149 
150 	wxSize const descSize = XRCCTRL(*this, "ID_ENCRYPTION_DESC", wxWindow)->GetSize();
151 	wxSize const encSize = XRCCTRL(*this, "ID_ENCRYPTION", wxWindow)->GetSize();
152 
153 	int dataWidth = std::max(encSize.GetWidth(), XRCCTRL(*this, "ID_PROTOCOL", wxWindow)->GetSize().GetWidth());
154 
155 	auto generalSizer = static_cast<wxGridBagSizer*>(xrc_call(*this, "ID_PROTOCOL", &wxWindow::GetContainingSizer));
156 	width = std::max(width, static_cast<int>(descSize.GetWidth() * 2 + dataWidth + generalSizer->GetHGap() * 3));
157 
158 	wxSize page_min_size = GetPage(0)->GetSizer()->GetMinSize();
159 	if (page_min_size.x < width) {
160 		page_min_size.x = width;
161 		GetPage(0)->GetSizer()->SetMinSize(page_min_size);
162 	}
163 
164 	// Set min height of general page sizer
165 	generalSizer->SetMinSize(generalSizer->GetMinSize());
166 
167 	// Set min height of encryption row
168 	auto encSizer = xrc_call(*this, "ID_ENCRYPTION", &wxWindow::GetContainingSizer);
169 	encSizer->GetItem(encSizer->GetItemCount() - 1)->SetMinSize(0, std::max(descSize.GetHeight(), encSize.GetHeight()));
170 
171 	return true;
172 }
173 
SetControlVisibility(ServerProtocol protocol,LogonType type)174 void CSiteManagerSite::SetControlVisibility(ServerProtocol protocol, LogonType type)
175 {
176 	for (auto & controls : controls_) {
177 		controls->SetPredefined(predefined_);
178 		controls->SetControlVisibility(protocol, type);
179 	}
180 
181 	if (charsetPage_) {
182 		if (CServer::ProtocolHasFeature(protocol, ProtocolFeature::Charset)) {
183 			if (FindPage(charsetPage_) == wxNOT_FOUND) {
184 				AddPage(charsetPage_, m_charsetPageText);
185 			}
186 		}
187 		else {
188 			int const charsetPageIndex = FindPage(charsetPage_);
189 			if (charsetPageIndex != wxNOT_FOUND) {
190 				RemovePage(charsetPageIndex);
191 			}
192 		}
193 	}
194 
195 	if (s3Page_) {
196 		if (protocol == S3) {
197 			if (FindPage(s3Page_) == wxNOT_FOUND) {
198 				AddPage(s3Page_, L"S3");
199 			}
200 		}
201 		else {
202 			int const s3PageIndex = FindPage(s3Page_);
203 			if (s3PageIndex != wxNOT_FOUND) {
204 				RemovePage(s3PageIndex);
205 			}
206 		}
207 	}
208 
209 	if (swiftPage_) {
210 		if (protocol == SWIFT) {
211 			if (FindPage(swiftPage_) == wxNOT_FOUND) {
212 				AddPage(swiftPage_, L"Swift");
213 			}
214 		}
215 		else {
216 			int const swiftPageIndex = FindPage(swiftPage_);
217 			if (swiftPageIndex != wxNOT_FOUND) {
218 				RemovePage(swiftPageIndex);
219 			}
220 		}
221 	}
222 
223 	if (dropboxPage_) {
224 		if (protocol == DROPBOX) {
225 			if (FindPage(dropboxPage_) == wxNOT_FOUND) {
226 				AddPage(dropboxPage_, L"Dropbox");
227 			}
228 		}
229 		else {
230 			int const dropboxPageIndex = FindPage(dropboxPage_);
231 			if (dropboxPageIndex != wxNOT_FOUND) {
232 				RemovePage(dropboxPageIndex);
233 			}
234 		}
235 	}
236 
237 	GetPage(0)->GetSizer()->Fit(GetPage(0));
238 }
239 
UpdateSite(Site & site,bool silent)240 bool CSiteManagerSite::UpdateSite(Site &site, bool silent)
241 {
242 	for (auto & controls : controls_) {
243 		if (!controls->UpdateSite(site, silent)) {
244 			return false;
245 		}
246 	}
247 
248 	site.comments_ = xrc_call(*this, "ID_COMMENTS", &wxTextCtrl::GetValue).ToStdWstring();
249 	site.m_colour = CSiteManager::GetColourFromIndex(xrc_call(*this, "ID_COLOR", &wxChoice::GetSelection));
250 
251 	return true;
252 }
253 
SetSite(Site const & site,bool predefined)254 void CSiteManagerSite::SetSite(Site const& site, bool predefined)
255 {
256 	predefined_ = predefined;
257 
258 	if (site) {
259 		SetControlVisibility(site.server.GetProtocol(), site.credentials.logonType_);
260 	}
261 	else {
262 		bool const kiosk_mode = COptions::Get()->get_int(OPTION_DEFAULT_KIOSKMODE) != 0;
263 		auto const logonType = kiosk_mode ? LogonType::ask : LogonType::normal;
264 		SetControlVisibility(FTP, logonType);
265 	}
266 
267 	xrc_call(*this, "ID_COLOR", &wxWindow::Enable, !predefined);
268 	xrc_call(*this, "ID_COMMENTS", &wxWindow::Enable, !predefined);
269 
270 	for (auto & controls : controls_) {
271 		controls->SetSite(site);
272 		controls->SetControlState();
273 	}
274 
275 	if (!site) {
276 		xrc_call(*this, "ID_COMMENTS", &wxTextCtrl::ChangeValue, wxString());
277 		xrc_call(*this, "ID_COLOR", &wxChoice::Select, 0);
278 	}
279 	else {
280 		xrc_call(*this, "ID_COMMENTS", &wxTextCtrl::ChangeValue, site.comments_);
281 		xrc_call(*this, "ID_COLOR", &wxChoice::Select, CSiteManager::GetColourIndex(site_colour_to_wx(site.m_colour)));
282 	}
283 }
284