diff options
author | Lorn Potter <lorn.potter@nokia.com> | 2010-03-12 05:05:05 (GMT) |
---|---|---|
committer | Lorn Potter <lorn.potter@nokia.com> | 2010-03-12 05:05:05 (GMT) |
commit | 837e6acbda362da0e0130b784c90f765d6cd8c8e (patch) | |
tree | c32f9e6558daba6247ebd869be2c563e67973c0e | |
parent | aa4ab19776a67f882b901b488de8664811df8ae5 (diff) | |
download | Qt-837e6acbda362da0e0130b784c90f765d6cd8c8e.zip Qt-837e6acbda362da0e0130b784c90f765d6cd8c8e.tar.gz Qt-837e6acbda362da0e0130b784c90f765d6cd8c8e.tar.bz2 |
get known wifi networks a more complicated way, but without accessing
the keychain.
Users will still see the keychain prompt when attempting to
connect/associate with a wifi network.
-rw-r--r-- | src/plugins/bearer/corewlan/qcorewlanengine.h | 10 | ||||
-rw-r--r-- | src/plugins/bearer/corewlan/qcorewlanengine.mm | 357 |
2 files changed, 265 insertions, 102 deletions
diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.h b/src/plugins/bearer/corewlan/qcorewlanengine.h index f6d5b7a..76574a8 100644 --- a/src/plugins/bearer/corewlan/qcorewlanengine.h +++ b/src/plugins/bearer/corewlan/qcorewlanengine.h @@ -90,15 +90,21 @@ private: QMap<QString, QString> configurationInterface; QStringList scanForSsids(const QString &interfaceName); - bool isKnownSsid(const QString &interfaceName, const QString &ssid); + bool isKnownSsid(const QString &ssid); QList<QNetworkConfigurationPrivate *> foundConfigurations; SCDynamicStoreRef storeSession; CFRunLoopSourceRef runloopSource; - void startNetworkChangeLoop(); bool hasWifi; +protected: + QMap<QString, QMap<QString,QString> > userProfiles; + + void startNetworkChangeLoop(); + void getUserConfigurations(); + QString getNetworkNameFromSsid(const QString &ssid); + QString getSsidFromNetworkName(const QString &name); }; QT_END_NAMESPACE diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.mm b/src/plugins/bearer/corewlan/qcorewlanengine.mm index 84dd6a5..392e24c 100644 --- a/src/plugins/bearer/corewlan/qcorewlanengine.mm +++ b/src/plugins/bearer/corewlan/qcorewlanengine.mm @@ -50,13 +50,11 @@ #include <QtCore/qstringlist.h> #include <QtCore/qdebug.h> - -#if defined(MAC_SDK_10_6) //not much functionality without this +#include <QDir> #include <CoreWLAN/CoreWLAN.h> #include <CoreWLAN/CWInterface.h> #include <CoreWLAN/CWNetwork.h> #include <CoreWLAN/CWNetwork.h> -#endif #include <Foundation/NSEnumerator.h> #include <Foundation/NSKeyValueObserving.h> @@ -69,16 +67,14 @@ QMap <QString, QString> networkInterfaces; -#ifdef MAC_SDK_10_6 @interface QNSListener : NSObject { NSNotificationCenter *center; CWInterface *currentInterface; QCoreWlanEngine *engine; - NSAutoreleasePool *autoreleasepool; NSLock *locker; } -- (void)notificationHandler:(NSNotification *)notification; +- (void)notificationHandler;//:(NSNotification *)notification; - (void)remove; - (void)setEngine:(QCoreWlanEngine *)coreEngine; - (void)dealloc; @@ -91,7 +87,7 @@ QMap <QString, QString> networkInterfaces; - (id) init { [locker lock]; - autoreleasepool = [[NSAutoreleasePool alloc] init]; + QMacCocoaAutoReleasePool pool; center = [NSNotificationCenter defaultCenter]; currentInterface = [CWInterface interface]; // [center addObserver:self selector:@selector(notificationHandler:) name:kCWLinkDidChangeNotification object:nil]; @@ -102,7 +98,6 @@ QMap <QString, QString> networkInterfaces; -(void)dealloc { - [autoreleasepool release]; [super dealloc]; } @@ -121,7 +116,7 @@ QMap <QString, QString> networkInterfaces; [locker unlock]; } -- (void)notificationHandler:(NSNotification *)notification +- (void)notificationHandler//:(NSNotification *)notification { engine->requestUpdate(); } @@ -129,14 +124,12 @@ QMap <QString, QString> networkInterfaces; QNSListener *listener = 0; -#endif - QT_BEGIN_NAMESPACE static QString qGetInterfaceType(const QString &interfaceString) { - return networkInterfaces.value(interfaceString, QLatin1String("Unknown")); + return networkInterfaces.value(interfaceString, QLatin1String("WLAN")); } void networkChangeCallback(SCDynamicStoreRef/* store*/, CFArrayRef changedKeys, void *info) @@ -157,7 +150,7 @@ QCoreWlanEngine::QCoreWlanEngine(QObject *parent) { startNetworkChangeLoop(); -#if defined(MAC_SDK_10_6) + QMacCocoaAutoReleasePool pool; if([[CWInterface supportedInterfaces] count] > 0 && !listener) { listener = [[QNSListener alloc] init]; listener.engine = this; @@ -165,17 +158,16 @@ QCoreWlanEngine::QCoreWlanEngine(QObject *parent) } else { hasWifi = false; } -#endif + getUserConfigurations(); + requestUpdate(); } QCoreWlanEngine::~QCoreWlanEngine() { while (!foundConfigurations.isEmpty()) delete foundConfigurations.takeFirst(); -#if defined(MAC_SDK_10_6) [listener remove]; [listener release]; -#endif } QString QCoreWlanEngine::getInterfaceFromId(const QString &id) @@ -195,79 +187,88 @@ bool QCoreWlanEngine::hasIdentifier(const QString &id) void QCoreWlanEngine::connectToId(const QString &id) { QMutexLocker locker(&mutex); - - NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + QMacCocoaAutoReleasePool pool; QString interfaceString = getInterfaceFromId(id); if(networkInterfaces.value(interfaceString) == "WLAN") { -#if defined(MAC_SDK_10_6) CWInterface *wifiInterface = [CWInterface interfaceWithName: qt_mac_QStringToNSString(interfaceString)]; - CWConfiguration *userConfig = [ wifiInterface configuration]; - - NSSet *remNets = [userConfig rememberedNetworks]; //CWWirelessProfile - NSEnumerator *enumerator = [remNets objectEnumerator]; - CWWirelessProfile *wProfile; - NSUInteger index=0; - NSDictionary *parametersDict; - NSArray* apArray; - - CW8021XProfile *user8021XProfile; - NSError *err; - NSMutableDictionary *params; + if([wifiInterface power]) { + NSError *err = nil; + NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0]; + + NSString *wantedSsid = 0; + bool okToProceed = true; + if(getNetworkNameFromSsid(id) != id) { + NSArray *array = [CW8021XProfile allUser8021XProfiles]; + for (NSUInteger i=0; i<[array count]; ++i) { + const QString idCheck = QString::number(qHash(QLatin1String("corewlan:") + qt_mac_NSStringToQString([[array objectAtIndex:i] userDefinedName]))); + const QString idCheck2 = QString::number(qHash(QLatin1String("corewlan:") + qt_mac_NSStringToQString([[array objectAtIndex:i] ssid]))); + + if(id == idCheck + || id == idCheck2) { + QString thisName = getSsidFromNetworkName(id); + if(thisName.isEmpty()) { + wantedSsid = qt_mac_QStringToNSString(id); + } else { + wantedSsid = qt_mac_QStringToNSString(thisName); + } + okToProceed = false; + [params setValue: [array objectAtIndex:i] forKey:kCWAssocKey8021XProfile]; + break; + } + } + } - while ((wProfile = [enumerator nextObject])) { //CWWirelessProfile + if(okToProceed) { + NSUInteger index = 0; - if(id == QString::number(qHash(QLatin1String("corewlan:") + qt_mac_NSStringToQString([wProfile ssid])))) { - user8021XProfile = nil; - user8021XProfile = [ wProfile user8021XProfile]; + CWConfiguration *userConfig = [ wifiInterface configuration]; + NSSet *remNets = [userConfig rememberedNetworks]; + NSEnumerator *enumerator = [remNets objectEnumerator]; + CWWirelessProfile *wProfile; - err = nil; - params = [NSMutableDictionary dictionaryWithCapacity:0]; + while ((wProfile = [enumerator nextObject])) { + const QString idCheck = QString::number(qHash(QLatin1String("corewlan:") + qt_mac_NSStringToQString([wProfile ssid]))); - if(user8021XProfile) { - [params setValue: user8021XProfile forKey:kCWAssocKey8021XProfile]; - } else { - [params setValue: [wProfile passphrase] forKey: kCWAssocKeyPassphrase]; + if(id == idCheck) { + wantedSsid = [wProfile ssid]; + [params setValue: [wProfile passphrase] forKey: kCWAssocKeyPassphrase]; + break; + } + index++; } + } - parametersDict = nil; - apArray = [NSMutableArray arrayWithArray:[wifiInterface scanForNetworksWithParameters:parametersDict error:&err]]; - - if(!err) { - - for(uint row=0; row < [apArray count]; row++ ) { - CWNetwork *apNetwork = [apArray objectAtIndex:row]; - if([[apNetwork ssid] compare:[wProfile ssid]] == NSOrderedSame) { + NSDictionary *parametersDict = nil; + NSArray *apArray = [NSMutableArray arrayWithArray:[wifiInterface scanForNetworksWithParameters:parametersDict error:&err]]; - bool result = [wifiInterface associateToNetwork: apNetwork parameters:[NSDictionary dictionaryWithDictionary:params] error:&err]; + if(!err) { + for(uint row=0; row < [apArray count]; row++ ) { + CWNetwork *apNetwork = [apArray objectAtIndex:row]; + if([[apNetwork ssid] compare:wantedSsid] == NSOrderedSame) { + bool result = [wifiInterface associateToNetwork: apNetwork parameters:[NSDictionary dictionaryWithDictionary:params] error:&err]; - if(!result) { - locker.unlock(); - emit connectionError(id, ConnectError); - locker.relock(); - } else { - [autoreleasepool release]; - return; - } + if(!result) { + emit connectionError(id, ConnectError); + } else { + return; } } } + } else { + qDebug() <<"ERROR"<< qt_mac_NSStringToQString([err localizedDescription ]); } - index++; - } + emit connectionError(id, InterfaceLookupError); + } else { + // not wifi + } locker.unlock(); emit connectionError(id, InterfaceLookupError); locker.relock(); -#endif - } else { - // not wifi } - - locker.unlock(); emit connectionError(id, OperationNotSupported); - [autoreleasepool release]; } void QCoreWlanEngine::disconnectFromId(const QString &id) @@ -277,7 +278,7 @@ void QCoreWlanEngine::disconnectFromId(const QString &id) QString interfaceString = getInterfaceFromId(id); if(networkInterfaces.value(getInterfaceFromId(id)) == "WLAN") { //wifi only for now #if defined(MAC_SDK_10_6) - NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + QMacCocoaAutoReleasePool pool; CWInterface *wifiInterface = [CWInterface interfaceWithName: qt_mac_QStringToNSString(interfaceString)]; [wifiInterface disassociate]; if([[wifiInterface interfaceState]intValue] != kCWInterfaceStateInactive) { @@ -285,7 +286,6 @@ void QCoreWlanEngine::disconnectFromId(const QString &id) emit connectionError(id, DisconnectionError); locker.relock(); } - [autoreleasepool release]; return; #endif } else { @@ -403,20 +403,20 @@ QStringList QCoreWlanEngine::scanForSsids(const QString &interfaceName) QStringList found; -#if defined(MAC_SDK_10_6) if(!hasWifi) { return found; } - QMacCocoaAutoReleasePool pool; CWInterface *currentInterface = [CWInterface interfaceWithName:qt_mac_QStringToNSString(interfaceName)]; + QStringList addedConfigs; + if([currentInterface power]) { NSError *err = nil; NSDictionary *parametersDict = nil; NSArray* apArray = [currentInterface scanForNetworksWithParameters:parametersDict error:&err]; - CWNetwork *apNetwork; + if (!err) { for(uint row=0; row < [apArray count]; row++ ) { @@ -428,15 +428,18 @@ QStringList QCoreWlanEngine::scanForSsids(const QString &interfaceName) found.append(id); QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined; - - if ([currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) { - if (networkSsid == qt_mac_NSStringToQString([currentInterface ssid])) + bool known = isKnownSsid(networkSsid); + if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) { + if( networkSsid == qt_mac_NSStringToQString( [currentInterface ssid])) { state = QNetworkConfiguration::Active; - } else { - if (isKnownSsid(interfaceName, networkSsid)) + } + } + if(state == QNetworkConfiguration::Undefined) { + if(known) { state = QNetworkConfiguration::Discovered; - else - state = QNetworkConfiguration::Defined; + } else { + state = QNetworkConfiguration::Undefined; + } } if (accessPointConfigurations.contains(id)) { @@ -473,9 +476,11 @@ QStringList QCoreWlanEngine::scanForSsids(const QString &interfaceName) emit configurationChanged(ptr); locker.relock(); } + addedConfigs << networkSsid; } else { QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate); + found.append(id); ptr->name = networkSsid; ptr->isValid = true; ptr->id = id; @@ -483,19 +488,60 @@ QStringList QCoreWlanEngine::scanForSsids(const QString &interfaceName) ptr->type = QNetworkConfiguration::InternetAccessPoint; ptr->bearer = QLatin1String("WLAN"); - accessPointConfigurations.insert(id, ptr); - configurationInterface.insert(id, interfaceName); + accessPointConfigurations.insert(ptr->id, ptr); + configurationInterface.insert(ptr->id, interfaceName); locker.unlock(); emit configurationAdded(ptr); locker.relock(); + addedConfigs << networkSsid; } } } } -#else - Q_UNUSED(interfaceName); -#endif + + // add known configurations that are not around. + QMapIterator<QString, QMap<QString,QString> > i(userProfiles); + while (i.hasNext()) { + i.next(); + QString networkName = i.key(); + if(!addedConfigs.contains(networkName)) { + QString interfaceName; + QMapIterator<QString, QString> ij(i.value()); + while (ij.hasNext()) { + ij.next(); + interfaceName = ij.value(); + } + QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate); + const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkName)); + found.append(id); + + ptr->name = networkName; + ptr->isValid = true; + ptr->id = id; + ptr->bearer = QLatin1String("WLAN"); + ptr->type = QNetworkConfiguration::InternetAccessPoint; + QString ssid = getSsidFromNetworkName(networkName); + + if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) { + if( ssid == qt_mac_NSStringToQString([currentInterface ssid])) { + ptr->state = QNetworkConfiguration::Active; + } + } + + if(!ptr->state) { + if( addedConfigs.contains(ssid)) { + ptr->state = QNetworkConfiguration::Discovered; + } + } + + if(!ptr->state) { + ptr->state = QNetworkConfiguration::Defined; + } + accessPointConfigurations.insert(ptr->id, ptr); + configurationInterface.insert(ptr->id, interfaceName); + } + } return found; } @@ -503,35 +549,27 @@ bool QCoreWlanEngine::isWifiReady(const QString &wifiDeviceName) { QMutexLocker locker(&mutex); -#if defined(MAC_SDK_10_6) if(hasWifi) { + QMacCocoaAutoReleasePool pool; CWInterface *defaultInterface = [CWInterface interfaceWithName: qt_mac_QStringToNSString(wifiDeviceName)]; if([defaultInterface power]) return true; } -#else - Q_UNUSED(wifiDeviceName); -#endif return false; } -bool QCoreWlanEngine::isKnownSsid(const QString &interfaceName, const QString &ssid) +bool QCoreWlanEngine::isKnownSsid(const QString &ssid) { QMutexLocker locker(&mutex); -#if defined(MAC_SDK_10_6) - if(!hasWifi) { return false; } - CWInterface *wifiInterface = [CWInterface interfaceWithName: qt_mac_QStringToNSString(interfaceName)]; - CWConfiguration *userConfig = [wifiInterface configuration]; - NSSet *remNets = [userConfig rememberedNetworks]; - for (CWWirelessProfile *wProfile in remNets) { - if(ssid == qt_mac_NSStringToQString([wProfile ssid])) + 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; + } } -#else - Q_UNUSED(interfaceName); - Q_UNUSED(ssid); -#endif return false; } @@ -546,7 +584,6 @@ bool QCoreWlanEngine::getWifiInterfaces() for(uint row=0; row < [wifiInterfaces count]; row++ ) { networkInterfaces.insert( qt_mac_NSStringToQString([wifiInterfaces objectAtIndex:row]),"WLAN"); } - return true; } @@ -650,4 +687,124 @@ bool QCoreWlanEngine::requiresPolling() const return true; } +QString QCoreWlanEngine::getSsidFromNetworkName(const QString &name) +{ + 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 idCheck = QString::number(qHash(QLatin1String("corewlan:") +i.key())); + if(name == i.key() || name == idCheck) { + return ij.key(); + } + } + } + return QString(); +} + +QString QCoreWlanEngine::getNetworkNameFromSsid(const QString &ssid) +{ + 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 map.key(ssid); + } + return QString(); +} + + +void QCoreWlanEngine::getUserConfigurations() +{ + QMacCocoaAutoReleasePool pool; + userProfiles.clear(); + + NSArray *wifiInterfaces = [CWInterface supportedInterfaces]; + for(uint row=0; row < [wifiInterfaces count]; row++ ) { + + CWInterface *wifiInterface = [CWInterface interfaceWithName: [wifiInterfaces objectAtIndex:row]]; + +// add user configured system networks + NSString *filePath = @"/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist"; + NSDictionary* plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath]; + NSString *input = @"KnownNetworks"; + NSString *ssidStr = @"SSID_STR"; + + for (id key in plistDict) { + if ([input isEqualToString:key]) { + + NSDictionary *knownNetworksDict = [plistDict objectForKey:key]; + for (id networkKey in knownNetworksDict) { + + NSDictionary *itemDict = [knownNetworksDict objectForKey:networkKey]; + NSInteger dictSize = [itemDict count]; + id objects[dictSize]; + id keys[dictSize]; + + [itemDict getObjects:objects andKeys:keys]; + + for(int i = 0; i < dictSize; i++) { + if([ssidStr isEqualToString:keys[i]]) { + QString thisSsid = qt_mac_NSStringToQString(objects[i]); + if(!userProfiles.contains(thisSsid)) { + QMap <QString,QString> map; + map.insert(thisSsid, qt_mac_NSStringToQString([wifiInterface name])); + userProfiles.insert(thisSsid, map); + } + } + } + } + } + } + + // 802.1X user profiles + QString userProfilePath = QDir::homePath() + "/Library/Preferences/com.apple.eap.profiles.plist"; + NSDictionary* eapDict = [[NSMutableDictionary alloc] initWithContentsOfFile:qt_mac_QStringToNSString(userProfilePath)]; + 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_mac_NSStringToQString(objects[i]); + } + if([networkSsidStr isEqualToString:keys[i]]) { + ssid = qt_mac_NSStringToQString(objects[i]); + } + if(!userProfiles.contains(networkName) + && !ssid.isEmpty()) { + QMap<QString,QString> map; + map.insert(ssid, qt_mac_NSStringToQString([wifiInterface name])); + userProfiles.insert(networkName, map); + } + } + } + } + } + } +} + QT_END_NAMESPACE |