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