vfs: check userland buffers before reading them.
[haiku.git] / src / bin / network / ppp_up / ConnectionView.cpp
blob14291bf4a521cb282209b6e5eba81862d863ef0c
1 /*
2 * Copyright 2005, Waldemar Kornewald <wkornew@gmx.net>
3 * Distributed under the terms of the MIT License.
4 */
6 #include "ConnectionView.h"
7 #include "PPPDeskbarReplicant.h"
8 #include <MessageDriverSettingsUtils.h>
10 #include <Application.h>
11 #include <Box.h>
12 #include <Button.h>
13 #include <Deskbar.h>
14 #include <Entry.h>
15 #include <File.h>
16 #include <String.h>
17 #include <StringView.h>
18 #include <TextControl.h>
19 #include <Window.h>
21 #include <PPPInterface.h>
22 #include <settings_tools.h>
23 #include <algorithm>
24 // for max()
26 using std::max;
28 // GUI constants
29 static const uint32 kDefaultButtonWidth = 80;
31 // message constants
32 static const uint32 kMsgCancel = 'CANC';
33 static const uint32 kMsgConnect = 'CONN';
34 static const uint32 kMsgUpdate = 'MUPD';
36 // labels
37 static const char *kLabelSavePassword = "Save password";
38 static const char *kLabelName = "Username: ";
39 static const char *kLabelPassword = "Password: ";
40 static const char *kLabelConnect = "Connect";
41 static const char *kLabelCancel = "Cancel";
42 static const char *kLabelAuthentication = "Authentication";
44 // connection status strings
45 static const char *kTextConnecting = "Connecting...";
46 static const char *kTextConnectionEstablished = "Connection established.";
47 static const char *kTextNotConnected = "Not connected.";
48 static const char *kTextDeviceUpFailed = "Failed to connect.";
49 static const char *kTextAuthenticating = "Authenticating...";
50 static const char *kTextAuthenticationFailed = "Authentication failed!";
51 static const char *kTextConnectionLost = "Connection lost!";
54 ConnectionView::ConnectionView(BRect rect, const BString& interfaceName)
55 : BView(rect, "ConnectionView", B_FOLLOW_NONE, 0),
56 fListener(this),
57 fInterfaceName(interfaceName),
58 fKeepLabel(false)
60 SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
62 rect = Bounds();
63 rect.InsetBy(5, 5);
64 rect.bottom = rect.top
65 + 25 // space for topmost control
66 + 3 * 20 // size of controls
67 + 3 * 5; // space beween controls and bottom of box
68 BBox *authenticationBox = new BBox(rect, "Authentication");
69 authenticationBox->SetLabel(kLabelAuthentication);
70 rect = authenticationBox->Bounds();
71 rect.InsetBy(10, 20);
72 rect.bottom = rect.top + 20;
73 fUsername = new BTextControl(rect, "username", kLabelName, NULL, NULL);
74 rect.top = rect.bottom + 5;
75 rect.bottom = rect.top + 20;
76 fPassword = new BTextControl(rect, "password", kLabelPassword, NULL, NULL);
77 fPassword->TextView()->HideTyping(true);
79 // set dividers
80 float width = max(StringWidth(fUsername->Label()),
81 StringWidth(fPassword->Label()));
82 fUsername->SetDivider(width + 5);
83 fPassword->SetDivider(width + 5);
85 rect.top = rect.bottom + 5;
86 rect.bottom = rect.top + 20;
87 fSavePassword = new BCheckBox(rect, "SavePassword", kLabelSavePassword, NULL);
89 authenticationBox->AddChild(fUsername);
90 authenticationBox->AddChild(fPassword);
91 authenticationBox->AddChild(fSavePassword);
92 AddChild(authenticationBox);
94 rect = authenticationBox->Frame();
95 rect.top = rect.bottom + 10;
96 rect.bottom = rect.top + 15;
97 fAttemptView = new BStringView(rect, "AttemptView", "");
98 AddChild(fAttemptView);
100 // add status view
101 rect.top = rect.bottom + 5;
102 rect.bottom = rect.top + 15;
103 fStatusView = new BStringView(rect, "StatusView", "");
104 AddChild(fStatusView);
106 // add "Connect" and "Cancel" buttons
107 rect.top = rect.bottom + 10;
108 rect.bottom = rect.top + 25;
109 rect.right = rect.left + kDefaultButtonWidth;
110 fConnectButton = new BButton(rect, "ConnectButton", kLabelConnect,
111 new BMessage(kMsgConnect));
113 rect.left = rect.right + 10;
114 rect.right = rect.left + kDefaultButtonWidth;
115 fCancelButton = new BButton(rect, "CancelButton", kLabelCancel,
116 new BMessage(kMsgCancel));
118 AddChild(fConnectButton);
119 AddChild(fCancelButton);
123 void
124 ConnectionView::AttachedToWindow()
126 Reload();
127 fListener.WatchManager();
128 WatchInterface(fListener.Manager().InterfaceWithName(fInterfaceName.String()));
130 Window()->SetDefaultButton(fConnectButton);
131 fConnectButton->SetTarget(this);
132 fCancelButton->SetTarget(this);
136 void
137 ConnectionView::MessageReceived(BMessage *message)
139 switch(message->what) {
140 case PPP_REPORT_MESSAGE:
141 HandleReportMessage(message);
142 break;
144 case kMsgConnect:
145 Connect();
146 break;
148 case kMsgCancel:
149 Cancel();
150 break;
152 default:
153 BView::MessageReceived(message);
158 // update authentication UI
159 void
160 ConnectionView::Reload()
162 // load username and password
163 BString path("ptpnet/");
164 path << fInterfaceName;
165 fSettings.MakeEmpty();
166 ReadMessageDriverSettings(path.String(), &fSettings);
168 fHasUsername = fHasPassword = false;
169 BString username, password;
171 BMessage parameter;
172 int32 parameterIndex = 0;
173 if(FindMessageParameter(PPP_USERNAME_KEY, fSettings, &parameter, &parameterIndex)
174 && parameter.FindString(MDSU_VALUES, &username) == B_OK)
175 fHasUsername = true;
177 parameterIndex = 0;
178 if(FindMessageParameter(PPP_PASSWORD_KEY, fSettings, &parameter, &parameterIndex)
179 && parameter.FindString(MDSU_VALUES, &password) == B_OK)
180 fHasPassword = true;
182 fUsername->SetText(username.String());
183 fPassword->SetText(password.String());
184 fSavePassword->SetValue(fHasPassword);
186 fUsername->SetEnabled(fHasUsername);
187 fPassword->SetEnabled(fHasUsername);
188 fSavePassword->SetEnabled(fHasUsername);
192 void
193 ConnectionView::Connect()
195 PPPInterface interface(PPPManager().CreateInterfaceWithName(
196 fInterfaceName.String()));
197 interface.SetUsername(Username());
198 interface.SetPassword(Password());
199 interface.SetAskBeforeConnecting(false);
200 interface.Up();
202 // save settings
203 if(fHasUsername) {
204 BMessage parameter;
205 int32 index = 0;
206 if(FindMessageParameter(PPP_USERNAME_KEY, fSettings, &parameter, &index))
207 fSettings.RemoveData(MDSU_PARAMETERS, index);
208 parameter.MakeEmpty();
209 parameter.AddString(MDSU_NAME, PPP_USERNAME_KEY);
210 parameter.AddString(MDSU_VALUES, Username());
211 fSettings.AddMessage(MDSU_PARAMETERS, &parameter);
213 index = 0;
214 if(FindMessageParameter(PPP_PASSWORD_KEY, fSettings, &parameter, &index))
215 fSettings.RemoveData(MDSU_PARAMETERS, index);
216 if(DoesSavePassword()) {
217 parameter.MakeEmpty();
218 parameter.AddString(MDSU_NAME, PPP_PASSWORD_KEY);
219 parameter.AddString(MDSU_VALUES, Password());
220 fSettings.AddMessage(MDSU_PARAMETERS, &parameter);
223 BEntry entry;
224 if(interface.GetSettingsEntry(&entry) == B_OK) {
225 BFile file(&entry, B_WRITE_ONLY);
226 WriteMessageDriverSettings(file, fSettings);
230 Reload();
234 void
235 ConnectionView::Cancel()
237 PPPInterface interface(fListener.Interface());
238 bool quit = false;
239 ppp_interface_info_t info;
240 if(interface.GetInterfaceInfo(&info) && info.info.phase < PPP_ESTABLISHMENT_PHASE)
241 quit = true;
242 interface.Down();
243 if(quit)
244 Window()->Quit();
248 // Clean up before our window quits (called by ConnectionWindow).
249 void
250 ConnectionView::CleanUp()
252 fListener.StopWatchingInterface();
253 fListener.StopWatchingManager();
257 BString
258 ConnectionView::AttemptString() const
260 PPPInterface interface(fListener.Interface());
261 ppp_interface_info_t info;
262 if(!interface.GetInterfaceInfo(&info))
263 return BString("");
264 BString attempt;
265 attempt << "Attempt " << info.info.connectAttempt << " of " <<
266 info.info.connectRetriesLimit + 1;
268 return attempt;
272 void
273 ConnectionView::HandleReportMessage(BMessage *message)
275 ppp_interface_id id;
276 if(message->FindInt32("interface", reinterpret_cast<int32*>(&id)) != B_OK
277 || (fListener.Interface() != PPP_UNDEFINED_INTERFACE_ID
278 && id != fListener.Interface()))
279 return;
281 int32 type, code;
282 message->FindInt32("type", &type);
283 message->FindInt32("code", &code);
285 if(type == PPP_MANAGER_REPORT && code == PPP_REPORT_INTERFACE_CREATED) {
286 PPPInterface interface(id);
287 if(interface.InitCheck() != B_OK || fInterfaceName != interface.Name())
288 return;
290 WatchInterface(id);
292 if(((fHasUsername && !fHasPassword) || fAskBeforeConnecting)
293 && Window()->IsHidden())
294 Window()->Show();
295 } else if(type == PPP_CONNECTION_REPORT)
296 UpdateStatus(code);
297 else if(type == PPP_DESTRUCTION_REPORT)
298 fListener.StopWatchingInterface();
302 void
303 ConnectionView::UpdateStatus(int32 code)
305 BString attemptString = AttemptString();
306 fAttemptView->SetText(attemptString.String());
308 if(code == PPP_REPORT_UP_SUCCESSFUL) {
309 fStatusView->SetText(kTextConnectionEstablished);
310 PPPDeskbarReplicant *item = new PPPDeskbarReplicant(fListener.Interface());
311 BDeskbar().AddItem(item);
312 delete item;
313 Window()->Quit();
314 return;
317 // maybe the status string must not be changed (codes that set fKeepLabel to false
318 // should still be handled)
319 if(fKeepLabel && code != PPP_REPORT_GOING_UP && code != PPP_REPORT_UP_SUCCESSFUL)
320 return;
322 if(fListener.InitCheck() != B_OK) {
323 fStatusView->SetText(kTextConnectionLost);
324 return;
327 // only errors should set fKeepLabel to true
328 switch(code) {
329 case PPP_REPORT_GOING_UP:
330 fKeepLabel = false;
331 fStatusView->SetText(kTextConnecting);
332 break;
334 case PPP_REPORT_DOWN_SUCCESSFUL:
335 fStatusView->SetText(kTextNotConnected);
336 break;
338 case PPP_REPORT_DEVICE_UP_FAILED:
339 fKeepLabel = true;
340 fStatusView->SetText(kTextDeviceUpFailed);
341 break;
343 case PPP_REPORT_AUTHENTICATION_REQUESTED:
344 fStatusView->SetText(kTextAuthenticating);
345 break;
347 case PPP_REPORT_AUTHENTICATION_FAILED:
348 fKeepLabel = true;
349 fStatusView->SetText(kTextAuthenticationFailed);
350 break;
352 case PPP_REPORT_CONNECTION_LOST:
353 fKeepLabel = true;
354 fStatusView->SetText(kTextConnectionLost);
355 break;
360 void
361 ConnectionView::WatchInterface(ppp_interface_id ID)
363 fListener.WatchInterface(ID);
365 // update status
366 Reload();
367 PPPInterface interface(fListener.Interface());
368 ppp_interface_info_t info;
369 if(!interface.GetInterfaceInfo(&info)) {
370 UpdateStatus(PPP_REPORT_DOWN_SUCCESSFUL);
371 fAskBeforeConnecting = false;
372 } else
373 fAskBeforeConnecting = info.info.askBeforeConnecting;