diff options
Diffstat (limited to 'kppp/kpppwidget.cpp')
-rw-r--r-- | kppp/kpppwidget.cpp | 1073 |
1 files changed, 1073 insertions, 0 deletions
diff --git a/kppp/kpppwidget.cpp b/kppp/kpppwidget.cpp new file mode 100644 index 00000000..9e635815 --- /dev/null +++ b/kppp/kpppwidget.cpp @@ -0,0 +1,1073 @@ +/* + * kPPP: A pppd front end for the KDE project + * + * + * Copyright (C) 1997 Bernd Johannes Wuebben + * wuebben@math.cornell.edu + * + * Copyright (C) 1998-2002 Harri Porten <porten@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "kpppwidget.h" + +#include <qapplication.h> +#include <qcombobox.h> +#include <qdir.h> +#include <qevent.h> +#include <qdialog.h> +#include <qlabel.h> +#include <qpushbutton.h> +#include <qregexp.h> +#include <kdialogbase.h> +#include <qwhatsthis.h> + +#include <kaboutdata.h> +#include <kapplication.h> +#include <kbuttonbox.h> +#include <kglobalsettings.h> +#include <kcmdlineargs.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kiconloader.h> // For BarIcon +#include <klocale.h> +#include <kmessagebox.h> +#include <kseparator.h> +#include <kstandarddirs.h> +#include <kwin.h> +#include <khelpmenu.h> +#include <kpushbutton.h> +#include <kguiitem.h> +#include <kstdguiitem.h> + +#include <stdlib.h> +#include <errno.h> + +#include "runtests.h" + +#include "main.h" +#include "auth.h" +#include "modem.h" +#include "ppplog.h" +#include "opener.h" +#include "requester.h" +#include "pppstats.h" +#include "pppdata.h" +#include "general.h" +#include "modems.h" + +// delay disconnection for a second +#define DISCONNECT_DELAY 1000 + +extern KPPPWidget *p_kppp; + +KPPPWidget::KPPPWidget( QWidget *parent, const char *name ) + : DCOPObject( "KpppIface" ), QWidget(parent, name) + , acct(0) + , m_bCmdlAccount (false) + , m_bCmdlModem (false) +{ + tabWindow = 0; + + // before doing anything else, run a few tests + + int result = runTests(); + if(result == TEST_CRITICAL) + exit(4); + + installEventFilter(this); + + QVBoxLayout *tl = new QVBoxLayout(this, 10, 10); + + l1 = new QGridLayout(4, 4); + tl->addLayout(l1); + l1->addColSpacing(0, 10); + l1->addColSpacing(3, 10); + l1->setColStretch(1, 3); + l1->setColStretch(2, 4); + + label1 = new QLabel(i18n("C&onnect to: "), this); + l1->addWidget(label1, 0, 1); + + connectto_c = new QComboBox(false, this); + label1->setBuddy(connectto_c); + + connect(connectto_c, SIGNAL(activated(int)), + SLOT(newdefaultaccount(int))); + l1->addWidget(connectto_c, 0, 2); + + label7 = new QLabel(i18n("Use &modem: "), this); + // l1->addWidget(label7, 1, 1); (done in resetmodems()) + modem_c = new QComboBox(false, this); + label7->setBuddy(connectto_c); + m_bModemCShown = false; + + connect(modem_c, SIGNAL(activated(int)), + SLOT(newdefaultmodem(int))); + // l1->addWidget(modem_c, 1, 2); (done in resetmodems()) + + ID_Label = new QLabel(i18n("&Login ID:"), this); + l1->addWidget(ID_Label, 2, 1); + + // the entry line for usernames + ID_Edit = new QLineEdit(this); + ID_Label->setBuddy(ID_Edit); + l1->addWidget(ID_Edit, 2, 2); + connect(ID_Edit, SIGNAL(returnPressed()), + this, SLOT(enterPressedInID())); + QString tmp = i18n("<p>Type in the username that you got from your\n" + "ISP. This is especially important for PAP\n" + "and CHAP. You may omit this when you use\n" + "terminal-based or script-based authentication.\n" + "\n" + "<b>Important</b>: case is important here:\n" + "<i>myusername</i> is not the same as <i>MyUserName</i>."); + + QWhatsThis::add(ID_Label,tmp); + QWhatsThis::add(ID_Edit,tmp); + + PW_Label = new QLabel(i18n("&Password:"), this); + l1->addWidget(PW_Label, 3, 1); + + PW_Edit= new QLineEdit(this); + PW_Label->setBuddy(PW_Edit); + PW_Edit->setEchoMode(QLineEdit::Password); + l1->addWidget(PW_Edit, 3, 2); + connect(PW_Edit, SIGNAL(returnPressed()), + this, SLOT(enterPressedInPW())); + + tmp = i18n("<p>Type in the password that you got from your\n" + "ISP. This is especially important for PAP\n" + "and CHAP. You may omit this when you use\n" + "terminal-based or script-based authentication.\n" + "\n" + "<b>Important</b>: case is important here:\n" + "<i>mypassword</i> is not the same as <i>MyPassword</i>."); + + QWhatsThis::add(PW_Label,tmp); + QWhatsThis::add(PW_Edit,tmp); + + QHBoxLayout *l3 = new QHBoxLayout; + tl->addSpacing(5); + tl->addLayout(l3); + tl->addSpacing(5); + l3->addSpacing(10); + log = new QCheckBox(i18n("Show lo&g window"), this); + connect(log, SIGNAL(toggled(bool)), + this, SLOT(log_window_toggled(bool))); + log->setChecked(gpppdata.get_show_log_window()); + l3->addWidget(log); + + QWhatsThis::add(log, + i18n("<p>This controls whether a log window is shown.\n" + "A log window shows the communication between\n" + "<i>kppp</i> and your modem. This will help you\n" + "in tracking down problems.\n" + "\n" + "Turn it off if <i>kppp</i> routinely connects without\n" + "problems")); + + fline = new KSeparator( KSeparator::HLine, this); + tl->addWidget(fline); + + QHBoxLayout *l2 = new QHBoxLayout; + tl->addLayout(l2); + + int minw = 0; + quit_b = new KPushButton(KStdGuiItem::quit(), this); + connect( quit_b, SIGNAL(clicked()), SLOT(quitbutton())); + if(quit_b->sizeHint().width() > minw) + minw = quit_b->sizeHint().width(); + + setup_b = new KPushButton(KGuiItem(i18n("Co&nfigure..."), "configure"), this); + connect( setup_b, SIGNAL(clicked()), SLOT(expandbutton())); + if(setup_b->sizeHint().width() > minw) + minw = setup_b->sizeHint().width(); + + if(gpppdata.access() != KConfig::ReadWrite) + setup_b->setEnabled(false); + + help_b = new KPushButton(KStdGuiItem::help(), this); + connect( help_b, SIGNAL(clicked()), SLOT(helpbutton())); + + KHelpMenu *helpMenu = new KHelpMenu(this, KGlobal::instance()->aboutData(), true); + help_b->setPopup((QPopupMenu*)helpMenu->menu()); + + if(help_b->sizeHint().width() > minw) + minw = help_b->sizeHint().width(); + + connect_b = new QPushButton(i18n("&Connect"), this); + connect_b->setDefault(true); + connect_b->setFocus(); + connect(connect_b, SIGNAL(clicked()), SLOT(beginConnect())); + if(connect_b->sizeHint().width() > minw) + minw = connect_b->sizeHint().width(); + + quit_b->setFixedWidth(minw); + setup_b->setFixedWidth(minw); + help_b->setFixedWidth(help_b->sizeHint().width()); + connect_b->setFixedWidth(minw); + + l2->addWidget(quit_b); + l2->addWidget(setup_b); + l2->addWidget(help_b); + l2->addSpacing(20); + l2->addWidget(connect_b); + + setFixedSize(sizeHint()); + + (void)new Modem; + + // we also connect cmld_start to the beginConnect so that I can run + // the dialer through a command line argument + connect(this,SIGNAL(cmdl_start()),this,SLOT(beginConnect())); + + stats = new PPPStats; + + KWin::setIcons(winId(), kapp->icon(), kapp->miniIcon()); + + // constructor of con_win reads position from config file + con_win = new ConWindow(0, "conw", this, stats); + KWin::setIcons(con_win->winId(), kapp->icon(), kapp->miniIcon()); + + statdlg = new PPPStatsDlg(0, "stats", this, stats); + statdlg->hide(); + + debugwindow = new DebugWidget(0,"debugwindow"); + KWin::setIcons(debugwindow->winId(), kapp->icon(), kapp->miniIcon()); + debugwindow->hide(); + + // load up the accounts combo box + + resetaccounts(); + resetmodems(); + con = new ConnectWidget(0, "con", stats); + KWin::setIcons(con->winId(), kapp->icon(), kapp->miniIcon() ); + connect(this, SIGNAL(begin_connect()),con, SLOT(preinit())); + + QRect desk = KGlobalSettings::desktopGeometry(topLevelWidget()); + con->setGeometry(desk.center().x()-175, desk.center().y()-55, 350,110); + + // connect the ConnectWidgets various signals + connect(con, SIGNAL(closeDebugWindow()), + debugwindow, SLOT(hide())); + connect(con, SIGNAL(debugMessage(const QString &)), + debugwindow, SLOT(statusLabel(const QString &))); + connect(con, SIGNAL(toggleDebugWindow()), + debugwindow, SLOT(toggleVisibility())); + connect(con, SIGNAL(debugPutChar(unsigned char)), + debugwindow, SLOT(addChar(unsigned char))); + connect(con, SIGNAL(startAccounting()), + this, SLOT(startAccounting())); + connect(con, SIGNAL(stopAccounting()), + this, SLOT(stopAccounting())); + connect(KApplication::kApplication(), SIGNAL(saveYourself()), + this, SLOT(saveMyself())); + connect(KApplication::kApplication(), SIGNAL(shutDown()), + this, SLOT(shutDown())); + + debugwindow->setGeometry(desk.center().x()+190, desk.center().y()-55, + debugwindow->width(),debugwindow->height()); + + move(desk.center().x()-width()/2, desk.center().y()-height()/2); + + + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + m_strCmdlAccount = args->getOption("c"); + m_strCmdlModem = args->getOption("m"); + m_bQuitOnDisconnect = args->isSet("q"); + + if(!m_strCmdlAccount.isEmpty()) { + m_bCmdlAccount = true; + kdDebug(5002) << "cmdl_account: " << m_bCmdlAccount << endl; + } + + if(!m_strCmdlModem.isEmpty()) { + m_bCmdlModem = true; + kdDebug(5002) << "cmdl_modem: " << m_bCmdlModem << endl; + } + + if(m_bCmdlModem){ + bool result = gpppdata.setModem(m_strCmdlModem); + if (!result){ + QString string; + string = i18n("No such Modem:\n%1\nFalling back to default").arg(m_strCmdlModem); + KMessageBox::error(this, string); + m_bCmdlModem = false; + } + } + + if(m_bCmdlAccount){ + bool result = gpppdata.setAccount(m_strCmdlAccount); + if (!result){ + QString string; + string = i18n("No such Account:\n%1").arg(m_strCmdlAccount); + KMessageBox::error(this, string); + m_bCmdlAccount = false; + show(); + } else { + beginConnect(); + } + } else + show(); + + +//#define KPPP_SHOW_NEWS +#ifdef KPPP_SHOW_NEWS + // keep user informed about recent changes + if(!m_bCmdlAccount) + showNews(); +#endif + + // attach to the DCOP server, if possible + if (!kapp->dcopClient()->attach()) + kdDebug(5002) << "Error: Could not connect to the DCOP server" << endl; + else + kapp->dcopClient()->registerAs(kapp->name(), true); + + // this timer will delay the actual disconnection DISCONNECTION_DELAY ms + // to give applications time to shutdown, logout, whatever.. + disconnectTimer = new QTimer(this); + connect(disconnectTimer, SIGNAL(timeout()), this, SLOT(delayedDisconnect())); +} + +KPPPWidget::~KPPPWidget() +{ + delete stats; +} + +bool KPPPWidget::eventFilter(QObject *o, QEvent *e) { + if(e->type() == QEvent::User) { + switch(((SignalEvent*)e)->sigType()) { + case SIGINT: + kdDebug(5002) << "Received a SIGINT" << endl; + interruptConnection(); + break; + case SIGCHLD: + sigChld(); + break; + case SIGUSR1: + sigPPPDDied(); + break; + } + return true; + } + + if(o == connect_b) { + if(e->type() == QEvent::KeyPress) { + if(connect_b->hasFocus() && ((QKeyEvent *)e)->key() == Qt::Key_Return) { + beginConnect(); + return true; + } + } + } + + return false; +} + +void KPPPWidget::prepareSetupDialog() { + if(tabWindow == 0) { + tabWindow = new KDialogBase( KDialogBase::Tabbed, i18n("KPPP Configuration"), + KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, + kapp->mainWidget(), 0, true); + + + KWin::setIcons(tabWindow->winId(), kapp->icon(), kapp->miniIcon()); + + // tabWindow->setFixedSize( 365, 375 ); + + accounts = new AccountWidget(tabWindow->addPage( i18n("&Accounts"), i18n("Account Setup") ) ); + connect(accounts, SIGNAL(resetaccounts()), + this, SLOT(resetaccounts())); + connect(accounts, SIGNAL(resetCosts(const QString &)), + this, SLOT(resetCosts(const QString &))); + connect(accounts, SIGNAL(resetVolume(const QString &)), + this, SLOT(resetVolume(const QString &))); + + modems = new ModemsWidget(tabWindow->addPage( i18n("&Modems"), i18n("Modems Setup") ) ); + connect(modems, SIGNAL(resetmodems()), + this, SLOT(resetmodems())); + + graph = new GraphSetup( tabWindow->addPage( i18n("&Graph"), i18n("Throughput Graph" ) ) ); + general = new GeneralWidget( tabWindow->addPage( i18n("M&isc"), i18n("Miscellaneous Settings") ) ); + } +} + + +void KPPPWidget::enterPressedInID() { + PW_Edit->setFocus(); +} + + +void KPPPWidget::enterPressedInPW() { + connect_b->setFocus(); +} + +// triggered by the session manager +void KPPPWidget::saveMyself() { + gpppdata.save(); +} + +void KPPPWidget::shutDown() { + interruptConnection(); + saveMyself(); +} + +void KPPPWidget::log_window_toggled(bool on) { + gpppdata.set_show_log_window(on); +} + + +void KPPPWidget::setup() { + prepareSetupDialog(); + + if(tabWindow->exec()) + gpppdata.save(); + else + gpppdata.cancel(); +} + + +void KPPPWidget::resetaccounts() { + connectto_c->clear(); + + int count = gpppdata.accountCount(); + + // enable/disable controls + connectto_c->setEnabled(count > 0); + setButtons(); + + //load the accounts + for(int i=0; i < count; i++) { + gpppdata.setAccountByIndex(i); + connectto_c->insertItem(gpppdata.accname()); + } + + //set the default account + if(!gpppdata.defaultAccount().isEmpty()) { + for(int i=0; i < count; i++) + if(gpppdata.defaultAccount() == connectto_c->text(i)) { + connectto_c->setCurrentItem(i); + gpppdata.setAccountByIndex(i); + + ID_Edit->setText(gpppdata.storedUsername()); + PW_Edit->setText(gpppdata.storedPassword()); + } + } + else + if(count > 0) { + gpppdata.setDefaultAccount(connectto_c->text(0)); + gpppdata.save(); + ID_Edit->setText(gpppdata.storedUsername()); + PW_Edit->setText(gpppdata.storedPassword()); + } + + connect(ID_Edit, SIGNAL(textChanged(const QString &)), + this, SLOT(usernameChanged(const QString &))); + + connect(PW_Edit, SIGNAL(textChanged(const QString &)), + this, SLOT(passwordChanged(const QString &))); + + if (ID_Edit->text().isEmpty()) + ID_Edit->setFocus(); + else if (PW_Edit->text().isEmpty()) + PW_Edit->setFocus(); + +} + +void KPPPWidget::resetmodems() { + modem_c->clear(); + + int count = gpppdata.modemCount(); + + // enable/disable controls + modem_c->setEnabled(count > 0); + setButtons(); + + //load the modems + for(int i=0; i < count; i++) { + gpppdata.setModemByIndex(i); + modem_c->insertItem(gpppdata.modname()); + } + + if (count > 1 && !m_bModemCShown) { + l1->addWidget(label7, 1, 1); + l1->addWidget(modem_c, 1, 2); + m_bModemCShown = true; + } else if (count <= 1 && m_bModemCShown){ + l1->remove(label7); + l1->remove(modem_c); + m_bModemCShown = false; + } + label7->setShown(m_bModemCShown); + modem_c->setShown(m_bModemCShown); + layout()->invalidate(); + setFixedSize(sizeHint()); + + //set the default modem + if(!gpppdata.defaultModem().isEmpty()) { + for(int i=0; i < count; i++) + if(gpppdata.defaultModem() == modem_c->text(i)) { + modem_c->setCurrentItem(i); + gpppdata.setModemByIndex(i); + + } + } + else + if(count > 0) { + gpppdata.setDefaultModem(modem_c->text(0)); + gpppdata.save(); + } +} + +void KPPPWidget::setButtons() +{ + int acccount = gpppdata.accountCount(); + int modcount = gpppdata.modemCount(); + + // enable/disable controls + connect_b->setEnabled(acccount > 0 && modcount > 0); + log->setEnabled(acccount > 0 && modcount > 0); + ID_Edit->setEnabled(acccount > 0 && modcount > 0); + PW_Edit->setEnabled(acccount > 0 && modcount > 0); + +} + + +void KPPPWidget::interruptConnection() { + // interrupt dial up + if (con->isVisible()) + emit con->cancelbutton(); + + // disconnect if online + if (gpppdata.pppdRunning()) + emit disconnect(); /* FIXME: are we emitting a slot here!!!??? */ +} + +void KPPPWidget::sigPPPDDied() { + kdDebug(5002) << "Received a SIGUSR1" << endl; + + // if we are not connected pppdpid is -1 so have have to check for that + // in the followin line to make sure that we don't raise a false alarm + // such as would be the case when the log file viewer exits. + if(gpppdata.pppdRunning() || gpppdata.pppdError()) { + kdDebug(5002) << "It was pppd that died" << endl; + + // when we killpppd() on Cancel in ConnectWidget + // we set pppid to -1 so we won't + // enter this block + + // just to be sure + Requester::rq->removeSecret(AUTH_PAP); + Requester::rq->removeSecret(AUTH_CHAP); + + gpppdata.setpppdRunning(false); + + // stop the disconnect timer (just in case) + disconnectTimer->stop(); + // signal other applications that we are disconnected now + kapp->dcopClient()->emitDCOPSignal("KpppIface", "disconnected()", QByteArray()); + + kdDebug(5002) << "Executing command on disconnect since pppd has died." << endl; + QApplication::flushX(); + execute_command(gpppdata.command_on_disconnect()); + + stopAccounting(); + + con_win->stopClock(); + DockWidget::dock_widget->stop_stats(); + DockWidget::dock_widget->hide(); + + if(!gpppdata.pppdError()) + gpppdata.setpppdError(E_PPPD_DIED); + removedns(); + Modem::modem->unlockdevice(); + con->pppdDied(); + + Requester::rq->pppdExitStatus(); + gpppdata.setWaitCallback(gpppdata.callbackType() && Requester::rq->lastStatus == E_CBCP_WAIT); + + if(!gpppdata.automatic_redial() && !gpppdata.waitCallback()) { + quit_b->setFocus(); + show(); + con_win->stopClock(); + stopAccounting(); + con_win->hide(); + con->hide(); + + gpppdata.setpppdRunning(false); + // // not in a signal handler !!! KNotifyClient::beep(); + QString msg; + if (gpppdata.pppdError() == E_IF_TIMEOUT) + msg = i18n("Timeout expired while waiting for the PPP interface " + "to come up."); + else { + msg = i18n("<p>The pppd daemon died unexpectedly!</p>"); + Requester::rq->pppdExitStatus(); + if (Requester::rq->lastStatus != 99) { // more recent pppds only + msg += i18n("<p>Exit status: %1").arg(Requester::rq->lastStatus); + msg += i18n("</p><p>See 'man pppd' for an explanation of the error " + "codes or take a look at the kppp FAQ on " + " <a href=\"%1\">%2</a></p>") + .arg("http://developer.kde.org/~kppp/index.html") + .arg("http://developer.kde.org/~kppp/index.html"); + } + } + + if(KMessageBox::warningYesNo(0, msg, i18n("Error"), KStdGuiItem::ok(), i18n("&Details")) == KMessageBox::No) + PPPL_ShowLog(); + } else { /* reconnect on disconnect */ + if(gpppdata.waitCallback()) + kdDebug(5002) << "Waiting for callback... " << endl; + else + kdDebug(5002) << "Trying to reconnect... " << endl; + + if(gpppdata.authMethod() == AUTH_PAP || + gpppdata.authMethod() == AUTH_CHAP || + gpppdata.authMethod() == AUTH_PAPCHAP) + Requester::rq->setSecret(gpppdata.authMethod(), + encodeWord(gpppdata.storedUsername()), + encodeWord(gpppdata.password())); + + con_win->hide(); + con_win->stopClock(); + stopAccounting(); + gpppdata.setpppdRunning(false); + // not in a signal handler !!! KNotifyClient::beep(); + emit cmdl_start(); + } + } + gpppdata.setpppdError(0); +} + + +void KPPPWidget::sigChld() { + kdDebug(5002) << "sigchld()" << endl; + // pid_t id = wait(0L); + // if(id == helperPid && helperPid != -1) { + // kdDebug(5002) << "It was the setuid child that died" << endl; + // helperPid = -1; + QString msg = i18n("kppp's helper process just died.\n" + "Since further execution would be pointless, " + "kppp will shut down now."); + KMessageBox::error(0L, msg); + remove_pidfile(); + exit(1); + // } +} + + +void KPPPWidget::newdefaultaccount(int i) { + gpppdata.setDefaultAccount(connectto_c->text(i)); + gpppdata.save(); + ID_Edit->setText(gpppdata.storedUsername()); + PW_Edit->setText(gpppdata.storedPassword()); +} + +void KPPPWidget::newdefaultmodem(int i) { + gpppdata.setDefaultModem(modem_c->text(i)); + gpppdata.save(); +} + + + +void KPPPWidget::expandbutton() { + setup(); +} + + +void KPPPWidget::beginConnect() { + // make sure to connect to the account that is selected in the combo box + // (exeption: an account given by a command line argument) + if(!m_bCmdlAccount) { + gpppdata.setAccount(connectto_c->currentText()); + gpppdata.setPassword(PW_Edit->text()); + } else { + gpppdata.setPassword(gpppdata.storedPassword()); + } + + QFileInfo info(pppdPath()); + + if(!info.exists()){ + KMessageBox::error(this, i18n("Cannot find the PPP daemon!\n" + "Make sure that pppd is installed and " + "that you have entered the correct path.")); + return; + } +#if 0 + if(!info.isExecutable()){ + + QString string; + string = i18n("kppp cannot execute:\n %1\n" + "Please make sure that you have given kppp " + "setuid permission and that " + "pppd is executable.").arg(gpppdata.pppdPath()); + KMessageBox::error(this, string); + return; + + } +#endif + + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + QString device = ""; + if (args->isSet("dev")) + device = args->getOption("dev"); + else + device = gpppdata.modemDevice(); + + QFileInfo info2(device); + + if(!info2.exists()){ + QString string; + string = i18n("kppp can not find:\n %1\nPlease make sure you have setup " + "your modem device properly " + "and/or adjust the location of the modem device on " + "the modem tab of " + "the setup dialog.").arg(device); + KMessageBox::error(this, string); + return; + } + + // if this is a PAP or CHAP account, ensure that username is + // supplied + if(gpppdata.authMethod() == AUTH_PAP || + gpppdata.authMethod() == AUTH_CHAP || + gpppdata.authMethod() == AUTH_PAPCHAP ) { + if(ID_Edit->text().isEmpty()) { + KMessageBox::error(this, + i18n( + "You have selected the authentication " + "method PAP or CHAP. This requires that you " + "supply a username and a password.")); + return; + } else { + if(!Requester::rq->setSecret(gpppdata.authMethod(), + encodeWord(gpppdata.storedUsername()), + encodeWord(gpppdata.password()))) { + QString s; + s = i18n("Cannot create PAP/CHAP authentication\n" + "file \"%1\"").arg(PAP_AUTH_FILE); + KMessageBox::error(this, s); + return; + } + } + } + + if (gpppdata.phonenumber().isEmpty()) { + QString s = i18n("You must specify a telephone number."); + KMessageBox::error(this, s); + return; + } + + hide(); + + QString tit = i18n("Connecting to: %1").arg(gpppdata.accname()); + con->setCaption(tit); + con->enableButtons(); + con->show(); + + bool show_debug = gpppdata.get_show_log_window(); + con->debug->setOn(show_debug); // toggle button + debugwindow->clear(); + if (!show_debug) + debugwindow->hide(); + else { + debugwindow->show(); + con->raise(); + } + + emit begin_connect(); +} + +void KPPPWidget::disconnect() { + if (disconnectTimer->isActive()) return; // you had already pressed disconnect before + + // signal other applications that we are about to go offline now + kapp->dcopClient()->emitDCOPSignal("KpppIface", "aboutToDisconnect()", QByteArray()); + con_win->hide(); + con->show(); + con->disableButtons(); // will reenable them later in delayedDisconnect() + con->setCaption(i18n("Disconnecting...")); + + if (!gpppdata.command_before_disconnect().isEmpty()) { + con->setMsg(i18n("Executing command before disconnection.")); + + kapp->processEvents(); + QApplication::flushX(); + pid_t id = execute_command(gpppdata.command_before_disconnect()); + int i, status; + + do { + kapp->processEvents(); + i = waitpid(id, &status, WNOHANG); + usleep(500000); + } while (i == 0 && errno == 0); + } + + con->setMsg(i18n("Announcing disconnection.")); + + // this is no longer necessary since I'm delaying disconnection usign a QTimer + // kapp->processEvents(); + + // set the timer to call delayedDisconnect() in DISCONNECT_DELAY ms + disconnectTimer->start(DISCONNECT_DELAY, true); +} + +void KPPPWidget::delayedDisconnect() { + // this is where the actual disconnection takes place + con->hide(); + + statdlg->stop_stats(); + Requester::rq->killPPPDaemon(); + + // signal other applications that we are disconnected now + kapp->dcopClient()->emitDCOPSignal("KpppIface", "disconnected()", QByteArray()); + + QApplication::flushX(); + execute_command(gpppdata.command_on_disconnect()); + + Requester::rq->removeSecret(AUTH_PAP); + Requester::rq->removeSecret(AUTH_CHAP); + + removedns(); + Modem::modem->unlockdevice(); + + con_win->stopClock(); + p_kppp->stopAccounting(); + con_win->hide(); + + DockWidget::dock_widget->stop_stats(); + DockWidget::dock_widget->hide(); + + if(m_bQuitOnDisconnect) + kapp->exit(0); + else { + quit_b->setFocus(); + show(); + } +} + + +void KPPPWidget::helpbutton() { + kapp->invokeHelp(); +} + + +void KPPPWidget::quitbutton() { + if(gpppdata.pppdRunning()) { + int ok = KMessageBox::warningContinueCancel(this, + i18n("Exiting kPPP will close your PPP Session."), + i18n("Quit kPPP?"), KStdGuiItem::quit()); + if(ok == KMessageBox::Continue) { + Requester::rq->killPPPDaemon(); + + // stop the disconnect delay timer + disconnectTimer->stop(); + + // signal other applications that we are disconnected now + kapp->dcopClient()->emitDCOPSignal("KpppIface", "disconnected()", QByteArray()); + + QApplication::flushX(); + execute_command(gpppdata.command_on_disconnect()); + removedns(); + Modem::modem->unlockdevice(); + } + } else { + if (!gpppdata.accname().isEmpty() && !gpppdata.storePassword()) + gpppdata.setStoredPassword(""); + } + gpppdata.save(); + kapp->quit(); +} + + +void KPPPWidget::rulesetLoadError() { + KMessageBox::error(this, ruleset_load_errmsg); +} + + +void KPPPWidget::startAccounting() { + // volume accounting + stats->totalbytes = 0; + + kdDebug(5002) << "AcctEnabled: " << gpppdata.AcctEnabled() << endl; + + // load the ruleset + if(!gpppdata.AcctEnabled()) + return; + + QString d = AccountingBase::getAccountingFile(gpppdata.accountingFile()); + // if(::access(d.data(), X_OK) != 0) + acct = new Accounting(this, stats); + // else + // acct = new ExecutableAccounting(this); + + // connect to the accounting object + connect(acct, SIGNAL(changed(QString, QString)), + con_win, SLOT(slotAccounting(QString, QString))); + + if(!acct->loadRuleSet(gpppdata.accountingFile())) { + QString s= i18n("Can not load the accounting " + "ruleset \"%1\".").arg(gpppdata.accountingFile()); + + // starting the messagebox with a timer will prevent us + // from blocking the calling function ConnectWidget::timerEvent + ruleset_load_errmsg = s; + QTimer::singleShot(0, this, SLOT(rulesetLoadError())); + return; + } else + acct->slotStart(); +} + +void KPPPWidget::stopAccounting() { + // store volume accounting + if(stats->totalbytes != 0) + gpppdata.setTotalBytes(stats->totalbytes); + + if(!gpppdata.AcctEnabled()) + return; + + if(acct != 0) { + acct->slotStop(); + delete acct; + acct = 0; + } +} + + +void KPPPWidget::showStats() { + if(statdlg) { + statdlg->toCurrentDesktop(); + statdlg->show(); + statdlg->raise(); + } +} + + +void KPPPWidget::usernameChanged(const QString &) { + // store username for later use + gpppdata.setStoredUsername(ID_Edit->text()); +} + + +void KPPPWidget::passwordChanged(const QString &) { + // store the password if so requested + if(gpppdata.storePassword()) + gpppdata.setStoredPassword(PW_Edit->text()); + else + gpppdata.setStoredPassword(""); +} + + +void KPPPWidget::setPW_Edit(const QString &pw) { + PW_Edit->setText(pw); +} + + +void KPPPWidget::resetCosts(const QString &s) { + AccountingBase::resetCosts(s); +} + + +void KPPPWidget::resetVolume(const QString &s) { + AccountingBase::resetVolume(s); +} + +/** + * pppd's getword() function knows about escape characters. + * If we write the username and password to the secrets file + * we'll therefore have to escape back slashes. + */ +QString KPPPWidget::encodeWord(const QString &s) { + QString r = s; + r.replace(QRegExp("\\"), "\\\\"); + return r; +} + +void KPPPWidget::setQuitOnDisconnect (bool b) +{ + m_bQuitOnDisconnect = b; +} + +void KPPPWidget::showNews() { +#ifdef KPPP_SHOW_NEWS + /* + * Introduce the QuickHelp feature to new users of this version + */ + #define QUICKHELP_HINT "Hint_QuickHelp" + if(gpppdata.readNumConfig(GENERAL_GRP, QUICKHELP_HINT, 0) == 0) { + QDialog dlg(0, 0, true); + dlg.setCaption(i18n("Recent Changes in KPPP")); + + QVBoxLayout *tl = new QVBoxLayout(&dlg, 10, 10); + QHBoxLayout *l1 = new QHBoxLayout(10); + QVBoxLayout *l2 = new QVBoxLayout(10); + tl->addLayout(l1); + + QLabel *icon = new QLabel(&dlg); + icon->setPixmap(BarIcon("exclamation")); + icon->setFixedSize(icon->sizeHint()); + l1->addWidget(icon); + l1->addLayout(l2); + + QLabel *l = new QLabel(i18n("From version 1.4.8 on, kppp has a new feature\n" + "called \"Quickhelp\". It's similar to a tooltip,\n" + "but you can activate it whenever you want.\n" + "\n" + "To activate it, simply click on a control like\n" + "a button or a label with the right mouse button.\n" + "If the item supports Quickhelp, a popup menu\n" + "will appear leading to Quickhelp.\n" + "\n" + "To test it, right-click somewhere in this text."), + &dlg); + + QCheckBox *cb = new QCheckBox(i18n("Don't show this hint again"), &dlg); + cb->setFixedSize(cb->sizeHint()); + + KButtonBox *bbox = new KButtonBox(&dlg); + bbox->addStretch(1); + QPushButton *ok = bbox->addButton(KStdGuiItem::ok()); + ok->setDefault(true); + dlg.connect(ok, SIGNAL(clicked()), + &dlg, SLOT(accept())); + bbox->addStretch(1); + bbox->layout(); + + l2->addWidget(l); + l2->addWidget(cb); + tl->addWidget(bbox); + + QString tmp = i18n("This is an example of <b>QuickHelp</b>.\n" + "This window will stay open until you\n" + "click a mouse button or a press a key.\n"); + + QWhatsThis::add(cb,tmp); + QWhatsThis::add(l, tmp); + + dlg.exec(); + if(cb->isChecked()) { + gpppdata.writeConfig(GENERAL_GRP, QUICKHELP_HINT, 1); + gpppdata.save(); + } + } +#endif +} + + +#include "kpppwidget.moc" + |