1/*
2 * Copyright 2011-2012, Haiku Inc. All Rights Reserved.
3 * Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
4 * Distributed under the terms of the MIT License.
5 */
6
7
8//! The standard config view for all protocols.
9
10
11#include "ProtocolConfigView.h"
12
13#include <stdio.h>
14#include <stdlib.h>
15
16#include <Catalog.h>
17#include <CheckBox.h>
18#include <ControlLook.h>
19#include <GridLayout.h>
20#include <LayoutBuilder.h>
21#include <MenuField.h>
22#include <MenuItem.h>
23#include <Message.h>
24#include <PopUpMenu.h>
25#include <String.h>
26#include <TextControl.h>
27
28#include <crypt.h>
29
30
31#undef B_TRANSLATION_CONTEXT
32#define B_TRANSLATION_CONTEXT "ProtocolConfigView"
33
34
35static const char* kPartialDownloadLimit = "partial_download_limit";
36
37static const uint32 kMsgLeaveOnServer = 'lmos';
38static const uint32 kMsgNoPassword = 'none';
39static const uint32 kMsgNeedPassword = 'some';
40
41
42namespace BPrivate {
43
44
45BodyDownloadConfigView::BodyDownloadConfigView()
46	:
47	BView("body_config", 0)
48{
49	fPartialBox = new BCheckBox("size_if", B_TRANSLATE(
50		"Partially download messages larger than"), new BMessage('SIZF'));
51
52	fSizeControl = new BTextControl("size",
53		B_TRANSLATE_COMMENT("KB", "kilo byte"), "", NULL);
54	fSizeControl->SetExplicitMinSize(BSize(be_plain_font->StringWidth("0000"),
55		B_SIZE_UNSET));
56
57	BLayoutBuilder::Group<>(this, B_HORIZONTAL,
58			be_control_look->DefaultLabelSpacing())
59		.Add(fPartialBox)
60		.Add(fSizeControl->CreateTextViewLayoutItem())
61		.Add(fSizeControl->CreateLabelLayoutItem());
62}
63
64
65void
66BodyDownloadConfigView::SetTo(const BMailProtocolSettings& settings)
67{
68	int32 limit = settings.GetInt32(kPartialDownloadLimit, -1);
69	if (limit < 0) {
70		fPartialBox->SetValue(B_CONTROL_OFF);
71		fSizeControl->SetText("0");
72		fSizeControl->SetEnabled(false);
73	} else {
74		BString kb;
75		kb << int32(limit / 1024);
76		fSizeControl->SetText(kb);
77		fPartialBox->SetValue(B_CONTROL_ON);
78		fSizeControl->SetEnabled(true);
79	}
80}
81
82
83status_t
84BodyDownloadConfigView::SaveInto(BMailAddOnSettings& settings) const
85{
86	if (fPartialBox->Value() == B_CONTROL_ON) {
87		settings.SetInt32(kPartialDownloadLimit,
88			atoi(fSizeControl->Text()) * 1024);
89	} else
90		settings.RemoveName(kPartialDownloadLimit);
91
92	return B_OK;
93}
94
95
96void
97BodyDownloadConfigView::MessageReceived(BMessage *msg)
98{
99	if (msg->what != 'SIZF')
100		return BView::MessageReceived(msg);
101	fSizeControl->SetEnabled(fPartialBox->Value());
102}
103
104
105void
106BodyDownloadConfigView::AttachedToWindow()
107{
108	fPartialBox->SetTarget(this);
109	fPartialBox->ResizeToPreferred();
110}
111
112
113// #pragma mark -
114
115
116MailProtocolConfigView::MailProtocolConfigView(uint32 optionsMask)
117	:
118	BMailSettingsView("protocol_config_view"),
119	fHostControl(NULL),
120	fUserControl(NULL),
121	fPasswordControl(NULL),
122	fFlavorField(NULL),
123	fAuthenticationField(NULL),
124	fLeaveOnServerCheckBox(NULL),
125	fRemoveFromServerCheckBox(NULL),
126	fBodyDownloadConfig(NULL)
127{
128	SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
129
130	BGridLayout* layout = new BGridLayout(0.f);
131	SetLayout(layout);
132
133	if ((optionsMask & B_MAIL_PROTOCOL_HAS_HOSTNAME) != 0) {
134		fHostControl = _AddTextControl(layout, "host",
135			B_TRANSLATE("Mail server:"));
136	}
137	if ((optionsMask & B_MAIL_PROTOCOL_HAS_USERNAME) != 0) {
138		fUserControl = _AddTextControl(layout, "user",
139			B_TRANSLATE("Username:"));
140	}
141
142	if ((optionsMask & B_MAIL_PROTOCOL_HAS_PASSWORD) != 0) {
143		fPasswordControl = _AddTextControl(layout, "pass",
144			B_TRANSLATE("Password:"));
145		fPasswordControl->TextView()->HideTyping(true);
146	}
147
148	if ((optionsMask & B_MAIL_PROTOCOL_HAS_FLAVORS) != 0) {
149		fFlavorField = _AddMenuField(layout, "flavor",
150			B_TRANSLATE("Connection type:"));
151	}
152
153	if ((optionsMask & B_MAIL_PROTOCOL_HAS_AUTH_METHODS) != 0) {
154		fAuthenticationField = _AddMenuField(layout, "auth_method",
155			B_TRANSLATE("Login type:"));
156	}
157
158	if ((optionsMask & B_MAIL_PROTOCOL_CAN_LEAVE_MAIL_ON_SERVER) != 0) {
159		fLeaveOnServerCheckBox = new BCheckBox("leave_mail_on_server",
160			B_TRANSLATE("Leave mail on server"),
161			new BMessage(kMsgLeaveOnServer));
162		layout->AddView(fLeaveOnServerCheckBox, 0, layout->CountRows(), 2);
163
164		fRemoveFromServerCheckBox = new BCheckBox("delete_remote_when_local",
165			B_TRANSLATE("Remove mail from server when deleted"), NULL);
166		fRemoveFromServerCheckBox->SetEnabled(false);
167		layout->AddView(fRemoveFromServerCheckBox, 0, layout->CountRows(), 2);
168	}
169
170	if ((optionsMask & B_MAIL_PROTOCOL_PARTIAL_DOWNLOAD) != 0) {
171		fBodyDownloadConfig = new BodyDownloadConfigView();
172		layout->AddView(fBodyDownloadConfig, 0, layout->CountRows(), 2);
173	}
174}
175
176
177MailProtocolConfigView::~MailProtocolConfigView()
178{
179}
180
181
182void
183MailProtocolConfigView::SetTo(const BMailProtocolSettings& settings)
184{
185	BString host = settings.FindString("server");
186	if (settings.HasInt32("port"))
187		host << ':' << settings.FindInt32("port");
188
189	if (fHostControl != NULL)
190		fHostControl->SetText(host.String());
191	if (fUserControl != NULL)
192		fUserControl->SetText(settings.FindString("username"));
193
194	if (fPasswordControl != NULL) {
195		char* password = get_passwd(&settings, "cpasswd");
196		if (password != NULL) {
197			fPasswordControl->SetText(password);
198			delete[] password;
199		} else
200			fPasswordControl->SetText(settings.FindString("password"));
201	}
202
203	if (settings.HasInt32("flavor") && fFlavorField != NULL) {
204		if (BMenuItem* item = fFlavorField->Menu()->ItemAt(
205				settings.FindInt32("flavor")))
206			item->SetMarked(true);
207	}
208
209	if (settings.HasInt32("auth_method") && fAuthenticationField != NULL) {
210		if (BMenuItem* item = fAuthenticationField->Menu()->ItemAt(
211				settings.FindInt32("auth_method"))) {
212			item->SetMarked(true);
213			_SetCredentialsEnabled(item->Command() != kMsgNoPassword);
214		}
215	}
216
217	if (fLeaveOnServerCheckBox != NULL) {
218		fLeaveOnServerCheckBox->SetValue(settings.FindBool(
219			"leave_mail_on_server") ? B_CONTROL_ON : B_CONTROL_OFF);
220	}
221
222	if (fRemoveFromServerCheckBox != NULL) {
223		fRemoveFromServerCheckBox->SetValue(settings.FindBool(
224			"delete_remote_when_local") ? B_CONTROL_ON : B_CONTROL_OFF);
225		fRemoveFromServerCheckBox->SetEnabled(
226			settings.FindBool("leave_mail_on_server"));
227	}
228
229	if (fBodyDownloadConfig != NULL)
230		fBodyDownloadConfig->SetTo(settings);
231}
232
233
234void
235MailProtocolConfigView::AddFlavor(const char* label)
236{
237	if (fFlavorField != NULL) {
238		fFlavorField->Menu()->AddItem(new BMenuItem(label, NULL));
239
240		if (fFlavorField->Menu()->FindMarked() == NULL)
241			fFlavorField->Menu()->ItemAt(0)->SetMarked(true);
242	}
243}
244
245
246void
247MailProtocolConfigView::AddAuthMethod(const char* label, bool needUserPassword)
248{
249	if (fAuthenticationField != NULL) {
250		fAuthenticationField->Menu()->AddItem(new BMenuItem(label,
251			new BMessage(needUserPassword
252				? kMsgNeedPassword : kMsgNoPassword)));
253
254		if (fAuthenticationField->Menu()->FindMarked() == NULL) {
255			BMenuItem* item = fAuthenticationField->Menu()->ItemAt(0);
256			item->SetMarked(true);
257			MessageReceived(item->Message());
258		}
259	}
260}
261
262
263BGridLayout*
264MailProtocolConfigView::Layout() const
265{
266	return (BGridLayout*)BView::GetLayout();
267}
268
269
270status_t
271MailProtocolConfigView::SaveInto(BMailAddOnSettings& settings) const
272{
273	if (fHostControl != NULL) {
274		int32 port = -1;
275		BString hostName = fHostControl->Text();
276		if (hostName.FindFirst(':') > -1) {
277			port = atol(hostName.String() + hostName.FindFirst(':') + 1);
278			hostName.Truncate(hostName.FindFirst(':'));
279		}
280
281		settings.SetString("server", hostName);
282
283		// since there is no need for the port option, remove it here
284		if (port != -1)
285			settings.SetInt32("port", port);
286		else
287			settings.RemoveName("port");
288	} else {
289		settings.RemoveName("server");
290		settings.RemoveName("port");
291	}
292
293	if (fUserControl != NULL)
294		settings.SetString("username", fUserControl->Text());
295	else
296		settings.RemoveName("username");
297
298	// remove old unencrypted passwords
299	settings.RemoveName("password");
300
301	if (fPasswordControl != NULL)
302		set_passwd(&settings, "cpasswd", fPasswordControl->Text());
303	else
304		settings.RemoveName("cpasswd");
305
306	_StoreIndexOfMarked(settings, "flavor", fFlavorField);
307	_StoreIndexOfMarked(settings, "auth_method", fAuthenticationField);
308
309	_StoreCheckBox(settings, "leave_mail_on_server", fLeaveOnServerCheckBox);
310	_StoreCheckBox(settings, "delete_remote_when_local",
311		fRemoveFromServerCheckBox);
312
313	if (fBodyDownloadConfig != NULL)
314		return fBodyDownloadConfig->SaveInto(settings);
315
316	return B_OK;
317}
318
319
320void
321MailProtocolConfigView::AttachedToWindow()
322{
323	if (fAuthenticationField != NULL)
324		fAuthenticationField->Menu()->SetTargetForItems(this);
325
326	if (fLeaveOnServerCheckBox != NULL)
327		fLeaveOnServerCheckBox->SetTarget(this);
328}
329
330
331void
332MailProtocolConfigView::MessageReceived(BMessage* message)
333{
334	switch (message->what) {
335		case kMsgNeedPassword:
336			_SetCredentialsEnabled(true);
337			break;
338		case kMsgNoPassword:
339			_SetCredentialsEnabled(false);
340			break;
341
342		case kMsgLeaveOnServer:
343			fRemoveFromServerCheckBox->SetEnabled(
344				message->FindInt32("be:value") == B_CONTROL_ON);
345			break;
346	}
347}
348
349
350BTextControl*
351MailProtocolConfigView::_AddTextControl(BGridLayout* layout, const char* name,
352	const char* label)
353{
354	BTextControl* control = new BTextControl(name, label, "", NULL);
355	control->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
356
357	int32 row = layout->CountRows();
358	layout->AddItem(control->CreateLabelLayoutItem(), 0, row);
359	layout->AddItem(control->CreateTextViewLayoutItem(), 1, row);
360	return control;
361}
362
363
364BMenuField*
365MailProtocolConfigView::_AddMenuField(BGridLayout* layout, const char* name,
366	const char* label)
367{
368	BPopUpMenu* menu = new BPopUpMenu("");
369	BMenuField* field = new BMenuField(name, label, menu);
370	field->SetAlignment(B_ALIGN_RIGHT);
371
372	int32 row = layout->CountRows();
373	layout->AddItem(field->CreateLabelLayoutItem(), 0, row);
374	layout->AddItem(field->CreateMenuBarLayoutItem(), 1, row);
375	return field;
376}
377
378
379void
380MailProtocolConfigView::_StoreIndexOfMarked(BMessage& message, const char* name,
381	BMenuField* field) const
382{
383	int32 index = -1;
384	if (field != NULL && field->Menu() != NULL) {
385		BMenuItem* item = field->Menu()->FindMarked();
386		if (item != NULL)
387			index = field->Menu()->IndexOf(item);
388	}
389	message.SetInt32(name, index);
390}
391
392
393void
394MailProtocolConfigView::_StoreCheckBox(BMessage& message, const char* name,
395	BCheckBox* checkBox) const
396{
397	bool value = checkBox != NULL && checkBox->Value() == B_CONTROL_ON;
398	if (value)
399		message.SetBool(name, value);
400	else
401		message.RemoveName(name);
402}
403
404
405void
406MailProtocolConfigView::_SetCredentialsEnabled(bool enabled)
407{
408	if (fUserControl != NULL && fPasswordControl != NULL) {
409		fUserControl->SetEnabled(enabled);
410		fPasswordControl->SetEnabled(enabled);
411	}
412}
413
414
415}	// namespace BPrivate
416