summaryrefslogtreecommitdiffstats
path: root/src/wlassistant.cpp
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-01 19:19:25 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-01 19:19:25 +0000
commite0311ffdf88fc311006351582b959a69d8aad328 (patch)
treedccf6212f21ef7e3824b54837be7b1d14139d2e1 /src/wlassistant.cpp
downloadwlassistant-e0311ffdf88fc311006351582b959a69d8aad328.tar.gz
wlassistant-e0311ffdf88fc311006351582b959a69d8aad328.zip
Added KDE3 version of wlassistant
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/wlassistant@1097621 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/wlassistant.cpp')
-rw-r--r--src/wlassistant.cpp1264
1 files changed, 1264 insertions, 0 deletions
diff --git a/src/wlassistant.cpp b/src/wlassistant.cpp
new file mode 100644
index 0000000..bf58914
--- /dev/null
+++ b/src/wlassistant.cpp
@@ -0,0 +1,1264 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Pawel Nawrocki *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU 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 General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU 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 "wlassistant.h"
+#include "netlistviewitem.h"
+#include "waconfig.h"
+#include "watools.h"
+#include "ui_netparamswizard.h"
+#include "ui_netparamsedit.h"
+
+#include <iostream>
+#include <linux/version.h> //provides LINUX_VERSION* macros
+
+#include <qregexp.h>
+#include <qlabel.h>
+#include <qprocess.h>
+#include <qcursor.h>
+#include <qeventloop.h>
+#include <qtimer.h>
+#include <qcheckbox.h>
+#include <qspinbox.h>
+#include <qwidgetstack.h>
+#include <qtooltip.h>
+
+#include <kpushbutton.h>
+#include <kcombobox.h>
+#include <klistview.h>
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+#include <kpopupmenu.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+
+WirelessAssistant::WirelessAssistant(QWidget* parent, const char* name, bool modal, WFlags fl)
+ : mainWindow(parent,name, modal,fl)
+{
+ buttonScan->setIconSet( SmallIconSet("reload") );
+ buttonConnect->setIconSet( SmallIconSet("connect_creating") );
+ buttonOptions->setIconSet( SmallIconSet("configure") );
+ buttonClose->setIconSet( SmallIconSet("fileclose") );
+
+ netList->setAllColumnsShowFocus(1);
+ netList->setItemMargin(8);
+ frameDevice->hide();
+
+ /// Network List Widget
+ connect( buttonScan, SIGNAL(clicked()),
+ this, SLOT(netScan()) );
+
+ connect( buttonConnect, SIGNAL(clicked()),
+ this, SLOT(itemAction()) );
+
+ connect( buttonClose, SIGNAL(clicked()),
+ this, SLOT(close()) );
+
+ connect( devCombo, SIGNAL(activated( const QString & )),
+ this, SLOT(setDev( const QString & )) );
+
+ connect( netList, SIGNAL(rightButtonPressed( QListViewItem*, const QPoint&, int )),
+ SLOT(showItemContextMenu( QListViewItem*, const QPoint&, int )) );
+
+ /// Settings Widget
+ connect( buttonOptions, SIGNAL(toggled(bool)),
+ this, SLOT(togglePage(bool)) );
+
+ connect( buttonEnableAllMessages, SIGNAL(clicked()),
+ this, SLOT(enableAllMessages()) );
+
+ /// Global KDE Options
+ connect( KApplication::kApplication(), SIGNAL(settingsChanged(int)),
+ this, SLOT(updateConfiguration(int)) );
+
+ setMouseBehaviour();
+
+ QTimer::singleShot(10, this, SLOT(init()) ); //WAIT FOR THE UI TO BE READY BEFORE FURTHER SETUP (msec)
+}
+
+WirelessAssistant::~WirelessAssistant()
+{}
+
+/*$SPECIALIZATION$*/
+
+
+void WirelessAssistant::init()
+{
+ statusLabel->setText(i18n("Initializing..."));
+ statusLabel->repaint();
+
+ ////////////////////////////////////////
+ ///// CHECK FOR SYSFS (KERNEL 2.6) /////
+ if ( !QFile::exists("/sys") ) {
+ std::cout << "Sysfs not present. Exiting." << std::endl;
+ KMessageBox::error( 0, i18n("Kernel 2.6 or later not present.\nWireless Assistant will now quit.") );
+ close();
+ return;
+ }
+
+ /////////////////////////////////////////////////////
+ ///// LOAD CONFIG FILE INCL. ALL NET PARAMETERS /////
+ WAConfig::self()->setCurrentGroup("Global Options");
+ WAConfig::self()->addItemBool("Auto Quit", autoQuit);
+ WAConfig::self()->addItemBool("Auto Reconnect", autoReconnect);
+ WAConfig::self()->addItemBool("Auto Connect", autoConnect);
+ WAConfig::self()->addItemInt("Delay Before Scanning", DelayBeforeScanning);
+ WAConfig::self()->addItemBool("Group APs", groupAPs);
+ WAConfig::self()->addItemInt("DHCP Client Timeout", DhcpTimeout);
+ WAConfig::self()->addItemString("Interface", NetParams.iface);
+
+ WAConfig::self()->setCurrentGroup("Paths");
+ // Commented out cos no longer needed. Paths are detected when necessary.
+ /*WAConfig::self()->addItemString("DHCP Info (dhcpcd)", dhcpcdInfoPath);
+ WAConfig::self()->addItemString("DHCP PID File (dhcpcd)", dhcpcdPidPath);
+ WAConfig::self()->addItemString("DHCP Info (dhclient)", dhclientInfoPath);
+ WAConfig::self()->addItemString("DHCP PID File (dhclient)", dhclientPidPath);*/
+
+ WAConfig::self()->setCurrentGroup("Network Parameters");
+ WAConfig::self()->addItemStringList("NetParamsList", NetParamsList );
+ WAConfig::self()->readConfig();
+ checkAutoQuit->setChecked(autoQuit);
+ checkAutoReconnect->setChecked(autoReconnect);
+ checkAutoConnect->setChecked(autoConnect);
+ checkGroupAPs->setChecked(groupAPs);
+ if (!DelayBeforeScanning)
+ DelayBeforeScanning = spinDelayBeforeScanning->value();
+ else
+ spinDelayBeforeScanning->setValue(DelayBeforeScanning);
+ if (!DhcpTimeout)
+ DhcpTimeout = spinDhcpTimeout->value();
+ else
+ spinDhcpTimeout->setValue(DhcpTimeout);
+
+ std::cout << "Loaded application options." << std::endl;
+
+ ///////////////////////////////////
+ ///// DETECT WIRELESS DEVICES /////
+ QStringList devList = interfaceList();
+ if ( devList.count()==0 ) {
+ std::cout << "No wireless interfaces found. Exiting." << std::endl;
+ KMessageBox::error(0, i18n("No usable wireless devices found.\nWireless Assistant will now quit."));
+ close();
+ return;
+ }
+ std::cout << "Wireless interface(s): " << devList.join(", ") << std::endl;
+ devCombo->insertStringList(devList);
+
+ if (devCombo->count() > 1) { //check if last used (saved) interface is available (only if more that 1 interface present).
+ for (int i=0; i<devCombo->count(); i++) {
+ if ( devCombo->text(i)==NetParams.iface ) { //select matching interface.
+ devCombo->setCurrentItem( i );
+ break;
+ }
+ }
+ frameDevice->show(); //only if more than 1 wireless device.
+ }
+ NetParams.iface = devCombo->currentText(); // set interface name
+ WATools::setInterface( NetParams.iface ); // set fallback interface for WATools
+
+ //////////////////////////////////
+ ///// CHECK FILE PERMISSIONS /////
+ if (!QFileInfo("/etc/resolv.conf").isWritable()) {
+ std::cout << "warning: /etc/resolv.conf not writable" << std::endl;
+ KMessageBox::information(0, i18n("<qt><p>You might have insufficient permissions for Wireless Assistant to function properly.</p><p>Did you run it using '<tt>sudo</tt>'?</p></qt>") );
+ }
+ std::cout << "Permissions checked." << std::endl;
+
+ //////////////////////////////////
+ ///// INITIALIZE COMMANDS
+ Commands.init();
+
+ ///////////////////////////////////////
+ ///// INITIALIZE GLOBAL VARIABLES /////
+ wpaAvailable = ( !( Commands.wpa_supplicant.isEmpty() || Commands.wpa_cli.isEmpty() ) );
+ connectedItem = 0;
+ timerGui = new QTimer();
+ timerConnectionCheck = new QTimer();
+ connect( timerGui, SIGNAL(timeout()), SLOT(updateConnectedItem()) );
+ connect( timerConnectionCheck, SIGNAL(timeout()), SLOT(checkConnectionStatus()) );
+
+ ////////////////////////
+ ///// DETECT & SET PATHS /////
+ if (!Commands.allFound) { //all ok or ONLY dhcpcd not found (i.e. dhclient present).
+ std::cout << "Missing executables (" << Commands.notFound.join("', '") << "). Exiting." << std::endl;
+ KMessageBox::error(0, i18n("Executable(s) '%1' could not be found.\nWireless Assistant will now quit.").arg(Commands.notFound.join("', '")) );
+ close();
+ return;
+ }
+
+ KStandardDirs standardDirs;
+ wpaConfigFile = standardDirs.saveLocation("config").append("wlassistantwpa");
+
+ ///////////////////////////////////////
+ ///// SCAN FOR AVAILABLE NETWORKS /////
+ if ( autoConnect )
+ QTimer::singleShot( 0, this, SLOT(netAutoConnect()) );
+ else
+ QTimer::singleShot( 0, this, SLOT(netScan()) );
+}
+
+void WirelessAssistant::checkConnectionStatus()
+{
+ QListViewItem* lvi;
+ if (groupAPs) lvi = getItemByEssid( WATools::essid(NetParams.iface));
+ else lvi = getItemByAp( WATools::ap(NetParams.iface ));
+ bool needsKey;
+ lvi ? needsKey = static_cast<NetListViewItem*>(lvi)->enc() : needsKey = 0;
+ if ( WATools::isConnected(NetParams.iface) && WATools::hasKey(NetParams.iface)==needsKey ) { //connection OK
+ if (!connectedItem) {
+ std::cout << "Now connected to '" << WATools::essid(NetParams.iface) << "'" << std::endl;
+ if (groupAPs && NetParams.ap=="any") {
+ setConnectedItem( WATools::essid( NetParams.iface ) );
+ setNetParamsFromConfig( WATools::essid( NetParams.iface ) );
+ } else {
+ setConnectedItem( WATools::ap( NetParams.iface ) );
+ setNetParamsFromConfig( WATools::ap( NetParams.iface ) );
+ }
+ setNetParamsFromList( connectedItem );
+ }
+ } else if (connectedItem) { //connection LOST
+ setConnectedItem(0);
+ timerConnectionCheck->stop();
+ if ( autoReconnect || KMessageBox::questionYesNo(0, i18n("Connection to '%1' has been lost!\nWould you like to reconnect?").arg(NetParams.essid), i18n("Connection Lost") , KStdGuiItem::yes(), KStdGuiItem::no() ) == KMessageBox::Yes ) {
+ netDisconnect( true );
+ netConnect();
+ }
+ timerConnectionCheck->start( WA_CONNECTION_CHECK_INTERVAL );
+ }
+}
+
+void WirelessAssistant::removeNetParams()
+{
+ NetListViewItem *nvi = static_cast<NetListViewItem*>(netList->selectedItem());
+ QString ap = nvi->ap(); QString essid = nvi->essid();
+ for (QStringList::Iterator nps = NetParamsList.begin(); nps != NetParamsList.end(); nps++) {
+ if ( (*nps).section(",",2,2)==ap && (*nps).section(",",1,1)==essid) {
+ if ( KMessageBox::warningContinueCancel(0, i18n("<qt><p>Settings for network '<b>%1</b>' are about to be deleted.</p><p>Would you like to continue?</p></qt>").arg(essid)) == KMessageBox::Continue ) {
+ if (nvi->hidden()) // hiddenEssid = 1
+ nvi->setEssid("<hidden>");
+ NetParamsList.remove(nps);
+ WAConfig::self()->writeConfig();
+ statusLabel->setText( i18n("Settings deleted.") );
+ }
+ break;
+ }
+ }
+}
+
+
+void WirelessAssistant::setDNS( const WANetParams & np )
+{
+ QFile f("/etc/resolv.conf");
+ if (f.open( IO_WriteOnly | IO_Truncate )) {
+ QTextStream s( &f );
+ if (!np.domain.isEmpty()) {
+ s << QString("domain " + np.domain + "\n");
+ std::cout << "resolv.conf: domain " << np.domain << std::endl;
+ }
+ if (!np.dns1.isEmpty()) {
+ s << QString("nameserver " + np.dns1 + "\n");
+ std::cout << "resolv.conf: nameserver " << np.dns1 << std::endl;
+ }
+ if (!np.dns2.isEmpty()) {
+ s << QString("nameserver " + np.dns2 + "\n");
+ std::cout << "resolv.conf: nameserver " << np.dns2 << std::endl;
+ }
+ f.close();
+ } else {
+ std::cout << "dns setup error: " << f.name() << " is not writeable." << std::endl;
+ KMessageBox::error(0, i18n("<qt><p>File '<i>%1</i>' could not be opened for writing.</p><p>Nameserver(s) and/or domain are not set.</p></qt>").arg(f.name()) );
+ }
+}
+
+void WirelessAssistant::netScan()
+{
+ timerConnectionCheck->stop(); //stop while scanning.
+ netScan( NetParams );
+ if (netList->childCount() > 0) {
+ QTimer::singleShot( 0, this, SLOT(checkConnectionStatus()) );
+ timerConnectionCheck->start(WA_CONNECTION_CHECK_INTERVAL);
+ }
+}
+
+void WirelessAssistant::netScan( const WANetParams & np )
+{
+ if (!radioEnabled()) {
+ statusLabel->setText("Radio off. Scanning aborted.");
+ std::cout << "Radio is off!" << std::endl;
+ setUi(1);
+ return;
+ }
+
+ setUi(0);
+
+ bool wasConnected = false;
+ if (connectedItem) {
+ wasConnected = true;
+ setConnectedItem( 0 );
+ }
+
+ if ( !WATools::isUp(np.iface) ) {
+ statusLabel->setText(i18n("Bringing interface %1 up...").arg(np.iface));
+ //runCommand( Commands.cmd("ifup",np) );
+ WATools::setUp(true, np.iface);
+ if (DelayBeforeScanning>0) {
+ statusLabel->setText(i18n("Waiting before scanning..."));
+ statusLabel->repaint();
+ KApplication::eventLoop()->processEvents( QEventLoop::ExcludeUserInput );
+ usleep(DelayBeforeScanning * 1000000); // delay * 1000ms
+ }
+ }
+
+ statusLabel->setText(i18n("Scanning..."));
+ statusLabel->repaint();
+
+ netList->clear();
+
+ QString result;
+ statusLabel->setText(i18n("Scanning..."));
+ result = runCommand( Commands.cmd("scan",np) );
+
+ parseScan( result );
+
+ if (netList->childCount() > 0) {
+ std::cout << "Networks found: " << QString::number( netList->childCount() ) << std::endl;
+ if (wasConnected)
+ groupAPs ? setConnectedItem( WATools::essid() ) : setConnectedItem( WATools::ap() ); //mark item as connected.
+ statusLabel->setText( i18n("Done.") );
+ } else {
+ //Workaround for cards overusing cache - bringing if down seems to solve it.
+ //runCommand( Commands.cmd("ifdown", NetParams) ); //Commented out b/c it seems to cause more problems than it solves. (like no scan results)
+ std::cout << "No networks found!" << std::endl;
+ statusLabel->setText( i18n("No networks found.") );
+ if ( result.find("Resource temporarily unavailable")>-1 ) {
+ std::cout << "Radio switch seems to be off." << std::endl;
+ KMessageBox::information(0, i18n("Radio of your wireless card seems to be turned off using an external switch on your computer.\nYou need turn it on to be able to use wireless networks.") );
+ }
+ }
+ setNetListColumns();
+}
+
+void WirelessAssistant::parseScan( const QString & output )
+{
+ QString essid;
+ QStringList essidList;
+ QString channel;
+ QString mode;
+ int qualInt;
+ bool enc; //default to false
+ bool hidden; //default to false
+ QString ap;
+
+ // security parameters
+ bool wpa;
+ QStringList wpaSettings;
+ //QString wpaVersion, wpaGroupCipher, wpaPairwiseCipher, wpaAuthenticationSuite;
+
+
+ bool ok_channel = true; //does iwlist return channel?
+ QString section;
+
+ netList->setUpdatesEnabled( false ); //do not redraw while adding items to avoid flicker.
+
+ for (int i=1; (!output.section("Cell ",i,i).isEmpty()); i++ ) {
+ section = output.section("Cell ",i,i);
+
+ // GET ESSID VALUE
+ essid = getVal(section, "ESSID\\W+\"(.+)\"");
+
+ // GET CHANNEL NUMBER
+ channel = getVal(section, "Channel\\D+(\\d+)" );
+ if (channel.isEmpty()) {
+ channel = getVal(section, "Frequency\\D+(\\d.+)Hz");
+ ok_channel = false;
+ }
+
+ // GET MODE VALUE
+ mode = getVal(section, "Mode:(\\w)"); //get 1st letter of mode.
+ if (mode.upper()!="M") //this covers both Managed and Master. Other are unsupported.
+ continue;
+
+ // GET AP
+ ap = getVal(section, "Address\\W+(\\S+)");
+
+ if (essid.isEmpty()) {
+ if (!ap.isEmpty()) //older wireless-tools report "", not "<hidden>"
+ essid = "<hidden>";
+ else
+ continue; //some cards report one '' essid even when no network's present. Workaround.
+ }
+
+ if (essid=="<hidden>") {
+ hidden = true;
+ essid = matchEssidForAp( ap );
+ } else
+ hidden=false;
+
+ // GET QUALITY
+ int wsignal;
+ //check if driver reports quality directly
+ qualInt = getVal(section, "Quality\\D+(\\d+)").toInt();
+
+ if (qualInt == 0) { //noise not reported? estimate.
+ wsignal = getVal(section, "Signal level\\D+(\\d+)" ).toInt();
+ qualInt = 100-wsignal;
+ }
+ qualInt = (100*qualInt)/50; //adjust and normalize quality (0-100). 50 is the best (6 stars) noise/signal difference
+ if (qualInt > 100) qualInt = 100;
+
+ // GET ENCRYPTION
+ if (getVal(section, "Encryption key\\W+(\\w+)" ).upper()=="OFF")
+ enc = false;
+ else {
+ enc = true;
+
+ wpaSettings.clear();
+ if ( section.contains("WPA2 Version") ) wpaSettings << "WPA2"; //prefer WPA2 over WPA
+ else if ( section.contains("WPA Version") ) wpaSettings << "WPA";
+
+ wpa = ( !wpaSettings.isEmpty() );
+ if (wpa) {
+ wpaSettings << getVal(section, "Group Cipher : (\\w+)") \
+ << getVal(section, "Pairwise Ciphers \\(\\d+\\) : ([\\w ]+)[\n\r]") \
+ << getVal(section, "Authentication Suites \\(\\d+\\) : ([\\w ]+)[\n\r]");
+ }
+ }
+
+ // CHECK IF SAME ESSID ALREADY FOUND, if necessary
+ if (groupAPs) {
+ if ( !hidden && essidList.contains(essid) ) {
+ NetListViewItem* sameEssid = static_cast<NetListViewItem*>(getItemByEssid(essid));
+ sameEssid->setAp("any");
+ if (sameEssid->quality() < qualInt) {
+ sameEssid->setQuality(qualInt);
+ sameEssid->setChannel(channel);
+ }
+ continue;
+ }
+ essidList << essid;
+ }
+
+ NetListViewItem* nvi = new NetListViewItem( netList, essid, channel, qualInt, enc, ap, hidden );
+ if (wpa) nvi->setWpaSettings( wpaSettings );
+ }
+
+ if (!ok_channel)
+ netList->setColumnText( 1, i18n("Freq (Hz)") );
+
+ /// @fixme HACK: Test item for the network list.
+ /// new NetListViewItem( netList, "Test Net", "9", 76, 1, "00:00:00:00:00:11", 0 );
+
+
+ netList->setUpdatesEnabled( true );
+ setUi(1);
+}
+
+bool WirelessAssistant::radioEnabled()
+{
+ bool r;
+ if ( WATools::txpower()==-1 ) {
+ if (KMessageBox::questionYesNo(0, i18n("Radio of your wireless card is off.\nWould you like to turn it on?") )== KMessageBox::Yes) {
+ runCommand( Commands.cmd("radio_on", NetParams) );
+ r = true;
+ } else {
+ r = false;
+ }
+ } else
+ r = true;
+
+ return r;
+}
+
+void WirelessAssistant::setNetParamsFromList( QListViewItem* lvi )
+{
+ NetListViewItem *nvi = static_cast<NetListViewItem*>(lvi);
+ NetParams.essid = nvi->essid();
+ NetParams.hiddenEssid = nvi->hidden();
+ //NetParams.mode = nvi->mode();
+ NetParams.channel = nvi->channel();
+ NetParams.ap = nvi->ap();
+ NetParams.wpaSettings = nvi->wpaSettings();
+ NetParams.wep = ( nvi->enc() && NetParams.wpaSettings.isEmpty() );
+ NetParams.wpa = ( nvi->enc() && !NetParams.wpaSettings.isEmpty() );
+}
+
+bool WirelessAssistant::setNetParamsFromConfig( const QString & s )
+{
+ for (QStringList::Iterator nps = NetParamsList.begin(); nps != NetParamsList.end(); nps++) {
+ if ( (*nps).section(",",2,2)==s || ( (*nps).section(",",1,1)==s && (*nps).section(",",2,2)=="any") ) {
+ NetParams.loadNetParamsString( *nps );
+ if (!s.contains(":")) NetParams.ap = "any"; //if searched by essid
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void WirelessAssistant::itemAction()
+{
+ QListViewItem* lvi = netList->selectedItem();
+ if (!lvi)
+ return;
+
+ NetListViewItem* nvi = static_cast<NetListViewItem*>(lvi);
+ ///////////////////
+ ///// ACTIONS /////
+ if (nvi->isConnected()) {
+ std::cout << "ACTION: DISCONNECT." << std::endl;
+ netDisconnect();
+ return;
+ } else {
+ std::cout << "ACTION: CONNECT." << std::endl;
+ netConnect();
+ return;
+ }
+}
+
+void WirelessAssistant::netAutoConnect()
+{
+ netScan();
+ if ( WATools::isConnected(NetParams.iface) ) return;
+
+ int bestItem = -1;
+ int bestQuality = 0;
+ for ( int i = 0; i < netList->childCount(); i++ ) {
+ NetListViewItem* nvi = static_cast<NetListViewItem*>( netList->itemAtIndex(i) );
+ QString search = nvi->ap();
+ if (search == "any") search = nvi->essid();
+ if ( setNetParamsFromConfig(search) ) {
+ if ( nvi->quality() > bestQuality ) {
+ bestQuality = nvi->quality();
+ bestItem = i;
+ }
+ }
+ }
+
+ if ( bestItem != -1 ) {
+ NetListViewItem* nvi = static_cast<NetListViewItem*>( netList->itemAtIndex( bestItem ) );
+ setNetParamsFromList( nvi );
+ QString search = nvi->ap();
+ if (search == "any") search = nvi->essid();
+ setNetParamsFromConfig( search );
+ timerConnectionCheck->stop();
+ netConnect( NetParams );
+ timerConnectionCheck->start(WA_CONNECTION_CHECK_INTERVAL);
+ } else {
+ statusLabel->setText( i18n("Auto connection failed.") );
+ std::cout << "Auto connection failed: no available configured networks found." << std::endl;
+ }
+}
+
+void WirelessAssistant::netConnect()
+{
+ timerConnectionCheck->stop();
+ setNetParamsFromList( netList->selectedItem() );
+ //can't connect if WPA needed, and wpa_supplicant and wpa_cli not available
+ if ( NetParams.wpa && !wpaAvailable ) {
+ KMessageBox::error(0, i18n("<qt><p><b>Can not connect to network '%1'.<b></p><p>The network you are trying to connect to requires WPA authentication. The necessary executables <i>wpa_supplicant</i> and <i>wpa_cli</i> could not be found. Install <i>wpa_supplicant</i> and restart Wireless Assistant to connect.</p></qt>").arg(NetParams.essid) );
+ timerConnectionCheck->start(WA_CONNECTION_CHECK_INTERVAL); //resume connection checking
+ return;
+ }
+ QString search = NetParams.ap;
+ if (search == "any") search = NetParams.essid;
+ if ( (NetParams.essid=="<hidden>") || (!setNetParamsFromConfig( search )) ) {
+ ui_NetParamsWizard *netwiz = new ui_NetParamsWizard;
+ if (!NetParams.hiddenEssid)
+ netwiz->setCaption( i18n("%1 - First Connection Wizard").arg(NetParams.essid) );
+ netwiz->setEssidEnabled( NetParams.hiddenEssid );
+ netwiz->setWepEnabled( NetParams.wep );
+ netwiz->setWpaEnabled( NetParams.wpa, NetParams.wpaSettings );
+ netwiz->exec();
+ if (netwiz->result()==QDialog::Rejected) {
+ delete netwiz;
+ timerConnectionCheck->start(WA_CONNECTION_CHECK_INTERVAL); //resume connection checking
+ return;
+ } else {
+ NetParams = netwiz->readNetParams( NetParams );
+ NetParams.wasHiddenEssid = NetParams.hiddenEssid; //first time values.
+ NetParams.wasWep = NetParams.wep;
+ NetParamsList << NetParams.netParamsString();
+ if (NetParams.hiddenEssid)
+ static_cast<NetListViewItem*>(netList->selectedItem())->setEssid( NetParams.essid );
+ WAConfig::self()->writeConfig();
+ delete netwiz;
+ }
+ }
+
+ if (NetParams.review())
+ editNetParams();
+ updateNetParams();
+ netConnect( NetParams );
+ timerConnectionCheck->start(WA_CONNECTION_CHECK_INTERVAL);
+}
+
+void WirelessAssistant::updateNetParams()
+{
+ for (QStringList::Iterator nps = NetParamsList.begin(); nps != NetParamsList.end(); nps++) {
+ if ( (*nps).section(",",2,2)==NetParams.ap ) {
+ QString newNps = NetParams.netParamsString();
+ if ( newNps!=(*nps) ) {
+ (*nps) = newNps;
+ WAConfig::self()->writeConfig();
+ std::cout << "Network settings updated." << std::endl;
+ statusLabel->setText( i18n("Network settings updated.") );
+ break;
+ }
+ }
+ }
+}
+
+QString WirelessAssistant::matchEssidForAp( const QString & ap )
+{
+ for (QStringList::Iterator nps = NetParamsList.begin(); nps != NetParamsList.end(); nps++) {
+ if ( (*nps).section(",",2,2)==ap ) {
+ return (*nps).section(",",1,1); //essid
+ }
+ }
+ return "<hidden>";
+}
+
+void WirelessAssistant::netConnect( const WANetParams & np )
+{
+ setUi(0);
+
+ if (connectedItem)
+ netDisconnect( true );
+ else if ( dhcpClientRunning() )
+ runCommand( Commands.cmd("kill_dhcp", np) ); //kill any stale DHCP client running
+
+ if ( !np.preConnectionCommand.isEmpty() ) {
+ std::cout << "Running pre-connection command: " << np.preConnectionCommand << std::endl;
+ statusLabel->setText( i18n("Running pre-connection command...") );
+ runCommand( QStringList::split( " ", np.preConnectionCommand ), np.preConnectionTimeout, np.preConnectionDetached );
+ } else
+ std::cout << "No pre-connection command specified." << std::endl;
+
+
+ statusLabel->setText( i18n("Connecting to '%1'...").arg(np.essid) );
+ statusLabel->repaint();
+ if (!WATools::isUp(np.iface) ) WATools::setUp( true, np.iface );
+ //runCommand( Commands.cmd("ifup", np) );
+ if ( runCommand( Commands.cmd("iwconfig_set", np) ).find("8B04") > -1 ) { // error 8B04 - Request 'Set Frequency' not supported.
+ WANetParams np2 = np;
+ np2.channel = "0";
+ runCommand( Commands.cmd("iwconfig_set", np2) );
+ }
+
+ runCommand( Commands.cmd("iwconfig_ap", np) );
+
+ ///////////////////////
+ ///// RUN WPA CLIENT IF NEEDED
+ if (np.wpa) {
+ if ( generateWpaConfigFile( np.essid, np.wpaSettings, np.wpaKey ) ) {
+ if ( !setWpaClientEnabled( true, np.iface ) ) {
+ setUi(1);
+ std::cout << "CONNECTION FAILED." << std::endl;
+ statusLabel->setText( i18n("Connection failed.") );
+ runCommand( Commands.cmd("disconnect", np ) );
+ return;
+ }
+ }
+ }
+
+ ////////////////////////
+ ///// CONFIGURE IP ADDRESS etc.
+ if (np.dhcp) { //DHCP config
+ QString dhcp_out = runCommand( Commands.cmd("ifconfig_dhcp", np), DhcpTimeout );
+ if ( dhcp_out.contains("::ERR::") && !dhcp_out.contains("bound to ") ) { // 'bound to' is a check for dhclient, which gives some output to stderr even when succeeded
+ if ( dhcpClientRunning() )
+ runCommand( Commands.cmd("kill_dhcp", np) ); //kill any stale DHCP client running (seems it's dhclient only)
+ setUi(1);
+ std::cout << "CONNECTION FAILED." << std::endl;
+ statusLabel->setText( i18n("Connection failed.") );
+ runCommand( Commands.cmd("disconnect", np ) );
+ return;
+ }
+ } else { //manual config
+ runCommand( Commands.cmd("ifconfig_manual", np) );
+ setDNS( np );
+ runCommand( Commands.cmd("route_add", np) );
+ }
+
+ if ( !np.postConnectionCommand.isEmpty() ) {
+ std::cout << "Running post-connection command: " << np.postConnectionCommand << std::endl;
+ statusLabel->setText( i18n("Running post-connection command...") );
+ runCommand( QStringList::split( " ", np.postConnectionCommand ), np.postConnectionTimeout, np.postConnectionDetached );
+ } else
+ std::cout << "No post-connection command specified." << std::endl;
+
+ //////////////////////
+ ///// CHECK CONNECTION
+ statusLabel->setText(i18n("Testing connection..."));
+ usleep(200*1000); //sleep 200ms to make sure all parameters are set.
+ if ( WATools::isConnected(np.iface)) {
+ if (autoQuit)
+ this->close();
+ groupAPs ? setConnectedItem( np.essid ) : setConnectedItem( np.ap );
+ statusLabel->setText( i18n("Successfully connected to '%1'.").arg(np.essid) );
+ setUi(1);
+ } else {
+ std::cout << "CONNECTION FAILED." << std::endl;
+ statusLabel->setText(i18n("Connection failed."));
+ runCommand( Commands.cmd("disconnect", np ) );
+ setConnectedItem( 0 );
+ setUi(1);
+ if (KMessageBox::questionYesNo(0, i18n("Connection failed.\nWould you like to review settings for this network?"), i18n("Review Settings?") , KStdGuiItem::yes(), KStdGuiItem::no(), "ReviewSettings" ) == KMessageBox::Yes)
+ editNetParams();
+ }
+}
+
+void WirelessAssistant::updateConnectedItem()
+{
+ connectedItem->setQuality( WATools::quality() );
+}
+
+void WirelessAssistant::setConnectedItem( const QString & netid )
+{
+ timerConnectionCheck->stop(); //stop timer while changing currentItem
+ if (connectedItem) {
+ timerGui->stop();
+ connectedItem->setConnected( false );
+ connectedItem = 0;
+ }
+ if (!netid.isEmpty()) {
+ QListViewItem* lvi;
+ if (netid.contains(":")) lvi = getItemByAp( netid ); //netid is an AP address
+ else lvi = getItemByEssid( netid );
+ if (lvi) {
+ NetListViewItem* nvi = static_cast<NetListViewItem*>(lvi);
+ nvi->setConnected( true );
+ connectedItem = nvi;
+ netList->sort(); // sort to make sure new connectedItem is 1st.
+ }
+ }
+
+ if (connectedItem) {
+ timerGui->start(2500); //update quality indicator every 2.5seconds
+ }
+ updateConnectButton( netList->selectedItem() );
+ timerConnectionCheck->start(WA_CONNECTION_CHECK_INTERVAL);
+}
+
+void WirelessAssistant::netDisconnect( const bool & quiet )
+{
+ if ( (quiet) || (KMessageBox::warningContinueCancel(0, i18n("<qt><p>You are about to disconnect from '<b>%1</b>'.</p><p>Would you like to continue?<p></qt>").arg(connectedItem->essid()) )== KMessageBox::Continue ) ) {
+ timerConnectionCheck->stop(); //stop while disconnecting.
+
+ if ( !NetParams.preDisconnectionCommand.isEmpty() ) {
+ std::cout << "Running pre-disconnection command: " << NetParams.preDisconnectionCommand << std::endl;
+ statusLabel->setText( i18n("Running pre-disconnection command...") );
+ runCommand( QStringList::split( " ", NetParams.preDisconnectionCommand ), NetParams.preDisconnectionTimeout, NetParams.preDisconnectionDetached );
+ } else
+ std::cout << "No pre-disconnection command specified." << std::endl;
+
+
+ statusLabel->setText( i18n("Disconnecting...") );
+ statusLabel->repaint();
+ setConnectedItem( 0 );
+ if ( NetParams.dhcp ) {
+ if ( dhcpClientRunning() ) {
+ runCommand( Commands.cmd( "kill_dhcp", NetParams ) );
+ statusLabel->setText( i18n("Waiting for DHCP client to shut down...") );
+ statusLabel->repaint();
+ QTimer* tmr = new QTimer();
+ tmr->start(1500, true); //wait 1.5sec for dhcp client to really shutdown, single shot.
+ while ( tmr->isActive() ) {
+ KApplication::eventLoop()->processEvents( QEventLoop::AllEvents );
+ usleep(75*1000); //75msec on Linux
+ }
+ delete tmr;
+ }
+ } else {
+ runCommand( Commands.cmd( "route_del", NetParams ) );
+ }
+ runCommand( Commands.cmd( "disconnect", NetParams ) );
+ WATools::setUp( false, NetParams.iface );
+
+ if ( NetParams.wpa )
+ setWpaClientEnabled( false );
+
+ std::cout << "DISCONNECTED." << std::endl;
+
+ if ( !NetParams.postDisconnectionCommand.isEmpty() ) {
+ std::cout << "Running post-disconnection command: " << NetParams.postDisconnectionCommand << std::endl;
+ statusLabel->setText( i18n("Running post-disconnection command...") );
+ runCommand( QStringList::split( " ", NetParams.postDisconnectionCommand ), NetParams.postDisconnectionTimeout, NetParams.postDisconnectionDetached );
+ } else
+ std::cout << "No post-disconnection command specified." << std::endl;
+
+
+ statusLabel->setText( i18n("Done.") );
+ timerConnectionCheck->start(WA_CONNECTION_CHECK_INTERVAL);
+ } else {
+ statusLabel->setText( i18n("Cancelled.") );
+ }
+}
+
+QListViewItem* WirelessAssistant::getItemByAp( const QString & ap )
+{
+ QListViewItem* lvi = netList->firstChild();
+ while (lvi) {
+ if ( static_cast<NetListViewItem*>(lvi)->
+ ap() == ap ) {
+ break;
+ }
+ lvi = lvi->nextSibling();
+ }
+ return lvi;
+}
+
+QListViewItem* WirelessAssistant::getItemByEssid( const QString & essid )
+{
+ QListViewItem* lvi = netList->firstChild();
+ while (lvi) {
+ if ( static_cast<NetListViewItem*>(lvi)->
+ essid() == essid ) {
+ break;
+ }
+ lvi = lvi->nextSibling();
+ }
+ return lvi;
+}
+
+
+void WirelessAssistant::updateConfiguration(int category)
+{
+ if (category == KApplication::SETTINGS_MOUSE) {
+ setMouseBehaviour();
+ return;
+ }
+ if (category == -1) {
+ autoQuit = checkAutoQuit->isChecked();
+ autoReconnect = checkAutoReconnect->isChecked();
+ autoConnect = checkAutoConnect->isChecked();
+ groupAPs = checkGroupAPs->isChecked();
+ DelayBeforeScanning = spinDelayBeforeScanning->value();
+ DhcpTimeout = spinDhcpTimeout->value();
+ }
+}
+
+void WirelessAssistant::togglePage(bool options)
+{
+ buttonScan->setDisabled(options);
+ buttonConnect->setDisabled(options);
+ if (options) {
+ if (WAConfig::self()->config()->groupList().contains("Notification Messages")>0)
+ buttonEnableAllMessages->setEnabled(true);
+ else
+ buttonEnableAllMessages->setEnabled(false);
+ widgetStack->raiseWidget(optionsPage);
+ } else {
+ widgetStack->raiseWidget(netPage);
+ updateConfiguration(-1);
+ }
+}
+
+void WirelessAssistant::enableAllMessages()
+{
+ KMessageBox::enableAllMessages();
+ buttonEnableAllMessages->setEnabled( false );
+}
+
+void WirelessAssistant::setMouseBehaviour()
+{
+ if ( KGlobalSettings::singleClick() ) {
+ disconnect( netList, SIGNAL(selectionChanged(QListViewItem*)),
+ this, SLOT(updateConnectButton(QListViewItem*)) );
+ disconnect( netList, SIGNAL(doubleClicked(QListViewItem*, const QPoint &, int)),
+ this, SLOT(itemAction()) );
+ connect( netList, SIGNAL(clicked(QListViewItem*, const QPoint &, int)),
+ this, SLOT(itemAction()) );
+ buttonConnect->hide();
+ } else {
+ disconnect( netList, SIGNAL(clicked(QListViewItem*, const QPoint &, int)),
+ this, SLOT(itemAction()) );
+
+ connect( netList, SIGNAL(selectionChanged(QListViewItem*)),
+ this, SLOT(updateConnectButton(QListViewItem*)) );
+ connect( netList, SIGNAL(doubleClicked(QListViewItem*, const QPoint &, int)),
+ this, SLOT(itemAction()) );
+ buttonConnect->show();
+ }
+}
+
+void WirelessAssistant::updateConnectButton(QListViewItem* lvi)
+{
+ QToolTip::remove
+ (buttonConnect);
+ if ( lvi == connectedItem ) {
+ buttonConnect->setText( i18n("&Disconnect") );
+ QToolTip::add
+ ( buttonConnect, i18n("Disconnect from the selected network") );
+
+ } else {
+ buttonConnect->setText( i18n("&Connect") );
+ QToolTip::add
+ ( buttonConnect, i18n("Connect to the selected network") );
+
+ }
+}
+
+void WirelessAssistant::setDev( const QString & ifname)
+{
+ NetParams.iface = ifname;
+ WATools::setInterface( ifname );
+ std::cout << "Selected interface: " << ifname << std::endl;
+ netScan();
+}
+
+QString WirelessAssistant::runCommand( const QStringList & cmd, int timeout, bool detached )
+{
+ if (cmd.isEmpty())
+ return QString::null;
+
+ // a very basic and easy-to-workaround attepmt to restrict using dangerous commands via custom commands setting. This *REALLY* needs a working solution.
+ if ( cmd[0] == "rm" || cmd[0] == "mv" || cmd[0] == "cp" || cmd[0] == "ln" ) return QString::null;
+
+ QProcess* p = new QProcess( this );
+ p->setArguments( cmd );
+
+ p->start();
+ if (detached) {
+ p = 0;
+ return QString::null;
+ }
+
+ QTimer* timerProc = new QTimer(); //timeout timer
+ if ( timeout>0 && !detached ) {
+ connect( timerProc, SIGNAL(timeout()), p, SLOT(kill()) );
+ timerProc->start(timeout*1000); //convert sec to msec
+ }
+
+ connect(buttonClose, SIGNAL(clicked()),
+ p, SLOT(kill()) );
+ int i = 0;
+
+ while ( p->isRunning() ) { // PROCESS USER EVENTS
+ KApplication::eventLoop()->processEvents( QEventLoop::AllEvents );
+ usleep(75*1000); //75msec on Linux (75000msec on Windows...)
+ if (i==27) { // ca 2sec have passed and the process is still running. Replace the 'Close' button with 'Stop'.
+ disconnect(buttonClose, SIGNAL(clicked()),
+ this, SLOT(close()) );
+ buttonClose->setIconSet( SmallIconSet("stop") );
+ buttonClose->setText( i18n("&Stop") );
+ QToolTip::remove
+ (buttonClose);
+ QToolTip::add
+ ( buttonClose, i18n("Terminate current process\n(%1)").arg( p->arguments().join(" ") ) );
+ }
+ i++;
+ }
+
+ disconnect(buttonClose, SIGNAL(clicked()),
+ p, SLOT(kill()) );
+ if (i>27) {//set 'stop' back to 'close' if needed
+ connect(buttonClose, SIGNAL(clicked()),
+ this, SLOT(close()) );
+ buttonClose->setIconSet( SmallIconSet("fileclose") );
+ buttonClose->setText( i18n("&Quit") );
+ QToolTip::remove
+ (buttonClose);
+ QToolTip::add
+ ( buttonClose, i18n("Quit the application") );
+ }
+
+ if (timerProc->isActive())
+ timerProc->stop();
+ delete timerProc;
+ QString e = QString( p->readStderr() );
+ QString o = QString( p->readStdout() );
+ if (!p->normalExit()) {
+ o.append("::ERR::killed");
+ //std::cout << "Process terminated (timed out)." << std::endl; //too much output when checking for internet when it's not available.
+ }
+ delete p;
+
+ if (!e.isEmpty()) {
+ std::cout << "==>stderr: " << e;// << std::endl;
+ o.append("::ERR::");
+ o.append(e);
+ }
+
+ return o;
+}
+
+void WirelessAssistant::setUi(int uiState)
+{
+
+ if (uiState==0) {
+ devCombo->setEnabled( false );
+ buttonScan->setEnabled( false );
+ buttonConnect->setEnabled( false );
+ buttonOptions->setEnabled( false );
+ KApplication::setOverrideCursor( QCursor(Qt::BusyCursor) );
+ } else {
+ if (devCombo->count() > 0) {
+ devCombo->setEnabled( true );
+ buttonScan->setEnabled( true );
+ }
+ if (netList->childCount() > 0)
+ buttonConnect->setEnabled( true );
+ buttonOptions->setEnabled( true );
+ KApplication::restoreOverrideCursor();
+ }
+}
+
+void WirelessAssistant::showItemContextMenu( QListViewItem* i, const QPoint& p, int c )
+{
+ if (!i)
+ return;
+
+ NetListViewItem *nvi = static_cast<NetListViewItem*>(i);
+
+ QString search = nvi->ap();
+ if (search == "any") search = nvi->essid();
+ bool isConfigured = setNetParamsFromConfig(search);
+
+ KPopupMenu *icm = new KPopupMenu();
+ icm->insertTitle(nvi->essid());
+ if (isConfigured) {
+ if (nvi->isConnected()) {
+ icm->insertItem( SmallIcon("connect_no"), i18n("Disconnect..."), this, SLOT(netDisconnect()) );
+ //icm->insertItem( SmallIcon("reload"), i18n("Reconnect"), this, SLOT(netConnect()) );
+ } else
+ icm->insertItem( SmallIcon("connect_creating"), i18n("Connect"), this, SLOT(netConnect()) );
+ icm->insertSeparator();
+ icm->insertItem(i18n("Forget Settings..."), this, SLOT(removeNetParams()) );
+ icm->insertItem(i18n("Edit Settings..."), this, SLOT(editNetParams()) );
+ } else {
+ if (nvi->isConnected()) {
+ icm->insertItem( SmallIcon("connect_no"), i18n("Disconnect..."), this, SLOT(netDisconnect()) );
+ //icm->insertItem( SmallIcon("reload"), i18n("Configure and Reconnect..."), this, SLOT(netConnect()) );
+ } else
+ icm->insertItem( SmallIcon("connect_creating"), i18n("Configure and Connect..."), this, SLOT(netConnect()) );
+ }
+ icm->exec( QCursor::pos() );
+}
+
+void WirelessAssistant::editNetParams()
+{
+ setNetParamsFromList( netList->selectedItem() ); //prepare NetParams
+ if (NetParams.ap!="any") setNetParamsFromConfig( NetParams.ap ); //prepare NetParams
+ else setNetParamsFromConfig( NetParams.essid );
+
+ ui_NetParamsEdit *netedit = new ui_NetParamsEdit();
+ netedit->setValues( NetParams );
+ netedit->setCaption( i18n("%1 Settings").arg(NetParams.essid) );
+ netedit->exec();
+ if (netedit->result() == QDialog::Rejected) {
+ delete netedit;
+ return;
+ } else { //accepted
+ NetParams = netedit->readNetParams( NetParams );
+ updateNetParams();
+ }
+}
+
+void WirelessAssistant::setNetListColumns()
+{
+ int realWidth = netList->viewportSize( netList->contentsWidth(), netList->contentsHeight() ).width(); //calculate actual width taking scrollbars into account
+ int essidWidth = realWidth - netList->columnWidth(1) - netList->columnWidth(2) - netList->columnWidth(3);
+
+ netList->setColumnWidth(0, essidWidth);
+ netList->triggerUpdate();
+}
+
+bool WirelessAssistant::dhcpClientRunning()
+{
+ QStringList pidPaths;
+ QString pidFile;
+ pidPaths << "/etc/" << "/etc/dhcpc/" << "/var/run/";
+ if ( Commands.dhcpClient=="dhcpcd" )
+ pidFile = QString("dhcpcd-%1.pid").arg(NetParams.iface);
+ else
+ pidFile = QString("dhclient.pid");
+
+ for ( QStringList::Iterator it = pidPaths.begin(); it != pidPaths.end(); ++it ) {
+ if ( QFile( QString(*it).append(pidFile) ).exists() ) {
+ std::cout << "Running DHCP client found." << std::endl;
+ return true;
+ }
+ }
+ std::cout << "No DHCP client running." << std::endl;
+ return false;
+}
+
+QStringList WirelessAssistant::interfaceList()
+{
+ QDir d("/sys/class/net");
+ QStringList ifList = d.entryList( QDir::Dirs );
+ ifList.remove("."); ifList.remove(".."); ifList.remove("lo");
+ std::cout << "All interfaces: " << ifList.join(", ") << std::endl;
+ for (QStringList::Iterator nps = ifList.begin(); nps != ifList.end(); nps++) {
+ const char* i = *nps;
+ bool w = WATools::isWireless( i );
+ if ( !WATools::isWireless( (const char*)*nps ) ) {
+ nps = ifList.remove( nps ); nps--;
+ }
+ }
+ return ifList;
+}
+
+QString WirelessAssistant::getVal(const QString & str, const QString & rxs)
+{
+ QRegExp rx(rxs);
+ rx.search(str);
+ return rx.cap(1).stripWhiteSpace();
+}
+
+bool WirelessAssistant::generateWpaConfigFile( const QString& essid, const QStringList& wpaSettings, const QString& wpaKey )
+{
+ // 0 WPA version (1 or 2), 1 group, 2 pairwise, 3 suite
+ if ( wpaSettings.isEmpty() ) return QString();
+ QString c = "ctrl_interface=/var/run/wpa_supplicant\nnetwork={\nscan_ssid=0\nssid=\""; //fast_reauth=1\n
+ c.append(essid).append("\"\n");
+
+ // WPA version
+ c.append("proto=").append(wpaSettings[0]).append("\n");
+
+ //WPA authentication suite
+ c.append("key_mgmt=");
+ if ( wpaSettings[3].contains("PSK") ) c.append("WPA-PSK\n");
+ else return QString(); // not supported
+
+ //WPA pairwise cipher
+ c.append("pairwise=");
+ c.append( wpaSettings[2] ).append("\n");
+
+ //WPA group cipher
+ c.append("group=");
+ c.append( wpaSettings[1] ).append("\n");
+
+ //WPA key
+ QString k = QString();
+ if (wpaKey.left(2)=="s:") { // PASSPHRASE
+ k.append("\"");
+ k.append( wpaKey.right( wpaKey.length() - 2 ) );
+ k.append("\"\n");
+ } else
+ k.append( wpaKey ).append("\n"); // HEX KEY
+
+ c.append("psk=").append(k);
+
+ c.append("}\n");
+ //std::cout << "WPA Config:\n" << c << std::endl;
+
+// # WPA protected network, supply your own ESSID and WPAPSK here:
+// network={
+// scan_ssid=0
+// ssid="your_essid_here"
+// proto=WPA
+// key_mgmt=WPA-PSK
+// pairwise=CCMP TKIP
+// group=CCMP TKIP WEP104 WEP40
+// psk=your_psk_here
+// }
+
+ QFile file( wpaConfigFile );
+ if (file.exists()) file.remove();
+ if ( file.open( IO_WriteOnly ) ) {
+ QTextStream stream( &file );
+ stream << c;
+ file.close();
+ //std::cout << "Wrote WPA config: " << wpaConfigFile << std::endl;
+ return 1;
+ } else
+ return 0;
+}
+
+bool WirelessAssistant::setWpaClientEnabled( bool e, const QString& iface, QString driver )
+{
+ if (!e) {
+ if ( runCommand( QStringList(Commands.wpa_cli) << QString("-i%1").arg(NetParams.iface) << "terminate" ).contains("OK") ) {
+ QFile( wpaConfigFile ).remove();
+ return 1;
+ } else
+ return 0; // wpa client was not running.
+ }
+
+ if ( !runCommand( QStringList(Commands.wpa_cli) << QString("-i%1").arg(NetParams.iface) << "status" ).contains("Failed to connect") ) {
+ std::cout << "WPA client already running. Reconfiguring..." << std::endl;
+ runCommand( QStringList(Commands.wpa_cli) << "reconfigure" );
+ } else {
+ if ( driver.isEmpty() ) { //detect needed driver
+ QString k = WATools::kernelModule( iface );
+ if ( k.contains("hermes") ) driver = "hermes";
+ else if ( k.contains("atmel") ) driver = "atmel";
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
+ else if ( k.contains("ipw") ) driver = "ipw"; //wext should be used for kernels newer than 2.6.12
+#endif
+ //Commented out, because ndiswrapper newer than 1.13 works with wext driver.
+ //else if ( k.contains("ndiswrapper") ) driver = "ndiswrapper";
+ //Commented out, because madwifi-ng works with wext driver.
+ //else if ( k.contains("ath") ) driver = "madwifi";
+ else driver = "wext";
+ std::cout << "Using wpa_supplicant driver: " << driver << std::endl;
+ }
+
+ QProcess* wp = new QProcess( this );
+ wp->clearArguments();
+ wp->addArgument( Commands.wpa_supplicant );
+ wp->addArgument( "-W" ); //wait for control interface
+ wp->addArgument( QString("-D%1").arg(driver) );
+ wp->addArgument( QString("-i%1").arg(iface) );
+ wp->addArgument( QString("-c%1").arg(wpaConfigFile) );
+ //std::cout << "Starting WPA client: " << wp->arguments().join(" ") << std::endl;
+ if ( !wp->start() ) {
+ std::cout << "Failed to start WPA client." << std::endl;
+ return 0;
+ }
+ wp = 0;
+ std::cout << "WPA client started. Waiting for status..." << std::endl;
+ }
+
+ usleep(200*1000); //200msec for wpa_supplicant to initiate
+
+ QString o;
+ int i = 0;
+ while ( !(o =runCommand( QStringList(Commands.wpa_cli) << QString("-i%1").arg(NetParams.iface) << "status" )).contains("Failed to connect") ) {
+ for (int c = 0; c < 15; c++) {
+ usleep(75*1000); //75msec
+ KApplication::eventLoop()->processEvents( QEventLoop::AllEvents );
+ i++;
+ }
+ if (i>400) { //more than 30sec have passed
+ runCommand( QStringList(Commands.wpa_cli) << QString("-i%1").arg(NetParams.iface) << "terminate" );
+ return 0;
+ }
+ if ( o.contains("wpa_state=COMPLETED") ) {
+ std::cout << "WPA Authorisation successful." << std::endl;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+bool WirelessAssistant::close()
+{
+ updateConfiguration(-1); //read values from setingsPage;
+ WAConfig::self()->writeConfig();
+ std::cout << "Application options saved." << std::endl;
+ WATools::cleanup();
+ std::cout << "Kernel socket closed." << std::endl;
+ return QWidget::close();
+}
+
+
+#include "wlassistant.moc"