added 5 changesets to branch 'refs/remotes/axeld-github/network-preferences' old head: 570028894185ba6deee249777f7743a91dd2a644 new head: 15dc9769fec1d716105720dd2a1c22783972a1cd overview: https://github.com/axeld/haiku/compare/570028894185...15dc9769fec1 ---------------------------------------------------------------------------- 7d314d612b50: Network: made InterfaceListItem::Name() const. c267dd590510: Network: fixed top item creation, sort entries. * Need a way to access the NetworkWindow object from a static method in order to sort all entries correctly, though. 10b39298f26b: Network: IPv[46] add-on Jamfile cleanup. bb520d88d3e2: BNetworkSettings: made service stuff writable. * And added the ability to disable a service without losing its configuration. 15dc9769fec1: Network: first steps to an SSH service add-on. [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ] ---------------------------------------------------------------------------- 13 files changed, 619 insertions(+), 51 deletions(-) .../add-ons/network_settings/NetworkSettings.h | 31 ++- .../network_settings/NetworkSettingsAddOn.h | 2 + src/add-ons/network_settings/Jamfile | 1 + src/add-ons/network_settings/ipv4/Jamfile | 4 - src/add-ons/network_settings/ipv6/Jamfile | 4 - src/add-ons/network_settings/sshd/Jamfile | 15 + .../network_settings/sshd/SSHServiceAddOn.cpp | 276 +++++++++++++++++++ src/kits/network/libnetapi/NetworkSettings.cpp | 205 ++++++++++++-- src/preferences/network/InterfaceListItem.h | 2 +- src/preferences/network/NetworkSettingsAddOn.cpp | 7 + src/preferences/network/NetworkWindow.cpp | 112 +++++++- src/preferences/network/NetworkWindow.h | 8 + src/servers/net/Services.cpp | 3 +- ############################################################################ Commit: 7d314d612b509b59784f27a3941675dbe4f974ec Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> Date: Tue Mar 10 21:34:12 2015 UTC Network: made InterfaceListItem::Name() const. ---------------------------------------------------------------------------- diff --git a/src/preferences/network/InterfaceListItem.h b/src/preferences/network/InterfaceListItem.h index 2725793..396afe8 100644 --- a/src/preferences/network/InterfaceListItem.h +++ b/src/preferences/network/InterfaceListItem.h @@ -30,7 +30,7 @@ public: BRect bounds, bool complete); void Update(BView* owner, const BFont* font); - inline const char* Name() { return fInterface.Name(); } + inline const char* Name() const { return fInterface.Name(); } virtual void ConfigurationUpdated(const BMessage& message); ############################################################################ Commit: c267dd590510bf7e0be91f01ea045b3e524a59e8 Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> Date: Tue Mar 10 21:35:20 2015 UTC Network: fixed top item creation, sort entries. * Need a way to access the NetworkWindow object from a static method in order to sort all entries correctly, though. ---------------------------------------------------------------------------- diff --git a/headers/os/add-ons/network_settings/NetworkSettingsAddOn.h b/headers/os/add-ons/network_settings/NetworkSettingsAddOn.h index 89371a6..6540138 100644 --- a/headers/os/add-ons/network_settings/NetworkSettingsAddOn.h +++ b/headers/os/add-ons/network_settings/NetworkSettingsAddOn.h @@ -92,6 +92,8 @@ public: BNetworkSettings& settings); ~BNetworkInterfaceListItem(); + const char* Label() const; + virtual void DrawItem(BView* owner, BRect bounds, bool complete); virtual void Update(BView* owner, const BFont* font); diff --git a/src/preferences/network/NetworkSettingsAddOn.cpp b/src/preferences/network/NetworkSettingsAddOn.cpp index 7b54fb4..6d1fccf 100644 --- a/src/preferences/network/NetworkSettingsAddOn.cpp +++ b/src/preferences/network/NetworkSettingsAddOn.cpp @@ -106,6 +106,13 @@ BNetworkInterfaceListItem::~BNetworkInterfaceListItem() } +const char* +BNetworkInterfaceListItem::Label() const +{ + return fLabel; +} + + void BNetworkInterfaceListItem::DrawItem(BView* owner, BRect bounds, bool complete) { diff --git a/src/preferences/network/NetworkWindow.cpp b/src/preferences/network/NetworkWindow.cpp index 03654ec..4242d5c 100644 --- a/src/preferences/network/NetworkWindow.cpp +++ b/src/preferences/network/NetworkWindow.cpp @@ -34,6 +34,7 @@ #include <PathMonitor.h> #include <Roster.h> #include <ScrollView.h> +#include <StringItem.h> #include <SymLink.h> #define ENABLE_PROFILES 0 @@ -62,7 +63,10 @@ static const uint32 kMsgItemSelected = 'ItSl'; NetworkWindow::NetworkWindow() : BWindow(BRect(100, 100, 400, 400), B_TRANSLATE("Network"), B_TITLED_WINDOW, - B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS) + B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS), + fServicesItem(NULL), + fDialUpItem(NULL), + fOtherItem(NULL) { // Profiles section #if ENABLE_PROFILES @@ -362,9 +366,10 @@ NetworkWindow::_ScanAddOns() break; fSettingsMap[item->ListItem()] = item; - // TODO: sort fListView->AddUnder(item->ListItem(), interfaceItem); } + fListView->SortItemsUnder(interfaceItem, true, + NetworkWindow::_CompareListItems); } // Generic items @@ -375,12 +380,18 @@ NetworkWindow::_ScanAddOns() break; fSettingsMap[item->ListItem()] = item; - // TODO: sort fListView->AddUnder(item->ListItem(), _ListItemFor(item->Type())); } + + _SortItemsUnder(fServicesItem); + _SortItemsUnder(fDialUpItem); + _SortItemsUnder(fOtherItem); } } + + fListView->SortItemsUnder(NULL, true, + NetworkWindow::_CompareTopLevelListItems); } @@ -395,28 +406,31 @@ NetworkWindow::_SettingsItemFor(BListItem* item) } +void +NetworkWindow::_SortItemsUnder(BListItem* item) +{ + if (item != NULL) + fListView->SortItemsUnder(item, true, NetworkWindow::_CompareListItems); +} + + BListItem* NetworkWindow::_ListItemFor(BNetworkSettingsType type) { switch (type) { case B_NETWORK_SETTINGS_TYPE_SERVICE: - if (fServicesItem == NULL) { - fServicesItem = new BStringItem(B_TRANSLATE("Services")); - fServicesItem->SetExpanded(true); - } - + if (fServicesItem == NULL) + fServicesItem = _CreateItem(B_TRANSLATE("Services")); return fServicesItem; case B_NETWORK_SETTINGS_TYPE_DIAL_UP: if (fDialUpItem == NULL) - fDialUpItem = new BStringItem(B_TRANSLATE("Dial Up")); - + fDialUpItem = _CreateItem(B_TRANSLATE("Dial Up")); return fDialUpItem; case B_NETWORK_SETTINGS_TYPE_OTHER: if (fOtherItem == NULL) - fOtherItem = new BStringItem(B_TRANSLATE("Other")); - + fOtherItem = _CreateItem(B_TRANSLATE("Other")); return fOtherItem; default: @@ -425,6 +439,16 @@ NetworkWindow::_ListItemFor(BNetworkSettingsType type) } +BListItem* +NetworkWindow::_CreateItem(const char* label) +{ + BListItem* item = new BStringItem(label); + item->SetExpanded(true); + fListView->AddItem(item); + return item; +} + + void NetworkWindow::_SelectItem(BListItem* listItem) { @@ -508,3 +532,67 @@ NetworkWindow::_IsReplicantInstalled() BDeskbar deskbar; return deskbar.HasItem("NetworkStatus"); } + + +/*static*/ const char* +NetworkWindow::_ItemName(const BListItem* item) +{ + if (const BNetworkInterfaceListItem* listItem = dynamic_cast< + const BNetworkInterfaceListItem*>(item)) + return listItem->Label(); + + if (const BStringItem* stringItem = dynamic_cast<const BStringItem*>(item)) + return stringItem->Text(); + + return NULL; +} + + +/*static*/ int +NetworkWindow::_CompareTopLevelListItems(const BListItem* a, const BListItem* b) +{ + if (a == b) + return 0; + + if (const InterfaceListItem* itemA + = dynamic_cast<const InterfaceListItem*>(a)) { + if (const InterfaceListItem* itemB + = dynamic_cast<const InterfaceListItem*>(b)) { + return strcasecmp(itemA->Name(), itemB->Name()); + } + return -1; + } else if (dynamic_cast<const InterfaceListItem*>(b) != NULL) + return 1; +/* + if (a == fDialUpItem) + return -1; + if (b == fDialUpItem) + return 1; + + if (a == fServicesItem) + return -1; + if (b == fServicesItem) + return 1; +*/ + return _CompareListItems(a, b); +} + + +/*static*/ int +NetworkWindow::_CompareListItems(const BListItem* a, const BListItem* b) +{ + if (a == b) + return 0; + + const char* nameA = _ItemName(a); + const char* nameB = _ItemName(b); + + if (nameA != NULL && nameB != NULL) + return strcasecmp(nameA, nameB); + if (nameA != NULL) + return 1; + if (nameB != NULL) + return -1; + + return (addr_t)a > (addr_t)b ? 1 : -1; +} diff --git a/src/preferences/network/NetworkWindow.h b/src/preferences/network/NetworkWindow.h index 5b55745..179ddd4 100644 --- a/src/preferences/network/NetworkWindow.h +++ b/src/preferences/network/NetworkWindow.h @@ -43,7 +43,9 @@ private: void _ScanAddOns(); BNetworkSettingsItem* _SettingsItemFor(BListItem* item); + void _SortItemsUnder(BListItem* item); BListItem* _ListItemFor(BNetworkSettingsType type); + BListItem* _CreateItem(const char* label); void _SelectItem(BListItem* listItem); void _BroadcastSettingsUpdate(uint32 type); void _BroadcastConfigurationUpdate( @@ -52,6 +54,12 @@ private: bool _IsReplicantInstalled(); void _ShowReplicant(bool show); + static const char* _ItemName(const BListItem* item); + static int _CompareTopLevelListItems(const BListItem* a, + const BListItem* b); + static int _CompareListItems(const BListItem* a, + const BListItem* b); + private: typedef BObjectList<BNetworkSettingsAddOn> AddOnList; typedef BObjectList<BNetworkSettingsItem> ItemList; ############################################################################ Commit: 10b39298f26b08bddf1560f9d2710347716baad1 Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> Date: Tue Mar 10 21:36:40 2015 UTC Network: IPv[46] add-on Jamfile cleanup. ---------------------------------------------------------------------------- diff --git a/src/add-ons/network_settings/ipv4/Jamfile b/src/add-ons/network_settings/ipv4/Jamfile index 104df00..8652b21 100644 --- a/src/add-ons/network_settings/ipv4/Jamfile +++ b/src/add-ons/network_settings/ipv4/Jamfile @@ -3,10 +3,6 @@ SubDir HAIKU_TOP src add-ons network_settings ipv4 ; UsePublicHeaders [ FDirName add-ons network_settings ] ; UsePrivateHeaders shared ; -AddResources Interfaces : - InterfacesIcons.rdef -; - Addon IPv4Interface : IPv4InterfaceAddOn.cpp InterfaceAddressView.cpp diff --git a/src/add-ons/network_settings/ipv6/Jamfile b/src/add-ons/network_settings/ipv6/Jamfile index e446bb4..fe6ea29b 100644 --- a/src/add-ons/network_settings/ipv6/Jamfile +++ b/src/add-ons/network_settings/ipv6/Jamfile @@ -5,10 +5,6 @@ UsePrivateHeaders shared ; SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons network_settings ipv4 ] ; -AddResources Interfaces : - InterfacesIcons.rdef -; - Addon IPv6Interface : IPv6InterfaceAddOn.cpp InterfaceAddressView.cpp ############################################################################ Commit: bb520d88d3e2e46a95dc25b9cb516e759ee242a8 Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> Date: Tue Mar 10 21:46:40 2015 UTC BNetworkSettings: made service stuff writable. * And added the ability to disable a service without losing its configuration. ---------------------------------------------------------------------------- diff --git a/headers/os/add-ons/network_settings/NetworkSettings.h b/headers/os/add-ons/network_settings/NetworkSettings.h index 38f7464..3383cac 100644 --- a/headers/os/add-ons/network_settings/NetworkSettings.h +++ b/headers/os/add-ons/network_settings/NetworkSettings.h @@ -22,6 +22,7 @@ namespace BNetworkKit { class BNetworkInterfaceSettings; +class BNetworkServiceSettings; class BNetworkSettings { @@ -57,6 +58,8 @@ public: status_t GetService(const char* name, BMessage& service); status_t AddService(const BMessage& service); status_t RemoveService(const char* name); + BNetworkServiceSettings + Service(const char* name); status_t StartMonitoring(const BMessenger& target); status_t StopMonitoring(const BMessenger& target); @@ -231,17 +234,43 @@ public: status_t InitCheck() const; const char* Name() const; + void SetName(const char* name); bool IsStandAlone() const; + void SetStandAlone(bool alone); + bool IsEnabled() const; + void SetEnabled(bool enable); + + int Family() const; + void SetFamily(int family); + int Protocol() const; + void SetProtocol(int protocol); + int Type() const; + void SetType(int type); + int Port() const; + void SetPort(int port); int32 CountArguments() const; const char* ArgumentAt(int32 index) const; + void AddArgument(const char* argument); + void RemoveArgument(int32 index); int32 CountAddresses() const; const BNetworkServiceAddressSettings& AddressAt(int32 index) const; + void AddAddress(const + BNetworkServiceAddressSettings& address); + void RemoveAddress(int32 index); + + status_t GetMessage(BMessage& data) const; private: - const BMessage& fData; + BString fName; + int32 fFamily; + int32 fType; + int32 fProtocol; + int32 fPort; + bool fEnabled; + bool fStandAlone; BStringList fArguments; std::vector<BNetworkServiceAddressSettings> fAddresses; diff --git a/src/kits/network/libnetapi/NetworkSettings.cpp b/src/kits/network/libnetapi/NetworkSettings.cpp index 292e01e..f15fef3 100644 --- a/src/kits/network/libnetapi/NetworkSettings.cpp +++ b/src/kits/network/libnetapi/NetworkSettings.cpp @@ -120,6 +120,7 @@ const static settings_template kServiceAddressTemplate[] = { const static settings_template kServiceTemplate[] = { {B_STRING_TYPE, "name", NULL, true}, + {B_BOOL_TYPE, "disabled", NULL}, {B_MESSAGE_TYPE, "address", kServiceAddressTemplate}, {B_STRING_TYPE, "user", NULL}, {B_STRING_TYPE, "group", NULL}, @@ -466,6 +467,15 @@ BNetworkSettings::RemoveService(const char* name) } +BNetworkServiceSettings +BNetworkSettings::Service(const char* name) +{ + BMessage service; + GetService(name, service); + return BNetworkServiceSettings(service); +} + + status_t BNetworkSettings::StartMonitoring(const BMessenger& target) { @@ -1393,10 +1403,16 @@ BNetworkServiceAddressSettings::operator==( BNetworkServiceSettings::BNetworkServiceSettings(const BMessage& message) : - fData(message) + fType(-1), + fProtocol(-1), + fPort(-1), + fEnabled(true), + fStandAlone(false) { // TODO: user/group is currently ignored! + fName = message.GetString("name"); + // Default family/port/protocol/type for all addresses // we default to inet/tcp/port-from-service-name if nothing is specified @@ -1404,35 +1420,33 @@ BNetworkServiceSettings::BNetworkServiceSettings(const BMessage& message) if (message.FindString("family", &string) != B_OK) string = "inet"; - int32 serviceFamily = get_address_family(string); - if (serviceFamily == AF_UNSPEC) - serviceFamily = AF_INET; + fFamily = get_address_family(string); + if (fFamily == AF_UNSPEC) + fFamily = AF_INET; - int32 serviceProtocol; if (message.FindString("protocol", &string) == B_OK) - serviceProtocol = parse_protocol(string); + fProtocol = parse_protocol(string); else { string = "tcp"; // we set 'string' here for an eventual call to getservbyname() // below - serviceProtocol = IPPROTO_TCP; + fProtocol = IPPROTO_TCP; } - int32 servicePort; - if (message.FindInt32("port", &servicePort) != B_OK) { + if (message.FindInt32("port", &fPort) != B_OK) { struct servent* servent = getservbyname(Name(), string); if (servent != NULL) - servicePort = ntohs(servent->s_port); + fPort = ntohs(servent->s_port); else - servicePort = -1; + fPort = -1; } - int32 serviceType = -1; - if (message.FindString("type", &string) == B_OK) { - serviceType = parse_type(string); - } else { - serviceType = type_for_protocol(serviceProtocol); - } + if (message.FindString("type", &string) == B_OK) + fType = parse_type(string); + else + fType = type_for_protocol(serviceProtocol); + + fStandAlone = message.GetBool("stand_alone"); const char* argument; for (int i = 0; message.FindString("launch", i, &argument) == B_OK; i++) { @@ -1442,12 +1456,12 @@ BNetworkServiceSettings::BNetworkServiceSettings(const BMessage& message) BMessage addressData; int32 i = 0; for (; message.FindMessage("address", i, &addressData) == B_OK; i++) { - BNetworkServiceAddressSettings address(addressData, serviceFamily, - serviceType, serviceProtocol, servicePort); + BNetworkServiceAddressSettings address(addressData, fFamily, + fType, fProtocol, fPort); fAddresses.push_back(address); } - if (i == 0 && (serviceFamily < 0 || servicePort < 0)) { + if (i == 0 && (fFamily < 0 || fPort < 0)) { // no address specified printf("service %s has no address specified\n", Name()); return; @@ -1456,10 +1470,10 @@ BNetworkServiceSettings::BNetworkServiceSettings(const BMessage& message) if (i == 0) { // no address specified, but family/port were given; add empty address BNetworkServiceAddressSettings address; - address.SetFamily(serviceFamily); - address.SetType(serviceType); - address.SetProtocol(serviceProtocol); - address.Address().SetToWildcard(serviceFamily, servicePort); + address.SetFamily(fFamily); + address.SetType(fType); + address.SetProtocol(fProtocol); + address.Address().SetToWildcard(fFamily, fPort); fAddresses.push_back(address); } @@ -1474,8 +1488,7 @@ BNetworkServiceSettings::~BNetworkServiceSettings() status_t BNetworkServiceSettings::InitCheck() const { - if (fData.HasString("name") && fData.HasString("launch") - && CountAddresses() > 0) + if (!fName.IsEmpty() && !fArguments.IsEmpty() && CountAddresses() > 0) return B_OK; return B_BAD_VALUE; @@ -1485,14 +1498,98 @@ BNetworkServiceSettings::InitCheck() const const char* BNetworkServiceSettings::Name() const { - return fData.GetString("name"); + return fName.String(); +} + + +void +BNetworkServiceSettings::SetName(const char* name) +{ + fName = name; } bool BNetworkServiceSettings::IsStandAlone() const { - return fData.GetBool("stand_alone"); + return fStandAlone; +} + + +void +BNetworkServiceSettings::SetStandAlone(bool alone) +{ + fStandAlone = alone; +} + + +bool +BNetworkServiceSettings::IsEnabled() const +{ + return InitCheck() == B_OK && !fEnabled; +} + + +void +BNetworkServiceSettings::SetEnabled(bool enable) +{ + fEnabled = enable; +} + + +int +BNetworkServiceSettings::Family() const +{ + return fFamily; +} + + +void +BNetworkServiceSettings::SetFamily(int family) +{ + fFamily = family; +} + + +int +BNetworkServiceSettings::Protocol() const +{ + return fProtocol; +} + + +void +BNetworkServiceSettings::SetProtocol(int protocol) +{ + fProtocol = protocol; +} + + +int +BNetworkServiceSettings::Type() const +{ + return fType; +} + + +void +BNetworkServiceSettings::SetType(int type) +{ + fType = type; +} + + +int +BNetworkServiceSettings::Port() const +{ + return fPort; +} + + +void +BNetworkServiceSettings::SetPort(int port) +{ + fPort = port; } @@ -1522,3 +1619,55 @@ BNetworkServiceSettings::AddressAt(int32 index) const { return fAddresses[index]; } + + +void +BNetworkServiceSettings::AddAddress( + const BNetworkServiceAddressSettings& address) +{ + fAddresses.push_back(address); +} + + +void +BNetworkServiceSettings::RemoveAddress(int32 index) +{ + fAddresses.erase(fAddresses.begin() + index); +} + + +status_t +BNetworkServiceSettings::GetMessage(BMessage& data) const +{ + status_t status = data.SetString("name", fName); + if (status == B_OK && !fEnabled) + status = data.SetBool("disabled", true); + if (status == B_OK && fStandAlone) + status = data.SetBool("stand_alone", true); + + if (fFamily != AF_UNSPEC) + status = data.SetInt32("family", fFamily); + if (fType != -1) + status = data.SetInt32("type", fType); + if (fProtocol != -1) + status = data.SetInt32("protocol", fProtocol); + if (fPort != -1) + status = data.SetInt32("port", fPort); + + for (int32 i = 0; i < fArguments.CountStrings(); i++) { + if (status == B_OK) + status = data.AddMessage("launch", fArguments.StringAt(i)); + if (status != B_OK) + break; + } + + for (int32 i = 0; i < CountAddresses(); i++) { + BMessage address; + status = AddressAt(i).GetMessage(address); + if (status == B_OK) + status = data.AddMessage("address", &address); + if (status != B_OK) + break; + } + return status; +} diff --git a/src/servers/net/Services.cpp b/src/servers/net/Services.cpp index db1f18b..2175d55 100644 --- a/src/servers/net/Services.cpp +++ b/src/servers/net/Services.cpp @@ -10,7 +10,6 @@ #include "Services.h" #include <new> -//#include <vector> #include <errno.h> #include <netinet/in.h> @@ -325,6 +324,8 @@ Services::_ToService(const BMessage& message, struct service*& service) status_t status = settings.InitCheck(); if (status != B_OK) return status; + if (!settings.IsEnabled()) + return B_NAME_NOT_FOUND; service = new (std::nothrow) ::service; if (service == NULL) ############################################################################ Commit: 15dc9769fec1d716105720dd2a1c22783972a1cd Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> Date: Tue Mar 10 21:47:44 2015 UTC Network: first steps to an SSH service add-on. ---------------------------------------------------------------------------- diff --git a/src/add-ons/network_settings/Jamfile b/src/add-ons/network_settings/Jamfile index 8b4a68b..c9b5846 100644 --- a/src/add-ons/network_settings/Jamfile +++ b/src/add-ons/network_settings/Jamfile @@ -2,3 +2,4 @@ SubDir HAIKU_TOP src add-ons network_settings ; SubInclude HAIKU_TOP src add-ons network_settings ipv4 ; SubInclude HAIKU_TOP src add-ons network_settings ipv6 ; +SubInclude HAIKU_TOP src add-ons network_settings sshd ; diff --git a/src/add-ons/network_settings/sshd/Jamfile b/src/add-ons/network_settings/sshd/Jamfile new file mode 100644 index 0000000..bdeb502 --- /dev/null +++ b/src/add-ons/network_settings/sshd/Jamfile @@ -0,0 +1,15 @@ +SubDir HAIKU_TOP src add-ons network_settings sshd ; + +UsePublicHeaders [ FDirName add-ons network_settings ] ; +UsePrivateHeaders shared ; + +Addon SSHService : + SSHServiceAddOn.cpp + + : be bnetapi shared <nogrist>Network [ TargetLibsupc++ ] + [ TargetLibstdc++ ] localestub +; + +DoCatalogs SSHService : x-vnd.Haiku-SSHService : + SSHServiceAddOn.cpp +; diff --git a/src/add-ons/network_settings/sshd/SSHServiceAddOn.cpp b/src/add-ons/network_settings/sshd/SSHServiceAddOn.cpp new file mode 100644 index 0000000..f2efaaf --- /dev/null +++ b/src/add-ons/network_settings/sshd/SSHServiceAddOn.cpp @@ -0,0 +1,276 @@ +/* + * Copyright 2015 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, <axeld@xxxxxxxxxxxxxxxx> + */ + + +#include <Button.h> +#include <Catalog.h> +#include <LayoutBuilder.h> +#include <NetworkSettingsAddOn.h> +#include <StringItem.h> +#include <StringView.h> +#include <TextView.h> + + +using namespace BNetworkKit; + + +#undef B_TRANSLATION_CONTEXT +#define B_TRANSLATION_CONTEXT "SSHServiceAddOn" + + +static const uint32 kMsgToggleService = 'tgls'; + + +class SSHServiceAddOn : public BNetworkSettingsAddOn { +public: + SSHServiceAddOn(image_id image, + BNetworkSettings& settings); + virtual ~SSHServiceAddOn(); + + virtual BNetworkSettingsItem* + CreateNextItem(uint32& cookie); +}; + + +class ServiceView : public BView { +public: + ServiceView(BNetworkSettings& settings); + virtual ~ServiceView(); + + void ConfigurationUpdated(const BMessage& message); + + virtual void MessageReceived(BMessage* message); + +private: + bool _IsEnabled() const; + void _Enable(); + void _Disable(); + +private: + BNetworkSettings& fSettings; +}; + + +class SSHServiceItem : public BNetworkSettingsItem { +public: + SSHServiceItem(BNetworkSettings& settings); + virtual ~SSHServiceItem(); + + virtual BNetworkSettingsType + Type() const; + + virtual BListItem* ListItem(); + virtual BView* View(); + + virtual status_t Revert(); + virtual bool IsRevertable(); + + virtual void ConfigurationUpdated(const BMessage& message); + +private: + BNetworkSettings& fSettings; + BStringItem* fItem; + ServiceView* fView; +}; + + +// #pragma mark - + + +ServiceView::ServiceView(BNetworkSettings& settings) + : + BView("service", 0), + fSettings(settings) +{ + BStringView* titleView = new BStringView("service", + B_TRANSLATE("SSH server")); + titleView->SetFont(be_bold_font); + titleView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); + + BTextView* descriptionView = new BTextView("description"); + descriptionView->SetText(B_TRANSLATE("The SSH server allows you to " + "remotely access your machine with a terminal session, as well as " + "file access using the SCP and SFTP protocols.")); + descriptionView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + descriptionView->MakeEditable(false); + + BButton* button = new BButton("toggler", B_TRANSLATE("Enable"), + new BMessage(kMsgToggleService)); + + BLayoutBuilder::Group<>(this, B_VERTICAL) + .Add(titleView) + .Add(descriptionView) + .AddGroup(B_HORIZONTAL) + .AddGlue() + .Add(button); + + SetExplicitMinSize(BSize(200, B_SIZE_UNSET)); +} + + +ServiceView::~ServiceView() +{ +} + + +void +ServiceView::ConfigurationUpdated(const BMessage& message) +{ +} + + +void +ServiceView::MessageReceived(BMessage* message) +{ + switch (message->what) { + case kMsgToggleService: + if (_IsEnabled()) + _Disable(); + else + _Enable(); + break; + default: + BView::MessageReceived(message); + break; + } +} + + +bool +ServiceView::_IsEnabled() const +{ + BNetworkServiceSettings settings = fSettings.Service("ssh"); + return settings.IsEnabled(); +} + + +void +ServiceView::_Enable() +{ + BNetworkServiceSettings settings; + settings.SetName("ssh"); + settings.SetStandAlone(true); + + settings.AddArgument("/bin/sshd"); + settings.AddArgument("-D"); + + BMessage service; + if (settings.GetMessage(service) == B_OK) + fSettings.AddService(service); +} + + +void +ServiceView::_Disable() +{ + fSettings.RemoveService("ssh"); +} + + +// #pragma mark - + + +SSHServiceItem::SSHServiceItem(BNetworkSettings& settings) + : + fSettings(settings), + fItem(new BStringItem(B_TRANSLATE("SSH server"))), + fView(NULL) +{ +} + + +SSHServiceItem::~SSHServiceItem() +{ + if (fView->Parent() == NULL) + delete fView; + + delete fItem; +} + + +BNetworkSettingsType +SSHServiceItem::Type() const +{ + return B_NETWORK_SETTINGS_TYPE_SERVICE; +} + + +BListItem* +SSHServiceItem::ListItem() +{ + return fItem; +} + + +BView* +SSHServiceItem::View() +{ + if (fView == NULL) + fView = new ServiceView(fSettings); + + return fView; +} + + +status_t +SSHServiceItem::Revert() +{ + return B_OK; +} + + +bool +SSHServiceItem::IsRevertable() +{ + return false; +} + + +void +SSHServiceItem::ConfigurationUpdated(const BMessage& message) +{ + if (fView != NULL) + fView->ConfigurationUpdated(message); +} + + +// #pragma mark - + + +SSHServiceAddOn::SSHServiceAddOn(image_id image, + BNetworkSettings& settings) + : + BNetworkSettingsAddOn(image, settings) +{ +} + + +SSHServiceAddOn::~SSHServiceAddOn() +{ +} + + +BNetworkSettingsItem* +SSHServiceAddOn::CreateNextItem(uint32& cookie) +{ + if (cookie++ == 0) + return new SSHServiceItem(Settings()); + + return NULL; +} + + +// #pragma mark - + + +extern "C" +BNetworkSettingsAddOn* +instantiate_network_settings_add_on(image_id image, BNetworkSettings& settings) +{ + return new SSHServiceAddOn(image, settings); +}