summaryrefslogtreecommitdiffstats
path: root/src/plugins/bearer/corewlan
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commit38be0d13830efd2d98281c645c3a60afe05ffece (patch)
tree6ea73f3ec77f7d153333779883e8120f82820abe /src/plugins/bearer/corewlan
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'src/plugins/bearer/corewlan')
-rw-r--r--src/plugins/bearer/corewlan/corewlan.pro25
-rw-r--r--src/plugins/bearer/corewlan/main.cpp88
-rw-r--r--src/plugins/bearer/corewlan/qcorewlanengine.h147
-rw-r--r--src/plugins/bearer/corewlan/qcorewlanengine.mm946
4 files changed, 1206 insertions, 0 deletions
diff --git a/src/plugins/bearer/corewlan/corewlan.pro b/src/plugins/bearer/corewlan/corewlan.pro
new file mode 100644
index 0000000000..90078e9290
--- /dev/null
+++ b/src/plugins/bearer/corewlan/corewlan.pro
@@ -0,0 +1,25 @@
+TARGET = qcorewlanbearer
+include(../../qpluginbase.pri)
+
+QT = core network
+LIBS += -framework Foundation -framework SystemConfiguration
+
+contains(QT_CONFIG, corewlan) {
+ isEmpty(QMAKE_MAC_SDK)|contains(QMAKE_MAC_SDK, "/Developer/SDKs/MacOSX10.6.sdk") {
+ LIBS += -framework CoreWLAN -framework Security
+ DEFINES += MAC_SDK_10_6
+ }
+}
+
+HEADERS += qcorewlanengine.h \
+ ../qnetworksession_impl.h \
+ ../qbearerengine_impl.h
+
+SOURCES += main.cpp \
+ ../qnetworksession_impl.cpp
+
+OBJECTIVE_SOURCES += qcorewlanengine.mm
+
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/bearer
+target.path += $$[QT_INSTALL_PLUGINS]/bearer
+INSTALLS += target
diff --git a/src/plugins/bearer/corewlan/main.cpp b/src/plugins/bearer/corewlan/main.cpp
new file mode 100644
index 0000000000..7a5e7e30bd
--- /dev/null
+++ b/src/plugins/bearer/corewlan/main.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcorewlanengine.h"
+
+#include <QtNetwork/private/qbearerplugin_p.h>
+
+#include <QtCore/qdebug.h>
+
+#ifndef QT_NO_BEARERMANAGEMENT
+
+QT_BEGIN_NAMESPACE
+
+class QCoreWlanEnginePlugin : public QBearerEnginePlugin
+{
+public:
+ QCoreWlanEnginePlugin();
+ ~QCoreWlanEnginePlugin();
+
+ QStringList keys() const;
+ QBearerEngine *create(const QString &key) const;
+};
+
+QCoreWlanEnginePlugin::QCoreWlanEnginePlugin()
+{
+}
+
+QCoreWlanEnginePlugin::~QCoreWlanEnginePlugin()
+{
+}
+
+QStringList QCoreWlanEnginePlugin::keys() const
+{
+ return QStringList() << QLatin1String("corewlan");
+}
+
+QBearerEngine *QCoreWlanEnginePlugin::create(const QString &key) const
+{
+ if (key == QLatin1String("corewlan"))
+ return new QCoreWlanEngine;
+ else
+ return 0;
+}
+
+Q_EXPORT_STATIC_PLUGIN(QCoreWlanEnginePlugin)
+Q_EXPORT_PLUGIN2(qcorewlanbearer, QCoreWlanEnginePlugin)
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_BEARERMANAGEMENT
diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.h b/src/plugins/bearer/corewlan/qcorewlanengine.h
new file mode 100644
index 0000000000..428c79e3f5
--- /dev/null
+++ b/src/plugins/bearer/corewlan/qcorewlanengine.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOREWLANENGINE_H
+#define QCOREWLANENGINE_H
+
+#include "../qbearerengine_impl.h"
+
+#include <QMap>
+#include <QTimer>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <QThread>
+
+#ifndef QT_NO_BEARERMANAGEMENT
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkConfigurationPrivate;
+class QScanThread;
+
+class QCoreWlanEngine : public QBearerEngineImpl
+{
+ friend class QScanThread;
+ Q_OBJECT
+
+public:
+ QCoreWlanEngine(QObject *parent = 0);
+ ~QCoreWlanEngine();
+
+ QString getInterfaceFromId(const QString &id);
+ bool hasIdentifier(const QString &id);
+
+ void connectToId(const QString &id);
+ void disconnectFromId(const QString &id);
+
+ Q_INVOKABLE void initialize();
+ Q_INVOKABLE void requestUpdate();
+
+ QNetworkSession::State sessionStateForId(const QString &id);
+
+ quint64 bytesWritten(const QString &id);
+ quint64 bytesReceived(const QString &id);
+ quint64 startTime(const QString &id);
+
+ QNetworkConfigurationManager::Capabilities capabilities() const;
+
+ QNetworkSessionPrivate *createSessionBackend();
+
+ QNetworkConfigurationPrivatePointer defaultConfiguration();
+
+ bool requiresPolling() const;
+
+private Q_SLOTS:
+ void doRequestUpdate();
+ void networksChanged();
+
+private:
+ bool isWifiReady(const QString &dev);
+ QList<QNetworkConfigurationPrivate *> foundConfigurations;
+
+ SCDynamicStoreRef storeSession;
+ CFRunLoopSourceRef runloopSource;
+ bool hasWifi;
+ bool scanning;
+ QScanThread *scanThread;
+
+ quint64 getBytes(const QString &interfaceName,bool b);
+
+protected:
+ void startNetworkChangeLoop();
+
+};
+
+class QScanThread : public QThread
+{
+ Q_OBJECT
+
+public:
+ QScanThread(QObject *parent = 0);
+ ~QScanThread();
+
+ void quit();
+ QList<QNetworkConfigurationPrivate *> getConfigurations();
+ QString interfaceName;
+ QMap<QString, QString> configurationInterface;
+ void getUserConfigurations();
+ QString getNetworkNameFromSsid(const QString &ssid);
+ QString getSsidFromNetworkName(const QString &name);
+ bool isKnownSsid(const QString &ssid);
+ QMap<QString, QMap<QString,QString> > userProfiles;
+
+signals:
+ void networksChanged();
+
+protected:
+ void run();
+
+private:
+ QList<QNetworkConfigurationPrivate *> fetchedConfigurations;
+ QMutex mutex;
+ QStringList foundNetwork(const QString &id, const QString &ssid, const QNetworkConfiguration::StateFlags state, const QString &interfaceName, const QNetworkConfiguration::Purpose purpose);
+
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_BEARERMANAGEMENT
+
+#endif
diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.mm b/src/plugins/bearer/corewlan/qcorewlanengine.mm
new file mode 100644
index 0000000000..07e74fec1f
--- /dev/null
+++ b/src/plugins/bearer/corewlan/qcorewlanengine.mm
@@ -0,0 +1,946 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcorewlanengine.h"
+#include "../qnetworksession_impl.h"
+
+#include <QtNetwork/private/qnetworkconfiguration_p.h>
+
+#include <QtCore/qthread.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qstringlist.h>
+
+#include <QtCore/qdebug.h>
+
+#include <QDir>
+#include <CoreWLAN/CoreWLAN.h>
+#include <CoreWLAN/CWInterface.h>
+#include <CoreWLAN/CWNetwork.h>
+#include <CoreWLAN/CWNetwork.h>
+#include <CoreWLAN/CW8021XProfile.h>
+
+#include <Foundation/NSEnumerator.h>
+#include <Foundation/NSKeyValueObserving.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSLock.h>
+
+#include <SystemConfiguration/SCNetworkConfiguration.h>
+#include "private/qcore_mac_p.h"
+
+#include <net/if.h>
+#include <ifaddrs.h>
+
+inline QString qt_NSStringToQString(const NSString *nsstr)
+{ return QCFString::toQString(reinterpret_cast<const CFStringRef>(nsstr)); }
+
+inline NSString *qt_QStringToNSString(const QString &qstr)
+{ return [reinterpret_cast<const NSString *>(QCFString::toCFStringRef(qstr)) autorelease]; }
+
+
+@interface QT_MANGLE_NAMESPACE(QNSListener) : NSObject
+{
+ NSNotificationCenter *notificationCenter;
+ CWInterface *currentInterface;
+ QCoreWlanEngine *engine;
+ NSLock *locker;
+}
+- (void)notificationHandler;//:(NSNotification *)notification;
+- (void)remove;
+- (void)setEngine:(QCoreWlanEngine *)coreEngine;
+- (void)dealloc;
+
+@property (assign) QCoreWlanEngine* engine;
+
+@end
+
+@implementation QT_MANGLE_NAMESPACE(QNSListener)
+@synthesize engine;
+
+- (id) init
+{
+ [locker lock];
+ NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+ notificationCenter = [NSNotificationCenter defaultCenter];
+ currentInterface = [CWInterface interfaceWithName:nil];
+ [notificationCenter addObserver:self selector:@selector(notificationHandler:) name:kCWPowerDidChangeNotification object:nil];
+ [locker unlock];
+ [autoreleasepool release];
+ return self;
+}
+
+-(void)dealloc
+{
+ [super dealloc];
+}
+
+-(void)setEngine:(QCoreWlanEngine *)coreEngine
+{
+ [locker lock];
+ if(!engine)
+ engine = coreEngine;
+ [locker unlock];
+}
+
+-(void)remove
+{
+ [locker lock];
+ [notificationCenter removeObserver:self];
+ [locker unlock];
+}
+
+- (void)notificationHandler//:(NSNotification *)notification
+{
+ engine->requestUpdate();
+}
+@end
+
+QT_MANGLE_NAMESPACE(QNSListener) *listener = 0;
+
+QT_BEGIN_NAMESPACE
+
+void networkChangeCallback(SCDynamicStoreRef/* store*/, CFArrayRef changedKeys, void *info)
+{
+ for ( long i = 0; i < CFArrayGetCount(changedKeys); i++) {
+
+ QString changed = QCFString::toQString((CFStringRef)CFArrayGetValueAtIndex(changedKeys, i));
+ if( changed.contains("/Network/Global/IPv4")) {
+ QCoreWlanEngine* wlanEngine = static_cast<QCoreWlanEngine*>(info);
+ wlanEngine->requestUpdate();
+ }
+ }
+ return;
+}
+
+
+QScanThread::QScanThread(QObject *parent)
+ :QThread(parent)
+{
+}
+
+QScanThread::~QScanThread()
+{
+}
+
+void QScanThread::quit()
+{
+ wait();
+}
+
+void QScanThread::run()
+{
+ NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+ QStringList found;
+ mutex.lock();
+ CWInterface *currentInterface = [CWInterface interfaceWithName:qt_QStringToNSString(interfaceName)];
+ mutex.unlock();
+
+ if([currentInterface power]) {
+ NSError *err = nil;
+ NSDictionary *parametersDict = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithBool:YES], kCWScanKeyMerge,
+ [NSNumber numberWithInt:kCWScanTypeFast], kCWScanKeyScanType,
+ [NSNumber numberWithInteger:100], kCWScanKeyRestTime, nil];
+
+ NSArray* apArray = [currentInterface scanForNetworksWithParameters:parametersDict error:&err];
+ CWNetwork *apNetwork;
+
+ if (!err) {
+
+ for(uint row=0; row < [apArray count]; row++ ) {
+ apNetwork = [apArray objectAtIndex:row];
+
+ const QString networkSsid = qt_NSStringToQString([apNetwork ssid]);
+ const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkSsid));
+ found.append(id);
+
+ QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined;
+ bool known = isKnownSsid(networkSsid);
+ if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) {
+ if( networkSsid == qt_NSStringToQString( [currentInterface ssid])) {
+ state = QNetworkConfiguration::Active;
+ }
+ }
+ if(state == QNetworkConfiguration::Undefined) {
+ if(known) {
+ state = QNetworkConfiguration::Discovered;
+ } else {
+ state = QNetworkConfiguration::Undefined;
+ }
+ }
+ QNetworkConfiguration::Purpose purpose = QNetworkConfiguration::UnknownPurpose;
+ if([[apNetwork securityMode] intValue] == kCWSecurityModeOpen) {
+ purpose = QNetworkConfiguration::PublicPurpose;
+ } else {
+ purpose = QNetworkConfiguration::PrivatePurpose;
+ }
+
+ found.append(foundNetwork(id, networkSsid, state, interfaceName, purpose));
+
+ }
+ }
+ }
+ // add known configurations that are not around.
+ QMapIterator<QString, QMap<QString,QString> > i(userProfiles);
+ while (i.hasNext()) {
+ i.next();
+
+ QString networkName = i.key();
+ const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkName));
+
+ if(!found.contains(id)) {
+ QString networkSsid = getSsidFromNetworkName(networkName);
+ const QString ssidId = QString::number(qHash(QLatin1String("corewlan:") + networkSsid));
+ QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined;
+ QString interfaceName;
+ QMapIterator<QString, QString> ij(i.value());
+ while (ij.hasNext()) {
+ ij.next();
+ interfaceName = ij.value();
+ }
+
+ if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) {
+ if( networkSsid == qt_NSStringToQString([currentInterface ssid])) {
+ state = QNetworkConfiguration::Active;
+ }
+ }
+ if(state == QNetworkConfiguration::Undefined) {
+ if( userProfiles.contains(networkName)
+ && found.contains(ssidId)) {
+ state = QNetworkConfiguration::Discovered;
+ }
+ }
+
+ if(state == QNetworkConfiguration::Undefined) {
+ state = QNetworkConfiguration::Defined;
+ }
+
+ found.append(foundNetwork(id, networkName, state, interfaceName, QNetworkConfiguration::UnknownPurpose));
+ }
+ }
+ emit networksChanged();
+ [autoreleasepool release];
+}
+
+QStringList QScanThread::foundNetwork(const QString &id, const QString &name, const QNetworkConfiguration::StateFlags state, const QString &interfaceName, const QNetworkConfiguration::Purpose purpose)
+{
+ QStringList found;
+ QMutexLocker locker(&mutex);
+ QNetworkConfigurationPrivate *ptr = new QNetworkConfigurationPrivate;
+
+ ptr->name = name;
+ ptr->isValid = true;
+ ptr->id = id;
+ ptr->state = state;
+ ptr->type = QNetworkConfiguration::InternetAccessPoint;
+ ptr->bearerType = QNetworkConfiguration::BearerWLAN;
+ ptr->purpose = purpose;
+
+ fetchedConfigurations.append( ptr);
+ configurationInterface.insert(ptr->id, interfaceName);
+
+ locker.unlock();
+ locker.relock();
+ found.append(id);
+ return found;
+}
+
+QList<QNetworkConfigurationPrivate *> QScanThread::getConfigurations()
+{
+ QMutexLocker locker(&mutex);
+
+ QList<QNetworkConfigurationPrivate *> foundConfigurations = fetchedConfigurations;
+ fetchedConfigurations.clear();
+
+ return foundConfigurations;
+}
+
+void QScanThread::getUserConfigurations()
+{
+ QMutexLocker locker(&mutex);
+
+ NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+ userProfiles.clear();
+
+ NSArray *wifiInterfaces = [CWInterface supportedInterfaces];
+ for(uint row=0; row < [wifiInterfaces count]; row++ ) {
+
+ CWInterface *wifiInterface = [CWInterface interfaceWithName: [wifiInterfaces objectAtIndex:row]];
+ if ( ![wifiInterface power] )
+ continue;
+
+ NSString *nsInterfaceName = [wifiInterface name];
+// add user configured system networks
+ SCDynamicStoreRef dynRef = SCDynamicStoreCreate(kCFAllocatorSystemDefault, (CFStringRef)@"Qt corewlan", nil, nil);
+ NSDictionary * airportPlist = (NSDictionary *)SCDynamicStoreCopyValue(dynRef, (CFStringRef)[NSString stringWithFormat:@"Setup:/Network/Interface/%@/AirPort", nsInterfaceName]);
+ CFRelease(dynRef);
+ if(airportPlist != nil) {
+ NSDictionary *prefNetDict = [airportPlist objectForKey:@"PreferredNetworks"];
+
+ NSArray *thisSsidarray = [prefNetDict valueForKey:@"SSID_STR"];
+ for(NSString *ssidkey in thisSsidarray) {
+ QString thisSsid = qt_NSStringToQString(ssidkey);
+ if(!userProfiles.contains(thisSsid)) {
+ QMap <QString,QString> map;
+ map.insert(thisSsid, qt_NSStringToQString(nsInterfaceName));
+ userProfiles.insert(thisSsid, map);
+ }
+ }
+ CFRelease(airportPlist);
+ }
+
+ // 802.1X user profiles
+ QString userProfilePath = QDir::homePath() + "/Library/Preferences/com.apple.eap.profiles.plist";
+ NSDictionary* eapDict = [[[NSDictionary alloc] initWithContentsOfFile:qt_QStringToNSString(userProfilePath)] autorelease];
+ if(eapDict != nil) {
+ NSString *profileStr= @"Profiles";
+ NSString *nameStr = @"UserDefinedName";
+ NSString *networkSsidStr = @"Wireless Network";
+ for (id profileKey in eapDict) {
+ if ([profileStr isEqualToString:profileKey]) {
+ NSDictionary *itemDict = [eapDict objectForKey:profileKey];
+ for (id itemKey in itemDict) {
+
+ NSInteger dictSize = [itemKey count];
+ id objects[dictSize];
+ id keys[dictSize];
+
+ [itemKey getObjects:objects andKeys:keys];
+ QString networkName;
+ QString ssid;
+ for(int i = 0; i < dictSize; i++) {
+ if([nameStr isEqualToString:keys[i]]) {
+ networkName = qt_NSStringToQString(objects[i]);
+ }
+ if([networkSsidStr isEqualToString:keys[i]]) {
+ ssid = qt_NSStringToQString(objects[i]);
+ }
+ if(!userProfiles.contains(networkName)
+ && !ssid.isEmpty()) {
+ QMap<QString,QString> map;
+ map.insert(ssid, qt_NSStringToQString(nsInterfaceName));
+ userProfiles.insert(networkName, map);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ [autoreleasepool release];
+}
+
+QString QScanThread::getSsidFromNetworkName(const QString &name)
+{
+ QMutexLocker locker(&mutex);
+
+ QMapIterator<QString, QMap<QString,QString> > i(userProfiles);
+ while (i.hasNext()) {
+ i.next();
+ QMap<QString,QString> map = i.value();
+ QMapIterator<QString, QString> ij(i.value());
+ while (ij.hasNext()) {
+ ij.next();
+ const QString networkNameHash = QString::number(qHash(QLatin1String("corewlan:") +i.key()));
+ if(name == i.key() || name == networkNameHash) {
+ return ij.key();
+ }
+ }
+ }
+ return QString();
+}
+
+QString QScanThread::getNetworkNameFromSsid(const QString &ssid)
+{
+ QMutexLocker locker(&mutex);
+
+ QMapIterator<QString, QMap<QString,QString> > i(userProfiles);
+ while (i.hasNext()) {
+ i.next();
+ QMap<QString,QString> map = i.value();
+ QMapIterator<QString, QString> ij(i.value());
+ while (ij.hasNext()) {
+ ij.next();
+ if(ij.key() == ssid) {
+ return i.key();
+ }
+ }
+ }
+ return QString();
+}
+
+bool QScanThread::isKnownSsid(const QString &ssid)
+{
+ QMutexLocker locker(&mutex);
+
+ QMapIterator<QString, QMap<QString,QString> > i(userProfiles);
+ while (i.hasNext()) {
+ i.next();
+ QMap<QString,QString> map = i.value();
+ if(map.keys().contains(ssid)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+QCoreWlanEngine::QCoreWlanEngine(QObject *parent)
+: QBearerEngineImpl(parent), scanThread(0)
+{
+ scanThread = new QScanThread(this);
+ connect(scanThread, SIGNAL(networksChanged()),
+ this, SLOT(networksChanged()));
+}
+
+QCoreWlanEngine::~QCoreWlanEngine()
+{
+ while (!foundConfigurations.isEmpty())
+ delete foundConfigurations.takeFirst();
+ [listener remove];
+ [listener release];
+}
+
+void QCoreWlanEngine::initialize()
+{
+ QMutexLocker locker(&mutex);
+ NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+
+ if([[CWInterface supportedInterfaces] count] > 0 && !listener) {
+ listener = [[QT_MANGLE_NAMESPACE(QNSListener) alloc] init];
+ listener.engine = this;
+ hasWifi = true;
+ } else {
+ hasWifi = false;
+ }
+ storeSession = NULL;
+
+ startNetworkChangeLoop();
+ [autoreleasepool release];
+}
+
+
+QString QCoreWlanEngine::getInterfaceFromId(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ return scanThread->configurationInterface.value(id);
+}
+
+bool QCoreWlanEngine::hasIdentifier(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ return scanThread->configurationInterface.contains(id);
+}
+
+void QCoreWlanEngine::connectToId(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+ NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+ QString interfaceString = getInterfaceFromId(id);
+
+ CWInterface *wifiInterface =
+ [CWInterface interfaceWithName: qt_QStringToNSString(interfaceString)];
+
+ if ([wifiInterface power]) {
+ NSError *err = nil;
+ NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0];
+
+ QString wantedSsid;
+
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+
+ const QString idHash = QString::number(qHash(QLatin1String("corewlan:") + ptr->name));
+ const QString idHash2 = QString::number(qHash(QLatin1String("corewlan:") + scanThread->getNetworkNameFromSsid(ptr->name)));
+
+ bool using8021X = false;
+ if (idHash2 != id) {
+ NSArray *array = [CW8021XProfile allUser8021XProfiles];
+
+ for (NSUInteger i = 0; i < [array count]; ++i) {
+ const QString networkNameHashCheck = QString::number(qHash(QLatin1String("corewlan:") + qt_NSStringToQString([[array objectAtIndex:i] userDefinedName])));
+
+ const QString ssidHash = QString::number(qHash(QLatin1String("corewlan:") + qt_NSStringToQString([[array objectAtIndex:i] ssid])));
+
+ if (id == networkNameHashCheck || id == ssidHash) {
+ const QString thisName = scanThread->getSsidFromNetworkName(id);
+ if (thisName.isEmpty())
+ wantedSsid = id;
+ else
+ wantedSsid = thisName;
+
+ [params setValue: [array objectAtIndex:i] forKey:kCWAssocKey8021XProfile];
+ using8021X = true;
+ break;
+ }
+ }
+ }
+
+ if (!using8021X) {
+ QString wantedNetwork;
+ QMapIterator<QString, QMap<QString,QString> > i(scanThread->userProfiles);
+ while (i.hasNext()) {
+ i.next();
+ wantedNetwork = i.key();
+ const QString networkNameHash = QString::number(qHash(QLatin1String("corewlan:") + wantedNetwork));
+ if (id == networkNameHash) {
+ wantedSsid = scanThread->getSsidFromNetworkName(wantedNetwork);
+ break;
+ }
+ }
+ }
+ NSDictionary *scanParameters = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithBool:YES], kCWScanKeyMerge,
+ [NSNumber numberWithInt:kCWScanTypeFast], kCWScanKeyScanType,
+ [NSNumber numberWithInteger:100], kCWScanKeyRestTime,
+ qt_QStringToNSString(wantedSsid), kCWScanKeySSID,
+ nil];
+
+ NSArray *scanArray = [wifiInterface scanForNetworksWithParameters:scanParameters error:&err];
+
+ if(!err) {
+ for(uint row=0; row < [scanArray count]; row++ ) {
+ CWNetwork *apNetwork = [scanArray objectAtIndex:row];
+
+ if(wantedSsid == qt_NSStringToQString([apNetwork ssid])) {
+
+ if(!using8021X) {
+ SecKeychainAttribute attributes[3];
+
+ NSString *account = [apNetwork ssid];
+ NSString *keyKind = @"AirPort network password";
+ NSString *keyName = account;
+
+ attributes[0].tag = kSecAccountItemAttr;
+ attributes[0].data = (void *)[account UTF8String];
+ attributes[0].length = [account length];
+
+ attributes[1].tag = kSecDescriptionItemAttr;
+ attributes[1].data = (void *)[keyKind UTF8String];
+ attributes[1].length = [keyKind length];
+
+ attributes[2].tag = kSecLabelItemAttr;
+ attributes[2].data = (void *)[keyName UTF8String];
+ attributes[2].length = [keyName length];
+
+ SecKeychainAttributeList attributeList = {3,attributes};
+
+ SecKeychainSearchRef searchRef;
+ SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, &attributeList, &searchRef);
+
+ NSString *password = @"";
+ SecKeychainItemRef searchItem;
+
+ if (SecKeychainSearchCopyNext(searchRef, &searchItem) == noErr) {
+ UInt32 realPasswordLength;
+ SecKeychainAttribute attributesW[8];
+ attributesW[0].tag = kSecAccountItemAttr;
+ SecKeychainAttributeList listW = {1,attributesW};
+ char *realPassword;
+ OSStatus status = SecKeychainItemCopyContent(searchItem, NULL, &listW, &realPasswordLength,(void **)&realPassword);
+
+ if (status == noErr) {
+ if (realPassword != NULL) {
+
+ QByteArray pBuf;
+ pBuf.resize(realPasswordLength);
+ pBuf.prepend(realPassword);
+ pBuf.insert(realPasswordLength,'\0');
+
+ password = [NSString stringWithUTF8String:pBuf];
+ }
+ SecKeychainItemFreeContent(&listW, realPassword);
+ }
+
+ CFRelease(searchItem);
+ } else {
+ qDebug() << "SecKeychainSearchCopyNext error";
+ }
+ [params setValue: password forKey: kCWAssocKeyPassphrase];
+ } // end using8021X
+
+
+ bool result = [wifiInterface associateToNetwork: apNetwork parameters:[NSDictionary dictionaryWithDictionary:params] error:&err];
+
+ if(!err) {
+ if(!result) {
+ emit connectionError(id, ConnectError);
+ } else {
+ return;
+ }
+ } else {
+ qDebug() <<"associate ERROR"<< qt_NSStringToQString([err localizedDescription ]);
+ }
+ }
+ } //end scan network
+ } else {
+ qDebug() <<"scan ERROR"<< qt_NSStringToQString([err localizedDescription ]);
+ }
+ emit connectionError(id, InterfaceLookupError);
+ }
+
+ locker.unlock();
+ emit connectionError(id, InterfaceLookupError);
+ [autoreleasepool release];
+}
+
+void QCoreWlanEngine::disconnectFromId(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ QString interfaceString = getInterfaceFromId(id);
+ NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+
+ CWInterface *wifiInterface =
+ [CWInterface interfaceWithName: qt_QStringToNSString(interfaceString)];
+
+ [wifiInterface disassociate];
+ if ([[wifiInterface interfaceState]intValue] != kCWInterfaceStateInactive) {
+ locker.unlock();
+ emit connectionError(id, DisconnectionError);
+ locker.relock();
+ }
+ [autoreleasepool release];
+}
+
+void QCoreWlanEngine::requestUpdate()
+{
+ scanThread->getUserConfigurations();
+ doRequestUpdate();
+}
+
+void QCoreWlanEngine::doRequestUpdate()
+{
+ QMutexLocker locker(&mutex);
+
+ NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+
+ NSArray *wifiInterfaces = [CWInterface supportedInterfaces];
+ for (uint row = 0; row < [wifiInterfaces count]; ++row) {
+ scanThread->interfaceName = qt_NSStringToQString([wifiInterfaces objectAtIndex:row]);
+ scanThread->start();
+ }
+ locker.unlock();
+ [autoreleasepool release];
+}
+
+bool QCoreWlanEngine::isWifiReady(const QString &wifiDeviceName)
+{
+ QMutexLocker locker(&mutex);
+ bool haswifi = false;
+ if(hasWifi) {
+ NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+ CWInterface *defaultInterface = [CWInterface interfaceWithName: qt_QStringToNSString(wifiDeviceName)];
+ if([defaultInterface power]) {
+ haswifi = true;
+ }
+ [autoreleasepool release];
+ }
+ return haswifi;
+}
+
+
+QNetworkSession::State QCoreWlanEngine::sessionStateForId(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+
+ if (!ptr)
+ return QNetworkSession::Invalid;
+
+ if (!ptr->isValid) {
+ return QNetworkSession::Invalid;
+ } else if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
+ return QNetworkSession::Connected;
+ } else if ((ptr->state & QNetworkConfiguration::Discovered) ==
+ QNetworkConfiguration::Discovered) {
+ return QNetworkSession::Disconnected;
+ } else if ((ptr->state & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) {
+ return QNetworkSession::NotAvailable;
+ } else if ((ptr->state & QNetworkConfiguration::Undefined) ==
+ QNetworkConfiguration::Undefined) {
+ return QNetworkSession::NotAvailable;
+ }
+
+ return QNetworkSession::Invalid;
+}
+
+QNetworkConfigurationManager::Capabilities QCoreWlanEngine::capabilities() const
+{
+ return QNetworkConfigurationManager::ForcedRoaming;
+}
+
+void QCoreWlanEngine::startNetworkChangeLoop()
+{
+
+ SCDynamicStoreContext dynStoreContext = { 0, this/*(void *)storeSession*/, NULL, NULL, NULL };
+ storeSession = SCDynamicStoreCreate(NULL,
+ CFSTR("networkChangeCallback"),
+ networkChangeCallback,
+ &dynStoreContext);
+ if (!storeSession ) {
+ qWarning() << "could not open dynamic store: error:" << SCErrorString(SCError());
+ return;
+ }
+
+ CFMutableArrayRef notificationKeys;
+ notificationKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ CFMutableArrayRef patternsArray;
+ patternsArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ CFStringRef storeKey;
+ storeKey = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+ kSCDynamicStoreDomainState,
+ kSCEntNetIPv4);
+ CFArrayAppendValue(notificationKeys, storeKey);
+ CFRelease(storeKey);
+
+ storeKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ kSCCompAnyRegex,
+ kSCEntNetIPv4);
+ CFArrayAppendValue(patternsArray, storeKey);
+ CFRelease(storeKey);
+
+ if (!SCDynamicStoreSetNotificationKeys(storeSession , notificationKeys, patternsArray)) {
+ qWarning() << "register notification error:"<< SCErrorString(SCError());
+ CFRelease(storeSession );
+ CFRelease(notificationKeys);
+ CFRelease(patternsArray);
+ return;
+ }
+ CFRelease(notificationKeys);
+ CFRelease(patternsArray);
+
+ runloopSource = SCDynamicStoreCreateRunLoopSource(NULL, storeSession , 0);
+ if (!runloopSource) {
+ qWarning() << "runloop source error:"<< SCErrorString(SCError());
+ CFRelease(storeSession );
+ return;
+ }
+
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), runloopSource, kCFRunLoopDefaultMode);
+ return;
+}
+
+QNetworkSessionPrivate *QCoreWlanEngine::createSessionBackend()
+{
+ return new QNetworkSessionPrivateImpl;
+}
+
+QNetworkConfigurationPrivatePointer QCoreWlanEngine::defaultConfiguration()
+{
+ return QNetworkConfigurationPrivatePointer();
+}
+
+bool QCoreWlanEngine::requiresPolling() const
+{
+ return true;
+}
+
+void QCoreWlanEngine::networksChanged()
+{
+ QMutexLocker locker(&mutex);
+
+ QStringList previous = accessPointConfigurations.keys();
+
+ QList<QNetworkConfigurationPrivate *> foundConfigurations = scanThread->getConfigurations();
+ while (!foundConfigurations.isEmpty()) {
+ QNetworkConfigurationPrivate *cpPriv = foundConfigurations.takeFirst();
+
+ previous.removeAll(cpPriv->id);
+
+ if (accessPointConfigurations.contains(cpPriv->id)) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(cpPriv->id);
+
+ bool changed = false;
+
+ ptr->mutex.lock();
+
+ if (ptr->isValid != cpPriv->isValid) {
+ ptr->isValid = cpPriv->isValid;
+ changed = true;
+ }
+
+ if (ptr->name != cpPriv->name) {
+ ptr->name = cpPriv->name;
+ changed = true;
+ }
+
+ if (ptr->bearerType != cpPriv->bearerType) {
+ ptr->bearerType = cpPriv->bearerType;
+ changed = true;
+ }
+
+ if (ptr->state != cpPriv->state) {
+ ptr->state = cpPriv->state;
+ changed = true;
+ }
+
+ ptr->mutex.unlock();
+
+ if (changed) {
+ locker.unlock();
+ emit configurationChanged(ptr);
+ locker.relock();
+ }
+
+ delete cpPriv;
+ } else {
+ QNetworkConfigurationPrivatePointer ptr(cpPriv);
+
+ accessPointConfigurations.insert(ptr->id, ptr);
+
+ locker.unlock();
+ emit configurationAdded(ptr);
+ locker.relock();
+ }
+ }
+
+ while (!previous.isEmpty()) {
+ QNetworkConfigurationPrivatePointer ptr =
+ accessPointConfigurations.take(previous.takeFirst());
+
+ locker.unlock();
+ emit configurationRemoved(ptr);
+ locker.relock();
+ }
+
+ locker.unlock();
+ emit updateCompleted();
+
+}
+
+quint64 QCoreWlanEngine::bytesWritten(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+ const QString interfaceStr = getInterfaceFromId(id);
+ return getBytes(interfaceStr,false);
+}
+
+quint64 QCoreWlanEngine::bytesReceived(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+ const QString interfaceStr = getInterfaceFromId(id);
+ return getBytes(interfaceStr,true);
+}
+
+quint64 QCoreWlanEngine::startTime(const QString &identifier)
+{
+ QMutexLocker locker(&mutex);
+ NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+ quint64 timestamp = 0;
+
+ NSString *filePath = @"/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist";
+ NSDictionary* plistDict = [[[NSDictionary alloc] initWithContentsOfFile:filePath] autorelease];
+ if(plistDict == nil)
+ return timestamp;
+ NSString *input = @"KnownNetworks";
+ NSString *timeStampStr = @"_timeStamp";
+
+ NSString *ssidStr = @"SSID_STR";
+
+ for (id key in plistDict) {
+ if ([input isEqualToString:key]) {
+
+ NSDictionary *knownNetworksDict = [plistDict objectForKey:key];
+ if(knownNetworksDict == nil)
+ return timestamp;
+ for (id networkKey in knownNetworksDict) {
+ bool isFound = false;
+ NSDictionary *itemDict = [knownNetworksDict objectForKey:networkKey];
+ if(itemDict == nil)
+ return timestamp;
+ NSInteger dictSize = [itemDict count];
+ id objects[dictSize];
+ id keys[dictSize];
+
+ [itemDict getObjects:objects andKeys:keys];
+ bool ok = false;
+ for(int i = 0; i < dictSize; i++) {
+ if([ssidStr isEqualToString:keys[i]]) {
+ const QString ident = QString::number(qHash(QLatin1String("corewlan:") + qt_NSStringToQString(objects[i])));
+ if(ident == identifier) {
+ ok = true;
+ }
+ }
+ if(ok && [timeStampStr isEqualToString:keys[i]]) {
+ timestamp = (quint64)[objects[i] timeIntervalSince1970];
+ isFound = true;
+ break;
+ }
+ }
+ if(isFound)
+ break;
+ }
+ }
+ }
+ [autoreleasepool release];
+ return timestamp;
+}
+
+quint64 QCoreWlanEngine::getBytes(const QString &interfaceName, bool b)
+{
+ struct ifaddrs *ifAddressList, *ifAddress;
+ struct if_data *if_data;
+
+ quint64 bytes = 0;
+ ifAddressList = nil;
+ if(getifaddrs(&ifAddressList) == 0) {
+ for(ifAddress = ifAddressList; ifAddress; ifAddress = ifAddress->ifa_next) {
+ if(interfaceName == ifAddress->ifa_name) {
+ if_data = (struct if_data*)ifAddress->ifa_data;
+ if(b) {
+ bytes = if_data->ifi_ibytes;
+ break;
+ } else {
+ bytes = if_data->ifi_obytes;
+ break;
+ }
+ }
+ }
+ freeifaddrs(ifAddressList);
+ }
+ return bytes;
+}
+
+QT_END_NAMESPACE