* Copyright 2005, Waldemar Kornewald <wkornew@gmx.net>
* Distributed under the terms of the MIT License.
*/
#include "ConnectionView.h"
#include "PPPDeskbarReplicant.h"
#include <MessageDriverSettingsUtils.h>
#include <Application.h>
#include <Box.h>
#include <Button.h>
#include <Deskbar.h>
#include <Entry.h>
#include <File.h>
#include <String.h>
#include <StringView.h>
#include <TextControl.h>
#include <Window.h>
#include <PPPInterface.h>
#include <settings_tools.h>
#include <algorithm>
using std::max;
static const uint32 kDefaultButtonWidth = 80;
static const uint32 kMsgCancel = 'CANC';
static const uint32 kMsgConnect = 'CONN';
static const uint32 kMsgUpdate = 'MUPD';
static const char *kLabelSavePassword = "Save password";
static const char *kLabelName = "Username: ";
static const char *kLabelPassword = "Password: ";
static const char *kLabelConnect = "Connect";
static const char *kLabelCancel = "Cancel";
static const char *kLabelAuthentication = "Authentication";
static const char *kTextConnecting = "Connecting...";
static const char *kTextConnectionEstablished = "Connection established.";
static const char *kTextNotConnected = "Not connected.";
static const char *kTextDeviceUpFailed = "Failed to connect.";
static const char *kTextAuthenticating = "Authenticating...";
static const char *kTextAuthenticationFailed = "Authentication failed!";
static const char *kTextConnectionLost = "Connection lost!";
ConnectionView::ConnectionView(BRect rect, const BString& interfaceName)
: BView(rect, "ConnectionView", B_FOLLOW_NONE, 0),
fListener(this),
fInterfaceName(interfaceName),
fKeepLabel(false)
{
SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
rect = Bounds();
rect.InsetBy(5, 5);
rect.bottom = rect.top
+ 25
+ 3 * 20
+ 3 * 5;
BBox *authenticationBox = new BBox(rect, "Authentication");
authenticationBox->SetLabel(kLabelAuthentication);
rect = authenticationBox->Bounds();
rect.InsetBy(10, 20);
rect.bottom = rect.top + 20;
fUsername = new BTextControl(rect, "username", kLabelName, NULL, NULL);
rect.top = rect.bottom + 5;
rect.bottom = rect.top + 20;
fPassword = new BTextControl(rect, "password", kLabelPassword, NULL, NULL);
fPassword->TextView()->HideTyping(true);
float width = max(StringWidth(fUsername->Label()),
StringWidth(fPassword->Label()));
fUsername->SetDivider(width + 5);
fPassword->SetDivider(width + 5);
rect.top = rect.bottom + 5;
rect.bottom = rect.top + 20;
fSavePassword = new BCheckBox(rect, "SavePassword", kLabelSavePassword, NULL);
authenticationBox->AddChild(fUsername);
authenticationBox->AddChild(fPassword);
authenticationBox->AddChild(fSavePassword);
AddChild(authenticationBox);
rect = authenticationBox->Frame();
rect.top = rect.bottom + 10;
rect.bottom = rect.top + 15;
fAttemptView = new BStringView(rect, "AttemptView", "");
AddChild(fAttemptView);
rect.top = rect.bottom + 5;
rect.bottom = rect.top + 15;
fStatusView = new BStringView(rect, "StatusView", "");
AddChild(fStatusView);
rect.top = rect.bottom + 10;
rect.bottom = rect.top + 25;
rect.right = rect.left + kDefaultButtonWidth;
fConnectButton = new BButton(rect, "ConnectButton", kLabelConnect,
new BMessage(kMsgConnect));
rect.left = rect.right + 10;
rect.right = rect.left + kDefaultButtonWidth;
fCancelButton = new BButton(rect, "CancelButton", kLabelCancel,
new BMessage(kMsgCancel));
AddChild(fConnectButton);
AddChild(fCancelButton);
}
void
ConnectionView::AttachedToWindow()
{
Reload();
fListener.WatchManager();
WatchInterface(fListener.Manager().InterfaceWithName(fInterfaceName.String()));
Window()->SetDefaultButton(fConnectButton);
fConnectButton->SetTarget(this);
fCancelButton->SetTarget(this);
}
void
ConnectionView::MessageReceived(BMessage *message)
{
switch(message->what) {
case PPP_REPORT_MESSAGE:
HandleReportMessage(message);
break;
case kMsgConnect:
Connect();
break;
case kMsgCancel:
Cancel();
break;
default:
BView::MessageReceived(message);
}
}
void
ConnectionView::Reload()
{
BString path("ptpnet/");
path << fInterfaceName;
fSettings.MakeEmpty();
ReadMessageDriverSettings(path.String(), &fSettings);
fHasUsername = fHasPassword = false;
BString username, password;
BMessage parameter;
int32 parameterIndex = 0;
if(FindMessageParameter(PPP_USERNAME_KEY, fSettings, ¶meter, ¶meterIndex)
&& parameter.FindString(MDSU_VALUES, &username) == B_OK)
fHasUsername = true;
parameterIndex = 0;
if(FindMessageParameter(PPP_PASSWORD_KEY, fSettings, ¶meter, ¶meterIndex)
&& parameter.FindString(MDSU_VALUES, &password) == B_OK)
fHasPassword = true;
fUsername->SetText(username.String());
fPassword->SetText(password.String());
fSavePassword->SetValue(fHasPassword);
fUsername->SetEnabled(fHasUsername);
fPassword->SetEnabled(fHasUsername);
fSavePassword->SetEnabled(fHasUsername);
}
void
ConnectionView::Connect()
{
PPPInterface interface(PPPManager().CreateInterfaceWithName(
fInterfaceName.String()));
interface.SetUsername(Username());
interface.SetPassword(Password());
interface.SetAskBeforeConnecting(false);
interface.Up();
if(fHasUsername) {
BMessage parameter;
int32 index = 0;
if(FindMessageParameter(PPP_USERNAME_KEY, fSettings, ¶meter, &index))
fSettings.RemoveData(MDSU_PARAMETERS, index);
parameter.MakeEmpty();
parameter.AddString(MDSU_NAME, PPP_USERNAME_KEY);
parameter.AddString(MDSU_VALUES, Username());
fSettings.AddMessage(MDSU_PARAMETERS, ¶meter);
index = 0;
if(FindMessageParameter(PPP_PASSWORD_KEY, fSettings, ¶meter, &index))
fSettings.RemoveData(MDSU_PARAMETERS, index);
if(DoesSavePassword()) {
parameter.MakeEmpty();
parameter.AddString(MDSU_NAME, PPP_PASSWORD_KEY);
parameter.AddString(MDSU_VALUES, Password());
fSettings.AddMessage(MDSU_PARAMETERS, ¶meter);
}
BEntry entry;
if(interface.GetSettingsEntry(&entry) == B_OK) {
BFile file(&entry, B_WRITE_ONLY);
WriteMessageDriverSettings(file, fSettings);
}
}
Reload();
}
void
ConnectionView::Cancel()
{
PPPInterface interface(fListener.Interface());
bool quit = false;
ppp_interface_info_t info;
if(interface.GetInterfaceInfo(&info) && info.info.phase < PPP_ESTABLISHMENT_PHASE)
quit = true;
interface.Down();
if(quit)
Window()->Quit();
}
void
ConnectionView::CleanUp()
{
fListener.StopWatchingInterface();
fListener.StopWatchingManager();
}
BString
ConnectionView::AttemptString() const
{
PPPInterface interface(fListener.Interface());
ppp_interface_info_t info;
if(!interface.GetInterfaceInfo(&info))
return BString("");
BString attempt;
attempt << "Attempt " << info.info.connectAttempt << " of " <<
info.info.connectRetriesLimit + 1;
return attempt;
}
void
ConnectionView::HandleReportMessage(BMessage *message)
{
ppp_interface_id id;
if(message->FindInt32("interface", reinterpret_cast<int32*>(&id)) != B_OK
|| (fListener.Interface() != PPP_UNDEFINED_INTERFACE_ID
&& id != fListener.Interface()))
return;
int32 type, code;
message->FindInt32("type", &type);
message->FindInt32("code", &code);
if(type == PPP_MANAGER_REPORT && code == PPP_REPORT_INTERFACE_CREATED) {
PPPInterface interface(id);
if(interface.InitCheck() != B_OK || fInterfaceName != interface.Name())
return;
WatchInterface(id);
if(((fHasUsername && !fHasPassword) || fAskBeforeConnecting)
&& Window()->IsHidden())
Window()->Show();
} else if(type == PPP_CONNECTION_REPORT)
UpdateStatus(code);
else if(type == PPP_DESTRUCTION_REPORT)
fListener.StopWatchingInterface();
}
void
ConnectionView::UpdateStatus(int32 code)
{
BString attemptString = AttemptString();
fAttemptView->SetText(attemptString.String());
if(code == PPP_REPORT_UP_SUCCESSFUL) {
fStatusView->SetText(kTextConnectionEstablished);
PPPDeskbarReplicant *item = new PPPDeskbarReplicant(fListener.Interface());
BDeskbar().AddItem(item);
delete item;
Window()->Quit();
return;
}
if(fKeepLabel && code != PPP_REPORT_GOING_UP && code != PPP_REPORT_UP_SUCCESSFUL)
return;
if(fListener.InitCheck() != B_OK) {
fStatusView->SetText(kTextConnectionLost);
return;
}
switch(code) {
case PPP_REPORT_GOING_UP:
fKeepLabel = false;
fStatusView->SetText(kTextConnecting);
break;
case PPP_REPORT_DOWN_SUCCESSFUL:
fStatusView->SetText(kTextNotConnected);
break;
case PPP_REPORT_DEVICE_UP_FAILED:
fKeepLabel = true;
fStatusView->SetText(kTextDeviceUpFailed);
break;
case PPP_REPORT_AUTHENTICATION_REQUESTED:
fStatusView->SetText(kTextAuthenticating);
break;
case PPP_REPORT_AUTHENTICATION_FAILED:
fKeepLabel = true;
fStatusView->SetText(kTextAuthenticationFailed);
break;
case PPP_REPORT_CONNECTION_LOST:
fKeepLabel = true;
fStatusView->SetText(kTextConnectionLost);
break;
}
}
void
ConnectionView::WatchInterface(ppp_interface_id ID)
{
fListener.WatchInterface(ID);
Reload();
PPPInterface interface(fListener.Interface());
ppp_interface_info_t info;
if(!interface.GetInterfaceInfo(&info)) {
UpdateStatus(PPP_REPORT_DOWN_SUCCESSFUL);
fAskBeforeConnecting = false;
} else
fAskBeforeConnecting = info.info.askBeforeConnecting;
}