xref: /haiku/src/add-ons/network_settings/dnsclient/DNSSettingsView.cpp (revision 38aa1d3b8228744ce9b527a50729a51e2368c4c7)
1a4a34e42SAxel Dörfler /*
29a7e231eSAxel Dörfler  * Copyright 2014-2015 Haiku Inc. All rights reserved.
3a4a34e42SAxel Dörfler  * Distributed under the terms of the MIT License.
4a4a34e42SAxel Dörfler  *
5a4a34e42SAxel Dörfler  * Authors:
6a4a34e42SAxel Dörfler  *		Adrien Destugues, pulkomandy@pulkomandy.tk
7a4a34e42SAxel Dörfler  */
8a4a34e42SAxel Dörfler 
9a4a34e42SAxel Dörfler 
10a4a34e42SAxel Dörfler #include "DNSSettingsView.h"
11a4a34e42SAxel Dörfler 
129a7e231eSAxel Dörfler #include <arpa/inet.h>
139a7e231eSAxel Dörfler #include <netinet/in.h>
149a7e231eSAxel Dörfler #include <resolv.h>
159a7e231eSAxel Dörfler #include <stdio.h>
169a7e231eSAxel Dörfler #include <string.h>
179a7e231eSAxel Dörfler #include <sys/socket.h>
189a7e231eSAxel Dörfler 
19b4ec589bSAxel Dörfler #include <Box.h>
20a4a34e42SAxel Dörfler #include <Button.h>
21b4ec589bSAxel Dörfler #include <Catalog.h>
220ecdbff3SHumdinger #include <ControlLook.h>
23a4a34e42SAxel Dörfler #include <File.h>
24a4a34e42SAxel Dörfler #include <FindDirectory.h>
25a4a34e42SAxel Dörfler #include <LayoutBuilder.h>
26a4a34e42SAxel Dörfler #include <ListView.h>
27a4a34e42SAxel Dörfler #include <Path.h>
280ecdbff3SHumdinger #include <SeparatorView.h>
29a4a34e42SAxel Dörfler #include <ScrollView.h>
30b4ec589bSAxel Dörfler #include <StringView.h>
31d0b107f3SAxel Dörfler 
32d0b107f3SAxel Dörfler #include "IPAddressControl.h"
33a4a34e42SAxel Dörfler 
34a4a34e42SAxel Dörfler 
35b4ec589bSAxel Dörfler static const int32 kMsgAddServer = 'adds';
36b4ec589bSAxel Dörfler static const int32 kMsgDeleteServer = 'dels';
37b4ec589bSAxel Dörfler static const int32 kMsgMoveUp = 'mvup';
38b4ec589bSAxel Dörfler static const int32 kMsgMoveDown = 'mvdn';
39b4ec589bSAxel Dörfler static const int32 kMsgApply = 'aply';
40b4ec589bSAxel Dörfler 
41b4ec589bSAxel Dörfler 
42b4ec589bSAxel Dörfler #undef B_TRANSLATION_CONTEXT
43b4ec589bSAxel Dörfler #define B_TRANSLATION_CONTEXT "DNSSettingsView"
44a4a34e42SAxel Dörfler 
45a4a34e42SAxel Dörfler 
463d7aaa30SAxel Dörfler DNSSettingsView::DNSSettingsView(BNetworkSettingsItem* item)
479a7e231eSAxel Dörfler 	:
483d7aaa30SAxel Dörfler 	BView("dns", 0),
493d7aaa30SAxel Dörfler 	fItem(item)
50a4a34e42SAxel Dörfler {
510ecdbff3SHumdinger 	BStringView* titleView = new BStringView("title",
520ecdbff3SHumdinger 		B_TRANSLATE("DNS settings"));
530ecdbff3SHumdinger 	titleView->SetFont(be_bold_font);
540ecdbff3SHumdinger 	titleView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
550ecdbff3SHumdinger 
56a4a34e42SAxel Dörfler 	fServerListView = new BListView("nameservers");
57*38aa1d3bSHumdinger 	const char* serverLabel = B_TRANSLATE("Server:");
58*38aa1d3bSHumdinger 	fTextControl = new IPAddressControl(AF_UNSPEC, serverLabel, "server");
590ecdbff3SHumdinger 	fTextControl->SetExplicitMinSize(BSize(fTextControl->StringWidth("5") * 16
60*38aa1d3bSHumdinger 		+ fTextControl->StringWidth(serverLabel), B_SIZE_UNSET));
61a4a34e42SAxel Dörfler 
62b4ec589bSAxel Dörfler 	fAddButton = new BButton(B_TRANSLATE("Add"), new BMessage(kMsgAddServer));
63b4ec589bSAxel Dörfler 	fAddButton->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
64b4ec589bSAxel Dörfler 	fUpButton = new BButton(B_TRANSLATE("Move up"), new BMessage(kMsgMoveUp));
65b4ec589bSAxel Dörfler 	fUpButton->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
66b4ec589bSAxel Dörfler 	fDownButton = new BButton(B_TRANSLATE("Move down"),
67b4ec589bSAxel Dörfler 		new BMessage(kMsgMoveDown));
68b4ec589bSAxel Dörfler 	fDownButton->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
690ecdbff3SHumdinger 	fRemoveButton = new BButton(B_TRANSLATE("Remove"),
700ecdbff3SHumdinger 		new BMessage(kMsgDeleteServer));
71b4ec589bSAxel Dörfler 	fRemoveButton->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
720ecdbff3SHumdinger 	fDomain = new BTextControl(B_TRANSLATE("Domain:"), "", NULL);
73b4ec589bSAxel Dörfler 	fApplyButton = new BButton(B_TRANSLATE("Apply"), new BMessage(kMsgApply));
74b4ec589bSAxel Dörfler 
750ecdbff3SHumdinger 	float spacing = be_control_look->DefaultItemSpacing();
760ecdbff3SHumdinger 
770ecdbff3SHumdinger 	BGridView* serviceGridView = new BGridView();
780ecdbff3SHumdinger 	BLayoutBuilder::Grid<>(serviceGridView)
79a4a34e42SAxel Dörfler 		.Add(fTextControl, 0, 0)
80a4a34e42SAxel Dörfler 		.Add(fAddButton, 1, 0)
81a4a34e42SAxel Dörfler 		.Add(new BScrollView("scroll", fServerListView, 0, false, true),
82b4ec589bSAxel Dörfler 			0, 1, 1, 3)
83a4a34e42SAxel Dörfler 		.Add(fUpButton, 1, 1)
84a4a34e42SAxel Dörfler 		.Add(fDownButton, 1, 2)
85a4a34e42SAxel Dörfler 		.Add(fRemoveButton, 1, 3)
860ecdbff3SHumdinger 		.SetColumnWeight(0, 10.f);
87b4ec589bSAxel Dörfler 
88b4ec589bSAxel Dörfler 	BLayoutBuilder::Group<>(this, B_VERTICAL)
890ecdbff3SHumdinger 		.Add(titleView)
900ecdbff3SHumdinger 		.Add(serviceGridView)
910ecdbff3SHumdinger 		.Add(new BSeparatorView(B_HORIZONTAL))
920ecdbff3SHumdinger 		.Add(fDomain)
930ecdbff3SHumdinger 		.AddStrut(spacing)
94b4ec589bSAxel Dörfler 		.AddGroup(B_HORIZONTAL)
95b4ec589bSAxel Dörfler 			.AddGlue()
96b4ec589bSAxel Dörfler 			.Add(fApplyButton);
97a4a34e42SAxel Dörfler 
98a4a34e42SAxel Dörfler 	_LoadDNSConfiguration();
99a4a34e42SAxel Dörfler }
100a4a34e42SAxel Dörfler 
101a4a34e42SAxel Dörfler 
1029a7e231eSAxel Dörfler DNSSettingsView::~DNSSettingsView()
1039a7e231eSAxel Dörfler {
1049a7e231eSAxel Dörfler }
1059a7e231eSAxel Dörfler 
1069a7e231eSAxel Dörfler 
107a4a34e42SAxel Dörfler status_t
108a4a34e42SAxel Dörfler DNSSettingsView::Revert()
109a4a34e42SAxel Dörfler {
110a4a34e42SAxel Dörfler 	int i;
111a4a34e42SAxel Dörfler 	for (i = 0; i < fRevertList.CountStrings(); i++) {
1129a7e231eSAxel Dörfler 		BStringItem* item = static_cast<BStringItem*>(
1139a7e231eSAxel Dörfler 			fServerListView->ItemAt(i));
114a4a34e42SAxel Dörfler 		if (item == NULL) {
115a4a34e42SAxel Dörfler 			item = new BStringItem("");
116a4a34e42SAxel Dörfler 			fServerListView->AddItem(item);
117a4a34e42SAxel Dörfler 		}
118a4a34e42SAxel Dörfler 
119a4a34e42SAxel Dörfler 		item->SetText(fRevertList.StringAt(i));
120a4a34e42SAxel Dörfler 	}
121a4a34e42SAxel Dörfler 
122a4a34e42SAxel Dörfler 	// Now remove any extra item
123a4a34e42SAxel Dörfler 	for (; i < fServerListView->CountItems(); i++)
124a4a34e42SAxel Dörfler 		delete fServerListView->RemoveItem(i);
125a4a34e42SAxel Dörfler 
126a4a34e42SAxel Dörfler 	return B_OK;
127a4a34e42SAxel Dörfler }
128a4a34e42SAxel Dörfler 
129a4a34e42SAxel Dörfler 
1306a290205SAxel Dörfler bool
1316a290205SAxel Dörfler DNSSettingsView::IsRevertable() const
1326a290205SAxel Dörfler {
1336a290205SAxel Dörfler 	// TODO
1346a290205SAxel Dörfler 	return false;
1356a290205SAxel Dörfler }
1366a290205SAxel Dörfler 
1376a290205SAxel Dörfler 
138b4ec589bSAxel Dörfler void
139b4ec589bSAxel Dörfler DNSSettingsView::AttachedToWindow()
140b4ec589bSAxel Dörfler {
141b4ec589bSAxel Dörfler 	fAddButton->SetTarget(this);
142b4ec589bSAxel Dörfler 	fRemoveButton->SetTarget(this);
143b4ec589bSAxel Dörfler 	fUpButton->SetTarget(this);
144b4ec589bSAxel Dörfler 	fDownButton->SetTarget(this);
145b4ec589bSAxel Dörfler 
146b4ec589bSAxel Dörfler 	fTextControl->SetTarget(this);
147b4ec589bSAxel Dörfler 
148b4ec589bSAxel Dörfler 	fApplyButton->SetTarget(this);
149b4ec589bSAxel Dörfler }
150b4ec589bSAxel Dörfler 
151b4ec589bSAxel Dörfler 
152b4ec589bSAxel Dörfler void
153b4ec589bSAxel Dörfler DNSSettingsView::MessageReceived(BMessage* message)
154b4ec589bSAxel Dörfler {
155b4ec589bSAxel Dörfler 	switch (message->what) {
156b4ec589bSAxel Dörfler 		case kMsgAddServer:
157b4ec589bSAxel Dörfler 		{
158b4ec589bSAxel Dörfler 			const char* address = fTextControl->Text();
159b4ec589bSAxel Dörfler 			fServerListView->AddItem(new BStringItem(address));
160b4ec589bSAxel Dörfler 			break;
161b4ec589bSAxel Dörfler 		}
162b4ec589bSAxel Dörfler 		case kMsgDeleteServer:
163b4ec589bSAxel Dörfler 			delete fServerListView->RemoveItem(
164b4ec589bSAxel Dörfler 				fServerListView->CurrentSelection());
165b4ec589bSAxel Dörfler 			break;
166b4ec589bSAxel Dörfler 
167b4ec589bSAxel Dörfler 		case kMsgMoveUp:
168b4ec589bSAxel Dörfler 		{
169b4ec589bSAxel Dörfler 			int index = fServerListView->CurrentSelection();
170b4ec589bSAxel Dörfler 			if (index > 0)
171b4ec589bSAxel Dörfler 				fServerListView->SwapItems(index, index - 1);
172b4ec589bSAxel Dörfler 			break;
173b4ec589bSAxel Dörfler 		}
174b4ec589bSAxel Dörfler 		case kMsgMoveDown:
175b4ec589bSAxel Dörfler 		{
176b4ec589bSAxel Dörfler 			int index = fServerListView->CurrentSelection();
177b4ec589bSAxel Dörfler 			if (index < fServerListView->CountItems() - 1)
178b4ec589bSAxel Dörfler 				fServerListView->SwapItems(index, index + 1);
179b4ec589bSAxel Dörfler 			break;
180b4ec589bSAxel Dörfler 		}
181b4ec589bSAxel Dörfler 		case kMsgApply:
1823d7aaa30SAxel Dörfler 			if (_SaveDNSConfiguration() == B_OK)
1833d7aaa30SAxel Dörfler 				fItem->NotifySettingsUpdated();
184b4ec589bSAxel Dörfler 			break;
185b4ec589bSAxel Dörfler 
186b4ec589bSAxel Dörfler 		default:
187b4ec589bSAxel Dörfler 			BView::MessageReceived(message);
188b4ec589bSAxel Dörfler 			break;
189b4ec589bSAxel Dörfler 	}
190b4ec589bSAxel Dörfler }
191b4ec589bSAxel Dörfler 
192b4ec589bSAxel Dörfler 
193a4a34e42SAxel Dörfler status_t
194a4a34e42SAxel Dörfler DNSSettingsView::_LoadDNSConfiguration()
195a4a34e42SAxel Dörfler {
196e587c279SAxel Dörfler 	if (res_init() != 0)
197e587c279SAxel Dörfler 		return B_ERROR;
198e587c279SAxel Dörfler 
199a4a34e42SAxel Dörfler 	res_state state = __res_state();
200a4a34e42SAxel Dörfler 
201a4a34e42SAxel Dörfler 	if (state != NULL) {
202a4a34e42SAxel Dörfler 		for (int i = 0; i < state->nscount; i++) {
203a4a34e42SAxel Dörfler 			char* address = inet_ntoa(state->nsaddr_list[i].sin_addr);
204a4a34e42SAxel Dörfler 			fServerListView->AddItem(new BStringItem(address));
205a4a34e42SAxel Dörfler 			fRevertList.Add(address);
206a4a34e42SAxel Dörfler 		}
207a4a34e42SAxel Dörfler 
208a4a34e42SAxel Dörfler 		fDomain->SetText(state->dnsrch[0]);
209a4a34e42SAxel Dörfler 		return B_OK;
210a4a34e42SAxel Dörfler 	}
211a4a34e42SAxel Dörfler 
212a4a34e42SAxel Dörfler 	return B_ERROR;
213a4a34e42SAxel Dörfler }
214a4a34e42SAxel Dörfler 
215a4a34e42SAxel Dörfler 
216a4a34e42SAxel Dörfler status_t
217a4a34e42SAxel Dörfler DNSSettingsView::_SaveDNSConfiguration()
218a4a34e42SAxel Dörfler {
219a4a34e42SAxel Dörfler 	BPath path;
220a4a34e42SAxel Dörfler 	status_t status;
221a4a34e42SAxel Dörfler 	status = find_directory(B_SYSTEM_SETTINGS_DIRECTORY, &path);
222a4a34e42SAxel Dörfler 	if (status != B_OK)
223a4a34e42SAxel Dörfler 		return status;
224a4a34e42SAxel Dörfler 
225a4a34e42SAxel Dörfler 	path.Append("network/resolv.conf");
226a4a34e42SAxel Dörfler 
227a4a34e42SAxel Dörfler 	BFile file(path.Path(), B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY);
228a4a34e42SAxel Dörfler 	if (file.InitCheck() != B_OK) {
229a4a34e42SAxel Dörfler 		fprintf(stderr, "failed to open %s for writing: %s\n", path.Path(),
230a4a34e42SAxel Dörfler 			strerror(file.InitCheck()));
231a4a34e42SAxel Dörfler 		return file.InitCheck();
232a4a34e42SAxel Dörfler 	}
233a4a34e42SAxel Dörfler 
234b4ec589bSAxel Dörfler 	BString content("# Generated by Network preferences\n");
235a4a34e42SAxel Dörfler 
2369a7e231eSAxel Dörfler 	for (int i = 0; i < fServerListView->CountItems(); i++) {
2379a7e231eSAxel Dörfler 		BString item = ((BStringItem*)fServerListView->ItemAt(i))->Text();
2389a7e231eSAxel Dörfler 		if (item.Length() > 0)
239a4a34e42SAxel Dörfler 			content << "nameserver\t" << item.String() << "\n";
240a4a34e42SAxel Dörfler 	}
241a4a34e42SAxel Dörfler 
242a4a34e42SAxel Dörfler 	if (strlen(fDomain->Text()) > 0)
243a4a34e42SAxel Dörfler 		content << "domain\t" << fDomain->Text() << "\n";
244a4a34e42SAxel Dörfler 
245a4a34e42SAxel Dörfler 	return file.Write(content.String(), content.Length());
246a4a34e42SAxel Dörfler }
247