diff --git a/src/preferences/network/EthernetSettingsView.cpp b/src/preferences/network/EthernetSettingsView.cpp index c3bda26881..a8bac00c7c 100644 --- a/src/preferences/network/EthernetSettingsView.cpp +++ b/src/preferences/network/EthernetSettingsView.cpp @@ -7,6 +7,7 @@ * Stephan Assmuß * Axel Dörfler * Hugo Santos + * Philippe Saint-Pierre */ #include "EthernetSettingsView.h" @@ -59,6 +60,8 @@ #include +#include + #include "AutoDeleter.h" @@ -164,6 +167,13 @@ EthernetSettingsView::EthernetSettingsView() layout->AddItem(fSecondaryDNSTextControl->CreateLabelLayoutItem(), 0, 6); layout->AddItem(fSecondaryDNSTextControl->CreateTextViewLayoutItem(), 1, 6); + fErrorMessage = new BStringView("error", ""); + fErrorMessage->SetAlignment(B_ALIGN_LEFT); + fErrorMessage->SetFont(be_bold_font); + fErrorMessage->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); + + layout->AddView(fErrorMessage, 1, 7); + // button group (TODO: move to window, but take care of // enabling/disabling) BGroupView* buttonGroup = new BGroupView(B_HORIZONTAL); @@ -486,6 +496,38 @@ EthernetSettingsView::_GetPath(const char* name, BPath& path) } +bool +MatchPattern(const char* string, const char* pattern) +{ + regex_t compiled; + bool result = regcomp(&compiled, pattern, REG_NOSUB | REG_EXTENDED) == 0 + && regexec(&compiled, string, 0, NULL, 0) == 0; + regfree(&compiled); + + return result; +} + + +bool +EthernetSettingsView::_ValidateControl(BTextControl* control) +{ + static const char* pattern = "^(25[0-5]|2[0-4][0-9]|[01][0-9]{2}|[0-9]" + "{1,2})(\\.(25[0-5]|2[0-4][0-9]|[01][0-9]{2}|[0-9]{1,2})){3}$"; + + if (control->IsEnabled() && !MatchPattern(control->Text(), pattern)) { + control->MakeFocus(); + BString errorMessage; + errorMessage << control->Label(); + errorMessage.RemoveLast(":"); + errorMessage << " is invalid"; + fErrorMessage->SetText(errorMessage.String()); + beep(); + return false; + } + return true; +} + + void EthernetSettingsView::MessageReceived(BMessage* message) { @@ -514,9 +556,16 @@ EthernetSettingsView::MessageReceived(BMessage* message) fRevertButton->SetEnabled(false); break; case kMsgApply: - _SaveConfiguration(); + if (_ValidateControl(fIPTextControl) + && _ValidateControl(fNetMaskTextControl) + && _ValidateControl(fGatewayTextControl) + && _ValidateControl(fPrimaryDNSTextControl) + && (strlen(fSecondaryDNSTextControl->Text()) == 0 + || _ValidateControl(fSecondaryDNSTextControl))) + _SaveConfiguration(); break; case kMsgChange: + fErrorMessage->SetText(""); fApplyButton->SetEnabled(true); break; default: diff --git a/src/preferences/network/EthernetSettingsView.h b/src/preferences/network/EthernetSettingsView.h index 3d26c9a913..07915cd9fb 100644 --- a/src/preferences/network/EthernetSettingsView.h +++ b/src/preferences/network/EthernetSettingsView.h @@ -16,10 +16,13 @@ #include #include +#include + class BButton; class BMenuField; class BPath; class BTextControl; +class BStringView; class EthernetSettingsView : public BView { @@ -46,6 +49,8 @@ private: void _ApplyControlsToConfiguration(); status_t _GetPath(const char* name, BPath& path); status_t _TriggerAutoConfig(const char* device); + + bool _ValidateControl(BTextControl* control); private: BButton* fApplyButton; @@ -60,6 +65,9 @@ private: BTextControl* fPrimaryDNSTextControl; BTextControl* fSecondaryDNSTextControl; + + BStringView* fErrorMessage; + // TODO: DNS settings do not belong here, do they? BObjectList fInterfaces; // TODO: the view should not know about the interfaces,