BTRFS: Implement BTree::Path and change _Find.
[haiku.git] / src / add-ons / network_settings / dialup / GeneralAddon.cpp
blob8862ed028660ecc822734d0a8c608340c9a54057
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 */
7 //-----------------------------------------------------------------------
8 // GeneralAddon saves the loaded settings.
9 // GeneralView saves the current settings.
10 //-----------------------------------------------------------------------
12 #include "GeneralAddon.h"
14 #include "InterfaceUtils.h"
15 #include "MessageDriverSettingsUtils.h"
17 #include <Box.h>
18 #include <Button.h>
19 #include <MenuField.h>
20 #include <MenuItem.h>
21 #include <LayoutBuilder.h>
22 #include <PopUpMenu.h>
23 #include <StringView.h>
25 #include <PPPDefs.h>
28 // message constants
29 static const uint32 kMsgSelectDevice = 'SELD';
30 static const uint32 kMsgSelectAuthenticator = 'SELA';
32 // labels
33 static const char *kLabelGeneral = "General";
34 static const char *kLabelDevice = "Device: ";
35 static const char *kLabelNoDevicesFound = "No Devices Found!";
36 static const char *kLabelAuthenticator = "Login: ";
37 static const char *kLabelNoAuthenticatorsFound = "No Authenticators Found!";
38 static const char *kLabelName = "Username: ";
39 static const char *kLabelPassword = "Password: ";
40 static const char *kLabelSavePassword = "Save Password";
41 static const char *kLabelNone = "None";
43 // string constants for information saved in the settings message
44 static const char *kGeneralTabAuthentication = "Authentication";
45 static const char *kGeneralTabAuthenticators = "Authenticators";
48 #define DEFAULT_AUTHENTICATOR "PAP"
49 // this authenticator is selected by default when creating a new interface
52 GeneralAddon::GeneralAddon(BMessage *addons)
53 : DialUpAddon(addons),
54 fHasPassword(false),
55 fAuthenticatorsCount(0),
56 fSettings(NULL),
57 fProfile(NULL),
58 fGeneralView(NULL)
63 GeneralAddon::~GeneralAddon()
68 bool
69 GeneralAddon::NeedsAuthenticationRequest() const
71 return fGeneralView->AuthenticatorName();
75 DialUpAddon*
76 GeneralAddon::FindDevice(const BString& moduleName) const
78 DialUpAddon *addon;
79 for(int32 index = 0; Addons()->FindPointer(DUN_DEVICE_ADDON_TYPE, index,
80 reinterpret_cast<void**>(&addon)) == B_OK; index++)
81 if(addon && moduleName == addon->KernelModuleName())
82 return addon;
84 return NULL;
88 bool
89 GeneralAddon::LoadSettings(BMessage *settings, BMessage *profile, bool isNew)
91 fIsNew = isNew;
92 fHasPassword = false;
93 fDeviceName = fUsername = fPassword = "";
94 fDeviceAddon = NULL;
95 fAuthenticatorsCount = 0;
96 fSettings = settings;
97 fProfile = profile;
99 if(fGeneralView)
100 fGeneralView->Reload();
101 // reset all views (empty settings)
103 if(!settings || !profile || isNew)
104 return true;
106 if(!LoadDeviceSettings())
107 return false;
109 if(!LoadAuthenticationSettings())
110 return false;
112 if(fGeneralView)
113 fGeneralView->Reload();
114 // reload new settings
116 return true;
120 bool
121 GeneralAddon::LoadDeviceSettings()
123 int32 index = 0;
124 BMessage device;
125 if(!FindMessageParameter(PPP_DEVICE_KEY, *fSettings, &device, &index))
126 return false;
127 // TODO: tell user that device specification is missing
129 if(device.FindString(MDSU_VALUES, &fDeviceName) != B_OK)
130 return false;
131 // TODO: tell user that device specification is missing
133 device.AddBool(MDSU_VALID, true);
134 fSettings->ReplaceMessage(MDSU_PARAMETERS, index, &device);
136 fDeviceAddon = FindDevice(fDeviceName);
137 if(!fDeviceAddon)
138 return false;
140 return fDeviceAddon->LoadSettings(fSettings, fProfile, false);
144 bool
145 GeneralAddon::LoadAuthenticationSettings()
147 // we only handle the profile (although settings could contain different data)
148 int32 itemIndex = 0;
149 BMessage authentication, item;
151 if(!FindMessageParameter(PPP_AUTHENTICATOR_KEY, *fProfile, &item, &itemIndex))
152 return true;
154 // find authenticators (though we load all authenticators, we only use one)
155 BString name;
156 for(int32 index = 0; item.FindString(MDSU_VALUES, index, &name) == B_OK; index++) {
157 BMessage authenticator;
158 if(!GetAuthenticator(name, &authenticator))
159 return false;
160 // fatal error: we do not know how to handle this authenticator
162 MarkAuthenticatorAsValid(name);
163 authentication.AddString(kGeneralTabAuthenticators, name);
164 ++fAuthenticatorsCount;
167 fSettings->AddMessage(kGeneralTabAuthentication, &authentication);
169 bool hasUsername = false;
170 // a username must be present
172 // load username and password
173 BMessage parameter;
174 int32 parameterIndex = 0;
175 if(FindMessageParameter("User", item, &parameter, &parameterIndex)
176 && parameter.FindString(MDSU_VALUES, &fUsername) == B_OK) {
177 hasUsername = true;
178 parameter.AddBool(MDSU_VALID, true);
179 item.ReplaceMessage(MDSU_PARAMETERS, parameterIndex, &parameter);
182 parameterIndex = 0;
183 if(FindMessageParameter("Password", item, &parameter, &parameterIndex)
184 && parameter.FindString(MDSU_VALUES, &fPassword) == B_OK) {
185 fHasPassword = true;
186 parameter.AddBool(MDSU_VALID, true);
187 item.ReplaceMessage(MDSU_PARAMETERS, parameterIndex, &parameter);
190 // tell DUN whether everything is valid
191 if(hasUsername)
192 item.AddBool(MDSU_VALID, true);
194 fProfile->ReplaceMessage(MDSU_PARAMETERS, itemIndex, &item);
196 return true;
200 bool
201 GeneralAddon::HasTemporaryProfile() const
203 return fGeneralView->HasTemporaryProfile();
207 void
208 GeneralAddon::IsModified(bool *settings, bool *profile) const
210 if(!fSettings) {
211 *settings = *profile = false;
212 return;
215 bool deviceSettings, authenticationSettings, deviceProfile, authenticationProfile;
217 IsDeviceModified(&deviceSettings, &deviceProfile);
218 IsAuthenticationModified(&authenticationSettings, &authenticationProfile);
220 *settings = (deviceSettings || authenticationSettings);
221 *profile = (deviceProfile || authenticationProfile);
225 void
226 GeneralAddon::IsDeviceModified(bool *settings, bool *profile) const
228 fGeneralView->IsDeviceModified(settings, profile);
232 void
233 GeneralAddon::IsAuthenticationModified(bool *settings, bool *profile) const
235 // currently we only support selecting one authenticator
236 if(fAuthenticatorsCount == 0)
237 *settings = fGeneralView->AuthenticatorName();
238 else {
239 BMessage authentication;
240 if(fSettings->FindMessage(kGeneralTabAuthentication, &authentication) != B_OK) {
241 *settings = *profile = false;
242 return;
243 // error!
246 BString authenticator;
247 if(authentication.FindString(kGeneralTabAuthenticators,
248 &authenticator) != B_OK) {
249 *settings = *profile = false;
250 return;
251 // error!
254 *settings = (!fGeneralView->AuthenticatorName()
255 || authenticator != fGeneralView->AuthenticatorName());
258 *profile = (*settings || fUsername != fGeneralView->Username()
259 || (fPassword != fGeneralView->Password() && fHasPassword)
260 || fHasPassword != fGeneralView->DoesSavePassword());
264 bool
265 GeneralAddon::SaveSettings(BMessage *settings, BMessage *profile, bool saveTemporary)
267 if(!fSettings || !settings || !fGeneralView->DeviceName())
268 return false;
269 // TODO: tell user that a device is needed (if we fail because of this)
271 if(!fGeneralView->DeviceAddon() || !fGeneralView->DeviceAddon()->SaveSettings(
272 settings, profile, saveTemporary))
273 return false;
275 if(fGeneralView->AuthenticatorName()) {
276 BMessage authenticator;
277 authenticator.AddString(MDSU_NAME, PPP_AUTHENTICATOR_KEY);
278 authenticator.AddString(MDSU_VALUES, fGeneralView->AuthenticatorName());
279 settings->AddMessage(MDSU_PARAMETERS, &authenticator);
281 BMessage username;
282 username.AddString(MDSU_NAME, "User");
283 username.AddString(MDSU_VALUES, fGeneralView->Username());
284 authenticator.AddMessage(MDSU_PARAMETERS, &username);
286 if(saveTemporary || fGeneralView->DoesSavePassword()) {
287 // save password, too
288 BMessage password;
289 password.AddString(MDSU_NAME, "Password");
290 password.AddString(MDSU_VALUES, fGeneralView->Password());
291 authenticator.AddMessage(MDSU_PARAMETERS, &password);
294 profile->AddMessage(MDSU_PARAMETERS, &authenticator);
297 return true;
301 bool
302 GeneralAddon::GetPreferredSize(float *width, float *height) const
304 BRect rect;
305 if(Addons()->FindRect(DUN_TAB_VIEW_RECT, &rect) != B_OK)
306 rect.Set(0, 0, 200, 300);
307 // set default values
309 if(width)
310 *width = rect.Width();
311 if(height)
312 *height = rect.Height();
314 return true;
318 BView*
319 GeneralAddon::CreateView()
321 if (!fGeneralView) {
322 fGeneralView = new GeneralView(this);
323 fGeneralView->Reload();
326 return fGeneralView;
330 bool
331 GeneralAddon::GetAuthenticator(const BString& moduleName, BMessage *entry) const
333 if(!entry)
334 return false;
336 BString name;
337 for(int32 index = 0; Addons()->FindMessage(DUN_AUTHENTICATOR_ADDON_TYPE, index,
338 entry) == B_OK; index++) {
339 entry->FindString("KernelModuleName", &name);
340 if (name == moduleName)
341 return true;
344 return false;
348 bool
349 GeneralAddon::MarkAuthenticatorAsValid(const BString& moduleName)
351 BMessage authenticator;
352 int32 index = 0;
353 BString name;
355 for(; FindMessageParameter(PPP_AUTHENTICATOR_KEY, *fSettings, &authenticator,
356 &index); index++) {
357 authenticator.FindString("KernelModuleName", &name);
358 if(name == moduleName) {
359 authenticator.AddBool(MDSU_VALID, true);
360 fSettings->ReplaceMessage(MDSU_PARAMETERS, index, &authenticator);
361 return true;
365 return false;
369 GeneralView::GeneralView(GeneralAddon *addon)
370 : BView(kLabelGeneral, 0),
371 fAddon(addon)
373 fDeviceBox = new BBox("Device");
374 Addon()->Addons()->AddFloat(DUN_DEVICE_VIEW_WIDTH,
375 fDeviceBox->Bounds().Width() - 10); // FIXME: remove
377 fDeviceField = new BMenuField("Device",
378 kLabelDevice, new BPopUpMenu(kLabelNoDevicesFound));
379 fDeviceField->Menu()->SetRadioMode(true);
380 AddDevices();
381 fDeviceBox->SetLabel(fDeviceField);
383 fAuthenticatorField = new BMenuField("Authenticator",
384 kLabelAuthenticator, new BPopUpMenu(kLabelNoAuthenticatorsFound));
385 fAuthenticatorField->Menu()->SetRadioMode(true);
386 AddAuthenticators();
388 fUsername = new BTextControl("username", kLabelName, NULL, NULL);
389 fPassword = new BTextControl("password", kLabelPassword, NULL, NULL);
390 fPassword->TextView()->HideTyping(true);
392 fSavePassword = new BCheckBox("SavePassword", kLabelSavePassword, NULL);
394 BLayoutBuilder::Group<>(this, B_VERTICAL, B_USE_HALF_ITEM_SPACING)
395 .SetInsets(B_USE_HALF_ITEM_INSETS)
396 .AddGroup(B_HORIZONTAL)
397 .Add(fDeviceBox)
398 .AddGlue()
399 .End()
400 .Add(fAuthenticatorField)
401 .Add(fUsername)
402 .Add(fPassword)
403 .Add(fSavePassword)
404 .AddGlue()
405 .End();
409 GeneralView::~GeneralView()
414 void
415 GeneralView::Reload()
417 fDeviceAddon = NULL;
419 BMenuItem *item = NULL;
420 for(int32 index = 0; index < fDeviceField->Menu()->CountItems(); index++) {
421 item = fDeviceField->Menu()->ItemAt(index);
422 if(item && item->Message() && item->Message()->FindPointer("Addon",
423 reinterpret_cast<void**>(&fDeviceAddon)) == B_OK
424 && fDeviceAddon == Addon()->DeviceAddon())
425 break;
428 if(fDeviceAddon && fDeviceAddon == Addon()->DeviceAddon())
429 item->SetMarked(true);
430 else if(Addon()->IsNew() && fDeviceField->Menu()->CountItems() > 0) {
431 item = fDeviceField->Menu()->ItemAt(0);
432 item->SetMarked(true);
433 item->Message()->FindPointer("Addon", reinterpret_cast<void**>(&fDeviceAddon));
434 fDeviceAddon->LoadSettings(Addon()->Settings(), Addon()->Profile(), true);
435 } else {
436 fDeviceAddon = NULL;
437 item = fDeviceField->Menu()->FindMarked();
438 if(item)
439 item->SetMarked(false);
442 if(Addon()->CountAuthenticators() > 0) {
443 BString kernelModule, authenticator;
444 BMessage authentication;
445 if(Addon()->Settings()->FindMessage(kGeneralTabAuthentication,
446 &authentication) == B_OK)
447 authentication.FindString(kGeneralTabAuthenticators, &authenticator);
448 BMenu *menu = fAuthenticatorField->Menu();
449 for(int32 index = 0; index < menu->CountItems(); index++) {
450 item = menu->ItemAt(index);
451 if(item && item->Message()
452 && item->Message()->FindString("KernelModuleName",
453 &kernelModule) == B_OK && kernelModule == authenticator) {
454 item->SetMarked(true);
455 break;
458 } else if(Addon()->IsNew() && fAuthenticatorDefault)
459 fAuthenticatorDefault->SetMarked(true);
460 else
461 fAuthenticatorNone->SetMarked(true);
463 fUsername->SetText(Addon()->Username());
464 fPassword->SetText(Addon()->Password());
465 fSavePassword->SetValue(Addon()->HasPassword());
467 ReloadDeviceView();
468 UpdateControls();
472 const char*
473 GeneralView::DeviceName() const
475 if(fDeviceAddon)
476 return fDeviceAddon->KernelModuleName();
478 return NULL;
482 const char*
483 GeneralView::AuthenticatorName() const
485 BMenuItem *marked = fAuthenticatorField->Menu()->FindMarked();
486 if(marked && marked != fAuthenticatorNone)
487 return marked->Message()->FindString("KernelModuleName");
489 return NULL;
493 void
494 GeneralView::IsDeviceModified(bool *settings, bool *profile) const
496 if(fDeviceAddon != Addon()->DeviceAddon())
497 *settings = *profile = true;
498 else if(fDeviceAddon)
499 fDeviceAddon->IsModified(settings, profile);
500 else
501 *settings = *profile = false;
505 void
506 GeneralView::AttachedToWindow()
508 SetViewColor(Parent()->ViewColor());
509 fDeviceField->Menu()->SetTargetForItems(this);
510 fAuthenticatorField->Menu()->SetTargetForItems(this);
511 fUsername->SetTarget(this);
512 fPassword->SetTarget(this);
516 void
517 GeneralView::MessageReceived(BMessage *message)
519 switch(message->what) {
520 case kMsgSelectDevice:
521 if(message->FindPointer("Addon", reinterpret_cast<void**>(&fDeviceAddon))
522 != B_OK)
523 fDeviceAddon = NULL;
524 else {
525 if(fDeviceAddon != Addon()->DeviceAddon())
526 fDeviceAddon->LoadSettings(Addon()->Settings(), Addon()->Profile(),
527 Addon()->IsNew());
529 ReloadDeviceView();
531 break;
533 case kMsgSelectAuthenticator:
534 UpdateControls();
535 break;
537 default:
538 BView::MessageReceived(message);
543 void
544 GeneralView::ReloadDeviceView()
546 // first remove existing device view(s)
547 while (fDeviceBox->CountChildren() > 1)
548 fDeviceBox->RemoveChild(fDeviceBox->ChildAt(1));
550 if (!fDeviceAddon)
551 return;
553 BView* deviceView = fDeviceAddon->CreateView();
554 if (deviceView) {
555 BLayoutBuilder::Group<>(fDeviceBox, B_VERTICAL)
556 .Add(deviceView)
557 .End();
562 void
563 GeneralView::UpdateControls()
565 BMenu *menu = fAuthenticatorField->Menu();
566 int32 index = menu->IndexOf(menu->FindMarked());
567 if (index < 0)
568 fAuthenticatorNone->SetMarked(true);
570 if (index == 0) {
571 fUsername->SetEnabled(false);
572 fPassword->SetEnabled(false);
573 fSavePassword->SetEnabled(false);
574 } else {
575 fUsername->SetEnabled(true);
576 fPassword->SetEnabled(true);
577 fSavePassword->SetEnabled(true);
582 void
583 GeneralView::AddDevices()
585 AddAddonsToMenu(Addon()->Addons(), fDeviceField->Menu(), DUN_DEVICE_ADDON_TYPE,
586 kMsgSelectDevice);
590 void
591 GeneralView::AddAuthenticators()
593 fAuthenticatorDefault = NULL;
594 fAuthenticatorNone = new BMenuItem(kLabelNone,
595 new BMessage(kMsgSelectAuthenticator));
596 fAuthenticatorField->Menu()->AddItem(fAuthenticatorNone);
597 fAuthenticatorNone->SetMarked(true);
598 fAuthenticatorField->Menu()->AddSeparatorItem();
600 BMenuItem *item;
601 BMessage addon;
602 for(int32 index = 0;
603 Addon()->Addons()->FindMessage(DUN_AUTHENTICATOR_ADDON_TYPE, index,
604 &addon) == B_OK; index++) {
605 BMessage *message = new BMessage(kMsgSelectAuthenticator);
606 message->AddString("KernelModuleName", addon.FindString("KernelModuleName"));
608 BString name, technicalName, friendlyName;
609 bool hasTechnicalName
610 = (addon.FindString("TechnicalName", &technicalName) == B_OK);
611 bool hasFriendlyName
612 = (addon.FindString("FriendlyName", &friendlyName) == B_OK);
613 if(hasTechnicalName) {
614 name << technicalName;
615 if(hasFriendlyName)
616 name << " (";
618 if(hasFriendlyName) {
619 name << friendlyName;
620 if(hasTechnicalName)
621 name << ")";
624 int32 insertAt = FindNextMenuInsertionIndex(fAuthenticatorField->Menu(),
625 name.String(), 2);
626 item = new BMenuItem(name.String(), message);
627 if(hasTechnicalName && technicalName == DEFAULT_AUTHENTICATOR)
628 fAuthenticatorDefault = item;
629 fAuthenticatorField->Menu()->AddItem(item, insertAt);