qtmobility/src/bearer/qcorewlanengine_mac.mm
branchRCL_3
changeset 9 5d007b20cfd0
parent 8 885c2596c964
child 10 cd2778e5acfe
equal deleted inserted replaced
8:885c2596c964 9:5d007b20cfd0
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qcorewlanengine_mac_p.h"
       
    43 #include "qnetworkconfiguration_p.h"
       
    44 
       
    45 #include <QtCore/qthread.h>
       
    46 #include <QThread>
       
    47 #include <QtCore/qmutex.h>
       
    48 #include <QtCore/qcoreapplication.h>
       
    49 #include <QtCore/qstringlist.h>
       
    50 
       
    51 #include <QtCore/qdebug.h>
       
    52 
       
    53 #include <QDir>
       
    54 #if defined(MAC_SDK_10_6) //not much functionality without this
       
    55 #include <CoreWLAN/CoreWLAN.h>
       
    56 #include <CoreWLAN/CWInterface.h>
       
    57 #include <CoreWLAN/CWNetwork.h>
       
    58 #include <CoreWLAN/CWNetwork.h>
       
    59 #include <CoreWLAN/CW8021XProfile.h>
       
    60 
       
    61 #endif
       
    62 
       
    63 #include <Foundation/NSEnumerator.h>
       
    64 #include <Foundation/NSKeyValueObserving.h>
       
    65 #include <Foundation/NSAutoreleasePool.h>
       
    66 
       
    67 #include <SystemConfiguration/SCNetworkConfiguration.h>
       
    68 QMap <QString, QString> networkInterfaces;
       
    69 
       
    70 #ifdef MAC_SDK_10_6
       
    71 @interface QNSListener : NSObject
       
    72 {
       
    73     NSNotificationCenter *center;
       
    74     CWInterface * currentInterface;
       
    75 }
       
    76 - (void)notificationHandler;//:(NSNotification *)notification;
       
    77 - (void)remove;
       
    78 @end
       
    79 
       
    80 @implementation QNSListener
       
    81 - (id) init
       
    82 {
       
    83     [super init];
       
    84     center = [NSNotificationCenter defaultCenter];
       
    85     currentInterface = [CWInterface interfaceWithName:nil];
       
    86     [center addObserver:self selector:@selector(notificationHandler:) name:kCWLinkDidChangeNotification object:nil];
       
    87     [center addObserver:self selector:@selector(notificationHandler:) name:kCWPowerDidChangeNotification object:nil];
       
    88 
       
    89     return self;
       
    90 }
       
    91 
       
    92 -(void)dealloc
       
    93 {
       
    94    [center release];
       
    95    [currentInterface release];
       
    96    [super dealloc];
       
    97 }
       
    98 
       
    99 -(void)remove
       
   100 {
       
   101     [center removeObserver:self];
       
   102 }
       
   103 
       
   104 - (void)notificationHandler;//:(NSNotification *)notification
       
   105 {
       
   106     QTM_NAMESPACE::QCoreWlanEngine::instance()->requestUpdate();
       
   107 }
       
   108 @end
       
   109 
       
   110 QNSListener *listener = 0;
       
   111 #endif
       
   112 
       
   113 QTM_BEGIN_NAMESPACE
       
   114 
       
   115 Q_GLOBAL_STATIC(QCoreWlanEngine, coreWlanEngine)
       
   116 
       
   117 inline QString cfstringRefToQstring(CFStringRef cfStringRef) {
       
   118     QString retVal;
       
   119     CFIndex maxLength = 2 * CFStringGetLength(cfStringRef) + 1/*zero term*/; // max UTF8
       
   120     char *cstring = new char[maxLength];
       
   121     if (CFStringGetCString(CFStringRef(cfStringRef), cstring, maxLength, kCFStringEncodingUTF8)) {
       
   122         retVal = QString::fromUtf8(cstring);
       
   123     }
       
   124     delete[] cstring;
       
   125     return retVal;
       
   126 }
       
   127 
       
   128 inline CFStringRef qstringToCFStringRef(const QString &string)
       
   129 {
       
   130     return CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar *>(string.unicode()),
       
   131                                         string.length());
       
   132 }
       
   133 
       
   134 inline NSString *qstringToNSString(const QString &qstr)
       
   135 { return [reinterpret_cast<const NSString *>(qstringToCFStringRef(qstr)) autorelease]; }
       
   136 
       
   137 inline QString nsstringToQString(const NSString *nsstr)
       
   138 { return cfstringRefToQstring(reinterpret_cast<const CFStringRef>(nsstr)); }
       
   139 
       
   140 inline QStringList nsarrayToQStringList(void *nsarray)
       
   141 {
       
   142     QStringList result;
       
   143     NSArray *array = static_cast<NSArray *>(nsarray);
       
   144     for (NSUInteger i=0; i<[array count]; ++i)
       
   145         result << nsstringToQString([array objectAtIndex:i]);
       
   146     return result;
       
   147 }
       
   148 
       
   149 void networkChangeCallback(SCDynamicStoreRef/* store*/, CFArrayRef changedKeys, void *info)
       
   150 {
       
   151     for ( long i = 0; i < CFArrayGetCount(changedKeys); i++) {
       
   152 
       
   153         CFStringRef changed = (CFStringRef)CFArrayGetValueAtIndex(changedKeys, i);
       
   154         if( cfstringRefToQstring(changed).contains("/Network/Global/IPv4")) {
       
   155             QCoreWlanEngine* wlanEngine = static_cast<QCoreWlanEngine*>(info);
       
   156             wlanEngine->requestUpdate();
       
   157         }
       
   158     }
       
   159     return;
       
   160 }
       
   161 
       
   162 QScanThread::QScanThread(QObject *parent)
       
   163     :QThread(parent)
       
   164 {
       
   165 }
       
   166 
       
   167 QScanThread::~QScanThread()
       
   168 {
       
   169 }
       
   170 
       
   171 void QScanThread::quit()
       
   172 {
       
   173     wait();
       
   174 }
       
   175 
       
   176 void QScanThread::run()
       
   177 {
       
   178 #if defined(MAC_SDK_10_6)
       
   179     getUserProfiles();
       
   180     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
       
   181     QStringList found;
       
   182     mutex.lock();
       
   183     CWInterface *currentInterface;
       
   184     if(interfaceName.isEmpty()) {
       
   185         currentInterface = [CWInterface interfaceWithName:nil];
       
   186         interfaceName = nsstringToQString([currentInterface name]);
       
   187     } else {
       
   188         currentInterface = [CWInterface interfaceWithName:qstringToNSString(interfaceName)];
       
   189     }
       
   190     mutex.unlock();
       
   191 
       
   192     if([currentInterface power]) {
       
   193         NSError *err = nil;
       
   194         NSDictionary *parametersDict =  [NSDictionary dictionaryWithObjectsAndKeys:
       
   195                                          [NSNumber numberWithBool:YES], kCWScanKeyMerge,
       
   196                                          [NSNumber numberWithInteger:100], kCWScanKeyRestTime, nil];
       
   197 
       
   198         NSArray* apArray = [currentInterface scanForNetworksWithParameters:parametersDict error:&err];
       
   199         CWNetwork *apNetwork;
       
   200 
       
   201         if (!err) {
       
   202             for(uint row=0; row < [apArray count]; row++ ) {
       
   203                 apNetwork = [apArray objectAtIndex:row];
       
   204 
       
   205                 const QString networkSsid = nsstringToQString([apNetwork ssid]);
       
   206                 found.append(networkSsid);
       
   207 
       
   208                 QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined;
       
   209 
       
   210                 bool known = isKnownSsid(networkSsid);
       
   211                 if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) {
       
   212                     if( networkSsid == nsstringToQString( [currentInterface ssid])) {
       
   213                         state = QNetworkConfiguration::Active;
       
   214                     }
       
   215                 }
       
   216                 if(state == QNetworkConfiguration::Undefined) {
       
   217                     if(known) {
       
   218                         state = QNetworkConfiguration::Discovered;
       
   219                     } else {
       
   220                         state = QNetworkConfiguration::Undefined;
       
   221                     }
       
   222                 }
       
   223 
       
   224                 QNetworkConfiguration::Purpose purpose = QNetworkConfiguration::UnknownPurpose;
       
   225                 if([[apNetwork securityMode] intValue] == kCWSecurityModeOpen) {
       
   226                     purpose = QNetworkConfiguration::PublicPurpose;
       
   227                 } else {
       
   228                     purpose = QNetworkConfiguration::PrivatePurpose;
       
   229                 }
       
   230 
       
   231                 found.append(foundNetwork(networkSsid, networkSsid, state, interfaceName, purpose));
       
   232 
       
   233             } //end row
       
   234         }//end error
       
   235     }// endwifi power
       
   236 
       
   237 // add known configurations that are not around.
       
   238     QMapIterator<QString, QMap<QString,QString> > i(userProfiles);
       
   239     while (i.hasNext()) {
       
   240         i.next();
       
   241 
       
   242         QString networkName = i.key();
       
   243         const QString id = networkName;
       
   244 
       
   245         if(!found.contains(id)) {
       
   246             QString networkSsid = getSsidFromNetworkName(networkName);
       
   247             const QString ssidId = QString::number(qHash(QLatin1String("corewlan:") + networkSsid));
       
   248             QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined;
       
   249             QString interfaceName;
       
   250             QMapIterator<QString, QString> ij(i.value());
       
   251             while (ij.hasNext()) {
       
   252                 ij.next();
       
   253                 interfaceName = ij.value();
       
   254             }
       
   255 
       
   256             if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) {
       
   257                 if( networkSsid == nsstringToQString([currentInterface ssid])) {
       
   258                     state = QNetworkConfiguration::Active;
       
   259                 }
       
   260             }
       
   261             if(state == QNetworkConfiguration::Undefined) {
       
   262                 if( userProfiles.contains(networkName)
       
   263                     && found.contains(ssidId)) {
       
   264                     state = QNetworkConfiguration::Discovered;
       
   265                 }
       
   266             }
       
   267 
       
   268             if(state == QNetworkConfiguration::Undefined) {
       
   269                 state = QNetworkConfiguration::Defined;
       
   270             }
       
   271 
       
   272             found.append(foundNetwork(id, networkName, state, interfaceName, QNetworkConfiguration::UnknownPurpose));
       
   273         }
       
   274     }
       
   275     emit networksChanged();
       
   276     [pool release];
       
   277 #endif
       
   278 }
       
   279 
       
   280 QStringList QScanThread::foundNetwork(const QString &id, const QString &name, const QNetworkConfiguration::StateFlags state, const QString &interfaceName, const QNetworkConfiguration::Purpose purpose)
       
   281 {
       
   282     QStringList found;
       
   283     QMutexLocker locker(&mutex);
       
   284     QNetworkConfigurationPrivate *ptr = new QNetworkConfigurationPrivate;
       
   285 
       
   286     ptr->name = name;
       
   287     ptr->isValid = true;
       
   288     ptr->id = id;
       
   289     ptr->state = state;
       
   290     ptr->type = QNetworkConfiguration::InternetAccessPoint;
       
   291     ptr->bearer = QLatin1String("WLAN");
       
   292     ptr->purpose = purpose;
       
   293     ptr->internet = true;
       
   294     ptr->serviceInterface = QNetworkInterface::interfaceFromName(interfaceName);
       
   295 
       
   296     fetchedConfigurations.append( ptr);
       
   297     configurationInterface[name] =  interfaceName;
       
   298 
       
   299     locker.unlock();
       
   300     locker.relock();
       
   301     found.append(id);
       
   302     return found;
       
   303 }
       
   304 
       
   305 QList<QNetworkConfigurationPrivate *> QScanThread::getConfigurations()
       
   306 {
       
   307     QMutexLocker locker(&mutex);
       
   308 
       
   309     QList<QNetworkConfigurationPrivate *> foundConfigurations;
       
   310 
       
   311     for (int i = 0; i < fetchedConfigurations.count(); ++i) {
       
   312         QNetworkConfigurationPrivate *config = new QNetworkConfigurationPrivate;
       
   313         config->name = fetchedConfigurations.at(i)->name;
       
   314         config->isValid = fetchedConfigurations.at(i)->isValid;
       
   315         config->id = fetchedConfigurations.at(i)->id;
       
   316         config->state = fetchedConfigurations.at(i)->state;
       
   317         config->bearer = fetchedConfigurations.at(i)->bearer;
       
   318         config->type = fetchedConfigurations.at(i)->type;
       
   319         config->roamingSupported = fetchedConfigurations.at(i)->roamingSupported;
       
   320         config->purpose = fetchedConfigurations.at(i)->purpose;
       
   321         config->internet = fetchedConfigurations.at(i)->internet;
       
   322         foundConfigurations.append(config);
       
   323     }
       
   324 
       
   325     return foundConfigurations;
       
   326 }
       
   327 
       
   328 void QScanThread::getUserProfiles()
       
   329 {
       
   330 #if defined(MAC_SDK_10_6)
       
   331     QMutexLocker locker(&mutex);
       
   332     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
       
   333     userProfiles.clear();
       
   334 
       
   335     NSArray *wifiInterfaces = [CWInterface supportedInterfaces];
       
   336     for(uint row=0; row < [wifiInterfaces count]; row++ ) {
       
   337 
       
   338         CWInterface *wifiInterface = [CWInterface interfaceWithName: [wifiInterfaces objectAtIndex:row]];
       
   339         if (![wifiInterface power])
       
   340             continue;
       
   341 
       
   342         NSString *nsInterfaceName = [wifiInterface name];
       
   343 // add user configured system networks
       
   344         SCDynamicStoreRef dynRef = SCDynamicStoreCreate(kCFAllocatorSystemDefault, (CFStringRef)@"Qt corewlan", nil, nil);
       
   345         NSDictionary * airportPlist = (NSDictionary *)SCDynamicStoreCopyValue(dynRef, (CFStringRef)[NSString stringWithFormat:@"Setup:/Network/Interface/%@/AirPort", nsInterfaceName]);
       
   346         CFRelease(dynRef);
       
   347 
       
   348         NSDictionary *prefNetDict = [airportPlist objectForKey:@"PreferredNetworks"];
       
   349 
       
   350         NSArray *thisSsidarray = [prefNetDict valueForKey:@"SSID_STR"];
       
   351         NSEnumerator *ssidEnumerator = [thisSsidarray objectEnumerator];
       
   352         NSString *ssidkey;
       
   353         while ((ssidkey = [ssidEnumerator nextObject])) {
       
   354             QString thisSsid = nsstringToQString(ssidkey);
       
   355             if(!userProfiles.contains(thisSsid)) {
       
   356                 QMap <QString,QString> map;
       
   357                 map.insert(thisSsid, nsstringToQString(nsInterfaceName));
       
   358                 userProfiles.insert(thisSsid, map);
       
   359             }
       
   360         }
       
   361         CFRelease(airportPlist);
       
   362 
       
   363         // 802.1X user profiles
       
   364         QString userProfilePath = QDir::homePath() + "/Library/Preferences/com.apple.eap.profiles.plist";
       
   365         NSDictionary* eapDict = [[[NSDictionary alloc] initWithContentsOfFile:qstringToNSString(userProfilePath)] autorelease];
       
   366         NSString *profileStr= @"Profiles";
       
   367         NSString *nameStr = @"UserDefinedName";
       
   368         NSString *networkSsidStr = @"Wireless Network";
       
   369 
       
   370         id profileKey;
       
   371         NSEnumerator *dictEnumerator = [eapDict objectEnumerator];
       
   372         while ((profileKey = [dictEnumerator nextObject])) {
       
   373 
       
   374             if ([profileStr isEqualToString:profileKey]) {
       
   375                 NSDictionary *itemDict = [eapDict objectForKey:profileKey];
       
   376                 id itemKey;
       
   377                 NSEnumerator *dictEnumerator = [thisSsidarray objectEnumerator];
       
   378                 while ((itemKey = [dictEnumerator nextObject])) {
       
   379 
       
   380                     NSInteger dictSize = [itemKey count];
       
   381                     id objects[dictSize];
       
   382                     id keys[dictSize];
       
   383 
       
   384                     [itemKey getObjects:objects andKeys:keys];
       
   385                     QString networkName;
       
   386                     QString ssid;
       
   387                     for(int i = 0; i < dictSize; i++) {
       
   388                         if([nameStr isEqualToString:keys[i]]) {
       
   389                             networkName = nsstringToQString(objects[i]);
       
   390                         }
       
   391                         if([networkSsidStr isEqualToString:keys[i]]) {
       
   392                             ssid = nsstringToQString(objects[i]);
       
   393                         }
       
   394                         if(!userProfiles.contains(networkName)
       
   395                             && !ssid.isEmpty()) {
       
   396                             QMap<QString,QString> map;
       
   397                             map.insert(ssid, nsstringToQString(nsInterfaceName));
       
   398                             userProfiles.insert(networkName, map);
       
   399                         }
       
   400                     }
       
   401                 }
       
   402             }
       
   403         }
       
   404     }
       
   405 
       
   406     [pool release];
       
   407 #endif    
       
   408 }
       
   409 
       
   410 QString QScanThread::getSsidFromNetworkName(const QString &name)
       
   411 {
       
   412     QMutexLocker locker(&mutex);
       
   413     QMapIterator<QString, QMap<QString,QString> > i(userProfiles);
       
   414     while (i.hasNext()) {
       
   415         i.next();
       
   416         QMap<QString,QString> map = i.value();
       
   417         QMapIterator<QString, QString> ij(i.value());
       
   418          while (ij.hasNext()) {
       
   419              ij.next();
       
   420              const QString networkNameHash = QString::number(qHash(QLatin1String("corewlan:") +i.key()));
       
   421              if(name == i.key() || name == networkNameHash) {
       
   422                  return ij.key();
       
   423              }
       
   424         }
       
   425     }
       
   426     return QString();
       
   427 }
       
   428 
       
   429 QString QScanThread::getNetworkNameFromSsid(const QString &ssid)
       
   430 {
       
   431     QMutexLocker locker(&mutex);
       
   432     QMapIterator<QString, QMap<QString,QString> > i(userProfiles);
       
   433     while (i.hasNext()) {
       
   434         i.next();
       
   435         QMap<QString,QString> map = i.value();
       
   436         QMapIterator<QString, QString> ij(i.value());
       
   437          while (ij.hasNext()) {
       
   438              ij.next();
       
   439              if(ij.key() == ssid) {
       
   440                  return i.key();
       
   441              }
       
   442          }
       
   443     }
       
   444     return QString();
       
   445 }
       
   446 
       
   447 bool QScanThread::isKnownSsid(const QString &ssid)
       
   448 {
       
   449     QMutexLocker locker(&mutex);
       
   450 
       
   451     QMapIterator<QString, QMap<QString,QString> > i(userProfiles);
       
   452     while (i.hasNext()) {
       
   453         i.next();
       
   454         QMap<QString,QString> map = i.value();
       
   455         if(map.keys().contains(ssid)) {
       
   456             return true;
       
   457         }
       
   458     }
       
   459     return false;
       
   460 }
       
   461 
       
   462 
       
   463 QCoreWlanEngine::QCoreWlanEngine(QObject *parent)
       
   464 :   QNetworkSessionEngine(parent)
       
   465 {
       
   466     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
       
   467     getAllScInterfaces();
       
   468     scanThread = new QScanThread(this);
       
   469     connect(scanThread, SIGNAL(networksChanged()),
       
   470             this, SIGNAL(configurationsChanged()));
       
   471 
       
   472     QTimer::singleShot(0,this,SLOT(init()));
       
   473     [pool release];
       
   474 }
       
   475 
       
   476 QCoreWlanEngine::~QCoreWlanEngine()
       
   477 {
       
   478     QNetworkConfigurationPrivate* cpPriv = 0;
       
   479     foundConfigurations.clear();
       
   480     while(!foundConfigurations.isEmpty()) {
       
   481         cpPriv = foundConfigurations.takeFirst();
       
   482         delete cpPriv;
       
   483     }
       
   484 }
       
   485 
       
   486 void QCoreWlanEngine::init()
       
   487 {
       
   488 #ifdef MAC_SDK_10_6
       
   489     if([[CWInterface supportedInterfaces] count] > 0 && !listener) {
       
   490         listener = [[QNSListener alloc] init];
       
   491         hasWifi = true;
       
   492     } else {
       
   493         hasWifi = false;
       
   494     }
       
   495 #endif
       
   496     storeSession = NULL;
       
   497     scanThread->start();
       
   498 
       
   499     startNetworkChangeLoop();
       
   500 }
       
   501 
       
   502 
       
   503 QList<QNetworkConfigurationPrivate *> QCoreWlanEngine::getConfigurations(bool *ok)
       
   504 {
       
   505     if (ok)
       
   506         *ok = true;
       
   507     foundConfigurations.clear();
       
   508 
       
   509     QNetworkConfigurationPrivate* cpPriv = 0;
       
   510     QMutexLocker locker(&mutex);
       
   511      QList<QNetworkConfigurationPrivate *> fetchedConfigurations = scanThread->getConfigurations();
       
   512 locker.unlock();
       
   513 
       
   514      for (int i = 0; i < fetchedConfigurations.count(); ++i) {
       
   515 
       
   516          QNetworkConfigurationPrivate *config = new QNetworkConfigurationPrivate();
       
   517          cpPriv = fetchedConfigurations.at(i);
       
   518          config->name = cpPriv->name;
       
   519          config->isValid = cpPriv->isValid;
       
   520          config->id = cpPriv->id;
       
   521          config->state = cpPriv->state;
       
   522          config->type = cpPriv->type;
       
   523          config->roamingSupported = cpPriv->roamingSupported;
       
   524          config->purpose = cpPriv->purpose;
       
   525          config->internet = cpPriv->internet;
       
   526          config->serviceInterface = cpPriv->serviceInterface;
       
   527          config->bearer = cpPriv->bearer;
       
   528 
       
   529          foundConfigurations.append(config);
       
   530          delete cpPriv;
       
   531      }
       
   532 
       
   533 
       
   534      return foundConfigurations;
       
   535 }
       
   536 
       
   537 QString QCoreWlanEngine::getInterfaceFromId(const QString &id)
       
   538 {
       
   539     return scanThread->configurationInterface.value(id);
       
   540 }
       
   541 
       
   542 bool QCoreWlanEngine::hasIdentifier(const QString &id)
       
   543 {
       
   544     return scanThread->configurationInterface.contains(id);
       
   545 }
       
   546 
       
   547 void QCoreWlanEngine::connectToId(const QString &id)
       
   548 {
       
   549     QString interfaceString = getInterfaceFromId(id);
       
   550 
       
   551     if(networkInterfaces.value(interfaceString) == "WLAN") {
       
   552 #if defined(MAC_SDK_10_6)
       
   553         NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
       
   554         CWInterface *wifiInterface = [CWInterface interfaceWithName: qstringToNSString(interfaceString)];
       
   555 
       
   556         if([wifiInterface power]) {
       
   557             NSError *err = nil;
       
   558             NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0];
       
   559 
       
   560             QString wantedSsid = 0;
       
   561             bool using8021X = false;
       
   562 
       
   563             if(scanThread->getNetworkNameFromSsid(id) != id) {
       
   564                 NSArray *array = [CW8021XProfile allUser8021XProfiles];
       
   565                 for (NSUInteger i=0; i<[array count]; ++i) {
       
   566 
       
   567                     if(id == nsstringToQString([[array objectAtIndex:i] userDefinedName])
       
   568                         || id == nsstringToQString([[array objectAtIndex:i] ssid]) ) {
       
   569                         QString thisName = scanThread->getSsidFromNetworkName(id);
       
   570                         if(thisName.isEmpty()) {
       
   571                             wantedSsid = id;
       
   572                         } else {
       
   573                             wantedSsid = thisName;
       
   574                         }
       
   575                         [params setValue: [array objectAtIndex:i] forKey:kCWAssocKey8021XProfile];
       
   576                         using8021X = true;
       
   577                         break;
       
   578                     }
       
   579                 }
       
   580             }
       
   581 
       
   582             if(!using8021X) {
       
   583                 QString wantedNetwork;
       
   584                 QMapIterator<QString, QMap<QString,QString> > i(scanThread->userProfiles);
       
   585                 while (i.hasNext()) {
       
   586                     i.next();
       
   587                     wantedNetwork = i.key();
       
   588                     if(id == wantedNetwork) {
       
   589                         wantedSsid = scanThread->getSsidFromNetworkName(wantedNetwork);
       
   590                         break;
       
   591                     }
       
   592                 }
       
   593             }
       
   594 
       
   595             NSDictionary *parametersDict = [NSDictionary dictionaryWithObjectsAndKeys:
       
   596                                        [NSNumber numberWithBool:YES], kCWScanKeyMerge,
       
   597                                        [NSNumber numberWithInt:kCWScanTypeFast], kCWScanKeyScanType,
       
   598                                        [NSNumber numberWithInteger:100], kCWScanKeyRestTime,
       
   599                                        qstringToNSString(wantedSsid), kCWScanKeySSID,
       
   600                                        nil];
       
   601 
       
   602             NSArray *scanArray = [wifiInterface scanForNetworksWithParameters:parametersDict error:&err];
       
   603             if(!err) {
       
   604                 for(uint row=0; row < [scanArray count]; row++ ) {
       
   605                     CWNetwork *apNetwork = [scanArray objectAtIndex:row];
       
   606                     if(wantedSsid == nsstringToQString([apNetwork ssid])) {
       
   607 
       
   608                         if(!using8021X) {
       
   609                             SecKeychainAttribute attributes[3];
       
   610 
       
   611                             NSString *account = [apNetwork ssid];
       
   612                             NSString *keyKind = @"AirPort network password";
       
   613                             NSString *keyName = account;
       
   614 
       
   615                             attributes[0].tag = kSecAccountItemAttr;
       
   616                             attributes[0].data = (void *)[account UTF8String];
       
   617                             attributes[0].length = [account length];
       
   618 
       
   619                             attributes[1].tag = kSecDescriptionItemAttr;
       
   620                             attributes[1].data = (void *)[keyKind UTF8String];
       
   621                             attributes[1].length = [keyKind length];
       
   622 
       
   623                             attributes[2].tag = kSecLabelItemAttr;
       
   624                             attributes[2].data = (void *)[keyName UTF8String];
       
   625                             attributes[2].length = [keyName length];
       
   626 
       
   627                             SecKeychainAttributeList attributeList = {3,attributes};
       
   628 
       
   629                             SecKeychainSearchRef searchRef;
       
   630                             OSErr result = SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, &attributeList, &searchRef);
       
   631 Q_UNUSED(result);
       
   632                             NSString *password = @"";
       
   633                             SecKeychainItemRef searchItem;
       
   634                             OSStatus resultStatus;
       
   635                             resultStatus = SecKeychainSearchCopyNext(searchRef, &searchItem);
       
   636 
       
   637                             if (resultStatus == errSecSuccess) {
       
   638                                 UInt32 realPasswordLength;
       
   639                                 SecKeychainAttribute attributesW[8];
       
   640                                 attributesW[0].tag = kSecAccountItemAttr;
       
   641                                 SecKeychainAttributeList listW = {1,attributesW};
       
   642                                 char *realPassword;
       
   643                                 OSStatus status = SecKeychainItemCopyContent(searchItem, NULL, &listW, &realPasswordLength,(void **)&realPassword);
       
   644 
       
   645                                 if (status == noErr) {
       
   646                                     if (realPassword != NULL) {
       
   647 
       
   648                                         QByteArray pBuf;
       
   649                                         pBuf.resize(realPasswordLength);
       
   650                                         pBuf.prepend(realPassword);
       
   651                                         pBuf.insert(realPasswordLength,'\0');
       
   652 
       
   653                                         password = [NSString stringWithUTF8String:pBuf];
       
   654                                     }
       
   655                                 }
       
   656 
       
   657                                 CFRelease(searchItem);
       
   658                                 SecKeychainItemFreeContent(&listW, realPassword);
       
   659                             } else {
       
   660                                 qDebug() << "SecKeychainSearchCopyNext error" << cfstringRefToQstring(SecCopyErrorMessageString(resultStatus, NULL));
       
   661                             }
       
   662                             [params setValue: password forKey: kCWAssocKeyPassphrase];
       
   663                         } // end using8021X
       
   664 
       
   665                         bool result = [wifiInterface associateToNetwork: apNetwork parameters:[NSDictionary dictionaryWithDictionary:params] error:&err];
       
   666 
       
   667                         if(!result) {
       
   668                             emit connectionError(id, ConnectError);
       
   669                         } else {
       
   670                             [autoreleasepool release];
       
   671                             return;
       
   672                         }
       
   673                     }
       
   674                 }
       
   675             } else {
       
   676                 qDebug() <<"ERROR"<< nsstringToQString([err localizedDescription ]);
       
   677             }
       
   678 
       
   679             emit connectionError(id, InterfaceLookupError);
       
   680             [autoreleasepool release];
       
   681 
       
   682         } else {
       
   683             qDebug() << "wifi power off";
       
   684             // not wifi
       
   685         }
       
   686 #endif
       
   687     }
       
   688     emit connectionError(id, OperationNotSupported);
       
   689 }
       
   690 
       
   691 void QCoreWlanEngine::disconnectFromId(const QString &id)
       
   692 {
       
   693     QString interfaceString = getInterfaceFromId(id);
       
   694     if(networkInterfaces.value(getInterfaceFromId(id)) == "WLAN") { //wifi only for now
       
   695 #if defined(MAC_SDK_10_6)
       
   696         NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
       
   697         CWInterface *wifiInterface = [CWInterface interfaceWithName:  qstringToNSString(interfaceString)];
       
   698         [wifiInterface disassociate];
       
   699         if([[wifiInterface interfaceState]intValue] != kCWInterfaceStateInactive) {
       
   700             emit connectionError(id, DisconnectionError);
       
   701         }
       
   702        [autoreleasepool release];
       
   703        return;
       
   704 #endif
       
   705     } else {
       
   706 
       
   707     }
       
   708     emit connectionError(id, OperationNotSupported);
       
   709 }
       
   710 
       
   711 void QCoreWlanEngine::requestUpdate()
       
   712 {
       
   713     getAllScInterfaces();
       
   714     scanThread->getUserProfiles();
       
   715     scanThread->start();
       
   716 }
       
   717 
       
   718 QCoreWlanEngine *QCoreWlanEngine::instance()
       
   719 {
       
   720     return coreWlanEngine();
       
   721 }
       
   722 
       
   723 bool QCoreWlanEngine::isWifiReady(const QString &wifiDeviceName)
       
   724 {
       
   725 #if defined(MAC_SDK_10_6)
       
   726     if([[CWInterface supportedInterfaces] count] > 0 ) {
       
   727         CWInterface *defaultInterface = [CWInterface interfaceWithName: qstringToNSString(wifiDeviceName)];
       
   728         if([defaultInterface power])
       
   729             return true;
       
   730     }
       
   731 #else
       
   732     Q_UNUSED(wifiDeviceName);
       
   733 #endif
       
   734     return false;
       
   735 }
       
   736 
       
   737 bool QCoreWlanEngine::getAllScInterfaces()
       
   738 {
       
   739     networkInterfaces.clear();
       
   740     NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
       
   741 
       
   742     CFArrayRef interfaces = SCNetworkInterfaceCopyAll();
       
   743     if (interfaces != NULL) {
       
   744         CFIndex interfaceCount;
       
   745         CFIndex interfaceIndex;
       
   746         interfaceCount = CFArrayGetCount(interfaces);
       
   747         for (interfaceIndex = 0; interfaceIndex < interfaceCount; interfaceIndex++) {
       
   748             NSAutoreleasePool *looppool = [[NSAutoreleasePool alloc] init];
       
   749 
       
   750             CFStringRef bsdName;
       
   751             CFTypeRef thisInterface = CFArrayGetValueAtIndex(interfaces, interfaceIndex);
       
   752             bsdName = SCNetworkInterfaceGetBSDName((SCNetworkInterfaceRef)thisInterface);
       
   753             QString interfaceName = cfstringRefToQstring(bsdName);
       
   754             QString typeStr;
       
   755             CFStringRef type = SCNetworkInterfaceGetInterfaceType((SCNetworkInterfaceRef)thisInterface);
       
   756             if ( CFEqual(type, kSCNetworkInterfaceTypeIEEE80211)) {
       
   757                 typeStr = "WLAN";
       
   758 //            } else if (CFEqual(type, kSCNetworkInterfaceTypeBluetooth)) {
       
   759 //                typeStr = "Bluetooth";
       
   760             } else if(CFEqual(type, kSCNetworkInterfaceTypeEthernet)) {
       
   761                 typeStr = "Ethernet";
       
   762             } else if(CFEqual(type, kSCNetworkInterfaceTypeFireWire)) {
       
   763                 typeStr = "Ethernet"; //ok a bit fudged
       
   764             }
       
   765             if(!networkInterfaces.contains(interfaceName) && !typeStr.isEmpty()) {
       
   766                 networkInterfaces.insert(interfaceName,typeStr);
       
   767             }
       
   768             [looppool release];
       
   769         }
       
   770     }
       
   771     CFRelease(interfaces);
       
   772 
       
   773     [autoreleasepool drain];
       
   774     return true;
       
   775 }
       
   776 
       
   777 void QCoreWlanEngine::startNetworkChangeLoop()
       
   778 {
       
   779     storeSession = NULL;
       
   780 
       
   781     SCDynamicStoreContext dynStoreContext = { 0, this/*(void *)storeSession*/, NULL, NULL, NULL };
       
   782     storeSession = SCDynamicStoreCreate(NULL,
       
   783                                  CFSTR("networkChangeCallback"),
       
   784                                  networkChangeCallback,
       
   785                                  &dynStoreContext);
       
   786     if (!storeSession ) {
       
   787         qDebug() << "could not open dynamic store: error:" << SCErrorString(SCError());
       
   788         return;
       
   789     }
       
   790 
       
   791     CFMutableArrayRef notificationKeys;
       
   792     notificationKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
       
   793     CFMutableArrayRef patternsArray;
       
   794     patternsArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
       
   795 
       
   796     CFStringRef storeKey;
       
   797     storeKey = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
       
   798                                                      kSCDynamicStoreDomainState,
       
   799                                                      kSCEntNetIPv4);
       
   800     CFArrayAppendValue(notificationKeys, storeKey);
       
   801     CFRelease(storeKey);
       
   802 
       
   803     storeKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
       
   804                                                       kSCDynamicStoreDomainState,
       
   805                                                       kSCCompAnyRegex,
       
   806                                                       kSCEntNetIPv4);
       
   807     CFArrayAppendValue(patternsArray, storeKey);
       
   808     CFRelease(storeKey);
       
   809 
       
   810     if (!SCDynamicStoreSetNotificationKeys(storeSession , notificationKeys, patternsArray)) {
       
   811         qDebug() << "register notification error:"<< SCErrorString(SCError());
       
   812         CFRelease(storeSession );
       
   813         CFRelease(notificationKeys);
       
   814         CFRelease(patternsArray);
       
   815         return;
       
   816     }
       
   817     CFRelease(notificationKeys);
       
   818     CFRelease(patternsArray);
       
   819 
       
   820     runloopSource = SCDynamicStoreCreateRunLoopSource(NULL, storeSession , 0);
       
   821     if (!runloopSource) {
       
   822         qDebug() << "runloop source error:"<< SCErrorString(SCError());
       
   823         CFRelease(storeSession );
       
   824         return;
       
   825     }
       
   826 
       
   827     CFRunLoopAddSource(CFRunLoopGetCurrent(), runloopSource, kCFRunLoopDefaultMode);
       
   828     return;
       
   829 }
       
   830 #include "moc_qcorewlanengine_mac_p.cpp"
       
   831 
       
   832 QTM_END_NAMESPACE