You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1265 lines
50 KiB
1265 lines
50 KiB
/***************************************************************************
|
|
* Copyright (C) 2005 by Pawel Nawrocki *
|
|
* pnawrocki@interia.pl *
|
|
* *
|
|
* 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 <tqregexp.h>
|
|
#include <tqlabel.h>
|
|
#include <tqprocess.h>
|
|
#include <tqcursor.h>
|
|
#include <tqeventloop.h>
|
|
#include <tqtimer.h>
|
|
#include <tqcheckbox.h>
|
|
#include <tqspinbox.h>
|
|
#include <tqwidgetstack.h>
|
|
#include <tqtooltip.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(TQWidget* tqparent, const char* name, bool modal, WFlags fl)
|
|
: mainWindow(tqparent,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, TQT_SIGNAL(clicked()),
|
|
this, TQT_SLOT(netScan()) );
|
|
|
|
connect( buttonConnect, TQT_SIGNAL(clicked()),
|
|
this, TQT_SLOT(itemAction()) );
|
|
|
|
connect( buttonClose, TQT_SIGNAL(clicked()),
|
|
this, TQT_SLOT(close()) );
|
|
|
|
connect( devCombo, TQT_SIGNAL(activated( const TQString & )),
|
|
this, TQT_SLOT(setDev( const TQString & )) );
|
|
|
|
connect( netList, TQT_SIGNAL(rightButtonPressed( TQListViewItem*, const TQPoint&, int )),
|
|
TQT_SLOT(showItemContextMenu( TQListViewItem*, const TQPoint&, int )) );
|
|
|
|
/// Settings Widget
|
|
connect( buttonOptions, TQT_SIGNAL(toggled(bool)),
|
|
this, TQT_SLOT(togglePage(bool)) );
|
|
|
|
connect( buttonEnableAllMessages, TQT_SIGNAL(clicked()),
|
|
this, TQT_SLOT(enableAllMessages()) );
|
|
|
|
/// Global KDE Options
|
|
connect( KApplication::kApplication(), TQT_SIGNAL(settingsChanged(int)),
|
|
this, TQT_SLOT(updateConfiguration(int)) );
|
|
|
|
setMouseBehaviour();
|
|
|
|
TQTimer::singleShot(10, this, TQT_SLOT(init()) ); //WAIT FOR THE UI TO BE READY BEFORE FURTHER SETUP (msec)
|
|
}
|
|
|
|
WirelessAssistant::~WirelessAssistant()
|
|
{}
|
|
|
|
/*$SPECIALIZATION$*/
|
|
|
|
|
|
void WirelessAssistant::init()
|
|
{
|
|
statusLabel->setText(i18n("Initializing..."));
|
|
statusLabel->tqrepaint();
|
|
|
|
////////////////////////////////////////
|
|
///// CHECK FOR SYSFS (KERNEL 2.6) /////
|
|
if ( !TQFile::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 /////
|
|
TQStringList 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 (!TQFileInfo("/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 TQTimer();
|
|
timerConnectionCheck = new TQTimer();
|
|
connect( timerGui, TQT_SIGNAL(timeout()), TQT_SLOT(updateConnectedItem()) );
|
|
connect( timerConnectionCheck, TQT_SIGNAL(timeout()), TQT_SLOT(checkConnectiontqStatus()) );
|
|
|
|
////////////////////////
|
|
///// 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.").tqarg(Commands.notFound.join("', '")) );
|
|
close();
|
|
return;
|
|
}
|
|
|
|
KStandardDirs standardDirs;
|
|
wpaConfigFile = standardDirs.saveLocation("config").append("wlassistantwpa");
|
|
|
|
///////////////////////////////////////
|
|
///// SCAN FOR AVAILABLE NETWORKS /////
|
|
if ( autoConnect )
|
|
TQTimer::singleShot( 0, this, TQT_SLOT(netAutoConnect()) );
|
|
else
|
|
TQTimer::singleShot( 0, this, TQT_SLOT(netScan()) );
|
|
}
|
|
|
|
void WirelessAssistant::checkConnectiontqStatus()
|
|
{
|
|
TQListViewItem* 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?").tqarg(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());
|
|
TQString ap = nvi->ap(); TQString essid = nvi->essid();
|
|
for (TQStringList::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>").tqarg(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 )
|
|
{
|
|
TQFile f("/etc/resolv.conf");
|
|
if (f.open( IO_WriteOnly | IO_Truncate )) {
|
|
TQTextStream s( &f );
|
|
if (!np.domain.isEmpty()) {
|
|
s << TQString("domain " + np.domain + "\n");
|
|
std::cout << "resolv.conf: domain " << np.domain << std::endl;
|
|
}
|
|
if (!np.dns1.isEmpty()) {
|
|
s << TQString("nameserver " + np.dns1 + "\n");
|
|
std::cout << "resolv.conf: nameserver " << np.dns1 << std::endl;
|
|
}
|
|
if (!np.dns2.isEmpty()) {
|
|
s << TQString("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>").tqarg(f.name()) );
|
|
}
|
|
}
|
|
|
|
void WirelessAssistant::netScan()
|
|
{
|
|
timerConnectionCheck->stop(); //stop while scanning.
|
|
netScan( NetParams );
|
|
if (netList->childCount() > 0) {
|
|
TQTimer::singleShot( 0, this, TQT_SLOT(checkConnectiontqStatus()) );
|
|
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...").tqarg(np.iface));
|
|
//runCommand( Commands.cmd("ifup",np) );
|
|
WATools::setUp(true, np.iface);
|
|
if (DelayBeforeScanning>0) {
|
|
statusLabel->setText(i18n("Waiting before scanning..."));
|
|
statusLabel->tqrepaint();
|
|
KApplication::eventLoop()->processEvents( TQEventLoop::ExcludeUserInput );
|
|
usleep(DelayBeforeScanning * 1000000); // delay * 1000ms
|
|
}
|
|
}
|
|
|
|
statusLabel->setText(i18n("Scanning..."));
|
|
statusLabel->tqrepaint();
|
|
|
|
netList->clear();
|
|
|
|
TQString result;
|
|
statusLabel->setText(i18n("Scanning..."));
|
|
result = runCommand( Commands.cmd("scan",np) );
|
|
|
|
parseScan( result );
|
|
|
|
if (netList->childCount() > 0) {
|
|
std::cout << "Networks found: " << TQString::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 TQString & output )
|
|
{
|
|
TQString essid;
|
|
TQStringList essidList;
|
|
TQString channel;
|
|
TQString mode;
|
|
int qualInt;
|
|
bool enc; //default to false
|
|
bool hidden; //default to false
|
|
TQString ap;
|
|
|
|
// security parameters
|
|
bool wpa;
|
|
TQStringList wpaSettings;
|
|
//TQString wpaVersion, wpaGroupCipher, wpaPairwiseCipher, wpaAuthenticationSuite;
|
|
|
|
|
|
bool ok_channel = true; //does iwlist return channel?
|
|
TQString 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 TQUALITY
|
|
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( TQListViewItem* 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 TQString & s )
|
|
{
|
|
for (TQStringList::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()
|
|
{
|
|
TQListViewItem* 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) );
|
|
TQString 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 );
|
|
TQString 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>").tqarg(NetParams.essid) );
|
|
timerConnectionCheck->start(WA_CONNECTION_CHECK_INTERVAL); //resume connection checking
|
|
return;
|
|
}
|
|
TQString 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").tqarg(NetParams.essid) );
|
|
netwiz->setEssidEnabled( NetParams.hiddenEssid );
|
|
netwiz->setWepEnabled( NetParams.wep );
|
|
netwiz->setWpaEnabled( NetParams.wpa, NetParams.wpaSettings );
|
|
netwiz->exec();
|
|
if (netwiz->result()==TQDialog::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 (TQStringList::Iterator nps = NetParamsList.begin(); nps != NetParamsList.end(); nps++) {
|
|
if ( (*nps).section(",",2,2)==NetParams.ap ) {
|
|
TQString 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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TQString WirelessAssistant::matchEssidForAp( const TQString & ap )
|
|
{
|
|
for (TQStringList::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( TQStringList::split( " ", np.preConnectionCommand ), np.preConnectionTimeout, np.preConnectionDetached );
|
|
} else
|
|
std::cout << "No pre-connection command specified." << std::endl;
|
|
|
|
|
|
statusLabel->setText( i18n("Connecting to '%1'...").tqarg(np.essid) );
|
|
statusLabel->tqrepaint();
|
|
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
|
|
TQString 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( TQStringList::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'.").tqarg(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 TQString & netid )
|
|
{
|
|
timerConnectionCheck->stop(); //stop timer while changing currentItem
|
|
if (connectedItem) {
|
|
timerGui->stop();
|
|
connectedItem->setConnected( false );
|
|
connectedItem = 0;
|
|
}
|
|
if (!netid.isEmpty()) {
|
|
TQListViewItem* 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>").tqarg(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( TQStringList::split( " ", NetParams.preDisconnectionCommand ), NetParams.preDisconnectionTimeout, NetParams.preDisconnectionDetached );
|
|
} else
|
|
std::cout << "No pre-disconnection command specified." << std::endl;
|
|
|
|
|
|
statusLabel->setText( i18n("Disconnecting...") );
|
|
statusLabel->tqrepaint();
|
|
setConnectedItem( 0 );
|
|
if ( NetParams.dhcp ) {
|
|
if ( dhcpClientRunning() ) {
|
|
runCommand( Commands.cmd( "kill_dhcp", NetParams ) );
|
|
statusLabel->setText( i18n("Waiting for DHCP client to shut down...") );
|
|
statusLabel->tqrepaint();
|
|
TQTimer* tmr = new TQTimer();
|
|
tmr->start(1500, true); //wait 1.5sec for dhcp client to really shutdown, single shot.
|
|
while ( tmr->isActive() ) {
|
|
KApplication::eventLoop()->processEvents( TQEventLoop::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( TQStringList::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.") );
|
|
}
|
|
}
|
|
|
|
TQListViewItem* WirelessAssistant::getItemByAp( const TQString & ap )
|
|
{
|
|
TQListViewItem* lvi = netList->firstChild();
|
|
while (lvi) {
|
|
if ( static_cast<NetListViewItem*>(lvi)->
|
|
ap() == ap ) {
|
|
break;
|
|
}
|
|
lvi = lvi->nextSibling();
|
|
}
|
|
return lvi;
|
|
}
|
|
|
|
TQListViewItem* WirelessAssistant::getItemByEssid( const TQString & essid )
|
|
{
|
|
TQListViewItem* 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, TQT_SIGNAL(selectionChanged(TQListViewItem*)),
|
|
this, TQT_SLOT(updateConnectButton(TQListViewItem*)) );
|
|
disconnect( netList, TQT_SIGNAL(doubleClicked(TQListViewItem*, const TQPoint &, int)),
|
|
this, TQT_SLOT(itemAction()) );
|
|
connect( netList, TQT_SIGNAL(clicked(TQListViewItem*, const TQPoint &, int)),
|
|
this, TQT_SLOT(itemAction()) );
|
|
buttonConnect->hide();
|
|
} else {
|
|
disconnect( netList, TQT_SIGNAL(clicked(TQListViewItem*, const TQPoint &, int)),
|
|
this, TQT_SLOT(itemAction()) );
|
|
|
|
connect( netList, TQT_SIGNAL(selectionChanged(TQListViewItem*)),
|
|
this, TQT_SLOT(updateConnectButton(TQListViewItem*)) );
|
|
connect( netList, TQT_SIGNAL(doubleClicked(TQListViewItem*, const TQPoint &, int)),
|
|
this, TQT_SLOT(itemAction()) );
|
|
buttonConnect->show();
|
|
}
|
|
}
|
|
|
|
void WirelessAssistant::updateConnectButton(TQListViewItem* lvi)
|
|
{
|
|
TQToolTip::remove
|
|
(buttonConnect);
|
|
if ( lvi == connectedItem ) {
|
|
buttonConnect->setText( i18n("&Disconnect") );
|
|
TQToolTip::add
|
|
( buttonConnect, i18n("Disconnect from the selected network") );
|
|
|
|
} else {
|
|
buttonConnect->setText( i18n("&Connect") );
|
|
TQToolTip::add
|
|
( buttonConnect, i18n("Connect to the selected network") );
|
|
|
|
}
|
|
}
|
|
|
|
void WirelessAssistant::setDev( const TQString & ifname)
|
|
{
|
|
NetParams.iface = ifname;
|
|
WATools::setInterface( ifname );
|
|
std::cout << "Selected interface: " << ifname << std::endl;
|
|
netScan();
|
|
}
|
|
|
|
TQString WirelessAssistant::runCommand( const TQStringList & cmd, int timeout, bool detached )
|
|
{
|
|
if (cmd.isEmpty())
|
|
return TQString();
|
|
|
|
// 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 TQString();
|
|
|
|
TQProcess* p = new TQProcess( TQT_TQOBJECT(this) );
|
|
p->setArguments( cmd );
|
|
|
|
p->start();
|
|
if (detached) {
|
|
p = 0;
|
|
return TQString();
|
|
}
|
|
|
|
TQTimer* timerProc = new TQTimer(); //timeout timer
|
|
if ( timeout>0 && !detached ) {
|
|
connect( timerProc, TQT_SIGNAL(timeout()), p, TQT_SLOT(kill()) );
|
|
timerProc->start(timeout*1000); //convert sec to msec
|
|
}
|
|
|
|
connect(buttonClose, TQT_SIGNAL(clicked()),
|
|
p, TQT_SLOT(kill()) );
|
|
int i = 0;
|
|
|
|
while ( p->isRunning() ) { // PROCESS USER EVENTS
|
|
KApplication::eventLoop()->processEvents( TQEventLoop::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, TQT_SIGNAL(clicked()),
|
|
this, TQT_SLOT(close()) );
|
|
buttonClose->setIconSet( SmallIconSet("stop") );
|
|
buttonClose->setText( i18n("&Stop") );
|
|
TQToolTip::remove
|
|
(buttonClose);
|
|
TQToolTip::add
|
|
( buttonClose, i18n("Terminate current process\n(%1)").tqarg( p->arguments().join(" ") ) );
|
|
}
|
|
i++;
|
|
}
|
|
|
|
disconnect(buttonClose, TQT_SIGNAL(clicked()),
|
|
p, TQT_SLOT(kill()) );
|
|
if (i>27) {//set 'stop' back to 'close' if needed
|
|
connect(buttonClose, TQT_SIGNAL(clicked()),
|
|
this, TQT_SLOT(close()) );
|
|
buttonClose->setIconSet( SmallIconSet("fileclose") );
|
|
buttonClose->setText( i18n("&Quit") );
|
|
TQToolTip::remove
|
|
(buttonClose);
|
|
TQToolTip::add
|
|
( buttonClose, i18n("Quit the application") );
|
|
}
|
|
|
|
if (timerProc->isActive())
|
|
timerProc->stop();
|
|
delete timerProc;
|
|
TQString e = TQString( p->readStderr() );
|
|
TQString o = TQString( 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( TQCursor(TQt::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( TQListViewItem* i, const TQPoint& p, int c )
|
|
{
|
|
if (!i)
|
|
return;
|
|
|
|
NetListViewItem *nvi = static_cast<NetListViewItem*>(i);
|
|
|
|
TQString 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, TQT_SLOT(netDisconnect()) );
|
|
//icm->insertItem( SmallIcon("reload"), i18n("Reconnect"), this, TQT_SLOT(netConnect()) );
|
|
} else
|
|
icm->insertItem( SmallIcon("connect_creating"), i18n("Connect"), this, TQT_SLOT(netConnect()) );
|
|
icm->insertSeparator();
|
|
icm->insertItem(i18n("Forget Settings..."), this, TQT_SLOT(removeNetParams()) );
|
|
icm->insertItem(i18n("Edit Settings..."), this, TQT_SLOT(editNetParams()) );
|
|
} else {
|
|
if (nvi->isConnected()) {
|
|
icm->insertItem( SmallIcon("connect_no"), i18n("Disconnect..."), this, TQT_SLOT(netDisconnect()) );
|
|
//icm->insertItem( SmallIcon("reload"), i18n("Configure and Reconnect..."), this, TQT_SLOT(netConnect()) );
|
|
} else
|
|
icm->insertItem( SmallIcon("connect_creating"), i18n("Configure and Connect..."), this, TQT_SLOT(netConnect()) );
|
|
}
|
|
icm->exec( TQCursor::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").tqarg(NetParams.essid) );
|
|
netedit->exec();
|
|
if (netedit->result() == TQDialog::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()
|
|
{
|
|
TQStringList pidPaths;
|
|
TQString pidFile;
|
|
pidPaths << "/etc/" << "/etc/dhcpc/" << "/var/run/";
|
|
if ( Commands.dhcpClient=="dhcpcd" )
|
|
pidFile = TQString("dhcpcd-%1.pid").tqarg(NetParams.iface);
|
|
else
|
|
pidFile = TQString("dhclient.pid");
|
|
|
|
for ( TQStringList::Iterator it = pidPaths.begin(); it != pidPaths.end(); ++it ) {
|
|
if ( TQFile( TQString(*it).append(pidFile) ).exists() ) {
|
|
std::cout << "Running DHCP client found." << std::endl;
|
|
return true;
|
|
}
|
|
}
|
|
std::cout << "No DHCP client running." << std::endl;
|
|
return false;
|
|
}
|
|
|
|
TQStringList WirelessAssistant::interfaceList()
|
|
{
|
|
TQDir d("/sys/class/net");
|
|
TQStringList ifList = d.entryList( TQDir::Dirs );
|
|
ifList.remove("."); ifList.remove(".."); ifList.remove("lo");
|
|
std::cout << "All interfaces: " << ifList.join(", ") << std::endl;
|
|
for (TQStringList::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;
|
|
}
|
|
|
|
TQString WirelessAssistant::getVal(const TQString & str, const TQString & rxs)
|
|
{
|
|
TQRegExp rx(rxs);
|
|
rx.search(str);
|
|
return rx.cap(1).stripWhiteSpace();
|
|
}
|
|
|
|
bool WirelessAssistant::generateWpaConfigFile( const TQString& essid, const TQStringList& wpaSettings, const TQString& wpaKey )
|
|
{
|
|
// 0 WPA version (1 or 2), 1 group, 2 pairwise, 3 suite
|
|
if ( wpaSettings.isEmpty() ) return TQString();
|
|
TQString 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 TQString(); // 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
|
|
TQString k = TQString();
|
|
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
|
|
// }
|
|
|
|
TQFile file( wpaConfigFile );
|
|
if (file.exists()) file.remove();
|
|
if ( file.open( IO_WriteOnly ) ) {
|
|
TQTextStream 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 TQString& iface, TQString driver )
|
|
{
|
|
if (!e) {
|
|
if ( runCommand( TQStringList(Commands.wpa_cli) << TQString("-i%1").tqarg(NetParams.iface) << "terminate" ).contains("OK") ) {
|
|
TQFile( wpaConfigFile ).remove();
|
|
return 1;
|
|
} else
|
|
return 0; // wpa client was not running.
|
|
}
|
|
|
|
if ( !runCommand( TQStringList(Commands.wpa_cli) << TQString("-i%1").tqarg(NetParams.iface) << "status" ).contains("Failed to connect") ) {
|
|
std::cout << "WPA client already running. Reconfiguring..." << std::endl;
|
|
runCommand( TQStringList(Commands.wpa_cli) << "reconfigure" );
|
|
} else {
|
|
if ( driver.isEmpty() ) { //detect needed driver
|
|
TQString 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;
|
|
}
|
|
|
|
TQProcess* wp = new TQProcess( TQT_TQOBJECT(this) );
|
|
wp->clearArguments();
|
|
wp->addArgument( Commands.wpa_supplicant );
|
|
wp->addArgument( "-W" ); //wait for control interface
|
|
wp->addArgument( TQString("-D%1").tqarg(driver) );
|
|
wp->addArgument( TQString("-i%1").tqarg(iface) );
|
|
wp->addArgument( TQString("-c%1").tqarg(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
|
|
|
|
TQString o;
|
|
int i = 0;
|
|
while ( !(o =runCommand( TQStringList(Commands.wpa_cli) << TQString("-i%1").tqarg(NetParams.iface) << "status" )).contains("Failed to connect") ) {
|
|
for (int c = 0; c < 15; c++) {
|
|
usleep(75*1000); //75msec
|
|
KApplication::eventLoop()->processEvents( TQEventLoop::AllEvents );
|
|
i++;
|
|
}
|
|
if (i>400) { //more than 30sec have passed
|
|
runCommand( TQStringList(Commands.wpa_cli) << TQString("-i%1").tqarg(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 TQWidget::close();
|
|
}
|
|
|
|
|
|
#include "wlassistant.moc"
|