1/*
2 * kPPP: A pppd front end for the KDE project
3 *
4 *
5 * Copyright (C) 1997 Bernd Johannes Wuebben
6 * wuebben@math.cornell.edu
7 *
8 * Copyright (C) 1998-2002 Harri Porten <porten@kde.org>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU Library General Public
21 * License along with this program; if not, write to the Free
22 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 */
24
25#include "kpppwidget.h"
26#include <qapplication.h>
27#include <qcombobox.h>
28#include <qdir.h>
29#include <qevent.h>
30#include <qdialog.h>
31#include <qlabel.h>
32#include <qpushbutton.h>
33#include <qregexp.h>
34//Added by qt3to4:
35#include <QGridLayout>
36#include <QKeyEvent>
37#include <QHBoxLayout>
38#include <QVBoxLayout>
39#include <kpagedialog.h>
40
41#include <QMenu>
42#include <kaboutdata.h>
43#include <kglobalsettings.h>
44#include <kcmdlineargs.h>
45#include <kconfig.h>
46#include <kdebug.h>
47#include <kiconloader.h> // For BarIcon
48#include <klocale.h>
49#include <kmessagebox.h>
50#include <kseparator.h>
51#include <kstandarddirs.h>
52#include <kapplication.h>
53#include <kwindowsystem.h>
54#include <khelpmenu.h>
55#include <kpushbutton.h>
56#include <kguiitem.h>
57#include <KStandardGuiItem>
58
59#include <stdlib.h>
60#include <errno.h>
61#include <ktoolinvocation.h>
62
63#include "runtests.h"
64
65#include "main.h"
66#include "auth.h"
67#include "modem.h"
68#include "ppplog.h"
69#include "opener.h"
70#include "requester.h"
71#include "pppstats.h"
72#include "pppdata.h"
73#include "general.h"
74#include "modems.h"
75
76#include "kpppadaptor.h"
77
78// delay disconnection for a second
79#define DISCONNECT_DELAY 1000
80
81extern KPPPWidget *p_kppp;
82
83KPPPWidget::KPPPWidget( QWidget *parent, const char *name )
84 : QWidget(parent)
85 , acct(0)
86 , m_bCmdlAccount (false)
87 , m_bCmdlModem (false)
88{
89 KpppAdaptor *kpppAdaptor = new KpppAdaptor(this);
90 QDBusConnection::sessionBus().registerObject("/Kppp", this);
91
92 setObjectName( name );
93
94 connect( this, SIGNAL(sig_aboutToConnect()), kpppAdaptor, SIGNAL(aboutToConnect()) );
95 connect( this, SIGNAL(sig_aboutToDisconnect()), kpppAdaptor, SIGNAL(aboutToDisconnect()) );
96 connect( this, SIGNAL(sig_connected()), kpppAdaptor, SIGNAL(connected()) );
97 connect( this, SIGNAL(sig_disconnected()), kpppAdaptor, SIGNAL(disconnected()) );
98
99
100 tabWindow = 0;
101
102 // before doing anything else, run a few tests
103
104 int result = runTests();
105 if(result == TEST_CRITICAL)
106 exit(4);
107
108 installEventFilter(this);
109
110 QVBoxLayout *tl = new QVBoxLayout(this);
111 tl->setSpacing(10);
112 tl->setMargin(10);
113
114 l1 = new QGridLayout();
115 tl->addLayout(l1);
116 l1->addItem(new QSpacerItem(10, 0), 0, 0);
117 l1->addItem(new QSpacerItem(10, 0), 0, 3);
118 l1->setColumnStretch(1, 3);
119 l1->setColumnStretch(2, 4);
120
121 label1 = new QLabel(i18n("C&onnect to: "), this);
122 l1->addWidget(label1, 0, 1);
123
124 connectto_c = new QComboBox(this);
125 connectto_c->setEditable( false );
126 label1->setBuddy(connectto_c);
127
128 connect(connectto_c, SIGNAL(activated(int)),
129 SLOT(newdefaultaccount(int)));
130 l1->addWidget(connectto_c, 0, 2);
131
132 label7 = new QLabel(i18n("Use &modem: "), this);
133 // l1->addWidget(label7, 1, 1); (done in resetmodems())
134 modem_c = new QComboBox(this);
135 modem_c->setEditable( false );
136 label7->setBuddy(connectto_c);
137 m_bModemCShown = false;
138
139 connect(modem_c, SIGNAL(activated(int)),
140 SLOT(newdefaultmodem(int)));
141 // l1->addWidget(modem_c, 1, 2); (done in resetmodems())
142
143 ID_Label = new QLabel(i18n("&Login ID:"), this);
144 l1->addWidget(ID_Label, 2, 1);
145
146 // the entry line for usernames
147 ID_Edit = new QLineEdit(this);
148 ID_Label->setBuddy(ID_Edit);
149 l1->addWidget(ID_Edit, 2, 2);
150 connect(ID_Edit, SIGNAL(returnPressed()),
151 this, SLOT(enterPressedInID()));
152 QString tmp = i18n("<p>Type in the username that you got from your\n"
153 "ISP. This is especially important for PAP\n"
154 "and CHAP. You may omit this when you use\n"
155 "terminal-based or script-based authentication.\n"
156 "\n"
157 "<b>Important</b>: case is important here:\n"
158 "<i>myusername</i> is not the same as <i>MyUserName</i>.");
159
160 ID_Label->setWhatsThis(tmp);
161 ID_Edit->setWhatsThis(tmp);
162
163 PW_Label = new QLabel(i18n("&Password:"), this);
164 l1->addWidget(PW_Label, 3, 1);
165
166 PW_Edit= new QLineEdit(this);
167 PW_Label->setBuddy(PW_Edit);
168 PW_Edit->setEchoMode(QLineEdit::Password);
169 l1->addWidget(PW_Edit, 3, 2);
170 connect(PW_Edit, SIGNAL(returnPressed()),
171 this, SLOT(enterPressedInPW()));
172
173 tmp = i18n("<p>Type in the password that you got from your\n"
174 "ISP. This is especially important for PAP\n"
175 "and CHAP. You may omit this when you use\n"
176 "terminal-based or script-based authentication.\n"
177 "\n"
178 "<b>Important</b>: case is important here:\n"
179 "<i>mypassword</i> is not the same as <i>MyPassword</i>.");
180
181 PW_Label->setWhatsThis(tmp);
182 PW_Edit->setWhatsThis(tmp);
183
184 QHBoxLayout *l3 = new QHBoxLayout;
185 tl->addSpacing(5);
186 tl->addLayout(l3);
187 tl->addSpacing(5);
188 l3->addSpacing(10);
189 log = new QCheckBox(i18n("Show lo&g window"), this);
190 connect(log, SIGNAL(toggled(bool)),
191 this, SLOT(log_window_toggled(bool)));
192 log->setChecked(gpppdata.get_show_log_window());
193 l3->addWidget(log);
194
195 log->setWhatsThis(
196 i18n("<p>This controls whether a log window is shown.\n"
197 "A log window shows the communication between\n"
198 "<i>kppp</i> and your modem. This will help you\n"
199 "in tracking down problems.\n"
200 "\n"
201 "Turn it off if <i>kppp</i> routinely connects without\n"
202 "problems"));
203
204 fline = new KSeparator( Qt::Horizontal, this);
205 tl->addWidget(fline);
206
207 QHBoxLayout *l2 = new QHBoxLayout;
208 tl->addLayout(l2);
209
210 int minw = 0;
211 quit_b = new KPushButton(KStandardGuiItem::quit(), this);
212 connect( quit_b, SIGNAL(clicked()), SLOT(quitbutton()));
213 if(quit_b->sizeHint().width() > minw)
214 minw = quit_b->sizeHint().width();
215
216 setup_b = new KPushButton(KGuiItem(i18n("Co&nfigure..."), "configure"), this);
217 connect( setup_b, SIGNAL(clicked()), SLOT(expandbutton()));
218 if(setup_b->sizeHint().width() > minw)
219 minw = setup_b->sizeHint().width();
220
221 if(gpppdata.access() != KConfig::ReadWrite)
222 setup_b->setEnabled(false);
223
224 help_b = new KPushButton(KStandardGuiItem::help(), this);
225 connect( help_b, SIGNAL(clicked()), SLOT(helpbutton()));
226
227 KHelpMenu *helpMenu = new KHelpMenu(this, KGlobal::mainComponent().aboutData(), true);
228 help_b->setMenu((QMenu*)helpMenu->menu());
229 if(help_b->sizeHint().width() > minw)
230 minw = help_b->sizeHint().width();
231
232 connect_b = new QPushButton(i18n("&Connect"), this);
233 connect_b->setDefault(true);
234 connect_b->setFocus();
235 connect(connect_b, SIGNAL(clicked()), SLOT(beginConnect()));
236 if(connect_b->sizeHint().width() > minw)
237 minw = connect_b->sizeHint().width();
238
239 quit_b->setFixedWidth(minw);
240 setup_b->setFixedWidth(minw);
241 help_b->setFixedWidth(help_b->sizeHint().width());
242 connect_b->setFixedWidth(minw);
243
244 l2->addWidget(quit_b);
245 l2->addWidget(setup_b);
246 l2->addWidget(help_b);
247 l2->addSpacing(20);
248 l2->addWidget(connect_b);
249
250 setFixedSize(sizeHint());
251
252 (void)new Modem;
253
254 // we also connect cmld_start to the beginConnect so that I can run
255 // the dialer through a command line argument
256 connect(this,SIGNAL(cmdl_start()),this,SLOT(beginConnect()));
257
258 stats = new PPPStats;
259
260 KWindowSystem::setIcons(winId(), qApp->windowIcon().pixmap(IconSize(KIconLoader::Desktop),IconSize(KIconLoader::Desktop)), qApp->windowIcon().pixmap(IconSize(KIconLoader::Small),IconSize(KIconLoader::Small)));
261
262 // constructor of con_win reads position from config file
263 con_win = new ConWindow(0, "conw", this, stats);
264 KWindowSystem::setIcons(con_win->winId(), qApp->windowIcon().pixmap(IconSize(KIconLoader::Desktop),IconSize(KIconLoader::Desktop)), qApp->windowIcon().pixmap(IconSize(KIconLoader::Small),IconSize(KIconLoader::Small)));
265
266 statdlg = new PPPStatsDlg(0, "stats", this, stats);
267 statdlg->hide();
268
269 debugwindow = new DebugWidget(0);
270 debugwindow->setObjectName( "debugwindow" );
271 KWindowSystem::setIcons(debugwindow->winId(), qApp->windowIcon().pixmap(IconSize(KIconLoader::Desktop),IconSize(KIconLoader::Desktop)), qApp->windowIcon().pixmap(IconSize(KIconLoader::Small),IconSize(KIconLoader::Small)));
272
273 // load up the accounts combo box
274
275 resetaccounts();
276 resetmodems();
277 con = new ConnectWidget(0, "con", stats);
278 KWindowSystem::setIcons(con->winId(), qApp->windowIcon().pixmap(IconSize(KIconLoader::Desktop),IconSize(KIconLoader::Desktop)), qApp->windowIcon().pixmap(IconSize(KIconLoader::Small),IconSize(KIconLoader::Small)) );
279 connect(this, SIGNAL(begin_connect()),con, SLOT(preinit()));
280
281 QRect desk = KGlobalSettings::desktopGeometry(topLevelWidget());
282 con->setGeometry(desk.center().x()-175, desk.center().y()-55, 350,110);
283
284 // connect the ConnectWidgets various signals
285 connect(con, SIGNAL(closeDebugWindow()),
286 debugwindow, SLOT(hide()));
287 connect(con, SIGNAL(debugMessage(QString)),
288 debugwindow, SLOT(statusLabel(QString)));
289 connect(con, SIGNAL(toggleDebugWindow()),
290 debugwindow, SLOT(toggleVisibility()));
291 connect(con, SIGNAL(debugPutChar(unsigned char)),
292 debugwindow, SLOT(addChar(unsigned char)));
293 connect(con, SIGNAL(startAccounting()),
294 this, SLOT(startAccounting()));
295 connect(con, SIGNAL(stopAccounting()),
296 this, SLOT(stopAccounting()));
297 connect(KApplication::kApplication(), SIGNAL(saveYourself()),
298 this, SLOT(saveMyself()));
299 connect(KApplication::kApplication(), SIGNAL(aboutToQuit()),
300 this, SLOT(shutDown()));
301 connect(con, SIGNAL(aboutToConnect()), this, SIGNAL(sig_aboutToConnect()));
302 connect(con, SIGNAL(connected()), this, SIGNAL(sig_connected()));
303
304 debugwindow->setGeometry(desk.center().x()+190, desk.center().y()-55,
305 debugwindow->width(),debugwindow->height());
306
307 move(desk.center().x()-width()/2, desk.center().y()-height()/2);
308
309
310 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
311
312 m_strCmdlAccount = args->getOption("c");
313 m_strCmdlModem = args->getOption("m");
314 m_bQuitOnDisconnect = args->isSet("q");
315
316 if(!m_strCmdlAccount.isEmpty()) {
317 m_bCmdlAccount = true;
318 kDebug(5002) << "cmdl_account: " << m_bCmdlAccount;
319 }
320
321 if(!m_strCmdlModem.isEmpty()) {
322 m_bCmdlModem = true;
323 kDebug(5002) << "cmdl_modem: " << m_bCmdlModem;
324 }
325
326 if(m_bCmdlModem){
327 bool result = gpppdata.setModem(m_strCmdlModem);
328 if (!result){
329 QString string;
330 string = i18n("No such Modem:\n%1\nFalling back to default", m_strCmdlModem);
331 KMessageBox::error(this, string);
332 m_bCmdlModem = false;
333 }
334 }
335
336 if(m_bCmdlAccount){
337 bool result = gpppdata.setAccount(m_strCmdlAccount);
338 if (!result){
339 QString string;
340 string = i18n("No such Account:\n%1", m_strCmdlAccount);
341 KMessageBox::error(this, string);
342 m_bCmdlAccount = false;
343 show();
344 } else {
345 beginConnect();
346 }
347 } else
348 show();
349
350
351//#define KPPP_SHOW_NEWS
352#ifdef KPPP_SHOW_NEWS
353 // keep user informed about recent changes
354 if(!m_bCmdlAccount)
355 showNews();
356#endif
357 // this timer will delay the actual disconnection DISCONNECTION_DELAY ms
358 // to give applications time to shutdown, logout, whatever..
359 disconnectTimer = new QTimer(this);
360 connect(disconnectTimer, SIGNAL(timeout()), this, SLOT(delayedDisconnect()));
361}
362
363KPPPWidget::~KPPPWidget()
364{
365 delete stats;
366}
367
368bool KPPPWidget::eventFilter(QObject *o, QEvent *e) {
369 if(e->type() == QEvent::User) {
370 switch(((SignalEvent*)e)->sigType()) {
371 case SIGINT:
372 kDebug(5002) << "Received a SIGINT";
373 interruptConnection();
374 break;
375 case SIGCHLD:
376 sigChld();
377 break;
378 case SIGUSR1:
379 sigPPPDDied();
380 break;
381 }
382 return true;
383 }
384
385 if(o == connect_b) {
386 if(e->type() == QEvent::KeyPress) {
387 if(connect_b->hasFocus() && ((QKeyEvent *)e)->key() == Qt::Key_Return) {
388 beginConnect();
389 return true;
390 }
391 }
392 }
393
394 return false;
395}
396
397void KPPPWidget::prepareSetupDialog() {
398 if(tabWindow == 0) {
399 tabWindow = new KPageDialog( this );
400 tabWindow->setCaption( i18n("KPPP Configuration") );
401 tabWindow->setButtons( KDialog::Ok|KDialog::Cancel );
402 tabWindow->setDefaultButton( KDialog::Ok );
403 tabWindow->setFaceType( KPageDialog::Tabbed );
404 tabWindow->setModal( true );
405
406 KWindowSystem::setIcons(tabWindow->winId(), qApp->windowIcon().pixmap(IconSize(KIconLoader::Desktop),IconSize(KIconLoader::Desktop)), qApp->windowIcon().pixmap(IconSize(KIconLoader::Small),IconSize(KIconLoader::Small)));
407
408 // tabWindow->setFixedSize( 365, 375 );
409 QFrame *frame = new QFrame();
410 KPageWidgetItem *pageItem = new KPageWidgetItem( frame, i18n("&Accounts") );
411 pageItem->setHeader( i18n("Account Setup") );
412 tabWindow->addPage( pageItem );
413 accounts = new AccountWidget(frame);
414 connect(accounts, SIGNAL(resetaccounts()),
415 this, SLOT(resetaccounts()));
416 connect(accounts, SIGNAL(resetCosts(QString)),
417 this, SLOT(resetCosts(QString)));
418 connect(accounts, SIGNAL(resetVolume(QString)),
419 this, SLOT(resetVolume(QString)));
420
421
422 frame = new QFrame();
423 pageItem = new KPageWidgetItem( frame, i18n("&Modems") );
424 pageItem->setHeader( i18n("Modems Setup") );
425 tabWindow->addPage( pageItem );
426 modems = new ModemsWidget(frame);
427 connect(modems, SIGNAL(resetmodems()),
428 this, SLOT(resetmodems()));
429
430 frame = new QFrame();
431 pageItem = new KPageWidgetItem( frame, i18n("&Graph") );
432 pageItem->setHeader( i18n("Throughput Graph") );
433 tabWindow->addPage( pageItem );
434
435 graph = new GraphSetup( frame );
436
437 frame = new QFrame();
438 pageItem = new KPageWidgetItem( frame, i18n("M&isc") );
439 pageItem->setHeader( i18n("Miscellaneous Settings") );
440 tabWindow->addPage( pageItem );
441 general = new GeneralWidget( frame );
442 }
443}
444
445
446void KPPPWidget::enterPressedInID() {
447 PW_Edit->setFocus();
448}
449
450
451void KPPPWidget::enterPressedInPW() {
452 connect_b->setFocus();
453}
454
455// triggered by the session manager
456void KPPPWidget::saveMyself() {
457 gpppdata.save();
458}
459
460void KPPPWidget::shutDown() {
461 interruptConnection();
462 saveMyself();
463}
464
465void KPPPWidget::log_window_toggled(bool on) {
466 gpppdata.set_show_log_window(on);
467}
468
469
470void KPPPWidget::setup() {
471 prepareSetupDialog();
472
473 if(tabWindow->exec())
474 gpppdata.save();
475 else
476 gpppdata.cancel();
477}
478
479
480void KPPPWidget::resetaccounts() {
481 connectto_c->clear();
482
483 int count = gpppdata.accountCount();
484
485 // enable/disable controls
486 connectto_c->setEnabled(count > 0);
487 setButtons();
488
489 //load the accounts
490 for(int i=0; i < count; i++) {
491 gpppdata.setAccountByIndex(i);
492 connectto_c->addItem(gpppdata.accname());
493 }
494
495 //set the default account
496 if(!gpppdata.defaultAccount().isEmpty()) {
497 for(int i=0; i < count; i++)
498 if(gpppdata.defaultAccount() == connectto_c->itemText(i)) {
499 connectto_c->setCurrentIndex(i);
500 gpppdata.setAccountByIndex(i);
501
502 ID_Edit->setText(gpppdata.storedUsername());
503 PW_Edit->setText(gpppdata.storedPassword());
504 }
505 }
506 else
507 if(count > 0) {
508 gpppdata.setDefaultAccount(connectto_c->itemText(0));
509 gpppdata.save();
510 ID_Edit->setText(gpppdata.storedUsername());
511 PW_Edit->setText(gpppdata.storedPassword());
512 }
513
514 connect(ID_Edit, SIGNAL(textChanged(QString)),
515 this, SLOT(usernameChanged(QString)));
516
517 connect(PW_Edit, SIGNAL(textChanged(QString)),
518 this, SLOT(passwordChanged(QString)));
519
520 if (ID_Edit->text().isEmpty())
521 ID_Edit->setFocus();
522 else if (PW_Edit->text().isEmpty())
523 PW_Edit->setFocus();
524
525}
526
527void KPPPWidget::resetmodems() {
528 modem_c->clear();
529
530 int count = gpppdata.modemCount();
531
532 // enable/disable controls
533 modem_c->setEnabled(count > 0);
534 setButtons();
535
536 //load the modems
537 for(int i=0; i < count; i++) {
538 gpppdata.setModemByIndex(i);
539 modem_c->addItem(gpppdata.modname());
540 }
541
542 if (count > 1 && !m_bModemCShown) {
543 l1->addWidget(label7, 1, 1);
544 l1->addWidget(modem_c, 1, 2);
545 m_bModemCShown = true;
546 } else if (count <= 1 && m_bModemCShown){
547 l1->removeWidget(label7);
548 l1->removeWidget(modem_c);
549 m_bModemCShown = false;
550 }
551 label7->setVisible(m_bModemCShown);
552 modem_c->setVisible(m_bModemCShown);
553 layout()->invalidate();
554 setFixedSize(sizeHint());
555
556 //set the default modem
557 if(!gpppdata.defaultModem().isEmpty()) {
558 for(int i=0; i < count; i++)
559 if(gpppdata.defaultModem() == modem_c->itemText(i)) {
560 modem_c->setCurrentIndex(i);
561 gpppdata.setModemByIndex(i);
562
563 }
564 }
565 else
566 if(count > 0) {
567 gpppdata.setDefaultModem(modem_c->itemText(0));
568 gpppdata.save();
569 }
570}
571
572void KPPPWidget::setButtons()
573{
574 int acccount = gpppdata.accountCount();
575 int modcount = gpppdata.modemCount();
576
577 // enable/disable controls
578 connect_b->setEnabled(acccount > 0 && modcount > 0);
579 log->setEnabled(acccount > 0 && modcount > 0);
580 ID_Edit->setEnabled(acccount > 0 && modcount > 0);
581 PW_Edit->setEnabled(acccount > 0 && modcount > 0);
582
583}
584
585
586void KPPPWidget::interruptConnection() {
587 // interrupt dial up
588 if (con->isVisible())
589 emit con->cancelbutton();
590
591 // disconnect if online
592 if (gpppdata.pppdRunning())
593 emit disconnect(); /* FIXME: are we emitting a slot here!!!??? */
594}
595
596void KPPPWidget::sigPPPDDied() {
597 kDebug(5002) << "Received a SIGUSR1";
598
599 // if we are not connected pppdpid is -1 so have have to check for that
600 // in the followin line to make sure that we don't raise a false alarm
601 // such as would be the case when the log file viewer exits.
602 if(gpppdata.pppdRunning() || gpppdata.pppdError()) {
603 kDebug(5002) << "It was pppd that died";
604
605 // when we killpppd() on Cancel in ConnectWidget
606 // we set pppid to -1 so we won't
607 // enter this block
608
609 // just to be sure
610 Requester::rq->removeSecret(AUTH_PAP);
611 Requester::rq->removeSecret(AUTH_CHAP);
612
613 gpppdata.setpppdRunning(false);
614
615 // stop the disconnect timer (just in case)
616 disconnectTimer->stop();
617 // signal other applications that we are disconnected now
618 emit sig_disconnected();
619 kDebug(5002) << "Executing command on disconnect since pppd has died.";
620 QApplication::flush();
621 execute_command(gpppdata.command_on_disconnect());
622
623 stopAccounting();
624
625 con_win->stopClock();
626 DockWidget::dock_widget->stop_stats();
627 DockWidget::dock_widget->hide();
628
629 if(!gpppdata.pppdError())
630 gpppdata.setpppdError(E_PPPD_DIED);
631 removedns();
632 Modem::modem->unlockdevice();
633 con->pppdDied();
634
635 Requester::rq->pppdExitStatus();
636 gpppdata.setWaitCallback(gpppdata.callbackType() && Requester::rq->lastStatus == E_CBCP_WAIT);
637
638 if(!gpppdata.automatic_redial() && !gpppdata.waitCallback()) {
639 quit_b->setFocus();
640 show();
641 con_win->stopClock();
642 stopAccounting();
643 con_win->hide();
644 con->hide();
645
646 gpppdata.setpppdRunning(false);
647 // // not in a signal handler !!! KNotifyClient::beep();
648 QString msg;
649 if (gpppdata.pppdError() == E_IF_TIMEOUT)
650 msg = i18n("Timeout expired while waiting for the PPP interface "
651 "to come up.");
652 else {
653 msg = i18n("<p>The pppd daemon died unexpectedly!</p>");
654 Requester::rq->pppdExitStatus();
655 if (Requester::rq->lastStatus != 99) { // more recent pppds only
656 msg += i18n("<p>Exit status: %1", Requester::rq->lastStatus);
657 msg += i18n("</p><p>See 'man pppd' for an explanation of the error "
658 "codes or take a look at the kppp FAQ on "
659 " <a href=\"%1\">%1</a></p>",
660 QString("http://developer.kde.org/~kppp/index.html"));
661 }
662 }
663
664 if(KMessageBox::warningYesNo(0, msg, i18n("Error"), KStandardGuiItem::ok(), KGuiItem(i18n("&Details"))) == KMessageBox::No)
665 PPPL_ShowLog();
666 } else { /* reconnect on disconnect */
667 if(gpppdata.waitCallback())
668 kDebug(5002) << "Waiting for callback... ";
669 else
670 kDebug(5002) << "Trying to reconnect... ";
671
672 if(gpppdata.authMethod() == AUTH_PAP ||
673 gpppdata.authMethod() == AUTH_CHAP ||
674 gpppdata.authMethod() == AUTH_PAPCHAP)
675 Requester::rq->setSecret(gpppdata.authMethod(),
676 encodeWord(gpppdata.storedUsername()),
677 encodeWord(gpppdata.password()));
678
679 con_win->hide();
680 con_win->stopClock();
681 stopAccounting();
682 gpppdata.setpppdRunning(false);
683 // not in a signal handler !!! KNotifyClient::beep();
684 emit cmdl_start();
685 }
686 }
687 gpppdata.setpppdError(0);
688}
689
690
691void KPPPWidget::sigChld() {
692 kDebug(5002) << "sigchld()";
693 // pid_t id = wait(0L);
694 // if(id == helperPid && helperPid != -1) {
695 // kDebug(5002) << "It was the setuid child that died";
696 // helperPid = -1;
697 QString msg = i18n("kppp's helper process just died.\n"
698 "Since further execution would be pointless, "
699 "kppp will shut down now.");
700 KMessageBox::error(0L, msg);
701 remove_pidfile();
702 exit(1);
703 // }
704}
705
706
707void KPPPWidget::newdefaultaccount(int i) {
708 gpppdata.setDefaultAccount(connectto_c->itemText(i));
709 gpppdata.save();
710 ID_Edit->setText(gpppdata.storedUsername());
711 PW_Edit->setText(gpppdata.storedPassword());
712}
713
714void KPPPWidget::newdefaultmodem(int i) {
715 gpppdata.setDefaultModem(modem_c->itemText(i));
716 gpppdata.save();
717}
718
719
720
721void KPPPWidget::expandbutton() {
722 setup();
723}
724
725
726void KPPPWidget::beginConnect() {
727 // make sure to connect to the account that is selected in the combo box
728 // (exeption: an account given by a command line argument)
729 if(!m_bCmdlAccount) {
730 gpppdata.setAccount(connectto_c->currentText());
731 gpppdata.setPassword(PW_Edit->text());
732 } else {
733 gpppdata.setPassword(gpppdata.storedPassword());
734 }
735
736 QFileInfo info(pppdPath());
737
738 if(!info.exists()){
739 KMessageBox::error(this, i18n("Cannot find the PPP daemon!\n"
740 "Make sure that pppd is installed and "
741 "that you have entered the correct path."));
742 return;
743 }
744#if 0
745 if(!info.isExecutable()){
746
747 QString string;
748 string = i18n("kppp cannot execute:\n %1\n"
749 "Please make sure that you have given kppp "
750 "setuid permission and that "
751 "pppd is executable.", gpppdata.pppdPath());
752 KMessageBox::error(this, string);
753 return;
754
755 }
756#endif
757
758 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
759 QString device = "";
760 if (args->isSet("dev"))
761 device = args->getOption("dev");
762 else
763 device = gpppdata.modemDevice();
764
765 QFileInfo info2(device);
766
767 if(!info2.exists()){
768 QString string;
769 string = i18n("kppp can not find:\n %1\nPlease make sure you have setup "
770 "your modem device properly "
771 "and/or adjust the location of the modem device on "
772 "the modem tab of "
773 "the setup dialog.", device);
774 KMessageBox::error(this, string);
775 return;
776 }
777
778 // if this is a PAP or CHAP account, ensure that username is
779 // supplied
780 if(gpppdata.authMethod() == AUTH_PAP ||
781 gpppdata.authMethod() == AUTH_CHAP ||
782 gpppdata.authMethod() == AUTH_PAPCHAP ) {
783 if(ID_Edit->text().isEmpty()) {
784 KMessageBox::error(this,
785 i18n(
786 "You have selected the authentication "
787 "method PAP or CHAP. This requires that you "
788 "supply a username and a password."));
789 return;
790 } else {
791 if(!Requester::rq->setSecret(gpppdata.authMethod(),
792 encodeWord(gpppdata.storedUsername()),
793 encodeWord(gpppdata.password()))) {
794 QString s;
795 s = i18n("Cannot create PAP/CHAP authentication\n"
796 "file \"%1\"", QString(PAP_AUTH_FILE));
797 KMessageBox::error(this, s);
798 return;
799 }
800 }
801 }
802
803 if (gpppdata.phonenumber().isEmpty()) {
804 QString s = i18n("You must specify a telephone number.");
805 KMessageBox::error(this, s);
806 return;
807 }
808
809 hide();
810
811 QString tit = i18n("Connecting to: %1", gpppdata.accname());
812 con->setWindowTitle(tit);
813 con->enableButtons();
814 con->show();
815
816 bool show_debug = gpppdata.get_show_log_window();
817 con->debug->setChecked(show_debug); // toggle button
818 debugwindow->clear();
819 if (!show_debug)
820 debugwindow->hide();
821 else {
822 debugwindow->show();
823 con->raise();
824 }
825
826 emit begin_connect();
827}
828
829void KPPPWidget::disconnect() {
830 if (disconnectTimer->isActive()) return; // you had already pressed disconnect before
831
832 // signal other applications that we are about to go offline now
833 emit sig_aboutToDisconnect();
834
835 con_win->hide();
836 con->show();
837 con->disableButtons(); // will reenable them later in delayedDisconnect()
838 con->setWindowTitle(i18n("Disconnecting..."));
839
840 if (!gpppdata.command_before_disconnect().isEmpty()) {
841 con->setMsg(i18n("Executing command before disconnection."));
842
843 qApp->processEvents();
844 QApplication::flush();
845 pid_t id = execute_command(gpppdata.command_before_disconnect());
846 int i, status;
847
848 do {
849 qApp->processEvents();
850 i = waitpid(id, &status, WNOHANG);
851 usleep(500000);
852 } while (i == 0 && errno == 0);
853 }
854
855 con->setMsg(i18n("Announcing disconnection."));
856
857 // this is no longer necessary since I'm delaying disconnection usign a QTimer
858 // qApp->processEvents();
859
860 // set the timer to call delayedDisconnect() in DISCONNECT_DELAY ms
861 disconnectTimer->setSingleShot(true);
862 disconnectTimer->start(DISCONNECT_DELAY);
863}
864
865void KPPPWidget::delayedDisconnect() {
866 // this is where the actual disconnection takes place
867 con->hide();
868
869 statdlg->stop_stats();
870 Requester::rq->killPPPDaemon();
871
872 // signal other applications that we are disconnected now
873 emit sig_disconnected();
874 QApplication::flush();
875 execute_command(gpppdata.command_on_disconnect());
876
877 Requester::rq->removeSecret(AUTH_PAP);
878 Requester::rq->removeSecret(AUTH_CHAP);
879
880 removedns();
881 Modem::modem->unlockdevice();
882
883 con_win->stopClock();
884 p_kppp->stopAccounting();
885 con_win->hide();
886
887 DockWidget::dock_widget->stop_stats();
888 DockWidget::dock_widget->hide();
889
890 if(m_bQuitOnDisconnect)
891 kapp->exit(0);
892 else {
893 quit_b->setFocus();
894 show();
895 }
896}
897
898
899void KPPPWidget::helpbutton() {
900 KToolInvocation::invokeHelp();
901}
902
903
904void KPPPWidget::quitbutton() {
905 if(gpppdata.pppdRunning()) {
906 int ok = KMessageBox::warningContinueCancel(this,
907 i18n("Exiting kPPP will close your PPP Session."),
908 i18n("Quit kPPP?"), KStandardGuiItem::quit());
909 if(ok == KMessageBox::Continue) {
910 Requester::rq->killPPPDaemon();
911
912 // stop the disconnect delay timer
913 disconnectTimer->stop();
914
915 // signal other applications that we are disconnected now
916 emit sig_disconnected();
917 QApplication::flush();
918 execute_command(gpppdata.command_on_disconnect());
919 removedns();
920 Modem::modem->unlockdevice();
921 }
922 } else {
923 if (!gpppdata.accname().isEmpty() && !gpppdata.storePassword())
924 gpppdata.setStoredPassword("");
925 }
926 gpppdata.save();
927 qApp->quit();
928}
929
930
931void KPPPWidget::rulesetLoadError() {
932 KMessageBox::error(this, ruleset_load_errmsg);
933}
934
935
936void KPPPWidget::startAccounting() {
937 // volume accounting
938 stats->totalbytes = 0;
939
940 kDebug(5002) << "AcctEnabled: " << gpppdata.AcctEnabled();
941
942 // load the ruleset
943 if(!gpppdata.AcctEnabled())
944 return;
945
946 QString d = AccountingBase::getAccountingFile(gpppdata.accountingFile());
947 // if(::access(d.data(), X_OK) != 0)
948 acct = new Accounting(this, stats);
949 // else
950 // acct = new ExecutableAccounting(this);
951
952 // connect to the accounting object
953 connect(acct, SIGNAL(changed(QString,QString)),
954 con_win, SLOT(slotAccounting(QString,QString)));
955
956 if(!acct->loadRuleSet(gpppdata.accountingFile())) {
957 QString s= i18n("Can not load the accounting "
958 "ruleset \"%1\".", gpppdata.accountingFile());
959
960 // starting the messagebox with a timer will prevent us
961 // from blocking the calling function ConnectWidget::timerEvent
962 ruleset_load_errmsg = s;
963 QTimer::singleShot(0, this, SLOT(rulesetLoadError()));
964 return;
965 } else
966 acct->slotStart();
967}
968
969void KPPPWidget::stopAccounting() {
970 // store volume accounting
971 if(stats->totalbytes != 0)
972 gpppdata.setTotalBytes(stats->totalbytes);
973
974 if(!gpppdata.AcctEnabled())
975 return;
976
977 if(acct != 0) {
978 acct->slotStop();
979 delete acct;
980 acct = 0;
981 }
982}
983
984
985void KPPPWidget::showStats() {
986 if(statdlg) {
987 statdlg->toCurrentDesktop();
988 statdlg->show();
989 statdlg->raise();
990 }
991}
992
993
994void KPPPWidget::usernameChanged(const QString &) {
995 // store username for later use
996 gpppdata.setStoredUsername(ID_Edit->text());
997}
998
999
1000void KPPPWidget::passwordChanged(const QString &) {
1001 // store the password if so requested
1002 if(gpppdata.storePassword())
1003 gpppdata.setStoredPassword(PW_Edit->text());
1004 else
1005 gpppdata.setStoredPassword("");
1006}
1007
1008
1009void KPPPWidget::setPW_Edit(const QString &pw) {
1010 PW_Edit->setText(pw);
1011}
1012
1013
1014void KPPPWidget::resetCosts(const QString &s) {
1015 AccountingBase::resetCosts(s);
1016}
1017
1018
1019void KPPPWidget::resetVolume(const QString &s) {
1020 AccountingBase::resetVolume(s);
1021}
1022
1023/**
1024 * pppd's getword() function knows about escape characters.
1025 * If we write the username and password to the secrets file
1026 * we'll therefore have to escape back slashes.
1027 */
1028QString KPPPWidget::encodeWord(const QString &s) {
1029 QString r = s;
1030 r.replace(QRegExp("\\"), "\\\\");
1031 return r;
1032}
1033
1034void KPPPWidget::setQuitOnDisconnect (bool b)
1035{
1036 m_bQuitOnDisconnect = b;
1037}
1038
1039void KPPPWidget::showNews() {
1040#ifdef KPPP_SHOW_NEWS
1041 /*
1042 * Introduce the QuickHelp feature to new users of this version
1043 */
1044 #define QUICKHELP_HINT "Hint_QuickHelp"
1045 if(gpppdata.readNumConfig(GENERAL_GRP, QUICKHELP_HINT, 0) == 0) {
1046 KDialog dlg();
1047 dlg.setCaption(i18n("Recent Changes in KPPP"));
1048
1049 QVBoxLayout *tl = new QVBoxLayout(&dlg);
1050 tl->setSpacing(10);
1051 tl->setMargin(10);
1052 QHBoxLayout *l1 = new QHBoxLayout(10);
1053 QVBoxLayout *l2 = new QVBoxLayout(10);
1054 tl->addLayout(l1);
1055
1056 QLabel *icon = new QLabel(&dlg);
1057 icon->setPixmap(BarIcon("exclamation"));
1058 icon->setFixedSize(icon->sizeHint());
1059 l1->addWidget(icon);
1060 l1->addLayout(l2);
1061
1062 QLabel *l = new QLabel(i18n("From version 1.4.8 on, kppp has a new feature\n"
1063 "called \"Quickhelp\". It is similar to a tooltip,\n"
1064 "but you can activate it whenever you want.\n"
1065 "\n"
1066 "To activate it, simply click on a control (like\n"
1067 "a button or a label) with the right mouse button.\n"
1068 "If the item supports Quickhelp, a popup menu\n"
1069 "will appear leading to Quickhelp.\n"
1070 "\n"
1071 "To test it, right-click somewhere in this text."),
1072 &dlg);
1073
1074 QCheckBox *cb = new QCheckBox(i18n("Do not show this hint again"), &dlg);
1075 cb->setFixedSize(cb->sizeHint());
1076
1077 dlg.setButtons(Ok)
1078
1079 l2->addWidget(l);
1080 l2->addWidget(cb);
1081
1082 QString tmp = i18n("This is an example of <b>QuickHelp</b>.\n"
1083 "This window will stay open until you\n"
1084 "click a mouse button or a press a key.\n");
1085
1086 cb->setWhatsThis(tmp);
1087 l->setWhatsThis( tmp);
1088
1089 dlg.exec();
1090 if(cb->isChecked()) {
1091 gpppdata.writeConfig(GENERAL_GRP, QUICKHELP_HINT, 1);
1092 gpppdata.save();
1093 }
1094 }
1095#endif
1096}
1097
1098
1099#include "kpppwidget.moc"
1100
1101