/* * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kpppwidget.h" #include <tqapplication.h> #include <tqcombobox.h> #include <tqdir.h> #include <tqevent.h> #include <tqdialog.h> #include <tqlabel.h> #include <tqpushbutton.h> #include <tqregexp.h> #include <kdialogbase.h> #include <tqwhatsthis.h> #include <tdeaboutdata.h> #include <tdeapplication.h> #include <kbuttonbox.h> #include <tdeglobalsettings.h> #include <tdecmdlineargs.h> #include <tdeconfig.h> #include <kdebug.h> #include <kiconloader.h> // For BarIcon #include <tdelocale.h> #include <tdemessagebox.h> #include <kseparator.h> #include <kstandarddirs.h> #include <twin.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( TQWidget *parent, const char *name ) : DCOPObject( "KpppIface" ), TQWidget(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); TQVBoxLayout *tl = new TQVBoxLayout(this, 10, 10); l1 = new TQGridLayout(4, 4); tl->addLayout(l1); l1->addColSpacing(0, 10); l1->addColSpacing(3, 10); l1->setColStretch(1, 3); l1->setColStretch(2, 4); label1 = new TQLabel(i18n("C&onnect to: "), this); l1->addWidget(label1, 0, 1); connectto_c = new TQComboBox(false, this); label1->setBuddy(connectto_c); connect(connectto_c, TQT_SIGNAL(activated(int)), TQT_SLOT(newdefaultaccount(int))); l1->addWidget(connectto_c, 0, 2); label7 = new TQLabel(i18n("Use &modem: "), this); // l1->addWidget(label7, 1, 1); (done in resetmodems()) modem_c = new TQComboBox(false, this); label7->setBuddy(connectto_c); m_bModemCShown = false; connect(modem_c, TQT_SIGNAL(activated(int)), TQT_SLOT(newdefaultmodem(int))); // l1->addWidget(modem_c, 1, 2); (done in resetmodems()) ID_Label = new TQLabel(i18n("&Login ID:"), this); l1->addWidget(ID_Label, 2, 1); // the entry line for usernames ID_Edit = new TQLineEdit(this); ID_Label->setBuddy(ID_Edit); l1->addWidget(ID_Edit, 2, 2); connect(ID_Edit, TQT_SIGNAL(returnPressed()), this, TQT_SLOT(enterPressedInID())); TQString 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>."); TQWhatsThis::add(ID_Label,tmp); TQWhatsThis::add(ID_Edit,tmp); PW_Label = new TQLabel(i18n("&Password:"), this); l1->addWidget(PW_Label, 3, 1); PW_Edit= new TQLineEdit(this); PW_Label->setBuddy(PW_Edit); PW_Edit->setEchoMode(TQLineEdit::Password); l1->addWidget(PW_Edit, 3, 2); connect(PW_Edit, TQT_SIGNAL(returnPressed()), this, TQT_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>."); TQWhatsThis::add(PW_Label,tmp); TQWhatsThis::add(PW_Edit,tmp); TQHBoxLayout *l3 = new TQHBoxLayout; tl->addSpacing(5); tl->addLayout(l3); tl->addSpacing(5); l3->addSpacing(10); log = new TQCheckBox(i18n("Show lo&g window"), this); connect(log, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(log_window_toggled(bool))); log->setChecked(gpppdata.get_show_log_window()); l3->addWidget(log); TQWhatsThis::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); TQHBoxLayout *l2 = new TQHBoxLayout; tl->addLayout(l2); int minw = 0; quit_b = new KPushButton(KStdGuiItem::quit(), this); connect( quit_b, TQT_SIGNAL(clicked()), TQT_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, TQT_SIGNAL(clicked()), TQT_SLOT(expandbutton())); if(setup_b->sizeHint().width() > minw) minw = setup_b->sizeHint().width(); if(gpppdata.access() != TDEConfig::ReadWrite) setup_b->setEnabled(false); help_b = new KPushButton(KStdGuiItem::help(), this); connect( help_b, TQT_SIGNAL(clicked()), TQT_SLOT(helpbutton())); KHelpMenu *helpMenu = new KHelpMenu(this, TDEGlobal::instance()->aboutData(), true); help_b->setPopup((TQPopupMenu*)helpMenu->menu()); if(help_b->sizeHint().width() > minw) minw = help_b->sizeHint().width(); connect_b = new TQPushButton(i18n("&Connect"), this); connect_b->setDefault(true); connect_b->setFocus(); connect(connect_b, TQT_SIGNAL(clicked()), TQT_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,TQT_SIGNAL(cmdl_start()),this,TQT_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, TQT_SIGNAL(begin_connect()),con, TQT_SLOT(preinit())); TQRect desk = TDEGlobalSettings::desktopGeometry(topLevelWidget()); con->setGeometry(desk.center().x()-175, desk.center().y()-55, 350,110); // connect the ConnectWidgets various signals connect(con, TQT_SIGNAL(closeDebugWindow()), debugwindow, TQT_SLOT(hide())); connect(con, TQT_SIGNAL(debugMessage(const TQString &)), debugwindow, TQT_SLOT(statusLabel(const TQString &))); connect(con, TQT_SIGNAL(toggleDebugWindow()), debugwindow, TQT_SLOT(toggleVisibility())); connect(con, TQT_SIGNAL(debugPutChar(unsigned char)), debugwindow, TQT_SLOT(addChar(unsigned char))); connect(con, TQT_SIGNAL(startAccounting()), this, TQT_SLOT(startAccounting())); connect(con, TQT_SIGNAL(stopAccounting()), this, TQT_SLOT(stopAccounting())); connect(TDEApplication::kApplication(), TQT_SIGNAL(saveYourself()), this, TQT_SLOT(saveMyself())); connect(TDEApplication::kApplication(), TQT_SIGNAL(shutDown()), this, TQT_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); TDECmdLineArgs *args = TDECmdLineArgs::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){ TQString 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){ TQString 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 TQTimer(this); connect(disconnectTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(delayedDisconnect())); } KPPPWidget::~KPPPWidget() { delete stats; } bool KPPPWidget::eventFilter(TQObject *o, TQEvent *e) { if(e->type() == TQEvent::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(TQT_BASE_OBJECT(o) == TQT_BASE_OBJECT(connect_b)) { if(e->type() == TQEvent::KeyPress) { if(connect_b->hasFocus() && ((TQKeyEvent *)e)->key() == TQt::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, TQT_SIGNAL(resetaccounts()), this, TQT_SLOT(resetaccounts())); connect(accounts, TQT_SIGNAL(resetCosts(const TQString &)), this, TQT_SLOT(resetCosts(const TQString &))); connect(accounts, TQT_SIGNAL(resetVolume(const TQString &)), this, TQT_SLOT(resetVolume(const TQString &))); modems = new ModemsWidget(tabWindow->addPage( i18n("&Modems"), i18n("Modems Setup") ) ); connect(modems, TQT_SIGNAL(resetmodems()), this, TQT_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, TQT_SIGNAL(textChanged(const TQString &)), this, TQT_SLOT(usernameChanged(const TQString &))); connect(PW_Edit, TQT_SIGNAL(textChanged(const TQString &)), this, TQT_SLOT(passwordChanged(const TQString &))); 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()", TQByteArray()); kdDebug(5002) << "Executing command on disconnect since pppd has died." << endl; TQApplication::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(); TQString 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; TQString 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()); } TQFileInfo 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()){ TQString 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 TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); TQString device = ""; if (args->isSet("dev")) device = args->getOption("dev"); else device = gpppdata.modemDevice(); TQFileInfo info2(device); if(!info2.exists()){ TQString 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()))) { TQString s; s = i18n("Cannot create PAP/CHAP authentication\n" "file \"%1\"").arg(PAP_AUTH_FILE); KMessageBox::error(this, s); return; } } } if (gpppdata.phonenumber().isEmpty()) { TQString s = i18n("You must specify a telephone number."); KMessageBox::error(this, s); return; } hide(); TQString 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()", TQByteArray()); 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(); TQApplication::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 TQTimer // 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()", TQByteArray()); TQApplication::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()", TQByteArray()); TQApplication::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; TQString d = AccountingBase::getAccountingFile(gpppdata.accountingFile()); // if(::access(d.data(), X_OK) != 0) acct = new Accounting(TQT_TQOBJECT(this), stats); // else // acct = new ExecutableAccounting(this); // connect to the accounting object connect(acct, TQT_SIGNAL(changed(TQString, TQString)), con_win, TQT_SLOT(slotAccounting(TQString, TQString))); if(!acct->loadRuleSet(gpppdata.accountingFile())) { TQString 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; TQTimer::singleShot(0, this, TQT_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 TQString &) { // store username for later use gpppdata.setStoredUsername(ID_Edit->text()); } void KPPPWidget::passwordChanged(const TQString &) { // store the password if so requested if(gpppdata.storePassword()) gpppdata.setStoredPassword(PW_Edit->text()); else gpppdata.setStoredPassword(""); } void KPPPWidget::setPW_Edit(const TQString &pw) { PW_Edit->setText(pw); } void KPPPWidget::resetCosts(const TQString &s) { AccountingBase::resetCosts(s); } void KPPPWidget::resetVolume(const TQString &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. */ TQString KPPPWidget::encodeWord(const TQString &s) { TQString r = s; r.replace(TQRegExp("\\"), "\\\\"); 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) { TQDialog dlg(0, 0, true); dlg.setCaption(i18n("Recent Changes in KPPP")); TQVBoxLayout *tl = new TQVBoxLayout(&dlg, 10, 10); TQHBoxLayout *l1 = new TQHBoxLayout(10); TQVBoxLayout *l2 = new TQVBoxLayout(10); tl->addLayout(l1); TQLabel *icon = new TQLabel(&dlg); icon->setPixmap(BarIcon("exclamation")); icon->setFixedSize(icon->sizeHint()); l1->addWidget(icon); l1->addLayout(l2); TQLabel *l = new TQLabel(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); TQCheckBox *cb = new TQCheckBox(i18n("Don't show this hint again"), &dlg); cb->setFixedSize(cb->sizeHint()); KButtonBox *bbox = new KButtonBox(&dlg); bbox->addStretch(1); TQPushButton *ok = bbox->addButton(KStdGuiItem::ok()); ok->setDefault(true); dlg.connect(ok, TQT_SIGNAL(clicked()), &dlg, TQT_SLOT(accept())); bbox->addStretch(1); bbox->layout(); l2->addWidget(l); l2->addWidget(cb); tl->addWidget(bbox); TQString 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"); TQWhatsThis::add(cb,tmp); TQWhatsThis::add(l, tmp); dlg.exec(); if(cb->isChecked()) { gpppdata.writeConfig(GENERAL_GRP, QUICKHELP_HINT, 1); gpppdata.save(); } } #endif } #include "kpppwidget.moc"