1/*
2 * Copyright 2003-2005, Waldemar Kornewald <wkornew@gmx.net>
3 * Distributed under the terms of the MIT License.
4 */
5
6//-----------------------------------------------------------------------
7// IPCPAddon saves the loaded settings.
8// IPCPView saves the current settings.
9//-----------------------------------------------------------------------
10
11#include "IPCPAddon.h"
12
13#include "MessageDriverSettingsUtils.h"
14#include <stl_algobase.h>
15	// for max()
16
17#include <StringView.h>
18
19#include <PPPDefs.h>
20#include <IPCP.h>
21	// from IPCP addon
22
23
24// GUI constants
25static const uint32 kDefaultButtonWidth = 80;
26
27// message constants
28static const uint32 kMsgUpdateControls = 'UCTL';
29
30// labels
31static const char *kLabelIPCP = "TCP/IP";
32static const char *kLabelIPAddress = "IP Address: ";
33static const char *kLabelPrimaryDNS = "Primary DNS: ";
34static const char *kLabelSecondaryDNS = "Secondary DNS: ";
35static const char *kLabelOptional = "(Optional)";
36static const char *kLabelExtendedOptions = "Extended Options:";
37static const char *kLabelEnabled = "Enable TCP/IP Protocol";
38
39// add-on descriptions
40static const char *kKernelModuleName = "ipcp";
41
42
43IPCPAddon::IPCPAddon(BMessage *addons)
44	: DialUpAddon(addons),
45	fSettings(NULL),
46	fIPCPView(NULL)
47{
48	CreateView(BPoint(0,0));
49	fDeleteView = true;
50}
51
52
53IPCPAddon::~IPCPAddon()
54{
55	if(fDeleteView)
56		delete fIPCPView;
57}
58
59
60bool
61IPCPAddon::LoadSettings(BMessage *settings, bool isNew)
62{
63	fIsNew = isNew;
64	fIsEnabled = false;
65	fIPAddress = fPrimaryDNS = fSecondaryDNS = "";
66	fSettings = settings;
67
68	fIPCPView->Reload();
69		// reset all views (empty settings)
70
71	if(!settings || isNew)
72		return true;
73
74	BMessage protocol;
75
76	int32 protocolIndex = FindIPCPProtocol(*fSettings, &protocol);
77	if(protocolIndex < 0)
78		return true;
79
80	protocol.AddBool(MDSU_VALID, true);
81	fSettings->ReplaceMessage(MDSU_PARAMETERS, protocolIndex, &protocol);
82
83	fIsEnabled = true;
84
85	// the "Local" side parameter
86	BMessage local;
87	int32 localSideIndex = 0;
88	if(!FindMessageParameter(IPCP_LOCAL_SIDE_KEY, protocol, &local, &localSideIndex))
89		local.MakeEmpty();
90			// just fall through and pretend we have an empty "Local" side parameter
91
92	// now load the supported parameters (the client-relevant subset)
93	BString name;
94	BMessage parameter;
95	int32 index = 0;
96	if(!FindMessageParameter(IPCP_IP_ADDRESS_KEY, local, &parameter, &index)
97			|| parameter.FindString(MDSU_VALUES, &fIPAddress) != B_OK)
98		fIPAddress = "";
99	else {
100		if(fIPAddress == "auto")
101			fIPAddress = "";
102
103		parameter.AddBool(MDSU_VALID, true);
104		local.ReplaceMessage(MDSU_PARAMETERS, index, &parameter);
105	}
106
107	index = 0;
108	if(!FindMessageParameter(IPCP_PRIMARY_DNS_KEY, local, &parameter, &index)
109			|| parameter.FindString(MDSU_VALUES, &fPrimaryDNS) != B_OK)
110		fPrimaryDNS = "";
111	else {
112		if(fPrimaryDNS == "auto")
113			fPrimaryDNS = "";
114
115		parameter.AddBool(MDSU_VALID, true);
116		local.ReplaceMessage(MDSU_PARAMETERS, index, &parameter);
117	}
118
119	index = 0;
120	if(!FindMessageParameter(IPCP_SECONDARY_DNS_KEY, local, &parameter, &index)
121			|| parameter.FindString(MDSU_VALUES, &fSecondaryDNS) != B_OK)
122		fSecondaryDNS = "";
123	else {
124		if(fSecondaryDNS == "auto")
125			fSecondaryDNS = "";
126
127		parameter.AddBool(MDSU_VALID, true);
128		local.ReplaceMessage(MDSU_PARAMETERS, index, &parameter);
129	}
130
131	local.AddBool(MDSU_VALID, true);
132	protocol.ReplaceMessage(MDSU_PARAMETERS, localSideIndex, &local);
133	protocol.AddBool(MDSU_VALID, true);
134	fSettings->ReplaceMessage(MDSU_PARAMETERS, protocolIndex, &protocol);
135
136	fIPCPView->Reload();
137
138	return true;
139}
140
141
142void
143IPCPAddon::IsModified(bool *settings) const
144{
145	if(!fSettings) {
146		*settings = false;
147		return;
148	}
149
150	*settings = (fIsEnabled != fIPCPView->IsEnabled()
151		|| fIPAddress != fIPCPView->IPAddress()
152		|| fPrimaryDNS != fIPCPView->PrimaryDNS()
153		|| fSecondaryDNS != fIPCPView->SecondaryDNS());
154}
155
156
157bool
158IPCPAddon::SaveSettings(BMessage *settings)
159{
160	if(!fSettings || !settings)
161		return false;
162
163	if(!fIPCPView->IsEnabled())
164		return true;
165
166	BMessage protocol, local;
167	protocol.AddString(MDSU_NAME, PPP_PROTOCOL_KEY);
168	protocol.AddString(MDSU_VALUES, kKernelModuleName);
169		// the settings contain a simple "protocol ipcp" string
170
171	// now create the settings with all subparameters
172	local.AddString(MDSU_NAME, IPCP_LOCAL_SIDE_KEY);
173	bool needsLocal = false;
174
175	if(fIPCPView->IPAddress() && strlen(fIPCPView->IPAddress()) > 0) {
176		// save IP address, too
177		needsLocal = true;
178		BMessage ip;
179		ip.AddString(MDSU_NAME, IPCP_IP_ADDRESS_KEY);
180		ip.AddString(MDSU_VALUES, fIPCPView->IPAddress());
181		local.AddMessage(MDSU_PARAMETERS, &ip);
182	}
183
184	if(fIPCPView->PrimaryDNS() && strlen(fIPCPView->PrimaryDNS()) > 0) {
185		// save service name, too
186		needsLocal = true;
187		BMessage dns;
188		dns.AddString(MDSU_NAME, IPCP_PRIMARY_DNS_KEY);
189		dns.AddString(MDSU_VALUES, fIPCPView->PrimaryDNS());
190		local.AddMessage(MDSU_PARAMETERS, &dns);
191	}
192
193	if(fIPCPView->SecondaryDNS() && strlen(fIPCPView->SecondaryDNS()) > 0) {
194		// save service name, too
195		needsLocal = true;
196		BMessage dns;
197		dns.AddString(MDSU_NAME, IPCP_SECONDARY_DNS_KEY);
198		dns.AddString(MDSU_VALUES, fIPCPView->SecondaryDNS());
199		local.AddMessage(MDSU_PARAMETERS, &dns);
200	}
201
202	if(needsLocal)
203		protocol.AddMessage(MDSU_PARAMETERS, &local);
204
205	settings->AddMessage(MDSU_PARAMETERS, &protocol);
206
207	return true;
208}
209
210
211bool
212IPCPAddon::GetPreferredSize(float *width, float *height) const
213{
214	BRect rect;
215	if(Addons()->FindRect(DUN_TAB_VIEW_RECT, &rect) != B_OK)
216		rect.Set(0, 0, 200, 300);
217			// set default values
218
219	if(width)
220		*width = rect.Width();
221	if(height)
222		*height = rect.Height();
223
224	return true;
225}
226
227
228BView*
229IPCPAddon::CreateView(BPoint leftTop)
230{
231	if(!fIPCPView) {
232		BRect rect;
233		Addons()->FindRect(DUN_TAB_VIEW_RECT, &rect);
234		fIPCPView = new IPCPView(this, rect);
235	}
236
237	fDeleteView = false;
238
239	fIPCPView->MoveTo(leftTop);
240	fIPCPView->Reload();
241	return fIPCPView;
242}
243
244
245int32
246IPCPAddon::FindIPCPProtocol(const BMessage& message, BMessage *protocol) const
247{
248	if(!protocol)
249		return -1;
250
251	BString name;
252	for(int32 index = 0; FindMessageParameter(PPP_PROTOCOL_KEY, message, protocol,
253			&index); index++)
254		if(protocol->FindString(MDSU_VALUES, &name) == B_OK
255				&& name == kKernelModuleName)
256			return index;
257
258	return -1;
259}
260
261
262IPCPView::IPCPView(IPCPAddon *addon, BRect frame)
263	: BView(frame, kLabelIPCP, B_FOLLOW_NONE, 0),
264	fAddon(addon)
265{
266	BRect rect = Bounds();
267	rect.InsetBy(10, 10);
268	rect.bottom = rect.top + 20;
269	BRect optionalRect(rect);
270	rect.right -= 75;
271	fIPAddress = new BTextControl(rect, "ip", kLabelIPAddress, NULL, NULL);
272	optionalRect.left = rect.right + 5;
273	optionalRect.bottom = optionalRect.top + 15;
274	AddChild(new BStringView(optionalRect, "optional_1", kLabelOptional));
275	rect.top = rect.bottom + 5;
276	rect.bottom = rect.top + 20;
277	fPrimaryDNS = new BTextControl(rect, "primaryDNS", kLabelPrimaryDNS, NULL, NULL);
278	optionalRect.top = rect.top;
279	optionalRect.bottom = optionalRect.top + 15;
280	AddChild(new BStringView(optionalRect, "optional_2", kLabelOptional));
281	rect.top = rect.bottom + 5;
282	rect.bottom = rect.top + 20;
283	fSecondaryDNS = new BTextControl(rect, "secondaryDNS", kLabelSecondaryDNS, NULL,
284		NULL);
285	optionalRect.top = rect.top;
286	optionalRect.bottom = optionalRect.top + 15;
287	AddChild(new BStringView(optionalRect, "optional_3", kLabelOptional));
288	rect.top = rect.bottom + 50;
289	rect.bottom = rect.top + 10;
290	AddChild(new BStringView(rect, "expert", kLabelExtendedOptions));
291	rect.top = rect.bottom + 5;
292	rect.bottom = rect.top + 15;
293	fIsEnabled = new BCheckBox(rect, "isEnabled", kLabelEnabled,
294		new BMessage(kMsgUpdateControls));
295
296	// set divider of text controls
297	float controlWidth = max(max(StringWidth(fIPAddress->Label()),
298		StringWidth(fPrimaryDNS->Label())), StringWidth(fSecondaryDNS->Label()));
299	fIPAddress->SetDivider(controlWidth + 5);
300	fPrimaryDNS->SetDivider(controlWidth + 5);
301	fSecondaryDNS->SetDivider(controlWidth + 5);
302
303	AddChild(fIsEnabled);
304	AddChild(fIPAddress);
305	AddChild(fPrimaryDNS);
306	AddChild(fSecondaryDNS);
307}
308
309
310void
311IPCPView::Reload()
312{
313	fIsEnabled->SetValue(Addon()->IsEnabled() || Addon()->IsNew());
314		// enable TCP/IP by default
315	fIPAddress->SetText(Addon()->IPAddress());
316	fPrimaryDNS->SetText(Addon()->PrimaryDNS());
317	fSecondaryDNS->SetText(Addon()->SecondaryDNS());
318
319	UpdateControls();
320}
321
322
323void
324IPCPView::AttachedToWindow()
325{
326	SetViewColor(Parent()->ViewColor());
327	fIsEnabled->SetTarget(this);
328}
329
330
331void
332IPCPView::MessageReceived(BMessage *message)
333{
334	switch(message->what) {
335		case kMsgUpdateControls:
336			UpdateControls();
337		break;
338
339		default:
340			BView::MessageReceived(message);
341	}
342}
343
344
345void
346IPCPView::UpdateControls()
347{
348	fIPAddress->SetEnabled(IsEnabled());
349	fPrimaryDNS->SetEnabled(IsEnabled());
350	fSecondaryDNS->SetEnabled(IsEnabled());
351}
352