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