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